bool Mapper_MiniUPnPc::add(const string& port, const Protocol protocol, const string& description) {
#ifdef HAVE_OLD_MINIUPNPC
	return UPNP_AddPortMapping(url.c_str(), service.c_str(), port.c_str(), port.c_str(),
		localIp.c_str(), description.c_str(), protocols[protocol], 0) == UPNPCOMMAND_SUCCESS;
#else
	return UPNP_AddPortMapping(url.c_str(), service.c_str(), port.c_str(), port.c_str(),
		localIp.c_str(), description.c_str(), protocols[protocol], 0, 0) == UPNPCOMMAND_SUCCESS;
#endif
}
Example #2
0
int upnpAddPortMapping( struct upnp_handle_t *handle, const char *proto, unsigned short port ) {
	char extPort[6];
	char inPort[6];

	snprintf( extPort, sizeof(extPort), "%hu", port );
	snprintf( inPort, sizeof(inPort), "%hu", port );
#if (MINIUPNPC_API_VERSION <= 5)
	return UPNP_AddPortMapping( handle->urls.controlURL, handle->data.first.servicetype, extPort, inPort, handle->addr, NULL, proto, NULL );
#else
	return UPNP_AddPortMapping( handle->urls.controlURL, handle->data.first.servicetype, extPort, inPort, handle->addr, NULL, proto, NULL, NULL );
#endif
}
Example #3
0
bool CUPnPImplMiniLib::CStartDiscoveryThread::OpenPort(uint16 nPort, bool bTCP, char* pachLANIP){
	const char achTCP[] = "TCP";
	const char achUDP[] = "UDP";
	const char achDescTCP[] = "eMule_TCP";
	const char achDescUDP[] = "eMule_UDP";
	char achPort[10];
	sprintf(achPort, "%u", nPort);
	
	if (m_pOwner->m_bAbortDiscovery)
		return false;

	int nResult;
	if (bTCP)
		nResult = UPNP_AddPortMapping(m_pOwner->m_pURLs->controlURL, m_pOwner->m_pIGDData->servicetype
		, achPort, achPort, pachLANIP, achDescTCP, achTCP);
	else
		nResult = UPNP_AddPortMapping(m_pOwner->m_pURLs->controlURL, m_pOwner->m_pIGDData->servicetype
		, achPort, achPort, pachLANIP, achDescUDP, achUDP);

	if (nResult != UPNPCOMMAND_SUCCESS){
		DebugLog(_T("Adding PortMapping failed, Error Code %u"), nResult);
		return false;
	}

	if (m_pOwner->m_bAbortDiscovery)
		return false;

	// make sure it really worked
	char achOutIP[20];
	achOutIP[0] = 0;
	if (bTCP)
		nResult = UPNP_GetSpecificPortMappingEntry(m_pOwner->m_pURLs->controlURL, m_pOwner->m_pIGDData->servicetype
		, achPort, achTCP, achOutIP, achPort);
	else
		nResult = UPNP_GetSpecificPortMappingEntry(m_pOwner->m_pURLs->controlURL, m_pOwner->m_pIGDData->servicetype
		, achPort, achUDP, achOutIP, achPort);

	if (nResult == UPNPCOMMAND_SUCCESS && achOutIP[0] != 0){
		DebugLog(_T("Sucessfully added mapping for port %u (%s) on local IP %S"), nPort, bTCP ? _T("TCP") : _T("UDP"), achOutIP);
		return true;
	}
	else {
		DebugLogWarning(_T("Failed to verfiy mapping for port %u (%s) on local IP %S - considering as failed"), nPort, bTCP ? _T("TCP") : _T("UDP"), achOutIP);
		// maybe counting this as error is a bit harsh as this may lead to false negatives, however if we would risk false postives
		// this would mean that the fallback implementations are not tried because eMule thinks it worked out fine
		return false;
	}
}
Example #4
0
	Utils::UPnPResult ModuleUPnP::UPnPForwardPort(bool tcp, int externalport, int internalport, const std::string & ruleName)
	{
		struct UPNPUrls urls;
		struct IGDdatas data;
		char lanaddr[16];

		if (upnpDiscoverError != UPNPDISCOVER_SUCCESS || upnpDevice == nullptr)
			return Utils::UPnPResult(Utils::UPnPErrorType::DiscoveryError, upnpDiscoverError);

		int ret = UPNP_GetValidIGD(upnpDevice, &urls, &data,
			lanaddr, sizeof(lanaddr));

		if (ret != Utils::UPNP_IGD_VALID_CONNECTED)
			return Utils::UPnPResult(Utils::UPnPErrorType::IGDError, ret);

		ret = UPNP_AddPortMapping(urls.controlURL, data.first.servicetype,
			std::to_string(externalport).c_str(), std::to_string(internalport).c_str(),
			lanaddr, ruleName.c_str(), tcp ? "TCP" : "UDP", NULL, NULL);

		Utils::UPnPErrorType type = Utils::UPnPErrorType::None;
		if (ret != UPNPCOMMAND_SUCCESS)
			type = Utils::UPnPErrorType::PortMapError;

		return Utils::UPnPResult(type, ret);
	}
/* AddPortMapping(externalPort, protocol, internalHost, internalPort, desc) 
 * protocol is 'UDP' or 'TCP' */
static PyObject *
UPnP_addportmapping(UPnPObject *self, PyObject *args)
{
	char extPort[6];
	unsigned short ePort;
	char inPort[6];
	unsigned short iPort;
	const char * proto;
	const char * host;
	const char * desc;
	int r;
	if (!PyArg_ParseTuple(args, "HssHs", &ePort, &proto,
	                                     &host, &iPort, &desc))
        return NULL;
	sprintf(extPort, "%hu", ePort);
	sprintf(inPort, "%hu", iPort);
	r = UPNP_AddPortMapping(self->urls.controlURL, self->data.servicetype,
	                        extPort, inPort, host, desc, proto);
	if(r)
	{
		Py_RETURN_TRUE;
	}
	else
	{
		Py_RETURN_FALSE;
	}
}
Example #6
0
int
tor_upnp_add_tcp_mapping(uint16_t internal_port, uint16_t external_port,
                         int is_verbose, void *backend_state)
{
  int retval;
  char internal_port_str[6];
  char external_port_str[6];
  miniupnpc_state_t *state = (miniupnpc_state_t *) backend_state;

  if (!state->init) {
    fprintf(stderr, "E: %s but state is not initialized.\n", __func__);
    return -1;
  }

  if (is_verbose)
    fprintf(stderr, "V: UPnP: internal port: %u, external port: %u\n",
            internal_port, external_port);

  tor_snprintf(internal_port_str, sizeof(internal_port_str),
               "%u", internal_port);
  tor_snprintf(external_port_str, sizeof(external_port_str),
               "%u", external_port);

  retval = UPNP_AddPortMapping(state->urls.controlURL,
                               state->data.first.servicetype,
                               external_port_str, internal_port_str,
#ifdef MINIUPNPC15
                               state->lanaddr, UPNP_DESC, "TCP", 0);
#else
                               state->lanaddr, UPNP_DESC, "TCP", 0, 0);
