Click here to Skip to main content
15,867,704 members
Articles / Programming Languages / C#

UpnpStat – List and Modify Port Mappings on your UPnP Enabled Router

Rate me:
Please Sign up or sign in to vote.
5.00/5 (5 votes)
16 Sep 2010CPOL5 min read 46.3K   1.8K   19   7
A simple console utility that allows you to query and modify port mappings on a UPnP enabled home networking router.

Introduction

In most home network environments, a router is used to provide access to multiple devices through a network connection provided by an internet service provider (ISP). Home network routers typically use Network Address Translation (NAT) to map internal, also known as ‘private’, IP addresses to a single public IP address provided by the ISPs internet access device, such as a cable or DSL modem. It is the router's job to watch which internal IP address sends a request to the internet and to then route responses to the device that originated the request. This generally works well in situations where the device initiates the request and keeps a connection open to obtain responses from the device on the internet. But what about situations in which a device on the internet needs to reach a device on the internal network? Without some sort of mapping mechanism, this is a difficult task. Fortunately, most routers provide some sort of port mapping, usually in the gaming and applications section of the routers configuration options. Static port mapping, however, requires that the internal device IP address remains the same (static), and makes it necessary for the user to configure a router assuming to have knowledge of IP addresses and ports. Another alternative is to let the application that is listening for requests from the internet to command the router to map connections from the public IP address of the router to an internal IP address. This feature is commonly known as UPnP support in the router. This article presents a simple console utility to query the router for current mappings, to clear out existing mappings, and to add new mappings on the router.

UPnP (Universal Plug and Play) is a networking protocol that is used for dynamic configuration and discovery of devices on a network. It is not restricted to mapping ports on a router or WIFI device, but is also frequently seen in many other device types. For the purpose of this utility, we are only interested in the port mapping aspect of UPnP.

Strategy

To write this utility, I did not want to use custom code to parse the rather complex XML format used by UPnP to communicate with applications (why re-invent the wheel?). Interestingly, I found that Microsoft Windows supports NAT mapping through a COM component library by the name of “NATUPnP 1.0 Type Library”. This library is contained in a DLL named hnetcfg.dll and is usually located in the \windows\system32 folder. According to the MSDN documentation, this API has been present in Windows since Windows XP. As it is packaged as a component library, it is accessible to C/C++ and .NET programming languages.

There are a few requirements on Windows machines before being able to use the NAT API provided by Windows:

  1. The UPnP ports 1900 and 2869 must be opened on the Windows Firewall
  2. The Windows Firewall may not be in shielded mode.
  3. Group Policy option “Allow UPnP” may not be disabled.

Items 1 and 2 can usually be controlled programmatically through the Windows Firewall API. However, Item 3 is often determined by your enterprise administrator. As the target audience for this utility is the home network, item 3 will rarely be a concern.

Using the Utility

