diff --git a/GlobalVars.cpp b/GlobalVars.cpp index 8aaea65..08a9ad2 100644 --- a/GlobalVars.cpp +++ b/GlobalVars.cpp @@ -2,6 +2,8 @@ #include "GlobalVars.hpp" std::vector DEVS; //Vector, containing all our interfaces +std::vector SentPackets; +std::vector ProlongationList; std::string SMAC{ "" }; //Our MAC std::string DMAC{ "" }; //MAC of device we will be impersonating (Optional) std::string GWMAC{ "" }; //Gateway MAC (Optional) @@ -11,8 +13,7 @@ bool istcp = false; bool both = false; uint_fast8_t progmode=0; uint_fast16_t gwlistenerport = 5351; //Default port -extern uint_fast16_t internalport = 1025; +uint_fast16_t internalport = 1025; uint_fast16_t externalport = 1025; uint_fast32_t mappinglifetime = 7200; //Recommended to be 2 hrs (https://datatracker.ietf.org/doc/html/rfc6886) -std::vector SentPackets; WinDev OutputInterface; \ No newline at end of file diff --git a/GlobalVars.hpp b/GlobalVars.hpp index ab43641..a46bcec 100644 --- a/GlobalVars.hpp +++ b/GlobalVars.hpp @@ -5,6 +5,7 @@ #include #include #include +#include extern bool istcp; extern bool both; @@ -18,9 +19,11 @@ extern uint_fast16_t gwlistenerport; //Port that NAT-PMP-capable gateway listeni extern uint_fast16_t internalport; extern uint_fast16_t externalport; extern uint_fast32_t mappinglifetime; //Recommended to be 2 hrs (https://datatracker.ietf.org/doc/html/rfc6886) + extern std::vector SentPackets; -extern struct WinDev { +extern struct WinDev +{ std::string ipaddr{ "" }; //IPv4 address of an interface as as tring std::string gwayip{ "" }; //DGWAY as a string std::vector macaddrvec; //MAC address of an interface @@ -33,4 +36,21 @@ extern struct WinDev { }; extern WinDev OutputInterface; extern std::vector DEVS; + +extern struct ProtoPort +{ + std::string proto{ "UDP" }; + uint_fast16_t portnumin{ 0 }; + uint_fast16_t portnumout{ 0 }; + std::string UpdateText{ "" }; +}; +extern struct ProlongationStruct +{ + pcpp::Packet Packet; + uint_fast64_t TimestampOfNextUpdate; + std::chrono::time_point chronotimepoint; + ProtoPort ProtocolAndPort; +}; + +extern std::vector ProlongationList; #endif \ No newline at end of file diff --git a/LaunchOptionsHandling.cpp b/LaunchOptionsHandling.cpp index ac45bd9..1f8df4f 100644 --- a/LaunchOptionsHandling.cpp +++ b/LaunchOptionsHandling.cpp @@ -216,6 +216,16 @@ int LaunchOptionsProcessing(int localargc, char* localargv[]) SMAC.clear(); } + if (true == has_option(launcharguments, "-T")) //Source MAC argument handling + { + std::string lifetimestring = get_option(launcharguments, "-T"); + mappinglifetime = stoi(lifetimestring); + std::cout << "Mapping lifetime is set to " << mappinglifetime << " seconds." << std::endl; + } + else + { + SMAC.clear(); + } if (true == has_option(launcharguments, "-GW")) //Gateway IPv4 argument handling { diff --git a/NetFormating.cpp b/NetFormating.cpp index b2ad589..37fdd9f 100644 --- a/NetFormating.cpp +++ b/NetFormating.cpp @@ -201,4 +201,12 @@ char DetermineDelimiter(std::string inputstring, uint_fast8_t expectedblocksize) } g = '\0'; return g; +} + +uint_fast32_t GetMappingLifetimeFromPacket(pcpp::Packet lspacket) +{ + uint8_t* ppayload = lspacket.getLayerOfType()->getPayload(); + uint_fast32_t* packetlifetime = (uint_fast32_t*)&ppayload[8]; + uint_fast32_t hostorder = ntohl(*packetlifetime); + return hostorder; } \ No newline at end of file diff --git a/NetFormating.hpp b/NetFormating.hpp index 7942a5f..34212d4 100644 --- a/NetFormating.hpp +++ b/NetFormating.hpp @@ -7,10 +7,13 @@ #include #include #include +#include +#include char DetermineDelimiter(std::string inputstring, uint_fast8_t expectedblocksize); int MakeMeIpv4(uint_fast32_t input, unsigned int& a, unsigned int& b, unsigned int& c, unsigned int& d); uint_fast16_t portcheck(const std::string inputstring, const char* whos); +uint_fast32_t GetMappingLifetimeFromPacket(pcpp::Packet lspacket); uint_fast32_t SchizoConverter(std::string inputstring); void PrintIPV4(const char* msg, uint_fast32_t input); diff --git a/NetFunctions.cpp b/NetFunctions.cpp index dc03424..c2fb185 100644 --- a/NetFunctions.cpp +++ b/NetFunctions.cpp @@ -1,6 +1,5 @@ #include "NetFunctions.hpp" - -#define VERBOSE +#pragma warning(disable : 4996) uint_fast8_t sendspoof(std::string lsDMAC, std::string lsGWMAC, std::string lsDADDR, WinDev Out, bool lstcp, uint_fast16_t lsinternalport, uint_fast16_t lsexternalport, std::string lsDGWAY, uint_fast16_t lsGWlistenport, uint_fast32_t mappingtime) { /* @@ -63,57 +62,8 @@ uint_fast8_t sendspoof(std::string lsDMAC, std::string lsGWMAC, std::string lsDA newPacket.computeCalculateFields(); pcpp::IPv4Address testv4(Out.ipaddr); - if (true == testv4.isValid()) - { - pcpp::PcapLiveDevice* dev = pcpp::PcapLiveDeviceList::getInstance().getPcapLiveDeviceByIp(testv4); - if (nullptr == dev) - { - std::cerr << "Couldn't find interface by provided IP address or name" << std::endl; - return 201; - } - if (!dev->open()) - { - std::cerr << "Couldn't open the device." << std::endl; - return 202; - } - else - { - std::cout << "Trying to send packet for "; - if (true == lstcp) - { - std::cout << "TCP" << std::endl; - } - else - { - std::cout << "UDP" << std::endl; - } - int sentCount = dev->sendPacket(&newPacket); - - - if (1 == progmode) //Caching mappings is only needed in Hold mode - { - bool alreadyexists = false; - for (unsigned int sp = 0; sp < SentPackets.size(); sp++) - { - if (0 == ComparePayloads(*(SentPackets.at(sp).getLayerOfType()), newPayload)) - { - alreadyexists = true; - SentPackets.at(sp) = newPacket; - } - } - if (false == alreadyexists) - { - SentPackets.push_back(newPacket); - } - } - - std::this_thread::sleep_for(std::chrono::milliseconds(250)); //250ms delay to assure correct processing in series of requests - - } - free(lsbuffer); - return 0; - } - std::cerr << "Host address didn't pass the validation check. Aborting..." << std::endl; + SendPacketWrap(newPacket, Out); + free(lsbuffer); return 322; } std::cerr << "Wasn't able to allocate memory. Aborting..." << std::endl; @@ -371,4 +321,189 @@ uint_fast8_t PrintPayloadFromPacket(pcpp::Packet packet) std::cout << std::hex << std::setfill('0') << std::setw(2) << (int)ppayload[i] << "-"; } return 0; +} + + +uint_fast64_t CreateTimestampOfNextUpdate(pcpp::PayloadLayer payload) +{ + uint8_t* pdata = payload.getPayload(); + uint_fast32_t* packetlifetime = (uint_fast32_t*)&pdata[8]; + uint_fast32_t hostorder = ntohl(*packetlifetime); + hostorder /= 2; //Time till refresh in seconds + uint_fast64_t systime = std::chrono::duration_cast(std::chrono::system_clock::now().time_since_epoch()).count(); //Current time + uint_fast64_t timeofrefresh = systime + hostorder; //Time of required update + + return timeofrefresh; +} + + +std::chrono::time_point CreateTimepointOfNextUpdate(pcpp::PayloadLayer payload) +{ + uint8_t* pdata = payload.getPayload(); + uint_fast32_t* packetlifetime = (uint_fast32_t*)&pdata[8]; + uint_fast32_t hostorder = ntohl(*packetlifetime); + hostorder /= 2; //Time till refresh in seconds + std::chrono::time_point systemtime = std::chrono::system_clock::now(); + std::chrono::time_point timeofrefresh = systemtime + std::chrono::seconds(hostorder); + const std::time_t datetimesyst = std::chrono::system_clock::to_time_t(systemtime); + const std::time_t datetimerefr = std::chrono::system_clock::to_time_t(timeofrefresh); + return timeofrefresh; +} + + + +uint_fast64_t CreateTimestampOfNextUpdate(pcpp::Packet packet) +{ + uint8_t* ppayload = packet.getLayerOfType()->getPayload(); + uint_fast64_t retval = CreateTimestampOfNextUpdate(*ppayload); + return retval; +} + +uint_fast64_t CreateTimestampOfNextUpdate(uint32_t lifetime) +{ + + uint_fast64_t secondstillupdate = lifetime / 2; + uint_fast64_t systime = std::chrono::duration_cast(std::chrono::system_clock::now().time_since_epoch()).count(); //Current time + uint_fast64_t timeofrefresh = systime + secondstillupdate; //Time of required update + + return timeofrefresh; +} + +ProtoPort GetProtoAndPortFromPayloadLayer(pcpp::PayloadLayer lspayload) +{ + uint8_t* pdata = lspayload.getPayload(); + uint8_t opmode = pdata[1]; + std::string retstr; + uint16_t retint = 0; + uint16_t retext = 0; + if (1 == opmode) + { + retstr = "UDP"; + } + if (2 == opmode) + { + retstr = "TCP"; + } + if ( retstr.empty() ) + { + std::cerr << "Error occured during protocol processing" << std::endl; + } + + uint_fast16_t* portnumint = (uint_fast16_t*)&pdata[4]; //4,5 = INT + retint = ntohs(*portnumint); + uint_fast16_t* portnumext = (uint_fast16_t*)&pdata[6]; //4,5 = INT + retext = ntohs(*portnumext); + std::string Updstr = "Updated mapping for " + retstr + '-' + std::to_string(retint) + '-' + std::to_string(retext) + '.'; + return { retstr,retint, retext, Updstr }; +} + +ProtoPort GetProtoAndPortFromPacket(pcpp::Packet packet) +{ + pcpp::PayloadLayer * ppayload = packet.getLayerOfType(); + ProtoPort retval = GetProtoAndPortFromPayloadLayer(*ppayload); + return retval; +} + +uint_fast8_t WatchList() +{ + std::chrono::time_point systemtime; + while (0 < ProlongationList.size() ) + { + systemtime = std::chrono::system_clock::now(); + for (int it = 0; it < ProlongationList.size(); it++) + { + if (ProlongationList.at(it).chronotimepoint <= systemtime) + { + uint8_t res = SendPacketWrap(ProlongationList.at(it).Packet, OutputInterface); + if (0 != res) + { + std::cerr << "An error occured when tried to update mapping time!" << std::endl; + } + } + + } + } + return 0; +} + +uint_fast8_t SendPacketWrap(pcpp::Packet &lspacket, WinDev lsOut) +{ + pcpp::IPv4Address testv4(lsOut.ipaddr); + if (true == testv4.isValid()) + { + pcpp::PcapLiveDevice* dev = pcpp::PcapLiveDeviceList::getInstance().getPcapLiveDeviceByIp(testv4); + if (nullptr == dev) + { + std::cerr << "Couldn't find interface by provided IP address or name" << std::endl; + return 201; + } + if (!dev->open()) + { + std::cerr << "Couldn't open the device." << std::endl; + return 202; + } + else + { + dev->sendPacket(&lspacket); + if (1 == progmode) //Caching mappings is only needed in Hold mode + { + bool alreadyexists = false; + pcpp::PayloadLayer lspayload = *(lspacket.getLayerOfType()); + for (unsigned int sp = 0; sp < SentPackets.size(); sp++) + { + if (0 == ComparePayloads(*(SentPackets.at(sp).getLayerOfType()), lspayload)) + { + alreadyexists = true; + SentPackets.at(sp) = lspacket; + } + } + if (false == alreadyexists) + { + SentPackets.push_back(lspacket); + } + uint32_t mappingtime = GetMappingLifetimeFromPacket(lspacket); + if (0 != mappingtime) + { + alreadyexists = false; + for (unsigned int sp = 0; sp < ProlongationList.size(); sp++) + { + if (0 == ComparePayloads(*(ProlongationList.at(sp).Packet.getLayerOfType()), lspayload)) + { + alreadyexists = true; + std::chrono::time_point UpdateTime = CreateTimepointOfNextUpdate(lspayload); + ProlongationList.at(sp).TimestampOfNextUpdate = CreateTimestampOfNextUpdate(lspacket); + ProlongationList.at(sp).chronotimepoint = UpdateTime; + std::time_t datetimerefr = std::chrono::system_clock::to_time_t(UpdateTime); + std::string str1 = ProlongationList.at(sp).ProtocolAndPort.UpdateText; + std::string str2 = "Next update for this mapping will be at " + (std::string) std::ctime(&datetimerefr); + uint_fast64_t outwidth; + if (str1.size() > str2.size()) + { + outwidth = str1.size(); + } + else + { + outwidth = str2.size(); + } + std::cout << std::setw(outwidth) << std::setfill('-') << " " << std::endl; + std::cout << str1 << std::endl; + std::cout << str2; + std::cout << std::setw(outwidth) << std::setfill('-') << " " << std::endl; + } + } + if (false == alreadyexists) + { + ProtoPort lsportstruc = GetProtoAndPortFromPayloadLayer(lspayload); + std::string Updstr= "Updated mapping for " + lsportstruc.proto + '-' + std::to_string(lsportstruc.portnumin) + '-' + std::to_string(lsportstruc.portnumout) + '.'; + ProlongationList.push_back({ lspacket, CreateTimestampOfNextUpdate(mappinglifetime),CreateTimepointOfNextUpdate(lspayload),lsportstruc}); + } + } + } + std::this_thread::sleep_for(std::chrono::milliseconds(250)); //250ms delay to assure correct processing in series of requests + return 0; + } + } + std::cerr << "Host address didn't pass the validation check. Aborting..." << std::endl; + return 322; + } \ No newline at end of file diff --git a/NetFunctions.hpp b/NetFunctions.hpp index fa772e0..277b67d 100644 --- a/NetFunctions.hpp +++ b/NetFunctions.hpp @@ -16,6 +16,8 @@ #include "GlobalVars.hpp" WinDev FindAppropriateDevice(const std::vector inputvec, const std::string DestIp); WinDev FindAppropriateDeviceByMac(const std::vector inputvec, const std::string SMAC); +ProtoPort GetProtoAndPortFromPayloadLayer(pcpp::PayloadLayer lspayload); +ProtoPort GetProtoAndPortFromPacket(pcpp::Packet packet); void getDevices(); void sendarp(WinDev localstruct, std::string destinationv4, std::vector & inputvec); //[IN] WinDev, [IN] std::string IPV4, [OUT] std::vector uint_fast8_t uint_fast8_t ComparePayloads(pcpp::PayloadLayer payload1, pcpp::PayloadLayer payload2); //0 = equal, 1 = not equal, 2 = len(p1)>len(p2), 3 = len(p1)& packetvector, WinDev lsOut); + +uint_fast8_t SendPacketWrap(pcpp::Packet& lspacket, WinDev lsOut); +uint_fast64_t CreateTimestampOfNextUpdate(pcpp::Packet packet); +uint_fast64_t CreateTimestampOfNextUpdate(pcpp::PayloadLayer payload); +uint_fast64_t CreateTimestampOfNextUpdate(uint32_t lifetime); +std::chrono::time_point CreateTimepointOfNextUpdate(pcpp::PayloadLayer payload); +uint_fast8_t WatchList(); + + diff --git a/OtherFunctions.cpp b/OtherFunctions.cpp index b6ab233..8defc90 100644 --- a/OtherFunctions.cpp +++ b/OtherFunctions.cpp @@ -36,7 +36,6 @@ BOOL WINAPI CtrlHandler(DWORD fdwCtrlType) else { std::cerr << "An error occured during mapping removal process" << std::endl; - } return TRUE; } @@ -95,4 +94,5 @@ BOOL WINAPI CtrlHandler(DWORD fdwCtrlType) default: return FALSE; } -} \ No newline at end of file +} + diff --git a/main.cpp b/main.cpp index 5a995f5..4afd8dc 100644 --- a/main.cpp +++ b/main.cpp @@ -24,6 +24,7 @@ #pragma comment(lib, "Pcap++.lib") + int main(int argc, char* argv[]) { if (EXIT_FAILURE == LaunchOptionsProcessing(argc, argv) ) //Handling of launch arguments @@ -139,9 +140,16 @@ int main(int argc, char* argv[]) { if (SetConsoleCtrlHandler(CtrlHandler, TRUE)) { - std::cout << "Press CTRL+C, CTRL+Break, or close the window to exit and delete all created mappings" << std::endl; + std::cout << std::endl << "Program has entered updating state." << std::endl << "Press CTRL + C, CTRL + Break, or close the window to exit with deletion of all created mappings." << std::endl << std::endl; + uint8_t loopbreak; while (true) { + loopbreak = WatchList(); + if (0 != loopbreak) + { + std::cout << "No mappings left to renew!" << std::endl; + break; + } std::this_thread::sleep_for(std::chrono::seconds(5)); } } @@ -195,7 +203,9 @@ int main(int argc, char* argv[]) } } - - system("PAUSE"); + if (1 != progmode) + { + system("PAUSE"); + } return 0; }