From 057a7b4344651e6bb16938e7109f8749025a0d22 Mon Sep 17 00:00:00 2001 From: /jedi/ Date: Wed, 20 Jan 2016 20:56:00 +0100 Subject: [PATCH 1/5] updates --- README.md | 12 +++-- src/File.cpp | 2 +- src/Host.cpp | 2 +- src/Lookup.h | 38 +++++++++------- src/Options.h | 66 --------------------------- src/Program.cpp | 36 ++++++++++----- src/Program.h | 1 + src/Socket.cpp | 2 +- src/Switch.cpp | 113 ++++++----------------------------------------- src/Switch.h | 36 ++++++++++++--- src/bytes.cpp | 19 ++++---- src/bytes.h | 10 ++--- src/smrtlink.cpp | 6 ++- src/table.h | 2 +- 14 files changed, 123 insertions(+), 222 deletions(-) delete mode 100644 src/Options.h diff --git a/README.md b/README.md index 4a32078..36f6447 100644 --- a/README.md +++ b/README.md @@ -1,7 +1,13 @@ # smrtlink Command-Line Tool which might in the future be able to configure TP-Link Easy Smart Switches. -The usage is loosely based on the swconfig utility. +The usage is loosely based on the swconfig utility. -###dependencys +### dependencys libboost-filesystem-dev - libboost-system-dev \ No newline at end of file + libboost-system-dev + +### compatible devices ++ TL-SG105E ++ TL-SG108E ++ TL-SG1016DE (not tested) ++ TL-SG1024DE (not tested) diff --git a/src/File.cpp b/src/File.cpp index 654bca2..0e6e944 100644 --- a/src/File.cpp +++ b/src/File.cpp @@ -7,7 +7,7 @@ #include #include "File.h" -#include "Options.h" +#include "Constant.h" std::string File::read() { if (!fs::exists(home)) { diff --git a/src/Host.cpp b/src/Host.cpp index 83a06b4..1fbba26 100644 --- a/src/Host.cpp +++ b/src/Host.cpp @@ -21,7 +21,7 @@ #include #include -#include "Options.h" +#include "Constant.h" #include "Host.h" #include "Types.h" diff --git a/src/Lookup.h b/src/Lookup.h index dc07b7f..9a6bfef 100644 --- a/src/Lookup.h +++ b/src/Lookup.h @@ -16,30 +16,33 @@ static table rcv_lookup = { // { 6, table::DEC, "gateway" }, //+byte[4] { 7, table::STRING, "firmware_version" },//+ { 8, table::STRING, "hardware_version" },//+ - { 9, table::DEC, "dhcp" }, //+bool byte + { 9, table::BOOL, "dhcp_enabled" }, //+bool byte { 10, table::DEC, "ports" }, //+byte, maybe number of ports + { 2101, table::HEX, "port_vlan ????????" }, + { 4352, table::HEX, "igmp_snooping" }, //??? { 4096, table::HEX, "port_settings" }, //+per port { 4608, table::HEX, "port_trunk" }, //byte[5] last byte bitmask?? { 8192, table::HEX, "mtu_vlan" }, //byte[2] first byte bool,second byte port id - { 8448, table::HEX, "port_vlan_1" }, //??? - { 8450, table::HEX, "port_vlan_2" }, //??? - { 8704, table::HEX, "vlan_enabled" }, //+bool byte + { 8448, table::BOOL, "port_vlan_enabled" }, //open page + { 8449, table::HEX, "port_vlan" }, //??? + { 8450, table::DEC, "port_vlan_max" }, //??? + { 8704, table::BOOL, "vlan_enabled" }, //+bool byte { 8705, table::HEX, "vlan" }, //+one set per vlan { 8706, table::HEX, "vlan_pvid" }, //+per port - { 8707, table::HEX, "vlan ?????" }, //???? + { 8707, table::DEC, "vlan ?????" }, //???? - { 12288, table::HEX, "qos_basic_enabled" }, //+bool = QoS Mod + { 12288, table::BOOL, "qos_basic_enabled" }, //+bool = QoS Mod { 12289, table::HEX, "qos_basic" }, //+per port ??? - { 12544, table::HEX, "bandwidth_control_1" }, //+per port ??? - { 12545, table::HEX, "bandwidth_control_2" }, //+per port ??? + { 12544, table::HEX, "bandwidth_control_ingress" }, //+per port ??? + { 12545, table::HEX, "bandwidth_control_egress" }, //+per port ??? { 12800, table::HEX, "storm_control" }, //+per port ??? { 16640, table::HEX, "port_mirror" }, //byte[10] second byte port id??? { 16384, table::HEX, "port_statistics" }, //+per port ??? { 16896, table::HEX, "cable_test" }, //+per port ??? - { 17152, table::HEX, "loop_prevention" }, //+bool byte + { 17152, table::BOOL, "loop_prevention" }, //+bool byte //{0000," "}, }; @@ -54,7 +57,7 @@ static table snd_lookup = { { 513, table::STRING, "new_user" }, //string { 514, table::STRING, "login_password" }, //string { 515, table::STRING, "new_passwoord" }, //string - { 773, table::HEX, "reboot" }, //bool byte = save config + { 773, table::BOOL, "reboot" }, //bool byte = save config { 1280, table::ACTION, "reset" }, // { 1536, table::ACTION, "flash" }, //update firmware @@ -68,20 +71,21 @@ static table snd_lookup = { { 4608, table::HEX, "port_trunk" }, //byte[5] last byte bitmask?? { 8192, table::HEX, "mtu_vlan" }, //byte[2] first byte bool, second byte port id - { 8449, table::HEX, "port_vlan ???" }, //??? - { 8448, table::HEX, "port_vlan" }, //open page - { 8704, table::HEX, "vlan_enabled" }, //??? get vlan / set status + { 8448, table::BOOL, "port_vlan_enabled" }, //open page + { 8449, table::HEX, "port_vlan" }, //??? + { 8704, table::BOOL, "vlan_enabled" }, //??? get vlan / set status { 8705, table::HEX, "vlan" }, // per vlan { 8706, table::HEX, "vlan_pvid" }, //per port - { 12288, table::HEX, "qos_basic_enabled" }, //bool = QoS Mod + { 12288, table::BOOL, "qos_basic_enabled" }, //bool = QoS Mod { 12289, table::HEX, "qos_basic" }, //per port - { 12544, table::HEX, "bandwidth_control_1" }, //per port - { 12545, table::HEX, "bandwidth_control_2" }, //per port + { 12544, table::HEX, "bandwidth_control_ingress" }, //per port + { 12545, table::HEX, "bandwidth_control_egress" }, //per port { 12800, table::HEX, "storm_control" }, //??? { 16640, table::HEX, "port_mirror" }, //byte[10] second byte port id?? { 16384, table::HEX, "port_statistics" }, //??? - { 17152, table::HEX, "loop_prevention" }, //bool byte + { 16896, table::HEX, "cable_test" }, //+per port ??? + { 17152, table::BOOL, "loop_prevention" }, //bool byte //{0000," "}, }; diff --git a/src/Options.h b/src/Options.h deleted file mode 100644 index 034ee3f..0000000 --- a/src/Options.h +++ /dev/null @@ -1,66 +0,0 @@ -/* - * Options.h - * - * Created on: 11.09.2015 - * Author: jdi - */ - -#ifndef OPTIONS_H_ -#define OPTIONS_H_ - -#include "Types.h" - -#define VERSION "smrtlink (v1 Linux)\n" -#define USAGE "usage: %s [-bdhjrvswx] [-i interface] [-u [password:]username]\n\ - [-p password] \n\n" -#define HELP "\ - Option Summary:\n\ - -h --help This help text\n\ - -v --version Display version of this tool\n\ - -d --debug [n] Show debugging messages\n\ - -r switch ports to emulate switch while sniffing\n\ - -b --header Show header\n\ - -x --hex Display Packets as Hex String\n\ - -j --json Display Packets as JSON\n\ - -i --interface only use one Interface\n\ - -u --user <[password:]username>\n\ - -p --password \n\ - Login with Username and Password\n\ - -f --file choose a settings file\n\n\ - -t --timeout Timeout in milliseconds. Default: 180\n\ - -I --interactive Not yet implemented\n\ - -O --stdout Not yet implemented\n\ - -w --wait Not yet implemented: blocking until operation is completed\n\ - -s --permanent Not yet implemented: make changes immediately permanent\n\n\ - Command Summary:\n\ - help This help text\n\ - list list all connected switches\n\ - sniff [type:] []\n\ - capture and display all incoming or outgoing packets\n\ - depending on the --reverse option\n\ - encode use encoding algorithm on hex data separated by colon\n\ - get Not yet implemented\n\ - set Not yet implemented\n\ - get|save Not yet implemented: save config to file\n\ - set|restore Not yet implemented: restore onfig from file\n\ - flash Not yet implemented: replace firmware\n\ - reboot Not yet implemented\n\ - reset Not yet implemented\n\n\ - ### for questions please contact ###\n\n" -//TODO -/* - * Stdin - * socketmode - * - */ - -#define FLAG_HEX 1 -#define FLAG_REVERSE 2 -#define FLAG_HEADER 4 -#define FLAG_PERMANENT 8 -#define FLAG_WAIT 16 -#define FLAG_DEBUG 32 - -extern Options options; - -#endif /* OPTIONS_H_ */ diff --git a/src/Program.cpp b/src/Program.cpp index 70b7e74..f939b5f 100644 --- a/src/Program.cpp +++ b/src/Program.cpp @@ -7,7 +7,7 @@ #include #include -#include "Options.h" +#include "Constant.h" #include "Program.h" #include "File.h" #include "Host.h" @@ -44,10 +44,22 @@ int printPacket(Packet p) { std::cout << "+\t" << s->name << " = " << &d.value[0] << "\n"; break; + case table::BOOL: + std::cout << "+\t" << s->name << " = " << (d.value[0]?"YES":"NO") + << "\n"; + break; case table::HEX: std::cout << "+\t" << s->name << " = " << d.value << "\n"; break; + case table::DEC: + std::cout << "+\t" << s->name << " = "; + if (d.value.size() > 0) + std::cout << std::dec << (unsigned) d.value[0]; + for (unsigned i = 1; i < d.value.size(); i++) + std::cout << std::dec << "." << (unsigned) d.value[i]; + std::cout << "\n"; + break; case table::ACTION: std::cout << "Error:" << s->name << " is marked as 'action' but carries payload." @@ -56,6 +68,7 @@ int printPacket(Packet p) { default: std::cout << "+\t" << s->name << " = " << d.value << "\n"; + break; } } else { //empty std::cout << std::dec << ">\t" << s->name << "\n"; @@ -149,17 +162,13 @@ int Program::getProperty() { p.setPayload( { }); bytes b = p.getBytes(); p.encode(b); - std::cout << "count-x:" << sock.use_count() << "\n"; auto s = sock; try { sock->setHostIp(host.getIp()); sock->init(DST_PORT, SRC_PORT); - - std::cout << "count-y:" << sock.use_count() << "\n"; sock->callback = [this](Packet a) { auto s = sock; - std::cout<<"count-z:"<send(c); - - std::cout<<"count-a:"<send(b); @@ -245,6 +254,11 @@ int Program::reset() { return 0; } +int Program::ping(std::function){ + + return 0; +} + void Program::init() { if (options.interface.compare("") == 0) options.interface = host.getIface(); diff --git a/src/Program.h b/src/Program.h index 1df58ec..1bd97da 100644 --- a/src/Program.h +++ b/src/Program.h @@ -19,6 +19,7 @@ private: std::shared_ptr io_service; std::shared_ptr sock; Host host = Host(); + int ping(std::function); public: Program() { io_service = std::make_shared(); diff --git a/src/Socket.cpp b/src/Socket.cpp index 7ef01d4..942f563 100644 --- a/src/Socket.cpp +++ b/src/Socket.cpp @@ -9,7 +9,7 @@ #include #include "Socket.h" #include "Packet.h" -#include "Options.h" +#include "Constant.h" #include "Host.h" #include "Types.h" diff --git a/src/Switch.cpp b/src/Switch.cpp index 00d1a55..2fe8980 100644 --- a/src/Switch.cpp +++ b/src/Switch.cpp @@ -9,8 +9,7 @@ #include "Types.h" #include "Switch.h" #include "Lookup.h" -#include "jsonNode.h" -#include "Options.h" +#include "Constant.h" #include "table.h" int Switch::parse(datasets arr) { @@ -22,129 +21,45 @@ int Switch::parse(datasets arr) { int Switch::parse(dataset d) { auto lookup = (options.flags & FLAG_REVERSE) ? snd_lookup : rcv_lookup; + std::string id = lookup.exists(d.type)?lookup[d.type]:"unknown"; if (d.type == lookup["type"]) { device.type = d.value; } - if (d.type == lookup["mac"]) { + else if (id == "mac") { device.mac = d.value; } - if (d.type == lookup["firmware_version"]) { + else if (d.type == lookup["firmware_version"]) { device.firmware_version = d.value; } - if (d.type == lookup["hardware_version"]) { + else if (id == "hardware_version") { device.hardware_version = d.value; } - if (d.type == lookup["ports"]) { + else if (id == "ports") { device.ports = d.value[0]; } - if (d.type == lookup["hostname"]) { + else if (id == "hostname") { settings.hostname = d.value; } - if (d.type == lookup["ip_addr"]) { + else if (id == "ip_addr") { settings.ip_addr = d.value; } - if (d.type == lookup["ip_mask"]) { + else if (id == "ip_mask") { settings.ip_mask = d.value; } - if (d.type == lookup["gateway"]) { + else if (id == "gateway") { settings.gateway = d.value; } - if (d.type == lookup["dhcp"]) { + else if (id == "dhcp_enabled") { settings.dhcp = d.value[0]; } - if (d.type == lookup["loop_prevention"]) { + else if (id == "loop_prevention") { settings.loop_prevention = d.value[0]; } - if (d.type == lookup["qos_basic_enabled"]) { + else if (id == "qos_basic_enabled") { settings.qos_enabled = d.value[0]; } - if (d.type == lookup["vlan_enabled"]) { + else if (id == "vlan_enabled") { settings.vlan_enabled = d.value[0]; } return 0; } - -int Switch::parse(std::string str) { - - if (json.Parse(str.c_str()).HasParseError()) - return 1; - if (options.flags & FLAG_DEBUG) - std::cout << "\nParsing to document succeeded.\n"; - - if (json.IsObject()) { - if (json.HasMember("hostname")) - settings.hostname = json["hostname"].GetString(); - if (json.HasMember("type")) - device.type = json["type"].GetString(); - if (json.HasMember("hardware_version")) - device.hardware_version = json["hardware_version"].GetString(); - if (json.HasMember("firmware_version")) - device.hardware_version = json["firmware_version"].GetString(); - if (json.HasMember("ports") && json["ports"].IsArray()) { - const rapidjson::Value& a = json["ports"]; - for (rapidjson::SizeType i = 0; i < a.Size(); i++) - if (a[i].IsObject()) { - port p; - if (a[i].HasMember("id") && a[i]["id"].IsInt()) { - p.id = a[i]["id"].GetInt(); - std::cout << a[i]["id"].GetInt() << "\n"; - } - ports.push_back(p); - } - } - if (json.HasMember("vlans") && json["vlans"].IsArray()) { - const rapidjson::Value& a = json["vlans"]; - for (rapidjson::SizeType i = 0; i < a.Size(); i++) - if (a[i].IsObject()) { - vlan v; - if (a[i].HasMember("name") && a[i]["name"].IsString()) { - v.name = a[i]["name"].GetString(); - std::cout << a[i]["name"].GetString() << "\n"; - } - vlans.push_back(v); - } - } - - } - - /* - - - { - const rapidjson::Value& a = json["a"]; - assert(a.IsArray()); - for (rapidjson::SizeType i = 0; i < a.Size(); i++) - printf("a[%d] = %d\n", i, a[i].GetInt()); - - int y = a[0].GetInt(); - (void) y; - - */ - return 0; -} - -std::string Switch::toString() { - - if (!json.IsObject()) { - json.SetObject(); - } - rapidjson::Document::AllocatorType& allocator = json.GetAllocator(); - - json.AddMember("hostname", jsonNode(settings.hostname, json), allocator); - json.AddMember("ip", jsonNode(settings.ip_addr, json), allocator); - json.AddMember("netmask", jsonNode(settings.ip_mask, json), allocator); - json.AddMember("gateway", jsonNode(settings.gateway, json), allocator); - json.AddMember("type", jsonNode(device.type, json), allocator); - json.AddMember("hardware_version", jsonNode(device.hardware_version, json), - allocator); - json.AddMember("firmware_version", jsonNode(device.firmware_version, json), - allocator); - json.AddMember("ports", jsonNode(ports, json), allocator); - json.AddMember("vlans", jsonNode(vlans, json), allocator); - - rapidjson::StringBuffer sb; - rapidjson::PrettyWriter writer(sb); - json.Accept(writer); - return sb.GetString(); -} - diff --git a/src/Switch.h b/src/Switch.h index 0a5c7ea..88a3351 100644 --- a/src/Switch.h +++ b/src/Switch.h @@ -17,6 +17,10 @@ #define DEFAULT_USER "admin" #define DEFAULT_PASS "admin" +enum CntStatus { + OPEN, SHORT +}; + struct vlan { int vlan_id; std::string name; @@ -24,17 +28,34 @@ struct vlan { std::vector untagged_member; }; +struct trunk { + int trunk_id; + std::vector member; +}; + struct port { byte id; byte status; int pvid; - //port_settings + struct { + //port_settings + } settings; + struct { + //port_statistics + } stats; + struct { + //bandwidth_control_ingress + //bandwidth_control_egress + } bw_control; + struct { + //storm_control + } storm_control; + struct { + CntStatus status; + int fault_distace; + } test; //qos_basic - //bandwidth_control_1 - //bandwidth_control_2 - //storm_control - //port_statistics - //cable_test + }; class Switch { @@ -45,6 +66,7 @@ public: int parse(dataset); int parse(std::string); std::string toString(); + struct { std::string type; std::string hardware_version; @@ -63,7 +85,9 @@ public: bool loop_prevention; bool qos_enabled; bool vlan_enabled; + //mtu_vlan } settings; + private: rapidjson::Document json; std::vector vlans; diff --git a/src/bytes.cpp b/src/bytes.cpp index bdc8c9d..9dac956 100644 --- a/src/bytes.cpp +++ b/src/bytes.cpp @@ -7,22 +7,23 @@ #include "bytes.h" -bytes::bytes(std::string d) { - vector(); +bytes bytes::readHex(std::string s){ + vector ret; std::string delimiter = ":"; std::string token; size_t pos = 0; int hex; byte b; - resize(0); - while ((pos = d.find(delimiter)) != std::string::npos) { - token = d.substr(0, pos); + ret.resize(0); + while ((pos = s.find(delimiter)) != std::string::npos) { + token = s.substr(0, pos); sscanf(token.c_str(), "%x", &hex); - d.erase(0, pos + delimiter.length()); + s.erase(0, pos + delimiter.length()); b = hex & 0xFF; - push_back(b); + ret.push_back(b); } - sscanf(d.c_str(), "%x", &hex); + sscanf(s.c_str(), "%x", &hex); b = hex & 0xFF; - push_back(b); + ret.push_back(b); + return ret; } diff --git a/src/bytes.h b/src/bytes.h index dcc0ec9..eb129d6 100644 --- a/src/bytes.h +++ b/src/bytes.h @@ -24,11 +24,11 @@ public: using vector::operator[]; bytes() { } - bytes(int n) : - vector(n) { + bytes(int n) : vector(n){ } - bytes(std::string); + bytes(std::string d) : vector(d.begin(), d.end()){ + } bytes(std::initializer_list s) { @@ -42,9 +42,7 @@ public: this->insert(this->begin(), B.begin(), B.end()); } - bytes readHex(std::string s){ - return bytes(s); - } + bytes readHex(std::string); bytes operator=(const vector &B) { this->reserve(B.size()); diff --git a/src/smrtlink.cpp b/src/smrtlink.cpp index c23c0a0..8a821ee 100644 --- a/src/smrtlink.cpp +++ b/src/smrtlink.cpp @@ -16,9 +16,10 @@ #include #include -#include "Options.h" +#include "Constant.h" #include "Host.h" #include "Program.h" +#include "Switch.h" #define no_argument 0 #define required_argument 1 @@ -33,6 +34,9 @@ constexpr unsigned int caseArg(const char* str, int h = 0) { int main(int argc, char *argv[]) { int opt, index; + options.user = DEFAULT_USER; + options.password = DEFAULT_PASS; + const struct option longopts[] = { { "version", no_argument, 0, 'v' }, { "help", no_argument, 0, 'h' }, { "reverse", no_argument, 0, 'r' }, { "permanent", no_argument, 0, 's' }, { "debug", optional_argument, 0, diff --git a/src/table.h b/src/table.h index f9171a6..54f8a91 100644 --- a/src/table.h +++ b/src/table.h @@ -13,7 +13,7 @@ class table { public: - enum F {STRING,HEX,DEC,ACTION,EMPTY}; + enum F {STRING,HEX,DEC,ACTION,BOOL,EMPTY}; struct set { short type; F format; From 45434738214e146671fbe5a23a03b52799469b09 Mon Sep 17 00:00:00 2001 From: /jedi/ Date: Thu, 21 Jan 2016 05:19:26 +0100 Subject: [PATCH 2/5] merging dev --- src/Program.cpp | 128 ------------------------------------------------ src/Switch.cpp | 50 ------------------- 2 files changed, 178 deletions(-) diff --git a/src/Program.cpp b/src/Program.cpp index f7d161a..636ed70 100644 --- a/src/Program.cpp +++ b/src/Program.cpp @@ -30,62 +30,6 @@ int printHeader(Packet p) { } int printPacket(Packet p) { -<<<<<<< HEAD - if (options.flags & FLAG_HEX) { - std::cout << "Received Payload:\n\t" << p.getBody() << "\n"; - } else { - for (dataset d : p.getPayload()) { - auto lookup = - (options.flags & FLAG_REVERSE) ? snd_lookup : rcv_lookup; - if (lookup.exists(d.type)) { - const table::set *s = lookup.get(d.type); - if (d.len > 0) { - switch (s->format) { - case table::STRING: - std::cout << "+\t" << s->name << " = " << &d.value[0] - << "\n"; - break; - case table::BOOL: - std::cout << "+\t" << s->name << " = " << (d.value[0]?"YES":"NO") - << "\n"; - break; - case table::HEX: - std::cout << "+\t" << s->name << " = " << d.value - << "\n"; - break; - case table::DEC: - std::cout << "+\t" << s->name << " = "; - if (d.value.size() > 0) - std::cout << std::dec << (unsigned) d.value[0]; - for (unsigned i = 1; i < d.value.size(); i++) - std::cout << std::dec << "." << (unsigned) d.value[i]; - std::cout << "\n"; - break; - case table::ACTION: - std::cout << "Error:" << s->name - << " is marked as 'action' but carries payload." - << d.value << "\n"; - break; - default: - std::cout << "+\t" << s->name << " = " << d.value - << "\n"; - break; - } - } else { //empty - std::cout << std::dec << ">\t" << s->name << "\n"; - } - } else { //unknown id - if (d.len > 0) { - std::cout << "##\t" << d.type << ":\n\t"; - std::cout << std::hex << d.value << std::dec << "\n"; - } else { //empty - std::cout << "#>\t" << d.type << "\n"; - } - } - } - } - return 0; -======= if (options.flags & FLAG_HEX) { std::cout << "Received Payload:\n\t" << p.getBody() << "\n"; } else { @@ -141,7 +85,6 @@ int printPacket(Packet p) { } } return 0; ->>>>>>> 3ef2da7b7a10c8b34f20c452acc0f8d0ffc17db5 } int Program::list() { @@ -214,71 +157,6 @@ int Program::setProperty() { } int Program::getProperty() { -<<<<<<< HEAD - std::cout << "List:\n"; - Packet p = Packet(Packet::DISCOVERY); - p.setHostMac(host.getMac()); - p.setPayload( { }); - bytes b = p.getBytes(); - p.encode(b); - auto s = sock; - try { - sock->setHostIp(host.getIp()); - sock->init(DST_PORT, SRC_PORT); - sock->callback = - [this](Packet a) { - auto s = sock; - datasets d =a.getPayload(); - Switch sw = Switch(); - sw.parse(d); - std::cout <<"Devices:\n\t"<callback = - [this](Packet a) { - auto s = sock; - datasets d =a.getPayload(); - Switch sw = Switch(); - sw.parse(d); - Packet p = Packet(Packet::SET); - p.setSwitchMac(a.getSwitchMac()); - p.setHostMac(host.getMac()); - datasets t = { - {snd_lookup["login_user"], (short)(options.user.length()), options.user}, - {snd_lookup["login_password"], (short)(options.password.length()), options.password} - }; - std::cout<callback = - [this](Packet a) { - std::cout << a.opCodeToString() << "\n"; - printHeader(a); - printPacket(a); - return 0; - }; - sock->send(c); - return 0; - }; - - sock->send(c); - return 0; - }; - sock->send(b); - io_service->run(); - } catch (std::exception& e) { - std::cerr << "Exception: " << e.what() << "\n"; - } - return 1; -======= std::cout << "List:\n"; Packet p = Packet(Packet::DISCOVERY); p.setHostMac(host.getMac()); @@ -348,7 +226,6 @@ int Program::getProperty() { std::cerr << "Exception: " << e.what() << "\n"; } return 1; ->>>>>>> 3ef2da7b7a10c8b34f20c452acc0f8d0ffc17db5 } int Program::save() { @@ -389,11 +266,6 @@ int Program::ping(std::function) { return 0; } -int Program::ping(std::function){ - - return 0; -} - void Program::init() { if (options.interface.compare("") == 0) options.interface = host.getIface(); diff --git a/src/Switch.cpp b/src/Switch.cpp index baf5c91..89419a8 100644 --- a/src/Switch.cpp +++ b/src/Switch.cpp @@ -8,11 +8,7 @@ #include #include "Types.h" #include "Switch.h" -<<<<<<< HEAD -#include "Lookup.h" -======= #include "lookup.h" ->>>>>>> 3ef2da7b7a10c8b34f20c452acc0f8d0ffc17db5 #include "Constant.h" #include "table.h" @@ -24,51 +20,6 @@ int Switch::parse(datasets arr) { } int Switch::parse(dataset d) { -<<<<<<< HEAD - auto lookup = (options.flags & FLAG_REVERSE) ? snd_lookup : rcv_lookup; - std::string id = lookup.exists(d.type)?lookup[d.type]:"unknown"; - if (d.type == lookup["type"]) { - device.type = d.value; - } - else if (id == "mac") { - device.mac = d.value; - } - else if (d.type == lookup["firmware_version"]) { - device.firmware_version = d.value; - } - else if (id == "hardware_version") { - device.hardware_version = d.value; - } - else if (id == "ports") { - device.ports = d.value[0]; - } - else if (id == "hostname") { - settings.hostname = d.value; - } - else if (id == "ip_addr") { - settings.ip_addr = d.value; - } - else if (id == "ip_mask") { - settings.ip_mask = d.value; - } - else if (id == "gateway") { - settings.gateway = d.value; - } - else if (id == "dhcp_enabled") { - settings.dhcp = d.value[0]; - } - else if (id == "loop_prevention") { - settings.loop_prevention = d.value[0]; - } - else if (id == "qos_basic_enabled") { - settings.qos_enabled = d.value[0]; - } - else if (id == "vlan_enabled") { - settings.vlan_enabled = d.value[0]; - } - return 0; -} -======= switch (d.type) { case RCV_TYPE: device.type = d.value; @@ -113,4 +64,3 @@ int Switch::parse(dataset d) { return 0; } ->>>>>>> 3ef2da7b7a10c8b34f20c452acc0f8d0ffc17db5 From 299490ca5f132065501ee556f3d0193638a4e0a6 Mon Sep 17 00:00:00 2001 From: /jedi/ Date: Thu, 28 Jan 2016 00:37:13 +0100 Subject: [PATCH 3/5] clean up --- Makefile | 2 +- src/Constant.h | 65 +++----- src/Interactive.cpp | 33 ++++ src/Interactive.h | 18 +++ src/Packet.cpp | 8 + src/Packet.h | 4 +- src/Program.cpp | 333 +++++++++++++++++++++++---------------- src/Program.h | 8 +- src/Socket.cpp | 8 +- src/Socket.h | 2 +- src/Switch-Json.cpp | 2 +- src/Switch.cpp | 7 +- src/Switch.h | 1 + src/Types.h | 141 +++++++++-------- src/bytes.h | 1 + src/datasets.h | 8 + src/lookup.h | 4 +- src/smrtlink.cpp | 370 +++++++++++++++++++++++++------------------- src/table.cpp | 33 +++- src/table.h | 19 ++- 20 files changed, 638 insertions(+), 429 deletions(-) create mode 100644 src/Interactive.cpp create mode 100644 src/Interactive.h diff --git a/Makefile b/Makefile index 2404b58..5743050 100644 --- a/Makefile +++ b/Makefile @@ -15,7 +15,7 @@ $(BUILDDIR): $(TARGET): $(OBJECTS) - $(CC) $^ -o $(BUILDDIR)/$@ -lboost_filesystem -lboost_system + $(CC) $^ -o $(BUILDDIR)/$@ -lboost_filesystem -lboost_system -lpthread $(OBJECTS): $(BUILDDIR)/%.o : $(SOURCEDIR)/%.cpp diff --git a/src/Constant.h b/src/Constant.h index 31e73fc..ecc44a4 100644 --- a/src/Constant.h +++ b/src/Constant.h @@ -11,41 +11,31 @@ #include "Types.h" #define VERSION "smrtlink (v1.1 Linux)\n" -#define USAGE "usage: %s [-bdhjrvswx] [-i interface] [-u [password:]username]\n\ - [-p password] \n\n" +#define USAGE "usage: %s [-bhrVstx] [-i interface] [-U [password:]username]\n\ + [-P password] \n\n" #define HELP "\ - Option Summary:\n\ - -h --help This help text\n\ - -v --version Display version of this tool\n\ - -d --debug [n] Show debugging messages\n\ - -r switch ports to emulate switch while sniffing\n\ - -b --header Show header\n\ - -x --hex Display Packets as Hex String\n\ - -j --json Display Packets as JSON\n\ - -i --interface only use one Interface\n\ - -u --user <[password:]username>\n\ - -p --password \n\ - Login with Username and Password\n\ - -f --file choose a settings file\n\n\ - -t --timeout Timeout in milliseconds. Default: 180\n\ - -I --interactive Not yet implemented\n\ - -O --stdout Not yet implemented\n\ - -w --wait Not yet implemented: blocking until operation is completed\n\ - -s --permanent Not yet implemented: make changes immediately permanent\n\n\ - Command Summary:\n\ - help This help text\n\ - list list all connected switches\n\ - sniff [type:] []\n\ - capture and display all incoming or outgoing packets\n\ - depending on the --reverse option\n\ - encode use encoding algorithm on hex data separated by colon\n\ - get Not yet implemented\n\ - set Not yet implemented\n\ - get|save Not yet implemented: save config to file\n\ - set|restore Not yet implemented: restore onfig from file\n\ - flash Not yet implemented: replace firmware\n\ - reboot Not yet implemented\n\ - reset Not yet implemented\n\n\ + Option Summary:\n\ + -h --help This help text\n\ + -V --version Display version of this tool\n\ +\ + -r --reverse switch ports to emulate switch while sniffing\n\ + -i --interface only use one Interface\n\ + -t --timeout Timeout in milliseconds. Default: 180\n\ + -s --permanent make changes immediately permanent\n\ +\ + -b --header Show header\n\ + -x --hex Display Packets as Hex String\n\ +\ + -U --user <[password:]username>\n\ + -P --password \n\ + Login with Username and Password\n\n\ + Command Summary:\n\ + list list all connected switches\n\ + sniff capture and display all incoming or outgoing packets\n\ + depending on the --reverse option\n\ + encode use encoding algorithm on hex data separated by colon\n\ + reboot Not yet implemented\n\ + reset Not yet implemented\n\n\ ### for questions please contact ###\n\n" //TODO /* @@ -54,13 +44,6 @@ * */ -#define FLAG_HEX 1 -#define FLAG_REVERSE 2 -#define FLAG_HEADER 4 -#define FLAG_PERMANENT 8 -#define FLAG_WAIT 16 -#define FLAG_DEBUG 32 - extern Options options; #endif /* OPTIONS_H_ */ diff --git a/src/Interactive.cpp b/src/Interactive.cpp new file mode 100644 index 0000000..6875dc2 --- /dev/null +++ b/src/Interactive.cpp @@ -0,0 +1,33 @@ +/* + * Interactive.cpp + * + * Created on: 27.01.2016 + * Author: jedi + */ + +#include +#include + +#include "Interactive.h" + +using namespace std; + +Interactive::Interactive() { + // TODO Auto-generated constructor stub + +} + +Interactive::~Interactive() { + // TODO Auto-generated destructor stub +} + +int Interactive::run() { + string cmd; + while(cmd.compare("quit")){ + cout<< "smrtlink>" << flush; + cin >> cmd; + cout << cmd <opCode = opCode; +} + void Packet::pull(bytes &arr, int &index, dataset &ret) { pull(arr, index, ret.type); pull(arr, index, ret.len); diff --git a/src/Packet.h b/src/Packet.h index 327e713..2e04a2d 100644 --- a/src/Packet.h +++ b/src/Packet.h @@ -20,7 +20,7 @@ class Packet public: enum OpCode {DISCOVERY, GET, RETURN, SET, CONFIRM, NONE}; Packet(OpCode); - void encode(bytes&); + static void encode(bytes&); bytes getBytes(); void parse(bytes); void printHeader(); @@ -41,6 +41,8 @@ public: void setPayload(datasets payload); short getTokenId() const; void setTokenId(short tokenId = 0); + byte getOpCode() const; + void setOpCode(byte opCode); private: bytes head = bytes(32); diff --git a/src/Program.cpp b/src/Program.cpp index 636ed70..33f27d7 100644 --- a/src/Program.cpp +++ b/src/Program.cpp @@ -17,10 +17,12 @@ #include "lookup.h" #include "table.h" +using namespace std; + int printHeader(Packet p) { - if (options.flags & FLAG_HEADER) { - if (options.flags & FLAG_HEX) { - std::cout << "Received Header:\n\t" << p.getHead() << "\n"; + if (options.flags.HEADER) { + if (options.flags.HEX) { + cout << "Received Header:\n\t" << p.getHead() << "\n"; } else { p.printHeader(); printf("\n"); @@ -30,56 +32,51 @@ int printHeader(Packet p) { } int printPacket(Packet p) { - if (options.flags & FLAG_HEX) { - std::cout << "Received Payload:\n\t" << p.getBody() << "\n"; + if (options.flags.HEX) { + cout << "Received Payload:\n\t" << p.getBody() << "\n"; } else { for (dataset d : p.getPayload()) { - auto lookup = - (options.flags & FLAG_REVERSE) ? snd_lookup : rcv_lookup; + auto lookup = (options.flags.REVERSE) ? snd_lookup : rcv_lookup; if (lookup.exists(d.type)) { table::set s = lookup[d.type]; if (d.len > 0) { switch (s.format) { case table::STRING: - std::cout << "+\t" << s.name << " = " << &d.value[0] - << "\n"; + cout << "+\t" << s.name << " = " << &d.value[0] << "\n"; break; case table::BOOL: - std::cout << "+\t" << s.name << " = " + cout << "+\t" << s.name << " = " << (d.value[0] ? "YES" : "NO") << "\n"; break; case table::HEX: - std::cout << "+\t" << s.name << " = " << d.value - << "\n"; + cout << "+\t" << s.name << " = " << d.value << "\n"; break; case table::DEC: - std::cout << "+\t" << s.name << " = "; + cout << "+\t" << s.name << " = "; if (d.value.size() > 0) - std::cout << std::dec << (unsigned) d.value[0]; + cout << dec << (unsigned) d.value[0]; for (unsigned i = 1; i < d.value.size(); i++) - std::cout << std::dec << "." - << (unsigned) d.value[i]; - std::cout << "\n"; + cout << dec << "." << (unsigned) d.value[i]; + cout << "\n"; break; case table::ACTION: - std::cout << "Error:" << s.name + cout << "Error:" << s.name << " is marked as 'action' but carries payload." << d.value << "\n"; break; default: - std::cout << "+\t" << s.name << " = " << d.value - << "\n"; + cout << "+\t" << s.name << " = " << d.value << "\n"; break; } } else { //empty - std::cout << std::dec << ">\t" << s.name << "\n"; + cout << dec << ">\t" << s.name << "\n"; } } else { //unknown id if (d.len > 0) { - std::cout << "##\t" << d.type << ":\n\t"; - std::cout << std::hex << d.value << std::dec << "\n"; + cout << "##\t" << d.type << ":\n\t"; + cout << hex << d.value << dec << "\n"; } else { //empty - std::cout << "#>\t" << d.type << "\n"; + cout << "#>\t" << d.type << "\n"; } } } @@ -88,38 +85,27 @@ int printPacket(Packet p) { } int Program::list() { - - std::cout << "List:\n"; - Packet p = Packet(Packet::DISCOVERY); - p.setHostMac(host.getMac()); - p.setPayload( { }); - bytes b = p.getBytes(); - p.encode(b); - try { - sock->setHostIp(host.getIp()); - sock->init(DST_PORT, SRC_PORT); - sock->callback = - [this](Packet a) { - printHeader(a); - if (options.flags & FLAG_HEX) { - std::cout <<"Received Payload:\n"<send(b); + cout << "List:\n"; + discover([this](Packet a) { + printHeader(a); + if (options.flags.HEX) { + cout <<"Received Payload:\n"<run(); - } catch (std::exception& e) { - std::cerr << "Exception: " << e.what() << "\n"; + } catch (exception& e) { + cerr << "Exception: " << e.what() << "\n"; } - return 1; + return 0; } int Program::sniff() { @@ -130,102 +116,105 @@ int Program::sniff() { s.setHostIp(host.getIp()); s.init(DST_PORT, SRC_PORT); s.callback = [](Packet p) { - std::cout << p.opCodeToString() << "\n"; + cout << p.opCodeToString() << "\n"; printHeader(p); printPacket(p); return 0; }; s.listen(); io_service.run(); - } catch (std::exception& e) { - std::cerr << "Exception: " << e.what() << "\n"; + } catch (exception& e) { + cerr << "Exception: " << e.what() << "\n"; } - return 1; + return 0; } -int Program::encode(std::string s) { - bytes d(s); - Packet p = Packet(Packet::DISCOVERY); +int Program::encode(string s) { + bytes d; + d = d.readHex(s); + Packet p = Packet(Packet::NONE); p.encode(d); - std::cout << d << std::endl; + cout << d << endl; return 0; } -int Program::setProperty() { - return 0; -} - -int Program::getProperty() { - std::cout << "List:\n"; - Packet p = Packet(Packet::DISCOVERY); - p.setHostMac(host.getMac()); - p.setPayload( { }); - bytes b = p.getBytes(); - p.encode(b); - auto s = sock; +int Program::setProperty(map prop) { try { - sock->setHostIp(host.getIp()); - sock->init(DST_PORT, SRC_PORT); - sock->callback = - [this](Packet a) { - auto s = sock; - datasets d =a.getPayload(); - Switch sw = Switch(); - sw.parse(d); - std::cout <<"\t"<callback = - [this](Packet a) { - auto s = sock; + datasets t = { {SND_PING, 0, {}}}; + get(a, t, [this,data](Packet a) { datasets d =a.getPayload(); Switch sw = Switch(); sw.parse(d); - Packet p = Packet(Packet::SET); - p.setSwitchMac(a.getSwitchMac()); - p.setTokenId(a.getTokenId()); - p.setHostMac(host.getMac()); - bytes n = options.user; - bytes w = options.password; - n.push_back('\0'); - w.push_back('\0'); - datasets t = { - { LOGIN_USER, (short)(n.size()), n}, - { LOGIN_PASSWORD, (short)(w.size()), w}, - { REBOOT, 1, {0}} - }; - p.setPayload(t); - bytes c = p.getBytes(); - p.encode(c); + set(a,data, - sock->callback = - [this](Packet a) { - std::cout << a.opCodeToString() << "\n"; - printHeader(a); - printPacket(a); - return 0; - }; - sock->send(c); + [this](Packet a) { + cout << a.opCodeToString() << "\n"; + printHeader(a); + printPacket(a); + return 0; + }); return 0; - }; + }); + return 0; + }); - sock->send(c); - return 0; - }; - sock->send(b); io_service->run(); - } catch (std::exception& e) { - std::cerr << "Exception: " << e.what() << "\n"; + } catch (exception& e) { + cerr << "Exception: " << e.what() << "\n"; } - return 1; + return 0; +} + +int Program::getProperty(vector prop) { + try { + datasets data = { }; + for (string s : prop) { + dataset d; + d.type = snd_lookup.type(s); + data.push_back(d); + } + cout << "List:\n"; + discover([this,data](Packet a) { + datasets d =a.getPayload(); + Switch sw = Switch(); + sw.parse(d); + sw.print(); + get(a, data, [this](Packet a) { + cout << a.opCodeToString() << "\n"; + printHeader(a); + printPacket(a); + return 0; + }); + return 0; + }); + + io_service->run(); + } catch (exception& e) { + cerr << "Exception: " << e.what() << "\n"; + } + return 0; } int Program::save() { @@ -233,40 +222,118 @@ int Program::save() { sw.settings.hostname = "testname.lan"; File f; f.write(sw.toString()); - return 1; + return 0; } int Program::restore() { File f; Switch sw; sw.parse(f.read()); - std::cout << "Devices:\n\t" << sw.settings.hostname << " (" - << sw.device.type << ")\tMAC: " << sw.device.mac << "\tIP: " - << sw.settings.ip_addr << "\n"; - return 1; + sw.print(); + return 0; } int Program::flash() { - return 0; + return 1; } int Program::reboot() { - + try { + discover([this](Packet a) { + datasets d =a.getPayload(); + Switch sw = Switch(); + sw.parse(d); + cout <run(); + } catch (exception& e) { + cerr << "Exception: " << e.what() << "\n"; + } return 0; } int Program::reset() { - + try { + discover([this](Packet a) { + datasets d =a.getPayload(); + Switch sw = Switch(); + sw.parse(d); + cout <run(); + } catch (exception& e) { + cerr << "Exception: " << e.what() << "\n"; + } return 0; } -int Program::ping(std::function) { +int Program::discover(function c) { + Packet p = Packet(Packet::DISCOVERY); + p.setHostMac(host.getMac()); + p.setPayload( { }); + sock->callback = c; + sock->send(p); + return 0; +} +int Program::get(Packet l, datasets t, function c) { + Packet p = Packet(Packet::GET); + p.setSwitchMac(l.getSwitchMac()); + p.setHostMac(host.getMac()); + p.setPayload(t); + sock->callback = c; + sock->send(p); + return 0; +} + +int Program::set(Packet l, datasets t, function c) { + Packet p = Packet(Packet::SET); + p.setSwitchMac(l.getSwitchMac()); + p.setTokenId(l.getTokenId()); + p.setHostMac(host.getMac()); + bytes n = options.user; + bytes w = options.password; + datasets ld = { { LOGIN_USER, (short) (n.size()), n }, { LOGIN_PASSWORD, + (short) (w.size()), w } }; + p.setPayload(ld + t); + sock->callback = c; + sock->send(p); return 0; } void Program::init() { if (options.interface.compare("") == 0) options.interface = host.getIface(); + + sock->setHostIp(host.getIp()); + sock->init(DST_PORT, SRC_PORT); } diff --git a/src/Program.h b/src/Program.h index 1bd97da..614047c 100644 --- a/src/Program.h +++ b/src/Program.h @@ -19,7 +19,9 @@ private: std::shared_ptr io_service; std::shared_ptr sock; Host host = Host(); - int ping(std::function); + int get(Packet,datasets,std::function); + int set(Packet,datasets,std::function); + int discover(std::function); public: Program() { io_service = std::make_shared(); @@ -29,8 +31,8 @@ public: int list(); int sniff(); int encode(std::string); - int setProperty(); - int getProperty(); + int getProperty(std::vector); + int setProperty(std::map); int save(); int restore(); int flash(); diff --git a/src/Socket.cpp b/src/Socket.cpp index 191971e..2d0e363 100644 --- a/src/Socket.cpp +++ b/src/Socket.cpp @@ -21,13 +21,13 @@ void Socket::init(short dst_port, short src_port) { if (initialized) return; - if (options.flags & FLAG_REVERSE) { + if (options.flags.REVERSE) { short p = dst_port; dst_port = src_port; src_port = p; } - if (options.flags & FLAG_DEBUG) + if (options.debug_level>=1) std::cout << "Local IP:\t" << local_ip << "\n"; wildcard_endpoint_ = boost::asio::ip::udp::endpoint( @@ -67,7 +67,9 @@ void Socket::setHostIp(ipAddr ip) { local_ip = ip; } -void Socket::send(bytes data) { +void Socket::send(Packet p) { + bytes data = p.getBytes(); + p.encode(data); unsigned char * a = &data[0]; send_socket_.async_send_to(boost::asio::buffer(a, data.size()), broadcast_endpoint_, diff --git a/src/Socket.h b/src/Socket.h index 6bda28a..7abce0d 100644 --- a/src/Socket.h +++ b/src/Socket.h @@ -23,7 +23,7 @@ public: virtual ~Socket() { } void init(short, short); - void send(bytes); + void send(Packet); void listen(); void setHostIp(ipAddr); std::function callback = [](Packet a) { diff --git a/src/Switch-Json.cpp b/src/Switch-Json.cpp index 21f1477..c94961c 100644 --- a/src/Switch-Json.cpp +++ b/src/Switch-Json.cpp @@ -16,7 +16,7 @@ int Switch::parse(std::string str) { if (json.Parse(str.c_str()).HasParseError()) return 1; - if (options.flags & FLAG_DEBUG) + if (options.debug_level>=1) std::cout << "\nParsing to document succeeded.\n"; if (json.IsObject()) { diff --git a/src/Switch.cpp b/src/Switch.cpp index 89419a8..0d6966e 100644 --- a/src/Switch.cpp +++ b/src/Switch.cpp @@ -19,6 +19,12 @@ int Switch::parse(datasets arr) { return 0; } +int Switch::print() { + std::cout << "\t" << settings.hostname << " (" << device.type << ")\tMAC: " + << device.mac << "\tIP: " << settings.ip_addr << "\n"; + return 0; +} + int Switch::parse(dataset d) { switch (d.type) { case RCV_TYPE: @@ -63,4 +69,3 @@ int Switch::parse(dataset d) { } return 0; } - diff --git a/src/Switch.h b/src/Switch.h index 88a3351..1b40071 100644 --- a/src/Switch.h +++ b/src/Switch.h @@ -65,6 +65,7 @@ public: int parse(datasets); int parse(dataset); int parse(std::string); + int print(); std::string toString(); struct { diff --git a/src/Types.h b/src/Types.h index 019c07f..489529a 100644 --- a/src/Types.h +++ b/src/Types.h @@ -21,105 +21,114 @@ class macAddr: public std::array { public: - friend std::ostream& operator<<(std::ostream& out, const macAddr& arr) { - out << std::hex << std::setw(2) << std::setfill('0') - << (unsigned) arr[0]; - for (unsigned i = 1; i < 6; i++) { - out << ":" << std::setw(2) << std::setfill('0') - << (unsigned) arr[i]; - } - return out; - } + friend std::ostream& operator<<(std::ostream& out, const macAddr& arr) { + out << std::hex << std::setw(2) << std::setfill('0') + << (unsigned) arr[0]; + for (unsigned i = 1; i < 6; i++) { + out << ":" << std::setw(2) << std::setfill('0') + << (unsigned) arr[i]; + } + return out; + } - macAddr() { - *this= {0,0,0,0,0,0}; - } + macAddr() { + *this= {0,0,0,0,0,0}; + } - macAddr(std::initializer_list s) { - int i = 0; + macAddr(std::initializer_list s) { + int i = 0; for (byte b : s) { - if(i<6) (*this)[i++]=b; - else break; + if(i<6) (*this)[i++]=b; + else break; } - } + } - macAddr(bytes bts) { - int i = 0; + macAddr(bytes bts) { + int i = 0; for (byte b : bts) { - if(i<6) (*this)[i++]=b; - else break; + if(i<6) (*this)[i++]=b; + else break; } - } + } }; /* -class mac_addr : public std::array { -public: - typedef std::array super; + class mac_addr : public std::array { + public: + typedef std::array super; - using super::super; - - mac_addr{00, 00, 00, 000}; -}; -*/ + using super::super; + mac_addr{00, 00, 00, 000}; + }; + */ class ipAddr: public std::array { public: - ipAddr() { - *this= {0,0,0,0,0,0}; - } + ipAddr() { + *this= {0,0,0,0,0,0}; + } - ipAddr(std::initializer_list s) { - int i = 0; - for (byte b : s) { - if(i<4) (*this)[i++]=b; - else break; + ipAddr(std::initializer_list s) { + int i = 0; + for (byte b : s) { + if(i<4) (*this)[i++]=b; + else break; } - } + } - ipAddr(bytes bts) { - int i = 0; + ipAddr(bytes bts) { + int i = 0; for (byte b : bts) { - if(i<4) (*this)[i++]=b; - else break; + if(i<4) (*this)[i++]=b; + else break; } - } + } - friend std::ostream& operator<<(std::ostream& out, ipAddr& arr) { - out << std::dec << (unsigned) arr[0]; - for (unsigned i = 1; i < 4; i++) { - out << "." << (unsigned) arr[i]; - } - return out; - } + friend std::ostream& operator<<(std::ostream& out, ipAddr& arr) { + out << std::dec << (unsigned) arr[0]; + for (unsigned i = 1; i < 4; i++) { + out << "." << (unsigned) arr[i]; + } + return out; + } }; template std::vector operator+(const std::vector &A, const std::vector &B) { - std::vector AB; - AB.reserve(A.size() + B.size()); // preallocate memory - AB.insert(AB.end(), A.begin(), A.end()); // add A; - AB.insert(AB.end(), B.begin(), B.end()); // add B; - return AB; + std::vector AB; + AB.reserve(A.size() + B.size()); // preallocate memory + AB.insert(AB.end(), A.begin(), A.end()); // add A; + AB.insert(AB.end(), B.begin(), B.end()); // add B; + return AB; } template std::vector &operator+=(std::vector &A, const std::vector &B) { - A.reserve(A.size() + B.size()); - A.insert(A.end(), B.begin(), B.end()); - return A; + A.reserve(A.size() + B.size()); + A.insert(A.end(), B.begin(), B.end()); + return A; } struct Options { - unsigned flags = 0x00; - std::string user; - std::string password; - std::string interface; - std::string file; - int debug_level=0; - long timeout = 180U; + struct { + bool HEX; + bool JSON; + bool PLAIN; + bool REVERSE; + bool HEADER; + bool PERMANENT; + bool WAIT; + bool INTERACTIVE; + } flags; + std::string user; + std::string password; + std::string interface; + std::string file; + int debug_level = 0; + int verbosity = 0; + long timeout = 180U; }; #endif /* TYPES_H_ */ diff --git a/src/bytes.h b/src/bytes.h index eb129d6..01f597d 100644 --- a/src/bytes.h +++ b/src/bytes.h @@ -28,6 +28,7 @@ public: } bytes(std::string d) : vector(d.begin(), d.end()){ + this->push_back('\0'); } bytes(std::initializer_list s) diff --git a/src/datasets.h b/src/datasets.h index bc9ac83..7b08f4f 100644 --- a/src/datasets.h +++ b/src/datasets.h @@ -27,6 +27,14 @@ public: push_back(b); } } + + datasets operator+(const datasets &B) { + datasets AB; + AB.reserve(this->size() + B.size()); + AB.insert(AB.end(), this->begin(), this->end()); + AB.insert(AB.end(), B.begin(), B.end()); + return AB; + } }; #endif /* DATASETS_H_ */ diff --git a/src/lookup.h b/src/lookup.h index a51f9bf..179c638 100644 --- a/src/lookup.h +++ b/src/lookup.h @@ -15,14 +15,14 @@ enum { }; static table rcv_lookup { -#define LOOKUP_SET(id, num, type) { RCV_ ## id, table::type, #id }, +#define LOOKUP_SET(id, num, type) { RCV_ ## id, table::type,#id, #id }, #include "lookup/rcv.lst" #include "lookup/general.lst" #undef LOOKUP_SET }; static table snd_lookup { -#define LOOKUP_SET(id, num, type) { SND_ ## id, table::type, #id }, +#define LOOKUP_SET(id, num, type) { SND_ ## id, table::type,#id, #id }, #include "lookup/snd.lst" #include "lookup/general.lst" #undef LOOKUP_SET diff --git a/src/smrtlink.cpp b/src/smrtlink.cpp index 8a821ee..7a76c1e 100644 --- a/src/smrtlink.cpp +++ b/src/smrtlink.cpp @@ -6,216 +6,262 @@ // Description : SmrtLink in C++, Ansi-style //============================================================================ -#include #include -#include #include +#include + +#include +#include #include -#include #include #include #include "Constant.h" +#include "Interactive.h" #include "Host.h" #include "Program.h" #include "Switch.h" +#include "lookup.h" #define no_argument 0 #define required_argument 1 #define optional_argument 2 +using namespace std; + Options options; constexpr unsigned int caseArg(const char* str, int h = 0) { - return !str[h] ? 5381 : (caseArg(str, h + 1) * 33) ^ str[h]; + return !str[h] ? 5381 : (caseArg(str, h + 1) * 33) ^ str[h]; } int main(int argc, char *argv[]) { - int opt, index; + int index,opt; - options.user = DEFAULT_USER; - options.password = DEFAULT_PASS; + options.user = DEFAULT_USER; + options.password = DEFAULT_PASS; - const struct option longopts[] = { { "version", no_argument, 0, 'v' }, { - "help", no_argument, 0, 'h' }, { "reverse", no_argument, 0, 'r' }, { - "permanent", no_argument, 0, 's' }, { "debug", optional_argument, 0, - 'd' }, { "password", required_argument, 0, 'p' }, { "user", - required_argument, 0, 'u' }, { "interface", required_argument, 0, 'i' }, { - "header", required_argument, 0, 'b' }, { "hex", required_argument, - 0, 'x' }, { "file", required_argument, 0, 'f' }, { "timeout", - required_argument, 0, 't' }, { "wait", - required_argument, 0, 'w' }, { 0, 0, 0, 0 }, }; + const struct option longopts[] = { { "version", no_argument, 0, 'V' }, { + "verbose", no_argument, 0, 'v' }, { "help", no_argument, 0, 'h' }, { + "reverse", no_argument, 0, 'r' }, + { "permanent", no_argument, 0, 's' }, { "debug", optional_argument, + 0, 'd' }, { "password", required_argument, 0, 'P' }, { + "user", required_argument, 0, 'U' }, { "interface", + required_argument, 0, 'i' }, { "header", required_argument, + 0, 'b' }, { "hex", required_argument, 0, 'x' }, { "file", + required_argument, 0, 'f' }, { "timeout", required_argument, + 0, 't' }, { "wait", required_argument, 0, 'w' }, { 0, 0, 0, + 0 }, }; - Program p = Program(); - while ((opt = getopt_long(argc, argv, "bhrvswxp:u:i:f:t:d::", longopts, - &index)) != -1) { - switch (opt) { - case 'h': - fprintf(stderr, VERSION); - fprintf(stderr, USAGE, argv[0]); - fprintf(stderr, HELP); - exit(EXIT_SUCCESS); - break; + while ((opt = getopt_long(argc, argv, "bhrVsxP:U:i:t::", longopts, + &index)) != -1) { + switch (opt) { - case 'v': - fprintf(stderr, VERSION); - exit(EXIT_SUCCESS); - break; + case 'h': + fprintf(stderr, VERSION); + fprintf(stderr, USAGE, argv[0]); + fprintf(stderr, HELP); + exit(EXIT_SUCCESS); + break; - case 'r': - options.flags |= FLAG_REVERSE; - break; + case 'V': + fprintf(stderr, VERSION); + exit(EXIT_SUCCESS); + break; - case 'b': - options.flags |= FLAG_HEADER; - break; + case 'r': + options.flags.REVERSE = true; + break; - case 'x': - options.flags |= FLAG_HEX; - break; + case 'b': + options.flags.HEADER = true; + break; - case 's': - options.flags |= FLAG_PERMANENT; - break; + case 'x': + options.flags.HEX = true; + break; - case 'w': - options.flags |= FLAG_WAIT; - break; + case 's': + options.flags.PERMANENT = true; + break; - case 'd': - options.flags |= FLAG_DEBUG; - if (optarg != NULL) - options.debug_level = atoi(optarg); - break; + case 'w': + options.flags.WAIT = true; + break; - case 't': - options.timeout = atol(optarg); - break; + case 'X': + options.flags.INTERACTIVE = true; + break; - case 'f': - options.file = std::string(optarg); - break; + case 'v': + if (optarg != NULL) + options.verbosity = atoi(optarg); + else + options.verbosity++; + break; - case 'p': - options.password = std::string(optarg); - break; + case 'd': + if (optarg != NULL) + options.debug_level = atoi(optarg); + else + options.debug_level++; + break; - case 'u': - options.user = std::string(optarg); - break; + case 't': + options.timeout = atol(optarg); + break; - case 'i': - options.interface = std::string(optarg); - break; + case 'f': + options.file = std::string(optarg); + break; - default: /* '?' */ - fprintf(stderr, "Unknown option\n"); - fprintf(stderr, USAGE, argv[0]); - exit(EXIT_FAILURE); - } - } + case 'P': + options.password = std::string(optarg); + break; - /*//TODO stdin - std::ostringstream bucket; - bucket << std::cin.rdbuf(); - p.input = bucket.str(); - */ + case 'U': + options.user = std::string(optarg); + break; - if (optind >= argc) { - fprintf(stderr, "Command expected\n"); - fprintf(stderr, USAGE, argv[0]); - exit(EXIT_FAILURE); - } + case 'i': + options.interface = std::string(optarg); + break; - p.init(); + default: /* '?' */ + fprintf(stderr, "Unknown option\n"); + fprintf(stderr, USAGE, argv[0]); + exit(EXIT_FAILURE); + } + } - if (optind < argc) { - std::string cmd = std::string(argv[optind++]); + /*//TODO stdin + std::ostringstream bucket; + bucket << std::cin.rdbuf(); + p.input = bucket.str(); + */ - switch (caseArg(cmd.c_str())) { - case caseArg("set"): - if (p.setProperty()) - exit(EXIT_SUCCESS); - fprintf(stderr, "Not yet implemented.\n"); - exit(EXIT_FAILURE); - break; - case caseArg("reboot"): - if (p.reboot()) - exit(EXIT_SUCCESS); - fprintf(stderr, "Not yet implemented.\n"); - exit(EXIT_FAILURE); - break; - case caseArg("reset"): - if (p.reset()) - exit(EXIT_SUCCESS); - fprintf(stderr, "Not yet implemented.\n"); - exit(EXIT_FAILURE); - break; - case caseArg("save"): - if (p.save()) - exit(EXIT_SUCCESS); - fprintf(stderr, "Not yet implemented.\n"); - exit(EXIT_FAILURE); - break; - case caseArg("restore"): - if (p.restore()) - exit(EXIT_SUCCESS); - fprintf(stderr, "Not yet implemented.\n"); - exit(EXIT_FAILURE); - break; - case caseArg("flash"): - if (p.flash()) - exit(EXIT_SUCCESS); - fprintf(stderr, "Not yet implemented.\n"); - exit(EXIT_FAILURE); - break; + if (optind >= argc && !options.flags.INTERACTIVE) { + cerr << "Command expected\n"; + cerr << USAGE; + exit(EXIT_FAILURE); + } - case caseArg("get"): - if (p.getProperty()) - exit(EXIT_SUCCESS); - break; + if (options.flags.INTERACTIVE) { + if (optind < argc) { + cerr << "Command is ignored in interactive mode\n"; + } + Interactive p = Interactive(); + if (!p.run()) + exit(EXIT_SUCCESS); + fprintf(stderr, "Not yet implemented.\n"); + exit(EXIT_FAILURE); + } + else if (optind < argc) { + Program p = Program(); + p.init(); + std::vector vect; + std::map list; + std::cmatch sm; + std::string cmd = std::string(argv[optind++]); + switch (caseArg(cmd.c_str())) { + case caseArg("reboot"): + if (!p.reboot()) + exit(EXIT_SUCCESS); + fprintf(stderr, "Not yet implemented.\n"); + exit(EXIT_FAILURE); + break; + case caseArg("reset"): + if (!p.reset()) + exit(EXIT_SUCCESS); + fprintf(stderr, "Not yet implemented.\n"); + exit(EXIT_FAILURE); + break; + case caseArg("save"): + if (!p.save()) + exit(EXIT_SUCCESS); + fprintf(stderr, "Not yet implemented.\n"); + exit(EXIT_FAILURE); + break; + case caseArg("restore"): + if (!p.restore()) + exit(EXIT_SUCCESS); + fprintf(stderr, "Not yet implemented.\n"); + exit(EXIT_FAILURE); + break; + case caseArg("flash"): + if (!p.flash()) + exit(EXIT_SUCCESS); + fprintf(stderr, "Not yet implemented.\n"); + exit(EXIT_FAILURE); + break; - case caseArg("list"): - if (p.list()) - exit(EXIT_SUCCESS); - break; + case caseArg("list"): + if (!p.list()) + exit(EXIT_SUCCESS); + break; - case caseArg("sniff"): - if (p.sniff()) - exit(EXIT_SUCCESS); - break; + case caseArg("sniff"): + if (!p.sniff()) + exit(EXIT_SUCCESS); + break; - case caseArg("encode"): - if (optind < argc) { - std::string s(argv[optind]); - optind++; - if (p.encode(s)) - exit(EXIT_SUCCESS); - } else { - fprintf(stderr, "Argument expected after encode\n"); - exit(EXIT_FAILURE); - } - break; - - case caseArg("help"): - fprintf(stderr, VERSION); - fprintf(stderr, USAGE, argv[0]); - fprintf(stderr, HELP); - exit(EXIT_SUCCESS); - break; - - default: - printf("Unknown command: %s\n", cmd.c_str()); - while (optind < argc) { - printf("->%s\n", argv[optind]); - optind++; - } - exit(EXIT_FAILURE); - } - } - exit(EXIT_FAILURE); + case caseArg("encode"): + if (optind < argc) { + std::string s(argv[optind]); + optind++; + if (p.encode(s)) + exit(EXIT_SUCCESS); + } else { + fprintf(stderr, "Argument expected after encode\n"); + exit(EXIT_FAILURE); + } + break; + case caseArg("set"): + while (optind < argc) { + if (regex_match(argv[optind], sm, + std::regex("^([a-z]+)=(.*)$"))) { + if (!snd_lookup.exists(sm[1])&&!rcv_lookup.exists(sm[1])) { + cerr << "Unknown argument " << argv[optind] << endl; + exit(EXIT_FAILURE); + } + list.insert( + std::pair(sm[1], sm[2])); + } else { + cerr << "Invalid Syntax " << argv[optind] << endl; + exit(EXIT_FAILURE); + } + optind++; + } + if (!p.setProperty(list)) + exit(EXIT_SUCCESS); + fprintf(stderr, "Not yet implemented.\n"); + exit(EXIT_FAILURE); + break; + case caseArg("get"): + while (optind < argc) { + if (regex_match(argv[optind], sm, std::regex("^([a-z]+)$"))) { + if (!snd_lookup.exists(sm[1])&&!rcv_lookup.exists(sm[1])) { + cerr << "Unknown argument " << argv[optind] << endl; + exit(EXIT_FAILURE); + } + vect.push_back(sm[1]); + } else { + cerr << "Invalid argument " << argv[optind] << endl; + exit(EXIT_FAILURE); + } + optind++; + } + if (!p.getProperty(vect)) + exit(EXIT_SUCCESS); + break; + default: + printf("Unknown command: %s\n", cmd.c_str()); + exit(EXIT_FAILURE); + } + } + exit(EXIT_FAILURE); } diff --git a/src/table.cpp b/src/table.cpp index e207490..f159ced 100644 --- a/src/table.cpp +++ b/src/table.cpp @@ -8,18 +8,35 @@ #include #include "table.h" + table::table(std::initializer_list l) { - int i = 0; - for (set s : l) { - this->left[s.type] = s; - } + int i = 0; + this->data.resize(l.size()); + for (set s : l) { + this->data[i] = s; + this->left[s.type] = &this->data[i]; + this->right[s.name] = &this->data[i]; + i++; + } } -table::set table::operator[](short n){ - return this->left[n]; +const table::set table::operator[](std::string s){ + return *this->right[s]; +} +const table::set table::operator[](short n){ + return *this->left[n]; +} +bool table::exists(std::string s){ + return !(right.find(s) == right.end()); } bool table::exists(short n){ - return !(left.find(n) == left.end()); + return !(left.find(n) == left.end()); +} +short table::type(std::string s){ + return this->right[s]->type; +} +std::string table::id(short n){ + return this->left[n]->id; } std::string table::name(short n){ - return this->left[n].name; + return this->left[n]->name; } diff --git a/src/table.h b/src/table.h index 377c768..128d26e 100644 --- a/src/table.h +++ b/src/table.h @@ -17,14 +17,21 @@ public: struct set { short type; F format; - std::string name; + std::string name; + std::string id; }; - table(std::initializer_list l); - set operator[](short); - bool exists(short); - std::string name(short); + table(std::initializer_list l); + const table::set operator[](std::string); + const table::set operator[](short); + bool exists(std::string); + bool exists(short); + short type(std::string); + std::string id(short); + std::string name(short); private: - std::map left; + std::vector data; + std::map left; + std::map right; }; #endif /* LOOKUPTABLE_H_ */ From 0f01d375dbf8e09a81d88349cf61ae1a2b191d60 Mon Sep 17 00:00:00 2001 From: /jedi/ Date: Tue, 23 Feb 2016 21:47:45 +0100 Subject: [PATCH 4/5] 1.2 --- Makefile | 3 +- README.md | 6 +- src/Interactive.cpp | 41 ++++++---- src/Interactive.h | 9 ++- src/Packet.cpp | 4 +- src/Packet.h | 21 ++--- src/Program.cpp | 186 +++++++++++++++++++++++++++++++++----------- src/Program.h | 48 +++++++----- src/Socket.cpp | 80 ++++++++++++------- src/Socket.h | 44 ++++++----- src/Switch.h | 6 +- src/Types.h | 33 +++++++- src/smrtlink.cpp | 128 ++++-------------------------- 13 files changed, 347 insertions(+), 262 deletions(-) diff --git a/Makefile b/Makefile index 5743050..a031fb5 100644 --- a/Makefile +++ b/Makefile @@ -15,8 +15,7 @@ $(BUILDDIR): $(TARGET): $(OBJECTS) - $(CC) $^ -o $(BUILDDIR)/$@ -lboost_filesystem -lboost_system -lpthread - + $(CC) $^ -o $(BUILDDIR)/$@ -lboost_filesystem -lboost_system -lreadline -lboost_program_options $(OBJECTS): $(BUILDDIR)/%.o : $(SOURCEDIR)/%.cpp $(CC) $(CFLAGS) $< -o $@ diff --git a/README.md b/README.md index 36f6447..cd00218 100644 --- a/README.md +++ b/README.md @@ -3,8 +3,10 @@ Command-Line Tool which might in the future be able to configure TP-Link Easy Sm The usage is loosely based on the swconfig utility. ### dependencys - libboost-filesystem-dev - libboost-system-dev + libboost-filesystem + libboost-system + libboost-program-options + libreadline ### compatible devices + TL-SG105E diff --git a/src/Interactive.cpp b/src/Interactive.cpp index 6875dc2..19ab930 100644 --- a/src/Interactive.cpp +++ b/src/Interactive.cpp @@ -7,27 +7,40 @@ #include #include +#include +#include +#include +#include +#include + +#include "Program.h" #include "Interactive.h" using namespace std; -Interactive::Interactive() { - // TODO Auto-generated constructor stub - -} - -Interactive::~Interactive() { - // TODO Auto-generated destructor stub -} - -int Interactive::run() { +int Interactive::loop() { string cmd; - while(cmd.compare("quit")){ - cout<< "smrtlink>" << flush; - cin >> cmd; - cout << cmd < v; + Program p = Program(); + p.init(); + while (1) { + cmd = readline("smrtlink> "); + if (!cmd.compare("quit") || !cmd.compare("q")) + return 0; + if (!cmd.empty()) { + add_history(cmd.c_str()); + v = boost::program_options::split_unix(cmd); + p.run(v); + } } return 0; } +int Interactive::single(vector v) { + Program p = Program(); + p.init(); + p.run(v); + return 0; +} + diff --git a/src/Interactive.h b/src/Interactive.h index 2bf41be..d1d974a 100644 --- a/src/Interactive.h +++ b/src/Interactive.h @@ -10,9 +10,12 @@ class Interactive { public: - Interactive(); - virtual ~Interactive(); - int run(); + Interactive() { + } + virtual ~Interactive() { + } + int loop(); + int single(std::vector v); }; #endif /* INTERACTIVE_H_ */ diff --git a/src/Packet.cpp b/src/Packet.cpp index 0e61bf7..9bcf06c 100644 --- a/src/Packet.cpp +++ b/src/Packet.cpp @@ -158,8 +158,8 @@ std::string Packet::opCodeToString() { return "SET"; case CONFIRM: return "CONFIRM"; - case RETURN: - return "RETURN"; + case REPLY: + return "REPLY"; default: return "NONE"; } diff --git a/src/Packet.h b/src/Packet.h index 2e04a2d..a34e1c9 100644 --- a/src/Packet.h +++ b/src/Packet.h @@ -13,12 +13,13 @@ #include "Types.h" -static short sequenceId=0; +static short sequenceId = 0; -class Packet -{ +class Packet { public: - enum OpCode {DISCOVERY, GET, RETURN, SET, CONFIRM, NONE}; + enum OpCode { + DISCOVERY, GET, REPLY, SET, CONFIRM, NONE + }; Packet(OpCode); static void encode(bytes&); bytes getBytes(); @@ -37,7 +38,7 @@ public: void setHostMac(macAddr); void setSwitchMac(macAddr); void setCheckSum(int); - void setSequenceId(short ); + void setSequenceId(short); void setPayload(datasets payload); short getTokenId() const; void setTokenId(short tokenId = 0); @@ -50,9 +51,9 @@ private: datasets payload; byte version = 1; byte opCode; - macAddr switchMac { {0, 0, 0, 0, 0, 0}}; - macAddr hostMac { {0, 0, 0, 0, 0, 0}}; - macAddr broadcastMac { {0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF}}; + macAddr switchMac { { 0, 0, 0, 0, 0, 0 } }; + macAddr hostMac { { 0, 0, 0, 0, 0, 0 } }; + macAddr broadcastMac { { 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF } }; short tokenId = 0; short fragmentOffset = 0; int errorCode = 0; @@ -60,7 +61,7 @@ private: short flag = 0; void buildHead(); void buildBody(); - void push(bytes&, int&, short ); + void push(bytes&, int&, short); void push(bytes&, int&, int); void push(bytes&, int&, byte); void push(bytes&, int&, bytes); @@ -70,7 +71,7 @@ private: void pull(bytes&, int&, short &); void pull(bytes&, int&, int&); void pull(bytes&, int&, byte&); - void pull(bytes&, int&, bytes&, unsigned ); + void pull(bytes&, int&, bytes&, unsigned); void pull(bytes&, int&, ipAddr&); void pull(bytes&, int&, macAddr&); void pull(bytes&, int&, dataset&); diff --git a/src/Program.cpp b/src/Program.cpp index 33f27d7..d14c7d1 100644 --- a/src/Program.cpp +++ b/src/Program.cpp @@ -6,6 +6,9 @@ */ #include #include +#include +#include +#include #include "Constant.h" #include "Program.h" @@ -14,11 +17,110 @@ #include "Socket.h" #include "Switch.h" #include "Packet.h" +#include "Filter.h" +#include "Types.h" #include "lookup.h" #include "table.h" +using namespace smrtlink; using namespace std; +int Program::run(vector arg) { + int optind = 0; + std::vector vect; + std::map ll; + std::cmatch sm; + std::string cmd = arg[optind++]; + + io_service->reset(); + sock->clear(); + switch (caseArg(cmd.c_str())) { + case caseArg("reboot"): + if (reboot()) + return 1; + break; + case caseArg("reset"): + if (!reset()) + return 0; + break; + case caseArg("save"): + if (save()) + return 1; + break; + case caseArg("restore"): + if (restore()) + return 1; + break; + case caseArg("flash"): + if (flash()) + return 1; + break; + + case caseArg("list"): + if (list()) + return 1; + break; + + case caseArg("sniff"): + if (sniff()) + return 1; + break; + + case caseArg("encode"): + if (optind < arg.size()) { + std::string s(arg[optind]); + optind++; + if (!encode(s)) + return 1; + } else { + fprintf(stderr, "Argument expected after encode\n"); + return 1; + } + break; + case caseArg("set"): + while (optind < arg.size()) { + if (regex_match(arg[optind].c_str(), sm, + std::regex("^([a-z]+)=(.*)$"))) { + if (!snd_lookup.exists(sm[1]) && !rcv_lookup.exists(sm[1])) { + cerr << "Unknown argument " << arg[optind] << endl; + return 1; + } + ll.insert(std::pair(sm[1], sm[2])); + } else { + cerr << "Invalid Syntax " << arg[optind] << endl; + return 1; + } + optind++; + } + if (setProperty(ll)) + return 1; + break; + case caseArg("get"): + while (optind < arg.size()) { + if (regex_match(arg[optind].c_str(), sm, + std::regex("^([a-z]+)$"))) { + if (!snd_lookup.exists(sm[1]) && !rcv_lookup.exists(sm[1])) { + cerr << "Unknown argument " << arg[optind] << endl; + return 1; + } + vect.push_back(sm[1]); + } else { + cerr << "Invalid argument " << arg[optind] << endl; + return 1; + } + optind++; + } + if (getProperty(vect)) + return 1; + break; + default: + printf("Unknown command: %s\n", cmd.c_str()); + return 1; + } + io_service->run(); + return 0; +} + int printHeader(Packet p) { if (options.flags.HEADER) { if (options.flags.HEX) { @@ -93,15 +195,18 @@ int Program::list() { cout <<"Received Payload:\n"<(b,Switch())); + devices[a.getSwitchMac().hash()].parse(d); + devices[a.getSwitchMac().hash()].print(); + File f; - f.write(sw.toString()); - sw.print(); + f.write(devices[a.getSwitchMac().hash()].toString()); } return 0; }); - io_service->run(); } catch (exception& e) { cerr << "Exception: " << e.what() << "\n"; } @@ -111,22 +216,15 @@ int Program::list() { int Program::sniff() { printf("Listening:\n"); try { - boost::asio::io_service io_service; - Socket s(io_service); - s.setHostIp(host.getIp()); - s.init(DST_PORT, SRC_PORT); - s.callback = [](Packet p) { + sock->listen([](Packet p) { cout << p.opCodeToString() << "\n"; printHeader(p); printPacket(p); return 0; - }; - s.listen(); - io_service.run(); + }); } catch (exception& e) { cerr << "Exception: " << e.what() << "\n"; } - return 0; } @@ -179,8 +277,6 @@ int Program::setProperty(map prop) { }); return 0; }); - - io_service->run(); } catch (exception& e) { cerr << "Exception: " << e.what() << "\n"; } @@ -210,7 +306,6 @@ int Program::getProperty(vector prop) { return 0; }); - io_service->run(); } catch (exception& e) { cerr << "Exception: " << e.what() << "\n"; } @@ -240,27 +335,27 @@ int Program::flash() { int Program::reboot() { try { - discover([this](Packet a) { - datasets d =a.getPayload(); - Switch sw = Switch(); - sw.parse(d); - cout <run(); + discover( + [this](Packet a) { + datasets d =a.getPayload(); + int b = a.getSwitchMac().hash(); + if (devices.empty()||devices.find(b) == devices.end()) + devices.insert(pair(b,Switch())); + devices[a.getSwitchMac().hash()].parse(d); + datasets t = { {SND_PING, 0, {}}}; + get(a, t, [this](Packet a) { + datasets d =a.getPayload(); + cout <run(); } catch (exception& e) { cerr << "Exception: " << e.what() << "\n"; } return 0; } -int Program::discover(function c) { +int Program::discover(Listener c) { Packet p = Packet(Packet::DISCOVERY); p.setHostMac(host.getMac()); p.setPayload( { }); - sock->callback = c; + sock->listen(c, Filter(Packet::REPLY)); sock->send(p); return 0; } -int Program::get(Packet l, datasets t, function c) { +int Program::get(Packet l, datasets t, Listener c) { Packet p = Packet(Packet::GET); p.setSwitchMac(l.getSwitchMac()); p.setHostMac(host.getMac()); p.setPayload(t); - sock->callback = c; + sock->listen(c, Filter(Packet::REPLY).mac(l.getSwitchMac())); sock->send(p); return 0; } -int Program::set(Packet l, datasets t, function c) { +int Program::set(Packet l, datasets t, Listener c) { Packet p = Packet(Packet::SET); p.setSwitchMac(l.getSwitchMac()); p.setTokenId(l.getTokenId()); @@ -325,12 +419,14 @@ int Program::set(Packet l, datasets t, function c) { datasets ld = { { LOGIN_USER, (short) (n.size()), n }, { LOGIN_PASSWORD, (short) (w.size()), w } }; p.setPayload(ld + t); - sock->callback = c; + sock->listen(c, Filter(Packet::CONFIRM).mac(l.getSwitchMac())); sock->send(p); return 0; } void Program::init() { + io_service = std::make_shared(); + sock = std::make_shared < Socket > (*io_service); if (options.interface.compare("") == 0) options.interface = host.getIface(); diff --git a/src/Program.h b/src/Program.h index 614047c..b039623 100644 --- a/src/Program.h +++ b/src/Program.h @@ -9,36 +9,42 @@ #define PROGRAM_H_ #include +#include #include "Types.h" #include "Host.h" +#include "Switch.h" #include "Socket.h" class Program { private: - std::shared_ptr io_service; - std::shared_ptr sock; - Host host = Host(); - int get(Packet,datasets,std::function); - int set(Packet,datasets,std::function); + std::shared_ptr io_service; + std::shared_ptr sock; + Host host = Host(); + std::map devices; + int get(Packet, datasets, std::function); + int set(Packet, datasets, std::function); int discover(std::function); public: - Program() { - io_service = std::make_shared(); - sock = std::make_shared(*io_service); - } - void init(); - int list(); - int sniff(); - int encode(std::string); - int getProperty(std::vector); - int setProperty(std::map); - int save(); - int restore(); - int flash(); - int reboot(); - int reset(); - std::string input; + Program() { + } + void init(); + int run(std::vector); + std::function callback = []() { + return 0; + }; + + int list(); + int sniff(); + int encode(std::string); + int getProperty(std::vector); + int setProperty(std::map); + int save(); + int restore(); + int flash(); + int reboot(); + int reset(); + std::string input; }; #endif /* PROGRAM_H_ */ diff --git a/src/Socket.cpp b/src/Socket.cpp index 2d0e363..f6d6282 100644 --- a/src/Socket.cpp +++ b/src/Socket.cpp @@ -5,29 +5,33 @@ * Author: jdi */ #include -#include +#include #include #include "Socket.h" #include "Packet.h" #include "Constant.h" +#include "Filter.h" #include "Host.h" #include "Types.h" +using namespace std; + Socket::Socket(boost::asio::io_service& io_service) : send_socket_(io_service), receive_socket_(io_service), timer(io_service) { } //, resolver( io_service) -void Socket::init(short dst_port, short src_port) { - if (initialized) - return; +Socket::~Socket() { +} + +void Socket::init(short dst_port, short src_port) { if (options.flags.REVERSE) { short p = dst_port; dst_port = src_port; src_port = p; } - if (options.debug_level>=1) + if (options.debug_level >= 1) std::cout << "Local IP:\t" << local_ip << "\n"; wildcard_endpoint_ = boost::asio::ip::udp::endpoint( @@ -47,26 +51,25 @@ void Socket::init(short dst_port, short src_port) { receive_socket_.set_option(boost::asio::socket_base::broadcast(true)); receive_socket_.set_option(boost::asio::socket_base::reuse_address(true)); receive_socket_.bind(wildcard_endpoint_); - - if (options.timeout != 0) { - timer.expires_from_now( - boost::posix_time::milliseconds(options.timeout)); - timer.async_wait([this](const boost::system::error_code& error) - { - if (!error) - { - receive_socket_.close(); - } - }); - } - - initialized = 1; } void Socket::setHostIp(ipAddr ip) { local_ip = ip; } +void Socket::clear(){ + callback.clear(); +} + +void Socket::listen(Listener l, Filter f) { + if (callback.find(f) == callback.end()) { + callback.insert(ListenerPair(f, l)); + } else { + callback[f] = l; + } + receive(); +} + void Socket::send(Packet p) { bytes data = p.getBytes(); p.encode(data); @@ -75,11 +78,12 @@ void Socket::send(Packet p) { broadcast_endpoint_, [this](boost::system::error_code ec, std::size_t bytes_sent) { - listen(); + receive(); + settimeout(); }); } -void Socket::listen() { +void Socket::receive() { data.resize(MAX_LENGTH); receive_socket_.async_receive_from(boost::asio::buffer(data, MAX_LENGTH), remote_endpoint_, @@ -92,13 +96,37 @@ void Socket::listen() { data.resize(bytes_recvd); Packet p = Packet(Packet::NONE); p.encode(data); - // std::cout << "err" << p.getErrorCode() < #include #include "Packet.h" +#include "Filter.h" #include "Types.h" #define SRC_PORT 29809 @@ -17,30 +19,32 @@ #define MAX_LENGTH 1024 +typedef std::function Listener; +typedef std::pair ListenerPair; + class Socket { public: - Socket(boost::asio::io_service&); - virtual ~Socket() { - } - void init(short, short); - void send(Packet); - void listen(); - void setHostIp(ipAddr); - std::function callback = [](Packet a) { - return 0; - }; + Socket(boost::asio::io_service&); + virtual ~Socket(); + void init(short, short); + void clear(); + void send(Packet); + void setHostIp(ipAddr); + void listen(Listener l, Filter f = Filter()); private: - boost::asio::ip::udp::socket send_socket_; - boost::asio::ip::udp::socket receive_socket_; - boost::asio::ip::udp::endpoint broadcast_endpoint_; - boost::asio::ip::udp::endpoint remote_endpoint_; - boost::asio::ip::udp::endpoint wildcard_endpoint_; - boost::asio::ip::udp::endpoint local_endpoint_; - boost::asio::deadline_timer timer; - bytes data = bytes(MAX_LENGTH); - ipAddr local_ip; - int initialized = 0; + void receive(); + void settimeout(); + boost::asio::ip::udp::socket send_socket_; + boost::asio::ip::udp::socket receive_socket_; + boost::asio::ip::udp::endpoint broadcast_endpoint_; + boost::asio::ip::udp::endpoint remote_endpoint_; + boost::asio::ip::udp::endpoint wildcard_endpoint_; + boost::asio::ip::udp::endpoint local_endpoint_; + boost::asio::deadline_timer timer; + bytes data = bytes(MAX_LENGTH); + ipAddr local_ip; + std::map callback = { }; }; diff --git a/src/Switch.h b/src/Switch.h index 1b40071..cb962ab 100644 --- a/src/Switch.h +++ b/src/Switch.h @@ -65,9 +65,13 @@ public: int parse(datasets); int parse(dataset); int parse(std::string); - int print(); + int set(std::pair); + + std::string get(std::string); std::string toString(); + int print(); + struct { std::string type; std::string hardware_version; diff --git a/src/Types.h b/src/Types.h index 489529a..b27657d 100644 --- a/src/Types.h +++ b/src/Types.h @@ -50,6 +50,28 @@ public: else break; } } + + int hash() { + int ret=0; + for (unsigned i = 0; i < 6; i++) { + ret = (ret*33) ^ (*this)[i]; + } + return ret; + } + + bool operator==(const macAddr &A) { + for (unsigned i = 0; i < 6; i++) { + if(A[i]!=(*this)[i])return false; + } + return true; + } + + bool operator!=(const macAddr &A) { + for (unsigned i = 0; i < 6; i++) { + if(A[i]!=(*this)[i])return true; + } + return false; + } }; /* @@ -95,6 +117,14 @@ public: } }; +namespace smrtlink { + +constexpr unsigned int caseArg(const char* str, int h = 0) { + return !str[h] ? 5381 : (caseArg(str, h + 1) * 33) ^ str[h]; +} + +} + template std::vector operator+(const std::vector &A, const std::vector &B) { std::vector AB; @@ -117,6 +147,7 @@ struct Options { bool JSON; bool PLAIN; bool REVERSE; + bool HEADER; bool PERMANENT; bool WAIT; @@ -128,7 +159,7 @@ struct Options { std::string file; int debug_level = 0; int verbosity = 0; - long timeout = 180U; + long timeout = 250U; }; #endif /* TYPES_H_ */ diff --git a/src/smrtlink.cpp b/src/smrtlink.cpp index 7a76c1e..735587c 100644 --- a/src/smrtlink.cpp +++ b/src/smrtlink.cpp @@ -1,14 +1,13 @@ //============================================================================ // Name : smrtlink.cpp // Author : jdi -// Version : +// Version : 1.2 // Copyright : GPL v2 // Description : SmrtLink in C++, Ansi-style //============================================================================ #include #include -#include #include #include @@ -21,6 +20,7 @@ #include "Interactive.h" #include "Host.h" #include "Program.h" +#include "Types.h" #include "Switch.h" #include "lookup.h" @@ -32,12 +32,8 @@ using namespace std; Options options; -constexpr unsigned int caseArg(const char* str, int h = 0) { - return !str[h] ? 5381 : (caseArg(str, h + 1) * 33) ^ str[h]; -} - int main(int argc, char *argv[]) { - int index,opt; + int index, opt; options.user = DEFAULT_USER; options.password = DEFAULT_PASS; @@ -56,7 +52,7 @@ int main(int argc, char *argv[]) { - while ((opt = getopt_long(argc, argv, "bhrVsxP:U:i:t::", longopts, + while ((opt = getopt_long(argc, argv, "bhrVXsxP:U:i:t::", longopts, &index)) != -1) { switch (opt) { @@ -149,118 +145,20 @@ int main(int argc, char *argv[]) { exit(EXIT_FAILURE); } + Interactive p = Interactive(); if (options.flags.INTERACTIVE) { if (optind < argc) { - cerr << "Command is ignored in interactive mode\n"; - } - Interactive p = Interactive(); - if (!p.run()) + cerr << "Command is ignored in interactive mode\n"; + } + if (!p.loop()) exit(EXIT_SUCCESS); fprintf(stderr, "Not yet implemented.\n"); exit(EXIT_FAILURE); - } - else if (optind < argc) { - Program p = Program(); - p.init(); - std::vector vect; - std::map list; - std::cmatch sm; - std::string cmd = std::string(argv[optind++]); - switch (caseArg(cmd.c_str())) { - case caseArg("reboot"): - if (!p.reboot()) - exit(EXIT_SUCCESS); - fprintf(stderr, "Not yet implemented.\n"); - exit(EXIT_FAILURE); - break; - case caseArg("reset"): - if (!p.reset()) - exit(EXIT_SUCCESS); - fprintf(stderr, "Not yet implemented.\n"); - exit(EXIT_FAILURE); - break; - case caseArg("save"): - if (!p.save()) - exit(EXIT_SUCCESS); - fprintf(stderr, "Not yet implemented.\n"); - exit(EXIT_FAILURE); - break; - case caseArg("restore"): - if (!p.restore()) - exit(EXIT_SUCCESS); - fprintf(stderr, "Not yet implemented.\n"); - exit(EXIT_FAILURE); - break; - case caseArg("flash"): - if (!p.flash()) - exit(EXIT_SUCCESS); - fprintf(stderr, "Not yet implemented.\n"); - exit(EXIT_FAILURE); - break; - - case caseArg("list"): - if (!p.list()) - exit(EXIT_SUCCESS); - break; - - case caseArg("sniff"): - if (!p.sniff()) - exit(EXIT_SUCCESS); - break; - - case caseArg("encode"): - if (optind < argc) { - std::string s(argv[optind]); - optind++; - if (p.encode(s)) - exit(EXIT_SUCCESS); - } else { - fprintf(stderr, "Argument expected after encode\n"); - exit(EXIT_FAILURE); - } - break; - case caseArg("set"): - while (optind < argc) { - if (regex_match(argv[optind], sm, - std::regex("^([a-z]+)=(.*)$"))) { - if (!snd_lookup.exists(sm[1])&&!rcv_lookup.exists(sm[1])) { - cerr << "Unknown argument " << argv[optind] << endl; - exit(EXIT_FAILURE); - } - list.insert( - std::pair(sm[1], sm[2])); - } else { - cerr << "Invalid Syntax " << argv[optind] << endl; - exit(EXIT_FAILURE); - } - optind++; - } - if (!p.setProperty(list)) - exit(EXIT_SUCCESS); - fprintf(stderr, "Not yet implemented.\n"); - exit(EXIT_FAILURE); - break; - case caseArg("get"): - while (optind < argc) { - if (regex_match(argv[optind], sm, std::regex("^([a-z]+)$"))) { - if (!snd_lookup.exists(sm[1])&&!rcv_lookup.exists(sm[1])) { - cerr << "Unknown argument " << argv[optind] << endl; - exit(EXIT_FAILURE); - } - vect.push_back(sm[1]); - } else { - cerr << "Invalid argument " << argv[optind] << endl; - exit(EXIT_FAILURE); - } - optind++; - } - if (!p.getProperty(vect)) - exit(EXIT_SUCCESS); - break; - default: - printf("Unknown command: %s\n", cmd.c_str()); - exit(EXIT_FAILURE); - } + } else if (optind < argc) { + vector v; + while (optind < argc) + v.push_back(argv[optind++]); + p.single(v); } exit(EXIT_FAILURE); } From 86437239e49a58a9ab661b127709af482aa981e4 Mon Sep 17 00:00:00 2001 From: /jedi/ Date: Thu, 25 Feb 2016 19:56:00 +0100 Subject: [PATCH 5/5] 1.2 --- src/Filter.cpp | 53 ++++++++++++++++++++++++++++++++++++++++++++ src/Filter.h | 30 +++++++++++++++++++++++++ src/Switch-Cmd.cpp | 31 ++++++++++++++++++++++++++ src/lookup/input.lst | 38 +++++++++++++++++++++++++++++++ 4 files changed, 152 insertions(+) create mode 100644 src/Filter.cpp create mode 100644 src/Filter.h create mode 100644 src/Switch-Cmd.cpp create mode 100644 src/lookup/input.lst diff --git a/src/Filter.cpp b/src/Filter.cpp new file mode 100644 index 0000000..cb5f87d --- /dev/null +++ b/src/Filter.cpp @@ -0,0 +1,53 @@ +/* + * Filter.cpp + * + * Created on: 23.02.2016 + * Author: jedi + */ + +#include "Filter.h" + +Filter::Filter() { +} +Filter::Filter(macAddr a) { + switchMac = a; +} +Filter::Filter(Packet::OpCode o) { + oc = o; +} + +Filter Filter::opcode(Packet::OpCode o) { + oc = o; + return *this; +} +Filter Filter::mac(macAddr a) { + switchMac = a; + return *this; +} +Filter Filter::tokenid(short i) { + tokenId = i; + return *this; +} + +bool Filter::pass(const Packet p) const { + macAddr none { 0, 0, 0, 0, 0, 0 }; + if (this->oc != Packet::NONE && this->oc != p.getOpCode()) + return false; + if (this->switchMac != none && this->switchMac != p.getSwitchMac()) + return false; + if (this->tokenId != -1 && this->tokenId != p.getTokenId()) + return false; + /* if (fragmentOffset != p.getF && fragmentOffset != -1) + return false;*/ + return true; +} + +bool Filter::operator<(const Filter f) const { + if (this->oc != f.oc) + return this->oc > f.oc; + if (this->switchMac != f.switchMac) + return this->switchMac > f.switchMac; + if (this->tokenId != f.tokenId) + return this->tokenId > f.tokenId; + return false; +} diff --git a/src/Filter.h b/src/Filter.h new file mode 100644 index 0000000..a9d9213 --- /dev/null +++ b/src/Filter.h @@ -0,0 +1,30 @@ +/* + * Filter.h + * + * Created on: 23.02.2016 + * Author: jedi + */ + +#ifndef FILTER_H_ +#define FILTER_H_ + +#include "Packet.h" + +class Filter { +public: + Filter(); + Filter(Packet::OpCode); + Filter(macAddr); + Filter opcode(Packet::OpCode); + Filter mac(macAddr); + Filter tokenid(short); + bool pass(const Packet) const; + bool operator<(const Filter) const; +private: + Packet::OpCode oc = Packet::NONE; + macAddr switchMac = { 0, 0, 0, 0, 0, 0 }; + short tokenId = -1; + short fragmentOffset = -1; +}; + +#endif /* FILTER_H_ */ diff --git a/src/Switch-Cmd.cpp b/src/Switch-Cmd.cpp new file mode 100644 index 0000000..916b69e --- /dev/null +++ b/src/Switch-Cmd.cpp @@ -0,0 +1,31 @@ +/* + * Switch.cpp + * + * Created on: 29.09.2015 + * Author: jdi + */ + +#include +#include "Types.h" +#include "Switch.h" +#include "Constant.h" +#include "table.h" + +using namespace smrtlink; +using namespace std; + +int Switch::set(pair str) { + + return 0; +} + +std::string Switch::get(std::string str) { + std::string ret; + switch (caseArg(str.c_str())) { + case caseArg("ip"): + ret = "0.0.0.0"; + break; + } + return ret; +} + diff --git a/src/lookup/input.lst b/src/lookup/input.lst new file mode 100644 index 0000000..5c48cff --- /dev/null +++ b/src/lookup/input.lst @@ -0,0 +1,38 @@ +LOOKUP_SET(type, TYPE, STRING) //+string +LOOKUP_SET(mac, MAC, HEX) //+byte[6] +LOOKUP_SET(firmware,FIRMWARE_VERSION, STRING) +LOOKUP_SET(hardware,HARDWARE_VERSION, STRING) + + +LOOKUP_SET(HOSTNAME,host, 2, STRING) //+string +LOOKUP_SET(IP_ADDR,ip, 4, DEC) //+byte[4] +LOOKUP_SET(IP_MASK,mask, 5, DEC) //+byte[4] +LOOKUP_SET(GATEWAY,gateway, 6, DEC) //+byte[4] +LOOKUP_SET(DHCP_ENABLED,dhcp, 9, BOOL) //+bool byte + +LOOKUP_SET(PORT_VLAN_FOOOOO, 2101,2101, HEX) + +LOOKUP_SET(PORTS, ports, 10, DEC) //+byte, maybe number of ports + +LOOKUP_SET(IGMP_SNOOPING, igmp, 4352, HEX) //??? +LOOKUP_SET(PORTS_SETTINGS, psetings, 4096, HEX) //+per port +LOOKUP_SET(PORT_TRUNK, trunk, 4608, HEX) //byte[5] last byte bitmask?? + +LOOKUP_SET(MTU_VLAN, 8192,8192, HEX) //byte[2] first byte bool,second byte port id +LOOKUP_SET(PORT_VLAN_ENABLED, 8448,8448, BOOL) //open page +LOOKUP_SET(PORT_VLAN, 8449,8449, HEX) +LOOKUP_SET(PORT_VLAN_MAX, 8450,8450, DEC) +LOOKUP_SET(VLAN_ENABLED, 8704, 8704, BOOL) //+bool byte +LOOKUP_SET(VLAN, 8705,8705, HEX) //+one set per vlan +LOOKUP_SET(VLAN_PVID, 8706,8706, HEX) //+per port +LOOKUP_SET(VLAN_FOOOO, 8707,8707, DEC) //???? + +LOOKUP_SET(QOS_BASIC_ENABLED, 12288,12288, BOOL) //+bool = QoS Mod +LOOKUP_SET(QOS_BASIC, 12289,12289, HEX) //+per port ??? +LOOKUP_SET(BW_CONTROL_INGRESS, 12544,12544, HEX) //+per port ??? +LOOKUP_SET(BW_CONTROL_EGRESS, 12545,12545, HEX) //+per port ??? +LOOKUP_SET(STORM_CONTROL, 12800,12800, HEX) //+per port ??? +LOOKUP_SET(PORT_MIRROR, 16640,16640, HEX) //byte[10] second byte port id??? +LOOKUP_SET(PORT_STATISTICS, 16384,16384, HEX) //+per port ??? +LOOKUP_SET(CABLE_TEST, 16896,16896, HEX) //+per port ??? +LOOKUP_SET(LOOP_PREVENTION, 17152,17152, BOOL) //+bool byte \ No newline at end of file