#endif

  return (retval == UPNP_ERR_SUCCESS) ? 0 : -1;
}
Example #7
0
/* AddPortMapping(externalPort, protocol, internalHost, internalPort, desc,
 *                remoteHost) 
 * protocol is 'UDP' or 'TCP' */
static PyObject *
UPnP_addportmapping(UPnPObject *self, PyObject *args)
{
	char extPort[6];
	unsigned short ePort;
	char inPort[6];
	unsigned short iPort;
	const char * proto;
	const char * host;
	const char * desc;
	const char * remoteHost;
	int r;
	if (!PyArg_ParseTuple(args, "HssHss", &ePort, &proto,
	                                     &host, &iPort, &desc, &remoteHost))
        return NULL;
	sprintf(extPort, "%hu", ePort);
	sprintf(inPort, "%hu", iPort);
	r = UPNP_AddPortMapping(self->urls.controlURL, self->data.servicetype,
	                        extPort, inPort, host, desc, proto, remoteHost);
	if(r==UPNPCOMMAND_SUCCESS)
	{
		Py_RETURN_TRUE;
	}
	else
	{
		// TODO: RAISE an Exception. See upnpcommands.h for errors codes.
		// upnperrors.c
		//Py_RETURN_FALSE;
		/* TODO: have our own exception type ! */
		PyErr_SetString(PyExc_Exception, strupnperror(r));
		return NULL;
	}
}
Example #8
0
int AddPortMapping(unsigned int extPort, unsigned int intPort, const char* protocol, const char* intClient)
{
    char myextPort[6]      = {0};
    char myintPort[6]      = {0};
    char desc[80]          = {0};
    char leaseDuration[16] = {0};

    sprintf(myextPort, "%d", extPort);
    sprintf(myintPort, "%d", intPort);
    sprintf(desc, "%s", "my_upnp_test");
    sprintf(leaseDuration, "%d", 0);

    printf("***extPort:%s, intPort:%s, %s, %s***\n", myextPort, myintPort, intClient, protocol);
    printf("***%s, %s***\n", desc, leaseDuration);

    int result = UPNP_AddPortMapping(g_urls->controlURL, g_data->first.servicetype, 
                                     myextPort, myintPort, intClient, desc, protocol, NULL, leaseDuration);

    if(0 == result)
    {
        printf("add port mapping ok\n");
    }
    else
    {
        printf("add port mapping failed: %d\n", result);
    }

    return 0;
}
Example #9
0
boost::optional<NATPortMapping> MiniUPnPInterface::addPortForward(int actualLocalPort, int actualPublicPort) {
	if (!p->isValid) {
		return boost::optional<NATPortMapping>();
	}

	NATPortMapping mapping(actualLocalPort, actualPublicPort, NATPortMapping::TCP);

	std::string publicPort = boost::lexical_cast<std::string>(mapping.getPublicPort());
	std::string localPort = boost::lexical_cast<std::string>(mapping.getLocalPort());
	std::string leaseSeconds = boost::lexical_cast<std::string>(mapping.getLeaseInSeconds());

	int ret = UPNP_AddPortMapping(
			p->urls.controlURL, 
			p->data.first.servicetype, 
			publicPort.c_str(), 
			localPort.c_str(), 
			p->localAddress.c_str(), 
			"Swift",
			mapping.getProtocol() == NATPortMapping::TCP ? "TCP" : "UDP", 
			0, 
			leaseSeconds.c_str());
	if (ret == UPNPCOMMAND_SUCCESS) {
		return mapping;
	}
	else {
		return boost::optional<NATPortMapping>();
	}
}
Example #10
0
bool Gateway::addTCPPortMapping(const char *ip, unsigned short iport, unsigned short eport)
{
	if (UPNP_AddPortMapping(urls.controlURL, data.first.servicetype, ulong2CString(iport),
				ulong2CString(eport),  ip, "IPCameraGenius", "TCP", 0, 0) != 0) {
			return false;
	}
	return true;
}
Example #11
0
static inline void I_UPnP_add(const char * addr, const char *port, const char * servicetype)
{
	if (addr == NULL)
		addr = lanaddr;
	if (!urls.controlURL || urls.controlURL[0] == '\0')
		return;
	UPNP_AddPortMapping(urls.controlURL, data.first.servicetype,
	                    port, port, addr, "SRB2", servicetype, NULL, NULL);
}
Example #12
0
/* Test function
 * 1 - get connection type
 * 2 - get extenal ip address
 * 3 - Add port mapping
 * 4 - get this port mapping from the IGD */
