From d84f10cf085c5b1bd66752f69d771f99aa457f5f Mon Sep 17 00:00:00 2001 From: Matias Fontanini Date: Sat, 2 Jan 2016 08:17:59 -0800 Subject: [PATCH] Code cleanup and use same syntax on the entire project Initial code cleanup More code cleanup Cleanup more code Cleanup Dot11 code Fix OSX build issue Cleanup examples Fix ref and pointer declaration syntax Fix braces --- examples/arpmonitor.cpp | 42 +- examples/arpspoofing.cpp | 28 +- examples/beacon_display.cpp | 37 +- examples/dns_queries.cpp | 16 +- examples/dns_spoof.cpp | 24 +- examples/dns_stats.cpp | 86 +- examples/icmp_responses.cpp | 164 +-- examples/interfaces_info.cpp | 43 +- examples/portscan.cpp | 67 +- examples/route_table.cpp | 24 +- examples/traceroute.cpp | 74 +- examples/wps_detect.cpp | 8 +- include/tins/address_range.h | 85 +- include/tins/arp.h | 563 +++++----- include/tins/bootp.h | 628 +++++------ include/tins/constants.h | 250 ++--- include/tins/crypto.h | 903 +++++++-------- include/tins/dhcp.h | 935 ++++++++-------- include/tins/dhcpv6.h | 169 +-- include/tins/dns.h | 1197 ++++++++++---------- include/tins/dot11/dot11_assoc.h | 147 ++- include/tins/dot11/dot11_auth.h | 50 +- include/tins/dot11/dot11_base.h | 93 +- include/tins/dot11/dot11_beacon.h | 258 ++--- include/tins/dot11/dot11_control.h | 163 +-- include/tins/dot11/dot11_data.h | 96 +- include/tins/dot11/dot11_mgmt.h | 353 +++--- include/tins/dot11/dot11_probe.h | 46 +- include/tins/dot1q.h | 31 +- include/tins/dot3.h | 306 +++--- include/tins/eapol.h | 1463 +++++++++++++------------ include/tins/endianness.h | 304 +++-- include/tins/ethernetII.h | 323 +++--- include/tins/exceptions.h | 84 +- include/tins/handshake_capturer.h | 226 ++-- include/tins/hw_address.h | 112 +- include/tins/icmp.h | 84 +- include/tins/icmp_extension.h | 26 +- include/tins/icmpv6.h | 274 ++--- include/tins/internals.h | 50 +- include/tins/ip.h | 1276 ++++++++++----------- include/tins/ip_address.h | 32 +- include/tins/ip_reassembler.h | 41 +- include/tins/ipsec.h | 43 +- include/tins/ipv6.h | 60 +- include/tins/ipv6_address.h | 51 +- include/tins/llc.h | 714 ++++++------ include/tins/loopback.h | 29 +- include/tins/memory_helpers.h | 39 + include/tins/mpls.h | 8 +- include/tins/network_interface.h | 23 +- include/tins/offline_packet_filter.h | 15 +- include/tins/packet.h | 65 +- include/tins/packet_sender.h | 703 ++++++------ include/tins/packet_writer.h | 28 +- include/tins/pdu.h | 931 ++++++++-------- include/tins/pdu_allocator.h | 41 +- include/tins/pdu_cacher.h | 46 +- include/tins/pdu_option.h | 110 +- include/tins/pktap.h | 12 +- include/tins/ppi.h | 25 +- include/tins/pppoe.h | 65 +- include/tins/radiotap.h | 32 +- include/tins/rawpdu.h | 300 ++--- include/tins/rsn_information.h | 34 +- include/tins/sll.h | 23 +- include/tins/small_uint.h | 8 +- include/tins/snap.h | 273 ++--- include/tins/sniffer.h | 998 ++++++++--------- include/tins/stp.h | 42 +- include/tins/tcp.h | 1006 ++++++++--------- include/tins/tcp_stream.h | 114 +- include/tins/timestamp.h | 5 +- include/tins/udp.h | 273 ++--- include/tins/utils.h | 639 +++++------ src/address_range.cpp | 20 +- src/arp.cpp | 92 +- src/bootp.cpp | 96 +- src/crypto.cpp | 320 +++--- src/dhcp.cpp | 78 +- src/dhcpv6.cpp | 538 ++++----- src/dns.cpp | 450 ++++---- src/dot11/dot11_assoc.cpp | 125 +-- src/dot11/dot11_auth.cpp | 57 +- src/dot11/dot11_base.cpp | 197 ++-- src/dot11/dot11_beacon.cpp | 29 +- src/dot11/dot11_control.cpp | 184 ++-- src/dot11/dot11_data.cpp | 84 +- src/dot11/dot11_mgmt.cpp | 419 +++---- src/dot11/dot11_probe.cpp | 44 +- src/dot1q.cpp | 54 +- src/dot3.cpp | 70 +- src/eapol.cpp | 206 ++-- src/ethernetII.cpp | 63 +- src/handshake_capturer.cpp | 117 +- src/icmp.cpp | 95 +- src/icmp_extension.cpp | 8 +- src/icmpv6.cpp | 737 ++++++------- src/internals.cpp | 79 +- src/ip.cpp | 241 ++-- src/ip_address.cpp | 51 +- src/ip_reassembler.cpp | 95 +- src/ipsec.cpp | 92 +- src/ipv6.cpp | 120 +- src/ipv6_address.cpp | 49 +- src/llc.cpp | 73 +- src/loopback.cpp | 38 +- src/mpls.cpp | 15 +- src/network_interface.cpp | 119 +- src/offline_packet_filter.cpp | 44 +- src/packet_sender.cpp | 289 +++-- src/packet_writer.cpp | 38 +- src/pdu.cpp | 56 +- src/pktap.cpp | 5 +- src/ppi.cpp | 27 +- src/pppoe.cpp | 119 +- src/radiotap.cpp | 425 +++---- src/rawpdu.cpp | 24 +- src/rsn_information.cpp | 63 +- src/sll.cpp | 24 +- src/snap.cpp | 29 +- src/sniffer.cpp | 274 +++-- src/stp.cpp | 56 +- src/tcp.cpp | 194 ++-- src/tcp_stream.cpp | 161 +-- src/udp.cpp | 79 +- src/utils.cpp | 108 +- tests/include/tests/dot11.h | 4 +- tests/include/tests/dot11_control.h | 4 +- tests/include/tests/dot11_data.h | 4 +- tests/include/tests/dot11_mgmt.h | 8 +- tests/src/address_range.cpp | 12 +- tests/src/allocators.cpp | 4 +- tests/src/arp.cpp | 6 +- tests/src/dhcp.cpp | 10 +- tests/src/dhcpv6.cpp | 2 +- tests/src/dns.cpp | 20 +- tests/src/dot11/ack.cpp | 6 +- tests/src/dot11/assoc_request.cpp | 6 +- tests/src/dot11/assoc_response.cpp | 6 +- tests/src/dot11/authentication.cpp | 6 +- tests/src/dot11/beacon.cpp | 6 +- tests/src/dot11/block_ack_request.cpp | 6 +- tests/src/dot11/cfend.cpp | 6 +- tests/src/dot11/cfendack.cpp | 6 +- tests/src/dot11/data.cpp | 2 +- tests/src/dot11/deauthentication.cpp | 6 +- tests/src/dot11/disassoc.cpp | 6 +- tests/src/dot11/dot11.cpp | 2 +- tests/src/dot11/probe_request.cpp | 6 +- tests/src/dot11/probe_response.cpp | 6 +- tests/src/dot11/pspoll.cpp | 6 +- tests/src/dot11/reassoc_request.cpp | 6 +- tests/src/dot11/reassoc_response.cpp | 6 +- tests/src/dot11/rts.cpp | 6 +- tests/src/dot1q.cpp | 6 +- tests/src/ethernetII.cpp | 6 +- tests/src/hwaddress.cpp | 4 +- tests/src/icmp.cpp | 6 +- tests/src/icmpv6.cpp | 9 +- tests/src/ip.cpp | 8 +- tests/src/ip_reassembler.cpp | 6 +- tests/src/ipsec.cpp | 2 +- tests/src/ipv6.cpp | 14 +- tests/src/ipv6address.cpp | 2 +- tests/src/llc.cpp | 2 +- tests/src/main.cpp | 2 +- tests/src/matches_response.cpp | 8 +- tests/src/pdu.cpp | 20 +- tests/src/rsn_eapol.cpp | 4 +- tests/src/sll.cpp | 2 +- tests/src/snap.cpp | 6 +- tests/src/stp.cpp | 8 +- tests/src/tcp.cpp | 10 +- tests/src/udp.cpp | 6 +- tests/src/wep_decrypt.cpp | 2 +- tests/src/wpa2_decrypt.cpp | 24 +- 177 files changed, 13134 insertions(+), 12203 deletions(-) diff --git a/examples/arpmonitor.cpp b/examples/arpmonitor.cpp index 16655fff..6caa2dfc 100644 --- a/examples/arpmonitor.cpp +++ b/examples/arpmonitor.cpp @@ -32,21 +32,25 @@ #include #include +using std::cout; +using std::endl; +using std::map; +using std::bind; + using namespace Tins; class arp_monitor { public: - void run(Sniffer &sniffer); + void run(Sniffer& sniffer); private: - bool callback(const PDU &pdu); + bool callback(const PDU& pdu); - std::map> addresses; + map> addresses; }; -void arp_monitor::run(Sniffer &sniffer) -{ +void arp_monitor::run(Sniffer& sniffer) { sniffer.sniff_loop( - std::bind( + bind( &arp_monitor::callback, this, std::placeholders::_1 @@ -54,36 +58,34 @@ void arp_monitor::run(Sniffer &sniffer) ); } -bool arp_monitor::callback(const PDU &pdu) -{ +bool arp_monitor::callback(const PDU& pdu) { // Retrieve the ARP layer - const ARP &arp = pdu.rfind_pdu(); + const ARP& arp = pdu.rfind_pdu(); // Is it an ARP reply? - if(arp.opcode() == ARP::REPLY) { + if (arp.opcode() == ARP::REPLY) { // Let's check if there's already an entry for this address auto iter = addresses.find(arp.sender_ip_addr()); - if(iter == addresses.end()) { + if (iter == addresses.end()) { // We haven't seen this address. Save it. addresses.insert({ arp.sender_ip_addr(), arp.sender_hw_addr()}); - std::cout << "[INFO] " << arp.sender_ip_addr() << " is at " - << arp.sender_hw_addr() << std::endl; + cout << "[INFO] " << arp.sender_ip_addr() << " is at " + << arp.sender_hw_addr() << std::endl; } else { // We've seen this address. If it's not the same HW address, inform it - if(arp.sender_hw_addr() != iter->second) { - std::cout << "[WARNING] " << arp.sender_ip_addr() << " is at " - << iter->second << " but also at " << arp.sender_hw_addr() - << std::endl; + if (arp.sender_hw_addr() != iter->second) { + cout << "[WARNING] " << arp.sender_ip_addr() << " is at " + << iter->second << " but also at " << arp.sender_hw_addr() + << endl; } } } return true; } -int main(int argc, char *argv[]) -{ +int main(int argc, char* argv[]) { if(argc != 2) { - std::cout << "Usage: " << *argv << " \n"; + cout << "Usage: " <<* argv << " " << endl; return 1; } arp_monitor monitor; diff --git a/examples/arpspoofing.cpp b/examples/arpspoofing.cpp index 879fcf16..543ca549 100644 --- a/examples/arpspoofing.cpp +++ b/examples/arpspoofing.cpp @@ -44,13 +44,17 @@ #include #include -using namespace std; +using std::cout; +using std::runtime_error; +using std::endl; + using namespace Tins; -void do_arp_spoofing(NetworkInterface iface, IPv4Address gw, IPv4Address victim, - const NetworkInterface::Info &info) -{ +void do_arp_spoofing(NetworkInterface iface, + IPv4Address gw, + IPv4Address victim, + const NetworkInterface::Info& info) { PacketSender sender; EthernetII::address_type gw_hw, victim_hw; @@ -79,7 +83,7 @@ void do_arp_spoofing(NetworkInterface iface, IPv4Address gw, IPv4Address victim, * performed by any routers. */ EthernetII to_gw = EthernetII(gw_hw, info.hw_addr) / gw_arp; EthernetII to_victim = EthernetII(victim_hw, info.hw_addr) / victim_arp; - while(true) { + while (true) { // Just send them once every 5 seconds. sender.send(to_gw, iface); sender.send(to_victim, iface); @@ -91,9 +95,11 @@ void do_arp_spoofing(NetworkInterface iface, IPv4Address gw, IPv4Address victim, } } -int main(int argc, char *argv[]) { - if(argc != 3 && cout << "Usage: " << *argv << " \n") +int main(int argc, char* argv[]) { + if (argc != 3) { + cout << "Usage: " <<* argv << " " << endl; return 1; + } IPv4Address gw, victim; EthernetII::address_type own_hw; try { @@ -101,7 +107,7 @@ int main(int argc, char *argv[]) { gw = argv[1]; victim = argv[2]; } - catch(...) { + catch (...) { cout << "Invalid ip found...\n"; return 2; } @@ -115,15 +121,15 @@ int main(int argc, char *argv[]) { // Find the interface hardware and ip address. info = iface.addresses(); } - catch(std::runtime_error &ex) { + catch (runtime_error& ex) { cout << ex.what() << endl; return 3; } try { do_arp_spoofing(iface, gw, victim, info); } - catch(std::runtime_error &ex) { - std::cout << "Runtime error: " << ex.what() << std::endl; + catch (runtime_error& ex) { + cout << "Runtime error: " << ex.what() << endl; return 7; } } diff --git a/examples/beacon_display.cpp b/examples/beacon_display.cpp index 042d7a00..eb99a304 100644 --- a/examples/beacon_display.cpp +++ b/examples/beacon_display.cpp @@ -32,21 +32,27 @@ #include #include +using std::set; +using std::cout; +using std::endl; +using std::string; +using std::runtime_error; + using namespace Tins; class BeaconSniffer { public: - void run(const std::string &iface); + void run(const string& iface); private: typedef Dot11::address_type address_type; - typedef std::set ssids_type; + typedef set ssids_type; - bool callback(PDU &pdu); + bool callback(PDU& pdu); ssids_type ssids; }; -void BeaconSniffer::run(const std::string &iface) { +void BeaconSniffer::run(const std::string& iface) { SnifferConfiguration config; config.set_promisc_mode(true); config.set_filter("type mgt subtype beacon"); @@ -55,28 +61,28 @@ void BeaconSniffer::run(const std::string &iface) { sniffer.sniff_loop(make_sniffer_handler(this, &BeaconSniffer::callback)); } -bool BeaconSniffer::callback(PDU &pdu) { +bool BeaconSniffer::callback(PDU& pdu) { // Get the Dot11 layer - const Dot11Beacon &beacon = pdu.rfind_pdu(); + const Dot11Beacon& beacon = pdu.rfind_pdu(); // All beacons must have from_ds == to_ds == 0 - if(!beacon.from_ds() && !beacon.to_ds()) { + if (!beacon.from_ds() && !beacon.to_ds()) { // Get the AP address address_type addr = beacon.addr2(); // Look it up in our set ssids_type::iterator it = ssids.find(addr); - if(it == ssids.end()) { + if (it == ssids.end()) { // First time we encounter this BSSID. try { /* If no ssid option is set, then Dot11::ssid will throw * a std::runtime_error. */ - std::string ssid = beacon.ssid(); + string ssid = beacon.ssid(); // Save it so we don't show it again. ssids.insert(addr); // Display the tuple "address - ssid". - std::cout << addr << " - " << ssid << std::endl; + cout << addr << " - " << ssid << endl; } - catch(std::runtime_error&) { + catch (runtime_error&) { // No ssid, just ignore it. } } @@ -85,10 +91,11 @@ bool BeaconSniffer::callback(PDU &pdu) { } int main(int argc, char* argv[]) { - // By default, sniff wlan0 - std::string interface = "wlan0"; - if(argc == 2) - interface = argv[1]; + if (argc != 2) { + cout << "Usage: " <<* argv << " " << endl; + return 1; + } + string interface = argv[1]; BeaconSniffer sniffer; sniffer.run(interface); } diff --git a/examples/dns_queries.cpp b/examples/dns_queries.cpp index 05d94126..f3d914f7 100644 --- a/examples/dns_queries.cpp +++ b/examples/dns_queries.cpp @@ -30,10 +30,12 @@ #include #include +using std::cout; +using std::endl; + using namespace Tins; -bool callback(const PDU &pdu) -{ +bool callback(const PDU& pdu) { // The packet probably looks like this: // // EthernetII / IP / UDP / RawPDU @@ -43,15 +45,15 @@ bool callback(const PDU &pdu) DNS dns = pdu.rfind_pdu().to(); // Retrieve the queries and print the domain name: - for(const auto &query : dns.queries()) - std::cout << query.dname() << std::endl; + for (const auto& query : dns.queries()) { + cout << query.dname() << std::endl; + } return true; } -int main(int argc, char *argv[]) -{ +int main(int argc, char* argv[]) { if(argc != 2) { - std::cout << "Usage: " << *argv << " " << std::endl; + cout << "Usage: " <<* argv << " " << endl; return 1; } // Sniff on the provided interface in promiscuos mode diff --git a/examples/dns_spoof.cpp b/examples/dns_spoof.cpp index ace62afa..0ea4fa4b 100644 --- a/examples/dns_spoof.cpp +++ b/examples/dns_spoof.cpp @@ -30,11 +30,14 @@ #include #include +using std::cout; +using std::endl; + using namespace Tins; PacketSender sender; -bool callback(const PDU &pdu) +bool callback(const PDU& pdu) { // The packet probably looks like this: // @@ -48,10 +51,10 @@ bool callback(const PDU &pdu) DNS dns = udp.rfind_pdu().to(); // Is it a DNS query? - if(dns.type() == DNS::QUERY) { + if (dns.type() == DNS::QUERY) { // Let's see if there's any query for an "A" record. - for(const auto &query : dns.queries()) { - if(query.type() == DNS::A) { + for (const auto& query : dns.queries()) { + if (query.type() == DNS::A) { // Here's one! Let's add an answer. dns.add_answer( DNS::Resource( @@ -66,16 +69,16 @@ bool callback(const PDU &pdu) } } // Have we added some answers? - if(dns.answers_count() > 0) { + if (dns.answers_count() > 0) { // It's a response now dns.type(DNS::RESPONSE); // Recursion is available(just in case) dns.recursion_available(1); // Build our packet auto pkt = EthernetII(eth.src_addr(), eth.dst_addr()) / - IP(ip.src_addr(), ip.dst_addr()) / - UDP(udp.sport(), udp.dport()) / - dns; + IP(ip.src_addr(), ip.dst_addr()) / + UDP(udp.sport(), udp.dport()) / + dns; // Send it! sender.send(pkt); } @@ -83,10 +86,9 @@ bool callback(const PDU &pdu) return true; } -int main(int argc, char *argv[]) -{ +int main(int argc, char* argv[]) { if(argc != 2) { - std::cout << "Usage: " << *argv << " " << std::endl; + cout << "Usage: " <<* argv << " " << endl; return 1; } // Sniff on the provided interface in promiscuos mode diff --git a/examples/dns_stats.cpp b/examples/dns_stats.cpp index c467d4fd..0d4bda50 100644 --- a/examples/dns_stats.cpp +++ b/examples/dns_stats.cpp @@ -39,6 +39,25 @@ #include #include +using std::cout; +using std::endl; +using std::thread; +using std::string; +using std::bind; +using std::map; +using std::mutex; +using std::max; +using std::min; +using std::exception; +using std::lock_guard; +using std::tuple; +using std::make_tuple; +using std::this_thread::sleep_for; +using std::chrono::seconds; +using std::chrono::milliseconds; +using std::chrono::duration_cast; +using std::chrono::system_clock; + using namespace Tins; // Holds the DNS response time statistics. The response time is @@ -47,7 +66,7 @@ template class statistics { public: using duration_type = Duration; - using locker_type = std::lock_guard; + using locker_type = lock_guard; struct information { duration_type average, worst; @@ -55,42 +74,41 @@ class statistics { }; statistics() - : m_duration(), m_worst(duration_type::min()), m_count() - { + : m_duration(), m_worst(duration_type::min()), m_count() { } - void add_response_time(const duration_type& duration) - { + void add_response_time(const duration_type& duration) { locker_type _(m_lock); m_duration += duration; m_count++; - m_worst = std::max(m_worst, duration); + m_worst = max(m_worst, duration); } - information get_information() const - { + information get_information() const { locker_type _(m_lock); - if(m_count == 0) + if(m_count == 0) { return { }; - else + } + else { return { m_duration / m_count, m_worst, m_count }; + } }; private: duration_type m_duration, m_worst; size_t m_count; - mutable std::mutex m_lock; + mutable mutex m_lock; }; // Sniffs and tracks DNS queries. When a matching DNS response is found, // the response time is added to a statistics object. // -// This class performs *no cleanup* on data associated with queries that +// This class performs* no cleanup* on data associated with queries that // weren't answered. class dns_monitor { public: // The response times are measured in milliseconds - using duration_type = std::chrono::milliseconds; + using duration_type = milliseconds; // The statistics type used. using statistics_type = statistics; @@ -99,21 +117,21 @@ class dns_monitor { return m_stats; } private: - using packet_info = std::tuple; - using clock_type = std::chrono::system_clock; + using packet_info = tuple; + using clock_type = system_clock; using time_point_type = clock_type::time_point; bool callback(const PDU& pdu); static packet_info make_packet_info(const PDU& pdu, const DNS& dns); statistics_type m_stats; - std::map m_packet_info; + map m_packet_info; }; void dns_monitor::run(BaseSniffer& sniffer) { sniffer.sniff_loop( - std::bind( + bind( &dns_monitor::callback, this, std::placeholders::_1 @@ -127,7 +145,7 @@ bool dns_monitor::callback(const PDU& pdu) auto dns = pdu.rfind_pdu().to(); auto info = make_packet_info(pdu, dns); // If it's a query, add the sniff time to our map. - if(dns.type() == DNS::QUERY) { + if (dns.type() == DNS::QUERY) { m_packet_info.insert( std::make_pair(info, now) ); @@ -135,11 +153,11 @@ bool dns_monitor::callback(const PDU& pdu) else { // It's a response, we need to find the query in our map. auto iter = m_packet_info.find(info); - if(iter != m_packet_info.end()) { + if (iter != m_packet_info.end()) { // We found the query, let's add the response time to the // statistics object. m_stats.add_response_time( - std::chrono::duration_cast(now - iter->second) + duration_cast(now - iter->second) ); // Forget about the query. m_packet_info.erase(iter); @@ -155,17 +173,17 @@ bool dns_monitor::callback(const PDU& pdu) auto dns_monitor::make_packet_info(const PDU& pdu, const DNS& dns) -> packet_info { const auto& ip = pdu.rfind_pdu(); - return std::make_tuple( + return make_tuple( // smallest address first - std::min(ip.src_addr(), ip.dst_addr()), + min(ip.src_addr(), ip.dst_addr()), // largest address second - std::max(ip.src_addr(), ip.dst_addr()), + max(ip.src_addr(), ip.dst_addr()), dns.id() ); } -int main(int argc, char *argv[]) { - std::string iface; +int main(int argc, char* argv[]) { + string iface; if (argc == 2) { // Use the provided interface iface = argv[1]; @@ -180,21 +198,21 @@ int main(int argc, char *argv[]) { config.set_filter("udp and port 53"); Sniffer sniffer(iface, config); dns_monitor monitor; - std::thread thread( + thread thread( [&]() { monitor.run(sniffer); } ); - while(true) { + while (true) { auto info = monitor.stats().get_information(); - std::cout << "\rAverage " << info.average.count() - << "ms. Worst: " << info.worst.count() << "ms. Count: " - << info.count; - std::cout.flush(); - std::this_thread::sleep_for(std::chrono::seconds(1)); + cout << "\rAverage " << info.average.count() + << "ms. Worst: " << info.worst.count() << "ms. Count: " + << info.count; + cout.flush(); + sleep_for(seconds(1)); } } - catch(std::exception& ex) { - std::cout << "[-] Error: " << ex.what() << std::endl; + catch (exception& ex) { + cout << "[-] Error: " << ex.what() << endl; } } diff --git a/examples/icmp_responses.cpp b/examples/icmp_responses.cpp index 50ace8a8..aa65a889 100644 --- a/examples/icmp_responses.cpp +++ b/examples/icmp_responses.cpp @@ -33,7 +33,13 @@ #include #include -using namespace std; +using std::cout; +using std::endl; +using std::bind; +using std::string; +using std::runtime_error; +using std::exception; + using namespace Tins; // This class captured packets on an interface, using the specified filter @@ -42,93 +48,93 @@ using namespace Tins; // has swapped HW and IP addresses (dst as src, src as dst). class ICMPResponder { public: - // Use the given interface and ICMP type/code on responses - ICMPResponder(string iface, int type, int code) - : m_iface(iface), m_sender(iface), m_type(type), m_code(code) { + // Use the given interface and ICMP type/code on responses + ICMPResponder(string iface, int type, int code) + : m_iface(iface), m_sender(iface), m_type(type), m_code(code) { - } + } - // Run using the given filter - void run(const string& filter) { - // Initialize the configuration - SnifferConfiguration config; - // Use promiscuous mode - config.set_promisc_mode(true); - // Use this packet filter - config.set_filter(filter); - // Use immediate mode (we don't want to buffer packets, we want the mright away). - config.set_immediate_mode(true); + // Run using the given filter + void run(const string& filter) { + // Initialize the configuration + SnifferConfiguration config; + // Use promiscuous mode + config.set_promisc_mode(true); + // Use this packet filter + config.set_filter(filter); + // Use immediate mode (we don't want to buffer packets, we want the mright away). + config.set_immediate_mode(true); - // Now create the Sniffer - Sniffer sniffer(m_iface, config); - if (sniffer.link_type() != DLT_EN10MB) { - throw runtime_error("Ethernet interfaces only supported"); - } - // Start the sniffing! For each packet, ICMPReponder::callback will be called - sniffer.sniff_loop(bind(&ICMPResponder::callback, this, placeholders::_1)); - } + // Now create the Sniffer + Sniffer sniffer(m_iface, config); + if (sniffer.link_type() != DLT_EN10MB) { + throw runtime_error("Ethernet interfaces only supported"); + } + // Start the sniffing! For each packet, ICMPReponder::callback will be called + sniffer.sniff_loop(bind(&ICMPResponder::callback, this, std::placeholders::_1)); + } private: - // Extracts the payload to be used over the ICMP layer in the response. - // This will be the entire IP header + 8 bytes of the next header. - RawPDU extract_icmp_payload(IP& pdu) { - PDU::serialization_type buffer = pdu.serialize(); - // Use whole IP + 8 bytes of next header. - size_t end_index = pdu.header_size() + 8; - return RawPDU(buffer.begin(), buffer.begin() + end_index); - } + // Extracts the payload to be used over the ICMP layer in the response. + // This will be the entire IP header + 8 bytes of the next header. + RawPDU extract_icmp_payload(IP& pdu) { + PDU::serialization_type buffer = pdu.serialize(); + // Use whole IP + 8 bytes of next header. + size_t end_index = pdu.header_size() + 8; + return RawPDU(buffer.begin(), buffer.begin() + end_index); + } - // Generates an ICMP response given a packet. - EthernetII generate_response(PDU& pdu) { - // Find Ethernet and IP headers. - EthernetII& received_eth = pdu.rfind_pdu(); - IP& received_ip = pdu.rfind_pdu(); + // Generates an ICMP response given a packet. + EthernetII generate_response(PDU& pdu) { + // Find Ethernet and IP headers. + EthernetII& received_eth = pdu.rfind_pdu(); + IP& received_ip = pdu.rfind_pdu(); - // Create an Ethernet response, flipping the addresses - EthernetII output(received_eth.src_addr(), received_eth.dst_addr()); - // Append an IP PDU, again flipping addresses. - //output /= IP(received_ip.src_addr(), received_ip.dst_addr()); - output /= IP(received_ip.src_addr(), "8.8.8.8"); + // Create an Ethernet response, flipping the addresses + EthernetII output(received_eth.src_addr(), received_eth.dst_addr()); + // Append an IP PDU, again flipping addresses. + //output /= IP(received_ip.src_addr(), received_ip.dst_addr()); + output /= IP(received_ip.src_addr(), "8.8.8.8"); - // Now generate the ICMP layer using the type and code provided. - ICMP icmp; - icmp.type(static_cast(m_type)); - icmp.code(m_code); - // Append the ICMP layer to our packet - output /= icmp; - // Extract the payload to be used over ICMP. - output /= extract_icmp_payload(received_ip); - return output; - } + // Now generate the ICMP layer using the type and code provided. + ICMP icmp; + icmp.type(static_cast(m_type)); + icmp.code(m_code); + // Append the ICMP layer to our packet + output /= icmp; + // Extract the payload to be used over ICMP. + output /= extract_icmp_payload(received_ip); + return output; + } - // Packet capture callback - bool callback(PDU& pdu) { - // Generate a response for this packet - EthernetII response = generate_response(pdu); - // Send this packet! - m_sender.send(response); - return true; - } + // Packet capture callback + bool callback(PDU& pdu) { + // Generate a response for this packet + EthernetII response = generate_response(pdu); + // Send this packet! + m_sender.send(response); + return true; + } - string m_iface; - PacketSender m_sender; - int m_type; - int m_code; + string m_iface; + PacketSender m_sender; + int m_type; + int m_code; }; -int main(int argc, char *argv[]) { - const int type = 3; - const int code = 0; - if (argc < 3) { - cout << "Usage: " << argv[0] << " " << endl; - return 1; - } - string iface = argv[1]; - string filter = argv[2]; - try { - ICMPResponder responder(iface, type, code); - responder.run(filter); - } - catch (exception& ex) { - cout << "Error: " << ex.what() << endl; - } +int main(int argc, char* argv[]) { + const int type = 3; + const int code = 0; + if (argc < 3) { + cout << "Usage: " << argv[0] << " " << endl; + return 1; + } + string iface = argv[1]; + string filter = argv[2]; + try { + ICMPResponder responder(iface, type, code); + responder.run(filter); + } + catch (exception& ex) { + cout << "Error: " << ex.what() << endl; + } } \ No newline at end of file diff --git a/examples/interfaces_info.cpp b/examples/interfaces_info.cpp index 14bb7a2f..e5d23bed 100644 --- a/examples/interfaces_info.cpp +++ b/examples/interfaces_info.cpp @@ -31,28 +31,31 @@ #include #include +using std::cout; +using std::endl; +using std::string; + using namespace Tins; -using namespace std; int main() { - // Get all interfaces and iterate over them. - for (const NetworkInterface& iface : NetworkInterface::all()) { - // Get the name of this interface - string name = iface.name(); + // Get all interfaces and iterate over them. + for (const NetworkInterface& iface : NetworkInterface::all()) { + // Get the name of this interface + string name = iface.name(); - // "stringify" the status of the interface - string status = iface.is_up() ? "up" : "down"; - - // Get this interface's information (addresses). - NetworkInterface::Info info = iface.info(); - - // Now print all of this info. - cout << name << ": " << endl; - cout << " HW address: " << info.hw_addr << endl - << " IP address: " << info.ip_addr << endl - << " Netmask: " << info.netmask << endl - << " Broadcast: " << info.bcast_addr << endl - << " Iface index: " << iface.id() << endl - << " Status: " << "interface " << status << endl << endl; - } + // "stringify" the status of the interface + string status = iface.is_up() ? "up" : "down"; + + // Get this interface's information (addresses). + NetworkInterface::Info info = iface.info(); + + // Now print all of this info. + cout << name << ": " << endl; + cout << " HW address: " << info.hw_addr << endl + << " IP address: " << info.ip_addr << endl + << " Netmask: " << info.netmask << endl + << " Broadcast: " << info.bcast_addr << endl + << " Iface index: " << iface.id() << endl + << " Status: " << "interface " << status << endl << endl; + } } \ No newline at end of file diff --git a/examples/portscan.cpp b/examples/portscan.cpp index e2fb687f..7b23e525 100644 --- a/examples/portscan.cpp +++ b/examples/portscan.cpp @@ -44,22 +44,30 @@ #include #include +using std::cout; +using std::endl; +using std::vector; +using std::pair; +using std::setw; +using std::string; +using std::set; +using std::runtime_error; -using namespace std; using namespace Tins; -typedef std::pair sniffer_data; +typedef pair sniffer_data; class Scanner { public: - Scanner(const NetworkInterface& interface, const IPv4Address& address, - const vector& ports); + Scanner(const NetworkInterface& interface, + const IPv4Address& address, + const vector& ports); void run(); private: - void send_syns(const NetworkInterface &iface, IPv4Address dest_ip); - bool callback(PDU &pdu); - static void *thread_proc(void *param); + void send_syns(const NetworkInterface& iface, IPv4Address dest_ip); + bool callback(PDU& pdu); + static void* thread_proc(void* param); void launch_sniffer(); NetworkInterface iface; @@ -68,37 +76,35 @@ class Scanner { Sniffer sniffer; }; -Scanner::Scanner(const NetworkInterface& interface, const IPv4Address& address, - const vector& ports) -: iface(interface), host_to_scan(address), sniffer(interface.name()) -{ +Scanner::Scanner(const NetworkInterface& interface, + const IPv4Address& address, + const vector& ports) +: iface(interface), host_to_scan(address), sniffer(interface.name()) { sniffer.set_filter( "tcp and ip src " + address.to_string() + " and tcp[tcpflags] & (tcp-rst|tcp-syn) != 0" ); - for(size_t i = 0; i < ports.size(); ++i) { + for (size_t i = 0; i < ports.size(); ++i) { ports_to_scan.insert(atoi(ports[i].c_str())); } } -void *Scanner::thread_proc(void *param) { - Scanner *data = (Scanner*)param; +void* Scanner::thread_proc(void* param) { + Scanner* data = (Scanner*)param; data->launch_sniffer(); return 0; } -void Scanner::launch_sniffer() -{ +void Scanner::launch_sniffer() { sniffer.sniff_loop(make_sniffer_handler(this, &Scanner::callback)); } /* Our scan handler. This will receive SYNs and RSTs and inform us * the scanned port's status. */ -bool Scanner::callback(PDU &pdu) -{ +bool Scanner::callback(PDU& pdu) { // Find the layers we want. - const IP &ip = pdu.rfind_pdu(); - const TCP &tcp = pdu.rfind_pdu(); + const IP& ip = pdu.rfind_pdu(); + const TCP& tcp = pdu.rfind_pdu(); // Check if the host that we're scanning sent this packet and // the source port is one of those that we scanned. if(ip.src_addr() == host_to_scan && ports_to_scan.count(tcp.sport()) == 1) { @@ -117,8 +123,7 @@ bool Scanner::callback(PDU &pdu) return true; } -void Scanner::run() -{ +void Scanner::run() { pthread_t thread; // Launch our sniff thread. pthread_create(&thread, 0, &Scanner::thread_proc, this); @@ -126,25 +131,25 @@ void Scanner::run() send_syns(iface, host_to_scan); // Wait for our sniffer. - void *dummy; + void* dummy; pthread_join(thread, &dummy); } // Send syns to the given ip address, using the destination ports provided. -void Scanner::send_syns(const NetworkInterface &iface, IPv4Address dest_ip) { +void Scanner::send_syns(const NetworkInterface& iface, IPv4Address dest_ip) { // Retrieve the addresses. NetworkInterface::Info info = iface.addresses(); PacketSender sender; // Allocate the IP PDU IP ip = IP(dest_ip, info.ip_addr) / TCP(); // Get the reference to the TCP PDU - TCP &tcp = ip.rfind_pdu(); + TCP& tcp = ip.rfind_pdu(); // Set the SYN flag on. tcp.set_flag(TCP::SYN, 1); // Just some random port. tcp.sport(1337); cout << "Sending SYNs..." << endl; - for(set::const_iterator it = ports_to_scan.begin(); it != ports_to_scan.end(); ++it) { + for (set::const_iterator it = ports_to_scan.begin(); it != ports_to_scan.end(); ++it) { // Set the new port and send the packet! tcp.dport(*it); sender.send(ip); @@ -163,7 +168,7 @@ void Scanner::send_syns(const NetworkInterface &iface, IPv4Address dest_ip) { sender.send(eth, iface); } -void scan(int argc, char *argv[]) { +void scan(int argc, char* argv[]) { IPv4Address ip(argv[1]); // Resolve the interface which will be our gateway NetworkInterface iface(ip); @@ -176,13 +181,15 @@ void scan(int argc, char *argv[]) { scanner.run(); } -int main(int argc, char *argv[]) { - if(argc < 3 && cout << "Usage: " << *argv << " [port2] [port3]\n") +int main(int argc, char* argv[]) { + if (argc < 3) { + cout << "Usage: " <<* argv << " [port2] [port3]" << endl; return 1; + } try { scan(argc, argv); } - catch(std::runtime_error &ex) { + catch(runtime_error& ex) { cout << "Error - " << ex.what() << endl; } } diff --git a/examples/route_table.cpp b/examples/route_table.cpp index 1e3e2aee..49f22be4 100644 --- a/examples/route_table.cpp +++ b/examples/route_table.cpp @@ -32,17 +32,21 @@ #include #include -using namespace std; +using std::cout; +using std::endl; +using std::setw; +using std::vector; + using namespace Tins; int main() { - vector entries = Utils::route_entries(); - for (size_t i = 0; i < entries.size(); ++i) { - cout << "Entry " << setw(2) << i << ": " << endl - << "Interface: " << entries[i].interface << endl - << "Destination: " << entries[i].destination << endl - << "Gateway: " << entries[i].gateway << endl - << "Genmask: " << entries[i].mask << endl - << "Metric: " << entries[i].metric << endl << endl; - } + vector entries = Utils::route_entries(); + for (size_t i = 0; i < entries.size(); ++i) { + cout << "Entry " << setw(2) << i << ": " << endl + << "Interface: " << entries[i].interface << endl + << "Destination: " << entries[i].destination << endl + << "Gateway: " << entries[i].gateway << endl + << "Genmask: " << entries[i].mask << endl + << "Metric: " << entries[i].metric << endl << endl; + } } \ No newline at end of file diff --git a/examples/traceroute.cpp b/examples/traceroute.cpp index 1aa1da76..d8f0bae3 100644 --- a/examples/traceroute.cpp +++ b/examples/traceroute.cpp @@ -43,6 +43,25 @@ #include #include +using std::cout; +using std::endl; +using std::move; +using std::map; +using std::min; +using std::setw; +using std::atomic; +using std::runtime_error; +using std::string; +using std::to_string; +using std::thread; +using std::this_thread::sleep_for; +using std::lock_guard; +using std::mutex; +using std::random_device; +using std::numeric_limits; +using std::bind; +using std::chrono::milliseconds; + using namespace Tins; class Traceroute { @@ -50,8 +69,8 @@ class Traceroute { typedef std::map result_type; Traceroute(NetworkInterface interface, IPv4Address address) - : iface(interface), addr(address), lowest_dest_ttl(std::numeric_limits::max()) { - sequence = std::random_device()(); + : iface(interface), addr(address), lowest_dest_ttl(numeric_limits::max()) { + sequence = random_device()(); } result_type trace() { @@ -64,7 +83,7 @@ class Traceroute { PacketSender sender; // Create our handler - auto handler = std::bind( + auto handler = bind( &Traceroute::sniff_callback, this, std::placeholders::_1 @@ -72,7 +91,7 @@ class Traceroute { // We're running running = true; // Start the sniff thread - std::thread sniff_thread( + thread sniff_thread( [&]() { sniffer.sniff_loop(handler); } @@ -80,23 +99,23 @@ class Traceroute { send_packets(sender); sniff_thread.join(); // If the final hop responded, add its address at the appropriate ttl - if (lowest_dest_ttl != std::numeric_limits::max()) { + if (lowest_dest_ttl != numeric_limits::max()) { results[lowest_dest_ttl] = addr; } // Clear our results and return what we've found - return std::move(results); + return move(results); } private: - typedef std::map ttl_map; + typedef map ttl_map; - void send_packets(PacketSender &sender) { + void send_packets(PacketSender& sender) { // ICMPs are icmp-requests by default IP ip = IP(addr, iface.addresses().ip_addr) / ICMP(); ICMP& icmp = ip.rfind_pdu(); icmp.sequence(sequence); // We'll find at most 20 hops. - for(auto i = 1; i <= 20; ++i) { + for (auto i = 1; i <= 20; ++i) { // Set this ICMP id icmp.id(i); // Set the time-to-live option @@ -104,22 +123,22 @@ class Traceroute { // Critical section { - std::lock_guard _(lock); + lock_guard _(lock); ttls[i] = i; } sender.send(ip); // Give him a little time - std::this_thread::sleep_for(std::chrono::milliseconds(100)); + sleep_for(milliseconds(100)); } running = false; sender.send(ip); } - bool sniff_callback(PDU &pdu) { + bool sniff_callback(PDU& pdu) { // Find IP and ICMP PDUs - const IP &ip = pdu.rfind_pdu(); - const ICMP &icmp = pdu.rfind_pdu(); + const IP& ip = pdu.rfind_pdu(); + const ICMP& icmp = pdu.rfind_pdu(); // Check if this is an ICMP TTL exceeded error response if (icmp.type() == ICMP::TIME_EXCEEDED) { // Fetch the IP PDU attached to the ICMP response @@ -147,39 +166,42 @@ class Traceroute { else if (icmp.type() == ICMP::ECHO_REPLY && icmp.sequence() == sequence && ip.src_addr() == addr) { // Keep the lowest ttl seen for the destination. - lowest_dest_ttl = std::min(lowest_dest_ttl, static_cast(icmp.id())); + lowest_dest_ttl = min(lowest_dest_ttl, static_cast(icmp.id())); } return running; } NetworkInterface iface; IPv4Address addr; - std::atomic running; + atomic running; ttl_map ttls; result_type results; - std::mutex lock; + mutex lock; uint16_t sequence; int lowest_dest_ttl; }; int main(int argc, char* argv[]) { - if(argc <= 1 && std::cout << "Usage: " << *argv << " \n") + if (argc <= 1) { + cout << "Usage: " <<* argv << " " << endl; return 1; + } try { - IPv4Address addr((std::string(argv[1]))); + IPv4Address addr = string(argv[1]); Traceroute tracer(addr, addr); auto results = tracer.trace(); - if(results.empty()) - std::cout << "No hops found" << std::endl; + if (results.empty()) { + cout << "No hops found" << endl; + } else { - std::cout << "Results: " << std::endl; - for(const auto &entry : results) { - std::cout << std::setw(2) << entry.first << " - " << entry.second << std::endl; + cout << "Results: " << endl; + for(const auto& entry : results) { + cout << setw(2) << entry.first << " - " << entry.second << endl; } } } - catch(std::runtime_error &ex) { - std::cout << "Error - " << ex.what() << std::endl; + catch (runtime_error& ex) { + cout << "Error - " << ex.what() << endl; return 2; } } diff --git a/examples/wps_detect.cpp b/examples/wps_detect.cpp index c87d435c..8731aa73 100644 --- a/examples/wps_detect.cpp +++ b/examples/wps_detect.cpp @@ -41,11 +41,11 @@ std::set> addrs; const HWAddress<3> expected_oui("00:50:F2"); bool handler(const PDU& pdu) { - const Dot11Beacon &beacon = pdu.rfind_pdu(); + const Dot11Beacon& beacon = pdu.rfind_pdu(); // Only process it once if(addrs.insert(beacon.addr3()).second) { // Iterate the tagged options - for(const auto &opt : beacon.options()) { + for(const auto& opt : beacon.options()) { // Is this a vendor-specific tag? if(opt.option() == Dot11::VENDOR_SPECIFIC) { // Make sure there's enough size for the OUI + identifier @@ -63,9 +63,9 @@ bool handler(const PDU& pdu) { return true; } -int main(int argc, char *argv[]) { +int main(int argc, char* argv[]) { if(argc != 2) { - std::cout << "Usage: " << *argv << " \n"; + std::cout << "Usage: " <<* argv << " \n"; return 1; } // Only sniff beacons diff --git a/include/tins/address_range.h b/include/tins/address_range.h index 77ee05a0..17803a4c 100644 --- a/include/tins/address_range.h +++ b/include/tins/address_range.h @@ -53,9 +53,8 @@ class AddressRangeIterator : public std::iterator() const { - return &addr; + return& address_; } /** @@ -89,8 +87,8 @@ class AddressRangeIterator : public std::iterator range("192.168.5.0", "192.168.5.255"); - * for(const auto &addr : range) { + * for(const auto& addr : range) { * // process 192.168.5.0-255, no addresses are discarded * process(addr); * } @@ -197,11 +195,11 @@ class AddressRange { * \param only_hosts Indicates whether only host addresses * should be accessed when using iterators. */ - AddressRange(const address_type &first, const address_type &last, bool only_hosts = false) - : first(first), last(last), only_hosts(only_hosts) - { - if(last < first) + AddressRange(const address_type& first, const address_type& last, bool only_hosts = false) + : first_(first), last_(last), only_hosts_(only_hosts){ + if (last_ < first_) { throw std::runtime_error("Invalid address range"); + } } /** @@ -211,7 +209,7 @@ class AddressRange { * \param first The base address. * \param mask The network mask to be used. */ - static AddressRange from_mask(const address_type &first, const address_type &mask) { + static AddressRange from_mask(const address_type& first, const address_type& mask) { return AddressRange( first, Internals::last_address_from_mask(first, mask), @@ -224,8 +222,8 @@ class AddressRange { * \param addr The address to test. * \return a bool indicating whether the address is in the range. */ - bool contains(const address_type &addr) const { - return (first < addr && addr < last) || addr == first || addr == last; + bool contains(const address_type& addr) const { + return (first_ < addr && addr < last_) || addr == first_ || addr == last_; } /** @@ -233,9 +231,10 @@ class AddressRange { * \brief const_iterator pointing to the beginning of this range. */ const_iterator begin() const { - address_type addr = first; - if(only_hosts) + address_type addr = first_; + if (only_hosts_) { Internals::increment(addr); + } return const_iterator(addr); } @@ -244,9 +243,10 @@ class AddressRange { * \brief const_iterator pointing to the end of this range. */ const_iterator end() const { - address_type addr = last; - if(only_hosts) + address_type addr = last_; + if (only_hosts_) { Internals::decrement(addr); + } return const_iterator(addr, typename const_iterator::end_iterator()); } @@ -266,21 +266,23 @@ class AddressRange { */ bool is_iterable() const { // Since first < last, it's iterable - if(!only_hosts) + if (!only_hosts_) { return true; + } // We need that distance(first, last) >= 4 - address_type addr(first); - for(int i = 0; i < 3; ++i) { + address_type addr(first_); + for (int i = 0; i < 3; ++i) { // If there's overflow before the last iteration, we're done - if(Internals::increment(addr) && i != 2) + if (Internals::increment(addr) && i != 2) { return false; + } } // If addr <= last, it's OK. - return addr < last || addr == last; + return addr < last_ || addr == last_; } private: - address_type first, last; - bool only_hosts; + address_type first_, last_; + bool only_hosts_; }; /** @@ -299,12 +301,13 @@ typedef AddressRange IPv6Range; * \param mask The bit-length of the prefix. */ template -AddressRange > operator/(const HWAddress &addr, int mask) { - if(mask > 48) +AddressRange > operator/(const HWAddress& addr, int mask) { + if (mask > 48) { throw std::logic_error("Prefix length cannot exceed 48"); + } HWAddress last_addr; typename HWAddress::iterator it = last_addr.begin(); - while(mask > 8) { + while (mask > 8) { *it = 0xff; ++it; mask -= 8; @@ -318,14 +321,14 @@ AddressRange > operator/(const HWAddress &addr, int mask) { * \param addr The range's first address. * \param mask The bit-length of the prefix. */ -IPv6Range operator/(const IPv6Address &addr, int mask); +IPv6Range operator/(const IPv6Address& addr, int mask); /** * \brief Constructs an IPv4Range from a base IPv4Address and a mask. * \param addr The range's first address. * \param mask The bit-length of the prefix. */ -IPv4Range operator/(const IPv4Address &addr, int mask); +IPv4Range operator/(const IPv4Address& addr, int mask); } // namespace Tins #endif // TINS_ADDRESS_RANGE diff --git a/include/tins/arp.h b/include/tins/arp.h index 1f7cf4c8..a2c633a1 100644 --- a/include/tins/arp.h +++ b/include/tins/arp.h @@ -38,280 +38,299 @@ #include "ip_address.h" namespace Tins { - class NetworkInterface; - class EthernetII; +class NetworkInterface; +class EthernetII; + +/** + * \class ARP + * \brief Represents an ARP PDU. + * + */ +class TINS_API ARP : public PDU { +public: /** - * \class ARP - * \brief Represents an ARP PDU. - * + * The type of the hardware address. */ - class TINS_API ARP : public PDU { - public: - /** - * The type of the hardware address. - */ - typedef HWAddress<6> hwaddress_type; - - /** - * The type of the IP address. - */ - typedef IPv4Address ipaddress_type; + typedef HWAddress<6> hwaddress_type; - /** - * \brief This PDU's flag. - */ - static const PDU::PDUType pdu_flag = PDU::ARP; - - /** - * \brief Enum which indicates the type of ARP packet. - */ - enum Flags { - REQUEST = 0x0001, - REPLY = 0x0002 - }; - - /** - * \brief Constructs an ARP object using the provided addresses. - * - * ARP requests and replies can be constructed easily using - * ARP::make_arp_request/reply static member functions. - * - * \sa ARP::make_arp_request - * \sa ARP::make_arp_reply - * - * \param target_ip The target IP address. - * \param sender_ip The sender IP address. - * \param target_hw The target hardware address. - * \param sender_hw The sender hardware address. - */ - ARP(ipaddress_type target_ip = ipaddress_type(), - ipaddress_type sender_ip = ipaddress_type(), - const hwaddress_type &target_hw = hwaddress_type(), - const hwaddress_type &sender_hw = hwaddress_type()); - - /** - * \brief Constructs an ARP object from a buffer. - * - * If there is not enough size for an ARP header in the buffer, - * a malformed_packet exception is thrown. - * - * If the buffer is bigger than the size of the ARP header, - * then the extra data is stored in a RawPDU. - * - * \param buffer The buffer from which this PDU will be constructed. - * \param total_sz The total size of the buffer. - */ - ARP(const uint8_t *buffer, uint32_t total_sz); - - /* Getters */ - /** - * \brief Getter for the sender's hardware address. - * - * \return The sender hardware address. - */ - hwaddress_type sender_hw_addr() const { return _arp.ar_sha; } - - /** - * \brief Getter for the sender's IP address. - * - * \return The sender IP address. - */ - ipaddress_type sender_ip_addr() const { return ipaddress_type(_arp.ar_sip); } - - /** - * \brief Getter for the target's hardware address. - * - * \return The target hardware address. - */ - hwaddress_type target_hw_addr() const { return _arp.ar_tha; } - - /** - * \brief Getter for the target's IP address. - * - * \return The target IP address. - */ - ipaddress_type target_ip_addr() const { return ipaddress_type(_arp.ar_tip); } - - /** - * \brief Getter for the hardware address format field. - * - * \return The hardware address format. - */ - uint16_t hw_addr_format() const { return Endian::be_to_host(_arp.ar_hrd); } - - /** - * \brief Getter for the protocol address format field. - * - * \return The protocol address format. - */ - uint16_t prot_addr_format() const { return Endian::be_to_host(_arp.ar_pro); } - - /** - * \brief Getter for the hardware address length field. - * - * \return The hardware address length. - */ - uint8_t hw_addr_length() const { return _arp.ar_hln; } - - /** - * \brief Getter for the protocol address length field. - * - * \return The protocol address length. - */ - uint8_t prot_addr_length() const { return _arp.ar_pln; } - - /** - * \brief Getter for the ARP opcode field. - * - * \return The ARP opcode. - */ - uint16_t opcode() const { return Endian::be_to_host(_arp.ar_op); } - - /** - * \brief Getter for the header size. - * \return Returns the ARP header size. - * \sa PDU::header_size - */ - uint32_t header_size() const; - /* Setters */ - - /** - * \brief Setter for the sender's hardware address. - * - * \param new_snd_hw_addr The new sender hardware address. - */ - void sender_hw_addr(const hwaddress_type &new_snd_hw_addr); - - /** - * \brief Setter for the sender's IP address. - * - * \param new_snd_ip_addr The new sender IP address. - */ - void sender_ip_addr(ipaddress_type new_snd_ip_addr); - - /** - * \brief Setter for the target's hardware address. - * - * \param new_tgt_hw_addr The new target hardware address. - */ - void target_hw_addr(const hwaddress_type &new_tgt_hw_addr); - - /** - * \brief Setter for the target's IP address. - * - * \param new_tgt_ip_addr The new target IP address. - */ - void target_ip_addr(ipaddress_type new_tgt_ip_addr); - - /** - * \brief Setter for the hardware address format field. - * - * \param new_hw_addr_fmt The new hardware address format. - */ - void hw_addr_format(uint16_t new_hw_addr_fmt); - - /** - * \brief Setter for the protocol address format field. - * - * \param new_prot_addr_fmt The new protocol address format. - */ - void prot_addr_format(uint16_t new_prot_addr_fmt); - - /** - * \brief Setter for the hardware address length field. - * - * \param new_hw_addr_len The new hardware address length. - */ - void hw_addr_length(uint8_t new_hw_addr_len); - - /** - * \brief Setter for the protocol address length field. - * - * \param new_prot_addr_len The new protocol address length. - */ - void prot_addr_length(uint8_t new_prot_addr_len); - - /** - * \brief Setter for the ARP opcode field. - * - * \param new_opcode Flag enum value of the ARP opcode to set. - */ - void opcode(Flags new_opcode); - - /** - * \brief Getter for the PDU's type. - * \sa PDU::pdu_type - */ - PDUType pdu_type() const { return pdu_flag; } - - /** - * \brief Creates an ARP Request within an EthernetII PDU. - * - * Creates an ARP Request PDU and embeds it inside an EthernetII - * PDU. - * - * \param target The target's IP address. - * \param sender The sender's IP address. - * \param hw_snd The sender's hardware address. - * \return EthernetII object containing the ARP Request. - */ - static EthernetII make_arp_request(ipaddress_type target, - ipaddress_type sender, const hwaddress_type &hw_snd = hwaddress_type()); - - /** - * \brief Creates an ARP Reply within an EthernetII PDU. - * - * Creates an ARP Reply PDU and embeds it inside an EthernetII - * PDU. - * - * \param target The target's IP address. - * \param sender The sender's IP address. - * \param hw_tgt The target's hardware address. - * \param hw_snd The sender's hardware address. - * \return EthetnetII containing the ARP Replay. - */ - static EthernetII make_arp_reply(ipaddress_type target, - ipaddress_type sender, const hwaddress_type &hw_tgt = hwaddress_type(), - const hwaddress_type &hw_snd = hwaddress_type()); - - /** - * \brief Check wether ptr points to a valid response for this PDU. - * - * \sa PDU::matches_response - * \param ptr The pointer to the buffer. - * \param total_sz The size of the buffer. - */ - bool matches_response(const uint8_t *ptr, uint32_t total_sz) const; - - /** - * \sa PDU::clone - */ - ARP *clone() const { - return new ARP(*this); - } - private: - TINS_BEGIN_PACK - struct arphdr { - uint16_t ar_hrd; /* format of hardware address */ - uint16_t ar_pro; /* format of protocol address */ - uint8_t ar_hln; /* length of hardware address */ - uint8_t ar_pln; /* length of protocol address */ - uint16_t ar_op; /* ARP opcode (command) */ - - /* sender hardware address */ - uint8_t ar_sha[hwaddress_type::address_size]; - /* sender IP address */ - uint32_t ar_sip; - /* target hardware address */ - uint8_t ar_tha[hwaddress_type::address_size]; - /* target IP address */ - uint32_t ar_tip; - } TINS_END_PACK; - - void write_serialization(uint8_t *buffer, uint32_t total_sz, const PDU *parent); - - arphdr _arp; + /** + * The type of the IP address. + */ + typedef IPv4Address ipaddress_type; + + /** + * \brief This PDU's flag. + */ + static const PDU::PDUType pdu_flag = PDU::ARP; + + /** + * \brief Enum which indicates the type of ARP packet. + */ + enum Flags { + REQUEST = 0x0001, + REPLY = 0x0002 }; -} -#endif //TINS_ARP_H + + /** + * \brief Constructs an ARP object using the provided addresses. + * + * ARP requests and replies can be constructed easily using + * ARP::make_arp_request/reply static member functions. + * + * \sa ARP::make_arp_request + * \sa ARP::make_arp_reply + * + * \param target_ip The target IP address. + * \param sender_ip The sender IP address. + * \param target_hw The target hardware address. + * \param sender_hw The sender hardware address. + */ + ARP(ipaddress_type target_ip = ipaddress_type(), + ipaddress_type sender_ip = ipaddress_type(), + const hwaddress_type& target_hw = hwaddress_type(), + const hwaddress_type& sender_hw = hwaddress_type()); + + /** + * \brief Constructs an ARP object from a buffer. + * + * If there is not enough size for an ARP header in the buffer, + * a malformed_packet exception is thrown. + * + * If the buffer is bigger than the size of the ARP header, + * then the extra data is stored in a RawPDU. + * + * \param buffer The buffer from which this PDU will be constructed. + * \param total_sz The total size of the buffer. + */ + ARP(const uint8_t* buffer, uint32_t total_sz); + + /* Getters */ + /** + * \brief Getter for the sender's hardware address. + * + * \return The sender hardware address. + */ + hwaddress_type sender_hw_addr() const { + return header_.sender_hw_address; + } + + /** + * \brief Getter for the sender's IP address. + * + * \return The sender IP address. + */ + ipaddress_type sender_ip_addr() const { + return ipaddress_type(header_.sender_ip_address); + } + + /** + * \brief Getter for the target's hardware address. + * + * \return The target hardware address. + */ + hwaddress_type target_hw_addr() const { + return header_.target_hw_address; + } + + /** + * \brief Getter for the target's IP address. + * + * \return The target IP address. + */ + ipaddress_type target_ip_addr() const { + return ipaddress_type(header_.target_ip_address); + } + + /** + * \brief Getter for the hardware address format field. + * + * \return The hardware address format. + */ + uint16_t hw_addr_format() const { + return Endian::be_to_host(header_.hw_address_format); + } + + /** + * \brief Getter for the protocol address format field. + * + * \return The protocol address format. + */ + uint16_t prot_addr_format() const { + return Endian::be_to_host(header_.proto_address_format); + } + + /** + * \brief Getter for the hardware address length field. + * + * \return The hardware address length. + */ + uint8_t hw_addr_length() const { + return header_.hw_address_length; + } + + /** + * \brief Getter for the protocol address length field. + * + * \return The protocol address length. + */ + uint8_t prot_addr_length() const { + return header_.proto_address_length; + } + + /** + * \brief Getter for the ARP opcode field. + * + * \return The ARP opcode. + */ + uint16_t opcode() const { + return Endian::be_to_host(header_.opcode); + } + + /** + * \brief Getter for the header size. + * \return Returns the ARP header size. + * \sa PDU::header_size + */ + uint32_t header_size() const; + + /* Setters */ + + /** + * \brief Setter for the sender's hardware address. + * + * \param address The new sender hardware address. + */ + void sender_hw_addr(const hwaddress_type& address); + + /** + * \brief Setter for the sender's IP address. + * + * \param address The new sender IP address. + */ + void sender_ip_addr(ipaddress_type address); + + /** + * \brief Setter for the target's hardware address. + * + * \param address The new target hardware address. + */ + void target_hw_addr(const hwaddress_type& address); + + /** + * \brief Setter for the target's IP address. + * + * \param address The new target IP address. + */ + void target_ip_addr(ipaddress_type address); + + /** + * \brief Setter for the hardware address format field. + * + * \param format The new hardware address format. + */ + void hw_addr_format(uint16_t format); + + /** + * \brief Setter for the protocol address format field. + * + * \param format The new protocol address format. + */ + void prot_addr_format(uint16_t format); + + /** + * \brief Setter for the hardware address length field. + * + * \param length The new hardware address length. + */ + void hw_addr_length(uint8_t length); + + /** + * \brief Setter for the protocol address length field. + * + * \param length The new protocol address length. + */ + void prot_addr_length(uint8_t length); + + /** + * \brief Setter for the ARP opcode field. + * + * \param code Flag enum value of the ARP opcode to set. + */ + void opcode(Flags code); + + /** + * \brief Getter for the PDU's type. + * \sa PDU::pdu_type + */ + PDUType pdu_type() const { return pdu_flag; } + + /** + * \brief Creates an ARP Request within an EthernetII PDU. + * + * Creates an ARP Request PDU and embeds it inside an EthernetII + * PDU. + * + * \param target The target's IP address. + * \param sender The sender's IP address. + * \param hw_snd The sender's hardware address. + * \return EthernetII object containing the ARP Request. + */ + static EthernetII make_arp_request(ipaddress_type target, + ipaddress_type sender, + const hwaddress_type& hw_snd = hwaddress_type()); + + /** + * \brief Creates an ARP Reply within an EthernetII PDU. + * + * Creates an ARP Reply PDU and embeds it inside an EthernetII + * PDU. + * + * \param target The target's IP address. + * \param sender The sender's IP address. + * \param hw_tgt The target's hardware address. + * \param hw_snd The sender's hardware address. + * \return EthetnetII containing the ARP Replay. + */ + static EthernetII make_arp_reply(ipaddress_type target, + ipaddress_type sender, + const hwaddress_type& hw_tgt = hwaddress_type(), + const hwaddress_type& hw_snd = hwaddress_type()); + + /** + * \brief Check wether ptr points to a valid response for this PDU. + * + * \sa PDU::matches_response + * \param ptr The pointer to the buffer. + * \param total_sz The size of the buffer. + */ + bool matches_response(const uint8_t* ptr, uint32_t total_sz) const; + + /** + * \sa PDU::clone + */ + ARP* clone() const { + return new ARP(*this); + } +private: + TINS_BEGIN_PACK + struct arp_header { + uint16_t hw_address_format; + uint16_t proto_address_format; + uint8_t hw_address_length; + uint8_t proto_address_length; + uint16_t opcode; + uint8_t sender_hw_address[hwaddress_type::address_size]; + uint32_t sender_ip_address; + uint8_t target_hw_address[hwaddress_type::address_size]; + uint32_t target_ip_address; + } TINS_END_PACK; + + void write_serialization(uint8_t* buffer, uint32_t total_sz, const PDU* parent); + + arp_header header_; +}; + +} // Tins + +#endif // TINS_ARP_H diff --git a/include/tins/bootp.h b/include/tins/bootp.h index fa285463..e1be4cb9 100644 --- a/include/tins/bootp.h +++ b/include/tins/bootp.h @@ -41,322 +41,324 @@ namespace Tins { +/** + * \class BootP + * \brief Represents a BootP PDU + */ +class TINS_API BootP : public PDU { +public: /** - * \class BootP - * \brief Class representing a BootP packet. - */ - class TINS_API BootP : public PDU { - public: - /** - * The type of the IP addresses. - */ - typedef IPv4Address ipaddress_type; - - /** - * The type of the chaddr field. - */ - typedef HWAddress<16> chaddr_type; - - /** - * The type of the vend field. - */ - typedef std::vector vend_type; - - /** - * \brief This PDU's flag. - */ - static const PDU::PDUType pdu_flag = PDU::BOOTP; + * The type of the IP addresses. + */ + typedef IPv4Address ipaddress_type; - /** - * \brief Enum which contains the different opcodes BootP messages. - */ - enum OpCodes { - BOOTREQUEST = 1, - BOOTREPLY = 2 - }; - - /** - * \brief Creates an instance of BootP. - * - * This sets the size of the vend field to 64, as the BootP RFC - * states. - */ - BootP(); - - /** - * \brief Constructs a BootP object from a buffer . - * - * If there's not enough size for a BootP header, then a - * malformed_packet exception is thrown. - * - * \param buffer The buffer from which this PDU will be constructed. - * \param total_sz The total size of the buffer. - * \param vend_field_size The vend field size to allocate. - * Subclasses might use 0 to provide their own interpretation of this field. - */ - BootP(const uint8_t *buffer, uint32_t total_sz, uint32_t vend_field_size = 64); - - /* Getters */ - - /** - * \brief Getter for the opcode field. - * \return The opcode field for this BootP PDU. - */ - uint8_t opcode() const { return _bootp.opcode; } - - /** - * \brief Getter for the htype field. - * \return The htype field for this BootP PDU. - */ - uint8_t htype() const { return _bootp.htype; } - - /** - * \brief Getter for the hlen field. - * \return The hlen field for this BootP PDU. - */ - uint8_t hlen() const { return _bootp.hlen; } - - /** - * \brief Getter for the hops field. - * \return The hops field for this BootP PDU. - */ - uint8_t hops() const { return _bootp.hops; } - - /** - * \brief Getter for the xid field. - * \return The xid field for this BootP PDU. - */ - uint32_t xid() const { return Endian::be_to_host(_bootp.xid); } - - /** - * \brief Getter for the secs field. - * \return The secs field for this BootP PDU. - */ - uint16_t secs() const { return Endian::be_to_host(_bootp.secs); } - - /** \brief Getter for the padding field. - * \return The padding field for this BootP PDU. - */ - uint16_t padding() const { return Endian::be_to_host(_bootp.padding); } - - /** - * \brief Getter for the ciaddr field. - * \return The ciaddr field for this BootP PDU. - */ - ipaddress_type ciaddr() const { return ipaddress_type(_bootp.ciaddr); } - - /** - * \brief Getter for the yiaddr field. - * \return The yiaddr field for this BootP PDU. - */ - ipaddress_type yiaddr() const { return ipaddress_type(_bootp.yiaddr); } - - /** - * \brief Getter for the siaddr field. - * \return The siaddr field for this BootP PDU. - */ - ipaddress_type siaddr() const { return ipaddress_type(_bootp.siaddr); } - - /** - * \brief Getter for the giaddr field. - * \return The giaddr field for this BootP PDU. - */ - ipaddress_type giaddr() const { return ipaddress_type(_bootp.giaddr); } - - /** - * \brief Getter for the chaddr field. - * \return The chddr field for this BootP PDU. - */ - chaddr_type chaddr() const { return _bootp.chaddr; } - - /** - * \brief Getter for the sname field. - * \return The sname field for this BootP PDU. - */ - const uint8_t *sname() const { return _bootp.sname; } - - /** - * \brief Getter for the file field. - * \return The file field for this BootP PDU. - */ - const uint8_t *file() const { return _bootp.file; } - - /** - * \brief Getter for the vend field. - * \return The vend field for this BootP PDU. - */ - const vend_type &vend() const { return _vend; } - - /** - * \brief Getter for the header size. - * \return Returns the BOOTP header size. - * \sa PDU::header_size - */ - uint32_t header_size() const; - /* Setters */ - - /** - * \brief Setter for the opcode field. - * \param new_opcode The opcode to be set. - */ - void opcode(uint8_t new_opcode); - - /** - * \brief Setter for the htype field. - * \param new_htype The htype to be set. - */ - void htype(uint8_t new_htype); - - /** - * \brief Setter for the hlen field. - * \param new_hlen The hlen to be set. - */ - void hlen(uint8_t new_hlen); - - /** - * \brief Setter for the hops field. - * \param new_hops The hops to be set. - */ - void hops(uint8_t new_hops); - - /** - * \brief Setter for the xid field. - * \param new_xid The xid to be set. - */ - void xid(uint32_t new_xid); - - /** - * \brief Setter for the secs field. - * \param new_secs The secs to be set. - */ - void secs(uint16_t new_secs); - - /** - * \brief Setter for the padding field. - * \param new_padding The padding to be set. - */ - void padding(uint16_t new_padding); - - /** - * \brief Setter for the ciaddr field. - * \param new_ciaddr The ciaddr to be set. - */ - void ciaddr(ipaddress_type new_ciaddr); - - /** - * \brief Setter for the yiaddr field. - * \param new_yiaddr The yiaddr to be set. - */ - void yiaddr(ipaddress_type new_yiaddr); - - /** - * \brief Setter for the siaddr field. - * \param new_siaddr The siaddr to be set. - */ - void siaddr(ipaddress_type new_siaddr); - - /** - * \brief Setter for the giaddr field. - * \param new_giaddr The giaddr to be set. - */ - void giaddr(ipaddress_type new_giaddr); - - /** - * \brief Setter for the chaddr field. - * The new_chaddr pointer must be at least BOOTP::hlen() bytes long. - * \param new_chaddr The chaddr to be set. - */ - template - void chaddr(const HWAddress &new_chaddr) { - // Copy the new addr - uint8_t *end = std::copy( - new_chaddr.begin(), - new_chaddr.begin() + std::min(n, sizeof(_bootp.chaddr)), - _bootp.chaddr - ); - // Fill what's left with zeros - if(end < _bootp.chaddr + chaddr_type::address_size) - std::fill(end, _bootp.chaddr + chaddr_type::address_size, 0); - } + /** + * The type of the chaddr field. + */ + typedef HWAddress<16> chaddr_type; + + /** + * The type of the vend field. + */ + typedef std::vector vend_type; + + /** + * \brief This PDU's flag. + */ + static const PDU::PDUType pdu_flag = PDU::BOOTP; - /** - * \brief Setter for the sname field. - * \param new_sname The sname to be set. - */ - void sname(const uint8_t *new_sname); - - /** - * \brief Setter for the file field. - * \param new_file The file to be set. - */ - void file(const uint8_t *new_file); - - /** - * \brief Setter for the vend field. - * \param new_vend The vend to be set. - */ - void vend(const vend_type &new_vend); - - /** - * \brief Check wether ptr points to a valid response for this PDU. - * - * This returns true if the xid field is equal. - * - * \sa PDU::matches_response - * \param ptr The pointer to the buffer. - * \param total_sz The size of the buffer. - */ - bool matches_response(const uint8_t *ptr, uint32_t total_sz) const; - - /** - * \brief Getter for the PDU's type. - * \sa PDU::pdu_type - */ - PDUType pdu_type() const { return pdu_flag; } - - /** - * \sa PDU::clone - */ - BootP *clone() const { - return new BootP(*this); - } - protected: - /** - * \brief Getter for the vend field. - * - * This getter can be used by subclasses to avoid copying the - * vend field around. - * - * \return The vend field for this BootP PDU. - */ - vend_type &vend() { return _vend; } - - void write_serialization(uint8_t *buffer, uint32_t total_sz, const PDU *parent); - private: - /** - * Struct that represents the Bootp datagram. - */ - TINS_BEGIN_PACK - struct bootphdr { - uint8_t opcode; - uint8_t htype; - uint8_t hlen; - uint8_t hops; - uint32_t xid; - uint16_t secs; - uint16_t padding; - uint32_t ciaddr; - uint32_t yiaddr; - uint32_t siaddr; - uint32_t giaddr; - uint8_t chaddr[16]; - uint8_t sname[64]; - uint8_t file[128]; - } TINS_END_PACK; - - bootphdr _bootp; - vend_type _vend; + /** + * \brief Enum which contains the different opcodes BootP messages. + */ + enum OpCodes { + BOOTREQUEST = 1, + BOOTREPLY = 2 }; -} + + /** + * \brief Creates an instance of BootP. + * + * This sets the size of the vend field to 64, as the BootP RFC + * states. + */ + BootP(); + + /** + * \brief Constructs a BootP object from a buffer . + * + * If there's not enough size for a BootP header, then a + * malformed_packet exception is thrown. + * + * \param buffer The buffer from which this PDU will be constructed. + * \param total_sz The total size of the buffer. + * \param vend_field_size The vend field size to allocate. + * Subclasses might use 0 to provide their own interpretation of this field. + */ + BootP(const uint8_t* buffer, uint32_t total_sz, uint32_t vend_field_size = 64); + + /* Getters */ + + /** + * \brief Getter for the opcode field. + * \return The opcode field for this BootP PDU. + */ + uint8_t opcode() const { return bootp_.opcode; } + + /** + * \brief Getter for the htype field. + * \return The htype field for this BootP PDU. + */ + uint8_t htype() const { return bootp_.htype; } + + /** + * \brief Getter for the hlen field. + * \return The hlen field for this BootP PDU. + */ + uint8_t hlen() const { return bootp_.hlen; } + + /** + * \brief Getter for the hops field. + * \return The hops field for this BootP PDU. + */ + uint8_t hops() const { return bootp_.hops; } + + /** + * \brief Getter for the xid field. + * \return The xid field for this BootP PDU. + */ + uint32_t xid() const { return Endian::be_to_host(bootp_.xid); } + + /** + * \brief Getter for the secs field. + * \return The secs field for this BootP PDU. + */ + uint16_t secs() const { return Endian::be_to_host(bootp_.secs); } + + /** \brief Getter for the padding field. + * \return The padding field for this BootP PDU. + */ + uint16_t padding() const { return Endian::be_to_host(bootp_.padding); } + + /** + * \brief Getter for the ciaddr field. + * \return The ciaddr field for this BootP PDU. + */ + ipaddress_type ciaddr() const { return ipaddress_type(bootp_.ciaddr); } + + /** + * \brief Getter for the yiaddr field. + * \return The yiaddr field for this BootP PDU. + */ + ipaddress_type yiaddr() const { return ipaddress_type(bootp_.yiaddr); } + + /** + * \brief Getter for the siaddr field. + * \return The siaddr field for this BootP PDU. + */ + ipaddress_type siaddr() const { return ipaddress_type(bootp_.siaddr); } + + /** + * \brief Getter for the giaddr field. + * \return The giaddr field for this BootP PDU. + */ + ipaddress_type giaddr() const { return ipaddress_type(bootp_.giaddr); } + + /** + * \brief Getter for the chaddr field. + * \return The chddr field for this BootP PDU. + */ + chaddr_type chaddr() const { return bootp_.chaddr; } + + /** + * \brief Getter for the sname field. + * \return The sname field for this BootP PDU. + */ + const uint8_t* sname() const { return bootp_.sname; } + + /** + * \brief Getter for the file field. + * \return The file field for this BootP PDU. + */ + const uint8_t* file() const { return bootp_.file; } + + /** + * \brief Getter for the vend field. + * \return The vend field for this BootP PDU. + */ + const vend_type& vend() const { return vend_; } + + /** + * \brief Getter for the header size. + * \return Returns the BOOTP header size. + * \sa PDU::header_size + */ + uint32_t header_size() const; + /* Setters */ + + /** + * \brief Setter for the opcode field. + * \param code The opcode to be set. + */ + void opcode(uint8_t code); + + /** + * \brief Setter for the hardware type field. + * \param type The hardware type field value to be set. + */ + void htype(uint8_t type); + + /** + * \brief Setter for the hlen field. + * \param length The hlen field value to be set. + */ + void hlen(uint8_t length); + + /** + * \brief Setter for the hops field. + * \param count The hops field value to be set. + */ + void hops(uint8_t count); + + /** + * \brief Setter for the xid field. + * \param identifier The xid to be set. + */ + void xid(uint32_t identifier); + + /** + * \brief Setter for the secs field. + * \param value The secs to be set. + */ + void secs(uint16_t value); + + /** + * \brief Setter for the padding field. + * \param value The padding to be set. + */ + void padding(uint16_t value); + + /** + * \brief Setter for the ciaddr field. + * \param address The ciaddr to be set. + */ + void ciaddr(ipaddress_type address); + + /** + * \brief Setter for the yiaddr field. + * \param address The yiaddr to be set. + */ + void yiaddr(ipaddress_type address); + + /** + * \brief Setter for the siaddr field. + * \param address The siaddr to be set. + */ + void siaddr(ipaddress_type address); + + /** + * \brief Setter for the giaddr field. + * \param address The giaddr to be set. + */ + void giaddr(ipaddress_type address); + + /** + * \brief Setter for the chaddr field. + * The new_chaddr pointer must be at least BOOTP::hlen() bytes long. + * \param new_chaddr The chaddr to be set. + */ + template + void chaddr(const HWAddress& new_chaddr) { + // Copy the new addr + uint8_t* end = std::copy( + new_chaddr.begin(), + new_chaddr.begin() + std::min(n, sizeof(bootp_.chaddr)), + bootp_.chaddr + ); + // Fill what's left with zeros + if (end < bootp_.chaddr + chaddr_type::address_size) { + std::fill(end, bootp_.chaddr + chaddr_type::address_size, 0); + } + } + + /** + * \brief Setter for the sname field. + * \param new_sname The sname to be set. + */ + void sname(const uint8_t* new_sname); + + /** + * \brief Setter for the file field. + * \param new_file The file to be set. + */ + void file(const uint8_t* new_file); + + /** + * \brief Setter for the vend field. + * \param newvend_ The vend to be set. + */ + void vend(const vend_type& newvend_); + + /** + * \brief Check wether ptr points to a valid response for this PDU. + * + * This returns true if the xid field is equal. + * + * \sa PDU::matches_response + * \param ptr The pointer to the buffer. + * \param total_sz The size of the buffer. + */ + bool matches_response(const uint8_t* ptr, uint32_t total_sz) const; + + /** + * \brief Getter for the PDU's type. + * \sa PDU::pdu_type + */ + PDUType pdu_type() const { return pdu_flag; } + + /** + * \sa PDU::clone + */ + BootP* clone() const { + return new BootP(*this); + } +protected: + /** + * \brief Getter for the vend field. + * + * This getter can be used by subclasses to avoid copying the + * vend field around. + * + * \return The vend field for this BootP PDU. + */ + vend_type& vend() { return vend_; } + + void write_serialization(uint8_t* buffer, uint32_t total_sz, const PDU* parent); +private: + /** + * Struct that represents the Bootp datagram. + */ + TINS_BEGIN_PACK + struct bootp_header { + uint8_t opcode; + uint8_t htype; + uint8_t hlen; + uint8_t hops; + uint32_t xid; + uint16_t secs; + uint16_t padding; + uint32_t ciaddr; + uint32_t yiaddr; + uint32_t siaddr; + uint32_t giaddr; + uint8_t chaddr[16]; + uint8_t sname[64]; + uint8_t file[128]; + } TINS_END_PACK; + + bootp_header bootp_; + vend_type vend_; +}; + +} // Tins #endif // TINS_BOOTP_H diff --git a/include/tins/constants.h b/include/tins/constants.h index d71fd220..a20cd0ab 100644 --- a/include/tins/constants.h +++ b/include/tins/constants.h @@ -31,131 +31,131 @@ #define TINS_CONSTANTS_H namespace Tins { - /** - * \brief Constants used in protocols. - */ - namespace Constants { - /** \cond */ - struct IP { - /** \endcond */ - enum e { - PROTO_IP = 0, /* Dummy protocol for TCP. */ - PROTO_HOPOPTS = 0, /* IPv6 Hop-by-Hop options. */ - PROTO_ICMP = 1, /* Internet Control Message Protocol. */ - PROTO_IGMP = 2, /* Internet Group Management Protocol. */ - PROTO_IPIP = 4, /* IPIP tunnels (older KA9Q tunnels use 94). */ - PROTO_TCP = 6, /* Transmission Control Protocol. */ - PROTO_EGP = 8, /* Exterior Gateway Protocol. */ - PROTO_PUP = 12, /* PUP protocol. */ - PROTO_UDP = 17, /* User Datagram Protocol. */ - PROTO_IDP = 22, /* XNS IDP protocol. */ - PROTO_TP = 29, /* SO Transport Protocol Class 4. */ - PROTO_DCCP = 33, /* Datagram Congestion Control Protocol. */ - PROTO_IPV6 = 41, /* IPv6 header. */ - PROTO_ROUTING = 43, /* IPv6 routing header. */ - PROTO_FRAGMENT = 44, /* IPv6 fragmentation header. */ - PROTO_RSVP = 46, /* Reservation Protocol. */ - PROTO_GRE = 47, /* General Routing Encapsulation. */ - PROTO_ESP = 50, /* encapsulating security payload. */ - PROTO_AH = 51, /* authentication header. */ - PROTO_ICMPV6 = 58, /* ICMPv6. */ - PROTO_NONE = 59, /* IPv6 no next header. */ - PROTO_DSTOPTS = 60, /* IPv6 destination options. */ - PROTO_MTP = 92, /* Multicast Transport Protocol. */ - PROTO_ENCAP = 98, /* Encapsulation Header. */ - PROTO_PIM = 103, /* Protocol Independent Multicast. */ - PROTO_COMP = 108, /* Compression Header Protocol. */ - PROTO_SCTP = 132, /* Stream Control Transmission Protocol. */ - PROTO_UDPLITE = 136, /* UDP-Lite protocol. */ - PROTO_RAW = 255 /* Raw IP packets. */ - }; - }; - - struct Ethernet { - enum e { - UNKNOWN = 0, - //~ PUP = 0x0200, /* Xerox PUP */ - SPRITE = 0x0500, /* Sprite */ - IP = 0x0800, /* IP */ - ARP = 0x0806, /* Address resolution */ - MPLS = 0x8847, /* MPLS */ - REVARP = 0x8035, /* Reverse ARP */ - AT = 0x809B, /* AppleTalk protocol */ - AARP = 0x80F3, /* AppleTalk ARP */ - VLAN = 0x8100, /* IEEE 802.1Q VLAN tagging */ - IPX = 0x8137, /* IPX */ - IPV6 = 0x86dd, /* IP protocol version 6 */ - PPPOED = 0x8863, /* PPPoE Discovery */ - PPPOES = 0x8864, /* PPPoE Session */ - EAPOL = 0x888e, /* EAPOL */ - LOOPBACK = 0x9000 /* used to test interfaces */ - }; - }; - - struct ARP { - enum e { - NETROM = 0, /* From KA9Q: NET/ROM pseudo. */ - ETHER = 1, /* Ethernet 10/100Mbps. */ - EETHER = 2, /* Experimental Ethernet. */ - AX25 = 3, /* AX.25 Level 2. */ - PRONET = 4, /* PROnet token ring. */ - CHAOS = 5, /* Chaosnet. */ - IEEE802 = 6, /* IEEE 802.2 Ethernet/TR/TB. */ - ARCNET = 7, /* ARCnet. */ - APPLETLK = 8, /* APPLEtalk. */ - DLCI = 15, /* Frame Relay DLCI. */ - ATM = 19, /* ATM. */ - METRICOM = 23, /* Metricom STRIP (new IANA id). */ - IEEE1394 = 24, /* IEEE 1394 IPv4 - RFC 2734. */ - EUI64 = 27, /* EUI-64. */ - INFINIBAND = 32, /* InfiniBand. */ - SLIP = 256, - CSLIP = 257, - SLIP6 = 258, - CSLIP6 = 259, - RSRVD = 260, /* Notional KISS type. */ - ADAPT = 264, - ROSE = 270, - X25 = 271, /* CCITT X.25. */ - HWX25 = 272, /* Boards with X.25 in firmware. */ - PPP = 512, - CISCO = 513, /* Cisco HDLC. */ - HDLC = CISCO, - LAPB = 516, /* LAPB. */ - DDCMP = 517, /* Digital's DDCMP. */ - RAWHDLC = 518, /* Raw HDLC. */ - TUNNEL = 768, /* IPIP tunnel. */ - TUNNEL6 = 769, /* IPIP6 tunnel. */ - FRAD = 770, /* Frame Relay Access Device. */ - SKIP = 771, /* SKIP vif. */ - LOOPBACK = 772, /* Loopback device. */ - LOCALTLK = 773, /* Localtalk device. */ - FDDI = 774, /* Fiber Distributed Data Interface. */ - BIF = 775, /* AP1000 BIF. */ - SIT = 776, /* sit0 device - IPv6-in-IPv4. */ - IPDDP = 777, /* IP-in-DDP tunnel. */ - IPGRE = 778, /* GRE over IP. */ - PIMREG = 779, /* PIMSM register interface. */ - HIPPI = 780, /* High Performance Parallel I'face. */ - ASH = 781, /* (Nexus Electronics) Ash. */ - ECONET = 782, /* Acorn Econet. */ - IRDA = 783, /* Linux-IrDA. */ - FCPP = 784, /* Point to point fibrechanel. */ - FCAL = 785, /* Fibrechanel arbitrated loop. */ - FCPL = 786, /* Fibrechanel public loop. */ - FCFABRIC = 787, /* Fibrechanel fabric. */ - IEEE802_TR = 800, /* Magic type ident for TR. */ - IEEE80211 = 801, /* IEEE 802.11. */ - IEEE80211_PRISM = 802, /* IEEE 802.11 + Prism2 header. */ - IEEE80211_RADIOTAP = 803, /* IEEE 802.11 + radiotap header. */ - IEEE802154 = 804, /* IEEE 802.15.4 header. */ - IEEE802154_PHY = 805, /* IEEE 802.15.4 PHY header. */ - VOID_TYPE = 0xFFFF, /* Void type, nothing is known. */ - NONE = 0xFFFE /* Zero header length. */ - }; - }; - } -} +/** + * \brief Constants used in protocols. + */ +namespace Constants { +/** \cond */ +struct IP { +/** \endcond */ + enum e { + PROTO_IP = 0, // Dummy protocol for TCP. + PROTO_HOPOPTS = 0, // IPv6 Hop-by-Hop options. + PROTO_ICMP = 1, // Internet Control Message Protocol. + PROTO_IGMP = 2, // Internet Group Management Protocol. + PROTO_IPIP = 4, // IPIP tunnels (older KA9Q tunnels use 94). + PROTO_TCP = 6, // Transmission Control Protocol. + PROTO_EGP = 8, // Exterior Gateway Protocol. + PROTO_PUP = 12, // PUP protocol. + PROTO_UDP = 17, // User Datagram Protocol. + PROTO_IDP = 22, // XNS IDP protocol. + PROTO_TP = 29, // SO Transport Protocol Class 4. + PROTO_DCCP = 33, // Datagram Congestion Control Protocol. + PROTO_IPV6 = 41, // IPv6 header. + PROTO_ROUTING = 43, // IPv6 routing header. + PROTO_FRAGMENT = 44, // IPv6 fragmentation header. + PROTO_RSVP = 46, // Reservation Protocol. + PROTO_GRE = 47, // General Routing Encapsulation. + PROTO_ESP = 50, // encapsulating security payload. + PROTO_AH = 51, // authentication header. + PROTO_ICMPV6 = 58, // ICMPv6. + PROTO_NONE = 59, // IPv6 no next header. + PROTO_DSTOPTS = 60, // IPv6 destination options. + PROTO_MTP = 92, // Multicast Transport Protocol. + PROTO_ENCAP = 98, // Encapsulation Header. + PROTO_PIM = 103, // Protocol Independent Multicast. + PROTO_COMP = 108, // Compression Header Protocol. + PROTO_SCTP = 132, // Stream Control Transmission Protocol. + PROTO_UDPLITE = 136, // UDP-Lite protocol. + PROTO_RAW = 255 // Raw IP packets. + }; +}; + +struct Ethernet { + enum e { + UNKNOWN = 0, + SPRITE = 0x0500, // Sprite + IP = 0x0800, // IP + ARP = 0x0806, // Address resolution + MPLS = 0x8847, // MPLS + REVARP = 0x8035, // Reverse ARP + AT = 0x809B, // AppleTalk protocol + AARP = 0x80F3, // AppleTalk ARP + VLAN = 0x8100, // IEEE 802.1Q VLAN tagging + IPX = 0x8137, // IPX + IPV6 = 0x86dd, // IP protocol version 6 + PPPOED = 0x8863, // PPPoE Discovery + PPPOES = 0x8864, // PPPoE Session + EAPOL = 0x888e, // EAPOL + LOOPBACK = 0x9000 // used to test interfaces + }; +}; + +struct ARP { + enum e { + NETROM = 0, // From KA9Q: NET/ROM pseudo. + ETHER = 1, // Ethernet 10/100Mbps. + EETHER = 2, // Experimental Ethernet. + AX25 = 3, // AX.25 Level 2. + PRONET = 4, // PROnet token ring. + CHAOS = 5, // Chaosnet. + IEEE802 = 6, // IEEE 802.2 Ethernet/TR/TB. + ARCNET = 7, // ARCnet. + APPLETLK = 8, // APPLEtalk. + DLCI = 15, // Frame Relay DLCI. + ATM = 19, // ATM. + METRICOM = 23, // Metricom STRIP (new IANA id). + IEEE1394 = 24, // IEEE 1394 IPv4 - RFC 2734. + EUI64 = 27, // EUI-64. + INFINIBAND = 32, // InfiniBand. + SLIP = 256, + CSLIP = 257, + SLIP6 = 258, + CSLIP6 = 259, + RSRVD = 260, // Notional KISS type. + ADAPT = 264, + ROSE = 270, + X25 = 271, // CCITT X.25. + HWX25 = 272, // Boards with X.25 in firmware. + PPP = 512, + CISCO = 513, // Cisco HDLC. + HDLC = CISCO, + LAPB = 516, // LAPB. + DDCMP = 517, // Digital's DDCMP. + RAWHDLC = 518, // Raw HDLC. + TUNNEL = 768, // IPIP tunnel. + TUNNEL6 = 769, // IPIP6 tunnel. + FRAD = 770, // Frame Relay Access Device. + SKIP = 771, // SKIP vif. + LOOPBACK = 772, // Loopback device. + LOCALTLK = 773, // Localtalk device. + FDDI = 774, // Fiber Distributed Data Interface. + BIF = 775, // AP1000 BIF. + SIT = 776, // sit0 device - IPv6-in-IPv4. + IPDDP = 777, // IP-in-DDP tunnel. + IPGRE = 778, // GRE over IP. + PIMREG = 779, // PIMSM register interface. + HIPPI = 780, // High Performance Parallel I'face. + ASH = 781, // (Nexus Electronics) Ash. + ECONET = 782, // Acorn Econet. + IRDA = 783, // Linux-IrDA. + FCPP = 784, // Point to point fibrechanel. + FCAL = 785, // Fibrechanel arbitrated loop. + FCPL = 786, // Fibrechanel public loop. + FCFABRIC = 787, // Fibrechanel fabric. + IEEE802_TR = 800, // Magic type ident for TR. + IEEE80211 = 801, // IEEE 802.11. + IEEE80211_PRISM = 802, // IEEE 802.11 + Prism2 header. + IEEE80211_RADIOTAP = 803, // IEEE 802.11 + radiotap header. + IEEE802154 = 804, // IEEE 802.15.4 header. + IEEE802154_PHY = 805, // IEEE 802.15.4 PHY header. + VOID_TYPE = 0xFFFF, // Void type, nothing is known. + NONE = 0xFFFE // Zero header length. + }; +}; + +} // Constants +} // Tins #endif // TINS_CONSTANTS_H diff --git a/include/tins/crypto.h b/include/tins/crypto.h index 8c538dcd..1ada1460 100644 --- a/include/tins/crypto.h +++ b/include/tins/crypto.h @@ -43,494 +43,499 @@ #include "handshake_capturer.h" namespace Tins { + class PDU; class Dot11; class Dot11Data; namespace Crypto { - struct RC4Key; - #ifdef HAVE_WPA2_DECRYPTION - namespace WPA2 { - /** - * \brief Class that represents the keys used to decrypt a session. - */ - class TINS_API SessionKeys { - public: - /** - * The size of the Pairwise Master Key. - */ - static const size_t PMK_SIZE; - - /** - * The size of the Pairwise Transient Key. - */ - static const size_t PTK_SIZE; - - /** - * The type used to hold the PTK (this has to be PTK_SIZE bytes long). - */ - typedef std::vector ptk_type; - - /** - * The type used to hold the PMK (this has to be PMK_SIZE bytes long). - */ - typedef std::vector pmk_type; - - /** - * Default constructs a SessionKeys object. - */ - SessionKeys(); - - /** - * \brief Constructs an instance using the provided PTK and a flag - * indicating whether it should use ccmp. - * - * \param ptk The PTK to use. - * \param is_ccmp Indicates whether to use CCMP to decrypt this traffic. - */ - SessionKeys(const ptk_type& ptk, bool is_ccmp); - - /** - * \brief Constructs an instance using a handshake and a PMK. - * - * This will internally construct the PTK from the input parameters. - * - * \param hs The handshake to use. - * \param pmk The PMK to use. - */ - SessionKeys(const RSNHandshake &hs, const pmk_type &pmk); - - /** - * \brief Decrypts a unicast packet. - * - * \param dot11 The encrypted packet to decrypt. - * \param raw The raw layer on the packet to decrypt. - * \return A SNAP layer containing the decrypted traffic or a null pointer - * if decryption failed. - */ - SNAP *decrypt_unicast(const Dot11Data &dot11, RawPDU &raw) const; - - /** - * \brief Gets the PTK for this session keys. - * \return The Pairwise Transcient Key. - */ - const ptk_type& get_ptk() const; - - /** - * \brief Indicates whether CCMP is used to decrypt packets - * /return true iff CCMP is used. - */ - bool uses_ccmp() const; - private: - SNAP *ccmp_decrypt_unicast(const Dot11Data &dot11, RawPDU &raw) const; - SNAP *tkip_decrypt_unicast(const Dot11Data &dot11, RawPDU &raw) const; - RC4Key generate_rc4_key(const Dot11Data &dot11, const RawPDU &raw) const; - - ptk_type ptk; - bool is_ccmp; - }; - - /** - * \brief Represents a WPA2 supplicant's data. - * - * Objects of this class can be given the pre-shared key and the SSID - * of some access point, and this will generate the Pairwise Master Key - * from those parameters. - */ - class TINS_API SupplicantData { - public: - /** - * The type used to store the PMK. - */ - typedef SessionKeys::pmk_type pmk_type; - - /** - * \brief Constructs a SupplicantData. - * \param psk The pre-shared key. - * \param ssid The access point's SSID. - */ - SupplicantData(const std::string &psk, const std::string &ssid); - - /** - * \brief Getter for the PMK. - * \return The generated PMK. - */ - const pmk_type &pmk() const; - private: - pmk_type pmk_; - }; - } // WPA2 - #endif // HAVE_WPA2_DECRYPTION - - /** - * \brief RC4 Key abstraction. - */ - struct RC4Key { - static const size_t data_size = 256; - - /** - * \brief Initializes the key using the provided iterator range. - * - * \param start The start of the range. - * \param end The end of the range. - */ - template - RC4Key(ForwardIterator start, ForwardIterator end); - - /** - * The actual key data. - */ - uint8_t data[data_size]; - }; - - /** - * \brief Decrypts WEP-encrypted traffic. - */ - class TINS_API WEPDecrypter { - public: - typedef HWAddress<6> address_type; + +struct RC4Key; + +#ifdef HAVE_WPA2_DECRYPTION +namespace WPA2 { + +/** + * \brief Class that represents the keys used to decrypt a session. + */ +class TINS_API SessionKeys { +public: + /** + * The size of the Pairwise Master Key. + */ + static const size_t PMK_SIZE; + + /** + * The size of the Pairwise Transient Key. + */ + static const size_t PTK_SIZE; + + /** + * The type used to hold the PTK (this has to be PTK_SIZE bytes long). + */ + typedef std::vector ptk_type; + + /** + * The type used to hold the PMK (this has to be PMK_SIZE bytes long). + */ + typedef std::vector pmk_type; - /** - * \brief Constructs a WEPDecrypter object. - */ - WEPDecrypter(); - - /** - * \brief Adds a decryption password. - * - * \param addr The access point's BSSID. - * \param password The password which will be used to decrypt - * packets sent from and to the AP identifier by the BSSID addr. - */ - void add_password(const address_type &addr, const std::string &password); - - /** - * \brief Removes a decryption password - * - * \param addr The BSSID of the access point. - */ - void remove_password(const address_type &addr); - - /** - * \brief Decrypts the provided PDU. - * - * A Dot11Data PDU is looked up inside the provided PDU chain. - * If no such PDU exists or there is no password associated - * with the Dot11 packet's BSSID, then the PDU is left intact. - * - * Otherwise, the packet is decrypted using the given password. - * If the CRC found after decrypting is invalid, false is - * returned. - * - * \return false if no decryption was performed or decryption - * failed, true otherwise. - */ - bool decrypt(PDU &pdu); - private: - typedef std::map passwords_type; + /** + * Default constructs a SessionKeys object. + */ + SessionKeys(); + + /** + * \brief Constructs an instance using the provided PTK and a flag + * indicating whether it should use ccmp. + * + * \param ptk The PTK to use. + * \param is_ccmp Indicates whether to use CCMP to decrypt this traffic. + */ + SessionKeys(const ptk_type& ptk, bool is_ccmp); + + /** + * \brief Constructs an instance using a handshake and a PMK. + * + * This will internally construct the PTK from the input parameters. + * + * \param hs The handshake to use. + * \param pmk The PMK to use. + */ + SessionKeys(const RSNHandshake& hs, const pmk_type& pmk); + + /** + * \brief Decrypts a unicast packet. + * + * \param dot11 The encrypted packet to decrypt. + * \param raw The raw layer on the packet to decrypt. + * \return A SNAP layer containing the decrypted traffic or a null pointer + * if decryption failed. + */ + SNAP* decrypt_unicast(const Dot11Data& dot11, RawPDU& raw) const; + + /** + * \brief Gets the PTK for this session keys. + * \return The Pairwise Transcient Key. + */ + const ptk_type& get_ptk() const; + + /** + * \brief Indicates whether CCMP is used to decrypt packets + * /return true iff CCMP is used. + */ + bool uses_ccmp() const; +private: + SNAP* ccmp_decrypt_unicast(const Dot11Data& dot11, RawPDU& raw) const; + SNAP* tkip_decrypt_unicast(const Dot11Data& dot11, RawPDU& raw) const; + RC4Key generate_rc4_key(const Dot11Data& dot11, const RawPDU& raw) const; + + ptk_type ptk_; + bool is_ccmp_; +}; + +/** + * \brief Represents a WPA2 supplicant's data. + * + * Objects of this class can be given the pre-shared key and the SSID + * of some access point, and this will generate the Pairwise Master Key + * from those parameters. + */ +class TINS_API SupplicantData { +public: + /** + * The type used to store the PMK. + */ + typedef SessionKeys::pmk_type pmk_type; - PDU *decrypt(RawPDU &raw, const std::string &password); + /** + * \brief Constructs a SupplicantData. + * \param psk The pre-shared key. + * \param ssid The access point's SSID. + */ + SupplicantData(const std::string& psk, const std::string& ssid); - passwords_type passwords; - std::vector key_buffer; - }; + /** + * \brief Getter for the PMK. + * \return The generated PMK. + */ + const pmk_type& pmk() const; +private: + pmk_type pmk_; +}; + +} // WPA2 +#endif // HAVE_WPA2_DECRYPTION + +/** + * \brief RC4 Key abstraction. + */ +struct RC4Key { + static const size_t data_size = 256; - #ifdef HAVE_WPA2_DECRYPTION /** - * \brief Decrypts WPA2-encrypted traffic. - * - * This class takes valid PSK and SSID tuples, captures client handshakes, - * and decrypts their traffic afterwards. - */ - class TINS_API WPA2Decrypter { - public: - /* - * \brief The type used to store Dot11 addresses. - */ - typedef HWAddress<6> address_type; - - /** - * \brief Represents a pair of mac addresses. - * - * This is used to identify a host and the access point to which - * it is connected. The first element in the pair will always de - * lower or equal than the second one, so that given any host and - * the access point it's connected to, we can uniquely identify - * it with an address pair. - */ - typedef std::pair addr_pair; - - /** - * \brief Maps an address pair to the session keys. - * - * This type associates an address pair (host, access point) with the - * session keys, as generated using the packets seen on a handshake. - * - * \sa addr_pair - */ - typedef std::map keys_map; - - /** - * \brief Adds an access points's information. - * - * This associates an SSID with a PSK, and allows the decryption of - * any BSSIDs that broadcast the same SSID. - * - * The decrypter will inspect beacon frames, looking for SSID tags - * that contain the given SSID. - * - * Note that using this overload, the decryption of data frames and - * handshake capturing will be disabled until any access point - * broadcasts the provided SSID(this shouldn't take long at all). - * If this is not the desired behaviour, then you should check out - * the ovther add_ap_data overload. - * - * \param psk The PSK associated with the SSID. - * \param ssid The network's SSID. - */ - void add_ap_data(const std::string &psk, const std::string &ssid); - - /** - * \brief Adds a access points's information, including its BSSID. - * - * This overload can be used if the BSSID associated with this SSID is - * known beforehand. The addr parameter indicates which specific BSSID - * is associated to the SSID. - * - * Note that if any other access point broadcasts the provided SSID, - * it will be taken into account as well. - * - * \param psk The PSK associated with this SSID. - * \param ssid The network's SSID. - * \param addr The access point's BSSID. - */ - void add_ap_data(const std::string &psk, const std::string &ssid, const address_type &addr); - - /** - * \brief Explicitly add decryption keys. - * - * This method associates a pair (host, access point) with the given decryption keys. - * All encrypted packets sent between the given addresses will be decrypted using the - * provided keys. - * - * This method shouldn't normally be required. The WPA2Decrypter will be waiting for - * handshakes and will automatically extract the session keys, decrypting all - * encrypted packets with them. You should only use this method if for some reason - * you know the actual keys being used (because you checked and stored the keys_map - * somewhere). - * - * The actual order of the addresses doesn't matter, this method will make sure - * they're sorted. - * - * \param addresses The address pair (host, access point) to associate. - * \param session_keys The keys to use when decrypting messages sent between the - * given addresses. - */ - void add_decryption_keys(const addr_pair& addresses, const WPA2::SessionKeys& session_keys); - - /** - * \brief Decrypts the provided PDU. - * - * A Dot11Data PDU is looked up inside the provided PDU chain. - * If no such PDU exists or no PSK was associated with the SSID - * broadcasted by the Dot11 packet's BSSID, or no EAPOL handshake - * was captured for the client involved in the communication, - * then the PDU is left intact. - * - * Otherwise, the packet is decrypted using the generated PTK. - * If the resulting MIC is invalid, then the packet is left intact. - * - * \return false if no decryption was performed, or the decryption - * failed, true otherwise. - */ - bool decrypt(PDU &pdu); - - /** - * \brief Getter for the keys on this decrypter - * - * The returned map will be populated every time a new, complete, handshake - * is captured. - * - * \return The WPA2Decrypter keys map. - */ - const keys_map& get_keys() const; - private: - typedef std::map pmks_map; - typedef std::map bssids_map; - - void try_add_keys(const Dot11Data &dot11, const RSNHandshake &hs); - addr_pair make_addr_pair(const address_type &addr1, const address_type &addr2) { - return (addr1 < addr2) ? - std::make_pair(addr1, addr2) : - std::make_pair(addr2, addr1); - } - addr_pair extract_addr_pair(const Dot11Data &dot11); - addr_pair extract_addr_pair_dst(const Dot11Data &dot11); - bssids_map::const_iterator find_ap(const Dot11Data &dot11); - void add_access_point(const std::string &ssid, const address_type &addr); + * \brief Initializes the key using the provided iterator range. + * + * \param start The start of the range. + * \param end The end of the range. + */ + template + RC4Key(ForwardIterator start, ForwardIterator end); + + /** + * The actual key data. + */ + uint8_t data[data_size]; +}; - RSNHandshakeCapturer capturer; - pmks_map pmks; - bssids_map aps; - keys_map keys; - }; - #endif // HAVE_WPA2_DECRYPTION +/** + * \brief Decrypts WEP-encrypted traffic. + */ +class TINS_API WEPDecrypter { +public: + typedef HWAddress<6> address_type; /** - * \brief Pluggable decrypter object which can be used to decrypt - * data on sniffing sessions. + * \brief Constructs a WEPDecrypter object. + */ + WEPDecrypter(); + + /** + * \brief Adds a decryption password. + * + * \param addr The access point's BSSID. + * \param password The password which will be used to decrypt + * packets sent from and to the AP identifier by the BSSID addr. + */ + void add_password(const address_type& addr, const std::string& password); + + /** + * \brief Removes a decryption password * - * This class holds a decrypter object and a functor, and implements - * a suitable operator() to be used on BaseSniffer::sniff_loop, which - * decrypts packets and forwards them to the given functor. - */ - template - class DecrypterProxy { - public: - /** - * The type of the functor object. - */ - typedef Functor functor_type; + * \param addr The BSSID of the access point. + */ + void remove_password(const address_type& addr); - /** - * The type of the decrypter object. - */ - typedef Decrypter decrypter_type; - - /** - * \brief Constructs an object from a functor and a decrypter. - * \param func The functor to be used to forward decrypted - * packets. - * \param decrypter The decrypter which will be used to decrypt - * packets - */ - DecrypterProxy(const functor_type &func, - const decrypter_type &decr = decrypter_type()); - - /** - * \brief Retrieves a reference to the decrypter object. - */ - decrypter_type &decrypter(); - - /** - * \brief Retrieves a const reference to the decrypter object. - */ - const decrypter_type &decrypter() const; - - /** - * \brief The operator() which decrypts packets and forwards - * them to the functor. - */ - bool operator() (PDU &pdu); - private: - Functor functor_; - decrypter_type decrypter_; - }; - - /** - * \brief Performs RC4 encription/decryption of the given byte range, - * using the provided key. + /** + * \brief Decrypts the provided PDU. + * + * A Dot11Data PDU is looked up inside the provided PDU chain. + * If no such PDU exists or there is no password associated + * with the Dot11 packet's BSSID, then the PDU is left intact. * - * The decrypted range will be copied to the OutputIterator provided. + * Otherwise, the packet is decrypted using the given password. + * If the CRC found after decrypting is invalid, false is + * returned. * - * \param start The beginning of the range. - * \param start The end of the range. - * \param key The key to be used. - * \param output The iterator in which to write the output. + * \return false if no decryption was performed or decryption + * failed, true otherwise. */ - template - void rc4(ForwardIterator start, ForwardIterator end, RC4Key &key, OutputIterator output); + bool decrypt(PDU& pdu); +private: + typedef std::map passwords_type; + + PDU* decrypt(RawPDU& raw, const std::string& password); + + passwords_type passwords_; + std::vector key_buffer_; +}; + +#ifdef HAVE_WPA2_DECRYPTION +/** + * \brief Decrypts WPA2-encrypted traffic. + * + * This class takes valid PSK and SSID tuples, captures client handshakes, + * and decrypts their traffic afterwards. + */ +class TINS_API WPA2Decrypter { +public: + /* + * \brief The type used to store Dot11 addresses. + */ + typedef HWAddress<6> address_type; /** - * \brief Wrapper function to create a DecrypterProxy using a - * WEPDecrypter as the Decrypter template parameter. + * \brief Represents a pair of mac addresses. * - * \param functor The functor to be forwarded to the DecrypterProxy - * constructor. + * This is used to identify a host and the access point to which + * it is connected. The first element in the pair will always de + * lower or equal than the second one, so that given any host and + * the access point it's connected to, we can uniquely identify + * it with an address pair. + */ + typedef std::pair addr_pair; + + /** + * \brief Maps an address pair to the session keys. + * + * This type associates an address pair (host, access point) with the + * session keys, as generated using the packets seen on a handshake. + * + * \sa addr_pair */ - template - DecrypterProxy make_wep_decrypter_proxy(const Functor &functor); + typedef std::map keys_map; - #ifdef HAVE_WPA2_DECRYPTION /** - * \brief Wrapper function to create a DecrypterProxy using a - * WPA2Decrypter as the Decrypter template parameter. + * \brief Adds an access points's information. + * + * This associates an SSID with a PSK, and allows the decryption of + * any BSSIDs that broadcast the same SSID. + * + * The decrypter will inspect beacon frames, looking for SSID tags + * that contain the given SSID. + * + * Note that using this overload, the decryption of data frames and + * handshake capturing will be disabled until any access point + * broadcasts the provided SSID(this shouldn't take long at all). + * If this is not the desired behaviour, then you should check out + * the ovther add_ap_data overload. + * + * \param psk The PSK associated with the SSID. + * \param ssid The network's SSID. + */ + void add_ap_data(const std::string& psk, const std::string& ssid); + + /** + * \brief Adds a access points's information, including its BSSID. + * + * This overload can be used if the BSSID associated with this SSID is + * known beforehand. The addr parameter indicates which specific BSSID + * is associated to the SSID. + * + * Note that if any other access point broadcasts the provided SSID, + * it will be taken into account as well. + * + * \param psk The PSK associated with this SSID. + * \param ssid The network's SSID. + * \param addr The access point's BSSID. + */ + void add_ap_data(const std::string& psk, + const std::string& ssid, + const address_type& addr); + + /** + * \brief Explicitly add decryption keys. * - * \param functor The functor to be forwarded to the DecrypterProxy - * constructor. + * This method associates a pair (host, access point) with the given decryption keys. + * All encrypted packets sent between the given addresses will be decrypted using the + * provided keys. + * + * This method shouldn't normally be required. The WPA2Decrypter will be waiting for + * handshakes and will automatically extract the session keys, decrypting all + * encrypted packets with them. You should only use this method if for some reason + * you know the actual keys being used (because you checked and stored the keys_map + * somewhere). + * + * The actual order of the addresses doesn't matter, this method will make sure + * they're sorted. + * + * \param addresses The address pair (host, access point) to associate. + * \param session_keys The keys to use when decrypting messages sent between the + * given addresses. */ - template - DecrypterProxy make_wpa2_decrypter_proxy(const Functor &functor) { - return DecrypterProxy(functor); + void add_decryption_keys(const addr_pair& addresses, + const WPA2::SessionKeys& session_keys); + + /** + * \brief Decrypts the provided PDU. + * + * A Dot11Data PDU is looked up inside the provided PDU chain. + * If no such PDU exists or no PSK was associated with the SSID + * broadcasted by the Dot11 packet's BSSID, or no EAPOL handshake + * was captured for the client involved in the communication, + * then the PDU is left intact. + * + * Otherwise, the packet is decrypted using the generated PTK. + * If the resulting MIC is invalid, then the packet is left intact. + * + * \return false if no decryption was performed, or the decryption + * failed, true otherwise. + */ + bool decrypt(PDU& pdu); + + /** + * \brief Getter for the keys on this decrypter + * + * The returned map will be populated every time a new, complete, handshake + * is captured. + * + * \return The WPA2Decrypter keys map. + */ + const keys_map& get_keys() const; +private: + typedef std::map pmks_map; + typedef std::map bssids_map; + + void try_add_keys(const Dot11Data& dot11, const RSNHandshake& hs); + addr_pair make_addr_pair(const address_type& addr1, const address_type& addr2) { + return (addr1 < addr2) ? + std::make_pair(addr1, addr2) : + std::make_pair(addr2, addr1); } - #endif // HAVE_WPA2_DECRYPTION + addr_pair extract_addr_pair(const Dot11Data& dot11); + addr_pair extract_addr_pair_dst(const Dot11Data& dot11); + bssids_map::const_iterator find_ap(const Dot11Data& dot11); + void add_access_point(const std::string& ssid, const address_type& addr); + + RSNHandshakeCapturer capturer_; + pmks_map pmks_; + bssids_map aps_; + keys_map keys_; +}; +#endif // HAVE_WPA2_DECRYPTION + +/** + * \brief Pluggable decrypter object which can be used to decrypt + * data on sniffing sessions. + * + * This class holds a decrypter object and a functor, and implements + * a suitable operator() to be used on BaseSniffer::sniff_loop, which + * decrypts packets and forwards them to the given functor. + */ +template +class DecrypterProxy { +public: + /** + * The type of the functor object. + */ + typedef Functor functor_type; + + /** + * The type of the decrypter object. + */ + typedef Decrypter decrypter_type; - // Implementation section + /** + * \brief Constructs an object from a functor and a decrypter. + * \param func The functor to be used to forward decrypted + * packets. + * \param decrypter The decrypter which will be used to decrypt + * packets + */ + DecrypterProxy(const functor_type& func, + const decrypter_type& decr = decrypter_type()); - // DecrypterProxy + /** + * \brief Retrieves a reference to the decrypter object. + */ + decrypter_type& decrypter(); - template - DecrypterProxy::DecrypterProxy( - const functor_type &func, const decrypter_type& decr) - : functor_(func), decrypter_(decr) - { - - } + /** + * \brief Retrieves a const reference to the decrypter object. + */ + const decrypter_type& decrypter() const; + + /** + * \brief The operator() which decrypts packets and forwards + * them to the functor. + */ + bool operator() (PDU& pdu); +private: + Functor functor_; + decrypter_type decrypter_; +}; + +/** + * \brief Performs RC4 encription/decryption of the given byte range, + * using the provided key. + * + * The decrypted range will be copied to the OutputIterator provided. + * + * \param start The beginning of the range. + * \param start The end of the range. + * \param key The key to be used. + * \param output The iterator in which to write the output. + */ +template +void rc4(ForwardIterator start, ForwardIterator end, RC4Key& key, OutputIterator output); - template - typename DecrypterProxy::decrypter_type & - DecrypterProxy::decrypter() - { - return decrypter_; - } +/** + * \brief Wrapper function to create a DecrypterProxy using a + * WEPDecrypter as the Decrypter template parameter. + * + * \param functor The functor to be forwarded to the DecrypterProxy + * constructor. + */ +template +DecrypterProxy make_wep_decrypter_proxy(const Functor& functor); - template - const typename DecrypterProxy::decrypter_type & - DecrypterProxy::decrypter() const - { - return decrypter_; - } +#ifdef HAVE_WPA2_DECRYPTION +/** + * \brief Wrapper function to create a DecrypterProxy using a + * WPA2Decrypter as the Decrypter template parameter. + * + * \param functor The functor to be forwarded to the DecrypterProxy + * constructor. + */ +template +DecrypterProxy make_wpa2_decrypter_proxy(const Functor& functor) { + return DecrypterProxy(functor); +} +#endif // HAVE_WPA2_DECRYPTION - template - bool DecrypterProxy::operator() (PDU &pdu) - { - return decrypter_.decrypt(pdu) ? functor_(pdu) : true; - } - - template - DecrypterProxy make_wep_decrypter_proxy(const Functor &functor) - { - return DecrypterProxy(functor); - } +// Implementation section - // RC4 stuff +// DecrypterProxy + +template +DecrypterProxy::DecrypterProxy(const functor_type& func, + const decrypter_type& decr) +: functor_(func), decrypter_(decr) { - template - RC4Key::RC4Key(ForwardIterator start, ForwardIterator end) { - for(size_t i = 0; i < data_size; ++i) { - data[i] = static_cast(i); - } - size_t j = 0; - ForwardIterator iter = start; - for(size_t i = 0; i < data_size; ++i) { - j = (j + data[i] + *iter++) % 256; - if(iter == end) - iter = start; - std::swap(data[i], data[j]); - } +} + +template +typename DecrypterProxy::decrypter_type & + DecrypterProxy::decrypter() { + return decrypter_; +} + +template +const typename DecrypterProxy::decrypter_type & + DecrypterProxy::decrypter() const { + return decrypter_; +} + +template +bool DecrypterProxy::operator() (PDU& pdu) { + return decrypter_.decrypt(pdu) ? functor_(pdu) : true; +} + +template +DecrypterProxy make_wep_decrypter_proxy(const Functor& functor) { + return DecrypterProxy(functor); +} + +// RC4 stuff + +template +RC4Key::RC4Key(ForwardIterator start, ForwardIterator end) { + for (size_t i = 0; i < data_size; ++i) { + data[i] = static_cast(i); } - - template - void rc4(ForwardIterator start, ForwardIterator end, RC4Key &key, OutputIterator output) { - size_t i = 0, j = 0; - while(start != end) { - i = (i + 1) % RC4Key::data_size; - j = (j + key.data[i]) % RC4Key::data_size; - std::swap(key.data[i], key.data[j]); - *output++ = *start++ ^ key.data[(key.data[i] + key.data[j]) % RC4Key::data_size]; + size_t j = 0; + ForwardIterator iter = start; + for (size_t i = 0; i < data_size; ++i) { + j = (j + data[i] + *iter++) % 256; + if(iter == end) { + iter = start; } + std::swap(data[i], data[j]); } } + +template +void rc4(ForwardIterator start, ForwardIterator end, RC4Key& key, OutputIterator output) { + size_t i = 0, j = 0; + while (start != end) { + i = (i + 1) % RC4Key::data_size; + j = (j + key.data[i]) % RC4Key::data_size; + std::swap(key.data[i], key.data[j]); + *output++ = *start++ ^ key.data[(key.data[i] + key.data[j]) % RC4Key::data_size]; + } } +} // Crypto +} // Tins + #endif // TINS_CRYPTO_H diff --git a/include/tins/dhcp.h b/include/tins/dhcp.h index 4b4c636e..4d5c8972 100644 --- a/include/tins/dhcp.h +++ b/include/tins/dhcp.h @@ -39,485 +39,488 @@ #include "cxxstd.h" namespace Tins { + +/** + * \class DHCP + * \brief Represents the DHCP PDU. + * + * This class represents a DHCP PDU. It contains helpers methods + * which make it easy to set/get specific option values. + * + * Note that when adding options, the "End" option is not added + * automatically, so you will have to add it yourself. + * + * Options can be retrieved easily from DHCP PDUs: + * + * \code + * // Sniff a packet from somewhere + * DHCP dhcp = get_dhcp_from_somewhere(); + * + * // This retrieves the Domain Name Servers option and converts + * // it to a std::vector. Note that if this option + * // is not present, an option_not_found exception is thrown. + * for(const auto& address : dhcp.domain_name_servers()) { + * // address is an ip + * } + * + * \endcode + */ +class TINS_API DHCP : public BootP { +public: + /** + * This PDU's flag. + */ + static const PDU::PDUType pdu_flag = PDU::DHCP; + /** - * \class DHCP - * \brief Represents the DHCP PDU. - * - * This class represents a DHCP PDU. It contains helpers methods - * which make it easy to set/get specific option values. + * DHCP flags. + */ + enum Flags { + DISCOVER = 1, + OFFER = 2, + REQUEST = 3, + DECLINE = 4, + ACK = 5, + NAK = 6, + RELEASE = 7, + INFORM = 8 + }; + + /** + * \brief DHCP options enum. + */ + enum OptionTypes { + PAD, + SUBNET_MASK, + TIME_OFFSET, + ROUTERS, + TIME_SERVERS, + NAME_SERVERS, + DOMAIN_NAME_SERVERS, + LOG_SERVERS, + COOKIE_SERVERS, + LPR_SERVERS, + IMPRESS_SERVERS, + RESOURCE_LOCATION_SERVERS, + HOST_NAME, + BOOT_SIZE, + MERIT_DUMP, + DOMAIN_NAME, + SWAP_SERVER, + ROOT_PATH, + EXTENSIONS_PATH, + IP_FORWARDING, + NON_LOCAL_SOURCE_ROUTING, + POLICY_FILTER, + MAX_DGRAM_REASSEMBLY, + DEFAULT_IP_TTL, + PATH_MTU_AGING_TIMEOUT, + PATH_MTU_PLATEAU_TABLE, + INTERFACE_MTU, + ALL_SUBNETS_LOCAL, + BROADCAST_ADDRESS, + PERFORM_MASK_DISCOVERY, + MASK_SUPPLIER, + ROUTER_DISCOVERY, + ROUTER_SOLICITATION_ADDRESS, + STATIC_ROUTES, + TRAILER_ENCAPSULATION, + ARP_CACHE_TIMEOUT, + IEEE802_3_ENCAPSULATION, + DEFAULT_TCP_TTL, + TCP_KEEPALIVE_INTERVAL, + TCP_KEEPALIVE_GARBAGE, + NIS_DOMAIN, + NIS_SERVERS, + NTP_SERVERS, + VENDOR_ENCAPSULATED_OPTIONS, + NETBIOS_NAME_SERVERS, + NETBIOS_DD_SERVER, + NETBIOS_NODE_TYPE, + NETBIOS_SCOPE, + FONT_SERVERS, + X_DISPLAY_MANAGER, + DHCP_REQUESTED_ADDRESS, + DHCP_LEASE_TIME, + DHCP_OPTION_OVERLOAD, + DHCP_MESSAGE_TYPE, + DHCP_SERVER_IDENTIFIER, + DHCP_PARAMETER_REQUEST_LIST, + DHCP_MESSAGE, + DHCP_MAX_MESSAGE_SIZE, + DHCP_RENEWAL_TIME, + DHCP_REBINDING_TIME, + VENDOR_CLASS_IDENTIFIER, + DHCP_CLIENT_IDENTIFIER, + NWIP_DOMAIN_NAME, + NWIP_SUBOPTIONS, + USER_CLASS = 77, + FQDN = 81, + DHCP_AGENT_OPTIONS = 82, + SUBNET_SELECTION = 118, + AUTHENTICATE = 210, + END = 255 + }; + + /** + * The DHCP option type. + */ + typedef PDUOption option; + + /** + * The type used to store the DHCP options. + */ + typedef std::list