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_
#define HOST_H_
#include "../Types.h"
#include "Types.h"
class Host {
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 <ctime>
#include "Packet.h"
#include "../Types.h"
#include "../Utils.h"
#include "Types.h"
#include "Utils.h"
Packet::Packet(OpCode c) {
srand(time(NULL));
@ -19,6 +19,17 @@ Packet::Packet(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() {
int i = 0;
for (unsigned j = 0; j < payload.size(); j++)
@ -130,6 +141,22 @@ void Packet::setPayload(const datasets& 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) {
int len = data.size();
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 PACKET_END 0xFFFF0000
#include "../Types.h"
#include "Types.h"
class Packet {
public:
@ -24,6 +24,8 @@ public:
void encode(bytes&);
bytes getBytes();
void parse(bytes);
void printHeader();
std::string opCodeToString();
short getLength() const;
int getCheckSum() const;
short getSequenceId() const;

View file

@ -4,23 +4,21 @@
* Created on: 04.09.2015
* Author: jdi
*/
#include <stdio.h>
#include <cstdio>
#include <algorithm>
#include "Utils.h"
#include "Options.h"
#include "Program.h"
#include "device/Device.h"
#include "device/Host.h"
#include "transfer/Socket.h"
#include "transfer/Packet.h"
#include "Device.h"
#include "Host.h"
#include "Socket.h"
#include "Packet.h"
Program::Program() {
// TODO Auto-generated constructor stub
}
Program::~Program() {
// TODO Auto-generated destructor stub
}
int Program::list() {
printf("List:\n");
@ -37,10 +35,20 @@ int Program::list() {
try {
asio::io_service io_service;
Socket s(io_service);
s.init(dst_port, src_port);
s.init(DST_PORT, SRC_PORT);
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();
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);
printf("\tIP: ");
utils::printDec(d[4].value);
@ -57,26 +65,35 @@ int Program::list() {
}
int Program::sniff() {
printf("Listening:\n");
try {
asio::io_service io_service;
Socket s(io_service);
s.init(src_port, dst_port);
s.init(DST_PORT,SRC_PORT);
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());
printf("\nReceive Body:\t");
utils::printHex(p.getBody());
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]);
}else{
p.printHeader();
}
printf("\n");
}
if (options.flags & FLAG_HEX) {
printf("Received Payload:\t");
utils::printHex(p.getBody());
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;
};
s.listen();
@ -87,3 +104,30 @@ int Program::sniff() {
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_
#define PROGRAM_H_
#include "Types.h"
#define SRC_PORT 29809
#define DST_PORT 29808
class Program {
public:
Program();
virtual ~Program();
virtual ~Program() {
}
int list();
int sniff();
void setPort(int);
void setPort();
int src_port = 29809;
int dst_port = 29808;
int encode(std::string);
};
#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 "Packet.h"
#include "../Types.h"
#include "Types.h"
#define MAX_LENGTH 1024
@ -29,6 +29,7 @@ public:
private:
asio::ip::udp::socket send_socket_;
asio::ip::udp::socket receive_socket_;
asio::ip::udp::resolver resolver;
asio::ip::udp::endpoint broadcast_endpoint_;
asio::ip::udp::endpoint remote_endpoint_;
asio::ip::udp::endpoint wildcard_endpoint_;

View file

@ -42,5 +42,11 @@ typedef std::map<short, dataset> datasets;
//std::function<int()>;
//typedef int receiveCallback;
struct Options {
unsigned flags = 0x00;
std::string user;
std::string password;
std::string interface;
};
#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 <stdio.h>
#include "Options.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 required_argument 1
#define optional_argument 2
int main(int argc, char *argv[]) {
int opt, index, option_flags;
Options options;
option_flags = 0;
int main(int argc, char *argv[]) {
int opt, index;
const struct option longopts[] = { { "version", no_argument, 0, 'v' }, {
"help", no_argument, 0, 'h' },
{ "port", required_argument, 0, 'p' }, { "srcport",
required_argument, 0, 's' },
{ "dstport", required_argument, 0, 'p' }, { 0, 0, 0, 0 }, };
"help", no_argument, 0, 'h' }, { "reverse", no_argument, 0, 'r' }, {
"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' }, { 0, 0, 0, 0 }, };
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) {
case 'h':
std::cout << "You hit help" << std::endl;
option_flags |= flag_version;
fprintf(stderr, VERSION);
fprintf(stderr, USAGE, argv[0]);
fprintf(stderr, HELP);
exit(EXIT_SUCCESS);
break;
case 'v':
std::cout << "You hit version" << std::endl;
option_flags |= flag_help;
fprintf(stderr, VERSION);
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;
case 'p':
p.dst_port = atoi(optarg);
option_flags |= 4;
//TODO add password
break;
case 's':
p.src_port = atoi(optarg);
option_flags |= 4;
case 'u':
//TODO add username
break;
case 'i':
//TODO add interface
break;
default: /* '?' */
fprintf(stderr, "Unknown option\n");
fprintf(stderr, USAGE);
fprintf(stderr, USAGE, argv[0]);
exit(EXIT_FAILURE);
}
}
if (optind >= argc && !option_flags) {
//fprintf(stderr, "Expected argument\n");
fprintf(stderr, USAGE);
if (optind >= argc) {
fprintf(stderr, "Command expected\n");
fprintf(stderr, USAGE, argv[0]);
exit(EXIT_FAILURE);
}
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++;
if (p.list())
exit(EXIT_SUCCESS);
@ -84,6 +103,17 @@ int main(int argc, char *argv[]) {
optind++;
if (p.sniff())
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 {
printf("Unknown command: %s\n", argv[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();
}
}
});
}