static void SetRedirectAndTest(struct UPNPUrls * urls,
                               struct IGDdatas * data,
							   const char * iaddr,
							   const char * iport,
							   const char * eport,
                               const char * proto,
                               const char * leaseDuration,
                               const char * description)
{
	char externalIPAddress[40];
	char intClient[40];
	char intPort[6];
	char duration[16];
	int r;

	if(!iaddr || !iport || !eport || !proto)
	{
		fprintf(stderr, "Wrong arguments\n");
		return;
	}
	proto = protofix(proto);
	if(!proto)
	{
		fprintf(stderr, "invalid protocol\n");
		return;
	}

	UPNP_GetExternalIPAddress(urls->controlURL,
	                          data->first.servicetype,
							  externalIPAddress);
	if(externalIPAddress[0])
		printf("ExternalIPAddress = %s\n", externalIPAddress);
	else
		printf("GetExternalIPAddress failed.\n");

	r = UPNP_AddPortMapping(urls->controlURL, data->first.servicetype,
	                        eport, iport, iaddr, description,
	                        proto, 0, leaseDuration);
	if(r!=UPNPCOMMAND_SUCCESS)
		printf("AddPortMapping(%s, %s, %s) failed with code %d (%s)\n",
		       eport, iport, iaddr, r, strupnperror(r));

	r = UPNP_GetSpecificPortMappingEntry(urls->controlURL,
	                                 data->first.servicetype,
    	                             eport, proto, NULL/*remoteHost*/,
									 intClient, intPort, NULL/*desc*/,
	                                 NULL/*enabled*/, duration);
	if(r!=UPNPCOMMAND_SUCCESS)
		printf("GetSpecificPortMappingEntry() failed with code %d (%s)\n",
		       r, strupnperror(r));

	if(intClient[0]) {
		printf("InternalIP:Port = %s:%s\n", intClient, intPort);
		printf("external %s:%s %s is redirected to internal %s:%s (duration=%s)\n",
		       externalIPAddress, eport, proto, intClient, intPort, duration);
	}
}
Example #13
0
static int
tr_upnpAddPortMapping (const tr_upnp * handle, const char * proto, tr_port port, const char * desc)
{
    int err;
    const int old_errno = errno;
    char portStr[16];
    errno = 0;

    tr_snprintf (portStr, sizeof (portStr), "%d", (int)port);

#if (MINIUPNPC_API_VERSION >= 8)
    err = UPNP_AddPortMapping (handle->urls.controlURL, handle->data.first.servicetype, portStr, portStr, handle->lanaddr, desc, proto, NULL, NULL);
#else
    err = UPNP_AddPortMapping (handle->urls.controlURL, handle->data.first.servicetype, portStr, portStr, handle->lanaddr, desc, proto, NULL);
#endif

    if (err)
        tr_logAddNamedDbg (getKey (), "%s Port forwarding failed with error %d (errno %d - %s)", proto, err, errno, tr_strerror (errno));

    errno = old_errno;
    return err;
}
Example #14
0
static switch_status_t switch_nat_add_mapping_upnp(switch_port_t port, switch_nat_ip_proto_t proto)
{
	switch_status_t status = SWITCH_STATUS_FALSE;
	char port_str[IP_LEN];
	int r = UPNPCOMMAND_UNKNOWN_ERROR;

	sprintf(port_str, "%d", port);

	if (proto == SWITCH_NAT_TCP) {
		r = UPNP_AddPortMapping(nat_globals.urls.controlURL, nat_globals.data.servicetype, port_str, port_str,
								nat_globals.pvt_addr, "FreeSWITCH", "TCP", 0);
	} else if (proto == SWITCH_NAT_UDP) {
		r = UPNP_AddPortMapping(nat_globals.urls.controlURL, nat_globals.data.servicetype, port_str, port_str,
								nat_globals.pvt_addr, "FreeSWITCH", "UDP", 0);
	}

	if (r == UPNPCOMMAND_SUCCESS) {
		switch_log_printf(SWITCH_CHANNEL_LOG, SWITCH_LOG_DEBUG, "mapped public port %s protocol %s to localport %s\n", port_str,
						  (proto == SWITCH_NAT_TCP) ? "TCP" : (proto == SWITCH_NAT_UDP ? "UDP" : "UNKNOWN"), port_str);
		status = SWITCH_STATUS_SUCCESS;
	}

	return status;
}
void C4Network2UPnPP::AddPortMapping(const PortMapping& mapping)
{
	if (!initialized) return; // Catches the case that UPnP initialization failed

	auto eport = std::to_string(mapping.external_port);
	auto iport = std::to_string(mapping.internal_port);

	int r = UPNP_AddPortMapping(upnp_urls.controlURL, igd_data.first.servicetype,
			eport.c_str(), iport.c_str(), lanaddr, description,
			mapping.protocol.c_str(), 0, 0);
	if (r == UPNPCOMMAND_SUCCESS)
		ThreadLogS("UPnP: Added mapping %s %s -> %s:%s", mapping.protocol.c_str(), eport.c_str(), lanaddr, iport.c_str());
	else
		ThreadLog("UPnP: AddPortMapping failed with code %d (%s)", r, strupnperror(r));
}
Example #16
0
// called from ---UPnP--- thread
// Attempt to portforward!
static bool MapPort(const char* addr, const u16 port)
{
  if (s_mapped > 0)
    UnmapPort(s_mapped);

  std::string port_str = std::to_string(port);
  int result = UPNP_AddPortMapping(
    s_urls.controlURL, s_data.first.servicetype, port_str.c_str(), port_str.c_str(), addr,
    (std::string("dolphin-emu UDP on ") + addr).c_str(), "UDP", nullptr, nullptr);

  if (result != 0)
    return false;

  s_mapped = port;

  return true;
}
Example #17
0
File: UPnP.cpp Project: l-n-s/i2pd
 void UPnP::TryPortMapping (std::shared_ptr<i2p::data::RouterInfo::Address> address)
 {
     std::string strType (GetProto (address)), strPort (std::to_string (address->port));
     int r;
     std::string strDesc; i2p::config::GetOption("upnp.name", strDesc);
     r = UPNP_AddPortMapping (m_upnpUrls.controlURL, m_upnpData.first.servicetype, strPort.c_str (), strPort.c_str (), m_NetworkAddr, strDesc.c_str (), strType.c_str (), 0, "0");
     if (r!=UPNPCOMMAND_SUCCESS)
     {
         LogPrint (eLogError, "UPnP: AddPortMapping (", m_NetworkAddr, ":", strPort, ") failed with code ", r);
         return;
     }
     else
     {
         LogPrint (eLogDebug, "UPnP: Port Mapping successful. (", m_NetworkAddr ,":", strPort, " type ", strType, " -> ", m_externalIPAddress ,":", strPort ,")");
         return;
     }
 }
Example #18
0
// called from ---UPnP--- thread
// Attempt to portforward!
bool NetPlayServer::UPnPMapPort(const std::string& addr, const u16 port)
{
	if (m_upnp_mapped > 0)
		UPnPUnmapPort(m_upnp_mapped);

	std::string port_str = StringFromFormat("%d", port);
	int result = UPNP_AddPortMapping(m_upnp_urls.controlURL, m_upnp_data.first.servicetype,
	                             port_str.c_str(), port_str.c_str(), addr.c_str(),
	                             (std::string("dolphin-emu TCP on ") + addr).c_str(),
	                             "TCP", nullptr, nullptr);

	if (result != 0)
		return false;

	m_upnp_mapped = port;

	return true;
}
Example #19
0
/* AddPortMapping(externalPort, protocol, internalHost, internalPort, desc,
 *                remoteHost, leaseDuration)
 * protocol is 'UDP' or 'TCP' */
