65.9K
CodeProject is changing. Read more.
Home

Portmappings on UPnP-NAT(s) using C++, winsock2, xerces2.8 (Linux friendly code)

starIconstarIconstarIconstarIconstarIcon

5.00/5 (2 votes)

Apr 28, 2009

CPOL
viewsIcon

35413

downloadIcon

759

Portmappings on UPnP-NAT(s) using C++, winsock2, xerces2.8 (Linux friendly code)

Introduction  

This article introducing a portmapping method and some IGD's UPnP SOAP actions using C++ without the Microsoft's COM library for the UPnP. So sorry, you have to setup libraries and VC paths like an image[red square] below. This project using boost-cpplib and xerces (DOM parsing). But I couldn't upload libraries with my source code because of an upload timeout with large file size.

dirplace.png

I had just tested soap responses from UPnP-enabled routers. I had not tested the connections and data streams as points of this article.

Sorry for potential bugs and my poor English.

  • Multiple NICs and multiple routers are supported. But CASCADED NATs are not supported.

Background

I want to implement the portmapping without third party (UPnP) libraries and attempt to write platform independent code AS POSSIBLE.

Using the Code

#include "stdafx.h"

#include "Manager/ApplicationManager.h"
#include "Manager/COMManager.h"

#include "Network/NetworkManager.h"
#include "Network/NetworkHelper.h"

#include "NATBreak/UPNPNATServiceTypes.h"
#include "NATBreak/IGDDiscoverProcess.h"
#include "NATBreak/UPNPNATHTTPClient.h"

using namespace std;
using namespace boost;

thread_group tg;

int _tmain(int argc, _TCHAR* argv[])
{
	ApplicationManager am;
	NetworkManager nm;

	try
	{	
		IGDDiscoverProcess discoverer( 500000 );

		tg.create_thread( ref( discoverer ) );
		tg.join_all();

		IGDDiscoverProcess::IGDControlInformations cinfos = 
			discoverer.GetAllIGDControlInformations();
		boost_foreach( IGDDiscoverProcess::ControlInfo info, cinfos )
		{
			if( info.has_problem )
			{
				cout << "has problem" << endl;
				continue;
			}

			if( info.service_type == UPNPSERVICE_LAYER3FORWARDING1 )
			{
				// Layer3Forwarding:1 srvice

				UPNPNATHTTPClient soap( info.ip, info.port );

				soap.GetDefaultConnectionService
				( info.control_url, info.service_type );
			}
			else if( info.service_type == UPNPSERVICE_WANIPCONNECTION1 )
			{
				// WANIPConnection service
				UPNPNATHTTPClient soap( info.ip, info.port );
				string ip;
				UPNPNATHTTPClient::SoapResult res = 
					soap.GetWANIPAddress( 
					ip, info.control_url, info.service_type 
					);
				cout << "WAN IP : " << ip << endl;

				UPNPNATHTTPClient::SoapResult soap_res;
				soap_res = soap.AddPortMapping( 
				    string("test"), 12345, 12345, string("UDP"), 
				    string("192.168.0.2"), // own nic's address 

                                         info.control_url, info.service_type 
					);
				if( UPNPNATHTTPClient::SoapSucceeded == soap_res )
				{
					cout << "portmapping succeeded." << endl;
				}

				soap_res = soap.DeletePortMapping(
					12345, string("UDP"), info.control_url, 
					info.service_type
					);
				if( UPNPNATHTTPClient::SoapSucceeded == soap_res )
				{
					cout << "delete portmapping succeeded." 
						<< endl;
				}
			}
			else if( info.service_type == 
				UPNPSERVICE_WANCOMMONINTERFACECONFIG1 )
			{
				// WANCommonInterafaceConfig:1 srvice

				UPNPNATHTTPClient soap( info.ip, info.port );

				string ip;
				soap.GetActiveConnection( 0,  
					info.service_type, info.control_url );
			}
		}
	} 
	catch( IGDDiscoverProcess::exception &e )
	{
		cout << e.what() << endl;
	}

	_CrtSetDbgFlag(_CRTDBG_ALLOC_MEM_DF | _CRTDBG_LEAK_CHECK_DF);
	return 0;
}	

Points of Interest

  • In case when multiple UPnP-enabled NATs are cascaded
  • IPv6 support

History

This is the first version. 

The sample code has been fixed. The fixed part seems "string("192.168.0.2"),". This address means an own nic's address to send a m-search message.