This commit is contained in:
j3d1 2016-01-28 00:37:13 +01:00
parent 4543473821
commit 299490ca5f
20 changed files with 638 additions and 429 deletions

View file

@ -15,7 +15,7 @@ $(BUILDDIR):
$(TARGET): $(OBJECTS) $(TARGET): $(OBJECTS)
$(CC) $^ -o $(BUILDDIR)/$@ -lboost_filesystem -lboost_system $(CC) $^ -o $(BUILDDIR)/$@ -lboost_filesystem -lboost_system -lpthread
$(OBJECTS): $(BUILDDIR)/%.o : $(SOURCEDIR)/%.cpp $(OBJECTS): $(BUILDDIR)/%.o : $(SOURCEDIR)/%.cpp

View file

@ -11,39 +11,29 @@
#include "Types.h" #include "Types.h"
#define VERSION "smrtlink (v1.1 Linux)\n" #define VERSION "smrtlink (v1.1 Linux)\n"
#define USAGE "usage: %s [-bdhjrvswx] [-i interface] [-u [password:]username]\n\ #define USAGE "usage: %s [-bhrVstx] [-i interface] [-U [password:]username]\n\
[-p password] <command>\n\n" [-P password] <command>\n\n"
#define HELP "\ #define HELP "\
Option Summary:\n\ Option Summary:\n\
-h --help This help text\n\ -h --help This help text\n\
-v --version Display version of this tool\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\ -r --reverse switch ports to emulate switch while sniffing\n\
-i --interface <iface> only use one Interface\n\
-t --timeout <n> Timeout in milliseconds. Default: 180\n\
-s --permanent make changes immediately permanent\n\
\
-b --header Show header\n\ -b --header Show header\n\
-x --hex Display Packets as Hex String\n\ -x --hex Display Packets as Hex String\n\
-j --json Display Packets as JSON\n\ \
-i --interface <iface> only use one Interface\n\ -U --user <[password:]username>\n\
-u --user <[password:]username>\n\ -P --password <password>\n\
-p --password <password>\n\ Login with Username and Password\n\n\
Login with Username and Password\n\
-f --file <path> choose a settings file\n\n\
-t --timeout <n> 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\ Command Summary:\n\
help This help text\n\
list list all connected switches\n\ list list all connected switches\n\
sniff [type:<type>] [<filter>]\n\ sniff capture and display all incoming or outgoing packets\n\
capture and display all incoming or outgoing packets\n\
depending on the --reverse option\n\ depending on the --reverse option\n\
encode use encoding algorithm on hex data separated by colon\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\ reboot Not yet implemented\n\
reset Not yet implemented\n\n\ reset Not yet implemented\n\n\
### for questions please contact <smrtlink@jdi.li> ###\n\n" ### for questions please contact <smrtlink@jdi.li> ###\n\n"
@ -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; extern Options options;
#endif /* OPTIONS_H_ */ #endif /* OPTIONS_H_ */

33
src/Interactive.cpp Normal file
View file

@ -0,0 +1,33 @@
/*
* Interactive.cpp
*
* Created on: 27.01.2016
* Author: jedi
*/
#include <iostream>
#include <string>
#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 <<endl;;
}
return 0;
}

18
src/Interactive.h Normal file
View file

@ -0,0 +1,18 @@
/*
* Interactive.h
*
* Created on: 27.01.2016
* Author: jedi
*/
#ifndef INTERACTIVE_H_
#define INTERACTIVE_H_
class Interactive {
public:
Interactive();
virtual ~Interactive();
int run();
};
#endif /* INTERACTIVE_H_ */

View file

