commit 5d74460e654ad625b1653d56f0eb338a40413954 Author: Svante Kaiser Date: Wed Feb 21 14:52:47 2024 +0300 initial commit diff --git a/.gitignore b/.gitignore new file mode 100644 index 0000000..89cc49c --- /dev/null +++ b/.gitignore @@ -0,0 +1,5 @@ +.pio +.vscode/.browse.c_cpp.db* +.vscode/c_cpp_properties.json +.vscode/launch.json +.vscode/ipch diff --git a/.vscode/extensions.json b/.vscode/extensions.json new file mode 100644 index 0000000..080e70d --- /dev/null +++ b/.vscode/extensions.json @@ -0,0 +1,10 @@ +{ + // See http://go.microsoft.com/fwlink/?LinkId=827846 + // for the documentation about the extensions.json format + "recommendations": [ + "platformio.platformio-ide" + ], + "unwantedRecommendations": [ + "ms-vscode.cpptools-extension-pack" + ] +} diff --git a/.vscode/settings.json b/.vscode/settings.json new file mode 100644 index 0000000..d53f0bb --- /dev/null +++ b/.vscode/settings.json @@ -0,0 +1,59 @@ +{ + "files.associations": { + "algorithm": "cpp", + "array": "cpp", + "atomic": "cpp", + "*.tcc": "cpp", + "cctype": "cpp", + "cerrno": "cpp", + "climits": "cpp", + "clocale": "cpp", + "cmath": "cpp", + "cstdarg": "cpp", + "cstddef": "cpp", + "cstdint": "cpp", + "cstdio": "cpp", + "cstdlib": "cpp", + "cstring": "cpp", + "ctime": "cpp", + "cwchar": "cpp", + "cwctype": "cpp", + "deque": "cpp", + "map": "cpp", + "string": "cpp", + "unordered_map": "cpp", + "unordered_set": "cpp", + "vector": "cpp", + "exception": "cpp", + "functional": "cpp", + "iterator": "cpp", + "memory": "cpp", + "memory_resource": "cpp", + "numeric": "cpp", + "optional": "cpp", + "random": "cpp", + "string_view": "cpp", + "system_error": "cpp", + "tuple": "cpp", + "type_traits": "cpp", + "utility": "cpp", + "fstream": "cpp", + "initializer_list": "cpp", + "iomanip": "cpp", + "ios": "cpp", + "iosfwd": "cpp", + "istream": "cpp", + "limits": "cpp", + "locale": "cpp", + "new": "cpp", + "ostream": "cpp", + "queue": "cpp", + "sstream": "cpp", + "stdexcept": "cpp", + "streambuf": "cpp", + "cinttypes": "cpp", + "cstdbool": "cpp", + "typeinfo": "cpp", + "freertos.h": "c" + } +} \ No newline at end of file diff --git a/include/README b/include/README new file mode 100644 index 0000000..194dcd4 --- /dev/null +++ b/include/README @@ -0,0 +1,39 @@ + +This directory is intended for project header files. + +A header file is a file containing C declarations and macro definitions +to be shared between several project source files. You request the use of a +header file in your project source file (C, C++, etc) located in `src` folder +by including it, with the C preprocessing directive `#include'. + +```src/main.c + +#include "header.h" + +int main (void) +{ + ... +} +``` + +Including a header file produces the same results as copying the header file +into each source file that needs it. Such copying would be time-consuming +and error-prone. With a header file, the related declarations appear +in only one place. If they need to be changed, they can be changed in one +place, and programs that include the header file will automatically use the +new version when next recompiled. The header file eliminates the labor of +finding and changing all the copies as well as the risk that a failure to +find one copy will result in inconsistencies within a program. + +In C, the usual convention is to give header files names that end with `.h'. +It is most portable to use only letters, digits, dashes, and underscores in +header file names, and at most one dot. + +Read more about using header files in official GCC documentation: + +* Include Syntax +* Include Operation +* Once-Only Headers +* Computed Includes + +https://gcc.gnu.org/onlinedocs/cpp/Header-Files.html diff --git a/lib/Freenove_WS2812_Lib_for_ESP32/LICENSE b/lib/Freenove_WS2812_Lib_for_ESP32/LICENSE new file mode 100644 index 0000000..59f221d --- /dev/null +++ b/lib/Freenove_WS2812_Lib_for_ESP32/LICENSE @@ -0,0 +1,165 @@ + GNU LESSER GENERAL PUBLIC LICENSE + Version 3, 29 June 2007 + + Copyright (C) Freenove + Everyone is permitted to copy and distribute verbatim copies + of this license document, but changing it is not allowed. + + + This version of the GNU Lesser General Public License incorporates +the terms and conditions of version 3 of the GNU General Public +License, supplemented by the additional permissions listed below. + + 0. Additional Definitions. + + As used herein, "this License" refers to version 3 of the GNU Lesser +General Public License, and the "GNU GPL" refers to version 3 of the GNU +General Public License. + + "The Library" refers to a covered work governed by this License, +other than an Application or a Combined Work as defined below. + + An "Application" is any work that makes use of an interface provided +by the Library, but which is not otherwise based on the Library. +Defining a subclass of a class defined by the Library is deemed a mode +of using an interface provided by the Library. + + A "Combined Work" is a work produced by combining or linking an +Application with the Library. The particular version of the Library +with which the Combined Work was made is also called the "Linked +Version". + + The "Minimal Corresponding Source" for a Combined Work means the +Corresponding Source for the Combined Work, excluding any source code +for portions of the Combined Work that, considered in isolation, are +based on the Application, and not on the Linked Version. + + The "Corresponding Application Code" for a Combined Work means the +object code and/or source code for the Application, including any data +and utility programs needed for reproducing the Combined Work from the +Application, but excluding the System Libraries of the Combined Work. + + 1. Exception to Section 3 of the GNU GPL. + + You may convey a covered work under sections 3 and 4 of this License +without being bound by section 3 of the GNU GPL. + + 2. Conveying Modified Versions. + + If you modify a copy of the Library, and, in your modifications, a +facility refers to a function or data to be supplied by an Application +that uses the facility (other than as an argument passed when the +facility is invoked), then you may convey a copy of the modified +version: + + a) under this License, provided that you make a good faith effort to + ensure that, in the event an Application does not supply the + function or data, the facility still operates, and performs + whatever part of its purpose remains meaningful, or + + b) under the GNU GPL, with none of the additional permissions of + this License applicable to that copy. + + 3. Object Code Incorporating Material from Library Header Files. + + The object code form of an Application may incorporate material from +a header file that is part of the Library. You may convey such object +code under terms of your choice, provided that, if the incorporated +material is not limited to numerical parameters, data structure +layouts and accessors, or small macros, inline functions and templates +(ten or fewer lines in length), you do both of the following: + + a) Give prominent notice with each copy of the object code that the + Library is used in it and that the Library and its use are + covered by this License. + + b) Accompany the object code with a copy of the GNU GPL and this license + document. + + 4. Combined Works. + + You may convey a Combined Work under terms of your choice that, +taken together, effectively do not restrict modification of the +portions of the Library contained in the Combined Work and reverse +engineering for debugging such modifications, if you also do each of +the following: + + a) Give prominent notice with each copy of the Combined Work that + the Library is used in it and that the Library and its use are + covered by this License. + + b) Accompany the Combined Work with a copy of the GNU GPL and this license + document. + + c) For a Combined Work that displays copyright notices during + execution, include the copyright notice for the Library among + these notices, as well as a reference directing the user to the + copies of the GNU GPL and this license document. + + d) Do one of the following: + + 0) Convey the Minimal Corresponding Source under the terms of this + License, and the Corresponding Application Code in a form + suitable for, and under terms that permit, the user to + recombine or relink the Application with a modified version of + the Linked Version to produce a modified Combined Work, in the + manner specified by section 6 of the GNU GPL for conveying + Corresponding Source. + + 1) Use a suitable shared library mechanism for linking with the + Library. A suitable mechanism is one that (a) uses at run time + a copy of the Library already present on the user's computer + system, and (b) will operate properly with a modified version + of the Library that is interface-compatible with the Linked + Version. + + e) Provide Installation Information, but only if you would otherwise + be required to provide such information under section 6 of the + GNU GPL, and only to the extent that such information is + necessary to install and execute a modified version of the + Combined Work produced by recombining or relinking the + Application with a modified version of the Linked Version. (If + you use option 4d0, the Installation Information must accompany + the Minimal Corresponding Source and Corresponding Application + Code. If you use option 4d1, you must provide the Installation + Information in the manner specified by section 6 of the GNU GPL + for conveying Corresponding Source.) + + 5. Combined Libraries. + + You may place library facilities that are a work based on the +Library side by side in a single library together with other library +facilities that are not Applications and are not covered by this +License, and convey such a combined library under terms of your +choice, if you do both of the following: + + a) Accompany the combined library with a copy of the same work based + on the Library, uncombined with any other library facilities, + conveyed under the terms of this License. + + b) Give prominent notice with the combined library that part of it + is a work based on the Library, and explaining where to find the + accompanying uncombined form of the same work. + + 6. Revised Versions of the GNU Lesser General Public License. + + The Free Software Foundation may publish revised and/or new versions +of the GNU Lesser General Public License from time to time. Such new +versions will be similar in spirit to the present version, but may +differ in detail to address new problems or concerns. + + Each version is given a distinguishing version number. If the +Library as you received it specifies that a certain numbered version +of the GNU Lesser General Public License "or any later version" +applies to it, you have the option of following the terms and +conditions either of that published version or of any later version +published by the Free Software Foundation. If the Library as you +received it does not specify a version number of the GNU Lesser +General Public License, you may choose any version of the GNU Lesser +General Public License ever published by the Free Software Foundation. + + If the Library as you received it specifies that a proxy can decide +whether future versions of the GNU Lesser General Public License shall +apply, that proxy's public statement of acceptance of any version is +permanent authorization for you to choose that version for the +Library. diff --git a/lib/Freenove_WS2812_Lib_for_ESP32/README.md b/lib/Freenove_WS2812_Lib_for_ESP32/README.md new file mode 100644 index 0000000..120f64a --- /dev/null +++ b/lib/Freenove_WS2812_Lib_for_ESP32/README.md @@ -0,0 +1,82 @@ +# Freenove WS2812 Lib for ESP32 + +## Description +This is an Arduino library for controlling ws2812b led on esp32. + +Based on the example program "led_strip" in IDF-SDK. The source code repository is here: +https://github.com/espressif/esp-idf/tree/master/examples/peripherals/rmt/led_strip + + +## Examples: + +Here are some simple examples. + +### Show Rainbow +This example make your strip show a flowing rainbow. +``` +#include "Freenove_WS2812_Lib_for_ESP32.h" + +#define LEDS_COUNT 8 +#define LEDS_PIN 2 +#define CHANNEL 0 + +Freenove_ESP32_WS2812 strip = Freenove_ESP32_WS2812(LEDS_COUNT, LEDS_PIN, CHANNEL); + +void setup() { + strip.begin(); +} + +void loop() { + for (int j = 0; j < 255; j += 2) { + for (int i = 0; i < LEDS_COUNT; i++) { + strip.setLedColorData(i, strip.Wheel((i * 256 / LEDS_COUNT + j) & 255)); + } + strip.show(); + delay(2); + } +} + +``` + +## Usage +``` +Freenove_ESP32_WS2812 strip = Freenove_ESP32_WS2812(LEDS_COUNT, LEDS_PIN, CHANNEL, TYPE_GRB); +``` +* Construction. Create a strip object. + +``` +strip.begin() +``` +Initialization data, ready for communication. +``` +strip.setLedColorData(id, color); +strip.setLedColorData(id, r, g, b); +``` +* Send the color data of the specified LED to the controller. +* Display color change after calling show function. + * id: the index of led. + * color: color value. egg, 0xFF0000 is RED color. + * r,g,b: color value. 0-255. +``` +strip.show(); +``` +* Immediately display the color data that has been sent. + + +``` +strip.setLedColor(id, color); +strip.setLedColor(id, r, g, b); +``` +* Send color data and display it immediately. +* It is equivalent to "strip.setLedColorData(id, color); strip.show();" + * id: the index of led. + * color: color value. egg, 0xFF0000 is RED color. + * r,g,b: color value. 0-255. + +``` +strip.Wheel(i) +``` +* A simple color picker. + * i: 0-255. + + diff --git a/lib/Freenove_WS2812_Lib_for_ESP32/examples/RGBW/RGBW.ino b/lib/Freenove_WS2812_Lib_for_ESP32/examples/RGBW/RGBW.ino new file mode 100644 index 0000000..887d3f1 --- /dev/null +++ b/lib/Freenove_WS2812_Lib_for_ESP32/examples/RGBW/RGBW.ino @@ -0,0 +1,25 @@ +#include "Freenove_WS2812_Lib_for_ESP32.h" + +#define LEDS_COUNT 8 +#define LEDS_PIN 2 +#define CHANNEL 0 + +Freenove_ESP32_WS2812 strip = Freenove_ESP32_WS2812(LEDS_COUNT, LEDS_PIN, CHANNEL, TYPE_GRB); + +u8 m_color[5][3] = { {255, 0, 0}, {0, 255, 0}, {0, 0, 255}, {255, 255, 255}, {0, 0, 0} }; +int delayval = 100; + +void setup() { + strip.begin(); + strip.setBrightness(10); +} +void loop() { + for (int j = 0; j < 5; j++) { + for (int i = 0; i < LEDS_COUNT; i++) { + strip.setLedColorData(i, m_color[j][0], m_color[j][1], m_color[j][2]); + strip.show(); + delay(delayval); + } + delay(500); + } +} \ No newline at end of file diff --git a/lib/Freenove_WS2812_Lib_for_ESP32/examples/Rainbow/Rainbow.ino b/lib/Freenove_WS2812_Lib_for_ESP32/examples/Rainbow/Rainbow.ino new file mode 100644 index 0000000..4c38a5b --- /dev/null +++ b/lib/Freenove_WS2812_Lib_for_ESP32/examples/Rainbow/Rainbow.ino @@ -0,0 +1,21 @@ +#include "Freenove_WS2812_Lib_for_ESP32.h" + +#define LEDS_COUNT 8 +#define LEDS_PIN 2 +#define CHANNEL 0 + +Freenove_ESP32_WS2812 strip = Freenove_ESP32_WS2812(LEDS_COUNT, LEDS_PIN, CHANNEL, TYPE_GRB); + +void setup() { + strip.begin(); +} + +void loop() { + for (int j = 0; j < 255; j += 2) { + for (int i = 0; i < LEDS_COUNT; i++) { + strip.setLedColorData(i, strip.Wheel((i * 256 / LEDS_COUNT + j) & 255)); + } + strip.show(); + delay(5); + } +} diff --git a/lib/Freenove_WS2812_Lib_for_ESP32/extras/ColorWheel.jpg b/lib/Freenove_WS2812_Lib_for_ESP32/extras/ColorWheel.jpg new file mode 100644 index 0000000..60329f6 Binary files /dev/null and b/lib/Freenove_WS2812_Lib_for_ESP32/extras/ColorWheel.jpg differ diff --git a/lib/Freenove_WS2812_Lib_for_ESP32/keywords.txt b/lib/Freenove_WS2812_Lib_for_ESP32/keywords.txt new file mode 100644 index 0000000..4c77a6a --- /dev/null +++ b/lib/Freenove_WS2812_Lib_for_ESP32/keywords.txt @@ -0,0 +1,30 @@ +#class (KEYWORD1) + + +Freenove_ESP32_WS2812 KEYWORD1 +LED_TYPE KEYWORD1 + +#function and method (KEYWORD2) +begin KEYWORD2 +setLedsCount KEYWORD2 +setLedType KEYWORD2 +setBrightness KEYWORD2 +setLedColorData KEYWORD2 +setLedColor KEYWORD2 +setAllLedsColorData KEYWORD2 +setAllLedsColor KEYWORD2 +show KEYWORD2 + +Wheel KEYWORD2 +hsv2rgb KEYWORD2 + + +#constant (LITERAL1) +#none +TYPE_RGB LITERAL1 +TYPE_RBG LITERAL1 +TYPE_GRB LITERAL1 +TYPE_GBR LITERAL1 +TYPE_BRG LITERAL1 +TYPE_BGR LITERAL1 + diff --git a/lib/Freenove_WS2812_Lib_for_ESP32/library.properties b/lib/Freenove_WS2812_Lib_for_ESP32/library.properties new file mode 100644 index 0000000..93a890f --- /dev/null +++ b/lib/Freenove_WS2812_Lib_for_ESP32/library.properties @@ -0,0 +1,10 @@ +name=Freenove WS2812 Lib for ESP32 +version=1.0.4 +author=Freenove +maintainer=Freenove +sentence=An Arduino library for WS2812 led on ESP32.
+paragraph=This is an Arduino library for controlling ws2812b led on esp32. +category=Display +url=https://github.com/Freenove/Freenove_WS2812_Lib_for_ESP32 +architectures=esp32 +includes=Freenove_WS2812_Lib_for_ESP32.h \ No newline at end of file diff --git a/lib/Freenove_WS2812_Lib_for_ESP32/src/Freenove_WS2812_Lib_for_ESP32.cpp b/lib/Freenove_WS2812_Lib_for_ESP32/src/Freenove_WS2812_Lib_for_ESP32.cpp new file mode 100644 index 0000000..bbb7861 --- /dev/null +++ b/lib/Freenove_WS2812_Lib_for_ESP32/src/Freenove_WS2812_Lib_for_ESP32.cpp @@ -0,0 +1,179 @@ +// +// +// +/** + * Brief A library for controlling ws2812 in esp32 platform. + * Author SuhaylZhao + * Company Freenove + * Date 2020-07-31 + */ + + +#include "Freenove_WS2812_Lib_for_ESP32.h" + + +Freenove_ESP32_WS2812::Freenove_ESP32_WS2812(u16 n /*= 8*/, u8 pin_gpio /*= 2*/, u8 chn /*= 0*/, LED_TYPE t /*= TYPE_GRB*/) +{ + ledCounts = n; + pin = pin_gpio; + rmt_chn = chn; + br = 255; + setLedType(t); +} + +bool Freenove_ESP32_WS2812::begin() +{ + rmt_config_t config = RMT_DEFAULT_CONFIG_TX(pin, rmt_chn); + rmt_config(&config); + rmt_driver_install(config.channel, 0, 0); + + strip_config = LED_STRIP_DEFAULT_CONFIG(ledCounts, (led_strip_dev_t)config.channel); + + strip = led_strip_new_rmt_ws2812(&strip_config); + if (!strip) { + return false; + } + return true; +} + +void Freenove_ESP32_WS2812::setLedCount(u16 n) +{ + ledCounts = n; + begin(); +} + +void Freenove_ESP32_WS2812::setLedType(LED_TYPE t) +{ + rOffset = (t >> 4) & 0x03; + gOffset = (t >> 2) & 0x03; + bOffset = t & 0x03; +} + +void Freenove_ESP32_WS2812::setBrightness(u8 brightness) +{ + br = constrain(brightness, 0, 255); +} + +esp_err_t Freenove_ESP32_WS2812::setLedColorData(u16 index, u32 rgb) +{ + return setLedColorData(index, rgb >> 16, rgb >> 8, rgb); +} + +esp_err_t Freenove_ESP32_WS2812::setLedColorData(u16 index, u8 r, u8 g, u8 b) +{ + u8 p[3]; + p[rOffset] = r * br / 255; + p[gOffset] = g * br / 255; + p[bOffset] = b * br / 255; + return strip->set_pixel(strip, index, p[0], p[1], p[2]); +} + +esp_err_t Freenove_ESP32_WS2812::setLedColor(u16 index, u32 rgb) +{ + return setLedColor(index, rgb >> 16, rgb >> 8, rgb); +} + +esp_err_t Freenove_ESP32_WS2812::setLedColor(u16 index, u8 r, u8 g, u8 b) +{ + setLedColorData(index, r, g, b); + return show(); +} + +esp_err_t Freenove_ESP32_WS2812::setAllLedsColorData(u32 rgb) +{ + for (int i = 0; i < ledCounts; i++) + { + setLedColorData(i, rgb); + } + return ESP_OK; +} + +esp_err_t Freenove_ESP32_WS2812::setAllLedsColorData(u8 r, u8 g, u8 b) +{ + for (int i = 0; i < ledCounts; i++) + { + setLedColorData(i, r, g, b); + } + return ESP_OK; +} + +esp_err_t Freenove_ESP32_WS2812::setAllLedsColor(u32 rgb) +{ + setAllLedsColorData(rgb); + show(); + return ESP_OK; +} + +esp_err_t Freenove_ESP32_WS2812::setAllLedsColor(u8 r, u8 g, u8 b) +{ + setAllLedsColorData(r, g, b); + show(); + return ESP_OK; +} + +esp_err_t Freenove_ESP32_WS2812::show() +{ + return strip->refresh(strip, 100); +} + +uint32_t Freenove_ESP32_WS2812::Wheel(byte pos) +{ + u32 WheelPos = pos % 0xff; + if (WheelPos < 85) { + return ((255 - WheelPos * 3) << 16) | ((WheelPos * 3) << 8); + } + if (WheelPos < 170) { + WheelPos -= 85; + return (((255 - WheelPos * 3) << 8) | (WheelPos * 3)); + } + WheelPos -= 170; + return ((WheelPos * 3) << 16 | (255 - WheelPos * 3)); +} + +uint32_t Freenove_ESP32_WS2812::hsv2rgb(uint32_t h, uint32_t s, uint32_t v) +{ + u8 r, g, b; + h %= 360; // h -> [0,360] + uint32_t rgb_max = v * 2.55f; + uint32_t rgb_min = rgb_max * (100 - s) / 100.0f; + + uint32_t i = h / 60; + uint32_t diff = h % 60; + + // RGB adjustment amount by hue + uint32_t rgb_adj = (rgb_max - rgb_min) * diff / 60; + + switch (i) { + case 0: + r = rgb_max; + g = rgb_min + rgb_adj; + b = rgb_min; + break; + case 1: + r = rgb_max - rgb_adj; + g = rgb_max; + b = rgb_min; + break; + case 2: + r = rgb_min; + g = rgb_max; + b = rgb_min + rgb_adj; + break; + case 3: + r = rgb_min; + g = rgb_max - rgb_adj; + b = rgb_max; + break; + case 4: + r = rgb_min + rgb_adj; + g = rgb_min; + b = rgb_max; + break; + default: + r = rgb_max; + g = rgb_min; + b = rgb_max - rgb_adj; + break; + } + return (uint32_t)(r << 16 | g << 8 | b); +} diff --git a/lib/Freenove_WS2812_Lib_for_ESP32/src/Freenove_WS2812_Lib_for_ESP32.h b/lib/Freenove_WS2812_Lib_for_ESP32/src/Freenove_WS2812_Lib_for_ESP32.h new file mode 100644 index 0000000..3676356 --- /dev/null +++ b/lib/Freenove_WS2812_Lib_for_ESP32/src/Freenove_WS2812_Lib_for_ESP32.h @@ -0,0 +1,98 @@ +// Freenove_WS2812_Lib_for_ESP32.h +/** + * Brief A library for controlling ws2812 in esp32 platform. + * Author SuhaylZhao + * Company Freenove + * Date 2020-07-31 + */ + +#ifndef _FREENOVE_WS2812_LIB_FOR_ESP32_h +#define _FREENOVE_WS2812_LIB_FOR_ESP32_h + +#if defined(ARDUINO) && ARDUINO >= 100 +#include +#else +#include "WProgram.h" +#endif + +#include "driver/rmt.h" +#include "led_strip.h" + +typedef unsigned char u8; +typedef unsigned short u16; +typedef unsigned long u32; + +enum LED_TYPE +{ //R G B + TYPE_RGB = 0x06, //00 01 10 + TYPE_RBG = 0x09, //00 10 01 + TYPE_GRB = 0x12, //01 00 10 + TYPE_GBR = 0x21, //10 00 01 + TYPE_BRG = 0x18, //01 10 00 + TYPE_BGR = 0x24 //10 01 00 +}; + +#define RMT_DEFAULT_CONFIG_TX(gpio, channel_id) \ + { \ + .rmt_mode = RMT_MODE_TX, \ + .channel = (rmt_channel_t)channel_id, \ + .gpio_num = (gpio_num_t)gpio, \ + .clk_div = 2, \ + .mem_block_num = 1, \ + .flags = 0, \ + .tx_config = { \ + .carrier_freq_hz = 38000, \ + .carrier_level = RMT_CARRIER_LEVEL_HIGH, \ + .idle_level = RMT_IDLE_LEVEL_LOW, \ + .carrier_duty_percent = 33, \ + .carrier_en = false, \ + .loop_en = false, \ + .idle_output_en = true, \ + } \ + } + +class Freenove_ESP32_WS2812 +{ +protected: + + u16 ledCounts; + u8 rmt_chn; + u8 pin; + u8 br; + + u8 rOffset; + u8 gOffset; + u8 bOffset; + + rmt_config_t config; + led_strip_config_t strip_config; + led_strip_t *strip; + +public: + Freenove_ESP32_WS2812(u16 n = 8, u8 pin_gpio = 2, u8 chn = 0, LED_TYPE t = TYPE_GRB); + + bool begin(); + void setLedCount(u16 n); + void setLedType(LED_TYPE t); + void setBrightness(u8 brightness); + + esp_err_t setLedColorData(u16 index, u32 rgb); + esp_err_t setLedColorData(u16 index, u8 r, u8 g, u8 b); + + esp_err_t setLedColor(u16 index, u32 rgb); + esp_err_t setLedColor(u16 index, u8 r, u8 g, u8 b); + + esp_err_t setAllLedsColorData(u32 rgb); + esp_err_t setAllLedsColorData(u8 r, u8 g, u8 b); + + esp_err_t setAllLedsColor(u32 rgb); + esp_err_t setAllLedsColor(u8 r, u8 g, u8 b); + + esp_err_t show(); + + uint32_t Wheel(byte pos); + uint32_t hsv2rgb(uint32_t h, uint32_t s, uint32_t v); +}; + +#endif + diff --git a/lib/Freenove_WS2812_Lib_for_ESP32/src/led_strip.h b/lib/Freenove_WS2812_Lib_for_ESP32/src/led_strip.h new file mode 100644 index 0000000..fa3c12f --- /dev/null +++ b/lib/Freenove_WS2812_Lib_for_ESP32/src/led_strip.h @@ -0,0 +1,127 @@ +// Copyright 2019 Espressif Systems (Shanghai) PTE LTD +// +// Licensed under the Apache License, Version 2.0 (the "License"); +// you may not use this file except in compliance with the License. +// You may obtain a copy of the License at +// +// http://www.apache.org/licenses/LICENSE-2.0 +// +// Unless required by applicable law or agreed to in writing, software +// distributed under the License is distributed on an "AS IS" BASIS, +// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +// See the License for the specific language governing permissions and +// limitations under the License. +#pragma once + +#ifdef __cplusplus +extern "C" { +#endif + +#include "esp_err.h" + +/** +* @brief LED Strip Type +* +*/ +typedef struct led_strip_s led_strip_t; + +/** +* @brief LED Strip Device Type +* +*/ +typedef void *led_strip_dev_t; + +/** +* @brief Declare of LED Strip Type +* +*/ +struct led_strip_s { + /** + * @brief Set RGB for a specific pixel + * + * @param strip: LED strip + * @param index: index of pixel to set + * @param red: red part of color + * @param green: green part of color + * @param blue: blue part of color + * + * @return + * - ESP_OK: Set RGB for a specific pixel successfully + * - ESP_ERR_INVALID_ARG: Set RGB for a specific pixel failed because of invalid parameters + * - ESP_FAIL: Set RGB for a specific pixel failed because other error occurred + */ + esp_err_t (*set_pixel)(led_strip_t *strip, uint32_t index, uint32_t red, uint32_t green, uint32_t blue); + + /** + * @brief Refresh memory colors to LEDs + * + * @param strip: LED strip + * @param timeout_ms: timeout value for refreshing task + * + * @return + * - ESP_OK: Refresh successfully + * - ESP_ERR_TIMEOUT: Refresh failed because of timeout + * - ESP_FAIL: Refresh failed because some other error occurred + * + * @note: + * After updating the LED colors in the memory, a following invocation of this API is needed to flush colors to strip. + */ + esp_err_t (*refresh)(led_strip_t *strip, uint32_t timeout_ms); + + /** + * @brief Clear LED strip (turn off all LEDs) + * + * @param strip: LED strip + * @param timeout_ms: timeout value for clearing task + * + * @return + * - ESP_OK: Clear LEDs successfully + * - ESP_ERR_TIMEOUT: Clear LEDs failed because of timeout + * - ESP_FAIL: Clear LEDs failed because some other error occurred + */ + esp_err_t (*clear)(led_strip_t *strip, uint32_t timeout_ms); + + /** + * @brief Free LED strip resources + * + * @param strip: LED strip + * + * @return + * - ESP_OK: Free resources successfully + * - ESP_FAIL: Free resources failed because error occurred + */ + esp_err_t (*del)(led_strip_t *strip); +}; + +/** +* @brief LED Strip Configuration Type +* +*/ +typedef struct { + uint32_t max_leds; /*!< Maximum LEDs in a single strip */ + led_strip_dev_t dev; /*!< LED strip device (e.g. RMT channel, PWM channel, etc) */ +} led_strip_config_t; + +/** + * @brief Default configuration for LED strip + * + */ +#define LED_STRIP_DEFAULT_CONFIG(number, dev_hdl) \ + { \ + .max_leds = number, \ + .dev = dev_hdl, \ + } + +/** +* @brief Install a new ws2812 driver (based on RMT peripheral) +* +* @param config: LED strip configuration +* @return +* LED strip instance or NULL +*/ +led_strip_t *led_strip_new_rmt_ws2812(const led_strip_config_t *config); + + +#ifdef __cplusplus +} +#endif diff --git a/lib/Freenove_WS2812_Lib_for_ESP32/src/led_strip_rmt_ws2812.c b/lib/Freenove_WS2812_Lib_for_ESP32/src/led_strip_rmt_ws2812.c new file mode 100644 index 0000000..b750947 --- /dev/null +++ b/lib/Freenove_WS2812_Lib_for_ESP32/src/led_strip_rmt_ws2812.c @@ -0,0 +1,183 @@ +// Copyright 2019 Espressif Systems (Shanghai) PTE LTD +// +// Licensed under the Apache License, Version 2.0 (the "License"); +// you may not use this file except in compliance with the License. +// You may obtain a copy of the License at +// +// http://www.apache.org/licenses/LICENSE-2.0 +// +// Unless required by applicable law or agreed to in writing, software +// distributed under the License is distributed on an "AS IS" BASIS, +// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +// See the License for the specific language governing permissions and +// limitations under the License. +#include +#include +#include +#include "esp_log.h" +#include "esp_attr.h" +#include "led_strip.h" +#include "driver/rmt.h" + + +static const char *TAG = "ws2812"; +#define STRIP_CHECK(a, str, goto_tag, ret_value, ...) \ + do \ + { \ + if (!(a)) \ + { \ + ESP_LOGE(TAG, "%s(%d): " str, __FUNCTION__, __LINE__, ##__VA_ARGS__); \ + ret = ret_value; \ + goto goto_tag; \ + } \ + } while (0) + +#define WS2812_T0H_NS (350) +#define WS2812_T0L_NS (1000) +#define WS2812_T1H_NS (1000) +#define WS2812_T1L_NS (350) +#define WS2812_RESET_US (280) + +static uint32_t ws2812_t0h_ticks = 0; +static uint32_t ws2812_t1h_ticks = 0; +static uint32_t ws2812_t0l_ticks = 0; +static uint32_t ws2812_t1l_ticks = 0; + +typedef struct { + led_strip_t parent; + rmt_channel_t rmt_channel; + uint32_t strip_len; + uint8_t buffer[0]; +} ws2812_t; + +/** + * @brief Conver RGB data to RMT format. + * + * @note For WS2812, R,G,B each contains 256 different choices (i.e. uint8_t) + * + * @param[in] src: source data, to converted to RMT format + * @param[in] dest: place where to store the convert result + * @param[in] src_size: size of source data + * @param[in] wanted_num: number of RMT items that want to get + * @param[out] translated_size: number of source data that got converted + * @param[out] item_num: number of RMT items which are converted from source data + */ +static void IRAM_ATTR ws2812_rmt_adapter(const void *src, rmt_item32_t *dest, size_t src_size, + size_t wanted_num, size_t *translated_size, size_t *item_num) +{ + if (src == NULL || dest == NULL) { + *translated_size = 0; + *item_num = 0; + return; + } + const rmt_item32_t bit0 = {{{ ws2812_t0h_ticks, 1, ws2812_t0l_ticks, 0 }}}; //Logical 0 + const rmt_item32_t bit1 = {{{ ws2812_t1h_ticks, 1, ws2812_t1l_ticks, 0 }}}; //Logical 1 + size_t size = 0; + size_t num = 0; + uint8_t *psrc = (uint8_t *)src; + rmt_item32_t *pdest = dest; + while (size < src_size && num < wanted_num) { + for (int i = 0; i < 8; i++) { + // MSB first + if (*psrc & (1 << (7 - i))) { + pdest->val = bit1.val; + } else { + pdest->val = bit0.val; + } + num++; + pdest++; + } + size++; + psrc++; + } + *translated_size = size; + *item_num = num; +} + +static esp_err_t ws2812_set_pixel(led_strip_t *strip, uint32_t index, uint32_t red, uint32_t green, uint32_t blue) +{ + esp_err_t ret = ESP_OK; + ws2812_t *ws2812 = __containerof(strip, ws2812_t, parent); + STRIP_CHECK(index < ws2812->strip_len, "index out of the maximum number of leds", err, ESP_ERR_INVALID_ARG); + uint32_t start = index * 3; + // In thr order of RGB + ws2812->buffer[start + 1] = green & 0xFF; + ws2812->buffer[start + 0] = red & 0xFF; + ws2812->buffer[start + 2] = blue & 0xFF; + return ESP_OK; +err: + return ret; +} + +static esp_err_t ws2812_refresh(led_strip_t *strip, uint32_t timeout_ms) +{ + esp_err_t ret = ESP_OK; + ws2812_t *ws2812 = __containerof(strip, ws2812_t, parent); + STRIP_CHECK(rmt_write_sample(ws2812->rmt_channel, ws2812->buffer, ws2812->strip_len * 3, true) == ESP_OK, + "transmit RMT samples failed", err, ESP_FAIL); + return rmt_wait_tx_done(ws2812->rmt_channel, pdMS_TO_TICKS(timeout_ms)); +err: + return ret; +} + +static esp_err_t ws2812_clear(led_strip_t *strip, uint32_t timeout_ms) +{ + ws2812_t *ws2812 = __containerof(strip, ws2812_t, parent); + // Write zero to turn off all leds + memset(ws2812->buffer, 0, ws2812->strip_len * 3); + return ws2812_refresh(strip, timeout_ms); +} + +static esp_err_t ws2812_del(led_strip_t *strip) +{ + ws2812_t *ws2812 = __containerof(strip, ws2812_t, parent); + free(ws2812); + return ESP_OK; +} + +led_strip_t *led_strip_new_rmt_ws2812(const led_strip_config_t *config) +{ + led_strip_t *ret = NULL; + STRIP_CHECK(config, "configuration can't be null", err, NULL); + + // 24 bits per led + uint32_t ws2812_size = sizeof(ws2812_t) + config->max_leds * 3; + ws2812_t *ws2812 = calloc(1, ws2812_size); + STRIP_CHECK(ws2812, "request memory for ws2812 failed", err, NULL); + + uint32_t counter_clk_hz = 0; + + rmt_source_clk_t clk_t; + uint8_t div_tt; + rmt_get_source_clk((rmt_channel_t)config->dev, &clk_t); + rmt_get_clk_div((rmt_channel_t)config->dev, &div_tt); + if (clk_t == 1) + { + counter_clk_hz = 80000000 / div_tt; + } + + //STRIP_CHECK(rmt_get_counter_clock((rmt_channel_t)config->dev, &counter_clk_hz) == ESP_OK, + // "get rmt counter clock failed", err, NULL); + //counter_clk_hz = 40000000; + // ns -> ticks + float ratio = (float)counter_clk_hz / 1e9; + ws2812_t0h_ticks = (uint32_t)(ratio * WS2812_T0H_NS); + ws2812_t0l_ticks = (uint32_t)(ratio * WS2812_T0L_NS); + ws2812_t1h_ticks = (uint32_t)(ratio * WS2812_T1H_NS); + ws2812_t1l_ticks = (uint32_t)(ratio * WS2812_T1L_NS); + + // set ws2812 to rmt adapter + rmt_translator_init((rmt_channel_t)config->dev, ws2812_rmt_adapter); + + ws2812->rmt_channel = (rmt_channel_t)config->dev; + ws2812->strip_len = config->max_leds; + + ws2812->parent.set_pixel = ws2812_set_pixel; + ws2812->parent.refresh = ws2812_refresh; + ws2812->parent.clear = ws2812_clear; + ws2812->parent.del = ws2812_del; + + return &ws2812->parent; +err: + return ret; +} diff --git a/lib/README b/lib/README new file mode 100644 index 0000000..6debab1 --- /dev/null +++ b/lib/README @@ -0,0 +1,46 @@ + +This directory is intended for project specific (private) libraries. +PlatformIO will compile them to static libraries and link into executable file. + +The source code of each library should be placed in a an own separate directory +("lib/your_library_name/[here are source files]"). + +For example, see a structure of the following two libraries `Foo` and `Bar`: + +|--lib +| | +| |--Bar +| | |--docs +| | |--examples +| | |--src +| | |- Bar.c +| | |- Bar.h +| | |- library.json (optional, custom build options, etc) https://docs.platformio.org/page/librarymanager/config.html +| | +| |--Foo +| | |- Foo.c +| | |- Foo.h +| | +| |- README --> THIS FILE +| +|- platformio.ini +|--src + |- main.c + +and a contents of `src/main.c`: +``` +#include +#include + +int main (void) +{ + ... +} + +``` + +PlatformIO Library Dependency Finder will find automatically dependent +libraries scanning project source files. + +More information about PlatformIO Library Dependency Finder +- https://docs.platformio.org/page/librarymanager/ldf.html diff --git a/lib/libtins/.github/workflows/tests.yaml b/lib/libtins/.github/workflows/tests.yaml new file mode 100644 index 0000000..151766e --- /dev/null +++ b/lib/libtins/.github/workflows/tests.yaml @@ -0,0 +1,28 @@ +name: Tests +on: + push: + branches: + - master + pull_request: + branches: + - master +jobs: + Ubuntu-Tests: + runs-on: ubuntu-latest + steps: + - uses: actions/checkout@v2 + + - name: Install libpcap + run: sudo apt-get install -y libpcap-dev + + - name: Initialize submodules + run: git submodule init && git submodule update + + - name: Initialize build system + run: mkdir build && cd build && cmake .. + + - name: Build tests + run: cmake --build build --target tests + + - name: Run tests + run: ctest build diff --git a/lib/libtins/.gitignore b/lib/libtins/.gitignore new file mode 100644 index 0000000..6109d95 --- /dev/null +++ b/lib/libtins/.gitignore @@ -0,0 +1,2 @@ +build/** +include/tins/config.h diff --git a/lib/libtins/.gitmodules b/lib/libtins/.gitmodules new file mode 100644 index 0000000..38d72db --- /dev/null +++ b/lib/libtins/.gitmodules @@ -0,0 +1,4 @@ +[submodule "googletest"] + path = googletest + url = https://github.com/google/googletest.git + ignore = dirty diff --git a/lib/libtins/.travis.yml b/lib/libtins/.travis.yml new file mode 100644 index 0000000..0741854 --- /dev/null +++ b/lib/libtins/.travis.yml @@ -0,0 +1,27 @@ +language: cpp + +sudo: false + +compiler: + - gcc + - clang + +os: + - linux + - osx + +addons: + apt: + packages: + - libpcap-dev + - libssl-dev + - libboost-all-dev + +before_script: + - mkdir build + - cd build + - cmake .. -DLIBTINS_ENABLE_CXX11=1 + - make tests + +script: + - ctest -V \ No newline at end of file diff --git a/lib/libtins/CHANGES.md b/lib/libtins/CHANGES.md new file mode 100644 index 0000000..dcf3375 --- /dev/null +++ b/lib/libtins/CHANGES.md @@ -0,0 +1,781 @@ +##### v4.4 - Thu Feb 17 14:41:59 UTC 2022 + +- Add RFC8335 extended echo types to `ICMP` and `ICMPv6` (#426) + +- Handle loops in DNS name decompression (#444) + +- Fix Windows' `interface` macro colliding with uses of that identifier in the code (#458) + +- Sending IPv6 packets to a link-scope destination address now uses the right interface index (#448) + +- Fix incorrect endian being used for ICMP's `gateway` and `address_mask` (#437) + +- Socket in `PacketSender::open_l3_socket` is now closed if `setsockopt` fails (#433) + +- Fix various incorrect doxygen documentation comments (#439). + +- Fix infinite loop when querying the routing table in \*BSD (#427) + +##### v4.3 - Fri Sep 18 03:08:33 UTC 2020 + +- Assign a PDUType to `Dot11ControlTA` (#420) + +- Don't consider IPv6 ESP header a normal extension header (#374) + +- Don't include non-existing headers when installed without libpcap (#382) + +- Add `IPv6Address::is_local_unicast` (#369) + +- Fix memory leak in `PacketWriter` (#343) + +- Fix memory leaks in `OfflinePacketFilter` (#343) + +- Fix detection of new TCP stream (#335) + +- Introduce `TCP::has_flags` (#334) + +- Fix padding calculations in RadioTapWriter (#333) + +##### v4.2 - Fri Mar 8 04:15:13 UTC 2019 + +- Updated location of installed CMake files in unix systems (#331) + +- Fix check to detect cross compilation (#330) + +- Allow getting a PDU's advertised size and use it in `PacketWriter` (#324) + +- Install DLLs in right directory (#326) + +- Add missing Dot11 tagged option types (#305) + +- Add support for DLT_RAW (#313) + +- Fix potential invalid memory accesses when parsing RadioTap (#322) + +##### v4.1 - Tue Dec 11 02:08:48 UTC 2018 + +- Fix serialization for QinQ (#316) + +- Added base class access specifier for socket_close_error (#306) + +- Rewrote hw_address_to_string to not require a stringstream (#299) + +- Make RadioTapParser::skip_to_field check for end of buffer (#296) + +- Ensure local include directory comes before system. (#293) + +- Calculate IP option sizes properly (#288) + +- Add parsing of well known IPv6 extension headers (#287) + +- Add missing operators to address classes (#275) + +- Add version macros in config.h + +- Don't assume IPv6 uses ICMPv6 underneath + +- Allow users to specify library install dir + +- Use Sleep windows function passing milliseconds as parameter + +- Implement IPv6::recv_response + +- Don't use nullptr in non C++11 code + +- Ignore (possibly malformed) options after EOL (#281) + +- Don't include dot11.h in tins.h if it is not configured in the library (#277) + +- Fix memory leak in PDU's move assignment operator + +- Append padding to IPv6 options + +##### v4.0 - Mon Dec 4 00:04:30 UTC 2017 + +- Add parent PDU to each PDU. + +- Removed parent PDU parameter on `PDU::write_serialization`. + +- Split `utils.h` into multiple files under the `utils` directory. + +- Split `internals.h` into multiple files under the `detail` directory. + +- Improve compilation times by removing useless include directives. + +- Refactor `PDUOption` conversions so that heavy headers are not included in source file. + +- Use `std::vector` instead of `std::list` in `TCP`, `IP`, `IPv6`, `DHCP`, `DHCPv6`, `DNS`, `LLC`, `Dot11` and `PPPoE`. + +- Improve performance on `IP`, `IPv6` and `TCP` by compiting option sizes during serialization. + +- Minor performance improvements in `DNS`. + +- Fix `IPv6` next header handling. Now each one contains its own type and the next type is only set during serialization for ease of use. + +- Refactor `RadioTap` parsing and serialization using a generic parser/writer. + +- Add `BaseSniffer::set_pcap_sniffing_method` to specify whether `pcap_loop` or `pcap_dispatch` should be used when sniffing. + +- Use `IFF_POINTOPOINT` on BSD when getting broadcast address for an interface. + +- Added cipher and akm suites from 802.11-2016. + +- Add IPv6 layer parsing on `Loopback` packets. + +- Allow serializing `Loopback` on Windows. + +- Use the right flag on `Loopback` for `IPv6`. + +- Use the first fragment as a base when reassembling `IP` packets in `IPv4Reassembler`. + +- Restructure CMake files removing useless `CMakeLists.txt` in `include` paths. + +- Add getter/setter for "more data" field in `Dot11Base`. + +- Implemented matching for ND protocol related ICMPv6 messages. + +- Ensure TCP::OptionTypes has 8-bit range. + +- Add header files into CMake sources so IDE can pick them up. + +- Add MPLS "experimental" field. + +- Fix dhcpv6::duid_type constructor from duid_ll. + +##### v3.5 - Sat Apr 1 09:11:58 PDT 2017 + +- Added Utils::route6_entries + +- Allow masking IPv4/6 and hardware addresses via `operator&` + +- Add IPv4Address::from_prefix_length + +- Move `stream_id` into a new file and rename it `StreamIdentifier` + +- Allow disabling TCPIP classes + +- Properly handle out of order SACKs on `AckTracker` + +- Move TCP data tracking into a separate class + +- Allow constructing `StreamIdentifier` from a `Stream` + +- Allow configuring pcap timestamp precision + +- Allow building libtins using MinGW + +- Allow including libtins using `add_subdirectory` via CMake + +- Allow setting customer user data to each TCP stream + +- Allow skipping data forward in TCP streams + +- Allow attaching to already existing TCP streams + +- Fix: AddressRange masks first address as well + +- Fix: Add TINS_API to `IPv4Address::operator<<`, `DataTracker` and `AckTracker` + +- Fix: Don't always set `key_t` to 0 on `RSNEAPOL` + +- Fix: Handle MLDv1 properly on ICMP + +- Fix: Make Utils::resolve_hwaddress work on Windows + +- Fix: Interface was sometimes considered down when it was up (BSD/Linux) + +- Fix: Don't set `Dot1Q`'s payload type if next protocol type is unknown + +- Fix: Use recvfrom on BSD/OSX when capturing layer 3 packets + +- Fix: Make `Timestamp::current_time` work on Windows + +- Fix: Forward `NetworkInterface` argument when calling `PacketSender::send_l2` + +- Fix: `Timestamp` overflow issue + +- Fix: boost's include directories variable incorrectly used on build system + +- Fix: Configuring auto cleanup of `Stream`'s server data not working + +- Fix: Set `EthernetII` payload type to `UNKNOWN` if there's no inner PDU + +- Fix: Set payload type to 0 if there's no inner PDU in `IP`, `Dot1Q` and `IPv6` + +- Fix: Buffer length check issues on `Dot11QosData` + +- Fix: Use AF_INET6 flag when opening L3 IPv6 socket + +- Fix: Check expecter size properly on `DNS::extract_metadata` + +- Fix: several unused parameter warnings + +- Fix: CCMP decryption issue when `Dot11QoSData` has a TID != 0 + +##### v3.4 - Wed Mar 9 20:24:54 PST 2016 + +- Check the secure bit on HandshakeCapturer to detect 2nd packet + +- Add info members directly into NetworkInterface + +- Add IPv6 addresses to NetworkInterface::Info + +- Make *MemoryStream use size_t rather than uint32_t + +- Add WPA2Decrypter callback interface + +- Set MACOSX_RPATH to ON + +- Don't fail configuration if openssl is missing + +- Build layer 5 as RawPDU if IPv6 has fragment header + +- Fix examples so they build on gcc 4.6 + +- Fix flag value for sniffer's immediate mode + +- Fix IP fragment reassemble when packet has flags DF+MF + +- Add extract_metadata to main PDU classes + +- Fix examples to make them work on Windows + +- Use timercmp/sub and std::chrono to subtract timevals on PacketSender + +- Build examples against local libtins build + +- Add uninstall target + +- Prefix HAVE_ config.h macros with TINS_ + +- Use compiler intrinsics to swap bytes + +- Use C++11 mode by default + +- Add missing TINS_API to PDU classes. + +- Extend/fix ICMPv6 enum values and unify naming + +- Return an empty string for dot11 ssid, if ssid is present but empty + +- Implement new TCP stream follower mechanism + +- Use ExternalProject_Add rather than including the gtest directory + +- Fix invalid endian on IP fragment offset on OSX + +##### v3.3 - Sun Jan 31 21:06:04 PST 2016 + +- Add TCP connection close example + +- Move implementations on utils.h to utils.cpp + +- Add ICMPv6 Multicast Listener Query Messages support + +- Add ICMPv6 Multicast Listener Report Message support + +- Make DNS::Query and DNS::Resource lowercase and deprecate the old names + +- Change DNS::query/resource::type to query_type and deprecate old name + +- Add DNS Start Of Authority parsing and serialization + +- Parse and serialize MX preference field correctly + +- Add NetworkInterface::friendly_name to get Windows friendly names + +- Mask 16 bits on random number generated on traceroute example + +- Fix TCP sequence number addition/subtraction when wrapping around + +- Use 802.1ad protocol flag when seralizing stacked Dot1Q + +- Code cleanup and use same syntax on the entire project + +- Correctly serialize PPPoE session packets + +- Fix IPv6 extension headers parsing/serialization + +- Include examples before src to avoid duplicate tins target issue + +- Add MPLS PDU and hook it up with ICMP extensions + +- Set UDP checksum to 0xffff if it's 0 + +- Don't define TINS_STATIC in config.h + +- Fix invalid RSNEAPOL parsing issue + +- Remove special clang on OSX case when building gtest + +- Update pseudoheader_checksum signature + +- Fix overall checksum calculation + +- Set ICMP payload length without padding if no extensions are present + +- Export classes on Windows shared lib builds + +- Use google/googletest submodule and update to HEAD + +- Remove unused cassert header inclusions + +- Add input/output memory stream classes port PDU classes to use them + +- Add extensions for ICMP/ICMPv6 + +- Fix RSNInformation issues on big endian architectures + +- Add IP::fragment_offset and IP::flags + +- Don't set Ethernet type if inner PDU type is unknown + +- Don't run IP source address overwrite tests on OSX + +- Always calculate IP/IPv6 checksum + +- Fix invalid constant value on PPPoE + +- Define default constructor for PKTAP + +- Guard 802.11 parsing code on PPI around HAVE_DOT11 + +- Fix parsing of Dot11 packets encapsulated on PPI having FCS-at-end + +- Fix DataLinkType typo on doxygen docs + +- Update docs on sniff_loop handle persistency + +- Use uint32_t for DNS resource TTL setter + +- Erase streams when they're reassembed on IPv4Reassembler + +- Make all exceptions derive from exception_base + +- Add remove_option member to IP, TCP, Dot11, ICMPv6, DHCP and DHCPv6 + +- Allow HW addresses to be 00:00:00:00:00 on NetworkInterface::info + +- Increment option size when adding a new DHCPv6 option + +- Use NOMINMAX on examples + +- Add metric field to RouteEntry + +- Allow setting immediate mode on Sniffer + +- Use one flags field for all flags on SnifferConfiguration + +- Add ICMP responses example + +- Add interfaces_info example + +- Fix bug on SessionKeys::SessionKeys + +- Fix compilation errors on android platform + +- Fix example compilation on Windows + +- Add PacketWriter::write overload that takes a Packet + +- Use different IP addresses on IP tests depending on OS + +- Allow retrieving keys on WPA2Decrypter + +- Add NetworkInterface::is_up and NetworkInterface::info + +- Add NetworkInterface::Info::is_up + +- Fix compilation warnings on Windows x64 + +- Fix FindPCAP.cmake to find winpcap on x64 + +- Fix more tests warnings triggered on Windows + +- Fix tests compilation warnings on Windows + +- Fix error on VC triggered by pcap redefining the "inline" keyword + +- Soften DNS parsing rules + +- Replace WIN32 macro with _WIN32 + +- Fix IPv6Address::to_string on Windows + +- Fix DNS issues triggered on VC + +- Add google test as git submodule + +- Perserve IP protocol when using RawPDU + +- Use pcap_sendpacket by default to send packets on Windows + +- Don't allow receiving l2 packets on windows + +- Added RadioTap channel map type + +- Made rsn_information() a const member function to make Dot11ManagementFrame +immutable + +- Ensure HAVE_CXX11 is checked when defining TINS_IS_CXX11 + +- Use one integer field for all flags on TCP + +- Fix invalid DNS IPv4 address parsing on big endian arch + +- Don't compile WPA2 test if LIBTINS_ENABLE_WPA2=0 + +- Add Dot11 radio measurement name corresponding to IEEE 802.11-2012 + +------------------------------------------------------------------------------- + +##### v3.2 - Fri Mar 20 22:12:23 PST 2015 + +- Added include guard for config.h. + +- The functor used on BaseSniffer::sniff_loop can now take a Packet. + +- Added mcs, tx_flags, ext and data_retries options to RadioTap. + +- Fixed big endian representation of RadioTap header. + +- RadioTap's dbm_signal and dbm_noise are now signed. + +- RadioTap now throws if an option is not present when getting +its value. + +- TKIP decryption now works correctly on packets from AP to STA. + +- Added support for PKTAP header. + +- Fixed endian issue on IPv4Address::ip_to_int on Windows. + +- Fixed IP parsing when total length is 0 due to TCP segmentation offload. + +- Re-added support for pkg-config. + +- TCPStreamFollower now calls PDU::find_pdu instead of PDU::rfind_pdu. + +- Fixed assertion throw caused by DNS parsing on Windows on debug mode. + +- Added throw on BSD when trying to send_recv L3 packets. + +- Added Loopback::matches_response. + +- Removed obsolete autotools files. + +- Fixed exception thrown when an interface didn't have an IP address +on NetworkInterface. + +- Added NetworkInterface::is_loopback. + +- Moved all headers to the directory include/tins. + +- Fixed compilation warning on TCPStramFollower due to signed to unsigned +conversion on integral constant. + +- BaseSniffer::get_pcap_handle is now public. + +- PPPoE session packets are now parsed correctly. + +- Fixed invalid Loopback protocol detection on FreeBSD/OSX. + +- Fixed OSX IP packet sending issue. + +- Added useful constructors to RawPDU. + +- Fixed compilation errors on FreeBSD. + +- Improved documentation on several classes. + +- Fixed parsing bug when allocating IP over IP packets. + +- Fixed Windows network interface naming. + +- Utils::network_interface returns pcap compatible names on Windows. + +- NetworkInterface::name now works on Windows. + +- Added documentation generation through the build system. + +- Added SnifferConfiguration class. + +- Fixed bug on Dot3 serialization. + +- Added OfflinePacketFilter class. + +- Renamed NOEXCEPT macro to TINS_NOEXCEPT. + +- Added DataLinkType class. + +- IPv4Address now uses inet_pton when constructing from string. + +------------------------------------------------------------------------------- + +##### v3.1 - Sun Aug 24 21:39:43 ART 2014 + +- Fixed ICMPv6 checksum error on serialization. + +- Fixed empty domain name encoding on DNS. + +- Changed the build system to CMake. + +------------------------------------------------------------------------------- + +##### v3.0 - Thu Aug 7 21:39:09 ART 2014 + +- Timestamps can now be constructed from std::chrono::duration. + +- Packets can now be constructed from a PDU pointer and take ownership +of it. + +- All protocols now set the next layer protocol flag, regardless if +it was already set. This was not done in some protocols, +like EthernetII, and as a consequence if the network layer protocol +was replaced by other, the packet would be serialized incorrectly. + +- Fixed invalid parsing of some unknown DNS records. + +- Fixed unaligned memory accesses that were not supported under +ARMv4 and ARMv5. + +- Added BaseSniffer::set_extract_raw_pdus. + +- Reduced minimum automake version to 1.11. + +- Added Utils::to_string(PDU::PDUType). + +- Fixed error compilations on Windows. + +- Fixed ICMPv6 checksum calculation. + +- Added method in IP and TCP to emplace an option (C++11 only). + +- Added small option optimization to PDUOption. + +- Fixed error compilation on RSNInformation. + +- Renamed ICMP::check to ICMP::checksum. + +- Added Sniffer support to set interface to promiscuous mode. + +- TCPStreamFollower now handles overlapping fragments correctly. + +- Fixed bugs in TCPStreamFollower which didn't allow it to follow +stream correctly. + +- TCPStreamFollower now doesn't clear its state after every call to +TCPStreamFollower::follow_streams. + +- Added IPv6 flag check to pdu_flag_to_ip_type. + +- Added DHCP::hostname to extract the hostname options. + +- Removed extra qualifier on SessionKeys::decrypt_unicast which +produced compilation errors on some platforms. + +- PacketSender::send now uses PDU::matches_flag to match specific +PDU types. + +- Removed 'no newline at end of file' warnings. + +- Fixed bug when calling BIOCIMMEDIATE on *BSD. + +- Fixed bug on PacketSender::send_recv which didn't work under *BSD. + +- Fixed bug triggered by not including the string header. + +------------------------------------------------------------------------------- + +##### v2.0 - Thu Jan 23 11:09:38 ART 2014 + +- DNSResourceRecord was removed. Now DNS records are added using +DNS::Resource. + +- tins.h now includes ppi.h. + +- Done significant improvements in the speed of DNS parsing. + +- Added PDUOption<>::to<> which converts a PDUOption to a specific type. + +- Layer 3 packets sent using PacketSender::send_recv for which the +answer is a different PDU type. + +- ICMP::gateway now uses IPv4Address. + +- Added support for ICMP address mask request/reply. + +- Fixed bug in PacketSender when using send_recv and a layer 2 PDU. The +interface in which the packet was sent was not the default_interface +set when the sender was constructed. + +- IP packets sent using PacketSender::send_recv now match ICMP +responses. + +- Added support for ICMP timestamp request/reply packets. +ICMP::matches_response now works with these types of packets as well. + +- Added support for reassembling of fragmented IP packets via the +IPv4Reassembler class. + +- Fragmented IP packet's inner_pdu PDUs are not decoded now. + +- Added 1000ms as the default read timeout used when calling +pcap_open_live. Added BaseSniffer::set_timeout to modify this parameter. + +- Added the --disable-dot11 configure switch. + +- Added support for IPSec. + +- Fixed bug triggered when ifaddrs::ifa_addr was null in +NetworkInterface::addresses. + +- Added another overload of Utils::route_entries which returns the +result either than storing it in a parameter. + +- Added ARP monitor, WPS detector, DNS queries sniffer and DNS spoofer +examples. + +- Added another Sniffer constructor which doesn't expect the maximum +capture size. + +- Added tins_cast as a replacement for dynamic_cast on PDUs. + +------------------------------------------------------------------------------- + +##### v1.2 - Mon oct 7 23:33:49 ART 2013 + +- Added BaseSniffer::begin and BaseSniffer::end. + +- BaseSniffer::next_packet uses pcap_loop instead of pcap_next, which +doesn't work well on some linux distributions. + +- Added PPI PDU class. + +- Fixed a bug in EthernetII triggered when the size of the whole frame +was lower than 60 bytes. + +- Added AddressRange class and IPv4Address, IPv6Address and +HWAddress<>::operator/. + +- Added is_broadcast, is_multicast and is_unicast to IPv4, IPv6 +and HWAddress. + +- Added is_private and is_loopback methods to IPv4 and IPv6 addresses. + +- Done some optimizations on TCP's constructor from buffer. + +- Added helper functions to Dot11Data to retrieve the source, +destination and BSSID addresses. + +- Fixed bugs in DNS triggered when parsing MX and unknown records. + +- BaseSniffer::next_packet now iterates until a valid packet is found. + +- TCP::get_flag is now const. + +- The --disable-wpa2 now works as expected. + +v1.1 - Wed Jun 5 09:03:37 ART 2013 + +- Implemented std::hash specialization for IPv4, IPv6 and HWAddress<> +types. + +- Added a RSNHandshakeCapturer class. + +- Added WPA2Decrypter class. + +- IEEE 802.11 frames are not parsed if the RadioTap FAILED_FCS flag +is on. + +- RadioTap now calculates its size everytime it's serialized. + +- Splitted the dot11.h and dot11.cpp files into several files to +speed up compilation times. + +- Added HWAddress<>::is_broadcast and HWAddress::operator[]. + +- Fixed a bug triggered when parsing Dot11QoSData frames. + +v1.0 - Tue Apr 23 20:40:57 ART 2013 + +- Link layer protocol PDUs now don't hold a NetworkInterface. This led +to changes in their constructors. + +- Removed the obsolete PDU* parameter taken by several classes' +constructors. + +- IP now sets the sender's address automatically when no link layer +PDU is used. + +- IP, TCP and UDP now calculate the checksum everytime they're +serialized. + +- Added PDU::rfind_pdu. + +- Defined several exception types. + +- Implemented matches_response on several protocols. + +- PacketSender is now movable. + +- Added an overload of add_option that takes an rvalue-reference in IP, +TCP, DHCP, ICMPv6 and Dot11. + +- Added support for GNU/kFreeBSD. + +- Removed several deprecated methods, such as PDU::clone_packet. + +- Added PacketSender::send(PDU&, NetworkInterface). + +- Normalized the TLV options naming conventions in all of the classes +that used them. + +- Added support for Dot1Q, STP, PPPoE protocols. + +- Made some important optimizations on PDUOption<>'s constructors. + +- Added Utils::resolve_domain and Utils::resolve_domain6 + +------------------------------------------------------------------------------- + +##### v0.3 - Thu Jan 31 16:47:27 ART 2013 + +- Added IPv6, ICMPv6 and DHCPv6 classes. + +- Added support for Loopback interfaces and the Linux Crooked Capture +pseudo protocol. + +- Added support for IPv6 records in DNS. + +- Added Packet/RefPacket class. + +- Added support for FreeBSD, OSX and Windows. + +- Added C++11 move semantics to several classes. + +- Done a complete rewrite of the build system; it now uses libtool. + +- Fixed several bugs in DNS. + +------------------------------------------------------------------------------- + +##### v0.2 - Sat Oct 20 11:26:40 2012 + +- Added support for big endian architectures. + +- Simplified several interfaces. + +- Added IPv4Address and HWAddress class to simplify handling IP and hardware addresses. + +- Added NetworkInterface class to abstract network interfaces. + +- Added TCPStreamFollower class to follow TCP streams on the fly. + +- Added WEPDecrypter class to decrypt WEP-encrypted 802.11 data frames on the fly. + +- Added several new PDUs: Loopback, IEEE802_3, LLC, DNS. + +- Added support for reading and writing pcap files. + +- Moved to BSD-2 license. diff --git a/lib/libtins/CMakeLists.txt b/lib/libtins/CMakeLists.txt new file mode 100644 index 0000000..696385f --- /dev/null +++ b/lib/libtins/CMakeLists.txt @@ -0,0 +1,361 @@ +CMAKE_MINIMUM_REQUIRED(VERSION 2.8.1) +PROJECT(libtins) + +OPTION(LIBTINS_BUILD_EXAMPLES "Build examples" ON) +OPTION(LIBTINS_BUILD_TESTS "Build tests" ON) + +# Compile in release mode by default +IF(NOT CMAKE_BUILD_TYPE) + MESSAGE(STATUS "Setting build type to 'RelWithDebInfo' as none was specified.") + SET(CMAKE_BUILD_TYPE RelWithDebInfo) +ELSE(NOT CMAKE_BUILD_TYPE) + MESSAGE(STATUS "Using specified '${CMAKE_BUILD_TYPE}' build type.") +ENDIF(NOT CMAKE_BUILD_TYPE) + +# Compilation flags. +IF(MSVC) + # Don't always use Wall, since VC's /Wall is ridiculously verbose. + SET(CMAKE_CXX_FLAGS "${CMAKE_CXX_FLAGS} /W3") + # Disable VC secure checks, since these are not really issues. + ADD_DEFINITIONS("-D_CRT_SECURE_NO_WARNINGS=1") + ADD_DEFINITIONS("-D_SCL_SECURE_NO_WARNINGS=1") + ADD_DEFINITIONS("-DNOGDI=1") +ELSE() + SET(CMAKE_CXX_FLAGS "${CMAKE_CXX_FLAGS} -Wall -Wextra") +ENDIF() + +IF(APPLE) + # This is set to ON as of policy CMP0042 + SET(CMAKE_MACOSX_RPATH ON) +ENDIF() + +# Build output checks +OPTION(LIBTINS_BUILD_SHARED "Build libtins as a shared library." ON) +IF(LIBTINS_BUILD_SHARED) + MESSAGE( + STATUS + "Build will generate a shared library. " + "Use LIBTINS_BUILD_SHARED=0 to perform a static build" + ) + SET(LIBTINS_TYPE SHARED) +ELSE(LIBTINS_BUILD_SHARED) + MESSAGE(STATUS "Build will generate a static library.") + SET(LIBTINS_TYPE STATIC) + ADD_DEFINITIONS("-DTINS_STATIC=1") +ENDIF(LIBTINS_BUILD_SHARED) + +# The version number. +SET(TINS_VERSION_MAJOR 4) +SET(TINS_VERSION_MINOR 5) +SET(TINS_VERSION_PATCH 0) +SET(LIBTINS_VERSION "${TINS_VERSION_MAJOR}.${TINS_VERSION_MINOR}") + +# Required Packages +SET(CMAKE_MODULE_PATH ${CMAKE_MODULE_PATH} "${CMAKE_CURRENT_SOURCE_DIR}/cmake/Modules/") + +# Allow disabling packet capture mechanism +OPTION(LIBTINS_ENABLE_PCAP "Enable capturing packets via libpcap" ON) + +# Look for libpcap +IF(LIBTINS_ENABLE_PCAP) + FIND_PACKAGE(PCAP REQUIRED) + SET(TINS_HAVE_PCAP ON) +ENDIF() + +# Set some Windows specific flags +IF(WIN32) + # We need to link against these libs + SET(LIBTINS_OS_LIBS Ws2_32.lib Iphlpapi.lib) + + # Add the NOMINMAX macro to avoid Windows' min and max macros. + ADD_DEFINITIONS(-DNOMINMAX) + + # MinWG need some extra definitions to compile properly (WIN32 for PCAP and WIN32_WINNT version for ws2tcpip.h) + IF(MINGW) + ADD_DEFINITIONS(-DWIN32) + MACRO(get_WIN32_WINNT version) + IF (WIN32 AND CMAKE_SYSTEM_VERSION) + SET(ver ${CMAKE_SYSTEM_VERSION}) + STRING(REPLACE "." "" ver ${ver}) + STRING(REGEX REPLACE "([0-9])" "0\\1" ver ${ver}) + SET(${version} "0x${ver}") + ENDIF() + ENDMACRO() + get_WIN32_WINNT(ver) + ADD_DEFINITIONS(-D_WIN32_WINNT=${ver}) + ENDIF(MINGW) + +ENDIF(WIN32) + +INCLUDE(ExternalProject) + +# ******************* +# Compilation options +# ******************* + +# Always check for C++ features +INCLUDE(CheckCXXFeatures) + +IF(HAS_GCC_BUILTIN_SWAP) + SET(TINS_HAVE_GCC_BUILTIN_SWAP ON) +ENDIF() + +# C++11 support +OPTION(LIBTINS_ENABLE_CXX11 "Compile libtins with c++11 features" ON) +IF(LIBTINS_ENABLE_CXX11) + # We only use declval and decltype on gcc/clang as VC fails to build that code, + # at least on VC2013 + IF(HAS_CXX11_RVALUE_REFERENCES AND HAS_CXX11_FUNCTIONAL AND HAS_CXX11_CHRONO AND + HAS_CXX11_NOEXCEPT AND ((HAS_CXX11_DECLVAL AND HAS_CXX11_DECLTYPE) OR MSVC)) + SET(TINS_HAVE_CXX11 ON) + MESSAGE(STATUS "Enabling C++11 features") + SET(CMAKE_CXX_FLAGS "${CMAKE_CXX_FLAGS} ${CXX11_COMPILER_FLAGS}") + ELSE() + MESSAGE(WARNING "The compiler doesn't support the necessary C++11 features. " + "Disabling C++11 on this build") + ENDIF() +ELSE(LIBTINS_ENABLE_CXX11) + MESSAGE( + WARNING + "Disabling C++11 features. Use LIBTINS_ENABLE_CXX11=1 to enable them. " + "Unless you are using an old compiler, you should enable this option, " + "as it increases the library's performance") +ENDIF(LIBTINS_ENABLE_CXX11) + +# IEEE 802.11 and WPA2 decryption support +OPTION(LIBTINS_ENABLE_DOT11 "Compile libtins with IEEE 802.11 support" ON) +OPTION(LIBTINS_ENABLE_WPA2 "Compile libtins with WPA2 decryption features (requires OpenSSL)" ON) +IF(LIBTINS_ENABLE_DOT11) + SET(TINS_HAVE_DOT11 ON) + MESSAGE(STATUS "Enabling IEEE 802.11 support.") + IF(LIBTINS_ENABLE_WPA2) + FIND_PACKAGE(OpenSSL) + IF(OPENSSL_FOUND) + SET(TINS_HAVE_WPA2_DECRYPTION ON) + MESSAGE(STATUS "Enabling WPA2 decryption support.") + ELSE() + MESSAGE(WARNING "Disabling WPA2 decryption support since OpenSSL was not found") + # Default this to empty strings + SET(OPENSSL_INCLUDE_DIR "") + SET(OPENSSL_LIBRARIES "") + ENDIF() + ELSE(LIBTINS_ENABLE_WPA2) + MESSAGE(STATUS "Disabling WPA2 decryption support.") + ENDIF(LIBTINS_ENABLE_WPA2) +ENDIF(LIBTINS_ENABLE_DOT11) + +# Optionally enable TCPIP classes (on by default) +OPTION(LIBTINS_ENABLE_TCPIP "Enable TCPIP classes" ON) +IF(LIBTINS_ENABLE_TCPIP AND TINS_HAVE_CXX11) + SET(TINS_HAVE_TCPIP ON) + MESSAGE(STATUS "Enabling TCPIP classes") +ELSE() + SET(TINS_HAVE_TCPIP OFF) + MESSAGE(STATUS "Disabling TCPIP classes") +ENDIF() + +# Search for libboost +FIND_PACKAGE(Boost) + +# Optionally enable the ACK tracker (on by default) +OPTION(LIBTINS_ENABLE_ACK_TRACKER "Enable TCP ACK tracking support" ON) +IF(LIBTINS_ENABLE_ACK_TRACKER AND TINS_HAVE_CXX11) + IF (Boost_FOUND) + MESSAGE(STATUS "Enabling TCP ACK tracking support.") + INCLUDE_DIRECTORIES(${Boost_INCLUDE_DIRS}) + SET(TINS_HAVE_ACK_TRACKER ON) + ELSE() + MESSAGE(WARNING "Disabling ACK tracking support as boost.icl was not found") + SET(TINS_HAVE_ACK_TRACKER OFF) + ENDIF() +ELSE() + SET(TINS_HAVE_ACK_TRACKER OFF) + MESSAGE(STATUS "Disabling ACK tracking support") +ENDIF() + +# Optionally enable the TCP stream custom data (on by default) +OPTION(LIBTINS_ENABLE_TCP_STREAM_CUSTOM_DATA "Enable TCP stream custom data support" ON) +IF(LIBTINS_ENABLE_TCP_STREAM_CUSTOM_DATA AND TINS_HAVE_CXX11) + IF (Boost_FOUND) + MESSAGE(STATUS "Enabling TCP stream custom data support.") + INCLUDE_DIRECTORIES(${Boost_INCLUDE_DIRS}) + SET(TINS_HAVE_TCP_STREAM_CUSTOM_DATA ON) + ELSE() + MESSAGE(WARNING "Disabling TCP stream custom data support as boost.any was not found") + SET(TINS_HAVE_TCP_STREAM_CUSTOM_DATA OFF) + ENDIF() +ELSE() + SET(TINS_HAVE_TCP_STREAM_CUSTOM_DATA OFF) + MESSAGE(STATUS "Disabling TCP stream custom data support") +ENDIF() + +OPTION(LIBTINS_ENABLE_WPA2_CALLBACKS "Enable WPA2 callback interface" ON) +IF(LIBTINS_ENABLE_WPA2_CALLBACKS AND TINS_HAVE_WPA2_DECRYPTION AND TINS_HAVE_CXX11) + SET(STATUS "Enabling WPA2 callback interface") + SET(TINS_HAVE_WPA2_CALLBACKS ON) +ENDIF() + +# Use pcap_sendpacket to send l2 packets rather than raw sockets +IF(WIN32) + SET(USE_PCAP_SENDPACKET_DEFAULT ON) +ELSE(WIN32) + SET(USE_PCAP_SENDPACKET_DEFAULT OFF) +ENDIF(WIN32) + +OPTION(LIBTINS_USE_PCAP_SENDPACKET "Use pcap_sendpacket to send l2 packets" + ${USE_PCAP_SENDPACKET_DEFAULT}) +IF(LIBTINS_ENABLE_PCAP AND LIBTINS_USE_PCAP_SENDPACKET) + SET(TINS_HAVE_PACKET_SENDER_PCAP_SENDPACKET ON) + MESSAGE(STATUS "Using pcap_sendpacket to send l2 packets.") +ENDIF() + +# Add a target to generate API documentation using Doxygen +FIND_PACKAGE(Doxygen QUIET) +IF(DOXYGEN_FOUND) + CONFIGURE_FILE( + ${CMAKE_CURRENT_SOURCE_DIR}/docs/Doxyfile.in + ${CMAKE_CURRENT_BINARY_DIR}/Doxyfile + @ONLY + ) + ADD_CUSTOM_TARGET( + docs + ${DOXYGEN_EXECUTABLE} ${CMAKE_CURRENT_BINARY_DIR}/Doxyfile + WORKING_DIRECTORY ${CMAKE_CURRENT_BINARY_DIR} + COMMENT "Generating API documentation with Doxygen" VERBATIM + ) +ENDIF(DOXYGEN_FOUND) + +# Configuration file +CONFIGURE_FILE( + "${PROJECT_SOURCE_DIR}/include/tins/config.h.in" + "${PROJECT_SOURCE_DIR}/include/tins/config.h" +) + +IF (NOT CMAKE_INSTALL_LIBDIR) + SET(CMAKE_INSTALL_LIBDIR lib) +ENDIF() +IF (NOT CMAKE_INSTALL_BINDIR) + SET(CMAKE_INSTALL_BINDIR bin) +ENDIF() +# The library output directory +SET(CMAKE_LIBRARY_OUTPUT_DIRECTORY ${PROJECT_BINARY_DIR}/${CMAKE_INSTALL_LIBDIR}) +SET(CMAKE_ARCHIVE_OUTPUT_DIRECTORY ${PROJECT_BINARY_DIR}/${CMAKE_INSTALL_LIBDIR}) +# Support for pkg-config +SET(pkgconfig_prefix ${CMAKE_INSTALL_PREFIX}) +SET(pkgconfig_exec_prefix ${CMAKE_INSTALL_PREFIX}) +SET(pkgconfig_libdir ${CMAKE_INSTALL_PREFIX}/${CMAKE_INSTALL_LIBDIR}) +SET(pkgconfig_version ${LIBTINS_VERSION}) +CONFIGURE_FILE(${CMAKE_CURRENT_SOURCE_DIR}/libtins.pc.in + ${CMAKE_CURRENT_BINARY_DIR}/libtins.pc @ONLY) + +INSTALL( + FILES + ${CMAKE_CURRENT_BINARY_DIR}/libtins.pc + DESTINATION ${CMAKE_INSTALL_LIBDIR}/pkgconfig +) + +# Confiugure the uninstall script +CONFIGURE_FILE( + "${CMAKE_CURRENT_SOURCE_DIR}/cmake/cmake_uninstall.cmake.in" + "${CMAKE_CURRENT_BINARY_DIR}/cmake_uninstall.cmake" + IMMEDIATE @ONLY +) + +# Add uninstall target +ADD_CUSTOM_TARGET(uninstall + COMMAND ${CMAKE_COMMAND} -P ${CMAKE_CURRENT_BINARY_DIR}/cmake_uninstall.cmake) + +# ****************** +# Add subdirectories +# ****************** +ADD_SUBDIRECTORY(src) + +IF(LIBTINS_BUILD_EXAMPLES) + IF(LIBTINS_ENABLE_PCAP) + ADD_SUBDIRECTORY(examples) + ELSE() + MESSAGE(STATUS "Not building examples as pcap support is disabled") + ENDIF() +ENDIF() + +IF(LIBTINS_BUILD_TESTS) + # Only include googletest if the git submodule has been fetched + IF(EXISTS "${CMAKE_CURRENT_SOURCE_DIR}/googletest/CMakeLists.txt") + # Enable tests and add the test directory + MESSAGE(STATUS "Tests have been enabled") + SET(GOOGLETEST_ROOT ${CMAKE_CURRENT_SOURCE_DIR}/googletest) + SET(GOOGLETEST_INCLUDE ${GOOGLETEST_ROOT}/googletest/include) + SET(GOOGLETEST_BINARY_DIR ${CMAKE_CURRENT_BINARY_DIR}/googletest) + SET(GOOGLETEST_LIBRARY ${GOOGLETEST_BINARY_DIR}/googletest) + + ExternalProject_Add( + googletest + DOWNLOAD_COMMAND "" + SOURCE_DIR ${GOOGLETEST_ROOT} + BINARY_DIR ${GOOGLETEST_BINARY_DIR} + CMAKE_CACHE_ARGS "-DBUILD_GTEST:bool=ON" "-DBUILD_GMOCK:bool=OFF" + "-Dgtest_force_shared_crt:bool=ON" + "-DCMAKE_CXX_COMPILER:path=${CMAKE_CXX_COMPILER}" + INSTALL_COMMAND "" + ) + # Make sure we build googletest before anything else + ADD_DEPENDENCIES(tins googletest) + ENABLE_TESTING() + ADD_SUBDIRECTORY(tests) + ELSE() + FIND_PACKAGE(GTest QUIET) + IF(${GTest_FOUND}) + ENABLE_TESTING() + ADD_SUBDIRECTORY(tests) + ELSE() + MESSAGE(STATUS "googletest git submodule is absent. Run `git submodule init && git submodule update` to get it") + ENDIF() + ENDIF() +ENDIF() + +# ********************************** +# CMake project configuration export +# ********************************** + +if(UNIX) + set(CONF_CMAKE_INSTALL_DIR "${CMAKE_INSTALL_LIBDIR}/cmake/libtins") +else() + set(CONF_CMAKE_INSTALL_DIR CMake) +endif() + +# Add all targets to the build-tree export set +EXPORT( + TARGETS tins + FILE "${PROJECT_BINARY_DIR}/libtinsTargets.cmake" +) + +# Export the package for use from the build-tree +# (this registers the build-tree with a global CMake-registry) +EXPORT(PACKAGE libtins) + +# Create the libtinsConfig.cmake and libtinsConfigVersion.cmake files +# for the build tree +SET(CONF_INCLUDE_DIRS "${PROJECT_SOURCE_DIR}/include") +CONFIGURE_FILE( + cmake/libtinsConfig.cmake.in + "${PROJECT_BINARY_DIR}/libtinsConfig.cmake" @ONLY +) +CONFIGURE_FILE( + cmake/libtinsConfigVersion.cmake.in + "${PROJECT_BINARY_DIR}/libtinsConfigVersion.cmake" @ONLY +) +# Install the libtinsConfig.cmake and libtinsConfigVersion.cmake +INSTALL( + FILES + "${PROJECT_BINARY_DIR}/libtinsConfig.cmake" + "${PROJECT_BINARY_DIR}/libtinsConfigVersion.cmake" + DESTINATION ${CONF_CMAKE_INSTALL_DIR} + COMPONENT dev +) + +# Install the export set for use with the install-tree +INSTALL( + EXPORT libtinsTargets + DESTINATION ${CONF_CMAKE_INSTALL_DIR} + COMPONENT dev +) diff --git a/lib/libtins/CONTRIBUTING.md b/lib/libtins/CONTRIBUTING.md new file mode 100644 index 0000000..664d062 --- /dev/null +++ b/lib/libtins/CONTRIBUTING.md @@ -0,0 +1,27 @@ +# Contributing + +Bug reports and enhancements to the library are really valued and appreciated! + +# Bug reports + +If you find a bug, please report it! Bugs on the library are taken seriously +and a patch for them is usually pushed on the same day. + +When reporting a bug, please make sure to indicate the platform (e.g. GNU/Linux, Windows, OSX) +in which you came across the issue, as this is essential to finding the cause. + +## Packet parsing bugs + +If you find a bug related to packet parsing (e.g. a field on a packet contains an +invalid value), please try to provide a pcap file that contains the packet that +was incorrectly parsed. Doing this will make it very simple to find the issue, plus +you will be asked to provide this file anyway, so this just makes things +easier. + +# Pull requests + +Pull requests are very welcomed. When doing a pull request please: + +* Notice that your code will be compiled and tests will be run automatically by the travis and +appveyor CI tools. If your code has issues on any of the tested platforms (GNU/Linux, Windows +and OSX), please fix it or otherwise the PR won't be merged. diff --git a/lib/libtins/LICENSE b/lib/libtins/LICENSE new file mode 100644 index 0000000..c4009ed --- /dev/null +++ b/lib/libtins/LICENSE @@ -0,0 +1,25 @@ +Copyright (c) 2012-2017, Matias Fontanini +All rights reserved. + +Redistribution and use in source and binary forms, with or without +modification, are permitted provided that the following conditions are +met: + +* Redistributions of source code must retain the above copyright + notice, this list of conditions and the following disclaimer. +* Redistributions in binary form must reproduce the above + copyright notice, this list of conditions and the following disclaimer + in the documentation and/or other materials provided with the + distribution. + +THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS +"AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT +LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR +A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT +OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, +SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT +LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, +DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY +THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT +(INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE +OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. diff --git a/lib/libtins/README.md b/lib/libtins/README.md new file mode 100644 index 0000000..745d145 --- /dev/null +++ b/lib/libtins/README.md @@ -0,0 +1,147 @@ +# libtins + +[![Build status](https://travis-ci.org/mfontanini/libtins.svg?branch=master)](https://travis-ci.org/mfontanini/libtins) +[![Build status](https://ci.appveyor.com/api/projects/status/33n8ib68nx3tptib/branch/master?svg=true)](https://ci.appveyor.com/project/mfontanini/libtins/branch/master) + +libtins is a high-level, multiplatform C++ network packet sniffing and +crafting library. + +Its main purpose is to provide the C++ developer an easy, efficient, +platform and endianess-independent way to create tools which need to +send, receive and manipulate specially crafted packets. + +In order to read tutorials, examples and checkout some benchmarks of the +library, please visit: + +http://libtins.github.io/ + +## Compiling ## + +[libtins](http://libtins.github.io/) depends on +[libpcap](http://www.tcpdump.org/) and +[openssl](http://www.openssl.org/), although the latter is not necessary +if some features of the library are disabled. + +In order to compile, execute: + +```Shell +# Create the build directory +mkdir build +cd build + +# Configure the project. Add any relevant configuration flags +cmake ../ + +# Compile! +make +``` + +### Static/shared build +Note that by default, only the shared object is compiled. If you would +like to generate a static library file, run: + +```Shell +cmake ../ -DLIBTINS_BUILD_SHARED=0 +``` + +The generated static/shared library files will be located in the +_build/lib_ directory. + +### C++11 support + +libtins is noticeably faster if you enable _C++11_ support. Therefore, +if your compiler supports this standard, then you should enable it. +In order to do so, use the _LIBTINS_ENABLE_CXX11_ switch: + +```Shell +cmake ../ -DLIBTINS_ENABLE_CXX11=1 +``` + +### TCP ACK tracker + +The TCP ACK tracker feature requires the boost.icl library (header only). +This feature is enabled by default but will be disabled if the boost +headers are not found. You can disable this feature by using: + +```Shell +cmake ../ -DLIBTINS_ENABLE_ACK_TRACKER=0 +``` + +If your boost installation is on some non-standard path, use +the parameters shown on the +[CMake FindBoost help](https://cmake.org/cmake/help/v3.0/module/FindBoost.html) + +### WPA2 decryption + +If you want to disable _WPA2_ decryption support, which will remove +openssl as a dependency for compilation, use the +_LIBTINS_ENABLE_WPA2_ switch: + +```Shell +cmake ../ -DLIBTINS_ENABLE_WPA2=0 +``` + +### IEEE 802.11 support + +If you want to disable IEEE 802.11 support(this will also disable +RadioTap and WPA2 decryption), which will reduce the size of the +resulting library in around 20%, use the _LIBTINS_ENABLE_DOT11_ switch: + +```Shell +cmake ../ -DLIBTINS_ENABLE_DOT11=0 +``` + +## Installing ## + +Once you're done, if you want to install the header files and the +shared object, execute as root: + +```Shell +make install +``` + +This will install the shared object typically in _/usr/local/lib_. Note +that you might have to update ldconfig's cache before using it, so +in order to invalidate it, you should run(as root): + +```Shell +ldconfig +``` + +## Running tests ## + +You may want to run the unit tests on your system so you make sure +everything works. In order to do so, you need to follow these steps: + +```Shell +# This will fetch the googletest submodule, needed for tests +git submodule init +git submodule update + +mkdir build +cd build + +# Use any options you want +cmake .. + +# Compile tests +make tests + +# Run them +make test +``` + +If you find that any tests fail, please create an ticket in the +issue tracker indicating the platform and architecture you're using. + +## Examples ## + +You might want to have a look at the examples located in the "examples" +directory. The same samples can be found online at: + +http://libtins.github.io/examples/ + +## Contributing ## + +If you want to report a bug or make a pull request, please have a look at +the [contributing](CONTRIBUTING.md) file before doing so. diff --git a/lib/libtins/THANKS b/lib/libtins/THANKS new file mode 100644 index 0000000..82ee375 --- /dev/null +++ b/lib/libtins/THANKS @@ -0,0 +1,4 @@ +We'd like to thank the following people, who have been of great help +through the development of libtins: + +- Raúl Benencia - For creating the Debian package. diff --git a/lib/libtins/cmake/Modules/CheckCXXFeatures.cmake b/lib/libtins/cmake/Modules/CheckCXXFeatures.cmake new file mode 100644 index 0000000..b7b7f14 --- /dev/null +++ b/lib/libtins/cmake/Modules/CheckCXXFeatures.cmake @@ -0,0 +1,135 @@ +# - Check which parts of the C++11 standard the compiler supports +# +# When found it will set the following variables +# +# CXX11_COMPILER_FLAGS - the compiler flags needed to get C++11 features +# +# HAS_CXX11_AUTO - auto keyword +# HAS_CXX11_AUTO_RET_TYPE - function declaration with deduced return types +# HAS_CXX11_CLASS_OVERRIDE - override and final keywords for classes and methods +# HAS_CXX11_CONSTEXPR - constexpr keyword +# HAS_CXX11_CSTDINT_H - cstdint header +# HAS_CXX11_DECLTYPE - decltype keyword +# HAS_CXX11_DECLVAL - declval feature +# HAS_CXX11_FUNC - __func__ preprocessor constant +# HAS_CXX11_INITIALIZER_LIST - initializer list +# HAS_CXX11_LAMBDA - lambdas +# HAS_CXX11_LIB_REGEX - regex library +# HAS_CXX11_LONG_LONG - long long signed & unsigned types +# HAS_CXX11_NULLPTR - nullptr +# HAS_CXX11_RVALUE_REFERENCES - rvalue references +# HAS_CXX11_SIZEOF_MEMBER - sizeof() non-static members +# HAS_CXX11_STATIC_ASSERT - static_assert() +# HAS_CXX11_VARIADIC_TEMPLATES - variadic templates + +#============================================================================= +# Copyright 2011,2012 Rolf Eike Beer +# Copyright 2012 Andreas Weis +# +# Distributed under the OSI-approved BSD License (the "License"); +# see accompanying file Copyright.txt for details. +# +# This software is distributed WITHOUT ANY WARRANTY; without even the +# implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. +# See the License for more information. +#============================================================================= +# (To distribute this file outside of CMake, substitute the full +# License text for the above reference.) + +# +# Each feature may have up to 3 checks, every one of them in it's own file +# FEATURE.cpp - example that must build and return 0 when run +# FEATURE_fail.cpp - example that must build, but may not return 0 when run +# FEATURE_fail_compile.cpp - example that must fail compilation +# +# The first one is mandatory, the latter 2 are optional and do not depend on +# each other (i.e. only one may be present). +# + +if (NOT CMAKE_CXX_COMPILER_LOADED) + message(FATAL_ERROR "CheckCXX11Features modules only works if language CXX is enabled") +endif () + +cmake_minimum_required(VERSION 2.8.3) + +# +### Check for needed compiler flags +# +include(CheckCXXCompilerFlag) +check_cxx_compiler_flag("-std=c++11" _HAS_CXX11_FLAG) +if (NOT _HAS_CXX11_FLAG) + check_cxx_compiler_flag("-std=c++0x" _HAS_CXX0X_FLAG) +endif () + +if (_HAS_CXX11_FLAG) + set(CXX11_COMPILER_FLAGS "-std=c++11") +elseif (_HAS_CXX0X_FLAG) + set(CXX11_COMPILER_FLAGS "-std=c++0x") +endif () + +function(cxx11_check_feature FEATURE_NAME RESULT_VAR) + if (NOT DEFINED ${RESULT_VAR}) + set(_bindir "${CMAKE_CURRENT_BINARY_DIR}/cxx_${FEATURE_NAME}") + + set(_SRCFILE_BASE ${CMAKE_CURRENT_LIST_DIR}/CheckCXXFeatures/cxx-test-${FEATURE_NAME}) + set(_LOG_NAME "\"${FEATURE_NAME}\"") + message(STATUS "Checking C++ support for ${_LOG_NAME}") + + set(_SRCFILE "${_SRCFILE_BASE}.cpp") + set(_SRCFILE_FAIL "${_SRCFILE_BASE}_fail.cpp") + set(_SRCFILE_FAIL_COMPILE "${_SRCFILE_BASE}_fail_compile.cpp") + + if (CMAKE_CROSSCOMPILING) + try_compile(${RESULT_VAR} "${_bindir}" "${_SRCFILE}" + COMPILE_DEFINITIONS "${CXX11_COMPILER_FLAGS}") + if (${RESULT_VAR} AND EXISTS ${_SRCFILE_FAIL}) + try_compile(${RESULT_VAR} "${_bindir}_fail" "${_SRCFILE_FAIL}" + COMPILE_DEFINITIONS "${CXX11_COMPILER_FLAGS}") + endif (${RESULT_VAR} AND EXISTS ${_SRCFILE_FAIL}) + else (CMAKE_CROSSCOMPILING) + try_run(_RUN_RESULT_VAR _COMPILE_RESULT_VAR + "${_bindir}" "${_SRCFILE}" + COMPILE_DEFINITIONS "${CXX11_COMPILER_FLAGS}") + if (_COMPILE_RESULT_VAR AND NOT _RUN_RESULT_VAR) + set(${RESULT_VAR} TRUE) + else (_COMPILE_RESULT_VAR AND NOT _RUN_RESULT_VAR) + set(${RESULT_VAR} FALSE) + endif (_COMPILE_RESULT_VAR AND NOT _RUN_RESULT_VAR) + if (${RESULT_VAR} AND EXISTS ${_SRCFILE_FAIL}) + try_run(_RUN_RESULT_VAR _COMPILE_RESULT_VAR + "${_bindir}_fail" "${_SRCFILE_FAIL}" + COMPILE_DEFINITIONS "${CXX11_COMPILER_FLAGS}") + if (_COMPILE_RESULT_VAR AND _RUN_RESULT_VAR) + set(${RESULT_VAR} TRUE) + else (_COMPILE_RESULT_VAR AND _RUN_RESULT_VAR) + set(${RESULT_VAR} FALSE) + endif (_COMPILE_RESULT_VAR AND _RUN_RESULT_VAR) + endif (${RESULT_VAR} AND EXISTS ${_SRCFILE_FAIL}) + endif (CMAKE_CROSSCOMPILING) + if (${RESULT_VAR} AND EXISTS ${_SRCFILE_FAIL_COMPILE}) + try_compile(_TMP_RESULT "${_bindir}_fail_compile" "${_SRCFILE_FAIL_COMPILE}" + COMPILE_DEFINITIONS "${CXX11_COMPILER_FLAGS}") + if (_TMP_RESULT) + set(${RESULT_VAR} FALSE) + else (_TMP_RESULT) + set(${RESULT_VAR} TRUE) + endif (_TMP_RESULT) + endif (${RESULT_VAR} AND EXISTS ${_SRCFILE_FAIL_COMPILE}) + + if (${RESULT_VAR}) + message(STATUS "Checking C++ support for ${_LOG_NAME}: works") + else (${RESULT_VAR}) + message(STATUS "Checking C++ support for ${_LOG_NAME}: not supported") + endif (${RESULT_VAR}) + set(${RESULT_VAR} ${${RESULT_VAR}} CACHE INTERNAL "C++ support for ${_LOG_NAME}") + endif (NOT DEFINED ${RESULT_VAR}) +endfunction(cxx11_check_feature) + +cxx11_check_feature("decltype" HAS_CXX11_DECLTYPE) +cxx11_check_feature("declval" HAS_CXX11_DECLVAL) +cxx11_check_feature("initializer_list" HAS_CXX11_INITIALIZER_LIST) +cxx11_check_feature("rvalue-references" HAS_CXX11_RVALUE_REFERENCES) +cxx11_check_feature("functional" HAS_CXX11_FUNCTIONAL) +cxx11_check_feature("chrono" HAS_CXX11_CHRONO) +cxx11_check_feature("noexcept" HAS_CXX11_NOEXCEPT) +cxx11_check_feature("builtin-swap" HAS_GCC_BUILTIN_SWAP) diff --git a/lib/libtins/cmake/Modules/CheckCXXFeatures/cxx-test-__func__.cpp b/lib/libtins/cmake/Modules/CheckCXXFeatures/cxx-test-__func__.cpp new file mode 100644 index 0000000..3bfd8a8 --- /dev/null +++ b/lib/libtins/cmake/Modules/CheckCXXFeatures/cxx-test-__func__.cpp @@ -0,0 +1,8 @@ +int main(void) +{ + if (!__func__) + return 1; + if (!(*__func__)) + return 1; + return 0; +} diff --git a/lib/libtins/cmake/Modules/CheckCXXFeatures/cxx-test-auto.cpp b/lib/libtins/cmake/Modules/CheckCXXFeatures/cxx-test-auto.cpp new file mode 100644 index 0000000..948648e --- /dev/null +++ b/lib/libtins/cmake/Modules/CheckCXXFeatures/cxx-test-auto.cpp @@ -0,0 +1,12 @@ + +int main() +{ + auto i = 5; + auto f = 3.14159f; + auto d = 3.14159; + bool ret = ( + (sizeof(f) < sizeof(d)) && + (sizeof(i) == sizeof(int)) + ); + return ret ? 0 : 1; +} diff --git a/lib/libtins/cmake/Modules/CheckCXXFeatures/cxx-test-auto_fail_compile.cpp b/lib/libtins/cmake/Modules/CheckCXXFeatures/cxx-test-auto_fail_compile.cpp new file mode 100644 index 0000000..3c0e3f2 --- /dev/null +++ b/lib/libtins/cmake/Modules/CheckCXXFeatures/cxx-test-auto_fail_compile.cpp @@ -0,0 +1,7 @@ +int main(void) +{ + // must fail because there is no initializer + auto i; + + return 0; +} diff --git a/lib/libtins/cmake/Modules/CheckCXXFeatures/cxx-test-auto_ret_type.cpp b/lib/libtins/cmake/Modules/CheckCXXFeatures/cxx-test-auto_ret_type.cpp new file mode 100644 index 0000000..937b683 --- /dev/null +++ b/lib/libtins/cmake/Modules/CheckCXXFeatures/cxx-test-auto_ret_type.cpp @@ -0,0 +1,8 @@ +auto foo(int i) -> int { + return i - 1; +} + +int main() +{ + return foo(1); +} diff --git a/lib/libtins/cmake/Modules/CheckCXXFeatures/cxx-test-builtin-swap.cpp b/lib/libtins/cmake/Modules/CheckCXXFeatures/cxx-test-builtin-swap.cpp new file mode 100644 index 0000000..e4437b7 --- /dev/null +++ b/lib/libtins/cmake/Modules/CheckCXXFeatures/cxx-test-builtin-swap.cpp @@ -0,0 +1,8 @@ +#include + +int main() { + uint16_t u16 = __builtin_bswap16(0x9812U); + uint32_t u32 = __builtin_bswap32(0x9812ad81U); + uint64_t u64 = __builtin_bswap64(0x9812ad81f61a890dU); + return (u16 > 0 && u32 > 0 && u64 > 0) ? 0 : 1; +} \ No newline at end of file diff --git a/lib/libtins/cmake/Modules/CheckCXXFeatures/cxx-test-chrono.cpp b/lib/libtins/cmake/Modules/CheckCXXFeatures/cxx-test-chrono.cpp new file mode 100644 index 0000000..7ebc382 --- /dev/null +++ b/lib/libtins/cmake/Modules/CheckCXXFeatures/cxx-test-chrono.cpp @@ -0,0 +1,9 @@ +#include + +using namespace std::chrono; + +int main() { + system_clock::time_point tp = system_clock::now(); + milliseconds ms = duration_cast(tp.time_since_epoch()); + return (ms.count() > 0) ? 0 : 1; +} \ No newline at end of file diff --git a/lib/libtins/cmake/Modules/CheckCXXFeatures/cxx-test-class_override_final.cpp b/lib/libtins/cmake/Modules/CheckCXXFeatures/cxx-test-class_override_final.cpp new file mode 100644 index 0000000..f5870b1 --- /dev/null +++ b/lib/libtins/cmake/Modules/CheckCXXFeatures/cxx-test-class_override_final.cpp @@ -0,0 +1,21 @@ +class base { +public: + virtual int foo(int a) + { return 4 + a; } + int bar(int a) final + { return a - 2; } +}; + +class sub final : public base { +public: + virtual int foo(int a) override + { return 8 + 2 * a; }; +}; + +int main(void) +{ + base b; + sub s; + + return (b.foo(2) * 2 == s.foo(2)) ? 0 : 1; +} diff --git a/lib/libtins/cmake/Modules/CheckCXXFeatures/cxx-test-class_override_final_fail_compile.cpp b/lib/libtins/cmake/Modules/CheckCXXFeatures/cxx-test-class_override_final_fail_compile.cpp new file mode 100644 index 0000000..bc00b27 --- /dev/null +++ b/lib/libtins/cmake/Modules/CheckCXXFeatures/cxx-test-class_override_final_fail_compile.cpp @@ -0,0 +1,25 @@ +class base { +public: + virtual int foo(int a) + { return 4 + a; } + virtual int bar(int a) final + { return a - 2; } +}; + +class sub final : public base { +public: + virtual int foo(int a) override + { return 8 + 2 * a; }; + virtual int bar(int a) + { return a; } +}; + +class impossible : public sub { }; + +int main(void) +{ + base b; + sub s; + + return 1; +} diff --git a/lib/libtins/cmake/Modules/CheckCXXFeatures/cxx-test-constexpr.cpp b/lib/libtins/cmake/Modules/CheckCXXFeatures/cxx-test-constexpr.cpp new file mode 100644 index 0000000..ed62451 --- /dev/null +++ b/lib/libtins/cmake/Modules/CheckCXXFeatures/cxx-test-constexpr.cpp @@ -0,0 +1,19 @@ +constexpr int square(int x) +{ + return x*x; +} + +constexpr int the_answer() +{ + return 42; +} + +int main() +{ + int test_arr[square(3)]; + bool ret = ( + (square(the_answer()) == 1764) && + (sizeof(test_arr)/sizeof(test_arr[0]) == 9) + ); + return ret ? 0 : 1; +} diff --git a/lib/libtins/cmake/Modules/CheckCXXFeatures/cxx-test-cstdint.cpp b/lib/libtins/cmake/Modules/CheckCXXFeatures/cxx-test-cstdint.cpp new file mode 100644 index 0000000..ca2c72d --- /dev/null +++ b/lib/libtins/cmake/Modules/CheckCXXFeatures/cxx-test-cstdint.cpp @@ -0,0 +1,11 @@ +#include + +int main() +{ + bool test = + (sizeof(int8_t) == 1) && + (sizeof(int16_t) == 2) && + (sizeof(int32_t) == 4) && + (sizeof(int64_t) == 8); + return test ? 0 : 1; +} diff --git a/lib/libtins/cmake/Modules/CheckCXXFeatures/cxx-test-decltype.cpp b/lib/libtins/cmake/Modules/CheckCXXFeatures/cxx-test-decltype.cpp new file mode 100644 index 0000000..0dbb1cc --- /dev/null +++ b/lib/libtins/cmake/Modules/CheckCXXFeatures/cxx-test-decltype.cpp @@ -0,0 +1,10 @@ +bool check_size(int i) +{ + return sizeof(int) == sizeof(decltype(i)); +} + +int main() +{ + bool ret = check_size(42); + return ret ? 0 : 1; +} diff --git a/lib/libtins/cmake/Modules/CheckCXXFeatures/cxx-test-declval.cpp b/lib/libtins/cmake/Modules/CheckCXXFeatures/cxx-test-declval.cpp new file mode 100644 index 0000000..e0ed16f --- /dev/null +++ b/lib/libtins/cmake/Modules/CheckCXXFeatures/cxx-test-declval.cpp @@ -0,0 +1,19 @@ +// Example code taken from http://en.cppreference.com/w/cpp/utility/declval + +#include +#include + +struct Default { int foo() const { return 1; } }; + +struct NonDefault +{ + NonDefault(const NonDefault&) { } + int foo() const { return 1; } +}; + +int main() +{ + decltype(Default().foo()) n1 = 1; // type of n1 is int + decltype(std::declval().foo()) n2 = n1; // type of n2 is int + return (n1 == 1 && n2 == 1) ? 0 : 1; +} \ No newline at end of file diff --git a/lib/libtins/cmake/Modules/CheckCXXFeatures/cxx-test-functional.cpp b/lib/libtins/cmake/Modules/CheckCXXFeatures/cxx-test-functional.cpp new file mode 100644 index 0000000..20d2b79 --- /dev/null +++ b/lib/libtins/cmake/Modules/CheckCXXFeatures/cxx-test-functional.cpp @@ -0,0 +1,11 @@ +#include + +int add(int x, int y) { + return x + y; +} + +int main() { + std::function func; + func = std::bind(&add, std::placeholders::_1, std::placeholders::_2); + return (func(2, 2) == 4) ? 0 : 1; +} \ No newline at end of file diff --git a/lib/libtins/cmake/Modules/CheckCXXFeatures/cxx-test-initializer_list.cpp b/lib/libtins/cmake/Modules/CheckCXXFeatures/cxx-test-initializer_list.cpp new file mode 100644 index 0000000..35e6c38 --- /dev/null +++ b/lib/libtins/cmake/Modules/CheckCXXFeatures/cxx-test-initializer_list.cpp @@ -0,0 +1,27 @@ +#include + +class seq { +public: + seq(std::initializer_list list); + + int length() const; +private: + std::vector m_v; +}; + +seq::seq(std::initializer_list list) + : m_v(list) +{ +} + +int seq::length() const +{ + return m_v.size(); +} + +int main(void) +{ + seq a = {18, 20, 2, 0, 4, 7}; + + return (a.length() == 6) ? 0 : 1; +} diff --git a/lib/libtins/cmake/Modules/CheckCXXFeatures/cxx-test-lambda.cpp b/lib/libtins/cmake/Modules/CheckCXXFeatures/cxx-test-lambda.cpp new file mode 100644 index 0000000..4c33ed5 --- /dev/null +++ b/lib/libtins/cmake/Modules/CheckCXXFeatures/cxx-test-lambda.cpp @@ -0,0 +1,5 @@ +int main() +{ + int ret = 0; + return ([&ret]() -> int { return ret; })(); +} diff --git a/lib/libtins/cmake/Modules/CheckCXXFeatures/cxx-test-long_long.cpp b/lib/libtins/cmake/Modules/CheckCXXFeatures/cxx-test-long_long.cpp new file mode 100644 index 0000000..0911127 --- /dev/null +++ b/lib/libtins/cmake/Modules/CheckCXXFeatures/cxx-test-long_long.cpp @@ -0,0 +1,7 @@ +int main(void) +{ + long long l; + unsigned long long ul; + + return ((sizeof(l) >= 8) && (sizeof(ul) >= 8)) ? 0 : 1; +} diff --git a/lib/libtins/cmake/Modules/CheckCXXFeatures/cxx-test-noexcept.cpp b/lib/libtins/cmake/Modules/CheckCXXFeatures/cxx-test-noexcept.cpp new file mode 100644 index 0000000..1f45e4f --- /dev/null +++ b/lib/libtins/cmake/Modules/CheckCXXFeatures/cxx-test-noexcept.cpp @@ -0,0 +1,7 @@ +int foo() noexcept { + return 0; +} + +int main() { + return foo(); +} diff --git a/lib/libtins/cmake/Modules/CheckCXXFeatures/cxx-test-nullptr.cpp b/lib/libtins/cmake/Modules/CheckCXXFeatures/cxx-test-nullptr.cpp new file mode 100644 index 0000000..9f41071 --- /dev/null +++ b/lib/libtins/cmake/Modules/CheckCXXFeatures/cxx-test-nullptr.cpp @@ -0,0 +1,6 @@ +int main(void) +{ + void *v = nullptr; + + return v ? 1 : 0; +} diff --git a/lib/libtins/cmake/Modules/CheckCXXFeatures/cxx-test-nullptr_fail_compile.cpp b/lib/libtins/cmake/Modules/CheckCXXFeatures/cxx-test-nullptr_fail_compile.cpp new file mode 100644 index 0000000..6a002bc --- /dev/null +++ b/lib/libtins/cmake/Modules/CheckCXXFeatures/cxx-test-nullptr_fail_compile.cpp @@ -0,0 +1,6 @@ +int main(void) +{ + int i = nullptr; + + return 1; +} diff --git a/lib/libtins/cmake/Modules/CheckCXXFeatures/cxx-test-regex.cpp b/lib/libtins/cmake/Modules/CheckCXXFeatures/cxx-test-regex.cpp new file mode 100644 index 0000000..2fe01c4 --- /dev/null +++ b/lib/libtins/cmake/Modules/CheckCXXFeatures/cxx-test-regex.cpp @@ -0,0 +1,26 @@ +#include +#include + +int parse_line(std::string const& line) +{ + std::string tmp; + if(std::regex_search(line, std::regex("(\\s)+(-)?(\\d)+//(-)?(\\d)+(\\s)+"))) { + tmp = std::regex_replace(line, std::regex("(-)?(\\d)+//(-)?(\\d)+"), std::string("V")); + } else if(std::regex_search(line, std::regex("(\\s)+(-)?(\\d)+/(-)?(\\d)+(\\s)+"))) { + tmp = std::regex_replace(line, std::regex("(-)?(\\d)+/(-)?(\\d)+"), std::string("V")); + } else if(std::regex_search(line, std::regex("(\\s)+(-)?(\\d)+/(-)?(\\d)+/(-)?(\\d)+(\\s)+"))) { + tmp = std::regex_replace(line, std::regex("(-)?(\\d)+/(-)?(\\d)+/(-)?(\\d)+"), std::string("V")); + } else { + tmp = std::regex_replace(line, std::regex("(-)?(\\d)+"), std::string("V")); + } + return static_cast(std::count(tmp.begin(), tmp.end(), 'V')); +} + +int main() +{ + bool test = (parse_line("f 7/7/7 -3/3/-3 2/-2/2") == 3) && + (parse_line("f 7//7 3//-3 -2//2") == 3) && + (parse_line("f 7/7 3/-3 -2/2") == 3) && + (parse_line("f 7 3 -2") == 3); + return test ? 0 : 1; +} diff --git a/lib/libtins/cmake/Modules/CheckCXXFeatures/cxx-test-rvalue-references.cpp b/lib/libtins/cmake/Modules/CheckCXXFeatures/cxx-test-rvalue-references.cpp new file mode 100644 index 0000000..e6e7e5a --- /dev/null +++ b/lib/libtins/cmake/Modules/CheckCXXFeatures/cxx-test-rvalue-references.cpp @@ -0,0 +1,57 @@ +#include + +class rvmove { +public: + void *ptr; + char *array; + + rvmove() + : ptr(0), + array(new char[10]) + { + ptr = this; + } + + rvmove(rvmove &&other) + : ptr(other.ptr), + array(other.array) + { + other.array = 0; + other.ptr = 0; + } + + ~rvmove() + { + assert(((ptr != 0) && (array != 0)) || ((ptr == 0) && (array == 0))); + delete[] array; + } + + rvmove &operator=(rvmove &&other) + { + delete[] array; + ptr = other.ptr; + array = other.array; + other.array = 0; + other.ptr = 0; + return *this; + } + + static rvmove create() + { + return rvmove(); + } +private: + rvmove(const rvmove &); + rvmove &operator=(const rvmove &); +}; + +int main() +{ + rvmove mine; + if (mine.ptr != &mine) + return 1; + mine = rvmove::create(); + if (mine.ptr == &mine) + return 1; + return 0; +} diff --git a/lib/libtins/cmake/Modules/CheckCXXFeatures/cxx-test-sizeof_member.cpp b/lib/libtins/cmake/Modules/CheckCXXFeatures/cxx-test-sizeof_member.cpp new file mode 100644 index 0000000..4902fc7 --- /dev/null +++ b/lib/libtins/cmake/Modules/CheckCXXFeatures/cxx-test-sizeof_member.cpp @@ -0,0 +1,14 @@ +struct foo { + char bar; + int baz; +}; + +int main(void) +{ + bool ret = ( + (sizeof(foo::bar) == 1) && + (sizeof(foo::baz) >= sizeof(foo::bar)) && + (sizeof(foo) >= sizeof(foo::bar) + sizeof(foo::baz)) + ); + return ret ? 0 : 1; +} diff --git a/lib/libtins/cmake/Modules/CheckCXXFeatures/cxx-test-sizeof_member_fail.cpp b/lib/libtins/cmake/Modules/CheckCXXFeatures/cxx-test-sizeof_member_fail.cpp new file mode 100644 index 0000000..0348c2c --- /dev/null +++ b/lib/libtins/cmake/Modules/CheckCXXFeatures/cxx-test-sizeof_member_fail.cpp @@ -0,0 +1,9 @@ +struct foo { + int baz; + double bar; +}; + +int main(void) +{ + return (sizeof(foo::bar) == 4) ? 0 : 1; +} diff --git a/lib/libtins/cmake/Modules/CheckCXXFeatures/cxx-test-static_assert.cpp b/lib/libtins/cmake/Modules/CheckCXXFeatures/cxx-test-static_assert.cpp new file mode 100644 index 0000000..47c2fef --- /dev/null +++ b/lib/libtins/cmake/Modules/CheckCXXFeatures/cxx-test-static_assert.cpp @@ -0,0 +1,5 @@ +int main(void) +{ + static_assert(0 < 1, "your ordering of integers is screwed"); + return 0; +} diff --git a/lib/libtins/cmake/Modules/CheckCXXFeatures/cxx-test-static_assert_fail_compile.cpp b/lib/libtins/cmake/Modules/CheckCXXFeatures/cxx-test-static_assert_fail_compile.cpp new file mode 100644 index 0000000..362fcdd --- /dev/null +++ b/lib/libtins/cmake/Modules/CheckCXXFeatures/cxx-test-static_assert_fail_compile.cpp @@ -0,0 +1,5 @@ +int main(void) +{ + static_assert(1 < 0, "your ordering of integers is screwed"); + return 0; +} diff --git a/lib/libtins/cmake/Modules/CheckCXXFeatures/cxx-test-variadic_templates.cpp b/lib/libtins/cmake/Modules/CheckCXXFeatures/cxx-test-variadic_templates.cpp new file mode 100644 index 0000000..4518e88 --- /dev/null +++ b/lib/libtins/cmake/Modules/CheckCXXFeatures/cxx-test-variadic_templates.cpp @@ -0,0 +1,23 @@ +int Accumulate() +{ + return 0; +} + +template +int Accumulate(T v, Ts... vs) +{ + return v + Accumulate(vs...); +} + +template +int CountElements() +{ + return sizeof...(Is); +} + +int main() +{ + int acc = Accumulate(1, 2, 3, 4, -5); + int count = CountElements<1,2,3,4,5>(); + return ((acc == 5) && (count == 5)) ? 0 : 1; +} diff --git a/lib/libtins/cmake/Modules/FindPCAP.cmake b/lib/libtins/cmake/Modules/FindPCAP.cmake new file mode 100644 index 0000000..388b30b --- /dev/null +++ b/lib/libtins/cmake/Modules/FindPCAP.cmake @@ -0,0 +1,85 @@ +# - Try to find libpcap include dirs and libraries +# +# Usage of this module as follows: +# +# find_package(PCAP) +# +# Variables used by this module, they can change the default behaviour and need +# to be set before calling find_package: +# +# PCAP_ROOT_DIR Set this variable to the root installation of +# libpcap if the module has problems finding the +# proper installation path. +# +# Variables defined by this module: +# +# PCAP_FOUND System has libpcap, include and library dirs found +# PCAP_INCLUDE_DIR The libpcap include directories. +# PCAP_LIBRARY The libpcap library (possibly includes a thread +# library e.g. required by pf_ring's libpcap) +# HAVE_PF_RING If a found version of libpcap supports PF_RING +# HAVE_PCAP_IMMEDIATE_MODE If the version of libpcap found supports immediate mode + +find_path(PCAP_ROOT_DIR + NAMES include/pcap.h +) + +find_path(PCAP_INCLUDE_DIR + NAMES pcap.h + HINTS ${PCAP_ROOT_DIR}/include +) + +set (HINT_DIR ${PCAP_ROOT_DIR}/lib) + +# On x64 windows, we should look also for the .lib at /lib/x64/ +# as this is the default path for the WinPcap developer's pack +if (${CMAKE_SIZEOF_VOID_P} EQUAL 8 AND WIN32) + set (HINT_DIR ${PCAP_ROOT_DIR}/lib/x64/ ${HINT_DIR}) +endif () + +find_library(PCAP_LIBRARY + NAMES pcap wpcap + HINTS ${HINT_DIR} +) + +include(FindPackageHandleStandardArgs) +find_package_handle_standard_args(PCAP DEFAULT_MSG + PCAP_LIBRARY + PCAP_INCLUDE_DIR +) + +include(CheckCXXSourceCompiles) +set(CMAKE_REQUIRED_LIBRARIES ${PCAP_LIBRARY}) +check_cxx_source_compiles("int main() { return 0; }" PCAP_LINKS_SOLO) +set(CMAKE_REQUIRED_LIBRARIES) + +# check if linking against libpcap also needs to link against a thread library +if (NOT PCAP_LINKS_SOLO) + find_package(Threads) + if (THREADS_FOUND) + set(CMAKE_REQUIRED_LIBRARIES ${PCAP_LIBRARY} ${CMAKE_THREAD_LIBS_INIT}) + check_cxx_source_compiles("int main() { return 0; }" PCAP_NEEDS_THREADS) + set(CMAKE_REQUIRED_LIBRARIES) + endif (THREADS_FOUND) + if (THREADS_FOUND AND PCAP_NEEDS_THREADS) + set(_tmp ${PCAP_LIBRARY} ${CMAKE_THREAD_LIBS_INIT}) + list(REMOVE_DUPLICATES _tmp) + set(PCAP_LIBRARY ${_tmp} + CACHE STRING "Libraries needed to link against libpcap" FORCE) + else (THREADS_FOUND AND PCAP_NEEDS_THREADS) + message(FATAL_ERROR "Couldn't determine how to link against libpcap") + endif (THREADS_FOUND AND PCAP_NEEDS_THREADS) +endif (NOT PCAP_LINKS_SOLO) + +include(CheckFunctionExists) +set(CMAKE_REQUIRED_LIBRARIES ${PCAP_LIBRARY}) +check_function_exists(pcap_get_pfring_id HAVE_PF_RING) +check_function_exists(pcap_set_immediate_mode HAVE_PCAP_IMMEDIATE_MODE) +check_function_exists(pcap_set_tstamp_precision HAVE_PCAP_TIMESTAMP_PRECISION) +set(CMAKE_REQUIRED_LIBRARIES) + +mark_as_advanced( + PCAP_ROOT_DIR + PCAP_INCLUDE_DIR + PCAP_LIBRARY +) diff --git a/lib/libtins/cmake/appveyor.yml b/lib/libtins/cmake/appveyor.yml new file mode 100644 index 0000000..f3cecb6 --- /dev/null +++ b/lib/libtins/cmake/appveyor.yml @@ -0,0 +1,53 @@ +version: 1.0.{build} +configuration: +- debug +- release +platform: +- Win32 +- x64 +environment: + matrix: + - compiler: vs2013 + - compiler: vs2015 + BOOST_ROOT: C:/Libraries/boost +clone_depth: 1 +install: +- git clone https://github.com/mfontanini/winpcap-installer.git +- cd winpcap-installer +- winpcap-boundary-meter-4.1.3.exe /S +- cd .. +- appveyor DownloadFile http://www.winpcap.org/install/bin/WpdPack_4_1_2.zip +- 7z x .\WpdPack_4_1_2.zip -oc:\ +- git submodule init +- git submodule update +before_build: +- mkdir build +- cd build +- if "%compiler%"=="vs2013" (set VS_VERSION=12) else (set VS_VERSION=14) +- set VS=Visual Studio %VS_VERSION% +- if "%platform%"=="Win32" (set GENERATOR="%VS%" & set ARCH_BITS=32) +- if "%platform%"=="x64" (set GENERATOR="%VS% Win64" & set ARCH_BITS=64) +- set BOOST_LIBRARYDIR=C:\Libraries\boost\lib%ARCH_BITS%-msvc-%VS_VERSION%.0 +- cmake .. -G %GENERATOR% -DPCAP_ROOT_DIR=c:\WpdPack -DLIBTINS_BUILD_SHARED=0 -DLIBTINS_ENABLE_WPA2=0 -DBOOST_ROOT="%BOOST_ROOT%" -DBOOST_LIBRARYDIR="%BOOST_LIBRARYDIR%" -DBoost_USE_STATIC_LIBS="ON" +build: + project: C:/projects/libtins/build/libtins.sln + verbosity: minimal +after_build: +- mkdir install\libtins\include +- mkdir install\libtins\lib +- cd install\libtins +- copy C:\projects\libtins\build\lib\%Configuration%\tins.lib lib +- xcopy C:\projects\libtins\include include /s /e +- del include\CMakeLists.txt +- del include\tins\CMakeLists.txt +- del include\tins\config.h.in +- del include\tins\dot11\CMakeLists.txt +- cd ..\ +- 7z a libtins-%compiler%-%platform%-%Configuration%.zip libtins +test_script: +- cd c:\projects\libtins\build +- ctest -C %Configuration% -V +deploy_script: +- ps: Push-AppveyorArtifact "install\libtins-$env:Compiler-$env:Platform-$env:Configuration.zip" +skip_commits: + message: /Update documentation.*/ diff --git a/lib/libtins/cmake/cmake_uninstall.cmake.in b/lib/libtins/cmake/cmake_uninstall.cmake.in new file mode 100644 index 0000000..fa826e2 --- /dev/null +++ b/lib/libtins/cmake/cmake_uninstall.cmake.in @@ -0,0 +1,23 @@ +# Taken from https://cmake.org/Wiki/CMake_FAQ#Can_I_do_.22make_uninstall.22_with_CMake.3F + +if(NOT EXISTS "@CMAKE_CURRENT_BINARY_DIR@/install_manifest.txt") + message(FATAL_ERROR "Cannot find install manifest: @CMAKE_CURRENT_BINARY_DIR@/install_manifest.txt") +endif(NOT EXISTS "@CMAKE_CURRENT_BINARY_DIR@/install_manifest.txt") + +file(READ "@CMAKE_CURRENT_BINARY_DIR@/install_manifest.txt" files) +string(REGEX REPLACE "\n" ";" files "${files}") +foreach(file ${files}) + message(STATUS "Uninstalling $ENV{DESTDIR}${file}") + if(IS_SYMLINK "$ENV{DESTDIR}${file}" OR EXISTS "$ENV{DESTDIR}${file}") + exec_program( + "@CMAKE_COMMAND@" ARGS "-E remove \"$ENV{DESTDIR}${file}\"" + OUTPUT_VARIABLE rm_out + RETURN_VALUE rm_retval + ) + if(NOT "${rm_retval}" STREQUAL 0) + message(FATAL_ERROR "Problem when removing $ENV{DESTDIR}${file}") + endif(NOT "${rm_retval}" STREQUAL 0) + else(IS_SYMLINK "$ENV{DESTDIR}${file}" OR EXISTS "$ENV{DESTDIR}${file}") + message(STATUS "File $ENV{DESTDIR}${file} does not exist.") + endif(IS_SYMLINK "$ENV{DESTDIR}${file}" OR EXISTS "$ENV{DESTDIR}${file}") +endforeach(file) \ No newline at end of file diff --git a/lib/libtins/cmake/libtinsConfig.cmake.in b/lib/libtins/cmake/libtinsConfig.cmake.in new file mode 100644 index 0000000..183b245 --- /dev/null +++ b/lib/libtins/cmake/libtinsConfig.cmake.in @@ -0,0 +1,16 @@ +# - Config file for the libtins package +# It defines the following variables +# LIBTINS_INCLUDE_DIRS - include directories for libtins +# LIBTINS_LIBRARIES - libraries to link against + +# Compute paths +get_filename_component(LIBTINS_CMAKE_DIR "${CMAKE_CURRENT_LIST_FILE}" PATH) +set(LIBTINS_INCLUDE_DIRS "@CONF_INCLUDE_DIRS@") + +# Our library dependencies (contains definitions for IMPORTED targets) +if(NOT TARGET libtins AND NOT LIBTINS_BINARY_DIR) + include("${LIBTINS_CMAKE_DIR}/libtinsTargets.cmake") +endif() + +# These are IMPORTED targets created by libtinsTargets.cmake +set(LIBTINS_LIBRARIES tins) diff --git a/lib/libtins/cmake/libtinsConfigVersion.cmake.in b/lib/libtins/cmake/libtinsConfigVersion.cmake.in new file mode 100644 index 0000000..9e643a8 --- /dev/null +++ b/lib/libtins/cmake/libtinsConfigVersion.cmake.in @@ -0,0 +1,11 @@ +set(PACKAGE_VERSION "@LIBTINS_VERSION@") + +# Check whether the requested PACKAGE_FIND_VERSION is compatible +if("${PACKAGE_VERSION}" VERSION_LESS "${PACKAGE_FIND_VERSION}") + set(PACKAGE_VERSION_COMPATIBLE FALSE) +else() + set(PACKAGE_VERSION_COMPATIBLE TRUE) + if ("${PACKAGE_VERSION}" VERSION_EQUAL "${PACKAGE_FIND_VERSION}") + set(PACKAGE_VERSION_EXACT TRUE) + endif() +endif() diff --git a/lib/libtins/docs/Doxyfile.in b/lib/libtins/docs/Doxyfile.in new file mode 100644 index 0000000..1c2ecd3 --- /dev/null +++ b/lib/libtins/docs/Doxyfile.in @@ -0,0 +1,1632 @@ +# Doxyfile 1.7.1 + +# This file describes the settings to be used by the documentation system +# doxygen (www.doxygen.org) for a project +# +# All text after a hash (#) is considered a comment and will be ignored +# The format is: +# TAG = value [value, ...] +# For lists items can also be appended using: +# TAG += value [value, ...] +# Values that contain spaces should be placed between quotes (" ") + +#--------------------------------------------------------------------------- +# Project related configuration options +#--------------------------------------------------------------------------- + +# This tag specifies the encoding used for all characters in the config file +# that follow. The default is UTF-8 which is also the encoding used for all +# text before the first occurrence of this tag. Doxygen uses libiconv (or the +# iconv built into libc) for the transcoding. See +# http://www.gnu.org/software/libiconv for the list of possible encodings. + +DOXYFILE_ENCODING = UTF-8 + +# The PROJECT_NAME tag is a single word (or a sequence of words surrounded +# by quotes) that should identify the project. + +PROJECT_NAME = libtins + +# The PROJECT_NUMBER tag can be used to enter a project or revision number. +# This could be handy for archiving the generated documentation or +# if some version control system is used. + +PROJECT_NUMBER = @LIBTINS_VERSION@ + +# The OUTPUT_DIRECTORY tag is used to specify the (relative or absolute) +# base path where the generated documentation will be put. +# If a relative path is entered, it will be relative to the location +# where doxygen was started. If left blank the current directory will be used. + +OUTPUT_DIRECTORY = @CMAKE_CURRENT_BINARY_DIR@/docs/ + +# If the CREATE_SUBDIRS tag is set to YES, then doxygen will create +# 4096 sub-directories (in 2 levels) under the output directory of each output +# format and will distribute the generated files over these directories. +# Enabling this option can be useful when feeding doxygen a huge amount of +# source files, where putting all generated files in the same directory would +# otherwise cause performance problems for the file system. + +CREATE_SUBDIRS = YES + +# The OUTPUT_LANGUAGE tag is used to specify the language in which all +# documentation generated by doxygen is written. Doxygen will use this +# information to generate all constant output in the proper language. +# The default language is English, other supported languages are: +# Afrikaans, Arabic, Brazilian, Catalan, Chinese, Chinese-Traditional, +# Croatian, Czech, Danish, Dutch, Esperanto, Farsi, Finnish, French, German, +# Greek, Hungarian, Italian, Japanese, Japanese-en (Japanese with English +# messages), Korean, Korean-en, Lithuanian, Norwegian, Macedonian, Persian, +# Polish, Portuguese, Romanian, Russian, Serbian, Serbian-Cyrilic, Slovak, +# Slovene, Spanish, Swedish, Ukrainian, and Vietnamese. + +OUTPUT_LANGUAGE = English + +# If the BRIEF_MEMBER_DESC tag is set to YES (the default) Doxygen will +# include brief member descriptions after the members that are listed in +# the file and class documentation (similar to JavaDoc). +# Set to NO to disable this. + +BRIEF_MEMBER_DESC = YES + +# If the REPEAT_BRIEF tag is set to YES (the default) Doxygen will prepend +# the brief description of a member or function before the detailed description. +# Note: if both HIDE_UNDOC_MEMBERS and BRIEF_MEMBER_DESC are set to NO, the +# brief descriptions will be completely suppressed. + +REPEAT_BRIEF = YES + +# This tag implements a quasi-intelligent brief description abbreviator +# that is used to form the text in various listings. Each string +# in this list, if found as the leading text of the brief description, will be +# stripped from the text and the result after processing the whole list, is +# used as the annotated text. Otherwise, the brief description is used as-is. +# If left blank, the following values are used ("$name" is automatically +# replaced with the name of the entity): "The $name class" "The $name widget" +# "The $name file" "is" "provides" "specifies" "contains" +# "represents" "a" "an" "the" + +ABBREVIATE_BRIEF = + +# If the ALWAYS_DETAILED_SEC and REPEAT_BRIEF tags are both set to YES then +# Doxygen will generate a detailed section even if there is only a brief +# description. + +ALWAYS_DETAILED_SEC = NO + +# If the INLINE_INHERITED_MEMB tag is set to YES, doxygen will show all +# inherited members of a class in the documentation of that class as if those +# members were ordinary class members. Constructors, destructors and assignment +# operators of the base classes will not be shown. + +INLINE_INHERITED_MEMB = NO + +# If the FULL_PATH_NAMES tag is set to YES then Doxygen will prepend the full +# path before files name in the file list and in the header files. If set +# to NO the shortest path that makes the file name unique will be used. + +FULL_PATH_NAMES = YES + +# If the FULL_PATH_NAMES tag is set to YES then the STRIP_FROM_PATH tag +# can be used to strip a user-defined part of the path. Stripping is +# only done if one of the specified strings matches the left-hand part of +# the path. The tag can be used to show relative paths in the file list. +# If left blank the directory from which doxygen is run is used as the +# path to strip. + +STRIP_FROM_PATH = + +# The STRIP_FROM_INC_PATH tag can be used to strip a user-defined part of +# the path mentioned in the documentation of a class, which tells +# the reader which header file to include in order to use a class. +# If left blank only the name of the header file containing the class +# definition is used. Otherwise one should specify the include paths that +# are normally passed to the compiler using the -I flag. + +STRIP_FROM_INC_PATH = + +# If the SHORT_NAMES tag is set to YES, doxygen will generate much shorter +# (but less readable) file names. This can be useful is your file systems +# doesn't support long names like on DOS, Mac, or CD-ROM. + +SHORT_NAMES = NO + +# If the JAVADOC_AUTOBRIEF tag is set to YES then Doxygen +# will interpret the first line (until the first dot) of a JavaDoc-style +# comment as the brief description. If set to NO, the JavaDoc +# comments will behave just like regular Qt-style comments +# (thus requiring an explicit @brief command for a brief description.) + +JAVADOC_AUTOBRIEF = NO + +# If the QT_AUTOBRIEF tag is set to YES then Doxygen will +# interpret the first line (until the first dot) of a Qt-style +# comment as the brief description. If set to NO, the comments +# will behave just like regular Qt-style comments (thus requiring +# an explicit \brief command for a brief description.) + +QT_AUTOBRIEF = NO + +# The MULTILINE_CPP_IS_BRIEF tag can be set to YES to make Doxygen +# treat a multi-line C++ special comment block (i.e. a block of //! or /// +# comments) as a brief description. This used to be the default behaviour. +# The new default is to treat a multi-line C++ comment block as a detailed +# description. Set this tag to YES if you prefer the old behaviour instead. + +MULTILINE_CPP_IS_BRIEF = NO + +# If the INHERIT_DOCS tag is set to YES (the default) then an undocumented +# member inherits the documentation from any documented member that it +# re-implements. + +INHERIT_DOCS = YES + +# If the SEPARATE_MEMBER_PAGES tag is set to YES, then doxygen will produce +# a new page for each member. If set to NO, the documentation of a member will +# be part of the file/class/namespace that contains it. + +SEPARATE_MEMBER_PAGES = NO + +# The TAB_SIZE tag can be used to set the number of spaces in a tab. +# Doxygen uses this value to replace tabs by spaces in code fragments. + +TAB_SIZE = 4 + +# This tag can be used to specify a number of aliases that acts +# as commands in the documentation. An alias has the form "name=value". +# For example adding "sideeffect=\par Side Effects:\n" will allow you to +# put the command \sideeffect (or @sideeffect) in the documentation, which +# will result in a user-defined paragraph with heading "Side Effects:". +# You can put \n's in the value part of an alias to insert newlines. + +ALIASES = + +# Set the OPTIMIZE_OUTPUT_FOR_C tag to YES if your project consists of C +# sources only. Doxygen will then generate output that is more tailored for C. +# For instance, some of the names that are used will be different. The list +# of all members will be omitted, etc. + +OPTIMIZE_OUTPUT_FOR_C = NO + +# Set the OPTIMIZE_OUTPUT_JAVA tag to YES if your project consists of Java +# sources only. Doxygen will then generate output that is more tailored for +# Java. For instance, namespaces will be presented as packages, qualified +# scopes will look different, etc. + +OPTIMIZE_OUTPUT_JAVA = NO + +# Set the OPTIMIZE_FOR_FORTRAN tag to YES if your project consists of Fortran +# sources only. Doxygen will then generate output that is more tailored for +# Fortran. + +OPTIMIZE_FOR_FORTRAN = NO + +# Set the OPTIMIZE_OUTPUT_VHDL tag to YES if your project consists of VHDL +# sources. Doxygen will then generate output that is tailored for +# VHDL. + +OPTIMIZE_OUTPUT_VHDL = NO + +# Doxygen selects the parser to use depending on the extension of the files it +# parses. With this tag you can assign which parser to use for a given extension. +# Doxygen has a built-in mapping, but you can override or extend it using this +# tag. The format is ext=language, where ext is a file extension, and language +# is one of the parsers supported by doxygen: IDL, Java, Javascript, CSharp, C, +# C++, D, PHP, Objective-C, Python, Fortran, VHDL, C, C++. For instance to make +# doxygen treat .inc files as Fortran files (default is PHP), and .f files as C +# (default is Fortran), use: inc=Fortran f=C. Note that for custom extensions +# you also need to set FILE_PATTERNS otherwise the files are not read by doxygen. + +EXTENSION_MAPPING = + +# If you use STL classes (i.e. std::string, std::vector, etc.) but do not want +# to include (a tag file for) the STL sources as input, then you should +# set this tag to YES in order to let doxygen match functions declarations and +# definitions whose arguments contain STL classes (e.g. func(std::string); v.s. +# func(std::string) {}). This also make the inheritance and collaboration +# diagrams that involve STL classes more complete and accurate. + +BUILTIN_STL_SUPPORT = NO + +# If you use Microsoft's C++/CLI language, you should set this option to YES to +# enable parsing support. + +CPP_CLI_SUPPORT = NO + +# Set the SIP_SUPPORT tag to YES if your project consists of sip sources only. +# Doxygen will parse them like normal C++ but will assume all classes use public +# instead of private inheritance when no explicit protection keyword is present. + +SIP_SUPPORT = NO + +# For Microsoft's IDL there are propget and propput attributes to indicate getter +# and setter methods for a property. Setting this option to YES (the default) +# will make doxygen to replace the get and set methods by a property in the +# documentation. This will only work if the methods are indeed getting or +# setting a simple type. If this is not the case, or you want to show the +# methods anyway, you should set this option to NO. + +IDL_PROPERTY_SUPPORT = YES + +# If member grouping is used in the documentation and the DISTRIBUTE_GROUP_DOC +# tag is set to YES, then doxygen will reuse the documentation of the first +# member in the group (if any) for the other members of the group. By default +# all members of a group must be documented explicitly. + +DISTRIBUTE_GROUP_DOC = NO + +# Set the SUBGROUPING tag to YES (the default) to allow class member groups of +# the same type (for instance a group of public functions) to be put as a +# subgroup of that type (e.g. under the Public Functions section). Set it to +# NO to prevent subgrouping. Alternatively, this can be done per class using +# the \nosubgrouping command. + +SUBGROUPING = YES + +# When TYPEDEF_HIDES_STRUCT is enabled, a typedef of a struct, union, or enum +# is documented as struct, union, or enum with the name of the typedef. So +# typedef struct TypeS {} TypeT, will appear in the documentation as a struct +# with name TypeT. When disabled the typedef will appear as a member of a file, +# namespace, or class. And the struct will be named TypeS. This can typically +# be useful for C code in case the coding convention dictates that all compound +# types are typedef'ed and only the typedef is referenced, never the tag name. + +TYPEDEF_HIDES_STRUCT = NO + +# The SYMBOL_CACHE_SIZE determines the size of the internal cache use to +# determine which symbols to keep in memory and which to flush to disk. +# When the cache is full, less often used symbols will be written to disk. +# For small to medium size projects (<1000 input files) the default value is +# probably good enough. For larger projects a too small cache size can cause +# doxygen to be busy swapping symbols to and from disk most of the time +# causing a significant performance penality. +# If the system has enough physical memory increasing the cache will improve the +# performance by keeping more symbols in memory. Note that the value works on +# a logarithmic scale so increasing the size by one will rougly double the +# memory usage. The cache size is given by this formula: +# 2^(16+SYMBOL_CACHE_SIZE). The valid range is 0..9, the default is 0, +# corresponding to a cache size of 2^16 = 65536 symbols + +SYMBOL_CACHE_SIZE = 0 + +#--------------------------------------------------------------------------- +# Build related configuration options +#--------------------------------------------------------------------------- + +# If the EXTRACT_ALL tag is set to YES doxygen will assume all entities in +# documentation are documented, even if no documentation was available. +# Private class members and static file members will be hidden unless +# the EXTRACT_PRIVATE and EXTRACT_STATIC tags are set to YES + +EXTRACT_ALL = NO + +# If the EXTRACT_PRIVATE tag is set to YES all private members of a class +# will be included in the documentation. + +EXTRACT_PRIVATE = NO + +# If the EXTRACT_STATIC tag is set to YES all static members of a file +# will be included in the documentation. + +EXTRACT_STATIC = YES + +# If the EXTRACT_LOCAL_CLASSES tag is set to YES classes (and structs) +# defined locally in source files will be included in the documentation. +# If set to NO only classes defined in header files are included. + +EXTRACT_LOCAL_CLASSES = YES + +# This flag is only useful for Objective-C code. When set to YES local +# methods, which are defined in the implementation section but not in +# the interface are included in the documentation. +# If set to NO (the default) only methods in the interface are included. + +EXTRACT_LOCAL_METHODS = NO + +# If this flag is set to YES, the members of anonymous namespaces will be +# extracted and appear in the documentation as a namespace called +# 'anonymous_namespace{file}', where file will be replaced with the base +# name of the file that contains the anonymous namespace. By default +# anonymous namespace are hidden. + +EXTRACT_ANON_NSPACES = NO + +# If the HIDE_UNDOC_MEMBERS tag is set to YES, Doxygen will hide all +# undocumented members of documented classes, files or namespaces. +# If set to NO (the default) these members will be included in the +# various overviews, but no documentation section is generated. +# This option has no effect if EXTRACT_ALL is enabled. + +HIDE_UNDOC_MEMBERS = NO + +# If the HIDE_UNDOC_CLASSES tag is set to YES, Doxygen will hide all +# undocumented classes that are normally visible in the class hierarchy. +# If set to NO (the default) these classes will be included in the various +# overviews. This option has no effect if EXTRACT_ALL is enabled. + +HIDE_UNDOC_CLASSES = NO + +# If the HIDE_FRIEND_COMPOUNDS tag is set to YES, Doxygen will hide all +# friend (class|struct|union) declarations. +# If set to NO (the default) these declarations will be included in the +# documentation. + +HIDE_FRIEND_COMPOUNDS = NO + +# If the HIDE_IN_BODY_DOCS tag is set to YES, Doxygen will hide any +# documentation blocks found inside the body of a function. +# If set to NO (the default) these blocks will be appended to the +# function's detailed documentation block. + +HIDE_IN_BODY_DOCS = NO + +# The INTERNAL_DOCS tag determines if documentation +# that is typed after a \internal command is included. If the tag is set +# to NO (the default) then the documentation will be excluded. +# Set it to YES to include the internal documentation. + +INTERNAL_DOCS = NO + +# If the CASE_SENSE_NAMES tag is set to NO then Doxygen will only generate +# file names in lower-case letters. If set to YES upper-case letters are also +# allowed. This is useful if you have classes or files whose names only differ +# in case and if your file system supports case sensitive file names. Windows +# and Mac users are advised to set this option to NO. + +CASE_SENSE_NAMES = YES + +# If the HIDE_SCOPE_NAMES tag is set to NO (the default) then Doxygen +# will show members with their full class and namespace scopes in the +# documentation. If set to YES the scope will be hidden. + +HIDE_SCOPE_NAMES = NO + +# If the SHOW_INCLUDE_FILES tag is set to YES (the default) then Doxygen +# will put a list of the files that are included by a file in the documentation +# of that file. + +SHOW_INCLUDE_FILES = YES + +# If the FORCE_LOCAL_INCLUDES tag is set to YES then Doxygen +# will list include files with double quotes in the documentation +# rather than with sharp brackets. + +FORCE_LOCAL_INCLUDES = NO + +# If the INLINE_INFO tag is set to YES (the default) then a tag [inline] +# is inserted in the documentation for inline members. + +INLINE_INFO = YES + +# If the SORT_MEMBER_DOCS tag is set to YES (the default) then doxygen +# will sort the (detailed) documentation of file and class members +# alphabetically by member name. If set to NO the members will appear in +# declaration order. + +SORT_MEMBER_DOCS = YES + +# If the SORT_BRIEF_DOCS tag is set to YES then doxygen will sort the +# brief documentation of file, namespace and class members alphabetically +# by member name. If set to NO (the default) the members will appear in +# declaration order. + +SORT_BRIEF_DOCS = NO + +# If the SORT_MEMBERS_CTORS_1ST tag is set to YES then doxygen +# will sort the (brief and detailed) documentation of class members so that +# constructors and destructors are listed first. If set to NO (the default) +# the constructors will appear in the respective orders defined by +# SORT_MEMBER_DOCS and SORT_BRIEF_DOCS. +# This tag will be ignored for brief docs if SORT_BRIEF_DOCS is set to NO +# and ignored for detailed docs if SORT_MEMBER_DOCS is set to NO. + +SORT_MEMBERS_CTORS_1ST = NO + +# If the SORT_GROUP_NAMES tag is set to YES then doxygen will sort the +# hierarchy of group names into alphabetical order. If set to NO (the default) +# the group names will appear in their defined order. + +SORT_GROUP_NAMES = NO + +# If the SORT_BY_SCOPE_NAME tag is set to YES, the class list will be +# sorted by fully-qualified names, including namespaces. If set to +# NO (the default), the class list will be sorted only by class name, +# not including the namespace part. +# Note: This option is not very useful if HIDE_SCOPE_NAMES is set to YES. +# Note: This option applies only to the class list, not to the +# alphabetical list. + +SORT_BY_SCOPE_NAME = NO + +# The GENERATE_TODOLIST tag can be used to enable (YES) or +# disable (NO) the todo list. This list is created by putting \todo +# commands in the documentation. + +GENERATE_TODOLIST = YES + +# The GENERATE_TESTLIST tag can be used to enable (YES) or +# disable (NO) the test list. This list is created by putting \test +# commands in the documentation. + +GENERATE_TESTLIST = YES + +# The GENERATE_BUGLIST tag can be used to enable (YES) or +# disable (NO) the bug list. This list is created by putting \bug +# commands in the documentation. + +GENERATE_BUGLIST = YES + +# The GENERATE_DEPRECATEDLIST tag can be used to enable (YES) or +# disable (NO) the deprecated list. This list is created by putting +# \deprecated commands in the documentation. + +GENERATE_DEPRECATEDLIST= YES + +# The ENABLED_SECTIONS tag can be used to enable conditional +# documentation sections, marked by \if sectionname ... \endif. + +ENABLED_SECTIONS = + +# The MAX_INITIALIZER_LINES tag determines the maximum number of lines +# the initial value of a variable or define consists of for it to appear in +# the documentation. If the initializer consists of more lines than specified +# here it will be hidden. Use a value of 0 to hide initializers completely. +# The appearance of the initializer of individual variables and defines in the +# documentation can be controlled using \showinitializer or \hideinitializer +# command in the documentation regardless of this setting. + +MAX_INITIALIZER_LINES = 30 + +# Set the SHOW_USED_FILES tag to NO to disable the list of files generated +# at the bottom of the documentation of classes and structs. If set to YES the +# list will mention the files that were used to generate the documentation. + +SHOW_USED_FILES = YES + +# If the sources in your project are distributed over multiple directories +# then setting the SHOW_DIRECTORIES tag to YES will show the directory hierarchy +# in the documentation. The default is NO. + +SHOW_DIRECTORIES = NO + +# Set the SHOW_FILES tag to NO to disable the generation of the Files page. +# This will remove the Files entry from the Quick Index and from the +# Folder Tree View (if specified). The default is YES. + +SHOW_FILES = YES + +# Set the SHOW_NAMESPACES tag to NO to disable the generation of the +# Namespaces page. +# This will remove the Namespaces entry from the Quick Index +# and from the Folder Tree View (if specified). The default is YES. + +SHOW_NAMESPACES = YES + +# The FILE_VERSION_FILTER tag can be used to specify a program or script that +# doxygen should invoke to get the current version for each file (typically from +# the version control system). Doxygen will invoke the program by executing (via +# popen()) the command , where is the value of +# the FILE_VERSION_FILTER tag, and is the name of an input file +# provided by doxygen. Whatever the program writes to standard output +# is used as the file version. See the manual for examples. + +FILE_VERSION_FILTER = + +# The LAYOUT_FILE tag can be used to specify a layout file which will be parsed +# by doxygen. The layout file controls the global structure of the generated +# output files in an output format independent way. The create the layout file +# that represents doxygen's defaults, run doxygen with the -l option. +# You can optionally specify a file name after the option, if omitted +# DoxygenLayout.xml will be used as the name of the layout file. + +LAYOUT_FILE = + +#--------------------------------------------------------------------------- +# configuration options related to warning and progress messages +#--------------------------------------------------------------------------- + +# The QUIET tag can be used to turn on/off the messages that are generated +# by doxygen. Possible values are YES and NO. If left blank NO is used. + +QUIET = NO + +# The WARNINGS tag can be used to turn on/off the warning messages that are +# generated by doxygen. Possible values are YES and NO. If left blank +# NO is used. + +WARNINGS = YES + +# If WARN_IF_UNDOCUMENTED is set to YES, then doxygen will generate warnings +# for undocumented members. If EXTRACT_ALL is set to YES then this flag will +# automatically be disabled. + +WARN_IF_UNDOCUMENTED = YES + +# If WARN_IF_DOC_ERROR is set to YES, doxygen will generate warnings for +# potential errors in the documentation, such as not documenting some +# parameters in a documented function, or documenting parameters that +# don't exist or using markup commands wrongly. + +WARN_IF_DOC_ERROR = YES + +# This WARN_NO_PARAMDOC option can be abled to get warnings for +# functions that are documented, but have no documentation for their parameters +# or return value. If set to NO (the default) doxygen will only warn about +# wrong or incomplete parameter documentation, but not about the absence of +# documentation. + +WARN_NO_PARAMDOC = NO + +# The WARN_FORMAT tag determines the format of the warning messages that +# doxygen can produce. The string should contain the $file, $line, and $text +# tags, which will be replaced by the file and line number from which the +# warning originated and the warning text. Optionally the format may contain +# $version, which will be replaced by the version of the file (if it could +# be obtained via FILE_VERSION_FILTER) + +WARN_FORMAT = "$file:$line: $text" + +# The WARN_LOGFILE tag can be used to specify a file to which warning +# and error messages should be written. If left blank the output is written +# to stderr. + +WARN_LOGFILE = + +#--------------------------------------------------------------------------- +# configuration options related to the input files +#--------------------------------------------------------------------------- + +# The INPUT tag can be used to specify the files and/or directories that contain +# documented source files. You may enter file names like "myfile.cpp" or +# directories like "/usr/src/myproject". Separate the files or directories +# with spaces. + +INPUT = @CMAKE_CURRENT_SOURCE_DIR@/include @CMAKE_CURRENT_SOURCE_DIR@/src @CMAKE_CURRENT_SOURCE_DIR@/docs/mainpage.dox + +# This tag can be used to specify the character encoding of the source files +# that doxygen parses. Internally doxygen uses the UTF-8 encoding, which is +# also the default input encoding. Doxygen uses libiconv (or the iconv built +# into libc) for the transcoding. See http://www.gnu.org/software/libiconv for +# the list of possible encodings. + +INPUT_ENCODING = UTF-8 + +# If the value of the INPUT tag contains directories, you can use the +# FILE_PATTERNS tag to specify one or more wildcard pattern (like *.cpp +# and *.h) to filter out the source-files in the directories. If left +# blank the following patterns are tested: +# *.c *.cc *.cxx *.cpp *.c++ *.java *.ii *.ixx *.ipp *.i++ *.inl *.h *.hh *.hxx +# *.hpp *.h++ *.idl *.odl *.cs *.php *.php3 *.inc *.m *.mm *.py *.f90 + +FILE_PATTERNS = *.cpp *.h + +# The RECURSIVE tag can be used to turn specify whether or not subdirectories +# should be searched for input files as well. Possible values are YES and NO. +# If left blank NO is used. + +RECURSIVE = YES + +# The EXCLUDE tag can be used to specify files and/or directories that should +# excluded from the INPUT source files. This way you can easily exclude a +# subdirectory from a directory tree whose root is specified with the INPUT tag. + +EXCLUDE = + +# The EXCLUDE_SYMLINKS tag can be used select whether or not files or +# directories that are symbolic links (a Unix filesystem feature) are excluded +# from the input. + +EXCLUDE_SYMLINKS = NO + +# If the value of the INPUT tag contains directories, you can use the +# EXCLUDE_PATTERNS tag to specify one or more wildcard patterns to exclude +# certain files from those directories. Note that the wildcards are matched +# against the file with absolute path, so to exclude all test directories +# for example use the pattern */test/* + +EXCLUDE_PATTERNS = */main.cpp + +# The EXCLUDE_SYMBOLS tag can be used to specify one or more symbol names +# (namespaces, classes, functions, etc.) that should be excluded from the +# output. The symbol name can be a fully qualified name, a word, or if the +# wildcard * is used, a substring. Examples: ANamespace, AClass, +# AClass::ANamespace, ANamespace::*Test + +EXCLUDE_SYMBOLS = + +# The EXAMPLE_PATH tag can be used to specify one or more files or +# directories that contain example code fragments that are included (see +# the \include command). + +EXAMPLE_PATH = + +# If the value of the EXAMPLE_PATH tag contains directories, you can use the +# EXAMPLE_PATTERNS tag to specify one or more wildcard pattern (like *.cpp +# and *.h) to filter out the source-files in the directories. If left +# blank all files are included. + +EXAMPLE_PATTERNS = + +# If the EXAMPLE_RECURSIVE tag is set to YES then subdirectories will be +# searched for input files to be used with the \include or \dontinclude +# commands irrespective of the value of the RECURSIVE tag. +# Possible values are YES and NO. If left blank NO is used. + +EXAMPLE_RECURSIVE = NO + +# The IMAGE_PATH tag can be used to specify one or more files or +# directories that contain image that are included in the documentation (see +# the \image command). + +IMAGE_PATH = + +# The INPUT_FILTER tag can be used to specify a program that doxygen should +# invoke to filter for each input file. Doxygen will invoke the filter program +# by executing (via popen()) the command , where +# is the value of the INPUT_FILTER tag, and is the name of an +# input file. Doxygen will then use the output that the filter program writes +# to standard output. +# If FILTER_PATTERNS is specified, this tag will be +# ignored. + +INPUT_FILTER = + +# The FILTER_PATTERNS tag can be used to specify filters on a per file pattern +# basis. +# Doxygen will compare the file name with each pattern and apply the +# filter if there is a match. +# The filters are a list of the form: +# pattern=filter (like *.cpp=my_cpp_filter). See INPUT_FILTER for further +# info on how filters are used. If FILTER_PATTERNS is empty, INPUT_FILTER +# is applied to all files. + +FILTER_PATTERNS = + +# If the FILTER_SOURCE_FILES tag is set to YES, the input filter (if set using +# INPUT_FILTER) will be used to filter the input files when producing source +# files to browse (i.e. when SOURCE_BROWSER is set to YES). + +FILTER_SOURCE_FILES = NO + +#--------------------------------------------------------------------------- +# configuration options related to source browsing +#--------------------------------------------------------------------------- + +# If the SOURCE_BROWSER tag is set to YES then a list of source files will +# be generated. Documented entities will be cross-referenced with these sources. +# Note: To get rid of all source code in the generated output, make sure also +# VERBATIM_HEADERS is set to NO. + +SOURCE_BROWSER = NO + +# Setting the INLINE_SOURCES tag to YES will include the body +# of functions and classes directly in the documentation. + +INLINE_SOURCES = NO + +# Setting the STRIP_CODE_COMMENTS tag to YES (the default) will instruct +# doxygen to hide any special comment blocks from generated source code +# fragments. Normal C and C++ comments will always remain visible. + +STRIP_CODE_COMMENTS = YES + +# If the REFERENCED_BY_RELATION tag is set to YES +# then for each documented function all documented +# functions referencing it will be listed. + +REFERENCED_BY_RELATION = NO + +# If the REFERENCES_RELATION tag is set to YES +# then for each documented function all documented entities +# called/used by that function will be listed. + +REFERENCES_RELATION = NO + +# If the REFERENCES_LINK_SOURCE tag is set to YES (the default) +# and SOURCE_BROWSER tag is set to YES, then the hyperlinks from +# functions in REFERENCES_RELATION and REFERENCED_BY_RELATION lists will +# link to the source code. +# Otherwise they will link to the documentation. + +REFERENCES_LINK_SOURCE = YES + +# If the USE_HTAGS tag is set to YES then the references to source code +# will point to the HTML generated by the htags(1) tool instead of doxygen +# built-in source browser. The htags tool is part of GNU's global source +# tagging system (see http://www.gnu.org/software/global/global.html). You +# will need version 4.8.6 or higher. + +USE_HTAGS = NO + +# If the VERBATIM_HEADERS tag is set to YES (the default) then Doxygen +# will generate a verbatim copy of the header file for each class for +# which an include is specified. Set to NO to disable this. + +VERBATIM_HEADERS = YES + +#--------------------------------------------------------------------------- +# configuration options related to the alphabetical class index +#--------------------------------------------------------------------------- + +# If the ALPHABETICAL_INDEX tag is set to YES, an alphabetical index +# of all compounds will be generated. Enable this if the project +# contains a lot of classes, structs, unions or interfaces. + +ALPHABETICAL_INDEX = YES + +# If the alphabetical index is enabled (see ALPHABETICAL_INDEX) then +# the COLS_IN_ALPHA_INDEX tag can be used to specify the number of columns +# in which this list will be split (can be a number in the range [1..20]) + +COLS_IN_ALPHA_INDEX = 5 + +# In case all classes in a project start with a common prefix, all +# classes will be put under the same header in the alphabetical index. +# The IGNORE_PREFIX tag can be used to specify one or more prefixes that +# should be ignored while generating the index headers. + +IGNORE_PREFIX = + +#--------------------------------------------------------------------------- +# configuration options related to the HTML output +#--------------------------------------------------------------------------- + +# If the GENERATE_HTML tag is set to YES (the default) Doxygen will +# generate HTML output. + +GENERATE_HTML = YES + +# The HTML_OUTPUT tag is used to specify where the HTML docs will be put. +# If a relative path is entered the value of OUTPUT_DIRECTORY will be +# put in front of it. If left blank `html' will be used as the default path. + +HTML_OUTPUT = html + +# The HTML_FILE_EXTENSION tag can be used to specify the file extension for +# each generated HTML page (for example: .htm,.php,.asp). If it is left blank +# doxygen will generate files with .html extension. + +HTML_FILE_EXTENSION = .html + +# The HTML_HEADER tag can be used to specify a personal HTML header for +# each generated HTML page. If it is left blank doxygen will generate a +# standard header. + +HTML_HEADER = + +# The HTML_FOOTER tag can be used to specify a personal HTML footer for +# each generated HTML page. If it is left blank doxygen will generate a +# standard footer. + +HTML_FOOTER = + +# The HTML_STYLESHEET tag can be used to specify a user-defined cascading +# style sheet that is used by each HTML page. It can be used to +# fine-tune the look of the HTML output. If the tag is left blank doxygen +# will generate a default style sheet. Note that doxygen will try to copy +# the style sheet file to the HTML output directory, so don't put your own +# stylesheet in the HTML output directory as well, or it will be erased! + +HTML_STYLESHEET = + +# The HTML_COLORSTYLE_HUE tag controls the color of the HTML output. +# Doxygen will adjust the colors in the stylesheet and background images +# according to this color. Hue is specified as an angle on a colorwheel, +# see http://en.wikipedia.org/wiki/Hue for more information. +# For instance the value 0 represents red, 60 is yellow, 120 is green, +# 180 is cyan, 240 is blue, 300 purple, and 360 is red again. +# The allowed range is 0 to 359. + +HTML_COLORSTYLE_HUE = 220 + +# The HTML_COLORSTYLE_SAT tag controls the purity (or saturation) of +# the colors in the HTML output. For a value of 0 the output will use +# grayscales only. A value of 255 will produce the most vivid colors. + +HTML_COLORSTYLE_SAT = 100 + +# The HTML_COLORSTYLE_GAMMA tag controls the gamma correction applied to +# the luminance component of the colors in the HTML output. Values below +# 100 gradually make the output lighter, whereas values above 100 make +# the output darker. The value divided by 100 is the actual gamma applied, +# so 80 represents a gamma of 0.8, The value 220 represents a gamma of 2.2, +# and 100 does not change the gamma. + +HTML_COLORSTYLE_GAMMA = 80 + +# If the HTML_TIMESTAMP tag is set to YES then the footer of each generated HTML +# page will contain the date and time when the page was generated. Setting +# this to NO can help when comparing the output of multiple runs. + +HTML_TIMESTAMP = YES + +# If the HTML_ALIGN_MEMBERS tag is set to YES, the members of classes, +# files or namespaces will be aligned in HTML using tables. If set to +# NO a bullet list will be used. + +HTML_ALIGN_MEMBERS = YES + +# If the HTML_DYNAMIC_SECTIONS tag is set to YES then the generated HTML +# documentation will contain sections that can be hidden and shown after the +# page has loaded. For this to work a browser that supports +# JavaScript and DHTML is required (for instance Mozilla 1.0+, Firefox +# Netscape 6.0+, Internet explorer 5.0+, Konqueror, or Safari). + +HTML_DYNAMIC_SECTIONS = NO + +# If the GENERATE_DOCSET tag is set to YES, additional index files +# will be generated that can be used as input for Apple's Xcode 3 +# integrated development environment, introduced with OSX 10.5 (Leopard). +# To create a documentation set, doxygen will generate a Makefile in the +# HTML output directory. Running make will produce the docset in that +# directory and running "make install" will install the docset in +# ~/Library/Developer/Shared/Documentation/DocSets so that Xcode will find +# it at startup. +# See http://developer.apple.com/tools/creatingdocsetswithdoxygen.html +# for more information. + +GENERATE_DOCSET = NO + +# When GENERATE_DOCSET tag is set to YES, this tag determines the name of the +# feed. A documentation feed provides an umbrella under which multiple +# documentation sets from a single provider (such as a company or product suite) +# can be grouped. + +DOCSET_FEEDNAME = "Doxygen generated docs" + +# When GENERATE_DOCSET tag is set to YES, this tag specifies a string that +# should uniquely identify the documentation set bundle. This should be a +# reverse domain-name style string, e.g. com.mycompany.MyDocSet. Doxygen +# will append .docset to the name. + +DOCSET_BUNDLE_ID = org.doxygen.Project + +# When GENERATE_PUBLISHER_ID tag specifies a string that should uniquely identify +# the documentation publisher. This should be a reverse domain-name style +# string, e.g. com.mycompany.MyDocSet.documentation. + +DOCSET_PUBLISHER_ID = org.doxygen.Publisher + +# The GENERATE_PUBLISHER_NAME tag identifies the documentation publisher. + +DOCSET_PUBLISHER_NAME = Publisher + +# If the GENERATE_HTMLHELP tag is set to YES, additional index files +# will be generated that can be used as input for tools like the +# Microsoft HTML help workshop to generate a compiled HTML help file (.chm) +# of the generated HTML documentation. + +GENERATE_HTMLHELP = NO + +# If the GENERATE_HTMLHELP tag is set to YES, the CHM_FILE tag can +# be used to specify the file name of the resulting .chm file. You +# can add a path in front of the file if the result should not be +# written to the html output directory. + +CHM_FILE = + +# If the GENERATE_HTMLHELP tag is set to YES, the HHC_LOCATION tag can +# be used to specify the location (absolute path including file name) of +# the HTML help compiler (hhc.exe). If non-empty doxygen will try to run +# the HTML help compiler on the generated index.hhp. + +HHC_LOCATION = + +# If the GENERATE_HTMLHELP tag is set to YES, the GENERATE_CHI flag +# controls if a separate .chi index file is generated (YES) or that +# it should be included in the master .chm file (NO). + +GENERATE_CHI = NO + +# If the GENERATE_HTMLHELP tag is set to YES, the CHM_INDEX_ENCODING +# is used to encode HtmlHelp index (hhk), content (hhc) and project file +# content. + +CHM_INDEX_ENCODING = + +# If the GENERATE_HTMLHELP tag is set to YES, the BINARY_TOC flag +# controls whether a binary table of contents is generated (YES) or a +# normal table of contents (NO) in the .chm file. + +BINARY_TOC = NO + +# The TOC_EXPAND flag can be set to YES to add extra items for group members +# to the contents of the HTML help documentation and to the tree view. + +TOC_EXPAND = NO + +# If the GENERATE_QHP tag is set to YES and both QHP_NAMESPACE and +# QHP_VIRTUAL_FOLDER are set, an additional index file will be generated +# that can be used as input for Qt's qhelpgenerator to generate a +# Qt Compressed Help (.qch) of the generated HTML documentation. + +GENERATE_QHP = NO + +# If the QHG_LOCATION tag is specified, the QCH_FILE tag can +# be used to specify the file name of the resulting .qch file. +# The path specified is relative to the HTML output folder. + +QCH_FILE = + +# The QHP_NAMESPACE tag specifies the namespace to use when generating +# Qt Help Project output. For more information please see +# http://doc.trolltech.com/qthelpproject.html#namespace + +QHP_NAMESPACE = org.doxygen.Project + +# The QHP_VIRTUAL_FOLDER tag specifies the namespace to use when generating +# Qt Help Project output. For more information please see +# http://doc.trolltech.com/qthelpproject.html#virtual-folders + +QHP_VIRTUAL_FOLDER = doc + +# If QHP_CUST_FILTER_NAME is set, it specifies the name of a custom filter to +# add. For more information please see +# http://doc.trolltech.com/qthelpproject.html#custom-filters + +QHP_CUST_FILTER_NAME = + +# The QHP_CUST_FILT_ATTRS tag specifies the list of the attributes of the +# custom filter to add. For more information please see +# +# Qt Help Project / Custom Filters. + +QHP_CUST_FILTER_ATTRS = + +# The QHP_SECT_FILTER_ATTRS tag specifies the list of the attributes this +# project's +# filter section matches. +# +# Qt Help Project / Filter Attributes. + +QHP_SECT_FILTER_ATTRS = + +# If the GENERATE_QHP tag is set to YES, the QHG_LOCATION tag can +# be used to specify the location of Qt's qhelpgenerator. +# If non-empty doxygen will try to run qhelpgenerator on the generated +# .qhp file. + +QHG_LOCATION = + +# If the GENERATE_ECLIPSEHELP tag is set to YES, additional index files +# will be generated, which together with the HTML files, form an Eclipse help +# plugin. To install this plugin and make it available under the help contents +# menu in Eclipse, the contents of the directory containing the HTML and XML +# files needs to be copied into the plugins directory of eclipse. The name of +# the directory within the plugins directory should be the same as +# the ECLIPSE_DOC_ID value. After copying Eclipse needs to be restarted before +# the help appears. + +GENERATE_ECLIPSEHELP = NO + +# A unique identifier for the eclipse help plugin. When installing the plugin +# the directory name containing the HTML and XML files should also have +# this name. + +ECLIPSE_DOC_ID = org.doxygen.Project + +# The DISABLE_INDEX tag can be used to turn on/off the condensed index at +# top of each HTML page. The value NO (the default) enables the index and +# the value YES disables it. + +DISABLE_INDEX = NO + +# This tag can be used to set the number of enum values (range [1..20]) +# that doxygen will group on one line in the generated HTML documentation. + +ENUM_VALUES_PER_LINE = 4 + +# The GENERATE_TREEVIEW tag is used to specify whether a tree-like index +# structure should be generated to display hierarchical information. +# If the tag value is set to YES, a side panel will be generated +# containing a tree-like index structure (just like the one that +# is generated for HTML Help). For this to work a browser that supports +# JavaScript, DHTML, CSS and frames is required (i.e. any modern browser). +# Windows users are probably better off using the HTML help feature. + +GENERATE_TREEVIEW = NO + +# By enabling USE_INLINE_TREES, doxygen will generate the Groups, Directories, +# and Class Hierarchy pages using a tree view instead of an ordered list. + +USE_INLINE_TREES = NO + +# If the treeview is enabled (see GENERATE_TREEVIEW) then this tag can be +# used to set the initial width (in pixels) of the frame in which the tree +# is shown. + +TREEVIEW_WIDTH = 250 + +# When the EXT_LINKS_IN_WINDOW option is set to YES doxygen will open +# links to external symbols imported via tag files in a separate window. + +EXT_LINKS_IN_WINDOW = NO + +# Use this tag to change the font size of Latex formulas included +# as images in the HTML documentation. The default is 10. Note that +# when you change the font size after a successful doxygen run you need +# to manually remove any form_*.png images from the HTML output directory +# to force them to be regenerated. + +FORMULA_FONTSIZE = 10 + +# Use the FORMULA_TRANPARENT tag to determine whether or not the images +# generated for formulas are transparent PNGs. Transparent PNGs are +# not supported properly for IE 6.0, but are supported on all modern browsers. +# Note that when changing this option you need to delete any form_*.png files +# in the HTML output before the changes have effect. + +FORMULA_TRANSPARENT = YES + +# When the SEARCHENGINE tag is enabled doxygen will generate a search box +# for the HTML output. The underlying search engine uses javascript +# and DHTML and should work on any modern browser. Note that when using +# HTML help (GENERATE_HTMLHELP), Qt help (GENERATE_QHP), or docsets +# (GENERATE_DOCSET) there is already a search function so this one should +# typically be disabled. For large projects the javascript based search engine +# can be slow, then enabling SERVER_BASED_SEARCH may provide a better solution. + +SEARCHENGINE = YES + +# When the SERVER_BASED_SEARCH tag is enabled the search engine will be +# implemented using a PHP enabled web server instead of at the web client +# using Javascript. Doxygen will generate the search PHP script and index +# file to put on the web server. The advantage of the server +# based approach is that it scales better to large projects and allows +# full text search. The disadvances is that it is more difficult to setup +# and does not have live searching capabilities. + +SERVER_BASED_SEARCH = NO + +#--------------------------------------------------------------------------- +# configuration options related to the LaTeX output +#--------------------------------------------------------------------------- + +# If the GENERATE_LATEX tag is set to YES (the default) Doxygen will +# generate Latex output. + +GENERATE_LATEX = NO + +# The LATEX_OUTPUT tag is used to specify where the LaTeX docs will be put. +# If a relative path is entered the value of OUTPUT_DIRECTORY will be +# put in front of it. If left blank `latex' will be used as the default path. + +LATEX_OUTPUT = latex + +# The LATEX_CMD_NAME tag can be used to specify the LaTeX command name to be +# invoked. If left blank `latex' will be used as the default command name. +# Note that when enabling USE_PDFLATEX this option is only used for +# generating bitmaps for formulas in the HTML output, but not in the +# Makefile that is written to the output directory. + +LATEX_CMD_NAME = latex + +# The MAKEINDEX_CMD_NAME tag can be used to specify the command name to +# generate index for LaTeX. If left blank `makeindex' will be used as the +# default command name. + +MAKEINDEX_CMD_NAME = makeindex + +# If the COMPACT_LATEX tag is set to YES Doxygen generates more compact +# LaTeX documents. This may be useful for small projects and may help to +# save some trees in general. + +COMPACT_LATEX = NO + +# The PAPER_TYPE tag can be used to set the paper type that is used +# by the printer. Possible values are: a4, a4wide, letter, legal and +# executive. If left blank a4wide will be used. + +PAPER_TYPE = a4wide + +# The EXTRA_PACKAGES tag can be to specify one or more names of LaTeX +# packages that should be included in the LaTeX output. + +EXTRA_PACKAGES = + +# The LATEX_HEADER tag can be used to specify a personal LaTeX header for +# the generated latex document. The header should contain everything until +# the first chapter. If it is left blank doxygen will generate a +# standard header. Notice: only use this tag if you know what you are doing! + +LATEX_HEADER = + +# If the PDF_HYPERLINKS tag is set to YES, the LaTeX that is generated +# is prepared for conversion to pdf (using ps2pdf). The pdf file will +# contain links (just like the HTML output) instead of page references +# This makes the output suitable for online browsing using a pdf viewer. + +PDF_HYPERLINKS = YES + +# If the USE_PDFLATEX tag is set to YES, pdflatex will be used instead of +# plain latex in the generated Makefile. Set this option to YES to get a +# higher quality PDF documentation. + +USE_PDFLATEX = YES + +# If the LATEX_BATCHMODE tag is set to YES, doxygen will add the \\batchmode. +# command to the generated LaTeX files. This will instruct LaTeX to keep +# running if errors occur, instead of asking the user for help. +# This option is also used when generating formulas in HTML. + +LATEX_BATCHMODE = NO + +# If LATEX_HIDE_INDICES is set to YES then doxygen will not +# include the index chapters (such as File Index, Compound Index, etc.) +# in the output. + +LATEX_HIDE_INDICES = NO + +# If LATEX_SOURCE_CODE is set to YES then doxygen will include +# source code with syntax highlighting in the LaTeX output. +# Note that which sources are shown also depends on other settings +# such as SOURCE_BROWSER. + +LATEX_SOURCE_CODE = NO + +#--------------------------------------------------------------------------- +# configuration options related to the RTF output +#--------------------------------------------------------------------------- + +# If the GENERATE_RTF tag is set to YES Doxygen will generate RTF output +# The RTF output is optimized for Word 97 and may not look very pretty with +# other RTF readers or editors. + +GENERATE_RTF = NO + +# The RTF_OUTPUT tag is used to specify where the RTF docs will be put. +# If a relative path is entered the value of OUTPUT_DIRECTORY will be +# put in front of it. If left blank `rtf' will be used as the default path. + +RTF_OUTPUT = rtf + +# If the COMPACT_RTF tag is set to YES Doxygen generates more compact +# RTF documents. This may be useful for small projects and may help to +# save some trees in general. + +COMPACT_RTF = NO + +# If the RTF_HYPERLINKS tag is set to YES, the RTF that is generated +# will contain hyperlink fields. The RTF file will +# contain links (just like the HTML output) instead of page references. +# This makes the output suitable for online browsing using WORD or other +# programs which support those fields. +# Note: wordpad (write) and others do not support links. + +RTF_HYPERLINKS = NO + +# Load stylesheet definitions from file. Syntax is similar to doxygen's +# config file, i.e. a series of assignments. You only have to provide +# replacements, missing definitions are set to their default value. + +RTF_STYLESHEET_FILE = + +# Set optional variables used in the generation of an rtf document. +# Syntax is similar to doxygen's config file. + +RTF_EXTENSIONS_FILE = + +#--------------------------------------------------------------------------- +# configuration options related to the man page output +#--------------------------------------------------------------------------- + +# If the GENERATE_MAN tag is set to YES (the default) Doxygen will +# generate man pages + +GENERATE_MAN = NO + +# The MAN_OUTPUT tag is used to specify where the man pages will be put. +# If a relative path is entered the value of OUTPUT_DIRECTORY will be +# put in front of it. If left blank `man' will be used as the default path. + +MAN_OUTPUT = man + +# The MAN_EXTENSION tag determines the extension that is added to +# the generated man pages (default is the subroutine's section .3) + +MAN_EXTENSION = .3 + +# If the MAN_LINKS tag is set to YES and Doxygen generates man output, +# then it will generate one additional man file for each entity +# documented in the real man page(s). These additional files +# only source the real man page, but without them the man command +# would be unable to find the correct page. The default is NO. + +MAN_LINKS = NO + +#--------------------------------------------------------------------------- +# configuration options related to the XML output +#--------------------------------------------------------------------------- + +# If the GENERATE_XML tag is set to YES Doxygen will +# generate an XML file that captures the structure of +# the code including all documentation. + +GENERATE_XML = NO + +# The XML_OUTPUT tag is used to specify where the XML pages will be put. +# If a relative path is entered the value of OUTPUT_DIRECTORY will be +# put in front of it. If left blank `xml' will be used as the default path. + +XML_OUTPUT = xml + +# The XML_SCHEMA tag can be used to specify an XML schema, +# which can be used by a validating XML parser to check the +# syntax of the XML files. + +XML_SCHEMA = + +# The XML_DTD tag can be used to specify an XML DTD, +# which can be used by a validating XML parser to check the +# syntax of the XML files. + +XML_DTD = + +# If the XML_PROGRAMLISTING tag is set to YES Doxygen will +# dump the program listings (including syntax highlighting +# and cross-referencing information) to the XML output. Note that +# enabling this will significantly increase the size of the XML output. + +XML_PROGRAMLISTING = YES + +#--------------------------------------------------------------------------- +# configuration options for the AutoGen Definitions output +#--------------------------------------------------------------------------- + +# If the GENERATE_AUTOGEN_DEF tag is set to YES Doxygen will +# generate an AutoGen Definitions (see autogen.sf.net) file +# that captures the structure of the code including all +# documentation. Note that this feature is still experimental +# and incomplete at the moment. + +GENERATE_AUTOGEN_DEF = NO + +#--------------------------------------------------------------------------- +# configuration options related to the Perl module output +#--------------------------------------------------------------------------- + +# If the GENERATE_PERLMOD tag is set to YES Doxygen will +# generate a Perl module file that captures the structure of +# the code including all documentation. Note that this +# feature is still experimental and incomplete at the +# moment. + +GENERATE_PERLMOD = NO + +# If the PERLMOD_LATEX tag is set to YES Doxygen will generate +# the necessary Makefile rules, Perl scripts and LaTeX code to be able +# to generate PDF and DVI output from the Perl module output. + +PERLMOD_LATEX = NO + +# If the PERLMOD_PRETTY tag is set to YES the Perl module output will be +# nicely formatted so it can be parsed by a human reader. +# This is useful +# if you want to understand what is going on. +# On the other hand, if this +# tag is set to NO the size of the Perl module output will be much smaller +# and Perl will parse it just the same. + +PERLMOD_PRETTY = YES + +# The names of the make variables in the generated doxyrules.make file +# are prefixed with the string contained in PERLMOD_MAKEVAR_PREFIX. +# This is useful so different doxyrules.make files included by the same +# Makefile don't overwrite each other's variables. + +PERLMOD_MAKEVAR_PREFIX = + +#--------------------------------------------------------------------------- +# Configuration options related to the preprocessor +#--------------------------------------------------------------------------- + +# If the ENABLE_PREPROCESSING tag is set to YES (the default) Doxygen will +# evaluate all C-preprocessor directives found in the sources and include +# files. + +ENABLE_PREPROCESSING = YES + +# If the MACRO_EXPANSION tag is set to YES Doxygen will expand all macro +# names in the source code. If set to NO (the default) only conditional +# compilation will be performed. Macro expansion can be done in a controlled +# way by setting EXPAND_ONLY_PREDEF to YES. + +MACRO_EXPANSION = NO + +# If the EXPAND_ONLY_PREDEF and MACRO_EXPANSION tags are both set to YES +# then the macro expansion is limited to the macros specified with the +# PREDEFINED and EXPAND_AS_DEFINED tags. + +EXPAND_ONLY_PREDEF = NO + +# If the SEARCH_INCLUDES tag is set to YES (the default) the includes files +# in the INCLUDE_PATH (see below) will be search if a #include is found. + +SEARCH_INCLUDES = YES + +# The INCLUDE_PATH tag can be used to specify one or more directories that +# contain include files that are not input files but should be processed by +# the preprocessor. + +INCLUDE_PATH = + +# You can use the INCLUDE_FILE_PATTERNS tag to specify one or more wildcard +# patterns (like *.h and *.hpp) to filter out the header-files in the +# directories. If left blank, the patterns specified with FILE_PATTERNS will +# be used. + +INCLUDE_FILE_PATTERNS = + +# The PREDEFINED tag can be used to specify one or more macro names that +# are defined before the preprocessor is started (similar to the -D option of +# gcc). The argument of the tag is a list of macros of the form: name +# or name=definition (no spaces). If the definition and the = are +# omitted =1 is assumed. To prevent a macro definition from being +# undefined via #undef or recursively expanded use the := operator +# instead of the = operator. + +PREDEFINED = "TINS_IS_CXX11=1" \ + "TINS_HAVE_WPA2_CALLBACKS=1" \ + "TINS_HAVE_DOT11=1" + +# If the MACRO_EXPANSION and EXPAND_ONLY_PREDEF tags are set to YES then +# this tag can be used to specify a list of macro names that should be expanded. +# The macro definition that is found in the sources will be used. +# Use the PREDEFINED tag if you want to use a different macro definition. + +EXPAND_AS_DEFINED = + +# If the SKIP_FUNCTION_MACROS tag is set to YES (the default) then +# doxygen's preprocessor will remove all function-like macros that are alone +# on a line, have an all uppercase name, and do not end with a semicolon. Such +# function macros are typically used for boiler-plate code, and will confuse +# the parser if not removed. + +SKIP_FUNCTION_MACROS = YES + +#--------------------------------------------------------------------------- +# Configuration::additions related to external references +#--------------------------------------------------------------------------- + +# The TAGFILES option can be used to specify one or more tagfiles. +# Optionally an initial location of the external documentation +# can be added for each tagfile. The format of a tag file without +# this location is as follows: +# +# TAGFILES = file1 file2 ... +# Adding location for the tag files is done as follows: +# +# TAGFILES = file1=loc1 "file2 = loc2" ... +# where "loc1" and "loc2" can be relative or absolute paths or +# URLs. If a location is present for each tag, the installdox tool +# does not have to be run to correct the links. +# Note that each tag file must have a unique name +# (where the name does NOT include the path) +# If a tag file is not located in the directory in which doxygen +# is run, you must also specify the path to the tagfile here. + +TAGFILES = + +# When a file name is specified after GENERATE_TAGFILE, doxygen will create +# a tag file that is based on the input files it reads. + +GENERATE_TAGFILE = + +# If the ALLEXTERNALS tag is set to YES all external classes will be listed +# in the class index. If set to NO only the inherited external classes +# will be listed. + +ALLEXTERNALS = NO + +# If the EXTERNAL_GROUPS tag is set to YES all external groups will be listed +# in the modules index. If set to NO, only the current project's groups will +# be listed. + +EXTERNAL_GROUPS = YES + +# The PERL_PATH should be the absolute path and name of the perl script +# interpreter (i.e. the result of `which perl'). + +PERL_PATH = /usr/bin/perl + +#--------------------------------------------------------------------------- +# Configuration options related to the dot tool +#--------------------------------------------------------------------------- + +# If the CLASS_DIAGRAMS tag is set to YES (the default) Doxygen will +# generate a inheritance diagram (in HTML, RTF and LaTeX) for classes with base +# or super classes. Setting the tag to NO turns the diagrams off. Note that +# this option is superseded by the HAVE_DOT option below. This is only a +# fallback. It is recommended to install and use dot, since it yields more +# powerful graphs. + +CLASS_DIAGRAMS = YES + +# You can define message sequence charts within doxygen comments using the \msc +# command. Doxygen will then run the mscgen tool (see +# http://www.mcternan.me.uk/mscgen/) to produce the chart and insert it in the +# documentation. The MSCGEN_PATH tag allows you to specify the directory where +# the mscgen tool resides. If left empty the tool is assumed to be found in the +# default search path. + +MSCGEN_PATH = + +# If set to YES, the inheritance and collaboration graphs will hide +# inheritance and usage relations if the target is undocumented +# or is not a class. + +HIDE_UNDOC_RELATIONS = YES + +# If you set the HAVE_DOT tag to YES then doxygen will assume the dot tool is +# available from the path. This tool is part of Graphviz, a graph visualization +# toolkit from AT&T and Lucent Bell Labs. The other options in this section +# have no effect if this option is set to NO (the default) + +HAVE_DOT = NO + +# The DOT_NUM_THREADS specifies the number of dot invocations doxygen is +# allowed to run in parallel. When set to 0 (the default) doxygen will +# base this on the number of processors available in the system. You can set it +# explicitly to a value larger than 0 to get control over the balance +# between CPU load and processing speed. + +DOT_NUM_THREADS = 0 + +# By default doxygen will write a font called FreeSans.ttf to the output +# directory and reference it in all dot files that doxygen generates. This +# font does not include all possible unicode characters however, so when you need +# these (or just want a differently looking font) you can specify the font name +# using DOT_FONTNAME. You need need to make sure dot is able to find the font, +# which can be done by putting it in a standard location or by setting the +# DOTFONTPATH environment variable or by setting DOT_FONTPATH to the directory +# containing the font. + +DOT_FONTNAME = FreeSans.ttf + +# The DOT_FONTSIZE tag can be used to set the size of the font of dot graphs. +# The default size is 10pt. + +DOT_FONTSIZE = 10 + +# By default doxygen will tell dot to use the output directory to look for the +# FreeSans.ttf font (which doxygen will put there itself). If you specify a +# different font using DOT_FONTNAME you can set the path where dot +# can find it using this tag. + +DOT_FONTPATH = + +# If the CLASS_GRAPH and HAVE_DOT tags are set to YES then doxygen +# will generate a graph for each documented class showing the direct and +# indirect inheritance relations. Setting this tag to YES will force the +# the CLASS_DIAGRAMS tag to NO. + +CLASS_GRAPH = YES + +# If the COLLABORATION_GRAPH and HAVE_DOT tags are set to YES then doxygen +# will generate a graph for each documented class showing the direct and +# indirect implementation dependencies (inheritance, containment, and +# class references variables) of the class with other documented classes. + +COLLABORATION_GRAPH = YES + +# If the GROUP_GRAPHS and HAVE_DOT tags are set to YES then doxygen +# will generate a graph for groups, showing the direct groups dependencies + +GROUP_GRAPHS = YES + +# If the UML_LOOK tag is set to YES doxygen will generate inheritance and +# collaboration diagrams in a style similar to the OMG's Unified Modeling +# Language. + +UML_LOOK = NO + +# If set to YES, the inheritance and collaboration graphs will show the +# relations between templates and their instances. + +TEMPLATE_RELATIONS = NO + +# If the ENABLE_PREPROCESSING, SEARCH_INCLUDES, INCLUDE_GRAPH, and HAVE_DOT +# tags are set to YES then doxygen will generate a graph for each documented +# file showing the direct and indirect include dependencies of the file with +# other documented files. + +INCLUDE_GRAPH = YES + +# If the ENABLE_PREPROCESSING, SEARCH_INCLUDES, INCLUDED_BY_GRAPH, and +# HAVE_DOT tags are set to YES then doxygen will generate a graph for each +# documented header file showing the documented files that directly or +# indirectly include this file. + +INCLUDED_BY_GRAPH = YES + +# If the CALL_GRAPH and HAVE_DOT options are set to YES then +# doxygen will generate a call dependency graph for every global function +# or class method. Note that enabling this option will significantly increase +# the time of a run. So in most cases it will be better to enable call graphs +# for selected functions only using the \callgraph command. + +CALL_GRAPH = NO + +# If the CALLER_GRAPH and HAVE_DOT tags are set to YES then +# doxygen will generate a caller dependency graph for every global function +# or class method. Note that enabling this option will significantly increase +# the time of a run. So in most cases it will be better to enable caller +# graphs for selected functions only using the \callergraph command. + +CALLER_GRAPH = NO + +# If the GRAPHICAL_HIERARCHY and HAVE_DOT tags are set to YES then doxygen +# will graphical hierarchy of all classes instead of a textual one. + +GRAPHICAL_HIERARCHY = YES + +# If the DIRECTORY_GRAPH, SHOW_DIRECTORIES and HAVE_DOT tags are set to YES +# then doxygen will show the dependencies a directory has on other directories +# in a graphical way. The dependency relations are determined by the #include +# relations between the files in the directories. + +DIRECTORY_GRAPH = YES + +# The DOT_IMAGE_FORMAT tag can be used to set the image format of the images +# generated by dot. Possible values are png, jpg, or gif +# If left blank png will be used. + +DOT_IMAGE_FORMAT = png + +# The tag DOT_PATH can be used to specify the path where the dot tool can be +# found. If left blank, it is assumed the dot tool can be found in the path. + +DOT_PATH = + +# The DOTFILE_DIRS tag can be used to specify one or more directories that +# contain dot files that are included in the documentation (see the +# \dotfile command). + +DOTFILE_DIRS = + +# The DOT_GRAPH_MAX_NODES tag can be used to set the maximum number of +# nodes that will be shown in the graph. If the number of nodes in a graph +# becomes larger than this value, doxygen will truncate the graph, which is +# visualized by representing a node as a red box. Note that doxygen if the +# number of direct children of the root node in a graph is already larger than +# DOT_GRAPH_MAX_NODES then the graph will not be shown at all. Also note +# that the size of a graph can be further restricted by MAX_DOT_GRAPH_DEPTH. + +DOT_GRAPH_MAX_NODES = 50 + +# The MAX_DOT_GRAPH_DEPTH tag can be used to set the maximum depth of the +# graphs generated by dot. A depth value of 3 means that only nodes reachable +# from the root by following a path via at most 3 edges will be shown. Nodes +# that lay further from the root node will be omitted. Note that setting this +# option to 1 or 2 may greatly reduce the computation time needed for large +# code bases. Also note that the size of a graph can be further restricted by +# DOT_GRAPH_MAX_NODES. Using a depth of 0 means no depth restriction. + +MAX_DOT_GRAPH_DEPTH = 0 + +# Set the DOT_TRANSPARENT tag to YES to generate images with a transparent +# background. This is disabled by default, because dot on Windows does not +# seem to support this out of the box. Warning: Depending on the platform used, +# enabling this option may lead to badly anti-aliased labels on the edges of +# a graph (i.e. they become hard to read). + +DOT_TRANSPARENT = NO + +# Set the DOT_MULTI_TARGETS tag to YES allow dot to generate multiple output +# files in one run (i.e. multiple -o and -T options on the command line). This +# makes dot run faster, but since only newer versions of dot (>1.8.10) +# support this, this feature is disabled by default. + +DOT_MULTI_TARGETS = YES + +# If the GENERATE_LEGEND tag is set to YES (the default) Doxygen will +# generate a legend page explaining the meaning of the various boxes and +# arrows in the dot generated graphs. + +GENERATE_LEGEND = YES + +# If the DOT_CLEANUP tag is set to YES (the default) Doxygen will +# remove the intermediate dot files that are used to generate +# the various graphs. + +DOT_CLEANUP = YES diff --git a/lib/libtins/docs/mainpage.dox b/lib/libtins/docs/mainpage.dox new file mode 100644 index 0000000..3cf936d --- /dev/null +++ b/lib/libtins/docs/mainpage.dox @@ -0,0 +1,29 @@ +/** + * \mainpage Documentation + * + * \section intro_sec Introduction + * + * libtins is a high-level, multiplatform C++ network packet + * sniffing and crafting library. + * + * Its main purpose is to provide the C++ developer an easy, efficient, + * platform and endianess-independent way to create tools which need to + * send, receive and manipulate network packets. + * + * \section install_sec Installation + * + * Please visit the downloads + * section in order to see the installation instructions. + * + * \section tutorials_sec Tutorials + * + * If you want to learn about how the library works, please visit the + * tutorials section. + * + * \section examples_sec Examples + * + * Make sure to visit the + * examples section to see some short but illustrative examples on how + * to send and sniff packets using libtins. + * + */ diff --git a/lib/libtins/examples/CMakeLists.txt b/lib/libtins/examples/CMakeLists.txt new file mode 100644 index 0000000..c035780 --- /dev/null +++ b/lib/libtins/examples/CMakeLists.txt @@ -0,0 +1,81 @@ +FIND_PACKAGE(Threads QUIET) +FIND_PACKAGE(Boost COMPONENTS regex) + +SET(CMAKE_RUNTIME_OUTPUT_DIRECTORY ${CMAKE_BINARY_DIR}/examples) +INCLUDE_DIRECTORIES( + ${CMAKE_CURRENT_SOURCE_DIR}/../include + ${PCAP_INCLUDE_DIR} +) +LINK_LIBRARIES(tins) + +IF(TINS_HAVE_CXX11) + SET(LIBTINS_CXX11_EXAMPLES + arpmonitor + dns_queries + dns_spoof + dns_stats + stream_dump + icmp_responses + interfaces_info + tcp_connection_close + traceroute + wps_detect + ) + IF(Boost_REGEX_FOUND) + SET(LIBTINS_CXX11_EXAMPLES ${LIBTINS_CXX11_EXAMPLES} http_requests) + ELSE() + MESSAGE(WARNING "Disabling HTTP requests example since boost.regex was not found") + ENDIF() +ELSE(TINS_HAVE_CXX11) + MESSAGE(WARNING "Disabling some examples since C++11 support is disabled.") +ENDIF(TINS_HAVE_CXX11) + +ADD_CUSTOM_TARGET( + examples DEPENDS + arpspoofing + ${LIBTINS_CXX11_EXAMPLES} + beacon_display + portscan + route_table + defragmenter +) + +# Make sure we first build libtins +ADD_DEPENDENCIES(examples tins) + +ADD_EXECUTABLE(arpspoofing EXCLUDE_FROM_ALL arpspoofing.cpp) +ADD_EXECUTABLE(route_table EXCLUDE_FROM_ALL route_table.cpp) +ADD_EXECUTABLE(defragmenter EXCLUDE_FROM_ALL defragmenter.cpp) +IF(TINS_HAVE_CXX11) + ADD_EXECUTABLE(arpmonitor EXCLUDE_FROM_ALL arpmonitor.cpp) + ADD_EXECUTABLE(dns_queries EXCLUDE_FROM_ALL dns_queries.cpp) + ADD_EXECUTABLE(dns_spoof EXCLUDE_FROM_ALL dns_spoof.cpp) + ADD_EXECUTABLE(stream_dump EXCLUDE_FROM_ALL stream_dump.cpp) + ADD_EXECUTABLE(icmp_responses EXCLUDE_FROM_ALL icmp_responses.cpp) + ADD_EXECUTABLE(interfaces_info EXCLUDE_FROM_ALL interfaces_info.cpp) + ADD_EXECUTABLE(tcp_connection_close EXCLUDE_FROM_ALL tcp_connection_close.cpp) + ADD_EXECUTABLE(wps_detect EXCLUDE_FROM_ALL wps_detect.cpp) + IF (Boost_REGEX_FOUND) + ADD_EXECUTABLE(http_requests EXCLUDE_FROM_ALL http_requests.cpp) + TARGET_LINK_LIBRARIES(http_requests ${Boost_LIBRARIES}) + ENDIF() +ENDIF(TINS_HAVE_CXX11) + +ADD_EXECUTABLE(beacon_display EXCLUDE_FROM_ALL beacon_display.cpp) + +if(THREADS_FOUND) + IF(TINS_HAVE_CXX11) + ADD_EXECUTABLE(traceroute EXCLUDE_FROM_ALL traceroute.cpp) + ADD_EXECUTABLE(dns_stats EXCLUDE_FROM_ALL dns_stats.cpp) + TARGET_LINK_LIBRARIES(traceroute ${CMAKE_THREAD_LIBS_INIT}) + TARGET_LINK_LIBRARIES(dns_stats ${CMAKE_THREAD_LIBS_INIT}) + ENDIF(TINS_HAVE_CXX11) + IF(WIN32) + MESSAGE(WARNING "Disabling portscan example since it doesn't compile on Windows.") + ELSE() + ADD_EXECUTABLE(portscan EXCLUDE_FROM_ALL portscan.cpp) + TARGET_LINK_LIBRARIES(portscan ${CMAKE_THREAD_LIBS_INIT}) + ENDIF() +ELSE() + MESSAGE(WARNING "Disabling portscan and traceroute examples since pthreads library was not found.") +ENDIF() diff --git a/lib/libtins/examples/arpmonitor.cpp b/lib/libtins/examples/arpmonitor.cpp new file mode 100644 index 0000000..16911a4 --- /dev/null +++ b/lib/libtins/examples/arpmonitor.cpp @@ -0,0 +1,107 @@ +/* + * Copyright (c) 2017, Matias Fontanini + * All rights reserved. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions are + * met: + * + * * Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * * Redistributions in binary form must reproduce the above + * copyright notice, this list of conditions and the following disclaimer + * in the documentation and/or other materials provided with the + * distribution. + * + * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS + * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT + * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR + * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT + * OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, + * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT + * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, + * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY + * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT + * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE + * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + * + */ + +#include +#include +#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); +private: + bool callback(const PDU& pdu); + + map> addresses; +}; + +void arp_monitor::run(Sniffer& sniffer) { + sniffer.sniff_loop( + bind( + &arp_monitor::callback, + this, + std::placeholders::_1 + ) + ); +} + +bool arp_monitor::callback(const PDU& pdu) { + // Retrieve the ARP layer + const ARP& arp = pdu.rfind_pdu(); + // Is it an 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()) { + // We haven't seen this address. Save it. + addresses.insert({ arp.sender_ip_addr(), arp.sender_hw_addr()}); + 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) { + 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[]) { + if(argc != 2) { + cout << "Usage: " <<* argv << " " << endl; + return 1; + } + arp_monitor monitor; + // Sniffer configuration + SnifferConfiguration config; + config.set_promisc_mode(true); + config.set_filter("arp"); + + try { + // Sniff on the provided interface in promiscuous mode + Sniffer sniffer(argv[1], config); + + // Only capture arp packets + monitor.run(sniffer); + } + catch (std::exception& ex) { + std::cerr << "Error: " << ex.what() << std::endl; + } +} diff --git a/lib/libtins/examples/arpspoofing.cpp b/lib/libtins/examples/arpspoofing.cpp new file mode 100644 index 0000000..0378c35 --- /dev/null +++ b/lib/libtins/examples/arpspoofing.cpp @@ -0,0 +1,136 @@ +/* + * Copyright (c) 2017, Matias Fontanini + * All rights reserved. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions are + * met: + * + * * Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * * Redistributions in binary form must reproduce the above + * copyright notice, this list of conditions and the following disclaimer + * in the documentation and/or other materials provided with the + * distribution. + * + * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS + * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT + * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR + * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT + * OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, + * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT + * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, + * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY + * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT + * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE + * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + * + */ + + +#include +#include +#include +#include +#ifdef _WIN32 + #define WIN32_LEAN_AND_MEAN + #include +#else + #include +#endif // _WIN32 +#include +#include +#include +#include +#include + +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) { + PacketSender sender; + EthernetII::address_type gw_hw, victim_hw; + + // Resolves gateway's hardware address. + gw_hw = Utils::resolve_hwaddr(iface, gw, sender); + + // Resolves victim's hardware address. + victim_hw = Utils::resolve_hwaddr(iface, victim, sender); + + // Print out the hw addresses we're using. + cout << " Using gateway hw address: " << gw_hw << "\n"; + cout << " Using victim hw address: " << victim_hw << "\n"; + cout << " Using own hw address: " << info.hw_addr << "\n"; + + /* We tell the gateway that the victim is at out hw address, + * and tell the victim that the gateway is at out hw address */ + ARP gw_arp(gw, victim, gw_hw, info.hw_addr), + victim_arp(victim, gw, victim_hw, info.hw_addr); + // We are "replying" ARP requests + gw_arp.opcode(ARP::REPLY); + victim_arp.opcode(ARP::REPLY); + + /* The packet we'll send to the gateway and victim. + * We include our hw address as the source address + * in ethernet layer, to avoid possible packet dropping + * 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) { + // Just send them once every 5 seconds. + sender.send(to_gw, iface); + sender.send(to_victim, iface); + #ifdef _WIN32 + Sleep(5000); + #else + sleep(5); + #endif + } +} + +int main(int argc, char* argv[]) { + if (argc != 3) { + cout << "Usage: " <<* argv << " " << endl; + return 1; + } + IPv4Address gw, victim; + EthernetII::address_type own_hw; + try { + // Convert dotted-notation ip addresses to integer. + gw = argv[1]; + victim = argv[2]; + } + catch (...) { + cout << "Invalid ip found...\n"; + return 2; + } + + NetworkInterface iface; + NetworkInterface::Info info; + try { + // Get the interface which will be the gateway for our requests. + iface = gw; + // Lookup the interface id. This will be required while forging packets. + // Find the interface hardware and ip address. + info = iface.addresses(); + } + catch (runtime_error& ex) { + cout << ex.what() << endl; + return 3; + } + try { + do_arp_spoofing(iface, gw, victim, info); + } + catch (runtime_error& ex) { + cout << "Runtime error: " << ex.what() << endl; + return 7; + } +} + diff --git a/lib/libtins/examples/beacon_display.cpp b/lib/libtins/examples/beacon_display.cpp new file mode 100644 index 0000000..5d3ccd1 --- /dev/null +++ b/lib/libtins/examples/beacon_display.cpp @@ -0,0 +1,101 @@ +/* + * Copyright (c) 2017, Matias Fontanini + * All rights reserved. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions are + * met: + * + * * Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * * Redistributions in binary form must reproduce the above + * copyright notice, this list of conditions and the following disclaimer + * in the documentation and/or other materials provided with the + * distribution. + * + * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS + * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT + * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR + * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT + * OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, + * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT + * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, + * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY + * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT + * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE + * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + * + */ + +#include +#include +#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 string& iface); +private: + typedef Dot11::address_type address_type; + typedef set ssids_type; + + bool callback(PDU& pdu); + + ssids_type ssids; +}; + +void BeaconSniffer::run(const std::string& iface) { + SnifferConfiguration config; + config.set_promisc_mode(true); + config.set_filter("type mgt subtype beacon"); + config.set_rfmon(true); + Sniffer sniffer(iface, config); + sniffer.sniff_loop(make_sniffer_handler(this, &BeaconSniffer::callback)); +} + +bool BeaconSniffer::callback(PDU& pdu) { + // Get the Dot11 layer + const Dot11Beacon& beacon = pdu.rfind_pdu(); + // All beacons must have from_ds == to_ds == 0 + 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()) { + // First time we encounter this BSSID. + try { + /* If no ssid option is set, then Dot11::ssid will throw + * a std::runtime_error. + */ + string ssid = beacon.ssid(); + // Save it so we don't show it again. + ssids.insert(addr); + // Display the tuple "address - ssid". + cout << addr << " - " << ssid << endl; + } + catch (runtime_error&) { + // No ssid, just ignore it. + } + } + } + return true; +} + +int main(int argc, char* argv[]) { + if (argc != 2) { + cout << "Usage: " <<* argv << " " << endl; + return 1; + } + string interface = argv[1]; + BeaconSniffer sniffer; + sniffer.run(interface); +} diff --git a/lib/libtins/examples/defragmenter.cpp b/lib/libtins/examples/defragmenter.cpp new file mode 100644 index 0000000..6665b89 --- /dev/null +++ b/lib/libtins/examples/defragmenter.cpp @@ -0,0 +1,118 @@ +/* + * Copyright (c) 2017, Matias Fontanini + * All rights reserved. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions are + * met: + * + * * Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * * Redistributions in binary form must reproduce the above + * copyright notice, this list of conditions and the following disclaimer + * in the documentation and/or other materials provided with the + * distribution. + * + * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS + * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT + * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR + * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT + * OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, + * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT + * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, + * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY + * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT + * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE + * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + * + */ + +#include +#include +#include +#include "tins/ip.h" +#include "tins/ip_reassembler.h" +#include "tins/sniffer.h" +#include "tins/packet_writer.h" + +using std::cout; +using std::cerr; +using std::endl; +using std::string; +using std::exception; + +using Tins::IPv4Reassembler; +using Tins::IP; +using Tins::Packet; +using Tins::FileSniffer; +using Tins::PacketWriter; +using Tins::DataLinkType; + +// This example reads packets from a pcap file and writes them to a new file. +// If any IPv4 fragmented packets are found in the input file, then they will +// be reassembled before writing them, so instead of the individual fragments +// it will write the whole packet. + +class Defragmenter { +public: + // Construct the sniffer and the packet writer using the sniffer's + // data link type + Defragmenter(const string& input_file, const string& output_file) + : sniffer_(input_file), + writer_(output_file, (PacketWriter::LinkType)sniffer_.link_type()), + total_reassembled_(0) { + + } + + void run() { + Packet packet; + // Read packets and keep going until there's no more packets to read + while (packet = sniffer_.next_packet()) { + // Try to reassemble the packet + IPv4Reassembler::PacketStatus status = reassembler_.process(*packet.pdu()); + + // If we did reassemble it, increase this counter + if (status == IPv4Reassembler::REASSEMBLED) { + total_reassembled_++; + } + + // Regardless, we'll write it into the output file unless it's fragmented + // (and not yet reassembled) + if (status != IPv4Reassembler::FRAGMENTED) { + writer_.write(packet); + } + } + } + + uint64_t total_packets_reassembled() const { + return total_reassembled_; + } +private: + FileSniffer sniffer_; + IPv4Reassembler reassembler_; + PacketWriter writer_; + uint64_t total_reassembled_; +}; + +int main(int argc, char* argv[]) { + if (argc != 3) { + cout << "Usage: " << argv[0] << " " << endl; + return 1; + } + try { + // Build the defragmented + Defragmenter defragmenter(argv[1], argv[2]); + cout << "Processing " << argv[1] << endl; + cout << "Writing results to " << argv[2] << endl; + + // Run! + defragmenter.run(); + cout << "Done" << endl; + cout << "Reassembled: " << defragmenter.total_packets_reassembled() + << " packet(s)" << endl; + } + catch (exception& ex) { + cerr << "Error: " << ex.what() << endl; + } +} + diff --git a/lib/libtins/examples/dns_queries.cpp b/lib/libtins/examples/dns_queries.cpp new file mode 100644 index 0000000..5445254 --- /dev/null +++ b/lib/libtins/examples/dns_queries.cpp @@ -0,0 +1,68 @@ +/* + * Copyright (c) 2017, Matias Fontanini + * All rights reserved. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions are + * met: + * + * * Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * * Redistributions in binary form must reproduce the above + * copyright notice, this list of conditions and the following disclaimer + * in the documentation and/or other materials provided with the + * distribution. + * + * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS + * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT + * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR + * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT + * OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, + * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT + * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, + * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY + * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT + * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE + * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + * + */ + +#include +#include + +using std::cout; +using std::endl; + +using namespace Tins; + +bool callback(const PDU& pdu) { + // The packet probably looks like this: + // + // EthernetII / IP / UDP / RawPDU + // + // So we retrieve the RawPDU layer, and construct a + // DNS PDU using its contents. + DNS dns = pdu.rfind_pdu().to(); + + // Retrieve the queries and print the domain name: + for (const auto& query : dns.queries()) { + cout << query.dname() << std::endl; + } + return true; +} + +int main(int argc, char* argv[]) { + if(argc != 2) { + cout << "Usage: " <<* argv << " " << endl; + return 1; + } + // Sniff on the provided interface in promiscuous mode + SnifferConfiguration config; + config.set_promisc_mode(true); + // Only capture udp packets sent to port 53 + config.set_filter("udp and dst port 53"); + Sniffer sniffer(argv[1], config); + + // Start the capture + sniffer.sniff_loop(callback); +} diff --git a/lib/libtins/examples/dns_spoof.cpp b/lib/libtins/examples/dns_spoof.cpp new file mode 100644 index 0000000..96b743a --- /dev/null +++ b/lib/libtins/examples/dns_spoof.cpp @@ -0,0 +1,107 @@ +/* + * Copyright (c) 2017, Matias Fontanini + * All rights reserved. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions are + * met: + * + * * Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * * Redistributions in binary form must reproduce the above + * copyright notice, this list of conditions and the following disclaimer + * in the documentation and/or other materials provided with the + * distribution. + * + * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS + * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT + * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR + * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT + * OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, + * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT + * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, + * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY + * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT + * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE + * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + * + */ + +#include +#include + +using std::cout; +using std::endl; + +using namespace Tins; + +PacketSender sender; + +bool callback(const PDU& pdu) { + // The packet probably looks like this: + // + // EthernetII / IP / UDP / RawPDU + // + // So we retrieve each layer, and construct a + // DNS PDU from the RawPDU layer contents. + EthernetII eth = pdu.rfind_pdu(); + IP ip = eth.rfind_pdu(); + UDP udp = ip.rfind_pdu(); + DNS dns = udp.rfind_pdu().to(); + + // Is it a 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.query_type() == DNS::A) { + // Here's one! Let's add an answer. + dns.add_answer( + DNS::resource( + query.dname(), + "127.0.0.1", + DNS::A, + query.query_class(), + // 777 is just a random TTL + 777 + ) + ); + } + } + // Have we added some answers? + 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; + // Send it! + sender.send(pkt); + } + } + return true; +} + +int main(int argc, char* argv[]) { + if(argc != 2) { + cout << "Usage: " <<* argv << " " << endl; + return 1; + } + // Sniff on the provided interface in promiscuous mode + SnifferConfiguration config; + config.set_promisc_mode(true); + // Use immediate mode so we get the packets as fast as we can + config.set_immediate_mode(true); + // Only capture udp packets sent to port 53 + config.set_filter("udp and dst port 53"); + Sniffer sniffer(argv[1], config); + + // All packets will be sent through the provided interface + sender.default_interface(argv[1]); + + // Start the capture + sniffer.sniff_loop(callback); +} diff --git a/lib/libtins/examples/dns_stats.cpp b/lib/libtins/examples/dns_stats.cpp new file mode 100644 index 0000000..c08111f --- /dev/null +++ b/lib/libtins/examples/dns_stats.cpp @@ -0,0 +1,218 @@ +/* + * Copyright (c) 2017, Matias Fontanini + * All rights reserved. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions are + * met: + * + * * Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * * Redistributions in binary form must reproduce the above + * copyright notice, this list of conditions and the following disclaimer + * in the documentation and/or other materials provided with the + * distribution. + * + * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS + * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT + * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR + * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT + * OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, + * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT + * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, + * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY + * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT + * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE + * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + * + */ + +#ifdef _WIN32 + #define NOMINMAX +#endif // _WIN32 + +// Fix for gcc 4.6 +#define _GLIBCXX_USE_NANOSLEEP + +#include +#include +#include +#include +#include +#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 +// represented using the Duration template parameter. +template +class statistics { +public: + typedef Duration duration_type; + typedef lock_guard locker_type; + + struct information { + duration_type average, worst; + size_t count; + }; + + statistics() + : m_duration(), m_worst(duration_type::min()), m_count() { + + } + + void add_response_time(const duration_type& duration) { + locker_type _(m_lock); + m_duration += duration; + m_count++; + m_worst = max(m_worst, duration); + } + + information get_information() const { + locker_type _(m_lock); + if(m_count == 0) { + return { }; + } + else { + return { m_duration / m_count, m_worst, m_count }; + } + }; +private: + duration_type m_duration, m_worst; + size_t m_count; + 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 +// weren't answered. +class dns_monitor { +public: + // The response times are measured in milliseconds + typedef milliseconds duration_type; + // The statistics type used. + typedef statistics statistics_type; + + void run(BaseSniffer& sniffer); + const statistics_type& stats() const { + return m_stats; + } +private: + typedef tuple packet_info; + typedef system_clock clock_type; + typedef clock_type::time_point time_point_type; + + bool callback(const PDU& pdu); + static packet_info make_packet_info(const PDU& pdu, const DNS& dns); + + statistics_type m_stats; + map m_packet_info; +}; + +void dns_monitor::run(BaseSniffer& sniffer) { + sniffer.sniff_loop( + bind( + &dns_monitor::callback, + this, + std::placeholders::_1 + ) + ); +} + +bool dns_monitor::callback(const PDU& pdu) { + auto now = clock_type::now(); + 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) { + m_packet_info.insert( + std::make_pair(info, now) + ); + } + 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()) { + // We found the query, let's add the response time to the + // statistics object. + m_stats.add_response_time( + duration_cast(now - iter->second) + ); + // Forget about the query. + m_packet_info.erase(iter); + } + } + return true; +} + +// It is required that we can identify packets sent and received that +// hold the same DNS id as belonging to the same query. +// +// This function retrieves a tuple (addr, addr, id) that will achieve it. +auto dns_monitor::make_packet_info(const PDU& pdu, const DNS& dns) -> packet_info { + const auto& ip = pdu.rfind_pdu(); + return make_tuple( + // smallest address first + min(ip.src_addr(), ip.dst_addr()), + // largest address second + max(ip.src_addr(), ip.dst_addr()), + dns.id() + ); +} + +int main(int argc, char* argv[]) { + string iface; + if (argc == 2) { + // Use the provided interface + iface = argv[1]; + } + else { + // Use the default interface + iface = NetworkInterface::default_interface().name(); + } + try { + SnifferConfiguration config; + config.set_promisc_mode(true); + config.set_filter("udp and port 53"); + Sniffer sniffer(iface, config); + dns_monitor monitor; + thread thread( + [&]() { + monitor.run(sniffer); + } + ); + while (true) { + auto info = monitor.stats().get_information(); + cout << "\rAverage " << info.average.count() + << "ms. Worst: " << info.worst.count() << "ms. Count: " + << info.count << " "; + cout.flush(); + sleep_for(seconds(1)); + } + } + catch (exception& ex) { + cout << "[-] Error: " << ex.what() << endl; + } +} diff --git a/lib/libtins/examples/http_requests.cpp b/lib/libtins/examples/http_requests.cpp new file mode 100644 index 0000000..9597220 --- /dev/null +++ b/lib/libtins/examples/http_requests.cpp @@ -0,0 +1,147 @@ +/* + * Copyright (c) 2017, Matias Fontanini + * All rights reserved. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions are + * met: + * + * * Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * * Redistributions in binary form must reproduce the above + * copyright notice, this list of conditions and the following disclaimer + * in the documentation and/or other materials provided with the + * distribution. + * + * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS + * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT + * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR + * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT + * OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, + * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT + * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, + * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY + * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT + * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE + * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + * + */ + +#include +#include +#include +#include +#include "tins/tcp_ip/stream_follower.h" +#include "tins/sniffer.h" + +using std::string; +using std::cout; +using std::cerr; +using std::endl; +using std::exception; + +using boost::regex; +using boost::match_results; + +using Tins::PDU; +using Tins::Sniffer; +using Tins::SnifferConfiguration; +using Tins::TCPIP::Stream; +using Tins::TCPIP::StreamFollower; + +// This example captures and follows TCP streams seen on port 80. It will +// wait until both the client and server send data and then apply a regex +// to both payloads, extrating some information and printing it. + +// Don't buffer more than 3kb of data in either request/response +const size_t MAX_PAYLOAD = 3 * 1024; +// The regex to be applied on the request. This will extract the HTTP +// method being used, the request's path and the Host header value. +regex request_regex("([\\w]+) ([^ ]+).+\r\nHost: ([\\d\\w\\.-]+)\r\n"); +// The regex to be applied on the response. This finds the response code. +regex response_regex("HTTP/[^ ]+ ([\\d]+)"); + +void on_server_data(Stream& stream) { + match_results client_match; + match_results server_match; + const Stream::payload_type& client_payload = stream.client_payload(); + const Stream::payload_type& server_payload = stream.server_payload(); + // Run the regexes on client/server payloads + bool valid = regex_search(server_payload.begin(), server_payload.end(), + server_match, response_regex) && + regex_search(client_payload.begin(), client_payload.end(), + client_match, request_regex); + // If we matched both the client and the server regexes + if (valid) { + // Extract all fields + string method = string(client_match[1].first, client_match[1].second); + string url = string(client_match[2].first, client_match[2].second); + string host = string(client_match[3].first, client_match[3].second); + string response_code = string(server_match[1].first, server_match[1].second); + // Now print them + cout << method << " http://" << host << url << " -> " << response_code << endl; + + // Once we've seen the first request on this stream, ignore it + stream.ignore_client_data(); + stream.ignore_server_data(); + } + + // Just in case the server returns invalid data, stop at 3kb + if (stream.server_payload().size() > MAX_PAYLOAD) { + stream.ignore_server_data(); + } +} + +void on_client_data(Stream& stream) { + // Don't hold more than 3kb of data from the client's flow + if (stream.client_payload().size() > MAX_PAYLOAD) { + stream.ignore_client_data(); + } +} + +void on_new_connection(Stream& stream) { + stream.client_data_callback(&on_client_data); + stream.server_data_callback(&on_server_data); + // Don't automatically cleanup the stream's data, as we'll manage + // the buffer ourselves and let it grow until we see a full request + // and response + stream.auto_cleanup_payloads(false); +} + +int main(int argc, char* argv[]) { + if (argc != 2) { + cout << "Usage: " << argv[0] << " " << endl; + return 1; + } + + try { + // Construct the sniffer configuration object + SnifferConfiguration config; + // Get packets as quickly as possible + config.set_immediate_mode(true); + // Only capture TCP traffic sent from/to port 80 + config.set_filter("tcp port 80"); + // Construct the sniffer we'll use + Sniffer sniffer(argv[1], config); + + cout << "Starting capture on interface " << argv[1] << endl; + + // Now construct the stream follower + StreamFollower follower; + // We just need to specify the callback to be executed when a new + // stream is captured. In this stream, you should define which callbacks + // will be executed whenever new data is sent on that stream + // (see on_new_connection) + follower.new_stream_callback(&on_new_connection); + // Now start capturing. Every time there's a new packet, call + // follower.process_packet + sniffer.sniff_loop([&](PDU& packet) { + follower.process_packet(packet); + return true; + }); + } + catch (exception& ex) { + cerr << "Error: " << ex.what() << endl; + return 1; + } +} diff --git a/lib/libtins/examples/icmp_responses.cpp b/lib/libtins/examples/icmp_responses.cpp new file mode 100644 index 0000000..aa65a88 --- /dev/null +++ b/lib/libtins/examples/icmp_responses.cpp @@ -0,0 +1,140 @@ +/* + * Copyright (c) 2015, Matias Fontanini + * All rights reserved. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions are + * met: + * + * * Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * * Redistributions in binary form must reproduce the above + * copyright notice, this list of conditions and the following disclaimer + * in the documentation and/or other materials provided with the + * distribution. + * + * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS + * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT + * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR + * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT + * OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, + * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT + * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, + * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY + * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT + * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE + * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + * + */ + +#include +#include +#include +#include +#include + +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 +// and will respond with ICMP error packets whenever a packet is captured. +// The response mechanism is pretty naive as it generates a packet which +// 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) { + + } + + // 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, 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); + } + + // 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"); + + // 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; + } + + 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; + } +} \ No newline at end of file diff --git a/lib/libtins/examples/interfaces_info.cpp b/lib/libtins/examples/interfaces_info.cpp new file mode 100644 index 0000000..9c6746d --- /dev/null +++ b/lib/libtins/examples/interfaces_info.cpp @@ -0,0 +1,87 @@ +/* + * Copyright (c) 2015, Matias Fontanini + * All rights reserved. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions are + * met: + * + * * Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * * Redistributions in binary form must reproduce the above + * copyright notice, this list of conditions and the following disclaimer + * in the documentation and/or other materials provided with the + * distribution. + * + * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS + * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT + * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR + * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT + * OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, + * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT + * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, + * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY + * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT + * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE + * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + * + */ + +#include +#include +#include +#include + +using std::cout; +using std::wcout; +using std::endl; +using std::string; +using std::ostringstream; + +using namespace Tins; + +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(); + + // "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; + + #ifdef _WIN32 + // If this is running on Windows, also print the friendly name + wcout << " (" << iface.friendly_name() << ")"; + #endif // _WIN32 + cout << ": " << endl; + + string ipv6_string; + if (info.ipv6_addrs.empty()) { + ipv6_string = "(none)"; + } + else { + ostringstream oss; + for (size_t i = 0; i < info.ipv6_addrs.size(); ++i) { + const NetworkInterface::IPv6Prefix& prefix = info.ipv6_addrs[i]; + if (i > 0) { + oss << ", "; + } + oss << prefix.address << "/" << prefix.prefix_length; + } + ipv6_string = oss.str(); + } + cout << " HW address: " << info.hw_addr << endl + << " IP address: " << info.ip_addr << endl + << " IPv6 addresses: " << ipv6_string << 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/lib/libtins/examples/portscan.cpp b/lib/libtins/examples/portscan.cpp new file mode 100644 index 0000000..df37711 --- /dev/null +++ b/lib/libtins/examples/portscan.cpp @@ -0,0 +1,195 @@ +/* + * Copyright (c) 2017, Matias Fontanini + * All rights reserved. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions are + * met: + * + * * Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * * Redistributions in binary form must reproduce the above + * copyright notice, this list of conditions and the following disclaimer + * in the documentation and/or other materials provided with the + * distribution. + * + * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS + * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT + * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR + * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT + * OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, + * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT + * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, + * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY + * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT + * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE + * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + * + */ + +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#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 Tins; + +typedef pair sniffer_data; + +class Scanner { +public: + 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 launch_sniffer(); + + NetworkInterface iface; + IPv4Address host_to_scan; + set ports_to_scan; + Sniffer sniffer; +}; + +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) { + ports_to_scan.insert(atoi(ports[i].c_str())); + } +} + +void* Scanner::thread_proc(void* param) { + Scanner* data = (Scanner*)param; + data->launch_sniffer(); + return 0; +} + +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) { + // Find the layers we want. + 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) { + // Ok, it's a TCP PDU. Is RST flag on? Then port is closed. + if(tcp.get_flag(TCP::RST)) { + // This indicates we should stop sniffing. + if(tcp.get_flag(TCP::SYN)) + return false; + cout << "Port: " << setw(5) << tcp.sport() << " closed\n"; + } + // Is SYN flag on? Then port is open! + else if(tcp.has_flags(TCP::SYN | TCP::ACK)) { + cout << "Port: " << setw(5) << tcp.sport() << " open\n"; + } + } + return true; +} + +void Scanner::run() { + pthread_t thread; + // Launch our sniff thread. + pthread_create(&thread, 0, &Scanner::thread_proc, this); + // Start sending SYNs to port. + send_syns(iface, host_to_scan); + + // Wait for our sniffer. + 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) { + // 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(); + // 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) { + // Set the new port and send the packet! + tcp.dport(*it); + sender.send(ip); + } + // Wait 1 second. + sleep(1); + /* Special packet to indicate that we're done. This will be sniffed + * by our function, which will in turn return false. + */ + tcp.set_flag(TCP::RST, 1); + tcp.sport(*ports_to_scan.begin()); + // Pretend we're the scanned host... + ip.src_addr(dest_ip); + // We use an ethernet pdu, otherwise the kernel will drop it. + EthernetII eth = EthernetII(info.hw_addr, info.hw_addr) / ip; + sender.send(eth, iface); +} + +void scan(int argc, char* argv[]) { + IPv4Address ip(argv[1]); + // Resolve the interface which will be our gateway + NetworkInterface iface(ip); + cout << "Sniffing on interface: " << iface.name() << endl; + + // Consume arguments + argv += 2; + argc -= 2; + Scanner scanner(iface, ip, vector(argv, argv + (argc))); + scanner.run(); +} + +int main(int argc, char* argv[]) { + if (argc < 3) { + cout << "Usage: " <<* argv << " [port2] [port3]" << endl; + return 1; + } + try { + scan(argc, argv); + } + catch(runtime_error& ex) { + cout << "Error - " << ex.what() << endl; + } +} diff --git a/lib/libtins/examples/route_table.cpp b/lib/libtins/examples/route_table.cpp new file mode 100644 index 0000000..f6c58ce --- /dev/null +++ b/lib/libtins/examples/route_table.cpp @@ -0,0 +1,69 @@ +/* + * Copyright (c) 2015, Matias Fontanini + * All rights reserved. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions are + * met: + * + * * Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * * Redistributions in binary form must reproduce the above + * copyright notice, this list of conditions and the following disclaimer + * in the documentation and/or other materials provided with the + * distribution. + * + * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS + * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT + * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR + * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT + * OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, + * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT + * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, + * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY + * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT + * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE + * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + * + */ + +#include +#include +#include +#include + +using std::cout; +using std::endl; +using std::setw; +using std::vector; + +using namespace Tins; + +int main() { + vector v4_entries = Utils::route_entries(); + cout << "IPv4 route table entries: " << endl + << "========================= " << endl; + for (size_t i = 0; i < v4_entries.size(); ++i) { + cout << "Entry " << setw(2) << i << ": " << endl + << "Interface: " << v4_entries[i].interface << endl + << "Destination: " << v4_entries[i].destination << endl + << "Gateway: " << v4_entries[i].gateway << endl + << "Genmask: " << v4_entries[i].mask << endl + << "Metric: " << v4_entries[i].metric << endl << endl; + } + + vector v6_entries = Utils::route6_entries(); + if (!v6_entries.empty()) { + cout << endl + << "IPv6 route table entries: " << endl + << "========================= " << endl; + for (size_t i = 0; i < v6_entries.size(); ++i) { + cout << "Entry " << setw(2) << i << ": " << endl + << "Interface: " << v6_entries[i].interface << endl + << "Destination: " << v6_entries[i].destination << endl + << "Gateway: " << v6_entries[i].gateway << endl + << "Genmask: " << v6_entries[i].mask << endl + << "Metric: " << v6_entries[i].metric << endl << endl; + } + } +} \ No newline at end of file diff --git a/lib/libtins/examples/stream_dump.cpp b/lib/libtins/examples/stream_dump.cpp new file mode 100644 index 0000000..4fe0068 --- /dev/null +++ b/lib/libtins/examples/stream_dump.cpp @@ -0,0 +1,192 @@ +/* + * Copyright (c) 2017, Matias Fontanini + * All rights reserved. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions are + * met: + * + * * Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * * Redistributions in binary form must reproduce the above + * copyright notice, this list of conditions and the following disclaimer + * in the documentation and/or other materials provided with the + * distribution. + * + * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS + * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT + * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR + * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT + * OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, + * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT + * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, + * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY + * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT + * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE + * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + * + */ + +#include +#include +#include "tins/tcp_ip/stream_follower.h" +#include "tins/sniffer.h" +#include "tins/packet.h" +#include "tins/ip_address.h" +#include "tins/ipv6_address.h" + +using std::cout; +using std::cerr; +using std::endl; +using std::bind; +using std::string; +using std::to_string; +using std::ostringstream; +using std::exception; + +using Tins::Sniffer; +using Tins::SnifferConfiguration; +using Tins::PDU; +using Tins::TCPIP::StreamFollower; +using Tins::TCPIP::Stream; + +// This example takes an interface and a port as an argument and +// it listens for TCP streams on the given interface and port. +// It will reassemble TCP streams and show the traffic sent by +// both the client and the server. + +// Convert the client endpoint to a readable string +string client_endpoint(const Stream& stream) { + ostringstream output; + // Use the IPv4 or IPv6 address depending on which protocol the + // connection uses + if (stream.is_v6()) { + output << stream.client_addr_v6(); + } + else { + output << stream.client_addr_v4(); + } + output << ":" << stream.client_port(); + return output.str(); +} + +// Convert the server endpoint to a readable string +string server_endpoint(const Stream& stream) { + ostringstream output; + if (stream.is_v6()) { + output << stream.server_addr_v6(); + } + else { + output << stream.server_addr_v4(); + } + output << ":" << stream.server_port(); + return output.str(); +} + +// Concat both endpoints to get a readable stream identifier +string stream_identifier(const Stream& stream) { + ostringstream output; + output << client_endpoint(stream) << " - " << server_endpoint(stream); + return output.str(); +} + +// Whenever there's new client data on the stream, this callback is executed. +void on_client_data(Stream& stream) { + // Construct a string out of the contents of the client's payload + string data(stream.client_payload().begin(), stream.client_payload().end()); + + // Now print it, prepending some information about the stream + cout << client_endpoint(stream) << " >> " + << server_endpoint(stream) << ": " << endl << data << endl; +} + +// Whenever there's new server data on the stream, this callback is executed. +// This does the same thing as on_client_data +void on_server_data(Stream& stream) { + string data(stream.server_payload().begin(), stream.server_payload().end()); + cout << server_endpoint(stream) << " >> " + << client_endpoint(stream) << ": " << endl << data << endl; +} + +// When a connection is closed, this callback is executed. +void on_connection_closed(Stream& stream) { + cout << "[+] Connection closed: " << stream_identifier(stream) << endl; +} + +// When a new connection is captured, this callback will be executed. +void on_new_connection(Stream& stream) { + if (stream.is_partial_stream()) { + // We found a partial stream. This means this connection/stream had + // been established before we started capturing traffic. + // + // In this case, we need to allow for the stream to catch up, as we + // may have just captured an out of order packet and if we keep waiting + // for the holes to be filled, we may end up waiting forever. + // + // Calling enable_recovery_mode will skip out of order packets that + // fall withing the range of the given window size. + // See Stream::enable_recover_mode for more information + cout << "[+] New connection " << stream_identifier(stream) << endl; + + // Enable recovery mode using a window of 10kb + stream.enable_recovery_mode(10 * 1024); + } + else { + // Print some information about the new connection + cout << "[+] New connection " << stream_identifier(stream) << endl; + } + + // Now configure the callbacks on it. + // First, we want on_client_data to be called every time there's new client data + stream.client_data_callback(&on_client_data); + + // Same thing for server data, but calling on_server_data + stream.server_data_callback(&on_server_data); + + // When the connection is closed, call on_connection_closed + stream.stream_closed_callback(&on_connection_closed); +} + +int main(int argc, char* argv[]) { + if (argc != 3) { + cout << "Usage: " << argv[0] << " " << endl; + return 1; + } + + try { + // Construct the sniffer configuration object + SnifferConfiguration config; + + // Only capture TCP traffic sent from/to the given port + config.set_filter("tcp port " + to_string(stoi(string(argv[2])))); + + // Construct the sniffer we'll use + Sniffer sniffer(argv[1], config); + + cout << "Starting capture on interface " << argv[1] << endl; + + // Now construct the stream follower + StreamFollower follower; + + // We just need to specify the callback to be executed when a new + // stream is captured. In this stream, you should define which callbacks + // will be executed whenever new data is sent on that stream + // (see on_new_connection) + follower.new_stream_callback(&on_new_connection); + + // Allow following partial TCP streams (e.g. streams that were + // open before the sniffer started running) + follower.follow_partial_streams(true); + + // Now start capturing. Every time there's a new packet, call + // follower.process_packet + sniffer.sniff_loop([&](PDU& packet) { + follower.process_packet(packet); + return true; + }); + } + catch (exception& ex) { + cerr << "Error: " << ex.what() << endl; + return 1; + } +} diff --git a/lib/libtins/examples/tcp_connection_close.cpp b/lib/libtins/examples/tcp_connection_close.cpp new file mode 100644 index 0000000..b1694cc --- /dev/null +++ b/lib/libtins/examples/tcp_connection_close.cpp @@ -0,0 +1,107 @@ +/* + * Copyright (c) 2017, Matias Fontanini + * All rights reserved. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions are + * met: + * + * * Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * * Redistributions in binary form must reproduce the above + * copyright notice, this list of conditions and the following disclaimer + * in the documentation and/or other materials provided with the + * distribution. + * + * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS + * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT + * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR + * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT + * OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, + * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT + * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, + * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY + * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT + * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE + * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + * + */ + +#include +#include +#include +#include + +using std::string; +using std::bind; +using std::cout; +using std::endl; +using std::exception; + +using namespace Tins; + +// This example will capture TCP packets and send packet that will reset +// the connection when it captures a packet with the SYN and ACK flags on. +class tcp_connection_closer { +public: + tcp_connection_closer() { + + } + + void run(const string& interface) { + using std::placeholders::_1; + // Make the PacketSender use this interface by default + sender_.default_interface(interface); + + // Create the sniffer configuration + SnifferConfiguration config; + config.set_filter("tcp"); + // We want to get the packets as fast as possible + config.set_immediate_mode(true); + // Create the sniffer and start the capture + Sniffer sniffer(interface, config); + sniffer.sniff_loop(bind(&tcp_connection_closer::callback, this, _1)); + } +private: + bool callback(const PDU& pdu) { + const EthernetII& eth = pdu.rfind_pdu(); + const IP& ip = pdu.rfind_pdu(); + const TCP& tcp = pdu.rfind_pdu(); + // We'll only close a connection when seeing a SYN|ACK + if (tcp.has_flags(TCP::SYN | TCP::ACK)) { + // Create an ethernet header flipping the addresses + EthernetII packet(eth.src_addr(), eth.dst_addr()); + // Do the same for IP + packet /= IP(ip.src_addr(), ip.dst_addr()); + // Flip TCP ports + TCP response_tcp(tcp.sport(), tcp.dport()); + // Set RST|ACK flags + response_tcp.flags(TCP::RST | TCP::ACK); + // Use the right sequence and ack numbers + response_tcp.seq(tcp.ack_seq()); + response_tcp.ack_seq(tcp.seq()); + // Add this PDU to the packet we'll send + packet /= response_tcp; + // Send it! + sender_.send(packet); + } + return true; + } + + PacketSender sender_; +}; + +int main(int argc, char* argv[]) { + if (argc != 2) { + cout << "Usage: " << *argv << " " << endl; + return 1; + } + try { + tcp_connection_closer closer; + closer.run(argv[1]); + } + catch (exception& ex) { + cout << "[-] Error: " << ex.what() << endl; + return 1; + } +} \ No newline at end of file diff --git a/lib/libtins/examples/traceroute.cpp b/lib/libtins/examples/traceroute.cpp new file mode 100644 index 0000000..9a4da46 --- /dev/null +++ b/lib/libtins/examples/traceroute.cpp @@ -0,0 +1,211 @@ +/* + * Copyright (c) 2017, Matias Fontanini + * All rights reserved. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions are + * met: + * + * * Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * * Redistributions in binary form must reproduce the above + * copyright notice, this list of conditions and the following disclaimer + * in the documentation and/or other materials provided with the + * distribution. + * + * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS + * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT + * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR + * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT + * OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, + * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT + * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, + * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY + * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT + * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE + * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + * + */ + +#ifdef _WIN32 + #define NOMINMAX +#endif // _WIN32 + +// Fix for gcc 4.6 +#define _GLIBCXX_USE_NANOSLEEP + +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#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 { +public: + typedef std::map result_type; + + Traceroute(NetworkInterface interface, IPv4Address address) + : iface(interface), addr(address), lowest_dest_ttl(numeric_limits::max()) { + sequence = random_device()() & 0xffff; + } + + result_type trace() { + SnifferConfiguration config; + config.set_promisc_mode(false); + // ICMPs that aren't sent from us. + config.set_filter( + "ip proto \\icmp and not src host " + iface.addresses().ip_addr.to_string()); + Sniffer sniffer(iface.name(), config); + + PacketSender sender; + // Create our handler + auto handler = bind( + &Traceroute::sniff_callback, + this, + std::placeholders::_1 + ); + // We're running + running = true; + // Start the sniff thread + thread sniff_thread( + [&]() { + sniffer.sniff_loop(handler); + } + ); + send_packets(sender); + sniff_thread.join(); + // If the final hop responded, add its address at the appropriate ttl + if (lowest_dest_ttl != numeric_limits::max()) { + results[lowest_dest_ttl] = addr; + } + // Clear our results and return what we've found + return move(results); + } +private: + typedef map ttl_map; + + 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) { + // Set this ICMP id + icmp.id(i); + // Set the time-to-live option + ip.ttl(i); + + // Critical section + { + lock_guard _(lock); + ttls[i] = i; + } + + sender.send(ip); + // Give it a little time + sleep_for(milliseconds(100)); + } + running = false; + sender.send(ip); + } + + bool sniff_callback(PDU& pdu) { + // Find IP and ICMP PDUs + 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 + const IP inner_ip = pdu.rfind_pdu().to(); + // Now get the ICMP layer + const ICMP& inner_icmp = inner_ip.rfind_pdu(); + // Make sure this is one of our packets. + if (inner_icmp.sequence() == sequence) { + ttl_map::const_iterator iter; + + // Critical section + { + std::lock_guard _(lock); + iter = ttls.find(inner_icmp.id()); + } + + // It's an actual response + if(iter != ttls.end()) { + // Store it + results[inner_icmp.id()] = ip.src_addr(); + } + } + } + // Otherwise, this could be the final hop making an echo response + 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 = min(lowest_dest_ttl, static_cast(icmp.id())); + } + return running; + } + + NetworkInterface iface; + IPv4Address addr; + atomic running; + ttl_map ttls; + result_type results; + mutex lock; + uint16_t sequence; + int lowest_dest_ttl; +}; + +int main(int argc, char* argv[]) { + if (argc <= 1) { + cout << "Usage: " <<* argv << " " << endl; + return 1; + } + try { + IPv4Address addr = string(argv[1]); + Traceroute tracer(addr, addr); + auto results = tracer.trace(); + if (results.empty()) { + cout << "No hops found" << endl; + } + else { + cout << "Results: " << endl; + for(const auto& entry : results) { + cout << setw(2) << entry.first << " - " << entry.second << endl; + } + } + } + catch (runtime_error& ex) { + cout << "Error - " << ex.what() << endl; + return 2; + } +} diff --git a/lib/libtins/examples/wps_detect.cpp b/lib/libtins/examples/wps_detect.cpp new file mode 100644 index 0000000..9f4e8ca --- /dev/null +++ b/lib/libtins/examples/wps_detect.cpp @@ -0,0 +1,78 @@ +/* + * Copyright (c) 2017, Matias Fontanini + * All rights reserved. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions are + * met: + * + * * Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * * Redistributions in binary form must reproduce the above + * copyright notice, this list of conditions and the following disclaimer + * in the documentation and/or other materials provided with the + * distribution. + * + * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS + * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT + * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR + * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT + * OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, + * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT + * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, + * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY + * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT + * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE + * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + * + */ + +#include +#include +#include +#include + +using namespace Tins; + +// BSSIDs which we've already seen +std::set> addrs; +// This will be the content of the OUI field in the vendor specific +// tagged option if it's a WPS tag. +const HWAddress<3> expected_oui("00:50:F2"); + +bool handler(const PDU& 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()) { + // Is this a vendor-specific tag? + if(opt.option() == Dot11::VENDOR_SPECIFIC) { + // Make sure there's enough size for the OUI + identifier + if(opt.data_size() >= 4) { + // Retrieve the OUI field + HWAddress<3> addr = opt.data_ptr(); + // Are we interested in this OUI and is it a WPS tag? + if(addr == expected_oui && opt.data_ptr()[3] == 0x04) { + std::cout << "[+] Access point: " << beacon.ssid() << " uses WPS\n"; + } + } + } + } + } + return true; +} + +int main(int argc, char* argv[]) { + if(argc != 2) { + std::cout << "Usage: " <<* argv << " \n"; + return 1; + } + // Only sniff beacons + SnifferConfiguration config; + config.set_snap_len(2000); + config.set_promisc_mode(true); + config.set_filter("wlan type mgt subtype beacon"); + Sniffer sniffer(argv[1], config); + sniffer.sniff_loop(handler); +} diff --git a/lib/libtins/include/tins/address_range.h b/lib/libtins/include/tins/address_range.h new file mode 100644 index 0000000..30c1e92 --- /dev/null +++ b/lib/libtins/include/tins/address_range.h @@ -0,0 +1,338 @@ +/* + * Copyright (c) 2017, Matias Fontanini + * All rights reserved. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions are + * met: + * + * * Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * * Redistributions in binary form must reproduce the above + * copyright notice, this list of conditions and the following disclaimer + * in the documentation and/or other materials provided with the + * distribution. + * + * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS + * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT + * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR + * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT + * OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, + * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT + * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, + * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY + * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT + * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE + * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + * + */ + +#ifndef TINS_ADDRESS_RANGE +#define TINS_ADDRESS_RANGE + +#include +#include +#include +#include + +namespace Tins { +/** + * \brief AddressRange iterator class. + */ +template +class AddressRangeIterator { +public: + typedef std::forward_iterator_tag iterator_category; + typedef const Address value_type; + typedef std::ptrdiff_t difference_type; + typedef const Address* pointer; + typedef const Address& reference; + + struct end_iterator { + + }; + + /** + * Constructs an iterator. + * + * \param first The address held by this iterator. + */ + AddressRangeIterator(const value_type& address) + : address_(address), reached_end_(false) { + + } + + /** + * Constructs an iterator. + * + * \param first The address held by this iterator. + */ + AddressRangeIterator(const value_type& address, end_iterator) + : address_(address) { + reached_end_ = Internals::increment(address_); + } + + /** + * Retrieves the current address pointed by this iterator. + */ + const value_type& operator*() const { + return address_; + } + + /** + * Retrieves a pointer to the current address pointed by this iterator. + */ + const value_type* operator->() const { + return& address_; + } + + /** + * Compares two iterators for equality. + * + * \param rhs The iterator with which to compare. + */ + bool operator==(const AddressRangeIterator& rhs) const { + return reached_end_ == rhs.reached_end_ && address_ == rhs.address_; + } + + /** + * Compares two iterators for inequality. + * + * \param rhs The iterator with which to compare. + */ + bool operator!=(const AddressRangeIterator& rhs) const { + return !(*this == rhs); + } + + /** + * Increments this iterator. + */ + AddressRangeIterator& operator++() { + reached_end_ = Internals::increment(address_); + return* this; + } + + /** + * Increments this iterator. + */ + AddressRangeIterator operator++(int) { + AddressRangeIterator copy(*this); + (*this)++; + return copy; + } +private: + Address address_; + bool reached_end_; +}; + +/** + * \brief Represents a range of addresses. + * + * This class provides a begin()/end() interface which allows + * iterating through every address stored in it. + * + * Note that when iterating a range that was created using + * operator/(IPv4Address, int) and the analog for IPv6, the + * network and broadcast addresses are discarded: + * + * \code + * auto range = IPv4Address("192.168.5.0") / 24; + * for(const auto& addr : range) { + * // process 192.168.5.1-254, .0 and .255 are discarded + * process(addr); + * } + * + * // That's only valid for iteration, not for AddressRange<>::contains + * + * assert(range.contains("192.168.5.0")); // works + * assert(range.contains("192.168.5.255")); // works + * \endcode + * + * Ranges created using AddressRange(address_type, address_type) + * will allow the iteration over the entire range: + * + * \code + * AddressRange range("192.168.5.0", "192.168.5.255"); + * for(const auto& addr : range) { + * // process 192.168.5.0-255, no addresses are discarded + * process(addr); + * } + * + * assert(range.contains("192.168.5.0")); // still valid + * assert(range.contains("192.168.5.255")); // still valid + * \endcode + * + */ +template +class AddressRange { +public: + /** + * The type of addresses stored in the range. + */ + typedef Address address_type; + + /** + * The iterator type. + */ + typedef AddressRangeIterator const_iterator; + + /** + * \brief The iterator type. + * + * This is the same type as const_iterator, since the + * addresses stored in this range are read only. + */ + typedef const_iterator iterator; + + /** + * \brief Constructs an address range from two addresses. + * + * The range will consist of the addresses [first, last]. + * + * If only_hosts is true, then the network and broadcast addresses + * will not be available when iterating the range. + * + * If last < first, an std::runtime_error exception is thrown. + * + * \param first The first address in the range. + * \param last The last address(inclusive) in the range. + * \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_) { + throw exception_base("Invalid address range"); + } + } + + /** + * \brief Creates an address range from a base address + * and a network mask. + * + * \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) { + return AddressRange( + first & mask, + Internals::last_address_from_mask(first, mask), + true + ); + } + + /** + * \brief Indicates whether an address is included in this range. + * \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_; + } + + /** + * \brief Returns an interator to the beginning of this range. + * \brief const_iterator pointing to the beginning of this range. + */ + const_iterator begin() const { + address_type addr = first_; + if (only_hosts_) { + Internals::increment(addr); + } + return const_iterator(addr); + } + + /** + * \brief Returns an interator to the end of this range. + * \brief const_iterator pointing to the end of this range. + */ + const_iterator end() const { + address_type addr = last_; + if (only_hosts_) { + Internals::decrement(addr); + } + return const_iterator(addr, typename const_iterator::end_iterator()); + } + + /** + * \brief Indicates whether this range is iterable. + * + * Iterable ranges are those for which there is at least one + * address that could represent a host. For IPv4 ranges, a /31 or + * /32 ranges does not contain any, therefore it's not iterable. + * The same is true for /127 and /128 IPv6 ranges. + * + * If is_iterable returns false for a range, then iterating it + * through the iterators returned by begin() and end() is + * undefined. + * + * \return bool indicating whether this range is iterable. + */ + bool is_iterable() const { + // Since first < last, it's iterable + if (!only_hosts_) { + return true; + } + // We need that distance(first, last) >= 4 + 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) { + return false; + } + } + // If addr <= last, it's OK. + return addr < last_ || addr == last_; + } +private: + address_type first_, last_; + bool only_hosts_; +}; + +/** + * An IPv4 address range. + */ +typedef AddressRange IPv4Range; + +/** + * An IPv6 address range. + */ +typedef AddressRange IPv6Range; + +/** + * \brief Constructs an AddressRange from a base address and a mask. + * \param addr The range's first address. + * \param mask The bit-length of the prefix. + */ +template +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) { + *it = 0xff; + ++it; + mask -= 8; + } + *it = 0xff << (8 - mask); + return AddressRange >::from_mask(addr, last_addr); +} + +/** + * \brief Constructs an IPv6Range from a base IPv6Address and a mask. + * \param addr The range's first address. + * \param mask The bit-length of the prefix. + */ +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); +} // namespace Tins + +#endif // TINS_ADDRESS_RANGE diff --git a/lib/libtins/include/tins/arp.h b/lib/libtins/include/tins/arp.h new file mode 100644 index 0000000..f46783d --- /dev/null +++ b/lib/libtins/include/tins/arp.h @@ -0,0 +1,344 @@ +/* + * Copyright (c) 2017, Matias Fontanini + * All rights reserved. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions are + * met: + * + * * Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * * Redistributions in binary form must reproduce the above + * copyright notice, this list of conditions and the following disclaimer + * in the documentation and/or other materials provided with the + * distribution. + * + * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS + * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT + * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR + * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT + * OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, + * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT + * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, + * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY + * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT + * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE + * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + * + */ + + +#ifndef TINS_ARP_H +#define TINS_ARP_H + +#include +#include +#include +#include +#include + +namespace Tins { + +class NetworkInterface; +class EthernetII; + +/** + * \class ARP + * \brief Represents an ARP PDU. + * + */ +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; + + /** + * \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 Extracts metadata for this protocol based on the buffer provided + * + * \param buffer Pointer to a buffer + * \param total_sz Size of the buffer pointed by buffer + */ + static metadata extract_metadata(const uint8_t *buffer, uint32_t total_sz); + + /** + * \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 EthernetII object containing the ARP Reply. + */ + 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 whether 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); + + arp_header header_; +}; + +} // Tins + +#endif // TINS_ARP_H diff --git a/lib/libtins/include/tins/bootp.h b/lib/libtins/include/tins/bootp.h new file mode 100644 index 0000000..47f7332 --- /dev/null +++ b/lib/libtins/include/tins/bootp.h @@ -0,0 +1,363 @@ +/* + * Copyright (c) 2017, Matias Fontanini + * All rights reserved. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions are + * met: + * + * * Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * * Redistributions in binary form must reproduce the above + * copyright notice, this list of conditions and the following disclaimer + * in the documentation and/or other materials provided with the + * distribution. + * + * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS + * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT + * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR + * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT + * OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, + * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT + * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, + * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY + * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT + * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE + * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + * + */ + +#ifndef TINS_BOOTP_H +#define TINS_BOOTP_H + +#include +#include +#include +#include +#include +#include +#include + +namespace Tins { + +/** + * \class BootP + * \brief Represents a BootP PDU + */ +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; + + /** + * \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) { + size_t copy_threshold = std::min(n, sizeof(bootp_.chaddr)); + for (size_t i = 0; i < copy_threshold; ++i) { + if (i < copy_threshold) { + bootp_.chaddr[i] = new_chaddr[i]; + } + else { + bootp_.chaddr[i] = 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 whether 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); + + /** + * 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; + +private: + bootp_header bootp_; + vend_type vend_; +}; + +} // Tins + +#endif // TINS_BOOTP_H diff --git a/lib/libtins/include/tins/config.h.in b/lib/libtins/include/tins/config.h.in new file mode 100644 index 0000000..a103973 --- /dev/null +++ b/lib/libtins/include/tins/config.h.in @@ -0,0 +1,39 @@ +#ifndef TINS_CONFIG_H +#define TINS_CONFIG_H + +/* Define if the compiler supports basic C++11 syntax */ +#cmakedefine TINS_HAVE_CXX11 + +/* Have IEEE 802.11 support */ +#cmakedefine TINS_HAVE_DOT11 + +/* Have WPA2 decryption library */ +#cmakedefine TINS_HAVE_WPA2_DECRYPTION + +/* Use pcap_sendpacket to send l2 packets */ +#cmakedefine TINS_HAVE_PACKET_SENDER_PCAP_SENDPACKET + +/* Have TCPIP classes */ +#cmakedefine TINS_HAVE_TCPIP + +/* Have TCP ACK tracking */ +#cmakedefine TINS_HAVE_ACK_TRACKER + +/* Have TCP stream custom data */ +#cmakedefine TINS_HAVE_TCP_STREAM_CUSTOM_DATA + +/* Have GCC builtin swap */ +#cmakedefine TINS_HAVE_GCC_BUILTIN_SWAP + +/* Have WPA2Decrypter callbacks */ +#cmakedefine TINS_HAVE_WPA2_CALLBACKS + +/* Have libpcap */ +#cmakedefine TINS_HAVE_PCAP + +/* Version macros */ +#define TINS_VERSION_MAJOR ${TINS_VERSION_MAJOR} +#define TINS_VERSION_MINOR ${TINS_VERSION_MINOR} +#define TINS_VERSION_PATCH ${TINS_VERSION_PATCH} + +#endif // TINS_CONFIG_H diff --git a/lib/libtins/include/tins/constants.h b/lib/libtins/include/tins/constants.h new file mode 100644 index 0000000..c5d2a70 --- /dev/null +++ b/lib/libtins/include/tins/constants.h @@ -0,0 +1,163 @@ +/* + * Copyright (c) 2017, Matias Fontanini + * All rights reserved. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions are + * met: + * + * * Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * * Redistributions in binary form must reproduce the above + * copyright notice, this list of conditions and the following disclaimer + * in the documentation and/or other materials provided with the + * distribution. + * + * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS + * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT + * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR + * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT + * OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, + * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT + * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, + * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY + * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT + * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE + * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + * + */ + +#ifndef TINS_CONSTANTS_H +#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, + 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 + QINQ = 0x88a8, // IEEE 802.1ad VLAN tagging + OLD_QINQ = 0x9100, // IEEE 802.1ad VLAN tagging (old, deprecated, value) + 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/lib/libtins/include/tins/crypto.h b/lib/libtins/include/tins/crypto.h new file mode 100644 index 0000000..a6040ce --- /dev/null +++ b/lib/libtins/include/tins/crypto.h @@ -0,0 +1,536 @@ +/* + * Copyright (c) 2017, Matias Fontanini + * All rights reserved. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions are + * met: + * + * * Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * * Redistributions in binary form must reproduce the above + * copyright notice, this list of conditions and the following disclaimer + * in the documentation and/or other materials provided with the + * distribution. + * + * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS + * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT + * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR + * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT + * OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, + * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT + * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, + * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY + * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT + * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE + * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + * + */ + +#include + +#if !defined(TINS_CRYPTO_H) && defined(TINS_HAVE_DOT11) +#define TINS_CRYPTO_H + +#include +#include +#include +#ifdef TINS_HAVE_WPA2_CALLBACKS + #include +#endif // TINS_HAVE_WPA2_CALLBACKS +#include +#include + +namespace Tins { + +class PDU; +class Dot11; +class Dot11Data; +class SNAP; +class RawPDU; + +namespace Crypto { + +#ifdef TINS_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; + + 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; + + /** + * \brief Getter for the SSID + * \return The access point's SSID + */ + const std::string& ssid() const; +private: + pmk_type pmk_; + std::string ssid_; +}; + +} // WPA2 +#endif // TINS_HAVE_WPA2_DECRYPTION + +/** + * \brief Decrypts WEP-encrypted traffic. + */ +class TINS_API WEPDecrypter { +public: + typedef HWAddress<6> address_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; + + PDU* decrypt(RawPDU& raw, const std::string& password); + + passwords_type passwords_; + std::vector key_buffer_; +}; + +#ifdef TINS_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; + + #ifdef TINS_HAVE_WPA2_CALLBACKS + + /** + * \brief The type used to store the callback type used when a new access + * point is found. + * + * The first argument to the function will be the access point's SSID and + * the second one its BSSID. + */ + typedef std::function ap_found_callback_type; + + /** + * The type used to store the callback type used when a new handshake + * is captured. + * + * The first argument to the function will be the access point's SSID and + * the second one its BSSID. The third argument will be the client's hardware + * address. + */ + typedef std::function handshake_captured_callback_type; + + #endif // TINS_HAVE_WPA2_CALLBACKS + + /** + * \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); + + #ifdef TINS_HAVE_WPA2_CALLBACKS + /** + * \brief Sets the handshake captured callback + * + * This callback will be executed every time a new handshake is captured. + * + * \sa handshake_captured_callback_type + * \param callback The new callback to be set + */ + void handshake_captured_callback(const handshake_captured_callback_type& callback); + + /** + * \brief Sets the access point found callback + * + * This callback will be executed every time a new access point is found, that's + * advertising an SSID added when calling add_ap_data. + * + * \sa ap_found_callback_type + * \param callback The new callback to be set + */ + void ap_found_callback(const ap_found_callback_type& callback); + + #endif // TINS_HAVE_WPA2_CALLBACKS + + /** + * \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); + + RSNHandshakeCapturer capturer_; + pmks_map pmks_; + bssids_map aps_; + keys_map keys_; + #ifdef TINS_HAVE_WPA2_CALLBACKS + handshake_captured_callback_type handshake_captured_callback_; + ap_found_callback_type ap_found_callback_; + #endif // TINS_HAVE_WPA2_CALLBACKS +}; +#endif // TINS_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; + + /** + * \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 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); + +#ifdef TINS_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 // TINS_HAVE_WPA2_DECRYPTION + +// Implementation section + +// DecrypterProxy + +template +DecrypterProxy::DecrypterProxy(const functor_type& func, + const decrypter_type& decr) +: functor_(func), decrypter_(decr) { + +} + +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); +} + +} // Crypto +} // Tins + +#endif // TINS_CRYPTO_H diff --git a/lib/libtins/include/tins/cxxstd.h b/lib/libtins/include/tins/cxxstd.h new file mode 100644 index 0000000..f88f255 --- /dev/null +++ b/lib/libtins/include/tins/cxxstd.h @@ -0,0 +1,53 @@ +/* + * Copyright (c) 2017, Matias Fontanini + * All rights reserved. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions are + * met: + * + * * Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * * Redistributions in binary form must reproduce the above + * copyright notice, this list of conditions and the following disclaimer + * in the documentation and/or other materials provided with the + * distribution. + * + * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS + * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT + * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR + * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT + * OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, + * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT + * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, + * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY + * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT + * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE + * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + * + */ + +#ifndef TINS_CXXSTD_H +#define TINS_CXXSTD_H + +#include + +#ifdef __GXX_EXPERIMENTAL_CXX0X__ + #define TINS_CXXSTD_GCC_FIX 1 +#else + #define TINS_CXXSTD_GCC_FIX 0 +#endif // __GXX_EXPERIMENTAL_CXX0X__ + +#if !defined(TINS_IS_CXX11) && defined(TINS_HAVE_CXX11) +#define TINS_IS_CXX11 (__cplusplus > 199711L || TINS_CXXSTD_GCC_FIX == 1 || _MSC_VER >= 1800) +#elif !defined(TINS_IS_CXX11) +#define TINS_IS_CXX11 0 +#endif // TINS_IS_CXX11 + +namespace Tins{ +namespace Internals { +template void unused(const T&) { } +} +} + +#endif // TINS_CXXSTD_H diff --git a/lib/libtins/include/tins/data_link_type.h b/lib/libtins/include/tins/data_link_type.h new file mode 100644 index 0000000..6822dd7 --- /dev/null +++ b/lib/libtins/include/tins/data_link_type.h @@ -0,0 +1,83 @@ +/* + * Copyright (c) 2017, Matias Fontanini + * All rights reserved. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions are + * met: + * + * * Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * * Redistributions in binary form must reproduce the above + * copyright notice, this list of conditions and the following disclaimer + * in the documentation and/or other materials provided with the + * distribution. + * + * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS + * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT + * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR + * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT + * OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, + * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT + * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, + * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY + * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT + * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE + * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + * + */ + +#ifndef TINS_DATA_LINK_TYPE_H +#define TINS_DATA_LINK_TYPE_H + +#include + +namespace Tins { + +class EthernetII; +class RadioTap; +class Dot11; +class Dot3; +class SLL; +class Loopback; +class PPI; +class IP; + +/** + * \struct DataLinkType + * \brief Maps a libtins link layer PDU to a libpcap data link identifier. + * + * This is an empty class that should be instantiated with any object that + * represents a link layer PDU (EthernetII, Dot11, RadioTap, etc): + * + * \code + * // Instantiate it and pass it to PacketWriter's constructor. + * PacketWriter writer("file.pcap", DataLinkType()); + * \endcode + */ +template +struct DataLinkType; + +#define TINS_MAKE_DATA_LINK_TYPE(tins_type, pcap_type) \ +template<> \ +struct DataLinkType { \ + static const int type = pcap_type; \ + int get_type() const { \ + return type; \ + } \ +}; + +TINS_MAKE_DATA_LINK_TYPE(EthernetII, DLT_EN10MB) +TINS_MAKE_DATA_LINK_TYPE(Dot3, DLT_EN10MB) +TINS_MAKE_DATA_LINK_TYPE(SLL, DLT_LINUX_SLL) +TINS_MAKE_DATA_LINK_TYPE(Loopback, DLT_LOOP) +TINS_MAKE_DATA_LINK_TYPE(PPI, DLT_PPI) +TINS_MAKE_DATA_LINK_TYPE(Dot11, DLT_IEEE802_11) +TINS_MAKE_DATA_LINK_TYPE(RadioTap, DLT_IEEE802_11_RADIO) +TINS_MAKE_DATA_LINK_TYPE(IP, DLT_RAW) + +#undef TINS_MAKE_DATA_LINK_TYPE + +} // Tins + +#endif // TINS_DATA_LINK_TYPE_H diff --git a/lib/libtins/include/tins/detail/address_helpers.h b/lib/libtins/include/tins/detail/address_helpers.h new file mode 100644 index 0000000..c653d4a --- /dev/null +++ b/lib/libtins/include/tins/detail/address_helpers.h @@ -0,0 +1,106 @@ +/* + * Copyright (c) 2017, Matias Fontanini + * All rights reserved. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions are + * met: + * + * * Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * * Redistributions in binary form must reproduce the above + * copyright notice, this list of conditions and the following disclaimer + * in the documentation and/or other materials provided with the + * distribution. + * + * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS + * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT + * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR + * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT + * OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, + * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT + * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, + * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY + * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT + * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE + * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + * + */ + +#ifndef TINS_ADDRESS_HELPERS_H +#define TINS_ADDRESS_HELPERS_H + +#include + +/** + * \cond + */ +namespace Tins { + +class IPv4Address; +class IPv6Address; + +namespace Internals { + +template +bool increment_buffer(T& addr) { + typename T::iterator it = addr.end() - 1; + while (it >= addr.begin() && *it == 0xff) { + *it = 0; + --it; + } + // reached end + if (it < addr.begin()) { + return true; + } + (*it)++; + return false; +} + +template +bool decrement_buffer(T& addr) { + typename T::iterator it = addr.end() - 1; + while (it >= addr.begin() && *it == 0) { + *it = 0xff; + --it; + } + // reached end + if (it < addr.begin()) { + return true; + } + (*it)--; + return false; +} + +bool increment(IPv4Address& addr); +bool increment(IPv6Address& addr); +bool decrement(IPv4Address& addr); +bool decrement(IPv6Address& addr); +template +bool increment(HWAddress& addr) { + return increment_buffer(addr); +} +template +bool decrement(HWAddress& addr) { + return decrement_buffer(addr); +} + +IPv4Address last_address_from_mask(IPv4Address addr, IPv4Address mask); +IPv6Address last_address_from_mask(IPv6Address addr, const IPv6Address& mask); +template +HWAddress last_address_from_mask(HWAddress addr, const HWAddress& mask) { + typename HWAddress::iterator addr_iter = addr.begin(); + for (typename HWAddress::const_iterator it = mask.begin(); it != mask.end(); ++it, ++addr_iter) { + *addr_iter = *addr_iter | ~*it; + } + return addr; +} + +} // Internals +} // Tins + +/** + * \endcond + */ + +#endif // TINS_ADDRESS_HELPERS_H diff --git a/lib/libtins/include/tins/detail/icmp_extension_helpers.h b/lib/libtins/include/tins/detail/icmp_extension_helpers.h new file mode 100644 index 0000000..cfd6bd1 --- /dev/null +++ b/lib/libtins/include/tins/detail/icmp_extension_helpers.h @@ -0,0 +1,61 @@ +/* + * Copyright (c) 2017, Matias Fontanini + * All rights reserved. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions are + * met: + * + * * Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * * Redistributions in binary form must reproduce the above + * copyright notice, this list of conditions and the following disclaimer + * in the documentation and/or other materials provided with the + * distribution. + * + * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS + * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT + * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR + * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT + * OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, + * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT + * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, + * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY + * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT + * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE + * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + * + */ + +#ifndef TINS_ICMP_EXTENSION_HELPERS_H +#define TINS_ICMP_EXTENSION_HELPERS_H + +#include + +/** + * \cond + */ +namespace Tins { + +class PDU; +class ICMPExtensionsStructure; + +namespace Memory { +class InputMemoryStream; +} // Memory + +namespace Internals { + +uint32_t get_padded_icmp_inner_pdu_size(const PDU* inner_pdu, uint32_t pad_alignment); +void try_parse_icmp_extensions(Memory::InputMemoryStream& stream, uint32_t payload_length, + ICMPExtensionsStructure& extensions); + + +} // Internals +} // Tins + +/** + * \endcond + */ + +#endif // TINS_ICMP_EXTENSION_HELPERS_H diff --git a/lib/libtins/include/tins/detail/pdu_helpers.h b/lib/libtins/include/tins/detail/pdu_helpers.h new file mode 100644 index 0000000..d790019 --- /dev/null +++ b/lib/libtins/include/tins/detail/pdu_helpers.h @@ -0,0 +1,70 @@ +/* + * Copyright (c) 2017, Matias Fontanini + * All rights reserved. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions are + * met: + * + * * Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * * Redistributions in binary form must reproduce the above + * copyright notice, this list of conditions and the following disclaimer + * in the documentation and/or other materials provided with the + * distribution. + * + * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS + * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT + * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR + * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT + * OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, + * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT + * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, + * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY + * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT + * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE + * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + * + */ + +#ifndef TINS_PDU_HELPERS_H +#define TINS_PDU_HELPERS_H + +#include +#include +#include + +/** + * \cond + */ + +namespace Tins { +namespace Internals { + +PDU* pdu_from_flag(Constants::Ethernet::e flag, const uint8_t* buffer, + uint32_t size, bool rawpdu_on_no_match = true); +PDU* pdu_from_flag(Constants::IP::e flag, const uint8_t* buffer, + uint32_t size, bool rawpdu_on_no_match = true); +#ifdef TINS_HAVE_PCAP +PDU* pdu_from_dlt_flag(int flag, const uint8_t* buffer, + uint32_t size, bool rawpdu_on_no_match = true); +#endif // TINS_HAVE_PCAP +PDU* pdu_from_flag(PDU::PDUType type, const uint8_t* buffer, uint32_t size); + +Constants::Ethernet::e pdu_flag_to_ether_type(PDU::PDUType flag); +PDU::PDUType ether_type_to_pdu_flag(Constants::Ethernet::e flag); +Constants::IP::e pdu_flag_to_ip_type(PDU::PDUType flag); +PDU::PDUType ip_type_to_pdu_flag(Constants::IP::e flag); + +inline bool is_dot3(const uint8_t* ptr, size_t sz) { + return (sz >= 13 && ptr[12] < 8); +} + +} // Internals +} // Tins + +/** + * \endcond + */ + +#endif // TINS_PDU_HELPERS_H diff --git a/lib/libtins/include/tins/detail/sequence_number_helpers.h b/lib/libtins/include/tins/detail/sequence_number_helpers.h new file mode 100644 index 0000000..04af18d --- /dev/null +++ b/lib/libtins/include/tins/detail/sequence_number_helpers.h @@ -0,0 +1,49 @@ +/* + * Copyright (c) 2017, Matias Fontanini + * All rights reserved. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions are + * met: + * + * * Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * * Redistributions in binary form must reproduce the above + * copyright notice, this list of conditions and the following disclaimer + * in the documentation and/or other materials provided with the + * distribution. + * + * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS + * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT + * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR + * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT + * OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, + * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT + * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, + * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY + * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT + * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE + * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + * + */ + +#ifndef TINS_SEQUENCE_NUMBER_HELPERS_H +#define TINS_SEQUENCE_NUMBER_HELPERS_H + +#include +/** + * \cond + */ +namespace Tins { +namespace Internals { + +// Compares sequence numbers as defined by RFC 1982. +int seq_compare(uint32_t seq1, uint32_t seq2); + +} // namespace Internals +} // namespace Tins +/** + * \endcond + */ + +#endif // TINS_SEQUENCE_NUMBER_HELPERS_H diff --git a/lib/libtins/include/tins/detail/smart_ptr.h b/lib/libtins/include/tins/detail/smart_ptr.h new file mode 100644 index 0000000..f825cbb --- /dev/null +++ b/lib/libtins/include/tins/detail/smart_ptr.h @@ -0,0 +1,51 @@ +/* + * Copyright (c) 2017, Matias Fontanini + * All rights reserved. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions are + * met: + * + * * Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * * Redistributions in binary form must reproduce the above + * copyright notice, this list of conditions and the following disclaimer + * in the documentation and/or other materials provided with the + * distribution. + * + * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS + * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT + * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR + * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT + * OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, + * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT + * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, + * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY + * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT + * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE + * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + * + */ + +#ifndef TINS_SMART_PTR_H +#define TINS_SMART_PTR_H + +#include +#include + +namespace Tins { +namespace Internals { + +template +struct smart_ptr { +#if TINS_IS_CXX11 + typedef std::unique_ptr type; +#else + typedef std::auto_ptr type; +#endif +}; + +} // Internals +} // Tins + +#endif // TINS_SMART_PTR_H diff --git a/lib/libtins/include/tins/detail/type_traits.h b/lib/libtins/include/tins/detail/type_traits.h new file mode 100644 index 0000000..be3fdeb --- /dev/null +++ b/lib/libtins/include/tins/detail/type_traits.h @@ -0,0 +1,127 @@ +/* + * Copyright (c) 2017, Matias Fontanini + * All rights reserved. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions are + * met: + * + * * Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * * Redistributions in binary form must reproduce the above + * copyright notice, this list of conditions and the following disclaimer + * in the documentation and/or other materials provided with the + * distribution. + * + * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS + * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT + * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR + * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT + * OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, + * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT + * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, + * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY + * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT + * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE + * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + * + */ + +#ifndef TINS_TYPE_TRAITS_H +#define TINS_TYPE_TRAITS_H + +#include +#include +#if TINS_IS_CXX11 + #include + #include +#endif + +namespace Tins { +namespace Internals { +/** + * \cond + */ + +template +struct enable_if { + typedef T type; +}; + +template +struct enable_if { + +}; + +template +struct type_to_type { + typedef T type; +}; + +template +struct is_unsigned_integral { + static const bool value = false; +}; + +template<> +struct is_unsigned_integral { + static const bool value = true; +}; + +template<> +struct is_unsigned_integral { + static const bool value = true; +}; + +template<> +struct is_unsigned_integral { + static const bool value = true; +}; + +template<> +struct is_unsigned_integral { + static const bool value = true; +}; + +#if TINS_IS_CXX11 && !defined(_MSC_VER) + +// Template metaprogramming trait to determine if a functor can accept another parameter as an argument +template +struct accepts_type : std::false_type { }; + +template +struct accepts_type()(std::declval

()) ), bool>::value + >::type +> : std::true_type { }; + +// use enable_if to invoke the Packet&& version of the sniff_loop handler if possible - otherwise fail to old behavior +template +bool invoke_loop_cb(Functor& f, Packet& p, + typename std::enable_if::value, bool>::type* = 0) { + return f(std::move(p)); +} + +template +bool invoke_loop_cb(Functor& f, Packet& p, + typename std::enable_if::value && accepts_type::value, bool>::type* = 0) { + return f(p); +} + +template +bool invoke_loop_cb(Functor& f, Packet& p, + typename std::enable_if::value && !accepts_type::value, bool>::type* = 0) { + return f(*p.pdu()); +} + +#endif + +/** + * \endcond + */ + +} // Internals +} // Tins + +#endif // TINS_TYPE_TRAITS_H diff --git a/lib/libtins/include/tins/dhcp.h b/lib/libtins/include/tins/dhcp.h new file mode 100644 index 0000000..877d1b8 --- /dev/null +++ b/lib/libtins/include/tins/dhcp.h @@ -0,0 +1,532 @@ +/* + * Copyright (c) 2017, Matias Fontanini + * All rights reserved. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions are + * met: + * + * * Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * * Redistributions in binary form must reproduce the above + * copyright notice, this list of conditions and the following disclaimer + * in the documentation and/or other materials provided with the + * distribution. + * + * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS + * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT + * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR + * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT + * OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, + * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT + * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, + * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY + * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT + * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE + * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + * + */ + +#ifndef TINS_DHCP_H +#define TINS_DHCP_H + +#include +#include +#include +#include +#include +#include + +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; + + /** + * 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::vector