static PyObject *
UPnP_addportmapping(UPnPObject *self, PyObject *args)
{
	char extPort[6];
	unsigned short ePort;
	char inPort[6];
	unsigned short iPort;
	const char * proto;
	const char * host;
	const char * desc;
	const char * remoteHost;
	unsigned int intLeaseDuration = 0;
	char strLeaseDuration[12];
	int r;
#if (PY_MAJOR_VERSION >= 3) || (PY_MAJOR_VERSION == 2 && PY_MINOR_VERSION > 3)
	if (!PyArg_ParseTuple(args, "HssHzz|I", &ePort, &proto,
	                                     &host, &iPort, &desc, &remoteHost, &intLeaseDuration))
#else
	if (!PyArg_ParseTuple(args, "HssHzz|i", &ePort, &proto,
	                                     &host, &iPort, &desc, &remoteHost, (int *)&intLeaseDuration))
#endif
        return NULL;
Py_BEGIN_ALLOW_THREADS
	sprintf(extPort, "%hu", ePort);
	sprintf(inPort, "%hu", iPort);
	sprintf(strLeaseDuration, "%u", intLeaseDuration);
	r = UPNP_AddPortMapping(self->urls.controlURL, self->data.first.servicetype,
	                        extPort, inPort, host, desc, proto,
	                        remoteHost, strLeaseDuration);
Py_END_ALLOW_THREADS
	if(r==UPNPCOMMAND_SUCCESS)
	{
		Py_RETURN_TRUE;
	}
	else
	{
		// TODO: RAISE an Exception. See upnpcommands.h for errors codes.
		// upnperrors.c
		//Py_RETURN_FALSE;
		/* TODO: have our own exception type ! */
		PyErr_SetString(PyExc_Exception, strupnperror(r));
		return NULL;
	}
}
// called from ---UPnP--- thread
// Attempt to portforward!
bool NetPlayServer::UPnPMapPort(const std::string& addr, const u16 port)
{
	char port_str[6] = { 0 };
	int result;

	if (m_upnp_mapped > 0)
		UPnPUnmapPort(m_upnp_mapped);

	sprintf(port_str, "%d", port);
	result = UPNP_AddPortMapping(m_upnp_urls.controlURL, m_upnp_data.first.servicetype,
	                             port_str, port_str, addr.c_str(),
	                             (std::string("dolphin-emu TCP on ") + addr).c_str(),
	                             "TCP", NULL, NULL);

	if(result != 0)
		return false;

	m_upnp_mapped = port;

	return true;
}
Example #21
0
bool
Portfwd::add( unsigned short port )
{
   char port_str[16];
   int r;
   printf("Portfwd::add (%s, %d)\n", m_lanip.c_str(), port);
   if(urls->controlURL[0] == '\0')
   {
       printf("Portfwd - the init was not done !\n");
       return false;
   }
   sprintf(port_str, "%d", port);
   r = UPNP_AddPortMapping(urls->controlURL, data->servicetype,
                           port_str, port_str, m_lanip.c_str(), 0, "TCP", NULL);
   if(r!=0)
   {
    printf("AddPortMapping(%s, %s, %s) failed, code %d\n", port_str, port_str, m_lanip.c_str(), r);
    return false;
   }
   return true;
}
Example #22
0
void upnp_add_redir (const char * addr, int port)
{
	char port_str[16];
	int r;

    if (!sv_upnp || !is_upnp_ok)
        return;

	if(urls.controlURL == NULL)
		return;

	sprintf(port_str, "%d", port);

    // Set a description if none exists
    if (!sv_upnp_description.cstring()[0])
    {
        std::stringstream desc;

        desc << "Odasrv " << "(" << addr << ":" << port_str << ")";

        sv_upnp_description.Set(desc.str().c_str());
    }

	r = UPNP_AddPortMapping(urls.controlURL, data.first.servicetype,
            port_str, port_str, addr, sv_upnp_description.cstring(), "UDP", NULL, 0);

	if (r != 0)
	{
		Printf(PRINT_HIGH, "UPnP: AddPortMapping failed: %d\n", r);

        is_upnp_ok = false;
	}
    else
    {
        Printf(PRINT_HIGH, "UPnP: Port mapping added to router: %s",
            sv_upnp_description.cstring());

        is_upnp_ok = true;
    }
}
Example #23
0
/** Add a TCP port mapping for a single port stored in <b>tor_fw_options</b>
 * and store the results in <b>backend_state</b>. */
int
tor_upnp_add_tcp_mapping(tor_fw_options_t *options, void *backend_state)
{
  miniupnpc_state_t *state = (miniupnpc_state_t *) backend_state;
  int r;
  char internal_port_str[6];
  char external_port_str[6];

  if (!state->init) {
    r = tor_upnp_init(options, state);
    if (r != UPNP_ERR_SUCCESS)
      return r;
  }

  if (options->verbose)
    fprintf(stdout, "V: internal port: %d, external port: %d\n",
            (int)options->internal_port, (int)options->external_port);

  tor_snprintf(internal_port_str, sizeof(internal_port_str),
               "%d", (int)options->internal_port);
  tor_snprintf(external_port_str, sizeof(external_port_str),
               "%d", (int)options->external_port);

  r = UPNP_AddPortMapping(state->urls.controlURL,
                          state->data.first.servicetype,
                          external_port_str, internal_port_str,
#ifdef MINIUPNPC15
                          state->lanaddr, UPNP_DESC, "TCP", 0);
#else
                          state->lanaddr, UPNP_DESC, "TCP", 0, 0);
#endif
  if (r != UPNPCOMMAND_SUCCESS)
    return UPNP_ERR_ADDPORTMAPPING;

  options->upnp_status = 1;
  return UPNP_ERR_SUCCESS;
}
Example #24
0
static bool natt_open_port(struct natt_status *status,
      struct sockaddr *addr, socklen_t addrlen, enum socket_protocol proto)
{
#ifndef HAVE_SOCKET_LEGACY
#if HAVE_MINIUPNPC
   int r;
   char host[PATH_MAX_LENGTH], ext_host[PATH_MAX_LENGTH],
        port_str[6], ext_port_str[6];
   struct addrinfo hints         = {0};
   const char *proto_str         = NULL;
   struct addrinfo *ext_addrinfo = NULL;

   /* if NAT traversal is uninitialized or unavailable, oh well */
   if (!urls.controlURL || !urls.controlURL[0])
      return false;

   /* figure out the internal info */
   if (getnameinfo(addr, addrlen, host, PATH_MAX_LENGTH,
            port_str, 6, NI_NUMERICHOST|NI_NUMERICSERV) != 0)
      return false;

   proto_str = (proto == SOCKET_PROTOCOL_UDP) ? "UDP" : "TCP";

   /* add the port mapping */
   r = UPNP_AddAnyPortMapping(urls.controlURL,
         data.first.servicetype, port_str,
         port_str, host, "retroarch",
         proto_str, NULL, "3600", ext_port_str);

   if (r != 0)
   {
      /* try the older AddPortMapping */
      memcpy(ext_port_str, port_str, 6);
      r = UPNP_AddPortMapping(urls.controlURL,
            data.first.servicetype, port_str,
            port_str, host, "retroarch",
            proto_str, NULL, "3600");
   }
   if (r != 0)
      return false;

