1 /* $Id: miniupnpd.c,v 1.207 2015/03/07 15:53:50 nanard Exp $ */
3 * http://miniupnp.free.fr/ or http://miniupnp.tuxfamily.org/
4 * (c) 2006-2015 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
54 #include "upnpglobalvars.h"
56 #include "upnpdescgen.h"
57 #include "miniupnpdpath.h"
58 #include "getifaddr.h"
62 #include "upnpredirect.h"
63 #include "upnppinhole.h"
64 #include "miniupnpdtypes.h"
65 #include "daemonize.h"
66 #include "upnpevents.h"
67 #include "asyncsendto.h"
71 #include "pcpserver.h"
73 #define PCP_MAX_LEN 32
76 #include "commonrdr.h"
77 #include "upnputils.h"
78 #ifdef USE_IFACEWATCHER
79 #include "ifacewatcher.h"
81 #ifdef ENABLE_UPNPPINHOLE
83 void init_iptpinhole(void);
87 #ifndef DEFAULT_CONFIG
88 #define DEFAULT_CONFIG "/etc/miniupnpd.conf"
91 #ifdef USE_MINIUPNPDCTL
94 LIST_ENTRY(ctlelem
) entries
;
100 static struct nfq_handle
*nfqHandle
;
101 static struct sockaddr_in ssdp
;
104 static int nfqueue_cb( struct nfq_q_handle
*qh
, struct nfgenmsg
*nfmsg
, struct nfq_data
*nfa
, void *data
) ;
105 int identify_ip_protocol (char *payload
);
106 int get_udp_dst_port (char *payload
);
109 /* variables used by signals */
110 static volatile sig_atomic_t quitting
= 0;
111 volatile sig_atomic_t should_send_public_address_change_notif
= 0;
115 static volatile int gotusr2
= 0;
117 static void sigusr2(int sig
)
122 static void tomato_save(const char *fname
)
124 unsigned short eport
;
125 unsigned short iport
;
126 unsigned int leaseduration
;
127 unsigned int timestamp
;
137 strcpy(tmp
, "/etc/upnp/saveXXXXXX");
138 if ((t
= mkstemp(tmp
)) != -1) {
139 if ((f
= fdopen(t
, "w")) != NULL
) {
141 while (upnp_get_redirection_infos_by_index(n
, &eport
, proto
, &iport
, iaddr
, sizeof(iaddr
), desc
, sizeof(desc
), rhost
, sizeof(rhost
), &leaseduration
) == 0) {
142 timestamp
= (leaseduration
> 0) ? time(NULL
) + leaseduration
: 0;
143 fprintf(f
, "%s %u %s %u [%s] %u\n", proto
, eport
, iaddr
, iport
, desc
, timestamp
);
156 static void tomato_load(void)
160 unsigned short eport
;
161 unsigned short iport
;
162 unsigned int leaseduration
;
163 unsigned int timestamp
;
170 if ((f
= fopen("/etc/upnp/data", "r")) != NULL
) {
171 current_time
= time(NULL
);
172 s
[sizeof(s
) - 1] = 0;
173 while (fgets(s
, sizeof(s
) - 1, f
)) {
174 if (sscanf(s
, "%3s %hu %31s %hu [%*s] %u", proto
, &eport
, iaddr
, &iport
, ×tamp
) >= 4) {
175 if (((a
= strchr(s
, '[')) != NULL
) && ((b
= strrchr(a
, ']')) != NULL
)) {
177 if (timestamp
> current_time
)
178 leaseduration
= current_time
- timestamp
;
182 leaseduration
= 0; /* default value */
186 upnp_redirect(rhost
, eport
, iaddr
, iport
, proto
, a
+ 1, leaseduration
);
194 ScanNATPMPforExpiration();
197 unlink("/etc/upnp/load");
200 static void tomato_delete(void)
204 unsigned short eport
;
205 unsigned short iport
;
206 unsigned int leaseduration
;
213 if ((f
= fopen("/etc/upnp/delete", "r")) != NULL
) {
214 s
[sizeof(s
) - 1] = 0;
215 while (fgets(s
, sizeof(s
) - 1, f
)) {
216 if (sscanf(s
, "%3s %hu", proto
, &eport
) == 2) {
217 if (proto
[0] == '*') {
218 n
= upnp_get_portmapping_number_of_entries();
220 if (upnp_get_redirection_infos_by_index(n
, &eport
, proto
, &iport
, iaddr
, sizeof(iaddr
), desc
, sizeof(desc
), rhost
, sizeof(rhost
), &leaseduration
) == 0) {
221 upnp_delete_redirection(eport
, proto
);
227 upnp_delete_redirection(eport
, proto
);
232 unlink("/etc/upnp/delete");
236 static void tomato_helper(void)
240 if (stat("/etc/upnp/delete", &st
) == 0) {
244 if (stat("/etc/upnp/load", &st
) == 0) {
248 if (stat("/etc/upnp/save", &st
) == 0) {
249 tomato_save("/etc/upnp/data");
250 unlink("/etc/upnp/save");
253 if (stat("/etc/upnp/info", &st
) == 0) {
254 tomato_save("/etc/upnp/data.info");
255 unlink("/etc/upnp/info");
258 #endif /* 1 (tomato) */
261 /* OpenAndConfHTTPSocket() :
262 * setup the socket used to handle incoming HTTP connections. */
265 OpenAndConfHTTPSocket(unsigned short * port
, int ipv6
)
267 OpenAndConfHTTPSocket(unsigned short * port
)
273 struct sockaddr_in6 listenname6
;
274 struct sockaddr_in listenname4
;
276 struct sockaddr_in listenname
;
278 socklen_t listenname_len
;
282 ipv6
? PF_INET6
: PF_INET
,
288 if(s
< 0 && ipv6
&& errno
== EAFNOSUPPORT
)
290 /* the system doesn't support IPV6 */
291 syslog(LOG_WARNING
, "socket(PF_INET6, ...) failed with EAFNOSUPPORT, disabling IPv6");
292 SETFLAG(IPV6DISABLEDMASK
);
294 s
= socket(PF_INET
, SOCK_STREAM
, 0);
299 syslog(LOG_ERR
, "socket(http): %m");
303 if(setsockopt(s
, SOL_SOCKET
, SO_REUSEADDR
, &i
, sizeof(i
)) < 0)
305 syslog(LOG_WARNING
, "setsockopt(http, SO_REUSEADDR): %m");
308 /* enable this to force IPV6 only for IPV6 socket.
309 * see http://www.ietf.org/rfc/rfc3493.txt section 5.3 */
310 if(setsockopt(s
, IPPROTO_IPV6
, IPV6_V6ONLY
, &i
, sizeof(i
)) < 0)
312 syslog(LOG_WARNING
, "setsockopt(http, IPV6_V6ONLY): %m");
316 if(!set_non_blocking(s
))
318 syslog(LOG_WARNING
, "set_non_blocking(http): %m");
324 memset(&listenname6
, 0, sizeof(struct sockaddr_in6
));
325 listenname6
.sin6_family
= AF_INET6
;
326 listenname6
.sin6_port
= htons(*port
);
327 listenname6
.sin6_addr
= ipv6_bind_addr
;
328 listenname_len
= sizeof(struct sockaddr_in6
);
330 memset(&listenname4
, 0, sizeof(struct sockaddr_in
));
331 listenname4
.sin_family
= AF_INET
;
332 listenname4
.sin_port
= htons(*port
);
333 listenname4
.sin_addr
.s_addr
= htonl(INADDR_ANY
);
334 listenname_len
= sizeof(struct sockaddr_in
);
337 memset(&listenname
, 0, sizeof(struct sockaddr_in
));
338 listenname
.sin_family
= AF_INET
;
339 listenname
.sin_port
= htons(*port
);
340 listenname
.sin_addr
.s_addr
= htonl(INADDR_ANY
);
341 listenname_len
= sizeof(struct sockaddr_in
);
346 ipv6
? (struct sockaddr
*)&listenname6
: (struct sockaddr
*)&listenname4
,
349 if(bind(s
, (struct sockaddr
*)&listenname
, listenname_len
) < 0)
352 syslog(LOG_ERR
, "bind(http): %m");
359 syslog(LOG_ERR
, "listen(http): %m");
367 struct sockaddr_in6 sockinfo
;
368 socklen_t len
= sizeof(struct sockaddr_in6
);
369 if (getsockname(s
, (struct sockaddr
*)&sockinfo
, &len
) < 0) {
370 syslog(LOG_ERR
, "getsockname(): %m");
372 *port
= ntohs(sockinfo
.sin6_port
);
375 #endif /* ENABLE_IPV6 */
376 struct sockaddr_in sockinfo
;
377 socklen_t len
= sizeof(struct sockaddr_in
);
378 if (getsockname(s
, (struct sockaddr
*)&sockinfo
, &len
) < 0) {
379 syslog(LOG_ERR
, "getsockname(): %m");
381 *port
= ntohs(sockinfo
.sin_port
);
385 #endif /* ENABLE_IPV6 */
390 static struct upnphttp
*
391 ProcessIncomingHTTP(int shttpl
, const char * protocol
)
394 socklen_t clientnamelen
;
396 struct sockaddr_storage clientname
;
397 clientnamelen
= sizeof(struct sockaddr_storage
);
399 struct sockaddr_in clientname
;
400 clientnamelen
= sizeof(struct sockaddr_in
);
402 shttp
= accept(shttpl
, (struct sockaddr
*)&clientname
, &clientnamelen
);
405 /* ignore EAGAIN, EWOULDBLOCK, EINTR, we just try again later */
406 if(errno
!= EAGAIN
&& errno
!= EWOULDBLOCK
&& errno
!= EINTR
)
407 syslog(LOG_ERR
, "accept(http): %m");
411 struct upnphttp
* tmp
= 0;
414 sockaddr_to_string((struct sockaddr
*)&clientname
, addr_str
, sizeof(addr_str
));
415 syslog(LOG_INFO
, "%s connection from %s", protocol
, addr_str
);
416 if(get_lan_for_peer((struct sockaddr
*)&clientname
) == NULL
)
418 /* The peer is not a LAN ! */
420 "%s peer %s is not from a LAN, closing the connection",
426 /* Create a new upnphttp object and add it to
427 * the active upnphttp object list */
428 tmp
= New_upnphttp(shttp
);
432 if(clientname
.ss_family
== AF_INET
)
434 tmp
->clientaddr
= ((struct sockaddr_in
*)&clientname
)->sin_addr
;
436 else if(clientname
.ss_family
== AF_INET6
)
438 struct sockaddr_in6
* addr
= (struct sockaddr_in6
*)&clientname
;
439 if(IN6_IS_ADDR_V4MAPPED(&addr
->sin6_addr
))
441 memcpy(&tmp
->clientaddr
,
442 &addr
->sin6_addr
.s6_addr
[12],
448 memcpy(&tmp
->clientaddr_v6
,
450 sizeof(struct in6_addr
));
454 tmp
->clientaddr
= clientname
.sin_addr
;
460 syslog(LOG_ERR
, "New_upnphttp() failed");
468 #ifdef ENABLE_NFQUEUE
470 int identify_ip_protocol(char *payload
) {
476 * This function returns the destination port of the captured packet UDP
478 int get_udp_dst_port(char *payload
) {
479 char *pkt_data_ptr
= NULL
;
480 pkt_data_ptr
= payload
+ sizeof(struct ip
);
482 /* Cast the UDP Header from the raw packet */
483 struct udphdr
*udp
= (struct udphdr
*) pkt_data_ptr
;
485 /* get the dst port of the packet */
486 return(ntohs(udp
->dest
));
490 OpenAndConfNFqueue(){
492 struct nfq_q_handle
*myQueue
;
493 struct nfnl_handle
*netlinkHandle
;
497 inet_pton(AF_INET
, "239.255.255.250", &(ssdp
.sin_addr
));
499 /* Get a queue connection handle from the module */
500 if (!(nfqHandle
= nfq_open())) {
501 syslog(LOG_ERR
, "Error in nfq_open(): %m");
505 /* Unbind the handler from processing any IP packets
506 Not totally sure why this is done, or if it's necessary... */
507 if ((e
= nfq_unbind_pf(nfqHandle
, AF_INET
)) < 0) {
508 syslog(LOG_ERR
, "Error in nfq_unbind_pf(): %m");
512 /* Bind this handler to process IP packets... */
513 if (nfq_bind_pf(nfqHandle
, AF_INET
) < 0) {
514 syslog(LOG_ERR
, "Error in nfq_bind_pf(): %m");
518 /* Install a callback on queue -Q */
519 if (!(myQueue
= nfq_create_queue(nfqHandle
, nfqueue
, &nfqueue_cb
, NULL
))) {
520 syslog(LOG_ERR
, "Error in nfq_create_queue(): %m");
524 /* Turn on packet copy mode */
525 if (nfq_set_mode(myQueue
, NFQNL_COPY_PACKET
, 0xffff) < 0) {
526 syslog(LOG_ERR
, "Error setting packet copy mode (): %m");
530 netlinkHandle
= nfq_nfnlh(nfqHandle
);
531 fd
= nfnl_fd(netlinkHandle
);
538 static int nfqueue_cb(
539 struct nfq_q_handle
*qh
,
540 struct nfgenmsg
*nfmsg
,
541 struct nfq_data
*nfa
,
545 struct nfqnl_msg_packet_hdr
*ph
;
546 ph
= nfq_get_msg_packet_hdr(nfa
);
550 int id
= 0, size
= 0;
551 id
= ntohl(ph
->packet_id
);
553 size
= nfq_get_payload(nfa
, &pkt
);
555 struct ip
*iph
= (struct ip
*) pkt
;
557 int id_protocol
= identify_ip_protocol(pkt
);
559 int dport
= get_udp_dst_port(pkt
);
561 int x
= sizeof (struct ip
) + sizeof (struct udphdr
);
563 /* packets we are interested in are UDP multicast to 239.255.255.250:1900
564 * and start with a data string M-SEARCH
566 if ( (dport
== 1900) && (id_protocol
== IPPROTO_UDP
)
567 && (ssdp
.sin_addr
.s_addr
== iph
->ip_dst
.s_addr
) ) {
569 /* get the index that the packet came in on */
570 u_int32_t idx
= nfq_get_indev(nfa
);
572 for ( ;i
< n_nfqix
; i
++) {
573 if ( nfqix
[i
] == idx
) {
575 struct udphdr
*udp
= (struct udphdr
*) (pkt
+ sizeof(struct ip
));
579 struct sockaddr_in sendername
;
580 sendername
.sin_family
= AF_INET
;
581 sendername
.sin_port
= udp
->source
;
582 sendername
.sin_addr
.s_addr
= iph
->ip_src
.s_addr
;
584 /* printf("pkt found %s\n",dd);*/
585 ProcessSSDPData (sudp
, dd
, size
- x
,
586 &sendername
, (unsigned short) 5555);
591 nfq_set_verdict(qh
, id
, NF_ACCEPT
, 0, NULL
);
594 syslog(LOG_ERR
,"nfq_get_msg_packet_hdr failed");
596 /* from nfqueue source: 0 = ok, >0 = soft error, <0 hard error */
602 static void ProcessNFQUEUE(int fd
){
606 struct sockaddr_in sendername
;
607 len_r
= sizeof(struct sockaddr_in
);
609 int res
= recvfrom(fd
, buf
, sizeof(buf
), 0,
610 (struct sockaddr
*)&sendername
, &len_r
);
612 nfq_handle_packet(nfqHandle
, buf
, res
);
616 /* Functions used to communicate with miniupnpdctl */
617 #ifdef USE_MINIUPNPDCTL
619 OpenAndConfCtlUnixSocket(const char * path
)
621 struct sockaddr_un localun
;
623 s
= socket(AF_UNIX
, SOCK_STREAM
, 0);
624 localun
.sun_family
= AF_UNIX
;
625 strncpy(localun
.sun_path
, path
,
626 sizeof(localun
.sun_path
));
627 if(bind(s
, (struct sockaddr
*)&localun
,
628 sizeof(struct sockaddr_un
)) < 0)
630 syslog(LOG_ERR
, "bind(sctl): %m");
634 else if(listen(s
, 5) < 0)
636 syslog(LOG_ERR
, "listen(sctl): %m");
644 write_upnphttp_details(int fd
, struct upnphttp
* e
)
648 write(fd
, "HTTP :\n", 7);
651 len
= snprintf(buffer
, sizeof(buffer
),
652 "%d %d %s req_buf=%p(%dbytes) res_buf=%p(%dbytes alloc)\n",
653 e
->socket
, e
->state
, e
->HttpVer
,
654 e
->req_buf
, e
->req_buflen
,
655 e
->res_buf
, e
->res_buf_alloclen
);
656 write(fd
, buffer
, len
);
657 e
= e
->entries
.le_next
;
662 write_ctlsockets_list(int fd
, struct ctlelem
* e
)
666 write(fd
, "CTL :\n", 6);
669 len
= snprintf(buffer
, sizeof(buffer
),
670 "struct ctlelem: socket=%d\n", e
->socket
);
671 write(fd
, buffer
, len
);
672 e
= e
->entries
.le_next
;
676 #ifndef DISABLE_CONFIG_FILE
678 write_option_list(int fd
)
683 write(fd
, "Options :\n", 10);
684 for(i
=0; i
<num_options
; i
++)
686 len
= snprintf(buffer
, sizeof(buffer
),
688 ary_options
[i
].id
, ary_options
[i
].value
);
689 write(fd
, buffer
, len
);
695 write_command_line(int fd
, int argc
, char * * argv
)
700 write(fd
, "Command Line :\n", 15);
701 for(i
=0; i
<argc
; i
++)
703 len
= snprintf(buffer
, sizeof(buffer
),
706 write(fd
, buffer
, len
);
712 /* Handler for the SIGTERM signal (kill)
713 * SIGINT is also handled */
718 /*int save_errno = errno; */
719 /*signal(sig, SIG_IGN);*/ /* Ignore this signal while we are quitting */
720 /* Note : isn't it useless ? */
723 /* calling syslog() is forbidden in signal handler according to
725 syslog(LOG_NOTICE
, "received signal %d, good-bye", sig
);
729 /*errno = save_errno;*/
732 /* Handler for the SIGUSR1 signal indicating public IP address change. */
738 /* calling syslog() is forbidden in signal handler according to
740 syslog(LOG_INFO
, "received signal %d, public ip address change", sig
);
743 should_send_public_address_change_notif
= 1;
746 /* record the startup time, for returning uptime */
748 set_startup_time(int sysuptime
)
750 startup_time
= time(NULL
);
751 #ifdef USE_TIME_AS_BOOTID
752 if(startup_time
> 60*60*24 && upnp_bootid
== 1) {
753 /* We know we are not January the 1st 1970 */
754 upnp_bootid
= (unsigned int)startup_time
;
756 * A convenient mechanism is to set this field value to the time
757 * that the device sends its initial announcement, expressed as
758 * seconds elapsed since midnight January 1, 1970; */
760 #endif /* USE_TIME_AS_BOOTID */
763 /* use system uptime instead of daemon uptime */
764 #if defined(__linux__)
767 fd
= open("/proc/uptime", O_RDONLY
);
770 syslog(LOG_ERR
, "open(\"/proc/uptime\" : %m");
774 memset(buff
, 0, sizeof(buff
));
775 if(read(fd
, buff
, sizeof(buff
) - 1) < 0)
777 syslog(LOG_ERR
, "read(\"/proc/uptime\" : %m");
782 syslog(LOG_INFO
, "system uptime is %d seconds", uptime
);
785 startup_time
-= uptime
;
787 #elif defined(SOLARIS_KSTATS)
793 ksp
= kstat_lookup(kc
, "unix", 0, "system_misc");
794 if(ksp
&& (kstat_read(kc
, ksp
, NULL
) != -1))
796 void *ptr
= kstat_data_lookup(ksp
, "boot_time");
798 memcpy(&startup_time
, ptr
, sizeof(startup_time
));
800 syslog(LOG_ERR
, "cannot find boot_time kstat");
803 syslog(LOG_ERR
, "cannot open kstats for unix/0/system_misc: %m");
807 struct timeval boottime
;
808 size_t size
= sizeof(boottime
);
809 int name
[2] = { CTL_KERN
, KERN_BOOTTIME
};
810 if(sysctl(name
, 2, &boottime
, &size
, NULL
, 0) < 0)
812 syslog(LOG_ERR
, "sysctl(\"kern.boottime\") failed");
816 startup_time
= boottime
.tv_sec
;
822 /* structure containing variables used during "main loop"
823 * that are filled during the init */
824 struct runtime_vars
{
825 /* LAN IP addresses for SSDP traffic and HTTP */
826 /* moved to global vars */
827 int port
; /* HTTP Port */
829 int https_port
; /* HTTPS Port */
831 int notify_interval
; /* seconds between SSDP announces */
832 /* unused rules cleaning related variables : */
833 int clean_ruleset_threshold
; /* threshold for removing unused rules */
834 int clean_ruleset_interval
; /* (minimum) interval between checks */
838 * parse address with mask
839 * ex: 192.168.1.1/24 or 192.168.1.1/255.255.255.0
840 * When MULTIPLE_EXTERNAL_IP is enabled, the ip address of the
841 * external interface associated with the lan subnet follows.
842 * ex : 192.168.1.1/24 81.21.41.11
844 * Can also use the interface name (ie eth0)
850 parselanaddr(struct lan_addr_s
* lan_addr
, const char * str
)
856 memset(lan_addr
, 0, sizeof(struct lan_addr_s
));
858 while(*p
&& *p
!= '/' && !isspace(*p
))
861 if(!isdigit(str
[0]) && n
< (int)sizeof(lan_addr
->ifname
))
863 /* not starting with a digit : suppose it is an interface name */
864 memcpy(lan_addr
->ifname
, str
, n
);
865 lan_addr
->ifname
[n
] = '\0';
866 if(getifaddr(lan_addr
->ifname
, lan_addr
->str
, sizeof(lan_addr
->str
),
867 &lan_addr
->addr
, &lan_addr
->mask
) < 0) {
869 fprintf(stderr
, "interface \"%s\" has no IPv4 address\n", str
);
870 lan_addr
->str
[0] = '\0';
871 lan_addr
->addr
.s_addr
= htonl(0x00000000u
);
872 lan_addr
->mask
.s_addr
= htonl(0xffffffffu
);
873 #else /* ENABLE_IPV6 */
875 #endif /* ENABLE_IPV6 */
877 /*printf("%s => %s\n", lan_addr->ifname, lan_addr->str);*/
883 memcpy(lan_addr
->str
, str
, n
);
884 lan_addr
->str
[n
] = '\0';
885 if(!inet_aton(lan_addr
->str
, &lan_addr
->addr
))
890 const char * q
= ++p
;
891 while(*p
&& isdigit(*p
))
895 /* parse mask in /255.255.255.0 format */
896 while(*p
&& (*p
=='.' || isdigit(*p
)))
903 if(!inet_aton(tmp
, &lan_addr
->mask
))
908 /* it is a /24 format */
910 if(nbits
> 32 || nbits
< 0)
912 lan_addr
->mask
.s_addr
= htonl(nbits
? (0xffffffffu
<< (32 - nbits
)) : 0);
915 else if(lan_addr
->mask
.s_addr
== 0)
917 /* by default, networks are /24 */
918 lan_addr
->mask
.s_addr
= htonl(0xffffff00u
);
920 #ifdef MULTIPLE_EXTERNAL_IP
922 while(*p
&& isspace(*p
))
925 /* parse the exteral ip address to associate with this subnet */
927 while(p
[n
] && !isspace(*p
))
930 memcpy(lan_addr
->ext_ip_str
, p
, n
);
931 lan_addr
->ext_ip_str
[n
] = '\0';
932 if(!inet_aton(lan_addr
->ext_ip_str
, &lan_addr
->ext_ip_addr
)) {
934 fprintf(stderr
, "Error parsing address : %s\n", lan_addr
->ext_ip_str
);
940 if(lan_addr
->ifname
[0] != '\0')
942 lan_addr
->index
= if_nametoindex(lan_addr
->ifname
);
943 if(lan_addr
->index
== 0)
944 fprintf(stderr
, "Cannot get index for network interface %s",
950 "Error: please specify LAN network interface by name instead of IPv4 address : %s\n",
957 fprintf(stderr
, "Error parsing address/mask (or interface name) : %s\n",
962 /* fill uuidvalue_wan and uuidvalue_wcd based on uuidvalue_igd */
963 void complete_uuidvalues(void)
966 len
= strlen(uuidvalue_igd
);
967 memcpy(uuidvalue_wan
, uuidvalue_igd
, len
+1);
968 switch(uuidvalue_wan
[len
-1]) {
970 uuidvalue_wan
[len
-1] = 'a';
973 uuidvalue_wan
[len
-1] = '0';
976 uuidvalue_wan
[len
-1]++;
978 memcpy(uuidvalue_wcd
, uuidvalue_wan
, len
+1);
979 switch(uuidvalue_wcd
[len
-1]) {
981 uuidvalue_wcd
[len
-1] = 'a';
984 uuidvalue_wcd
[len
-1] = '0';
987 uuidvalue_wcd
[len
-1]++;
992 * 1) read configuration file
993 * 2) read command line arguments
996 * 5) check and write pid file
997 * 6) set startup time stamp
998 * 7) compute presentation URL
999 * 8) set signal handlers
1000 * 9) init random generator (srandom())
1001 * 10) init redirection engine
1002 * 11) reload mapping from leasefile */
1004 init(int argc
, char * * argv
, struct runtime_vars
* v
)
1010 struct sigaction sa
;
1011 /*const char * logfilename = 0;*/
1012 const char * presurl
= 0;
1013 #ifndef DISABLE_CONFIG_FILE
1014 int options_flag
= 0;
1015 const char * optionsfile
= DEFAULT_CONFIG
;
1016 #endif /* DISABLE_CONFIG_FILE */
1017 struct lan_addr_s
* lan_addr
;
1018 struct lan_addr_s
* lan_addr2
;
1020 /* only print usage if -h is used */
1021 for(i
=1; i
<argc
; i
++)
1023 if(0 == strcmp(argv
[i
], "-h"))
1026 #ifndef DISABLE_CONFIG_FILE
1027 /* first check if "-f" option is used */
1028 for(i
=2; i
<argc
; i
++)
1030 if(0 == strcmp(argv
[i
-1], "-f"))
1032 optionsfile
= argv
[i
];
1037 #endif /* DISABLE_CONFIG_FILE */
1039 /* set initial values */
1040 SETFLAG(ENABLEUPNPMASK
); /* UPnP is enabled by default */
1042 ipv6_bind_addr
= in6addr_any
;
1043 #endif /* ENABLE_IPV6 */
1045 LIST_INIT(&lan_addrs
);
1050 v
->notify_interval
= 30; /* seconds between SSDP announces */
1051 v
->clean_ruleset_threshold
= 20;
1052 v
->clean_ruleset_interval
= 0; /* interval between ruleset check. 0=disabled */
1053 #ifndef DISABLE_CONFIG_FILE
1054 /* read options file first since
1055 * command line arguments have final say */
1056 if(readoptionsfile(optionsfile
) < 0)
1058 /* only error if file exists or using -f */
1059 if(access(optionsfile
, F_OK
) == 0 || options_flag
)
1060 fprintf(stderr
, "Error reading configuration file %s\n", optionsfile
);
1064 for(i
=0; i
<(int)num_options
; i
++)
1066 switch(ary_options
[i
].id
)
1068 case UPNPEXT_IFNAME
:
1069 ext_if_name
= ary_options
[i
].value
;
1072 use_ext_ip_addr
= ary_options
[i
].value
;
1074 case UPNPLISTENING_IP
:
1075 lan_addr
= (struct lan_addr_s
*) malloc(sizeof(struct lan_addr_s
));
1076 if (lan_addr
== NULL
)
1078 fprintf(stderr
, "malloc(sizeof(struct lan_addr_s)): %m");
1081 if(parselanaddr(lan_addr
, ary_options
[i
].value
) != 0)
1083 fprintf(stderr
, "can't parse \"%s\" as a valid "
1087 "interface name\n", ary_options
[i
].value
);
1091 LIST_INSERT_HEAD(&lan_addrs
, lan_addr
, list
);
1094 case UPNPIPV6_LISTENING_IP
:
1095 if (inet_pton(AF_INET6
, ary_options
[i
].value
, &ipv6_bind_addr
) < 1)
1097 fprintf(stderr
, "can't parse \"%s\" as valid IPv6 listening address", ary_options
[i
].value
);
1100 #endif /* ENABLE_IPV6 */
1102 v
->port
= atoi(ary_options
[i
].value
);
1106 v
->https_port
= atoi(ary_options
[i
].value
);
1109 case UPNPBITRATE_UP
:
1110 upstream_bitrate
= strtoul(ary_options
[i
].value
, 0, 0);
1112 case UPNPBITRATE_DOWN
:
1113 downstream_bitrate
= strtoul(ary_options
[i
].value
, 0, 0);
1115 case UPNPPRESENTATIONURL
:
1116 presurl
= ary_options
[i
].value
;
1118 #ifdef ENABLE_MANUFACTURER_INFO_CONFIGURATION
1119 case UPNPFRIENDLY_NAME
:
1120 strncpy(friendly_name
, ary_options
[i
].value
, FRIENDLY_NAME_MAX_LEN
);
1121 friendly_name
[FRIENDLY_NAME_MAX_LEN
-1] = '\0';
1123 case UPNPMANUFACTURER_NAME
:
1124 strncpy(manufacturer_name
, ary_options
[i
].value
, MANUFACTURER_NAME_MAX_LEN
);
1125 manufacturer_name
[MANUFACTURER_NAME_MAX_LEN
-1] = '\0';
1127 case UPNPMANUFACTURER_URL
:
1128 strncpy(manufacturer_url
, ary_options
[i
].value
, MANUFACTURER_URL_MAX_LEN
);
1129 manufacturer_url
[MANUFACTURER_URL_MAX_LEN
-1] = '\0';
1131 case UPNPMODEL_NAME
:
1132 strncpy(model_name
, ary_options
[i
].value
, MODEL_NAME_MAX_LEN
);
1133 model_name
[MODEL_NAME_MAX_LEN
-1] = '\0';
1135 case UPNPMODEL_DESCRIPTION
:
1136 strncpy(model_description
, ary_options
[i
].value
, MODEL_DESCRIPTION_MAX_LEN
);
1137 model_description
[MODEL_DESCRIPTION_MAX_LEN
-1] = '\0';
1140 strncpy(model_url
, ary_options
[i
].value
, MODEL_URL_MAX_LEN
);
1141 model_url
[MODEL_URL_MAX_LEN
-1] = '\0';
1144 #ifdef USE_NETFILTER
1145 case UPNPFORWARDCHAIN
:
1146 miniupnpd_forward_chain
= ary_options
[i
].value
;
1149 miniupnpd_nat_chain
= ary_options
[i
].value
;
1152 case UPNPNOTIFY_INTERVAL
:
1153 v
->notify_interval
= atoi(ary_options
[i
].value
);
1155 case UPNPSYSTEM_UPTIME
:
1156 if(strcmp(ary_options
[i
].value
, "yes") == 0)
1157 SETFLAG(SYSUPTIMEMASK
); /*sysuptime = 1;*/
1159 #if defined(USE_PF) || defined(USE_IPF)
1160 case UPNPPACKET_LOG
:
1161 if(strcmp(ary_options
[i
].value
, "yes") == 0)
1162 SETFLAG(LOGPACKETSMASK
); /*logpackets = 1;*/
1166 strncpy(uuidvalue_igd
+5, ary_options
[i
].value
,
1167 strlen(uuidvalue_igd
+5) + 1);
1168 complete_uuidvalues();
1171 strncpy(serialnumber
, ary_options
[i
].value
, SERIALNUMBER_MAX_LEN
);
1172 serialnumber
[SERIALNUMBER_MAX_LEN
-1] = '\0';
1174 case UPNPMODEL_NUMBER
:
1175 strncpy(modelnumber
, ary_options
[i
].value
, MODELNUMBER_MAX_LEN
);
1176 modelnumber
[MODELNUMBER_MAX_LEN
-1] = '\0';
1178 case UPNPCLEANTHRESHOLD
:
1179 v
->clean_ruleset_threshold
= atoi(ary_options
[i
].value
);
1181 case UPNPCLEANINTERVAL
:
1182 v
->clean_ruleset_interval
= atoi(ary_options
[i
].value
);
1186 anchor_name
= ary_options
[i
].value
;
1189 queue
= ary_options
[i
].value
;
1192 tag
= ary_options
[i
].value
;
1195 #ifdef ENABLE_NATPMP
1196 case UPNPENABLENATPMP
:
1197 if(strcmp(ary_options
[i
].value
, "yes") == 0)
1198 SETFLAG(ENABLENATPMPMASK
); /*enablenatpmp = 1;*/
1200 if(atoi(ary_options
[i
].value
))
1201 SETFLAG(ENABLENATPMPMASK
);
1202 /*enablenatpmp = atoi(ary_options[i].value);*/
1206 case UPNPPCPMINLIFETIME
:
1207 min_lifetime
= atoi(ary_options
[i
].value
);
1208 if (min_lifetime
> 120 ) {
1212 case UPNPPCPMAXLIFETIME
:
1213 max_lifetime
= atoi(ary_options
[i
].value
);
1214 if (max_lifetime
> 86400 ) {
1215 max_lifetime
= 86400;
1218 case UPNPPCPALLOWTHIRDPARTY
:
1219 if(strcmp(ary_options
[i
].value
, "yes") == 0)
1220 SETFLAG(PCP_ALLOWTHIRDPARTYMASK
);
1223 #ifdef PF_ENABLE_FILTER_RULES
1224 case UPNPQUICKRULES
:
1225 if(strcmp(ary_options
[i
].value
, "no") == 0)
1226 SETFLAG(PFNOQUICKRULESMASK
);
1230 if(strcmp(ary_options
[i
].value
, "yes") != 0)
1231 CLEARFLAG(ENABLEUPNPMASK
);
1233 case UPNPSECUREMODE
:
1234 if(strcmp(ary_options
[i
].value
, "yes") == 0)
1235 SETFLAG(SECUREMODEMASK
);
1237 #ifdef ENABLE_LEASEFILE
1239 lease_file
= ary_options
[i
].value
;
1242 case UPNPMINISSDPDSOCKET
:
1243 minissdpdsocketpath
= ary_options
[i
].value
;
1246 fprintf(stderr
, "Unknown option in file %s\n",
1251 /* if lifetimes are inverse */
1252 if (min_lifetime
>= max_lifetime
) {
1253 fprintf(stderr
, "Minimum lifetime (%lu) is greater than or equal to maximum lifetime (%lu).\n", min_lifetime
, max_lifetime
);
1254 fprintf(stderr
, "Check your configuration file.\n");
1259 #endif /* DISABLE_CONFIG_FILE */
1261 /* command line arguments processing */
1262 for(i
=1; i
<argc
; i
++)
1266 fprintf(stderr
, "Unknown option: %s\n", argv
[i
]);
1268 else switch(argv
[i
][1])
1272 upnp_bootid
= (unsigned int)strtoul(argv
[++i
], NULL
, 10);
1274 fprintf(stderr
, "Option -%c takes one argument.\n", argv
[i
][1]);
1278 use_ext_ip_addr
= argv
[++i
];
1280 fprintf(stderr
, "Option -%c takes one argument.\n", argv
[i
][1]);
1284 v
->notify_interval
= atoi(argv
[++i
]);
1286 fprintf(stderr
, "Option -%c takes one argument.\n", argv
[i
][1]);
1290 v
->clean_ruleset_interval
= atoi(argv
[++i
]);
1292 fprintf(stderr
, "Option -%c takes one argument.\n", argv
[i
][1]);
1296 strncpy(uuidvalue_igd
+5, argv
[++i
], strlen(uuidvalue_igd
+5) + 1);
1297 complete_uuidvalues();
1299 fprintf(stderr
, "Option -%c takes one argument.\n", argv
[i
][1]);
1301 #ifdef ENABLE_MANUFACTURER_INFO_CONFIGURATION
1304 strncpy(friendly_name
, argv
[++i
], FRIENDLY_NAME_MAX_LEN
);
1306 fprintf(stderr
, "Option -%c takes one argument.\n", argv
[i
][1]);
1307 friendly_name
[FRIENDLY_NAME_MAX_LEN
-1] = '\0';
1312 strncpy(serialnumber
, argv
[++i
], SERIALNUMBER_MAX_LEN
);
1314 fprintf(stderr
, "Option -%c takes one argument.\n", argv
[i
][1]);
1315 serialnumber
[SERIALNUMBER_MAX_LEN
-1] = '\0';
1319 strncpy(modelnumber
, argv
[++i
], MODELNUMBER_MAX_LEN
);
1321 fprintf(stderr
, "Option -%c takes one argument.\n", argv
[i
][1]);
1322 modelnumber
[MODELNUMBER_MAX_LEN
-1] = '\0';
1324 #ifdef ENABLE_NATPMP
1326 /*enablenatpmp = 1;*/
1327 SETFLAG(ENABLENATPMPMASK
);
1332 SETFLAG(SYSUPTIMEMASK
);
1335 logfilename = argv[++i];
1337 #if defined(USE_PF) || defined(USE_IPF)
1340 SETFLAG(LOGPACKETSMASK
);
1344 SETFLAG(SECUREMODEMASK
);
1348 ext_if_name
= argv
[++i
];
1350 fprintf(stderr
, "Option -%c takes one argument.\n", argv
[i
][1]);
1357 fprintf(stderr
, "Option -%c takes one argument.\n", argv
[i
][1]);
1363 fprintf(stderr
, "Option -%c takes one argument.\n", argv
[i
][1]);
1368 v
->port
= atoi(argv
[++i
]);
1370 fprintf(stderr
, "Option -%c takes one argument.\n", argv
[i
][1]);
1375 v
->https_port
= atoi(argv
[++i
]);
1377 fprintf(stderr
, "Option -%c takes one argument.\n", argv
[i
][1]);
1380 #ifdef ENABLE_NFQUEUE
1384 nfqueue
= atoi(argv
[++i
]);
1387 fprintf(stderr
, "Option -%c takes one argument.\n", argv
[i
][1]);
1392 if(n_nfqix
< MAX_LAN_ADDR
) {
1393 nfqix
[n_nfqix
++] = if_nametoindex(argv
[i
]);
1395 fprintf(stderr
,"Too many nfq interfaces. Ignoring %s\n", argv
[i
]);
1398 fprintf(stderr
, "Option -%c takes one argument.\n", argv
[i
][1]);
1404 pidfilename
= argv
[++i
];
1406 fprintf(stderr
, "Option -%c takes one argument.\n", argv
[i
][1]);
1413 presurl
= argv
[++i
];
1415 fprintf(stderr
, "Option -%c takes one argument.\n", argv
[i
][1]);
1420 downstream_bitrate
= strtoul(argv
[++i
], 0, 0);
1421 upstream_bitrate
= strtoul(argv
[++i
], 0, 0);
1424 fprintf(stderr
, "Option -%c takes two arguments.\n", argv
[i
][1]);
1427 #ifndef MULTIPLE_EXTERNAL_IP
1431 lan_addr
= (struct lan_addr_s
*) malloc(sizeof(struct lan_addr_s
));
1432 if (lan_addr
== NULL
)
1434 fprintf(stderr
, "malloc(sizeof(struct lan_addr_s)): %m");
1437 if(parselanaddr(lan_addr
, argv
[i
]) != 0)
1439 fprintf(stderr
, "can't parse \"%s\" as a valid "
1443 "interface name\n", argv
[i
]);
1447 /* check if we already have this address */
1448 for(lan_addr2
= lan_addrs
.lh_first
; lan_addr2
!= NULL
; lan_addr2
= lan_addr2
->list
.le_next
)
1450 if (0 == strncmp(lan_addr2
->str
, lan_addr
->str
, 15))
1453 if (lan_addr2
== NULL
)
1454 LIST_INSERT_HEAD(&lan_addrs
, lan_addr
, list
);
1457 fprintf(stderr
, "Option -%c takes one argument.\n", argv
[i
][1]);
1461 char *val
=calloc((strlen(argv
[i
+1]) + strlen(argv
[i
+2]) + 1), sizeof(char));
1464 fprintf(stderr
, "memory allocation error for listen address storage\n");
1467 sprintf(val
, "%s %s", argv
[i
+1], argv
[i
+2]);
1469 lan_addr
= (struct lan_addr_s
*) malloc(sizeof(struct lan_addr_s
));
1470 if (lan_addr
== NULL
)
1472 fprintf(stderr
, "malloc(sizeof(struct lan_addr_s)): %m");
1476 if(parselanaddr(lan_addr
, val
) != 0)
1478 fprintf(stderr
, "can't parse \"%s\" as a valid LAN address or interface name\n", val
);
1483 /* check if we already have this address */
1484 for(lan_addr2
= lan_addrs
.lh_first
; lan_addr2
!= NULL
; lan_addr2
= lan_addr2
->list
.le_next
)
1486 if (0 == strncmp(lan_addr2
->str
, lan_addr
->str
, 15))
1489 if (lan_addr2
== NULL
)
1490 LIST_INSERT_HEAD(&lan_addrs
, lan_addr
, list
);
1496 fprintf(stderr
, "Option -%c takes two arguments.\n", argv
[i
][1]);
1502 tmp
= realloc(upnppermlist
, sizeof(struct upnpperm
) * (num_upnpperm
+1));
1504 fprintf(stderr
, "memory allocation error for permission\n");
1507 if(read_permission_line(upnppermlist
+ num_upnpperm
, argv
[++i
]) >= 0) {
1510 fprintf(stderr
, "Permission rule parsing error :\n%s\n", argv
[i
]);
1514 fprintf(stderr
, "Option -%c takes one argument.\n", argv
[i
][1]);
1517 i
++; /* discarding, the config file is already read */
1520 fprintf(stderr
, "Unknown option: %s\n", argv
[i
]);
1523 if(!ext_if_name
|| !lan_addrs
.lh_first
)
1525 /* bad configuration */
1536 if(daemon(0, 0)<0) {
1545 openlog_option
= LOG_PID
|LOG_CONS
;
1548 openlog_option
|= LOG_PERROR
; /* also log on stderr */
1551 openlog("miniupnpd", openlog_option
, LOG_MINIUPNPD
);
1555 /* speed things up and ignore LOG_INFO and LOG_DEBUG */
1556 setlogmask(LOG_UPTO(LOG_NOTICE
));
1559 if(checkforrunning(pidfilename
) < 0)
1561 syslog(LOG_ERR
, "MiniUPnPd is already running. EXITING");
1565 syslog(LOG_NOTICE
, "version " MINIUPNPD_VERSION
" started");
1567 set_startup_time(GETFLAG(SYSUPTIMEMASK
));
1569 /* presentation url */
1572 strncpy(presentationurl
, presurl
, PRESENTATIONURL_MAX_LEN
);
1573 presentationurl
[PRESENTATIONURL_MAX_LEN
-1] = '\0';
1577 snprintf(presentationurl
, PRESENTATIONURL_MAX_LEN
,
1578 "http://%s/", lan_addrs
.lh_first
->str
);
1579 /*"http://%s:%d/", lan_addrs.lh_first->str, 80);*/
1582 /* set signal handler */
1583 memset(&sa
, 0, sizeof(struct sigaction
));
1584 sa
.sa_handler
= sigterm
;
1586 if(sigaction(SIGTERM
, &sa
, NULL
) < 0)
1588 syslog(LOG_ERR
, "Failed to set %s handler. EXITING", "SIGTERM");
1591 if(sigaction(SIGINT
, &sa
, NULL
) < 0)
1593 syslog(LOG_ERR
, "Failed to set %s handler. EXITING", "SIGINT");
1598 sa
.sa_handler
= sigusr2
;
1599 sigaction(SIGUSR2
, &sa
, NULL
);
1601 if(signal(SIGPIPE
, SIG_IGN
) == SIG_ERR
)
1603 syslog(LOG_ERR
, "Failed to ignore SIGPIPE signals");
1606 sa
.sa_handler
= sigusr1
;
1607 if(sigaction(SIGUSR1
, &sa
, NULL
) < 0)
1609 syslog(LOG_NOTICE
, "Failed to set %s handler", "SIGUSR1");
1612 /* initialize random number generator */
1613 srandom((unsigned int)time(NULL
));
1615 /* initialize redirection engine (and pinholes) */
1616 if(init_redirect() < 0)
1618 syslog(LOG_ERR
, "Failed to init redirection engine. EXITING");
1621 #ifdef ENABLE_UPNPPINHOLE
1622 #ifdef USE_NETFILTER
1627 if(writepidfile(pidfilename
, pid
) < 0)
1630 #ifdef ENABLE_LEASEFILE
1631 /*remove(lease_file);*/
1632 syslog(LOG_INFO
, "Reloading rules from lease file");
1633 reload_from_lease_file();
1635 tomato_load(); // zzz
1639 fprintf(stderr
, "Usage:\n\t"
1641 #ifndef DISABLE_CONFIG_FILE
1644 "[-i ext_ifname] [-o ext_ip]\n"
1645 #ifndef MULTIPLE_EXTERNAL_IP
1646 "\t\t[-a listening_ip]"
1648 "\t\t[-a listening_ip ext_ip]"
1654 #if defined(USE_PF) || defined(USE_IPF)
1658 #ifdef ENABLE_NATPMP
1662 /*"[-l logfile] " not functionnal */
1663 "\t\t[-u uuid] [-s serial] [-m model_number] \n"
1664 "\t\t[-t notify_interval] [-P pid_filename] "
1665 #ifdef ENABLE_MANUFACTURER_INFO_CONFIGURATION
1668 "\n\t\t[-B down up] [-w url] [-r clean_ruleset_interval]\n"
1670 "\t\t[-q queue] [-T tag]\n"
1672 #ifdef ENABLE_NFQUEUE
1673 "\t\t[-Q queue] [-n name]\n"
1675 "\t\t[-A \"permission rule\"] [-b BOOTID]\n"
1676 "\nNotes:\n\tThere can be one or several listening_ips.\n"
1677 "\tNotify interval is in seconds. Default is 30 seconds.\n"
1678 "\tDefault pid file is '%s'.\n"
1679 "\tDefault config file is '%s'.\n"
1680 "\tWith -d miniupnpd will run as a standard program.\n"
1681 #if defined(USE_PF) || defined(USE_IPF)
1682 "\t-L sets packet log in pf and ipf on.\n"
1684 "\t-S sets \"secure\" mode : clients can only add mappings to their own ip\n"
1685 "\t-U causes miniupnpd to report system uptime instead "
1686 "of daemon uptime.\n"
1687 #ifdef ENABLE_NATPMP
1688 "\t-N enables NAT-PMP functionality.\n"
1690 "\t-B sets bitrates reported by daemon in bits per second.\n"
1691 "\t-w sets the presentation url. Default is http address on port 80\n"
1693 "\t-q sets the ALTQ queue in pf.\n"
1694 "\t-T sets the tag name in pf.\n"
1696 #ifdef ENABLE_NFQUEUE
1697 "\t-Q sets the queue number that is used by NFQUEUE.\n"
1698 "\t-n sets the name of the interface(s) that packets will arrive on.\n"
1700 "\t-A use following syntax for permission rules :\n"
1701 "\t (allow|deny) (external port range) ip/mask (internal port range)\n"
1703 "\t \"allow 1024-65535 192.168.1.0/24 1024-65535\"\n"
1704 "\t \"deny 0-65535 0.0.0.0/0 0-65535\"\n"
1705 "\t-b sets the value of BOOTID.UPNP.ORG SSDP header\n"
1706 "\t-h prints this help and quits.\n"
1707 "", argv
[0], pidfilename
, DEFAULT_CONFIG
);
1712 /* process HTTP or SSDP requests */
1714 main(int argc
, char * * argv
)
1717 int shttpl
= -1; /* socket for HTTP */
1718 #if defined(V6SOCKETS_ARE_V6ONLY) && defined(ENABLE_IPV6)
1719 int shttpl_v4
= -1; /* socket for HTTP (ipv4 only) */
1722 int shttpsl
= -1; /* socket for HTTPS */
1723 #if defined(V6SOCKETS_ARE_V6ONLY) && defined(ENABLE_IPV6)
1724 int shttpsl_v4
= -1; /* socket for HTTPS (ipv4 only) */
1726 #endif /* ENABLE_HTTPS */
1727 int sudp
= -1; /* IP v4 socket for receiving SSDP */
1729 int sudpv6
= -1; /* IP v6 socket for receiving SSDP */
1731 #ifdef ENABLE_NATPMP
1732 int * snatpmp
= NULL
; /* also used for PCP */
1734 #if defined(ENABLE_IPV6) && defined(ENABLE_PCP)
1737 #ifdef ENABLE_NFQUEUE
1740 #ifdef USE_IFACEWATCHER
1741 int sifacewatcher
= -1;
1744 int * snotify
= NULL
;
1746 LIST_HEAD(httplisthead
, upnphttp
) upnphttphead
;
1747 struct upnphttp
* e
= 0;
1748 struct upnphttp
* next
;
1749 fd_set readset
; /* for select() */
1751 struct timeval timeout
, timeofday
, lasttimeofday
= {0, 0};
1753 #ifdef USE_MINIUPNPDCTL
1755 LIST_HEAD(ctlstructhead
, ctlelem
) ctllisthead
;
1756 struct ctlelem
* ectl
;
1757 struct ctlelem
* ectlnext
;
1759 struct runtime_vars v
;
1760 /* variables used for the unused-rule cleanup process */
1761 struct rule_state
* rule_list
= 0;
1762 struct timeval checktime
= {0, 0};
1763 struct lan_addr_s
* lan_addr
;
1764 #ifdef ENABLE_UPNPPINHOLE
1765 unsigned int next_pinhole_ts
;
1768 if(init(argc
, argv
, &v
) != 0)
1773 #endif /* ENABLE_HTTPS */
1774 /* count lan addrs */
1776 for(lan_addr
= lan_addrs
.lh_first
; lan_addr
!= NULL
; lan_addr
= lan_addr
->list
.le_next
)
1778 if(addr_count
> 0) {
1780 snotify
= calloc(addr_count
, sizeof(int));
1782 /* one for IPv4, one for IPv6 */
1783 snotify
= calloc(addr_count
* 2, sizeof(int));
1786 #ifdef ENABLE_NATPMP
1787 if(addr_count
> 0) {
1788 snatpmp
= malloc(addr_count
* sizeof(int));
1789 for(i
= 0; i
< addr_count
; i
++)
1794 LIST_INIT(&upnphttphead
);
1795 #ifdef USE_MINIUPNPDCTL
1796 LIST_INIT(&ctllisthead
);
1800 #ifdef ENABLE_NATPMP
1801 !GETFLAG(ENABLENATPMPMASK
) &&
1803 !GETFLAG(ENABLEUPNPMASK
) ) {
1804 syslog(LOG_ERR
, "Why did you run me anyway?");
1808 syslog(LOG_INFO
, "version " MINIUPNPD_VERSION
" starting%s%sext if %s BOOTID=%u",
1809 #ifdef ENABLE_NATPMP
1811 GETFLAG(ENABLENATPMPMASK
) ? " NAT-PMP/PCP " : " ",
1813 GETFLAG(ENABLENATPMPMASK
) ? " NAT-PMP " : " ",
1818 GETFLAG(ENABLEUPNPMASK
) ? "UPnP-IGD " : "",
1819 ext_if_name
, upnp_bootid
);
1821 if(GETFLAG(ENABLEUPNPMASK
))
1823 unsigned short listen_port
;
1824 listen_port
= (v
.port
> 0) ? v
.port
: 0;
1825 /* open socket for HTTP connections. Listen on the 1st LAN address */
1827 shttpl
= OpenAndConfHTTPSocket(&listen_port
, 1);
1828 #else /* ENABLE_IPV6 */
1829 shttpl
= OpenAndConfHTTPSocket(&listen_port
);
1830 #endif /* ENABLE_IPV6 */
1833 syslog(LOG_ERR
, "Failed to open socket for HTTP. EXITING");
1836 v
.port
= listen_port
;
1837 syslog(LOG_NOTICE
, "HTTP listening on port %d", v
.port
);
1838 #if defined(V6SOCKETS_ARE_V6ONLY) && defined(ENABLE_IPV6)
1839 if(!GETFLAG(IPV6DISABLEDMASK
))
1841 shttpl_v4
= OpenAndConfHTTPSocket(&listen_port
, 0);
1844 syslog(LOG_ERR
, "Failed to open socket for HTTP on port %hu (IPv4). EXITING", v
.port
);
1848 #endif /* V6SOCKETS_ARE_V6ONLY */
1851 listen_port
= (v
.https_port
> 0) ? v
.https_port
: 0;
1853 shttpsl
= OpenAndConfHTTPSocket(&listen_port
, 1);
1854 #else /* ENABLE_IPV6 */
1855 shttpsl
= OpenAndConfHTTPSocket(&listen_port
);
1856 #endif /* ENABLE_IPV6 */
1859 syslog(LOG_ERR
, "Failed to open socket for HTTPS. EXITING");
1862 v
.https_port
= listen_port
;
1863 syslog(LOG_NOTICE
, "HTTPS listening on port %d", v
.https_port
);
1864 #if defined(V6SOCKETS_ARE_V6ONLY) && defined(ENABLE_IPV6)
1865 shttpsl_v4
= OpenAndConfHTTPSocket(&listen_port
, 0);
1868 syslog(LOG_ERR
, "Failed to open socket for HTTPS on port %hu (IPv4). EXITING", v
.https_port
);
1871 #endif /* V6SOCKETS_ARE_V6ONLY */
1872 #endif /* ENABLE_HTTPS */
1874 if(find_ipv6_addr(NULL
, ipv6_addr_for_http_with_brackets
, sizeof(ipv6_addr_for_http_with_brackets
)) > 0) {
1875 syslog(LOG_NOTICE
, "HTTP IPv6 address given to control points : %s",
1876 ipv6_addr_for_http_with_brackets
);
1878 memcpy(ipv6_addr_for_http_with_brackets
, "[::1]", 6);
1879 syslog(LOG_WARNING
, "no HTTP IPv6 address, disabling IPv6");
1880 SETFLAG(IPV6DISABLEDMASK
);
1884 /* open socket for SSDP connections */
1885 sudp
= OpenAndConfSSDPReceiveSocket(0);
1888 syslog(LOG_NOTICE
, "Failed to open socket for receiving SSDP. Trying to use MiniSSDPd");
1889 if(SubmitServicesToMiniSSDPD(lan_addrs
.lh_first
->str
, v
.port
) < 0) {
1890 syslog(LOG_ERR
, "Failed to connect to MiniSSDPd. EXITING");
1895 if(!GETFLAG(IPV6DISABLEDMASK
))
1897 sudpv6
= OpenAndConfSSDPReceiveSocket(1);
1900 syslog(LOG_WARNING
, "Failed to open socket for receiving SSDP (IP v6).");
1905 /* open socket for sending notifications */
1906 if(OpenAndConfSSDPNotifySockets(snotify
) < 0)
1908 syslog(LOG_ERR
, "Failed to open sockets for sending SSDP notify "
1909 "messages. EXITING");
1913 #ifdef USE_IFACEWATCHER
1914 /* open socket for kernel notifications about new network interfaces */
1917 sifacewatcher
= OpenAndConfInterfaceWatchSocket();
1918 if (sifacewatcher
< 0)
1920 syslog(LOG_ERR
, "Failed to open socket for receiving network interface notifications");
1926 #ifdef ENABLE_NATPMP
1927 /* open socket for NAT PMP traffic */
1928 if(GETFLAG(ENABLENATPMPMASK
))
1930 if(OpenAndConfNATPMPSockets(snatpmp
) < 0)
1933 syslog(LOG_ERR
, "Failed to open sockets for NAT-PMP/PCP.");
1935 syslog(LOG_NOTICE
, "Listening for NAT-PMP/PCP traffic on port %u",
1940 syslog(LOG_ERR
, "Failed to open sockets for NAT PMP.");
1942 syslog(LOG_NOTICE
, "Listening for NAT-PMP traffic on port %u",
1949 #if defined(ENABLE_IPV6) && defined(ENABLE_PCP)
1950 spcp_v6
= OpenAndConfPCPv6Socket();
1953 /* for miniupnpdctl */
1954 #ifdef USE_MINIUPNPDCTL
1955 sctl
= OpenAndConfCtlUnixSocket("/var/run/miniupnpd.ctl");
1958 #ifdef ENABLE_NFQUEUE
1959 if ( nfqueue
!= -1 && n_nfqix
> 0) {
1960 nfqh
= OpenAndConfNFqueue();
1962 syslog(LOG_ERR
, "Failed to open fd for NFQUEUE.");
1965 syslog(LOG_NOTICE
, "Opened NFQUEUE %d",nfqueue
);
1970 tomato_helper(); // zzz
1975 /* Correct startup_time if it was set with a RTC close to 0 */
1976 if((startup_time
<60*60*24) && (time(NULL
)>60*60*24))
1978 set_startup_time(GETFLAG(SYSUPTIMEMASK
));
1980 /* send public address change notifications if needed */
1981 if(should_send_public_address_change_notif
)
1983 syslog(LOG_INFO
, "should send external iface address change notification(s)");
1984 #ifdef ENABLE_NATPMP
1985 if(GETFLAG(ENABLENATPMPMASK
))
1986 SendNATPMPPublicAddressChangeNotification(snatpmp
, addr_count
);
1988 #ifdef ENABLE_EVENTS
1989 if(GETFLAG(ENABLEUPNPMASK
))
1991 upnp_event_var_change_notify(EWanIPC
);
1994 should_send_public_address_change_notif
= 0;
1996 /* Check if we need to send SSDP NOTIFY messages and do it if
1998 if(gettimeofday(&timeofday
, 0) < 0)
2000 syslog(LOG_ERR
, "gettimeofday(): %m");
2001 timeout
.tv_sec
= v
.notify_interval
;
2002 timeout
.tv_usec
= 0;
2006 /* the comparaison is not very precise but who cares ? */
2007 if(timeofday
.tv_sec
>= (lasttimeofday
.tv_sec
+ v
.notify_interval
))
2009 if (GETFLAG(ENABLEUPNPMASK
))
2010 SendSSDPNotifies2(snotify
,
2011 (unsigned short)v
.port
,
2013 (unsigned short)v
.https_port
,
2015 v
.notify_interval
<< 1);
2016 memcpy(&lasttimeofday
, &timeofday
, sizeof(struct timeval
));
2017 timeout
.tv_sec
= v
.notify_interval
;
2018 timeout
.tv_usec
= 0;
2022 timeout
.tv_sec
= lasttimeofday
.tv_sec
+ v
.notify_interval
2024 if(timeofday
.tv_usec
> lasttimeofday
.tv_usec
)
2026 timeout
.tv_usec
= 1000000 + lasttimeofday
.tv_usec
2027 - timeofday
.tv_usec
;
2032 timeout
.tv_usec
= lasttimeofday
.tv_usec
- timeofday
.tv_usec
;
2036 /* remove unused rules */
2037 if( v
.clean_ruleset_interval
2038 && (timeofday
.tv_sec
>= checktime
.tv_sec
+ v
.clean_ruleset_interval
))
2042 remove_unused_rules(rule_list
);
2047 rule_list
= get_upnp_rules_state_list(v
.clean_ruleset_threshold
);
2049 memcpy(&checktime
, &timeofday
, sizeof(struct timeval
));
2051 /* Remove expired port mappings, based on UPnP IGD LeaseDuration
2052 * or NAT-PMP lifetime) */
2053 if(nextruletoclean_timestamp
2054 && ((unsigned int)timeofday
.tv_sec
>= nextruletoclean_timestamp
))
2056 syslog(LOG_DEBUG
, "cleaning expired Port Mappings");
2057 get_upnp_rules_state_list(0);
2059 if(nextruletoclean_timestamp
2060 && ((unsigned int)timeout
.tv_sec
>= (nextruletoclean_timestamp
- timeofday
.tv_sec
)))
2062 timeout
.tv_sec
= nextruletoclean_timestamp
- timeofday
.tv_sec
;
2063 timeout
.tv_usec
= 0;
2064 syslog(LOG_DEBUG
, "setting timeout to %u sec",
2065 (unsigned)timeout
.tv_sec
);
2067 #ifdef ENABLE_UPNPPINHOLE
2068 /* Clean up expired IPv6 PinHoles */
2069 next_pinhole_ts
= 0;
2070 upnp_clean_expired_pinholes(&next_pinhole_ts
);
2071 if(next_pinhole_ts
&&
2072 timeout
.tv_sec
>= (int)(next_pinhole_ts
- timeofday
.tv_sec
)) {
2073 timeout
.tv_sec
= next_pinhole_ts
- timeofday
.tv_sec
;
2074 timeout
.tv_usec
= 0;
2076 #endif /* ENABLE_UPNPPINHOLE */
2078 /* select open sockets (SSDP, HTTP listen, and all HTTP soap sockets) */
2084 FD_SET(sudp
, &readset
);
2085 max_fd
= MAX( max_fd
, sudp
);
2086 #ifdef USE_IFACEWATCHER
2087 if (sifacewatcher
>= 0)
2089 FD_SET(sifacewatcher
, &readset
);
2090 max_fd
= MAX(max_fd
, sifacewatcher
);
2096 FD_SET(shttpl
, &readset
);
2097 max_fd
= MAX( max_fd
, shttpl
);
2099 #if defined(V6SOCKETS_ARE_V6ONLY) && defined(ENABLE_IPV6)
2102 FD_SET(shttpl_v4
, &readset
);
2103 max_fd
= MAX( max_fd
, shttpl_v4
);
2109 FD_SET(shttpsl
, &readset
);
2110 max_fd
= MAX( max_fd
, shttpsl
);
2112 #if defined(V6SOCKETS_ARE_V6ONLY) && defined(ENABLE_IPV6)
2113 if (shttpsl_v4
>= 0)
2115 FD_SET(shttpsl_v4
, &readset
);
2116 max_fd
= MAX( max_fd
, shttpsl_v4
);
2119 #endif /* ENABLE_HTTPS */
2123 FD_SET(sudpv6
, &readset
);
2124 max_fd
= MAX( max_fd
, sudpv6
);
2128 #ifdef ENABLE_NFQUEUE
2131 FD_SET(nfqh
, &readset
);
2132 max_fd
= MAX( max_fd
, nfqh
);
2136 i
= 0; /* active HTTP connections count */
2137 for(e
= upnphttphead
.lh_first
; e
!= NULL
; e
= e
->entries
.le_next
)
2141 if(e
->state
<= EWaitingForHttpContent
)
2142 FD_SET(e
->socket
, &readset
);
2143 else if(e
->state
== ESendingAndClosing
)
2144 FD_SET(e
->socket
, &writeset
);
2147 max_fd
= MAX(max_fd
, e
->socket
);
2155 syslog(LOG_DEBUG
, "%d active incoming HTTP connections", i
);
2158 #ifdef ENABLE_NATPMP
2159 for(i
=0; i
<addr_count
; i
++) {
2160 if(snatpmp
[i
] >= 0) {
2161 FD_SET(snatpmp
[i
], &readset
);
2162 max_fd
= MAX( max_fd
, snatpmp
[i
]);
2166 #if defined(ENABLE_IPV6) && defined(ENABLE_PCP)
2168 FD_SET(spcp_v6
, &readset
);
2169 max_fd
= MAX(max_fd
, spcp_v6
);
2172 #ifdef USE_MINIUPNPDCTL
2174 FD_SET(sctl
, &readset
);
2175 max_fd
= MAX( max_fd
, sctl
);
2178 for(ectl
= ctllisthead
.lh_first
; ectl
; ectl
= ectl
->entries
.le_next
)
2180 if(ectl
->socket
>= 0) {
2181 FD_SET(ectl
->socket
, &readset
);
2182 max_fd
= MAX( max_fd
, ectl
->socket
);
2187 #ifdef ENABLE_EVENTS
2188 upnpevents_selectfds(&readset
, &writeset
, &max_fd
);
2191 /* queued "sendto" */
2193 struct timeval next_send
;
2194 i
= get_next_scheduled_send(&next_send
);
2197 syslog(LOG_DEBUG
, "%d queued sendto", i
);
2199 i
= get_sendto_fds(&writeset
, &max_fd
, &timeofday
);
2200 if(timeofday
.tv_sec
> next_send
.tv_sec
||
2201 (timeofday
.tv_sec
== next_send
.tv_sec
&& timeofday
.tv_usec
>= next_send
.tv_usec
)) {
2204 timeout
.tv_usec
= 0;
2207 struct timeval tmp_timeout
;
2208 tmp_timeout
.tv_sec
= (next_send
.tv_sec
- timeofday
.tv_sec
);
2209 tmp_timeout
.tv_usec
= (next_send
.tv_usec
- timeofday
.tv_usec
);
2210 if(tmp_timeout
.tv_usec
< 0) {
2211 tmp_timeout
.tv_usec
+= 1000000;
2212 tmp_timeout
.tv_sec
--;
2214 if(timeout
.tv_sec
> tmp_timeout
.tv_sec
2215 || (timeout
.tv_sec
== tmp_timeout
.tv_sec
&& timeout
.tv_usec
> tmp_timeout
.tv_usec
)) {
2216 timeout
.tv_sec
= tmp_timeout
.tv_sec
;
2217 timeout
.tv_usec
= tmp_timeout
.tv_usec
;
2223 if(select(max_fd
+1, &readset
, &writeset
, 0, &timeout
) < 0)
2225 if(quitting
) goto shutdown
;
2226 if (gotusr2
) { // zzz
2231 if(errno
== EINTR
) continue; /* interrupted by a signal, start again */
2232 syslog(LOG_ERR
, "select(all): %m");
2233 syslog(LOG_ERR
, "Failed to select open sockets. EXITING");
2234 return 1; /* very serious cause of error */
2236 i
= try_sendto(&writeset
);
2238 syslog(LOG_ERR
, "try_sendto failed to send %d packets", -i
);
2240 #ifdef USE_MINIUPNPDCTL
2241 for(ectl
= ctllisthead
.lh_first
; ectl
;)
2243 ectlnext
= ectl
->entries
.le_next
;
2244 if((ectl
->socket
>= 0) && FD_ISSET(ectl
->socket
, &readset
))
2248 l
= read(ectl
->socket
, buf
, sizeof(buf
));
2251 /*write(ectl->socket, buf, l);*/
2252 write_command_line(ectl
->socket
, argc
, argv
);
2253 #ifndef DISABLE_CONFIG_FILE
2254 write_option_list(ectl
->socket
);
2256 write_permlist(ectl
->socket
, upnppermlist
, num_upnpperm
);
2257 write_upnphttp_details(ectl
->socket
, upnphttphead
.lh_first
);
2258 write_ctlsockets_list(ectl
->socket
, ctllisthead
.lh_first
);
2259 write_ruleset_details(ectl
->socket
);
2260 #ifdef ENABLE_EVENTS
2261 write_events_details(ectl
->socket
);
2263 /* close the socket */
2264 close(ectl
->socket
);
2269 close(ectl
->socket
);
2273 if(ectl
->socket
< 0)
2275 LIST_REMOVE(ectl
, entries
);
2280 if((sctl
>= 0) && FD_ISSET(sctl
, &readset
))
2283 struct sockaddr_un clientname
;
2284 struct ctlelem
* tmp
;
2285 socklen_t clientnamelen
= sizeof(struct sockaddr_un
);
2286 /*syslog(LOG_DEBUG, "sctl!");*/
2287 s
= accept(sctl
, (struct sockaddr
*)&clientname
,
2289 syslog(LOG_DEBUG
, "sctl! : '%s'", clientname
.sun_path
);
2290 tmp
= malloc(sizeof(struct ctlelem
));
2293 syslog(LOG_ERR
, "Unable to allocate memory for ctlelem in main()");
2299 LIST_INSERT_HEAD(&ctllisthead
, tmp
, entries
);
2303 #ifdef ENABLE_EVENTS
2304 upnpevents_processfds(&readset
, &writeset
);
2306 #ifdef ENABLE_NATPMP
2307 /* process NAT-PMP packets */
2308 for(i
=0; i
<addr_count
; i
++)
2310 if((snatpmp
[i
] >= 0) && FD_ISSET(snatpmp
[i
], &readset
))
2312 unsigned char msg_buff
[PCP_MAX_LEN
];
2313 struct sockaddr_in senderaddr
;
2314 socklen_t senderaddrlen
;
2316 memset(msg_buff
, 0, PCP_MAX_LEN
);
2317 senderaddrlen
= sizeof(senderaddr
);
2318 len
= ReceiveNATPMPOrPCPPacket(snatpmp
[i
],
2319 (struct sockaddr
*)&senderaddr
,
2322 msg_buff
, sizeof(msg_buff
));
2326 if (msg_buff
[0]==0) { /* version equals to 0 -> means NAT-PMP */
2327 /* Check if the packet is coming from a LAN to enforce RFC6886 :
2328 * The NAT gateway MUST NOT accept mapping requests destined to the NAT
2329 * gateway's external IP address or received on its external network
2330 * interface. Only packets received on the internal interface(s) with a
2331 * destination address matching the internal address(es) of the NAT
2332 * gateway should be allowed. */
2333 /* TODO : move to ProcessIncomingNATPMPPacket() ? */
2334 lan_addr
= get_lan_for_peer((struct sockaddr
*)&senderaddr
);
2335 if(lan_addr
== NULL
) {
2336 char sender_str
[64];
2337 sockaddr_to_string((struct sockaddr
*)&senderaddr
, sender_str
, sizeof(sender_str
));
2338 syslog(LOG_WARNING
, "NAT-PMP packet sender %s not from a LAN, ignoring",
2342 ProcessIncomingNATPMPPacket(snatpmp
[i
], msg_buff
, len
,
2344 } else { /* everything else can be PCP */
2345 ProcessIncomingPCPPacket(snatpmp
[i
], msg_buff
, len
,
2346 (struct sockaddr
*)&senderaddr
, NULL
);
2350 /* Check if the packet is coming from a LAN to enforce RFC6886 :
2351 * The NAT gateway MUST NOT accept mapping requests destined to the NAT
2352 * gateway's external IP address or received on its external network
2353 * interface. Only packets received on the internal interface(s) with a
2354 * destination address matching the internal address(es) of the NAT
2355 * gateway should be allowed. */
2356 /* TODO : move to ProcessIncomingNATPMPPacket() ? */
2357 lan_addr
= get_lan_for_peer((struct sockaddr
*)&senderaddr
);
2358 if(lan_addr
== NULL
) {
2359 char sender_str
[64];
2360 sockaddr_to_string((struct sockaddr
*)&senderaddr
, sender_str
, sizeof(sender_str
));
2361 syslog(LOG_WARNING
, "NAT-PMP packet sender %s not from a LAN, ignoring",
2365 ProcessIncomingNATPMPPacket(snatpmp
[i
], msg_buff
, len
, &senderaddr
);
2370 #if defined(ENABLE_IPV6) && defined(ENABLE_PCP)
2371 /* in IPv6, only PCP is supported, not NAT-PMP */
2372 if(spcp_v6
>= 0 && FD_ISSET(spcp_v6
, &readset
))
2374 unsigned char msg_buff
[PCP_MAX_LEN
];
2375 struct sockaddr_in6 senderaddr
;
2376 socklen_t senderaddrlen
;
2377 struct sockaddr_in6 receiveraddr
;
2379 memset(msg_buff
, 0, PCP_MAX_LEN
);
2380 senderaddrlen
= sizeof(senderaddr
);
2381 len
= ReceiveNATPMPOrPCPPacket(spcp_v6
,
2382 (struct sockaddr
*)&senderaddr
,
2385 msg_buff
, sizeof(msg_buff
));
2387 ProcessIncomingPCPPacket(spcp_v6
, msg_buff
, len
,
2388 (struct sockaddr
*)&senderaddr
,
2392 /* process SSDP packets */
2393 if(sudp
>= 0 && FD_ISSET(sudp
, &readset
))
2395 /*syslog(LOG_INFO, "Received UDP Packet");*/
2397 ProcessSSDPRequest(sudp
, (unsigned short)v
.port
, (unsigned short)v
.https_port
);
2399 ProcessSSDPRequest(sudp
, (unsigned short)v
.port
);
2403 if(sudpv6
>= 0 && FD_ISSET(sudpv6
, &readset
))
2405 syslog(LOG_INFO
, "Received UDP Packet (IPv6)");
2407 ProcessSSDPRequest(sudpv6
, (unsigned short)v
.port
, (unsigned short)v
.https_port
);
2409 ProcessSSDPRequest(sudpv6
, (unsigned short)v
.port
);
2413 #ifdef USE_IFACEWATCHER
2414 /* process kernel notifications */
2415 if (sifacewatcher
>= 0 && FD_ISSET(sifacewatcher
, &readset
))
2416 ProcessInterfaceWatchNotify(sifacewatcher
);
2419 /* process active HTTP connections */
2420 /* LIST_FOREACH macro is not available under linux */
2421 for(e
= upnphttphead
.lh_first
; e
!= NULL
; e
= e
->entries
.le_next
)
2425 if(FD_ISSET(e
->socket
, &readset
) ||
2426 FD_ISSET(e
->socket
, &writeset
))
2428 Process_upnphttp(e
);
2432 /* process incoming HTTP connections */
2433 if(shttpl
>= 0 && FD_ISSET(shttpl
, &readset
))
2435 struct upnphttp
* tmp
;
2436 tmp
= ProcessIncomingHTTP(shttpl
, "HTTP");
2439 LIST_INSERT_HEAD(&upnphttphead
, tmp
, entries
);
2442 #if defined(V6SOCKETS_ARE_V6ONLY) && defined(ENABLE_IPV6)
2443 if(shttpl_v4
>= 0 && FD_ISSET(shttpl_v4
, &readset
))
2445 struct upnphttp
* tmp
;
2446 tmp
= ProcessIncomingHTTP(shttpl_v4
, "HTTP");
2449 LIST_INSERT_HEAD(&upnphttphead
, tmp
, entries
);
2454 if(shttpsl
>= 0 && FD_ISSET(shttpsl
, &readset
))
2456 struct upnphttp
* tmp
;
2457 tmp
= ProcessIncomingHTTP(shttpsl
, "HTTPS");
2460 InitSSL_upnphttp(tmp
);
2461 LIST_INSERT_HEAD(&upnphttphead
, tmp
, entries
);
2464 #if defined(V6SOCKETS_ARE_V6ONLY) && defined(ENABLE_IPV6)
2465 if(shttpsl_v4
>= 0 && FD_ISSET(shttpsl_v4
, &readset
))
2467 struct upnphttp
* tmp
;
2468 tmp
= ProcessIncomingHTTP(shttpsl_v4
, "HTTPS");
2471 InitSSL_upnphttp(tmp
);
2472 LIST_INSERT_HEAD(&upnphttphead
, tmp
, entries
);
2476 #endif /* ENABLE_HTTPS */
2477 #ifdef ENABLE_NFQUEUE
2478 /* process NFQ packets */
2479 if(nfqh
>= 0 && FD_ISSET(nfqh
, &readset
))
2481 /* syslog(LOG_INFO, "Received NFQUEUE Packet");*/
2482 ProcessNFQUEUE(nfqh
);
2485 /* delete finished HTTP connections */
2486 for(e
= upnphttphead
.lh_first
; e
!= NULL
; )
2488 next
= e
->entries
.le_next
;
2489 if(e
->state
>= EToDelete
)
2491 LIST_REMOVE(e
, entries
);
2497 } /* end of main loop */
2500 syslog(LOG_NOTICE
, "shutting down MiniUPnPd");
2502 if (GETFLAG(ENABLEUPNPMASK
))
2505 if(SendSSDPGoodbye(snotify
, addr_count
) < 0)
2507 if(SendSSDPGoodbye(snotify
, addr_count
* 2) < 0)
2510 syslog(LOG_ERR
, "Failed to broadcast good-bye notifications");
2513 /* try to send pending packets */
2516 tomato_save("/etc/upnp/data"); // zzz
2518 /* close out open sockets */
2519 while(upnphttphead
.lh_first
!= NULL
)
2521 e
= upnphttphead
.lh_first
;
2522 LIST_REMOVE(e
, entries
);
2526 if (sudp
>= 0) close(sudp
);
2527 if (shttpl
>= 0) close(shttpl
);
2528 #if defined(V6SOCKETS_ARE_V6ONLY) && defined(ENABLE_IPV6)
2529 if (shttpl_v4
>= 0) close(shttpl_v4
);
2532 if (sudpv6
>= 0) close(sudpv6
);
2534 #ifdef USE_IFACEWATCHER
2535 if(sifacewatcher
>= 0) close(sifacewatcher
);
2537 #ifdef ENABLE_NATPMP
2538 for(i
=0; i
<addr_count
; i
++) {
2546 #if defined(ENABLE_IPV6) && defined(ENABLE_PCP)
2553 #ifdef USE_MINIUPNPDCTL
2558 if(unlink("/var/run/miniupnpd.ctl") < 0)
2560 syslog(LOG_ERR
, "unlink() %m");
2565 if (GETFLAG(ENABLEUPNPMASK
))
2568 for(i
= 0; i
< addr_count
; i
++)
2570 for(i
= 0; i
< addr_count
* 2; i
++)
2575 /* remove pidfile */
2576 if(pidfilename
&& (unlink(pidfilename
) < 0))
2578 syslog(LOG_ERR
, "Failed to remove pidfile %s: %m", pidfilename
);
2582 while(lan_addrs
.lh_first
!= NULL
)
2584 lan_addr
= lan_addrs
.lh_first
;
2585 LIST_REMOVE(lan_addrs
.lh_first
, list
);
2592 #ifdef ENABLE_NATPMP
2597 #ifndef DISABLE_CONFIG_FILE