1 /* $Id: miniupnpd.c,v 1.173 2013/02/06 10:50:04 nanard Exp $ */
3 * http://miniupnp.free.fr/ or http://miniupnp.tuxfamily.org/
4 * (c) 2006-2013 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>
43 /* for BSD's sysctl */
44 #include <sys/sysctl.h>
48 #ifdef USE_MINIUPNPDCTL
53 #include "upnpglobalvars.h"
55 #include "upnpdescgen.h"
56 #include "miniupnpdpath.h"
57 #include "getifaddr.h"
61 #include "upnpredirect.h"
62 #include "upnppinhole.h"
63 #include "miniupnpdtypes.h"
64 #include "daemonize.h"
65 #include "upnpevents.h"
69 #include "commonrdr.h"
70 #include "upnputils.h"
71 #ifdef USE_IFACEWATCHER
72 #include "ifacewatcher.h"
74 #ifdef ENABLE_6FC_SERVICE
76 void init_iptpinhole(void);
80 #ifndef DEFAULT_CONFIG
81 #define DEFAULT_CONFIG "/etc/miniupnpd.conf"
84 #ifdef USE_MINIUPNPDCTL
87 LIST_ENTRY(ctlelem
) entries
;
93 static struct nfq_handle
*nfqHandle
;
94 static struct sockaddr_in ssdp
;
97 static int nfqueue_cb( struct nfq_q_handle
*qh
, struct nfgenmsg
*nfmsg
, struct nfq_data
*nfa
, void *data
) ;
98 int identify_ip_protocol (char *payload
);
99 int get_udp_dst_port (char *payload
);
102 /* variables used by signals */
103 static volatile sig_atomic_t quitting
= 0;
104 volatile sig_atomic_t should_send_public_address_change_notif
= 0;
108 static volatile int gotusr2
= 0;
110 static void sigusr2(int sig
)
115 static void tomato_save(const char *fname
)
117 unsigned short eport
;
118 unsigned short iport
;
119 unsigned int leaseduration
;
120 unsigned int timestamp
;
130 strcpy(tmp
, "/etc/upnp/saveXXXXXX");
131 if ((t
= mkstemp(tmp
)) != -1) {
132 if ((f
= fdopen(t
, "w")) != NULL
) {
134 while (upnp_get_redirection_infos_by_index(n
, &eport
, proto
, &iport
, iaddr
, sizeof(iaddr
), desc
, sizeof(desc
), rhost
, sizeof(rhost
), &leaseduration
) == 0) {
135 timestamp
= (leaseduration
> 0) ? time(NULL
) + leaseduration
: 0;
136 fprintf(f
, "%s %u %s %u [%s] %u\n", proto
, eport
, iaddr
, iport
, desc
, timestamp
);
149 static void tomato_load(void)
153 unsigned short eport
;
154 unsigned short iport
;
155 unsigned int leaseduration
;
156 unsigned int timestamp
;
163 if ((f
= fopen("/etc/upnp/data", "r")) != NULL
) {
164 current_time
= time(NULL
);
165 s
[sizeof(s
) - 1] = 0;
166 while (fgets(s
, sizeof(s
) - 1, f
)) {
167 if (sscanf(s
, "%3s %hu %31s %hu [%*s] %u", proto
, &eport
, iaddr
, &iport
, ×tamp
) >= 4) {
168 if (((a
= strchr(s
, '[')) != NULL
) && ((b
= strrchr(a
, ']')) != NULL
)) {
170 if (timestamp
> current_time
)
171 leaseduration
= current_time
- timestamp
;
175 leaseduration
= 0; /* default value */
179 upnp_redirect(rhost
, eport
, iaddr
, iport
, proto
, a
+ 1, leaseduration
);
187 ScanNATPMPforExpiration();
190 unlink("/etc/upnp/load");
193 static void tomato_delete(void)
197 unsigned short eport
;
198 unsigned short iport
;
199 unsigned int leaseduration
;
206 if ((f
= fopen("/etc/upnp/delete", "r")) != NULL
) {
207 s
[sizeof(s
) - 1] = 0;
208 while (fgets(s
, sizeof(s
) - 1, f
)) {
209 if (sscanf(s
, "%3s %hu", proto
, &eport
) == 2) {
210 if (proto
[0] == '*') {
211 n
= upnp_get_portmapping_number_of_entries();
213 if (upnp_get_redirection_infos_by_index(n
, &eport
, proto
, &iport
, iaddr
, sizeof(iaddr
), desc
, sizeof(desc
), rhost
, sizeof(rhost
), &leaseduration
) == 0) {
214 upnp_delete_redirection(eport
, proto
);
220 upnp_delete_redirection(eport
, proto
);
225 unlink("/etc/upnp/delete");
229 static void tomato_helper(void)
233 if (stat("/etc/upnp/delete", &st
) == 0) {
237 if (stat("/etc/upnp/load", &st
) == 0) {
241 if (stat("/etc/upnp/save", &st
) == 0) {
242 tomato_save("/etc/upnp/data");
243 unlink("/etc/upnp/save");
246 if (stat("/etc/upnp/info", &st
) == 0) {
247 tomato_save("/etc/upnp/data.info");
248 unlink("/etc/upnp/info");
251 #endif /* 1 (tomato) */
254 /* OpenAndConfHTTPSocket() :
255 * setup the socket used to handle incoming HTTP connections. */
257 OpenAndConfHTTPSocket(unsigned short port
)
262 struct sockaddr_in6 listenname
;
264 struct sockaddr_in listenname
;
266 socklen_t listenname_len
;
274 SOCK_STREAM
, 0)) < 0)
276 syslog(LOG_ERR
, "socket(http): %m");
280 if(setsockopt(s
, SOL_SOCKET
, SO_REUSEADDR
, &i
, sizeof(i
)) < 0)
282 syslog(LOG_WARNING
, "setsockopt(http, SO_REUSEADDR): %m");
285 /* enable this to force IPV6 only for IPV6 socket.
286 * see http://www.ietf.org/rfc/rfc3493.txt section 5.3 */
287 if(setsockopt(s
, IPPROTO_IPV6
, IPV6_V6ONLY
, &i
, sizeof(i
)) < 0)
289 syslog(LOG_WARNING
, "setsockopt(http, IPV6_V6ONLY): %m");
293 if(!set_non_blocking(s
))
295 syslog(LOG_WARNING
, "set_non_blocking(http): %m");
299 memset(&listenname
, 0, sizeof(struct sockaddr_in6
));
300 listenname
.sin6_family
= AF_INET6
;
301 listenname
.sin6_port
= htons(port
);
302 listenname
.sin6_addr
= in6addr_any
;
303 listenname_len
= sizeof(struct sockaddr_in6
);
305 listenname
.sin_family
= AF_INET
;
306 listenname
.sin_port
= htons(port
);
307 listenname
.sin_addr
.s_addr
= htonl(INADDR_ANY
);
308 listenname_len
= sizeof(struct sockaddr_in
);
311 if(bind(s
, (struct sockaddr
*)&listenname
, listenname_len
) < 0)
313 syslog(LOG_ERR
, "bind(http): %m");
320 syslog(LOG_ERR
, "listen(http): %m");
327 #ifdef ENABLE_NFQUEUE
329 int identify_ip_protocol(char *payload
) {
335 * This function returns the destination port of the captured packet UDP
337 int get_udp_dst_port(char *payload
) {
338 char *pkt_data_ptr
= NULL
;
339 pkt_data_ptr
= payload
+ sizeof(struct ip
);
341 /* Cast the UDP Header from the raw packet */
342 struct udphdr
*udp
= (struct udphdr
*) pkt_data_ptr
;
344 /* get the dst port of the packet */
345 return(ntohs(udp
->dest
));
349 OpenAndConfNFqueue(){
351 struct nfq_q_handle
*myQueue
;
352 struct nfnl_handle
*netlinkHandle
;
356 inet_pton(AF_INET
, "239.255.255.250", &(ssdp
.sin_addr
));
358 /* Get a queue connection handle from the module */
359 if (!(nfqHandle
= nfq_open())) {
360 syslog(LOG_ERR
, "Error in nfq_open(): %m");
364 /* Unbind the handler from processing any IP packets
365 Not totally sure why this is done, or if it's necessary... */
366 if ((e
= nfq_unbind_pf(nfqHandle
, AF_INET
)) < 0) {
367 syslog(LOG_ERR
, "Error in nfq_unbind_pf(): %m");
371 /* Bind this handler to process IP packets... */
372 if (nfq_bind_pf(nfqHandle
, AF_INET
) < 0) {
373 syslog(LOG_ERR
, "Error in nfq_bind_pf(): %m");
377 /* Install a callback on queue -Q */
378 if (!(myQueue
= nfq_create_queue(nfqHandle
, nfqueue
, &nfqueue_cb
, NULL
))) {
379 syslog(LOG_ERR
, "Error in nfq_create_queue(): %m");
383 /* Turn on packet copy mode */
384 if (nfq_set_mode(myQueue
, NFQNL_COPY_PACKET
, 0xffff) < 0) {
385 syslog(LOG_ERR
, "Error setting packet copy mode (): %m");
389 netlinkHandle
= nfq_nfnlh(nfqHandle
);
390 fd
= nfnl_fd(netlinkHandle
);
397 static int nfqueue_cb(
398 struct nfq_q_handle
*qh
,
399 struct nfgenmsg
*nfmsg
,
400 struct nfq_data
*nfa
,
404 struct nfqnl_msg_packet_hdr
*ph
;
405 ph
= nfq_get_msg_packet_hdr(nfa
);
409 int id
= 0, size
= 0;
410 id
= ntohl(ph
->packet_id
);
412 size
= nfq_get_payload(nfa
, &pkt
);
414 struct ip
*iph
= (struct ip
*) pkt
;
416 int id_protocol
= identify_ip_protocol(pkt
);
418 int dport
= get_udp_dst_port(pkt
);
420 int x
= sizeof (struct ip
) + sizeof (struct udphdr
);
422 /* packets we are interested in are UDP multicast to 239.255.255.250:1900
423 * and start with a data string M-SEARCH
425 if ( (dport
== 1900) && (id_protocol
== IPPROTO_UDP
)
426 && (ssdp
.sin_addr
.s_addr
== iph
->ip_dst
.s_addr
) ) {
428 /* get the index that the packet came in on */
429 u_int32_t idx
= nfq_get_indev(nfa
);
431 for ( ;i
< n_nfqix
; i
++) {
432 if ( nfqix
[i
] == idx
) {
434 struct udphdr
*udp
= (struct udphdr
*) (pkt
+ sizeof(struct ip
));
438 struct sockaddr_in sendername
;
439 sendername
.sin_family
= AF_INET
;
440 sendername
.sin_port
= udp
->source
;
441 sendername
.sin_addr
.s_addr
= iph
->ip_src
.s_addr
;
443 /* printf("pkt found %s\n",dd);*/
444 ProcessSSDPData (sudp
, dd
, size
- x
,
445 &sendername
, (unsigned short) 5555);
450 nfq_set_verdict(qh
, id
, NF_ACCEPT
, 0, NULL
);
453 syslog(LOG_ERR
,"nfq_get_msg_packet_hdr failed");
455 /* from nfqueue source: 0 = ok, >0 = soft error, <0 hard error */
461 static void ProcessNFQUEUE(int fd
){
465 struct sockaddr_in sendername
;
466 len_r
= sizeof(struct sockaddr_in
);
468 int res
= recvfrom(fd
, buf
, sizeof(buf
), 0,
469 (struct sockaddr
*)&sendername
, &len_r
);
471 nfq_handle_packet(nfqHandle
, buf
, res
);
475 /* Functions used to communicate with miniupnpdctl */
476 #ifdef USE_MINIUPNPDCTL
478 OpenAndConfCtlUnixSocket(const char * path
)
480 struct sockaddr_un localun
;
482 s
= socket(AF_UNIX
, SOCK_STREAM
, 0);
483 localun
.sun_family
= AF_UNIX
;
484 strncpy(localun
.sun_path
, path
,
485 sizeof(localun
.sun_path
));
486 if(bind(s
, (struct sockaddr
*)&localun
,
487 sizeof(struct sockaddr_un
)) < 0)
489 syslog(LOG_ERR
, "bind(sctl): %m");
493 else if(listen(s
, 5) < 0)
495 syslog(LOG_ERR
, "listen(sctl): %m");
503 write_upnphttp_details(int fd
, struct upnphttp
* e
)
507 write(fd
, "HTTP :\n", 7);
510 len
= snprintf(buffer
, sizeof(buffer
),
511 "%d %d %s req_buf=%p(%dbytes) res_buf=%p(%dbytes alloc)\n",
512 e
->socket
, e
->state
, e
->HttpVer
,
513 e
->req_buf
, e
->req_buflen
,
514 e
->res_buf
, e
->res_buf_alloclen
);
515 write(fd
, buffer
, len
);
516 e
= e
->entries
.le_next
;
521 write_ctlsockets_list(int fd
, struct ctlelem
* e
)
525 write(fd
, "CTL :\n", 6);
528 len
= snprintf(buffer
, sizeof(buffer
),
529 "struct ctlelem: socket=%d\n", e
->socket
);
530 write(fd
, buffer
, len
);
531 e
= e
->entries
.le_next
;
535 #ifndef DISABLE_CONFIG_FILE
537 write_option_list(int fd
)
542 write(fd
, "Options :\n", 10);
543 for(i
=0; i
<num_options
; i
++)
545 len
= snprintf(buffer
, sizeof(buffer
),
547 ary_options
[i
].id
, ary_options
[i
].value
);
548 write(fd
, buffer
, len
);
554 write_command_line(int fd
, int argc
, char * * argv
)
559 write(fd
, "Command Line :\n", 15);
560 for(i
=0; i
<argc
; i
++)
562 len
= snprintf(buffer
, sizeof(buffer
),
565 write(fd
, buffer
, len
);
571 /* Handler for the SIGTERM signal (kill)
572 * SIGINT is also handled */
577 /*int save_errno = errno; */
578 /*signal(sig, SIG_IGN);*/ /* Ignore this signal while we are quitting */
579 /* Note : isn't it useless ? */
582 /* calling syslog() is forbidden in signal handler according to
584 syslog(LOG_NOTICE
, "received signal %d, good-bye", sig
);
588 /*errno = save_errno;*/
591 /* Handler for the SIGUSR1 signal indicating public IP address change. */
597 /* calling syslog() is forbidden in signal handler according to
599 syslog(LOG_INFO
, "received signal %d, public ip address change", sig
);
602 should_send_public_address_change_notif
= 1;
605 /* record the startup time, for returning uptime */
607 set_startup_time(int sysuptime
)
609 startup_time
= time(NULL
);
612 /* use system uptime instead of daemon uptime */
613 #if defined(__linux__)
616 fd
= open("/proc/uptime", O_RDONLY
);
619 syslog(LOG_ERR
, "open(\"/proc/uptime\" : %m");
623 memset(buff
, 0, sizeof(buff
));
624 if(read(fd
, buff
, sizeof(buff
) - 1) < 0)
626 syslog(LOG_ERR
, "read(\"/proc/uptime\" : %m");
631 syslog(LOG_INFO
, "system uptime is %d seconds", uptime
);
634 startup_time
-= uptime
;
636 #elif defined(SOLARIS_KSTATS)
642 ksp
= kstat_lookup(kc
, "unix", 0, "system_misc");
643 if(ksp
&& (kstat_read(kc
, ksp
, NULL
) != -1))
645 void *ptr
= kstat_data_lookup(ksp
, "boot_time");
647 memcpy(&startup_time
, ptr
, sizeof(startup_time
));
649 syslog(LOG_ERR
, "cannot find boot_time kstat");
652 syslog(LOG_ERR
, "cannot open kstats for unix/0/system_misc: %m");
656 struct timeval boottime
;
657 size_t size
= sizeof(boottime
);
658 int name
[2] = { CTL_KERN
, KERN_BOOTTIME
};
659 if(sysctl(name
, 2, &boottime
, &size
, NULL
, 0) < 0)
661 syslog(LOG_ERR
, "sysctl(\"kern.boottime\") failed");
665 startup_time
= boottime
.tv_sec
;
671 /* structure containing variables used during "main loop"
672 * that are filled during the init */
673 struct runtime_vars
{
674 /* LAN IP addresses for SSDP traffic and HTTP */
675 /* moved to global vars */
676 int port
; /* HTTP Port */
677 int notify_interval
; /* seconds between SSDP announces */
678 /* unused rules cleaning related variables : */
679 int clean_ruleset_threshold
; /* threshold for removing unused rules */
680 int clean_ruleset_interval
; /* (minimum) interval between checks */
684 * parse address with mask
685 * ex: 192.168.1.1/24 or 192.168.1.1/255.255.255.0
686 * When MULTIPLE_EXTERNAL_IP is enabled, the ip address of the
687 * external interface associated with the lan subnet follows.
688 * ex : 192.168.1.1/24 81.21.41.11
690 * Can also use the interface name (ie eth0)
696 parselanaddr(struct lan_addr_s
* lan_addr
, const char * str
)
702 memset(lan_addr
, 0, sizeof(struct lan_addr_s
));
704 while(*p
&& *p
!= '/' && !isspace(*p
))
707 if(!isdigit(str
[0]) && n
< (int)sizeof(lan_addr
->ifname
))
709 /* not starting with a digit : suppose it is an interface name */
710 memcpy(lan_addr
->ifname
, str
, n
);
711 lan_addr
->ifname
[n
] = '\0';
712 if(getifaddr(lan_addr
->ifname
, lan_addr
->str
, sizeof(lan_addr
->str
)) < 0)
719 memcpy(lan_addr
->str
, str
, n
);
720 lan_addr
->str
[n
] = '\0';
722 if(!inet_aton(lan_addr
->str
, &lan_addr
->addr
))
726 const char * q
= ++p
;
727 while(*p
&& isdigit(*p
))
731 while(*p
&& (*p
=='.' || isdigit(*p
)))
738 if(!inet_aton(tmp
, &lan_addr
->mask
))
744 if(nbits
> 32 || nbits
< 0)
746 lan_addr
->mask
.s_addr
= htonl(nbits
? (0xffffffffu
<< (32 - nbits
)) : 0);
751 /* by default, networks are /24 */
752 lan_addr
->mask
.s_addr
= htonl(0xffffff00u
);
754 #ifdef MULTIPLE_EXTERNAL_IP
756 while(*p
&& isspace(*p
))
759 /* parse the exteral ip address to associate with this subnet */
761 while(p
[n
] && !isspace(*p
))
764 memcpy(lan_addr
->ext_ip_str
, p
, n
);
765 lan_addr
->ext_ip_str
[n
] = '\0';
766 if(!inet_aton(lan_addr
->ext_ip_str
, &lan_addr
->ext_ip_addr
)) {
768 fprintf(stderr
, "Error parsing address : %s\n", lan_addr
->ext_ip_str
);
774 if(lan_addr
->ifname
[0] != '\0')
776 lan_addr
->index
= if_nametoindex(lan_addr
->ifname
);
777 if(lan_addr
->index
== 0)
778 fprintf(stderr
, "Cannot get index for network interface %s",
784 fprintf(stderr
, "Error parsing address/mask (or interface name) : %s\n",
790 * 1) read configuration file
791 * 2) read command line arguments
794 * 5) check and write pid file
795 * 6) set startup time stamp
796 * 7) compute presentation URL
797 * 8) set signal handlers */
799 init(int argc
, char * * argv
, struct runtime_vars
* v
)
806 /*const char * logfilename = 0;*/
807 const char * presurl
= 0;
808 #ifndef DISABLE_CONFIG_FILE
809 int options_flag
= 0;
810 const char * optionsfile
= DEFAULT_CONFIG
;
811 #endif /* DISABLE_CONFIG_FILE */
812 struct lan_addr_s
* lan_addr
;
813 struct lan_addr_s
* lan_addr2
;
815 /* only print usage if -h is used */
816 for(i
=1; i
<argc
; i
++)
818 if(0 == strcmp(argv
[i
], "-h"))
821 #ifndef DISABLE_CONFIG_FILE
822 /* first check if "-f" option is used */
823 for(i
=2; i
<argc
; i
++)
825 if(0 == strcmp(argv
[i
-1], "-f"))
827 optionsfile
= argv
[i
];
832 #endif /* DISABLE_CONFIG_FILE */
834 /* set initial values */
835 SETFLAG(ENABLEUPNPMASK
); /* UPnP is enabled by default */
837 LIST_INIT(&lan_addrs
);
839 v
->notify_interval
= 30; /* seconds between SSDP announces */
840 v
->clean_ruleset_threshold
= 20;
841 v
->clean_ruleset_interval
= 0; /* interval between ruleset check. 0=disabled */
842 #ifndef DISABLE_CONFIG_FILE
843 /* read options file first since
844 * command line arguments have final say */
845 if(readoptionsfile(optionsfile
) < 0)
847 /* only error if file exists or using -f */
848 if(access(optionsfile
, F_OK
) == 0 || options_flag
)
849 fprintf(stderr
, "Error reading configuration file %s\n", optionsfile
);
853 for(i
=0; i
<(int)num_options
; i
++)
855 switch(ary_options
[i
].id
)
858 ext_if_name
= ary_options
[i
].value
;
861 use_ext_ip_addr
= ary_options
[i
].value
;
863 case UPNPLISTENING_IP
:
864 lan_addr
= (struct lan_addr_s
*) malloc(sizeof(struct lan_addr_s
));
865 if (lan_addr
== NULL
)
867 fprintf(stderr
, "malloc(sizeof(struct lan_addr_s)): %m");
870 if(parselanaddr(lan_addr
, ary_options
[i
].value
) != 0)
872 fprintf(stderr
, "can't parse \"%s\" as valid lan address\n", ary_options
[i
].value
);
876 LIST_INSERT_HEAD(&lan_addrs
, lan_addr
, list
);
879 v
->port
= atoi(ary_options
[i
].value
);
882 upstream_bitrate
= strtoul(ary_options
[i
].value
, 0, 0);
884 case UPNPBITRATE_DOWN
:
885 downstream_bitrate
= strtoul(ary_options
[i
].value
, 0, 0);
887 case UPNPPRESENTATIONURL
:
888 presurl
= ary_options
[i
].value
;
890 case UPNPFRIENDLY_NAME
:
891 strncpy(friendly_name
, ary_options
[i
].value
, FRIENDLY_NAME_MAX_LEN
);
892 friendly_name
[FRIENDLY_NAME_MAX_LEN
-1] = '\0';
895 case UPNPFORWARDCHAIN
:
896 miniupnpd_forward_chain
= ary_options
[i
].value
;
899 miniupnpd_nat_chain
= ary_options
[i
].value
;
902 case UPNPNOTIFY_INTERVAL
:
903 v
->notify_interval
= atoi(ary_options
[i
].value
);
905 case UPNPSYSTEM_UPTIME
:
906 if(strcmp(ary_options
[i
].value
, "yes") == 0)
907 SETFLAG(SYSUPTIMEMASK
); /*sysuptime = 1;*/
909 #if defined(USE_PF) || defined(USE_IPF)
911 if(strcmp(ary_options
[i
].value
, "yes") == 0)
912 SETFLAG(LOGPACKETSMASK
); /*logpackets = 1;*/
916 strncpy(uuidvalue
+5, ary_options
[i
].value
,
917 strlen(uuidvalue
+5) + 1);
920 strncpy(serialnumber
, ary_options
[i
].value
, SERIALNUMBER_MAX_LEN
);
921 serialnumber
[SERIALNUMBER_MAX_LEN
-1] = '\0';
923 case UPNPMODEL_NUMBER
:
924 strncpy(modelnumber
, ary_options
[i
].value
, MODELNUMBER_MAX_LEN
);
925 modelnumber
[MODELNUMBER_MAX_LEN
-1] = '\0';
927 case UPNPCLEANTHRESHOLD
:
928 v
->clean_ruleset_threshold
= atoi(ary_options
[i
].value
);
930 case UPNPCLEANINTERVAL
:
931 v
->clean_ruleset_interval
= atoi(ary_options
[i
].value
);
935 anchor_name
= ary_options
[i
].value
;
938 queue
= ary_options
[i
].value
;
941 tag
= ary_options
[i
].value
;
945 case UPNPENABLENATPMP
:
946 if(strcmp(ary_options
[i
].value
, "yes") == 0)
947 SETFLAG(ENABLENATPMPMASK
); /*enablenatpmp = 1;*/
949 if(atoi(ary_options
[i
].value
))
950 SETFLAG(ENABLENATPMPMASK
);
951 /*enablenatpmp = atoi(ary_options[i].value);*/
954 #ifdef PF_ENABLE_FILTER_RULES
956 if(strcmp(ary_options
[i
].value
, "no") == 0)
957 SETFLAG(PFNOQUICKRULESMASK
);
961 if(strcmp(ary_options
[i
].value
, "yes") != 0)
962 CLEARFLAG(ENABLEUPNPMASK
);
965 if(strcmp(ary_options
[i
].value
, "yes") == 0)
966 SETFLAG(SECUREMODEMASK
);
968 #ifdef ENABLE_LEASEFILE
970 lease_file
= ary_options
[i
].value
;
973 case UPNPMINISSDPDSOCKET
:
974 minissdpdsocketpath
= ary_options
[i
].value
;
977 fprintf(stderr
, "Unknown option in file %s\n",
982 #endif /* DISABLE_CONFIG_FILE */
984 /* command line arguments processing */
985 for(i
=1; i
<argc
; i
++)
989 fprintf(stderr
, "Unknown option: %s\n", argv
[i
]);
991 else switch(argv
[i
][1])
995 use_ext_ip_addr
= argv
[++i
];
997 fprintf(stderr
, "Option -%c takes one argument.\n", argv
[i
][1]);
1001 v
->notify_interval
= atoi(argv
[++i
]);
1003 fprintf(stderr
, "Option -%c takes one argument.\n", argv
[i
][1]);
1007 v
->clean_ruleset_interval
= atoi(argv
[++i
]);
1009 fprintf(stderr
, "Option -%c takes one argument.\n", argv
[i
][1]);
1013 strncpy(uuidvalue
+5, argv
[++i
], strlen(uuidvalue
+5) + 1);
1015 fprintf(stderr
, "Option -%c takes one argument.\n", argv
[i
][1]);
1019 strncpy(friendly_name
, argv
[++i
], FRIENDLY_NAME_MAX_LEN
);
1021 fprintf(stderr
, "Option -%c takes one argument.\n", argv
[i
][1]);
1022 friendly_name
[FRIENDLY_NAME_MAX_LEN
-1] = '\0';
1026 strncpy(serialnumber
, argv
[++i
], SERIALNUMBER_MAX_LEN
);
1028 fprintf(stderr
, "Option -%c takes one argument.\n", argv
[i
][1]);
1029 serialnumber
[SERIALNUMBER_MAX_LEN
-1] = '\0';
1033 strncpy(modelnumber
, argv
[++i
], MODELNUMBER_MAX_LEN
);
1035 fprintf(stderr
, "Option -%c takes one argument.\n", argv
[i
][1]);
1036 modelnumber
[MODELNUMBER_MAX_LEN
-1] = '\0';
1038 #ifdef ENABLE_NATPMP
1040 /*enablenatpmp = 1;*/
1041 SETFLAG(ENABLENATPMPMASK
);
1046 SETFLAG(SYSUPTIMEMASK
);
1049 logfilename = argv[++i];
1051 #if defined(USE_PF) || defined(USE_IPF)
1054 SETFLAG(LOGPACKETSMASK
);
1058 SETFLAG(SECUREMODEMASK
);
1062 ext_if_name
= argv
[++i
];
1064 fprintf(stderr
, "Option -%c takes one argument.\n", argv
[i
][1]);
1071 fprintf(stderr
, "Option -%c takes one argument.\n", argv
[i
][1]);
1077 fprintf(stderr
, "Option -%c takes one argument.\n", argv
[i
][1]);
1082 v
->port
= atoi(argv
[++i
]);
1084 #ifdef ENABLE_NFQUEUE
1088 nfqueue
= atoi(argv
[++i
]);
1091 fprintf(stderr
, "Option -%c takes one argument.\n", argv
[i
][1]);
1096 if(n_nfqix
< MAX_LAN_ADDR
) {
1097 nfqix
[n_nfqix
++] = if_nametoindex(argv
[i
]);
1099 fprintf(stderr
,"Too many nfq interfaces. Ignoring %s\n", argv
[i
]);
1102 fprintf(stderr
, "Option -%c takes one argument.\n", argv
[i
][1]);
1106 fprintf(stderr
, "Option -%c takes one argument.\n", argv
[i
][1]);
1110 pidfilename
= argv
[++i
];
1112 fprintf(stderr
, "Option -%c takes one argument.\n", argv
[i
][1]);
1119 presurl
= argv
[++i
];
1121 fprintf(stderr
, "Option -%c takes one argument.\n", argv
[i
][1]);
1126 downstream_bitrate
= strtoul(argv
[++i
], 0, 0);
1127 upstream_bitrate
= strtoul(argv
[++i
], 0, 0);
1130 fprintf(stderr
, "Option -%c takes two arguments.\n", argv
[i
][1]);
1133 #ifndef MULTIPLE_EXTERNAL_IP
1137 lan_addr
= (struct lan_addr_s
*) malloc(sizeof(struct lan_addr_s
));
1138 if (lan_addr
== NULL
)
1140 fprintf(stderr
, "malloc(sizeof(struct lan_addr_s)): %m");
1143 if(parselanaddr(lan_addr
, argv
[i
]) != 0)
1145 fprintf(stderr
, "can't parse \"%s\" as valid lan address\n", argv
[i
]);
1149 /* check if we already have this address */
1150 for(lan_addr2
= lan_addrs
.lh_first
; lan_addr2
!= NULL
; lan_addr2
= lan_addr2
->list
.le_next
)
1152 if (0 == strncmp(lan_addr2
->str
, lan_addr
->str
, 15))
1155 if (lan_addr2
== NULL
)
1156 LIST_INSERT_HEAD(&lan_addrs
, lan_addr
, list
);
1159 fprintf(stderr
, "Option -%c takes one argument.\n", argv
[i
][1]);
1163 char *val
=calloc((strlen(argv
[i
+1]) + strlen(argv
[i
+2]) + 1), sizeof(char));
1166 fprintf(stderr
, "memory allocation error for listen address storage\n");
1169 sprintf(val
, "%s %s", argv
[i
+1], argv
[i
+2]);
1171 lan_addr
= (struct lan_addr_s
*) malloc(sizeof(struct lan_addr_s
));
1172 if (lan_addr
== NULL
)
1174 fprintf(stderr
, "malloc(sizeof(struct lan_addr_s)): %m");
1178 if(parselanaddr(lan_addr
, val
) != 0)
1180 fprintf(stderr
, "can't parse \"%s\" as valid lan address\n", val
);
1185 /* check if we already have this address */
1186 for(lan_addr2
= lan_addrs
.lh_first
; lan_addr2
!= NULL
; lan_addr2
= lan_addr2
->list
.le_next
)
1188 if (0 == strncmp(lan_addr2
->str
, lan_addr
->str
, 15))
1191 if (lan_addr2
== NULL
)
1192 LIST_INSERT_HEAD(&lan_addrs
, lan_addr
, list
);
1198 fprintf(stderr
, "Option -%c takes two arguments.\n", argv
[i
][1]);
1204 tmp
= realloc(upnppermlist
, sizeof(struct upnpperm
) * (num_upnpperm
+1));
1206 fprintf(stderr
, "memory allocation error for permission\n");
1209 if(read_permission_line(upnppermlist
+ num_upnpperm
, argv
[++i
]) >= 0) {
1212 fprintf(stderr
, "Permission rule parsing error :\n%s\n", argv
[i
]);
1216 fprintf(stderr
, "Option -%c takes one argument.\n", argv
[i
][1]);
1219 i
++; /* discarding, the config file is already read */
1222 fprintf(stderr
, "Unknown option: %s\n", argv
[i
]);
1225 if(!ext_if_name
|| !lan_addrs
.lh_first
)
1227 /* bad configuration */
1238 if(daemon(0, 0)<0) {
1247 openlog_option
= LOG_PID
|LOG_CONS
;
1250 openlog_option
|= LOG_PERROR
; /* also log on stderr */
1253 openlog("miniupnpd", openlog_option
, LOG_MINIUPNPD
);
1257 /* speed things up and ignore LOG_INFO and LOG_DEBUG */
1258 setlogmask(LOG_UPTO(LOG_NOTICE
));
1261 if(checkforrunning(pidfilename
) < 0)
1263 syslog(LOG_ERR
, "MiniUPnPd is already running. EXITING");
1267 syslog(LOG_NOTICE
, "version " MINIUPNPD_VERSION
" started");
1269 set_startup_time(GETFLAG(SYSUPTIMEMASK
));
1271 /* presentation url */
1274 strncpy(presentationurl
, presurl
, PRESENTATIONURL_MAX_LEN
);
1275 presentationurl
[PRESENTATIONURL_MAX_LEN
-1] = '\0';
1279 snprintf(presentationurl
, PRESENTATIONURL_MAX_LEN
,
1280 "http://%s/", lan_addrs
.lh_first
->str
);
1281 /*"http://%s:%d/", lan_addrs.lh_first->str, 80);*/
1284 /* set signal handler */
1285 memset(&sa
, 0, sizeof(struct sigaction
));
1286 sa
.sa_handler
= sigterm
;
1288 if(sigaction(SIGTERM
, &sa
, NULL
) < 0)
1290 syslog(LOG_ERR
, "Failed to set %s handler. EXITING", "SIGTERM");
1293 if(sigaction(SIGINT
, &sa
, NULL
) < 0)
1295 syslog(LOG_ERR
, "Failed to set %s handler. EXITING", "SIGINT");
1300 sa
.sa_handler
= sigusr2
;
1301 sigaction(SIGUSR2
, &sa
, NULL
);
1303 if(signal(SIGPIPE
, SIG_IGN
) == SIG_ERR
)
1305 syslog(LOG_ERR
, "Failed to ignore SIGPIPE signals");
1308 sa
.sa_handler
= sigusr1
;
1309 if(sigaction(SIGUSR1
, &sa
, NULL
) < 0)
1311 syslog(LOG_NOTICE
, "Failed to set %s handler", "SIGUSR1");
1314 if(init_redirect() < 0)
1316 syslog(LOG_ERR
, "Failed to init redirection engine. EXITING");
1319 #ifdef ENABLE_6FC_SERVICE
1320 #ifdef USE_NETFILTER
1325 if(writepidfile(pidfilename
, pid
) < 0)
1328 #ifdef ENABLE_LEASEFILE
1329 /*remove(lease_file);*/
1330 syslog(LOG_INFO
, "Reloading rules from lease file");
1331 reload_from_lease_file();
1333 tomato_load(); // zzz
1337 fprintf(stderr
, "Usage:\n\t"
1339 #ifndef DISABLE_CONFIG_FILE
1342 "[-i ext_ifname] [-o ext_ip]\n"
1343 #ifndef MULTIPLE_EXTERNAL_IP
1344 "\t\t[-a listening_ip]"
1346 "\t\t[-a listening_ip ext_ip]"
1349 #if defined(USE_PF) || defined(USE_IPF)
1353 #ifdef ENABLE_NATPMP
1357 /*"[-l logfile] " not functionnal */
1358 "\t\t[-u uuid] [-s serial] [-m model_number] \n"
1359 "\t\t[-t notify_interval] [-P pid_filename] [-z fiendly_name]\n"
1360 "\t\t[-B down up] [-w url] [-r clean_ruleset_interval]\n"
1362 "\t\t[-q queue] [-T tag]\n"
1364 #ifdef ENABLE_NFQUEUE
1365 "\t\t[-Q queue] [-n name]\n"
1367 "\t\t[-A \"permission rule\"]\n"
1368 "\nNotes:\n\tThere can be one or several listening_ips.\n"
1369 "\tNotify interval is in seconds. Default is 30 seconds.\n"
1370 "\tDefault pid file is '%s'.\n"
1371 "\tDefault config file is '%s'.\n"
1372 "\tWith -d miniupnpd will run as a standard program.\n"
1373 #if defined(USE_PF) || defined(USE_IPF)
1374 "\t-L sets packet log in pf and ipf on.\n"
1376 "\t-S sets \"secure\" mode : clients can only add mappings to their own ip\n"
1377 "\t-U causes miniupnpd to report system uptime instead "
1378 "of daemon uptime.\n"
1379 #ifdef ENABLE_NATPMP
1380 "\t-N enable NAT-PMP functionality.\n"
1382 "\t-B sets bitrates reported by daemon in bits per second.\n"
1383 "\t-w sets the presentation url. Default is http address on port 80\n"
1385 "\t-q sets the ALTQ queue in pf.\n"
1386 "\t-T sets the tag name in pf.\n"
1388 #ifdef ENABLE_NFQUEUE
1389 "\t-Q sets the queue number that is used by NFQUEUE.\n"
1390 "\t-n sets the name of the interface(s) that packets will arrive on.\n"
1392 "\t-A use following syntax for permission rules :\n"
1393 "\t (allow|deny) (external port range) ip/mask (internal port range)\n"
1395 "\t \"allow 1024-65535 192.168.1.0/24 1024-65535\"\n"
1396 "\t \"deny 0-65535 0.0.0.0/0 0-65535\"\n"
1397 "\t-h prints this help and quits.\n"
1398 "", argv
[0], pidfilename
, DEFAULT_CONFIG
);
1403 /* process HTTP or SSDP requests */
1405 main(int argc
, char * * argv
)
1408 int shttpl
= -1; /* socket for HTTP */
1409 int sudp
= -1; /* IP v4 socket for receiving SSDP */
1411 int sudpv6
= -1; /* IP v6 socket for receiving SSDP */
1413 #ifdef ENABLE_NATPMP
1414 int * snatpmp
= NULL
;
1416 #ifdef ENABLE_NFQUEUE
1419 #ifdef USE_IFACEWATCHER
1420 int sifacewatcher
= -1;
1423 int * snotify
= NULL
;
1425 LIST_HEAD(httplisthead
, upnphttp
) upnphttphead
;
1426 struct upnphttp
* e
= 0;
1427 struct upnphttp
* next
;
1428 fd_set readset
; /* for select() */
1430 struct timeval timeout
, timeofday
, lasttimeofday
= {0, 0};
1432 #ifdef USE_MINIUPNPDCTL
1434 LIST_HEAD(ctlstructhead
, ctlelem
) ctllisthead
;
1435 struct ctlelem
* ectl
;
1436 struct ctlelem
* ectlnext
;
1438 struct runtime_vars v
;
1439 /* variables used for the unused-rule cleanup process */
1440 struct rule_state
* rule_list
= 0;
1441 struct timeval checktime
= {0, 0};
1442 struct lan_addr_s
* lan_addr
;
1443 #ifdef ENABLE_6FC_SERVICE
1444 unsigned int next_pinhole_ts
;
1447 if(init(argc
, argv
, &v
) != 0)
1449 /* count lan addrs */
1451 for(lan_addr
= lan_addrs
.lh_first
; lan_addr
!= NULL
; lan_addr
= lan_addr
->list
.le_next
)
1453 if(addr_count
> 0) {
1455 snotify
= calloc(addr_count
, sizeof(int));
1457 /* one for IPv4, one for IPv6 */
1458 snotify
= calloc(addr_count
* 2, sizeof(int));
1461 #ifdef ENABLE_NATPMP
1462 if(addr_count
> 0) {
1463 snatpmp
= malloc(addr_count
* sizeof(int));
1464 for(i
= 0; i
< addr_count
; i
++)
1469 LIST_INIT(&upnphttphead
);
1470 #ifdef USE_MINIUPNPDCTL
1471 LIST_INIT(&ctllisthead
);
1475 #ifdef ENABLE_NATPMP
1476 !GETFLAG(ENABLENATPMPMASK
) &&
1478 !GETFLAG(ENABLEUPNPMASK
) ) {
1479 syslog(LOG_ERR
, "Why did you run me anyway?");
1483 syslog(LOG_INFO
, "Starting%s%swith external interface %s",
1484 #ifdef ENABLE_NATPMP
1485 GETFLAG(ENABLENATPMPMASK
) ? " NAT-PMP " : " ",
1489 GETFLAG(ENABLEUPNPMASK
) ? "UPnP-IGD " : "",
1492 if(GETFLAG(ENABLEUPNPMASK
))
1495 /* open socket for HTTP connections. Listen on the 1st LAN address */
1496 shttpl
= OpenAndConfHTTPSocket((v
.port
> 0) ? v
.port
: 0);
1499 syslog(LOG_ERR
, "Failed to open socket for HTTP. EXITING");
1503 struct sockaddr_in sockinfo
;
1504 socklen_t len
= sizeof(struct sockaddr_in
);
1505 if (getsockname(shttpl
, (struct sockaddr
*)&sockinfo
, &len
) < 0) {
1506 syslog(LOG_ERR
, "getsockname(): %m");
1509 v
.port
= ntohs(sockinfo
.sin_port
);
1511 syslog(LOG_NOTICE
, "HTTP listening on port %d", v
.port
);
1513 if(find_ipv6_addr(NULL
, ipv6_addr_for_http_with_brackets
, sizeof(ipv6_addr_for_http_with_brackets
)) > 0) {
1514 syslog(LOG_NOTICE
, "HTTP IPv6 address given to control points : %s",
1515 ipv6_addr_for_http_with_brackets
);
1517 memcpy(ipv6_addr_for_http_with_brackets
, "[::1]", 6);
1518 syslog(LOG_WARNING
, "no HTTP IPv6 address");
1522 /* open socket for SSDP connections */
1523 sudp
= OpenAndConfSSDPReceiveSocket(0);
1526 syslog(LOG_NOTICE
, "Failed to open socket for receiving SSDP. Trying to use MiniSSDPd");
1527 if(SubmitServicesToMiniSSDPD(lan_addrs
.lh_first
->str
, v
.port
) < 0) {
1528 syslog(LOG_ERR
, "Failed to connect to MiniSSDPd. EXITING");
1533 sudpv6
= OpenAndConfSSDPReceiveSocket(1);
1536 syslog(LOG_WARNING
, "Failed to open socket for receiving SSDP (IP v6).");
1540 /* open socket for sending notifications */
1541 if(OpenAndConfSSDPNotifySockets(snotify
) < 0)
1543 syslog(LOG_ERR
, "Failed to open sockets for sending SSDP notify "
1544 "messages. EXITING");
1548 #ifdef USE_IFACEWATCHER
1549 /* open socket for kernel notifications about new network interfaces */
1552 sifacewatcher
= OpenAndConfInterfaceWatchSocket();
1553 if (sifacewatcher
< 0)
1555 syslog(LOG_ERR
, "Failed to open socket for receiving network interface notifications");
1561 #ifdef ENABLE_NATPMP
1562 /* open socket for NAT PMP traffic */
1563 if(GETFLAG(ENABLENATPMPMASK
))
1565 if(OpenAndConfNATPMPSockets(snatpmp
) < 0)
1567 syslog(LOG_ERR
, "Failed to open sockets for NAT PMP.");
1569 syslog(LOG_NOTICE
, "Listening for NAT-PMP traffic on port %u",
1573 ScanNATPMPforExpiration();
1578 /* for miniupnpdctl */
1579 #ifdef USE_MINIUPNPDCTL
1580 sctl
= OpenAndConfCtlUnixSocket("/var/run/miniupnpd.ctl");
1583 #ifdef ENABLE_NFQUEUE
1584 if ( nfqueue
!= -1 && n_nfqix
> 0) {
1585 nfqh
= OpenAndConfNFqueue();
1587 syslog(LOG_ERR
, "Failed to open fd for NFQUEUE.");
1590 syslog(LOG_NOTICE
, "Opened NFQUEUE %d",nfqueue
);
1595 tomato_helper(); // zzz
1600 /* Correct startup_time if it was set with a RTC close to 0 */
1601 if((startup_time
<60*60*24) && (time(NULL
)>60*60*24))
1603 set_startup_time(GETFLAG(SYSUPTIMEMASK
));
1605 /* send public address change notifications if needed */
1606 if(should_send_public_address_change_notif
)
1608 syslog(LOG_DEBUG
, "should send external iface address change notification(s)");
1609 #ifdef ENABLE_NATPMP
1610 if(GETFLAG(ENABLENATPMPMASK
))
1611 SendNATPMPPublicAddressChangeNotification(snatpmp
, addr_count
);
1613 #ifdef ENABLE_EVENTS
1614 if(GETFLAG(ENABLEUPNPMASK
))
1616 upnp_event_var_change_notify(EWanIPC
);
1619 should_send_public_address_change_notif
= 0;
1621 /* Check if we need to send SSDP NOTIFY messages and do it if
1623 if(gettimeofday(&timeofday
, 0) < 0)
1625 syslog(LOG_ERR
, "gettimeofday(): %m");
1626 timeout
.tv_sec
= v
.notify_interval
;
1627 timeout
.tv_usec
= 0;
1631 /* the comparaison is not very precise but who cares ? */
1632 if(timeofday
.tv_sec
>= (lasttimeofday
.tv_sec
+ v
.notify_interval
))
1634 if (GETFLAG(ENABLEUPNPMASK
))
1635 SendSSDPNotifies2(snotify
,
1636 (unsigned short)v
.port
,
1637 v
.notify_interval
<< 1);
1638 memcpy(&lasttimeofday
, &timeofday
, sizeof(struct timeval
));
1639 timeout
.tv_sec
= v
.notify_interval
;
1640 timeout
.tv_usec
= 0;
1644 timeout
.tv_sec
= lasttimeofday
.tv_sec
+ v
.notify_interval
1646 if(timeofday
.tv_usec
> lasttimeofday
.tv_usec
)
1648 timeout
.tv_usec
= 1000000 + lasttimeofday
.tv_usec
1649 - timeofday
.tv_usec
;
1654 timeout
.tv_usec
= lasttimeofday
.tv_usec
- timeofday
.tv_usec
;
1658 /* remove unused rules */
1659 if( v
.clean_ruleset_interval
1660 && (timeofday
.tv_sec
>= checktime
.tv_sec
+ v
.clean_ruleset_interval
))
1664 remove_unused_rules(rule_list
);
1669 rule_list
= get_upnp_rules_state_list(v
.clean_ruleset_threshold
);
1671 memcpy(&checktime
, &timeofday
, sizeof(struct timeval
));
1673 /* Remove expired port mappings, based on UPnP IGD LeaseDuration
1674 * or NAT-PMP lifetime) */
1675 if(nextruletoclean_timestamp
1676 && ((unsigned int)timeofday
.tv_sec
>= nextruletoclean_timestamp
))
1678 syslog(LOG_DEBUG
, "cleaning expired Port Mappings");
1679 get_upnp_rules_state_list(0);
1681 if(nextruletoclean_timestamp
1682 && ((unsigned int)timeout
.tv_sec
>= (nextruletoclean_timestamp
- timeofday
.tv_sec
)))
1684 timeout
.tv_sec
= nextruletoclean_timestamp
- timeofday
.tv_sec
;
1685 timeout
.tv_usec
= 0;
1686 syslog(LOG_DEBUG
, "setting timeout to %u sec",
1687 (unsigned)timeout
.tv_sec
);
1689 #ifdef ENABLE_NATPMP
1691 /* Remove expired NAT-PMP mappings */
1692 while(nextnatpmptoclean_timestamp
1693 && (timeofday
.tv_sec
>= nextnatpmptoclean_timestamp
+ startup_time
))
1695 /*syslog(LOG_DEBUG, "cleaning expired NAT-PMP mappings");*/
1696 if(CleanExpiredNATPMP() < 0) {
1697 syslog(LOG_ERR
, "CleanExpiredNATPMP() failed");
1701 if(nextnatpmptoclean_timestamp
1702 && timeout
.tv_sec
>= (nextnatpmptoclean_timestamp
+ startup_time
- timeofday
.tv_sec
))
1704 /*syslog(LOG_DEBUG, "setting timeout to %d sec",
1705 nextnatpmptoclean_timestamp + startup_time - timeofday.tv_sec);*/
1706 timeout
.tv_sec
= nextnatpmptoclean_timestamp
+ startup_time
- timeofday
.tv_sec
;
1707 timeout
.tv_usec
= 0;
1711 #ifdef ENABLE_6FC_SERVICE
1712 /* Clean up expired IPv6 PinHoles */
1713 next_pinhole_ts
= 0;
1714 upnp_clean_expired_pinholes(&next_pinhole_ts
);
1715 if(next_pinhole_ts
&&
1716 timeout
.tv_sec
>= (int)(next_pinhole_ts
- timeofday
.tv_sec
)) {
1717 timeout
.tv_sec
= next_pinhole_ts
- timeofday
.tv_sec
;
1718 timeout
.tv_usec
= 0;
1722 /* select open sockets (SSDP, HTTP listen, and all HTTP soap sockets) */
1728 FD_SET(sudp
, &readset
);
1729 max_fd
= MAX( max_fd
, sudp
);
1730 #ifdef USE_IFACEWATCHER
1731 if (sifacewatcher
>= 0)
1733 FD_SET(sifacewatcher
, &readset
);
1734 max_fd
= MAX(max_fd
, sifacewatcher
);
1740 FD_SET(shttpl
, &readset
);
1741 max_fd
= MAX( max_fd
, shttpl
);
1746 FD_SET(sudpv6
, &readset
);
1747 max_fd
= MAX( max_fd
, sudpv6
);
1751 #ifdef ENABLE_NFQUEUE
1754 FD_SET(nfqh
, &readset
);
1755 max_fd
= MAX( max_fd
, nfqh
);
1759 i
= 0; /* active HTTP connections count */
1760 for(e
= upnphttphead
.lh_first
; e
!= NULL
; e
= e
->entries
.le_next
)
1764 if(e
->state
<= EWaitingForHttpContent
)
1765 FD_SET(e
->socket
, &readset
);
1766 else if(e
->state
== ESendingAndClosing
)
1767 FD_SET(e
->socket
, &writeset
);
1770 max_fd
= MAX(max_fd
, e
->socket
);
1778 syslog(LOG_DEBUG
, "%d active incoming HTTP connections", i
);
1781 #ifdef ENABLE_NATPMP
1782 for(i
=0; i
<addr_count
; i
++) {
1783 if(snatpmp
[i
] >= 0) {
1784 FD_SET(snatpmp
[i
], &readset
);
1785 max_fd
= MAX( max_fd
, snatpmp
[i
]);
1789 #ifdef USE_MINIUPNPDCTL
1791 FD_SET(sctl
, &readset
);
1792 max_fd
= MAX( max_fd
, sctl
);
1795 for(ectl
= ctllisthead
.lh_first
; ectl
; ectl
= ectl
->entries
.le_next
)
1797 if(ectl
->socket
>= 0) {
1798 FD_SET(ectl
->socket
, &readset
);
1799 max_fd
= MAX( max_fd
, ectl
->socket
);
1804 #ifdef ENABLE_EVENTS
1805 upnpevents_selectfds(&readset
, &writeset
, &max_fd
);
1808 if(select(max_fd
+1, &readset
, &writeset
, 0, &timeout
) < 0)
1810 if(quitting
) goto shutdown
;
1811 if (gotusr2
) { // zzz
1816 if(errno
== EINTR
) continue; /* interrupted by a signal, start again */
1817 syslog(LOG_ERR
, "select(all): %m");
1818 syslog(LOG_ERR
, "Failed to select open sockets. EXITING");
1819 return 1; /* very serious cause of error */
1821 #ifdef USE_MINIUPNPDCTL
1822 for(ectl
= ctllisthead
.lh_first
; ectl
;)
1824 ectlnext
= ectl
->entries
.le_next
;
1825 if((ectl
->socket
>= 0) && FD_ISSET(ectl
->socket
, &readset
))
1829 l
= read(ectl
->socket
, buf
, sizeof(buf
));
1832 /*write(ectl->socket, buf, l);*/
1833 write_command_line(ectl
->socket
, argc
, argv
);
1834 #ifndef DISABLE_CONFIG_FILE
1835 write_option_list(ectl
->socket
);
1837 write_permlist(ectl
->socket
, upnppermlist
, num_upnpperm
);
1838 write_upnphttp_details(ectl
->socket
, upnphttphead
.lh_first
);
1839 write_ctlsockets_list(ectl
->socket
, ctllisthead
.lh_first
);
1840 write_ruleset_details(ectl
->socket
);
1841 #ifdef ENABLE_EVENTS
1842 write_events_details(ectl
->socket
);
1844 /* close the socket */
1845 close(ectl
->socket
);
1850 close(ectl
->socket
);
1854 if(ectl
->socket
< 0)
1856 LIST_REMOVE(ectl
, entries
);
1861 if((sctl
>= 0) && FD_ISSET(sctl
, &readset
))
1864 struct sockaddr_un clientname
;
1865 struct ctlelem
* tmp
;
1866 socklen_t clientnamelen
= sizeof(struct sockaddr_un
);
1867 /*syslog(LOG_DEBUG, "sctl!");*/
1868 s
= accept(sctl
, (struct sockaddr
*)&clientname
,
1870 syslog(LOG_DEBUG
, "sctl! : '%s'", clientname
.sun_path
);
1871 tmp
= malloc(sizeof(struct ctlelem
));
1874 syslog(LOG_ERR
, "Unable to allocate memory for ctlelem in main()");
1880 LIST_INSERT_HEAD(&ctllisthead
, tmp
, entries
);
1884 #ifdef ENABLE_EVENTS
1885 upnpevents_processfds(&readset
, &writeset
);
1887 #ifdef ENABLE_NATPMP
1888 /* process NAT-PMP packets */
1889 for(i
=0; i
<addr_count
; i
++)
1891 if((snatpmp
[i
] >= 0) && FD_ISSET(snatpmp
[i
], &readset
))
1893 ProcessIncomingNATPMPPacket(snatpmp
[i
]);
1897 /* process SSDP packets */
1898 if(sudp
>= 0 && FD_ISSET(sudp
, &readset
))
1900 /*syslog(LOG_INFO, "Received UDP Packet");*/
1901 ProcessSSDPRequest(sudp
, (unsigned short)v
.port
);
1904 if(sudpv6
>= 0 && FD_ISSET(sudpv6
, &readset
))
1906 syslog(LOG_INFO
, "Received UDP Packet (IPv6)");
1907 ProcessSSDPRequest(sudpv6
, (unsigned short)v
.port
);
1910 #ifdef USE_IFACEWATCHER
1911 /* process kernel notifications */
1912 if (sifacewatcher
>= 0 && FD_ISSET(sifacewatcher
, &readset
))
1913 ProcessInterfaceWatchNotify(sifacewatcher
);
1916 /* process active HTTP connections */
1917 /* LIST_FOREACH macro is not available under linux */
1918 for(e
= upnphttphead
.lh_first
; e
!= NULL
; e
= e
->entries
.le_next
)
1922 if(FD_ISSET(e
->socket
, &readset
) ||
1923 FD_ISSET(e
->socket
, &writeset
))
1925 Process_upnphttp(e
);
1929 /* process incoming HTTP connections */
1930 if(shttpl
>= 0 && FD_ISSET(shttpl
, &readset
))
1933 socklen_t clientnamelen
;
1935 struct sockaddr_storage clientname
;
1936 clientnamelen
= sizeof(struct sockaddr_storage
);
1938 struct sockaddr_in clientname
;
1939 clientnamelen
= sizeof(struct sockaddr_in
);
1941 shttp
= accept(shttpl
, (struct sockaddr
*)&clientname
, &clientnamelen
);
1944 /* ignore EAGAIN, EWOULDBLOCK, EINTR, we just try again later */
1945 if(errno
!= EAGAIN
&& errno
!= EWOULDBLOCK
&& errno
!= EINTR
)
1946 syslog(LOG_ERR
, "accept(http): %m");
1950 struct upnphttp
* tmp
= 0;
1953 sockaddr_to_string((struct sockaddr
*)&clientname
, addr_str
, sizeof(addr_str
));
1954 syslog(LOG_INFO
, "HTTP connection from %s", addr_str
);
1955 if(get_lan_for_peer((struct sockaddr
*)&clientname
) == NULL
)
1957 /* The peer is not a LAN ! */
1959 "HTTP peer %s is not from a LAN, closing the connection",
1965 /* Create a new upnphttp object and add it to
1966 * the active upnphttp object list */
1967 tmp
= New_upnphttp(shttp
);
1971 if(clientname
.ss_family
== AF_INET
)
1973 tmp
->clientaddr
= ((struct sockaddr_in
*)&clientname
)->sin_addr
;
1975 else if(clientname
.ss_family
== AF_INET6
)
1977 struct sockaddr_in6
* addr
= (struct sockaddr_in6
*)&clientname
;
1978 if(IN6_IS_ADDR_V4MAPPED(&addr
->sin6_addr
))
1980 memcpy(&tmp
->clientaddr
,
1981 &addr
->sin6_addr
.s6_addr
[12],
1987 memcpy(&tmp
->clientaddr_v6
,
1989 sizeof(struct in6_addr
));
1993 tmp
->clientaddr
= clientname
.sin_addr
;
1995 LIST_INSERT_HEAD(&upnphttphead
, tmp
, entries
);
1999 syslog(LOG_ERR
, "New_upnphttp() failed");
2005 #ifdef ENABLE_NFQUEUE
2006 /* process NFQ packets */
2007 if(nfqh
>= 0 && FD_ISSET(nfqh
, &readset
))
2009 /* syslog(LOG_INFO, "Received NFQUEUE Packet");*/
2010 ProcessNFQUEUE(nfqh
);
2013 /* delete finished HTTP connections */
2014 for(e
= upnphttphead
.lh_first
; e
!= NULL
; )
2016 next
= e
->entries
.le_next
;
2017 if(e
->state
>= EToDelete
)
2019 LIST_REMOVE(e
, entries
);
2025 } /* end of main loop */
2028 tomato_save("/etc/upnp/data"); // zzz
2030 /* close out open sockets */
2031 while(upnphttphead
.lh_first
!= NULL
)
2033 e
= upnphttphead
.lh_first
;
2034 LIST_REMOVE(e
, entries
);
2038 if (sudp
>= 0) close(sudp
);
2039 if (shttpl
>= 0) close(shttpl
);
2041 if (sudpv6
>= 0) close(sudpv6
);
2043 #ifdef USE_IFACEWATCHER
2044 if(sifacewatcher
>= 0) close(sifacewatcher
);
2046 #ifdef ENABLE_NATPMP
2047 for(i
=0; i
<addr_count
; i
++) {
2055 #ifdef USE_MINIUPNPDCTL
2060 if(unlink("/var/run/miniupnpd.ctl") < 0)
2062 syslog(LOG_ERR
, "unlink() %m");
2067 if (GETFLAG(ENABLEUPNPMASK
))
2070 if(SendSSDPGoodbye(snotify
, addr_count
) < 0)
2072 if(SendSSDPGoodbye(snotify
, addr_count
* 2) < 0)
2075 syslog(LOG_ERR
, "Failed to broadcast good-bye notifications");
2078 for(i
= 0; i
< addr_count
; i
++)
2080 for(i
= 0; i
< addr_count
* 2; i
++)
2085 if(pidfilename
&& (unlink(pidfilename
) < 0))
2087 syslog(LOG_ERR
, "Failed to remove pidfile %s: %m", pidfilename
);
2091 while(lan_addrs
.lh_first
!= NULL
)
2093 lan_addr
= lan_addrs
.lh_first
;
2094 LIST_REMOVE(lan_addrs
.lh_first
, list
);
2098 #ifdef ENABLE_NATPMP
2103 #ifndef DISABLE_CONFIG_FILE