   /* get the external IP */
   r = UPNP_GetExternalIPAddress(urls.controlURL,
         data.first.servicetype, ext_host);
   if (r != 0)
      return false;

   /* update the status */
   if (getaddrinfo_retro(ext_host,
            ext_port_str, &hints, &ext_addrinfo) != 0)
      return false;

   if (ext_addrinfo->ai_family == AF_INET &&
       ext_addrinfo->ai_addrlen >= sizeof(struct sockaddr_in))
   {
      status->have_inet4     = true;
      status->ext_inet4_addr = *((struct sockaddr_in *)
            ext_addrinfo->ai_addr);
   }
#if defined(AF_INET6) && !defined(HAVE_SOCKET_LEGACY)
   else if (ext_addrinfo->ai_family == AF_INET6 &&
            ext_addrinfo->ai_addrlen >= sizeof(struct sockaddr_in6))
   {
      status->have_inet6     = true;
      status->ext_inet6_addr = *((struct sockaddr_in6 *)
            ext_addrinfo->ai_addr);
   }
#endif
   else
   {
      freeaddrinfo_retro(ext_addrinfo);
      return false;
   }

   freeaddrinfo_retro(ext_addrinfo);
   return true;

#else
   return false;
#endif
#else
   return false;
#endif
}
Example #25
0
void* CNetServerWorker::SetupUPnP(void*)
{
	// Values we want to set.
	char psPort[6];
	sprintf_s(psPort, ARRAY_SIZE(psPort), "%d", PS_DEFAULT_PORT);
	const char* leaseDuration = "0"; // Indefinite/permanent lease duration.
	const char* description = "0AD Multiplayer";
	const char* protocall = "UDP";
	char internalIPAddress[64];
	char externalIPAddress[40];
	// Variables to hold the values that actually get set.
	char intClient[40];
	char intPort[6];
	char duration[16];
	// Intermediate variables.
	struct UPNPUrls urls;
	struct IGDdatas data;
	struct UPNPDev* devlist = NULL;

	// Cached root descriptor URL.
	std::string rootDescURL;
	CFG_GET_VAL("network.upnprootdescurl", rootDescURL);
	if (!rootDescURL.empty())
		LOGMESSAGE("Net server: attempting to use cached root descriptor URL: %s", rootDescURL.c_str());

	int ret = 0;
	bool allocatedUrls = false;

	// Try a cached URL first
	if (!rootDescURL.empty() && UPNP_GetIGDFromUrl(rootDescURL.c_str(), &urls, &data, internalIPAddress, sizeof(internalIPAddress)))
	{
		LOGMESSAGE("Net server: using cached IGD = %s", urls.controlURL);
		ret = 1;
	}
	// No cached URL, or it did not respond. Try getting a valid UPnP device for 10 seconds.
	else if ((devlist = upnpDiscover(10000, 0, 0, 0, 0, 0)) != NULL)
	{
		ret = UPNP_GetValidIGD(devlist, &urls, &data, internalIPAddress, sizeof(internalIPAddress));
		allocatedUrls = ret != 0; // urls is allocated on non-zero return values
	}
	else
	{
		LOGMESSAGE("Net server: upnpDiscover failed and no working cached URL.");
		return NULL;
	}

	switch (ret)
	{
	case 0:
		LOGMESSAGE("Net server: No IGD found");
		break;
	case 1:
		LOGMESSAGE("Net server: found valid IGD = %s", urls.controlURL);
		break;
	case 2:
		LOGMESSAGE("Net server: found a valid, not connected IGD = %s, will try to continue anyway", urls.controlURL);
		break;
	case 3:
		LOGMESSAGE("Net server: found a UPnP device unrecognized as IGD = %s, will try to continue anyway", urls.controlURL);
		break;
	default:
		debug_warn(L"Unrecognized return value from UPNP_GetValidIGD");
	}

	// Try getting our external/internet facing IP. TODO: Display this on the game-setup page for conviniance.
	ret = UPNP_GetExternalIPAddress(urls.controlURL, data.first.servicetype, externalIPAddress);
	if (ret != UPNPCOMMAND_SUCCESS)
	{
		LOGMESSAGE("Net server: GetExternalIPAddress failed with code %d (%s)", ret, strupnperror(ret));
		return NULL;
	}
	LOGMESSAGE("Net server: ExternalIPAddress = %s", externalIPAddress);

	// Try to setup port forwarding.
	ret = UPNP_AddPortMapping(urls.controlURL, data.first.servicetype, psPort, psPort,
							internalIPAddress, description, protocall, 0, leaseDuration);
	if (ret != UPNPCOMMAND_SUCCESS)
	{
		LOGMESSAGE("Net server: AddPortMapping(%s, %s, %s) failed with code %d (%s)",
			   psPort, psPort, internalIPAddress, ret, strupnperror(ret));
		return NULL;
	}

	// Check that the port was actually forwarded.
	ret = UPNP_GetSpecificPortMappingEntry(urls.controlURL,
									 data.first.servicetype,
									 psPort, protocall,
#if defined(MINIUPNPC_API_VERSION) && MINIUPNPC_API_VERSION >= 10
									 NULL/*remoteHost*/,
#endif
									 intClient, intPort, NULL/*desc*/,
									 NULL/*enabled*/, duration);

	if (ret != UPNPCOMMAND_SUCCESS)
	{
		LOGMESSAGE("Net server: GetSpecificPortMappingEntry() failed with code %d (%s)", ret, strupnperror(ret));
		return NULL;
	}

	LOGMESSAGE("Net server: External %s:%s %s is redirected to internal %s:%s (duration=%s)",
				   externalIPAddress, psPort, protocall, intClient, intPort, duration);

	// Cache root descriptor URL to try to avoid discovery next time.
	g_ConfigDB.SetValueString(CFG_USER, "network.upnprootdescurl", urls.controlURL);
	g_ConfigDB.WriteFile(CFG_USER);
	LOGMESSAGE("Net server: cached UPnP root descriptor URL as %s", urls.controlURL);

	// Make sure everything is properly freed.
	if (allocatedUrls)
		FreeUPNPUrls(&urls);
    
	freeUPNPDevlist(devlist);

	return NULL;
}
Example #26
0
void upnp_service::map_port( uint16_t local_port )
{
  std::string port = fc::variant(local_port).as_string();

  my->map_port_complete = my->upnp_thread.async( [=]() {
      const char * multicastif = 0;
      const char * minissdpdpath = 0;
      struct UPNPDev * devlist = 0;
      char lanaddr[64];
      
      /* miniupnpc 1.6 */
      int error = 0;
      devlist = upnpDiscover(2000, multicastif, minissdpdpath, 0, 0, &error);

      struct UPNPUrls urls;
      memset( &urls, 0, sizeof(urls) );
      struct IGDdatas data;
      memset( &data, 0, sizeof(data) );
      int r;
      
      r = UPNP_GetValidIGD(devlist, &urls, &data, lanaddr, sizeof(lanaddr));

      bool port_mapping_added = false;
      bool port_mapping_added_successfully = false;

       if (r == 1)
       {
           if (true) //  TODO  config this ?  fDiscover) 
           {
               char externalIPAddress[40];
               r = UPNP_GetExternalIPAddress(urls.controlURL, data.first.servicetype, externalIPAddress);
               if(r != UPNPCOMMAND_SUCCESS)
                   wlog("UPnP: GetExternalIPAddress() returned ${code}", ("code", r));
               else
               {
                   if(externalIPAddress[0])
                   {
                       ulog("UPnP: ExternalIPAddress = ${address}", ("address", externalIPAddress));
                       my->external_ip = fc::ip::address( std::string(externalIPAddress) );
                       // AddLocal(CNetAddr(externalIPAddress), LOCAL_UPNP);
                   }
                   else
                       wlog("UPnP: GetExternalIPAddress failed.");
               }
           }
       
           std::string strDesc = "BitShares 0.0"; // TODO  + FormatFullVersion();
       
     //      try 
           {
               while(!my->done)  // TODO provide way to exit cleanly
               {
                   /* miniupnpc 1.6 */
                   r = UPNP_AddPortMapping(urls.controlURL, data.first.servicetype,
                                       port.c_str(), port.c_str(), lanaddr, strDesc.c_str(), "TCP", 0, "0");
       
                   port_mapping_added = true;
                   if(r!=UPNPCOMMAND_SUCCESS)
                       wlog("AddPortMapping(${port}, ${port}, ${addr}) failed with code ${code} (${string})",
                            ("port", port)("addr", lanaddr)("code", r)("string", strupnperror(r)));
                   else
                   {
                       if (!port_mapping_added_successfully)
                         ulog("UPnP Port Mapping successful");
                       port_mapping_added_successfully = true;

                       my->mapped_port = local_port;
                   }
       
                   fc::usleep( fc::seconds(60*20) ); // Refresh every 20 minutes
               }
           }
     //      catch (boost::thread_interrupted)
           {
               if( port_mapping_added )
               {
                 r = UPNP_DeletePortMapping(urls.controlURL, data.first.servicetype, port.c_str(), "TCP", 0);
                 ilog("UPNP_DeletePortMapping() returned : ${r}", ("r",r));
                 freeUPNPDevlist(devlist); devlist = 0;
                 FreeUPNPUrls(&urls);
               }
      //         throw;
           }
       } else {
           //printf("No valid UPnP IGDs found\n");
           wlog("No valid UPnP IGDs found");
           freeUPNPDevlist(devlist); devlist = 0;
           if (r != 0)
           {
               FreeUPNPUrls(&urls);
           }
       }
  }, "upnp::map_port" );
}
Example #27
0
int
tr_upnpPulse( tr_upnp * handle,
              int       port,
              int       isEnabled,
              int       doPortCheck )
{
    int ret;

    if( isEnabled && ( handle->state == TR_UPNP_DISCOVER ) )
    {
        struct UPNPDev * devlist;
        errno = 0;
        devlist = upnpDiscover( 2000, NULL, NULL, 0 );
        if( devlist == NULL )
        {
            tr_ndbg(
                 getKey( ), "upnpDiscover failed (errno %d - %s)", errno,
                tr_strerror( errno ) );
        }
        errno = 0;
        if( UPNP_GetValidIGD( devlist, &handle->urls, &handle->data,
                             handle->lanaddr, sizeof( handle->lanaddr ) ) == UPNP_IGD_VALID_CONNECTED )
        {
            tr_ninf( getKey( ), _(
                         "Found Internet Gateway Device \"%s\"" ),
                     handle->urls.controlURL );
            tr_ninf( getKey( ), _(
                         "Local Address is \"%s\"" ), handle->lanaddr );
            handle->state = TR_UPNP_IDLE;
            handle->hasDiscovered = 1;
        }
        else
        {
            handle->state = TR_UPNP_ERR;
            tr_ndbg(
                 getKey( ), "UPNP_GetValidIGD failed (errno %d - %s)",
                errno,
                tr_strerror( errno ) );
            tr_ndbg(
                getKey( ),
                "If your router supports UPnP, please make sure UPnP is enabled!" );
        }
        freeUPNPDevlist( devlist );
    }

    if( handle->state == TR_UPNP_IDLE )
    {
        if( handle->isMapped && ( !isEnabled || ( handle->port != port ) ) )
            handle->state = TR_UPNP_UNMAP;
    }

    if( isEnabled && handle->isMapped && doPortCheck )
    {
        char portStr[8];
        char intPort[8];
        char intClient[16];

        tr_snprintf( portStr, sizeof( portStr ), "%d", handle->port );
        if( UPNP_GetSpecificPortMappingEntry( handle->urls.controlURL, handle->data.first.servicetype, 
            portStr, "TCP", intClient, intPort ) != UPNPCOMMAND_SUCCESS  ||
            UPNP_GetSpecificPortMappingEntry( handle->urls.controlURL, handle->data.first.servicetype, 
            portStr, "UDP", intClient, intPort ) != UPNPCOMMAND_SUCCESS )
        {
            tr_ninf( getKey( ), _( "Port %d isn't forwarded" ), handle->port );
            handle->isMapped = FALSE;
        }
    }

    if( handle->state == TR_UPNP_UNMAP )
    {
        char portStr[16];
        tr_snprintf( portStr, sizeof( portStr ), "%d", handle->port );
        UPNP_DeletePortMapping( handle->urls.controlURL,
                                handle->data.first.servicetype,
                                portStr, "TCP", NULL );
        UPNP_DeletePortMapping( handle->urls.controlURL,
                                handle->data.first.servicetype,
                                portStr, "UDP", NULL );
        tr_ninf( getKey( ),
                 _(
                     "Stopping port forwarding through \"%s\", service \"%s\"" ),
                 handle->urls.controlURL, handle->data.first.servicetype );
        handle->isMapped = 0;
        handle->state = TR_UPNP_IDLE;
        handle->port = -1;
    }

    if( handle->state == TR_UPNP_IDLE )
    {
        if( isEnabled && !handle->isMapped )
            handle->state = TR_UPNP_MAP;
    }

    if( handle->state == TR_UPNP_MAP )
    {
        int  err_tcp = -1;
        int  err_udp = -1;
        errno = 0;

        if( !handle->urls.controlURL || !handle->data.first.servicetype )
            handle->isMapped = 0;
        else
        {
            char portStr[16];
            char desc[64];
            const int prev_errno = errno;
            tr_snprintf( portStr, sizeof( portStr ), "%d", port );
            tr_snprintf( desc, sizeof( desc ), "%s at %d", TR_NAME, port );

            errno = 0;
            err_tcp = UPNP_AddPortMapping( handle->urls.controlURL,
                                       handle->data.first.servicetype,
                                       portStr, portStr, handle->lanaddr,
                                       desc, "TCP", NULL );
            if( err_tcp )
                tr_ndbg( getKey( ), "TCP Port forwarding failed with error %d (errno %d - %s)",
                         err_tcp, errno, tr_strerror( errno ) );

            errno = 0;
            err_udp = UPNP_AddPortMapping( handle->urls.controlURL,
                                       handle->data.first.servicetype,
                                       portStr, portStr, handle->lanaddr,
                                       desc, "UDP", NULL );
            if( err_udp )
                tr_ndbg( getKey( ), "UDP Port forwarding failed with error %d (errno %d - %s)",
                         err_udp, errno, tr_strerror( errno ) );

            errno = prev_errno;
            handle->isMapped = !err_tcp | !err_udp;
        }
        tr_ninf( getKey( ),
                 _( "Port forwarding through \"%s\", service \"%s\". (local address: %s:%d)" ),
                 handle->urls.controlURL, handle->data.first.servicetype,
                 handle->lanaddr, port );
        if( handle->isMapped )
        {
            tr_ninf( getKey( ), "%s", _( "Port forwarding successful!" ) );
            handle->port = port;
            handle->state = TR_UPNP_IDLE;
        }
        else
        {
            tr_ndbg( getKey( ), "If your router supports UPnP, please make sure UPnP is enabled!" );
            handle->port = -1;
            handle->state = TR_UPNP_ERR;
        }
    }

    switch( handle->state )
    {
        case TR_UPNP_DISCOVER:
            ret = TR_PORT_UNMAPPED; break;

        case TR_UPNP_MAP:
            ret = TR_PORT_MAPPING; break;

        case TR_UPNP_UNMAP:
            ret = TR_PORT_UNMAPPING; break;

        case TR_UPNP_IDLE:
            ret = handle->isMapped ? TR_PORT_MAPPED
                  : TR_PORT_UNMAPPED; break;

        default:
            ret = TR_PORT_ERROR; break;
    }

    return ret;
}
Example #28
0
	void threadMain()
		throw()
	{
		char lanaddr[4096];
		char externalip[4096]; // no range checking? so make these buffers larger than any UDP packet a uPnP server could send us as a precaution :P
		char inport[16];
		char outport[16];
		struct UPNPUrls urls;
		struct IGDdatas data;

#ifdef ZT_UPNP_TRACE
		fprintf(stderr,"UPNPClient: started for UDP port %d"ZT_EOL_S,localPort);
#endif

		unsigned int tryPortStart = 0;
		Utils::getSecureRandom(&tryPortStart,sizeof(tryPortStart));
		tryPortStart = (tryPortStart % (65535 - 1025)) + 1025;

		while (run) {
			{
				int upnpError = 0;
				UPNPDev *devlist = upnpDiscover(2000,(const char *)0,(const char *)0,0,0,0,&upnpError);
				if (devlist) {
#ifdef ZT_UPNP_TRACE
					{
						UPNPDev *dev = devlist;
						while (dev) {
							fprintf(stderr,"UPNPClient: found device at URL '%s': %s"ZT_EOL_S,dev->descURL,dev->st);
							dev = dev->pNext;
						}
					}
#endif

					memset(lanaddr,0,sizeof(lanaddr));
					memset(externalip,0,sizeof(externalip));
					memset(&urls,0,sizeof(urls));
					memset(&data,0,sizeof(data));
					Utils::snprintf(inport,sizeof(inport),"%d",localPort);

					if ((UPNP_GetValidIGD(devlist,&urls,&data,lanaddr,sizeof(lanaddr)))&&(lanaddr[0])) {
#ifdef ZT_UPNP_TRACE
						fprintf(stderr,"UPNPClient: my LAN IP address: %s"ZT_EOL_S,lanaddr);
#endif
						if ((UPNP_GetExternalIPAddress(urls.controlURL,data.first.servicetype,externalip) == UPNPCOMMAND_SUCCESS)&&(externalip[0])) {
#ifdef ZT_UPNP_TRACE
							fprintf(stderr,"UPNPClient: my external IP address: %s"ZT_EOL_S,externalip);
#endif

							for(int tries=0;tries<64;++tries) {
								int tryPort = (int)tryPortStart + tries;
								if (tryPort >= 65535)
									tryPort = (tryPort - 65535) + 1025;
								Utils::snprintf(outport,sizeof(outport),"%u",tryPort);

								int mapResult = 0;
								if ((mapResult = UPNP_AddPortMapping(urls.controlURL,data.first.servicetype,outport,inport,lanaddr,"ZeroTier","UDP",(const char *)0,"0")) == UPNPCOMMAND_SUCCESS) {
	#ifdef ZT_UPNP_TRACE
									fprintf(stderr,"UPNPClient: reserved external port: %s"ZT_EOL_S,outport);
	#endif
									{
										Mutex::Lock sl(surface_l);
										surface.clear();
										InetAddress tmp(externalip);
										tmp.setPort(tryPort);
										surface.push_back(tmp);
									}
									break;
								} else {
	#ifdef ZT_UPNP_TRACE
									fprintf(stderr,"UPNPClient: UPNP_AddAnyPortMapping(%s) failed: %d"ZT_EOL_S,outport,mapResult);
	#endif
									Thread::sleep(1000);
								}
							}
						} else {
#ifdef ZT_UPNP_TRACE
							fprintf(stderr,"UPNPClient: UPNP_GetExternalIPAddress failed"ZT_EOL_S);
#endif
						}
					} else {
#ifdef ZT_UPNP_TRACE
						fprintf(stderr,"UPNPClient: UPNP_GetValidIGD failed"ZT_EOL_S);
#endif
					}

					freeUPNPDevlist(devlist);
				} else {
#ifdef ZT_UPNP_TRACE
					fprintf(stderr,"UPNPClient: upnpDiscover error code: %d"ZT_EOL_S,upnpError);
#endif
				}
			}

#ifdef ZT_UPNP_TRACE
			fprintf(stderr,"UPNPClient: rescanning in %d ms"ZT_EOL_S,ZT_UPNP_CLIENT_REFRESH_DELAY);
#endif
			Thread::sleep(ZT_UPNP_CLIENT_REFRESH_DELAY);
		}
		delete this;
	}
