1 /* $Id: miniupnpd.c,v 1.214 2016/01/01 11:15:56 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
56 #include "upnpglobalvars.h"
58 #include "upnpdescgen.h"
59 #include "miniupnpdpath.h"
60 #include "getifaddr.h"
64 #include "upnpredirect.h"
65 #include "upnppinhole.h"
66 #include "miniupnpdtypes.h"
67 #include "daemonize.h"
68 #include "upnpevents.h"
69 #include "asyncsendto.h"
73 #include "pcpserver.h"
75 #define PCP_MAX_LEN 32
78 #include "commonrdr.h"
79 #include "upnputils.h"
80 #ifdef USE_IFACEWATCHER
81 #include "ifacewatcher.h"
83 #ifdef ENABLE_UPNPPINHOLE
85 void init_iptpinhole(void);
89 #ifndef DEFAULT_CONFIG
90 #define DEFAULT_CONFIG "/etc/miniupnpd.conf"
93 #ifdef USE_MINIUPNPDCTL
96 LIST_ENTRY(ctlelem
) entries
;
98 #endif /* USE_MINIUPNPDCTL */
100 #ifdef ENABLE_NFQUEUE
102 static struct nfq_handle
*nfqHandle
;
103 static struct sockaddr_in ssdp
;
106 static int nfqueue_cb( struct nfq_q_handle
*qh
, struct nfgenmsg
*nfmsg
, struct nfq_data
*nfa
, void *data
) ;
107 int identify_ip_protocol (char *payload
);
108 int get_udp_dst_port (char *payload
);
109 #endif /* ENABLE_NFQUEUE */
111 /* variables used by signals */
112 static volatile sig_atomic_t quitting
= 0;
113 volatile sig_atomic_t should_send_public_address_change_notif
= 0;
117 /* Tomato specific code */
118 static volatile sig_atomic_t gotusr2
= 0;
127 tomato_save(const char *fname
)
129 unsigned short eport
;
130 unsigned short iport
;
131 unsigned int leaseduration
;
132 unsigned int timestamp
;
142 strcpy(tmp
, "/etc/upnp/saveXXXXXX");
143 if ((t
= mkstemp(tmp
)) != -1)
145 if ((f
= fdopen(t
, "w")) != NULL
)
148 while (upnp_get_redirection_infos_by_index(n
, &eport
, proto
, &iport
, iaddr
, sizeof(iaddr
), desc
, sizeof(desc
), rhost
, sizeof(rhost
), &leaseduration
) == 0)
150 timestamp
= (leaseduration
> 0) ? time(NULL
) + leaseduration
: 0;
151 fprintf(f
, "%s %u %s %u [%s] %u\n", proto
, eport
, iaddr
, iport
, desc
, timestamp
);
170 unsigned short eport
;
171 unsigned short iport
;
172 unsigned int leaseduration
;
173 unsigned int timestamp
;
180 if ((f
= fopen("/etc/upnp/data", "r")) != NULL
)
182 current_time
= time(NULL
);
183 s
[sizeof(s
) - 1] = 0;
184 while (fgets(s
, sizeof(s
) - 1, f
)) {
185 if (sscanf(s
, "%3s %hu %31s %hu [%*s] %u", proto
, &eport
, iaddr
, &iport
, ×tamp
) >= 4)
187 if (((a
= strchr(s
, '[')) != NULL
) && ((b
= strrchr(a
, ']')) != NULL
))
191 if (timestamp
> current_time
)
192 leaseduration
= current_time
- timestamp
;
198 leaseduration
= 0; /* default value */
202 upnp_redirect(rhost
, eport
, iaddr
, iport
, proto
, a
+ 1, leaseduration
);
210 ScanNATPMPforExpiration();
212 #endif /* ENABLE_NATPMP */
213 unlink("/etc/upnp/load");
221 unsigned short eport
;
222 unsigned short iport
;
223 unsigned int leaseduration
;
230 if ((f
= fopen("/etc/upnp/delete", "r")) != NULL
)
232 s
[sizeof(s
) - 1] = 0;
233 while (fgets(s
, sizeof(s
) - 1, f
))
235 if (sscanf(s
, "%3s %hu", proto
, &eport
) == 2)
239 n
= upnp_get_portmapping_number_of_entries();
242 if (upnp_get_redirection_infos_by_index(n
, &eport
, proto
, &iport
, iaddr
, sizeof(iaddr
), desc
, sizeof(desc
), rhost
, sizeof(rhost
), &leaseduration
) == 0)
244 upnp_delete_redirection(eport
, proto
);
251 upnp_delete_redirection(eport
, proto
);
256 unlink("/etc/upnp/delete");
265 if (stat("/etc/upnp/delete", &st
) == 0)
270 if (stat("/etc/upnp/load", &st
) == 0)
275 if (stat("/etc/upnp/save", &st
) == 0)
277 tomato_save("/etc/upnp/data");
278 unlink("/etc/upnp/save");
281 if (stat("/etc/upnp/info", &st
) == 0)
283 tomato_save("/etc/upnp/data.info");
284 unlink("/etc/upnp/info");
287 #endif /* 1 (tomato) */
290 /* OpenAndConfHTTPSocket() :
291 * setup the socket used to handle incoming HTTP connections. */
294 OpenAndConfHTTPSocket(unsigned short * port
, int ipv6
)
296 OpenAndConfHTTPSocket(unsigned short * port
)
302 struct sockaddr_in6 listenname6
;
303 struct sockaddr_in listenname4
;
305 struct sockaddr_in listenname
;
307 socklen_t listenname_len
;
311 ipv6
? PF_INET6
: PF_INET
,
317 if(s
< 0 && ipv6
&& errno
== EAFNOSUPPORT
)
319 /* the system doesn't support IPV6 */
320 syslog(LOG_WARNING
, "socket(PF_INET6, ...) failed with EAFNOSUPPORT, disabling IPv6");
321 SETFLAG(IPV6DISABLEDMASK
);
323 s
= socket(PF_INET
, SOCK_STREAM
, 0);
328 syslog(LOG_ERR
, "socket(http): %m");
332 if(setsockopt(s
, SOL_SOCKET
, SO_REUSEADDR
, &i
, sizeof(i
)) < 0)
334 syslog(LOG_WARNING
, "setsockopt(http, SO_REUSEADDR): %m");
337 /* enable this to force IPV6 only for IPV6 socket.
338 * see http://www.ietf.org/rfc/rfc3493.txt section 5.3 */
339 if(setsockopt(s
, IPPROTO_IPV6
, IPV6_V6ONLY
, &i
, sizeof(i
)) < 0)
341 syslog(LOG_WARNING
, "setsockopt(http, IPV6_V6ONLY): %m");
345 if(!set_non_blocking(s
))
347 syslog(LOG_WARNING
, "set_non_blocking(http): %m");
353 memset(&listenname6
, 0, sizeof(struct sockaddr_in6
));
354 listenname6
.sin6_family
= AF_INET6
;
355 listenname6
.sin6_port
= htons(*port
);
356 listenname6
.sin6_addr
= ipv6_bind_addr
;
357 listenname_len
= sizeof(struct sockaddr_in6
);
359 memset(&listenname4
, 0, sizeof(struct sockaddr_in
));
360 listenname4
.sin_family
= AF_INET
;
361 listenname4
.sin_port
= htons(*port
);
362 listenname4
.sin_addr
.s_addr
= htonl(INADDR_ANY
);
363 listenname_len
= sizeof(struct sockaddr_in
);
366 memset(&listenname
, 0, sizeof(struct sockaddr_in
));
367 listenname
.sin_family
= AF_INET
;
368 listenname
.sin_port
= htons(*port
);
369 listenname
.sin_addr
.s_addr
= htonl(INADDR_ANY
);
370 listenname_len
= sizeof(struct sockaddr_in
);
373 #if defined(SO_BINDTODEVICE) && !defined(MULTIPLE_EXTERNAL_IP)
374 /* One and only one LAN interface */
375 if(lan_addrs
.lh_first
!= NULL
&& lan_addrs
.lh_first
->list
.le_next
== NULL
376 && strlen(lan_addrs
.lh_first
->ifname
) > 0)
378 if(setsockopt(s
, SOL_SOCKET
, SO_BINDTODEVICE
,
379 lan_addrs
.lh_first
->ifname
,
380 strlen(lan_addrs
.lh_first
->ifname
)) < 0)
381 syslog(LOG_WARNING
, "setsockopt(http, SO_BINDTODEVICE, %s): %m",
382 lan_addrs
.lh_first
->ifname
);
384 #endif /* defined(SO_BINDTODEVICE) && !defined(MULTIPLE_EXTERNAL_IP) */
388 ipv6
? (struct sockaddr
*)&listenname6
: (struct sockaddr
*)&listenname4
,
391 if(bind(s
, (struct sockaddr
*)&listenname
, listenname_len
) < 0)
394 syslog(LOG_ERR
, "bind(http): %m");
401 syslog(LOG_ERR
, "listen(http): %m");
409 struct sockaddr_in6 sockinfo
;
410 socklen_t len
= sizeof(struct sockaddr_in6
);
411 if (getsockname(s
, (struct sockaddr
*)&sockinfo
, &len
) < 0) {
412 syslog(LOG_ERR
, "getsockname(): %m");
414 *port
= ntohs(sockinfo
.sin6_port
);
417 #endif /* ENABLE_IPV6 */
418 struct sockaddr_in sockinfo
;
419 socklen_t len
= sizeof(struct sockaddr_in
);
420 if (getsockname(s
, (struct sockaddr
*)&sockinfo
, &len
) < 0) {
421 syslog(LOG_ERR
, "getsockname(): %m");
423 *port
= ntohs(sockinfo
.sin_port
);
427 #endif /* ENABLE_IPV6 */
432 static struct upnphttp
*
433 ProcessIncomingHTTP(int shttpl
, const char * protocol
)
436 socklen_t clientnamelen
;
438 struct sockaddr_storage clientname
;
439 clientnamelen
= sizeof(struct sockaddr_storage
);
441 struct sockaddr_in clientname
;
442 clientnamelen
= sizeof(struct sockaddr_in
);
444 shttp
= accept(shttpl
, (struct sockaddr
*)&clientname
, &clientnamelen
);
447 /* ignore EAGAIN, EWOULDBLOCK, EINTR, we just try again later */
448 if(errno
!= EAGAIN
&& errno
!= EWOULDBLOCK
&& errno
!= EINTR
)
449 syslog(LOG_ERR
, "accept(http): %m");
453 struct upnphttp
* tmp
= 0;
456 sockaddr_to_string((struct sockaddr
*)&clientname
, addr_str
, sizeof(addr_str
));
458 syslog(LOG_DEBUG
, "%s connection from %s", protocol
, addr_str
);
460 if(get_lan_for_peer((struct sockaddr
*)&clientname
) == NULL
)
462 /* The peer is not a LAN ! */
464 "%s peer %s is not from a LAN, closing the connection",
470 /* Create a new upnphttp object and add it to
471 * the active upnphttp object list */
472 tmp
= New_upnphttp(shttp
);
476 if(clientname
.ss_family
== AF_INET
)
478 tmp
->clientaddr
= ((struct sockaddr_in
*)&clientname
)->sin_addr
;
480 else if(clientname
.ss_family
== AF_INET6
)
482 struct sockaddr_in6
* addr
= (struct sockaddr_in6
*)&clientname
;
483 if(IN6_IS_ADDR_V4MAPPED(&addr
->sin6_addr
))
485 memcpy(&tmp
->clientaddr
,
486 &addr
->sin6_addr
.s6_addr
[12],
492 memcpy(&tmp
->clientaddr_v6
,
494 sizeof(struct in6_addr
));
498 tmp
->clientaddr
= clientname
.sin_addr
;
500 memcpy(tmp
->clientaddr_str
, addr_str
, sizeof(tmp
->clientaddr_str
));
505 syslog(LOG_ERR
, "New_upnphttp() failed");
513 #ifdef ENABLE_NFQUEUE
515 int identify_ip_protocol(char *payload
) {
521 * This function returns the destination port of the captured packet UDP
523 int get_udp_dst_port(char *payload
) {
524 char *pkt_data_ptr
= NULL
;
525 pkt_data_ptr
= payload
+ sizeof(struct ip
);
527 /* Cast the UDP Header from the raw packet */
528 struct udphdr
*udp
= (struct udphdr
*) pkt_data_ptr
;
530 /* get the dst port of the packet */
531 return(ntohs(udp
->dest
));
535 OpenAndConfNFqueue(){
537 struct nfq_q_handle
*myQueue
;
538 struct nfnl_handle
*netlinkHandle
;
542 inet_pton(AF_INET
, "239.255.255.250", &(ssdp
.sin_addr
));
544 /* Get a queue connection handle from the module */
545 if (!(nfqHandle
= nfq_open())) {
546 syslog(LOG_ERR
, "Error in nfq_open(): %m");
550 /* Unbind the handler from processing any IP packets
551 Not totally sure why this is done, or if it's necessary... */
552 if ((e
= nfq_unbind_pf(nfqHandle
, AF_INET
)) < 0) {
553 syslog(LOG_ERR
, "Error in nfq_unbind_pf(): %m");
557 /* Bind this handler to process IP packets... */
558 if (nfq_bind_pf(nfqHandle
, AF_INET
) < 0) {
559 syslog(LOG_ERR
, "Error in nfq_bind_pf(): %m");
563 /* Install a callback on queue -Q */
564 if (!(myQueue
= nfq_create_queue(nfqHandle
, nfqueue
, &nfqueue_cb
, NULL
))) {
565 syslog(LOG_ERR
, "Error in nfq_create_queue(): %m");
569 /* Turn on packet copy mode */
570 if (nfq_set_mode(myQueue
, NFQNL_COPY_PACKET
, 0xffff) < 0) {
571 syslog(LOG_ERR
, "Error setting packet copy mode (): %m");
575 netlinkHandle
= nfq_nfnlh(nfqHandle
);
576 fd
= nfnl_fd(netlinkHandle
);
583 static int nfqueue_cb(
584 struct nfq_q_handle
*qh
,
585 struct nfgenmsg
*nfmsg
,
586 struct nfq_data
*nfa
,
590 struct nfqnl_msg_packet_hdr
*ph
;
591 ph
= nfq_get_msg_packet_hdr(nfa
);
595 int id
= 0, size
= 0;
596 id
= ntohl(ph
->packet_id
);
598 size
= nfq_get_payload(nfa
, &pkt
);
600 struct ip
*iph
= (struct ip
*) pkt
;
602 int id_protocol
= identify_ip_protocol(pkt
);
604 int dport
= get_udp_dst_port(pkt
);
606 int x
= sizeof (struct ip
) + sizeof (struct udphdr
);
608 /* packets we are interested in are UDP multicast to 239.255.255.250:1900
609 * and start with a data string M-SEARCH
611 if ( (dport
== 1900) && (id_protocol
== IPPROTO_UDP
)
612 && (ssdp
.sin_addr
.s_addr
== iph
->ip_dst
.s_addr
) ) {
614 /* get the index that the packet came in on */
615 u_int32_t idx
= nfq_get_indev(nfa
);
617 for ( ;i
< n_nfqix
; i
++) {
618 if ( nfqix
[i
] == idx
) {
620 struct udphdr
*udp
= (struct udphdr
*) (pkt
+ sizeof(struct ip
));
624 struct sockaddr_in sendername
;
625 sendername
.sin_family
= AF_INET
;
626 sendername
.sin_port
= udp
->source
;
627 sendername
.sin_addr
.s_addr
= iph
->ip_src
.s_addr
;
629 /* printf("pkt found %s\n",dd);*/
630 ProcessSSDPData (sudp
, dd
, size
- x
,
631 &sendername
, (unsigned short) 5555);
636 nfq_set_verdict(qh
, id
, NF_ACCEPT
, 0, NULL
);
639 syslog(LOG_ERR
,"nfq_get_msg_packet_hdr failed");
641 /* from nfqueue source: 0 = ok, >0 = soft error, <0 hard error */
647 static void ProcessNFQUEUE(int fd
){
651 struct sockaddr_in sendername
;
652 len_r
= sizeof(struct sockaddr_in
);
654 int res
= recvfrom(fd
, buf
, sizeof(buf
), 0,
655 (struct sockaddr
*)&sendername
, &len_r
);
657 nfq_handle_packet(nfqHandle
, buf
, res
);
661 /* Functions used to communicate with miniupnpdctl */
662 #ifdef USE_MINIUPNPDCTL
664 OpenAndConfCtlUnixSocket(const char * path
)
666 struct sockaddr_un localun
;
668 s
= socket(AF_UNIX
, SOCK_STREAM
, 0);
669 localun
.sun_family
= AF_UNIX
;
670 strncpy(localun
.sun_path
, path
,
671 sizeof(localun
.sun_path
));
672 if(bind(s
, (struct sockaddr
*)&localun
,
673 sizeof(struct sockaddr_un
)) < 0)
675 syslog(LOG_ERR
, "bind(sctl): %m");
679 else if(listen(s
, 5) < 0)
681 syslog(LOG_ERR
, "listen(sctl): %m");
689 write_upnphttp_details(int fd
, struct upnphttp
* e
)
693 write(fd
, "HTTP :\n", 7);
696 len
= snprintf(buffer
, sizeof(buffer
),
697 "%d %d %s req_buf=%p(%dbytes) res_buf=%p(%dbytes alloc)\n",
698 e
->socket
, e
->state
, e
->HttpVer
,
699 e
->req_buf
, e
->req_buflen
,
700 e
->res_buf
, e
->res_buf_alloclen
);
701 write(fd
, buffer
, len
);
702 e
= e
->entries
.le_next
;
707 write_ctlsockets_list(int fd
, struct ctlelem
* e
)
711 write(fd
, "CTL :\n", 6);
714 len
= snprintf(buffer
, sizeof(buffer
),
715 "struct ctlelem: socket=%d\n", e
->socket
);
716 write(fd
, buffer
, len
);
717 e
= e
->entries
.le_next
;
721 #ifndef DISABLE_CONFIG_FILE
723 write_option_list(int fd
)
728 write(fd
, "Options :\n", 10);
729 for(i
=0; i
<num_options
; i
++)
731 len
= snprintf(buffer
, sizeof(buffer
),
733 ary_options
[i
].id
, ary_options
[i
].value
);
734 write(fd
, buffer
, len
);
740 write_command_line(int fd
, int argc
, char * * argv
)
745 write(fd
, "Command Line :\n", 15);
746 for(i
=0; i
<argc
; i
++)
748 len
= snprintf(buffer
, sizeof(buffer
),
751 write(fd
, buffer
, len
);
757 /* Handler for the SIGTERM signal (kill)
758 * SIGINT is also handled */
763 /*int save_errno = errno; */
764 /*signal(sig, SIG_IGN);*/ /* Ignore this signal while we are quitting */
765 /* Note : isn't it useless ? */
768 /* calling syslog() is forbidden in signal handler according to
770 syslog(LOG_NOTICE
, "received signal %d, good-bye", sig
);
774 /*errno = save_errno;*/
777 /* Handler for the SIGUSR1 signal indicating public IP address change. */
783 /* calling syslog() is forbidden in signal handler according to
785 syslog(LOG_INFO
, "received signal %d, public ip address change", sig
);
788 should_send_public_address_change_notif
= 1;
791 /* record the startup time, for returning uptime */
793 set_startup_time(int sysuptime
)
795 startup_time
= time(NULL
);
796 #ifdef USE_TIME_AS_BOOTID
797 if(startup_time
> 60*60*24 && upnp_bootid
== 1) {
798 /* We know we are not January the 1st 1970 */
799 upnp_bootid
= (unsigned int)startup_time
;
801 * A convenient mechanism is to set this field value to the time
802 * that the device sends its initial announcement, expressed as
803 * seconds elapsed since midnight January 1, 1970; */
805 #endif /* USE_TIME_AS_BOOTID */
808 /* use system uptime instead of daemon uptime */
809 #if defined(__linux__)
812 fd
= open("/proc/uptime", O_RDONLY
);
815 syslog(LOG_ERR
, "open(\"/proc/uptime\" : %m");
819 memset(buff
, 0, sizeof(buff
));
820 if(read(fd
, buff
, sizeof(buff
) - 1) < 0)
822 syslog(LOG_ERR
, "read(\"/proc/uptime\" : %m");
827 syslog(LOG_INFO
, "system uptime is %d seconds", uptime
);
830 startup_time
-= uptime
;
832 #elif defined(SOLARIS_KSTATS)
838 ksp
= kstat_lookup(kc
, "unix", 0, "system_misc");
839 if(ksp
&& (kstat_read(kc
, ksp
, NULL
) != -1))
841 void *ptr
= kstat_data_lookup(ksp
, "boot_time");
843 memcpy(&startup_time
, ptr
, sizeof(startup_time
));
845 syslog(LOG_ERR
, "cannot find boot_time kstat");
848 syslog(LOG_ERR
, "cannot open kstats for unix/0/system_misc: %m");
852 struct timeval boottime
;
853 size_t size
= sizeof(boottime
);
854 int name
[2] = { CTL_KERN
, KERN_BOOTTIME
};
855 if(sysctl(name
, 2, &boottime
, &size
, NULL
, 0) < 0)
857 syslog(LOG_ERR
, "sysctl(\"kern.boottime\") failed");
861 startup_time
= boottime
.tv_sec
;
867 /* structure containing variables used during "main loop"
868 * that are filled during the init */
869 struct runtime_vars
{
870 /* LAN IP addresses for SSDP traffic and HTTP */
871 /* moved to global vars */
872 int port
; /* HTTP Port */
874 int https_port
; /* HTTPS Port */
876 int notify_interval
; /* seconds between SSDP announces */
877 /* unused rules cleaning related variables : */
878 int clean_ruleset_threshold
; /* threshold for removing unused rules */
879 int clean_ruleset_interval
; /* (minimum) interval between checks */
883 * parse address with mask
884 * ex: 192.168.1.1/24 or 192.168.1.1/255.255.255.0
885 * When MULTIPLE_EXTERNAL_IP is enabled, the ip address of the
886 * external interface associated with the lan subnet follows.
887 * ex : 192.168.1.1/24 81.21.41.11
889 * Can also use the interface name (ie eth0)
895 parselanaddr(struct lan_addr_s
* lan_addr
, const char * str
)
901 memset(lan_addr
, 0, sizeof(struct lan_addr_s
));
903 while(*p
&& *p
!= '/' && !isspace(*p
))
906 if(!isdigit(str
[0]) && n
< (int)sizeof(lan_addr
->ifname
))
908 /* not starting with a digit : suppose it is an interface name */
909 memcpy(lan_addr
->ifname
, str
, n
);
910 lan_addr
->ifname
[n
] = '\0';
911 if(getifaddr(lan_addr
->ifname
, lan_addr
->str
, sizeof(lan_addr
->str
),
912 &lan_addr
->addr
, &lan_addr
->mask
) < 0) {
914 fprintf(stderr
, "interface \"%s\" has no IPv4 address\n", str
);
915 lan_addr
->str
[0] = '\0';
916 lan_addr
->addr
.s_addr
= htonl(0x00000000u
);
917 lan_addr
->mask
.s_addr
= htonl(0xffffffffu
);
918 #else /* ENABLE_IPV6 */
920 #endif /* ENABLE_IPV6 */
922 /*printf("%s => %s\n", lan_addr->ifname, lan_addr->str);*/
928 memcpy(lan_addr
->str
, str
, n
);
929 lan_addr
->str
[n
] = '\0';
930 if(!inet_aton(lan_addr
->str
, &lan_addr
->addr
))
935 const char * q
= ++p
;
936 while(*p
&& isdigit(*p
))
940 /* parse mask in /255.255.255.0 format */
941 while(*p
&& (*p
=='.' || isdigit(*p
)))
948 if(!inet_aton(tmp
, &lan_addr
->mask
))
953 /* it is a /24 format */
955 if(nbits
> 32 || nbits
< 0)
957 lan_addr
->mask
.s_addr
= htonl(nbits
? (0xffffffffu
<< (32 - nbits
)) : 0);
960 else if(lan_addr
->mask
.s_addr
== 0)
962 /* by default, networks are /24 */
963 lan_addr
->mask
.s_addr
= htonl(0xffffff00u
);
965 #ifdef MULTIPLE_EXTERNAL_IP
967 while(*p
&& isspace(*p
))
970 /* parse the exteral ip address to associate with this subnet */
972 while(p
[n
] && !isspace(*p
))
975 memcpy(lan_addr
->ext_ip_str
, p
, n
);
976 lan_addr
->ext_ip_str
[n
] = '\0';
977 if(!inet_aton(lan_addr
->ext_ip_str
, &lan_addr
->ext_ip_addr
)) {
979 fprintf(stderr
, "Error parsing address : %s\n", lan_addr
->ext_ip_str
);
985 if(lan_addr
->ifname
[0] != '\0')
987 lan_addr
->index
= if_nametoindex(lan_addr
->ifname
);
988 if(lan_addr
->index
== 0)
989 fprintf(stderr
, "Cannot get index for network interface %s",
995 "Error: please specify LAN network interface by name instead of IPv4 address : %s\n",
1002 fprintf(stderr
, "Error parsing address/mask (or interface name) : %s\n",
1007 /* fill uuidvalue_wan and uuidvalue_wcd based on uuidvalue_igd */
1008 void complete_uuidvalues(void)
1011 len
= strlen(uuidvalue_igd
);
1012 memcpy(uuidvalue_wan
, uuidvalue_igd
, len
+1);
1013 switch(uuidvalue_wan
[len
-1]) {
1015 uuidvalue_wan
[len
-1] = 'a';
1018 uuidvalue_wan
[len
-1] = '0';
1021 uuidvalue_wan
[len
-1]++;
1023 memcpy(uuidvalue_wcd
, uuidvalue_wan
, len
+1);
1024 switch(uuidvalue_wcd
[len
-1]) {
1026 uuidvalue_wcd
[len
-1] = 'a';
1029 uuidvalue_wcd
[len
-1] = '0';
1032 uuidvalue_wcd
[len
-1]++;
1037 * 1) read configuration file
1038 * 2) read command line arguments
1041 * 5) check and write pid file
1042 * 6) set startup time stamp
1043 * 7) compute presentation URL
1044 * 8) set signal handlers
1045 * 9) init random generator (srandom())
1046 * 10) init redirection engine
1047 * 11) reload mapping from leasefile */
1049 init(int argc
, char * * argv
, struct runtime_vars
* v
)
1055 struct sigaction sa
;
1056 /*const char * logfilename = 0;*/
1057 const char * presurl
= 0;
1058 #ifndef DISABLE_CONFIG_FILE
1059 int options_flag
= 0;
1060 const char * optionsfile
= DEFAULT_CONFIG
;
1061 #endif /* DISABLE_CONFIG_FILE */
1062 struct lan_addr_s
* lan_addr
;
1063 struct lan_addr_s
* lan_addr2
;
1065 /* only print usage if -h is used */
1066 for(i
=1; i
<argc
; i
++)
1068 if(0 == strcmp(argv
[i
], "-h"))
1071 #ifndef DISABLE_CONFIG_FILE
1072 /* first check if "-f" option is used */
1073 for(i
=2; i
<argc
; i
++)
1075 if(0 == strcmp(argv
[i
-1], "-f"))
1077 optionsfile
= argv
[i
];
1082 #endif /* DISABLE_CONFIG_FILE */
1084 /* set initial values */
1085 SETFLAG(ENABLEUPNPMASK
); /* UPnP is enabled by default */
1087 ipv6_bind_addr
= in6addr_any
;
1088 #endif /* ENABLE_IPV6 */
1090 LIST_INIT(&lan_addrs
);
1095 v
->notify_interval
= 30; /* seconds between SSDP announces */
1096 v
->clean_ruleset_threshold
= 20;
1097 v
->clean_ruleset_interval
= 0; /* interval between ruleset check. 0=disabled */
1098 #ifndef DISABLE_CONFIG_FILE
1099 /* read options file first since
1100 * command line arguments have final say */
1101 if(readoptionsfile(optionsfile
) < 0)
1103 /* only error if file exists or using -f */
1104 if(access(optionsfile
, F_OK
) == 0 || options_flag
)
1105 fprintf(stderr
, "Error reading configuration file %s\n", optionsfile
);
1109 for(i
=0; i
<(int)num_options
; i
++)
1111 switch(ary_options
[i
].id
)
1113 case UPNPEXT_IFNAME
:
1114 ext_if_name
= ary_options
[i
].value
;
1117 use_ext_ip_addr
= ary_options
[i
].value
;
1119 case UPNPLISTENING_IP
:
1120 lan_addr
= (struct lan_addr_s
*) malloc(sizeof(struct lan_addr_s
));
1121 if (lan_addr
== NULL
)
1123 fprintf(stderr
, "malloc(sizeof(struct lan_addr_s)): %m");
1126 if(parselanaddr(lan_addr
, ary_options
[i
].value
) != 0)
1128 fprintf(stderr
, "can't parse \"%s\" as a valid "
1132 "interface name\n", ary_options
[i
].value
);
1136 LIST_INSERT_HEAD(&lan_addrs
, lan_addr
, list
);
1139 case UPNPIPV6_LISTENING_IP
:
1140 if (inet_pton(AF_INET6
, ary_options
[i
].value
, &ipv6_bind_addr
) < 1)
1142 fprintf(stderr
, "can't parse \"%s\" as valid IPv6 listening address", ary_options
[i
].value
);
1145 #endif /* ENABLE_IPV6 */
1147 v
->port
= atoi(ary_options
[i
].value
);
1151 v
->https_port
= atoi(ary_options
[i
].value
);
1154 case UPNPBITRATE_UP
:
1155 upstream_bitrate
= strtoul(ary_options
[i
].value
, 0, 0);
1157 case UPNPBITRATE_DOWN
:
1158 downstream_bitrate
= strtoul(ary_options
[i
].value
, 0, 0);
1160 case UPNPPRESENTATIONURL
:
1161 presurl
= ary_options
[i
].value
;
1163 #ifdef ENABLE_MANUFACTURER_INFO_CONFIGURATION
1164 case UPNPFRIENDLY_NAME
:
1165 strncpy(friendly_name
, ary_options
[i
].value
, FRIENDLY_NAME_MAX_LEN
);
1166 friendly_name
[FRIENDLY_NAME_MAX_LEN
-1] = '\0';
1168 case UPNPMANUFACTURER_NAME
:
1169 strncpy(manufacturer_name
, ary_options
[i
].value
, MANUFACTURER_NAME_MAX_LEN
);
1170 manufacturer_name
[MANUFACTURER_NAME_MAX_LEN
-1] = '\0';
1172 case UPNPMANUFACTURER_URL
:
1173 strncpy(manufacturer_url
, ary_options
[i
].value
, MANUFACTURER_URL_MAX_LEN
);
1174 manufacturer_url
[MANUFACTURER_URL_MAX_LEN
-1] = '\0';
1176 case UPNPMODEL_NAME
:
1177 strncpy(model_name
, ary_options
[i
].value
, MODEL_NAME_MAX_LEN
);
1178 model_name
[MODEL_NAME_MAX_LEN
-1] = '\0';
1180 case UPNPMODEL_DESCRIPTION
:
1181 strncpy(model_description
, ary_options
[i
].value
, MODEL_DESCRIPTION_MAX_LEN
);
1182 model_description
[MODEL_DESCRIPTION_MAX_LEN
-1] = '\0';
1185 strncpy(model_url
, ary_options
[i
].value
, MODEL_URL_MAX_LEN
);
1186 model_url
[MODEL_URL_MAX_LEN
-1] = '\0';
1188 #endif /* ENABLE_MANUFACTURER_INFO_CONFIGURATION */
1189 #ifdef USE_NETFILTER
1190 case UPNPFORWARDCHAIN
:
1191 miniupnpd_forward_chain
= ary_options
[i
].value
;
1194 miniupnpd_nat_chain
= ary_options
[i
].value
;
1196 #endif /* USE_NETFILTER */
1197 case UPNPNOTIFY_INTERVAL
:
1198 v
->notify_interval
= atoi(ary_options
[i
].value
);
1200 case UPNPSYSTEM_UPTIME
:
1201 if(strcmp(ary_options
[i
].value
, "yes") == 0)
1202 SETFLAG(SYSUPTIMEMASK
); /*sysuptime = 1;*/
1204 #if defined(USE_PF) || defined(USE_IPF)
1205 case UPNPPACKET_LOG
:
1206 if(strcmp(ary_options
[i
].value
, "yes") == 0)
1207 SETFLAG(LOGPACKETSMASK
); /*logpackets = 1;*/
1209 #endif /* defined(USE_PF) || defined(USE_IPF) */
1211 strncpy(uuidvalue_igd
+5, ary_options
[i
].value
,
1212 strlen(uuidvalue_igd
+5) + 1);
1213 complete_uuidvalues();
1216 strncpy(serialnumber
, ary_options
[i
].value
, SERIALNUMBER_MAX_LEN
);
1217 serialnumber
[SERIALNUMBER_MAX_LEN
-1] = '\0';
1219 case UPNPMODEL_NUMBER
:
1220 strncpy(modelnumber
, ary_options
[i
].value
, MODELNUMBER_MAX_LEN
);
1221 modelnumber
[MODELNUMBER_MAX_LEN
-1] = '\0';
1223 case UPNPCLEANTHRESHOLD
:
1224 v
->clean_ruleset_threshold
= atoi(ary_options
[i
].value
);
1226 case UPNPCLEANINTERVAL
:
1227 v
->clean_ruleset_interval
= atoi(ary_options
[i
].value
);
1231 anchor_name
= ary_options
[i
].value
;
1234 queue
= ary_options
[i
].value
;
1237 tag
= ary_options
[i
].value
;
1240 #ifdef ENABLE_NATPMP
1241 case UPNPENABLENATPMP
:
1242 if(strcmp(ary_options
[i
].value
, "yes") == 0)
1243 SETFLAG(ENABLENATPMPMASK
); /*enablenatpmp = 1;*/
1245 if(atoi(ary_options
[i
].value
))
1246 SETFLAG(ENABLENATPMPMASK
);
1247 /*enablenatpmp = atoi(ary_options[i].value);*/
1249 #endif /* ENABLE_NATPMP */
1251 case UPNPPCPMINLIFETIME
:
1252 min_lifetime
= atoi(ary_options
[i
].value
);
1253 if (min_lifetime
> 120 ) {
1257 case UPNPPCPMAXLIFETIME
:
1258 max_lifetime
= atoi(ary_options
[i
].value
);
1259 if (max_lifetime
> 86400 ) {
1260 max_lifetime
= 86400;
1263 case UPNPPCPALLOWTHIRDPARTY
:
1264 if(strcmp(ary_options
[i
].value
, "yes") == 0)
1265 SETFLAG(PCP_ALLOWTHIRDPARTYMASK
);
1267 #endif /* ENABLE_PCP */
1268 #ifdef PF_ENABLE_FILTER_RULES
1269 case UPNPQUICKRULES
:
1270 if(strcmp(ary_options
[i
].value
, "no") == 0)
1271 SETFLAG(PFNOQUICKRULESMASK
);
1273 #endif /* PF_ENABLE_FILTER_RULES */
1275 if(strcmp(ary_options
[i
].value
, "yes") != 0)
1276 CLEARFLAG(ENABLEUPNPMASK
);
1278 case UPNPSECUREMODE
:
1279 if(strcmp(ary_options
[i
].value
, "yes") == 0)
1280 SETFLAG(SECUREMODEMASK
);
1282 #ifdef ENABLE_LEASEFILE
1284 lease_file
= ary_options
[i
].value
;
1286 #endif /* ENABLE_LEASEFILE */
1287 case UPNPMINISSDPDSOCKET
:
1288 minissdpdsocketpath
= ary_options
[i
].value
;
1291 fprintf(stderr
, "Unknown option in file %s\n",
1296 /* if lifetimes are inverse */
1297 if (min_lifetime
>= max_lifetime
) {
1298 fprintf(stderr
, "Minimum lifetime (%lu) is greater than or equal to maximum lifetime (%lu).\n", min_lifetime
, max_lifetime
);
1299 fprintf(stderr
, "Check your configuration file.\n");
1302 #endif /* ENABLE_PCP */
1304 #endif /* DISABLE_CONFIG_FILE */
1306 /* command line arguments processing */
1307 for(i
=1; i
<argc
; i
++)
1311 fprintf(stderr
, "Unknown option: %s\n", argv
[i
]);
1313 else switch(argv
[i
][1])
1317 upnp_bootid
= (unsigned int)strtoul(argv
[++i
], NULL
, 10);
1319 fprintf(stderr
, "Option -%c takes one argument.\n", argv
[i
][1]);
1323 use_ext_ip_addr
= argv
[++i
];
1325 fprintf(stderr
, "Option -%c takes one argument.\n", argv
[i
][1]);
1329 v
->notify_interval
= atoi(argv
[++i
]);
1331 fprintf(stderr
, "Option -%c takes one argument.\n", argv
[i
][1]);
1335 v
->clean_ruleset_interval
= atoi(argv
[++i
]);
1337 fprintf(stderr
, "Option -%c takes one argument.\n", argv
[i
][1]);
1341 strncpy(uuidvalue_igd
+5, argv
[++i
], strlen(uuidvalue_igd
+5) + 1);
1342 complete_uuidvalues();
1344 fprintf(stderr
, "Option -%c takes one argument.\n", argv
[i
][1]);
1346 #ifdef ENABLE_MANUFACTURER_INFO_CONFIGURATION
1349 strncpy(friendly_name
, argv
[++i
], FRIENDLY_NAME_MAX_LEN
);
1351 fprintf(stderr
, "Option -%c takes one argument.\n", argv
[i
][1]);
1352 friendly_name
[FRIENDLY_NAME_MAX_LEN
-1] = '\0';
1354 #endif /* ENABLE_MANUFACTURER_INFO_CONFIGURATION */
1357 strncpy(serialnumber
, argv
[++i
], SERIALNUMBER_MAX_LEN
);
1359 fprintf(stderr
, "Option -%c takes one argument.\n", argv
[i
][1]);
1360 serialnumber
[SERIALNUMBER_MAX_LEN
-1] = '\0';
1364 strncpy(modelnumber
, argv
[++i
], MODELNUMBER_MAX_LEN
);
1366 fprintf(stderr
, "Option -%c takes one argument.\n", argv
[i
][1]);
1367 modelnumber
[MODELNUMBER_MAX_LEN
-1] = '\0';
1369 #ifdef ENABLE_NATPMP
1371 /*enablenatpmp = 1;*/
1372 SETFLAG(ENABLENATPMPMASK
);
1374 #endif /* ENABLE_NATPMP */
1377 SETFLAG(SYSUPTIMEMASK
);
1380 logfilename = argv[++i];
1382 #if defined(USE_PF) || defined(USE_IPF)
1385 SETFLAG(LOGPACKETSMASK
);
1387 #endif /* defined(USE_PF) || defined(USE_IPF) */
1389 SETFLAG(SECUREMODEMASK
);
1393 ext_if_name
= argv
[++i
];
1395 fprintf(stderr
, "Option -%c takes one argument.\n", argv
[i
][1]);
1402 fprintf(stderr
, "Option -%c takes one argument.\n", argv
[i
][1]);
1408 fprintf(stderr
, "Option -%c takes one argument.\n", argv
[i
][1]);
1413 v
->port
= atoi(argv
[++i
]);
1415 fprintf(stderr
, "Option -%c takes one argument.\n", argv
[i
][1]);
1420 v
->https_port
= atoi(argv
[++i
]);
1422 fprintf(stderr
, "Option -%c takes one argument.\n", argv
[i
][1]);
1424 #endif /* ENABLE_HTTPS */
1425 #ifdef ENABLE_NFQUEUE
1429 nfqueue
= atoi(argv
[++i
]);
1432 fprintf(stderr
, "Option -%c takes one argument.\n", argv
[i
][1]);
1437 if(n_nfqix
< MAX_LAN_ADDR
) {
1438 nfqix
[n_nfqix
++] = if_nametoindex(argv
[i
]);
1440 fprintf(stderr
,"Too many nfq interfaces. Ignoring %s\n", argv
[i
]);
1443 fprintf(stderr
, "Option -%c takes one argument.\n", argv
[i
][1]);
1446 #endif /* ENABLE_NFQUEUE */
1449 pidfilename
= argv
[++i
];
1451 fprintf(stderr
, "Option -%c takes one argument.\n", argv
[i
][1]);
1458 presurl
= argv
[++i
];
1460 fprintf(stderr
, "Option -%c takes one argument.\n", argv
[i
][1]);
1465 downstream_bitrate
= strtoul(argv
[++i
], 0, 0);
1466 upstream_bitrate
= strtoul(argv
[++i
], 0, 0);
1469 fprintf(stderr
, "Option -%c takes two arguments.\n", argv
[i
][1]);
1472 #ifndef MULTIPLE_EXTERNAL_IP
1476 lan_addr
= (struct lan_addr_s
*) malloc(sizeof(struct lan_addr_s
));
1477 if (lan_addr
== NULL
)
1479 fprintf(stderr
, "malloc(sizeof(struct lan_addr_s)): %m");
1482 if(parselanaddr(lan_addr
, argv
[i
]) != 0)
1484 fprintf(stderr
, "can't parse \"%s\" as a valid "
1487 #endif /* #ifndef ENABLE_IPV6 */
1488 "interface name\n", argv
[i
]);
1492 /* check if we already have this address */
1493 for(lan_addr2
= lan_addrs
.lh_first
; lan_addr2
!= NULL
; lan_addr2
= lan_addr2
->list
.le_next
)
1495 if (0 == strncmp(lan_addr2
->str
, lan_addr
->str
, 15))
1498 if (lan_addr2
== NULL
)
1499 LIST_INSERT_HEAD(&lan_addrs
, lan_addr
, list
);
1502 fprintf(stderr
, "Option -%c takes one argument.\n", argv
[i
][1]);
1503 #else /* #ifndef MULTIPLE_EXTERNAL_IP */
1506 char *val
= calloc((strlen(argv
[i
+1]) + strlen(argv
[i
+2]) + 2), sizeof(char));
1509 fprintf(stderr
, "memory allocation error for listen address storage\n");
1512 sprintf(val
, "%s %s", argv
[i
+1], argv
[i
+2]);
1514 lan_addr
= (struct lan_addr_s
*) malloc(sizeof(struct lan_addr_s
));
1515 if (lan_addr
== NULL
)
1517 fprintf(stderr
, "malloc(sizeof(struct lan_addr_s)): %m");
1521 if(parselanaddr(lan_addr
, val
) != 0)
1523 fprintf(stderr
, "can't parse \"%s\" as a valid LAN address or interface name\n", val
);
1528 /* check if we already have this address */
1529 for(lan_addr2
= lan_addrs
.lh_first
; lan_addr2
!= NULL
; lan_addr2
= lan_addr2
->list
.le_next
)
1531 if (0 == strncmp(lan_addr2
->str
, lan_addr
->str
, 15))
1534 if (lan_addr2
== NULL
)
1535 LIST_INSERT_HEAD(&lan_addrs
, lan_addr
, list
);
1541 fprintf(stderr
, "Option -%c takes two arguments.\n", argv
[i
][1]);
1542 #endif /* #ifndef MULTIPLE_EXTERNAL_IP */
1547 tmp
= realloc(upnppermlist
, sizeof(struct upnpperm
) * (num_upnpperm
+1));
1549 fprintf(stderr
, "memory allocation error for permission\n");
1552 if(read_permission_line(upnppermlist
+ num_upnpperm
, argv
[++i
]) >= 0) {
1555 fprintf(stderr
, "Permission rule parsing error :\n%s\n", argv
[i
]);
1559 fprintf(stderr
, "Option -%c takes one argument.\n", argv
[i
][1]);
1562 i
++; /* discarding, the config file is already read */
1565 fprintf(stderr
, "Unknown option: %s\n", argv
[i
]);
1568 if(!ext_if_name
|| !lan_addrs
.lh_first
)
1570 /* bad configuration */
1581 if(daemon(0, 0)<0) {
1590 openlog_option
= LOG_PID
|LOG_CONS
;
1593 openlog_option
|= LOG_PERROR
; /* also log on stderr */
1596 openlog("miniupnpd", openlog_option
, LOG_MINIUPNPD
);
1600 /* speed things up and ignore LOG_INFO and LOG_DEBUG */
1601 setlogmask(LOG_UPTO(LOG_NOTICE
));
1604 if(checkforrunning(pidfilename
) < 0)
1606 syslog(LOG_ERR
, "MiniUPnPd is already running. EXITING");
1611 syslog(LOG_NOTICE
, "version " MINIUPNPD_VERSION
" started");
1614 set_startup_time(GETFLAG(SYSUPTIMEMASK
));
1616 /* presentation url */
1619 strncpy(presentationurl
, presurl
, PRESENTATIONURL_MAX_LEN
);
1620 presentationurl
[PRESENTATIONURL_MAX_LEN
-1] = '\0';
1624 snprintf(presentationurl
, PRESENTATIONURL_MAX_LEN
,
1625 "http://%s/", lan_addrs
.lh_first
->str
);
1626 /*"http://%s:%d/", lan_addrs.lh_first->str, 80);*/
1629 /* set signal handler */
1630 memset(&sa
, 0, sizeof(struct sigaction
));
1631 sa
.sa_handler
= sigterm
;
1633 if(sigaction(SIGTERM
, &sa
, NULL
) < 0)
1635 syslog(LOG_ERR
, "Failed to set %s handler. EXITING", "SIGTERM");
1638 if(sigaction(SIGINT
, &sa
, NULL
) < 0)
1640 syslog(LOG_ERR
, "Failed to set %s handler. EXITING", "SIGINT");
1644 sa
.sa_handler
= sigusr2
;
1645 sigaction(SIGUSR2
, &sa
, NULL
);
1646 if(signal(SIGPIPE
, SIG_IGN
) == SIG_ERR
)
1648 sa
.sa_handler
= SIG_IGN
;
1649 if(sigaction(SIGPIPE
, &sa
, NULL
) < 0)
1652 syslog(LOG_ERR
, "Failed to ignore SIGPIPE signals");
1654 sa
.sa_handler
= sigusr1
;
1655 if(sigaction(SIGUSR1
, &sa
, NULL
) < 0)
1657 syslog(LOG_NOTICE
, "Failed to set %s handler", "SIGUSR1");
1660 /* initialize random number generator */
1661 srandom((unsigned int)time(NULL
));
1663 /* initialize redirection engine (and pinholes) */
1664 if(init_redirect() < 0)
1666 syslog(LOG_ERR
, "Failed to init redirection engine. EXITING");
1669 #ifdef ENABLE_UPNPPINHOLE
1670 #ifdef USE_NETFILTER
1675 if(writepidfile(pidfilename
, pid
) < 0)
1678 #ifdef ENABLE_LEASEFILE
1679 /*remove(lease_file);*/
1680 syslog(LOG_INFO
, "Reloading rules from lease file");
1681 reload_from_lease_file();
1690 fprintf(stderr
, "Usage:\n\t"
1692 #ifndef DISABLE_CONFIG_FILE
1695 "[-i ext_ifname] [-o ext_ip]\n"
1696 #ifndef MULTIPLE_EXTERNAL_IP
1697 "\t\t[-a listening_ip]"
1699 "\t\t[-a listening_ip ext_ip]"
1705 #if defined(USE_PF) || defined(USE_IPF)
1709 #ifdef ENABLE_NATPMP
1713 /*"[-l logfile] " not functionnal */
1714 "\t\t[-u uuid] [-s serial] [-m model_number] \n"
1715 "\t\t[-t notify_interval] [-P pid_filename] "
1716 #ifdef ENABLE_MANUFACTURER_INFO_CONFIGURATION
1719 "\n\t\t[-B down up] [-w url] [-r clean_ruleset_interval]\n"
1721 "\t\t[-q queue] [-T tag]\n"
1723 #ifdef ENABLE_NFQUEUE
1724 "\t\t[-Q queue] [-n name]\n"
1726 "\t\t[-A \"permission rule\"] [-b BOOTID]\n"
1727 "\nNotes:\n\tThere can be one or several listening_ips.\n"
1728 "\tNotify interval is in seconds. Default is 30 seconds.\n"
1729 "\tDefault pid file is '%s'.\n"
1730 "\tDefault config file is '%s'.\n"
1731 "\tWith -d miniupnpd will run as a standard program.\n"
1732 #if defined(USE_PF) || defined(USE_IPF)
1733 "\t-L sets packet log in pf and ipf on.\n"
1735 "\t-S sets \"secure\" mode : clients can only add mappings to their own ip\n"
1736 "\t-U causes miniupnpd to report system uptime instead "
1737 "of daemon uptime.\n"
1738 #ifdef ENABLE_NATPMP
1739 "\t-N enables NAT-PMP functionality.\n"
1741 "\t-B sets bitrates reported by daemon in bits per second.\n"
1742 "\t-w sets the presentation url. Default is http address on port 80\n"
1744 "\t-q sets the ALTQ queue in pf.\n"
1745 "\t-T sets the tag name in pf.\n"
1747 #ifdef ENABLE_NFQUEUE
1748 "\t-Q sets the queue number that is used by NFQUEUE.\n"
1749 "\t-n sets the name of the interface(s) that packets will arrive on.\n"
1751 "\t-A use following syntax for permission rules :\n"
1752 "\t (allow|deny) (external port range) ip/mask (internal port range)\n"
1754 "\t \"allow 1024-65535 192.168.1.0/24 1024-65535\"\n"
1755 "\t \"deny 0-65535 0.0.0.0/0 0-65535\"\n"
1756 "\t-b sets the value of BOOTID.UPNP.ORG SSDP header\n"
1757 "\t-h prints this help and quits.\n"
1758 "", argv
[0], pidfilename
, DEFAULT_CONFIG
);
1763 /* process HTTP or SSDP requests */
1765 main(int argc
, char * * argv
)
1768 int shttpl
= -1; /* socket for HTTP */
1769 #if defined(V6SOCKETS_ARE_V6ONLY) && defined(ENABLE_IPV6)
1770 int shttpl_v4
= -1; /* socket for HTTP (ipv4 only) */
1773 int shttpsl
= -1; /* socket for HTTPS */
1774 #if defined(V6SOCKETS_ARE_V6ONLY) && defined(ENABLE_IPV6)
1775 int shttpsl_v4
= -1; /* socket for HTTPS (ipv4 only) */
1777 #endif /* ENABLE_HTTPS */
1778 int sudp
= -1; /* IP v4 socket for receiving SSDP */
1780 int sudpv6
= -1; /* IP v6 socket for receiving SSDP */
1782 #ifdef ENABLE_NATPMP
1783 int * snatpmp
= NULL
; /* also used for PCP */
1785 #if defined(ENABLE_IPV6) && defined(ENABLE_PCP)
1788 #ifdef ENABLE_NFQUEUE
1791 #ifdef USE_IFACEWATCHER
1792 int sifacewatcher
= -1;
1795 int * snotify
= NULL
;
1797 LIST_HEAD(httplisthead
, upnphttp
) upnphttphead
;
1798 struct upnphttp
* e
= 0;
1799 struct upnphttp
* next
;
1800 fd_set readset
; /* for select() */
1802 struct timeval timeout
, timeofday
, lasttimeofday
= {0, 0};
1804 #ifdef USE_MINIUPNPDCTL
1806 LIST_HEAD(ctlstructhead
, ctlelem
) ctllisthead
;
1807 struct ctlelem
* ectl
;
1808 struct ctlelem
* ectlnext
;
1810 struct runtime_vars v
;
1811 /* variables used for the unused-rule cleanup process */
1812 struct rule_state
* rule_list
= 0;
1813 struct timeval checktime
= {0, 0};
1814 struct lan_addr_s
* lan_addr
;
1815 #ifdef ENABLE_UPNPPINHOLE
1816 unsigned int next_pinhole_ts
;
1819 if(init(argc
, argv
, &v
) != 0)
1824 #endif /* ENABLE_HTTPS */
1825 /* count lan addrs */
1827 for(lan_addr
= lan_addrs
.lh_first
; lan_addr
!= NULL
; lan_addr
= lan_addr
->list
.le_next
)
1829 if(addr_count
> 0) {
1831 snotify
= calloc(addr_count
, sizeof(int));
1833 /* one for IPv4, one for IPv6 */
1834 snotify
= calloc(addr_count
* 2, sizeof(int));
1837 #ifdef ENABLE_NATPMP
1838 if(addr_count
> 0) {
1839 snatpmp
= malloc(addr_count
* sizeof(int));
1840 for(i
= 0; i
< addr_count
; i
++)
1845 LIST_INIT(&upnphttphead
);
1846 #ifdef USE_MINIUPNPDCTL
1847 LIST_INIT(&ctllisthead
);
1851 #ifdef ENABLE_NATPMP
1852 !GETFLAG(ENABLENATPMPMASK
) &&
1854 !GETFLAG(ENABLEUPNPMASK
) ) {
1855 syslog(LOG_ERR
, "Why did you run me anyway?");
1859 syslog(LOG_INFO
, "version " MINIUPNPD_VERSION
" starting%s%sext if %s BOOTID=%u",
1860 #ifdef ENABLE_NATPMP
1862 GETFLAG(ENABLENATPMPMASK
) ? " NAT-PMP/PCP " : " ",
1864 GETFLAG(ENABLENATPMPMASK
) ? " NAT-PMP " : " ",
1869 GETFLAG(ENABLEUPNPMASK
) ? "UPnP-IGD " : "",
1870 ext_if_name
, upnp_bootid
);
1872 if(GETFLAG(ENABLEUPNPMASK
))
1874 unsigned short listen_port
;
1875 listen_port
= (v
.port
> 0) ? v
.port
: 0;
1876 /* open socket for HTTP connections. Listen on the 1st LAN address */
1878 shttpl
= OpenAndConfHTTPSocket(&listen_port
, 1);
1879 #else /* ENABLE_IPV6 */
1880 shttpl
= OpenAndConfHTTPSocket(&listen_port
);
1881 #endif /* ENABLE_IPV6 */
1884 syslog(LOG_ERR
, "Failed to open socket for HTTP. EXITING");
1887 v
.port
= listen_port
;
1888 syslog(LOG_NOTICE
, "HTTP listening on port %d", v
.port
);
1889 #if defined(V6SOCKETS_ARE_V6ONLY) && defined(ENABLE_IPV6)
1890 if(!GETFLAG(IPV6DISABLEDMASK
))
1892 shttpl_v4
= OpenAndConfHTTPSocket(&listen_port
, 0);
1895 syslog(LOG_ERR
, "Failed to open socket for HTTP on port %hu (IPv4). EXITING", v
.port
);
1899 #endif /* V6SOCKETS_ARE_V6ONLY */
1902 listen_port
= (v
.https_port
> 0) ? v
.https_port
: 0;
1904 shttpsl
= OpenAndConfHTTPSocket(&listen_port
, 1);
1905 #else /* ENABLE_IPV6 */
1906 shttpsl
= OpenAndConfHTTPSocket(&listen_port
);
1907 #endif /* ENABLE_IPV6 */
1910 syslog(LOG_ERR
, "Failed to open socket for HTTPS. EXITING");
1913 v
.https_port
= listen_port
;
1914 syslog(LOG_NOTICE
, "HTTPS listening on port %d", v
.https_port
);
1915 #if defined(V6SOCKETS_ARE_V6ONLY) && defined(ENABLE_IPV6)
1916 shttpsl_v4
= OpenAndConfHTTPSocket(&listen_port
, 0);
1919 syslog(LOG_ERR
, "Failed to open socket for HTTPS on port %hu (IPv4). EXITING", v
.https_port
);
1922 #endif /* V6SOCKETS_ARE_V6ONLY */
1923 #endif /* ENABLE_HTTPS */
1925 if(find_ipv6_addr(lan_addrs
.lh_first
? lan_addrs
.lh_first
->ifname
: NULL
,
1926 ipv6_addr_for_http_with_brackets
, sizeof(ipv6_addr_for_http_with_brackets
)) > 0) {
1927 syslog(LOG_NOTICE
, "HTTP IPv6 address given to control points : %s",
1928 ipv6_addr_for_http_with_brackets
);
1930 memcpy(ipv6_addr_for_http_with_brackets
, "[::1]", 6);
1931 syslog(LOG_WARNING
, "no HTTP IPv6 address, disabling IPv6");
1932 SETFLAG(IPV6DISABLEDMASK
);
1936 /* open socket for SSDP connections */
1937 sudp
= OpenAndConfSSDPReceiveSocket(0);
1940 syslog(LOG_NOTICE
, "Failed to open socket for receiving SSDP. Trying to use MiniSSDPd");
1941 if(SubmitServicesToMiniSSDPD(lan_addrs
.lh_first
->str
, v
.port
) < 0) {
1942 syslog(LOG_ERR
, "Failed to connect to MiniSSDPd. EXITING");
1947 if(!GETFLAG(IPV6DISABLEDMASK
))
1949 sudpv6
= OpenAndConfSSDPReceiveSocket(1);
1952 syslog(LOG_WARNING
, "Failed to open socket for receiving SSDP (IP v6).");
1957 /* open socket for sending notifications */
1958 if(OpenAndConfSSDPNotifySockets(snotify
) < 0)
1960 syslog(LOG_ERR
, "Failed to open sockets for sending SSDP notify "
1961 "messages. EXITING");
1965 #ifdef USE_IFACEWATCHER
1966 /* open socket for kernel notifications about new network interfaces */
1969 sifacewatcher
= OpenAndConfInterfaceWatchSocket();
1970 if (sifacewatcher
< 0)
1972 syslog(LOG_ERR
, "Failed to open socket for receiving network interface notifications");
1978 #ifdef ENABLE_NATPMP
1979 /* open socket for NAT PMP traffic */
1980 if(GETFLAG(ENABLENATPMPMASK
))
1982 if(OpenAndConfNATPMPSockets(snatpmp
) < 0)
1985 syslog(LOG_ERR
, "Failed to open sockets for NAT-PMP/PCP.");
1987 syslog(LOG_NOTICE
, "Listening for NAT-PMP/PCP traffic on port %u",
1992 syslog(LOG_ERR
, "Failed to open sockets for NAT PMP.");
1994 syslog(LOG_NOTICE
, "Listening for NAT-PMP traffic on port %u",
2001 #if defined(ENABLE_IPV6) && defined(ENABLE_PCP)
2002 spcp_v6
= OpenAndConfPCPv6Socket();
2005 /* for miniupnpdctl */
2006 #ifdef USE_MINIUPNPDCTL
2007 sctl
= OpenAndConfCtlUnixSocket("/var/run/miniupnpd.ctl");
2010 #ifdef ENABLE_NFQUEUE
2011 if ( nfqueue
!= -1 && n_nfqix
> 0) {
2012 nfqh
= OpenAndConfNFqueue();
2014 syslog(LOG_ERR
, "Failed to open fd for NFQUEUE.");
2017 syslog(LOG_NOTICE
, "Opened NFQUEUE %d",nfqueue
);
2029 /* Correct startup_time if it was set with a RTC close to 0 */
2030 if((startup_time
<60*60*24) && (time(NULL
)>60*60*24))
2032 set_startup_time(GETFLAG(SYSUPTIMEMASK
));
2034 /* send public address change notifications if needed */
2035 if(should_send_public_address_change_notif
)
2037 syslog(LOG_INFO
, "should send external iface address change notification(s)");
2038 #ifdef ENABLE_NATPMP
2039 if(GETFLAG(ENABLENATPMPMASK
))
2040 SendNATPMPPublicAddressChangeNotification(snatpmp
, addr_count
);
2042 #ifdef ENABLE_EVENTS
2043 if(GETFLAG(ENABLEUPNPMASK
))
2045 upnp_event_var_change_notify(EWanIPC
);
2048 should_send_public_address_change_notif
= 0;
2050 /* Check if we need to send SSDP NOTIFY messages and do it if
2052 if(gettimeofday(&timeofday
, 0) < 0)
2054 syslog(LOG_ERR
, "gettimeofday(): %m");
2055 timeout
.tv_sec
= v
.notify_interval
;
2056 timeout
.tv_usec
= 0;
2060 /* the comparaison is not very precise but who cares ? */
2061 if(timeofday
.tv_sec
>= (lasttimeofday
.tv_sec
+ v
.notify_interval
))
2063 if (GETFLAG(ENABLEUPNPMASK
))
2064 SendSSDPNotifies2(snotify
,
2065 (unsigned short)v
.port
,
2067 (unsigned short)v
.https_port
,
2069 v
.notify_interval
<< 1);
2070 memcpy(&lasttimeofday
, &timeofday
, sizeof(struct timeval
));
2071 timeout
.tv_sec
= v
.notify_interval
;
2072 timeout
.tv_usec
= 0;
2076 timeout
.tv_sec
= lasttimeofday
.tv_sec
+ v
.notify_interval
2078 if(timeofday
.tv_usec
> lasttimeofday
.tv_usec
)
2080 timeout
.tv_usec
= 1000000 + lasttimeofday
.tv_usec
2081 - timeofday
.tv_usec
;
2086 timeout
.tv_usec
= lasttimeofday
.tv_usec
- timeofday
.tv_usec
;
2090 /* remove unused rules */
2091 if( v
.clean_ruleset_interval
2092 && (timeofday
.tv_sec
>= checktime
.tv_sec
+ v
.clean_ruleset_interval
))
2096 remove_unused_rules(rule_list
);
2101 rule_list
= get_upnp_rules_state_list(v
.clean_ruleset_threshold
);
2103 memcpy(&checktime
, &timeofday
, sizeof(struct timeval
));
2105 /* Remove expired port mappings, based on UPnP IGD LeaseDuration
2106 * or NAT-PMP lifetime) */
2107 if(nextruletoclean_timestamp
2108 && ((unsigned int)timeofday
.tv_sec
>= nextruletoclean_timestamp
))
2110 syslog(LOG_DEBUG
, "cleaning expired Port Mappings");
2111 get_upnp_rules_state_list(0);
2113 if(nextruletoclean_timestamp
2114 && ((unsigned int)timeout
.tv_sec
>= (nextruletoclean_timestamp
- timeofday
.tv_sec
)))
2116 timeout
.tv_sec
= nextruletoclean_timestamp
- timeofday
.tv_sec
;
2117 timeout
.tv_usec
= 0;
2118 syslog(LOG_DEBUG
, "setting timeout to %u sec",
2119 (unsigned)timeout
.tv_sec
);
2121 #ifdef ENABLE_UPNPPINHOLE
2122 /* Clean up expired IPv6 PinHoles */
2123 next_pinhole_ts
= 0;
2124 upnp_clean_expired_pinholes(&next_pinhole_ts
);
2125 if(next_pinhole_ts
&&
2126 timeout
.tv_sec
>= (int)(next_pinhole_ts
- timeofday
.tv_sec
)) {
2127 timeout
.tv_sec
= next_pinhole_ts
- timeofday
.tv_sec
;
2128 timeout
.tv_usec
= 0;
2130 #endif /* ENABLE_UPNPPINHOLE */
2132 /* select open sockets (SSDP, HTTP listen, and all HTTP soap sockets) */
2138 FD_SET(sudp
, &readset
);
2139 max_fd
= MAX( max_fd
, sudp
);
2140 #ifdef USE_IFACEWATCHER
2141 if (sifacewatcher
>= 0)
2143 FD_SET(sifacewatcher
, &readset
);
2144 max_fd
= MAX(max_fd
, sifacewatcher
);
2150 FD_SET(shttpl
, &readset
);
2151 max_fd
= MAX( max_fd
, shttpl
);
2153 #if defined(V6SOCKETS_ARE_V6ONLY) && defined(ENABLE_IPV6)
2156 FD_SET(shttpl_v4
, &readset
);
2157 max_fd
= MAX( max_fd
, shttpl_v4
);
2163 FD_SET(shttpsl
, &readset
);
2164 max_fd
= MAX( max_fd
, shttpsl
);
2166 #if defined(V6SOCKETS_ARE_V6ONLY) && defined(ENABLE_IPV6)
2167 if (shttpsl_v4
>= 0)
2169 FD_SET(shttpsl_v4
, &readset
);
2170 max_fd
= MAX( max_fd
, shttpsl_v4
);
2173 #endif /* ENABLE_HTTPS */
2177 FD_SET(sudpv6
, &readset
);
2178 max_fd
= MAX( max_fd
, sudpv6
);
2182 #ifdef ENABLE_NFQUEUE
2185 FD_SET(nfqh
, &readset
);
2186 max_fd
= MAX( max_fd
, nfqh
);
2190 i
= 0; /* active HTTP connections count */
2191 for(e
= upnphttphead
.lh_first
; e
!= NULL
; e
= e
->entries
.le_next
)
2195 if(e
->state
<= EWaitingForHttpContent
)
2196 FD_SET(e
->socket
, &readset
);
2197 else if(e
->state
== ESendingAndClosing
)
2198 FD_SET(e
->socket
, &writeset
);
2201 max_fd
= MAX(max_fd
, e
->socket
);
2209 syslog(LOG_DEBUG
, "%d active incoming HTTP connections", i
);
2212 #ifdef ENABLE_NATPMP
2213 for(i
=0; i
<addr_count
; i
++) {
2214 if(snatpmp
[i
] >= 0) {
2215 FD_SET(snatpmp
[i
], &readset
);
2216 max_fd
= MAX( max_fd
, snatpmp
[i
]);
2220 #if defined(ENABLE_IPV6) && defined(ENABLE_PCP)
2222 FD_SET(spcp_v6
, &readset
);
2223 max_fd
= MAX(max_fd
, spcp_v6
);
2226 #ifdef USE_MINIUPNPDCTL
2228 FD_SET(sctl
, &readset
);
2229 max_fd
= MAX( max_fd
, sctl
);
2232 for(ectl
= ctllisthead
.lh_first
; ectl
; ectl
= ectl
->entries
.le_next
)
2234 if(ectl
->socket
>= 0) {
2235 FD_SET(ectl
->socket
, &readset
);
2236 max_fd
= MAX( max_fd
, ectl
->socket
);
2241 #ifdef ENABLE_EVENTS
2242 upnpevents_selectfds(&readset
, &writeset
, &max_fd
);
2245 /* queued "sendto" */
2247 struct timeval next_send
;
2248 i
= get_next_scheduled_send(&next_send
);
2251 syslog(LOG_DEBUG
, "%d queued sendto", i
);
2253 i
= get_sendto_fds(&writeset
, &max_fd
, &timeofday
);
2254 if(timeofday
.tv_sec
> next_send
.tv_sec
||
2255 (timeofday
.tv_sec
== next_send
.tv_sec
&& timeofday
.tv_usec
>= next_send
.tv_usec
)) {
2258 timeout
.tv_usec
= 0;
2261 struct timeval tmp_timeout
;
2262 tmp_timeout
.tv_sec
= (next_send
.tv_sec
- timeofday
.tv_sec
);
2263 tmp_timeout
.tv_usec
= (next_send
.tv_usec
- timeofday
.tv_usec
);
2264 if(tmp_timeout
.tv_usec
< 0) {
2265 tmp_timeout
.tv_usec
+= 1000000;
2266 tmp_timeout
.tv_sec
--;
2268 if(timeout
.tv_sec
> tmp_timeout
.tv_sec
2269 || (timeout
.tv_sec
== tmp_timeout
.tv_sec
&& timeout
.tv_usec
> tmp_timeout
.tv_usec
)) {
2270 timeout
.tv_sec
= tmp_timeout
.tv_sec
;
2271 timeout
.tv_usec
= tmp_timeout
.tv_usec
;
2277 if(select(max_fd
+1, &readset
, &writeset
, 0, &timeout
) < 0)
2279 if(quitting
) goto shutdown
;
2288 if(errno
== EINTR
) continue; /* interrupted by a signal, start again */
2289 syslog(LOG_ERR
, "select(all): %m");
2290 syslog(LOG_ERR
, "Failed to select open sockets. EXITING");
2291 return 1; /* very serious cause of error */
2293 i
= try_sendto(&writeset
);
2295 syslog(LOG_ERR
, "try_sendto failed to send %d packets", -i
);
2297 #ifdef USE_MINIUPNPDCTL
2298 for(ectl
= ctllisthead
.lh_first
; ectl
;)
2300 ectlnext
= ectl
->entries
.le_next
;
2301 if((ectl
->socket
>= 0) && FD_ISSET(ectl
->socket
, &readset
))
2305 l
= read(ectl
->socket
, buf
, sizeof(buf
));
2308 /*write(ectl->socket, buf, l);*/
2309 write_command_line(ectl
->socket
, argc
, argv
);
2310 #ifndef DISABLE_CONFIG_FILE
2311 write_option_list(ectl
->socket
);
2313 write_permlist(ectl
->socket
, upnppermlist
, num_upnpperm
);
2314 write_upnphttp_details(ectl
->socket
, upnphttphead
.lh_first
);
2315 write_ctlsockets_list(ectl
->socket
, ctllisthead
.lh_first
);
2316 write_ruleset_details(ectl
->socket
);
2317 #ifdef ENABLE_EVENTS
2318 write_events_details(ectl
->socket
);
2320 /* close the socket */
2321 close(ectl
->socket
);
2326 close(ectl
->socket
);
2330 if(ectl
->socket
< 0)
2332 LIST_REMOVE(ectl
, entries
);
2337 if((sctl
>= 0) && FD_ISSET(sctl
, &readset
))
2340 struct sockaddr_un clientname
;
2341 struct ctlelem
* tmp
;
2342 socklen_t clientnamelen
= sizeof(struct sockaddr_un
);
2343 /*syslog(LOG_DEBUG, "sctl!");*/
2344 s
= accept(sctl
, (struct sockaddr
*)&clientname
,
2346 syslog(LOG_DEBUG
, "sctl! : '%s'", clientname
.sun_path
);
2347 tmp
= malloc(sizeof(struct ctlelem
));
2350 syslog(LOG_ERR
, "Unable to allocate memory for ctlelem in main()");
2356 LIST_INSERT_HEAD(&ctllisthead
, tmp
, entries
);
2360 #ifdef ENABLE_EVENTS
2361 upnpevents_processfds(&readset
, &writeset
);
2363 #ifdef ENABLE_NATPMP
2364 /* process NAT-PMP packets */
2365 for(i
=0; i
<addr_count
; i
++)
2367 if((snatpmp
[i
] >= 0) && FD_ISSET(snatpmp
[i
], &readset
))
2369 unsigned char msg_buff
[PCP_MAX_LEN
];
2370 struct sockaddr_in senderaddr
;
2371 socklen_t senderaddrlen
;
2373 memset(msg_buff
, 0, PCP_MAX_LEN
);
2374 senderaddrlen
= sizeof(senderaddr
);
2375 len
= ReceiveNATPMPOrPCPPacket(snatpmp
[i
],
2376 (struct sockaddr
*)&senderaddr
,
2379 msg_buff
, sizeof(msg_buff
));
2383 if (msg_buff
[0]==0) { /* version equals to 0 -> means NAT-PMP */
2384 /* Check if the packet is coming from a LAN to enforce RFC6886 :
2385 * The NAT gateway MUST NOT accept mapping requests destined to the NAT
2386 * gateway's external IP address or received on its external network
2387 * interface. Only packets received on the internal interface(s) with a
2388 * destination address matching the internal address(es) of the NAT
2389 * gateway should be allowed. */
2390 /* TODO : move to ProcessIncomingNATPMPPacket() ? */
2391 lan_addr
= get_lan_for_peer((struct sockaddr
*)&senderaddr
);
2392 if(lan_addr
== NULL
) {
2393 char sender_str
[64];
2394 sockaddr_to_string((struct sockaddr
*)&senderaddr
, sender_str
, sizeof(sender_str
));
2395 syslog(LOG_WARNING
, "NAT-PMP packet sender %s not from a LAN, ignoring",
2399 ProcessIncomingNATPMPPacket(snatpmp
[i
], msg_buff
, len
,
2401 } else { /* everything else can be PCP */
2402 ProcessIncomingPCPPacket(snatpmp
[i
], msg_buff
, len
,
2403 (struct sockaddr
*)&senderaddr
, NULL
);
2407 /* Check if the packet is coming from a LAN to enforce RFC6886 :
2408 * The NAT gateway MUST NOT accept mapping requests destined to the NAT
2409 * gateway's external IP address or received on its external network
2410 * interface. Only packets received on the internal interface(s) with a
2411 * destination address matching the internal address(es) of the NAT
2412 * gateway should be allowed. */
2413 /* TODO : move to ProcessIncomingNATPMPPacket() ? */
2414 lan_addr
= get_lan_for_peer((struct sockaddr
*)&senderaddr
);
2415 if(lan_addr
== NULL
) {
2416 char sender_str
[64];
2417 sockaddr_to_string((struct sockaddr
*)&senderaddr
, sender_str
, sizeof(sender_str
));
2418 syslog(LOG_WARNING
, "NAT-PMP packet sender %s not from a LAN, ignoring",
2422 ProcessIncomingNATPMPPacket(snatpmp
[i
], msg_buff
, len
, &senderaddr
);
2427 #if defined(ENABLE_IPV6) && defined(ENABLE_PCP)
2428 /* in IPv6, only PCP is supported, not NAT-PMP */
2429 if(spcp_v6
>= 0 && FD_ISSET(spcp_v6
, &readset
))
2431 unsigned char msg_buff
[PCP_MAX_LEN
];
2432 struct sockaddr_in6 senderaddr
;
2433 socklen_t senderaddrlen
;
2434 struct sockaddr_in6 receiveraddr
;
2436 memset(msg_buff
, 0, PCP_MAX_LEN
);
2437 senderaddrlen
= sizeof(senderaddr
);
2438 len
= ReceiveNATPMPOrPCPPacket(spcp_v6
,
2439 (struct sockaddr
*)&senderaddr
,
2442 msg_buff
, sizeof(msg_buff
));
2444 ProcessIncomingPCPPacket(spcp_v6
, msg_buff
, len
,
2445 (struct sockaddr
*)&senderaddr
,
2449 /* process SSDP packets */
2450 if(sudp
>= 0 && FD_ISSET(sudp
, &readset
))
2452 /*syslog(LOG_INFO, "Received UDP Packet");*/
2454 ProcessSSDPRequest(sudp
, (unsigned short)v
.port
, (unsigned short)v
.https_port
);
2456 ProcessSSDPRequest(sudp
, (unsigned short)v
.port
);
2460 if(sudpv6
>= 0 && FD_ISSET(sudpv6
, &readset
))
2462 syslog(LOG_INFO
, "Received UDP Packet (IPv6)");
2464 ProcessSSDPRequest(sudpv6
, (unsigned short)v
.port
, (unsigned short)v
.https_port
);
2466 ProcessSSDPRequest(sudpv6
, (unsigned short)v
.port
);
2470 #ifdef USE_IFACEWATCHER
2471 /* process kernel notifications */
2472 if (sifacewatcher
>= 0 && FD_ISSET(sifacewatcher
, &readset
))
2473 ProcessInterfaceWatchNotify(sifacewatcher
);
2476 /* process active HTTP connections */
2477 /* LIST_FOREACH macro is not available under linux */
2478 for(e
= upnphttphead
.lh_first
; e
!= NULL
; e
= e
->entries
.le_next
)
2482 if(FD_ISSET(e
->socket
, &readset
) ||
2483 FD_ISSET(e
->socket
, &writeset
))
2485 Process_upnphttp(e
);
2489 /* process incoming HTTP connections */
2490 if(shttpl
>= 0 && FD_ISSET(shttpl
, &readset
))
2492 struct upnphttp
* tmp
;
2493 tmp
= ProcessIncomingHTTP(shttpl
, "HTTP");
2496 LIST_INSERT_HEAD(&upnphttphead
, tmp
, entries
);
2499 #if defined(V6SOCKETS_ARE_V6ONLY) && defined(ENABLE_IPV6)
2500 if(shttpl_v4
>= 0 && FD_ISSET(shttpl_v4
, &readset
))
2502 struct upnphttp
* tmp
;
2503 tmp
= ProcessIncomingHTTP(shttpl_v4
, "HTTP");
2506 LIST_INSERT_HEAD(&upnphttphead
, tmp
, entries
);
2511 if(shttpsl
>= 0 && FD_ISSET(shttpsl
, &readset
))
2513 struct upnphttp
* tmp
;
2514 tmp
= ProcessIncomingHTTP(shttpsl
, "HTTPS");
2517 InitSSL_upnphttp(tmp
);
2518 LIST_INSERT_HEAD(&upnphttphead
, tmp
, entries
);
2521 #if defined(V6SOCKETS_ARE_V6ONLY) && defined(ENABLE_IPV6)
2522 if(shttpsl_v4
>= 0 && FD_ISSET(shttpsl_v4
, &readset
))
2524 struct upnphttp
* tmp
;
2525 tmp
= ProcessIncomingHTTP(shttpsl_v4
, "HTTPS");
2528 InitSSL_upnphttp(tmp
);
2529 LIST_INSERT_HEAD(&upnphttphead
, tmp
, entries
);
2533 #endif /* ENABLE_HTTPS */
2534 #ifdef ENABLE_NFQUEUE
2535 /* process NFQ packets */
2536 if(nfqh
>= 0 && FD_ISSET(nfqh
, &readset
))
2538 /* syslog(LOG_INFO, "Received NFQUEUE Packet");*/
2539 ProcessNFQUEUE(nfqh
);
2542 /* delete finished HTTP connections */
2543 for(e
= upnphttphead
.lh_first
; e
!= NULL
; )
2545 next
= e
->entries
.le_next
;
2546 if(e
->state
>= EToDelete
)
2548 LIST_REMOVE(e
, entries
);
2554 } /* end of main loop */
2557 syslog(LOG_NOTICE
, "shutting down MiniUPnPd");
2559 if (GETFLAG(ENABLEUPNPMASK
))
2562 if(SendSSDPGoodbye(snotify
, addr_count
) < 0)
2564 if(SendSSDPGoodbye(snotify
, addr_count
* 2) < 0)
2567 syslog(LOG_ERR
, "Failed to broadcast good-bye notifications");
2570 /* try to send pending packets */
2574 tomato_save("/etc/upnp/data");
2576 /* close out open sockets */
2577 while(upnphttphead
.lh_first
!= NULL
)
2579 e
= upnphttphead
.lh_first
;
2580 LIST_REMOVE(e
, entries
);
2584 if (sudp
>= 0) close(sudp
);
2585 if (shttpl
>= 0) close(shttpl
);
2586 #if defined(V6SOCKETS_ARE_V6ONLY) && defined(ENABLE_IPV6)
2587 if (shttpl_v4
>= 0) close(shttpl_v4
);
2590 if (sudpv6
>= 0) close(sudpv6
);
2592 #ifdef USE_IFACEWATCHER
2593 if(sifacewatcher
>= 0) close(sifacewatcher
);
2595 #ifdef ENABLE_NATPMP
2596 for(i
=0; i
<addr_count
; i
++) {
2604 #if defined(ENABLE_IPV6) && defined(ENABLE_PCP)
2611 #ifdef USE_MINIUPNPDCTL
2616 if(unlink("/var/run/miniupnpd.ctl") < 0)
2618 syslog(LOG_ERR
, "unlink() %m");
2623 if (GETFLAG(ENABLEUPNPMASK
))
2626 for(i
= 0; i
< addr_count
; i
++)
2628 for(i
= 0; i
< addr_count
* 2; i
++)
2633 /* remove pidfile */
2634 if(pidfilename
&& (unlink(pidfilename
) < 0))
2636 syslog(LOG_ERR
, "Failed to remove pidfile %s: %m", pidfilename
);
2640 while(lan_addrs
.lh_first
!= NULL
)
2642 lan_addr
= lan_addrs
.lh_first
;
2643 LIST_REMOVE(lan_addrs
.lh_first
, list
);
2650 #ifdef ENABLE_NATPMP
2655 #ifndef DISABLE_CONFIG_FILE