libnatpmp

Home | Downloads | Compatibility list | libnatpmp | MiniSSDPd | xchat upnp patch | Forum

English | Français

Last modified on February 5th 2008.

I hadn't noticed when I started to code libnatpmp, but another library was allready existing using the same name : Allen Porter made his C++ library in october/november 2007. If you want to have a look at it, it is available here. So what's next ? maybe I should change the name of my library ? what do you think of libnatpmpc ? (c like client or like the C language ?)

The NAT Port Mapping Protocol (NAT-PMP)

NAT-PMP is the direct concurrent to the UPnP IGD specification. It is providing a way to do NAT traversal. It is part of the Bonjour protocol specifications. You can get the description of this simple protocol here or by reading the draft. At the moment it is mainly supported by Apple software and hardware. If you are looking for a way to add NAT-PMP capabilities to your *BSD, Linux or (Open)Solaris Router, you should have a look at MiniUPnPd which is supporting NAT-PMP in addition to UPnP since December 2007 !

libnatpmp description

libnatpmp is an attempt to make a portable and fully compliant implementation of the protocol for the client side. It is based on non blocking sockets and all calls of the API are asynchronous. It is therefore very easy to integrate the NAT-PMP code to any event driven code.

Download and build libnatpmp

To download the source code, go to the MiniUPnP Download page.
Use gmake or make to build the library and samples.

Use libnatpmp in your programs

It should be very easy to use libnatpmp in any C/C++ program. All the API is described in the natpmp.h file.

Sample code

Error checking has been deliberately omitted. Please check all return codes in natpmp.h file.

simple sample

This very simple sample just ask for a redirection and return when the job is done.
void redirect(uint16_t privateport, uint16_t publicport)
{
  int r;
  natpmp_t natpmp;
  natpmpresp_t response;
  initnatpmp(&natpmp);
  sendnewportmappingrequest(&natpmp, NATPMP_PROTOCOL_TCP, privateport, publicport, 3600);
  do {
    fd_set fds;
    struct timeval timeout;
    FD_ZERO(&fds);
    FD_SET(natpmp.s, &fds);
    getnatpmprequesttimeout(&natpmp, &timeout);
    select(FD_SETSIZE, &fds, NULL, NULL, &timeout);
    r = readnatpmpresponseorretry(&natpmp, &response);
  } while(r==NATPMP_TRYAGAIN);
  printf("mapped public port %hu to localport %hu liftime %u\n",
         response.newportmapping.mappedpublicport,
         response.newportmapping.privateport,
         response.newportmapping.lifetime);
  closenatpmp(&natpmp);
}

more complex sample

We could imagine the init phase of a P2P software. During this phase, the software tries to get the public IP address and add a port mapping. At the end of the process, natpmpstate will be either Sdone or Serror.
{
  natpmp_t natpmp;
  natpmpresp_t response;
  enum { Sinit=0, Ssendpub, Srecvpub, Ssendmap, Srecvmap, Sdone, Serror=1000 } natpmpstate = Sinit;
  int r;
  [...]
  if(initnatpmp(&natpmp)<0)
    natpmpstate = Serror;
  else
    natpmpstate = Ssendpub;
  [...]
  while(!finished_all_init_stuff) {
    [...]
    other init stuff :)
    [...]
    switch(natpmpstate) {
    case Ssendpub:
      if(sendpublicaddressrequest(&natpmp)<0);
        natpmpstate = Serror;
      else
        natpmpstate = Srecvpub;
      break;
    case Srecvpub:
      r = readnatpmpresponseorretry(&natpmp, &response);
      if(r<0 && r!=NATPMP_TRYAGAIN)
        natpmpstate = Serror;
      else if(r!=NATPMP_TRYAGAIN) {
        copy(publicaddress, response.publicaddress.addr);
        natpmpstate = Ssendmap;
      }
      break;
    case Ssendmap:
      if(sendnewportmappingrequest(&natpmp, protocol, privateport, publicport, lifetime)<0);
        natpmpstate = Serror;
      else
        natpmpstate = Srecvmap;
      break;
    case Srecvmap:
      r = readnatpmpresponseorretry(&natpmp, &response);
      if(r<0 && r!=NATPMP_TRYAGAIN)
        natpmpstate = Serror;
      else if(r!=NATPMP_TRYAGAIN) {
        copy(publicport, response.newportmapping.mappedpublicport);
        copy(privateport, response.newportmapping.privateport);
        copy(mappinglifetime, response.newportmapping.lifetime);
        natpmpclose(&natpmp);
        natpmpstate = Sdone;
      }
      break;
    }
    [...]
  }
  [...]
}

Thomas Bernard

To contact me, use the MiniUPnP forum or use email : miniupnp _AT_ free _DOT_ fr

Search on this site and related sites

Custom Search

Valid XHTML 1.0 Transitional Valid CSS! freshmeat.net