1
0
Fork 0
mirror of https://bitbucket.org/King_DuckZ/keepupnpup.git synced 2024-11-07 21:29:00 +00:00

Implement listing redirections.

This commit is contained in:
King_DuckZ 2016-08-25 02:25:35 +02:00
parent 06562e9f0e
commit 0fa232d074
2 changed files with 163 additions and 7 deletions

1
.gitignore vendored
View file

@ -1,3 +1,4 @@
build/
*.swp
compile_commands.json
.ycm_extra_conf.py

View file

@ -4,27 +4,81 @@
#include "upnperrors.h"
#include <memory>
#include <vector>
#include <string>
#include <ciso646>
#include <cstdint>
#include <strings.h>
#if !defined(NDEBUG)
# define KUU_VERBOSE
#endif
namespace {
enum Protocol {
ProtocolUDP,
ProtocolTCP,
ProtocolOther
};
class UPNPUrlsResource {
public:
UPNPUrlsResource () :
m_initialized(false)
enum IGDReply {
IGDValid = 1,
IGDNotConnected = 2,
IGDUpnpNotSureIGD = 3,
IGDNotSure,
IGDNone
};
explicit UPNPUrlsResource (struct UPNPDev* parDevList) :
m_lanaddr(64, ' '),
m_igd_reply(IGDNone)
{
const auto i = UPNP_GetValidIGD(parDevList, &m_urls, &m_data, &m_lanaddr[0], m_lanaddr.size());
switch (i) {
case 1:
case 2:
case 3:
m_igd_reply = static_cast<IGDReply>(i);
break;
default:
m_igd_reply = IGDNotSure;
}
const auto idx = m_lanaddr.find('\0');
if (idx != m_lanaddr.npos)
m_lanaddr.resize(idx);
}
~UPNPUrlsResource() noexcept {
if (m_initialized) {
m_initialized = false;
if (IGDNone != m_igd_reply) {
m_igd_reply = IGDNone;
FreeUPNPUrls(&m_urls);
}
}
struct UPNPUrls* urls() { return &m_urls; }
const struct UPNPUrls* urls() const { return &m_urls; }
const struct IGDdatas* data() const { return &m_data; }
IGDReply igd_reply() const { return m_igd_reply; }
const std::string& lanaddr() const { return m_lanaddr; }
private:
std::string m_lanaddr;
struct UPNPUrls m_urls;
bool m_initialized;
struct IGDdatas m_data;
IGDReply m_igd_reply;
};
struct Redirection {
std::string internal_client;
std::string remote_host;
std::string desc;
Protocol protocol;
uint32_t duration;
uint16_t internal_port;
uint16_t external_port;
bool enabled;
};
using UPNPDevsPtr = std::unique_ptr<struct UPNPDev, void(*)(struct UPNPDev*)>;
@ -36,6 +90,83 @@ namespace {
}
return retval;
}
bool is_enabled (const std::string& parEnabled) {
if (parEnabled.size() == 4) {
if (strncasecmp("true", parEnabled.c_str(), 4) == 0)
return true;
}
else if (parEnabled.size() == 2) {
if (strncasecmp("on", parEnabled.c_str(), 2) == 0)
return true;
}
else if (parEnabled.size() == 3) {
if (strncasecmp("yes", parEnabled.c_str(), 3) == 0)
return true;
}
if (parEnabled == "1")
return true;
return false;
}
std::vector<Redirection> get_redirections (const UPNPUrlsResource& parResource) {
char intClient[40];
char intPort[6];
char extPort[6];
char protocol[4];
char desc[80];
char enabled[6];
char rHost[64];
char duration[16];
int r;
int z = 0;
std::vector<Redirection> retval;
do {
rHost[0] = '\0';
enabled[0] = '\0';
duration[0] = '\0';
desc[0] = '\0';
extPort[0] = '\0';
intPort[0] = '\0';
intClient[0] = '\0';
r = UPNP_GetGenericPortMappingEntry(
parResource.urls()->controlURL,
parResource.data()->first.servicetype,
std::to_string(z).c_str(),
extPort,
intClient,
intPort,
protocol,
desc,
enabled,
rHost,
duration
);
//if (r)
// printf("GetGenericPortMappingEntry() returned %d (%s)\n",
// r, strupnperror(r));
if (not r) {
Redirection redir;
redir.protocol = (std::string(protocol) == "TCP" ? ProtocolTCP : (std::string(protocol) == "UDP" ? ProtocolUDP : ProtocolOther));
redir.internal_client = intClient;
redir.remote_host = rHost;
redir.desc = desc;
redir.duration = static_cast<uint32_t>(stoul(std::string(duration)));
redir.internal_port = static_cast<uint16_t>(stoul(std::string(intPort)));
redir.external_port = static_cast<uint16_t>(stoul(std::string(extPort)));
redir.enabled = is_enabled(std::string(enabled));
retval.push_back(redir);
}
++z;
} while (not r);
return retval;
}
} //unnamed namespace
int main() {
@ -62,9 +193,33 @@ int main() {
return 1;
}
#if defined(KUU_VERBOSE)
std::cout << "Found: " << devs.front()->descURL << ", " << devs.front()->st << '\n';
//struct IGDdatas data;
UPNPUrlsResource urls(devlist.get());
switch (urls.igd_reply()) {
case UPNPUrlsResource::IGDValid:
std::cout << "Found valid IGD: " << urls.urls()->controlURL << '\n';
break;
case UPNPUrlsResource::IGDNotConnected:
std::cout << "Found a (not connected?) IGD: " << urls.urls()->controlURL << '\n';
break;
case UPNPUrlsResource::IGDUpnpNotSureIGD:
std::cout << "UPnP device found. Is it an IGD? " << urls.urls()->controlURL << '\n';
break;
case UPNPUrlsResource::IGDNotSure:
std::cout << "Found device (igd?): " << urls.urls()->controlURL << '\n';
}
std::cout << "Local LAN ip address: " << urls.lanaddr() << '\n';
#endif
const auto redirs = get_redirections(urls);
for (auto& redir : redirs) {
std::cout << redir.protocol << ", " << redir.remote_host << ":" << redir.external_port << " --> " <<
redir.internal_client << ":" << redir.internal_port << ", " << redir.duration << ", " <<
redir.enabled << R"(, ")" << redir.desc << "\"\n";
}
return 0;
}