1 /* $Id: miniupnpd.c,v 1.203 2014/10/30 22:15:46 nanard Exp $ */
3 * http://miniupnp.free.fr/ or http://miniupnp.tuxfamily.org/
4 * (c) 2006-2014 Thomas Bernard
5 * This software is subject to the conditions detailed
6 * in the LICENCE file provided within the distribution */
10 /* Experimental support for NFQUEUE interfaces */
12 /* apt-get install libnetfilter-queue-dev */
13 #include <netinet/ip.h>
14 #include <netinet/udp.h>
16 #include <linux/netfilter_ipv4.h> /* Defines verdicts (NF_ACCEPT, etc) */
18 #include <linux/netfilter.h>
19 #include <libnetfilter_queue/libnetfilter_queue.h>
20 #include <linux/netfilter/nfnetlink_queue.h>
28 #include <sys/types.h>
29 #include <sys/socket.h>
30 #include <netinet/in.h>
31 #include <arpa/inet.h>
39 #include <sys/param.h>
42 #elif !defined(__linux__)
43 /* for BSD's sysctl */
44 #include <sys/sysctl.h>
48 #ifdef USE_MINIUPNPDCTL
53 #include "upnpglobalvars.h"
55 #include "upnpdescgen.h"
56 #include "miniupnpdpath.h"
57 #include "getifaddr.h"
61 #include "upnpredirect.h"
62 #include "upnppinhole.h"
63 #include "miniupnpdtypes.h"
64 #include "daemonize.h"
65 #include "upnpevents.h"
66 #include "asyncsendto.h"
70 #include "pcpserver.h"
72 #define PCP_MAX_LEN 32
75 #include "commonrdr.h"
76 #include "upnputils.h"
77 #ifdef USE_IFACEWATCHER
78 #include "ifacewatcher.h"
80 #ifdef ENABLE_UPNPPINHOLE
82 void init_iptpinhole(void);
86 #ifndef DEFAULT_CONFIG
87 #define DEFAULT_CONFIG "/etc/miniupnpd.conf"
90 #ifdef USE_MINIUPNPDCTL
93 LIST_ENTRY(ctlelem
) entries
;
99 static struct nfq_handle
*nfqHandle
;
100 static struct sockaddr_in ssdp
;
103 static int nfqueue_cb( struct nfq_q_handle
*qh
, struct nfgenmsg
*nfmsg
, struct nfq_data
*nfa
, void *data
) ;
104 int identify_ip_protocol (char *payload
);
105 int get_udp_dst_port (char *payload
);
108 /* variables used by signals */
109 static volatile sig_atomic_t quitting
= 0;
110 volatile sig_atomic_t should_send_public_address_change_notif
= 0;
114 static volatile int gotusr2
= 0;
116 static void sigusr2(int sig
)
121 static void tomato_save(const char *fname
)
123 unsigned short eport
;
124 unsigned short iport
;
125 unsigned int leaseduration
;
126 unsigned int timestamp
;
136 strcpy(tmp
, "/etc/upnp/saveXXXXXX");
137 if ((t
= mkstemp(tmp
)) != -1) {
138 if ((f
= fdopen(t
, "w")) != NULL
) {
140 while (upnp_get_redirection_infos_by_index(n
, &eport
, proto
, &iport
, iaddr
, sizeof(iaddr
), desc
, sizeof(desc
), rhost
, sizeof(rhost
), &leaseduration
) == 0) {
141 timestamp
= (leaseduration
> 0) ? time(NULL
) + leaseduration
: 0;
142 fprintf(f
, "%s %u %s %u [%s] %u\n", proto
, eport
, iaddr
, iport
, desc
, timestamp
);
155 static void tomato_load(void)
159 unsigned short eport
;
160 unsigned short iport
;
161 unsigned int leaseduration
;
162 unsigned int timestamp
;
169 if ((f
= fopen("/etc/upnp/data", "r")) != NULL
) {
170 current_time
= time(NULL
);
171 s
[sizeof(s
) - 1] = 0;
172 while (fgets(s
, sizeof(s
) - 1, f
)) {
173 if (sscanf(s
, "%3s %hu %31s %hu [%*s] %u", proto
, &eport
, iaddr
, &iport
, ×tamp
) >= 4) {
174 if (((a
= strchr(s
, '[')) != NULL
) && ((b
= strrchr(a
, ']')) != NULL
)) {
176 if (timestamp
> current_time
)
177 leaseduration
= current_time
- timestamp
;
181 leaseduration
= 0; /* default value */
185 upnp_redirect(rhost
, eport
, iaddr
, iport
, proto
, a
+ 1, leaseduration
);
193 ScanNATPMPforExpiration();
196 unlink("/etc/upnp/load");
199 static void tomato_delete(void)
203 unsigned short eport
;
204 unsigned short iport
;
205 unsigned int leaseduration
;
212 if ((f
= fopen("/etc/upnp/delete", "r")) != NULL
) {
213 s
[sizeof(s
) - 1] = 0;
214 while (fgets(s
, sizeof(s
) - 1, f
)) {
215 if (sscanf(s
, "%3s %hu", proto
, &eport
) == 2) {
216 if (proto
[0] == '*') {
217 n
= upnp_get_portmapping_number_of_entries();
219 if (upnp_get_redirection_infos_by_index(n
, &eport
, proto
, &iport
, iaddr
, sizeof(iaddr
), desc
, sizeof(desc
), rhost
, sizeof(rhost
), &leaseduration
) == 0) {
220 upnp_delete_redirection(eport
, proto
);
226 upnp_delete_redirection(eport
, proto
);
231 unlink("/etc/upnp/delete");
235 static void tomato_helper(void)
239 if (stat("/etc/upnp/delete", &st
) == 0) {
243 if (stat("/etc/upnp/load", &st
) == 0) {
247 if (stat("/etc/upnp/save", &st
) == 0) {
248 tomato_save("/etc/upnp/data");
249 unlink("/etc/upnp/save");
252 if (stat("/etc/upnp/info", &st
) == 0) {
253 tomato_save("/etc/upnp/data.info");
254 unlink("/etc/upnp/info");
257 #endif /* 1 (tomato) */
260 /* OpenAndConfHTTPSocket() :
261 * setup the socket used to handle incoming HTTP connections. */
264 OpenAndConfHTTPSocket(unsigned short * port
, int ipv6
)
266 OpenAndConfHTTPSocket(unsigned short * port
)
272 struct sockaddr_in6 listenname6
;
273 struct sockaddr_in listenname4
;
275 struct sockaddr_in listenname
;
277 socklen_t listenname_len
;
281 ipv6
? PF_INET6
: PF_INET
,
287 if(s
< 0 && ipv6
&& errno
== EAFNOSUPPORT
)
289 /* the system doesn't support IPV6 */
290 syslog(LOG_WARNING
, "socket(PF_INET6, ...) failed with EAFNOSUPPORT, disabling IPv6");
291 SETFLAG(IPV6DISABLEDMASK
);
293 s
= socket(PF_INET
, SOCK_STREAM
, 0);
298 syslog(LOG_ERR
, "socket(http): %m");
302 if(setsockopt(s
, SOL_SOCKET
, SO_REUSEADDR
, &i
, sizeof(i
)) < 0)
304 syslog(LOG_WARNING
, "setsockopt(http, SO_REUSEADDR): %m");
307 /* enable this to force IPV6 only for IPV6 socket.
308 * see http://www.ietf.org/rfc/rfc3493.txt section 5.3 */
309 if(setsockopt(s
, IPPROTO_IPV6
, IPV6_V6ONLY
, &i
, sizeof(i
)) < 0)
311 syslog(LOG_WARNING
, "setsockopt(http, IPV6_V6ONLY): %m");
315 if(!set_non_blocking(s
))
317 syslog(LOG_WARNING
, "set_non_blocking(http): %m");
323 memset(&listenname6
, 0, sizeof(struct sockaddr_in6
));
324 listenname6
.sin6_family
= AF_INET6
;
325 listenname6
.sin6_port
= htons(*port
);
326 listenname6
.sin6_addr
= ipv6_bind_addr
;
327 listenname_len
= sizeof(struct sockaddr_in6
);
329 memset(&listenname4
, 0, sizeof(struct sockaddr_in
));
330 listenname4
.sin_family
= AF_INET
;
331 listenname4
.sin_port
= htons(*port
);
332 listenname4
.sin_addr
.s_addr
= htonl(INADDR_ANY
);
333 listenname_len
= sizeof(struct sockaddr_in
);
336 memset(&listenname
, 0, sizeof(struct sockaddr_in
));
337 listenname
.sin_family
= AF_INET
;
338 listenname
.sin_port
= htons(*port
);
339 listenname
.sin_addr
.s_addr
= htonl(INADDR_ANY
);
340 listenname_len
= sizeof(struct sockaddr_in
);
345 ipv6
? (struct sockaddr
*)&listenname6
: (struct sockaddr
*)&listenname4
,
348 if(bind(s
, (struct sockaddr
*)&listenname
, listenname_len
) < 0)
351 syslog(LOG_ERR
, "bind(http): %m");
358 syslog(LOG_ERR
, "listen(http): %m");
366 struct sockaddr_in6 sockinfo
;
367 socklen_t len
= sizeof(struct sockaddr_in6
);
368 if (getsockname(s
, (struct sockaddr
*)&sockinfo
, &len
) < 0) {
369 syslog(LOG_ERR
, "getsockname(): %m");
371 *port
= ntohs(sockinfo
.sin6_port
);
374 #endif /* ENABLE_IPV6 */
375 struct sockaddr_in sockinfo
;
376 socklen_t len
= sizeof(struct sockaddr_in
);
377 if (getsockname(s
, (struct sockaddr
*)&sockinfo
, &len
) < 0) {
378 syslog(LOG_ERR
, "getsockname(): %m");
380 *port
= ntohs(sockinfo
.sin_port
);
384 #endif /* ENABLE_IPV6 */
389 static struct upnphttp
*
390 ProcessIncomingHTTP(int shttpl
, const char * protocol
)
393 socklen_t clientnamelen
;
395 struct sockaddr_storage clientname
;
396 clientnamelen
= sizeof(struct sockaddr_storage
);
398 struct sockaddr_in clientname
;
399 clientnamelen
= sizeof(struct sockaddr_in
);
401 shttp
= accept(shttpl
, (struct sockaddr
*)&clientname
, &clientnamelen
);
404 /* ignore EAGAIN, EWOULDBLOCK, EINTR, we just try again later */
405 if(errno
!= EAGAIN
&& errno
!= EWOULDBLOCK
&& errno
!= EINTR
)
406 syslog(LOG_ERR
, "accept(http): %m");
410 struct upnphttp
* tmp
= 0;
413 sockaddr_to_string((struct sockaddr
*)&clientname
, addr_str
, sizeof(addr_str
));
414 syslog(LOG_INFO
, "%s connection from %s", protocol
, addr_str
);
415 if(get_lan_for_peer((struct sockaddr
*)&clientname
) == NULL
)
417 /* The peer is not a LAN ! */
419 "%s peer %s is not from a LAN, closing the connection",
425 /* Create a new upnphttp object and add it to
426 * the active upnphttp object list */
427 tmp
= New_upnphttp(shttp
);
431 if(clientname
.ss_family
== AF_INET
)
433 tmp
->clientaddr
= ((struct sockaddr_in
*)&clientname
)->sin_addr
;
435 else if(clientname
.ss_family
== AF_INET6
)
437 struct sockaddr_in6
* addr
= (struct sockaddr_in6
*)&clientname
;
438 if(IN6_IS_ADDR_V4MAPPED(&addr
->sin6_addr
))
440 memcpy(&tmp
->clientaddr
,
441 &addr
->sin6_addr
.s6_addr
[12],
447 memcpy(&tmp
->clientaddr_v6
,
449 sizeof(struct in6_addr
));
453 tmp
->clientaddr
= clientname
.sin_addr
;
459 syslog(LOG_ERR
, "New_upnphttp() failed");
467 #ifdef ENABLE_NFQUEUE
469 int identify_ip_protocol(char *payload
) {
475 * This function returns the destination port of the captured packet UDP
477 int get_udp_dst_port(char *payload
) {
478 char *pkt_data_ptr
= NULL
;
479 pkt_data_ptr
= payload
+ sizeof(struct ip
);
481 /* Cast the UDP Header from the raw packet */
482 struct udphdr
*udp
= (struct udphdr
*) pkt_data_ptr
;
484 /* get the dst port of the packet */
485 return(ntohs(udp
->dest
));
489 OpenAndConfNFqueue(){
491 struct nfq_q_handle
*myQueue
;
492 struct nfnl_handle
*netlinkHandle
;
496 inet_pton(AF_INET
, "239.255.255.250", &(ssdp
.sin_addr
));
498 /* Get a queue connection handle from the module */
499 if (!(nfqHandle
= nfq_open())) {
500 syslog(LOG_ERR
, "Error in nfq_open(): %m");
504 /* Unbind the handler from processing any IP packets
505 Not totally sure why this is done, or if it's necessary... */
506 if ((e
= nfq_unbind_pf(nfqHandle
, AF_INET
)) < 0) {
507 syslog(LOG_ERR
, "Error in nfq_unbind_pf(): %m");
511 /* Bind this handler to process IP packets... */
512 if (nfq_bind_pf(nfqHandle
, AF_INET
) < 0) {
513 syslog(LOG_ERR
, "Error in nfq_bind_pf(): %m");
517 /* Install a callback on queue -Q */
518 if (!(myQueue
= nfq_create_queue(nfqHandle
, nfqueue
, &nfqueue_cb
, NULL
))) {
519 syslog(LOG_ERR
, "Error in nfq_create_queue(): %m");
523 /* Turn on packet copy mode */
524 if (nfq_set_mode(myQueue
, NFQNL_COPY_PACKET
, 0xffff) < 0) {
525 syslog(LOG_ERR
, "Error setting packet copy mode (): %m");
529 netlinkHandle
= nfq_nfnlh(nfqHandle
);
530 fd
= nfnl_fd(netlinkHandle
);
537 static int nfqueue_cb(
538 struct nfq_q_handle
*qh
,
539 struct nfgenmsg
*nfmsg
,
540 struct nfq_data
*nfa
,
544 struct nfqnl_msg_packet_hdr
*ph
;
545 ph
= nfq_get_msg_packet_hdr(nfa
);
549 int id
= 0, size
= 0;
550 id
= ntohl(ph
->packet_id
);
552 size
= nfq_get_payload(nfa
, &pkt
);
554 struct ip
*iph
= (struct ip
*) pkt
;
556 int id_protocol
= identify_ip_protocol(pkt
);
558 int dport
= get_udp_dst_port(pkt
);
560 int x
= sizeof (struct ip
) + sizeof (struct udphdr
);
562 /* packets we are interested in are UDP multicast to 239.255.255.250:1900
563 * and start with a data string M-SEARCH
565 if ( (dport
== 1900) && (id_protocol
== IPPROTO_UDP
)
566 && (ssdp
.sin_addr
.s_addr
== iph
->ip_dst
.s_addr
) ) {
568 /* get the index that the packet came in on */
569 u_int32_t idx
= nfq_get_indev(nfa
);
571 for ( ;i
< n_nfqix
; i
++) {
572 if ( nfqix
[i
] == idx
) {
574 struct udphdr
*udp
= (struct udphdr
*) (pkt
+ sizeof(struct ip
));
578 struct sockaddr_in sendername
;
579 sendername
.sin_family
= AF_INET
;
580 sendername
.sin_port
= udp
->source
;
581 sendername
.sin_addr
.s_addr
= iph
->ip_src
.s_addr
;
583 /* printf("pkt found %s\n",dd);*/
584 ProcessSSDPData (sudp
, dd
, size
- x
,
585 &sendername
, (unsigned short) 5555);
590 nfq_set_verdict(qh
, id
, NF_ACCEPT
, 0, NULL
);
593 syslog(LOG_ERR
,"nfq_get_msg_packet_hdr failed");
595 /* from nfqueue source: 0 = ok, >0 = soft error, <0 hard error */
601 static void ProcessNFQUEUE(int fd
){
605 struct sockaddr_in sendername
;
606 len_r
= sizeof(struct sockaddr_in
);
608 int res
= recvfrom(fd
, buf
, sizeof(buf
), 0,
609 (struct sockaddr
*)&sendername
, &len_r
);
611 nfq_handle_packet(nfqHandle
, buf
, res
);
615 /* Functions used to communicate with miniupnpdctl */
616 #ifdef USE_MINIUPNPDCTL
618 OpenAndConfCtlUnixSocket(const char * path
)
620 struct sockaddr_un localun
;
622 s
= socket(AF_UNIX
, SOCK_STREAM
, 0);
623 localun
.sun_family
= AF_UNIX
;
624 strncpy(localun
.sun_path
, path
,
625 sizeof(localun
.sun_path
));
626 if(bind(s
, (struct sockaddr
*)&localun
,
627 sizeof(struct sockaddr_un
)) < 0)
629 syslog(LOG_ERR
, "bind(sctl): %m");
633 else if(listen(s
, 5) < 0)
635 syslog(LOG_ERR
, "listen(sctl): %m");
643 write_upnphttp_details(int fd
, struct upnphttp
* e
)
647 write(fd
, "HTTP :\n", 7);
650 len
= snprintf(buffer
, sizeof(buffer
),
651 "%d %d %s req_buf=%p(%dbytes) res_buf=%p(%dbytes alloc)\n",
652 e
->socket
, e
->state
, e
->HttpVer
,
653 e
->req_buf
, e
->req_buflen
,
654 e
->res_buf
, e
->res_buf_alloclen
);
655 write(fd
, buffer
, len
);
656 e
= e
->entries
.le_next
;
661 write_ctlsockets_list(int fd
, struct ctlelem
* e
)
665 write(fd
, "CTL :\n", 6);
668 len
= snprintf(buffer
, sizeof(buffer
),
669 "struct ctlelem: socket=%d\n", e
->socket
);
670 write(fd
, buffer
, len
);
671 e
= e
->entries
.le_next
;
675 #ifndef DISABLE_CONFIG_FILE
677 write_option_list(int fd
)
682 write(fd
, "Options :\n", 10);
683 for(i
=0; i
<num_options
; i
++)
685 len
= snprintf(buffer
, sizeof(buffer
),
687 ary_options
[i
].id
, ary_options
[i
].value
);
688 write(fd
, buffer
, len
);
694 write_command_line(int fd
, int argc
, char * * argv
)
699 write(fd
, "Command Line :\n", 15);
700 for(i
=0; i
<argc
; i
++)
702 len
= snprintf(buffer
, sizeof(buffer
),
705 write(fd
, buffer
, len
);
711 /* Handler for the SIGTERM signal (kill)
712 * SIGINT is also handled */
717 /*int save_errno = errno; */
718 /*signal(sig, SIG_IGN);*/ /* Ignore this signal while we are quitting */
719 /* Note : isn't it useless ? */
722 /* calling syslog() is forbidden in signal handler according to
724 syslog(LOG_NOTICE
, "received signal %d, good-bye", sig
);
728 /*errno = save_errno;*/
731 /* Handler for the SIGUSR1 signal indicating public IP address change. */
737 /* calling syslog() is forbidden in signal handler according to
739 syslog(LOG_INFO
, "received signal %d, public ip address change", sig
);
742 should_send_public_address_change_notif
= 1;
745 /* record the startup time, for returning uptime */
747 set_startup_time(int sysuptime
)
749 startup_time
= time(NULL
);
752 /* use system uptime instead of daemon uptime */
753 #if defined(__linux__)
756 fd
= open("/proc/uptime", O_RDONLY
);
759 syslog(LOG_ERR
, "open(\"/proc/uptime\" : %m");
763 memset(buff
, 0, sizeof(buff
));
764 if(read(fd
, buff
, sizeof(buff
) - 1) < 0)
766 syslog(LOG_ERR
, "read(\"/proc/uptime\" : %m");
771 syslog(LOG_INFO
, "system uptime is %d seconds", uptime
);
774 startup_time
-= uptime
;
776 #elif defined(SOLARIS_KSTATS)
782 ksp
= kstat_lookup(kc
, "unix", 0, "system_misc");
783 if(ksp
&& (kstat_read(kc
, ksp
, NULL
) != -1))
785 void *ptr
= kstat_data_lookup(ksp
, "boot_time");
787 memcpy(&startup_time
, ptr
, sizeof(startup_time
));
789 syslog(LOG_ERR
, "cannot find boot_time kstat");
792 syslog(LOG_ERR
, "cannot open kstats for unix/0/system_misc: %m");
796 struct timeval boottime
;
797 size_t size
= sizeof(boottime
);
798 int name
[2] = { CTL_KERN
, KERN_BOOTTIME
};
799 if(sysctl(name
, 2, &boottime
, &size
, NULL
, 0) < 0)
801 syslog(LOG_ERR
, "sysctl(\"kern.boottime\") failed");
805 startup_time
= boottime
.tv_sec
;
811 /* structure containing variables used during "main loop"
812 * that are filled during the init */
813 struct runtime_vars
{
814 /* LAN IP addresses for SSDP traffic and HTTP */
815 /* moved to global vars */
816 int port
; /* HTTP Port */
818 int https_port
; /* HTTPS Port */
820 int notify_interval
; /* seconds between SSDP announces */
821 /* unused rules cleaning related variables : */
822 int clean_ruleset_threshold
; /* threshold for removing unused rules */
823 int clean_ruleset_interval
; /* (minimum) interval between checks */
827 * parse address with mask
828 * ex: 192.168.1.1/24 or 192.168.1.1/255.255.255.0
829 * When MULTIPLE_EXTERNAL_IP is enabled, the ip address of the
830 * external interface associated with the lan subnet follows.
831 * ex : 192.168.1.1/24 81.21.41.11
833 * Can also use the interface name (ie eth0)
839 parselanaddr(struct lan_addr_s
* lan_addr
, const char * str
)
845 memset(lan_addr
, 0, sizeof(struct lan_addr_s
));
847 while(*p
&& *p
!= '/' && !isspace(*p
))
850 if(!isdigit(str
[0]) && n
< (int)sizeof(lan_addr
->ifname
))
852 /* not starting with a digit : suppose it is an interface name */
853 memcpy(lan_addr
->ifname
, str
, n
);
854 lan_addr
->ifname
[n
] = '\0';
855 if(getifaddr(lan_addr
->ifname
, lan_addr
->str
, sizeof(lan_addr
->str
),
856 &lan_addr
->addr
, &lan_addr
->mask
) < 0)
858 /*printf("%s => %s\n", lan_addr->ifname, lan_addr->str);*/
864 memcpy(lan_addr
->str
, str
, n
);
865 lan_addr
->str
[n
] = '\0';
866 if(!inet_aton(lan_addr
->str
, &lan_addr
->addr
))
871 const char * q
= ++p
;
872 while(*p
&& isdigit(*p
))
876 /* parse mask in /255.255.255.0 format */
877 while(*p
&& (*p
=='.' || isdigit(*p
)))
884 if(!inet_aton(tmp
, &lan_addr
->mask
))
889 /* it is a /24 format */
891 if(nbits
> 32 || nbits
< 0)
893 lan_addr
->mask
.s_addr
= htonl(nbits
? (0xffffffffu
<< (32 - nbits
)) : 0);
896 else if(lan_addr
->mask
.s_addr
== 0)
898 /* by default, networks are /24 */
899 lan_addr
->mask
.s_addr
= htonl(0xffffff00u
);
901 #ifdef MULTIPLE_EXTERNAL_IP
903 while(*p
&& isspace(*p
))
906 /* parse the exteral ip address to associate with this subnet */
908 while(p
[n
] && !isspace(*p
))
911 memcpy(lan_addr
->ext_ip_str
, p
, n
);
912 lan_addr
->ext_ip_str
[n
] = '\0';
913 if(!inet_aton(lan_addr
->ext_ip_str
, &lan_addr
->ext_ip_addr
)) {
915 fprintf(stderr
, "Error parsing address : %s\n", lan_addr
->ext_ip_str
);
921 if(lan_addr
->ifname
[0] != '\0')
923 lan_addr
->index
= if_nametoindex(lan_addr
->ifname
);
924 if(lan_addr
->index
== 0)
925 fprintf(stderr
, "Cannot get index for network interface %s",
931 "Error: please specify LAN network interface by name instead of IPv4 address : %s\n",
938 fprintf(stderr
, "Error parsing address/mask (or interface name) : %s\n",
943 /* fill uuidvalue_wan and uuidvalue_wcd based on uuidvalue_igd */
944 void complete_uuidvalues(void)
947 len
= strlen(uuidvalue_igd
);
948 memcpy(uuidvalue_wan
, uuidvalue_igd
, len
+1);
949 switch(uuidvalue_wan
[len
-1]) {
951 uuidvalue_wan
[len
-1] = 'a';
954 uuidvalue_wan
[len
-1] = '0';
957 uuidvalue_wan
[len
-1]++;
959 memcpy(uuidvalue_wcd
, uuidvalue_wan
, len
+1);
960 switch(uuidvalue_wcd
[len
-1]) {
962 uuidvalue_wcd
[len
-1] = 'a';
965 uuidvalue_wcd
[len
-1] = '0';
968 uuidvalue_wcd
[len
-1]++;
973 * 1) read configuration file
974 * 2) read command line arguments
977 * 5) check and write pid file
978 * 6) set startup time stamp
979 * 7) compute presentation URL
980 * 8) set signal handlers
981 * 9) init random generator (srandom())
982 * 10) init redirection engine
983 * 11) reload mapping from leasefile */
985 init(int argc
, char * * argv
, struct runtime_vars
* v
)
992 /*const char * logfilename = 0;*/
993 const char * presurl
= 0;
994 #ifndef DISABLE_CONFIG_FILE
995 int options_flag
= 0;
996 const char * optionsfile
= DEFAULT_CONFIG
;
997 #endif /* DISABLE_CONFIG_FILE */
998 struct lan_addr_s
* lan_addr
;
999 struct lan_addr_s
* lan_addr2
;
1001 /* only print usage if -h is used */
1002 for(i
=1; i
<argc
; i
++)
1004 if(0 == strcmp(argv
[i
], "-h"))
1007 #ifndef DISABLE_CONFIG_FILE
1008 /* first check if "-f" option is used */
1009 for(i
=2; i
<argc
; i
++)
1011 if(0 == strcmp(argv
[i
-1], "-f"))
1013 optionsfile
= argv
[i
];
1018 #endif /* DISABLE_CONFIG_FILE */
1020 /* set initial values */
1021 SETFLAG(ENABLEUPNPMASK
); /* UPnP is enabled by default */
1023 ipv6_bind_addr
= in6addr_any
;
1024 #endif /* ENABLE_IPV6 */
1026 LIST_INIT(&lan_addrs
);
1031 v
->notify_interval
= 30; /* seconds between SSDP announces */
1032 v
->clean_ruleset_threshold
= 20;
1033 v
->clean_ruleset_interval
= 0; /* interval between ruleset check. 0=disabled */
1034 #ifndef DISABLE_CONFIG_FILE
1035 /* read options file first since
1036 * command line arguments have final say */
1037 if(readoptionsfile(optionsfile
) < 0)
1039 /* only error if file exists or using -f */
1040 if(access(optionsfile
, F_OK
) == 0 || options_flag
)
1041 fprintf(stderr
, "Error reading configuration file %s\n", optionsfile
);
1045 for(i
=0; i
<(int)num_options
; i
++)
1047 switch(ary_options
[i
].id
)
1049 case UPNPEXT_IFNAME
:
1050 ext_if_name
= ary_options
[i
].value
;
1053 use_ext_ip_addr
= ary_options
[i
].value
;
1055 case UPNPLISTENING_IP
:
1056 lan_addr
= (struct lan_addr_s
*) malloc(sizeof(struct lan_addr_s
));
1057 if (lan_addr
== NULL
)
1059 fprintf(stderr
, "malloc(sizeof(struct lan_addr_s)): %m");
1062 if(parselanaddr(lan_addr
, ary_options
[i
].value
) != 0)
1064 fprintf(stderr
, "can't parse \"%s\" as a valid "
1068 "interface name\n", ary_options
[i
].value
);
1072 LIST_INSERT_HEAD(&lan_addrs
, lan_addr
, list
);
1075 case UPNPIPV6_LISTENING_IP
:
1076 if (inet_pton(AF_INET6
, ary_options
[i
].value
, &ipv6_bind_addr
) < 1)
1078 fprintf(stderr
, "can't parse \"%s\" as valid IPv6 listening address", ary_options
[i
].value
);
1081 #endif /* ENABLE_IPV6 */
1083 v
->port
= atoi(ary_options
[i
].value
);
1087 v
->https_port
= atoi(ary_options
[i
].value
);
1090 case UPNPBITRATE_UP
:
1091 upstream_bitrate
= strtoul(ary_options
[i
].value
, 0, 0);
1093 case UPNPBITRATE_DOWN
:
1094 downstream_bitrate
= strtoul(ary_options
[i
].value
, 0, 0);
1096 case UPNPPRESENTATIONURL
:
1097 presurl
= ary_options
[i
].value
;
1099 #ifdef ENABLE_MANUFACTURER_INFO_CONFIGURATION
1100 case UPNPFRIENDLY_NAME
:
1101 strncpy(friendly_name
, ary_options
[i
].value
, FRIENDLY_NAME_MAX_LEN
);
1102 friendly_name
[FRIENDLY_NAME_MAX_LEN
-1] = '\0';
1104 case UPNPMANUFACTURER_NAME
:
1105 strncpy(manufacturer_name
, ary_options
[i
].value
, MANUFACTURER_NAME_MAX_LEN
);
1106 manufacturer_name
[MANUFACTURER_NAME_MAX_LEN
-1] = '\0';
1108 case UPNPMANUFACTURER_URL
:
1109 strncpy(manufacturer_url
, ary_options
[i
].value
, MANUFACTURER_URL_MAX_LEN
);
1110 manufacturer_url
[MANUFACTURER_URL_MAX_LEN
-1] = '\0';
1112 case UPNPMODEL_NAME
:
1113 strncpy(model_name
, ary_options
[i
].value
, MODEL_NAME_MAX_LEN
);
1114 model_name
[MODEL_NAME_MAX_LEN
-1] = '\0';
1116 case UPNPMODEL_DESCRIPTION
:
1117 strncpy(model_description
, ary_options
[i
].value
, MODEL_DESCRIPTION_MAX_LEN
);
1118 model_description
[MODEL_DESCRIPTION_MAX_LEN
-1] = '\0';
1121 strncpy(model_url
, ary_options
[i
].value
, MODEL_URL_MAX_LEN
);
1122 model_url
[MODEL_URL_MAX_LEN
-1] = '\0';
1125 #ifdef USE_NETFILTER
1126 case UPNPFORWARDCHAIN
:
1127 miniupnpd_forward_chain
= ary_options
[i
].value
;
1130 miniupnpd_nat_chain
= ary_options
[i
].value
;
1133 case UPNPNOTIFY_INTERVAL
:
1134 v
->notify_interval
= atoi(ary_options
[i
].value
);
1136 case UPNPSYSTEM_UPTIME
:
1137 if(strcmp(ary_options
[i
].value
, "yes") == 0)
1138 SETFLAG(SYSUPTIMEMASK
); /*sysuptime = 1;*/
1140 #if defined(USE_PF) || defined(USE_IPF)
1141 case UPNPPACKET_LOG
:
1142 if(strcmp(ary_options
[i
].value
, "yes") == 0)
1143 SETFLAG(LOGPACKETSMASK
); /*logpackets = 1;*/
1147 strncpy(uuidvalue_igd
+5, ary_options
[i
].value
,
1148 strlen(uuidvalue_igd
+5) + 1);
1149 complete_uuidvalues();
1152 strncpy(serialnumber
, ary_options
[i
].value
, SERIALNUMBER_MAX_LEN
);
1153 serialnumber
[SERIALNUMBER_MAX_LEN
-1] = '\0';
1155 case UPNPMODEL_NUMBER
:
1156 strncpy(modelnumber
, ary_options
[i
].value
, MODELNUMBER_MAX_LEN
);
1157 modelnumber
[MODELNUMBER_MAX_LEN
-1] = '\0';
1159 case UPNPCLEANTHRESHOLD
:
1160 v
->clean_ruleset_threshold
= atoi(ary_options
[i
].value
);
1162 case UPNPCLEANINTERVAL
:
1163 v
->clean_ruleset_interval
= atoi(ary_options
[i
].value
);
1167 anchor_name
= ary_options
[i
].value
;
1170 queue
= ary_options
[i
].value
;
1173 tag
= ary_options
[i
].value
;
1176 #ifdef ENABLE_NATPMP
1177 case UPNPENABLENATPMP
:
1178 if(strcmp(ary_options
[i
].value
, "yes") == 0)
1179 SETFLAG(ENABLENATPMPMASK
); /*enablenatpmp = 1;*/
1181 if(atoi(ary_options
[i
].value
))
1182 SETFLAG(ENABLENATPMPMASK
);
1183 /*enablenatpmp = atoi(ary_options[i].value);*/
1187 case UPNPPCPMINLIFETIME
:
1188 min_lifetime
= atoi(ary_options
[i
].value
);
1189 if (min_lifetime
> 120 ) {
1193 case UPNPPCPMAXLIFETIME
:
1194 max_lifetime
= atoi(ary_options
[i
].value
);
1195 if (max_lifetime
> 86400 ) {
1196 max_lifetime
= 86400;
1199 case UPNPPCPALLOWTHIRDPARTY
:
1200 if(strcmp(ary_options
[i
].value
, "yes") == 0)
1201 SETFLAG(PCP_ALLOWTHIRDPARTYMASK
);
1204 #ifdef PF_ENABLE_FILTER_RULES
1205 case UPNPQUICKRULES
:
1206 if(strcmp(ary_options
[i
].value
, "no") == 0)
1207 SETFLAG(PFNOQUICKRULESMASK
);
1211 if(strcmp(ary_options
[i
].value
, "yes") != 0)
1212 CLEARFLAG(ENABLEUPNPMASK
);
1214 case UPNPSECUREMODE
:
1215 if(strcmp(ary_options
[i
].value
, "yes") == 0)
1216 SETFLAG(SECUREMODEMASK
);
1218 #ifdef ENABLE_LEASEFILE
1220 lease_file
= ary_options
[i
].value
;
1223 case UPNPMINISSDPDSOCKET
:
1224 minissdpdsocketpath
= ary_options
[i
].value
;
1227 fprintf(stderr
, "Unknown option in file %s\n",
1232 /* if lifetimes are inverse */
1233 if (min_lifetime
>= max_lifetime
) {
1234 fprintf(stderr
, "Minimum lifetime (%lu) is greater than or equal to maximum lifetime (%lu).\n", min_lifetime
, max_lifetime
);
1235 fprintf(stderr
, "Check your configuration file.\n");
1240 #endif /* DISABLE_CONFIG_FILE */
1242 /* command line arguments processing */
1243 for(i
=1; i
<argc
; i
++)
1247 fprintf(stderr
, "Unknown option: %s\n", argv
[i
]);
1249 else switch(argv
[i
][1])
1253 use_ext_ip_addr
= argv
[++i
];
1255 fprintf(stderr
, "Option -%c takes one argument.\n", argv
[i
][1]);
1259 v
->notify_interval
= atoi(argv
[++i
]);
1261 fprintf(stderr
, "Option -%c takes one argument.\n", argv
[i
][1]);
1265 v
->clean_ruleset_interval
= atoi(argv
[++i
]);
1267 fprintf(stderr
, "Option -%c takes one argument.\n", argv
[i
][1]);
1271 strncpy(uuidvalue_igd
+5, argv
[++i
], strlen(uuidvalue_igd
+5) + 1);
1272 complete_uuidvalues();
1274 fprintf(stderr
, "Option -%c takes one argument.\n", argv
[i
][1]);
1276 #ifdef ENABLE_MANUFACTURER_INFO_CONFIGURATION
1279 strncpy(friendly_name
, argv
[++i
], FRIENDLY_NAME_MAX_LEN
);
1281 fprintf(stderr
, "Option -%c takes one argument.\n", argv
[i
][1]);
1282 friendly_name
[FRIENDLY_NAME_MAX_LEN
-1] = '\0';
1287 strncpy(serialnumber
, argv
[++i
], SERIALNUMBER_MAX_LEN
);
1289 fprintf(stderr
, "Option -%c takes one argument.\n", argv
[i
][1]);
1290 serialnumber
[SERIALNUMBER_MAX_LEN
-1] = '\0';
1294 strncpy(modelnumber
, argv
[++i
], MODELNUMBER_MAX_LEN
);
1296 fprintf(stderr
, "Option -%c takes one argument.\n", argv
[i
][1]);
1297 modelnumber
[MODELNUMBER_MAX_LEN
-1] = '\0';
1299 #ifdef ENABLE_NATPMP
1301 /*enablenatpmp = 1;*/
1302 SETFLAG(ENABLENATPMPMASK
);
1307 SETFLAG(SYSUPTIMEMASK
);
1310 logfilename = argv[++i];
1312 #if defined(USE_PF) || defined(USE_IPF)
1315 SETFLAG(LOGPACKETSMASK
);
1319 SETFLAG(SECUREMODEMASK
);
1323 ext_if_name
= argv
[++i
];
1325 fprintf(stderr
, "Option -%c takes one argument.\n", argv
[i
][1]);
1332 fprintf(stderr
, "Option -%c takes one argument.\n", argv
[i
][1]);
1338 fprintf(stderr
, "Option -%c takes one argument.\n", argv
[i
][1]);
1343 v
->port
= atoi(argv
[++i
]);
1345 fprintf(stderr
, "Option -%c takes one argument.\n", argv
[i
][1]);
1350 v
->https_port
= atoi(argv
[++i
]);
1352 fprintf(stderr
, "Option -%c takes one argument.\n", argv
[i
][1]);
1355 #ifdef ENABLE_NFQUEUE
1359 nfqueue
= atoi(argv
[++i
]);
1362 fprintf(stderr
, "Option -%c takes one argument.\n", argv
[i
][1]);
1367 if(n_nfqix
< MAX_LAN_ADDR
) {
1368 nfqix
[n_nfqix
++] = if_nametoindex(argv
[i
]);
1370 fprintf(stderr
,"Too many nfq interfaces. Ignoring %s\n", argv
[i
]);
1373 fprintf(stderr
, "Option -%c takes one argument.\n", argv
[i
][1]);
1379 pidfilename
= argv
[++i
];
1381 fprintf(stderr
, "Option -%c takes one argument.\n", argv
[i
][1]);
1388 presurl
= argv
[++i
];
1390 fprintf(stderr
, "Option -%c takes one argument.\n", argv
[i
][1]);
1395 downstream_bitrate
= strtoul(argv
[++i
], 0, 0);
1396 upstream_bitrate
= strtoul(argv
[++i
], 0, 0);
1399 fprintf(stderr
, "Option -%c takes two arguments.\n", argv
[i
][1]);
1402 #ifndef MULTIPLE_EXTERNAL_IP
1406 lan_addr
= (struct lan_addr_s
*) malloc(sizeof(struct lan_addr_s
));
1407 if (lan_addr
== NULL
)
1409 fprintf(stderr
, "malloc(sizeof(struct lan_addr_s)): %m");
1412 if(parselanaddr(lan_addr
, argv
[i
]) != 0)
1414 fprintf(stderr
, "can't parse \"%s\" as a valid "
1418 "interface name\n", argv
[i
]);
1422 /* check if we already have this address */
1423 for(lan_addr2
= lan_addrs
.lh_first
; lan_addr2
!= NULL
; lan_addr2
= lan_addr2
->list
.le_next
)
1425 if (0 == strncmp(lan_addr2
->str
, lan_addr
->str
, 15))
1428 if (lan_addr2
== NULL
)
1429 LIST_INSERT_HEAD(&lan_addrs
, lan_addr
, list
);
1432 fprintf(stderr
, "Option -%c takes one argument.\n", argv
[i
][1]);
1436 char *val
=calloc((strlen(argv
[i
+1]) + strlen(argv
[i
+2]) + 1), sizeof(char));
1439 fprintf(stderr
, "memory allocation error for listen address storage\n");
1442 sprintf(val
, "%s %s", argv
[i
+1], argv
[i
+2]);
1444 lan_addr
= (struct lan_addr_s
*) malloc(sizeof(struct lan_addr_s
));
1445 if (lan_addr
== NULL
)
1447 fprintf(stderr
, "malloc(sizeof(struct lan_addr_s)): %m");
1451 if(parselanaddr(lan_addr
, val
) != 0)
1453 fprintf(stderr
, "can't parse \"%s\" as a valid LAN address or interface name\n", val
);
1458 /* check if we already have this address */
1459 for(lan_addr2
= lan_addrs
.lh_first
; lan_addr2
!= NULL
; lan_addr2
= lan_addr2
->list
.le_next
)
1461 if (0 == strncmp(lan_addr2
->str
, lan_addr
->str
, 15))
1464 if (lan_addr2
== NULL
)
1465 LIST_INSERT_HEAD(&lan_addrs
, lan_addr
, list
);
1471 fprintf(stderr
, "Option -%c takes two arguments.\n", argv
[i
][1]);
1477 tmp
= realloc(upnppermlist
, sizeof(struct upnpperm
) * (num_upnpperm
+1));
1479 fprintf(stderr
, "memory allocation error for permission\n");
1482 if(read_permission_line(upnppermlist
+ num_upnpperm
, argv
[++i
]) >= 0) {
1485 fprintf(stderr
, "Permission rule parsing error :\n%s\n", argv
[i
]);
1489 fprintf(stderr
, "Option -%c takes one argument.\n", argv
[i
][1]);
1492 i
++; /* discarding, the config file is already read */
1495 fprintf(stderr
, "Unknown option: %s\n", argv
[i
]);
1498 if(!ext_if_name
|| !lan_addrs
.lh_first
)
1500 /* bad configuration */
1511 if(daemon(0, 0)<0) {
1520 openlog_option
= LOG_PID
|LOG_CONS
;
1523 openlog_option
|= LOG_PERROR
; /* also log on stderr */
1526 openlog("miniupnpd", openlog_option
, LOG_MINIUPNPD
);
1530 /* speed things up and ignore LOG_INFO and LOG_DEBUG */
1531 setlogmask(LOG_UPTO(LOG_NOTICE
));
1534 if(checkforrunning(pidfilename
) < 0)
1536 syslog(LOG_ERR
, "MiniUPnPd is already running. EXITING");
1540 syslog(LOG_NOTICE
, "version " MINIUPNPD_VERSION
" started");
1542 set_startup_time(GETFLAG(SYSUPTIMEMASK
));
1544 /* presentation url */
1547 strncpy(presentationurl
, presurl
, PRESENTATIONURL_MAX_LEN
);
1548 presentationurl
[PRESENTATIONURL_MAX_LEN
-1] = '\0';
1552 snprintf(presentationurl
, PRESENTATIONURL_MAX_LEN
,
1553 "http://%s/", lan_addrs
.lh_first
->str
);
1554 /*"http://%s:%d/", lan_addrs.lh_first->str, 80);*/
1557 /* set signal handler */
1558 memset(&sa
, 0, sizeof(struct sigaction
));
1559 sa
.sa_handler
= sigterm
;
1561 if(sigaction(SIGTERM
, &sa
, NULL
) < 0)
1563 syslog(LOG_ERR
, "Failed to set %s handler. EXITING", "SIGTERM");
1566 if(sigaction(SIGINT
, &sa
, NULL
) < 0)
1568 syslog(LOG_ERR
, "Failed to set %s handler. EXITING", "SIGINT");
1573 sa
.sa_handler
= sigusr2
;
1574 sigaction(SIGUSR2
, &sa
, NULL
);
1576 if(signal(SIGPIPE
, SIG_IGN
) == SIG_ERR
)
1578 syslog(LOG_ERR
, "Failed to ignore SIGPIPE signals");
1581 sa
.sa_handler
= sigusr1
;
1582 if(sigaction(SIGUSR1
, &sa
, NULL
) < 0)
1584 syslog(LOG_NOTICE
, "Failed to set %s handler", "SIGUSR1");
1587 /* initialize random number generator */
1588 srandom((unsigned int)time(NULL
));
1590 /* initialize redirection engine (and pinholes) */
1591 if(init_redirect() < 0)
1593 syslog(LOG_ERR
, "Failed to init redirection engine. EXITING");
1596 #ifdef ENABLE_UPNPPINHOLE
1597 #ifdef USE_NETFILTER
1602 if(writepidfile(pidfilename
, pid
) < 0)
1605 #ifdef ENABLE_LEASEFILE
1606 /*remove(lease_file);*/
1607 syslog(LOG_INFO
, "Reloading rules from lease file");
1608 reload_from_lease_file();
1610 tomato_load(); // zzz
1614 fprintf(stderr
, "Usage:\n\t"
1616 #ifndef DISABLE_CONFIG_FILE
1619 "[-i ext_ifname] [-o ext_ip]\n"
1620 #ifndef MULTIPLE_EXTERNAL_IP
1621 "\t\t[-a listening_ip]"
1623 "\t\t[-a listening_ip ext_ip]"
1629 #if defined(USE_PF) || defined(USE_IPF)
1633 #ifdef ENABLE_NATPMP
1637 /*"[-l logfile] " not functionnal */
1638 "\t\t[-u uuid] [-s serial] [-m model_number] \n"
1639 "\t\t[-t notify_interval] [-P pid_filename] "
1640 #ifdef ENABLE_MANUFACTURER_INFO_CONFIGURATION
1641 "[-z fiendly_name]\n"
1643 "\t\t[-B down up] [-w url] [-r clean_ruleset_interval]\n"
1645 "\t\t[-q queue] [-T tag]\n"
1647 #ifdef ENABLE_NFQUEUE
1648 "\t\t[-Q queue] [-n name]\n"
1650 "\t\t[-A \"permission rule\"]\n"
1651 "\nNotes:\n\tThere can be one or several listening_ips.\n"
1652 "\tNotify interval is in seconds. Default is 30 seconds.\n"
1653 "\tDefault pid file is '%s'.\n"
1654 "\tDefault config file is '%s'.\n"
1655 "\tWith -d miniupnpd will run as a standard program.\n"
1656 #if defined(USE_PF) || defined(USE_IPF)
1657 "\t-L sets packet log in pf and ipf on.\n"
1659 "\t-S sets \"secure\" mode : clients can only add mappings to their own ip\n"
1660 "\t-U causes miniupnpd to report system uptime instead "
1661 "of daemon uptime.\n"
1662 #ifdef ENABLE_NATPMP
1663 "\t-N enable NAT-PMP functionality.\n"
1665 "\t-B sets bitrates reported by daemon in bits per second.\n"
1666 "\t-w sets the presentation url. Default is http address on port 80\n"
1668 "\t-q sets the ALTQ queue in pf.\n"
1669 "\t-T sets the tag name in pf.\n"
1671 #ifdef ENABLE_NFQUEUE
1672 "\t-Q sets the queue number that is used by NFQUEUE.\n"
1673 "\t-n sets the name of the interface(s) that packets will arrive on.\n"
1675 "\t-A use following syntax for permission rules :\n"
1676 "\t (allow|deny) (external port range) ip/mask (internal port range)\n"
1678 "\t \"allow 1024-65535 192.168.1.0/24 1024-65535\"\n"
1679 "\t \"deny 0-65535 0.0.0.0/0 0-65535\"\n"
1680 "\t-h prints this help and quits.\n"
1681 "", argv
[0], pidfilename
, DEFAULT_CONFIG
);
1686 /* process HTTP or SSDP requests */
1688 main(int argc
, char * * argv
)
1691 int shttpl
= -1; /* socket for HTTP */
1692 #if defined(V6SOCKETS_ARE_V6ONLY) && defined(ENABLE_IPV6)
1693 int shttpl_v4
= -1; /* socket for HTTP (ipv4 only) */
1696 int shttpsl
= -1; /* socket for HTTPS */
1697 #if defined(V6SOCKETS_ARE_V6ONLY) && defined(ENABLE_IPV6)
1698 int shttpsl_v4
= -1; /* socket for HTTPS (ipv4 only) */
1700 #endif /* ENABLE_HTTPS */
1701 int sudp
= -1; /* IP v4 socket for receiving SSDP */
1703 int sudpv6
= -1; /* IP v6 socket for receiving SSDP */
1705 #ifdef ENABLE_NATPMP
1706 int * snatpmp
= NULL
; /* also used for PCP */
1708 #if defined(ENABLE_IPV6) && defined(ENABLE_PCP)
1711 #ifdef ENABLE_NFQUEUE
1714 #ifdef USE_IFACEWATCHER
1715 int sifacewatcher
= -1;
1718 int * snotify
= NULL
;
1720 LIST_HEAD(httplisthead
, upnphttp
) upnphttphead
;
1721 struct upnphttp
* e
= 0;
1722 struct upnphttp
* next
;
1723 fd_set readset
; /* for select() */
1725 struct timeval timeout
, timeofday
, lasttimeofday
= {0, 0};
1727 #ifdef USE_MINIUPNPDCTL
1729 LIST_HEAD(ctlstructhead
, ctlelem
) ctllisthead
;
1730 struct ctlelem
* ectl
;
1731 struct ctlelem
* ectlnext
;
1733 struct runtime_vars v
;
1734 /* variables used for the unused-rule cleanup process */
1735 struct rule_state
* rule_list
= 0;
1736 struct timeval checktime
= {0, 0};
1737 struct lan_addr_s
* lan_addr
;
1738 #ifdef ENABLE_UPNPPINHOLE
1739 unsigned int next_pinhole_ts
;
1742 if(init(argc
, argv
, &v
) != 0)
1747 #endif /* ENABLE_HTTPS */
1748 /* count lan addrs */
1750 for(lan_addr
= lan_addrs
.lh_first
; lan_addr
!= NULL
; lan_addr
= lan_addr
->list
.le_next
)
1752 if(addr_count
> 0) {
1754 snotify
= calloc(addr_count
, sizeof(int));
1756 /* one for IPv4, one for IPv6 */
1757 snotify
= calloc(addr_count
* 2, sizeof(int));
1760 #ifdef ENABLE_NATPMP
1761 if(addr_count
> 0) {
1762 snatpmp
= malloc(addr_count
* sizeof(int));
1763 for(i
= 0; i
< addr_count
; i
++)
1768 LIST_INIT(&upnphttphead
);
1769 #ifdef USE_MINIUPNPDCTL
1770 LIST_INIT(&ctllisthead
);
1774 #ifdef ENABLE_NATPMP
1775 !GETFLAG(ENABLENATPMPMASK
) &&
1777 !GETFLAG(ENABLEUPNPMASK
) ) {
1778 syslog(LOG_ERR
, "Why did you run me anyway?");
1782 syslog(LOG_INFO
, "Starting%s%swith external interface %s",
1783 #ifdef ENABLE_NATPMP
1785 GETFLAG(ENABLENATPMPMASK
) ? " NAT-PMP/PCP " : " ",
1787 GETFLAG(ENABLENATPMPMASK
) ? " NAT-PMP " : " ",
1792 GETFLAG(ENABLEUPNPMASK
) ? "UPnP-IGD " : "",
1795 if(GETFLAG(ENABLEUPNPMASK
))
1797 unsigned short listen_port
;
1798 listen_port
= (v
.port
> 0) ? v
.port
: 0;
1799 /* open socket for HTTP connections. Listen on the 1st LAN address */
1801 shttpl
= OpenAndConfHTTPSocket(&listen_port
, 1);
1802 #else /* ENABLE_IPV6 */
1803 shttpl
= OpenAndConfHTTPSocket(&listen_port
);
1804 #endif /* ENABLE_IPV6 */
1807 syslog(LOG_ERR
, "Failed to open socket for HTTP. EXITING");
1810 v
.port
= listen_port
;
1811 syslog(LOG_NOTICE
, "HTTP listening on port %d", v
.port
);
1812 #if defined(V6SOCKETS_ARE_V6ONLY) && defined(ENABLE_IPV6)
1813 if(!GETFLAG(IPV6DISABLEDMASK
))
1815 shttpl_v4
= OpenAndConfHTTPSocket(&listen_port
, 0);
1818 syslog(LOG_ERR
, "Failed to open socket for HTTP on port %hu (IPv4). EXITING", v
.port
);
1822 #endif /* V6SOCKETS_ARE_V6ONLY */
1825 listen_port
= (v
.https_port
> 0) ? v
.https_port
: 0;
1827 shttpsl
= OpenAndConfHTTPSocket(&listen_port
, 1);
1828 #else /* ENABLE_IPV6 */
1829 shttpsl
= OpenAndConfHTTPSocket(&listen_port
);
1830 #endif /* ENABLE_IPV6 */
1833 syslog(LOG_ERR
, "Failed to open socket for HTTPS. EXITING");
1836 v
.https_port
= listen_port
;
1837 syslog(LOG_NOTICE
, "HTTPS listening on port %d", v
.https_port
);
1838 #if defined(V6SOCKETS_ARE_V6ONLY) && defined(ENABLE_IPV6)
1839 shttpsl_v4
= OpenAndConfHTTPSocket(&listen_port
, 0);
1842 syslog(LOG_ERR
, "Failed to open socket for HTTPS on port %hu (IPv4). EXITING", v
.https_port
);
1845 #endif /* V6SOCKETS_ARE_V6ONLY */
1846 #endif /* ENABLE_HTTPS */
1848 if(find_ipv6_addr(NULL
, ipv6_addr_for_http_with_brackets
, sizeof(ipv6_addr_for_http_with_brackets
)) > 0) {
1849 syslog(LOG_NOTICE
, "HTTP IPv6 address given to control points : %s",
1850 ipv6_addr_for_http_with_brackets
);
1852 memcpy(ipv6_addr_for_http_with_brackets
, "[::1]", 6);
1853 syslog(LOG_WARNING
, "no HTTP IPv6 address, disabling IPv6");
1854 SETFLAG(IPV6DISABLEDMASK
);
1858 /* open socket for SSDP connections */
1859 sudp
= OpenAndConfSSDPReceiveSocket(0);
1862 syslog(LOG_NOTICE
, "Failed to open socket for receiving SSDP. Trying to use MiniSSDPd");
1863 if(SubmitServicesToMiniSSDPD(lan_addrs
.lh_first
->str
, v
.port
) < 0) {
1864 syslog(LOG_ERR
, "Failed to connect to MiniSSDPd. EXITING");
1869 if(!GETFLAG(IPV6DISABLEDMASK
))
1871 sudpv6
= OpenAndConfSSDPReceiveSocket(1);
1874 syslog(LOG_WARNING
, "Failed to open socket for receiving SSDP (IP v6).");
1879 /* open socket for sending notifications */
1880 if(OpenAndConfSSDPNotifySockets(snotify
) < 0)
1882 syslog(LOG_ERR
, "Failed to open sockets for sending SSDP notify "
1883 "messages. EXITING");
1887 #ifdef USE_IFACEWATCHER
1888 /* open socket for kernel notifications about new network interfaces */
1891 sifacewatcher
= OpenAndConfInterfaceWatchSocket();
1892 if (sifacewatcher
< 0)
1894 syslog(LOG_ERR
, "Failed to open socket for receiving network interface notifications");
1900 #ifdef ENABLE_NATPMP
1901 /* open socket for NAT PMP traffic */
1902 if(GETFLAG(ENABLENATPMPMASK
))
1904 if(OpenAndConfNATPMPSockets(snatpmp
) < 0)
1907 syslog(LOG_ERR
, "Failed to open sockets for NAT-PMP/PCP.");
1909 syslog(LOG_NOTICE
, "Listening for NAT-PMP/PCP traffic on port %u",
1914 syslog(LOG_ERR
, "Failed to open sockets for NAT PMP.");
1916 syslog(LOG_NOTICE
, "Listening for NAT-PMP traffic on port %u",
1923 #if defined(ENABLE_IPV6) && defined(ENABLE_PCP)
1924 spcp_v6
= OpenAndConfPCPv6Socket();
1927 /* for miniupnpdctl */
1928 #ifdef USE_MINIUPNPDCTL
1929 sctl
= OpenAndConfCtlUnixSocket("/var/run/miniupnpd.ctl");
1932 #ifdef ENABLE_NFQUEUE
1933 if ( nfqueue
!= -1 && n_nfqix
> 0) {
1934 nfqh
= OpenAndConfNFqueue();
1936 syslog(LOG_ERR
, "Failed to open fd for NFQUEUE.");
1939 syslog(LOG_NOTICE
, "Opened NFQUEUE %d",nfqueue
);
1944 tomato_helper(); // zzz
1949 /* Correct startup_time if it was set with a RTC close to 0 */
1950 if((startup_time
<60*60*24) && (time(NULL
)>60*60*24))
1952 set_startup_time(GETFLAG(SYSUPTIMEMASK
));
1954 /* send public address change notifications if needed */
1955 if(should_send_public_address_change_notif
)
1957 syslog(LOG_INFO
, "should send external iface address change notification(s)");
1958 #ifdef ENABLE_NATPMP
1959 if(GETFLAG(ENABLENATPMPMASK
))
1960 SendNATPMPPublicAddressChangeNotification(snatpmp
, addr_count
);
1962 #ifdef ENABLE_EVENTS
1963 if(GETFLAG(ENABLEUPNPMASK
))
1965 upnp_event_var_change_notify(EWanIPC
);
1968 should_send_public_address_change_notif
= 0;
1970 /* Check if we need to send SSDP NOTIFY messages and do it if
1972 if(gettimeofday(&timeofday
, 0) < 0)
1974 syslog(LOG_ERR
, "gettimeofday(): %m");
1975 timeout
.tv_sec
= v
.notify_interval
;
1976 timeout
.tv_usec
= 0;
1980 /* the comparaison is not very precise but who cares ? */
1981 if(timeofday
.tv_sec
>= (lasttimeofday
.tv_sec
+ v
.notify_interval
))
1983 if (GETFLAG(ENABLEUPNPMASK
))
1984 SendSSDPNotifies2(snotify
,
1985 (unsigned short)v
.port
,
1987 (unsigned short)v
.https_port
,
1989 v
.notify_interval
<< 1);
1990 memcpy(&lasttimeofday
, &timeofday
, sizeof(struct timeval
));
1991 timeout
.tv_sec
= v
.notify_interval
;
1992 timeout
.tv_usec
= 0;
1996 timeout
.tv_sec
= lasttimeofday
.tv_sec
+ v
.notify_interval
1998 if(timeofday
.tv_usec
> lasttimeofday
.tv_usec
)
2000 timeout
.tv_usec
= 1000000 + lasttimeofday
.tv_usec
2001 - timeofday
.tv_usec
;
2006 timeout
.tv_usec
= lasttimeofday
.tv_usec
- timeofday
.tv_usec
;
2010 /* remove unused rules */
2011 if( v
.clean_ruleset_interval
2012 && (timeofday
.tv_sec
>= checktime
.tv_sec
+ v
.clean_ruleset_interval
))
2016 remove_unused_rules(rule_list
);
2021 rule_list
= get_upnp_rules_state_list(v
.clean_ruleset_threshold
);
2023 memcpy(&checktime
, &timeofday
, sizeof(struct timeval
));
2025 /* Remove expired port mappings, based on UPnP IGD LeaseDuration
2026 * or NAT-PMP lifetime) */
2027 if(nextruletoclean_timestamp
2028 && ((unsigned int)timeofday
.tv_sec
>= nextruletoclean_timestamp
))
2030 syslog(LOG_DEBUG
, "cleaning expired Port Mappings");
2031 get_upnp_rules_state_list(0);
2033 if(nextruletoclean_timestamp
2034 && ((unsigned int)timeout
.tv_sec
>= (nextruletoclean_timestamp
- timeofday
.tv_sec
)))
2036 timeout
.tv_sec
= nextruletoclean_timestamp
- timeofday
.tv_sec
;
2037 timeout
.tv_usec
= 0;
2038 syslog(LOG_DEBUG
, "setting timeout to %u sec",
2039 (unsigned)timeout
.tv_sec
);
2041 #ifdef ENABLE_UPNPPINHOLE
2042 /* Clean up expired IPv6 PinHoles */
2043 next_pinhole_ts
= 0;
2044 upnp_clean_expired_pinholes(&next_pinhole_ts
);
2045 if(next_pinhole_ts
&&
2046 timeout
.tv_sec
>= (int)(next_pinhole_ts
- timeofday
.tv_sec
)) {
2047 timeout
.tv_sec
= next_pinhole_ts
- timeofday
.tv_sec
;
2048 timeout
.tv_usec
= 0;
2050 #endif /* ENABLE_UPNPPINHOLE */
2052 /* select open sockets (SSDP, HTTP listen, and all HTTP soap sockets) */
2058 FD_SET(sudp
, &readset
);
2059 max_fd
= MAX( max_fd
, sudp
);
2060 #ifdef USE_IFACEWATCHER
2061 if (sifacewatcher
>= 0)
2063 FD_SET(sifacewatcher
, &readset
);
2064 max_fd
= MAX(max_fd
, sifacewatcher
);
2070 FD_SET(shttpl
, &readset
);
2071 max_fd
= MAX( max_fd
, shttpl
);
2073 #if defined(V6SOCKETS_ARE_V6ONLY) && defined(ENABLE_IPV6)
2076 FD_SET(shttpl_v4
, &readset
);
2077 max_fd
= MAX( max_fd
, shttpl_v4
);
2083 FD_SET(shttpsl
, &readset
);
2084 max_fd
= MAX( max_fd
, shttpsl
);
2086 #if defined(V6SOCKETS_ARE_V6ONLY) && defined(ENABLE_IPV6)
2087 if (shttpsl_v4
>= 0)
2089 FD_SET(shttpsl_v4
, &readset
);
2090 max_fd
= MAX( max_fd
, shttpsl_v4
);
2093 #endif /* ENABLE_HTTPS */
2097 FD_SET(sudpv6
, &readset
);
2098 max_fd
= MAX( max_fd
, sudpv6
);
2102 #ifdef ENABLE_NFQUEUE
2105 FD_SET(nfqh
, &readset
);
2106 max_fd
= MAX( max_fd
, nfqh
);
2110 i
= 0; /* active HTTP connections count */
2111 for(e
= upnphttphead
.lh_first
; e
!= NULL
; e
= e
->entries
.le_next
)
2115 if(e
->state
<= EWaitingForHttpContent
)
2116 FD_SET(e
->socket
, &readset
);
2117 else if(e
->state
== ESendingAndClosing
)
2118 FD_SET(e
->socket
, &writeset
);
2121 max_fd
= MAX(max_fd
, e
->socket
);
2129 syslog(LOG_DEBUG
, "%d active incoming HTTP connections", i
);
2132 #ifdef ENABLE_NATPMP
2133 for(i
=0; i
<addr_count
; i
++) {
2134 if(snatpmp
[i
] >= 0) {
2135 FD_SET(snatpmp
[i
], &readset
);
2136 max_fd
= MAX( max_fd
, snatpmp
[i
]);
2140 #if defined(ENABLE_IPV6) && defined(ENABLE_PCP)
2142 FD_SET(spcp_v6
, &readset
);
2143 max_fd
= MAX(max_fd
, spcp_v6
);
2146 #ifdef USE_MINIUPNPDCTL
2148 FD_SET(sctl
, &readset
);
2149 max_fd
= MAX( max_fd
, sctl
);
2152 for(ectl
= ctllisthead
.lh_first
; ectl
; ectl
= ectl
->entries
.le_next
)
2154 if(ectl
->socket
>= 0) {
2155 FD_SET(ectl
->socket
, &readset
);
2156 max_fd
= MAX( max_fd
, ectl
->socket
);
2161 #ifdef ENABLE_EVENTS
2162 upnpevents_selectfds(&readset
, &writeset
, &max_fd
);
2165 /* queued "sendto" */
2167 struct timeval next_send
;
2168 i
= get_next_scheduled_send(&next_send
);
2171 syslog(LOG_DEBUG
, "%d queued sendto", i
);
2173 i
= get_sendto_fds(&writeset
, &max_fd
, &timeofday
);
2174 if(timeofday
.tv_sec
> next_send
.tv_sec
||
2175 (timeofday
.tv_sec
== next_send
.tv_sec
&& timeofday
.tv_usec
>= next_send
.tv_usec
)) {
2178 timeout
.tv_usec
= 0;
2181 struct timeval tmp_timeout
;
2182 tmp_timeout
.tv_sec
= (next_send
.tv_sec
- timeofday
.tv_sec
);
2183 tmp_timeout
.tv_usec
= (next_send
.tv_usec
- timeofday
.tv_usec
);
2184 if(tmp_timeout
.tv_usec
< 0) {
2185 tmp_timeout
.tv_usec
+= 1000000;
2186 tmp_timeout
.tv_sec
--;
2188 if(timeout
.tv_sec
> tmp_timeout
.tv_sec
2189 || (timeout
.tv_sec
== tmp_timeout
.tv_sec
&& timeout
.tv_usec
> tmp_timeout
.tv_usec
)) {
2190 timeout
.tv_sec
= tmp_timeout
.tv_sec
;
2191 timeout
.tv_usec
= tmp_timeout
.tv_usec
;
2197 if(select(max_fd
+1, &readset
, &writeset
, 0, &timeout
) < 0)
2199 if(quitting
) goto shutdown
;
2200 if (gotusr2
) { // zzz
2205 if(errno
== EINTR
) continue; /* interrupted by a signal, start again */
2206 syslog(LOG_ERR
, "select(all): %m");
2207 syslog(LOG_ERR
, "Failed to select open sockets. EXITING");
2208 return 1; /* very serious cause of error */
2210 i
= try_sendto(&writeset
);
2212 syslog(LOG_ERR
, "try_sendto failed to send %d packets", -i
);
2214 #ifdef USE_MINIUPNPDCTL
2215 for(ectl
= ctllisthead
.lh_first
; ectl
;)
2217 ectlnext
= ectl
->entries
.le_next
;
2218 if((ectl
->socket
>= 0) && FD_ISSET(ectl
->socket
, &readset
))
2222 l
= read(ectl
->socket
, buf
, sizeof(buf
));
2225 /*write(ectl->socket, buf, l);*/
2226 write_command_line(ectl
->socket
, argc
, argv
);
2227 #ifndef DISABLE_CONFIG_FILE
2228 write_option_list(ectl
->socket
);
2230 write_permlist(ectl
->socket
, upnppermlist
, num_upnpperm
);
2231 write_upnphttp_details(ectl
->socket
, upnphttphead
.lh_first
);
2232 write_ctlsockets_list(ectl
->socket
, ctllisthead
.lh_first
);
2233 write_ruleset_details(ectl
->socket
);
2234 #ifdef ENABLE_EVENTS
2235 write_events_details(ectl
->socket
);
2237 /* close the socket */
2238 close(ectl
->socket
);
2243 close(ectl
->socket
);
2247 if(ectl
->socket
< 0)
2249 LIST_REMOVE(ectl
, entries
);
2254 if((sctl
>= 0) && FD_ISSET(sctl
, &readset
))
2257 struct sockaddr_un clientname
;
2258 struct ctlelem
* tmp
;
2259 socklen_t clientnamelen
= sizeof(struct sockaddr_un
);
2260 /*syslog(LOG_DEBUG, "sctl!");*/
2261 s
= accept(sctl
, (struct sockaddr
*)&clientname
,
2263 syslog(LOG_DEBUG
, "sctl! : '%s'", clientname
.sun_path
);
2264 tmp
= malloc(sizeof(struct ctlelem
));
2267 syslog(LOG_ERR
, "Unable to allocate memory for ctlelem in main()");
2273 LIST_INSERT_HEAD(&ctllisthead
, tmp
, entries
);
2277 #ifdef ENABLE_EVENTS
2278 upnpevents_processfds(&readset
, &writeset
);
2280 #ifdef ENABLE_NATPMP
2281 /* process NAT-PMP packets */
2282 for(i
=0; i
<addr_count
; i
++)
2284 if((snatpmp
[i
] >= 0) && FD_ISSET(snatpmp
[i
], &readset
))
2286 unsigned char msg_buff
[PCP_MAX_LEN
];
2287 struct sockaddr_in senderaddr
;
2288 socklen_t senderaddrlen
;
2290 memset(msg_buff
, 0, PCP_MAX_LEN
);
2291 senderaddrlen
= sizeof(senderaddr
);
2292 len
= ReceiveNATPMPOrPCPPacket(snatpmp
[i
],
2293 (struct sockaddr
*)&senderaddr
,
2296 msg_buff
, sizeof(msg_buff
));
2300 if (msg_buff
[0]==0) { /* version equals to 0 -> means NAT-PMP */
2301 /* Check if the packet is coming from a LAN to enforce RFC6886 :
2302 * The NAT gateway MUST NOT accept mapping requests destined to the NAT
2303 * gateway's external IP address or received on its external network
2304 * interface. Only packets received on the internal interface(s) with a
2305 * destination address matching the internal address(es) of the NAT
2306 * gateway should be allowed. */
2307 /* TODO : move to ProcessIncomingNATPMPPacket() ? */
2308 lan_addr
= get_lan_for_peer((struct sockaddr
*)&senderaddr
);
2309 if(lan_addr
== NULL
) {
2310 char sender_str
[64];
2311 sockaddr_to_string((struct sockaddr
*)&senderaddr
, sender_str
, sizeof(sender_str
));
2312 syslog(LOG_WARNING
, "NAT-PMP packet sender %s not from a LAN, ignoring",
2316 ProcessIncomingNATPMPPacket(snatpmp
[i
], msg_buff
, len
,
2318 } else { /* everything else can be PCP */
2319 ProcessIncomingPCPPacket(snatpmp
[i
], msg_buff
, len
,
2320 (struct sockaddr
*)&senderaddr
, NULL
);
2324 /* Check if the packet is coming from a LAN to enforce RFC6886 :
2325 * The NAT gateway MUST NOT accept mapping requests destined to the NAT
2326 * gateway's external IP address or received on its external network
2327 * interface. Only packets received on the internal interface(s) with a
2328 * destination address matching the internal address(es) of the NAT
2329 * gateway should be allowed. */
2330 /* TODO : move to ProcessIncomingNATPMPPacket() ? */
2331 lan_addr
= get_lan_for_peer((struct sockaddr
*)&senderaddr
);
2332 if(lan_addr
== NULL
) {
2333 char sender_str
[64];
2334 sockaddr_to_string((struct sockaddr
*)&senderaddr
, sender_str
, sizeof(sender_str
));
2335 syslog(LOG_WARNING
, "NAT-PMP packet sender %s not from a LAN, ignoring",
2339 ProcessIncomingNATPMPPacket(snatpmp
[i
], msg_buff
, len
, &senderaddr
);
2344 #if defined(ENABLE_IPV6) && defined(ENABLE_PCP)
2345 /* in IPv6, only PCP is supported, not NAT-PMP */
2346 if(spcp_v6
>= 0 && FD_ISSET(spcp_v6
, &readset
))
2348 unsigned char msg_buff
[PCP_MAX_LEN
];
2349 struct sockaddr_in6 senderaddr
;
2350 socklen_t senderaddrlen
;
2351 struct sockaddr_in6 receiveraddr
;
2353 memset(msg_buff
, 0, PCP_MAX_LEN
);
2354 senderaddrlen
= sizeof(senderaddr
);
2355 len
= ReceiveNATPMPOrPCPPacket(spcp_v6
,
2356 (struct sockaddr
*)&senderaddr
,
2359 msg_buff
, sizeof(msg_buff
));
2361 ProcessIncomingPCPPacket(spcp_v6
, msg_buff
, len
,
2362 (struct sockaddr
*)&senderaddr
,
2366 /* process SSDP packets */
2367 if(sudp
>= 0 && FD_ISSET(sudp
, &readset
))
2369 /*syslog(LOG_INFO, "Received UDP Packet");*/
2371 ProcessSSDPRequest(sudp
, (unsigned short)v
.port
, (unsigned short)v
.https_port
);
2373 ProcessSSDPRequest(sudp
, (unsigned short)v
.port
);
2377 if(sudpv6
>= 0 && FD_ISSET(sudpv6
, &readset
))
2379 syslog(LOG_INFO
, "Received UDP Packet (IPv6)");
2381 ProcessSSDPRequest(sudpv6
, (unsigned short)v
.port
, (unsigned short)v
.https_port
);
2383 ProcessSSDPRequest(sudpv6
, (unsigned short)v
.port
);
2387 #ifdef USE_IFACEWATCHER
2388 /* process kernel notifications */
2389 if (sifacewatcher
>= 0 && FD_ISSET(sifacewatcher
, &readset
))
2390 ProcessInterfaceWatchNotify(sifacewatcher
);
2393 /* process active HTTP connections */
2394 /* LIST_FOREACH macro is not available under linux */
2395 for(e
= upnphttphead
.lh_first
; e
!= NULL
; e
= e
->entries
.le_next
)
2399 if(FD_ISSET(e
->socket
, &readset
) ||
2400 FD_ISSET(e
->socket
, &writeset
))
2402 Process_upnphttp(e
);
2406 /* process incoming HTTP connections */
2407 if(shttpl
>= 0 && FD_ISSET(shttpl
, &readset
))
2409 struct upnphttp
* tmp
;
2410 tmp
= ProcessIncomingHTTP(shttpl
, "HTTP");
2413 LIST_INSERT_HEAD(&upnphttphead
, tmp
, entries
);
2416 #if defined(V6SOCKETS_ARE_V6ONLY) && defined(ENABLE_IPV6)
2417 if(shttpl_v4
>= 0 && FD_ISSET(shttpl_v4
, &readset
))
2419 struct upnphttp
* tmp
;
2420 tmp
= ProcessIncomingHTTP(shttpl_v4
, "HTTP");
2423 LIST_INSERT_HEAD(&upnphttphead
, tmp
, entries
);
2428 if(shttpsl
>= 0 && FD_ISSET(shttpsl
, &readset
))
2430 struct upnphttp
* tmp
;
2431 tmp
= ProcessIncomingHTTP(shttpsl
, "HTTPS");
2434 InitSSL_upnphttp(tmp
);
2435 LIST_INSERT_HEAD(&upnphttphead
, tmp
, entries
);
2438 #if defined(V6SOCKETS_ARE_V6ONLY) && defined(ENABLE_IPV6)
2439 if(shttpsl_v4
>= 0 && FD_ISSET(shttpsl_v4
, &readset
))
2441 struct upnphttp
* tmp
;
2442 tmp
= ProcessIncomingHTTP(shttpsl_v4
, "HTTPS");
2445 InitSSL_upnphttp(tmp
);
2446 LIST_INSERT_HEAD(&upnphttphead
, tmp
, entries
);
2450 #endif /* ENABLE_HTTPS */
2451 #ifdef ENABLE_NFQUEUE
2452 /* process NFQ packets */
2453 if(nfqh
>= 0 && FD_ISSET(nfqh
, &readset
))
2455 /* syslog(LOG_INFO, "Received NFQUEUE Packet");*/
2456 ProcessNFQUEUE(nfqh
);
2459 /* delete finished HTTP connections */
2460 for(e
= upnphttphead
.lh_first
; e
!= NULL
; )
2462 next
= e
->entries
.le_next
;
2463 if(e
->state
>= EToDelete
)
2465 LIST_REMOVE(e
, entries
);
2471 } /* end of main loop */
2474 syslog(LOG_NOTICE
, "shutting down MiniUPnPd");
2476 if (GETFLAG(ENABLEUPNPMASK
))
2479 if(SendSSDPGoodbye(snotify
, addr_count
) < 0)
2481 if(SendSSDPGoodbye(snotify
, addr_count
* 2) < 0)
2484 syslog(LOG_ERR
, "Failed to broadcast good-bye notifications");
2487 /* try to send pending packets */
2490 tomato_save("/etc/upnp/data"); // zzz
2492 /* close out open sockets */
2493 while(upnphttphead
.lh_first
!= NULL
)
2495 e
= upnphttphead
.lh_first
;
2496 LIST_REMOVE(e
, entries
);
2500 if (sudp
>= 0) close(sudp
);
2501 if (shttpl
>= 0) close(shttpl
);
2502 #if defined(V6SOCKETS_ARE_V6ONLY) && defined(ENABLE_IPV6)
2503 if (shttpl_v4
>= 0) close(shttpl_v4
);
2506 if (sudpv6
>= 0) close(sudpv6
);
2508 #ifdef USE_IFACEWATCHER
2509 if(sifacewatcher
>= 0) close(sifacewatcher
);
2511 #ifdef ENABLE_NATPMP
2512 for(i
=0; i
<addr_count
; i
++) {
2520 #if defined(ENABLE_IPV6) && defined(ENABLE_PCP)
2527 #ifdef USE_MINIUPNPDCTL
2532 if(unlink("/var/run/miniupnpd.ctl") < 0)
2534 syslog(LOG_ERR
, "unlink() %m");
2539 if (GETFLAG(ENABLEUPNPMASK
))
2542 for(i
= 0; i
< addr_count
; i
++)
2544 for(i
= 0; i
< addr_count
* 2; i
++)
2549 /* remove pidfile */
2550 if(pidfilename
&& (unlink(pidfilename
) < 0))
2552 syslog(LOG_ERR
, "Failed to remove pidfile %s: %m", pidfilename
);
2556 while(lan_addrs
.lh_first
!= NULL
)
2558 lan_addr
= lan_addrs
.lh_first
;
2559 LIST_REMOVE(lan_addrs
.lh_first
, list
);
2566 #ifdef ENABLE_NATPMP
2571 #ifndef DISABLE_CONFIG_FILE