@ -277,6 +277,14 @@ void Packet::pull(bytes &arr, int &index, int &ret) {
ret |= arr[index++] & 0xFF; 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) { void Packet::pull(bytes &arr, int &index, dataset &ret) {
pull(arr, index, ret.type); pull(arr, index, ret.type);
pull(arr, index, ret.len); pull(arr, index, ret.len);

View file

@ -20,7 +20,7 @@ class Packet
public: public:
enum OpCode {DISCOVERY, GET, RETURN, SET, CONFIRM, NONE}; enum OpCode {DISCOVERY, GET, RETURN, SET, CONFIRM, NONE};
Packet(OpCode); Packet(OpCode);
void encode(bytes&); static void encode(bytes&);
bytes getBytes(); bytes getBytes();
void parse(bytes); void parse(bytes);
void printHeader(); void printHeader();
@ -41,6 +41,8 @@ public:
void setPayload(datasets payload); void setPayload(datasets payload);
short getTokenId() const; short getTokenId() const;
void setTokenId(short tokenId = 0); void setTokenId(short tokenId = 0);
byte getOpCode() const;
void setOpCode(byte opCode);
private: private:
bytes head = bytes(32); bytes head = bytes(32);

View file

@ -17,10 +17,12 @@
#include "lookup.h" #include "lookup.h"
#include "table.h" #include "table.h"
using namespace std;
int printHeader(Packet p) { int printHeader(Packet p) {
if (options.flags & FLAG_HEADER) { if (options.flags.HEADER) {
if (options.flags & FLAG_HEX) { if (options.flags.HEX) {
std::cout << "Received Header:\n\t" << p.getHead() << "\n"; cout << "Received Header:\n\t" << p.getHead() << "\n";
} else { } else {
p.printHeader(); p.printHeader();
printf("\n"); printf("\n");
@ -30,56 +32,51 @@ int printHeader(Packet p) {
} }
int printPacket(Packet p) { int printPacket(Packet p) {
if (options.flags & FLAG_HEX) { if (options.flags.HEX) {
std::cout << "Received Payload:\n\t" << p.getBody() << "\n"; cout << "Received Payload:\n\t" << p.getBody() << "\n";
} else { } else {
for (dataset d : p.getPayload()) { for (dataset d : p.getPayload()) {
auto lookup = auto lookup = (options.flags.REVERSE) ? snd_lookup : rcv_lookup;
(options.flags & FLAG_REVERSE) ? snd_lookup : rcv_lookup;
if (lookup.exists(d.type)) { if (lookup.exists(d.type)) {
table::set s = lookup[d.type]; table::set s = lookup[d.type];
if (d.len > 0) { if (d.len > 0) {
switch (s.format) { switch (s.format) {
case table::STRING: case table::STRING:
std::cout << "+\t" << s.name << " = " << &d.value[0] cout << "+\t" << s.name << " = " << &d.value[0] << "\n";
<< "\n";
break; break;
case table::BOOL: case table::BOOL:
std::cout << "+\t" << s.name << " = " cout << "+\t" << s.name << " = "
<< (d.value[0] ? "YES" : "NO") << "\n"; << (d.value[0] ? "YES" : "NO") << "\n";
break; break;
case table::HEX: case table::HEX:
std::cout << "+\t" << s.name << " = " << d.value cout << "+\t" << s.name << " = " << d.value << "\n";
<< "\n";
break; break;
case table::DEC: case table::DEC:
std::cout << "+\t" << s.name << " = "; cout << "+\t" << s.name << " = ";
if (d.value.size() > 0) 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++) for (unsigned i = 1; i < d.value.size(); i++)
std::cout << std::dec << "." cout << dec << "." << (unsigned) d.value[i];
<< (unsigned) d.value[i]; cout << "\n";
std::cout << "\n";
break; break;
case table::ACTION: case table::ACTION:
std::cout << "Error:" << s.name cout << "Error:" << s.name
<< " is marked as 'action' but carries payload." << " is marked as 'action' but carries payload."
<< d.value << "\n"; << d.value << "\n";
break; break;
default: default:
std::cout << "+\t" << s.name << " = " << d.value cout << "+\t" << s.name << " = " << d.value << "\n";
<< "\n";
break; break;
} }
} else { //empty } else { //empty
std::cout << std::dec << ">\t" << s.name << "\n"; cout << dec << ">\t" << s.name << "\n";
} }
} else { //unknown id } else { //unknown id
if (d.len > 0) { if (d.len > 0) {
std::cout << "##\t" << d.type << ":\n\t"; cout << "##\t" << d.type << ":\n\t";
std::cout << std::hex << d.value << std::dec << "\n"; cout << hex << d.value << dec << "\n";
} else { //empty } else { //empty
std::cout << "#>\t" << d.type << "\n"; cout << "#>\t" << d.type << "\n";
} }
} }
} }
@ -88,38 +85,27 @@ int printPacket(Packet p) {
} }
int Program::list() { 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 { try {
sock->setHostIp(host.getIp()); cout << "List:\n";
sock->init(DST_PORT, SRC_PORT); discover([this](Packet a) {
sock->callback =
[this](Packet a) {
printHeader(a); printHeader(a);
if (options.flags & FLAG_HEX) { if (options.flags.HEX) {
std::cout <<"Received Payload:\n"<<a.getBody()<<"\n"; cout <<"Received Payload:\n"<<a.getBody()<<"\n";
} else { } else {
datasets d =a.getPayload(); datasets d =a.getPayload();
Switch sw = Switch(); Switch sw = Switch();
sw.parse(d); sw.parse(d);
File f; File f;
f.write(sw.toString()); f.write(sw.toString());
std::cout <<"\t"<<sw.settings.hostname<<" ("<< sw.device.type<<")\tMAC: "<<sw.device.mac<<"\tIP: "<<sw.settings.ip_addr<<"\n"; sw.print();
} }
return 1; return 0;
}; });
sock->send(b);
io_service->run(); io_service->run();
} catch (std::exception& e) { } catch (exception& e) {
std::cerr << "Exception: " << e.what() << "\n"; cerr << "Exception: " << e.what() << "\n";
} }
return 1; return 0;
} }
int Program::sniff() { int Program::sniff() {
@ -130,102 +116,105 @@ int Program::sniff() {
s.setHostIp(host.getIp()); s.setHostIp(host.getIp());
s.init(DST_PORT, SRC_PORT); s.init(DST_PORT, SRC_PORT);
s.callback = [](Packet p) { s.callback = [](Packet p) {
std::cout << p.opCodeToString() << "\n"; cout << p.opCodeToString() << "\n";
printHeader(p); printHeader(p);
printPacket(p); printPacket(p);
return 0; return 0;
}; };
s.listen(); s.listen();
io_service.run(); io_service.run();
} catch (std::exception& e) { } catch (exception& e) {
std::cerr << "Exception: " << e.what() << "\n"; cerr << "Exception: " << e.what() << "\n";
} }
return 1; return 0;
} }
int Program::encode(std::string s) { int Program::encode(string s) {
bytes d(s); bytes d;
Packet p = Packet(Packet::DISCOVERY); d = d.readHex(s);
Packet p = Packet(Packet::NONE);
p.encode(d); p.encode(d);
std::cout << d << std::endl; cout << d << endl;
return 0; return 0;
} }
int Program::setProperty() { int Program::setProperty(map<string, string> prop) {
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;
try { try {
sock->setHostIp(host.getIp()); datasets data = { };
sock->init(DST_PORT, SRC_PORT); for (auto p : prop) {
sock->callback = string s = p.second;
[this](Packet a) { dataset d;
auto s = sock; if (rcv_lookup.exists(p.first)) {
d.type = rcv_lookup.type(p.first);
if (rcv_lookup[p.first].format == table::STRING) {
d.len = s.size() + 1;
d.value = s;
data.push_back(d);
}
}
}
cout << "List:\n";
discover([this,data](Packet a) {
datasets d =a.getPayload(); datasets d =a.getPayload();
Switch sw = Switch(); Switch sw = Switch();
sw.parse(d); sw.parse(d);
std::cout <<"\t"<<sw.settings.hostname<<" ("<< sw.device.type<<")\tMAC: "<<sw.device.mac<<"\tIP: "<<sw.settings.ip_addr<<"\n"; sw.print();
Packet p = Packet(Packet::GET);
p.setSwitchMac(a.getSwitchMac());
p.setHostMac(host.getMac());
datasets t = { {SND_PING, 0, {}}}; datasets t = { {SND_PING, 0, {}}};
p.setPayload(t); get(a, t, [this,data](Packet a) {
bytes c = p.getBytes();
p.encode(c);
sock->callback =
[this](Packet a) {
auto s = sock;
datasets d =a.getPayload(); datasets d =a.getPayload();
Switch sw = Switch(); Switch sw = Switch();
sw.parse(d); sw.parse(d);
Packet p = Packet(Packet::SET); set(a,data,
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);
sock->callback =
[this](Packet a) { [this](Packet a) {
std::cout << a.opCodeToString() << "\n"; cout << a.opCodeToString() << "\n";
printHeader(a); printHeader(a);
printPacket(a); printPacket(a);
return 0; return 0;
}; });
sock->send(c);
return 0; return 0;
}; });
return 0;
});
sock->send(c);
return 0;
};
sock->send(b);
io_service->run(); io_service->run();
} catch (std::exception& e) { } catch (exception& e) {
std::cerr << "Exception: " << e.what() << "\n"; cerr << "Exception: " << e.what() << "\n";
} }
return 1; return 0;
}
int Program::getProperty(vector<string> 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() { int Program::save() {
@ -233,40 +222,118 @@ int Program::save() {
sw.settings.hostname = "testname.lan"; sw.settings.hostname = "testname.lan";
File f; File f;
f.write(sw.toString()); f.write(sw.toString());
return 1; return 0;
} }
int Program::restore() { int Program::restore() {
File f; File f;
Switch sw; Switch sw;
sw.parse(f.read()); sw.parse(f.read());
std::cout << "Devices:\n\t" << sw.settings.hostname << " (" sw.print();
<< sw.device.type << ")\tMAC: " << sw.device.mac << "\tIP: " return 0;
<< sw.settings.ip_addr << "\n";
return 1;
} }
int Program::flash() { int Program::flash() {
return 0; return 1;
} }
int Program::reboot() { int Program::reboot() {
try {
discover([this](Packet a) {
datasets d =a.getPayload();
Switch sw = Switch();
sw.parse(d);
cout <<sw.settings.hostname<<"\t";
datasets t = { {SND_PING, 0, {}}};
get(a, t, [this](Packet a) {
datasets d =a.getPayload();
Switch sw = Switch();
sw.parse(d);
datasets t = { {REBOOT, 1, {options.flags.PERMANENT?(byte)1:(byte)0}}};
set(a,t,[this](Packet a) {
if( a.getOpCode()==Packet::CONFIRM)
cout<< "rebooting now.\n";
return 0;
});
return 0;
});
return 0;
});
io_service->run();
} catch (exception& e) {
cerr << "Exception: " << e.what() << "\n";
}
return 0; return 0;
} }
int Program::reset() { int Program::reset() {
try {
discover([this](Packet a) {
datasets d =a.getPayload();
Switch sw = Switch();
sw.parse(d);
cout <<sw.settings.hostname<<"\t";
datasets t = { {SND_PING, 0, {}}};
get(a, t, [this](Packet a) {
datasets d =a.getPayload();
Switch sw = Switch();
sw.parse(d);
datasets t = { {RESET, 0, {}}};
set(a,t,[this](Packet a) {
if( a.getOpCode()==Packet::CONFIRM)
cout<< "reseting config.\n";
return 0;
});
return 0;
});
return 0;
});
io_service->run();
} catch (exception& e) {
cerr << "Exception: " << e.what() << "\n";
}
return 0; return 0;
} }
int Program::ping(std::function<int(Packet)>) { int Program::discover(function<int(Packet)> 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<int(Packet)> 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<int(Packet)> 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; return 0;
} }
void Program::init() { void Program::init() {
if (options.interface.compare("") == 0) if (options.interface.compare("") == 0)
options.interface = host.getIface(); options.interface = host.getIface();
sock->setHostIp(host.getIp());
sock->init(DST_PORT, SRC_PORT);
} }

View file

@ -19,7 +19,9 @@ private:
std::shared_ptr<boost::asio::io_service> io_service; std::shared_ptr<boost::asio::io_service> io_service;
std::shared_ptr<Socket> sock; std::shared_ptr<Socket> sock;
Host host = Host(); Host host = Host();
int ping(std::function<int(Packet)>); int get(Packet,datasets,std::function<int(Packet)>);
int set(Packet,datasets,std::function<int(Packet)>);
int discover(std::function<int(Packet)>);
public: public:
Program() { Program() {
io_service = std::make_shared<boost::asio::io_service>(); io_service = std::make_shared<boost::asio::io_service>();
@ -29,8 +31,8 @@ public:
int list(); int list();
int sniff(); int sniff();
int encode(std::string); int encode(std::string);
int setProperty(); int getProperty(std::vector<std::string>);
int getProperty(); int setProperty(std::map<std::string,std::string>);
int save(); int save();
int restore(); int restore();
int flash(); int flash();

View file

@ -21,13 +21,13 @@ void Socket::init(short dst_port, short src_port) {
if (initialized) if (initialized)
return; return;
if (options.flags & FLAG_REVERSE) { if (options.flags.REVERSE) {
short p = dst_port; short p = dst_port;
dst_port = src_port; dst_port = src_port;
src_port = p; src_port = p;
} }
if (options.flags & FLAG_DEBUG) if (options.debug_level>=1)
std::cout << "Local IP:\t" << local_ip << "\n"; std::cout << "Local IP:\t" << local_ip << "\n";
wildcard_endpoint_ = boost::asio::ip::udp::endpoint( wildcard_endpoint_ = boost::asio::ip::udp::endpoint(
@ -67,7 +67,9 @@ void Socket::setHostIp(ipAddr ip) {
local_ip = 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]; unsigned char * a = &data[0];
send_socket_.async_send_to(boost::asio::buffer(a, data.size()), send_socket_.async_send_to(boost::asio::buffer(a, data.size()),
broadcast_endpoint_, broadcast_endpoint_,

View file

@ -23,7 +23,7 @@ public:
virtual ~Socket() { virtual ~Socket() {
} }
void init(short, short); void init(short, short);
void send(bytes); void send(Packet);
void listen(); void listen();
void setHostIp(ipAddr); void setHostIp(ipAddr);
std::function<int(Packet)> callback = [](Packet a) { std::function<int(Packet)> callback = [](Packet a) {

View file

@ -16,7 +16,7 @@ int Switch::parse(std::string str) {
if (json.Parse(str.c_str()).HasParseError()) if (json.Parse(str.c_str()).HasParseError())
return 1; return 1;
if (options.flags & FLAG_DEBUG) if (options.debug_level>=1)
std::cout << "\nParsing to document succeeded.\n"; std::cout << "\nParsing to document succeeded.\n";
if (json.IsObject()) { if (json.IsObject()) {

View file

@ -19,6 +19,12 @@ int Switch::parse(datasets arr) {
return 0; 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) { int Switch::parse(dataset d) {
switch (d.type) { switch (d.type) {
case RCV_TYPE: case RCV_TYPE:
@ -63,4 +69,3 @@ int Switch::parse(dataset d) {
} }
return 0; return 0;
} }

View file

@ -65,6 +65,7 @@ public:
int parse(datasets); int parse(datasets);
int parse(dataset); int parse(dataset);
int parse(std::string); int parse(std::string);
int print();
std::string toString(); std::string toString();
struct { struct {

View file

@ -63,7 +63,6 @@ public:
}; };
*/ */
class ipAddr: public std::array<byte, 4> { class ipAddr: public std::array<byte, 4> {
public: public:
@ -113,12 +112,22 @@ std::vector<T> &operator+=(std::vector<T> &A, const std::vector<T> &B) {
} }
struct Options { struct Options {
unsigned flags = 0x00; struct {
bool HEX;
bool JSON;
bool PLAIN;
bool REVERSE;
bool HEADER;
bool PERMANENT;
bool WAIT;
bool INTERACTIVE;
} flags;
std::string user; std::string user;
std::string password; std::string password;
std::string interface; std::string interface;
std::string file; std::string file;
int debug_level = 0; int debug_level = 0;
int verbosity = 0;
long timeout = 180U; long timeout = 180U;
}; };

View file

@ -28,6 +28,7 @@ public:
} }
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<uint8_t> s) bytes(std::initializer_list<uint8_t> s)

View file

@ -27,6 +27,14 @@ public:
push_back(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_ */ #endif /* DATASETS_H_ */

View file

@ -15,14 +15,14 @@ enum {
}; };
static table rcv_lookup { 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/rcv.lst"
#include "lookup/general.lst" #include "lookup/general.lst"
#undef LOOKUP_SET #undef LOOKUP_SET
}; };
static table snd_lookup { 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/snd.lst"
#include "lookup/general.lst" #include "lookup/general.lst"
#undef LOOKUP_SET #undef LOOKUP_SET

View file

@ -6,25 +6,30 @@
// Description : SmrtLink in C++, Ansi-style // Description : SmrtLink in C++, Ansi-style
//============================================================================ //============================================================================
#include <cstring>
#include <iostream> #include <iostream>
#include <sstream>
#include <string> #include <string>
#include <regex>
#include <cstring>
#include <sstream>
#include <cstdlib> #include <cstdlib>
#include <cstdio>
#include <getopt.h> #include <getopt.h>
#include <unistd.h> #include <unistd.h>
#include "Constant.h" #include "Constant.h"
#include "Interactive.h"
#include "Host.h" #include "Host.h"
#include "Program.h" #include "Program.h"
#include "Switch.h" #include "Switch.h"
#include "lookup.h"
#define no_argument 0 #define no_argument 0
#define required_argument 1 #define required_argument 1
#define optional_argument 2 #define optional_argument 2
using namespace std;
Options options; Options options;
constexpr unsigned int caseArg(const char* str, int h = 0) { constexpr unsigned int caseArg(const char* str, int h = 0) {
@ -32,24 +37,26 @@ constexpr unsigned int caseArg(const char* str, int h = 0) {
} }
int main(int argc, char *argv[]) { int main(int argc, char *argv[]) {
int opt, index; int index,opt;
options.user = DEFAULT_USER; options.user = DEFAULT_USER;
options.password = DEFAULT_PASS; options.password = DEFAULT_PASS;
const struct option longopts[] = { { "version", no_argument, 0, 'v' }, { const struct option longopts[] = { { "version", no_argument, 0, 'V' }, {
"help", no_argument, 0, 'h' }, { "reverse", no_argument, 0, 'r' }, { "verbose", no_argument, 0, 'v' }, { "help", no_argument, 0, 'h' }, {
"permanent", no_argument, 0, 's' }, { "debug", optional_argument, 0, "reverse", no_argument, 0, 'r' },
'd' }, { "password", required_argument, 0, 'p' }, { "user", { "permanent", no_argument, 0, 's' }, { "debug", optional_argument,
required_argument, 0, 'u' }, { "interface", required_argument, 0, 'i' }, { 0, 'd' }, { "password", required_argument, 0, 'P' }, {
"header", required_argument, 0, 'b' }, { "hex", required_argument, "user", required_argument, 0, 'U' }, { "interface",
0, 'x' }, { "file", required_argument, 0, 'f' }, { "timeout", required_argument, 0, 'i' }, { "header", required_argument,
required_argument, 0, 't' }, { "wait", 0, 'b' }, { "hex", required_argument, 0, 'x' }, { "file",
required_argument, 0, 'w' }, { 0, 0, 0, 0 }, }; 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,
while ((opt = getopt_long(argc, argv, "bhrVsxP:U:i:t::", longopts,
&index)) != -1) { &index)) != -1) {
switch (opt) { switch (opt) {
@ -60,35 +67,47 @@ int main(int argc, char *argv[]) {
exit(EXIT_SUCCESS); exit(EXIT_SUCCESS);
break; break;
case 'v': case 'V':
fprintf(stderr, VERSION); fprintf(stderr, VERSION);
exit(EXIT_SUCCESS); exit(EXIT_SUCCESS);
break; break;
case 'r': case 'r':
options.flags |= FLAG_REVERSE; options.flags.REVERSE = true;
break; break;
case 'b': case 'b':
options.flags |= FLAG_HEADER; options.flags.HEADER = true;
break; break;
case 'x': case 'x':
options.flags |= FLAG_HEX; options.flags.HEX = true;
break; break;
case 's': case 's':
options.flags |= FLAG_PERMANENT; options.flags.PERMANENT = true;
break; break;
case 'w': case 'w':
options.flags |= FLAG_WAIT; options.flags.WAIT = true;
break;
case 'X':
options.flags.INTERACTIVE = true;
break;
case 'v':
if (optarg != NULL)
options.verbosity = atoi(optarg);
else
options.verbosity++;
break; break;
case 'd': case 'd':
options.flags |= FLAG_DEBUG;
if (optarg != NULL) if (optarg != NULL)
options.debug_level = atoi(optarg); options.debug_level = atoi(optarg);
else
options.debug_level++;
break; break;
case 't': case 't':
@ -99,11 +118,11 @@ int main(int argc, char *argv[]) {
options.file = std::string(optarg); options.file = std::string(optarg);
break; break;
case 'p': case 'P':
options.password = std::string(optarg); options.password = std::string(optarg);
break; break;
case 'u': case 'U':
options.user = std::string(optarg); options.user = std::string(optarg);
break; break;
@ -124,67 +143,68 @@ int main(int argc, char *argv[]) {
p.input = bucket.str(); p.input = bucket.str();
*/ */
if (optind >= argc) { if (optind >= argc && !options.flags.INTERACTIVE) {
fprintf(stderr, "Command expected\n"); cerr << "Command expected\n";
fprintf(stderr, USAGE, argv[0]); cerr << USAGE;
exit(EXIT_FAILURE); exit(EXIT_FAILURE);
} }
p.init(); if (options.flags.INTERACTIVE) {
if (optind < argc) { if (optind < argc) {
std::string cmd = std::string(argv[optind++]); cerr << "Command is ignored in interactive mode\n";
}
switch (caseArg(cmd.c_str())) { Interactive p = Interactive();
case caseArg("set"): if (!p.run())
if (p.setProperty())
exit(EXIT_SUCCESS); exit(EXIT_SUCCESS);
fprintf(stderr, "Not yet implemented.\n"); fprintf(stderr, "Not yet implemented.\n");
exit(EXIT_FAILURE); exit(EXIT_FAILURE);
break; }
else if (optind < argc) {
Program p = Program();
p.init();
std::vector<std::string> vect;
std::map<std::string, std::string> list;
std::cmatch sm;
std::string cmd = std::string(argv[optind++]);
switch (caseArg(cmd.c_str())) {
case caseArg("reboot"): case caseArg("reboot"):
if (p.reboot()) if (!p.reboot())
exit(EXIT_SUCCESS); exit(EXIT_SUCCESS);
fprintf(stderr, "Not yet implemented.\n"); fprintf(stderr, "Not yet implemented.\n");
exit(EXIT_FAILURE); exit(EXIT_FAILURE);
break; break;
case caseArg("reset"): case caseArg("reset"):
if (p.reset()) if (!p.reset())
exit(EXIT_SUCCESS); exit(EXIT_SUCCESS);
fprintf(stderr, "Not yet implemented.\n"); fprintf(stderr, "Not yet implemented.\n");
exit(EXIT_FAILURE); exit(EXIT_FAILURE);
break; break;
case caseArg("save"): case caseArg("save"):
if (p.save()) if (!p.save())
exit(EXIT_SUCCESS); exit(EXIT_SUCCESS);
fprintf(stderr, "Not yet implemented.\n"); fprintf(stderr, "Not yet implemented.\n");
exit(EXIT_FAILURE); exit(EXIT_FAILURE);
break; break;
case caseArg("restore"): case caseArg("restore"):
if (p.restore()) if (!p.restore())
exit(EXIT_SUCCESS); exit(EXIT_SUCCESS);
fprintf(stderr, "Not yet implemented.\n"); fprintf(stderr, "Not yet implemented.\n");
exit(EXIT_FAILURE); exit(EXIT_FAILURE);
break; break;
case caseArg("flash"): case caseArg("flash"):
if (p.flash()) if (!p.flash())
exit(EXIT_SUCCESS); exit(EXIT_SUCCESS);
fprintf(stderr, "Not yet implemented.\n"); fprintf(stderr, "Not yet implemented.\n");
exit(EXIT_FAILURE); exit(EXIT_FAILURE);
break; break;
case caseArg("get"):
if (p.getProperty())
exit(EXIT_SUCCESS);
break;
case caseArg("list"): case caseArg("list"):
if (p.list()) if (!p.list())
exit(EXIT_SUCCESS); exit(EXIT_SUCCESS);
break; break;
case caseArg("sniff"): case caseArg("sniff"):
if (p.sniff()) if (!p.sniff())
exit(EXIT_SUCCESS); exit(EXIT_SUCCESS);
break; break;
@ -199,20 +219,46 @@ int main(int argc, char *argv[]) {
exit(EXIT_FAILURE); exit(EXIT_FAILURE);
} }
break; break;
case caseArg("set"):
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) { while (optind < argc) {
printf("->%s\n", argv[optind]); 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<std::string, std::string>(sm[1], sm[2]));
} else {
cerr << "Invalid Syntax " << argv[optind] << endl;
exit(EXIT_FAILURE);
}
optind++; 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);
} }
} }

View file

@ -8,18 +8,35 @@
#include <string> #include <string>
#include "table.h" #include "table.h"
table::table(std::initializer_list<set> l) { table::table(std::initializer_list<set> l) {
int i = 0; int i = 0;
this->data.resize(l.size());
for (set s : l) { for (set s : l) {
this->left[s.type] = s; 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){ const table::set table::operator[](std::string s){
return this->left[n]; 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){ bool table::exists(short n){
return !(left.find(n) == left.end()); return !(left.find(n) == left.end());
} }
std::string table::name(short n){ short table::type(std::string s){
return this->left[n].name; 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;
} }

View file

@ -18,13 +18,20 @@ public:
short type; short type;
F format; F format;
std::string name; std::string name;
std::string id;
}; };
table(std::initializer_list<set> l); table(std::initializer_list<set> l);
set operator[](short); const table::set operator[](std::string);
const table::set operator[](short);
bool exists(std::string);
bool exists(short); bool exists(short);
short type(std::string);
std::string id(short);
std::string name(short); std::string name(short);
private: private:
std::map<short, set> left; std::vector<set> data;
std::map<short, set*> left;
std::map<std::string, set*> right;
}; };
#endif /* LOOKUPTABLE_H_ */ #endif /* LOOKUPTABLE_H_ */