diff --git a/Makefile b/Makefile index 2404b58..a031fb5 100644 --- a/Makefile +++ b/Makefile @@ -15,8 +15,7 @@ $(BUILDDIR): $(TARGET): $(OBJECTS) - $(CC) $^ -o $(BUILDDIR)/$@ -lboost_filesystem -lboost_system - + $(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/Constant.h b/src/Constant.h index 31e73fc..d9885e8 100644 --- a/src/Constant.h +++ b/src/Constant.h @@ -11,41 +11,48 @@ #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 [-bdhjrvVstwx] [-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\ + -d --debug [n] Show debugging messages\n\ + -v --verbose [n] Show debugging messages\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\ + -w --wait Not yet implemented: blocking until operation is completed\n\ + -s --permanent make changes immediately permanent\n\ +\ + -b --header Show header\n\ + -t --text Display Packets as readable Text (default)\n\ + -x --hex Display Packets as Hex String\n\ + -j --json Display Packets as JSON\n\n\ +\ + -U --user <[password:]username>\n\ + -P --password \n\ + Login with Username and Password\n\ + -f --file choose a settings file\n\ + -I --stdin Not yet implemented\n\ + -O --stdout Not yet implemented\n\ + -X --interactive gives in interactive Shell. Ignores all commands\n\n\ + Command Summary:\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 [ [...]]\n\ + Not yet implemented\n\ + set = [= [...]]\n\ + Not yet implemented\n\ + save Not yet implemented: save config to file\n\ + 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 /* @@ -54,13 +61,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/File.cpp b/src/File.cpp index 0e6e944..899946e 100644 --- a/src/File.cpp +++ b/src/File.cpp @@ -10,31 +10,32 @@ #include "Constant.h" std::string File::read() { - if (!fs::exists(home)) { - fs::create_directory(home); - } + if (!fs::exists(home)) { + fs::create_directory(home); + } - fs::ifstream in(((options.file=="")?home / DEFAULT_FILE:options.file), std::ios::in | std::ios::binary); - if (in) { - std::string contents; - in.seekg(0, std::ios::end); - contents.resize(in.tellg()); - in.seekg(0, std::ios::beg); - in.read(&contents[0], contents.size()); - in.close(); - return (contents); - } - return ""; + fs::ifstream in(((options.file == "") ? home / DEFAULT_FILE : options.file), + std::ios::in | std::ios::binary); + if (in) { + std::string contents; + in.seekg(0, std::ios::end); + contents.resize(in.tellg()); + in.seekg(0, std::ios::beg); + in.read(&contents[0], contents.size()); + in.close(); + return (contents); + } + return ""; } int File::write(std::string content) { - if (!fs::exists(home)) { - fs::create_directory(home); - } - fs::path p = (options.file=="")?home / DEFAULT_FILE:options.file; - fs::ofstream file(p); - file << content<<"\n"; - file.close(); - return 0; + if (!fs::exists(home)) { + fs::create_directory(home); + } + fs::path p = (options.file == "") ? home / DEFAULT_FILE : options.file; + fs::ofstream file(p); + file << content << "\n"; + file.close(); + return 0; } diff --git a/src/File.h b/src/File.h index 5a39bc0..4aa955d 100644 --- a/src/File.h +++ b/src/File.h @@ -17,14 +17,14 @@ namespace fs = boost::filesystem; #define DEFAULT_FILE "config.json" class File { -public: - File() { - home = fs::path(getenv("HOME")) / ".smrtlink"; - } - std::string read(); - int write(std::string); -private: - fs::path home; + public: + File() { + home = fs::path(getenv("HOME")) / ".smrtlink"; + } + std::string read(); + int write(std::string); + private: + fs::path home; }; #endif /* FILE_H_ */ diff --git a/src/Filter.cpp b/src/Filter.cpp new file mode 100644 index 0000000..421b407 --- /dev/null +++ b/src/Filter.cpp @@ -0,0 +1,54 @@ +/* + * 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..9bf7650 --- /dev/null +++ b/src/Filter.h @@ -0,0 +1,31 @@ +/* + * 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/Host.cpp b/src/Host.cpp index 1fbba26..db26e9e 100644 --- a/src/Host.cpp +++ b/src/Host.cpp @@ -26,77 +26,79 @@ #include "Types.h" macAddr Host::getMac() { - int s; - struct ifreq buffer; - macAddr data { 0, 0, 0, 0, 0, 0 }; - if (options.interface != "") { - s = socket(PF_INET, SOCK_DGRAM, 0); - memset(&buffer, 0x00, sizeof(buffer)); - strcpy(buffer.ifr_name, options.interface.c_str()); - ioctl(s, SIOCGIFHWADDR, &buffer); - close(s); - memcpy(&data[0], &buffer.ifr_hwaddr.sa_data[0], 6); - } - return data; + int s; + struct ifreq buffer; + macAddr data { + 0, 0, 0, 0, 0, 0 }; + if (options.interface != "") { + s = socket(PF_INET, SOCK_DGRAM, 0); + memset(&buffer, 0x00, sizeof(buffer)); + strcpy(buffer.ifr_name, options.interface.c_str()); + ioctl(s, SIOCGIFHWADDR, &buffer); + close(s); + memcpy(&data[0], &buffer.ifr_hwaddr.sa_data[0], 6); + } + return data; } ipAddr Host::getIp() { - struct ifaddrs *ifaddr, *ifa; - int n; - ipAddr data { 0, 0, 0, 0 }; - if (getifaddrs(&ifaddr) == -1) { - perror("getifaddrs"); - exit(EXIT_FAILURE); - } - for (ifa = ifaddr, n = 0; ifa != NULL; ifa = ifa->ifa_next, n++) { - if (ifa->ifa_addr == NULL) - continue; - if (ifa->ifa_addr->sa_family == AF_INET) - if (options.interface.compare(ifa->ifa_name) == 0) { - memcpy(&data[0], &ifa->ifa_addr->sa_data[2], 4); - return data; - } - } - /* - for (ifa = ifaddr, n = 0; ifa != NULL; ifa = ifa->ifa_next, n++) { - if (ifa->ifa_addr == NULL) - continue; - if (ifa->ifa_addr->sa_family == AF_INET) - if (getIface().compare(ifa->ifa_name) == 0) { - memcpy(&data[0], &ifa->ifa_addr->sa_data[2], 4); - return data; - } - } - */ - freeifaddrs(ifaddr); - return data; + struct ifaddrs *ifaddr, *ifa; + int n; + ipAddr data { + 0, 0, 0, 0 }; + if (getifaddrs(&ifaddr) == -1) { + perror("getifaddrs"); + exit(EXIT_FAILURE); + } + for (ifa = ifaddr, n = 0; ifa != NULL; ifa = ifa->ifa_next, n++) { + if (ifa->ifa_addr == NULL) + continue; + if (ifa->ifa_addr->sa_family == AF_INET) + if (options.interface.compare(ifa->ifa_name) == 0) { + memcpy(&data[0], &ifa->ifa_addr->sa_data[2], 4); + return data; + } + } + /* + for (ifa = ifaddr, n = 0; ifa != NULL; ifa = ifa->ifa_next, n++) { + if (ifa->ifa_addr == NULL) + continue; + if (ifa->ifa_addr->sa_family == AF_INET) + if (getIface().compare(ifa->ifa_name) == 0) { + memcpy(&data[0], &ifa->ifa_addr->sa_data[2], 4); + return data; + } + } + */ + freeifaddrs(ifaddr); + return data; } std::string Host::getIface() { - std::string defaultInterface; - std::ifstream routeFile("/proc/net/route", std::ios_base::in); - if (!routeFile.good()) - return ""; - std::string line; - std::vector tokens; - if (std::getline(routeFile, line)) - while (std::getline(routeFile, line)) { - std::istringstream stream(line); - std::string delimiter = "\t"; - size_t pos = 0; - std::string token; - while ((pos = line.find(delimiter)) != std::string::npos) { - token = line.substr(0, pos); - tokens.push_back(token); - line.erase(0, pos + delimiter.length()); - } - if ((tokens.size() >= 2) - && (tokens[1] == std::string("00000000"))) { - defaultInterface = tokens[0]; - break; - } - tokens.clear(); - } - routeFile.close(); - return defaultInterface; + std::string defaultInterface; + std::ifstream routeFile("/proc/net/route", std::ios_base::in); + if (!routeFile.good()) + return ""; + std::string line; + std::vector tokens; + if (std::getline(routeFile, line)) + while (std::getline(routeFile, line)) { + std::istringstream stream(line); + std::string delimiter = "\t"; + size_t pos = 0; + std::string token; + while ((pos = line.find(delimiter)) != std::string::npos) { + token = line.substr(0, pos); + tokens.push_back(token); + line.erase(0, pos + delimiter.length()); + } + if ((tokens.size() >= 2) + && (tokens[1] == std::string("00000000"))) { + defaultInterface = tokens[0]; + break; + } + tokens.clear(); + } + routeFile.close(); + return defaultInterface; } diff --git a/src/Host.h b/src/Host.h index 3e7f09f..6c5ee15 100644 --- a/src/Host.h +++ b/src/Host.h @@ -11,11 +11,12 @@ #include "Types.h" class Host { -public: - Host(){}; - macAddr getMac(); - ipAddr getIp(); - std::string getIface(); + public: + Host() { + } + macAddr getMac(); + ipAddr getIp(); + std::string getIface(); }; #endif /* HOST_H_ */ diff --git a/src/Interactive.cpp b/src/Interactive.cpp new file mode 100644 index 0000000..19ab930 --- /dev/null +++ b/src/Interactive.cpp @@ -0,0 +1,46 @@ +/* + * Interactive.cpp + * + * Created on: 27.01.2016 + * Author: jedi + */ + +#include +#include +#include +#include + +#include +#include +#include + +#include "Program.h" +#include "Interactive.h" + +using namespace std; + +int Interactive::loop() { + string cmd; + vector 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 new file mode 100644 index 0000000..7f2af8c --- /dev/null +++ b/src/Interactive.h @@ -0,0 +1,21 @@ +/* + * Interactive.h + * + * Created on: 27.01.2016 + * Author: jedi + */ + +#ifndef INTERACTIVE_H_ +#define INTERACTIVE_H_ + +class Interactive { + public: + Interactive() { + } + virtual ~Interactive() { + } + int loop(); + int single(std::vector v); +}; + +#endif /* INTERACTIVE_H_ */ 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/Packet.cpp b/src/Packet.cpp index ce3ad13..a469cea 100644 --- a/src/Packet.cpp +++ b/src/Packet.cpp @@ -150,42 +150,43 @@ void Packet::setTokenId(short tokenId) { std::string Packet::opCodeToString() { switch (opCode) { - case DISCOVERY: - return "DISCOVERY"; - case GET: - return "GET"; - case SET: - return "SET"; - case CONFIRM: - return "CONFIRM"; - case RETURN: - return "RETURN"; - default: - return "NONE"; + case DISCOVERY: + return "DISCOVERY"; + case GET: + return "GET"; + case SET: + return "SET"; + case CONFIRM: + return "CONFIRM"; + case REPLY: + return "REPLY"; + default: + return "NONE"; } return "NONE"; } void Packet::encode(bytes &data) { int len = data.size(); - bytes key = { 191, 155, 227, 202, 99, 162, 79, 104, 49, 18, 190, 164, 30, - 76, 189, 131, 23, 52, 86, 106, 207, 125, 126, 169, 196, 28, 172, 58, - 188, 132, 160, 3, 36, 120, 144, 168, 12, 231, 116, 44, 41, 97, 108, - 213, 42, 198, 32, 148, 218, 107, 247, 112, 204, 14, 66, 68, 91, 224, - 206, 235, 33, 130, 203, 178, 1, 134, 199, 78, 249, 123, 7, 145, 73, - 208, 209, 100, 74, 115, 72, 118, 8, 22, 243, 147, 64, 96, 5, 87, 60, - 113, 233, 152, 31, 219, 143, 174, 232, 153, 245, 158, 254, 70, 170, - 75, 77, 215, 211, 59, 71, 133, 214, 157, 151, 6, 46, 81, 94, 136, - 166, 210, 4, 43, 241, 29, 223, 176, 67, 63, 186, 137, 129, 40, 248, - 255, 55, 15, 62, 183, 222, 105, 236, 197, 127, 54, 179, 194, 229, - 185, 37, 90, 237, 184, 25, 156, 173, 26, 187, 220, 2, 225, 0, 240, - 50, 251, 212, 253, 167, 17, 193, 205, 177, 21, 181, 246, 82, 226, - 38, 101, 163, 182, 242, 92, 20, 11, 95, 13, 230, 16, 121, 124, 109, - 195, 117, 39, 98, 239, 84, 56, 139, 161, 47, 201, 51, 135, 250, 10, - 19, 150, 45, 111, 27, 24, 142, 80, 85, 83, 234, 138, 216, 57, 93, - 65, 154, 141, 122, 34, 140, 128, 238, 88, 89, 9, 146, 171, 149, 53, - 102, 61, 114, 69, 217, 175, 103, 228, 35, 180, 252, 200, 192, 165, - 159, 221, 244, 110, 119, 48 }; + bytes key = { + 191, 155, 227, 202, 99, 162, 79, 104, 49, 18, 190, 164, 30, 76, 189, + 131, 23, 52, 86, 106, 207, 125, 126, 169, 196, 28, 172, 58, 188, + 132, 160, 3, 36, 120, 144, 168, 12, 231, 116, 44, 41, 97, 108, 213, + 42, 198, 32, 148, 218, 107, 247, 112, 204, 14, 66, 68, 91, 224, 206, + 235, 33, 130, 203, 178, 1, 134, 199, 78, 249, 123, 7, 145, 73, 208, + 209, 100, 74, 115, 72, 118, 8, 22, 243, 147, 64, 96, 5, 87, 60, 113, + 233, 152, 31, 219, 143, 174, 232, 153, 245, 158, 254, 70, 170, 75, + 77, 215, 211, 59, 71, 133, 214, 157, 151, 6, 46, 81, 94, 136, 166, + 210, 4, 43, 241, 29, 223, 176, 67, 63, 186, 137, 129, 40, 248, 255, + 55, 15, 62, 183, 222, 105, 236, 197, 127, 54, 179, 194, 229, 185, + 37, 90, 237, 184, 25, 156, 173, 26, 187, 220, 2, 225, 0, 240, 50, + 251, 212, 253, 167, 17, 193, 205, 177, 21, 181, 246, 82, 226, 38, + 101, 163, 182, 242, 92, 20, 11, 95, 13, 230, 16, 121, 124, 109, 195, + 117, 39, 98, 239, 84, 56, 139, 161, 47, 201, 51, 135, 250, 10, 19, + 150, 45, 111, 27, 24, 142, 80, 85, 83, 234, 138, 216, 57, 93, 65, + 154, 141, 122, 34, 140, 128, 238, 88, 89, 9, 146, 171, 149, 53, 102, + 61, 114, 69, 217, 175, 103, 228, 35, 180, 252, 200, 192, 165, 159, + 221, 244, 110, 119, 48 }; bytes s = key; int i, j = 0; for (int k = 0; k < len; k++) { @@ -199,7 +200,8 @@ void Packet::encode(bytes &data) { void Packet::push(bytes &arr, int &index, byte data) { if (arr.size() > (unsigned) index) { arr[index++] = data; - } else { + } + else { arr.push_back(data); index++; } @@ -277,6 +279,14 @@ void Packet::pull(bytes &arr, int &index, int &ret) { ret |= arr[index++] & 0xFF; } +byte Packet::getOpCode() const { + return opCode; +} + +void Packet::setOpCode(byte opCode) { + this->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..466f01c 100644 --- a/src/Packet.h +++ b/src/Packet.h @@ -13,65 +13,71 @@ #include "Types.h" -static short sequenceId=0; +static short sequenceId = 0; -class Packet -{ -public: - enum OpCode {DISCOVERY, GET, RETURN, SET, CONFIRM, NONE}; - Packet(OpCode); - void encode(bytes&); - bytes getBytes(); - void parse(bytes); - void printHeader(); - std::string opCodeToString(); - short getLength() const; - int getCheckSum() const; - int getErrorCode() const; - short getSequenceId() const; - macAddr getSwitchMac() const; - const bytes& getBody() const; - const bytes& getHead() const; - const datasets& getPayload() const; - void setBody(bytes); - void setHostMac(macAddr); - void setSwitchMac(macAddr); - void setCheckSum(int); - void setSequenceId(short ); - void setPayload(datasets payload); - short getTokenId() const; - void setTokenId(short tokenId = 0); +class Packet { + public: + enum OpCode { + DISCOVERY, GET, REPLY, SET, CONFIRM, NONE + }; + Packet(OpCode); + static void encode(bytes&); + bytes getBytes(); + void parse(bytes); + void printHeader(); + std::string opCodeToString(); + short getLength() const; + int getCheckSum() const; + int getErrorCode() const; + short getSequenceId() const; + macAddr getSwitchMac() const; + const bytes& getBody() const; + const bytes& getHead() const; + const datasets& getPayload() const; + void setBody(bytes); + void setHostMac(macAddr); + void setSwitchMac(macAddr); + void setCheckSum(int); + void setSequenceId(short); + void setPayload(datasets payload); + short getTokenId() const; + void setTokenId(short tokenId = 0); + byte getOpCode() const; + void setOpCode(byte opCode); -private: - bytes head = bytes(32); - bytes body = bytes(0); - 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}}; - short tokenId = 0; - short fragmentOffset = 0; - int errorCode = 0; - int checkSum = 0; - short flag = 0; - void buildHead(); - void buildBody(); - void push(bytes&, int&, short ); - void push(bytes&, int&, int); - void push(bytes&, int&, byte); - void push(bytes&, int&, bytes); - void push(bytes&, int&, ipAddr); - void push(bytes&, int&, macAddr); - void push(bytes&, int&, dataset); - 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&, ipAddr&); - void pull(bytes&, int&, macAddr&); - void pull(bytes&, int&, dataset&); + private: + bytes head = bytes(32); + bytes body = bytes(0); + 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 } }; + short tokenId = 0; + short fragmentOffset = 0; + int errorCode = 0; + int checkSum = 0; + short flag = 0; + void buildHead(); + void buildBody(); + void push(bytes&, int&, short); + void push(bytes&, int&, int); + void push(bytes&, int&, byte); + void push(bytes&, int&, bytes); + void push(bytes&, int&, ipAddr); + void push(bytes&, int&, macAddr); + void push(bytes&, int&, dataset); + 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&, ipAddr&); + void pull(bytes&, int&, macAddr&); + void pull(bytes&, int&, dataset&); }; #endif /* PACKET_H_ */ diff --git a/src/Program.cpp b/src/Program.cpp index 636ed70..ad871d6 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,14 +17,120 @@ #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 (!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 (!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 & FLAG_HEADER) { - if (options.flags & FLAG_HEX) { - std::cout << "Received Header:\n\t" << p.getHead() << "\n"; - } else { + if (options.flags.HEADER) { + if (options.flags.HEX) { + cout << "Received Header:\n\t" << p.getHead() << "\n"; + } + else { p.printHeader(); printf("\n"); } @@ -30,56 +139,56 @@ int printHeader(Packet p) { } int printPacket(Packet p) { - if (options.flags & FLAG_HEX) { - std::cout << "Received Payload:\n\t" << p.getBody() << "\n"; - } else { + 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"; + case table::STRING: + cout << "+\t" << s.name << " = " << &d.value[0] + << "\n"; break; - case table::BOOL: - std::cout << "+\t" << s.name << " = " - << (d.value[0] ? "YES" : "NO") << "\n"; + case table::BOOL: + cout << "+\t" << s.name << " = " + << (d.value[0] ? "YES" : "NO") << "\n"; break; - case table::HEX: - std::cout << "+\t" << s.name << " = " << d.value - << "\n"; + case table::HEX: + 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"; + case table::DEC: + cout << "+\t" << s.name << " = "; + if (d.value.size() > 0) + cout << dec << (unsigned) d.value[0]; + for (unsigned i = 1; i < d.value.size(); i++) + cout << dec << "." << (unsigned) d.value[i]; + cout << "\n"; break; - case table::ACTION: - std::cout << "Error:" << s.name - << " is marked as 'action' but carries payload." - << d.value << "\n"; + case table::ACTION: + cout << "Error:" << s.name + << " is marked as 'action' but carries payload." + << d.value << "\n"; break; - default: - std::cout << "+\t" << s.name << " = " << d.value - << "\n"; + default: + cout << "+\t" << s.name << " = " << d.value << "\n"; break; } - } else { //empty - std::cout << std::dec << ">\t" << s.name << "\n"; } - } else { //unknown id + else { //empty + 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"; - } else { //empty - std::cout << "#>\t" << d.type << "\n"; + cout << "##\t" << d.type << ":\n\t"; + cout << hex << d.value << dec << "\n"; + } + else { //empty + cout << "#>\t" << d.type << "\n"; } } } @@ -88,144 +197,130 @@ 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); - io_service->run(); - } catch (std::exception& e) { - std::cerr << "Exception: " << e.what() << "\n"; + cout << "List:\n"; + discover([this](Packet a) { + printHeader(a); + if (options.flags.HEX) { + cout <<"Received Payload:\n"<(b,Switch())); + devices[a.getSwitchMac().hash()].parse(d); + devices[a.getSwitchMac().hash()].print(); + + File f; + f.write(devices[a.getSwitchMac().hash()].toString()); + } + return 0; + }); + } catch (exception& e) { + cerr << "Exception: " << e.what() << "\n"; } - return 1; + return 0; } 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) { - std::cout << p.opCodeToString() << "\n"; + sock->listen([](Packet p) { + 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 = { {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; - }; - - sock->send(c); - return 0; - }; - sock->send(b); - io_service->run(); - } catch (std::exception& e) { - std::cerr << "Exception: " << e.what() << "\n"; + }); + return 0; + }); + } 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 = 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; + }); + + } catch (exception& e) { + cerr << "Exception: " << e.what() << "\n"; + } + return 0; } int Program::save() { @@ -233,40 +328,120 @@ 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(); + 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 = { {PING, 0, {}}}; + get(a, t, [this](Packet a) { + datasets d =a.getPayload(); + cout <) { +int Program::discover(Listener c) { + Packet p = Packet(Packet::DISCOVERY); + p.setHostMac(host.getMac()); + p.setPayload( { }); + sock->listen(c, Filter(Packet::REPLY)); + sock->send(p); + return 0; +} +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->listen(c, Filter(Packet::REPLY).mac(l.getSwitchMac())); + sock->send(p); + return 0; +} + +int Program::set(Packet l, datasets t, Listener 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->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(); + + sock->setHostIp(host.getIp()); + sock->init(DST_PORT, SRC_PORT); } diff --git a/src/Program.h b/src/Program.h index 1bd97da..86e08a9 100644 --- a/src/Program.h +++ b/src/Program.h @@ -9,34 +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 ping(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 setProperty(); - int getProperty(); - int save(); - int restore(); - int flash(); - int reboot(); - int reset(); - std::string input; + private: + 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() { + } + 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 191971e..b1804f7 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; - if (options.flags & FLAG_REVERSE) { +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.flags & FLAG_DEBUG) + if (options.debug_level >= 1) std::cout << "Local IP:\t" << local_ip << "\n"; wildcard_endpoint_ = boost::asio::ip::udp::endpoint( @@ -47,37 +51,40 @@ 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::send(bytes data) { +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); unsigned char * a = &data[0]; send_socket_.async_send_to(boost::asio::buffer(a, data.size()), 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_, @@ -86,17 +93,43 @@ void Socket::listen() { if (ec || bytes_recvd == 0) { //listen(); // TODO distinguish error codes - } else { + } + else { 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 -class Socket { -public: - Socket(boost::asio::io_service&); - virtual ~Socket() { - } - void init(short, short); - void send(bytes); - void listen(); - void setHostIp(ipAddr); - std::function callback = [](Packet a) { - return 0; - }; +typedef std::function Listener; +typedef std::pair ListenerPair; -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; +class Socket { + public: + 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: + 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-Cmd.cpp b/src/Switch-Cmd.cpp new file mode 100644 index 0000000..765519f --- /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/Switch-Json.cpp b/src/Switch-Json.cpp index 21f1477..ed7f351 100644 --- a/src/Switch-Json.cpp +++ b/src/Switch-Json.cpp @@ -14,85 +14,85 @@ 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.Parse(str.c_str()).HasParseError()) + return 1; + if (options.debug_level >= 1) + 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); - } - } + 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()); + { + 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; + int y = a[0].GetInt(); + (void) y; - */ - return 0; + */ + return 0; } std::string Switch::toString() { - if (!json.IsObject()) { - json.SetObject(); - } - rapidjson::Document::AllocatorType& allocator = json.GetAllocator(); + 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); + 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(); + rapidjson::StringBuffer sb; + rapidjson::PrettyWriter writer(sb); + json.Accept(writer); + return sb.GetString(); } diff --git a/src/Switch.cpp b/src/Switch.cpp index 89419a8..3c928bf 100644 --- a/src/Switch.cpp +++ b/src/Switch.cpp @@ -19,48 +19,53 @@ 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: - device.type = d.value; + case TYPE: + device.type = d.value; break; - case RCV_MAC: - device.mac = d.value; + case MAC: + device.mac = d.value; break; - case FIRMWARE_VERSION: - device.firmware_version = d.value; + case FIRMWARE_VERSION: + device.firmware_version = d.value; break; - case HARDWARE_VERSION: - device.hardware_version = d.value; + case HARDWARE_VERSION: + device.hardware_version = d.value; break; - case PORTS: - device.ports = d.value[0]; + case PORTS: + device.ports = d.value[0]; break; - case HOSTNAME: - settings.hostname = d.value; + case HOSTNAME: + settings.hostname = d.value; break; - case IP_ADDR: - settings.ip_addr = d.value; + case IP_ADDR: + settings.ip_addr = d.value; break; - case IP_MASK: - settings.ip_mask = d.value; + case IP_MASK: + settings.ip_mask = d.value; break; - case GATEWAY: - settings.gateway = d.value; + case GATEWAY: + settings.gateway = d.value; break; - case DHCP_ENABLED: - settings.dhcp = d.value[0]; + case DHCP_ENABLED: + settings.dhcp = d.value[0]; break; - case LOOP_PREVENTION: - settings.loop_prevention = d.value[0]; + case LOOP_PREVENTION: + settings.loop_prevention = d.value[0]; break; - case QOS_BASIC_ENABLED: - settings.qos_enabled = d.value[0]; + case QOS_BASIC_ENABLED: + settings.qos_enabled = d.value[0]; break; - case VLAN_ENABLED: - settings.vlan_enabled = d.value[0]; + case VLAN_ENABLED: + settings.vlan_enabled = d.value[0]; break; } return 0; } - diff --git a/src/Switch.h b/src/Switch.h index 88a3351..1065cce 100644 --- a/src/Switch.h +++ b/src/Switch.h @@ -18,80 +18,87 @@ #define DEFAULT_PASS "admin" enum CntStatus { - OPEN, SHORT + OPEN, SHORT }; struct vlan { - int vlan_id; - std::string name; - std::vector tagged_member; - std::vector untagged_member; + int vlan_id; + std::string name; + std::vector tagged_member; + std::vector untagged_member; }; struct trunk { - int trunk_id; - std::vector member; + int trunk_id; + std::vector member; }; struct port { - byte id; - byte status; - int pvid; - 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 + byte id; + byte status; + int pvid; + 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 }; class Switch { -public: - Switch() { - } - int parse(datasets); - int parse(dataset); - int parse(std::string); - std::string toString(); + public: + Switch() { + } + int parse(datasets); + int parse(dataset); + int parse(std::string); + int set(std::pair); - struct { - std::string type; - std::string hardware_version; - std::string firmware_version; - macAddr mac { 0x0, 0x0, 0x0, 0x0, 0x0, 0x0 }; - int ports; - } device; - struct { - std::string password = DEFAULT_PASS; - std::string username = DEFAULT_USER; - std::string hostname; - ipAddr ip_addr { 0, 0, 0, 0, }; - ipAddr ip_mask; - ipAddr gateway; - bool dhcp; - bool loop_prevention; - bool qos_enabled; - bool vlan_enabled; - //mtu_vlan - } settings; + std::string get(std::string); + std::string toString(); -private: - rapidjson::Document json; - std::vector vlans; - std::vector ports; + int print(); + + struct { + std::string type; + std::string hardware_version; + std::string firmware_version; + macAddr mac { + 0x0, 0x0, 0x0, 0x0, 0x0, 0x0 }; + int ports; + } device; + struct { + std::string password = DEFAULT_PASS; + std::string username = DEFAULT_USER; + std::string hostname; + ipAddr ip_addr { + 0, 0, 0, 0, }; + ipAddr ip_mask; + ipAddr gateway; + bool dhcp; + bool loop_prevention; + bool qos_enabled; + bool vlan_enabled; + //mtu_vlan + } settings; + + private: + rapidjson::Document json; + std::vector vlans; + std::vector ports; }; #endif /* SWITCH_H_ */ diff --git a/src/Types.h b/src/Types.h index 019c07f..94abc15 100644 --- a/src/Types.h +++ b/src/Types.h @@ -20,106 +20,146 @@ #include "table.h" 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; - } - - macAddr() { - *this= {0,0,0,0,0,0}; - } - - macAddr(std::initializer_list s) { - int i = 0; - for (byte b : s) { - if(i<6) (*this)[i++]=b; - else break; + 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; } - } - macAddr(bytes bts) { - int i = 0; - for (byte b : bts) { - if(i<6) (*this)[i++]=b; - else break; + macAddr() { + *this= {0,0,0,0,0,0}; } - } -}; -/* -class mac_addr : public std::array { -public: - typedef std::array super; + macAddr(std::initializer_list s) { + int i = 0; + for (byte b : s) { + if(i<6) (*this)[i++]=b; + else break; + } + } - using super::super; + macAddr(bytes bts) { + int i = 0; + for (byte b : bts) { + if(i<6) (*this)[i++]=b; + else break; + } + } - mac_addr{00, 00, 00, 000}; -}; -*/ + 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; + } + }; + + /* + class mac_addr : public std::array { + public: + typedef std::array super; + + using super::super; + + mac_addr{00, 00, 00, 000}; + }; + */ class ipAddr: public std::array { -public: + public: - 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() { + *this= {0,0,0,0,0,0}; } - } - ipAddr(bytes bts) { - int i = 0; - for (byte b : bts) { - 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; + } } - } - 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; - } -}; + ipAddr(bytes bts) { + int i = 0; + for (byte b : bts) { + 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; + } + }; + +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; - 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 = 250U; }; #endif /* TYPES_H_ */ diff --git a/src/bytes.cpp b/src/bytes.cpp index 9dac956..c7ab164 100644 --- a/src/bytes.cpp +++ b/src/bytes.cpp @@ -7,23 +7,23 @@ #include "bytes.h" -bytes bytes::readHex(std::string s){ - vector ret; - std::string delimiter = ":"; - std::string token; - size_t pos = 0; - int hex; - byte b; - ret.resize(0); - while ((pos = s.find(delimiter)) != std::string::npos) { - token = s.substr(0, pos); - sscanf(token.c_str(), "%x", &hex); - s.erase(0, pos + delimiter.length()); - b = hex & 0xFF; - ret.push_back(b); - } - sscanf(s.c_str(), "%x", &hex); - b = hex & 0xFF; - ret.push_back(b); - return ret; +bytes bytes::readHex(std::string s) { + vector ret; + std::string delimiter = ":"; + std::string token; + size_t pos = 0; + int hex; + byte b; + ret.resize(0); + while ((pos = s.find(delimiter)) != std::string::npos) { + token = s.substr(0, pos); + sscanf(token.c_str(), "%x", &hex); + s.erase(0, pos + delimiter.length()); + b = hex & 0xFF; + ret.push_back(b); + } + sscanf(s.c_str(), "%x", &hex); + b = hex & 0xFF; + ret.push_back(b); + return ret; } diff --git a/src/bytes.h b/src/bytes.h index eb129d6..5f2fbac 100644 --- a/src/bytes.h +++ b/src/bytes.h @@ -19,66 +19,69 @@ typedef unsigned char byte; class bytes: public std::vector { - typedef std::vector vector; -public: - using vector::operator[]; - bytes() { - } - bytes(int n) : vector(n){ - } + typedef std::vector vector; + public: + using vector::operator[]; + bytes() { + } + bytes(int n) : + vector(n) { + } - bytes(std::string d) : vector(d.begin(), d.end()){ - } + bytes(std::string d) : + vector(d.begin(), d.end()) { + this->push_back('\0'); + } - bytes(std::initializer_list s) - { - for (uint8_t b : s) { - this->push_back(b); - } - } + bytes(std::initializer_list s) { + for (uint8_t b : s) { + this->push_back(b); + } + } - bytes(const vector &B) { - this->reserve(B.size()); - this->insert(this->begin(), B.begin(), B.end()); - } + bytes(const vector &B) { + this->reserve(B.size()); + this->insert(this->begin(), B.begin(), B.end()); + } - bytes readHex(std::string); + bytes readHex(std::string); - bytes operator=(const vector &B) { - this->reserve(B.size()); - this->insert(this->begin(), B.begin(), B.end()); - return *this; - } + bytes operator=(const vector &B) { + this->reserve(B.size()); + this->insert(this->begin(), B.begin(), B.end()); + return *this; + } - bytes &operator+=(const bytes &B) { - this->reserve(this->size() + B.size()); - this->insert(this->end(), B.begin(), B.end()); - return *this; - } + bytes &operator+=(const bytes &B) { + this->reserve(this->size() + B.size()); + this->insert(this->end(), B.begin(), B.end()); + return *this; + } - bytes operator+(const bytes &B) { - bytes 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; - } + bytes operator+(const bytes &B) { + bytes 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; + } - friend std::ostream& operator<<(std::ostream& out, const bytes& arr) { - if (arr.size() > 0) { - out << std::hex << std::setw(2) << std::setfill('0') - << (unsigned) arr[0]; - } - for (unsigned i = 1; i < arr.size(); i++) { - out << ":" << std::setw(2) << std::setfill('0') << (unsigned) arr[i]; - } - return out; - } + friend std::ostream& operator<<(std::ostream& out, const bytes& arr) { + if (arr.size() > 0) { + out << std::hex << std::setw(2) << std::setfill('0') + << (unsigned) arr[0]; + } + for (unsigned i = 1; i < arr.size(); i++) { + out << ":" << std::setw(2) << std::setfill('0') + << (unsigned) arr[i]; + } + return out; + } - operator std::string() { - std::string s(this->begin(),this->end()); - return s; - } + operator std::string() { + std::string s(this->begin(), this->end()); + return s; + } }; #endif /* BYTES_H_ */ diff --git a/src/datasets.h b/src/datasets.h index bc9ac83..dc1edef 100644 --- a/src/datasets.h +++ b/src/datasets.h @@ -12,21 +12,29 @@ #include "bytes.h" struct dataset { - short type; - short len; - bytes value; + short type; + short len; + bytes value; }; -class datasets : public std::vector { -public: - datasets(){}; - datasets(std::initializer_list s) - { - for (dataset b : s) { - //(*this)[b.type]=b; - push_back(b); - } - } +class datasets: public std::vector { + public: + datasets() { + } + datasets(std::initializer_list s) { + for (dataset b : s) { + //(*this)[b.type]=b; + 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/jsonNode.cpp b/src/jsonNode.cpp index 1ac0ea5..b6ed744 100644 --- a/src/jsonNode.cpp +++ b/src/jsonNode.cpp @@ -11,43 +11,43 @@ #include "jsonNode.h" jsonNode::jsonNode(const std::string &x, doc &root) { - super(rapidjson::kStringType); - char buffer[30]; - int len = sprintf(buffer, "%s", x.c_str()); - this->SetString(buffer, static_cast(len), root.GetAllocator()); - memset(buffer, 0, sizeof(buffer)); + super(rapidjson::kStringType); + char buffer[30]; + int len = sprintf(buffer, "%s", x.c_str()); + this->SetString(buffer, static_cast(len), root.GetAllocator()); + memset(buffer, 0, sizeof(buffer)); } jsonNode::jsonNode(const ipAddr &x, doc &root) { - super(rapidjson::kStringType); - char buffer[16]; - int len = sprintf(buffer, "%d.%d.%d.%d", x[0], x[1], x[2], x[3]); - this->SetString(buffer, static_cast(len), root.GetAllocator()); - memset(buffer, 0, sizeof(buffer)); + super(rapidjson::kStringType); + char buffer[16]; + int len = sprintf(buffer, "%d.%d.%d.%d", x[0], x[1], x[2], x[3]); + this->SetString(buffer, static_cast(len), root.GetAllocator()); + memset(buffer, 0, sizeof(buffer)); } jsonNode::jsonNode(const macAddr &x, doc &root) { - super(rapidjson::kStringType); - char buffer[18]; - int len = sprintf(buffer, "%02x:%02x:%02x:%02x:%02x:%02x", x[0], x[1], x[2], - x[3], x[4], x[5]); - this->SetString(buffer, static_cast(len), root.GetAllocator()); - memset(buffer, 0, sizeof(buffer)); + super(rapidjson::kStringType); + char buffer[18]; + int len = sprintf(buffer, "%02x:%02x:%02x:%02x:%02x:%02x", x[0], x[1], x[2], + x[3], x[4], x[5]); + this->SetString(buffer, static_cast(len), root.GetAllocator()); + memset(buffer, 0, sizeof(buffer)); } jsonNode::jsonNode(const vlan &x, doc &root) { - super(rapidjson::kObjectType); - AddMember("id", x.vlan_id, root.GetAllocator()); - AddMember("name", jsonNode(x.name, root), root.GetAllocator()); - AddMember("tagged-members", jsonNode(x.tagged_member, root), - root.GetAllocator()); - AddMember("untagged-members", jsonNode(x.untagged_member, root), - root.GetAllocator()); + super(rapidjson::kObjectType); + AddMember("id", x.vlan_id, root.GetAllocator()); + AddMember("name", jsonNode(x.name, root), root.GetAllocator()); + AddMember("tagged-members", jsonNode(x.tagged_member, root), + root.GetAllocator()); + AddMember("untagged-members", jsonNode(x.untagged_member, root), + root.GetAllocator()); } jsonNode::jsonNode(const port &x, doc &root) { - super(rapidjson::kObjectType); - AddMember("id", x.id, root.GetAllocator()); - AddMember("status", x.status, root.GetAllocator()); - AddMember("pvid", x.pvid, root.GetAllocator()); + super(rapidjson::kObjectType); + AddMember("id", x.id, root.GetAllocator()); + AddMember("status", x.status, root.GetAllocator()); + AddMember("pvid", x.pvid, root.GetAllocator()); } diff --git a/src/jsonNode.h b/src/jsonNode.h index 9fccbf5..d41084d 100644 --- a/src/jsonNode.h +++ b/src/jsonNode.h @@ -13,26 +13,26 @@ #include "Switch.h" class jsonNode: public rapidjson::Value { - typedef rapidjson::Value super; - typedef rapidjson::Document doc; -public: - jsonNode(const std::string&, doc&); - jsonNode(const macAddr&, doc&); - jsonNode(const ipAddr&, doc&); - jsonNode(const vlan&, doc&); - jsonNode(const port&, doc&); + typedef rapidjson::Value super; + typedef rapidjson::Document doc; + public: + jsonNode(const std::string&, doc&); + jsonNode(const macAddr&, doc&); + jsonNode(const ipAddr&, doc&); + jsonNode(const vlan&, doc&); + jsonNode(const port&, doc&); - template - jsonNode(const T &templ_arg, doc &root){ - std::cerr<<"Not serializable Type: "< + jsonNode(const T &templ_arg, doc &root) { + std::cerr << "Not serializable Type: " << typeid(T).name() << "\n"; + } - template - jsonNode(const std::vector &x, doc &root) { - super(rapidjson::kArrayType); - for (T y : x) - PushBack(jsonNode(y, root), root.GetAllocator()); - } + template + jsonNode(const std::vector &x, doc &root) { + super(rapidjson::kArrayType); + for (T y : x) + PushBack(jsonNode(y, root), root.GetAllocator()); + } }; #endif /* JSONNODE_H_ */ diff --git a/src/lookup.h b/src/lookup.h index a51f9bf..c40134c 100644 --- a/src/lookup.h +++ b/src/lookup.h @@ -1,30 +1,12 @@ enum { -#define LOOKUP_SET(id, num, type) RCV_ ## id = num, -#include "lookup/rcv.lst" -#include "lookup/general.lst" -#undef LOOKUP_SET -#define LOOKUP_SET(id, num, type) SND_ ## id = num, -#include "lookup/snd.lst" -#include "lookup/general.lst" -#undef LOOKUP_SET -#define LOOKUP_SET(id, num, type) id = num, -#include "lookup/rcv.lst" -#include "lookup/snd.lst" -#include "lookup/general.lst" +#define LOOKUP_SET(id, name, num, type, write) id = num, +#include "lookup/map.lst" #undef LOOKUP_SET }; -static table rcv_lookup { -#define LOOKUP_SET(id, num, type) { RCV_ ## id, table::type, #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 }, -#include "lookup/snd.lst" -#include "lookup/general.lst" +static table lookup { +#define LOOKUP_SET(id, name, num, type, write) { id, table::type, table::write, #name, #id}, +#include "lookup/map.lst" #undef LOOKUP_SET }; diff --git a/src/lookup/general.lst b/src/lookup/general.lst index c4a4f05..d70672f 100644 --- a/src/lookup/general.lst +++ b/src/lookup/general.lst @@ -1,25 +1,27 @@ -LOOKUP_SET(PORTS, 10, DEC) //+byte, maybe number of ports -LOOKUP_SET(IGMP_SNOOPING, 4352, HEX) //??? -LOOKUP_SET(PORTS_SETTINGS, 4096, HEX) //+per port -LOOKUP_SET(PORT_TRUNK, 4608, HEX) //byte[5] last byte bitmask?? -LOOKUP_SET(MTU_VLAN, 8192, HEX) //byte[2] first byte bool,second byte port id -LOOKUP_SET(PORT_VLAN_ENABLED, 8448, BOOL) //open page -LOOKUP_SET(PORT_VLAN, 8449, HEX) -LOOKUP_SET(PORT_VLAN_MAX, 8450, DEC) -LOOKUP_SET(VLAN_ENABLED, 8704, BOOL) //+bool byte -LOOKUP_SET(VLAN, 8705, HEX) //+one set per vlan -LOOKUP_SET(VLAN_PVID, 8706, HEX) //+per port -LOOKUP_SET(VLAN_FOOOO, 8707, DEC) //???? +LOOKUP_SET(PORTS, ports, 10, DEC) //+byte, maybe number of ports -LOOKUP_SET(QOS_BASIC_ENABLED, 12288, BOOL) //+bool = QoS Mod -LOOKUP_SET(QOS_BASIC, 12289, HEX) //+per port ??? -LOOKUP_SET(BW_CONTROL_INGRESS, 12544, HEX) //+per port ??? -LOOKUP_SET(BW_CONTROL_EGRESS, 12545, HEX) //+per port ??? -LOOKUP_SET(STORM_CONTROL, 12800, HEX) //+per port ??? -LOOKUP_SET(PORT_MIRROR, 16640, HEX) //byte[10] second byte port id??? -LOOKUP_SET(PORT_STATISTICS, 16384, HEX) //+per port ??? -LOOKUP_SET(CABLE_TEST, 16896, HEX) //+per port ??? -LOOKUP_SET(LOOP_PREVENTION, 17152, BOOL) //+bool byte +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 diff --git a/src/lookup/map.lst b/src/lookup/map.lst new file mode 100644 index 0000000..f7afb4b --- /dev/null +++ b/src/lookup/map.lst @@ -0,0 +1,49 @@ +LOOKUP_SET(TYPE, type, 1, STRING, RO) //+string +LOOKUP_SET(HOSTNAME, host, 2, STRING, RW) //+string //SYSTEM_INFO,SYSTEM_INFO, 2, HEX) //page sysinfo +LOOKUP_SET(MAC, mac, 3, HEX, RO) //+byte[6] +LOOKUP_SET(IP_ADDR, ip, 4, DEC, RW) //+byte[4] +LOOKUP_SET(IP_MASK, mask, 5, DEC, RW) //+byte[4] +LOOKUP_SET(GATEWAY, gateway, 6, DEC, RW) //+byte[4] +LOOKUP_SET(FIRMWARE_VERSION,firmware, 7, STRING, RO) +LOOKUP_SET(HARDWARE_VERSION,hardware, 8, STRING, RO) +LOOKUP_SET(DHCP_ENABLED, dhcp, 9, BOOL, RW) //+bool byte //IP_CONFIG,IP_CONFIG, 9, HEX) //page sysinfo + +LOOKUP_SET(PORTS, ports, 10, DEC, RO) //+byte, maybe number of ports + +LOOKUP_SET(LOGIN_USER, luser, 512, STRING, NONE) //string +LOOKUP_SET(NEW_USER, user, 513, STRING, WO) //string +LOOKUP_SET(LOGIN_PASSWORD, lpw, 514, STRING, NONE) //string +LOOKUP_SET(NEW_PASSWORD, password, 515, STRING, WO) //string +LOOKUP_SET(REBOOT, reboot, 773, BOOL, NONE) //bool byte = save config + +LOOKUP_SET(RESET, reset, 1280, ACTION, NONE) // +LOOKUP_SET(FLASH, flash, 1536, ACTION, NONE) //update firmware + +LOOKUP_SET(PORT_VLAN_FOOOOO,vlan21, 2101, HEX, RO) +LOOKUP_SET(VLAN_FOOOOOO, vlan22, 2200, HEX, RO) //vlan + +LOOKUP_SET(SAVE, save, 2304, ACTION, NONE) //save +LOOKUP_SET(PING, ping, 2305, ACTION, NONE) //sent before SET ??? + +LOOKUP_SET(IGMP_SNOOPING, igmp, 4352, HEX, RW) //??? +LOOKUP_SET(PORTS_SETTINGS, psetings, 4096, HEX, RW) //+per port +LOOKUP_SET(PORT_TRUNK, trunk, 4608, HEX, RW) //byte[5] last byte bitmask?? + +LOOKUP_SET(MTU_VLAN, 8192, 8192, HEX, UNKNOWN) //byte[2] first byte bool,second byte port id +LOOKUP_SET(PORT_VLAN_ENABLED,8448, 8448, BOOL, UNKNOWN) //open page +LOOKUP_SET(PORT_VLAN, 8449, 8449, HEX, UNKNOWN) +LOOKUP_SET(PORT_VLAN_MAX, 8450, 8450, DEC, UNKNOWN) +LOOKUP_SET(VLAN_ENABLED, 8704, 8704, BOOL, UNKNOWN) //+bool byte +LOOKUP_SET(VLAN, 8705, 8705, HEX, UNKNOWN) //+one set per vlan +LOOKUP_SET(VLAN_PVID, 8706, 8706, HEX, UNKNOWN) //+per port +LOOKUP_SET(VLAN_FOOOO, 8707, 8707, DEC, UNKNOWN) //???? + +LOOKUP_SET(QOS_BASIC_ENABLED,12288, 12288, BOOL, UNKNOWN) //+bool = QoS Mod +LOOKUP_SET(QOS_BASIC, 12289, 12289, HEX, UNKNOWN) //+per port ??? +LOOKUP_SET(BW_CONTROL_INGRESS,12544, 12544, HEX, UNKNOWN) //+per port ??? +LOOKUP_SET(BW_CONTROL_EGRESS,12545, 12545, HEX, UNKNOWN) //+per port ??? +LOOKUP_SET(STORM_CONTROL, 12800, 12800, HEX, UNKNOWN) //+per port ??? +LOOKUP_SET(PORT_MIRROR, 16640, 16640, HEX, UNKNOWN) //byte[10] second byte port id??? +LOOKUP_SET(PORT_STATISTICS, 16384, 16384, HEX, UNKNOWN) //+per port ??? +LOOKUP_SET(CABLE_TEST, 16896, 16896, HEX, UNKNOWN) //+per port ??? +LOOKUP_SET(LOOP_PREVENTION, 17152, 17152, BOOL, UNKNOWN) //+bool byte \ No newline at end of file diff --git a/src/lookup/rcv.lst b/src/lookup/rcv.lst index 7380ef2..f7cee17 100644 --- a/src/lookup/rcv.lst +++ b/src/lookup/rcv.lst @@ -1,13 +1,13 @@ -LOOKUP_SET(TYPE, 1, STRING) //+string -LOOKUP_SET(HOSTNAME, 2, STRING) //+string -LOOKUP_SET(MAC, 3, HEX) //+byte[6] -LOOKUP_SET(IP_ADDR, 4, DEC) //+byte[4] -LOOKUP_SET(IP_MASK, 5, DEC) //+byte[4] -LOOKUP_SET(GATEWAY, 6, DEC) //+byte[4] -LOOKUP_SET(FIRMWARE_VERSION, 7, STRING) -LOOKUP_SET(HARDWARE_VERSION, 8, STRING) -LOOKUP_SET(DHCP_ENABLED, 9, BOOL) //+bool byte +LOOKUP_SET(TYPE,type, 1, STRING) //+string +LOOKUP_SET(HOSTNAME,host, 2, STRING) //+string +LOOKUP_SET(MAC,MAC, 3, HEX) //+byte[6] +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(FIRMWARE_VERSION,FIRMWARE_VERSION, 7, STRING) +LOOKUP_SET(HARDWARE_VERSION,HARDWARE_VERSION, 8, STRING) +LOOKUP_SET(DHCP_ENABLED,dhcp, 9, BOOL) //+bool byte -LOOKUP_SET(PORT_VLAN_FOOOOO, 2101, HEX) +LOOKUP_SET(PORT_VLAN_FOOOOO, 2101,2101, HEX) diff --git a/src/lookup/snd.lst b/src/lookup/snd.lst index d254a39..797512e 100644 --- a/src/lookup/snd.lst +++ b/src/lookup/snd.lst @@ -1,17 +1,17 @@ -LOOKUP_SET(SYSTEM_INFO, 2, HEX) //page sysinfo -LOOKUP_SET(IP_CONFIG, 9, HEX) //page sysinfo +LOOKUP_SET(SYSTEM_INFO,SYSTEM_INFO, 2, HEX) //page sysinfo +LOOKUP_SET(IP_CONFIG,IP_CONFIG, 9, HEX) //page sysinfo -LOOKUP_SET(LOGIN_USER, 512, STRING) //string -LOOKUP_SET(NEW_USER, 513, STRING) //string -LOOKUP_SET(LOGIN_PASSWORD, 514, STRING) //string -LOOKUP_SET(NEW_PASSWORD, 515, STRING) //string -LOOKUP_SET(REBOOT, 773, BOOL) //bool byte = save config +LOOKUP_SET(LOGIN_USER,LOGIN_USER, 512, STRING) //string +LOOKUP_SET(NEW_USER,NEW_USER, 513, STRING) //string +LOOKUP_SET(LOGIN_PASSWORD,LOGIN_PASSWORD, 514, STRING) //string +LOOKUP_SET(NEW_PASSWORD,NEW_PASSWORD, 515, STRING) //string +LOOKUP_SET(REBOOT,REBOOT, 773, BOOL) //bool byte = save config -LOOKUP_SET(RESET, 1280, ACTION) // -LOOKUP_SET(FLASH, 1536, ACTION) //update firmware -LOOKUP_SET(VLAN_FOOOOOO, 2200, HEX) //vlan -LOOKUP_SET(SAVE, 2304, ACTION) //save -LOOKUP_SET(PING, 2305, ACTION) //sent before SET ??? +LOOKUP_SET(RESET,RESET, 1280, ACTION) // +LOOKUP_SET(FLASH,FLASH, 1536, ACTION) //update firmware +LOOKUP_SET(VLAN_FOOOOOO, 2200,2200, HEX) //vlan +LOOKUP_SET(SAVE,SAVE, 2304, ACTION) //save +LOOKUP_SET(PING,PING, 2305, ACTION) //sent before SET ??? diff --git a/src/smrtlink.cpp b/src/smrtlink.cpp index 8a821ee..ca4a5c6 100644 --- a/src/smrtlink.cpp +++ b/src/smrtlink.cpp @@ -1,221 +1,169 @@ //============================================================================ // Name : smrtlink.cpp // Author : jdi -// Version : +// Version : 1.2 // Copyright : GPL v2 // Description : SmrtLink in C++, Ansi-style //============================================================================ -#include #include -#include #include + +#include +#include #include -#include #include #include #include "Constant.h" +#include "Interactive.h" #include "Host.h" #include "Program.h" +#include "Types.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]; -} - 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, "bhrvVXIswxP:U:i:f:t:d::", longopts, + &index)) != -1) { + switch (opt) { - 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; - case 'h': - fprintf(stderr, VERSION); - fprintf(stderr, USAGE, argv[0]); - fprintf(stderr, HELP); - exit(EXIT_SUCCESS); - break; + case 'V': + fprintf(stderr, VERSION); + exit(EXIT_SUCCESS); + break; - case 'v': - fprintf(stderr, VERSION); - exit(EXIT_SUCCESS); - break; + case 'r': + options.flags.REVERSE = true; + break; - case 'r': - options.flags |= FLAG_REVERSE; - break; + case 'b': + options.flags.HEADER = true; + break; - case 'b': - options.flags |= FLAG_HEADER; - break; + case 'x': + options.flags.HEX = true; + break; - case 'x': - options.flags |= FLAG_HEX; - break; + case 's': + options.flags.PERMANENT = true; + break; - case 's': - options.flags |= FLAG_PERMANENT; - break; + case 'w': + options.flags.WAIT = true; + break; - case 'w': - options.flags |= FLAG_WAIT; - break; + case 'X': + options.flags.INTERACTIVE = true; + break; - case 'd': - options.flags |= FLAG_DEBUG; - if (optarg != NULL) - options.debug_level = atoi(optarg); - break; + case 'v': + if (optarg != NULL) + options.verbosity = atoi(optarg); + else + options.verbosity++; + break; - case 't': - options.timeout = atol(optarg); - break; + case 'd': + if (optarg != NULL) + options.debug_level = atoi(optarg); + else + options.debug_level++; + break; - case 'f': - options.file = std::string(optarg); - break; + case 't': + options.timeout = atol(optarg); + break; - case 'p': - options.password = std::string(optarg); - break; + case 'f': + options.file = std::string(optarg); + break; - case 'u': - options.user = std::string(optarg); - break; + case 'P': + options.password = std::string(optarg); + break; - case 'i': - options.interface = std::string(optarg); - break; + case 'U': + options.user = std::string(optarg); + break; - default: /* '?' */ - fprintf(stderr, "Unknown option\n"); - fprintf(stderr, USAGE, argv[0]); - exit(EXIT_FAILURE); - } - } + case 'i': + options.interface = std::string(optarg); + break; - /*//TODO stdin - std::ostringstream bucket; - bucket << std::cin.rdbuf(); - p.input = bucket.str(); - */ + default: /* '?' */ + fprintf(stderr, "Unknown option\n"); + fprintf(stderr, USAGE, argv[0]); + exit(EXIT_FAILURE); + } + } - if (optind >= argc) { - fprintf(stderr, "Command expected\n"); - fprintf(stderr, USAGE, argv[0]); - exit(EXIT_FAILURE); - } + /*//TODO stdin + std::ostringstream bucket; + bucket << std::cin.rdbuf(); + p.input = bucket.str(); + */ - p.init(); + if (optind >= argc && !options.flags.INTERACTIVE) { + cerr << "Command expected\n"; + cerr << USAGE; + exit(EXIT_FAILURE); + } - if (optind < argc) { - std::string cmd = std::string(argv[optind++]); - - 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; - - case caseArg("get"): - if (p.getProperty()) - 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("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); + Interactive p = Interactive(); + if (options.flags.INTERACTIVE) { + if (optind < argc) { + 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) { + vector v; + while (optind < argc) + v.push_back(argv[optind++]); + p.single(v); + } + exit(EXIT_FAILURE); } diff --git a/src/table.cpp b/src/table.cpp index e207490..7a14331 100644 --- a/src/table.cpp +++ b/src/table.cpp @@ -9,17 +9,33 @@ #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]; } -bool table::exists(short n){ - return !(left.find(n) == left.end()); +const table::set table::operator[](short n) { + return *this->left[n]; } -std::string table::name(short n){ - return this->left[n].name; +bool table::exists(std::string s) { + return !(right.find(s) == right.end()); +} +bool table::exists(short n) { + 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; } diff --git a/src/table.h b/src/table.h index 377c768..96b91b5 100644 --- a/src/table.h +++ b/src/table.h @@ -12,19 +12,32 @@ #include class table { -public: - enum F {STRING,HEX,DEC,ACTION,BOOL,EMPTY}; - struct set { - short type; - F format; - std::string name; - }; - table(std::initializer_list l); - set operator[](short); - bool exists(short); - std::string name(short); -private: - std::map left; + public: + enum A { + RW, RO, WO, NONE, UNKNOWN + }; + enum F { + STRING, HEX, DEC, ACTION, BOOL, EMPTY + }; + struct set { + short type; + F format; + A action; + std::string name; + std::string id; + }; + 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::vector data; + std::map left; + std::map right; }; #endif /* LOOKUPTABLE_H_ */ diff --git a/test.sh b/test.sh new file mode 100755 index 0000000..e4f2d29 --- /dev/null +++ b/test.sh @@ -0,0 +1,18 @@ +#!/bin/sh +clear +echo SmrtLink Test + +echo bin/smrtlink encode 00:11:22:33:44:55:66:77:88:99 +bin/smrtlink encode 00:11:22:33:44:55:66:77:88:9 + +echo bin/smrtlink -i eth0 list +bin/smrtlink -i eth0 list + +echo bin/smrtlink -i eth6 list +bin/smrtlink -i eth6 list + +echo bin/smrtlink list +bin/smrtlink list + +echo bin/smrtlink -i wlan0 list +bin/smrtlink -i wlan0 list