1.2
This commit is contained in:
parent
299490ca5f
commit
0f01d375db
13 changed files with 347 additions and 262 deletions
3
Makefile
3
Makefile
|
@ -15,8 +15,7 @@ $(BUILDDIR):
|
||||||
|
|
||||||
|
|
||||||
$(TARGET): $(OBJECTS)
|
$(TARGET): $(OBJECTS)
|
||||||
$(CC) $^ -o $(BUILDDIR)/$@ -lboost_filesystem -lboost_system -lpthread
|
$(CC) $^ -o $(BUILDDIR)/$@ -lboost_filesystem -lboost_system -lreadline -lboost_program_options
|
||||||
|
|
||||||
|
|
||||||
$(OBJECTS): $(BUILDDIR)/%.o : $(SOURCEDIR)/%.cpp
|
$(OBJECTS): $(BUILDDIR)/%.o : $(SOURCEDIR)/%.cpp
|
||||||
$(CC) $(CFLAGS) $< -o $@
|
$(CC) $(CFLAGS) $< -o $@
|
||||||
|
|
|
@ -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.
|
The usage is loosely based on the swconfig utility.
|
||||||
|
|
||||||
### dependencys
|
### dependencys
|
||||||
libboost-filesystem-dev
|
libboost-filesystem
|
||||||
libboost-system-dev
|
libboost-system
|
||||||
|
libboost-program-options
|
||||||
|
libreadline
|
||||||
|
|
||||||
### compatible devices
|
### compatible devices
|
||||||
+ TL-SG105E
|
+ TL-SG105E
|
||||||
|
|
|
@ -7,27 +7,40 @@
|
||||||
|
|
||||||
#include <iostream>
|
#include <iostream>
|
||||||
#include <string>
|
#include <string>
|
||||||
|
#include <vector>
|
||||||
|
#include <algorithm>
|
||||||
|
|
||||||
|
#include<boost/program_options/parsers.hpp>
|
||||||
|
#include<readline/readline.h>
|
||||||
|
#include<readline/history.h>
|
||||||
|
|
||||||
|
#include "Program.h"
|
||||||
#include "Interactive.h"
|
#include "Interactive.h"
|
||||||
|
|
||||||
using namespace std;
|
using namespace std;
|
||||||
|
|
||||||
Interactive::Interactive() {
|
int Interactive::loop() {
|
||||||
// TODO Auto-generated constructor stub
|
|
||||||
|
|
||||||
}
|
|
||||||
|
|
||||||
Interactive::~Interactive() {
|
|
||||||
// TODO Auto-generated destructor stub
|
|
||||||
}
|
|
||||||
|
|
||||||
int Interactive::run() {
|
|
||||||
string cmd;
|
string cmd;
|
||||||
while(cmd.compare("quit")){
|
vector<string> v;
|
||||||
cout<< "smrtlink>" << flush;
|
Program p = Program();
|
||||||
cin >> cmd;
|
p.init();
|
||||||
cout << cmd <<endl;;
|
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;
|
return 0;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
int Interactive::single(vector<string> v) {
|
||||||
|
Program p = Program();
|
||||||
|
p.init();
|
||||||
|
p.run(v);
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
|
|
@ -10,9 +10,12 @@
|
||||||
|
|
||||||
class Interactive {
|
class Interactive {
|
||||||
public:
|
public:
|
||||||
Interactive();
|
Interactive() {
|
||||||
virtual ~Interactive();
|
}
|
||||||
int run();
|
virtual ~Interactive() {
|
||||||
|
}
|
||||||
|
int loop();
|
||||||
|
int single(std::vector<std::string> v);
|
||||||
};
|
};
|
||||||
|
|
||||||
#endif /* INTERACTIVE_H_ */
|
#endif /* INTERACTIVE_H_ */
|
||||||
|
|
|
@ -158,8 +158,8 @@ std::string Packet::opCodeToString() {
|
||||||
return "SET";
|
return "SET";
|
||||||
case CONFIRM:
|
case CONFIRM:
|
||||||
return "CONFIRM";
|
return "CONFIRM";
|
||||||
case RETURN:
|
case REPLY:
|
||||||
return "RETURN";
|
return "REPLY";
|
||||||
default:
|
default:
|
||||||
return "NONE";
|
return "NONE";
|
||||||
}
|
}
|
||||||
|
|
21
src/Packet.h
21
src/Packet.h
|
@ -13,12 +13,13 @@
|
||||||
|
|
||||||
#include "Types.h"
|
#include "Types.h"
|
||||||
|
|
||||||
static short sequenceId=0;
|
static short sequenceId = 0;
|
||||||
|
|
||||||
class Packet
|
class Packet {
|
||||||
{
|
|
||||||
public:
|
public:
|
||||||
enum OpCode {DISCOVERY, GET, RETURN, SET, CONFIRM, NONE};
|
enum OpCode {
|
||||||
|
DISCOVERY, GET, REPLY, SET, CONFIRM, NONE
|
||||||
|
};
|
||||||
Packet(OpCode);
|
Packet(OpCode);
|
||||||
static void encode(bytes&);
|
static void encode(bytes&);
|
||||||
bytes getBytes();
|
bytes getBytes();
|
||||||
|
@ -37,7 +38,7 @@ public:
|
||||||
void setHostMac(macAddr);
|
void setHostMac(macAddr);
|
||||||
void setSwitchMac(macAddr);
|
void setSwitchMac(macAddr);
|
||||||
void setCheckSum(int);
|
void setCheckSum(int);
|
||||||
void setSequenceId(short );
|
void setSequenceId(short);
|
||||||
void setPayload(datasets payload);
|
void setPayload(datasets payload);
|
||||||
short getTokenId() const;
|
short getTokenId() const;
|
||||||
void setTokenId(short tokenId = 0);
|
void setTokenId(short tokenId = 0);
|
||||||
|
@ -50,9 +51,9 @@ private:
|
||||||
datasets payload;
|
datasets payload;
|
||||||
byte version = 1;
|
byte version = 1;
|
||||||
byte opCode;
|
byte opCode;
|
||||||
macAddr switchMac { {0, 0, 0, 0, 0, 0}};
|
macAddr switchMac { { 0, 0, 0, 0, 0, 0 } };
|
||||||
macAddr hostMac { {0, 0, 0, 0, 0, 0}};
|
macAddr hostMac { { 0, 0, 0, 0, 0, 0 } };
|
||||||
macAddr broadcastMac { {0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF}};
|
macAddr broadcastMac { { 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF } };
|
||||||
short tokenId = 0;
|
short tokenId = 0;
|
||||||
short fragmentOffset = 0;
|
short fragmentOffset = 0;
|
||||||
int errorCode = 0;
|
int errorCode = 0;
|
||||||
|
@ -60,7 +61,7 @@ private:
|
||||||
short flag = 0;
|
short flag = 0;
|
||||||
void buildHead();
|
void buildHead();
|
||||||
void buildBody();
|
void buildBody();
|
||||||
void push(bytes&, int&, short );
|
void push(bytes&, int&, short);
|
||||||
void push(bytes&, int&, int);
|
void push(bytes&, int&, int);
|
||||||
void push(bytes&, int&, byte);
|
void push(bytes&, int&, byte);
|
||||||
void push(bytes&, int&, bytes);
|
void push(bytes&, int&, bytes);
|
||||||
|
@ -70,7 +71,7 @@ private:
|
||||||
void pull(bytes&, int&, short &);
|
void pull(bytes&, int&, short &);
|
||||||
void pull(bytes&, int&, int&);
|
void pull(bytes&, int&, int&);
|
||||||
void pull(bytes&, int&, byte&);
|
void pull(bytes&, int&, byte&);
|
||||||
void pull(bytes&, int&, bytes&, unsigned );
|
void pull(bytes&, int&, bytes&, unsigned);
|
||||||
void pull(bytes&, int&, ipAddr&);
|
void pull(bytes&, int&, ipAddr&);
|
||||||
void pull(bytes&, int&, macAddr&);
|
void pull(bytes&, int&, macAddr&);
|
||||||
void pull(bytes&, int&, dataset&);
|
void pull(bytes&, int&, dataset&);
|
||||||
|
|
186
src/Program.cpp
186
src/Program.cpp
|
@ -6,6 +6,9 @@
|
||||||
*/
|
*/
|
||||||
#include <iostream>
|
#include <iostream>
|
||||||
#include <algorithm>
|
#include <algorithm>
|
||||||
|
#include <regex>
|
||||||
|
#include <string>
|
||||||
|
#include <cstring>
|
||||||
|
|
||||||
#include "Constant.h"
|
#include "Constant.h"
|
||||||
#include "Program.h"
|
#include "Program.h"
|
||||||
|
@ -14,11 +17,110 @@
|
||||||
#include "Socket.h"
|
#include "Socket.h"
|
||||||
#include "Switch.h"
|
#include "Switch.h"
|
||||||
#include "Packet.h"
|
#include "Packet.h"
|
||||||
|
#include "Filter.h"
|
||||||
|
#include "Types.h"
|
||||||
#include "lookup.h"
|
#include "lookup.h"
|
||||||
#include "table.h"
|
#include "table.h"
|
||||||
|
|
||||||
|
using namespace smrtlink;
|
||||||
using namespace std;
|
using namespace std;
|
||||||
|
|
||||||
|
int Program::run(vector<string> arg) {
|
||||||
|
int optind = 0;
|
||||||
|
std::vector<std::string> vect;
|
||||||
|
std::map<std::string, std::string> ll;
|
||||||
|
std::cmatch sm;
|
||||||
|
std::string cmd = arg[optind++];
|
||||||
|
|
||||||
|
io_service->reset();
|
||||||
|
sock->clear();
|
||||||
|
switch (caseArg(cmd.c_str())) {
|
||||||
|
case caseArg("reboot"):
|
||||||
|
if (reboot())
|
||||||
|
return 1;
|
||||||
|
break;
|
||||||
|
case caseArg("reset"):
|
||||||
|
if (!reset())
|
||||||
|
return 0;
|
||||||
|
break;
|
||||||
|
case caseArg("save"):
|
||||||
|
if (save())
|
||||||
|
return 1;
|
||||||
|
break;
|
||||||
|
case caseArg("restore"):
|
||||||
|
if (restore())
|
||||||
|
return 1;
|
||||||
|
break;
|
||||||
|
case caseArg("flash"):
|
||||||
|
if (flash())
|
||||||
|
return 1;
|
||||||
|
break;
|
||||||
|
|
||||||
|
case caseArg("list"):
|
||||||
|
if (list())
|
||||||
|
return 1;
|
||||||
|
break;
|
||||||
|
|
||||||
|
case caseArg("sniff"):
|
||||||
|
if (sniff())
|
||||||
|
return 1;
|
||||||
|
break;
|
||||||
|
|
||||||
|
case caseArg("encode"):
|
||||||
|
if (optind < arg.size()) {
|
||||||
|
std::string s(arg[optind]);
|
||||||
|
optind++;
|
||||||
|
if (!encode(s))
|
||||||
|
return 1;
|
||||||
|
} else {
|
||||||
|
fprintf(stderr, "Argument expected after encode\n");
|
||||||
|
return 1;
|
||||||
|
}
|
||||||
|
break;
|
||||||
|
case caseArg("set"):
|
||||||
|
while (optind < arg.size()) {
|
||||||
|
if (regex_match(arg[optind].c_str(), sm,
|
||||||
|
std::regex("^([a-z]+)=(.*)$"))) {
|
||||||
|
if (!snd_lookup.exists(sm[1]) && !rcv_lookup.exists(sm[1])) {
|
||||||
|
cerr << "Unknown argument " << arg[optind] << endl;
|
||||||
|
return 1;
|
||||||
|
}
|
||||||
|
ll.insert(std::pair<std::string, std::string>(sm[1], sm[2]));
|
||||||
|
} else {
|
||||||
|
cerr << "Invalid Syntax " << arg[optind] << endl;
|
||||||
|
return 1;
|
||||||
|
}
|
||||||
|
optind++;
|
||||||
|
}
|
||||||
|
if (setProperty(ll))
|
||||||
|
return 1;
|
||||||
|
break;
|
||||||
|
case caseArg("get"):
|
||||||
|
while (optind < arg.size()) {
|
||||||
|
if (regex_match(arg[optind].c_str(), sm,
|
||||||
|
std::regex("^([a-z]+)$"))) {
|
||||||
|
if (!snd_lookup.exists(sm[1]) && !rcv_lookup.exists(sm[1])) {
|
||||||
|
cerr << "Unknown argument " << arg[optind] << endl;
|
||||||
|
return 1;
|
||||||
|
}
|
||||||
|
vect.push_back(sm[1]);
|
||||||
|
} else {
|
||||||
|
cerr << "Invalid argument " << arg[optind] << endl;
|
||||||
|
return 1;
|
||||||
|
}
|
||||||
|
optind++;
|
||||||
|
}
|
||||||
|
if (getProperty(vect))
|
||||||
|
return 1;
|
||||||
|
break;
|
||||||
|
default:
|
||||||
|
printf("Unknown command: %s\n", cmd.c_str());
|
||||||
|
return 1;
|
||||||
|
}
|
||||||
|
io_service->run();
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
|
|
||||||
int printHeader(Packet p) {
|
int printHeader(Packet p) {
|
||||||
if (options.flags.HEADER) {
|
if (options.flags.HEADER) {
|
||||||
if (options.flags.HEX) {
|
if (options.flags.HEX) {
|
||||||
|
@ -93,15 +195,18 @@ int Program::list() {
|
||||||
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();
|
|
||||||
sw.parse(d);
|
int b = a.getSwitchMac().hash();
|
||||||
|
if (devices.empty()||devices.find(b) == devices.end())
|
||||||
|
devices.insert(pair<int,Switch>(b,Switch()));
|
||||||
|
devices[a.getSwitchMac().hash()].parse(d);
|
||||||
|
devices[a.getSwitchMac().hash()].print();
|
||||||
|
|
||||||
File f;
|
File f;
|
||||||
f.write(sw.toString());
|
f.write(devices[a.getSwitchMac().hash()].toString());
|
||||||
sw.print();
|
|
||||||
}
|
}
|
||||||
return 0;
|
return 0;
|
||||||
});
|
});
|
||||||
io_service->run();
|
|
||||||
} catch (exception& e) {
|
} catch (exception& e) {
|
||||||
cerr << "Exception: " << e.what() << "\n";
|
cerr << "Exception: " << e.what() << "\n";
|
||||||
}
|
}
|
||||||
|
@ -111,22 +216,15 @@ int Program::list() {
|
||||||
int Program::sniff() {
|
int Program::sniff() {
|
||||||
printf("Listening:\n");
|
printf("Listening:\n");
|
||||||
try {
|
try {
|
||||||
boost::asio::io_service io_service;
|
sock->listen([](Packet p) {
|
||||||
Socket s(io_service);
|
|
||||||
s.setHostIp(host.getIp());
|
|
||||||
s.init(DST_PORT, SRC_PORT);
|
|
||||||
s.callback = [](Packet p) {
|
|
||||||
cout << p.opCodeToString() << "\n";
|
cout << p.opCodeToString() << "\n";
|
||||||
printHeader(p);
|
printHeader(p);
|
||||||
printPacket(p);
|
printPacket(p);
|
||||||
return 0;
|
return 0;
|
||||||
};
|
});
|
||||||
s.listen();
|
|
||||||
io_service.run();
|
|
||||||
} catch (exception& e) {
|
} catch (exception& e) {
|
||||||
cerr << "Exception: " << e.what() << "\n";
|
cerr << "Exception: " << e.what() << "\n";
|
||||||
}
|
}
|
||||||
|
|
||||||
return 0;
|
return 0;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -179,8 +277,6 @@ int Program::setProperty(map<string, string> prop) {
|
||||||
});
|
});
|
||||||
return 0;
|
return 0;
|
||||||
});
|
});
|
||||||
|
|
||||||
io_service->run();
|
|
||||||
} catch (exception& e) {
|
} catch (exception& e) {
|
||||||
cerr << "Exception: " << e.what() << "\n";
|
cerr << "Exception: " << e.what() << "\n";
|
||||||
}
|
}
|
||||||
|
@ -210,7 +306,6 @@ int Program::getProperty(vector<string> prop) {
|
||||||
return 0;
|
return 0;
|
||||||
});
|
});
|
||||||
|
|
||||||
io_service->run();
|
|
||||||
} catch (exception& e) {
|
} catch (exception& e) {
|
||||||
cerr << "Exception: " << e.what() << "\n";
|
cerr << "Exception: " << e.what() << "\n";
|
||||||
}
|
}
|
||||||
|
@ -240,27 +335,27 @@ int Program::flash() {
|
||||||
|
|
||||||
int Program::reboot() {
|
int Program::reboot() {
|
||||||
try {
|
try {
|
||||||
discover([this](Packet a) {
|
discover(
|
||||||
datasets d =a.getPayload();
|
[this](Packet a) {
|
||||||
Switch sw = Switch();
|
datasets d =a.getPayload();
|
||||||
sw.parse(d);
|
int b = a.getSwitchMac().hash();
|
||||||
cout <<sw.settings.hostname<<"\t";
|
if (devices.empty()||devices.find(b) == devices.end())
|
||||||
datasets t = { {SND_PING, 0, {}}};
|
devices.insert(pair<int,Switch>(b,Switch()));
|
||||||
get(a, t, [this](Packet a) {
|
devices[a.getSwitchMac().hash()].parse(d);
|
||||||
datasets d =a.getPayload();
|
datasets t = { {SND_PING, 0, {}}};
|
||||||
Switch sw = Switch();
|
get(a, t, [this](Packet a) {
|
||||||
sw.parse(d);
|
datasets d =a.getPayload();
|
||||||
datasets t = { {REBOOT, 1, {options.flags.PERMANENT?(byte)1:(byte)0}}};
|
cout <<devices[a.getSwitchMac().hash()].settings.hostname<<"\t";
|
||||||
set(a,t,[this](Packet a) {
|
devices[a.getSwitchMac().hash()].parse(d);
|
||||||
if( a.getOpCode()==Packet::CONFIRM)
|
datasets t = { {REBOOT, 1, {options.flags.PERMANENT?(byte)1:(byte)0}}};
|
||||||
cout<< "rebooting now.\n";
|
set(a,t,[this](Packet a) {
|
||||||
return 0;
|
cout<< "rebooting now.\n";
|
||||||
});
|
return 0;
|
||||||
return 0;
|
});
|
||||||
});
|
return 0;
|
||||||
return 0;
|
});
|
||||||
});
|
return 0;
|
||||||
io_service->run();
|
});
|
||||||
} catch (exception& e) {
|
} catch (exception& e) {
|
||||||
cerr << "Exception: " << e.what() << "\n";
|
cerr << "Exception: " << e.what() << "\n";
|
||||||
}
|
}
|
||||||
|
@ -289,33 +384,32 @@ int Program::reset() {
|
||||||
});
|
});
|
||||||
return 0;
|
return 0;
|
||||||
});
|
});
|
||||||
io_service->run();
|
|
||||||
} catch (exception& e) {
|
} catch (exception& e) {
|
||||||
cerr << "Exception: " << e.what() << "\n";
|
cerr << "Exception: " << e.what() << "\n";
|
||||||
}
|
}
|
||||||
return 0;
|
return 0;
|
||||||
}
|
}
|
||||||
|
|
||||||
int Program::discover(function<int(Packet)> c) {
|
int Program::discover(Listener c) {
|
||||||
Packet p = Packet(Packet::DISCOVERY);
|
Packet p = Packet(Packet::DISCOVERY);
|
||||||
p.setHostMac(host.getMac());
|
p.setHostMac(host.getMac());
|
||||||
p.setPayload( { });
|
p.setPayload( { });
|
||||||
sock->callback = c;
|
sock->listen(c, Filter(Packet::REPLY));
|
||||||
sock->send(p);
|
sock->send(p);
|
||||||
return 0;
|
return 0;
|
||||||
}
|
}
|
||||||
|
|
||||||
int Program::get(Packet l, datasets t, function<int(Packet)> c) {
|
int Program::get(Packet l, datasets t, Listener c) {
|
||||||
Packet p = Packet(Packet::GET);
|
Packet p = Packet(Packet::GET);
|
||||||
p.setSwitchMac(l.getSwitchMac());
|
p.setSwitchMac(l.getSwitchMac());
|
||||||
p.setHostMac(host.getMac());
|
p.setHostMac(host.getMac());
|
||||||
p.setPayload(t);
|
p.setPayload(t);
|
||||||
sock->callback = c;
|
sock->listen(c, Filter(Packet::REPLY).mac(l.getSwitchMac()));
|
||||||
sock->send(p);
|
sock->send(p);
|
||||||
return 0;
|
return 0;
|
||||||
}
|
}
|
||||||
|
|
||||||
int Program::set(Packet l, datasets t, function<int(Packet)> c) {
|
int Program::set(Packet l, datasets t, Listener c) {
|
||||||
Packet p = Packet(Packet::SET);
|
Packet p = Packet(Packet::SET);
|
||||||
p.setSwitchMac(l.getSwitchMac());
|
p.setSwitchMac(l.getSwitchMac());
|
||||||
p.setTokenId(l.getTokenId());
|
p.setTokenId(l.getTokenId());
|
||||||
|
@ -325,12 +419,14 @@ int Program::set(Packet l, datasets t, function<int(Packet)> c) {
|
||||||
datasets ld = { { LOGIN_USER, (short) (n.size()), n }, { LOGIN_PASSWORD,
|
datasets ld = { { LOGIN_USER, (short) (n.size()), n }, { LOGIN_PASSWORD,
|
||||||
(short) (w.size()), w } };
|
(short) (w.size()), w } };
|
||||||
p.setPayload(ld + t);
|
p.setPayload(ld + t);
|
||||||
sock->callback = c;
|
sock->listen(c, Filter(Packet::CONFIRM).mac(l.getSwitchMac()));
|
||||||
sock->send(p);
|
sock->send(p);
|
||||||
return 0;
|
return 0;
|
||||||
}
|
}
|
||||||
|
|
||||||
void Program::init() {
|
void Program::init() {
|
||||||
|
io_service = std::make_shared<boost::asio::io_service>();
|
||||||
|
sock = std::make_shared < Socket > (*io_service);
|
||||||
if (options.interface.compare("") == 0)
|
if (options.interface.compare("") == 0)
|
||||||
options.interface = host.getIface();
|
options.interface = host.getIface();
|
||||||
|
|
||||||
|
|
|
@ -9,36 +9,42 @@
|
||||||
#define PROGRAM_H_
|
#define PROGRAM_H_
|
||||||
|
|
||||||
#include <memory>
|
#include <memory>
|
||||||
|
#include <vector>
|
||||||
|
|
||||||
#include "Types.h"
|
#include "Types.h"
|
||||||
#include "Host.h"
|
#include "Host.h"
|
||||||
|
#include "Switch.h"
|
||||||
#include "Socket.h"
|
#include "Socket.h"
|
||||||
|
|
||||||
class Program {
|
class Program {
|
||||||
private:
|
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 get(Packet,datasets,std::function<int(Packet)>);
|
std::map<int, Switch> devices;
|
||||||
int set(Packet,datasets,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)>);
|
int discover(std::function<int(Packet)>);
|
||||||
public:
|
public:
|
||||||
Program() {
|
Program() {
|
||||||
io_service = std::make_shared<boost::asio::io_service>();
|
}
|
||||||
sock = std::make_shared<Socket>(*io_service);
|
void init();
|
||||||
}
|
int run(std::vector<std::string>);
|
||||||
void init();
|
std::function<int()> callback = []() {
|
||||||
int list();
|
return 0;
|
||||||
int sniff();
|
};
|
||||||
int encode(std::string);
|
|
||||||
int getProperty(std::vector<std::string>);
|
int list();
|
||||||
int setProperty(std::map<std::string,std::string>);
|
int sniff();
|
||||||
int save();
|
int encode(std::string);
|
||||||
int restore();
|
int getProperty(std::vector<std::string>);
|
||||||
int flash();
|
int setProperty(std::map<std::string, std::string>);
|
||||||
int reboot();
|
int save();
|
||||||
int reset();
|
int restore();
|
||||||
std::string input;
|
int flash();
|
||||||
|
int reboot();
|
||||||
|
int reset();
|
||||||
|
std::string input;
|
||||||
};
|
};
|
||||||
|
|
||||||
#endif /* PROGRAM_H_ */
|
#endif /* PROGRAM_H_ */
|
||||||
|
|
|
@ -5,29 +5,33 @@
|
||||||
* Author: jdi
|
* Author: jdi
|
||||||
*/
|
*/
|
||||||
#include <cstdlib>
|
#include <cstdlib>
|
||||||
#include <array>
|
#include <map>
|
||||||
#include <unistd.h>
|
#include <unistd.h>
|
||||||
#include "Socket.h"
|
#include "Socket.h"
|
||||||
#include "Packet.h"
|
#include "Packet.h"
|
||||||
#include "Constant.h"
|
#include "Constant.h"
|
||||||
|
#include "Filter.h"
|
||||||
#include "Host.h"
|
#include "Host.h"
|
||||||
#include "Types.h"
|
#include "Types.h"
|
||||||
|
|
||||||
|
using namespace std;
|
||||||
|
|
||||||
Socket::Socket(boost::asio::io_service& io_service) :
|
Socket::Socket(boost::asio::io_service& io_service) :
|
||||||
send_socket_(io_service), receive_socket_(io_service), timer(io_service) {
|
send_socket_(io_service), receive_socket_(io_service), timer(io_service) {
|
||||||
}
|
}
|
||||||
//, resolver( io_service)
|
//, resolver( io_service)
|
||||||
void Socket::init(short dst_port, short src_port) {
|
|
||||||
if (initialized)
|
|
||||||
return;
|
|
||||||
|
|
||||||
|
Socket::~Socket() {
|
||||||
|
}
|
||||||
|
|
||||||
|
void Socket::init(short dst_port, short src_port) {
|
||||||
if (options.flags.REVERSE) {
|
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.debug_level>=1)
|
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(
|
||||||
|
@ -47,26 +51,25 @@ void Socket::init(short dst_port, short src_port) {
|
||||||
receive_socket_.set_option(boost::asio::socket_base::broadcast(true));
|
receive_socket_.set_option(boost::asio::socket_base::broadcast(true));
|
||||||
receive_socket_.set_option(boost::asio::socket_base::reuse_address(true));
|
receive_socket_.set_option(boost::asio::socket_base::reuse_address(true));
|
||||||
receive_socket_.bind(wildcard_endpoint_);
|
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) {
|
void Socket::setHostIp(ipAddr ip) {
|
||||||
local_ip = ip;
|
local_ip = ip;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
void Socket::clear(){
|
||||||
|
callback.clear();
|
||||||
|
}
|
||||||
|
|
||||||
|
void Socket::listen(Listener l, Filter f) {
|
||||||
|
if (callback.find(f) == callback.end()) {
|
||||||
|
callback.insert(ListenerPair(f, l));
|
||||||
|
} else {
|
||||||
|
callback[f] = l;
|
||||||
|
}
|
||||||
|
receive();
|
||||||
|
}
|
||||||
|
|
||||||
void Socket::send(Packet p) {
|
void Socket::send(Packet p) {
|
||||||
bytes data = p.getBytes();
|
bytes data = p.getBytes();
|
||||||
p.encode(data);
|
p.encode(data);
|
||||||
|
@ -75,11 +78,12 @@ void Socket::send(Packet p) {
|
||||||
broadcast_endpoint_,
|
broadcast_endpoint_,
|
||||||
[this](boost::system::error_code ec, std::size_t bytes_sent)
|
[this](boost::system::error_code ec, std::size_t bytes_sent)
|
||||||
{
|
{
|
||||||
listen();
|
receive();
|
||||||
|
settimeout();
|
||||||
});
|
});
|
||||||
}
|
}
|
||||||
|
|
||||||
void Socket::listen() {
|
void Socket::receive() {
|
||||||
data.resize(MAX_LENGTH);
|
data.resize(MAX_LENGTH);
|
||||||
receive_socket_.async_receive_from(boost::asio::buffer(data, MAX_LENGTH),
|
receive_socket_.async_receive_from(boost::asio::buffer(data, MAX_LENGTH),
|
||||||
remote_endpoint_,
|
remote_endpoint_,
|
||||||
|
@ -92,13 +96,37 @@ void Socket::listen() {
|
||||||
data.resize(bytes_recvd);
|
data.resize(bytes_recvd);
|
||||||
Packet p = Packet(Packet::NONE);
|
Packet p = Packet(Packet::NONE);
|
||||||
p.encode(data);
|
p.encode(data);
|
||||||
// std::cout << "err" << p.getErrorCode() <<std::endl;
|
|
||||||
p.parse(data);
|
p.parse(data);
|
||||||
//std::cout << "err" << p.getErrorCode() <<std::endl;
|
for(auto r : callback) {
|
||||||
if(!callback(p)) {
|
if(r.first.pass(p)) {
|
||||||
//TODO do something
|
r.second(p);
|
||||||
|
// std::cout<<"pass"<<std::endl;
|
||||||
|
break;
|
||||||
|
} else {
|
||||||
|
// std::cout<<"no pass"<<std::endl;
|
||||||
|
}
|
||||||
}
|
}
|
||||||
listen();
|
receive();
|
||||||
|
settimeout();
|
||||||
}
|
}
|
||||||
});
|
});
|
||||||
}
|
}
|
||||||
|
|
||||||
|
void Socket::settimeout() {
|
||||||
|
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();
|
||||||
|
receive_socket_.open(boost::asio::ip::udp::v4());
|
||||||
|
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_);
|
||||||
|
}
|
||||||
|
});
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
44
src/Socket.h
44
src/Socket.h
|
@ -8,8 +8,10 @@
|
||||||
#ifndef SOCKET_H_
|
#ifndef SOCKET_H_
|
||||||
#define SOCKET_H_
|
#define SOCKET_H_
|
||||||
|
|
||||||
|
#include <map>
|
||||||
#include <boost/asio.hpp>
|
#include <boost/asio.hpp>
|
||||||
#include "Packet.h"
|
#include "Packet.h"
|
||||||
|
#include "Filter.h"
|
||||||
#include "Types.h"
|
#include "Types.h"
|
||||||
|
|
||||||
#define SRC_PORT 29809
|
#define SRC_PORT 29809
|
||||||
|
@ -17,30 +19,32 @@
|
||||||
|
|
||||||
#define MAX_LENGTH 1024
|
#define MAX_LENGTH 1024
|
||||||
|
|
||||||
|
typedef std::function<int(Packet)> Listener;
|
||||||
|
typedef std::pair<Filter, Listener> ListenerPair;
|
||||||
|
|
||||||
class Socket {
|
class Socket {
|
||||||
public:
|
public:
|
||||||
Socket(boost::asio::io_service&);
|
Socket(boost::asio::io_service&);
|
||||||
virtual ~Socket() {
|
virtual ~Socket();
|
||||||
}
|
void init(short, short);
|
||||||
void init(short, short);
|
void clear();
|
||||||
void send(Packet);
|
void send(Packet);
|
||||||
void listen();
|
void setHostIp(ipAddr);
|
||||||
void setHostIp(ipAddr);
|
void listen(Listener l, Filter f = Filter());
|
||||||
std::function<int(Packet)> callback = [](Packet a) {
|
|
||||||
return 0;
|
|
||||||
};
|
|
||||||
|
|
||||||
private:
|
private:
|
||||||
boost::asio::ip::udp::socket send_socket_;
|
void receive();
|
||||||
boost::asio::ip::udp::socket receive_socket_;
|
void settimeout();
|
||||||
boost::asio::ip::udp::endpoint broadcast_endpoint_;
|
boost::asio::ip::udp::socket send_socket_;
|
||||||
boost::asio::ip::udp::endpoint remote_endpoint_;
|
boost::asio::ip::udp::socket receive_socket_;
|
||||||
boost::asio::ip::udp::endpoint wildcard_endpoint_;
|
boost::asio::ip::udp::endpoint broadcast_endpoint_;
|
||||||
boost::asio::ip::udp::endpoint local_endpoint_;
|
boost::asio::ip::udp::endpoint remote_endpoint_;
|
||||||
boost::asio::deadline_timer timer;
|
boost::asio::ip::udp::endpoint wildcard_endpoint_;
|
||||||
bytes data = bytes(MAX_LENGTH);
|
boost::asio::ip::udp::endpoint local_endpoint_;
|
||||||
ipAddr local_ip;
|
boost::asio::deadline_timer timer;
|
||||||
int initialized = 0;
|
bytes data = bytes(MAX_LENGTH);
|
||||||
|
ipAddr local_ip;
|
||||||
|
std::map<Filter, Listener> callback = { };
|
||||||
|
|
||||||
};
|
};
|
||||||
|
|
||||||
|
|
|
@ -65,9 +65,13 @@ public:
|
||||||
int parse(datasets);
|
int parse(datasets);
|
||||||
int parse(dataset);
|
int parse(dataset);
|
||||||
int parse(std::string);
|
int parse(std::string);
|
||||||
int print();
|
int set(std::pair<std::string,std::string>);
|
||||||
|
|
||||||
|
std::string get(std::string);
|
||||||
std::string toString();
|
std::string toString();
|
||||||
|
|
||||||
|
int print();
|
||||||
|
|
||||||
struct {
|
struct {
|
||||||
std::string type;
|
std::string type;
|
||||||
std::string hardware_version;
|
std::string hardware_version;
|
||||||
|
|
33
src/Types.h
33
src/Types.h
|
@ -50,6 +50,28 @@ public:
|
||||||
else break;
|
else break;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
int hash() {
|
||||||
|
int ret=0;
|
||||||
|
for (unsigned i = 0; i < 6; i++) {
|
||||||
|
ret = (ret*33) ^ (*this)[i];
|
||||||
|
}
|
||||||
|
return ret;
|
||||||
|
}
|
||||||
|
|
||||||
|
bool operator==(const macAddr &A) {
|
||||||
|
for (unsigned i = 0; i < 6; i++) {
|
||||||
|
if(A[i]!=(*this)[i])return false;
|
||||||
|
}
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
|
||||||
|
bool operator!=(const macAddr &A) {
|
||||||
|
for (unsigned i = 0; i < 6; i++) {
|
||||||
|
if(A[i]!=(*this)[i])return true;
|
||||||
|
}
|
||||||
|
return false;
|
||||||
|
}
|
||||||
};
|
};
|
||||||
|
|
||||||
/*
|
/*
|
||||||
|
@ -95,6 +117,14 @@ public:
|
||||||
}
|
}
|
||||||
};
|
};
|
||||||
|
|
||||||
|
namespace smrtlink {
|
||||||
|
|
||||||
|
constexpr unsigned int caseArg(const char* str, int h = 0) {
|
||||||
|
return !str[h] ? 5381 : (caseArg(str, h + 1) * 33) ^ str[h];
|
||||||
|
}
|
||||||
|
|
||||||
|
}
|
||||||
|
|
||||||
template<typename T>
|
template<typename T>
|
||||||
std::vector<T> operator+(const std::vector<T> &A, const std::vector<T> &B) {
|
std::vector<T> operator+(const std::vector<T> &A, const std::vector<T> &B) {
|
||||||
std::vector<T> AB;
|
std::vector<T> AB;
|
||||||
|
@ -117,6 +147,7 @@ struct Options {
|
||||||
bool JSON;
|
bool JSON;
|
||||||
bool PLAIN;
|
bool PLAIN;
|
||||||
bool REVERSE;
|
bool REVERSE;
|
||||||
|
|
||||||
bool HEADER;
|
bool HEADER;
|
||||||
bool PERMANENT;
|
bool PERMANENT;
|
||||||
bool WAIT;
|
bool WAIT;
|
||||||
|
@ -128,7 +159,7 @@ struct Options {
|
||||||
std::string file;
|
std::string file;
|
||||||
int debug_level = 0;
|
int debug_level = 0;
|
||||||
int verbosity = 0;
|
int verbosity = 0;
|
||||||
long timeout = 180U;
|
long timeout = 250U;
|
||||||
};
|
};
|
||||||
|
|
||||||
#endif /* TYPES_H_ */
|
#endif /* TYPES_H_ */
|
||||||
|
|
128
src/smrtlink.cpp
128
src/smrtlink.cpp
|
@ -1,14 +1,13 @@
|
||||||
//============================================================================
|
//============================================================================
|
||||||
// Name : smrtlink.cpp
|
// Name : smrtlink.cpp
|
||||||
// Author : jdi
|
// Author : jdi
|
||||||
// Version :
|
// Version : 1.2
|
||||||
// Copyright : GPL v2
|
// Copyright : GPL v2
|
||||||
// Description : SmrtLink in C++, Ansi-style
|
// Description : SmrtLink in C++, Ansi-style
|
||||||
//============================================================================
|
//============================================================================
|
||||||
|
|
||||||
#include <iostream>
|
#include <iostream>
|
||||||
#include <string>
|
#include <string>
|
||||||
#include <regex>
|
|
||||||
|
|
||||||
#include <cstring>
|
#include <cstring>
|
||||||
#include <sstream>
|
#include <sstream>
|
||||||
|
@ -21,6 +20,7 @@
|
||||||
#include "Interactive.h"
|
#include "Interactive.h"
|
||||||
#include "Host.h"
|
#include "Host.h"
|
||||||
#include "Program.h"
|
#include "Program.h"
|
||||||
|
#include "Types.h"
|
||||||
#include "Switch.h"
|
#include "Switch.h"
|
||||||
#include "lookup.h"
|
#include "lookup.h"
|
||||||
|
|
||||||
|
@ -32,12 +32,8 @@ using namespace std;
|
||||||
|
|
||||||
Options options;
|
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 main(int argc, char *argv[]) {
|
||||||
int index,opt;
|
int index, opt;
|
||||||
|
|
||||||
options.user = DEFAULT_USER;
|
options.user = DEFAULT_USER;
|
||||||
options.password = DEFAULT_PASS;
|
options.password = DEFAULT_PASS;
|
||||||
|
@ -56,7 +52,7 @@ int main(int argc, char *argv[]) {
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
while ((opt = getopt_long(argc, argv, "bhrVsxP:U:i:t::", longopts,
|
while ((opt = getopt_long(argc, argv, "bhrVXsxP:U:i:t::", longopts,
|
||||||
&index)) != -1) {
|
&index)) != -1) {
|
||||||
switch (opt) {
|
switch (opt) {
|
||||||
|
|
||||||
|
@ -149,118 +145,20 @@ int main(int argc, char *argv[]) {
|
||||||
exit(EXIT_FAILURE);
|
exit(EXIT_FAILURE);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
Interactive p = Interactive();
|
||||||
if (options.flags.INTERACTIVE) {
|
if (options.flags.INTERACTIVE) {
|
||||||
if (optind < argc) {
|
if (optind < argc) {
|
||||||
cerr << "Command is ignored in interactive mode\n";
|
cerr << "Command is ignored in interactive mode\n";
|
||||||
}
|
}
|
||||||
Interactive p = Interactive();
|
if (!p.loop())
|
||||||
if (!p.run())
|
|
||||||
exit(EXIT_SUCCESS);
|
exit(EXIT_SUCCESS);
|
||||||
fprintf(stderr, "Not yet implemented.\n");
|
fprintf(stderr, "Not yet implemented.\n");
|
||||||
exit(EXIT_FAILURE);
|
exit(EXIT_FAILURE);
|
||||||
}
|
} else if (optind < argc) {
|
||||||
else if (optind < argc) {
|
vector<string> v;
|
||||||
Program p = Program();
|
while (optind < argc)
|
||||||
p.init();
|
v.push_back(argv[optind++]);
|
||||||
std::vector<std::string> vect;
|
p.single(v);
|
||||||
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"):
|
|
||||||
if (!p.reboot())
|
|
||||||
exit(EXIT_SUCCESS);
|
|
||||||
fprintf(stderr, "Not yet implemented.\n");
|
|
||||||
exit(EXIT_FAILURE);
|
|
||||||
break;
|
|
||||||
case caseArg("reset"):
|
|
||||||
if (!p.reset())
|
|
||||||
exit(EXIT_SUCCESS);
|
|
||||||
fprintf(stderr, "Not yet implemented.\n");
|
|
||||||
exit(EXIT_FAILURE);
|
|
||||||
break;
|
|
||||||
case caseArg("save"):
|
|
||||||
if (!p.save())
|
|
||||||
exit(EXIT_SUCCESS);
|
|
||||||
fprintf(stderr, "Not yet implemented.\n");
|
|
||||||
exit(EXIT_FAILURE);
|
|
||||||
break;
|
|
||||||
case caseArg("restore"):
|
|
||||||
if (!p.restore())
|
|
||||||
exit(EXIT_SUCCESS);
|
|
||||||
fprintf(stderr, "Not yet implemented.\n");
|
|
||||||
exit(EXIT_FAILURE);
|
|
||||||
break;
|
|
||||||
case caseArg("flash"):
|
|
||||||
if (!p.flash())
|
|
||||||
exit(EXIT_SUCCESS);
|
|
||||||
fprintf(stderr, "Not yet implemented.\n");
|
|
||||||
exit(EXIT_FAILURE);
|
|
||||||
break;
|
|
||||||
|
|
||||||
case caseArg("list"):
|
|
||||||
if (!p.list())
|
|
||||||
exit(EXIT_SUCCESS);
|
|
||||||
break;
|
|
||||||
|
|
||||||
case caseArg("sniff"):
|
|
||||||
if (!p.sniff())
|
|
||||||
exit(EXIT_SUCCESS);
|
|
||||||
break;
|
|
||||||
|
|
||||||
case caseArg("encode"):
|
|
||||||
if (optind < argc) {
|
|
||||||
std::string s(argv[optind]);
|
|
||||||
optind++;
|
|
||||||
if (p.encode(s))
|
|
||||||
exit(EXIT_SUCCESS);
|
|
||||||
} else {
|
|
||||||
fprintf(stderr, "Argument expected after encode\n");
|
|
||||||
exit(EXIT_FAILURE);
|
|
||||||
}
|
|
||||||
break;
|
|
||||||
case caseArg("set"):
|
|
||||||
while (optind < argc) {
|
|
||||||
if (regex_match(argv[optind], sm,
|
|
||||||
std::regex("^([a-z]+)=(.*)$"))) {
|
|
||||||
if (!snd_lookup.exists(sm[1])&&!rcv_lookup.exists(sm[1])) {
|
|
||||||
cerr << "Unknown argument " << argv[optind] << endl;
|
|
||||||
exit(EXIT_FAILURE);
|
|
||||||
}
|
|
||||||
list.insert(
|
|
||||||
std::pair<std::string, std::string>(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);
|
exit(EXIT_FAILURE);
|
||||||
}
|
}
|
||||||
|
|
Loading…
Reference in a new issue