version 1.1.1.1, 2012/02/21 23:16:02
|
version 1.1.1.3, 2013/07/22 00:32:35
|
Line 1
|
Line 1
|
/* $Id$ */ |
/* $Id$ */ |
/* MiniUPnP project |
/* MiniUPnP project |
* http://miniupnp.free.fr/ or http://miniupnp.tuxfamily.org/ |
* http://miniupnp.free.fr/ or http://miniupnp.tuxfamily.org/ |
* (c) 2006-2010 Thomas Bernard | * (c) 2006-2013 Thomas Bernard |
* This software is subject to the conditions detailed |
* This software is subject to the conditions detailed |
* in the LICENCE file provided within the distribution */ |
* in the LICENCE file provided within the distribution */ |
|
|
Line 12
|
Line 12
|
/* apt-get install libnetfilter-queue-dev */ |
/* apt-get install libnetfilter-queue-dev */ |
#include <netinet/ip.h> |
#include <netinet/ip.h> |
#include <netinet/udp.h> |
#include <netinet/udp.h> |
//#include <linux/netfilter_ipv4.h> /* Defines verdicts (NF_ACCEPT, etc) */ | #if 0 |
| #include <linux/netfilter_ipv4.h> /* Defines verdicts (NF_ACCEPT, etc) */ |
| #endif |
#include <linux/netfilter.h> |
#include <linux/netfilter.h> |
#include <libnetfilter_queue/libnetfilter_queue.h> |
#include <libnetfilter_queue/libnetfilter_queue.h> |
#include <linux/netfilter/nfnetlink_queue.h> |
#include <linux/netfilter/nfnetlink_queue.h> |
Line 47
|
Line 49
|
#include <sys/un.h> |
#include <sys/un.h> |
#endif |
#endif |
|
|
|
#include "macros.h" |
#include "upnpglobalvars.h" |
#include "upnpglobalvars.h" |
#include "upnphttp.h" |
#include "upnphttp.h" |
#include "upnpdescgen.h" |
#include "upnpdescgen.h" |
Line 56
|
Line 59
|
#include "options.h" |
#include "options.h" |
#include "minissdp.h" |
#include "minissdp.h" |
#include "upnpredirect.h" |
#include "upnpredirect.h" |
|
#include "upnppinhole.h" |
#include "miniupnpdtypes.h" |
#include "miniupnpdtypes.h" |
#include "daemonize.h" |
#include "daemonize.h" |
#include "upnpevents.h" |
#include "upnpevents.h" |
Line 63
|
Line 67
|
#include "natpmp.h" |
#include "natpmp.h" |
#endif |
#endif |
#include "commonrdr.h" |
#include "commonrdr.h" |
|
#include "upnputils.h" |
|
#ifdef USE_IFACEWATCHER |
|
#include "ifacewatcher.h" |
|
#endif |
|
#ifdef ENABLE_6FC_SERVICE |
|
#ifdef USE_NETFILTER |
|
void init_iptpinhole(void); |
|
#endif |
|
#endif |
|
|
#ifndef DEFAULT_CONFIG |
#ifndef DEFAULT_CONFIG |
#define DEFAULT_CONFIG "/etc/miniupnpd.conf" |
#define DEFAULT_CONFIG "/etc/miniupnpd.conf" |
Line 81 static struct nfq_handle *nfqHandle;
|
Line 94 static struct nfq_handle *nfqHandle;
|
static struct sockaddr_in ssdp; |
static struct sockaddr_in ssdp; |
|
|
/* prototypes */ |
/* prototypes */ |
void ProcessSSDPData(int s, char *bufr, struct sockaddr_in sendername, int n, unsigned short port); |
|
static int nfqueue_cb( struct nfq_q_handle *qh, struct nfgenmsg *nfmsg, struct nfq_data *nfa, void *data) ; |
static int nfqueue_cb( struct nfq_q_handle *qh, struct nfgenmsg *nfmsg, struct nfq_data *nfa, void *data) ; |
int identify_ip_protocol (char *payload); |
int identify_ip_protocol (char *payload); |
int get_udp_dst_port (char *payload); |
int get_udp_dst_port (char *payload); |
#endif |
#endif |
|
|
|
/* variables used by signals */ |
|
static volatile sig_atomic_t quitting = 0; |
|
volatile sig_atomic_t should_send_public_address_change_notif = 0; |
|
|
static int sudp = -1; |
|
|
|
/* MAX_LAN_ADDR : maximum number of interfaces |
|
* to listen to SSDP traffic */ |
|
/*#define MAX_LAN_ADDR (4)*/ |
|
|
|
static volatile int quitting = 0; |
|
static volatile int should_send_public_address_change_notif = 0; |
|
|
|
/* OpenAndConfHTTPSocket() : |
/* OpenAndConfHTTPSocket() : |
* setup the socket used to handle incoming HTTP connections. */ |
* setup the socket used to handle incoming HTTP connections. */ |
static int |
static int |
Line 104 OpenAndConfHTTPSocket(unsigned short port)
|
Line 110 OpenAndConfHTTPSocket(unsigned short port)
|
{ |
{ |
int s; |
int s; |
int i = 1; |
int i = 1; |
|
#ifdef ENABLE_IPV6 |
|
struct sockaddr_in6 listenname; |
|
#else |
struct sockaddr_in listenname; |
struct sockaddr_in listenname; |
|
#endif |
|
socklen_t listenname_len; |
|
|
if( (s = socket(PF_INET, SOCK_STREAM, 0)) < 0) | if( (s = socket( |
| #ifdef ENABLE_IPV6 |
| PF_INET6, |
| #else |
| PF_INET, |
| #endif |
| SOCK_STREAM, 0)) < 0) |
{ |
{ |
syslog(LOG_ERR, "socket(http): %m"); |
syslog(LOG_ERR, "socket(http): %m"); |
return -1; |
return -1; |
Line 116 OpenAndConfHTTPSocket(unsigned short port)
|
Line 133 OpenAndConfHTTPSocket(unsigned short port)
|
{ |
{ |
syslog(LOG_WARNING, "setsockopt(http, SO_REUSEADDR): %m"); |
syslog(LOG_WARNING, "setsockopt(http, SO_REUSEADDR): %m"); |
} |
} |
|
#if 0 |
|
/* enable this to force IPV6 only for IPV6 socket. |
|
* see http://www.ietf.org/rfc/rfc3493.txt section 5.3 */ |
|
if(setsockopt(s, IPPROTO_IPV6, IPV6_V6ONLY, &i, sizeof(i)) < 0) |
|
{ |
|
syslog(LOG_WARNING, "setsockopt(http, IPV6_V6ONLY): %m"); |
|
} |
|
#endif |
|
|
memset(&listenname, 0, sizeof(struct sockaddr_in)); | if(!set_non_blocking(s)) |
| { |
| syslog(LOG_WARNING, "set_non_blocking(http): %m"); |
| } |
| |
| #ifdef ENABLE_IPV6 |
| memset(&listenname, 0, sizeof(struct sockaddr_in6)); |
| listenname.sin6_family = AF_INET6; |
| listenname.sin6_port = htons(port); |
| listenname.sin6_addr = in6addr_any; |
| listenname_len = sizeof(struct sockaddr_in6); |
| #else |
listenname.sin_family = AF_INET; |
listenname.sin_family = AF_INET; |
listenname.sin_port = htons(port); |
listenname.sin_port = htons(port); |
listenname.sin_addr.s_addr = htonl(INADDR_ANY); |
listenname.sin_addr.s_addr = htonl(INADDR_ANY); |
|
listenname_len = sizeof(struct sockaddr_in); |
|
#endif |
|
|
if(bind(s, (struct sockaddr *)&listenname, sizeof(struct sockaddr_in)) < 0) | if(bind(s, (struct sockaddr *)&listenname, listenname_len) < 0) |
{ |
{ |
syslog(LOG_ERR, "bind(http): %m"); |
syslog(LOG_ERR, "bind(http): %m"); |
close(s); |
close(s); |
return -1; |
return -1; |
} |
} |
|
|
if(listen(s, 6) < 0) | if(listen(s, 5) < 0) |
{ |
{ |
syslog(LOG_ERR, "listen(http): %m"); |
syslog(LOG_ERR, "listen(http): %m"); |
close(s); |
close(s); |
Line 169 OpenAndConfNFqueue(){
|
Line 207 OpenAndConfNFqueue(){
|
|
|
inet_pton(AF_INET, "239.255.255.250", &(ssdp.sin_addr)); |
inet_pton(AF_INET, "239.255.255.250", &(ssdp.sin_addr)); |
|
|
//Get a queue connection handle from the module | /* Get a queue connection handle from the module */ |
if (!(nfqHandle = nfq_open())) { |
if (!(nfqHandle = nfq_open())) { |
syslog(LOG_ERR, "Error in nfq_open(): %m"); |
syslog(LOG_ERR, "Error in nfq_open(): %m"); |
return -1; |
return -1; |
} |
} |
|
|
//Unbind the handler from processing any IP packets | /* Unbind the handler from processing any IP packets |
// Not totally sure why this is done, or if it's necessary... | Not totally sure why this is done, or if it's necessary... */ |
if ((e = nfq_unbind_pf(nfqHandle, AF_INET)) < 0) { |
if ((e = nfq_unbind_pf(nfqHandle, AF_INET)) < 0) { |
syslog(LOG_ERR, "Error in nfq_unbind_pf(): %m"); |
syslog(LOG_ERR, "Error in nfq_unbind_pf(): %m"); |
return -1; |
return -1; |
} |
} |
|
|
//Bind this handler to process IP packets... | /* Bind this handler to process IP packets... */ |
if (nfq_bind_pf(nfqHandle, AF_INET) < 0) { |
if (nfq_bind_pf(nfqHandle, AF_INET) < 0) { |
syslog(LOG_ERR, "Error in nfq_bind_pf(): %m"); |
syslog(LOG_ERR, "Error in nfq_bind_pf(): %m"); |
return -1; |
return -1; |
} |
} |
|
|
// Install a callback on queue -Q | /* Install a callback on queue -Q */ |
if (!(myQueue = nfq_create_queue(nfqHandle, nfqueue, &nfqueue_cb, NULL))) { |
if (!(myQueue = nfq_create_queue(nfqHandle, nfqueue, &nfqueue_cb, NULL))) { |
syslog(LOG_ERR, "Error in nfq_create_queue(): %m"); |
syslog(LOG_ERR, "Error in nfq_create_queue(): %m"); |
return -1; |
return -1; |
} |
} |
|
|
// Turn on packet copy mode | /* Turn on packet copy mode */ |
if (nfq_set_mode(myQueue, NFQNL_COPY_PACKET, 0xffff) < 0) { |
if (nfq_set_mode(myQueue, NFQNL_COPY_PACKET, 0xffff) < 0) { |
syslog(LOG_ERR, "Error setting packet copy mode (): %m"); |
syslog(LOG_ERR, "Error setting packet copy mode (): %m"); |
return -1; |
return -1; |
Line 232 static int nfqueue_cb(
|
Line 270 static int nfqueue_cb(
|
int dport = get_udp_dst_port(pkt); |
int dport = get_udp_dst_port(pkt); |
|
|
int x = sizeof (struct ip) + sizeof (struct udphdr); |
int x = sizeof (struct ip) + sizeof (struct udphdr); |
| |
/* packets we are interested in are UDP multicast to 239.255.255.250:1900 | /* packets we are interested in are UDP multicast to 239.255.255.250:1900 |
* and start with a data string M-SEARCH |
* and start with a data string M-SEARCH |
*/ |
*/ |
if ( (dport == 1900) && (id_protocol == IPPROTO_UDP) | if ( (dport == 1900) && (id_protocol == IPPROTO_UDP) |
&& (ssdp.sin_addr.s_addr == iph->ip_dst.s_addr) ) { |
&& (ssdp.sin_addr.s_addr == iph->ip_dst.s_addr) ) { |
| |
/* get the index that the packet came in on */ |
/* get the index that the packet came in on */ |
u_int32_t idx = nfq_get_indev(nfa); |
u_int32_t idx = nfq_get_indev(nfa); |
int i = 0; |
int i = 0; |
Line 248 static int nfqueue_cb(
|
Line 286 static int nfqueue_cb(
|
struct udphdr *udp = (struct udphdr *) (pkt + sizeof(struct ip)); |
struct udphdr *udp = (struct udphdr *) (pkt + sizeof(struct ip)); |
|
|
char *dd = pkt + x; |
char *dd = pkt + x; |
| |
struct sockaddr_in sendername; |
struct sockaddr_in sendername; |
sendername.sin_family = AF_INET; |
sendername.sin_family = AF_INET; |
sendername.sin_port = udp->source; |
sendername.sin_port = udp->source; |
sendername.sin_addr.s_addr = iph->ip_src.s_addr; |
sendername.sin_addr.s_addr = iph->ip_src.s_addr; |
|
|
/* printf("pkt found %s\n",dd);*/ |
/* printf("pkt found %s\n",dd);*/ |
ProcessSSDPData (sudp, dd, sendername, size - x, (unsigned short) 5555); | ProcessSSDPData (sudp, dd, size - x, |
| &sendername, (unsigned short) 5555); |
} |
} |
} |
} |
} |
} |
| |
nfq_set_verdict(qh, id, NF_ACCEPT, 0, NULL); |
nfq_set_verdict(qh, id, NF_ACCEPT, 0, NULL); |
|
|
} else { |
} else { |
syslog(LOG_ERR,"nfq_get_msg_packet_hdr failed"); |
syslog(LOG_ERR,"nfq_get_msg_packet_hdr failed"); |
return 1; // from nfqueue source: 0 = ok, >0 = soft error, <0 hard error | return 1; |
| /* from nfqueue source: 0 = ok, >0 = soft error, <0 hard error */ |
} |
} |
|
|
return 0; |
return 0; |
Line 344 write_ctlsockets_list(int fd, struct ctlelem * e)
|
Line 384 write_ctlsockets_list(int fd, struct ctlelem * e)
|
} |
} |
} |
} |
|
|
|
#ifndef DISABLE_CONFIG_FILE |
static void |
static void |
write_option_list(int fd) |
write_option_list(int fd) |
{ |
{ |
char buffer[256]; |
char buffer[256]; |
int len; |
int len; |
int i; | unsigned int i; |
write(fd, "Options :\n", 10); |
write(fd, "Options :\n", 10); |
for(i=0; i<num_options; i++) |
for(i=0; i<num_options; i++) |
{ |
{ |
Line 359 write_option_list(int fd)
|
Line 400 write_option_list(int fd)
|
write(fd, buffer, len); |
write(fd, buffer, len); |
} |
} |
} |
} |
|
#endif |
|
|
static void |
static void |
write_command_line(int fd, int argc, char * * argv) |
write_command_line(int fd, int argc, char * * argv) |
Line 378 write_command_line(int fd, int argc, char * * argv)
|
Line 420 write_command_line(int fd, int argc, char * * argv)
|
|
|
#endif |
#endif |
|
|
/* Handler for the SIGTERM signal (kill) | /* Handler for the SIGTERM signal (kill) |
* SIGINT is also handled */ |
* SIGINT is also handled */ |
static void |
static void |
sigterm(int sig) |
sigterm(int sig) |
{ |
{ |
/*int save_errno = errno;*/ | UNUSED(sig); |
signal(sig, SIG_IGN); /* Ignore this signal while we are quitting */ | /*int save_errno = errno; */ |
| /*signal(sig, SIG_IGN);*/ /* Ignore this signal while we are quitting */ |
| /* Note : isn't it useless ? */ |
|
|
|
#if 0 |
|
/* calling syslog() is forbidden in signal handler according to |
|
* signal(3) */ |
syslog(LOG_NOTICE, "received signal %d, good-bye", sig); |
syslog(LOG_NOTICE, "received signal %d, good-bye", sig); |
|
#endif |
|
|
quitting = 1; |
quitting = 1; |
/*errno = save_errno;*/ |
/*errno = save_errno;*/ |
Line 396 sigterm(int sig)
|
Line 444 sigterm(int sig)
|
static void |
static void |
sigusr1(int sig) |
sigusr1(int sig) |
{ |
{ |
|
UNUSED(sig); |
|
#if 0 |
|
/* calling syslog() is forbidden in signal handler according to |
|
* signal(3) */ |
syslog(LOG_INFO, "received signal %d, public ip address change", sig); |
syslog(LOG_INFO, "received signal %d, public ip address change", sig); |
|
#endif |
|
|
should_send_public_address_change_notif = 1; |
should_send_public_address_change_notif = 1; |
} |
} |
Line 472 set_startup_time(int sysuptime)
|
Line 525 set_startup_time(int sysuptime)
|
struct runtime_vars { |
struct runtime_vars { |
/* LAN IP addresses for SSDP traffic and HTTP */ |
/* LAN IP addresses for SSDP traffic and HTTP */ |
/* moved to global vars */ |
/* moved to global vars */ |
/*int n_lan_addr;*/ |
|
/*struct lan_addr_s lan_addr[MAX_LAN_ADDR];*/ |
|
int port; /* HTTP Port */ |
int port; /* HTTP Port */ |
int notify_interval; /* seconds between SSDP announces */ |
int notify_interval; /* seconds between SSDP announces */ |
/* unused rules cleaning related variables : */ |
/* unused rules cleaning related variables : */ |
Line 483 struct runtime_vars {
|
Line 534 struct runtime_vars {
|
|
|
/* parselanaddr() |
/* parselanaddr() |
* parse address with mask |
* parse address with mask |
* ex: 192.168.1.1/24 | * ex: 192.168.1.1/24 or 192.168.1.1/255.255.255.0 |
* When MULTIPLE_EXTERNAL_IP is enabled, the ip address of the |
* When MULTIPLE_EXTERNAL_IP is enabled, the ip address of the |
* external interface associated with the lan subnet follows. |
* external interface associated with the lan subnet follows. |
* ex : 192.168.1.1/24 81.21.41.11 |
* ex : 192.168.1.1/24 81.21.41.11 |
* |
* |
* return value : | * Can also use the interface name (ie eth0) |
| * |
| * return value : |
* 0 : ok |
* 0 : ok |
* -1 : error */ |
* -1 : error */ |
static int |
static int |
parselanaddr(struct lan_addr_s * lan_addr, const char * str) |
parselanaddr(struct lan_addr_s * lan_addr, const char * str) |
{ |
{ |
const char * p; |
const char * p; |
int nbits = 24; /* by default, networks are /24 */ |
|
int n; |
int n; |
|
char tmp[16]; |
|
|
|
memset(lan_addr, 0, sizeof(struct lan_addr_s)); |
p = str; |
p = str; |
while(*p && *p != '/' && !isspace(*p)) |
while(*p && *p != '/' && !isspace(*p)) |
p++; |
p++; |
n = p - str; |
n = p - str; |
if(*p == '/') | if(!isdigit(str[0]) && n < (int)sizeof(lan_addr->ifname)) |
{ |
{ |
nbits = atoi(++p); | /* not starting with a digit : suppose it is an interface name */ |
while(*p && !isspace(*p)) | memcpy(lan_addr->ifname, str, n); |
p++; | lan_addr->ifname[n] = '\0'; |
| if(getifaddr(lan_addr->ifname, lan_addr->str, sizeof(lan_addr->str)) < 0) |
| goto parselan_error; |
} |
} |
if(n>15) | else |
{ |
{ |
fprintf(stderr, "Error parsing address/mask : %s\n", str); | if(n>15) |
return -1; | goto parselan_error; |
| memcpy(lan_addr->str, str, n); |
| lan_addr->str[n] = '\0'; |
} |
} |
memcpy(lan_addr->str, str, n); |
|
lan_addr->str[n] = '\0'; |
|
if(!inet_aton(lan_addr->str, &lan_addr->addr)) |
if(!inet_aton(lan_addr->str, &lan_addr->addr)) |
|
goto parselan_error; |
|
if(*p == '/') |
{ |
{ |
fprintf(stderr, "Error parsing address/mask : %s\n", str); | const char * q = ++p; |
return -1; | while(*p && isdigit(*p)) |
| p++; |
| if(*p=='.') |
| { |
| while(*p && (*p=='.' || isdigit(*p))) |
| p++; |
| n = p - q; |
| if(n>15) |
| goto parselan_error; |
| memcpy(tmp, q, n); |
| tmp[n] = '\0'; |
| if(!inet_aton(tmp, &lan_addr->mask)) |
| goto parselan_error; |
| } |
| else |
| { |
| int nbits = atoi(q); |
| if(nbits > 32 || nbits < 0) |
| goto parselan_error; |
| lan_addr->mask.s_addr = htonl(nbits ? (0xffffffffu << (32 - nbits)) : 0); |
| } |
} |
} |
lan_addr->mask.s_addr = htonl(nbits ? (0xffffffff << (32 - nbits)) : 0); | else |
| { |
| /* by default, networks are /24 */ |
| lan_addr->mask.s_addr = htonl(0xffffff00u); |
| } |
#ifdef MULTIPLE_EXTERNAL_IP |
#ifdef MULTIPLE_EXTERNAL_IP |
/* skip spaces */ |
/* skip spaces */ |
while(*p && isspace(*p)) |
while(*p && isspace(*p)) |
Line 539 parselanaddr(struct lan_addr_s * lan_addr, const char
|
Line 622 parselanaddr(struct lan_addr_s * lan_addr, const char
|
} |
} |
} |
} |
#endif |
#endif |
|
#ifdef ENABLE_IPV6 |
|
if(lan_addr->ifname[0] != '\0') |
|
{ |
|
lan_addr->index = if_nametoindex(lan_addr->ifname); |
|
if(lan_addr->index == 0) |
|
fprintf(stderr, "Cannot get index for network interface %s", |
|
lan_addr->ifname); |
|
} |
|
#endif |
return 0; |
return 0; |
|
parselan_error: |
|
fprintf(stderr, "Error parsing address/mask (or interface name) : %s\n", |
|
str); |
|
return -1; |
} |
} |
|
|
/* init phase : |
/* init phase : |
Line 557 init(int argc, char * * argv, struct runtime_vars * v)
|
Line 653 init(int argc, char * * argv, struct runtime_vars * v)
|
int i; |
int i; |
int pid; |
int pid; |
int debug_flag = 0; |
int debug_flag = 0; |
int options_flag = 0; |
|
int openlog_option; |
int openlog_option; |
struct sigaction sa; |
struct sigaction sa; |
/*const char * logfilename = 0;*/ |
/*const char * logfilename = 0;*/ |
const char * presurl = 0; |
const char * presurl = 0; |
|
#ifndef DISABLE_CONFIG_FILE |
|
int options_flag = 0; |
const char * optionsfile = DEFAULT_CONFIG; |
const char * optionsfile = DEFAULT_CONFIG; |
|
#endif /* DISABLE_CONFIG_FILE */ |
|
struct lan_addr_s * lan_addr; |
|
struct lan_addr_s * lan_addr2; |
|
|
/* only print usage if -h is used */ |
/* only print usage if -h is used */ |
for(i=1; i<argc; i++) |
for(i=1; i<argc; i++) |
Line 570 init(int argc, char * * argv, struct runtime_vars * v)
|
Line 670 init(int argc, char * * argv, struct runtime_vars * v)
|
if(0 == strcmp(argv[i], "-h")) |
if(0 == strcmp(argv[i], "-h")) |
goto print_usage; |
goto print_usage; |
} |
} |
|
#ifndef DISABLE_CONFIG_FILE |
/* first check if "-f" option is used */ |
/* first check if "-f" option is used */ |
for(i=2; i<argc; i++) |
for(i=2; i<argc; i++) |
{ |
{ |
Line 580 init(int argc, char * * argv, struct runtime_vars * v)
|
Line 681 init(int argc, char * * argv, struct runtime_vars * v)
|
break; |
break; |
} |
} |
} |
} |
|
#endif /* DISABLE_CONFIG_FILE */ |
|
|
/* set initial values */ |
/* set initial values */ |
SETFLAG(ENABLEUPNPMASK); | SETFLAG(ENABLEUPNPMASK); /* UPnP is enabled by default */ |
|
|
/*v->n_lan_addr = 0;*/ | LIST_INIT(&lan_addrs); |
v->port = -1; |
v->port = -1; |
v->notify_interval = 30; /* seconds between SSDP announces */ |
v->notify_interval = 30; /* seconds between SSDP announces */ |
v->clean_ruleset_threshold = 20; |
v->clean_ruleset_threshold = 20; |
v->clean_ruleset_interval = 0; /* interval between ruleset check. 0=disabled */ |
v->clean_ruleset_interval = 0; /* interval between ruleset check. 0=disabled */ |
| #ifndef DISABLE_CONFIG_FILE |
/* read options file first since |
/* read options file first since |
* command line arguments have final say */ |
* command line arguments have final say */ |
if(readoptionsfile(optionsfile) < 0) |
if(readoptionsfile(optionsfile) < 0) |
Line 600 init(int argc, char * * argv, struct runtime_vars * v)
|
Line 702 init(int argc, char * * argv, struct runtime_vars * v)
|
} |
} |
else |
else |
{ |
{ |
for(i=0; i<num_options; i++) | for(i=0; i<(int)num_options; i++) |
{ |
{ |
switch(ary_options[i].id) |
switch(ary_options[i].id) |
{ |
{ |
Line 611 init(int argc, char * * argv, struct runtime_vars * v)
|
Line 713 init(int argc, char * * argv, struct runtime_vars * v)
|
use_ext_ip_addr = ary_options[i].value; |
use_ext_ip_addr = ary_options[i].value; |
break; |
break; |
case UPNPLISTENING_IP: |
case UPNPLISTENING_IP: |
if(n_lan_addr < MAX_LAN_ADDR)/* if(v->n_lan_addr < MAX_LAN_ADDR)*/ | lan_addr = (struct lan_addr_s *) malloc(sizeof(struct lan_addr_s)); |
| if (lan_addr == NULL) |
{ |
{ |
/*if(parselanaddr(&v->lan_addr[v->n_lan_addr],*/ | fprintf(stderr, "malloc(sizeof(struct lan_addr_s)): %m"); |
if(parselanaddr(&lan_addr[n_lan_addr], | break; |
ary_options[i].value) == 0) | |
n_lan_addr++; /*v->n_lan_addr++; */ | |
} |
} |
else | if(parselanaddr(lan_addr, ary_options[i].value) != 0) |
{ |
{ |
fprintf(stderr, "Too many listening ips (max: %d), ignoring %s\n", | fprintf(stderr, "can't parse \"%s\" as valid lan address\n", ary_options[i].value); |
MAX_LAN_ADDR, ary_options[i].value); | free(lan_addr); |
| break; |
} |
} |
|
LIST_INSERT_HEAD(&lan_addrs, lan_addr, list); |
break; |
break; |
case UPNPPORT: |
case UPNPPORT: |
v->port = atoi(ary_options[i].value); |
v->port = atoi(ary_options[i].value); |
Line 636 init(int argc, char * * argv, struct runtime_vars * v)
|
Line 739 init(int argc, char * * argv, struct runtime_vars * v)
|
case UPNPPRESENTATIONURL: |
case UPNPPRESENTATIONURL: |
presurl = ary_options[i].value; |
presurl = ary_options[i].value; |
break; |
break; |
|
case UPNPFRIENDLY_NAME: |
|
strncpy(friendly_name, ary_options[i].value, FRIENDLY_NAME_MAX_LEN); |
|
friendly_name[FRIENDLY_NAME_MAX_LEN-1] = '\0'; |
|
break; |
#ifdef USE_NETFILTER |
#ifdef USE_NETFILTER |
case UPNPFORWARDCHAIN: |
case UPNPFORWARDCHAIN: |
miniupnpd_forward_chain = ary_options[i].value; |
miniupnpd_forward_chain = ary_options[i].value; |
Line 651 init(int argc, char * * argv, struct runtime_vars * v)
|
Line 758 init(int argc, char * * argv, struct runtime_vars * v)
|
if(strcmp(ary_options[i].value, "yes") == 0) |
if(strcmp(ary_options[i].value, "yes") == 0) |
SETFLAG(SYSUPTIMEMASK); /*sysuptime = 1;*/ |
SETFLAG(SYSUPTIMEMASK); /*sysuptime = 1;*/ |
break; |
break; |
|
#if defined(USE_PF) || defined(USE_IPF) |
case UPNPPACKET_LOG: |
case UPNPPACKET_LOG: |
if(strcmp(ary_options[i].value, "yes") == 0) |
if(strcmp(ary_options[i].value, "yes") == 0) |
SETFLAG(LOGPACKETSMASK); /*logpackets = 1;*/ |
SETFLAG(LOGPACKETSMASK); /*logpackets = 1;*/ |
break; |
break; |
|
#endif |
case UPNPUUID: |
case UPNPUUID: |
strncpy(uuidvalue+5, ary_options[i].value, |
strncpy(uuidvalue+5, ary_options[i].value, |
strlen(uuidvalue+5) + 1); |
strlen(uuidvalue+5) + 1); |
Line 662 init(int argc, char * * argv, struct runtime_vars * v)
|
Line 771 init(int argc, char * * argv, struct runtime_vars * v)
|
case UPNPSERIAL: |
case UPNPSERIAL: |
strncpy(serialnumber, ary_options[i].value, SERIALNUMBER_MAX_LEN); |
strncpy(serialnumber, ary_options[i].value, SERIALNUMBER_MAX_LEN); |
serialnumber[SERIALNUMBER_MAX_LEN-1] = '\0'; |
serialnumber[SERIALNUMBER_MAX_LEN-1] = '\0'; |
break; | break; |
case UPNPMODEL_NUMBER: |
case UPNPMODEL_NUMBER: |
strncpy(modelnumber, ary_options[i].value, MODELNUMBER_MAX_LEN); |
strncpy(modelnumber, ary_options[i].value, MODELNUMBER_MAX_LEN); |
modelnumber[MODELNUMBER_MAX_LEN-1] = '\0'; |
modelnumber[MODELNUMBER_MAX_LEN-1] = '\0'; |
Line 674 init(int argc, char * * argv, struct runtime_vars * v)
|
Line 783 init(int argc, char * * argv, struct runtime_vars * v)
|
v->clean_ruleset_interval = atoi(ary_options[i].value); |
v->clean_ruleset_interval = atoi(ary_options[i].value); |
break; |
break; |
#ifdef USE_PF |
#ifdef USE_PF |
|
case UPNPANCHOR: |
|
anchor_name = ary_options[i].value; |
|
break; |
case UPNPQUEUE: |
case UPNPQUEUE: |
queue = ary_options[i].value; |
queue = ary_options[i].value; |
break; |
break; |
Line 719 init(int argc, char * * argv, struct runtime_vars * v)
|
Line 831 init(int argc, char * * argv, struct runtime_vars * v)
|
} |
} |
} |
} |
} |
} |
|
#endif /* DISABLE_CONFIG_FILE */ |
|
|
/* command line arguments processing */ |
/* command line arguments processing */ |
for(i=1; i<argc; i++) |
for(i=1; i<argc; i++) |
Line 741 init(int argc, char * * argv, struct runtime_vars * v)
|
Line 854 init(int argc, char * * argv, struct runtime_vars * v)
|
else |
else |
fprintf(stderr, "Option -%c takes one argument.\n", argv[i][1]); |
fprintf(stderr, "Option -%c takes one argument.\n", argv[i][1]); |
break; |
break; |
|
case 'r': |
|
if(i+1 < argc) |
|
v->clean_ruleset_interval = atoi(argv[++i]); |
|
else |
|
fprintf(stderr, "Option -%c takes one argument.\n", argv[i][1]); |
|
break; |
case 'u': |
case 'u': |
if(i+1 < argc) |
if(i+1 < argc) |
strncpy(uuidvalue+5, argv[++i], strlen(uuidvalue+5) + 1); |
strncpy(uuidvalue+5, argv[++i], strlen(uuidvalue+5) + 1); |
else |
else |
fprintf(stderr, "Option -%c takes one argument.\n", argv[i][1]); |
fprintf(stderr, "Option -%c takes one argument.\n", argv[i][1]); |
break; |
break; |
|
case 'z': |
|
if(i+1 < argc) |
|
strncpy(friendly_name, argv[++i], FRIENDLY_NAME_MAX_LEN); |
|
else |
|
fprintf(stderr, "Option -%c takes one argument.\n", argv[i][1]); |
|
friendly_name[FRIENDLY_NAME_MAX_LEN-1] = '\0'; |
|
break; |
case 's': |
case 's': |
if(i+1 < argc) |
if(i+1 < argc) |
strncpy(serialnumber, argv[++i], SERIALNUMBER_MAX_LEN); |
strncpy(serialnumber, argv[++i], SERIALNUMBER_MAX_LEN); |
Line 774 init(int argc, char * * argv, struct runtime_vars * v)
|
Line 900 init(int argc, char * * argv, struct runtime_vars * v)
|
/*case 'l': |
/*case 'l': |
logfilename = argv[++i]; |
logfilename = argv[++i]; |
break;*/ |
break;*/ |
|
#if defined(USE_PF) || defined(USE_IPF) |
case 'L': |
case 'L': |
/*logpackets = 1;*/ |
/*logpackets = 1;*/ |
SETFLAG(LOGPACKETSMASK); |
SETFLAG(LOGPACKETSMASK); |
break; |
break; |
|
#endif |
case 'S': |
case 'S': |
SETFLAG(SECUREMODEMASK); |
SETFLAG(SECUREMODEMASK); |
break; |
break; |
Line 854 init(int argc, char * * argv, struct runtime_vars * v)
|
Line 982 init(int argc, char * * argv, struct runtime_vars * v)
|
fprintf(stderr, "Option -%c takes two arguments.\n", argv[i][1]); |
fprintf(stderr, "Option -%c takes two arguments.\n", argv[i][1]); |
break; |
break; |
case 'a': |
case 'a': |
|
#ifndef MULTIPLE_EXTERNAL_IP |
if(i+1 < argc) |
if(i+1 < argc) |
{ |
{ |
int address_already_there = 0; |
|
int j; |
|
i++; |
i++; |
for(j=0; j<n_lan_addr; j++) | lan_addr = (struct lan_addr_s *) malloc(sizeof(struct lan_addr_s)); |
| if (lan_addr == NULL) |
{ |
{ |
struct lan_addr_s tmpaddr; | fprintf(stderr, "malloc(sizeof(struct lan_addr_s)): %m"); |
parselanaddr(&tmpaddr, argv[i]); | break; |
if(0 == strcmp(lan_addr[j].str, tmpaddr.str)) | |
address_already_there = 1; | |
} |
} |
if(address_already_there) | if(parselanaddr(lan_addr, argv[i]) != 0) |
| { |
| fprintf(stderr, "can't parse \"%s\" as valid lan address\n", argv[i]); |
| free(lan_addr); |
break; |
break; |
if(n_lan_addr < MAX_LAN_ADDR) | } |
| /* check if we already have this address */ |
| for(lan_addr2 = lan_addrs.lh_first; lan_addr2 != NULL; lan_addr2 = lan_addr2->list.le_next) |
{ |
{ |
if(parselanaddr(&lan_addr[n_lan_addr], argv[i]) == 0) | if (0 == strncmp(lan_addr2->str, lan_addr->str, 15)) |
n_lan_addr++; | break; |
} |
} |
else | if (lan_addr2 == NULL) |
| LIST_INSERT_HEAD(&lan_addrs, lan_addr, list); |
| } |
| else |
| fprintf(stderr, "Option -%c takes one argument.\n", argv[i][1]); |
| #else |
| if(i+2 < argc) |
| { |
| char *val=calloc((strlen(argv[i+1]) + strlen(argv[i+2]) + 1), sizeof(char)); |
| if (val == NULL) |
{ |
{ |
fprintf(stderr, "Too many listening ips (max: %d), ignoring %s\n", | fprintf(stderr, "memory allocation error for listen address storage\n"); |
MAX_LAN_ADDR, argv[i]); | break; |
} |
} |
|
sprintf(val, "%s %s", argv[i+1], argv[i+2]); |
|
|
|
lan_addr = (struct lan_addr_s *) malloc(sizeof(struct lan_addr_s)); |
|
if (lan_addr == NULL) |
|
{ |
|
fprintf(stderr, "malloc(sizeof(struct lan_addr_s)): %m"); |
|
free(val); |
|
break; |
|
} |
|
if(parselanaddr(lan_addr, val) != 0) |
|
{ |
|
fprintf(stderr, "can't parse \"%s\" as valid lan address\n", val); |
|
free(lan_addr); |
|
free(val); |
|
break; |
|
} |
|
/* check if we already have this address */ |
|
for(lan_addr2 = lan_addrs.lh_first; lan_addr2 != NULL; lan_addr2 = lan_addr2->list.le_next) |
|
{ |
|
if (0 == strncmp(lan_addr2->str, lan_addr->str, 15)) |
|
break; |
|
} |
|
if (lan_addr2 == NULL) |
|
LIST_INSERT_HEAD(&lan_addrs, lan_addr, list); |
|
|
|
free(val); |
|
i+=2; |
} |
} |
else |
else |
|
fprintf(stderr, "Option -%c takes two arguments.\n", argv[i][1]); |
|
#endif |
|
break; |
|
case 'A': |
|
if(i+1 < argc) { |
|
void * tmp; |
|
tmp = realloc(upnppermlist, sizeof(struct upnpperm) * (num_upnpperm+1)); |
|
if(tmp == NULL) { |
|
fprintf(stderr, "memory allocation error for permission\n"); |
|
} else { |
|
upnppermlist = tmp; |
|
if(read_permission_line(upnppermlist + num_upnpperm, argv[++i]) >= 0) { |
|
num_upnpperm++; |
|
} else { |
|
fprintf(stderr, "Permission rule parsing error :\n%s\n", argv[i]); |
|
} |
|
} |
|
} else |
fprintf(stderr, "Option -%c takes one argument.\n", argv[i][1]); |
fprintf(stderr, "Option -%c takes one argument.\n", argv[i][1]); |
break; |
break; |
case 'f': |
case 'f': |
Line 889 init(int argc, char * * argv, struct runtime_vars * v)
|
Line 1074 init(int argc, char * * argv, struct runtime_vars * v)
|
fprintf(stderr, "Unknown option: %s\n", argv[i]); |
fprintf(stderr, "Unknown option: %s\n", argv[i]); |
} |
} |
} |
} |
if(!ext_if_name || (n_lan_addr==0)) | if(!ext_if_name || !lan_addrs.lh_first) |
{ |
{ |
/* bad configuration */ |
/* bad configuration */ |
goto print_usage; |
goto print_usage; |
Line 929 init(int argc, char * * argv, struct runtime_vars * v)
|
Line 1114 init(int argc, char * * argv, struct runtime_vars * v)
|
{ |
{ |
syslog(LOG_ERR, "MiniUPnPd is already running. EXITING"); |
syslog(LOG_ERR, "MiniUPnPd is already running. EXITING"); |
return 1; |
return 1; |
} | } |
|
|
set_startup_time(GETFLAG(SYSUPTIMEMASK)); |
set_startup_time(GETFLAG(SYSUPTIMEMASK)); |
|
|
Line 942 init(int argc, char * * argv, struct runtime_vars * v)
|
Line 1127 init(int argc, char * * argv, struct runtime_vars * v)
|
else |
else |
{ |
{ |
snprintf(presentationurl, PRESENTATIONURL_MAX_LEN, |
snprintf(presentationurl, PRESENTATIONURL_MAX_LEN, |
"http://%s/", lan_addr[0].str); | "http://%s/", lan_addrs.lh_first->str); |
/*"http://%s:%d/", lan_addr[0].str, 80);*/ | /*"http://%s:%d/", lan_addrs.lh_first->str, 80);*/ |
} |
} |
|
|
/* set signal handler */ |
/* set signal handler */ |
memset(&sa, 0, sizeof(struct sigaction)); |
memset(&sa, 0, sizeof(struct sigaction)); |
sa.sa_handler = sigterm; |
sa.sa_handler = sigterm; |
|
|
if (sigaction(SIGTERM, &sa, NULL)) | if(sigaction(SIGTERM, &sa, NULL) < 0) |
{ |
{ |
syslog(LOG_ERR, "Failed to set %s handler. EXITING", "SIGTERM"); |
syslog(LOG_ERR, "Failed to set %s handler. EXITING", "SIGTERM"); |
return 1; |
return 1; |
} |
} |
if (sigaction(SIGINT, &sa, NULL)) | if(sigaction(SIGINT, &sa, NULL) < 0) |
{ |
{ |
syslog(LOG_ERR, "Failed to set %s handler. EXITING", "SIGINT"); |
syslog(LOG_ERR, "Failed to set %s handler. EXITING", "SIGINT"); |
return 1; |
return 1; |
} |
} |
| sa.sa_handler = SIG_IGN; |
if(signal(SIGPIPE, SIG_IGN) == SIG_ERR) { | if(sigaction(SIGPIPE, &sa, NULL) < 0) |
| { |
syslog(LOG_ERR, "Failed to ignore SIGPIPE signals"); |
syslog(LOG_ERR, "Failed to ignore SIGPIPE signals"); |
} |
} |
|
|
sa.sa_handler = sigusr1; |
sa.sa_handler = sigusr1; |
if (sigaction(SIGUSR1, &sa, NULL)) | if(sigaction(SIGUSR1, &sa, NULL) < 0) |
{ |
{ |
syslog(LOG_NOTICE, "Failed to set %s handler", "SIGUSR1"); |
syslog(LOG_NOTICE, "Failed to set %s handler", "SIGUSR1"); |
} |
} |
Line 976 init(int argc, char * * argv, struct runtime_vars * v)
|
Line 1161 init(int argc, char * * argv, struct runtime_vars * v)
|
syslog(LOG_ERR, "Failed to init redirection engine. EXITING"); |
syslog(LOG_ERR, "Failed to init redirection engine. EXITING"); |
return 1; |
return 1; |
} |
} |
|
#ifdef ENABLE_6FC_SERVICE |
|
#ifdef USE_NETFILTER |
|
init_iptpinhole(); |
|
#endif |
|
#endif |
|
|
writepidfile(pidfilename, pid); | if(writepidfile(pidfilename, pid) < 0) |
| pidfilename = NULL; |
|
|
#ifdef ENABLE_LEASEFILE |
#ifdef ENABLE_LEASEFILE |
/*remove(lease_file);*/ |
/*remove(lease_file);*/ |
Line 988 init(int argc, char * * argv, struct runtime_vars * v)
|
Line 1179 init(int argc, char * * argv, struct runtime_vars * v)
|
return 0; |
return 0; |
print_usage: |
print_usage: |
fprintf(stderr, "Usage:\n\t" |
fprintf(stderr, "Usage:\n\t" |
"%s [-f config_file] [-i ext_ifname] [-o ext_ip]\n" | "%s " |
#ifndef ENABLE_NATPMP | #ifndef DISABLE_CONFIG_FILE |
"\t\t[-a listening_ip] [-p port] [-d] [-L] [-U] [-S]\n" | "[-f config_file] " |
| #endif |
| "[-i ext_ifname] [-o ext_ip]\n" |
| #ifndef MULTIPLE_EXTERNAL_IP |
| "\t\t[-a listening_ip]" |
#else |
#else |
"\t\t[-a listening_ip] [-p port] [-d] [-L] [-U] [-S] [-N]\n" | "\t\t[-a listening_ip ext_ip]" |
#endif |
#endif |
|
" [-p port] [-d]" |
|
#if defined(USE_PF) || defined(USE_IPF) |
|
" [-L]" |
|
#endif |
|
" [-U] [-S]" |
|
#ifdef ENABLE_NATPMP |
|
" [-N]" |
|
#endif |
|
"\n" |
/*"[-l logfile] " not functionnal */ |
/*"[-l logfile] " not functionnal */ |
"\t\t[-u uuid] [-s serial] [-m model_number] \n" |
"\t\t[-u uuid] [-s serial] [-m model_number] \n" |
"\t\t[-t notify_interval] [-P pid_filename]\n" | "\t\t[-t notify_interval] [-P pid_filename] [-z fiendly_name]\n" |
"\t\t[-B down up] [-w url]\n" | "\t\t[-B down up] [-w url] [-r clean_ruleset_interval]\n" |
#ifdef USE_PF |
#ifdef USE_PF |
"\t\t[-q queue] [-T tag]\n" |
"\t\t[-q queue] [-T tag]\n" |
#endif |
#endif |
#ifdef ENABLE_NFQUEUE |
#ifdef ENABLE_NFQUEUE |
"\t\t[-Q queue] [-n name]\n" |
"\t\t[-Q queue] [-n name]\n" |
#endif |
#endif |
|
"\t\t[-A \"permission rule\"]\n" |
"\nNotes:\n\tThere can be one or several listening_ips.\n" |
"\nNotes:\n\tThere can be one or several listening_ips.\n" |
"\tNotify interval is in seconds. Default is 30 seconds.\n" |
"\tNotify interval is in seconds. Default is 30 seconds.\n" |
"\tDefault pid file is '%s'.\n" |
"\tDefault pid file is '%s'.\n" |
"\tDefault config file is '%s'.\n" |
"\tDefault config file is '%s'.\n" |
"\tWith -d miniupnpd will run as a standard program.\n" |
"\tWith -d miniupnpd will run as a standard program.\n" |
|
#if defined(USE_PF) || defined(USE_IPF) |
"\t-L sets packet log in pf and ipf on.\n" |
"\t-L sets packet log in pf and ipf on.\n" |
|
#endif |
"\t-S sets \"secure\" mode : clients can only add mappings to their own ip\n" |
"\t-S sets \"secure\" mode : clients can only add mappings to their own ip\n" |
"\t-U causes miniupnpd to report system uptime instead " |
"\t-U causes miniupnpd to report system uptime instead " |
"of daemon uptime.\n" |
"of daemon uptime.\n" |
#ifdef ENABLE_NATPMP |
#ifdef ENABLE_NATPMP |
"\t-N enable NAT-PMP functionnality.\n" | "\t-N enable NAT-PMP functionality.\n" |
#endif |
#endif |
"\t-B sets bitrates reported by daemon in bits per second.\n" |
"\t-B sets bitrates reported by daemon in bits per second.\n" |
"\t-w sets the presentation url. Default is http address on port 80\n" |
"\t-w sets the presentation url. Default is http address on port 80\n" |
Line 1023 print_usage:
|
Line 1230 print_usage:
|
"\t-T sets the tag name in pf.\n" |
"\t-T sets the tag name in pf.\n" |
#endif |
#endif |
#ifdef ENABLE_NFQUEUE |
#ifdef ENABLE_NFQUEUE |
"\t-Q sets the queue number that is used by NFQUEUE.\n" | "\t-Q sets the queue number that is used by NFQUEUE.\n" |
"\t-n sets the name of the interface(s) that packets will arrive on.\n" | "\t-n sets the name of the interface(s) that packets will arrive on.\n" |
#endif |
#endif |
|
"\t-A use following syntax for permission rules :\n" |
|
"\t (allow|deny) (external port range) ip/mask (internal port range)\n" |
|
"\texamples :\n" |
|
"\t \"allow 1024-65535 192.168.1.0/24 1024-65535\"\n" |
|
"\t \"deny 0-65535 0.0.0.0/0 0-65535\"\n" |
"\t-h prints this help and quits.\n" |
"\t-h prints this help and quits.\n" |
"", argv[0], pidfilename, DEFAULT_CONFIG); |
"", argv[0], pidfilename, DEFAULT_CONFIG); |
return 1; |
return 1; |
Line 1037 int
|
Line 1249 int
|
main(int argc, char * * argv) |
main(int argc, char * * argv) |
{ |
{ |
int i; |
int i; |
int shttpl = -1; | int shttpl = -1; /* socket for HTTP */ |
| int sudp = -1; /* IP v4 socket for receiving SSDP */ |
| #ifdef ENABLE_IPV6 |
| int sudpv6 = -1; /* IP v6 socket for receiving SSDP */ |
| #endif |
#ifdef ENABLE_NATPMP |
#ifdef ENABLE_NATPMP |
int snatpmp[MAX_LAN_ADDR]; | int * snatpmp = NULL; |
| #endif |
#ifdef ENABLE_NFQUEUE |
#ifdef ENABLE_NFQUEUE |
int nfqh = -1; |
int nfqh = -1; |
#endif |
#endif |
|
#ifdef USE_IFACEWATCHER |
|
int sifacewatcher = -1; |
#endif |
#endif |
int snotify[MAX_LAN_ADDR]; | |
| int * snotify = NULL; |
| int addr_count; |
LIST_HEAD(httplisthead, upnphttp) upnphttphead; |
LIST_HEAD(httplisthead, upnphttp) upnphttphead; |
struct upnphttp * e = 0; |
struct upnphttp * e = 0; |
struct upnphttp * next; |
struct upnphttp * next; |
fd_set readset; /* for select() */ |
fd_set readset; /* for select() */ |
#ifdef ENABLE_EVENTS |
|
fd_set writeset; |
fd_set writeset; |
#endif |
|
struct timeval timeout, timeofday, lasttimeofday = {0, 0}; |
struct timeval timeout, timeofday, lasttimeofday = {0, 0}; |
int max_fd = -1; |
int max_fd = -1; |
#ifdef USE_MINIUPNPDCTL |
#ifdef USE_MINIUPNPDCTL |
Line 1064 main(int argc, char * * argv)
|
Line 1283 main(int argc, char * * argv)
|
/* variables used for the unused-rule cleanup process */ |
/* variables used for the unused-rule cleanup process */ |
struct rule_state * rule_list = 0; |
struct rule_state * rule_list = 0; |
struct timeval checktime = {0, 0}; |
struct timeval checktime = {0, 0}; |
syslog(LOG_INFO, "SNet version started"); | struct lan_addr_s * lan_addr; |
| #ifdef ENABLE_6FC_SERVICE |
| unsigned int next_pinhole_ts; |
memset(snotify, 0, sizeof(snotify)); | |
#ifdef ENABLE_NATPMP | |
for(i = 0; i < MAX_LAN_ADDR; i++) | |
snatpmp[i] = -1; | |
#endif |
#endif |
|
|
if(init(argc, argv, &v) != 0) |
if(init(argc, argv, &v) != 0) |
return 1; |
return 1; |
|
/* count lan addrs */ |
|
addr_count = 0; |
|
for(lan_addr = lan_addrs.lh_first; lan_addr != NULL; lan_addr = lan_addr->list.le_next) |
|
addr_count++; |
|
if(addr_count > 0) { |
|
#ifndef ENABLE_IPV6 |
|
snotify = calloc(addr_count, sizeof(int)); |
|
#else |
|
/* one for IPv4, one for IPv6 */ |
|
snotify = calloc(addr_count * 2, sizeof(int)); |
|
#endif |
|
} |
|
#ifdef ENABLE_NATPMP |
|
if(addr_count > 0) { |
|
snatpmp = malloc(addr_count * sizeof(int)); |
|
for(i = 0; i < addr_count; i++) |
|
snatpmp[i] = -1; |
|
} |
|
#endif |
|
|
LIST_INIT(&upnphttphead); |
LIST_INIT(&upnphttphead); |
#ifdef USE_MINIUPNPDCTL |
#ifdef USE_MINIUPNPDCTL |
Line 1089 main(int argc, char * * argv)
|
Line 1324 main(int argc, char * * argv)
|
return 0; |
return 0; |
} |
} |
|
|
|
syslog(LOG_INFO, "Starting%s%swith external interface %s", |
|
#ifdef ENABLE_NATPMP |
|
GETFLAG(ENABLENATPMPMASK) ? " NAT-PMP " : " ", |
|
#else |
|
" ", |
|
#endif |
|
GETFLAG(ENABLEUPNPMASK) ? "UPnP-IGD " : "", |
|
ext_if_name); |
|
|
if(GETFLAG(ENABLEUPNPMASK)) |
if(GETFLAG(ENABLEUPNPMASK)) |
{ |
{ |
|
|
Line 1109 main(int argc, char * * argv)
|
Line 1353 main(int argc, char * * argv)
|
v.port = ntohs(sockinfo.sin_port); |
v.port = ntohs(sockinfo.sin_port); |
} |
} |
syslog(LOG_NOTICE, "HTTP listening on port %d", v.port); |
syslog(LOG_NOTICE, "HTTP listening on port %d", v.port); |
|
#ifdef ENABLE_IPV6 |
|
if(find_ipv6_addr(NULL, ipv6_addr_for_http_with_brackets, sizeof(ipv6_addr_for_http_with_brackets)) > 0) { |
|
syslog(LOG_NOTICE, "HTTP IPv6 address given to control points : %s", |
|
ipv6_addr_for_http_with_brackets); |
|
} else { |
|
memcpy(ipv6_addr_for_http_with_brackets, "[::1]", 6); |
|
syslog(LOG_WARNING, "no HTTP IPv6 address"); |
|
} |
|
#endif |
|
|
/* open socket for SSDP connections */ |
/* open socket for SSDP connections */ |
sudp = OpenAndConfSSDPReceiveSocket(n_lan_addr, lan_addr); | sudp = OpenAndConfSSDPReceiveSocket(0); |
if(sudp < 0) |
if(sudp < 0) |
{ |
{ |
syslog(LOG_INFO, "Failed to open socket for receiving SSDP. Trying to use MiniSSDPd"); | syslog(LOG_NOTICE, "Failed to open socket for receiving SSDP. Trying to use MiniSSDPd"); |
if(SubmitServicesToMiniSSDPD(lan_addr[0].str, v.port) < 0) { | if(SubmitServicesToMiniSSDPD(lan_addrs.lh_first->str, v.port) < 0) { |
syslog(LOG_ERR, "Failed to connect to MiniSSDPd. EXITING"); |
syslog(LOG_ERR, "Failed to connect to MiniSSDPd. EXITING"); |
return 1; |
return 1; |
} |
} |
} |
} |
|
#ifdef ENABLE_IPV6 |
|
sudpv6 = OpenAndConfSSDPReceiveSocket(1); |
|
if(sudpv6 < 0) |
|
{ |
|
syslog(LOG_WARNING, "Failed to open socket for receiving SSDP (IP v6)."); |
|
} |
|
#endif |
|
|
/* open socket for sending notifications */ |
/* open socket for sending notifications */ |
if(OpenAndConfSSDPNotifySockets(snotify) < 0) |
if(OpenAndConfSSDPNotifySockets(snotify) < 0) |
Line 1128 main(int argc, char * * argv)
|
Line 1388 main(int argc, char * * argv)
|
"messages. EXITING"); |
"messages. EXITING"); |
return 1; |
return 1; |
} |
} |
|
|
|
#ifdef USE_IFACEWATCHER |
|
/* open socket for kernel notifications about new network interfaces */ |
|
if (sudp >= 0) |
|
{ |
|
sifacewatcher = OpenAndConfInterfaceWatchSocket(); |
|
if (sifacewatcher < 0) |
|
{ |
|
syslog(LOG_ERR, "Failed to open socket for receiving network interface notifications"); |
|
} |
|
} |
|
#endif |
} |
} |
|
|
#ifdef ENABLE_NATPMP |
#ifdef ENABLE_NATPMP |
Line 1141 main(int argc, char * * argv)
|
Line 1413 main(int argc, char * * argv)
|
syslog(LOG_NOTICE, "Listening for NAT-PMP traffic on port %u", |
syslog(LOG_NOTICE, "Listening for NAT-PMP traffic on port %u", |
NATPMP_PORT); |
NATPMP_PORT); |
} |
} |
|
#if 0 |
ScanNATPMPforExpiration(); |
ScanNATPMPforExpiration(); |
|
#endif |
} |
} |
#endif |
#endif |
|
|
Line 1161 main(int argc, char * * argv)
|
Line 1435 main(int argc, char * * argv)
|
} |
} |
} |
} |
#endif |
#endif |
|
|
/* main loop */ |
/* main loop */ |
while(!quitting) |
while(!quitting) |
{ |
{ |
Line 1168 main(int argc, char * * argv)
|
Line 1443 main(int argc, char * * argv)
|
if((startup_time<60*60*24) && (time(NULL)>60*60*24)) |
if((startup_time<60*60*24) && (time(NULL)>60*60*24)) |
{ |
{ |
set_startup_time(GETFLAG(SYSUPTIMEMASK)); |
set_startup_time(GETFLAG(SYSUPTIMEMASK)); |
} | } |
| /* send public address change notifications if needed */ |
| if(should_send_public_address_change_notif) |
| { |
| syslog(LOG_DEBUG, "should send external iface address change notification(s)"); |
| #ifdef ENABLE_NATPMP |
| if(GETFLAG(ENABLENATPMPMASK)) |
| SendNATPMPPublicAddressChangeNotification(snatpmp, addr_count); |
| #endif |
| #ifdef ENABLE_EVENTS |
| if(GETFLAG(ENABLEUPNPMASK)) |
| { |
| upnp_event_var_change_notify(EWanIPC); |
| } |
| #endif |
| should_send_public_address_change_notif = 0; |
| } |
/* Check if we need to send SSDP NOTIFY messages and do it if |
/* Check if we need to send SSDP NOTIFY messages and do it if |
* needed */ |
* needed */ |
if(gettimeofday(&timeofday, 0) < 0) |
if(gettimeofday(&timeofday, 0) < 0) |
Line 1221 main(int argc, char * * argv)
|
Line 1512 main(int argc, char * * argv)
|
} |
} |
memcpy(&checktime, &timeofday, sizeof(struct timeval)); |
memcpy(&checktime, &timeofday, sizeof(struct timeval)); |
} |
} |
|
/* Remove expired port mappings, based on UPnP IGD LeaseDuration |
|
* or NAT-PMP lifetime) */ |
|
if(nextruletoclean_timestamp |
|
&& ((unsigned int)timeofday.tv_sec >= nextruletoclean_timestamp)) |
|
{ |
|
syslog(LOG_DEBUG, "cleaning expired Port Mappings"); |
|
get_upnp_rules_state_list(0); |
|
} |
|
if(nextruletoclean_timestamp |
|
&& ((unsigned int)timeout.tv_sec >= (nextruletoclean_timestamp - timeofday.tv_sec))) |
|
{ |
|
timeout.tv_sec = nextruletoclean_timestamp - timeofday.tv_sec; |
|
timeout.tv_usec = 0; |
|
syslog(LOG_DEBUG, "setting timeout to %u sec", |
|
(unsigned)timeout.tv_sec); |
|
} |
#ifdef ENABLE_NATPMP |
#ifdef ENABLE_NATPMP |
|
#if 0 |
/* Remove expired NAT-PMP mappings */ |
/* Remove expired NAT-PMP mappings */ |
while( nextnatpmptoclean_timestamp && (timeofday.tv_sec >= nextnatpmptoclean_timestamp + startup_time)) | while(nextnatpmptoclean_timestamp |
| && (timeofday.tv_sec >= nextnatpmptoclean_timestamp + startup_time)) |
{ |
{ |
/*syslog(LOG_DEBUG, "cleaning expired NAT-PMP mappings");*/ |
/*syslog(LOG_DEBUG, "cleaning expired NAT-PMP mappings");*/ |
if(CleanExpiredNATPMP() < 0) { |
if(CleanExpiredNATPMP() < 0) { |
Line 1231 main(int argc, char * * argv)
|
Line 1540 main(int argc, char * * argv)
|
break; |
break; |
} |
} |
} |
} |
if(nextnatpmptoclean_timestamp && timeout.tv_sec >= (nextnatpmptoclean_timestamp + startup_time - timeofday.tv_sec)) | if(nextnatpmptoclean_timestamp |
| && timeout.tv_sec >= (nextnatpmptoclean_timestamp + startup_time - timeofday.tv_sec)) |
{ |
{ |
/*syslog(LOG_DEBUG, "setting timeout to %d sec", nextnatpmptoclean_timestamp + startup_time - timeofday.tv_sec);*/ | /*syslog(LOG_DEBUG, "setting timeout to %d sec", |
#ifdef ENABLE_NFQUEUE | nextnatpmptoclean_timestamp + startup_time - timeofday.tv_sec);*/ |
if (nfqh >= 0) | timeout.tv_sec = nextnatpmptoclean_timestamp + startup_time - timeofday.tv_sec; |
{ | timeout.tv_usec = 0; |
FD_SET(nfqh, &readset); | |
max_fd = MAX( max_fd, nfqh); | |
} |
} |
#endif |
#endif |
| #endif |
timeout.tv_sec = nextnatpmptoclean_timestamp + startup_time - timeofday.tv_sec; | #ifdef ENABLE_6FC_SERVICE |
| /* Clean up expired IPv6 PinHoles */ |
| next_pinhole_ts = 0; |
| upnp_clean_expired_pinholes(&next_pinhole_ts); |
| if(next_pinhole_ts && |
| timeout.tv_sec >= (int)(next_pinhole_ts - timeofday.tv_sec)) { |
| timeout.tv_sec = next_pinhole_ts - timeofday.tv_sec; |
timeout.tv_usec = 0; |
timeout.tv_usec = 0; |
} |
} |
#endif |
#endif |
|
|
/* select open sockets (SSDP, HTTP listen, and all HTTP soap sockets) */ |
/* select open sockets (SSDP, HTTP listen, and all HTTP soap sockets) */ |
FD_ZERO(&readset); |
FD_ZERO(&readset); |
|
FD_ZERO(&writeset); |
|
|
if (sudp >= 0) | if (sudp >= 0) |
{ |
{ |
FD_SET(sudp, &readset); |
FD_SET(sudp, &readset); |
max_fd = MAX( max_fd, sudp); |
max_fd = MAX( max_fd, sudp); |
|
#ifdef USE_IFACEWATCHER |
|
if (sifacewatcher >= 0) |
|
{ |
|
FD_SET(sifacewatcher, &readset); |
|
max_fd = MAX(max_fd, sifacewatcher); |
|
} |
|
#endif |
} |
} |
| if (shttpl >= 0) |
if (shttpl >= 0) | |
{ |
{ |
FD_SET(shttpl, &readset); |
FD_SET(shttpl, &readset); |
max_fd = MAX( max_fd, shttpl); |
max_fd = MAX( max_fd, shttpl); |
} |
} |
|
#ifdef ENABLE_IPV6 |
|
if (sudpv6 >= 0) |
|
{ |
|
FD_SET(sudpv6, &readset); |
|
max_fd = MAX( max_fd, sudpv6); |
|
} |
|
#endif |
|
|
|
#ifdef ENABLE_NFQUEUE |
|
if (nfqh >= 0) |
|
{ |
|
FD_SET(nfqh, &readset); |
|
max_fd = MAX( max_fd, nfqh); |
|
} |
|
#endif |
|
|
i = 0; /* active HTTP connections count */ |
i = 0; /* active HTTP connections count */ |
for(e = upnphttphead.lh_first; e != NULL; e = e->entries.le_next) |
for(e = upnphttphead.lh_first; e != NULL; e = e->entries.le_next) |
{ |
{ |
if((e->socket >= 0) && (e->state <= 2)) | if(e->socket >= 0) |
{ |
{ |
FD_SET(e->socket, &readset); | if(e->state <= EWaitingForHttpContent) |
max_fd = MAX( max_fd, e->socket); | FD_SET(e->socket, &readset); |
| else if(e->state == ESendingAndClosing) |
| FD_SET(e->socket, &writeset); |
| else |
| continue; |
| max_fd = MAX(max_fd, e->socket); |
i++; |
i++; |
} |
} |
} |
} |
Line 1280 main(int argc, char * * argv)
|
Line 1621 main(int argc, char * * argv)
|
} |
} |
#endif |
#endif |
#ifdef ENABLE_NATPMP |
#ifdef ENABLE_NATPMP |
for(i=0; i<n_lan_addr; i++) { | for(i=0; i<addr_count; i++) { |
if(snatpmp[i] >= 0) { |
if(snatpmp[i] >= 0) { |
FD_SET(snatpmp[i], &readset); |
FD_SET(snatpmp[i], &readset); |
max_fd = MAX( max_fd, snatpmp[i]); |
max_fd = MAX( max_fd, snatpmp[i]); |
Line 1292 main(int argc, char * * argv)
|
Line 1633 main(int argc, char * * argv)
|
FD_SET(sctl, &readset); |
FD_SET(sctl, &readset); |
max_fd = MAX( max_fd, sctl); |
max_fd = MAX( max_fd, sctl); |
} |
} |
| |
for(ectl = ctllisthead.lh_first; ectl; ectl = ectl->entries.le_next) |
for(ectl = ctllisthead.lh_first; ectl; ectl = ectl->entries.le_next) |
{ |
{ |
if(ectl->socket >= 0) { |
if(ectl->socket >= 0) { |
Line 1303 main(int argc, char * * argv)
|
Line 1644 main(int argc, char * * argv)
|
#endif |
#endif |
|
|
#ifdef ENABLE_EVENTS |
#ifdef ENABLE_EVENTS |
FD_ZERO(&writeset); |
|
upnpevents_selectfds(&readset, &writeset, &max_fd); |
upnpevents_selectfds(&readset, &writeset, &max_fd); |
#endif |
#endif |
|
|
#ifdef ENABLE_EVENTS |
|
if(select(max_fd+1, &readset, &writeset, 0, &timeout) < 0) |
if(select(max_fd+1, &readset, &writeset, 0, &timeout) < 0) |
#else |
|
if(select(max_fd+1, &readset, 0, 0, &timeout) < 0) |
|
#endif |
|
{ |
{ |
if(quitting) goto shutdown; |
if(quitting) goto shutdown; |
if(errno == EINTR) continue; /* interrupted by a signal, start again */ |
if(errno == EINTR) continue; /* interrupted by a signal, start again */ |
Line 1332 main(int argc, char * * argv)
|
Line 1668 main(int argc, char * * argv)
|
{ |
{ |
/*write(ectl->socket, buf, l);*/ |
/*write(ectl->socket, buf, l);*/ |
write_command_line(ectl->socket, argc, argv); |
write_command_line(ectl->socket, argc, argv); |
|
#ifndef DISABLE_CONFIG_FILE |
write_option_list(ectl->socket); |
write_option_list(ectl->socket); |
|
#endif |
write_permlist(ectl->socket, upnppermlist, num_upnpperm); |
write_permlist(ectl->socket, upnppermlist, num_upnpperm); |
write_upnphttp_details(ectl->socket, upnphttphead.lh_first); |
write_upnphttp_details(ectl->socket, upnphttphead.lh_first); |
write_ctlsockets_list(ectl->socket, ctllisthead.lh_first); |
write_ctlsockets_list(ectl->socket, ctllisthead.lh_first); |
Line 1363 main(int argc, char * * argv)
|
Line 1701 main(int argc, char * * argv)
|
struct sockaddr_un clientname; |
struct sockaddr_un clientname; |
struct ctlelem * tmp; |
struct ctlelem * tmp; |
socklen_t clientnamelen = sizeof(struct sockaddr_un); |
socklen_t clientnamelen = sizeof(struct sockaddr_un); |
//syslog(LOG_DEBUG, "sctl!"); | /*syslog(LOG_DEBUG, "sctl!");*/ |
s = accept(sctl, (struct sockaddr *)&clientname, |
s = accept(sctl, (struct sockaddr *)&clientname, |
&clientnamelen); |
&clientnamelen); |
syslog(LOG_DEBUG, "sctl! : '%s'", clientname.sun_path); |
syslog(LOG_DEBUG, "sctl! : '%s'", clientname.sun_path); |
tmp = malloc(sizeof(struct ctlelem)); |
tmp = malloc(sizeof(struct ctlelem)); |
tmp->socket = s; | if (tmp == NULL) |
LIST_INSERT_HEAD(&ctllisthead, tmp, entries); | { |
| syslog(LOG_ERR, "Unable to allocate memory for ctlelem in main()"); |
| close(s); |
| } |
| else |
| { |
| tmp->socket = s; |
| LIST_INSERT_HEAD(&ctllisthead, tmp, entries); |
| } |
} |
} |
#endif |
#endif |
#ifdef ENABLE_EVENTS |
#ifdef ENABLE_EVENTS |
Line 1377 main(int argc, char * * argv)
|
Line 1723 main(int argc, char * * argv)
|
#endif |
#endif |
#ifdef ENABLE_NATPMP |
#ifdef ENABLE_NATPMP |
/* process NAT-PMP packets */ |
/* process NAT-PMP packets */ |
for(i=0; i<n_lan_addr; i++) | for(i=0; i<addr_count; i++) |
{ |
{ |
if((snatpmp[i] >= 0) && FD_ISSET(snatpmp[i], &readset)) |
if((snatpmp[i] >= 0) && FD_ISSET(snatpmp[i], &readset)) |
{ |
{ |
Line 1391 main(int argc, char * * argv)
|
Line 1737 main(int argc, char * * argv)
|
/*syslog(LOG_INFO, "Received UDP Packet");*/ |
/*syslog(LOG_INFO, "Received UDP Packet");*/ |
ProcessSSDPRequest(sudp, (unsigned short)v.port); |
ProcessSSDPRequest(sudp, (unsigned short)v.port); |
} |
} |
|
#ifdef ENABLE_IPV6 |
|
if(sudpv6 >= 0 && FD_ISSET(sudpv6, &readset)) |
|
{ |
|
syslog(LOG_INFO, "Received UDP Packet (IPv6)"); |
|
ProcessSSDPRequest(sudpv6, (unsigned short)v.port); |
|
} |
|
#endif |
|
#ifdef USE_IFACEWATCHER |
|
/* process kernel notifications */ |
|
if (sifacewatcher >= 0 && FD_ISSET(sifacewatcher, &readset)) |
|
ProcessInterfaceWatchNotify(sifacewatcher); |
|
#endif |
|
|
/* process active HTTP connections */ |
/* process active HTTP connections */ |
/* LIST_FOREACH macro is not available under linux */ |
/* LIST_FOREACH macro is not available under linux */ |
for(e = upnphttphead.lh_first; e != NULL; e = e->entries.le_next) |
for(e = upnphttphead.lh_first; e != NULL; e = e->entries.le_next) |
{ |
{ |
if( (e->socket >= 0) && (e->state <= 2) | if(e->socket >= 0) |
&&(FD_ISSET(e->socket, &readset)) ) | |
{ |
{ |
Process_upnphttp(e); | if(FD_ISSET(e->socket, &readset) || |
| FD_ISSET(e->socket, &writeset)) |
| { |
| Process_upnphttp(e); |
| } |
} |
} |
} |
} |
/* process incoming HTTP connections */ |
/* process incoming HTTP connections */ |
Line 1406 main(int argc, char * * argv)
|
Line 1768 main(int argc, char * * argv)
|
{ |
{ |
int shttp; |
int shttp; |
socklen_t clientnamelen; |
socklen_t clientnamelen; |
|
#ifdef ENABLE_IPV6 |
|
struct sockaddr_storage clientname; |
|
clientnamelen = sizeof(struct sockaddr_storage); |
|
#else |
struct sockaddr_in clientname; |
struct sockaddr_in clientname; |
clientnamelen = sizeof(struct sockaddr_in); |
clientnamelen = sizeof(struct sockaddr_in); |
|
#endif |
shttp = accept(shttpl, (struct sockaddr *)&clientname, &clientnamelen); |
shttp = accept(shttpl, (struct sockaddr *)&clientname, &clientnamelen); |
if(shttp<0) |
if(shttp<0) |
{ |
{ |
syslog(LOG_ERR, "accept(http): %m"); | /* ignore EAGAIN, EWOULDBLOCK, EINTR, we just try again later */ |
| if(errno != EAGAIN && errno != EWOULDBLOCK && errno != EINTR) |
| syslog(LOG_ERR, "accept(http): %m"); |
} |
} |
else |
else |
{ |
{ |
struct upnphttp * tmp = 0; |
struct upnphttp * tmp = 0; |
syslog(LOG_INFO, "HTTP connection from %s:%d", | char addr_str[64]; |
inet_ntoa(clientname.sin_addr), | |
ntohs(clientname.sin_port) ); | sockaddr_to_string((struct sockaddr *)&clientname, addr_str, sizeof(addr_str)); |
/*if (fcntl(shttp, F_SETFL, O_NONBLOCK) < 0) { | syslog(LOG_INFO, "HTTP connection from %s", addr_str); |
syslog(LOG_ERR, "fcntl F_SETFL, O_NONBLOCK"); | if(get_lan_for_peer((struct sockaddr *)&clientname) == NULL) |
}*/ | { |
| /* The peer is not a LAN ! */ |
| syslog(LOG_WARNING, |
| "HTTP peer %s is not from a LAN, closing the connection", |
| addr_str); |
| close(shttp); |
| } |
| else |
| { |
| /* Create a new upnphttp object and add it to |
| * the active upnphttp object list */ |
| tmp = New_upnphttp(shttp); |
| if(tmp) |
| { |
| #ifdef ENABLE_IPV6 |
| if(clientname.ss_family == AF_INET) |
| { |
| tmp->clientaddr = ((struct sockaddr_in *)&clientname)->sin_addr; |
| } |
| else if(clientname.ss_family == AF_INET6) |
| { |
| struct sockaddr_in6 * addr = (struct sockaddr_in6 *)&clientname; |
| if(IN6_IS_ADDR_V4MAPPED(&addr->sin6_addr)) |
| { |
| memcpy(&tmp->clientaddr, |
| &addr->sin6_addr.s6_addr[12], |
| 4); |
| } |
| else |
| { |
| tmp->ipv6 = 1; |
| memcpy(&tmp->clientaddr_v6, |
| &addr->sin6_addr, |
| sizeof(struct in6_addr)); |
| } |
| } |
| #else |
| tmp->clientaddr = clientname.sin_addr; |
| #endif |
| LIST_INSERT_HEAD(&upnphttphead, tmp, entries); |
| } |
| else |
| { |
| syslog(LOG_ERR, "New_upnphttp() failed"); |
| close(shttp); |
| } |
| } |
| } |
| } |
#ifdef ENABLE_NFQUEUE |
#ifdef ENABLE_NFQUEUE |
/* process NFQ packets */ |
/* process NFQ packets */ |
if(nfqh >= 0 && FD_ISSET(nfqh, &readset)) |
if(nfqh >= 0 && FD_ISSET(nfqh, &readset)) |
Line 1430 main(int argc, char * * argv)
|
Line 1847 main(int argc, char * * argv)
|
ProcessNFQUEUE(nfqh); |
ProcessNFQUEUE(nfqh); |
} |
} |
#endif |
#endif |
/* Create a new upnphttp object and add it to |
|
* the active upnphttp object list */ |
|
tmp = New_upnphttp(shttp); |
|
if(tmp) |
|
{ |
|
tmp->clientaddr = clientname.sin_addr; |
|
LIST_INSERT_HEAD(&upnphttphead, tmp, entries); |
|
} |
|
else |
|
{ |
|
syslog(LOG_ERR, "New_upnphttp() failed"); |
|
close(shttp); |
|
} |
|
} |
|
} |
|
/* delete finished HTTP connections */ |
/* delete finished HTTP connections */ |
for(e = upnphttphead.lh_first; e != NULL; ) |
for(e = upnphttphead.lh_first; e != NULL; ) |
{ |
{ |
next = e->entries.le_next; |
next = e->entries.le_next; |
if(e->state >= 100) | if(e->state >= EToDelete) |
{ |
{ |
LIST_REMOVE(e, entries); |
LIST_REMOVE(e, entries); |
Delete_upnphttp(e); |
Delete_upnphttp(e); |
Line 1457 main(int argc, char * * argv)
|
Line 1859 main(int argc, char * * argv)
|
e = next; |
e = next; |
} |
} |
|
|
/* send public address change notifications */ |
|
if(should_send_public_address_change_notif) |
|
{ |
|
#ifdef ENABLE_NATPMP |
|
if(GETFLAG(ENABLENATPMPMASK)) |
|
SendNATPMPPublicAddressChangeNotification(snatpmp/*snotify*/, n_lan_addr); |
|
#endif |
|
#ifdef ENABLE_EVENTS |
|
if(GETFLAG(ENABLEUPNPMASK)) |
|
{ |
|
upnp_event_var_change_notify(EWanIPC); |
|
} |
|
#endif |
|
should_send_public_address_change_notif = 0; |
|
} |
|
} /* end of main loop */ |
} /* end of main loop */ |
|
|
shutdown: |
shutdown: |
Line 1485 shutdown:
|
Line 1872 shutdown:
|
|
|
if (sudp >= 0) close(sudp); |
if (sudp >= 0) close(sudp); |
if (shttpl >= 0) close(shttpl); |
if (shttpl >= 0) close(shttpl); |
|
#ifdef ENABLE_IPV6 |
|
if (sudpv6 >= 0) close(sudpv6); |
|
#endif |
|
#ifdef USE_IFACEWATCHER |
|
if(sifacewatcher >= 0) close(sifacewatcher); |
|
#endif |
#ifdef ENABLE_NATPMP |
#ifdef ENABLE_NATPMP |
for(i=0; i<n_lan_addr; i++) { | for(i=0; i<addr_count; i++) { |
if(snatpmp[i]>=0) |
if(snatpmp[i]>=0) |
{ |
{ |
close(snatpmp[i]); |
close(snatpmp[i]); |
Line 1505 shutdown:
|
Line 1898 shutdown:
|
} |
} |
} |
} |
#endif |
#endif |
| |
/*if(SendSSDPGoodbye(snotify, v.n_lan_addr) < 0)*/ | |
if (GETFLAG(ENABLEUPNPMASK)) |
if (GETFLAG(ENABLEUPNPMASK)) |
{ |
{ |
if(SendSSDPGoodbye(snotify, n_lan_addr) < 0) | #ifndef ENABLE_IPV6 |
| if(SendSSDPGoodbye(snotify, addr_count) < 0) |
| #else |
| if(SendSSDPGoodbye(snotify, addr_count * 2) < 0) |
| #endif |
{ |
{ |
syslog(LOG_ERR, "Failed to broadcast good-bye notifications"); |
syslog(LOG_ERR, "Failed to broadcast good-bye notifications"); |
} |
} |
for(i=0; i<n_lan_addr; i++)/* for(i=0; i<v.n_lan_addr; i++)*/ | #ifndef ENABLE_IPV6 |
| for(i = 0; i < addr_count; i++) |
| #else |
| for(i = 0; i < addr_count * 2; i++) |
| #endif |
close(snotify[i]); |
close(snotify[i]); |
} |
} |
|
|
if(unlink(pidfilename) < 0) | if(pidfilename && (unlink(pidfilename) < 0)) |
{ |
{ |
syslog(LOG_ERR, "Failed to remove pidfile %s: %m", pidfilename); |
syslog(LOG_ERR, "Failed to remove pidfile %s: %m", pidfilename); |
} |
} |
|
|
closelog(); | /* delete lists */ |
| while(lan_addrs.lh_first != NULL) |
| { |
| lan_addr = lan_addrs.lh_first; |
| LIST_REMOVE(lan_addrs.lh_first, list); |
| free(lan_addr); |
| } |
| |
| #ifdef ENABLE_NATPMP |
| free(snatpmp); |
| #endif |
| free(snotify); |
| closelog(); |
| #ifndef DISABLE_CONFIG_FILE |
freeoptions(); |
freeoptions(); |
| #endif |
| |
return 0; |
return 0; |
} |
} |
|
|