The UpnpStat utility is executed from the command line (you can place it into a .CMD file to execute at login, or as part of starting other applications. The syntax is simple and includes the commands:

Help Provides a help screen
add To add a mapping to the router
clear To clear all mappings on the router
list To list existing mappings.

The add command requires parameters to specify the details of the mapping:

Add port protocol description 

Where:

port = port number to be mapped [1..65535]
protocol = UDP or TCP
description = a short description of the mapping 

For example:

To add a mapping from the internet to port 80 (default web server port) on the machine, you would type:

upnpstat add 80 TCP "My Web Server" 

The Project

The project is designed as a C# console application using the .NET 4 Framework. Figure 1 shows the Solution Explorer tree for the project, notice Reference section includes a reference to NATUPNPLib. This is the type library provided with Windows to perform NAT related functions.

Solution-UpnpStat.PNG

Fig 1. Note the reference to NATUPNPLib in the Solutions Explorer.

In addition to the reference in the Project Reference list, the Program.CS file includes several using statements in addition to the defaults created by the Visual Studio template:

C#
using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.Net;
using System.Net.Sockets;
using NATUPNPLib; 

The Code

The utility starts executing by parsing the command line arguments and calling an appropriate method in the class UpnpHelper. I will not detail the command line parsing; it is just a simple set of if statements.

When the class UpnpHelper is constructed, the default constructor creates a new instant of the interface to the UPnPNat library called NatMgr:

C#
class UpnpHelper
{
    UPnPNAT NatMgr;

    public UpnpHelper()
    {
        NatMgr = new UPnPNAT();
    }
:
:

The remaining methods then use the methods in NatMgr. For example, the ListMappings method in the UpnpHelper:

C#
class UpnpHelper
{
   :
   internal void ListMappings()
   {
      if (NatMgr == null)
      {
         Console.WriteLine("Initialization failed creating Windows UPnPNAT interface.");
         return;
      }

    
      IStaticPortMappingCollection mappings = NatMgr.StaticPortMappingCollection;
      if (mappings == null)
      { 
         Console.WriteLine("No mappings found. 
		Do you have a uPnP enabled router as your gateway?");
         return;
      }
      if (mappings.Count == 0)
      {
         Console.WriteLine("Router does not have any active uPnP mappings.");
      }
   
      foreach (IStaticPortMapping pm in mappings)
      {
         Console.WriteLine("Description:");
         Console.WriteLine(pm.Description);
         Console.WriteLine(" {0}:{1} ---> {2}:{3} ({4}",pm.ExternalIPAddress, 
         pm.ExternalPort, pm.InternalClient,pm.InternalPort,pm.Protocol);
         Console.WriteLine("");
      }
   }
   :

   :

The core object used by the methods is the StaticPortMappingCollection which represents a collection of mappings on the router. Using this collection, we can remove, add, and iterate mappings. It is a relatively simple and straightforward interface.

Look through the source code to discover how the other functions are used.

Points of Interest

It should be noted that the project is configured as a .NET 4 Framework application using Visual Studio 2010. Although there is nothing special about this code to prevent it from using .NET 2, 3, or 3.5, this would require the use of Visual Studio 2008 due to, what I believe, is a bug in the way Visual Studio 2010 tries to generate interop DLLs when targeting frameworks other than version 4.

History

  • 16th September, 2010: Initial post

License

This article, along with any associated source code and files, is licensed under The Code Project Open License (CPOL)


Written By
Software Developer (Senior) Logan Industries, Inc.
United States United States
Alex is a software developer and project manager at Logan Industries in Melbourne Florida.

His skills include Windows Server management, router configuration, and software development in C, C++, and C#.

Alex started developing software in the days of Turbo Pascal (Borland) and 8080 assembly language. He progressed through the various stages of coding on various operating system platforms including MP/M-86, Concurrent DOS, MS-DOS, Unix and Windows. He is now most active in the .NET environment using C# and the Visual Studio development platform.

Comments and Discussions

 
QuestionHmm... problem identified? Pin
pi19463-Mar-13 4:03
pi19463-Mar-13 4:03 
QuestionI forgot to mention.... Pin
pi19463-Mar-13 3:33
pi19463-Mar-13 3:33 
QuestionException HRESULT: 0x80040208 Pin
pi19462-Mar-13 15:44
pi19462-Mar-13 15:44 
AnswerRe: Exception HRESULT: 0x80040208 Pin
Gerardo Sanchez18-Mar-15 14:10
Gerardo Sanchez18-Mar-15 14:10 
GeneralMy vote of 5 Pin
Saed Leghaee19-Aug-12 10:35
Saed Leghaee19-Aug-12 10:35 
QuestionNatMgr.StaticPortMappingCollection is always null Pin
Member 434194518-Oct-11 4:08
Member 434194518-Oct-11 4:08 
AnswerRe: NatMgr.StaticPortMappingCollection is always null Pin
Alex Soya1-Nov-11 4:53
Alex Soya1-Nov-11 4:53 

General General    News News    Suggestion Suggestion    Question Question    Bug Bug    Answer Answer    Joke Joke    Praise Praise    Rant Rant    Admin Admin   

Use Ctrl+Left/Right to switch messages, Ctrl+Up/Down to switch threads, Ctrl+Shift+Left/Right to switch pages.