Example #29
0
/**
 *  Erstellt per UPnP ein Portforwarding.
 *
 *  @author FloSoft
 */
bool UPnP::OpenPort(const unsigned short& port)
{
    if(remote_port_ != 0)
        ClosePort();

    remote_port_ = port;

#ifdef _MSC_VER
    HRESULT hr;

    CoInitialize(NULL);

    IUPnPNAT* upnpnat;
    hr = CoCreateInstance (CLSID_UPnPNAT, NULL, CLSCTX_INPROC_SERVER, IID_IUPnPNAT, (void**)&upnpnat);
    if(FAILED(hr) || !upnpnat)
    {
        if(!upnpnat)
            hr = E_NOINTERFACE;
        SetLastError(hr);
        return false;
    }

    IStaticPortMappingCollection* upnpspmc = NULL;
    hr = upnpnat->get_StaticPortMappingCollection(&upnpspmc);
    if(FAILED(hr) || !upnpspmc)
    {
        if(!upnpspmc)
            hr = E_NOINTERFACE;
        SetLastError(hr);
        return false;
    }

    std::string local_address;
    std::vector<std::string> addresses = GetAllv4Addresses();

    // if we have multiple addresses, search the private one
    if(addresses.size() > 1)
    {
        for(std::vector<std::string>::iterator addr = addresses.begin(); addr != addresses.end(); ++addr)
        {
            std::string ss = *addr;
            std::stringstream s, sc;
            s << ss;
            std::getline(s, ss, '.');
            sc << ss << " ";
            std::getline(s, ss, '.');
            sc << ss << " ";

            int a, b;
            sc >> a;
            sc >> b;

            int ab = (a << 24) | (b << 16);

            if( (ab & 0xff000000) == 0x0a000000 || // 10.0.0.0/8
                    (ab & 0xff000000) == 0x7f000000 || // 127.0.0.0/8
                    (ab & 0xfff00000) == 0xac100000 || // 172.16.0.0/12
                    (ab & 0xffff0000) == 0xc0a80000 )  // 192.168.0.0/16
                local_address = *addr;
        }
    }

    // otherwise use the first one
    if(local_address == "" && !addresses.empty())
        local_address = addresses.front();

    // I hope we found one ...
    if(local_address == "")
    {
        SetLastError(E_FAIL);
        return false;
    }

    BSTR bstrProtocol = A2BSTR("TCP");
    BSTR bstrLocalAddress = A2BSTR(local_address.c_str());
    BSTR bstrDescription = A2BSTR("Return To The Roots");

    IStaticPortMapping* upnpspm = NULL;
    hr = upnpspmc->Add(port, bstrProtocol, port, bstrLocalAddress, VARIANT_TRUE, bstrDescription, &upnpspm);

    SysFreeString(bstrProtocol);
    SysFreeString(bstrLocalAddress);
    SysFreeString(bstrDescription);

    if(SUCCEEDED(hr) && !upnpspm)
        hr = E_NOINTERFACE;

    SetLastError(hr);

    if(SUCCEEDED(hr) && upnpspm)
        return true;
#else
    int hr;
    UPNPDev* devicelist = NULL;
#ifdef UPNPDISCOVER_SUCCESS
    int upnperror = 0;
    devicelist = upnpDiscover(2000, NULL, NULL, 0, 0 /* ipv6 */, &upnperror);
#else
    devicelist = upnpDiscover(2000, NULL, NULL, 0);
#endif
    if(!devicelist)
        return false;

    UPNPUrls urls;
    IGDdatas data;
    char lanAddr[64];
    hr = UPNP_GetValidIGD(devicelist, &urls, &data, lanAddr, sizeof(lanAddr));

    if(hr == 1 || hr == 2)
    {
        std::stringstream p;
        p << port;

#ifdef UPNPDISCOVER_SUCCESS
        hr = UPNP_AddPortMapping(urls.controlURL, data.first.servicetype, p.str().c_str(), p.str().c_str(), lanAddr, "Return To The Roots", "TCP", NULL, NULL);
#else
        hr = UPNP_AddPortMapping(urls.controlURL, data.first.servicetype, p.str().c_str(), p.str().c_str(), lanAddr, "Return To The Roots", "TCP", NULL);
#endif
    }

    freeUPNPDevlist(devicelist);

    if(hr == 0)
        return true;
#endif
    return false;
}
Example #30
0
int
vino_upnp_add_port (VinoUpnp *upnp, int port)
{
  char *ext_port, *int_port, *desc;
  int   err, local_port;
  char  int_client_tmp[16], int_port_tmp[6];

  g_return_val_if_fail (VINO_IS_UPNP (upnp), -1);

  if (!update_upnp_status (upnp))
    return -1;

  vino_upnp_remove_port (upnp);

  local_port = port;
  do
    {
      ext_port = g_strdup_printf ("%d", local_port);
      dprintf (UPNP, "UPnP: Trying to forward port %d...: ", local_port);
      UPNP_GetSpecificPortMappingEntry (upnp->priv->urls->controlURL,
					upnp->priv->data->servicetype,
					ext_port,
					"TCP",
					int_client_tmp,
					int_port_tmp);
      if ( (strcmp (int_client_tmp, upnp->priv->lanaddr) == 0) && (strcmp (int_port_tmp, ext_port) == 0) )
	{
	  dprintf (UPNP, "UPnP: Found a previous redirect\n");
	  break;
	}
      else if (int_client_tmp[0])
	{
	  dprintf (UPNP, "Failed, this port is already forwarded to %s:%s\n", int_client_tmp, int_port_tmp);
	  g_free (ext_port);
	}
      else
	{
	  dprintf (UPNP, "OK, this port is free on the router\n");
	  break;
	}

      local_port++;
    } while (local_port < INT_MAX);

  if (local_port == INT_MAX)
    {
      dprintf (UPNP, "UPnP: Not forwarding any port, tried so much\n");
      return -1;
    }

  int_port = g_strdup_printf ("%d", port);
  desc = g_strdup_printf ("VNC: %s@%s",
			  g_get_user_name (),
			  g_get_host_name ());  

  err = UPNP_AddPortMapping (upnp->priv->urls->controlURL,
			     upnp->priv->data->servicetype,
			     ext_port,
			     int_port,
			     upnp->priv->lanaddr,
			     desc,
			     "TCP");
  if (err == 0)
    {
      upnp->priv->port = local_port;
      upnp->priv->internal_port = port;
      dprintf (UPNP, "UPnP: Successfuly forwarded port %d\n", local_port);
    }
  else
    dprintf (UPNP, "Failed to forward port %d, with status %d\n", local_port, err);

  g_free (ext_port);
  g_free (int_port);
  g_free (desc);

  return upnp->priv->port;
}