This commit is contained in:
/jdi/ 2015-09-27 12:23:12 +02:00
parent 364bb25ab7
commit b76fb38bc2
16 changed files with 363 additions and 196 deletions

View file

@ -8,7 +8,7 @@
#ifndef HOST_H_ #ifndef HOST_H_
#define HOST_H_ #define HOST_H_
#include "../Types.h" #include "Types.h"
class Host { class Host {
public: public:

38
src/Options.h Normal file
View file

@ -0,0 +1,38 @@
/*
* Options.h
*
* Created on: 11.09.2015
* Author: jdi
*/
#ifndef OPTIONS_H_
#define OPTIONS_H_
#include "Types.h"
#define VERSION "smrtlink (v1 Linux)\n"
#define USAGE "usage: %s [-bhrvx] [-i interface] [-u [password:]username]\n\
[-p password] <command>\n\n"
#define HELP "\
Option Summary:\n\
-h --help This help text\n\
-v --version Display version of this tool\n\
-r switch ports to emulate switch while sniffing\n\
-b --header Show header\n\
-x --hex Display Packets as Hex String\n\
-i --interface only use one Interface\n\
-u --user Login with user\n\
-p Password\n\n\
Command Summary:\n\
help This help text\n\
list list all connected switches\n\
sniff capture and display all incoming or outgoing packets\n\
depending on the --reverse option\n\n"
#define FLAG_HEX 1
#define FLAG_REVERSE 2
#define FLAG_HEADER 4
extern Options options;
#endif /* OPTIONS_H_ */

View file

@ -10,8 +10,8 @@
#include <cstdio> #include <cstdio>
#include <ctime> #include <ctime>
#include "Packet.h" #include "Packet.h"
#include "../Types.h" #include "Types.h"
#include "../Utils.h" #include "Utils.h"
Packet::Packet(OpCode c) { Packet::Packet(OpCode c) {
srand(time(NULL)); srand(time(NULL));
@ -19,6 +19,17 @@ Packet::Packet(OpCode c) {
opCode = c; opCode = c;
} }
void Packet::printHeader() {
printf("Header:\n\tOpCode:\t\t%s\n\tID:\t\t%d\n\tVersion:\t%hhd\n\tError:\t\t%.8X\n\tSwitch MAC:\t", opCodeToString().c_str(),sequenceId, version, errorCode);
utils::printHex(switchMac);
printf("\n\tHost MAC:\t");
utils::printHex(hostMac);
printf("\n\tLength:\t%hd",this->getLength());
printf("\n\tOffset:\t%hd",fragmentOffset);
printf("\n\tFlags:\t%.4hX",flag);
printf("\n\tChecksum:\t%d",checkSum);
}
bytes Packet::getBytes() { bytes Packet::getBytes() {
int i = 0; int i = 0;
for (unsigned j = 0; j < payload.size(); j++) for (unsigned j = 0; j < payload.size(); j++)
@ -130,6 +141,22 @@ void Packet::setPayload(const datasets& payload) {
this->payload = payload; this->payload = payload;
} }
std::string Packet::opCodeToString() {
switch (opCode) {
case DISCOVERY:
return "DISCOVERY";
case GET:
return "GET";
case SET:
return "SET";
case READ:
return "READ";
default:
return "NONE";
}
return "NONE";
}
void Packet::encode(bytes &data) { void Packet::encode(bytes &data) {
int len = data.size(); int len = data.size();
bytes key = { 191, 155, 227, 202, 99, 162, 79, 104, 49, 18, 190, 164, 30, bytes key = { 191, 155, 227, 202, 99, 162, 79, 104, 49, 18, 190, 164, 30,

View file

@ -11,7 +11,7 @@
#define HEADER_LEN 32 #define HEADER_LEN 32
#define PACKET_END 0xFFFF0000 #define PACKET_END 0xFFFF0000
#include "../Types.h" #include "Types.h"
class Packet { class Packet {
public: public:
@ -24,6 +24,8 @@ public:
void encode(bytes&); void encode(bytes&);
bytes getBytes(); bytes getBytes();
void parse(bytes); void parse(bytes);
void printHeader();
std::string opCodeToString();
short getLength() const; short getLength() const;
int getCheckSum() const; int getCheckSum() const;
short getSequenceId() const; short getSequenceId() const;

View file

@ -4,23 +4,21 @@
* Created on: 04.09.2015 * Created on: 04.09.2015
* Author: jdi * Author: jdi
*/ */
#include <stdio.h> #include <cstdio>
#include <algorithm>
#include "Utils.h" #include "Utils.h"
#include "Options.h"
#include "Program.h" #include "Program.h"
#include "device/Device.h" #include "Device.h"
#include "device/Host.h" #include "Host.h"
#include "transfer/Socket.h" #include "Socket.h"
#include "transfer/Packet.h" #include "Packet.h"
Program::Program() { Program::Program() {
// TODO Auto-generated constructor stub // TODO Auto-generated constructor stub
} }
Program::~Program() {
// TODO Auto-generated destructor stub
}
int Program::list() { int Program::list() {
printf("List:\n"); printf("List:\n");
@ -37,10 +35,20 @@ int Program::list() {
try { try {
asio::io_service io_service; asio::io_service io_service;
Socket s(io_service); Socket s(io_service);
s.init(dst_port, src_port); s.init(DST_PORT, SRC_PORT);
s.callback = [](Packet a) { s.callback = [](Packet a) {
if (options.flags & FLAG_HEADER) {
printf("Received Header:\t");
utils::printHex(a.getHead());
printf("\n");
}
if (options.flags & FLAG_HEX) {
printf("Received Payload:\t");
utils::printHex(a.getBody());
printf("\n");
}
datasets d =a.getPayload(); datasets d =a.getPayload();
printf("%s (%s)\tMAC: ", &d[2].value[0], &d[1].value[0]); printf("\t%s (%s)\tMAC: ", &d[2].value[0], &d[1].value[0]);
utils::printHex(d[3].value); utils::printHex(d[3].value);
printf("\tIP: "); printf("\tIP: ");
utils::printDec(d[4].value); utils::printDec(d[4].value);
@ -57,26 +65,35 @@ int Program::list() {
} }
int Program::sniff() { int Program::sniff() {
printf("Listening:\n"); printf("Listening:\n");
try { try {
asio::io_service io_service; asio::io_service io_service;
Socket s(io_service); Socket s(io_service);
s.init(src_port, dst_port); s.init(DST_PORT,SRC_PORT);
s.callback = [](Packet p) { s.callback = [](Packet p) {
printf("Receive Head:\t"); if (options.flags & FLAG_HEADER) {
if (options.flags & FLAG_HEX) {
printf("Received Header:\t");
utils::printHex(p.getHead()); utils::printHex(p.getHead());
printf("\nReceive Body:\t"); }else{
utils::printHex(p.getBody()); p.printHeader();
printf("\n");
for(auto a : p.getPayload()) {
dataset d = a.second;
printf("#%d\tLength: %d Value: %s\n",d.type,d.len,&d.value[0]);
} }
printf("\n"); printf("\n");
}
if (options.flags & FLAG_HEX) {
printf("Received Payload:\t");
utils::printHex(p.getBody());
printf("\n"); printf("\n");
printf("\n"); }
for(auto a : p.getPayload()) {
dataset d = a.second;
printf("#%d\tLength: %d\n\tHex: ",d.type,d.len);
utils::printHex(d.value);
printf("\n\tDec: ");
utils::printDec(d.value);
d.value.push_back(0U);
printf("\n\tString: %s\n",&d.value[0]);
}
return 0; return 0;
}; };
s.listen(); s.listen();
@ -87,3 +104,30 @@ int Program::sniff() {
return 1; return 1;
} }
int Program::encode(std::string s){
std::string delimiter = ":";
std::string token;
size_t pos = 0;
bytes arr = { };
int hex;
byte b;
while ((pos = s.find(delimiter)) != std::string::npos) {
token = s.substr(0, pos);
sscanf(token.c_str(), "%x", &hex);
s.erase(0, pos + delimiter.length());
b = hex & 0xFF;
arr.push_back(b);
}
sscanf(s.c_str(), "%x", &hex);
b = hex & 0xFF;
arr.push_back(b);
Packet p = Packet(Packet::DISCOVERY);
p.encode(arr);
printf("%x", arr[0]);
for (unsigned i = 1; i < arr.size(); i++) {
printf(":%x", arr[i]);
}
printf("\n");
}

View file

@ -8,16 +8,19 @@
#ifndef PROGRAM_H_ #ifndef PROGRAM_H_
#define PROGRAM_H_ #define PROGRAM_H_
#include "Types.h"
#define SRC_PORT 29809
#define DST_PORT 29808
class Program { class Program {
public: public:
Program(); Program();
virtual ~Program(); virtual ~Program() {
}
int list(); int list();
int sniff(); int sniff();
void setPort(int); int encode(std::string);
void setPort();
int src_port = 29809;
int dst_port = 29808;
}; };
#endif /* PROGRAM_H_ */ #endif /* PROGRAM_H_ */

151
src/Socket.cpp Normal file
View file

@ -0,0 +1,151 @@
/*
* Socket.cpp
*
* Created on: 02.09.2015
* Author: jdi
*/
#include <sys/types.h>
#include <sys/socket.h>
#include <cstdio>
#include <cerrno>
#include <cstring>
#include <cstdlib>
#include <iostream>
#include <sys/types.h>
#include <ifaddrs.h>
#include <unistd.h>
#include <asio.hpp>
#include "Socket.h"
#include "Packet.h"
#include "Types.h"
#include "Utils.h"
#include "Options.h"
#include "Host.h"
Socket::Socket(asio::io_service& io_service) :
send_socket_(io_service), receive_socket_(io_service), resolver(
io_service) {
}
void Socket::init(short dst_port, short src_port) {
if (options.flags & FLAG_REVERSE) {
short p = dst_port;
dst_port = src_port;
src_port = p;
}
struct ifaddrs *ifaddr, *ifa;
int family, s, n;
char host[NI_MAXHOST];
if (getifaddrs(&ifaddr) == -1) {
perror("getifaddrs");
exit(EXIT_FAILURE);
}
/* Walk through linked list, maintaining head pointer so we
can free list later */
for (ifa = ifaddr, n = 0; ifa != NULL; ifa = ifa->ifa_next, n++) {
if (ifa->ifa_addr == NULL)
continue;
family = ifa->ifa_addr->sa_family;
/* Display interface name and family (including symbolic
form of the latter for the common families) */
printf("%-8s %s (%d)\n",
ifa->ifa_name,
(family == AF_PACKET) ? "AF_PACKET" :
(family == AF_INET) ? "AF_INET" :
(family == AF_INET6) ? "AF_INET6" : "???",
family);
/* For an AF_INET* interface address, display the address */
if (family == AF_INET || family == AF_INET6) {
s = getnameinfo(ifa->ifa_addr,
(family == AF_INET) ? sizeof(struct sockaddr_in) :
sizeof(struct sockaddr_in6),
host, NI_MAXHOST,
NULL, 0, NI_NUMERICHOST);
if (s != 0) {
printf("getnameinfo() failed: %s\n", gai_strerror(s));
exit(EXIT_FAILURE);
}
printf("\t\taddress: <%s>\n", host);
} /*else if (family == AF_PACKET && ifa->ifa_data != NULL) {
struct rtnl_link_stats *stats = ifa->ifa_data;
printf("\t\ttx_packets = %10u; rx_packets = %10u\n"
"\t\ttx_bytes = %10u; rx_bytes = %10u\n",
stats->tx_packets, stats->rx_packets,
stats->tx_bytes, stats->rx_bytes);
}*/
}
freeifaddrs(ifaddr);
/*
asio::ip::udp::resolver::query query(asio::ip::host_name(), "");
asio::ip::udp::resolver::iterator iter = resolver.resolve(query);
asio::ip::udp::resolver::iterator end;
while (iter != end) {
asio::ip::udp::endpoint ep = *iter++;
std::cout << "IP: " << ep << std::endl;
}*/
wildcard_endpoint_ = asio::ip::udp::endpoint(
asio::ip::address::from_string("0.0.0.0"), src_port);
local_endpoint_ = asio::ip::udp::endpoint(
asio::ip::address::from_string("192.168.0.3"), src_port);
broadcast_endpoint_ = asio::ip::udp::endpoint(
asio::ip::address_v4::from_string("255.255.255.255"), dst_port);
send_socket_.open(asio::ip::udp::v4());
send_socket_.set_option(asio::socket_base::broadcast(true));
send_socket_.set_option(asio::socket_base::reuse_address(true));
send_socket_.bind(local_endpoint_); //TODO reuse Address
receive_socket_.open(asio::ip::udp::v4());
receive_socket_.set_option(asio::socket_base::broadcast(true));
receive_socket_.set_option(asio::socket_base::reuse_address(true));
receive_socket_.bind(wildcard_endpoint_); //TODO reuse Address
}
void Socket::send(bytes data) {
unsigned char * a = &data[0];
send_socket_.async_send_to(asio::buffer(a, data.size()),
broadcast_endpoint_,
[this](asio::error_code ec, std::size_t bytes_sent)
{
listen();
});
}
void Socket::listen() {
data.resize(MAX_LENGTH);
receive_socket_.async_receive_from(asio::buffer(data, MAX_LENGTH),
remote_endpoint_,
[this](asio::error_code ec, std::size_t bytes_recvd)
{
if (ec || bytes_recvd == 0) {
listen();
} else {
data.resize(bytes_recvd);
Packet p = Packet(Packet::READ);
p.encode(data);
p.parse(data);
datasets l = p.getPayload();
if(!callback(p)) {
listen();
}
}
});
}

View file

@ -10,7 +10,7 @@
#include <asio.hpp> #include <asio.hpp>
#include "Packet.h" #include "Packet.h"
#include "../Types.h" #include "Types.h"
#define MAX_LENGTH 1024 #define MAX_LENGTH 1024
@ -29,6 +29,7 @@ public:
private: private:
asio::ip::udp::socket send_socket_; asio::ip::udp::socket send_socket_;
asio::ip::udp::socket receive_socket_; asio::ip::udp::socket receive_socket_;
asio::ip::udp::resolver resolver;
asio::ip::udp::endpoint broadcast_endpoint_; asio::ip::udp::endpoint broadcast_endpoint_;
asio::ip::udp::endpoint remote_endpoint_; asio::ip::udp::endpoint remote_endpoint_;
asio::ip::udp::endpoint wildcard_endpoint_; asio::ip::udp::endpoint wildcard_endpoint_;

View file

@ -42,5 +42,11 @@ typedef std::map<short, dataset> datasets;
//std::function<int()>; //std::function<int()>;
//typedef int receiveCallback; //typedef int receiveCallback;
struct Options {
unsigned flags = 0x00;
std::string user;
std::string password;
std::string interface;
};
#endif /* TYPES_H_ */ #endif /* TYPES_H_ */

View file

@ -1,15 +0,0 @@
change Password:
#512 Length: 6 Value: admin
#513 Length: 6 Value: admin
#514 Length: 10 Value: <oldPassword>
#515 Length: 10 Value: <newPassword>
login:
#2305 Length: 0 Value: (null)
#512 Length: 6 Value: admin
#514 Length: 10 Value: <Password>
#10 Length: 0 Value: (null)
#2 Length: 0 Value: (null)

View file

@ -1,44 +0,0 @@
/*
* encode.cpp
*
* Created on: 15.09.2015
* Author: jdi
*/
#include <iostream>
#include <string>
#include <string.h>
#include <stdlib.h>
#include <stdio.h>
#include <algorithm>
#include "Packet.h"
int encode(int argc, char *argv[]) {
std::string s(argv[1]);
std::string delimiter = ":";
std::string token;
size_t pos = 0;
bytes arr = { };
int hex;
byte b;
while ((pos = s.find(delimiter)) != std::string::npos) {
token = s.substr(0, pos);
sscanf(token.c_str(), "%x", &hex);
s.erase(0, pos + delimiter.length());
b = hex & 0xFF;
arr.push_back(b);
}
sscanf(s.c_str(), "%x", &hex);
b = hex & 0xFF;
arr.push_back(b);
Packet p = Packet(Packet::DISCOVERY);
p.encode(arr);
printf("%x", arr[0]);
for (unsigned i = 1; i < arr.size(); i++) {
printf(":%x", arr[i]);
}
printf("\n");
}

View file

@ -15,68 +15,87 @@
#include <stdlib.h> #include <stdlib.h>
#include <stdio.h> #include <stdio.h>
#include "Options.h"
#include "Program.h" #include "Program.h"
#define USAGE "Usage: smrtlink [-p n|--port n] [-h|--help] [-v|--version] <command>\n"
#define flag_version 1
#define flag_help 2
#define no_argument 0 #define no_argument 0
#define required_argument 1 #define required_argument 1
#define optional_argument 2 #define optional_argument 2
int main(int argc, char *argv[]) { Options options;
int opt, index, option_flags;
option_flags = 0; int main(int argc, char *argv[]) {
int opt, index;
const struct option longopts[] = { { "version", no_argument, 0, 'v' }, { const struct option longopts[] = { { "version", no_argument, 0, 'v' }, {
"help", no_argument, 0, 'h' }, "help", no_argument, 0, 'h' }, { "reverse", no_argument, 0, 'r' }, {
{ "port", required_argument, 0, 'p' }, { "srcport", "password", required_argument, 0, 'p' }, { "user",
required_argument, 0, 's' }, required_argument, 0, 'u' }, { "interface", required_argument, 0, 'i' }, {
{ "dstport", required_argument, 0, 'p' }, { 0, 0, 0, 0 }, }; "header", required_argument, 0, 'b' }, { "hex", required_argument,
0, 'x' }, { 0, 0, 0, 0 }, };
Program p = Program(); Program p = Program();
while ((opt = getopt_long(argc, argv, "vhp:s:", longopts, &index)) != -1) { while ((opt = getopt_long(argc, argv, "bhrvxp:u:i:", longopts, &index))
!= -1) {
switch (opt) { switch (opt) {
case 'h': case 'h':
std::cout << "You hit help" << std::endl; fprintf(stderr, VERSION);
option_flags |= flag_version; fprintf(stderr, USAGE, argv[0]);
fprintf(stderr, HELP);
exit(EXIT_SUCCESS);
break; break;
case 'v': case 'v':
std::cout << "You hit version" << std::endl; fprintf(stderr, VERSION);
option_flags |= flag_help; exit(EXIT_SUCCESS);
break;
case 'r':
options.flags |= FLAG_REVERSE;
break;
case 'b':
options.flags |= FLAG_HEADER;
break;
case 'x':
options.flags |= FLAG_HEX;
break; break;
case 'p': case 'p':
p.dst_port = atoi(optarg); //TODO add password
option_flags |= 4;
break; break;
case 's': case 'u':
p.src_port = atoi(optarg); //TODO add username
option_flags |= 4; break;
case 'i':
//TODO add interface
break; break;
default: /* '?' */ default: /* '?' */
fprintf(stderr, "Unknown option\n"); fprintf(stderr, "Unknown option\n");
fprintf(stderr, USAGE); fprintf(stderr, USAGE, argv[0]);
exit(EXIT_FAILURE); exit(EXIT_FAILURE);
} }
} }
if (optind >= argc && !option_flags) { if (optind >= argc) {
//fprintf(stderr, "Expected argument\n"); fprintf(stderr, "Command expected\n");
fprintf(stderr, USAGE); fprintf(stderr, USAGE, argv[0]);
exit(EXIT_FAILURE); exit(EXIT_FAILURE);
} }
if (optind < argc) { if (optind < argc) {
if (strcmp(argv[optind], "list") == 0) { if (strcmp(argv[optind], "help") == 0) {
fprintf(stderr, VERSION);
fprintf(stderr, USAGE, argv[0]);
fprintf(stderr, HELP);
exit(EXIT_SUCCESS);
} else if (strcmp(argv[optind], "list") == 0) {
optind++; optind++;
if (p.list()) if (p.list())
exit(EXIT_SUCCESS); exit(EXIT_SUCCESS);
@ -84,6 +103,17 @@ int main(int argc, char *argv[]) {
optind++; optind++;
if (p.sniff()) if (p.sniff())
exit(EXIT_SUCCESS); exit(EXIT_SUCCESS);
} else if (strcmp(argv[optind], "encode") == 0) {
optind++;
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);
}
} else { } else {
printf("Unknown command: %s\n", argv[optind]); printf("Unknown command: %s\n", argv[optind]);
optind++; optind++;

View file

@ -1,76 +0,0 @@
/*
* Socket.cpp
*
* Created on: 02.09.2015
* Author: jdi
*/
#include <sys/types.h>
#include <sys/socket.h>
#include <cstdio>
#include <cerrno>
#include <cstring>
#include <cstdlib>
#include <iostream>
#include <unistd.h>
#include <asio.hpp>
#include "Socket.h"
#include "../Types.h"
#include "../Utils.h"
#include "../device/Host.h"
#include "Packet.h"
Socket::Socket(asio::io_service& io_service) :
send_socket_(io_service), receive_socket_(io_service) {
}
void Socket::init(short dst_port, short src_port) {
wildcard_endpoint_ = asio::ip::udp::endpoint(
asio::ip::address::from_string("0.0.0.0"), src_port);
local_endpoint_ = asio::ip::udp::endpoint(
asio::ip::address::from_string("192.168.0.3"), src_port);
broadcast_endpoint_ = asio::ip::udp::endpoint(
asio::ip::address_v4::from_string("255.255.255.255"), dst_port);
send_socket_.open(asio::ip::udp::v4());
send_socket_.set_option(asio::socket_base::broadcast(true));
send_socket_.set_option(asio::socket_base::reuse_address(true));
send_socket_.bind(local_endpoint_); //TODO reuse Address
receive_socket_.open(asio::ip::udp::v4());
receive_socket_.set_option(asio::socket_base::broadcast(true));
receive_socket_.set_option(asio::socket_base::reuse_address(true));
receive_socket_.bind(wildcard_endpoint_); //TODO reuse Address
}
void Socket::send(bytes data) {
unsigned char * a = &data[0];
send_socket_.async_send_to(asio::buffer(a, data.size()),
broadcast_endpoint_,
[this](asio::error_code ec, std::size_t bytes_sent)
{
listen();
});
}
void Socket::listen() {
data.resize(MAX_LENGTH);
receive_socket_.async_receive_from(asio::buffer(data, MAX_LENGTH),
remote_endpoint_,
[this](asio::error_code ec, std::size_t bytes_recvd)
{
if (ec || bytes_recvd == 0) {
listen();
} else {
data.resize(bytes_recvd);
Packet p = Packet(Packet::READ);
p.encode(data);
p.parse(data);
datasets l = p.getPayload();
if(!callback(p)) {
listen();
}
}
});
}