From b76fb38bc28715bbfb7d483d2d86f3103670c5a8 Mon Sep 17 00:00:00 2001 From: /jdi/ Date: Sun, 27 Sep 2015 12:23:12 +0200 Subject: [PATCH] clean up --- src/{device => }/Device.cpp | 0 src/{device => }/Device.h | 0 src/{device => }/Host.cpp | 0 src/{device => }/Host.h | 2 +- src/Options.h | 38 +++++++++ src/{transfer => }/Packet.cpp | 31 ++++++- src/{transfer => }/Packet.h | 4 +- src/Program.cpp | 90 ++++++++++++++------ src/Program.h | 13 +-- src/Socket.cpp | 151 ++++++++++++++++++++++++++++++++++ src/{transfer => }/Socket.h | 3 +- src/Types.h | 6 ++ src/dict.txt | 15 ---- src/encode.cpp | 44 ---------- src/smrtlink.cpp | 86 ++++++++++++------- src/transfer/Socket.cpp | 76 ----------------- 16 files changed, 363 insertions(+), 196 deletions(-) rename src/{device => }/Device.cpp (100%) rename src/{device => }/Device.h (100%) rename src/{device => }/Host.cpp (100%) rename src/{device => }/Host.h (90%) create mode 100644 src/Options.h rename src/{transfer => }/Packet.cpp (88%) rename src/{transfer => }/Packet.h (95%) create mode 100644 src/Socket.cpp rename src/{transfer => }/Socket.h (92%) delete mode 100644 src/dict.txt delete mode 100644 src/encode.cpp delete mode 100644 src/transfer/Socket.cpp diff --git a/src/device/Device.cpp b/src/Device.cpp similarity index 100% rename from src/device/Device.cpp rename to src/Device.cpp diff --git a/src/device/Device.h b/src/Device.h similarity index 100% rename from src/device/Device.h rename to src/Device.h diff --git a/src/device/Host.cpp b/src/Host.cpp similarity index 100% rename from src/device/Host.cpp rename to src/Host.cpp diff --git a/src/device/Host.h b/src/Host.h similarity index 90% rename from src/device/Host.h rename to src/Host.h index 22ae192..be268da 100644 --- a/src/device/Host.h +++ b/src/Host.h @@ -8,7 +8,7 @@ #ifndef HOST_H_ #define HOST_H_ -#include "../Types.h" +#include "Types.h" class Host { public: diff --git a/src/Options.h b/src/Options.h new file mode 100644 index 0000000..70aa515 --- /dev/null +++ b/src/Options.h @@ -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] \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_ */ diff --git a/src/transfer/Packet.cpp b/src/Packet.cpp similarity index 88% rename from src/transfer/Packet.cpp rename to src/Packet.cpp index 49c3a8e..dc3145f 100644 --- a/src/transfer/Packet.cpp +++ b/src/Packet.cpp @@ -10,8 +10,8 @@ #include #include #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, diff --git a/src/transfer/Packet.h b/src/Packet.h similarity index 95% rename from src/transfer/Packet.h rename to src/Packet.h index d0dd19c..4ef10bc 100644 --- a/src/transfer/Packet.h +++ b/src/Packet.h @@ -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; diff --git a/src/Program.cpp b/src/Program.cpp index d711ed3..cbbfca3 100644 --- a/src/Program.cpp +++ b/src/Program.cpp @@ -4,23 +4,21 @@ * Created on: 04.09.2015 * Author: jdi */ -#include +#include +#include #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"); - utils::printHex(p.getHead()); - printf("\nReceive Body:\t"); - utils::printHex(p.getBody()); - printf("\n"); + if (options.flags & FLAG_HEADER) { + if (options.flags & FLAG_HEX) { + printf("Received Header:\t"); + utils::printHex(p.getHead()); + }else{ + p.printHeader(); + } + printf("\n"); + } + if (options.flags & FLAG_HEX) { + printf("Received Payload:\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]); + 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]); } - printf("\n"); - printf("\n"); - printf("\n"); 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"); +} diff --git a/src/Program.h b/src/Program.h index 64b9ef2..be7207a 100644 --- a/src/Program.h +++ b/src/Program.h @@ -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_ */ diff --git a/src/Socket.cpp b/src/Socket.cpp new file mode 100644 index 0000000..0351fbd --- /dev/null +++ b/src/Socket.cpp @@ -0,0 +1,151 @@ +/* + * Socket.cpp + * + * Created on: 02.09.2015 + * Author: jdi + */ +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#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(); + } + } + }); +} diff --git a/src/transfer/Socket.h b/src/Socket.h similarity index 92% rename from src/transfer/Socket.h rename to src/Socket.h index d25838f..c2c2078 100644 --- a/src/transfer/Socket.h +++ b/src/Socket.h @@ -10,7 +10,7 @@ #include #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_; diff --git a/src/Types.h b/src/Types.h index f90487f..3ad2763 100644 --- a/src/Types.h +++ b/src/Types.h @@ -42,5 +42,11 @@ typedef std::map datasets; //std::function; //typedef int receiveCallback; +struct Options { + unsigned flags = 0x00; + std::string user; + std::string password; + std::string interface; +}; #endif /* TYPES_H_ */ diff --git a/src/dict.txt b/src/dict.txt deleted file mode 100644 index 5b6fd7d..0000000 --- a/src/dict.txt +++ /dev/null @@ -1,15 +0,0 @@ -change Password: -#512 Length: 6 Value: admin -#513 Length: 6 Value: admin -#514 Length: 10 Value: -#515 Length: 10 Value: - -login: -#2305 Length: 0 Value: (null) - -#512 Length: 6 Value: admin -#514 Length: 10 Value: - -#10 Length: 0 Value: (null) - -#2 Length: 0 Value: (null) \ No newline at end of file diff --git a/src/encode.cpp b/src/encode.cpp deleted file mode 100644 index d4088b7..0000000 --- a/src/encode.cpp +++ /dev/null @@ -1,44 +0,0 @@ -/* - * encode.cpp - * - * Created on: 15.09.2015 - * Author: jdi - */ - -#include -#include -#include -#include -#include -#include - -#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"); - -} diff --git a/src/smrtlink.cpp b/src/smrtlink.cpp index 3835516..ceb0f4a 100644 --- a/src/smrtlink.cpp +++ b/src/smrtlink.cpp @@ -15,75 +15,105 @@ #include #include +#include "Options.h" #include "Program.h" -#define USAGE "Usage: smrtlink [-p n|--port n] [-h|--help] [-v|--version] \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); - }else if (strcmp(argv[optind], "sniff") == 0) { + } else if (strcmp(argv[optind], "sniff") == 0) { 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++; diff --git a/src/transfer/Socket.cpp b/src/transfer/Socket.cpp deleted file mode 100644 index 74984fe..0000000 --- a/src/transfer/Socket.cpp +++ /dev/null @@ -1,76 +0,0 @@ -/* - * Socket.cpp - * - * Created on: 02.09.2015 - * Author: jdi - */ -#include -#include -#include -#include -#include -#include -#include -#include -#include -#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(); - } - } - }); -}