src/hostlist/Makefile
src/monkey/Makefile
src/nat/Makefile
-src/nat/libnatpmp/Makefile
-src/nat/miniupnp/Makefile
src/peerinfo/Makefile
src/peerinfo-tool/Makefile
src/statistics/Makefile
/*
This file is part of GNUnet.
- (C) 2007, 2008, 2009 Christian Grothoff (and other contributing authors)
+ (C) 2007, 2008, 2009, 2010 Christian Grothoff (and other contributing authors)
GNUnet is free software; you can redistribute it and/or modify
it under the terms of the GNU General Public License as published
*/
#ifndef GNUNET_NAT_LIB_H
-#define GNUNET_NAT_LIB_H 1
+#define GNUNET_NAT_LIB_H
-#include "platform.h"
#include "gnunet_util_lib.h"
-#include "upnp.h"
-#include "natpmp.h"
-
-#include <inttypes.h>
-
-/**
- * Used to communicate with the UPnP and NAT-PMP plugins
- * FIXME: move to src/nat/common.h
- */
-enum GNUNET_NAT_port_forwarding
- {
- GNUNET_NAT_PORT_ERROR,
- GNUNET_NAT_PORT_UNMAPPED,
- GNUNET_NAT_PORT_UNMAPPING,
- GNUNET_NAT_PORT_MAPPING,
- GNUNET_NAT_PORT_MAPPED
- };
-
/**
* Signature of the callback passed to GNUNET_NAT_register.
* @param addr either the previous or the new public IP address
* @param addrlen actual lenght of the address
*/
-typedef void (*GNUNET_NAT_AddressCallback) (void *cls, int add_remove,
+typedef void (*GNUNET_NAT_AddressCallback) (void *cls,
+ int add_remove,
const struct sockaddr * addr,
socklen_t addrlen);
+
/**
* Handle for active NAT registrations.
*/
* @param callback_cls closure for callback
* @return NULL on error, otherwise handle that can be used to unregister
*/
-struct GNUNET_NAT_Handle *GNUNET_NAT_register (struct GNUNET_SCHEDULER_Handle
- *sched,
- const struct sockaddr *addr,
- socklen_t addrlen,
- GNUNET_NAT_AddressCallback
- callback, void *callback_cls);
+struct GNUNET_NAT_Handle *
+GNUNET_NAT_register (struct GNUNET_SCHEDULER_Handle *sched,
+ const struct sockaddr *addr,
+ socklen_t addrlen,
+ GNUNET_NAT_AddressCallback callback,
+ void *callback_cls);
+
/**
* Stop port redirection and public IP address detection for the given handle.
*/
void GNUNET_NAT_unregister (struct GNUNET_NAT_Handle *h);
-/**
- * Compare the sin(6)_addr fields of AF_INET or AF_INET(6) sockaddr.
- * FIXME: move to src/nat/common.h or so.
- *
- * @param a first sockaddr
- * @param b second sockaddr
- * @return 0 if addresses are equal, non-null value otherwise
- */
-int GNUNET_NAT_cmp_addr (const struct sockaddr *a,
- const struct sockaddr *b);
-
-
#endif
/* end of gnunet_nat_lib.h */
-SUBDIRS = miniupnp libnatpmp
+SUBDIRS = .
INCLUDES = -I$(top_srcdir)/src/include
if !MINGW
+if HAVE_EXPERIMENTAL
lib_LTLIBRARIES = libgnunetnat.la
+endif
libgnunetnat_la_SOURCES = \
upnp.c upnp.h \
libgnunetnat_la_LIBADD = \
$(top_builddir)/src/util/libgnunetutil.la \
- $(top_builddir)/src/nat/miniupnp/libminiupnp.la \
- $(top_builddir)/src/nat/libnatpmp/libnatpmp.la \
- $(GN_LIBINTL) @EXT_LIBS@
+ $(GN_LIBINTL) @EXT_LIBS@
libgnunetnat_la_LDFLAGS = \
$(GN_LIB_LDFLAGS) $(WINFLAGS) \
-version-info 0:0:0
+if HAVE_EXPERIMENTAL
check_PROGRAMS = \
test-nat
+endif
if !DISABLE_TEST_RUN
TESTS = $(check_PROGRAMS)
$(top_builddir)/src/nat/libgnunetnat.la \
$(top_builddir)/src/util/libgnunetutil.la
-endif
\ No newline at end of file
+endif
+++ /dev/null
-noinst_LTLIBRARIES = libnatpmp.la
-
-AM_CPPFLAGS = -DENABLE_STRNATPMPERR
-
-libnatpmp_la_SOURCES = \
- getgateway.c \
- natpmp.c
-
-noinst_HEADERS = \
- declspec.h \
- getgateway.h \
- natpmp.h
-
-extra_DIST = \
- README \
- LICENSE
+++ /dev/null
-libnatpmp is written by Thomas Bernard.
-Its homepage is http://miniupnp.tuxfamily.org/libnatpmp.html
-This code is from the libnatpmp-20090310 snapshot
-
+++ /dev/null
-#ifndef __DECLSPEC_H__
-#define __DECLSPEC_H__
-
-#if defined(WIN32) && !defined(STATICLIB)
-#ifdef NATPMP_EXPORTS
-#define LIBSPEC __declspec(dllexport)
-#else
-#define LIBSPEC __declspec(dllimport)
-#endif
-#else
-#define LIBSPEC
-#endif
-
-#endif
+++ /dev/null
-/* $Id: getgateway.c,v 1.13 2009/03/10 10:15:31 nanard Exp $ */
-/* libnatpmp
- * Copyright (c) 2007-2008, Thomas BERNARD <miniupnp@free.fr>
- *
- * Permission to use, copy, modify, and/or distribute this software for any
- * purpose with or without fee is hereby granted, provided that the above
- * copyright notice and this permission notice appear in all copies.
- *
- * THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES
- * WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF
- * MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR
- * ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES
- * WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN
- * ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF
- * OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE. */
-#include <stdio.h>
-#include <ctype.h>
-#include <string.h>
-#ifndef WIN32
-#include <netinet/in.h>
-#endif
-#include <sys/param.h>
-/* There is no portable method to get the default route gateway.
- * So below are three differents functions implementing this.
- * Parsing /proc/net/route is for linux.
- * sysctl is the way to access such informations on BSD systems.
- * Many systems should provide route information through raw PF_ROUTE
- * sockets. */
-#ifdef __linux__
-#define USE_PROC_NET_ROUTE
-#undef USE_SOCKET_ROUTE
-#undef USE_SYSCTL_NET_ROUTE
-#endif
-
-#ifdef BSD
-#undef USE_PROC_NET_ROUTE
-#define USE_SOCKET_ROUTE
-#undef USE_SYSCTL_NET_ROUTE
-#endif
-
-#ifdef __APPLE__
-#undef USE_PROC_NET_ROUTE
-#undef USE_SOCKET_ROUTE
-#define USE_SYSCTL_NET_ROUTE
-#endif
-
-#if (defined(sun) && defined(__SVR4))
-#undef USE_PROC_NET_ROUTE
-#define USE_SOCKET_ROUTE
-#undef USE_SYSCTL_NET_ROUTE
-#endif
-
-#ifdef WIN32
-#undef USE_PROC_NET_ROUTE
-#undef USE_SOCKET_ROUTE
-#undef USE_SYSCTL_NET_ROUTE
-#define USE_WIN32_CODE
-#endif
-
-#ifdef USE_PROC_NET_ROUTE
-#include <arpa/inet.h>
-#endif
-#ifdef USE_SYSCTL_NET_ROUTE
-#include <stdlib.h>
-#include <sys/sysctl.h>
-#include <sys/socket.h>
-#include <net/route.h>
-#endif
-#ifdef USE_SOCKET_ROUTE
-#include <unistd.h>
-#include <string.h>
-#include <sys/socket.h>
-#include <net/if.h>
-#include <net/route.h>
-#endif
-#ifdef WIN32
-#include <unknwn.h>
-#include <winreg.h>
-#define MAX_KEY_LENGTH 255
-#define MAX_VALUE_LENGTH 16383
-#endif
-#include "getgateway.h"
-
-#ifndef WIN32
-#define SUCCESS (0)
-#define FAILED (-1)
-#endif
-
-#ifdef USE_PROC_NET_ROUTE
-int
-getdefaultgateway (int *af, uint8_t addr[16])
-{
- unsigned int tmp;
- uint8_t d[16];
- char buf[256];
- int line = 0;
- FILE *f;
- char *p;
- int i;
- f = fopen ("/proc/net/route", "r");
- if (!f)
- return FAILED;
- while (fgets (buf, sizeof (buf), f))
- {
- if (line > 0)
- {
- p = buf;
- while (*p && !isspace ( (unsigned char) *p))
- p++;
- while (*p && isspace ( (unsigned char) *p))
- p++;
- for (i = 0; i < 16; i++)
- {
- if (sscanf (p, "%2X", &tmp) < 1)
- d[i] = tmp;
- else
- break;
- }
-
- if (i == 8) /* IPv4 address on 8 hex chars */
- {
- /* Move the 32 bits address to the end of the array */
- for (i = 4; i < 16; i++)
- d[i] = 0;
-
- for (i = 0; i < 4; i++)
- {
- d[i+12] = d[i];
- d[i] = 0;
- }
- memcpy (addr, d, 16 * sizeof (uint8_t));
- *af = AF_INET;
- fclose (f);
- return SUCCESS;
- }
- else if (i == 16) /* IPv6 address on 16 hex chars,
- * or IPv4 address padded with 0 */
- {
- memcpy (addr, d, 16 * sizeof (uint8_t));
- /* Check at what byte the actual address starts */
- for (i = 0; i <= 12; i++)
- if (addr[i]) break;
-
- if (i == 12)
- {
- *af = AF_INET;
- fclose (f);
- return SUCCESS;
- }
- else if (i == 0)
- {
- *af = AF_INET6;
- fclose (f);
- return SUCCESS;
- }
- }
- }
- line++;
- }
- /* default route not found ! */
- if (f)
- fclose (f);
- return FAILED;
-}
-#endif /* #ifdef USE_PROC_NET_ROUTE */
-
-
-#ifdef USE_SYSCTL_NET_ROUTE
-
-#define ROUNDUP(a) \
- ((a) > 0 ? (1 + (((a) - 1) | (sizeof(long) - 1))) : sizeof(long))
-
-int
-getdefaultgateway (int *af, uint8_t addr[16])
-{
-#if 0
- /* net.route.0.inet.dump.0.0 ? */
- int mib[] = { CTL_NET, PF_ROUTE, 0, AF_INET,
- NET_RT_DUMP, 0, 0 /*tableid */
- };
-#endif
- /* net.route.0.inet.flags.gateway */
- int mib[] = { CTL_NET, PF_ROUTE, 0, AF_INET,
- NET_RT_FLAGS, RTF_GATEWAY
- };
- size_t l;
- char *buf, *p;
- struct rt_msghdr *rt;
- struct sockaddr *sa;
- struct sockaddr *sa_tab[RTAX_MAX];
- int i;
- int r = FAILED;
- if (sysctl (mib, sizeof (mib) / sizeof (int), 0, &l, 0, 0) < 0)
- {
- return FAILED;
- }
- if (l > 0)
- {
- buf = malloc (l);
- if (sysctl (mib, sizeof (mib) / sizeof (int), buf, &l, 0, 0) < 0)
- {
- free (buf);
- return FAILED;
- }
- for (p = buf; p < buf + l; p += rt->rtm_msglen)
- {
- rt = (struct rt_msghdr *) p;
- sa = (struct sockaddr *) (rt + 1);
- for (i = 0; i < RTAX_MAX; i++)
- {
- if (rt->rtm_addrs & (1 << i))
- {
- sa_tab[i] = sa;
- sa =
- (struct sockaddr *) ((char *) sa + ROUNDUP (sa->sa_len));
- }
- else
- {
- sa_tab[i] = NULL;
- }
- }
- if (((rt->rtm_addrs & (RTA_DST | RTA_GATEWAY)) ==
- (RTA_DST | RTA_GATEWAY))
- && sa_tab[RTAX_DST]->sa_family == AF_INET
- && sa_tab[RTAX_GATEWAY]->sa_family == AF_INET)
- {
- if (((struct sockaddr_in *) sa_tab[RTAX_DST])->sin_addr.
- s_addr == 0)
- {
- *addr =
- ((struct sockaddr_in *) (sa_tab[RTAX_GATEWAY]))->sin_addr.
- s_addr;
- *af = AF_INET;
- r = SUCCESS;
- }
- }
- else if (((rt->rtm_addrs & (RTA_DST | RTA_GATEWAY)) ==
- (RTA_DST | RTA_GATEWAY))
- && sa_tab[RTAX_DST]->sa_family == AF_INET6
- && sa_tab[RTAX_GATEWAY]->sa_family == AF_INET6)
- {
- if (IN6_IS_ADDR_UNSPECIFIED (&(((struct sockaddr_in6 *)
- sa_tab[RTAX_DST])->sin6_addr)))
- {
- *(struct in6_addr *)addr =
- ((struct sockaddr_in6 *) (sa_tab[RTAX_GATEWAY]))->sin6_addr;
- *af = AF_INET6;
- r = SUCCESS;
- }
- }
- }
- free (buf);
- }
- return r;
-}
-#endif /* #ifdef USE_SYSCTL_NET_ROUTE */
-
-
-#ifdef USE_SOCKET_ROUTE
-/* Thanks to Darren Kenny for this code */
-#define NEXTADDR(w, u) \
- if (rtm_addrs & (w)) {\
- l = sizeof(struct sockaddr); memmove(cp, &(u), l); cp += l;\
- }
-
-#define rtm m_rtmsg.m_rtm
-
-struct
-{
- struct rt_msghdr m_rtm;
- char m_space[512];
-} m_rtmsg;
-
-int
-getdefaultgateway (int *af, uint8_t addr[16])
-{
- int s, seq, l, rtm_addrs, i;
- pid_t pid;
- struct sockaddr so_dst, so_mask;
- char *cp = m_rtmsg.m_space;
- struct sockaddr *gate = NULL, *sa;
- struct rt_msghdr *msg_hdr;
-
- pid = getpid ();
- seq = 0;
- rtm_addrs = RTA_DST | RTA_NETMASK;
-
- memset (&so_dst, 0, sizeof (so_dst));
- memset (&so_mask, 0, sizeof (so_mask));
- memset (&rtm, 0, sizeof (struct rt_msghdr));
-
- rtm.rtm_type = RTM_GET;
- rtm.rtm_flags = RTF_UP | RTF_GATEWAY;
- rtm.rtm_version = RTM_VERSION;
- rtm.rtm_seq = ++seq;
- rtm.rtm_addrs = rtm_addrs;
-
- so_dst.sa_family = AF_INET;
- so_mask.sa_family = AF_INET;
-
- NEXTADDR (RTA_DST, so_dst);
- NEXTADDR (RTA_NETMASK, so_mask);
-
- rtm.rtm_msglen = l = cp - (char *) &m_rtmsg;
-
- s = socket (PF_ROUTE, SOCK_RAW, 0);
-
- if (write (s, (char *) &m_rtmsg, l) < 0)
- {
- close (s);
- return FAILED;
- }
-
- do
- {
- l = read (s, (char *) &m_rtmsg, sizeof (m_rtmsg));
- }
- while (l > 0 && (rtm.rtm_seq != seq || rtm.rtm_pid != pid));
-
- close (s);
-
- msg_hdr = &rtm;
-
- cp = ((char *) (msg_hdr + 1));
- if (msg_hdr->rtm_addrs)
- {
- for (i = 1; i; i <<= 1)
- if (i & msg_hdr->rtm_addrs)
- {
- sa = (struct sockaddr *) cp;
- if (i == RTA_GATEWAY)
- gate = sa;
-
- cp += sizeof (struct sockaddr);
- }
- }
- else
- {
- return FAILED;
- }
-
-
- if (gate != NULL && gate->sa_family == AF_INET)
- {
- *addr = ((struct sockaddr_in *) gate)->sin_addr.s_addr;
- *af = AF_INET;
- return SUCCESS;
- }
- else if (gate != NULL && gate->sa_family == AF_INET6)
- {
- memcpy (addr, ((struct sockaddr_in6 *) gate)->sin6_addr.s6_addr, 16 * sizeof (uint8_t));
- *af = AF_INET6;
- return SUCCESS;
- }
- else
- {
- return FAILED;
- }
-}
-#endif /* #ifdef USE_SOCKET_ROUTE */
-
-#ifdef USE_WIN32_CODE
-int
-getdefaultgateway (int *af, uint8_t addr[16])
-{
- HKEY networkCardsKey;
- HKEY networkCardKey;
- HKEY interfacesKey;
- HKEY interfaceKey;
- DWORD i = 0;
- DWORD numSubKeys = 0;
- TCHAR keyName[MAX_KEY_LENGTH];
- DWORD keyNameLength = MAX_KEY_LENGTH;
- TCHAR keyValue[MAX_VALUE_LENGTH];
- DWORD keyValueLength = MAX_VALUE_LENGTH;
- DWORD keyValueType = REG_SZ;
- TCHAR gatewayValue[MAX_VALUE_LENGTH];
- DWORD gatewayValueLength = MAX_VALUE_LENGTH;
- DWORD gatewayValueType = REG_MULTI_SZ;
- int done = 0;
-
- char networkCardsPath[] =
- "SOFTWARE\\Microsoft\\Windows NT\\CurrentVersion\\NetworkCards";
- char interfacesPath[] =
- "SYSTEM\\CurrentControlSet\\Services\\Tcpip\\Parameters\\Interfaces";
-
- // The windows registry lists its primary network devices in the following location:
- // HKEY_LOCAL_MACHINE\SOFTWARE\Microsoft\Windows NT\CurrentVersion\NetworkCards
- //
- // Each network device has its own subfolder, named with an index, with various properties:
- // -NetworkCards
- // -5
- // -Description = Broadcom 802.11n Network Adapter
- // -ServiceName = {E35A72F8-5065-4097-8DFE-C7790774EE4D}
- // -8
- // -Description = Marvell Yukon 88E8058 PCI-E Gigabit Ethernet Controller
- // -ServiceName = {86226414-5545-4335-A9D1-5BD7120119AD}
- //
- // The above service name is the name of a subfolder within:
- // HKEY_LOCAL_MACHINE\SYSTEM\CurrentControlSet\Services\Tcpip\Parameters\Interfaces
- //
- // There may be more subfolders in this interfaces path than listed in the network cards path above:
- // -Interfaces
- // -{3a539854-6a70-11db-887c-806e6f6e6963}
- // -DhcpIPAddress = 0.0.0.0
- // -[more]
- // -{E35A72F8-5065-4097-8DFE-C7790774EE4D}
- // -DhcpIPAddress = 10.0.1.4
- // -DhcpDefaultGateway = 10.0.1.1
- // -[more]
- // -{86226414-5545-4335-A9D1-5BD7120119AD}
- // -DhcpIpAddress = 10.0.1.5
- // -DhcpDefaultGateay = 10.0.1.1
- // -[more]
- //
- // In order to extract this information, we enumerate each network card, and extract the ServiceName value.
- // This is then used to open the interface subfolder, and attempt to extract a DhcpDefaultGateway value.
- // Once one is found, we're done.
- //
- // It may be possible to simply enumerate the interface folders until we find one with a DhcpDefaultGateway value.
- // However, the technique used is the technique most cited on the web, and we assume it to be more correct.
-
- if (ERROR_SUCCESS != RegOpenKeyEx (HKEY_LOCAL_MACHINE, // Open registry key or predifined key
- networkCardsPath, // Name of registry subkey to open
- 0, // Reserved - must be zero
- KEY_READ, // Mask - desired access rights
- &networkCardsKey)) // Pointer to output key
- {
- // Unable to open network cards keys
- return -1;
- }
-
- if (ERROR_SUCCESS != RegOpenKeyEx (HKEY_LOCAL_MACHINE, // Open registry key or predefined key
- interfacesPath, // Name of registry subkey to open
- 0, // Reserved - must be zero
- KEY_READ, // Mask - desired access rights
- &interfacesKey)) // Pointer to output key
- {
- // Unable to open interfaces key
- RegCloseKey (networkCardsKey);
- return -1;
- }
-
- // Figure out how many subfolders are within the NetworkCards folder
- RegQueryInfoKey (networkCardsKey, NULL, NULL, NULL, &numSubKeys, NULL, NULL,
- NULL, NULL, NULL, NULL, NULL);
-
- //printf( "Number of subkeys: %u\n", (unsigned int)numSubKeys);
-
- // Enumrate through each subfolder within the NetworkCards folder
- for (i = 0; i < numSubKeys && !done; i++)
- {
- keyNameLength = MAX_KEY_LENGTH;
- if (ERROR_SUCCESS == RegEnumKeyEx (networkCardsKey, // Open registry key
- i, // Index of subkey to retrieve
- keyName, // Buffer that receives the name of the subkey
- &keyNameLength, // Variable that receives the size of the above buffer
- NULL, // Reserved - must be NULL
- NULL, // Buffer that receives the class string
- NULL, // Variable that receives the size of the above buffer
- NULL)) // Variable that receives the last write time of subkey
- {
- if (RegOpenKeyEx
- (networkCardsKey, keyName, 0, KEY_READ,
- &networkCardKey) == ERROR_SUCCESS)
- {
- keyValueLength = MAX_VALUE_LENGTH;
- if (ERROR_SUCCESS == RegQueryValueEx (networkCardKey, // Open registry key
- "ServiceName", // Name of key to query
- NULL, // Reserved - must be NULL
- &keyValueType, // Receives value type
- keyValue, // Receives value
- &keyValueLength)) // Receives value length in bytes
- {
- //printf("keyValue: %s\n", keyValue);
-
- if (RegOpenKeyEx
- (interfacesKey, keyValue, 0, KEY_READ,
- &interfaceKey) == ERROR_SUCCESS)
- {
- gatewayValueLength = MAX_VALUE_LENGTH;
- if (ERROR_SUCCESS == RegQueryValueEx (interfaceKey, // Open registry key
- "DhcpDefaultGateway", // Name of key to query
- NULL, // Reserved - must be NULL
- &gatewayValueType, // Receives value type
- gatewayValue, // Receives value
- &gatewayValueLength)) // Receives value length in bytes
- {
- // Check to make sure it's a string
- if (gatewayValueType == REG_MULTI_SZ
- || gatewayValueType == REG_SZ)
- {
- //printf("gatewayValue: %s\n", gatewayValue);
- done = 1;
- }
- }
- else if (ERROR_SUCCESS == RegQueryValueEx (interfaceKey, // Open registry key
- "DefaultGateway", // Name of key to query
- NULL, // Reserved - must be NULL
- &gatewayValueType, // Receives value type
- gatewayValue, // Receives value
- &gatewayValueLength)) // Receives value length in bytes
- {
- // Check to make sure it's a string
- if (gatewayValueType == REG_MULTI_SZ
- || gatewayValueType == REG_SZ)
- {
- //printf("gatewayValue: %s\n", gatewayValue);
- done = 1;
- }
- }
- RegCloseKey (interfaceKey);
- }
- }
- RegCloseKey (networkCardKey);
- }
- }
- }
-
- RegCloseKey (interfacesKey);
- RegCloseKey (networkCardsKey);
-
- if (done)
- {
- *addr = inet_addr (gatewayValue);
- return 0;
- }
-
- return -1;
-}
-#endif /* #ifdef USE_WIN32_CODE */
+++ /dev/null
-/* $Id: getgateway.h,v 1.3 2008/07/02 22:33:06 nanard Exp $ */
-/* libnatpmp
- * Copyright (c) 2007, Thomas BERNARD <miniupnp@free.fr>
- *
- * Permission to use, copy, modify, and/or distribute this software for any
- * purpose with or without fee is hereby granted, provided that the above
- * copyright notice and this permission notice appear in all copies.
- *
- * THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES
- * WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF
- * MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR
- * ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES
- * WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN
- * ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF
- * OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE. */
-#ifndef __GETGATEWAY_H__
-#define __GETGATEWAY_H__
-
-#ifdef WIN32
-#include <stdint.h>
-#define in_addr_t uint32_t
-#endif
-#include "declspec.h"
-
-/* getdefaultgateway() :
- * addr must point to an array of at least 16 u_int8 elements
- * return value :
- * 0 : success
- * -1 : failure */
-LIBSPEC int getdefaultgateway (int *af, uint8_t addr[16]);
-
-#endif
+++ /dev/null
-/* $Id: natpmp.c,v 1.8 2008/07/02 22:33:06 nanard Exp $ */
-/* libnatpmp
- * Copyright (c) 2007-2008, Thomas BERNARD <miniupnp@free.fr>
- * http://miniupnp.free.fr/libnatpmp.html
- *
- * Permission to use, copy, modify, and/or distribute this software for any
- * purpose with or without fee is hereby granted, provided that the above
- * copyright notice and this permission notice appear in all copies.
- *
- * THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES
- * WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF
- * MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR
- * ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES
- * WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN
- * ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF
- * OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE. */
-#include <string.h>
-#include <time.h>
-#include <sys/time.h>
-#ifdef WIN32
-#include <winsock2.h>
-#include <Ws2tcpip.h>
-#include <io.h>
-#define EWOULDBLOCK WSAEWOULDBLOCK
-#define ECONNREFUSED WSAECONNREFUSED
-#else
-#include <errno.h>
-#include <unistd.h>
-#include <fcntl.h>
-#include <sys/types.h>
-#include <sys/socket.h>
-#define closesocket close
-#endif
-#include "natpmp.h"
-#include "getgateway.h"
-
-int
-initnatpmp (natpmp_t * p)
-{
-#ifdef WIN32
- u_long ioctlArg = 1;
-#else
- int flags;
-#endif
- int domain = AF_INET;
- int gw_domain;
- struct sockaddr_in addr;
- struct sockaddr_in6 addr6;
-
- if (!p)
- return NATPMP_ERR_INVALIDARGS;
-
- if (p->addr)
- domain = (p->addr->sa_family == AF_INET) ? PF_INET : PF_INET6;
-
- memset (p, 0, sizeof (natpmp_t));
- p->s = socket (domain, SOCK_DGRAM, 0);
- if (p->s < 0)
- return NATPMP_ERR_SOCKETERROR;
- /* If addr has been set, use it, else get the default from connect() */
- if (p->addr && bind (p->s, p->addr, p->addrlen) < 0)
- return NATPMP_ERR_BINDERROR;
-#ifdef WIN32
- if (ioctlsocket (p->s, FIONBIO, &ioctlArg) == SOCKET_ERROR)
- return NATPMP_ERR_FCNTLERROR;
-#else
- if ((flags = fcntl (p->s, F_GETFL, 0)) < 0)
- return NATPMP_ERR_FCNTLERROR;
- if (fcntl (p->s, F_SETFL, flags | O_NONBLOCK) < 0)
- return NATPMP_ERR_FCNTLERROR;
-#endif
-
- if (getdefaultgateway (&gw_domain, p->gateway) < 0)
- return NATPMP_ERR_CANNOTGETGATEWAY;
-
- if (domain != gw_domain)
- return NATPMP_ERR_ADDRERROR;
-
- if (domain == AF_INET)
- {
- memset (&addr, 0, sizeof (addr));
- addr.sin_family = AF_INET;
- addr.sin_port = htons (NATPMP_PORT);
- memcpy (&addr.sin_addr.s_addr, p->gateway, 4 * sizeof (uint8_t));
-#ifdef HAVE_SOCKADDR_IN_SIN_LEN
- addr.sin_len = sizeof (addr);
-#endif
- if (connect (p->s, (struct sockaddr *) &addr, sizeof (addr)) < 0)
- return NATPMP_ERR_CONNECTERR;
- }
- else
- {
- memset (&addr6, 0, sizeof (addr6));
- addr6.sin6_family = AF_INET6;
- addr6.sin6_port = htons (NATPMP_PORT);
- memcpy (addr6.sin6_addr.s6_addr, p->gateway, 16 * sizeof (uint8_t));
-#ifdef HAVE_SOCKADDR_IN_SIN_LEN
- addr6.sin6_len = sizeof (addr6);
-#endif
- if (connect (p->s, (struct sockaddr *) &addr6, sizeof (addr6)) < 0)
- return NATPMP_ERR_CONNECTERR;
- }
-
- return 0;
-}
-
-int
-closenatpmp (natpmp_t * p)
-{
- if (!p)
- return NATPMP_ERR_INVALIDARGS;
- if (closesocket (p->s) < 0)
- return NATPMP_ERR_CLOSEERR;
- return 0;
-}
-
-static int
-sendpendingrequest (natpmp_t * p)
-{
- int r;
-/* struct sockaddr_in addr;*/
- if (!p)
- return NATPMP_ERR_INVALIDARGS;
-/* memset(&addr, 0, sizeof(addr));
- addr.sin_family = AF_INET;
- addr.sin_port = htons(NATPMP_PORT);
- addr.sin_addr.s_addr = p->gateway;
- r = (int)sendto(p->s, p->pending_request, p->pending_request_len, 0,
- (struct sockaddr *)&addr, sizeof(addr));*/
- r = (int) send (p->s, p->pending_request, p->pending_request_len, 0);
- return (r < 0) ? NATPMP_ERR_SENDERR : r;
-}
-
-static int
-sendnatpmprequest (natpmp_t * p)
-{
- int n;
- if (!p)
- return NATPMP_ERR_INVALIDARGS;
- /* TODO : check if no request is allready pending */
- p->has_pending_request = 1;
- p->try_number = 1;
- n = sendpendingrequest (p);
- gettimeofday (&p->retry_time, NULL); // check errors !
- p->retry_time.tv_usec += 250000; /* add 250ms */
- if (p->retry_time.tv_usec >= 1000000)
- {
- p->retry_time.tv_usec -= 1000000;
- p->retry_time.tv_sec++;
- }
- return n;
-}
-
-int
-getnatpmprequesttimeout (natpmp_t * p, struct timeval *timeout)
-{
- struct timeval now;
- if (!p || !timeout)
- return NATPMP_ERR_INVALIDARGS;
- if (!p->has_pending_request)
- return NATPMP_ERR_NOPENDINGREQ;
- if (gettimeofday (&now, NULL) < 0)
- return NATPMP_ERR_GETTIMEOFDAYERR;
- timeout->tv_sec = p->retry_time.tv_sec - now.tv_sec;
- timeout->tv_usec = p->retry_time.tv_usec - now.tv_usec;
- if (timeout->tv_usec < 0)
- {
- timeout->tv_usec += 1000000;
- timeout->tv_sec--;
- }
- return 0;
-}
-
-int
-sendpublicaddressrequest (natpmp_t * p)
-{
- if (!p)
- return NATPMP_ERR_INVALIDARGS;
- //static const unsigned char request[] = { 0, 0 };
- p->pending_request[0] = 0;
- p->pending_request[1] = 0;
- p->pending_request_len = 2;
- // TODO: return 0 instead of sizeof(request) ??
- return sendnatpmprequest (p);
-}
-
-int
-sendnewportmappingrequest (natpmp_t * p, int protocol,
- uint16_t privateport, uint16_t publicport,
- uint32_t lifetime)
-{
- if (!p
- || (protocol != NATPMP_PROTOCOL_TCP && protocol != NATPMP_PROTOCOL_UDP))
- return NATPMP_ERR_INVALIDARGS;
- p->pending_request[0] = 0;
- p->pending_request[1] = protocol;
- p->pending_request[2] = 0;
- p->pending_request[3] = 0;
- *((uint16_t *) (p->pending_request + 4)) = htons (privateport);
- *((uint16_t *) (p->pending_request + 6)) = htons (publicport);
- *((uint32_t *) (p->pending_request + 8)) = htonl (lifetime);
- p->pending_request_len = 12;
- return sendnatpmprequest (p);
-}
-
-static int
-readnatpmpresponse (natpmp_t * p, natpmpresp_t * response)
-{
- unsigned char buf[16];
- struct sockaddr_storage addr;
- socklen_t addrlen = sizeof (addr);
- int n;
- if (!p)
- return NATPMP_ERR_INVALIDARGS;
- n = recvfrom (p->s, buf, sizeof (buf), 0,
- (struct sockaddr *) &addr, &addrlen);
- if (n < 0)
- switch (errno)
- {
- /*case EAGAIN: */
- case EWOULDBLOCK:
- n = NATPMP_TRYAGAIN;
- break;
- case ECONNREFUSED:
- n = NATPMP_ERR_NOGATEWAYSUPPORT;
- break;
- default:
- n = NATPMP_ERR_RECVFROM;
- }
- /* check that addr is correct (= gateway) */
- else if (addr.ss_family == AF_INET && memcmp (&((struct sockaddr_in *) &addr)->sin_addr.s_addr, p->gateway, 4 * sizeof (uint8_t)) == 0)
- n = NATPMP_ERR_WRONGPACKETSOURCE;
- else if (addr.ss_family == AF_INET6 && memcmp (((struct sockaddr_in6 *) &addr)->sin6_addr.s6_addr, p->gateway, 16 * sizeof (uint8_t)) == 0)
- n = NATPMP_ERR_WRONGPACKETSOURCE;
- else
- {
- response->resultcode = ntohs (*((uint16_t *) (buf + 2)));
- response->epoch = ntohl (*((uint32_t *) (buf + 4)));
- if (buf[0] != 0)
- n = NATPMP_ERR_UNSUPPORTEDVERSION;
- else if (buf[1] < 128 || buf[1] > 130)
- n = NATPMP_ERR_UNSUPPORTEDOPCODE;
- else if (response->resultcode != 0)
- {
- switch (response->resultcode)
- {
- case 1:
- n = NATPMP_ERR_UNSUPPORTEDVERSION;
- break;
- case 2:
- n = NATPMP_ERR_NOTAUTHORIZED;
- break;
- case 3:
- n = NATPMP_ERR_NETWORKFAILURE;
- break;
- case 4:
- n = NATPMP_ERR_OUTOFRESOURCES;
- break;
- case 5:
- n = NATPMP_ERR_UNSUPPORTEDOPCODE;
- break;
- default:
- n = NATPMP_ERR_UNDEFINEDERROR;
- }
- }
- else
- {
- response->type = buf[1] & 0x7f;
- if (buf[1] == 128)
- {
- response->pnu.publicaddress.family = AF_INET;
- memset (&response->pnu.publicaddress.addr6.s6_addr, 0, sizeof (struct in6_addr));
- response->pnu.publicaddress.addr.s_addr =
- *((uint32_t *) (buf + 8));
- /* FIXME: support IPv6 address */
- }
- else
- {
- response->pnu.newportmapping.privateport =
- ntohs (*((uint16_t *) (buf + 8)));
- response->pnu.newportmapping.mappedpublicport =
- ntohs (*((uint16_t *) (buf + 10)));
- response->pnu.newportmapping.lifetime =
- ntohl (*((uint32_t *) (buf + 12)));
- }
- n = 0;
- }
- }
- return n;
-}
-
-int
-readnatpmpresponseorretry (natpmp_t * p, natpmpresp_t * response)
-{
- int n;
- if (!p || !response)
- return NATPMP_ERR_INVALIDARGS;
- if (!p->has_pending_request)
- return NATPMP_ERR_NOPENDINGREQ;
- n = readnatpmpresponse (p, response);
- if (n < 0)
- {
- if (n == NATPMP_TRYAGAIN)
- {
- struct timeval now;
- gettimeofday (&now, NULL); // check errors !
- if (timercmp (&now, &p->retry_time, >=))
- {
- int delay, r;
- if (p->try_number >= 9)
- {
- return NATPMP_ERR_NOGATEWAYSUPPORT;
- }
- /*printf("retry! %d\n", p->try_number); */
- delay = 250 * (1 << p->try_number); // ms
- /*for(i=0; i<p->try_number; i++)
- delay += delay; */
- p->retry_time.tv_sec += (delay / 1000);
- p->retry_time.tv_usec += (delay % 1000) * 1000;
- if (p->retry_time.tv_usec >= 1000000)
- {
- p->retry_time.tv_usec -= 1000000;
- p->retry_time.tv_sec++;
- }
- p->try_number++;
- r = sendpendingrequest (p);
- if (r < 0)
- return r;
- }
- }
- }
- else
- {
- p->has_pending_request = 0;
- }
- return n;
-}
-
-#ifdef ENABLE_STRNATPMPERR
-const char *
-strnatpmperr (int r)
-{
- const char *s;
- switch (r)
- {
- case NATPMP_ERR_INVALIDARGS:
- s = "invalid arguments";
- break;
- case NATPMP_ERR_SOCKETERROR:
- s = "socket() failed";
- break;
- case NATPMP_ERR_CANNOTGETGATEWAY:
- s = "cannot get default gateway ip address";
- break;
- case NATPMP_ERR_CLOSEERR:
-#ifdef WIN32
- s = "closesocket() failed";
-#else
- s = "close() failed";
-#endif
- break;
- case NATPMP_ERR_RECVFROM:
- s = "recvfrom() failed";
- break;
- case NATPMP_ERR_NOPENDINGREQ:
- s = "no pending request";
- break;
- case NATPMP_ERR_NOGATEWAYSUPPORT:
- s = "the gateway does not support nat-pmp";
- break;
- case NATPMP_ERR_CONNECTERR:
- s = "connect() failed";
- break;
- case NATPMP_ERR_WRONGPACKETSOURCE:
- s = "packet not received from the default gateway";
- break;
- case NATPMP_ERR_SENDERR:
- s = "send() failed";
- break;
- case NATPMP_ERR_FCNTLERROR:
- s = "fcntl() failed";
- break;
- case NATPMP_ERR_GETTIMEOFDAYERR:
- s = "gettimeofday() failed";
- break;
- case NATPMP_ERR_UNSUPPORTEDVERSION:
- s = "unsupported nat-pmp version error from server";
- break;
- case NATPMP_ERR_UNSUPPORTEDOPCODE:
- s = "unsupported nat-pmp opcode error from server";
- break;
- case NATPMP_ERR_UNDEFINEDERROR:
- s = "undefined nat-pmp server error";
- break;
- case NATPMP_ERR_NOTAUTHORIZED:
- s = "not authorized";
- break;
- case NATPMP_ERR_NETWORKFAILURE:
- s = "network failure";
- break;
- case NATPMP_ERR_OUTOFRESOURCES:
- s = "nat-pmp server out of resources";
- break;
- default:
- s = "Unknown libnatpmp error";
- }
- return s;
-}
-#endif
+++ /dev/null
-/* $Id: natpmp.h,v 1.11 2009/02/27 22:38:05 nanard Exp $ */
-/* libnatpmp
- * Copyright (c) 2007-2008, Thomas BERNARD <miniupnp@free.fr>
- * http://miniupnp.free.fr/libnatpmp.html
- *
- * Permission to use, copy, modify, and/or distribute this software for any
- * purpose with or without fee is hereby granted, provided that the above
- * copyright notice and this permission notice appear in all copies.
- *
- * THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES
- * WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF
- * MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR
- * ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES
- * WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN
- * ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF
- * OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE. */
-#ifndef __NATPMP_H__
-#define __NATPMP_H__
-
-/* NAT-PMP Port as defined by the NAT-PMP draft */
-#define NATPMP_PORT (5351)
-
-#include <stdint.h>
-#include <time.h>
-#include <sys/time.h>
-#ifdef WIN32
-#include <winsock2.h>
-#include <stdint.h>
-#define in_addr_t uint32_t
-#include "declspec.h"
-#else
-#define LIBSPEC
-#include <netinet/in.h>
-#include <sys/socket.h>
-#endif
-
-typedef struct
-{
- int s; /* socket */
- struct sockaddr *addr;
- socklen_t addrlen;
- uint8_t gateway[16]; /* default gateway (IPv4 or IPv6) */
- int has_pending_request;
- unsigned char pending_request[12];
- int pending_request_len;
- int try_number;
- struct timeval retry_time;
-} natpmp_t;
-
-typedef struct
-{
- uint16_t type; /* NATPMP_RESPTYPE_* */
- uint16_t resultcode; /* NAT-PMP response code */
- uint32_t epoch; /* Seconds since start of epoch */
- union
- {
- struct
- {
- int family;
- struct in_addr addr;
- struct in6_addr addr6;
- } publicaddress;
- struct
- {
- uint16_t privateport;
- uint16_t mappedpublicport;
- uint32_t lifetime;
- } newportmapping;
- } pnu;
-} natpmpresp_t;
-
-/* possible values for type field of natpmpresp_t */
-#define NATPMP_RESPTYPE_PUBLICADDRESS (0)
-#define NATPMP_RESPTYPE_UDPPORTMAPPING (1)
-#define NATPMP_RESPTYPE_TCPPORTMAPPING (2)
-
-/* Values to pass to sendnewportmappingrequest() */
-#define NATPMP_PROTOCOL_UDP (1)
-#define NATPMP_PROTOCOL_TCP (2)
-
-/* return values */
-/* NATPMP_ERR_INVALIDARGS : invalid arguments passed to the function */
-#define NATPMP_ERR_INVALIDARGS (-1)
-/* NATPMP_ERR_SOCKETERROR : socket() failed. check errno for details */
-#define NATPMP_ERR_SOCKETERROR (-2)
-/* NATPMP_ERR_CANNOTGETGATEWAY : can't get default gateway IP */
-#define NATPMP_ERR_CANNOTGETGATEWAY (-3)
-/* NATPMP_ERR_CLOSEERR : close() failed. check errno for details */
-#define NATPMP_ERR_CLOSEERR (-4)
-/* NATPMP_ERR_RECVFROM : recvfrom() failed. check errno for details */
-#define NATPMP_ERR_RECVFROM (-5)
-/* NATPMP_ERR_NOPENDINGREQ : readnatpmpresponseorretry() called while
- * no NAT-PMP request was pending */
-#define NATPMP_ERR_NOPENDINGREQ (-6)
-/* NATPMP_ERR_NOGATEWAYSUPPORT : the gateway does not support NAT-PMP */
-#define NATPMP_ERR_NOGATEWAYSUPPORT (-7)
-/* NATPMP_ERR_CONNECTERR : connect() failed. check errno for details */
-#define NATPMP_ERR_CONNECTERR (-8)
-/* NATPMP_ERR_WRONGPACKETSOURCE : packet not received from the network gateway */
-#define NATPMP_ERR_WRONGPACKETSOURCE (-9)
-/* NATPMP_ERR_SENDERR : send() failed. check errno for details */
-#define NATPMP_ERR_SENDERR (-10)
-/* NATPMP_ERR_FCNTLERROR : fcntl() failed. check errno for details */
-#define NATPMP_ERR_FCNTLERROR (-11)
-/* NATPMP_ERR_GETTIMEOFDAYERR : gettimeofday() failed. check errno for details */
-#define NATPMP_ERR_GETTIMEOFDAYERR (-12)
-/* NATPMP_ERR_BINDERROR : bind() failed. check errno for details */
-#define NATPMP_ERR_BINDERROR (-13)
-/* NATPMP_ERR_ADDRERROR : gateway does not use the same inet protocol as the passed address */
-#define NATPMP_ERR_ADDRERROR (-14)
-
-/* */
-#define NATPMP_ERR_UNSUPPORTEDVERSION (-15)
-#define NATPMP_ERR_UNSUPPORTEDOPCODE (-16)
-
-/* Errors from the server : */
-#define NATPMP_ERR_UNDEFINEDERROR (-49)
-#define NATPMP_ERR_NOTAUTHORIZED (-51)
-#define NATPMP_ERR_NETWORKFAILURE (-52)
-#define NATPMP_ERR_OUTOFRESOURCES (-53)
-
-/* NATPMP_TRYAGAIN : no data available for the moment. try again later */
-#define NATPMP_TRYAGAIN (-100)
-
-/* initnatpmp()
- * initialize a natpmp_t object
- * Return values :
- * 0 = OK
- * NATPMP_ERR_INVALIDARGS
- * NATPMP_ERR_SOCKETERROR
- * NATPMP_ERR_FCNTLERROR
- * NATPMP_ERR_CANNOTGETGATEWAY
- * NATPMP_ERR_CONNECTERR */
-LIBSPEC int initnatpmp (natpmp_t * p);
-
-/* closenatpmp()
- * close resources associated with a natpmp_t object
- * Return values :
- * 0 = OK
- * NATPMP_ERR_INVALIDARGS
- * NATPMP_ERR_CLOSEERR */
-LIBSPEC int closenatpmp (natpmp_t * p);
-
-/* sendpublicaddressrequest()
- * send a public address NAT-PMP request to the network gateway
- * Return values :
- * 2 = OK (size of the request)
- * NATPMP_ERR_INVALIDARGS
- * NATPMP_ERR_SENDERR */
-LIBSPEC int sendpublicaddressrequest (natpmp_t * p);
-
-/* sendnewportmappingrequest()
- * send a new port mapping NAT-PMP request to the network gateway
- * Arguments :
- * protocol is either NATPMP_PROTOCOL_TCP or NATPMP_PROTOCOL_UDP,
- * lifetime is in seconds.
- * To remove a port mapping, set lifetime to zero.
- * To remove all port mappings to the host, set lifetime and both ports
- * to zero.
- * Return values :
- * 12 = OK (size of the request)
- * NATPMP_ERR_INVALIDARGS
- * NATPMP_ERR_SENDERR */
-LIBSPEC int sendnewportmappingrequest (natpmp_t * p, int protocol,
- uint16_t privateport,
- uint16_t publicport,
- uint32_t lifetime);
-
-/* getnatpmprequesttimeout()
- * fills the timeval structure with the timeout duration of the
- * currently pending NAT-PMP request.
- * Return values :
- * 0 = OK
- * NATPMP_ERR_INVALIDARGS
- * NATPMP_ERR_GETTIMEOFDAYERR
- * NATPMP_ERR_NOPENDINGREQ */
-LIBSPEC int getnatpmprequesttimeout (natpmp_t * p, struct timeval *timeout);
-
-/* readnatpmpresponseorretry()
- * fills the natpmpresp_t structure if possible
- * Return values :
- * 0 = OK
- * NATPMP_TRYAGAIN
- * NATPMP_ERR_INVALIDARGS
- * NATPMP_ERR_NOPENDINGREQ
- * NATPMP_ERR_NOGATEWAYSUPPORT
- * NATPMP_ERR_RECVFROM
- * NATPMP_ERR_WRONGPACKETSOURCE
- * NATPMP_ERR_UNSUPPORTEDVERSION
- * NATPMP_ERR_UNSUPPORTEDOPCODE
- * NATPMP_ERR_NOTAUTHORIZED
- * NATPMP_ERR_NETWORKFAILURE
- * NATPMP_ERR_OUTOFRESOURCES
- * NATPMP_ERR_UNSUPPORTEDOPCODE
- * NATPMP_ERR_UNDEFINEDERROR */
-LIBSPEC int readnatpmpresponseorretry (natpmp_t * p, natpmpresp_t * response);
-
-#ifdef ENABLE_STRNATPMPERR
-LIBSPEC const char *strnatpmperr (int t);
-#endif
-
-#endif
+++ /dev/null
-noinst_LTLIBRARIES = libminiupnp.la
-
-AM_CPPFLAGS = -DNDEBUG
-
-libminiupnp_la_SOURCES = \
- igd_desc_parse.c \
- minisoap.c \
- minissdpc.c \
- miniupnpc.c \
- miniwget.c \
- minixml.c \
- upnpcommands.c \
- upnpreplyparse.c
-
-noinst_HEADERS = \
- bsdqueue.h \
- codelength.h \
- declspec.h \
- igd_desc_parse.h \
- minisoap.h \
- minissdpc.h \
- miniupnpc.h \
- miniupnpcstrings.h \
- miniwget.h \
- minixml.h \
- upnpcommands.h \
- upnpreplyparse.h
-
-extra_DIST = \
- README \
- LICENSE
+++ /dev/null
-MiniUPnP is written by Thomas Bernard.
-Its homepage is http://miniupnp.free.fr/
-This is from miniupnpc-1.3.tar.gz
+++ /dev/null
-/* $OpenBSD: queue.h,v 1.31 2005/11/25 08:06:25 otto Exp $ */
-/* $NetBSD: queue.h,v 1.11 1996/05/16 05:17:14 mycroft Exp $ */
-
-/*
- * Copyright (c) 1991, 1993
- * The Regents of the University of California. All rights reserved.
- *
- * Redistribution and use in source and binary forms, with or without
- * modification, are permitted provided that the following conditions
- * are met:
- * 1. Redistributions of source code must retain the above copyright
- * notice, this list of conditions and the following disclaimer.
- * 2. Redistributions in binary form must reproduce the above copyright
- * notice, this list of conditions and the following disclaimer in the
- * documentation and/or other materials provided with the distribution.
- * 3. Neither the name of the University nor the names of its contributors
- * may be used to endorse or promote products derived from this software
- * without specific prior written permission.
- *
- * THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND
- * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
- * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
- * ARE DISCLAIMED. IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE
- * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
- * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
- * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
- * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
- * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
- * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
- * SUCH DAMAGE.
- *
- * @(#)queue.h 8.5 (Berkeley) 8/20/94
- */
-
-#ifndef _SYS_QUEUE_H_
-#define _SYS_QUEUE_H_
-
-/*
- * This file defines five types of data structures: singly-linked lists,
- * lists, simple queues, tail queues, and circular queues.
- *
- *
- * A singly-linked list is headed by a single forward pointer. The elements
- * are singly linked for minimum space and pointer manipulation overhead at
- * the expense of O(n) removal for arbitrary elements. New elements can be
- * added to the list after an existing element or at the head of the list.
- * Elements being removed from the head of the list should use the explicit
- * macro for this purpose for optimum efficiency. A singly-linked list may
- * only be traversed in the forward direction. Singly-linked lists are ideal
- * for applications with large datasets and few or no removals or for
- * implementing a LIFO queue.
- *
- * A list is headed by a single forward pointer (or an array of forward
- * pointers for a hash table header). The elements are doubly linked
- * so that an arbitrary element can be removed without a need to
- * traverse the list. New elements can be added to the list before
- * or after an existing element or at the head of the list. A list
- * may only be traversed in the forward direction.
- *
- * A simple queue is headed by a pair of pointers, one the head of the
- * list and the other to the tail of the list. The elements are singly
- * linked to save space, so elements can only be removed from the
- * head of the list. New elements can be added to the list before or after
- * an existing element, at the head of the list, or at the end of the
- * list. A simple queue may only be traversed in the forward direction.
- *
- * A tail queue is headed by a pair of pointers, one to the head of the
- * list and the other to the tail of the list. The elements are doubly
- * linked so that an arbitrary element can be removed without a need to
- * traverse the list. New elements can be added to the list before or
- * after an existing element, at the head of the list, or at the end of
- * the list. A tail queue may be traversed in either direction.
- *
- * A circle queue is headed by a pair of pointers, one to the head of the
- * list and the other to the tail of the list. The elements are doubly
- * linked so that an arbitrary element can be removed without a need to
- * traverse the list. New elements can be added to the list before or after
- * an existing element, at the head of the list, or at the end of the list.
- * A circle queue may be traversed in either direction, but has a more
- * complex end of list detection.
- *
- * For details on the use of these macros, see the queue(3) manual page.
- */
-
-#ifdef QUEUE_MACRO_DEBUG
-#define _Q_INVALIDATE(a) (a) = ((void *)-1)
-#else
-#define _Q_INVALIDATE(a)
-#endif
-
-/*
- * Singly-linked List definitions.
- */
-#define SLIST_HEAD(name, type) \
-struct name { \
- struct type *slh_first; /* first element */ \
-}
-
-#define SLIST_HEAD_INITIALIZER(head) \
- { NULL }
-
-#ifdef SLIST_ENTRY
-#undef SLIST_ENTRY
-#endif
-
-#define SLIST_ENTRY(type) \
-struct { \
- struct type *sle_next; /* next element */ \
-}
-
-/*
- * Singly-linked List access methods.
- */
-#define SLIST_FIRST(head) ((head)->slh_first)
-#define SLIST_END(head) NULL
-#define SLIST_EMPTY(head) (SLIST_FIRST(head) == SLIST_END(head))
-#define SLIST_NEXT(elm, field) ((elm)->field.sle_next)
-
-#define SLIST_FOREACH(var, head, field) \
- for((var) = SLIST_FIRST(head); \
- (var) != SLIST_END(head); \
- (var) = SLIST_NEXT(var, field))
-
-#define SLIST_FOREACH_PREVPTR(var, varp, head, field) \
- for ((varp) = &SLIST_FIRST((head)); \
- ((var) = *(varp)) != SLIST_END(head); \
- (varp) = &SLIST_NEXT((var), field))
-
-/*
- * Singly-linked List functions.
- */
-#define SLIST_INIT(head) { \
- SLIST_FIRST(head) = SLIST_END(head); \
-}
-
-#define SLIST_INSERT_AFTER(slistelm, elm, field) do { \
- (elm)->field.sle_next = (slistelm)->field.sle_next; \
- (slistelm)->field.sle_next = (elm); \
-} while (0)
-
-#define SLIST_INSERT_HEAD(head, elm, field) do { \
- (elm)->field.sle_next = (head)->slh_first; \
- (head)->slh_first = (elm); \
-} while (0)
-
-#define SLIST_REMOVE_NEXT(head, elm, field) do { \
- (elm)->field.sle_next = (elm)->field.sle_next->field.sle_next; \
-} while (0)
-
-#define SLIST_REMOVE_HEAD(head, field) do { \
- (head)->slh_first = (head)->slh_first->field.sle_next; \
-} while (0)
-
-#define SLIST_REMOVE(head, elm, type, field) do { \
- if ((head)->slh_first == (elm)) { \
- SLIST_REMOVE_HEAD((head), field); \
- } else { \
- struct type *curelm = (head)->slh_first; \
- \
- while (curelm->field.sle_next != (elm)) \
- curelm = curelm->field.sle_next; \
- curelm->field.sle_next = \
- curelm->field.sle_next->field.sle_next; \
- _Q_INVALIDATE((elm)->field.sle_next); \
- } \
-} while (0)
-
-/*
- * List definitions.
- */
-#define LIST_HEAD(name, type) \
-struct name { \
- struct type *lh_first; /* first element */ \
-}
-
-#define LIST_HEAD_INITIALIZER(head) \
- { NULL }
-
-#define LIST_ENTRY(type) \
-struct { \
- struct type *le_next; /* next element */ \
- struct type **le_prev; /* address of previous next element */ \
-}
-
-/*
- * List access methods
- */
-#define LIST_FIRST(head) ((head)->lh_first)
-#define LIST_END(head) NULL
-#define LIST_EMPTY(head) (LIST_FIRST(head) == LIST_END(head))
-#define LIST_NEXT(elm, field) ((elm)->field.le_next)
-
-#define LIST_FOREACH(var, head, field) \
- for((var) = LIST_FIRST(head); \
- (var)!= LIST_END(head); \
- (var) = LIST_NEXT(var, field))
-
-/*
- * List functions.
- */
-#define LIST_INIT(head) do { \
- LIST_FIRST(head) = LIST_END(head); \
-} while (0)
-
-#define LIST_INSERT_AFTER(listelm, elm, field) do { \
- if (((elm)->field.le_next = (listelm)->field.le_next) != NULL) \
- (listelm)->field.le_next->field.le_prev = \
- &(elm)->field.le_next; \
- (listelm)->field.le_next = (elm); \
- (elm)->field.le_prev = &(listelm)->field.le_next; \
-} while (0)
-
-#define LIST_INSERT_BEFORE(listelm, elm, field) do { \
- (elm)->field.le_prev = (listelm)->field.le_prev; \
- (elm)->field.le_next = (listelm); \
- *(listelm)->field.le_prev = (elm); \
- (listelm)->field.le_prev = &(elm)->field.le_next; \
-} while (0)
-
-#define LIST_INSERT_HEAD(head, elm, field) do { \
- if (((elm)->field.le_next = (head)->lh_first) != NULL) \
- (head)->lh_first->field.le_prev = &(elm)->field.le_next;\
- (head)->lh_first = (elm); \
- (elm)->field.le_prev = &(head)->lh_first; \
-} while (0)
-
-#define LIST_REMOVE(elm, field) do { \
- if ((elm)->field.le_next != NULL) \
- (elm)->field.le_next->field.le_prev = \
- (elm)->field.le_prev; \
- *(elm)->field.le_prev = (elm)->field.le_next; \
- _Q_INVALIDATE((elm)->field.le_prev); \
- _Q_INVALIDATE((elm)->field.le_next); \
-} while (0)
-
-#define LIST_REPLACE(elm, elm2, field) do { \
- if (((elm2)->field.le_next = (elm)->field.le_next) != NULL) \
- (elm2)->field.le_next->field.le_prev = \
- &(elm2)->field.le_next; \
- (elm2)->field.le_prev = (elm)->field.le_prev; \
- *(elm2)->field.le_prev = (elm2); \
- _Q_INVALIDATE((elm)->field.le_prev); \
- _Q_INVALIDATE((elm)->field.le_next); \
-} while (0)
-
-/*
- * Simple queue definitions.
- */
-#define SIMPLEQ_HEAD(name, type) \
-struct name { \
- struct type *sqh_first; /* first element */ \
- struct type **sqh_last; /* addr of last next element */ \
-}
-
-#define SIMPLEQ_HEAD_INITIALIZER(head) \
- { NULL, &(head).sqh_first }
-
-#define SIMPLEQ_ENTRY(type) \
-struct { \
- struct type *sqe_next; /* next element */ \
-}
-
-/*
- * Simple queue access methods.
- */
-#define SIMPLEQ_FIRST(head) ((head)->sqh_first)
-#define SIMPLEQ_END(head) NULL
-#define SIMPLEQ_EMPTY(head) (SIMPLEQ_FIRST(head) == SIMPLEQ_END(head))
-#define SIMPLEQ_NEXT(elm, field) ((elm)->field.sqe_next)
-
-#define SIMPLEQ_FOREACH(var, head, field) \
- for((var) = SIMPLEQ_FIRST(head); \
- (var) != SIMPLEQ_END(head); \
- (var) = SIMPLEQ_NEXT(var, field))
-
-/*
- * Simple queue functions.
- */
-#define SIMPLEQ_INIT(head) do { \
- (head)->sqh_first = NULL; \
- (head)->sqh_last = &(head)->sqh_first; \
-} while (0)
-
-#define SIMPLEQ_INSERT_HEAD(head, elm, field) do { \
- if (((elm)->field.sqe_next = (head)->sqh_first) == NULL) \
- (head)->sqh_last = &(elm)->field.sqe_next; \
- (head)->sqh_first = (elm); \
-} while (0)
-
-#define SIMPLEQ_INSERT_TAIL(head, elm, field) do { \
- (elm)->field.sqe_next = NULL; \
- *(head)->sqh_last = (elm); \
- (head)->sqh_last = &(elm)->field.sqe_next; \
-} while (0)
-
-#define SIMPLEQ_INSERT_AFTER(head, listelm, elm, field) do { \
- if (((elm)->field.sqe_next = (listelm)->field.sqe_next) == NULL)\
- (head)->sqh_last = &(elm)->field.sqe_next; \
- (listelm)->field.sqe_next = (elm); \
-} while (0)
-
-#define SIMPLEQ_REMOVE_HEAD(head, field) do { \
- if (((head)->sqh_first = (head)->sqh_first->field.sqe_next) == NULL) \
- (head)->sqh_last = &(head)->sqh_first; \
-} while (0)
-
-/*
- * Tail queue definitions.
- */
-#define TAILQ_HEAD(name, type) \
-struct name { \
- struct type *tqh_first; /* first element */ \
- struct type **tqh_last; /* addr of last next element */ \
-}
-
-#define TAILQ_HEAD_INITIALIZER(head) \
- { NULL, &(head).tqh_first }
-
-#define TAILQ_ENTRY(type) \
-struct { \
- struct type *tqe_next; /* next element */ \
- struct type **tqe_prev; /* address of previous next element */ \
-}
-
-/*
- * tail queue access methods
- */
-#define TAILQ_FIRST(head) ((head)->tqh_first)
-#define TAILQ_END(head) NULL
-#define TAILQ_NEXT(elm, field) ((elm)->field.tqe_next)
-#define TAILQ_LAST(head, headname) \
- (*(((struct headname *)((head)->tqh_last))->tqh_last))
-/* XXX */
-#define TAILQ_PREV(elm, headname, field) \
- (*(((struct headname *)((elm)->field.tqe_prev))->tqh_last))
-#define TAILQ_EMPTY(head) \
- (TAILQ_FIRST(head) == TAILQ_END(head))
-
-#define TAILQ_FOREACH(var, head, field) \
- for((var) = TAILQ_FIRST(head); \
- (var) != TAILQ_END(head); \
- (var) = TAILQ_NEXT(var, field))
-
-#define TAILQ_FOREACH_REVERSE(var, head, headname, field) \
- for((var) = TAILQ_LAST(head, headname); \
- (var) != TAILQ_END(head); \
- (var) = TAILQ_PREV(var, headname, field))
-
-/*
- * Tail queue functions.
- */
-#define TAILQ_INIT(head) do { \
- (head)->tqh_first = NULL; \
- (head)->tqh_last = &(head)->tqh_first; \
-} while (0)
-
-#define TAILQ_INSERT_HEAD(head, elm, field) do { \
- if (((elm)->field.tqe_next = (head)->tqh_first) != NULL) \
- (head)->tqh_first->field.tqe_prev = \
- &(elm)->field.tqe_next; \
- else \
- (head)->tqh_last = &(elm)->field.tqe_next; \
- (head)->tqh_first = (elm); \
- (elm)->field.tqe_prev = &(head)->tqh_first; \
-} while (0)
-
-#define TAILQ_INSERT_TAIL(head, elm, field) do { \
- (elm)->field.tqe_next = NULL; \
- (elm)->field.tqe_prev = (head)->tqh_last; \
- *(head)->tqh_last = (elm); \
- (head)->tqh_last = &(elm)->field.tqe_next; \
-} while (0)
-
-#define TAILQ_INSERT_AFTER(head, listelm, elm, field) do { \
- if (((elm)->field.tqe_next = (listelm)->field.tqe_next) != NULL)\
- (elm)->field.tqe_next->field.tqe_prev = \
- &(elm)->field.tqe_next; \
- else \
- (head)->tqh_last = &(elm)->field.tqe_next; \
- (listelm)->field.tqe_next = (elm); \
- (elm)->field.tqe_prev = &(listelm)->field.tqe_next; \
-} while (0)
-
-#define TAILQ_INSERT_BEFORE(listelm, elm, field) do { \
- (elm)->field.tqe_prev = (listelm)->field.tqe_prev; \
- (elm)->field.tqe_next = (listelm); \
- *(listelm)->field.tqe_prev = (elm); \
- (listelm)->field.tqe_prev = &(elm)->field.tqe_next; \
-} while (0)
-
-#define TAILQ_REMOVE(head, elm, field) do { \
- if (((elm)->field.tqe_next) != NULL) \
- (elm)->field.tqe_next->field.tqe_prev = \
- (elm)->field.tqe_prev; \
- else \
- (head)->tqh_last = (elm)->field.tqe_prev; \
- *(elm)->field.tqe_prev = (elm)->field.tqe_next; \
- _Q_INVALIDATE((elm)->field.tqe_prev); \
- _Q_INVALIDATE((elm)->field.tqe_next); \
-} while (0)
-
-#define TAILQ_REPLACE(head, elm, elm2, field) do { \
- if (((elm2)->field.tqe_next = (elm)->field.tqe_next) != NULL) \
- (elm2)->field.tqe_next->field.tqe_prev = \
- &(elm2)->field.tqe_next; \
- else \
- (head)->tqh_last = &(elm2)->field.tqe_next; \
- (elm2)->field.tqe_prev = (elm)->field.tqe_prev; \
- *(elm2)->field.tqe_prev = (elm2); \
- _Q_INVALIDATE((elm)->field.tqe_prev); \
- _Q_INVALIDATE((elm)->field.tqe_next); \
-} while (0)
-
-/*
- * Circular queue definitions.
- */
-#define CIRCLEQ_HEAD(name, type) \
-struct name { \
- struct type *cqh_first; /* first element */ \
- struct type *cqh_last; /* last element */ \
-}
-
-#define CIRCLEQ_HEAD_INITIALIZER(head) \
- { CIRCLEQ_END(&head), CIRCLEQ_END(&head) }
-
-#define CIRCLEQ_ENTRY(type) \
-struct { \
- struct type *cqe_next; /* next element */ \
- struct type *cqe_prev; /* previous element */ \
-}
-
-/*
- * Circular queue access methods
- */
-#define CIRCLEQ_FIRST(head) ((head)->cqh_first)
-#define CIRCLEQ_LAST(head) ((head)->cqh_last)
-#define CIRCLEQ_END(head) ((void *)(head))
-#define CIRCLEQ_NEXT(elm, field) ((elm)->field.cqe_next)
-#define CIRCLEQ_PREV(elm, field) ((elm)->field.cqe_prev)
-#define CIRCLEQ_EMPTY(head) \
- (CIRCLEQ_FIRST(head) == CIRCLEQ_END(head))
-
-#define CIRCLEQ_FOREACH(var, head, field) \
- for((var) = CIRCLEQ_FIRST(head); \
- (var) != CIRCLEQ_END(head); \
- (var) = CIRCLEQ_NEXT(var, field))
-
-#define CIRCLEQ_FOREACH_REVERSE(var, head, field) \
- for((var) = CIRCLEQ_LAST(head); \
- (var) != CIRCLEQ_END(head); \
- (var) = CIRCLEQ_PREV(var, field))
-
-/*
- * Circular queue functions.
- */
-#define CIRCLEQ_INIT(head) do { \
- (head)->cqh_first = CIRCLEQ_END(head); \
- (head)->cqh_last = CIRCLEQ_END(head); \
-} while (0)
-
-#define CIRCLEQ_INSERT_AFTER(head, listelm, elm, field) do { \
- (elm)->field.cqe_next = (listelm)->field.cqe_next; \
- (elm)->field.cqe_prev = (listelm); \
- if ((listelm)->field.cqe_next == CIRCLEQ_END(head)) \
- (head)->cqh_last = (elm); \
- else \
- (listelm)->field.cqe_next->field.cqe_prev = (elm); \
- (listelm)->field.cqe_next = (elm); \
-} while (0)
-
-#define CIRCLEQ_INSERT_BEFORE(head, listelm, elm, field) do { \
- (elm)->field.cqe_next = (listelm); \
- (elm)->field.cqe_prev = (listelm)->field.cqe_prev; \
- if ((listelm)->field.cqe_prev == CIRCLEQ_END(head)) \
- (head)->cqh_first = (elm); \
- else \
- (listelm)->field.cqe_prev->field.cqe_next = (elm); \
- (listelm)->field.cqe_prev = (elm); \
-} while (0)
-
-#define CIRCLEQ_INSERT_HEAD(head, elm, field) do { \
- (elm)->field.cqe_next = (head)->cqh_first; \
- (elm)->field.cqe_prev = CIRCLEQ_END(head); \
- if ((head)->cqh_last == CIRCLEQ_END(head)) \
- (head)->cqh_last = (elm); \
- else \
- (head)->cqh_first->field.cqe_prev = (elm); \
- (head)->cqh_first = (elm); \
-} while (0)
-
-#define CIRCLEQ_INSERT_TAIL(head, elm, field) do { \
- (elm)->field.cqe_next = CIRCLEQ_END(head); \
- (elm)->field.cqe_prev = (head)->cqh_last; \
- if ((head)->cqh_first == CIRCLEQ_END(head)) \
- (head)->cqh_first = (elm); \
- else \
- (head)->cqh_last->field.cqe_next = (elm); \
- (head)->cqh_last = (elm); \
-} while (0)
-
-#define CIRCLEQ_REMOVE(head, elm, field) do { \
- if ((elm)->field.cqe_next == CIRCLEQ_END(head)) \
- (head)->cqh_last = (elm)->field.cqe_prev; \
- else \
- (elm)->field.cqe_next->field.cqe_prev = \
- (elm)->field.cqe_prev; \
- if ((elm)->field.cqe_prev == CIRCLEQ_END(head)) \
- (head)->cqh_first = (elm)->field.cqe_next; \
- else \
- (elm)->field.cqe_prev->field.cqe_next = \
- (elm)->field.cqe_next; \
- _Q_INVALIDATE((elm)->field.cqe_prev); \
- _Q_INVALIDATE((elm)->field.cqe_next); \
-} while (0)
-
-#define CIRCLEQ_REPLACE(head, elm, elm2, field) do { \
- if (((elm2)->field.cqe_next = (elm)->field.cqe_next) == \
- CIRCLEQ_END(head)) \
- (head).cqh_last = (elm2); \
- else \
- (elm2)->field.cqe_next->field.cqe_prev = (elm2); \
- if (((elm2)->field.cqe_prev = (elm)->field.cqe_prev) == \
- CIRCLEQ_END(head)) \
- (head).cqh_first = (elm2); \
- else \
- (elm2)->field.cqe_prev->field.cqe_next = (elm2); \
- _Q_INVALIDATE((elm)->field.cqe_prev); \
- _Q_INVALIDATE((elm)->field.cqe_next); \
-} while (0)
-
-#endif /* !_SYS_QUEUE_H_ */
+++ /dev/null
-/* $Id: codelength.h,v 1.1 2008/10/06 22:04:06 nanard Exp $ */
-/* Project : miniupnp
- * Author : Thomas BERNARD
- * copyright (c) 2005-2008 Thomas Bernard
- * This software is subjet to the conditions detailed in the
- * provided LICENCE file. */
-#ifndef __CODELENGTH_H__
-#define __CODELENGTH_H__
-
-/* Encode length by using 7bit per Byte :
- * Most significant bit of each byte specifies that the
- * following byte is part of the code */
-#define DECODELENGTH(n, p) n = 0; \
- do { n = (n << 7) | (*p & 0x7f); } \
- while(*(p++)&0x80);
-
-#define CODELENGTH(n, p) if(n>=268435456) *(p++) = (n >> 28) | 0x80; \
- if(n>=2097152) *(p++) = (n >> 21) | 0x80; \
- if(n>=16384) *(p++) = (n >> 14) | 0x80; \
- if(n>=128) *(p++) = (n >> 7) | 0x80; \
- *(p++) = n & 0x7f;
-
-#endif
+++ /dev/null
-#ifndef __DECLSPEC_H__
-#define __DECLSPEC_H__
-
-#if defined(WIN32) && !defined(STATICLIB)
-#ifdef MINIUPNP_EXPORTS
-#define LIBSPEC __declspec(dllexport)
-#else
-#define LIBSPEC __declspec(dllimport)
-#endif
-#else
-#define LIBSPEC
-#endif
-
-#endif
+++ /dev/null
-/* $Id: igd_desc_parse.c,v 1.8 2008/04/23 11:51:06 nanard Exp $ */
-/* Project : miniupnp
- * http://miniupnp.free.fr/
- * Author : Thomas Bernard
- * Copyright (c) 2005-2008 Thomas Bernard
- * This software is subject to the conditions detailed in the
- * LICENCE file provided in this distribution.
- * */
-#include "igd_desc_parse.h"
-#include <stdio.h>
-#include <string.h>
-
-/* TODO : rewrite this code so it correctly handle descriptions with
- * both WANIPConnection and/or WANPPPConnection */
-
-/* Start element handler :
- * update nesting level counter and copy element name */
-void
-IGDstartelt (void *d, const char *name, int l)
-{
- struct IGDdatas *datas = (struct IGDdatas *) d;
- memcpy (datas->cureltname, name, l);
- datas->cureltname[l] = '\0';
- datas->level++;
- if ((l == 7) && !memcmp (name, "service", l))
- {
- datas->controlurl_tmp[0] = '\0';
- datas->eventsuburl_tmp[0] = '\0';
- datas->scpdurl_tmp[0] = '\0';
- datas->servicetype_tmp[0] = '\0';
- }
-}
-
-/* End element handler :
- * update nesting level counter and update parser state if
- * service element is parsed */
-void
-IGDendelt (void *d, const char *name, int l)
-{
- struct IGDdatas *datas = (struct IGDdatas *) d;
- datas->level--;
- /*printf("endelt %2d %.*s\n", datas->level, l, name); */
- if ((l == 7) && !memcmp (name, "service", l))
- {
- /*
- if( datas->state < 1
- && !strcmp(datas->servicetype,
- // "urn:schemas-upnp-org:service:WANIPConnection:1") )
- "urn:schemas-upnp-org:service:WANCommonInterfaceConfig:1"))
- datas->state ++;
- */
- if (0 == strcmp (datas->servicetype_tmp,
- "urn:schemas-upnp-org:service:WANCommonInterfaceConfig:1"))
- {
- memcpy (datas->controlurl_CIF, datas->controlurl_tmp,
- MINIUPNPC_URL_MAXSIZE);
- memcpy (datas->eventsuburl_CIF, datas->eventsuburl_tmp,
- MINIUPNPC_URL_MAXSIZE);
- memcpy (datas->scpdurl_CIF, datas->scpdurl_tmp,
- MINIUPNPC_URL_MAXSIZE);
- memcpy (datas->servicetype_CIF, datas->servicetype_tmp,
- MINIUPNPC_URL_MAXSIZE);
- }
- else if (0 == strcmp (datas->servicetype_tmp,
- "urn:schemas-upnp-org:service:WANIPConnection:1")
- || 0 == strcmp (datas->servicetype_tmp,
- "urn:schemas-upnp-org:service:WANPPPConnection:1"))
- {
- memcpy (datas->controlurl, datas->controlurl_tmp,
- MINIUPNPC_URL_MAXSIZE);
- memcpy (datas->eventsuburl, datas->eventsuburl_tmp,
- MINIUPNPC_URL_MAXSIZE);
- memcpy (datas->scpdurl, datas->scpdurl_tmp, MINIUPNPC_URL_MAXSIZE);
- memcpy (datas->servicetype, datas->servicetype_tmp,
- MINIUPNPC_URL_MAXSIZE);
- }
- }
-}
-
-/* Data handler :
- * copy data depending on the current element name and state */
-void
-IGDdata (void *d, const char *data, int l)
-{
- struct IGDdatas *datas = (struct IGDdatas *) d;
- char *dstmember = 0;
- /*printf("%2d %s : %.*s\n",
- datas->level, datas->cureltname, l, data); */
- if (!strcmp (datas->cureltname, "URLBase"))
- dstmember = datas->urlbase;
- else if (!strcmp (datas->cureltname, "serviceType"))
- dstmember = datas->servicetype_tmp;
- else if (!strcmp (datas->cureltname, "controlURL"))
- dstmember = datas->controlurl_tmp;
- else if (!strcmp (datas->cureltname, "eventSubURL"))
- dstmember = datas->eventsuburl_tmp;
- else if (!strcmp (datas->cureltname, "SCPDURL"))
- dstmember = datas->scpdurl_tmp;
-/* else if( !strcmp(datas->cureltname, "deviceType") )
- dstmember = datas->devicetype_tmp;*/
- if (dstmember)
- {
- if (l >= MINIUPNPC_URL_MAXSIZE)
- l = MINIUPNPC_URL_MAXSIZE - 1;
- memcpy (dstmember, data, l);
- dstmember[l] = '\0';
- }
-}
-
-void
-printIGD (struct IGDdatas *d)
-{
- printf ("urlbase = %s\n", d->urlbase);
- printf ("WAN Device (Common interface config) :\n");
- /*printf(" deviceType = %s\n", d->devicetype_CIF); */
- printf (" serviceType = %s\n", d->servicetype_CIF);
- printf (" controlURL = %s\n", d->controlurl_CIF);
- printf (" eventSubURL = %s\n", d->eventsuburl_CIF);
- printf (" SCPDURL = %s\n", d->scpdurl_CIF);
- printf ("WAN Connection Device (IP or PPP Connection):\n");
- /*printf(" deviceType = %s\n", d->devicetype); */
- printf (" servicetype = %s\n", d->servicetype);
- printf (" controlURL = %s\n", d->controlurl);
- printf (" eventSubURL = %s\n", d->eventsuburl);
- printf (" SCPDURL = %s\n", d->scpdurl);
-}
+++ /dev/null
-/* $Id: igd_desc_parse.h,v 1.6 2008/04/23 11:51:07 nanard Exp $ */
-/* Project : miniupnp
- * http://miniupnp.free.fr/
- * Author : Thomas Bernard
- * Copyright (c) 2005-2008 Thomas Bernard
- * This software is subject to the conditions detailed in the
- * LICENCE file provided in this distribution.
- * */
-#ifndef __IGD_DESC_PARSE_H__
-#define __IGD_DESC_PARSE_H__
-
-/* Structure to store the result of the parsing of UPnP
- * descriptions of Internet Gateway Devices */
-#define MINIUPNPC_URL_MAXSIZE (128)
-struct IGDdatas
-{
- char cureltname[MINIUPNPC_URL_MAXSIZE];
- char urlbase[MINIUPNPC_URL_MAXSIZE];
- int level;
- /*int state; */
- /* "urn:schemas-upnp-org:service:WANCommonInterfaceConfig:1" */
- char controlurl_CIF[MINIUPNPC_URL_MAXSIZE];
- char eventsuburl_CIF[MINIUPNPC_URL_MAXSIZE];
- char scpdurl_CIF[MINIUPNPC_URL_MAXSIZE];
- char servicetype_CIF[MINIUPNPC_URL_MAXSIZE];
- /*char devicetype_CIF[MINIUPNPC_URL_MAXSIZE]; */
- /* "urn:schemas-upnp-org:service:WANIPConnection:1"
- * "urn:schemas-upnp-org:service:WANPPPConnection:1" */
- char controlurl[MINIUPNPC_URL_MAXSIZE];
- char eventsuburl[MINIUPNPC_URL_MAXSIZE];
- char scpdurl[MINIUPNPC_URL_MAXSIZE];
- char servicetype[MINIUPNPC_URL_MAXSIZE];
- /*char devicetype[MINIUPNPC_URL_MAXSIZE]; */
- /* tmp */
- char controlurl_tmp[MINIUPNPC_URL_MAXSIZE];
- char eventsuburl_tmp[MINIUPNPC_URL_MAXSIZE];
- char scpdurl_tmp[MINIUPNPC_URL_MAXSIZE];
- char servicetype_tmp[MINIUPNPC_URL_MAXSIZE];
- /*char devicetype_tmp[MINIUPNPC_URL_MAXSIZE]; */
-};
-
-void IGDstartelt (void *, const char *, int);
-void IGDendelt (void *, const char *, int);
-void IGDdata (void *, const char *, int);
-void printIGD (struct IGDdatas *);
-
-#endif
+++ /dev/null
-/* $Id: minisoap.c,v 1.16 2008/10/11 16:39:29 nanard Exp $ */
-/* Project : miniupnp
- * Author : Thomas Bernard
- * Copyright (c) 2005 Thomas Bernard
- * This software is subject to the conditions detailed in the
- * LICENCE file provided in this distribution.
- *
- * Minimal SOAP implementation for UPnP protocol.
- */
-#include <stdio.h>
-#include <string.h>
-#ifdef WIN32
-#include <io.h>
-#include <winsock2.h>
-#define snprintf _snprintf
-#else
-#include <unistd.h>
-#include <sys/types.h>
-#include <sys/socket.h>
-#endif
-#include "minisoap.h"
-#include "miniupnpcstrings.h"
-
-/* only for malloc */
-#include <stdlib.h>
-
-#ifdef WIN32
-#define PRINT_SOCKET_ERROR(x) printf("Socket error: %s, %d\n", x, WSAGetLastError());
-#else
-#define PRINT_SOCKET_ERROR(x) perror(x)
-#endif
-
-/* httpWrite sends the headers and the body to the socket
- * and returns the number of bytes sent */
-static int
-httpWrite (int fd, const char *body, int bodysize,
- const char *headers, int headerssize)
-{
- int n = 0;
- /*n = write(fd, headers, headerssize); */
- /*if(bodysize>0)
- n += write(fd, body, bodysize); */
- /* Note : my old linksys router only took into account
- * soap request that are sent into only one packet */
- char *p;
- /* TODO: AVOID MALLOC */
- p = malloc (headerssize + bodysize);
- if (!p)
- return 0;
- memcpy (p, headers, headerssize);
- memcpy (p + headerssize, body, bodysize);
- /*n = write(fd, p, headerssize+bodysize); */
- n = send (fd, p, headerssize + bodysize, 0);
- if (n < 0)
- {
- PRINT_SOCKET_ERROR ("send");
- }
- /* disable send on the socket */
- /* draytek routers dont seems to like that... */
-#if 0
-#ifdef WIN32
- if (shutdown (fd, SD_SEND) < 0)
- {
-#else
- if (shutdown (fd, SHUT_WR) < 0)
- { /*SD_SEND */
-#endif
- PRINT_SOCKET_ERROR ("shutdown");
- }
-#endif
- free (p);
- return n;
-}
-
-/* self explanatory */
-int
-soapPostSubmit (int fd,
- const char *url,
- const char *host,
- unsigned short port, const char *action, const char *body)
-{
- int bodysize;
- char headerbuf[512];
- int headerssize;
- char portstr[8];
- bodysize = (int) strlen (body);
- /* We are not using keep-alive HTTP connections.
- * HTTP/1.1 needs the header Connection: close to do that.
- * This is the default with HTTP/1.0 */
- /* Connection: Close is normally there only in HTTP/1.1 but who knows */
- portstr[0] = '\0';
- if (port != 80)
- snprintf (portstr, sizeof (portstr), ":%hu", port);
- headerssize = snprintf (headerbuf, sizeof (headerbuf),
- "POST %s HTTP/1.1\r\n"
-/* "POST %s HTTP/1.0\r\n"*/
- "Host: %s%s\r\n" "User-Agent: " OS_STRING ", UPnP/1.0, MiniUPnPc/" MINIUPNPC_VERSION_STRING "\r\n" "Content-Length: %d\r\n" "Content-Type: text/xml\r\n" "SOAPAction: \"%s\"\r\n" "Connection: Close\r\n" "Cache-Control: no-cache\r\n" /* ??? */
- "Pragma: no-cache\r\n"
- "\r\n", url, host, portstr, bodysize, action);
-#ifdef DEBUG
- printf ("SOAP request : headersize=%d bodysize=%d\n",
- headerssize, bodysize);
- /*printf("%s", headerbuf); */
-#endif
- return httpWrite (fd, body, bodysize, headerbuf, headerssize);
-}
+++ /dev/null
-/* $Id: minisoap.h,v 1.3 2006/11/19 22:32:34 nanard Exp $ */
-/* Project : miniupnp
- * Author : Thomas Bernard
- * Copyright (c) 2005 Thomas Bernard
- * This software is subject to the conditions detailed in the
- * LICENCE file provided in this distribution. */
-#ifndef __MINISOAP_H__
-#define __MINISOAP_H__
-
-/*int httpWrite(int, const char *, int, const char *);*/
-int soapPostSubmit (int, const char *, const char *, unsigned short,
- const char *, const char *);
-
-#endif
+++ /dev/null
-/* $Id: minissdpc.c,v 1.7 2008/12/18 17:45:48 nanard Exp $ */
-/* Project : miniupnp
- * Author : Thomas BERNARD
- * copyright (c) 2005-2008 Thomas Bernard
- * This software is subjet to the conditions detailed in the
- * provided LICENCE file. */
-/*#include <syslog.h>*/
-#include <stdio.h>
-#include <string.h>
-#include <stdlib.h>
-#include <unistd.h>
-#include <sys/types.h>
-#ifdef WIN32
-#include <winsock2.h>
-#include <Ws2tcpip.h>
-#include <io.h>
-#else
-#include <sys/socket.h>
-#include <sys/un.h>
-#endif
-
-#include "minissdpc.h"
-#include "miniupnpc.h"
-
-#include "codelength.h"
-
-struct UPNPDev *
-getDevicesFromMiniSSDPD (const char *devtype, const char *socketpath)
-{
- struct UPNPDev *tmp;
- struct UPNPDev *devlist = NULL;
- unsigned char buffer[2048];
- ssize_t n;
- unsigned char *p;
- unsigned char *url;
- unsigned int i;
- unsigned int urlsize, stsize, usnsize, l;
- int s;
- struct sockaddr_un addr;
-
- s = socket (AF_UNIX, SOCK_STREAM, 0);
- if (s < 0)
- {
- /*syslog(LOG_ERR, "socket(unix): %m"); */
- perror ("socket(unix)");
- return NULL;
- }
- addr.sun_family = AF_UNIX;
- strncpy (addr.sun_path, socketpath, sizeof (addr.sun_path));
- if (connect (s, (struct sockaddr *) &addr, sizeof (struct sockaddr_un)) < 0)
- {
- /*syslog(LOG_WARNING, "connect(\"%s\"): %m", socketpath); */
- close (s);
- return NULL;
- }
- stsize = strlen (devtype);
- buffer[0] = 1; /* request type 1 : request devices/services by type */
- p = buffer + 1;
- l = stsize;
- CODELENGTH (l, p);
- memcpy (p, devtype, stsize);
- p += stsize;
- if (write (s, buffer, p - buffer) < 0)
- {
- /*syslog(LOG_ERR, "write(): %m"); */
- perror ("minissdpc.c: write()");
- close (s);
- return NULL;
- }
- n = read (s, buffer, sizeof (buffer));
- if (n <= 0)
- {
- perror ("minissdpc.c: read()");
- close (s);
- return NULL;
- }
- p = buffer + 1;
- for (i = 0; i < buffer[0]; i++)
- {
- if (p + 2 >= buffer + sizeof (buffer))
- break;
- DECODELENGTH (urlsize, p);
- if (p + urlsize + 2 >= buffer + sizeof (buffer))
- break;
- url = p;
- p += urlsize;
- DECODELENGTH (stsize, p);
- if (p + stsize + 2 >= buffer + sizeof (buffer))
- break;
- tmp =
- (struct UPNPDev *) malloc (sizeof (struct UPNPDev) + urlsize +
- stsize);
- tmp->pNext = devlist;
- tmp->descURL = tmp->buffer;
- tmp->st = tmp->buffer + 1 + urlsize;
- memcpy (tmp->buffer, url, urlsize);
- tmp->buffer[urlsize] = '\0';
- memcpy (tmp->buffer + urlsize + 1, p, stsize);
- p += stsize;
- tmp->buffer[urlsize + 1 + stsize] = '\0';
- devlist = tmp;
- /* added for compatibility with recent versions of MiniSSDPd
- * >= 2007/12/19 */
- DECODELENGTH (usnsize, p);
- p += usnsize;
- if (p > buffer + sizeof (buffer))
- break;
- }
- close (s);
- return devlist;
-}
+++ /dev/null
-/* $Id: minissdpc.h,v 1.1 2007/08/31 15:15:33 nanard Exp $ */
-/* Project: miniupnp
- * http://miniupnp.free.fr/ or http://miniupnp.tuxfamily.org/
- * Author: Thomas Bernard
- * Copyright (c) 2005-2007 Thomas Bernard
- * This software is subjects to the conditions detailed
- * in the LICENCE file provided within this distribution */
-#ifndef __MINISSDPC_H__
-#define __MINISSDPC_H__
-
-struct UPNPDev *getDevicesFromMiniSSDPD (const char *devtype,
- const char *socketpath);
-
-#endif
+++ /dev/null
-/* $Id: miniupnpc.c,v 1.57 2008/12/18 17:46:36 nanard Exp $ */
-/* Project : miniupnp
- * Author : Thomas BERNARD
- * copyright (c) 2005-2007 Thomas Bernard
- * This software is subjet to the conditions detailed in the
- * provided LICENCE file. */
-#include <stdio.h>
-#include <stdlib.h>
-#include <string.h>
-#ifdef WIN32
-/* Win32 Specific includes and defines */
-#include <winsock2.h>
-#include <Ws2tcpip.h>
-#include <Iphlpapi.h>
-#include <io.h>
-#define snprintf _snprintf
-#if defined(_MSC_VER) && (_MSC_VER >= 1400)
-#define strncasecmp _memicmp
-#else
-#define strncasecmp memicmp
-#endif
-#define MAXHOSTNAMELEN 64
-#else
-/* Standard POSIX includes */
-#include <unistd.h>
-#include <sys/socket.h>
-#include <sys/types.h>
-#include <sys/param.h>
-#include <netinet/in.h>
-#include <net/if.h>
-#include <arpa/inet.h>
-#include <poll.h>
-#include <netdb.h>
-#define closesocket close
-#endif
-#include "miniupnpc.h"
-#include "minissdpc.h"
-#include "miniwget.h"
-#include "minisoap.h"
-#include "minixml.h"
-#include "upnpcommands.h"
-
-#ifdef WIN32
-#define PRINT_SOCKET_ERROR(x) printf("Socket error: %s, %d\n", x, WSAGetLastError());
-#else
-#define PRINT_SOCKET_ERROR(x) perror(x)
-#endif
-
-#define SOAPPREFIX "s"
-#define SERVICEPREFIX "u"
-#define SERVICEPREFIX2 'u'
-
-/* root description parsing */
-void
-parserootdesc (const char *buffer, int bufsize, struct IGDdatas *data)
-{
- struct xmlparser parser;
- /* xmlparser object */
- parser.xmlstart = buffer;
- parser.xmlsize = bufsize;
- parser.data = data;
- parser.starteltfunc = IGDstartelt;
- parser.endeltfunc = IGDendelt;
- parser.datafunc = IGDdata;
- parser.attfunc = 0;
- parsexml (&parser);
-#ifdef DEBUG
- printIGD (data);
-#endif
-}
-
-/* Content-length: nnn */
-static int
-getcontentlenfromline (const char *p, int n)
-{
- static const char contlenstr[] = "content-length";
- const char *p2 = contlenstr;
- int a = 0;
- while (*p2)
- {
- if (n == 0)
- return -1;
- if (*p2 != *p && *p2 != (*p + 32))
- return -1;
- p++;
- p2++;
- n--;
- }
- if (n == 0)
- return -1;
- if (*p != ':')
- return -1;
- p++;
- n--;
- while (*p == ' ')
- {
- if (n == 0)
- return -1;
- p++;
- n--;
- }
- while (*p >= '0' && *p <= '9')
- {
- if (n == 0)
- return -1;
- a = (a * 10) + (*p - '0');
- p++;
- n--;
- }
- return a;
-}
-
-static void
-getContentLengthAndHeaderLength (char *p, int n,
- int *contentlen, int *headerlen)
-{
- char *line;
- int linelen;
- int r;
- line = p;
- while (line < p + n)
- {
- linelen = 0;
- while (line[linelen] != '\r' && line[linelen] != '\r')
- {
- if (line + linelen >= p + n)
- return;
- linelen++;
- }
- r = getcontentlenfromline (line, linelen);
- if (r > 0)
- *contentlen = r;
- line = line + linelen + 2;
- if (line[0] == '\r' && line[1] == '\n')
- {
- *headerlen = (line - p) + 2;
- return;
- }
- }
-}
-
-/* simpleUPnPcommand :
- * not so simple !
- * return values :
- * 0 - OK
- * -1 - error */
-int
-simpleUPnPcommand (int s, const char *url, const char *service,
- const char *action, struct UPNParg *args,
- char *buffer, int *bufsize)
-{
- struct sockaddr_in dest;
- struct sockaddr_in6 dest6;
- char hostname[MAXHOSTNAMELEN + 1];
- unsigned short port = 0;
- char *path;
- char soapact[128];
- char soapbody[2048];
- char *buf;
- int buffree;
- int n;
- int err;
- int contentlen, headerlen; /* for the response */
- snprintf (soapact, sizeof (soapact), "%s#%s", service, action);
- if (args == NULL)
- {
- /*soapbodylen = */ snprintf (soapbody, sizeof (soapbody),
- "<?xml version=\"1.0\"?>\r\n"
- "<" SOAPPREFIX ":Envelope "
- "xmlns:" SOAPPREFIX
- "=\"http://schemas.xmlsoap.org/soap/envelope/\" "
- SOAPPREFIX
- ":encodingStyle=\"http://schemas.xmlsoap.org/soap/encoding/\">"
- "<" SOAPPREFIX ":Body>" "<" SERVICEPREFIX
- ":%s xmlns:" SERVICEPREFIX "=\"%s\">" "</"
- SERVICEPREFIX ":%s>" "</" SOAPPREFIX
- ":Body></" SOAPPREFIX ":Envelope>" "\r\n",
- action, service, action);
- }
- else
- {
- char *p;
- const char *pe, *pv;
- int soapbodylen;
- soapbodylen = snprintf (soapbody, sizeof (soapbody),
- "<?xml version=\"1.0\"?>\r\n"
- "<" SOAPPREFIX ":Envelope "
- "xmlns:" SOAPPREFIX
- "=\"http://schemas.xmlsoap.org/soap/envelope/\" "
- SOAPPREFIX
- ":encodingStyle=\"http://schemas.xmlsoap.org/soap/encoding/\">"
- "<" SOAPPREFIX ":Body>" "<" SERVICEPREFIX
- ":%s xmlns:" SERVICEPREFIX "=\"%s\">", action,
- service);
- p = soapbody + soapbodylen;
- while (args->elt)
- {
- /* check that we are never overflowing the string... */
- if (soapbody + sizeof (soapbody) <= p + 100)
- {
- /* we keep a margin of at least 100 bytes */
- *bufsize = 0;
- return -1;
- }
- *(p++) = '<';
- pe = args->elt;
- while (*pe)
- *(p++) = *(pe++);
- *(p++) = '>';
- if ((pv = args->val))
- {
- while (*pv)
- *(p++) = *(pv++);
- }
- *(p++) = '<';
- *(p++) = '/';
- pe = args->elt;
- while (*pe)
- *(p++) = *(pe++);
- *(p++) = '>';
- args++;
- }
- *(p++) = '<';
- *(p++) = '/';
- *(p++) = SERVICEPREFIX2;
- *(p++) = ':';
- pe = action;
- while (*pe)
- *(p++) = *(pe++);
- strncpy (p, "></" SOAPPREFIX ":Body></" SOAPPREFIX ":Envelope>\r\n",
- soapbody + sizeof (soapbody) - p);
- }
- if (!parseURL (url, hostname, &port, &path))
- return -1;
-
- if (s < 0)
- {
- /* Test IPv4 address, else use IPv6 */
- if (inet_pton (AF_INET, hostname, &dest.sin_addr) == 1)
- {
- memset (&dest, 0, sizeof (dest));
- dest.sin_family = AF_INET;
- dest.sin_port = htons (port);
-#ifdef HAVE_SOCKADDR_IN_SIN_LEN
- dest.sin_len = sizeof (dest);
-#endif
- if ((s = socket (PF_INET, SOCK_STREAM, 0)) < 0)
- {
- PRINT_SOCKET_ERROR ("socket");
- *bufsize = 0;
- return -1;
- }
- err = connect (s, (struct sockaddr *) &dest, sizeof (dest));
- }
- else if (inet_pton (AF_INET6, hostname, &dest6.sin6_addr) == 1)
- {
- memset (&dest6, 0, sizeof (dest6));
- dest6.sin6_family = AF_INET6;
- dest6.sin6_port = htons (port);
-#ifdef HAVE_SOCKADDR_IN_SIN_LEN
- dest6.sin6_len = sizeof (dest6);
-#endif
- if ((s = socket (PF_INET6, SOCK_STREAM, 0)) < 0)
- {
- PRINT_SOCKET_ERROR ("socket");
- *bufsize = 0;
- return -1;
- }
- err = connect (s, (struct sockaddr *) &dest6, sizeof (dest6));
- }
- else
- {
- PRINT_SOCKET_ERROR ("inet_pton");
- if (s > 0)
- closesocket (s);
-
- *bufsize = 0;
- return -1;
- }
-
- if (err < 0)
- {
- PRINT_SOCKET_ERROR ("connect");
- closesocket (s);
- *bufsize = 0;
- return -1;
- }
- }
- n = soapPostSubmit (s, path, hostname, port, soapact, soapbody);
- if (n <= 0)
- {
-#ifdef DEBUG
- printf ("Error sending SOAP request\n");
-#endif
- closesocket (s);
- return -1;
- }
-
- contentlen = -1;
- headerlen = -1;
- buf = buffer;
- buffree = *bufsize;
- *bufsize = 0;
- while ((n = ReceiveData (s, buf, buffree, 5000)) > 0)
- {
- buffree -= n;
- buf += n;
- *bufsize += n;
- getContentLengthAndHeaderLength (buffer, *bufsize,
- &contentlen, &headerlen);
-#ifdef DEBUG
- printf ("received n=%dbytes bufsize=%d ContLen=%d HeadLen=%d\n",
- n, *bufsize, contentlen, headerlen);
-#endif
- /* break if we received everything */
- if (contentlen > 0 && headerlen > 0
- && *bufsize >= contentlen + headerlen)
- break;
- }
-
- closesocket (s);
- return 0;
-}
-
-/* parseMSEARCHReply()
- * the last 4 arguments are filled during the parsing :
- * - location/locationsize : "location:" field of the SSDP reply packet
- * - st/stsize : "st:" field of the SSDP reply packet.
- * The strings are NOT null terminated */
-static void
-parseMSEARCHReply (const char *reply, int size,
- const char **location, int *locationsize,
- const char **st, int *stsize)
-{
- int a, b, i;
- i = 0;
- a = i; /* start of the line */
- b = 0;
- while (i < size)
- {
- switch (reply[i])
- {
- case ':':
- if (b == 0)
- {
- b = i; /* end of the "header" */
- /*for(j=a; j<b; j++)
- {
- putchar(reply[j]);
- }
- */
- }
- break;
- case '\x0a':
- case '\x0d':
- if (b != 0)
- {
- /*for(j=b+1; j<i; j++)
- {
- putchar(reply[j]);
- }
- putchar('\n'); */
- do
- {
- b++;
- }
- while (reply[b] == ' ');
- if (0 == strncasecmp (reply + a, "location", 8))
- {
- *location = reply + b;
- *locationsize = i - b;
- }
- else if (0 == strncasecmp (reply + a, "st", 2))
- {
- *st = reply + b;
- *stsize = i - b;
- }
- b = 0;
- }
- a = i + 1;
- break;
- default:
- break;
- }
- i++;
- }
-}
-
-/* port upnp discover : SSDP protocol */
-#define PORT 1900
-#define XSTR(s) STR(s)
-#define STR(s) #s
-#define UPNP_MCAST_ADDR "239.255.255.250"
-#define UPNP_MCAST_ADDR6 "FF02:0:0:0:0:0:0:F"
-
-/* upnpDiscover() :
- * return a chained list of all devices found or NULL if
- * no devices was found.
- * It is up to the caller to free the chained list
- * delay is in millisecond (poll) */
-struct UPNPDev *
-upnpDiscover (int delay, const char *multicastif,
- const struct sockaddr *addr,
- const char *minissdpdsock, int sameport)
-{
- struct UPNPDev *tmp;
- struct UPNPDev *devlist = 0;
- int opt = 1;
- static const char MSearchMsgFmt[] =
- "M-SEARCH * HTTP/1.1\r\n"
- "HOST: " UPNP_MCAST_ADDR ":" XSTR (PORT) "\r\n"
- "ST: %s\r\n" "MAN: \"ssdp:discover\"\r\n" "MX: 3\r\n" "\r\n";
- static const char *const deviceList[] = {
- "urn:schemas-upnp-org:device:InternetGatewayDevice:1",
- "urn:schemas-upnp-org:service:WANIPConnection:1",
- "urn:schemas-upnp-org:service:WANPPPConnection:1",
- "upnp:rootdevice",
- 0
- };
- int deviceIndex = 0;
- char bufr[1536]; /* reception and emission buffer */
- int sudp;
- int n;
- int domain = PF_INET;
- int if_index;
- struct in6_addr any_addr = IN6ADDR_ANY_INIT;
- struct sockaddr_in sockudp_r, sockudp_w;
- struct sockaddr_in6 sockudp6_r, sockudp6_w;
-
-#ifndef WIN32
- /* first try to get infos from minissdpd ! */
- if (!minissdpdsock)
- minissdpdsock = "/var/run/minissdpd.sock";
- while (!devlist && deviceList[deviceIndex])
- {
- devlist = getDevicesFromMiniSSDPD (deviceList[deviceIndex],
- minissdpdsock);
- /* We return what we have found if it was not only a rootdevice */
- if (devlist && !strstr (deviceList[deviceIndex], "rootdevice"))
- return devlist;
- deviceIndex++;
- }
- deviceIndex = 0;
-#endif
-
- if (addr && addr->sa_family == AF_INET)
- domain = PF_INET;
- else if (addr && addr->sa_family == AF_INET6)
- domain = PF_INET6;
- else if (addr)
- return NULL;
-
- /* fallback to direct discovery */
-#ifdef WIN32
- sudp = socket (domain, SOCK_DGRAM, IPPROTO_UDP);
-#else
- sudp = socket (domain, SOCK_DGRAM, 0);
-#endif
- if (sudp < 0)
- {
- PRINT_SOCKET_ERROR ("socket");
- return NULL;
- }
-
- if (domain == PF_INET)
- {
- /* receive */
- memset (&sockudp_r, 0, sizeof (struct sockaddr_in));
- sockudp_r.sin_family = AF_INET;
-#ifdef HAVE_SOCKADDR_IN_SIN_LEN
- sockudp_r.sin_len = sizeof (struct sockaddr_in);
-#endif
- if (sameport)
- sockudp_r.sin_port = htons (PORT);
- sockudp_r.sin_addr.s_addr = INADDR_ANY;
- /* send */
- memset (&sockudp_w, 0, sizeof (struct sockaddr_in));
- sockudp_w.sin_family = AF_INET;
- sockudp_w.sin_port = htons (PORT);
- sockudp_w.sin_addr.s_addr = inet_addr (UPNP_MCAST_ADDR);
-#ifdef HAVE_SOCKADDR_IN_SIN_LEN
- sockudp_w.sin_len = sizeof (struct sockaddr_in);
-#endif
- }
- else
- {
- /* receive */
- memcpy (&sockudp6_r, addr, sizeof (struct sockaddr_in6));
- if (sameport)
- sockudp6_r.sin6_port = htons (PORT);
- else
- sockudp6_r.sin6_port = 0;
- sockudp6_r.sin6_addr = any_addr;
-#ifdef HAVE_SOCKADDR_IN_SIN_LEN
- sockudp6_r.sin6_len = sizeof (struct sockaddr_in6);
-#endif
- /* send */
- memset (&sockudp6_w, 0, sizeof (struct sockaddr_in6));
- sockudp6_w.sin6_family = AF_INET6;
- sockudp6_w.sin6_port = htons (PORT);
- if (inet_pton (AF_INET6, UPNP_MCAST_ADDR6, &sockudp6_w.sin6_addr) != 1)
- {
- PRINT_SOCKET_ERROR ("inet_pton");
- return NULL;
- }
-#ifdef HAVE_SOCKADDR_IN_SIN_LEN
- sockudp6_w.sin6_len = sizeof (struct sockaddr_in6);
-#endif
- }
-
-#ifdef WIN32
- if (setsockopt
- (sudp, SOL_SOCKET, SO_REUSEADDR, (const char *) &opt, sizeof (opt)) < 0)
-#else
- if (setsockopt (sudp, SOL_SOCKET, SO_REUSEADDR, &opt, sizeof (opt)) < 0)
-#endif
- {
- PRINT_SOCKET_ERROR ("setsockopt");
- return NULL;
- }
-
- if (addr)
- {
- if (domain == PF_INET)
- {
- sockudp_r.sin_addr.s_addr = ((struct sockaddr_in *) addr)->sin_addr.s_addr;
- if (setsockopt
- (sudp, IPPROTO_IP, IP_MULTICAST_IF, (const char *) &sockudp_r.sin_addr,
- sizeof (struct in_addr)) < 0)
- {
- PRINT_SOCKET_ERROR ("setsockopt");
- }
-
- /* Bind to receive response before sending packet */
- if (bind (sudp, (struct sockaddr *) &sockudp_r, sizeof (struct sockaddr_in))
- != 0)
- {
- PRINT_SOCKET_ERROR ("bind");
- closesocket (sudp);
- return NULL;
- }
- }
- else
- {
- if (multicastif)
- {
- if_index = if_nametoindex (multicastif);
- if (!if_index)
- PRINT_SOCKET_ERROR ("if_nametoindex");
-
- if (setsockopt
- (sudp, IPPROTO_IPV6, IPV6_MULTICAST_IF, &if_index, sizeof (if_index)) < 0)
- {
- PRINT_SOCKET_ERROR ("setsockopt");
- }
- }
-
- /* Bind to receive response before sending packet */
- memcpy (&sockudp6_r.sin6_addr, &((struct sockaddr_in6 *) addr)->sin6_addr,
- sizeof (sockudp6_r.sin6_addr));
- if (bind (sudp, (struct sockaddr *) &sockudp6_r, sizeof (struct sockaddr_in6))
- != 0)
- {
- PRINT_SOCKET_ERROR ("bind");
- closesocket (sudp);
- return NULL;
- }
- }
- }
-
- /* receiving SSDP response packet */
- for (n = 0;;)
- {
- if (n == 0)
- {
- /* sending the SSDP M-SEARCH packet */
- n = snprintf (bufr, sizeof (bufr),
- MSearchMsgFmt, deviceList[deviceIndex++]);
- /*printf("Sending %s", bufr); */
- if (domain == PF_INET)
- n = sendto (sudp, bufr, n, 0,
- (struct sockaddr *) &sockudp_w,
- sizeof (struct sockaddr_in));
- else
- n = sendto (sudp, bufr, n, 0,
- (struct sockaddr *) &sockudp6_w,
- sizeof (struct sockaddr_in6));
-
- if (n < 0)
- {
- PRINT_SOCKET_ERROR ("sendto");
- closesocket (sudp);
- return devlist;
- }
- }
- /* Waiting for SSDP REPLY packet to M-SEARCH */
- n = ReceiveData (sudp, bufr, sizeof (bufr), delay);
-
- if (n < 0)
- {
- /* error */
- closesocket (sudp);
- return devlist;
- }
- else if (n == 0)
- {
- /* no data or Time Out */
- if (devlist || (deviceList[deviceIndex] == 0))
- {
- /* no more device type to look for... */
- closesocket (sudp);
- return devlist;
- }
- }
- else
- {
- const char *descURL = NULL;
- int urlsize = 0;
- const char *st = NULL;
- int stsize = 0;
- /*printf("%d byte(s) :\n%s\n", n, bufr); *//* affichage du message */
- parseMSEARCHReply (bufr, n, &descURL, &urlsize, &st, &stsize);
- if (st && descURL)
- {
- /*printf("M-SEARCH Reply:\nST: %.*s\nLocation: %.*s\n",
- stsize, st, urlsize, descURL); */
- tmp =
- (struct UPNPDev *) malloc (sizeof (struct UPNPDev) + urlsize +
- stsize);
- tmp->pNext = devlist;
- tmp->descURL = tmp->buffer;
- tmp->st = tmp->buffer + 1 + urlsize;
- memcpy (tmp->buffer, descURL, urlsize);
- tmp->buffer[urlsize] = '\0';
- memcpy (tmp->buffer + urlsize + 1, st, stsize);
- tmp->buffer[urlsize + 1 + stsize] = '\0';
- devlist = tmp;
- }
- }
- }
-}
-
-/* freeUPNPDevlist() should be used to
- * free the chained list returned by upnpDiscover() */
-void
-freeUPNPDevlist (struct UPNPDev *devlist)
-{
- struct UPNPDev *next;
- while (devlist)
- {
- next = devlist->pNext;
- free (devlist);
- devlist = next;
- }
-}
-
-static void
-url_cpy_or_cat (char *dst, const char *src, int n)
-{
- if ((src[0] == 'h')
- && (src[1] == 't')
- && (src[2] == 't')
- && (src[3] == 'p')
- && (src[4] == ':') && (src[5] == '/') && (src[6] == '/'))
- {
- strncpy (dst, src, n);
- }
- else
- {
- int l = strlen (dst);
- if (src[0] != '/')
- dst[l++] = '/';
- if (l <= n)
- strncpy (dst + l, src, n - l);
- }
-}
-
-/* Prepare the Urls for usage...
- */
-void
-GetUPNPUrls (struct UPNPUrls *urls, struct IGDdatas *data,
- const char *descURL)
-{
- char *p;
- int n1, n2, n3;
- n1 = strlen (data->urlbase);
- if (n1 == 0)
- n1 = strlen (descURL);
- n1 += 2; /* 1 byte more for Null terminator, 1 byte for '/' if needed */
- n2 = n1;
- n3 = n1;
- n1 += strlen (data->scpdurl);
- n2 += strlen (data->controlurl);
- n3 += strlen (data->controlurl_CIF);
-
- urls->ipcondescURL = (char *) malloc (n1);
- urls->controlURL = (char *) malloc (n2);
- urls->controlURL_CIF = (char *) malloc (n3);
- /* maintenant on chope la desc du WANIPConnection */
- if (data->urlbase[0] != '\0')
- strncpy (urls->ipcondescURL, data->urlbase, n1);
- else
- strncpy (urls->ipcondescURL, descURL, n1);
- p = strchr (urls->ipcondescURL + 7, '/');
- if (p)
- p[0] = '\0';
- strncpy (urls->controlURL, urls->ipcondescURL, n2);
- strncpy (urls->controlURL_CIF, urls->ipcondescURL, n3);
-
- url_cpy_or_cat (urls->ipcondescURL, data->scpdurl, n1);
-
- url_cpy_or_cat (urls->controlURL, data->controlurl, n2);
-
- url_cpy_or_cat (urls->controlURL_CIF, data->controlurl_CIF, n3);
-
-#ifdef DEBUG
- printf ("urls->ipcondescURL='%s' %d n1=%d\n", urls->ipcondescURL,
- strlen (urls->ipcondescURL), n1);
- printf ("urls->controlURL='%s' %d n2=%d\n", urls->controlURL,
- strlen (urls->controlURL), n2);
- printf ("urls->controlURL_CIF='%s' %d n3=%d\n", urls->controlURL_CIF,
- strlen (urls->controlURL_CIF), n3);
-#endif
-}
-
-void
-FreeUPNPUrls (struct UPNPUrls *urls)
-{
- if (!urls)
- return;
- free (urls->controlURL);
- urls->controlURL = 0;
- free (urls->ipcondescURL);
- urls->ipcondescURL = 0;
- free (urls->controlURL_CIF);
- urls->controlURL_CIF = 0;
-}
-
-
-int
-ReceiveData (int socket, char *data, int length, int timeout)
-{
- int n;
-#ifndef WIN32
- struct pollfd fds[1]; /* for the poll */
- fds[0].fd = socket;
- fds[0].events = POLLIN;
- n = poll (fds, 1, timeout);
- if (n < 0)
- {
- PRINT_SOCKET_ERROR ("poll");
- return -1;
- }
- else if (n == 0)
- {
- return 0;
- }
-#else
- fd_set socketSet;
- TIMEVAL timeval;
- FD_ZERO (&socketSet);
- FD_SET (socket, &socketSet);
- timeval.tv_sec = timeout / 1000;
- timeval.tv_usec = (timeout % 1000) * 1000;
- /*n = select(0, &socketSet, NULL, NULL, &timeval); */
- n = select (FD_SETSIZE, &socketSet, NULL, NULL, &timeval);
- if (n < 0)
- {
- PRINT_SOCKET_ERROR ("select");
- return -1;
- }
- else if (n == 0)
- {
- return 0;
- }
-#endif
- n = recv (socket, data, length, 0);
- if (n < 0)
- {
- PRINT_SOCKET_ERROR ("recv");
- }
- return n;
-}
-
-int
-UPNPIGD_IsConnected (struct UPNPUrls *urls, struct IGDdatas *data)
-{
- char status[64];
- unsigned int uptime;
- status[0] = '\0';
- UPNP_GetStatusInfo (urls->controlURL, data->servicetype,
- status, &uptime, NULL);
- if (0 == strcmp ("Connected", status))
- {
- return 1;
- }
- else
- return 0;
-}
-
-
-/* UPNP_GetValidIGD() :
- * return values :
- * 0 = NO IGD found
- * 1 = A valid connected IGD has been found
- * 2 = A valid IGD has been found but it reported as
- * not connected
- * 3 = an UPnP device has been found but was not recognized as an IGD
- *
- * In any non zero return case, the urls and data structures
- * passed as parameters are set. Donc forget to call FreeUPNPUrls(urls) to
- * free allocated memory.
- */
-int
-UPNP_GetValidIGD (struct UPNPDev *devlist,
- struct UPNPUrls *urls,
- struct IGDdatas *data, char *lanaddr, int lanaddrlen)
-{
- char *descXML;
- int descXMLsize = 0;
- struct UPNPDev *dev;
- int ndev = 0;
- int state; /* state 1 : IGD connected. State 2 : IGD. State 3 : anything */
- if (!devlist)
- {
-#ifdef DEBUG
- printf ("Empty devlist\n");
-#endif
- return 0;
- }
- for (state = 1; state <= 3; state++)
- {
- for (dev = devlist; dev; dev = dev->pNext)
- {
- /* we should choose an internet gateway device.
- * with st == urn:schemas-upnp-org:device:InternetGatewayDevice:1 */
- descXML = miniwget_getaddr (dev->descURL, &descXMLsize,
- lanaddr, lanaddrlen);
- if (descXML)
- {
- ndev++;
- memset (data, 0, sizeof (struct IGDdatas));
- memset (urls, 0, sizeof (struct UPNPUrls));
- parserootdesc (descXML, descXMLsize, data);
- free (descXML);
- descXML = NULL;
- if (0 == strcmp (data->servicetype_CIF,
- "urn:schemas-upnp-org:service:WANCommonInterfaceConfig:1")
- || state >= 3)
- {
- GetUPNPUrls (urls, data, dev->descURL);
-
-#ifdef DEBUG
- printf ("UPNPIGD_IsConnected(%s) = %d\n",
- urls->controlURL, UPNPIGD_IsConnected (urls, data));
-#endif
- if ((state >= 2) || UPNPIGD_IsConnected (urls, data))
- return state;
- FreeUPNPUrls (urls);
- }
- memset (data, 0, sizeof (struct IGDdatas));
- }
-#ifdef DEBUG
- else
- {
- printf ("error getting XML description %s\n", dev->descURL);
- }
-#endif
- }
- }
- return 0;
-}
-
-/* UPNP_GetIGDFromUrl()
- * Used when skipping the discovery process.
- * return value :
- * 0 - Not ok
- * 1 - OK */
-int
-UPNP_GetIGDFromUrl (const char *rootdescurl,
- struct UPNPUrls *urls,
- struct IGDdatas *data, char *lanaddr, int lanaddrlen)
-{
- char *descXML;
- int descXMLsize = 0;
- descXML = miniwget_getaddr (rootdescurl, &descXMLsize, lanaddr, lanaddrlen);
- if (descXML)
- {
- memset (data, 0, sizeof (struct IGDdatas));
- memset (urls, 0, sizeof (struct UPNPUrls));
- parserootdesc (descXML, descXMLsize, data);
- free (descXML);
- descXML = NULL;
- GetUPNPUrls (urls, data, rootdescurl);
- return 1;
- }
- else
- {
- return 0;
- }
-}
+++ /dev/null
-/* $Id: miniupnpc.h,v 1.18 2008/09/25 18:02:50 nanard Exp $ */
-/* Project: miniupnp
- * http://miniupnp.free.fr/
- * Author: Thomas Bernard
- * Copyright (c) 2005-2006 Thomas Bernard
- * This software is subjects to the conditions detailed
- * in the LICENCE file provided within this distribution */
-#ifndef __MINIUPNPC_H__
-#define __MINIUPNPC_H__
-
-#include "declspec.h"
-#include "igd_desc_parse.h"
-
-#ifdef WIN32
-#include <winsock2.h>
-#else
-#include <sys/socket.h>
-#endif
-
-#ifdef __cplusplus
-extern "C"
-{
-#endif
-
-/* Structures definitions : */
- struct UPNParg
- {
- const char *elt;
- const char *val;
- };
-
- int simpleUPnPcommand (int s, const char *, const char *,
- const char *, struct UPNParg *, char *, int *);
-
- struct UPNPDev
- {
- struct UPNPDev *pNext;
- char *descURL;
- char *st;
- char buffer[2];
- };
-
-/* upnpDiscover()
- * discover UPnP devices on the network.
- * The discovered devices are returned as a chained list.
- * It is up to the caller to free the list with freeUPNPDevlist().
- * delay (in millisecond) is the maximum time for waiting any device
- * response.
- * If available, device list will be obtained from MiniSSDPd.
- * Default path for minissdpd socket will be used if minissdpdsock argument
- * is NULL.
- * If multicastif is not NULL, it will be used instead of the default
- * multicast interface for sending SSDP discover packets.
- * If sameport is not null, SSDP packets will be sent from the source port
- * 1900 (same as destination port) otherwise system assign a source port. */
- LIBSPEC struct UPNPDev *upnpDiscover (int delay, const char *multicastif, const struct sockaddr *addr,
- const char *minissdpdsock, int sameport);
-/* freeUPNPDevlist()
- * free list returned by upnpDiscover() */
- LIBSPEC void freeUPNPDevlist (struct UPNPDev *devlist);
-
-/* parserootdesc() :
- * parse root XML description of a UPnP device and fill the IGDdatas
- * structure. */
- LIBSPEC void parserootdesc (const char *, int, struct IGDdatas *);
-
-/* structure used to get fast access to urls
- * controlURL: controlURL of the WANIPConnection
- * ipcondescURL: url of the description of the WANIPConnection
- * controlURL_CIF: controlURL of the WANCommonInterfaceConfig
- */
- struct UPNPUrls
- {
- char *controlURL;
- char *ipcondescURL;
- char *controlURL_CIF;
- };
-
-/* UPNP_GetValidIGD() :
- * return values :
- * 0 = NO IGD found
- * 1 = A valid connected IGD has been found
- * 2 = A valid IGD has been found but it reported as
- * not connected
- * 3 = an UPnP device has been found but was not recognized as an IGD
- *
- * In any non zero return case, the urls and data structures
- * passed as parameters are set. Donc forget to call FreeUPNPUrls(urls) to
- * free allocated memory.
- */
- LIBSPEC int
- UPNP_GetValidIGD (struct UPNPDev *devlist,
- struct UPNPUrls *urls,
- struct IGDdatas *data, char *lanaddr, int lanaddrlen);
-
-/* UPNP_GetIGDFromUrl()
- * Used when skipping the discovery process.
- * return value :
- * 0 - Not ok
- * 1 - OK */
- LIBSPEC int
- UPNP_GetIGDFromUrl (const char *rootdescurl,
- struct UPNPUrls *urls,
- struct IGDdatas *data, char *lanaddr, int lanaddrlen);
-
- LIBSPEC void GetUPNPUrls (struct UPNPUrls *, struct IGDdatas *,
- const char *);
-
- LIBSPEC void FreeUPNPUrls (struct UPNPUrls *);
-
-/* Reads data from the specified socket.
- * Returns the number of bytes read if successful, zero if no bytes were
- * read or if we timed out. Returns negative if there was an error. */
- int ReceiveData (int socket, char *data, int length, int timeout);
-
-#ifdef __cplusplus
-}
-#endif
-
-#endif
+++ /dev/null
-/* $Id: miniupnpcstrings.h,v 1.2 2008/10/14 17:39:04 nanard Exp $ */
-/* Project: miniupnp
- * http://miniupnp.free.fr/ or http://miniupnp.tuxfamily.org/
- * Author: Thomas Bernard
- * Copyright (c) 2005-2008 Thomas Bernard
- * This software is subjects to the conditions detailed
- * in the LICENCE file provided within this distribution */
-#ifndef __MINIUPNPCSTRINGS_H__
-#define __MINIUPNPCSTRINGS_H__
-
-#define OS_STRING "Debian/4.0"
-#define MINIUPNPC_VERSION_STRING "1.2"
-
-#endif
+++ /dev/null
-/* $Id: miniwget.c,v 1.22 2009/02/28 10:36:35 nanard Exp $ */
-/* Project : miniupnp
- * Author : Thomas Bernard
- * Copyright (c) 2005 Thomas Bernard
- * This software is subject to the conditions detailed in the
- * LICENCE file provided in this distribution.
- * */
-#include <stdio.h>
-#include <stdlib.h>
-#include <string.h>
-#include "miniupnpc.h"
-#ifdef WIN32
-#include <winsock2.h>
-#include <io.h>
-#define MAXHOSTNAMELEN 64
-#define MIN(x,y) (((x)<(y))?(x):(y))
-#define snprintf _snprintf
-#define herror
-#define socklen_t int
-#else
-#include <unistd.h>
-#include <sys/param.h>
-#include <sys/socket.h>
-#include <netdb.h>
-#include <netinet/in.h>
-#include <arpa/inet.h>
-#define closesocket close
-#endif
-#if defined(__sun) || defined(sun)
-#define MIN(x,y) (((x)<(y))?(x):(y))
-#endif
-
-#include "miniupnpcstrings.h"
-
-/* miniwget2() :
- * */
-static void *
-miniwget2 (const char *url, const char *host,
- unsigned short port, const char *path,
- int *size, char *addr_str, int addr_str_len)
-{
- char buf[2048];
- int s;
- struct sockaddr_in dest;
- struct hostent *hp;
- *size = 0;
- hp = gethostbyname (host);
- if (hp == NULL)
- {
- herror (host);
- return NULL;
- }
- /* memcpy((char *)&dest.sin_addr, hp->h_addr, hp->h_length); */
- memcpy (&dest.sin_addr, hp->h_addr, sizeof (dest.sin_addr));
- memset (dest.sin_zero, 0, sizeof (dest.sin_zero));
- s = socket (PF_INET, SOCK_STREAM, 0);
- if (s < 0)
- {
- perror ("socket");
- return NULL;
- }
- dest.sin_family = AF_INET;
- dest.sin_port = htons (port);
- if (connect (s, (struct sockaddr *) &dest, sizeof (struct sockaddr_in)) < 0)
- {
- perror ("connect");
- closesocket (s);
- return NULL;
- }
-
- /* get address for caller ! */
- if (addr_str)
- {
- struct sockaddr_in saddr;
- socklen_t len;
-
- len = sizeof (saddr);
- getsockname (s, (struct sockaddr *) &saddr, &len);
-#ifndef WIN32
- inet_ntop (AF_INET, &saddr.sin_addr, addr_str, addr_str_len);
-#else
- /* using INT WINAPI WSAAddressToStringA(LPSOCKADDR, DWORD, LPWSAPROTOCOL_INFOA, LPSTR, LPDWORD);
- * But his function make a string with the port : nn.nn.nn.nn:port */
-/* if(WSAAddressToStringA((SOCKADDR *)&saddr, sizeof(saddr),
- NULL, addr_str, (DWORD *)&addr_str_len))
- {
- printf("WSAAddressToStringA() failed : %d\n", WSAGetLastError());
- }*/
- strncpy (addr_str, inet_ntoa (saddr.sin_addr), addr_str_len);
-#endif
-#ifdef DEBUG
- printf ("address miniwget : %s\n", addr_str);
-#endif
- }
-
- snprintf (buf, sizeof (buf),
- "GET %s HTTP/1.1\r\n"
- "Host: %s:%d\r\n"
- "Connection: Close\r\n"
- "User-Agent: " OS_STRING ", UPnP/1.0, MiniUPnPc/"
- MINIUPNPC_VERSION_STRING "\r\n" "\r\n", path, host, port);
- /*write(s, buf, strlen(buf)); */
- send (s, buf, strlen (buf), 0);
- {
- int n, headers = 1;
- char *respbuffer = NULL;
- int allreadyread = 0;
- /*while((n = recv(s, buf, 2048, 0)) > 0) */
- while ((n = ReceiveData (s, buf, 2048, 5000)) > 0)
- {
- if (headers)
- {
- int i = 0;
- while (i < n - 3)
- {
- if (buf[i] == '\r' && buf[i + 1] == '\n'
- && buf[i + 2] == '\r' && buf[i + 3] == '\n')
- {
- headers = 0; /* end */
- if (i < n - 4)
- {
- respbuffer = (char *) realloc ((void *) respbuffer,
- allreadyread + (n - i -
- 4));
- memcpy (respbuffer + allreadyread, buf + i + 4,
- n - i - 4);
- allreadyread += (n - i - 4);
- }
- break;
- }
- i++;
- }
- }
- else
- {
- respbuffer = (char *) realloc ((void *) respbuffer,
- allreadyread + n);
- memcpy (respbuffer + allreadyread, buf, n);
- allreadyread += n;
- }
- }
- *size = allreadyread;
-#ifdef DEBUG
- printf ("%d bytes read\n", *size);
-#endif
- closesocket (s);
- return respbuffer;
- }
-}
-
-/* parseURL()
- * arguments :
- * url : source string not modified
- * hostname : hostname destination string (size of MAXHOSTNAMELEN+1)
- * port : port (destination)
- * path : pointer to the path part of the URL
- *
- * Return values :
- * 0 - Failure
- * 1 - Success */
-int
-parseURL (const char *url, char *hostname, unsigned short *port, char **path)
-{
- char *p1, *p2, *p3;
- p1 = strstr (url, "://");
- if (!p1)
- return 0;
- p1 += 3;
- if ((url[0] != 'h') || (url[1] != 't')
- || (url[2] != 't') || (url[3] != 'p'))
- return 0;
- p2 = strchr (p1, ':');
- p3 = strchr (p1, '/');
- if (!p3)
- return 0;
- memset (hostname, 0, MAXHOSTNAMELEN + 1);
- if (!p2 || (p2 > p3))
- {
- strncpy (hostname, p1, MIN (MAXHOSTNAMELEN, (int) (p3 - p1)));
- *port = 80;
- }
- else
- {
- strncpy (hostname, p1, MIN (MAXHOSTNAMELEN, (int) (p2 - p1)));
- *port = 0;
- p2++;
- while ((*p2 >= '0') && (*p2 <= '9'))
- {
- *port *= 10;
- *port += (unsigned short) (*p2 - '0');
- p2++;
- }
- }
- *path = p3;
- return 1;
-}
-
-void *
-miniwget (const char *url, int *size)
-{
- unsigned short port;
- char *path;
- /* protocol://host:port/chemin */
- char hostname[MAXHOSTNAMELEN + 1];
- *size = 0;
- if (!parseURL (url, hostname, &port, &path))
- return NULL;
- return miniwget2 (url, hostname, port, path, size, 0, 0);
-}
-
-void *
-miniwget_getaddr (const char *url, int *size, char *addr, int addrlen)
-{
- unsigned short port;
- char *path;
- /* protocol://host:port/chemin */
- char hostname[MAXHOSTNAMELEN + 1];
- *size = 0;
- if (addr)
- addr[0] = '\0';
- if (!parseURL (url, hostname, &port, &path))
- return NULL;
- return miniwget2 (url, hostname, port, path, size, addr, addrlen);
-}
+++ /dev/null
-/* $Id: miniwget.h,v 1.5 2007/01/29 20:27:23 nanard Exp $ */
-/* Project : miniupnp
- * Author : Thomas Bernard
- * Copyright (c) 2005 Thomas Bernard
- * This software is subject to the conditions detailed in the
- * LICENCE file provided in this distribution.
- * */
-#ifndef __MINIWGET_H__
-#define __MINIWGET_H__
-
-#include "declspec.h"
-
-#ifdef __cplusplus
-extern "C"
-{
-#endif
-
- LIBSPEC void *miniwget (const char *, int *);
-
- LIBSPEC void *miniwget_getaddr (const char *, int *, char *, int);
-
- int parseURL (const char *, char *, unsigned short *, char **);
-
-#ifdef __cplusplus
-}
-#endif
-
-#endif
+++ /dev/null
-/* $Id: minixml.c,v 1.6 2007/05/15 18:14:08 nanard Exp $ */
-/* minixml.c : the minimum size a xml parser can be ! */
-/* Project : miniupnp
- * webpage: http://miniupnp.free.fr/ or http://miniupnp.tuxfamily.org/
- * Author : Thomas Bernard
-
-Copyright (c) 2005-2007, Thomas BERNARD
-All rights reserved.
-
-Redistribution and use in source and binary forms, with or without
-modification, are permitted provided that the following conditions are met:
-
- * Redistributions of source code must retain the above copyright notice,
- this list of conditions and the following disclaimer.
- * Redistributions in binary form must reproduce the above copyright notice,
- this list of conditions and the following disclaimer in the documentation
- and/or other materials provided with the distribution.
- * The name of the author may not be used to endorse or promote products
- derived from this software without specific prior written permission.
-
-THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS"
-AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
-IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
-ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE
-LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
-CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
-SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
-INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
-CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
-ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
-POSSIBILITY OF SUCH DAMAGE.
-*/
-#include "minixml.h"
-
-/* parseatt : used to parse the argument list
- * return 0 (false) in case of success and -1 (true) if the end
- * of the xmlbuffer is reached. */
-int
-parseatt (struct xmlparser *p)
-{
- const char *attname;
- int attnamelen;
- const char *attvalue;
- int attvaluelen;
- while (p->xml < p->xmlend)
- {
- if (*p->xml == '/' || *p->xml == '>')
- return 0;
- if (!IS_WHITE_SPACE (*p->xml))
- {
- char sep;
- attname = p->xml;
- attnamelen = 0;
- while (*p->xml != '=' && !IS_WHITE_SPACE (*p->xml))
- {
- attnamelen++;
- p->xml++;
- if (p->xml >= p->xmlend)
- return -1;
- }
- while (*(p->xml++) != '=')
- {
- if (p->xml >= p->xmlend)
- return -1;
- }
- while (IS_WHITE_SPACE (*p->xml))
- {
- p->xml++;
- if (p->xml >= p->xmlend)
- return -1;
- }
- sep = *p->xml;
- if (sep == '\'' || sep == '\"')
- {
- p->xml++;
- if (p->xml >= p->xmlend)
- return -1;
- attvalue = p->xml;
- attvaluelen = 0;
- while (*p->xml != sep)
- {
- attvaluelen++;
- p->xml++;
- if (p->xml >= p->xmlend)
- return -1;
- }
- }
- else
- {
- attvalue = p->xml;
- attvaluelen = 0;
- while (!IS_WHITE_SPACE (*p->xml)
- && *p->xml != '>' && *p->xml != '/')
- {
- attvaluelen++;
- p->xml++;
- if (p->xml >= p->xmlend)
- return -1;
- }
- }
- /*printf("%.*s='%.*s'\n",
- attnamelen, attname, attvaluelen, attvalue); */
- if (p->attfunc)
- p->attfunc (p->data, attname, attnamelen, attvalue, attvaluelen);
- }
- p->xml++;
- }
- return -1;
-}
-
-/* parseelt parse the xml stream and
- * call the callback functions when needed... */
-void
-parseelt (struct xmlparser *p)
-{
- int i;
- const char *elementname;
- while (p->xml < (p->xmlend - 1))
- {
- if ((p->xml)[0] == '<' && (p->xml)[1] != '?')
- {
- i = 0;
- elementname = ++p->xml;
- while (!IS_WHITE_SPACE (*p->xml)
- && (*p->xml != '>') && (*p->xml != '/'))
- {
- i++;
- p->xml++;
- if (p->xml >= p->xmlend)
- return;
- /* to ignore namespace : */
- if (*p->xml == ':')
- {
- i = 0;
- elementname = ++p->xml;
- }
- }
- if (i > 0)
- {
- if (p->starteltfunc)
- p->starteltfunc (p->data, elementname, i);
- if (parseatt (p))
- return;
- if (*p->xml != '/')
- {
- const char *data;
- i = 0;
- data = ++p->xml;
- if (p->xml >= p->xmlend)
- return;
- while (IS_WHITE_SPACE (*p->xml))
- {
- p->xml++;
- if (p->xml >= p->xmlend)
- return;
- }
- while (*p->xml != '<')
- {
- i++;
- p->xml++;
- if (p->xml >= p->xmlend)
- return;
- }
- if (i > 0 && p->datafunc)
- p->datafunc (p->data, data, i);
- }
- }
- else if (*p->xml == '/')
- {
- i = 0;
- elementname = ++p->xml;
- if (p->xml >= p->xmlend)
- return;
- while ((*p->xml != '>'))
- {
- i++;
- p->xml++;
- if (p->xml >= p->xmlend)
- return;
- }
- if (p->endeltfunc)
- p->endeltfunc (p->data, elementname, i);
- p->xml++;
- }
- }
- else
- {
- p->xml++;
- }
- }
-}
-
-/* the parser must be initialized before calling this function */
-void
-parsexml (struct xmlparser *parser)
-{
- parser->xml = parser->xmlstart;
- parser->xmlend = parser->xmlstart + parser->xmlsize;
- parseelt (parser);
-}
+++ /dev/null
-/* $Id: minixml.h,v 1.6 2006/11/30 11:47:21 nanard Exp $ */
-/* minimal xml parser
- *
- * Project : miniupnp
- * Website : http://miniupnp.free.fr/
- * Author : Thomas Bernard
- * Copyright (c) 2005 Thomas Bernard
- * This software is subject to the conditions detailed in the
- * LICENCE file provided in this distribution.
- * */
-#ifndef __MINIXML_H__
-#define __MINIXML_H__
-#define IS_WHITE_SPACE(c) ((c==' ') || (c=='\t') || (c=='\r') || (c=='\n'))
-
-/* if a callback function pointer is set to NULL,
- * the function is not called */
-struct xmlparser
-{
- const char *xmlstart;
- const char *xmlend;
- const char *xml; /* pointer to current character */
- int xmlsize;
- void *data;
- void (*starteltfunc) (void *, const char *, int);
- void (*endeltfunc) (void *, const char *, int);
- void (*datafunc) (void *, const char *, int);
- void (*attfunc) (void *, const char *, int, const char *, int);
-};
-
-/* parsexml()
- * the xmlparser structure must be initialized before the call
- * the following structure members have to be initialized :
- * xmlstart, xmlsize, data, *func
- * xml is for internal usage, xmlend is computed automatically */
-void parsexml (struct xmlparser *);
-
-#endif
+++ /dev/null
-/* $Id: upnpcommands.c,v 1.24 2009/04/17 21:21:19 nanard Exp $ */
-/* Project : miniupnp
- * Author : Thomas Bernard
- * Copyright (c) 2005-2009 Thomas Bernard
- * This software is subject to the conditions detailed in the
- * LICENCE file provided in this distribution.
- * */
-#include <stdlib.h>
-#include <stdio.h>
-#include <string.h>
-#include "upnpcommands.h"
-#include "miniupnpc.h"
-
-static UNSIGNED_INTEGER
-my_atoui (const char *s)
-{
- return s ? ((UNSIGNED_INTEGER) STRTOUI (s, NULL, 0)) : 0;
-}
-
-/*
- * */
-UNSIGNED_INTEGER
-UPNP_GetTotalBytesSent (const char *controlURL, const char *servicetype)
-{
- struct NameValueParserData pdata;
- char buffer[4096];
- int bufsize = 4096;
- unsigned int r = 0;
- char *p;
- simpleUPnPcommand (-1, controlURL, servicetype, "GetTotalBytesSent", 0,
- buffer, &bufsize);
- ParseNameValue (buffer, bufsize, &pdata);
- /*DisplayNameValueList(buffer, bufsize); */
- p = GetValueFromNameValueList (&pdata, "NewTotalBytesSent");
- r = my_atoui (p);
- ClearNameValueList (&pdata);
- return r;
-}
-
-/*
- * */
-UNSIGNED_INTEGER
-UPNP_GetTotalBytesReceived (const char *controlURL, const char *servicetype)
-{
- struct NameValueParserData pdata;
- char buffer[4096];
- int bufsize = 4096;
- unsigned int r = 0;
- char *p;
- simpleUPnPcommand (-1, controlURL, servicetype, "GetTotalBytesReceived", 0,
- buffer, &bufsize);
- ParseNameValue (buffer, bufsize, &pdata);
- /*DisplayNameValueList(buffer, bufsize); */
- p = GetValueFromNameValueList (&pdata, "NewTotalBytesReceived");
- r = my_atoui (p);
- ClearNameValueList (&pdata);
- return r;
-}
-
-/*
- * */
-UNSIGNED_INTEGER
-UPNP_GetTotalPacketsSent (const char *controlURL, const char *servicetype)
-{
- struct NameValueParserData pdata;
- char buffer[4096];
- int bufsize = 4096;
- unsigned int r = 0;
- char *p;
- simpleUPnPcommand (-1, controlURL, servicetype, "GetTotalPacketsSent", 0,
- buffer, &bufsize);
- ParseNameValue (buffer, bufsize, &pdata);
- /*DisplayNameValueList(buffer, bufsize); */
- p = GetValueFromNameValueList (&pdata, "NewTotalPacketsSent");
- r = my_atoui (p);
- ClearNameValueList (&pdata);
- return r;
-}
-
-/*
- * */
-UNSIGNED_INTEGER
-UPNP_GetTotalPacketsReceived (const char *controlURL, const char *servicetype)
-{
- struct NameValueParserData pdata;
- char buffer[4096];
- int bufsize = 4096;
- unsigned int r = 0;
- char *p;
- simpleUPnPcommand (-1, controlURL, servicetype, "GetTotalPacketsReceived",
- 0, buffer, &bufsize);
- ParseNameValue (buffer, bufsize, &pdata);
- /*DisplayNameValueList(buffer, bufsize); */
- p = GetValueFromNameValueList (&pdata, "NewTotalPacketsReceived");
- r = my_atoui (p);
- ClearNameValueList (&pdata);
- return r;
-}
-
-/* UPNP_GetStatusInfo() call the corresponding UPNP method
- * returns the current status and uptime */
-int
-UPNP_GetStatusInfo (const char *controlURL,
- const char *servicetype,
- char *status, unsigned int *uptime, char *lastconnerror)
-{
- struct NameValueParserData pdata;
- char buffer[4096];
- int bufsize = 4096;
- char *p;
- char *up;
- char *err;
- int ret = UPNPCOMMAND_UNKNOWN_ERROR;
-
- if (!status && !uptime)
- return UPNPCOMMAND_INVALID_ARGS;
-
- simpleUPnPcommand (-1, controlURL, servicetype, "GetStatusInfo", 0, buffer,
- &bufsize);
- ParseNameValue (buffer, bufsize, &pdata);
- /*DisplayNameValueList(buffer, bufsize); */
- up = GetValueFromNameValueList (&pdata, "NewUptime");
- p = GetValueFromNameValueList (&pdata, "NewConnectionStatus");
- err = GetValueFromNameValueList (&pdata, "NewLastConnectionError");
- if (p && up)
- ret = UPNPCOMMAND_SUCCESS;
-
- if (status)
- {
- if (p)
- {
- strncpy (status, p, 64);
- status[63] = '\0';
- }
- else
- status[0] = '\0';
- }
-
- if (uptime)
- {
- if (up)
- sscanf (up, "%u", uptime);
- else
- uptime = 0;
- }
-
- if (lastconnerror)
- {
- if (err)
- {
- strncpy (lastconnerror, err, 64);
- lastconnerror[63] = '\0';
- }
- else
- lastconnerror[0] = '\0';
- }
-
- p = GetValueFromNameValueList (&pdata, "errorCode");
- if (p)
- {
- ret = UPNPCOMMAND_UNKNOWN_ERROR;
- sscanf (p, "%d", &ret);
- }
- ClearNameValueList (&pdata);
- return ret;
-}
-
-/* UPNP_GetConnectionTypeInfo() call the corresponding UPNP method
- * returns the connection type */
-int
-UPNP_GetConnectionTypeInfo (const char *controlURL,
- const char *servicetype, char *connectionType)
-{
- struct NameValueParserData pdata;
- char buffer[4096];
- int bufsize = 4096;
- char *p;
- int ret = UPNPCOMMAND_UNKNOWN_ERROR;
-
- if (!connectionType)
- return UPNPCOMMAND_INVALID_ARGS;
-
- simpleUPnPcommand (-1, controlURL, servicetype,
- "GetConnectionTypeInfo", 0, buffer, &bufsize);
- ParseNameValue (buffer, bufsize, &pdata);
- p = GetValueFromNameValueList (&pdata, "NewConnectionType");
- /*p = GetValueFromNameValueList(&pdata, "NewPossibleConnectionTypes"); */
- /* PossibleConnectionTypes will have several values.... */
- if (p)
- {
- strncpy (connectionType, p, 64);
- connectionType[63] = '\0';
- ret = UPNPCOMMAND_SUCCESS;
- }
- else
- connectionType[0] = '\0';
- p = GetValueFromNameValueList (&pdata, "errorCode");
- if (p)
- {
- ret = UPNPCOMMAND_UNKNOWN_ERROR;
- sscanf (p, "%d", &ret);
- }
- ClearNameValueList (&pdata);
- return ret;
-}
-
-/* UPNP_GetLinkLayerMaxBitRate() call the corresponding UPNP method.
- * Returns 2 values: Downloadlink bandwidth and Uplink bandwidth.
- * One of the values can be null
- * Note : GetLinkLayerMaxBitRates belongs to WANPPPConnection:1 only
- * We can use the GetCommonLinkProperties from WANCommonInterfaceConfig:1 */
-int
-UPNP_GetLinkLayerMaxBitRates (const char *controlURL, const char *servicetype,
- unsigned int *bitrateDown,
- unsigned int *bitrateUp)
-{
- struct NameValueParserData pdata;
- char buffer[4096];
- int bufsize = 4096;
- int ret = UPNPCOMMAND_UNKNOWN_ERROR;
- char *down;
- char *up;
- char *p;
-
- if (!bitrateDown && !bitrateUp)
- return UPNPCOMMAND_INVALID_ARGS;
-
- /* shouldn't we use GetCommonLinkProperties ? */
- simpleUPnPcommand (-1, controlURL, servicetype,
- "GetCommonLinkProperties", 0, buffer, &bufsize);
- /*"GetLinkLayerMaxBitRates", 0, buffer, &bufsize); */
- /*DisplayNameValueList(buffer, bufsize); */
- ParseNameValue (buffer, bufsize, &pdata);
- /*down = GetValueFromNameValueList(&pdata, "NewDownstreamMaxBitRate"); */
- /*up = GetValueFromNameValueList(&pdata, "NewUpstreamMaxBitRate"); */
- down = GetValueFromNameValueList (&pdata, "NewLayer1DownstreamMaxBitRate");
- up = GetValueFromNameValueList (&pdata, "NewLayer1UpstreamMaxBitRate");
- /*GetValueFromNameValueList(&pdata, "NewWANAccessType"); */
- /*GetValueFromNameValueList(&pdata, "NewPhysicalLinkSatus"); */
- if (down && up)
- ret = UPNPCOMMAND_SUCCESS;
-
- if (bitrateDown)
- {
- if (down)
- sscanf (down, "%u", bitrateDown);
- else
- *bitrateDown = 0;
- }
-
- if (bitrateUp)
- {
- if (up)
- sscanf (up, "%u", bitrateUp);
- else
- *bitrateUp = 0;
- }
- p = GetValueFromNameValueList (&pdata, "errorCode");
- if (p)
- {
- ret = UPNPCOMMAND_UNKNOWN_ERROR;
- sscanf (p, "%d", &ret);
- }
- ClearNameValueList (&pdata);
- return ret;
-}
-
-
-/* UPNP_GetExternalIPAddress() call the corresponding UPNP method.
- * if the third arg is not null the value is copied to it.
- * at least 128 bytes must be available
- *
- * Return values :
- * 0 : SUCCESS
- * NON ZERO : ERROR Either an UPnP error code or an unknown error.
- *
- * 402 Invalid Args - See UPnP Device Architecture section on Control.
- * 501 Action Failed - See UPnP Device Architecture section on Control.
- */
-int
-UPNP_GetExternalIPAddress (const char *controlURL,
- const char *servicetype, char *extIpAdd)
-{
- struct NameValueParserData pdata;
- char buffer[4096];
- int bufsize = 4096;
- char *p;
- int ret = UPNPCOMMAND_UNKNOWN_ERROR;
-
- if (!extIpAdd || !controlURL || !servicetype)
- return UPNPCOMMAND_INVALID_ARGS;
-
- simpleUPnPcommand (-1, controlURL, servicetype, "GetExternalIPAddress", 0,
- buffer, &bufsize);
- /*DisplayNameValueList(buffer, bufsize); */
- ParseNameValue (buffer, bufsize, &pdata);
- /*printf("external ip = %s\n", GetValueFromNameValueList(&pdata, "NewExternalIPAddress") ); */
- p = GetValueFromNameValueList (&pdata, "NewExternalIPAddress");
- if (p)
- {
- strncpy (extIpAdd, p, 128);
- extIpAdd[127] = '\0';
- ret = UPNPCOMMAND_SUCCESS;
- }
- else
- extIpAdd[0] = '\0';
-
- p = GetValueFromNameValueList (&pdata, "errorCode");
- if (p)
- {
- ret = UPNPCOMMAND_UNKNOWN_ERROR;
- sscanf (p, "%d", &ret);
- }
-
- ClearNameValueList (&pdata);
- return ret;
-}
-
-int
-UPNP_AddPortMapping (const char *controlURL, const char *servicetype,
- const char *extPort,
- const char *inPort,
- const char *inClient,
- const char *desc,
- const char *proto, const char *remoteHost)
-{
- struct UPNParg *AddPortMappingArgs;
- char buffer[4096];
- int bufsize = 4096;
- struct NameValueParserData pdata;
- const char *resVal;
- int ret;
-
- if (!inPort || !inClient || !proto || !extPort)
- return UPNPCOMMAND_INVALID_ARGS;
-
- AddPortMappingArgs = calloc (9, sizeof (struct UPNParg));
- AddPortMappingArgs[0].elt = "NewRemoteHost";
- AddPortMappingArgs[0].val = remoteHost;
- AddPortMappingArgs[1].elt = "NewExternalPort";
- AddPortMappingArgs[1].val = extPort;
- AddPortMappingArgs[2].elt = "NewProtocol";
- AddPortMappingArgs[2].val = proto;
- AddPortMappingArgs[3].elt = "NewInternalPort";
- AddPortMappingArgs[3].val = inPort;
- AddPortMappingArgs[4].elt = "NewInternalClient";
- AddPortMappingArgs[4].val = inClient;
- AddPortMappingArgs[5].elt = "NewEnabled";
- AddPortMappingArgs[5].val = "1";
- AddPortMappingArgs[6].elt = "NewPortMappingDescription";
- AddPortMappingArgs[6].val = desc ? desc : "libminiupnpc";
- AddPortMappingArgs[7].elt = "NewLeaseDuration";
- AddPortMappingArgs[7].val = "0";
- simpleUPnPcommand (-1, controlURL, servicetype, "AddPortMapping",
- AddPortMappingArgs, buffer, &bufsize);
- /*DisplayNameValueList(buffer, bufsize); */
- /*buffer[bufsize] = '\0'; */
- /*puts(buffer); */
- ParseNameValue (buffer, bufsize, &pdata);
- resVal = GetValueFromNameValueList (&pdata, "errorCode");
- if (resVal)
- {
- /* printf("AddPortMapping errorCode = '%s'\n", resVal); */
- ret = UPNPCOMMAND_UNKNOWN_ERROR;
- sscanf (resVal, "%d", &ret);
- }
- else
- {
- ret = UPNPCOMMAND_SUCCESS;
- }
- ClearNameValueList (&pdata);
- free (AddPortMappingArgs);
- return ret;
-}
-
-int
-UPNP_DeletePortMapping (const char *controlURL, const char *servicetype,
- const char *extPort, const char *proto,
- const char *remoteHost)
-{
- /*struct NameValueParserData pdata; */
- struct UPNParg *DeletePortMappingArgs;
- char buffer[4096];
- int bufsize = 4096;
- struct NameValueParserData pdata;
- const char *resVal;
- int ret;
-
- if (!extPort || !proto)
- return UPNPCOMMAND_INVALID_ARGS;
-
- DeletePortMappingArgs = calloc (4, sizeof (struct UPNParg));
- DeletePortMappingArgs[0].elt = "NewRemoteHost";
- DeletePortMappingArgs[0].val = remoteHost;
- DeletePortMappingArgs[1].elt = "NewExternalPort";
- DeletePortMappingArgs[1].val = extPort;
- DeletePortMappingArgs[2].elt = "NewProtocol";
- DeletePortMappingArgs[2].val = proto;
- simpleUPnPcommand (-1, controlURL, servicetype,
- "DeletePortMapping",
- DeletePortMappingArgs, buffer, &bufsize);
- /*DisplayNameValueList(buffer, bufsize); */
- ParseNameValue (buffer, bufsize, &pdata);
- resVal = GetValueFromNameValueList (&pdata, "errorCode");
- if (resVal)
- {
- ret = UPNPCOMMAND_UNKNOWN_ERROR;
- sscanf (resVal, "%d", &ret);
- }
- else
- {
- ret = UPNPCOMMAND_SUCCESS;
- }
- ClearNameValueList (&pdata);
- free (DeletePortMappingArgs);
- return ret;
-}
-
-int
-UPNP_GetGenericPortMappingEntry (const char *controlURL,
- const char *servicetype,
- const char *index,
- char *extPort,
- char *intClient,
- char *intPort,
- char *protocol,
- char *desc,
- char *enabled, char *rHost, char *duration)
-{
- struct NameValueParserData pdata;
- struct UPNParg *GetPortMappingArgs;
- char buffer[4096];
- int bufsize = 4096;
- char *p;
- int r = UPNPCOMMAND_UNKNOWN_ERROR;
- if (!index)
- return UPNPCOMMAND_INVALID_ARGS;
-
- GetPortMappingArgs = calloc (2, sizeof (struct UPNParg));
- GetPortMappingArgs[0].elt = "NewPortMappingIndex";
- GetPortMappingArgs[0].val = index;
- simpleUPnPcommand (-1, controlURL, servicetype,
- "GetGenericPortMappingEntry",
- GetPortMappingArgs, buffer, &bufsize);
- ParseNameValue (buffer, bufsize, &pdata);
- p = GetValueFromNameValueList (&pdata, "NewRemoteHost");
- if (p && rHost)
- {
- strncpy (rHost, p, 64);
- rHost[63] = '\0';
- }
- p = GetValueFromNameValueList (&pdata, "NewExternalPort");
- if (p && extPort)
- {
- strncpy (extPort, p, 6);
- extPort[5] = '\0';
- r = UPNPCOMMAND_SUCCESS;
- }
- p = GetValueFromNameValueList (&pdata, "NewProtocol");
- if (p && protocol)
- {
- strncpy (protocol, p, 4);
- protocol[3] = '\0';
- }
- p = GetValueFromNameValueList (&pdata, "NewInternalClient");
- if (p && intClient)
- {
- strncpy (intClient, p, 128);
- intClient[127] = '\0';
- r = 0;
- }
- p = GetValueFromNameValueList (&pdata, "NewInternalPort");
- if (p && intPort)
- {
- strncpy (intPort, p, 6);
- intPort[5] = '\0';
- }
- p = GetValueFromNameValueList (&pdata, "NewEnabled");
- if (p && enabled)
- {
- strncpy (enabled, p, 4);
- enabled[3] = '\0';
- }
- p = GetValueFromNameValueList (&pdata, "NewPortMappingDescription");
- if (p && desc)
- {
- strncpy (desc, p, 80);
- desc[79] = '\0';
- }
- p = GetValueFromNameValueList (&pdata, "NewLeaseDuration");
- if (p && duration)
- {
- strncpy (duration, p, 16);
- duration[15] = '\0';
- }
- p = GetValueFromNameValueList (&pdata, "errorCode");
- if (p)
- {
- r = UPNPCOMMAND_UNKNOWN_ERROR;
- sscanf (p, "%d", &r);
- }
- ClearNameValueList (&pdata);
- free (GetPortMappingArgs);
- return r;
-}
-
-int
-UPNP_GetPortMappingNumberOfEntries (const char *controlURL,
- const char *servicetype,
- unsigned int *numEntries)
-{
- struct NameValueParserData pdata;
- char buffer[4096];
- int bufsize = 4096;
- char *p;
- int ret = UPNPCOMMAND_UNKNOWN_ERROR;
- simpleUPnPcommand (-1, controlURL, servicetype,
- "GetPortMappingNumberOfEntries", 0, buffer, &bufsize);
-#ifdef DEBUG
- DisplayNameValueList (buffer, bufsize);
-#endif
- ParseNameValue (buffer, bufsize, &pdata);
-
- p = GetValueFromNameValueList (&pdata, "NewPortMappingNumberOfEntries");
- if (numEntries && p)
- {
- *numEntries = 0;
- sscanf (p, "%u", numEntries);
- ret = UPNPCOMMAND_SUCCESS;
- }
-
- p = GetValueFromNameValueList (&pdata, "errorCode");
- if (p)
- {
- ret = UPNPCOMMAND_UNKNOWN_ERROR;
- sscanf (p, "%d", &ret);
- }
-
- ClearNameValueList (&pdata);
- return ret;
-}
-
-/* UPNP_GetSpecificPortMappingEntry retrieves an existing port mapping
- * the result is returned in the intClient and intPort strings
- * please provide 128 and 6 bytes of data */
-int
-UPNP_GetSpecificPortMappingEntry (const char *controlURL,
- const char *servicetype,
- const char *extPort,
- const char *proto,
- char *intClient, char *intPort)
-{
- struct NameValueParserData pdata;
- struct UPNParg *GetPortMappingArgs;
- char buffer[4096];
- int bufsize = 4096;
- char *p;
- int ret = UPNPCOMMAND_UNKNOWN_ERROR;
-
- if (!intPort || !intClient || !extPort || !proto)
- return UPNPCOMMAND_INVALID_ARGS;
-
- GetPortMappingArgs = calloc (4, sizeof (struct UPNParg));
- GetPortMappingArgs[0].elt = "NewRemoteHost";
- GetPortMappingArgs[1].elt = "NewExternalPort";
- GetPortMappingArgs[1].val = extPort;
- GetPortMappingArgs[2].elt = "NewProtocol";
- GetPortMappingArgs[2].val = proto;
- simpleUPnPcommand (-1, controlURL, servicetype,
- "GetSpecificPortMappingEntry",
- GetPortMappingArgs, buffer, &bufsize);
- /*fd = simpleUPnPcommand(fd, controlURL, data.servicetype, "GetSpecificPortMappingEntry", AddPortMappingArgs, buffer, &bufsize); */
- /*DisplayNameValueList(buffer, bufsize); */
- ParseNameValue (buffer, bufsize, &pdata);
-
- p = GetValueFromNameValueList (&pdata, "NewInternalClient");
- if (p)
- {
- strncpy (intClient, p, 128);
- intClient[127] = '\0';
- ret = UPNPCOMMAND_SUCCESS;
- }
- else
- intClient[0] = '\0';
-
- p = GetValueFromNameValueList (&pdata, "NewInternalPort");
- if (p)
- {
- strncpy (intPort, p, 6);
- intPort[5] = '\0';
- }
- else
- intPort[0] = '\0';
-
- p = GetValueFromNameValueList (&pdata, "errorCode");
- if (p)
- {
- ret = UPNPCOMMAND_UNKNOWN_ERROR;
- sscanf (p, "%d", &ret);
- }
-
- ClearNameValueList (&pdata);
- free (GetPortMappingArgs);
- return ret;
-}
+++ /dev/null
-/* $Id: upnpcommands.h,v 1.17 2009/04/17 21:21:19 nanard Exp $ */
-/* Miniupnp project : http://miniupnp.free.fr/
- * Author : Thomas Bernard
- * Copyright (c) 2005-2008 Thomas Bernard
- * This software is subject to the conditions detailed in the
- * LICENCE file provided within this distribution */
-#ifndef __UPNPCOMMANDS_H__
-#define __UPNPCOMMANDS_H__
-
-#include "upnpreplyparse.h"
-#include "declspec.h"
-
-/* MiniUPnPc return codes : */
-#define UPNPCOMMAND_SUCCESS (0)
-#define UPNPCOMMAND_UNKNOWN_ERROR (-1)
-#define UPNPCOMMAND_INVALID_ARGS (-2)
-
-#ifdef __cplusplus
-extern "C"
-{
-#endif
-
-#if (defined __STDC_VERSION__ && __STDC_VERSION__ >= 199901L)
-#define UNSIGNED_INTEGER unsigned long long
-#define STRTOUI strtoull
-#else
-#define UNSIGNED_INTEGER unsigned int
-#define STRTOUI strtoul
-#endif
-
- LIBSPEC UNSIGNED_INTEGER
- UPNP_GetTotalBytesSent (const char *controlURL, const char *servicetype);
-
- LIBSPEC UNSIGNED_INTEGER
- UPNP_GetTotalBytesReceived (const char *controlURL,
- const char *servicetype);
-
- LIBSPEC UNSIGNED_INTEGER
- UPNP_GetTotalPacketsSent (const char *controlURL,
- const char *servicetype);
-
- LIBSPEC UNSIGNED_INTEGER
- UPNP_GetTotalPacketsReceived (const char *controlURL,
- const char *servicetype);
-
-/* UPNP_GetStatusInfo()
- * status and lastconnerror are 64 byte buffers
- * Return values :
- * UPNPCOMMAND_SUCCESS, UPNPCOMMAND_INVALID_ARGS, UPNPCOMMAND_UNKNOWN_ERROR
- * or a UPnP Error code */
- LIBSPEC int
- UPNP_GetStatusInfo (const char *controlURL,
- const char *servicetype,
- char *status,
- unsigned int *uptime, char *lastconnerror);
-
-/* UPNP_GetConnectionTypeInfo()
- * argument connectionType is a 64 character buffer
- * Return Values :
- * UPNPCOMMAND_SUCCESS, UPNPCOMMAND_INVALID_ARGS, UPNPCOMMAND_UNKNOWN_ERROR
- * or a UPnP Error code */
- LIBSPEC int
- UPNP_GetConnectionTypeInfo (const char *controlURL,
- const char *servicetype,
- char *connectionType);
-
-/* UPNP_GetExternalIPAddress() call the corresponding UPNP method.
- * if the third arg is not null the value is copied to it.
- * at least 128 bytes must be available
- *
- * Return values :
- * 0 : SUCCESS
- * NON ZERO : ERROR Either an UPnP error code or an unknown error.
- *
- * possible UPnP Errors :
- * 402 Invalid Args - See UPnP Device Architecture section on Control.
- * 501 Action Failed - See UPnP Device Architecture section on Control. */
- LIBSPEC int
- UPNP_GetExternalIPAddress (const char *controlURL,
- const char *servicetype, char *extIpAdd);
-
-/* UPNP_GetLinkLayerMaxBitRates()
- * call WANCommonInterfaceConfig:1#GetCommonLinkProperties
- *
- * return values :
- * UPNPCOMMAND_SUCCESS, UPNPCOMMAND_INVALID_ARGS, UPNPCOMMAND_UNKNOWN_ERROR
- * or a UPnP Error Code. */
- LIBSPEC int
- UPNP_GetLinkLayerMaxBitRates (const char *controlURL,
- const char *servicetype,
- unsigned int *bitrateDown,
- unsigned int *bitrateUp);
-
-/* UPNP_AddPortMapping()
- * if desc is NULL, it will be defaulted to "libminiupnpc"
- * remoteHost is usually NULL because IGD don't support it.
- *
- * Return values :
- * 0 : SUCCESS
- * NON ZERO : ERROR. Either an UPnP error code or an unknown error.
- *
- * List of possible UPnP errors for AddPortMapping :
- * errorCode errorDescription (short) - Description (long)
- * 402 Invalid Args - See UPnP Device Architecture section on Control.
- * 501 Action Failed - See UPnP Device Architecture section on Control.
- * 715 WildCardNotPermittedInSrcIP - The source IP address cannot be
- * wild-carded
- * 716 WildCardNotPermittedInExtPort - The external port cannot be wild-carded
- * 718 ConflictInMappingEntry - The port mapping entry specified conflicts
- * with a mapping assigned previously to another client
- * 724 SamePortValuesRequired - Internal and External port values
- * must be the same
- * 725 OnlyPermanentLeasesSupported - The NAT implementation only supports
- * permanent lease times on port mappings
- * 726 RemoteHostOnlySupportsWildcard - RemoteHost must be a wildcard
- * and cannot be a specific IP address or DNS name
- * 727 ExternalPortOnlySupportsWildcard - ExternalPort must be a wildcard and
- * cannot be a specific port value */
- LIBSPEC int
- UPNP_AddPortMapping (const char *controlURL, const char *servicetype,
- const char *extPort,
- const char *inPort,
- const char *inClient,
- const char *desc,
- const char *proto, const char *remoteHost);
-
-/* UPNP_DeletePortMapping()
- * Use same argument values as what was used for AddPortMapping().
- * remoteHost is usually NULL because IGD don't support it.
- * Return Values :
- * 0 : SUCCESS
- * NON ZERO : error. Either an UPnP error code or an undefined error.
- *
- * List of possible UPnP errors for DeletePortMapping :
- * 402 Invalid Args - See UPnP Device Architecture section on Control.
- * 714 NoSuchEntryInArray - The specified value does not exist in the array */
- LIBSPEC int
- UPNP_DeletePortMapping (const char *controlURL, const char *servicetype,
- const char *extPort, const char *proto,
- const char *remoteHost);
-
-/* UPNP_GetPortMappingNumberOfEntries()
- * not supported by all routers */
- LIBSPEC int
- UPNP_GetPortMappingNumberOfEntries (const char *controlURL,
- const char *servicetype,
- unsigned int *num);
-
-/* UPNP_GetSpecificPortMappingEntry retrieves an existing port mapping
- * the result is returned in the intClient and intPort strings
- * please provide 128 and 6 bytes of data
- *
- * return value :
- * UPNPCOMMAND_SUCCESS, UPNPCOMMAND_INVALID_ARGS, UPNPCOMMAND_UNKNOWN_ERROR
- * or a UPnP Error Code. */
- LIBSPEC int
- UPNP_GetSpecificPortMappingEntry (const char *controlURL,
- const char *servicetype,
- const char *extPort,
- const char *proto,
- char *intClient, char *intPort);
-
-/* UPNP_GetGenericPortMappingEntry()
- *
- * return value :
- * UPNPCOMMAND_SUCCESS, UPNPCOMMAND_INVALID_ARGS, UPNPCOMMAND_UNKNOWN_ERROR
- * or a UPnP Error Code.
- *
- * Possible UPNP Error codes :
- * 402 Invalid Args - See UPnP Device Architecture section on Control.
- * 713 SpecifiedArrayIndexInvalid - The specified array index is out of bounds
- */
- LIBSPEC int
- UPNP_GetGenericPortMappingEntry (const char *controlURL,
- const char *servicetype,
- const char *index,
- char *extPort,
- char *intClient,
- char *intPort,
- char *protocol,
- char *desc,
- char *enabled,
- char *rHost, char *duration);
-
-#ifdef __cplusplus
-}
-#endif
-
-#endif
+++ /dev/null
-/* $Id: upnpreplyparse.c,v 1.10 2008/02/21 13:05:27 nanard Exp $ */
-/* MiniUPnP project
- * http://miniupnp.free.fr/ or http://miniupnp.tuxfamily.org/
- * (c) 2006 Thomas Bernard
- * This software is subject to the conditions detailed
- * in the LICENCE file provided within the distribution */
-
-#include <stdlib.h>
-#include <string.h>
-#include <stdio.h>
-
-#include "upnpreplyparse.h"
-#include "minixml.h"
-
-static void
-NameValueParserStartElt (void *d, const char *name, int l)
-{
- struct NameValueParserData *data = (struct NameValueParserData *) d;
- if (l > 63)
- l = 63;
- memcpy (data->curelt, name, l);
- data->curelt[l] = '\0';
-}
-
-static void
-NameValueParserGetData (void *d, const char *datas, int l)
-{
- struct NameValueParserData *data = (struct NameValueParserData *) d;
- struct NameValue *nv;
- nv = malloc (sizeof (struct NameValue));
- if (l > 63)
- l = 63;
- strncpy (nv->name, data->curelt, 64);
- nv->name[63] = '\0';
- memcpy (nv->value, datas, l);
- nv->value[l] = '\0';
- LIST_INSERT_HEAD (&(data->head), nv, entries);
-}
-
-void
-ParseNameValue (const char *buffer, int bufsize,
- struct NameValueParserData *data)
-{
- struct xmlparser parser;
- LIST_INIT (&(data->head));
- /* init xmlparser object */
- parser.xmlstart = buffer;
- parser.xmlsize = bufsize;
- parser.data = data;
- parser.starteltfunc = NameValueParserStartElt;
- parser.endeltfunc = 0;
- parser.datafunc = NameValueParserGetData;
- parser.attfunc = 0;
- parsexml (&parser);
-}
-
-void
-ClearNameValueList (struct NameValueParserData *pdata)
-{
- struct NameValue *nv;
- while ((nv = pdata->head.lh_first) != NULL)
- {
- LIST_REMOVE (nv, entries);
- free (nv);
- }
-}
-
-char *
-GetValueFromNameValueList (struct NameValueParserData *pdata,
- const char *Name)
-{
- struct NameValue *nv;
- char *p = NULL;
- for (nv = pdata->head.lh_first;
- (nv != NULL) && (p == NULL); nv = nv->entries.le_next)
- {
- if (strcmp (nv->name, Name) == 0)
- p = nv->value;
- }
- return p;
-}
-
-#if 0
-/* useless now that minixml ignores namespaces by itself */
-char *
-GetValueFromNameValueListIgnoreNS (struct NameValueParserData *pdata,
- const char *Name)
-{
- struct NameValue *nv;
- char *p = NULL;
- char *pname;
- for (nv = pdata->head.lh_first;
- (nv != NULL) && (p == NULL); nv = nv->entries.le_next)
- {
- pname = strrchr (nv->name, ':');
- if (pname)
- pname++;
- else
- pname = nv->name;
- if (strcmp (pname, Name) == 0)
- p = nv->value;
- }
- return p;
-}
-#endif
-
-/* debug all-in-one function
- * do parsing then display to stdout */
-#ifdef DEBUG
-void
-DisplayNameValueList (char *buffer, int bufsize)
-{
- struct NameValueParserData pdata;
- struct NameValue *nv;
- ParseNameValue (buffer, bufsize, &pdata);
- for (nv = pdata.head.lh_first; nv != NULL; nv = nv->entries.le_next)
- {
- printf ("%s = %s\n", nv->name, nv->value);
- }
- ClearNameValueList (&pdata);
-}
-#endif
+++ /dev/null
-/* $Id: upnpreplyparse.h,v 1.8 2008/02/21 13:05:27 nanard Exp $ */
-/* MiniUPnP project
- * http://miniupnp.free.fr/ or http://miniupnp.tuxfamily.org/
- * (c) 2006 Thomas Bernard
- * This software is subject to the conditions detailed
- * in the LICENCE file provided within the distribution */
-
-#ifndef __UPNPREPLYPARSE_H__
-#define __UPNPREPLYPARSE_H__
-
-#if defined(NO_SYS_QUEUE_H) || defined(WIN32)
-#include "bsdqueue.h"
-#else
-#include <sys/queue.h>
-#endif
-
-#ifdef __cplusplus
-extern "C"
-{
-#endif
-
- struct NameValue
- {
- LIST_ENTRY (NameValue) entries;
- char name[64];
- char value[64];
- };
-
- struct NameValueParserData
- {
- LIST_HEAD (listhead, NameValue) head;
- char curelt[64];
- };
-
-/* ParseNameValue() */
- void
- ParseNameValue (const char *buffer, int bufsize,
- struct NameValueParserData *data);
-
-/* ClearNameValueList() */
- void ClearNameValueList (struct NameValueParserData *pdata);
-
-/* GetValueFromNameValueList() */
- char *GetValueFromNameValueList (struct NameValueParserData *pdata,
- const char *Name);
-
-/* GetValueFromNameValueListIgnoreNS() */
- char *GetValueFromNameValueListIgnoreNS (struct NameValueParserData *pdata,
- const char *Name);
-
-/* DisplayNameValueList() */
-#ifdef DEBUG
- void DisplayNameValueList (char *buffer, int bufsize);
-#endif
-
-#ifdef __cplusplus
-}
-#endif
-
-#endif
/*
This file is part of GNUnet.
- (C) 2009 Christian Grothoff (and other contributing authors)
+ (C) 2009, 2010 Christian Grothoff (and other contributing authors)
GNUnet is free software; you can redistribute it and/or modify
it under the terms of the GNU General Public License as published
*
* @author Milan Bouchet-Valat
*/
-#include <errno.h>
-#include <string.h>
-#include <stdio.h>
-
-#include <sys/types.h>
-
#include "platform.h"
-#include "gnunet_common.h"
#include "gnunet_util_lib.h"
#include "gnunet_nat_lib.h"
+#include "nat.h"
#include "natpmp.h"
#include "upnp.h"
-/* Component name for logging */
-#define COMP_NAT _("NAT")
-#define DEBUG
-
+/**
+ * Handle for active NAT registrations.
+ */
struct GNUNET_NAT_Handle
{
- int is_enabled;
-
- enum GNUNET_NAT_port_forwarding natpmp_status;
- enum GNUNET_NAT_port_forwarding upnp_status;
-
- int should_change;
- u_short public_port;
-
+ /**
+ * Handle for UPnP operations.
+ */
GNUNET_NAT_UPNP_Handle *upnp;
+
+ /**
+ * Handle for NAT PMP operations.
+ */
GNUNET_NAT_NATPMP_Handle *natpmp;
+ /**
+ * Scheduler.
+ */
struct GNUNET_SCHEDULER_Handle *sched;
- GNUNET_SCHEDULER_TaskIdentifier pulse_timer;
- struct sockaddr *local_addr; /* LAN address as passed by the caller */
- struct sockaddr *ext_addr; /* External address as reported by NAT box */
- struct sockaddr *contact_addr; /* External address and port where paquets are redirected*/
+ /**
+ * LAN address as passed by the caller
+ */
+ struct sockaddr *local_addr;
+
+ /**
+ * External address as reported by NAT box
+ */
+ struct sockaddr *ext_addr;
+
+ /**
+ * External address and port where packets are redirected
+ */
+ struct sockaddr *contact_addr;
+
GNUNET_NAT_AddressCallback callback;
+
+ /**
+ * Closure for 'callback'.
+ */
void *callback_cls;
+
+ GNUNET_SCHEDULER_TaskIdentifier pulse_timer;
+
+ enum GNUNET_NAT_PortState natpmp_status;
+
+ enum GNUNET_NAT_PortState upnp_status;
+
+ int is_enabled;
+
+ int should_change;
+
+ int port_mapped;
+
+ int did_warn;
+
+ uint16_t public_port;
+
};
#ifdef DEBUG
static const char *
-get_nat_state_str (int state)
+get_nat_state_str (enum GNUNET_NAT_PortState state)
{
switch (state)
{
- /* we're in the process of trying to set up port forwarding */
case GNUNET_NAT_PORT_MAPPING:
return "Starting";
-
- /* we've successfully forwarded the port */
case GNUNET_NAT_PORT_MAPPED:
return "Forwarded";
-
- /* we're cancelling the port forwarding */
case GNUNET_NAT_PORT_UNMAPPING:
return "Stopping";
-
- /* the port isn't forwarded */
case GNUNET_NAT_PORT_UNMAPPED:
return "Not forwarded";
-
case GNUNET_NAT_PORT_ERROR:
return "Redirection failed";
+ default:
+ return "not found";
}
-
- return "notfound";
}
#endif
+
static int
get_traversal_status (const struct GNUNET_NAT_Handle * s)
{
return MAX (s->natpmp_status, s->upnp_status);
}
+
/**
* Compare the sin(6)_addr fields of AF_INET or AF_INET(6) sockaddr.
* @param a first sockaddr
* @param b second sockaddr
* @return 0 if addresses are equal, non-null value otherwise */
int
-GNUNET_NAT_cmp_addr (const struct sockaddr *a, const struct sockaddr *b)
+GNUNET_NAT_cmp_addr (const struct sockaddr *a,
+ const struct sockaddr *b)
{
if (!(a && b))
return -1;
-
- if (a->sa_family == AF_INET && b->sa_family == AF_INET)
+ if ( (a->sa_family == AF_INET) && (b->sa_family == AF_INET) )
return memcmp (&(((struct sockaddr_in *) a)->sin_addr),
&(((struct sockaddr_in *) b)->sin_addr),
sizeof (struct in_addr));
- else if (a->sa_family == AF_INET6 && b->sa_family == AF_INET6)
+ if ( (a->sa_family == AF_INET6) && (b->sa_family == AF_INET6) )
return memcmp (&(((struct sockaddr_in6 *) a)->sin6_addr),
&(((struct sockaddr_in6 *) b)->sin6_addr),
sizeof (struct in6_addr));
- else
- return -1;
+ return -1;
}
-/* Deal with a new IP address or port redirection:
+
+/**
+ * Deal with a new IP address or port redirection:
* Send signals with the appropriate sockaddr (IP and port), free and changes
* or nullify the previous sockaddr. Change the port if needed.
*/
static void
-notify_change (struct GNUNET_NAT_Handle *nat, struct sockaddr *addr, int new_port_mapped)
+notify_change (struct GNUNET_NAT_Handle *nat,
+ struct sockaddr *addr,
+ size_t addrlen,
+ int new_port_mapped)
{
- static int port_mapped = GNUNET_NO;
-
- /* Nothing to do. We already check in nat_pulse() that addr has changed */
- if (new_port_mapped == port_mapped)
+ if (new_port_mapped == nat->port_mapped)
return;
-
- port_mapped = new_port_mapped;
-
- if (nat->contact_addr && nat->callback)
- (*nat->callback) (nat->callback_cls, GNUNET_NO, (struct sockaddr *) &nat->contact_addr,
- sizeof (nat->contact_addr));
-
- /* At this point, we're sure contact_addr has changed */
- if (nat->contact_addr)
- {
- GNUNET_free (nat->contact_addr);
- nat->contact_addr = NULL;
- }
-
- /* No address, don't signal a new one */
- if (!addr)
- {
- if (nat->ext_addr)
- GNUNET_free (nat->ext_addr);
- nat->ext_addr = NULL;
- return;
- }
- /* Copy the new address and use it */
- else if (addr != nat->ext_addr)
- {
- if (nat->ext_addr)
- GNUNET_free (nat->ext_addr);
- nat->ext_addr = GNUNET_malloc (sizeof (*addr));
- memcpy (nat->ext_addr, addr, sizeof (*addr));
- }
+ nat->port_mapped = new_port_mapped;
+
+ if ( (NULL != nat->contact_addr) &&
+ (NULL != nat->callback) )
+ nat->callback (nat->callback_cls,
+ GNUNET_NO,
+ nat->contact_addr,
+ sizeof (nat->contact_addr));
+ GNUNET_free_non_null (nat->contact_addr);
+ nat->contact_addr = NULL;
+ GNUNET_free_non_null (nat->ext_addr);
+ nat->ext_addr = NULL;
+ if (NULL == addr)
+ return;
+ nat->ext_addr = GNUNET_malloc (addrlen);
+ memcpy (nat->ext_addr, addr, addrlen);
/* Recreate the ext_addr:public_port bogus address to pass to the callback */
if (nat->ext_addr->sa_family == AF_INET)
{
- struct sockaddr_in *tmp_addr;
+ struct sockaddr_in tmp_addr;
+
tmp_addr = GNUNET_malloc (sizeof (struct sockaddr_in));
tmp_addr->sin_family = AF_INET;
#ifdef HAVE_SOCKADDR_IN_SIN_LEN
tmp_addr->sin_port = port_mapped ? htons (nat->public_port) : 0;
tmp_addr->sin_addr = ((struct sockaddr_in *) nat->ext_addr)->sin_addr;
nat->contact_addr = (struct sockaddr *) tmp_addr;
- if (nat->callback)
- (*nat->callback) (nat->callback_cls, GNUNET_YES, nat->contact_addr,
- sizeof (struct sockaddr_in));
+ if (NULL != nat->callback)
+ nat->callback (nat->callback_cls,
+ GNUNET_YES,
+ nat->contact_addr,
+ sizeof (struct sockaddr_in));
}
else if (nat->ext_addr->sa_family == AF_INET6)
{
struct sockaddr_in6 *tmp_addr;
+
tmp_addr = GNUNET_malloc (sizeof (struct sockaddr_in6));
tmp_addr->sin6_family = AF_INET6;
#ifdef HAVE_SOCKADDR_IN_SIN_LEN
tmp_addr->sin6_port = port_mapped ? htons (nat->public_port) : 0;
tmp_addr->sin6_addr = ((struct sockaddr_in6 *) nat->ext_addr)->sin6_addr;
nat->contact_addr = (struct sockaddr *) tmp_addr;
- if (nat->callback)
- (*nat->callback) (nat->callback_cls, GNUNET_YES, nat->contact_addr,
- sizeof (struct sockaddr_in6));
+ if (NULL != nat->callback)
+ nat->callback (nat->callback_cls,
+ GNUNET_YES,
+ nat->contact_addr,
+ sizeof (struct sockaddr_in6));
+ }
+ else
+ {
+ GNUNET_break (0);
}
}
+
static void
-nat_pulse (void *cls, const struct GNUNET_SCHEDULER_TaskContext *tc)
+nat_pulse (void *cls,
+ const struct GNUNET_SCHEDULER_TaskContext *tc)
{
struct GNUNET_NAT_Handle *nat = cls;
- static int first_warning = GNUNET_YES;
int old_status;
int new_status;
int port_mapped;
struct sockaddr *ext_addr_upnp = NULL;
struct sockaddr *ext_addr_natpmp = NULL;
+ nat->pulse_timer = GNUNET_SCHEDULER_NO_TASK;
old_status = get_traversal_status (nat);
/* Only update the protocol that has been successful until now */
&ext_addr_natpmp);
else
{
+ /* try both */
nat->upnp_status =
GNUNET_NAT_UPNP_pulse (nat->upnp, nat->is_enabled, GNUNET_YES,
&ext_addr_upnp);
GNUNET_NAT_NATPMP_pulse (nat->natpmp, nat->is_enabled,
&ext_addr_natpmp);
}
-
new_status = get_traversal_status (nat);
-
- if (old_status != new_status &&
- (new_status == GNUNET_NAT_PORT_UNMAPPED || new_status == GNUNET_NAT_PORT_ERROR))
- GNUNET_log_from (GNUNET_ERROR_TYPE_INFO, COMP_NAT,
+ if ( (old_status != new_status) &&
+ ( (new_status == GNUNET_NAT_PORT_UNMAPPED) ||
+ (new_status == GNUNET_NAT_PORT_ERROR) ) )
+ GNUNET_log_from (GNUNET_ERROR_TYPE_INFO,
+ "NAT",
_("Port redirection failed: no UPnP or NAT-PMP routers supporting this feature found\n"));
-
#ifdef DEBUG
if (new_status != old_status)
- GNUNET_log_from (GNUNET_ERROR_TYPE_DEBUG, COMP_NAT,
- _("State changed from \"%s\" to \"%s\"\n"),
+ GNUNET_log_from (GNUNET_ERROR_TYPE_DEBUG, "NAT",
+ _("State changed from `%s' to `%s'\n"),
get_nat_state_str (old_status),
get_nat_state_str (new_status));
#endif
if (!(ext_addr_upnp || ext_addr_natpmp))
{
/* Address has just changed and we could not get it, or it's the first try */
- if (nat->ext_addr || first_warning)
+ if ( (NULL != nat->ext_addr) ||
+ (GNUNET_NO == nat->did_warn) )
{
- GNUNET_log_from (GNUNET_ERROR_TYPE_INFO, COMP_NAT,
- _("Could not determine external IP address\n"));
- first_warning = GNUNET_NO;
+ GNUNET_log_from (GNUNET_ERROR_TYPE_INFO,
+ "NAT",
+ _("Could not determine external IP address\n"));
+ nat->did_warn = GNUNET_YES;
}
-
notify_change (nat, NULL, port_mapped);
}
else if (ext_addr_upnp && GNUNET_NAT_cmp_addr (nat->ext_addr, ext_addr_upnp) != 0)
{
- GNUNET_log_from (GNUNET_ERROR_TYPE_INFO, COMP_NAT,
- _("External IP address changed from %s to %s\n"),
- GNUNET_a2s (nat->ext_addr, sizeof (nat->ext_addr)),
- GNUNET_a2s (ext_addr_upnp, sizeof (ext_addr_upnp)));
-
+ GNUNET_log_from (GNUNET_ERROR_TYPE_INFO,
+ "NAT",
+ _("External IP address changed to %s\n"),
+ GNUNET_a2s (ext_addr_upnp, sizeof (ext_addr_upnp)));
notify_change (nat, ext_addr_upnp, port_mapped);
}
else if (ext_addr_natpmp && GNUNET_NAT_cmp_addr (nat->ext_addr, ext_addr_natpmp) != 0)
{
- GNUNET_log_from (GNUNET_ERROR_TYPE_INFO, COMP_NAT,
- _("External IP address changed from %s to %s\n"),
- GNUNET_a2s (nat->ext_addr, sizeof (nat->ext_addr)),
- GNUNET_a2s (ext_addr_natpmp, sizeof (ext_addr_natpmp)));
-
+ GNUNET_log_from (GNUNET_ERROR_TYPE_INFO, "NAT",
+ _("External IP address changed to `%s'\n"),
+ GNUNET_a2s (ext_addr_natpmp, sizeof (ext_addr_natpmp)));
notify_change (nat, ext_addr_natpmp, port_mapped);
}
-
nat->pulse_timer = GNUNET_SCHEDULER_add_delayed (nat->sched,
GNUNET_TIME_UNIT_SECONDS,
&nat_pulse, nat);
}
+
+/**
+ * Attempt to enable port redirection and detect public IP address contacting
+ * UPnP or NAT-PMP routers on the local network. Use addr to specify to which
+ * of the local host's addresses should the external port be mapped. The port
+ * is taken from the corresponding sockaddr_in[6] field.
+ *
+ * @param sched the sheduler used in the program
+ * @param addr the local address packets should be redirected to
+ * @param addrlen actual lenght of the address
+ * @param callback function to call everytime the public IP address changes
+ * @param callback_cls closure for callback
+ * @return NULL on error, otherwise handle that can be used to unregister
+ */
struct GNUNET_NAT_Handle *
GNUNET_NAT_register (struct GNUNET_SCHEDULER_Handle *sched,
const struct sockaddr *addr, socklen_t addrlen,
GNUNET_NAT_AddressCallback callback, void *callback_cls)
{
- struct GNUNET_NAT_Handle *nat = GNUNET_malloc (sizeof (struct GNUNET_NAT_Handle));
+ struct GNUNET_NAT_Handle *nat;
+ nat = GNUNET_malloc (sizeof (struct GNUNET_NAT_Handle));
if (addr)
{
- GNUNET_assert (addr->sa_family == AF_INET
- || addr->sa_family == AF_INET6);
+ GNUNET_assert ( (addr->sa_family == AF_INET) ||
+ (addr->sa_family == AF_INET6) );
nat->local_addr = GNUNET_malloc (addrlen);
memcpy (nat->local_addr, addr, addrlen);
-
if (addr->sa_family == AF_INET)
{
nat->public_port = ntohs (((struct sockaddr_in *) addr)->sin_port);
((struct sockaddr_in6 *) nat->local_addr)->sin6_port = 0;
}
}
- else
- {
- nat->local_addr = NULL;
- nat->public_port = 0;
- }
-
nat->should_change = GNUNET_YES;
nat->sched = sched;
nat->is_enabled = GNUNET_YES;
nat->natpmp_status = GNUNET_NAT_PORT_UNMAPPED;
nat->callback = callback;
nat->callback_cls = callback_cls;
- nat->ext_addr = NULL;
- nat->contact_addr = NULL;
nat->natpmp = GNUNET_NAT_NATPMP_init (nat->local_addr, addrlen, nat->public_port);
nat->upnp = GNUNET_NAT_UPNP_init (nat->local_addr, addrlen, nat->public_port);
-
nat->pulse_timer = GNUNET_SCHEDULER_add_delayed (sched,
GNUNET_TIME_UNIT_SECONDS,
&nat_pulse, nat);
-
return nat;
}
+
+/**
+ * Stop port redirection and public IP address detection for the given handle.
+ * This frees the handle, after having sent the needed commands to close open ports.
+ *
+ * @param h the handle to stop
+ */
void
GNUNET_NAT_unregister (struct GNUNET_NAT_Handle *nat)
{
struct sockaddr *addr;
- GNUNET_SCHEDULER_cancel (nat->sched, nat->pulse_timer);
+ GNUNET_SCHEDULER_cancel (nat->sched,
+ nat->pulse_timer);
nat->upnp_status =
- GNUNET_NAT_UPNP_pulse (nat->upnp, GNUNET_NO, GNUNET_NO,
+ GNUNET_NAT_UPNP_pulse (nat->upnp,
+ GNUNET_NO, GNUNET_NO,
&addr);
nat->natpmp_status =
GNUNET_NAT_NATPMP_pulse (nat->natpmp, GNUNET_NO,
&addr);
-
GNUNET_NAT_NATPMP_close (nat->natpmp);
GNUNET_NAT_UPNP_close (nat->upnp);
-
- if (nat->local_addr)
- GNUNET_free (nat->local_addr);
- if (nat->ext_addr)
- GNUNET_free (nat->ext_addr);
+ GNUNET_free_non_null (nat->local_addr);
+ GNUNET_free_non_null (nat->ext_addr);
GNUNET_free (nat);
}
+
+/* end of nat.c */
+
#include "platform.h"
-typedef struct GNUNET_NAT_NATPMP_Handle GNUNET_NAT_NATPMP_Handle;
+struct GNUNET_NAT_NATPMP_Handle;
-GNUNET_NAT_NATPMP_Handle *GNUNET_NAT_NATPMP_init (const struct sockaddr *addr,
- socklen_t addrlen,
- unsigned short port);
+struct GNUNET_NAT_NATPMP_Handle *
+GNUNET_NAT_NATPMP_init (const struct sockaddr *addr,
+ socklen_t addrlen,
+ unsigned short port);
-void GNUNET_NAT_NATPMP_close (GNUNET_NAT_NATPMP_Handle * nat);
+void GNUNET_NAT_NATPMP_close (struct GNUNET_NAT_NATPMP_Handle * nat);
-int GNUNET_NAT_NATPMP_pulse (GNUNET_NAT_NATPMP_Handle * nat, int is_enabled,
+int GNUNET_NAT_NATPMP_pulse (struct GNUNET_NAT_NATPMP_Handle * nat,
+ int is_enabled,
struct sockaddr **ext_addr);
-#endif /* NATPMP_H */
+#endif
+/* NATPMP_H */
/* Component name for logging */
#define COMP_NAT_UPNP _("NAT (UPnP)")
-typedef enum
+enum UPNP_State
{
UPNP_IDLE,
UPNP_ERR,
UPNP_DISCOVER,
UPNP_MAP,
UPNP_UNMAP
-}
-UPNP_state;
+};
struct GNUNET_NAT_UPNP_Handle
{
const struct sockaddr *addr;
socklen_t addrlen;
unsigned int is_mapped;
- UPNP_state state;
+ enum UPNP_State state;
struct sockaddr *ext_addr;
const char *iface;
};
if (addr && GNUNET_NAT_cmp_addr (upnp->addr, addr) == 0)
{
- upnp->iface = name;
+ upnp->iface = name; // BADNESS!
return GNUNET_SYSERR;
}
return GNUNET_OK;
}
+
GNUNET_NAT_UPNP_Handle *
-GNUNET_NAT_UPNP_init (const struct sockaddr *addr, socklen_t addrlen,
+GNUNET_NAT_UPNP_init (const struct sockaddr *addr,
+ socklen_t addrlen,
u_short port)
{
- GNUNET_NAT_UPNP_Handle *upnp =
- GNUNET_malloc (sizeof (GNUNET_NAT_UPNP_Handle));
+ GNUNET_NAT_UPNP_Handle *upnp;
+ upnp = GNUNET_malloc (sizeof (GNUNET_NAT_UPNP_Handle));
upnp->state = UPNP_DISCOVER;
upnp->addr = addr;
upnp->addrlen = addrlen;
upnp->port = port;
-
/* Find the interface corresponding to the address,
* on which we should broadcast call for routers */
- upnp->iface = NULL;
- GNUNET_OS_network_interfaces_list (process_if, upnp);
+ GNUNET_OS_network_interfaces_list (&process_if, upnp);
if (!upnp->iface)
- GNUNET_log_from (GNUNET_ERROR_TYPE_WARNING, COMP_NAT_UPNP, "Could not find an interface matching the wanted address.\n");
-
+ GNUNET_log_from (GNUNET_ERROR_TYPE_WARNING,
+ COMP_NAT_UPNP,
+ "Could not find an interface matching the wanted address.\n");
return upnp;
}
+
void
GNUNET_NAT_UPNP_close (GNUNET_NAT_UPNP_Handle * handle)
{
#include "platform.h"
-typedef struct GNUNET_NAT_UPNP_Handle GNUNET_NAT_UPNP_Handle;
+struct GNUNET_NAT_UPNP_Handle;
-GNUNET_NAT_UPNP_Handle *GNUNET_NAT_UPNP_init (const struct sockaddr *addr,
- socklen_t addrlen,
- unsigned short port);
+struct GNUNET_NAT_UPNP_Handle *
+GNUNET_NAT_UPNP_init (const struct sockaddr *addr,
+ socklen_t addrlen,
+ unsigned short port);
-void GNUNET_NAT_UPNP_close (GNUNET_NAT_UPNP_Handle *);
+void GNUNET_NAT_UPNP_close (struct GNUNET_NAT_UPNP_Handle * h);
-int GNUNET_NAT_UPNP_pulse (GNUNET_NAT_UPNP_Handle *, int is_enabled,
- int do_port_check, struct sockaddr **ext_addr);
-#endif /* UPNP_H */
+int GNUNET_NAT_UPNP_pulse (struct GNUNET_NAT_UPNP_Handle *h,
+ int is_enabled,
+ int do_port_check,
+ struct sockaddr **ext_addr);
+
+#endif
+/* UPNP_H */