2021-05-11 22:00:06 +00:00
/* $Id: upnpc.c,v 1.129 2021/05/10 20:51:29 nanard Exp $ */
2011-09-27 20:25:35 +00:00
/* Project : miniupnp
* Author : Thomas Bernard
2021-05-11 22:00:06 +00:00
* Copyright ( c ) 2005 - 2021 Thomas Bernard
2011-09-27 20:25:35 +00:00
* 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 <time.h>
2012-01-21 13:38:38 +00:00
# ifdef _WIN32
2011-09-27 20:25:35 +00:00
# include <winsock2.h>
2020-10-18 18:29:53 +00:00
# include "win32_snprintf.h"
2012-04-20 14:44:03 +00:00
# else
/* for IPPROTO_TCP / IPPROTO_UDP */
# include <netinet/in.h>
2011-09-27 20:25:35 +00:00
# endif
2015-04-24 20:52:04 +00:00
# include <ctype.h>
2011-09-27 20:25:35 +00:00
# include "miniwget.h"
# include "miniupnpc.h"
# include "upnpcommands.h"
2018-03-13 23:36:12 +00:00
# include "portlistingparse.h"
2011-09-27 20:25:35 +00:00
# include "upnperrors.h"
2015-04-30 08:31:53 +00:00
# include "miniupnpcstrings.h"
2011-09-27 20:25:35 +00:00
2012-03-01 01:51:24 +00:00
/* protofix() checks if protocol is "UDP" or "TCP"
2011-09-27 20:25:35 +00:00
* returns NULL if not */
const char * protofix ( const char * proto )
{
static const char proto_tcp [ 4 ] = { ' T ' , ' C ' , ' P ' , 0 } ;
static const char proto_udp [ 4 ] = { ' U ' , ' D ' , ' P ' , 0 } ;
int i , b ;
for ( i = 0 , b = 1 ; i < 4 ; i + + )
2012-03-01 01:51:24 +00:00
b = b & & ( ( proto [ i ] = = proto_tcp [ i ] )
2011-09-27 20:25:35 +00:00
| | ( proto [ i ] = = ( proto_tcp [ i ] | 32 ) ) ) ;
if ( b )
return proto_tcp ;
for ( i = 0 , b = 1 ; i < 4 ; i + + )
b = b & & ( ( proto [ i ] = = proto_udp [ i ] )
| | ( proto [ i ] = = ( proto_udp [ i ] | 32 ) ) ) ;
if ( b )
return proto_udp ;
return 0 ;
}
2015-04-24 17:24:20 +00:00
/* is_int() checks if parameter is an integer or not
* 1 for integer
* 0 for not an integer */
2015-04-24 20:52:04 +00:00
int is_int ( char const * s )
{
if ( s = = NULL )
return 0 ;
while ( * s ) {
/* #define isdigit(c) ((c) >= '0' && (c) <= '9') */
if ( ! isdigit ( * s ) )
return 0 ;
s + + ;
2015-04-24 17:24:20 +00:00
}
2015-04-24 20:52:04 +00:00
return 1 ;
2015-04-24 17:24:20 +00:00
}
2011-09-27 20:25:35 +00:00
static void DisplayInfos ( struct UPNPUrls * urls ,
struct IGDdatas * data )
{
char externalIPAddress [ 40 ] ;
char connectionType [ 64 ] ;
char status [ 64 ] ;
char lastconnerr [ 64 ] ;
2016-01-22 15:52:18 +00:00
unsigned int uptime = 0 ;
2011-09-27 20:25:35 +00:00
unsigned int brUp , brDown ;
time_t timenow , timestarted ;
int r ;
2012-06-23 22:44:22 +00:00
if ( UPNP_GetConnectionTypeInfo ( urls - > controlURL ,
data - > first . servicetype ,
connectionType ) ! = UPNPCOMMAND_SUCCESS )
printf ( " GetConnectionTypeInfo failed. \n " ) ;
else
2011-09-27 20:25:35 +00:00
printf ( " Connection Type : %s \n " , connectionType ) ;
2012-06-23 22:44:22 +00:00
if ( UPNP_GetStatusInfo ( urls - > controlURL , data - > first . servicetype ,
status , & uptime , lastconnerr ) ! = UPNPCOMMAND_SUCCESS )
printf ( " GetStatusInfo failed. \n " ) ;
2011-09-27 20:25:35 +00:00
else
2012-06-23 22:44:22 +00:00
printf ( " Status : %s, uptime=%us, LastConnectionError : %s \n " ,
status , uptime , lastconnerr ) ;
2016-01-22 15:52:18 +00:00
if ( uptime > 0 ) {
timenow = time ( NULL ) ;
timestarted = timenow - uptime ;
printf ( " Time started : %s " , ctime ( & timestarted ) ) ;
}
2012-06-23 22:44:22 +00:00
if ( UPNP_GetLinkLayerMaxBitRates ( urls - > controlURL_CIF , data - > CIF . servicetype ,
& brDown , & brUp ) ! = UPNPCOMMAND_SUCCESS ) {
printf ( " GetLinkLayerMaxBitRates failed. \n " ) ;
} else {
printf ( " MaxBitRateDown : %u bps " , brDown ) ;
if ( brDown > = 1000000 ) {
printf ( " (%u.%u Mbps) " , brDown / 1000000 , ( brDown / 100000 ) % 10 ) ;
} else if ( brDown > = 1000 ) {
printf ( " (%u Kbps) " , brDown / 1000 ) ;
}
printf ( " MaxBitRateUp %u bps " , brUp ) ;
if ( brUp > = 1000000 ) {
printf ( " (%u.%u Mbps) " , brUp / 1000000 , ( brUp / 100000 ) % 10 ) ;
} else if ( brUp > = 1000 ) {
printf ( " (%u Kbps) " , brUp / 1000 ) ;
}
printf ( " \n " ) ;
2011-09-27 20:25:35 +00:00
}
r = UPNP_GetExternalIPAddress ( urls - > controlURL ,
data - > first . servicetype ,
externalIPAddress ) ;
2012-06-23 22:44:22 +00:00
if ( r ! = UPNPCOMMAND_SUCCESS ) {
printf ( " GetExternalIPAddress failed. (errorcode=%d) \n " , r ) ;
2021-03-28 15:33:15 +00:00
} else if ( ! externalIPAddress [ 0 ] ) {
printf ( " GetExternalIPAddress failed. (empty string) \n " ) ;
2012-06-23 22:44:22 +00:00
} else {
2011-09-27 20:25:35 +00:00
printf ( " ExternalIPAddress = %s \n " , externalIPAddress ) ;
2012-06-23 22:44:22 +00:00
}
2011-09-27 20:25:35 +00:00
}
static void GetConnectionStatus ( struct UPNPUrls * urls ,
struct IGDdatas * data )
{
unsigned int bytessent , bytesreceived , packetsreceived , packetssent ;
DisplayInfos ( urls , data ) ;
bytessent = UPNP_GetTotalBytesSent ( urls - > controlURL_CIF , data - > CIF . servicetype ) ;
bytesreceived = UPNP_GetTotalBytesReceived ( urls - > controlURL_CIF , data - > CIF . servicetype ) ;
packetssent = UPNP_GetTotalPacketsSent ( urls - > controlURL_CIF , data - > CIF . servicetype ) ;
packetsreceived = UPNP_GetTotalPacketsReceived ( urls - > controlURL_CIF , data - > CIF . servicetype ) ;
printf ( " Bytes: Sent: %8u \t Recv: %8u \n " , bytessent , bytesreceived ) ;
printf ( " Packets: Sent: %8u \t Recv: %8u \n " , packetssent , packetsreceived ) ;
}
static void ListRedirections ( struct UPNPUrls * urls ,
struct IGDdatas * data )
{
int r ;
int i = 0 ;
char index [ 6 ] ;
char intClient [ 40 ] ;
char intPort [ 6 ] ;
char extPort [ 6 ] ;
char protocol [ 4 ] ;
char desc [ 80 ] ;
char enabled [ 6 ] ;
char rHost [ 64 ] ;
char duration [ 16 ] ;
/*unsigned int num=0;
UPNP_GetPortMappingNumberOfEntries ( urls - > controlURL , data - > servicetype , & num ) ;
printf ( " PortMappingNumberOfEntries : %u \n " , num ) ; */
2012-01-07 10:37:16 +00:00
printf ( " i protocol exPort->inAddr:inPort description remoteHost leaseTime \n " ) ;
2011-09-27 20:25:35 +00:00
do {
snprintf ( index , 6 , " %d " , i ) ;
rHost [ 0 ] = ' \0 ' ; enabled [ 0 ] = ' \0 ' ;
duration [ 0 ] = ' \0 ' ; desc [ 0 ] = ' \0 ' ;
extPort [ 0 ] = ' \0 ' ; intPort [ 0 ] = ' \0 ' ; intClient [ 0 ] = ' \0 ' ;
r = UPNP_GetGenericPortMappingEntry ( urls - > controlURL ,
data - > first . servicetype ,
index ,
extPort , intClient , intPort ,
protocol , desc , enabled ,
rHost , duration ) ;
if ( r = = 0 )
/*
printf ( " %02d - %s %s->%s:%s \t enabled=%s leaseDuration=%s \n "
" desc='%s' rHost='%s' \n " ,
i , protocol , extPort , intClient , intPort ,
enabled , duration ,
desc , rHost ) ;
*/
printf ( " %2d %s %5s->%s:%-5s '%s' '%s' %s \n " ,
i , protocol , extPort , intClient , intPort ,
desc , rHost , duration ) ;
else
printf ( " GetGenericPortMappingEntry() returned %d (%s) \n " ,
r , strupnperror ( r ) ) ;
i + + ;
2020-11-09 19:38:45 +00:00
} while ( r = = 0 & & i < 65536 ) ;
2011-09-27 20:25:35 +00:00
}
static void NewListRedirections ( struct UPNPUrls * urls ,
struct IGDdatas * data )
{
int r ;
int i = 0 ;
struct PortMappingParserData pdata ;
struct PortMapping * pm ;
memset ( & pdata , 0 , sizeof ( struct PortMappingParserData ) ) ;
r = UPNP_GetListOfPortMappings ( urls - > controlURL ,
data - > first . servicetype ,
" 0 " ,
" 65535 " ,
" TCP " ,
" 1000 " ,
& pdata ) ;
if ( r = = UPNPCOMMAND_SUCCESS )
{
2012-01-07 10:37:16 +00:00
printf ( " i protocol exPort->inAddr:inPort description remoteHost leaseTime \n " ) ;
2014-11-01 10:41:31 +00:00
for ( pm = pdata . l_head ; pm ! = NULL ; pm = pm - > l_next )
2011-09-27 20:25:35 +00:00
{
printf ( " %2d %s %5hu->%s:%-5hu '%s' '%s' %u \n " ,
i , pm - > protocol , pm - > externalPort , pm - > internalClient ,
pm - > internalPort ,
pm - > description , pm - > remoteHost ,
( unsigned ) pm - > leaseTime ) ;
i + + ;
}
FreePortListing ( & pdata ) ;
}
else
{
printf ( " GetListOfPortMappings() returned %d (%s) \n " ,
r , strupnperror ( r ) ) ;
}
r = UPNP_GetListOfPortMappings ( urls - > controlURL ,
data - > first . servicetype ,
" 0 " ,
" 65535 " ,
" UDP " ,
" 1000 " ,
& pdata ) ;
if ( r = = UPNPCOMMAND_SUCCESS )
{
2014-11-01 10:41:31 +00:00
for ( pm = pdata . l_head ; pm ! = NULL ; pm = pm - > l_next )
2011-09-27 20:25:35 +00:00
{
printf ( " %2d %s %5hu->%s:%-5hu '%s' '%s' %u \n " ,
i , pm - > protocol , pm - > externalPort , pm - > internalClient ,
pm - > internalPort ,
pm - > description , pm - > remoteHost ,
( unsigned ) pm - > leaseTime ) ;
i + + ;
}
FreePortListing ( & pdata ) ;
}
else
{
printf ( " GetListOfPortMappings() returned %d (%s) \n " ,
r , strupnperror ( r ) ) ;
}
}
2012-03-01 01:51:24 +00:00
/* Test function
2011-09-27 20:25:35 +00:00
* 1 - get connection type
* 2 - get extenal ip address
* 3 - Add port mapping
* 4 - get this port mapping from the IGD */
2016-09-22 20:02:00 +00:00
static int SetRedirectAndTest ( struct UPNPUrls * urls ,
2014-05-13 19:04:00 +00:00
struct IGDdatas * data ,
const char * iaddr ,
const char * iport ,
const char * eport ,
const char * proto ,
const char * leaseDuration ,
2019-07-13 10:39:33 +00:00
const char * remoteHost ,
2014-05-13 19:04:00 +00:00
const char * description ,
2014-05-13 19:35:00 +00:00
int addAny )
2011-09-27 20:25:35 +00:00
{
char externalIPAddress [ 40 ] ;
char intClient [ 40 ] ;
char intPort [ 6 ] ;
2014-05-13 19:35:00 +00:00
char reservedPort [ 6 ] ;
2011-09-27 20:25:35 +00:00
char duration [ 16 ] ;
int r ;
if ( ! iaddr | | ! iport | | ! eport | | ! proto )
{
fprintf ( stderr , " Wrong arguments \n " ) ;
2016-09-22 20:02:00 +00:00
return - 1 ;
2011-09-27 20:25:35 +00:00
}
proto = protofix ( proto ) ;
if ( ! proto )
{
fprintf ( stderr , " invalid protocol \n " ) ;
2016-09-22 20:02:00 +00:00
return - 1 ;
2011-09-27 20:25:35 +00:00
}
2012-03-01 01:51:24 +00:00
2014-05-13 20:04:14 +00:00
r = UPNP_GetExternalIPAddress ( urls - > controlURL ,
data - > first . servicetype ,
externalIPAddress ) ;
if ( r ! = UPNPCOMMAND_SUCCESS )
2011-09-27 20:25:35 +00:00
printf ( " GetExternalIPAddress failed. \n " ) ;
2014-05-13 20:04:14 +00:00
else
printf ( " ExternalIPAddress = %s \n " , externalIPAddress ) ;
2012-03-01 01:51:24 +00:00
2014-05-13 19:35:00 +00:00
if ( addAny ) {
r = UPNP_AddAnyPortMapping ( urls - > controlURL , data - > first . servicetype ,
eport , iport , iaddr , description ,
2019-07-13 10:39:33 +00:00
proto , remoteHost , leaseDuration , reservedPort ) ;
2014-05-13 19:35:00 +00:00
if ( r = = UPNPCOMMAND_SUCCESS )
eport = reservedPort ;
else
printf ( " AddAnyPortMapping(%s, %s, %s) failed with code %d (%s) \n " ,
eport , iport , iaddr , r , strupnperror ( r ) ) ;
} else {
r = UPNP_AddPortMapping ( urls - > controlURL , data - > first . servicetype ,
eport , iport , iaddr , description ,
2019-07-13 10:39:33 +00:00
proto , remoteHost , leaseDuration ) ;
2017-02-15 06:01:41 +00:00
if ( r ! = UPNPCOMMAND_SUCCESS ) {
2014-05-13 19:35:00 +00:00
printf ( " AddPortMapping(%s, %s, %s) failed with code %d (%s) \n " ,
eport , iport , iaddr , r , strupnperror ( r ) ) ;
2017-02-15 06:01:41 +00:00
return - 2 ;
}
2014-05-13 19:35:00 +00:00
}
2011-09-27 20:25:35 +00:00
r = UPNP_GetSpecificPortMappingEntry ( urls - > controlURL ,
2014-05-13 19:04:00 +00:00
data - > first . servicetype ,
2019-07-13 10:39:33 +00:00
eport , proto , remoteHost ,
2014-05-13 19:04:00 +00:00
intClient , intPort , NULL /*desc*/ ,
NULL /*enabled*/ , duration ) ;
2016-09-22 20:02:00 +00:00
if ( r ! = UPNPCOMMAND_SUCCESS ) {
2011-09-27 20:25:35 +00:00
printf ( " GetSpecificPortMappingEntry() failed with code %d (%s) \n " ,
r , strupnperror ( r ) ) ;
2016-09-22 20:02:00 +00:00
return - 2 ;
} else {
2011-09-27 20:25:35 +00:00
printf ( " InternalIP:Port = %s:%s \n " , intClient , intPort ) ;
printf ( " external %s:%s %s is redirected to internal %s:%s (duration=%s) \n " ,
externalIPAddress , eport , proto , intClient , intPort , duration ) ;
}
2016-09-22 20:02:00 +00:00
return 0 ;
2011-09-27 20:25:35 +00:00
}
2016-09-23 15:22:25 +00:00
static int
2011-09-27 20:25:35 +00:00
RemoveRedirect ( struct UPNPUrls * urls ,
struct IGDdatas * data ,
2014-09-11 14:31:36 +00:00
const char * eport ,
const char * proto ,
const char * remoteHost )
2011-09-27 20:25:35 +00:00
{
int r ;
if ( ! proto | | ! eport )
{
fprintf ( stderr , " invalid arguments \n " ) ;
2016-09-23 15:22:25 +00:00
return - 1 ;
2011-09-27 20:25:35 +00:00
}
proto = protofix ( proto ) ;
if ( ! proto )
{
fprintf ( stderr , " protocol invalid \n " ) ;
2016-09-23 15:22:25 +00:00
return - 1 ;
2011-09-27 20:25:35 +00:00
}
2014-09-11 14:31:36 +00:00
r = UPNP_DeletePortMapping ( urls - > controlURL , data - > first . servicetype , eport , proto , remoteHost ) ;
2016-09-23 15:22:25 +00:00
if ( r ! = UPNPCOMMAND_SUCCESS ) {
printf ( " UPNP_DeletePortMapping() failed with code : %d \n " , r ) ;
return - 2 ;
} else {
printf ( " UPNP_DeletePortMapping() returned : %d \n " , r ) ;
}
return 0 ;
2011-09-27 20:25:35 +00:00
}
2016-09-23 15:22:25 +00:00
static int
2014-05-13 19:35:00 +00:00
RemoveRedirectRange ( struct UPNPUrls * urls ,
struct IGDdatas * data ,
const char * ePortStart , char const * ePortEnd ,
const char * proto , const char * manage )
{
int r ;
if ( ! manage )
manage = " 0 " ;
if ( ! proto | | ! ePortStart | | ! ePortEnd )
{
fprintf ( stderr , " invalid arguments \n " ) ;
2016-09-23 15:22:25 +00:00
return - 1 ;
2014-05-13 19:35:00 +00:00
}
proto = protofix ( proto ) ;
if ( ! proto )
{
fprintf ( stderr , " protocol invalid \n " ) ;
2016-09-23 15:22:25 +00:00
return - 1 ;
2014-05-13 19:35:00 +00:00
}
r = UPNP_DeletePortMappingRange ( urls - > controlURL , data - > first . servicetype , ePortStart , ePortEnd , proto , manage ) ;
2016-09-23 15:22:25 +00:00
if ( r ! = UPNPCOMMAND_SUCCESS ) {
printf ( " UPNP_DeletePortMappingRange() failed with code : %d \n " , r ) ;
return - 2 ;
} else {
printf ( " UPNP_DeletePortMappingRange() returned : %d \n " , r ) ;
}
return 0 ;
2014-05-13 19:35:00 +00:00
}
2011-09-27 20:25:35 +00:00
/* IGD:2, functions for service WANIPv6FirewallControl:1 */
static void GetFirewallStatus ( struct UPNPUrls * urls , struct IGDdatas * data )
{
unsigned int bytessent , bytesreceived , packetsreceived , packetssent ;
int firewallEnabled = 0 , inboundPinholeAllowed = 0 ;
UPNP_GetFirewallStatus ( urls - > controlURL_6FC , data - > IPv6FC . servicetype , & firewallEnabled , & inboundPinholeAllowed ) ;
printf ( " FirewallEnabled: %d & Inbound Pinhole Allowed: %d \n " , firewallEnabled , inboundPinholeAllowed ) ;
printf ( " GetFirewallStatus: \n Firewall Enabled: %s \n Inbound Pinhole Allowed: %s \n " , ( firewallEnabled ) ? " Yes " : " No " , ( inboundPinholeAllowed ) ? " Yes " : " No " ) ;
2012-03-01 01:51:24 +00:00
2011-09-27 20:25:35 +00:00
bytessent = UPNP_GetTotalBytesSent ( urls - > controlURL_CIF , data - > CIF . servicetype ) ;
bytesreceived = UPNP_GetTotalBytesReceived ( urls - > controlURL_CIF , data - > CIF . servicetype ) ;
packetssent = UPNP_GetTotalPacketsSent ( urls - > controlURL_CIF , data - > CIF . servicetype ) ;
packetsreceived = UPNP_GetTotalPacketsReceived ( urls - > controlURL_CIF , data - > CIF . servicetype ) ;
printf ( " Bytes: Sent: %8u \t Recv: %8u \n " , bytessent , bytesreceived ) ;
printf ( " Packets: Sent: %8u \t Recv: %8u \n " , packetssent , packetsreceived ) ;
}
2012-03-01 01:51:24 +00:00
/* Test function
2011-09-27 20:25:35 +00:00
* 1 - Add pinhole
* 2 - Check if pinhole is working from the IGD side */
static void SetPinholeAndTest ( struct UPNPUrls * urls , struct IGDdatas * data ,
const char * remoteaddr , const char * eport ,
const char * intaddr , const char * iport ,
const char * proto , const char * lease_time )
{
char uniqueID [ 8 ] ;
2012-04-09 22:08:53 +00:00
/*int isWorking = 0;*/
2011-09-27 20:25:35 +00:00
int r ;
2012-04-20 14:44:03 +00:00
char proto_tmp [ 8 ] ;
2011-09-27 20:25:35 +00:00
if ( ! intaddr | | ! remoteaddr | | ! iport | | ! eport | | ! proto | | ! lease_time )
{
fprintf ( stderr , " Wrong arguments \n " ) ;
return ;
}
2012-04-20 14:44:03 +00:00
if ( atoi ( proto ) = = 0 )
2011-09-27 20:25:35 +00:00
{
2012-05-08 21:05:21 +00:00
const char * protocol ;
protocol = protofix ( proto ) ;
if ( protocol & & ( strcmp ( " TCP " , protocol ) = = 0 ) )
2012-04-20 14:44:03 +00:00
{
snprintf ( proto_tmp , sizeof ( proto_tmp ) , " %d " , IPPROTO_TCP ) ;
proto = proto_tmp ;
}
2012-05-08 21:05:21 +00:00
else if ( protocol & & ( strcmp ( " UDP " , protocol ) = = 0 ) )
2012-04-20 14:44:03 +00:00
{
snprintf ( proto_tmp , sizeof ( proto_tmp ) , " %d " , IPPROTO_UDP ) ;
proto = proto_tmp ;
}
else
{
fprintf ( stderr , " invalid protocol \n " ) ;
return ;
}
}
2011-09-27 20:25:35 +00:00
r = UPNP_AddPinhole ( urls - > controlURL_6FC , data - > IPv6FC . servicetype , remoteaddr , eport , intaddr , iport , proto , lease_time , uniqueID ) ;
if ( r ! = UPNPCOMMAND_SUCCESS )
printf ( " AddPinhole([%s]:%s -> [%s]:%s) failed with code %d (%s) \n " ,
2012-04-20 14:44:03 +00:00
remoteaddr , eport , intaddr , iport , r , strupnperror ( r ) ) ;
2011-09-27 20:25:35 +00:00
else
{
2012-04-20 14:44:03 +00:00
printf ( " AddPinhole: ([%s]:%s -> [%s]:%s) / Pinhole ID = %s \n " ,
remoteaddr , eport , intaddr , iport , uniqueID ) ;
2011-09-27 20:25:35 +00:00
/*r = UPNP_CheckPinholeWorking(urls->controlURL_6FC, data->servicetype_6FC, uniqueID, &isWorking);
if ( r ! = UPNPCOMMAND_SUCCESS )
printf ( " CheckPinholeWorking() failed with code %d (%s) \n " , r , strupnperror ( r ) ) ;
printf ( " CheckPinholeWorking: Pinhole ID = %s / IsWorking = %s \n " , uniqueID , ( isWorking ) ? " Yes " : " No " ) ; */
}
}
/* Test function
* 1 - Check if pinhole is working from the IGD side
* 2 - Update pinhole */
static void GetPinholeAndUpdate ( struct UPNPUrls * urls , struct IGDdatas * data ,
const char * uniqueID , const char * lease_time )
{
int isWorking = 0 ;
int r ;
if ( ! uniqueID | | ! lease_time )
{
fprintf ( stderr , " Wrong arguments \n " ) ;
return ;
}
r = UPNP_CheckPinholeWorking ( urls - > controlURL_6FC , data - > IPv6FC . servicetype , uniqueID , & isWorking ) ;
printf ( " CheckPinholeWorking: Pinhole ID = %s / IsWorking = %s \n " , uniqueID , ( isWorking ) ? " Yes " : " No " ) ;
if ( r ! = UPNPCOMMAND_SUCCESS )
printf ( " CheckPinholeWorking() failed with code %d (%s) \n " , r , strupnperror ( r ) ) ;
if ( isWorking | | r = = 709 )
{
r = UPNP_UpdatePinhole ( urls - > controlURL_6FC , data - > IPv6FC . servicetype , uniqueID , lease_time ) ;
printf ( " UpdatePinhole: Pinhole ID = %s with Lease Time: %s \n " , uniqueID , lease_time ) ;
if ( r ! = UPNPCOMMAND_SUCCESS )
printf ( " UpdatePinhole: ID (%s) failed with code %d (%s) \n " , uniqueID , r , strupnperror ( r ) ) ;
}
}
2012-03-01 01:51:24 +00:00
/* Test function
2011-09-27 20:25:35 +00:00
* Get pinhole timeout
*/
static void GetPinholeOutboundTimeout ( struct UPNPUrls * urls , struct IGDdatas * data ,
const char * remoteaddr , const char * eport ,
const char * intaddr , const char * iport ,
const char * proto )
{
int timeout = 0 ;
int r ;
if ( ! intaddr | | ! remoteaddr | | ! iport | | ! eport | | ! proto )
{
fprintf ( stderr , " Wrong arguments \n " ) ;
return ;
}
r = UPNP_GetOutboundPinholeTimeout ( urls - > controlURL_6FC , data - > IPv6FC . servicetype , remoteaddr , eport , intaddr , iport , proto , & timeout ) ;
if ( r ! = UPNPCOMMAND_SUCCESS )
printf ( " GetOutboundPinholeTimeout([%s]:%s -> [%s]:%s) failed with code %d (%s) \n " ,
intaddr , iport , remoteaddr , eport , r , strupnperror ( r ) ) ;
else
printf ( " GetOutboundPinholeTimeout: ([%s]:%s -> [%s]:%s) / Timeout = %d \n " , intaddr , iport , remoteaddr , eport , timeout ) ;
}
static void
GetPinholePackets ( struct UPNPUrls * urls ,
struct IGDdatas * data , const char * uniqueID )
{
int r , pinholePackets = 0 ;
if ( ! uniqueID )
{
fprintf ( stderr , " invalid arguments \n " ) ;
return ;
}
r = UPNP_GetPinholePackets ( urls - > controlURL_6FC , data - > IPv6FC . servicetype , uniqueID , & pinholePackets ) ;
if ( r ! = UPNPCOMMAND_SUCCESS )
printf ( " GetPinholePackets() failed with code %d (%s) \n " , r , strupnperror ( r ) ) ;
else
printf ( " GetPinholePackets: Pinhole ID = %s / PinholePackets = %d \n " , uniqueID , pinholePackets ) ;
}
static void
CheckPinhole ( struct UPNPUrls * urls ,
struct IGDdatas * data , const char * uniqueID )
{
int r , isWorking = 0 ;
if ( ! uniqueID )
{
fprintf ( stderr , " invalid arguments \n " ) ;
return ;
}
r = UPNP_CheckPinholeWorking ( urls - > controlURL_6FC , data - > IPv6FC . servicetype , uniqueID , & isWorking ) ;
if ( r ! = UPNPCOMMAND_SUCCESS )
printf ( " CheckPinholeWorking() failed with code %d (%s) \n " , r , strupnperror ( r ) ) ;
else
printf ( " CheckPinholeWorking: Pinhole ID = %s / IsWorking = %s \n " , uniqueID , ( isWorking ) ? " Yes " : " No " ) ;
}
static void
RemovePinhole ( struct UPNPUrls * urls ,
struct IGDdatas * data , const char * uniqueID )
{
int r ;
if ( ! uniqueID )
{
fprintf ( stderr , " invalid arguments \n " ) ;
return ;
}
r = UPNP_DeletePinhole ( urls - > controlURL_6FC , data - > IPv6FC . servicetype , uniqueID ) ;
printf ( " UPNP_DeletePinhole() returned : %d \n " , r ) ;
}
/* sample upnp client program */
int main ( int argc , char * * argv )
{
char command = 0 ;
char * * commandargv = 0 ;
int commandargc = 0 ;
struct UPNPDev * devlist = 0 ;
2016-01-22 15:52:18 +00:00
char lanaddr [ 64 ] = " unset " ; /* my ip address on the LAN */
2011-09-27 20:25:35 +00:00
int i ;
const char * rootdescurl = 0 ;
const char * multicastif = 0 ;
const char * minissdpdpath = 0 ;
2015-05-12 23:05:48 +00:00
int localport = UPNP_LOCAL_PORT_ANY ;
2011-09-27 20:25:35 +00:00
int retcode = 0 ;
int error = 0 ;
int ipv6 = 0 ;
2020-10-05 20:06:03 +00:00
int ignore = 0 ;
2015-07-23 20:44:37 +00:00
unsigned char ttl = 2 ; /* defaulting to 2 */
2012-08-30 10:38:27 +00:00
const char * description = 0 ;
2011-09-27 20:25:35 +00:00
2012-01-21 13:38:38 +00:00
# ifdef _WIN32
2011-09-27 20:25:35 +00:00
WSADATA wsaData ;
int nResult = WSAStartup ( MAKEWORD ( 2 , 2 ) , & wsaData ) ;
if ( nResult ! = NO_ERROR )
{
fprintf ( stderr , " WSAStartup() failed. \n " ) ;
return - 1 ;
}
# endif
2015-04-30 08:31:53 +00:00
printf ( " upnpc : miniupnpc library test client, version %s. \n " , MINIUPNPC_VERSION_STRING ) ;
2021-05-11 22:00:06 +00:00
printf ( " (c) 2005-2021 Thomas Bernard. \n " ) ;
2017-05-26 15:27:20 +00:00
printf ( " Go to http://miniupnp.free.fr/ or https://miniupnp.tuxfamily.org/ \n "
2011-09-27 20:25:35 +00:00
" for more information. \n " ) ;
/* command line processing */
for ( i = 1 ; i < argc ; i + + )
{
2013-12-09 09:25:27 +00:00
if ( 0 = = strcmp ( argv [ i ] , " --help " ) | | 0 = = strcmp ( argv [ i ] , " -h " ) )
{
command = 0 ;
break ;
}
2011-09-27 20:25:35 +00:00
if ( argv [ i ] [ 0 ] = = ' - ' )
{
if ( argv [ i ] [ 1 ] = = ' u ' )
rootdescurl = argv [ + + i ] ;
else if ( argv [ i ] [ 1 ] = = ' m ' )
2018-02-22 14:58:25 +00:00
{
2011-09-27 20:25:35 +00:00
multicastif = argv [ + + i ] ;
2018-02-22 14:58:25 +00:00
minissdpdpath = " " ; /* Disable usage of minissdpd */
}
2015-10-08 15:48:04 +00:00
else if ( argv [ i ] [ 1 ] = = ' z ' )
{
2015-05-12 23:05:48 +00:00
char junk ;
if ( sscanf ( argv [ + + i ] , " %d%c " , & localport , & junk ) ! = 1 | |
2015-10-08 15:48:04 +00:00
localport < 0 | | localport > 65535 | |
( localport > 1 & & localport < 1024 ) )
{
2015-05-12 23:05:48 +00:00
fprintf ( stderr , " Invalid localport '%s' \n " , argv [ i ] ) ;
localport = UPNP_LOCAL_PORT_ANY ;
break ;
}
}
2011-09-27 20:25:35 +00:00
else if ( argv [ i ] [ 1 ] = = ' p ' )
minissdpdpath = argv [ + + i ] ;
else if ( argv [ i ] [ 1 ] = = ' 6 ' )
ipv6 = 1 ;
2012-08-30 10:38:27 +00:00
else if ( argv [ i ] [ 1 ] = = ' e ' )
description = argv [ + + i ] ;
2015-07-23 20:44:37 +00:00
else if ( argv [ i ] [ 1 ] = = ' t ' )
ttl = ( unsigned char ) atoi ( argv [ + + i ] ) ;
2020-10-05 20:06:03 +00:00
else if ( argv [ i ] [ 1 ] = = ' i ' )
ignore = 1 ;
2011-09-27 20:25:35 +00:00
else
{
command = argv [ i ] [ 1 ] ;
i + + ;
commandargv = argv + i ;
commandargc = argc - i ;
break ;
}
}
else
{
fprintf ( stderr , " option '%s' invalid \n " , argv [ i ] ) ;
}
}
2015-04-24 20:52:04 +00:00
if ( ! command
2015-04-24 17:24:20 +00:00
| | ( command = = ' a ' & & commandargc < 4 )
2011-09-27 20:25:35 +00:00
| | ( command = = ' d ' & & argc < 2 )
| | ( command = = ' r ' & & argc < 2 )
| | ( command = = ' A ' & & commandargc < 6 )
| | ( command = = ' U ' & & commandargc < 2 )
| | ( command = = ' D ' & & commandargc < 1 ) )
{
2019-07-13 10:39:33 +00:00
fprintf ( stderr , " Usage : \t %s [options] -a ip port external_port protocol [duration] [remote host] \n \t \t Add port redirection \n " , argv [ 0 ] ) ;
fprintf ( stderr , " \t %s [options] -d external_port protocol [remote host] \n \t \t Delete port redirection \n " , argv [ 0 ] ) ;
2011-09-27 20:25:35 +00:00
fprintf ( stderr , " \t %s [options] -s \n \t \t Get Connection status \n " , argv [ 0 ] ) ;
fprintf ( stderr , " \t %s [options] -l \n \t \t List redirections \n " , argv [ 0 ] ) ;
2014-05-13 19:04:00 +00:00
fprintf ( stderr , " \t %s [options] -L \n \t \t List redirections (using GetListOfPortMappings (for IGD:2 only) \n " , argv [ 0 ] ) ;
2019-07-13 10:39:33 +00:00
fprintf ( stderr , " \t %s [options] -n ip port external_port protocol [duration] [remote host] \n \t \t Add (any) port redirection allowing IGD to use alternative external_port (for IGD:2 only) \n " , argv [ 0 ] ) ;
2014-05-13 19:35:00 +00:00
fprintf ( stderr , " \t %s [options] -N external_port_start external_port_end protocol [manage] \n \t \t Delete range of port redirections (for IGD:2 only) \n " , argv [ 0 ] ) ;
2015-04-24 17:24:20 +00:00
fprintf ( stderr , " \t %s [options] -r port1 [external_port1] protocol1 [port2 [external_port2] protocol2] [...] \n \t \t Add all redirections to the current host \n " , argv [ 0 ] ) ;
2011-09-27 20:25:35 +00:00
fprintf ( stderr , " \t %s [options] -A remote_ip remote_port internal_ip internal_port protocol lease_time \n \t \t Add Pinhole (for IGD:2 only) \n " , argv [ 0 ] ) ;
fprintf ( stderr , " \t %s [options] -U uniqueID new_lease_time \n \t \t Update Pinhole (for IGD:2 only) \n " , argv [ 0 ] ) ;
fprintf ( stderr , " \t %s [options] -C uniqueID \n \t \t Check if Pinhole is Working (for IGD:2 only) \n " , argv [ 0 ] ) ;
fprintf ( stderr , " \t %s [options] -K uniqueID \n \t \t Get Number of packets going through the rule (for IGD:2 only) \n " , argv [ 0 ] ) ;
fprintf ( stderr , " \t %s [options] -D uniqueID \n \t \t Delete Pinhole (for IGD:2 only) \n " , argv [ 0 ] ) ;
fprintf ( stderr , " \t %s [options] -S \n \t \t Get Firewall status (for IGD:2 only) \n " , argv [ 0 ] ) ;
fprintf ( stderr , " \t %s [options] -G remote_ip remote_port internal_ip internal_port protocol \n \t \t Get Outbound Pinhole Timeout (for IGD:2 only) \n " , argv [ 0 ] ) ;
fprintf ( stderr , " \t %s [options] -P \n \t \t Get Presentation url \n " , argv [ 0 ] ) ;
fprintf ( stderr , " \n protocol is UDP or TCP \n " ) ;
fprintf ( stderr , " Options: \n " ) ;
2012-08-30 10:38:27 +00:00
fprintf ( stderr , " -e description : set description for port mapping. \n " ) ;
2011-09-27 20:25:35 +00:00
fprintf ( stderr , " -6 : use ip v6 instead of ip v4. \n " ) ;
fprintf ( stderr , " -u url : bypass discovery process by providing the XML root description url. \n " ) ;
2012-01-07 10:40:50 +00:00
fprintf ( stderr , " -m address/interface : provide ip address (ip v4) or interface name (ip v4 or v6) to use for sending SSDP multicast packets. \n " ) ;
2015-05-12 23:05:48 +00:00
fprintf ( stderr , " -z localport : SSDP packets local (source) port (1024-65535). \n " ) ;
2011-09-27 20:25:35 +00:00
fprintf ( stderr , " -p path : use this path for MiniSSDPd socket. \n " ) ;
2015-07-23 20:44:37 +00:00
fprintf ( stderr , " -t ttl : set multicast TTL. Default value is 2. \n " ) ;
2020-10-05 20:06:03 +00:00
fprintf ( stderr , " -i : ignore errors and try to use also disconnected IGD or non-IGD device. \n " ) ;
2011-09-27 20:25:35 +00:00
return 1 ;
}
if ( rootdescurl
| | ( devlist = upnpDiscover ( 2000 , multicastif , minissdpdpath ,
2015-10-08 15:42:45 +00:00
localport , ipv6 , ttl , & error ) ) )
2011-09-27 20:25:35 +00:00
{
struct UPNPDev * device ;
struct UPNPUrls urls ;
struct IGDdatas data ;
if ( devlist )
{
printf ( " List of UPNP devices found on the network : \n " ) ;
for ( device = devlist ; device ; device = device - > pNext )
{
printf ( " desc: %s \n st: %s \n \n " ,
device - > descURL , device - > st ) ;
}
}
2015-01-01 18:40:44 +00:00
else if ( ! rootdescurl )
2011-09-27 20:25:35 +00:00
{
printf ( " upnpDiscover() error code=%d \n " , error ) ;
}
i = 1 ;
if ( ( rootdescurl & & UPNP_GetIGDFromUrl ( rootdescurl , & urls , & data , lanaddr , sizeof ( lanaddr ) ) )
| | ( i = UPNP_GetValidIGD ( devlist , & urls , & data , lanaddr , sizeof ( lanaddr ) ) ) )
{
switch ( i ) {
case 1 :
printf ( " Found valid IGD : %s \n " , urls . controlURL ) ;
break ;
case 2 :
printf ( " Found a (not connected?) IGD : %s \n " , urls . controlURL ) ;
2020-10-05 20:06:03 +00:00
if ( ignore ) printf ( " Trying to continue anyway \n " ) ;
2011-09-27 20:25:35 +00:00
break ;
case 3 :
printf ( " UPnP device found. Is it an IGD ? : %s \n " , urls . controlURL ) ;
2020-10-05 20:06:03 +00:00
if ( ignore ) printf ( " Trying to continue anyway \n " ) ;
2011-09-27 20:25:35 +00:00
break ;
default :
printf ( " Found device (igd ?) : %s \n " , urls . controlURL ) ;
2020-10-05 20:06:03 +00:00
if ( ignore ) printf ( " Trying to continue anyway \n " ) ;
2011-09-27 20:25:35 +00:00
}
2020-10-05 20:06:03 +00:00
if ( i = = 1 | | ignore ) {
2011-09-27 20:25:35 +00:00
printf ( " Local LAN ip address : %s \n " , lanaddr ) ;
#if 0
printf ( " getting \" %s \" \n " , urls . ipcondescURL ) ;
descXML = miniwget ( urls . ipcondescURL , & descXMLsize ) ;
if ( descXML )
{
/*fwrite(descXML, 1, descXMLsize, stdout);*/
free ( descXML ) ; descXML = NULL ;
}
# endif
switch ( command )
{
case ' l ' :
DisplayInfos ( & urls , & data ) ;
ListRedirections ( & urls , & data ) ;
break ;
case ' L ' :
NewListRedirections ( & urls , & data ) ;
break ;
case ' a ' :
2016-09-22 20:02:00 +00:00
if ( SetRedirectAndTest ( & urls , & data ,
2014-05-13 19:35:00 +00:00
commandargv [ 0 ] , commandargv [ 1 ] ,
commandargv [ 2 ] , commandargv [ 3 ] ,
2021-01-04 00:16:02 +00:00
( commandargc > 4 ) & & is_int ( commandargv [ 4 ] ) ? commandargv [ 4 ] : " 0 " ,
( commandargc > 4 ) & & ! is_int ( commandargv [ 4 ] ) ? commandargv [ 4 ] : ( commandargc > 5 ) ? commandargv [ 5 ] : NULL ,
2016-09-22 20:02:00 +00:00
description , 0 ) < 0 )
retcode = 2 ;
2011-09-27 20:25:35 +00:00
break ;
case ' d ' :
2016-09-23 15:22:25 +00:00
if ( RemoveRedirect ( & urls , & data , commandargv [ 0 ] , commandargv [ 1 ] ,
commandargc > 2 ? commandargv [ 2 ] : NULL ) < 0 )
retcode = 2 ;
2011-09-27 20:25:35 +00:00
break ;
2014-05-13 19:35:00 +00:00
case ' n ' : /* aNy */
2016-09-22 20:02:00 +00:00
if ( SetRedirectAndTest ( & urls , & data ,
2014-05-13 19:35:00 +00:00
commandargv [ 0 ] , commandargv [ 1 ] ,
commandargv [ 2 ] , commandargv [ 3 ] ,
2021-01-04 00:16:02 +00:00
( commandargc > 4 ) & & is_int ( commandargv [ 4 ] ) ? commandargv [ 4 ] : " 0 " ,
( commandargc > 4 ) & & ! is_int ( commandargv [ 4 ] ) ? commandargv [ 4 ] : ( commandargc > 5 ) ? commandargv [ 5 ] : NULL ,
2016-09-22 20:02:00 +00:00
description , 1 ) < 0 )
retcode = 2 ;
2014-05-13 19:35:00 +00:00
break ;
case ' N ' :
if ( commandargc < 3 )
fprintf ( stderr , " too few arguments \n " ) ;
2016-09-23 15:22:25 +00:00
if ( RemoveRedirectRange ( & urls , & data , commandargv [ 0 ] , commandargv [ 1 ] , commandargv [ 2 ] ,
commandargc > 3 ? commandargv [ 3 ] : NULL ) < 0 )
retcode = 2 ;
2014-05-13 19:35:00 +00:00
break ;
2011-09-27 20:25:35 +00:00
case ' s ' :
GetConnectionStatus ( & urls , & data ) ;
break ;
case ' r ' :
2015-04-24 20:52:04 +00:00
i = 0 ;
while ( i < commandargc )
{
if ( ! is_int ( commandargv [ i ] ) ) {
/* 1st parameter not an integer : error */
fprintf ( stderr , " command -r : %s is not an port number \n " , commandargv [ i ] ) ;
retcode = 1 ;
break ;
} else if ( is_int ( commandargv [ i + 1 ] ) ) {
/* 2nd parameter is an integer : <port> <external_port> <protocol> */
2016-09-22 20:02:00 +00:00
if ( SetRedirectAndTest ( & urls , & data ,
2015-04-24 17:24:20 +00:00
lanaddr , commandargv [ i ] ,
2019-07-13 10:39:33 +00:00
commandargv [ i + 1 ] , commandargv [ i + 2 ] , " 0 " , NULL ,
2016-09-22 20:02:00 +00:00
description , 0 ) < 0 )
retcode = 2 ;
2015-04-24 20:52:04 +00:00
i + = 3 ; /* 3 parameters parsed */
2015-04-24 17:24:20 +00:00
} else {
2015-04-24 20:52:04 +00:00
/* 2nd parameter not an integer : <port> <protocol> */
2016-09-22 20:02:00 +00:00
if ( SetRedirectAndTest ( & urls , & data ,
2015-04-24 17:24:20 +00:00
lanaddr , commandargv [ i ] ,
2019-07-13 10:39:33 +00:00
commandargv [ i ] , commandargv [ i + 1 ] , " 0 " , NULL ,
2016-09-22 20:02:00 +00:00
description , 0 ) < 0 )
retcode = 2 ;
2015-04-24 20:52:04 +00:00
i + = 2 ; /* 2 parameters parsed */
2015-04-24 17:24:20 +00:00
}
2011-09-27 20:25:35 +00:00
}
break ;
case ' A ' :
SetPinholeAndTest ( & urls , & data ,
commandargv [ 0 ] , commandargv [ 1 ] ,
commandargv [ 2 ] , commandargv [ 3 ] ,
commandargv [ 4 ] , commandargv [ 5 ] ) ;
break ;
case ' U ' :
GetPinholeAndUpdate ( & urls , & data ,
commandargv [ 0 ] , commandargv [ 1 ] ) ;
break ;
case ' C ' :
for ( i = 0 ; i < commandargc ; i + + )
{
CheckPinhole ( & urls , & data , commandargv [ i ] ) ;
}
break ;
case ' K ' :
for ( i = 0 ; i < commandargc ; i + + )
{
GetPinholePackets ( & urls , & data , commandargv [ i ] ) ;
}
break ;
case ' D ' :
for ( i = 0 ; i < commandargc ; i + + )
{
RemovePinhole ( & urls , & data , commandargv [ i ] ) ;
}
break ;
case ' S ' :
GetFirewallStatus ( & urls , & data ) ;
break ;
case ' G ' :
GetPinholeOutboundTimeout ( & urls , & data ,
commandargv [ 0 ] , commandargv [ 1 ] ,
commandargv [ 2 ] , commandargv [ 3 ] ,
commandargv [ 4 ] ) ;
break ;
case ' P ' :
printf ( " Presentation URL found: \n " ) ;
printf ( " %s \n " , data . presentationurl ) ;
break ;
default :
fprintf ( stderr , " Unknown switch -%c \n " , command ) ;
retcode = 1 ;
}
2020-10-05 20:06:03 +00:00
} else {
fprintf ( stderr , " No valid UPNP Internet Gateway Device found. \n " ) ;
retcode = 1 ;
}
2011-09-27 20:25:35 +00:00
FreeUPNPUrls ( & urls ) ;
}
else
{
fprintf ( stderr , " No valid UPNP Internet Gateway Device found. \n " ) ;
retcode = 1 ;
}
freeUPNPDevlist ( devlist ) ; devlist = 0 ;
}
else
{
fprintf ( stderr , " No IGD UPnP Device found on the network ! \n " ) ;
retcode = 1 ;
}
2014-12-01 09:33:00 +00:00
# ifdef _WIN32
nResult = WSACleanup ( ) ;
if ( nResult ! = NO_ERROR ) {
fprintf ( stderr , " WSACleanup() failed. \n " ) ;
}
# endif /* _WIN32 */
2011-09-27 20:25:35 +00:00
return retcode ;
}