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_ */