Busybox: Upgrade to 1.21.1 (stable). lsof active.
[tomato.git] / release / src / router / miniupnpd / miniupnpd.c
blob1ffe972604014b8b11218d8e14703589287120d4
1 /* $Id: miniupnpd.c,v 1.173 2013/02/06 10:50:04 nanard Exp $ */
2 /* MiniUPnP project
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 */
8 #include "config.h"
10 /* Experimental support for NFQUEUE interfaces */
11 #ifdef ENABLE_NFQUEUE
12 /* apt-get install libnetfilter-queue-dev */
13 #include <netinet/ip.h>
14 #include <netinet/udp.h>
15 #if 0
16 #include <linux/netfilter_ipv4.h> /* Defines verdicts (NF_ACCEPT, etc) */
17 #endif
18 #include <linux/netfilter.h>
19 #include <libnetfilter_queue/libnetfilter_queue.h>
20 #include <linux/netfilter/nfnetlink_queue.h>
21 #endif
23 #include <stdlib.h>
24 #include <unistd.h>
25 #include <string.h>
26 #include <stdio.h>
27 #include <ctype.h>
28 #include <sys/types.h>
29 #include <sys/socket.h>
30 #include <netinet/in.h>
31 #include <arpa/inet.h>
32 #include <fcntl.h>
33 #include <sys/file.h>
34 #include <syslog.h>
35 #include <sys/time.h>
36 #include <time.h>
37 #include <signal.h>
38 #include <errno.h>
39 #include <sys/param.h>
40 #if defined(sun)
41 #include <kstat.h>
42 #else
43 /* for BSD's sysctl */
44 #include <sys/sysctl.h>
45 #endif
47 /* unix sockets */
48 #ifdef USE_MINIUPNPDCTL
49 #include <sys/un.h>
50 #endif
52 #include "macros.h"
53 #include "upnpglobalvars.h"
54 #include "upnphttp.h"
55 #include "upnpdescgen.h"
56 #include "miniupnpdpath.h"
57 #include "getifaddr.h"
58 #include "upnpsoap.h"
59 #include "options.h"
60 #include "minissdp.h"
61 #include "upnpredirect.h"
62 #include "upnppinhole.h"
63 #include "miniupnpdtypes.h"
64 #include "daemonize.h"
65 #include "upnpevents.h"
66 #ifdef ENABLE_NATPMP
67 #include "natpmp.h"
68 #endif
69 #include "commonrdr.h"
70 #include "upnputils.h"
71 #ifdef USE_IFACEWATCHER
72 #include "ifacewatcher.h"
73 #endif
74 #ifdef ENABLE_6FC_SERVICE
75 #ifdef USE_NETFILTER
76 void init_iptpinhole(void);
77 #endif
78 #endif
80 #ifndef DEFAULT_CONFIG
81 #define DEFAULT_CONFIG "/etc/miniupnpd.conf"
82 #endif
84 #ifdef USE_MINIUPNPDCTL
85 struct ctlelem {
86 int socket;
87 LIST_ENTRY(ctlelem) entries;
89 #endif
91 #ifdef ENABLE_NFQUEUE
92 /* globals */
93 static struct nfq_handle *nfqHandle;
94 static struct sockaddr_in ssdp;
96 /* prototypes */
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);
100 #endif
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;
107 #if 1
108 static volatile int gotusr2 = 0;
110 static void sigusr2(int sig)
112 gotusr2 = 1;
115 static void tomato_save(const char *fname)
117 unsigned short eport;
118 unsigned short iport;
119 unsigned int leaseduration;
120 unsigned int timestamp;
121 char proto[4];
122 char iaddr[32];
123 char desc[64];
124 char rhost[32];
125 int n;
126 FILE *f;
127 int t;
128 char tmp[128];
130 strcpy(tmp, "/etc/upnp/saveXXXXXX");
131 if ((t = mkstemp(tmp)) != -1) {
132 if ((f = fdopen(t, "w")) != NULL) {
133 n = 0;
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);
137 ++n;
139 fclose(f);
140 rename(tmp, fname);
142 else {
143 close(t);
145 unlink(tmp);
149 static void tomato_load(void)
151 FILE *f;
152 char s[256];
153 unsigned short eport;
154 unsigned short iport;
155 unsigned int leaseduration;
156 unsigned int timestamp;
157 time_t current_time;
158 char proto[4];
159 char iaddr[32];
160 char *rhost;
161 char *a, *b;
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, &timestamp) >= 4) {
168 if (((a = strchr(s, '[')) != NULL) && ((b = strrchr(a, ']')) != NULL)) {
169 if (timestamp > 0) {
170 if (timestamp > current_time)
171 leaseduration = current_time - timestamp;
172 else
173 continue;
174 } else {
175 leaseduration = 0; /* default value */
177 *b = 0;
178 rhost = NULL;
179 upnp_redirect(rhost, eport, iaddr, iport, proto, a + 1, leaseduration);
183 fclose(f);
185 #ifdef ENABLE_NATPMP
186 #if 0
187 ScanNATPMPforExpiration();
188 #endif
189 #endif
190 unlink("/etc/upnp/load");
193 static void tomato_delete(void)
195 FILE *f;
196 char s[128];
197 unsigned short eport;
198 unsigned short iport;
199 unsigned int leaseduration;
200 char proto[4];
201 char iaddr[32];
202 char desc[64];
203 char rhost[32];
204 int n;
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();
212 while (--n >= 0) {
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);
217 break;
219 else {
220 upnp_delete_redirection(eport, proto);
224 fclose(f);
225 unlink("/etc/upnp/delete");
229 static void tomato_helper(void)
231 struct stat st;
233 if (stat("/etc/upnp/delete", &st) == 0) {
234 tomato_delete();
237 if (stat("/etc/upnp/load", &st) == 0) {
238 tomato_load();
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. */
256 static int
257 OpenAndConfHTTPSocket(unsigned short port)
259 int s;
260 int i = 1;
261 #ifdef ENABLE_IPV6
262 struct sockaddr_in6 listenname;
263 #else
264 struct sockaddr_in listenname;
265 #endif
266 socklen_t listenname_len;
268 if( (s = socket(
269 #ifdef ENABLE_IPV6
270 PF_INET6,
271 #else
272 PF_INET,
273 #endif
274 SOCK_STREAM, 0)) < 0)
276 syslog(LOG_ERR, "socket(http): %m");
277 return -1;
280 if(setsockopt(s, SOL_SOCKET, SO_REUSEADDR, &i, sizeof(i)) < 0)
282 syslog(LOG_WARNING, "setsockopt(http, SO_REUSEADDR): %m");
284 #if 0
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");
291 #endif
293 if(!set_non_blocking(s))
295 syslog(LOG_WARNING, "set_non_blocking(http): %m");
298 #ifdef ENABLE_IPV6
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);
304 #else
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);
309 #endif
311 if(bind(s, (struct sockaddr *)&listenname, listenname_len) < 0)
313 syslog(LOG_ERR, "bind(http): %m");
314 close(s);
315 return -1;
318 if(listen(s, 5) < 0)
320 syslog(LOG_ERR, "listen(http): %m");
321 close(s);
322 return -1;
325 return s;
327 #ifdef ENABLE_NFQUEUE
329 int identify_ip_protocol(char *payload) {
330 return payload[9];
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));
348 static int
349 OpenAndConfNFqueue(){
351 struct nfq_q_handle *myQueue;
352 struct nfnl_handle *netlinkHandle;
354 int fd = 0, e = 0;
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");
361 return -1;
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");
368 return -1;
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");
374 return -1;
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");
380 return -1;
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");
386 return -1;
389 netlinkHandle = nfq_nfnlh(nfqHandle);
390 fd = nfnl_fd(netlinkHandle);
392 return fd;
397 static int nfqueue_cb(
398 struct nfq_q_handle *qh,
399 struct nfgenmsg *nfmsg,
400 struct nfq_data *nfa,
401 void *data) {
403 char *pkt;
404 struct nfqnl_msg_packet_hdr *ph;
405 ph = nfq_get_msg_packet_hdr(nfa);
407 if ( ph ) {
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);
430 int i = 0;
431 for ( ;i < n_nfqix ; i++) {
432 if ( nfqix[i] == idx ) {
434 struct udphdr *udp = (struct udphdr *) (pkt + sizeof(struct ip));
436 char *dd = pkt + x;
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);
452 } else {
453 syslog(LOG_ERR,"nfq_get_msg_packet_hdr failed");
454 return 1;
455 /* from nfqueue source: 0 = ok, >0 = soft error, <0 hard error */
458 return 0;
461 static void ProcessNFQUEUE(int fd){
462 char buf[4096];
464 socklen_t len_r;
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);
473 #endif
475 /* Functions used to communicate with miniupnpdctl */
476 #ifdef USE_MINIUPNPDCTL
477 static int
478 OpenAndConfCtlUnixSocket(const char * path)
480 struct sockaddr_un localun;
481 int s;
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");
490 close(s);
491 s = -1;
493 else if(listen(s, 5) < 0)
495 syslog(LOG_ERR, "listen(sctl): %m");
496 close(s);
497 s = -1;
499 return s;
502 static void
503 write_upnphttp_details(int fd, struct upnphttp * e)
505 char buffer[256];
506 int len;
507 write(fd, "HTTP :\n", 7);
508 while(e)
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;
520 static void
521 write_ctlsockets_list(int fd, struct ctlelem * e)
523 char buffer[256];
524 int len;
525 write(fd, "CTL :\n", 6);
526 while(e)
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
536 static void
537 write_option_list(int fd)
539 char buffer[256];
540 int len;
541 unsigned int i;
542 write(fd, "Options :\n", 10);
543 for(i=0; i<num_options; i++)
545 len = snprintf(buffer, sizeof(buffer),
546 "opt=%02d %s\n",
547 ary_options[i].id, ary_options[i].value);
548 write(fd, buffer, len);
551 #endif
553 static void
554 write_command_line(int fd, int argc, char * * argv)
556 char buffer[256];
557 int len;
558 int i;
559 write(fd, "Command Line :\n", 15);
560 for(i=0; i<argc; i++)
562 len = snprintf(buffer, sizeof(buffer),
563 "argv[%02d]='%s'\n",
564 i, argv[i]);
565 write(fd, buffer, len);
569 #endif
571 /* Handler for the SIGTERM signal (kill)
572 * SIGINT is also handled */
573 static void
574 sigterm(int sig)
576 UNUSED(sig);
577 /*int save_errno = errno; */
578 /*signal(sig, SIG_IGN);*/ /* Ignore this signal while we are quitting */
579 /* Note : isn't it useless ? */
581 #if 0
582 /* calling syslog() is forbidden in signal handler according to
583 * signal(3) */
584 syslog(LOG_NOTICE, "received signal %d, good-bye", sig);
585 #endif
587 quitting = 1;
588 /*errno = save_errno;*/
591 /* Handler for the SIGUSR1 signal indicating public IP address change. */
592 static void
593 sigusr1(int sig)
595 UNUSED(sig);
596 #if 0
597 /* calling syslog() is forbidden in signal handler according to
598 * signal(3) */
599 syslog(LOG_INFO, "received signal %d, public ip address change", sig);
600 #endif
602 should_send_public_address_change_notif = 1;
605 /* record the startup time, for returning uptime */
606 static void
607 set_startup_time(int sysuptime)
609 startup_time = time(NULL);
610 if(sysuptime)
612 /* use system uptime instead of daemon uptime */
613 #if defined(__linux__)
614 char buff[64];
615 int uptime = 0, fd;
616 fd = open("/proc/uptime", O_RDONLY);
617 if(fd < 0)
619 syslog(LOG_ERR, "open(\"/proc/uptime\" : %m");
621 else
623 memset(buff, 0, sizeof(buff));
624 if(read(fd, buff, sizeof(buff) - 1) < 0)
626 syslog(LOG_ERR, "read(\"/proc/uptime\" : %m");
628 else
630 uptime = atoi(buff);
631 syslog(LOG_INFO, "system uptime is %d seconds", uptime);
633 close(fd);
634 startup_time -= uptime;
636 #elif defined(SOLARIS_KSTATS)
637 kstat_ctl_t *kc;
638 kc = kstat_open();
639 if(kc != NULL)
641 kstat_t *ksp;
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");
646 if(ptr)
647 memcpy(&startup_time, ptr, sizeof(startup_time));
648 else
649 syslog(LOG_ERR, "cannot find boot_time kstat");
651 else
652 syslog(LOG_ERR, "cannot open kstats for unix/0/system_misc: %m");
653 kstat_close(kc);
655 #else
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");
663 else
665 startup_time = boottime.tv_sec;
667 #endif
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 */
683 /* parselanaddr()
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)
692 * return value :
693 * 0 : ok
694 * -1 : error */
695 static int
696 parselanaddr(struct lan_addr_s * lan_addr, const char * str)
698 const char * p;
699 int n;
700 char tmp[16];
702 memset(lan_addr, 0, sizeof(struct lan_addr_s));
703 p = str;
704 while(*p && *p != '/' && !isspace(*p))
705 p++;
706 n = p - str;
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)
713 goto parselan_error;
715 else
717 if(n>15)
718 goto parselan_error;
719 memcpy(lan_addr->str, str, n);
720 lan_addr->str[n] = '\0';
722 if(!inet_aton(lan_addr->str, &lan_addr->addr))
723 goto parselan_error;
724 if(*p == '/')
726 const char * q = ++p;
727 while(*p && isdigit(*p))
728 p++;
729 if(*p=='.')
731 while(*p && (*p=='.' || isdigit(*p)))
732 p++;
733 n = p - q;
734 if(n>15)
735 goto parselan_error;
736 memcpy(tmp, q, n);
737 tmp[n] = '\0';
738 if(!inet_aton(tmp, &lan_addr->mask))
739 goto parselan_error;
741 else
743 int nbits = atoi(q);
744 if(nbits > 32 || nbits < 0)
745 goto parselan_error;
746 lan_addr->mask.s_addr = htonl(nbits ? (0xffffffffu << (32 - nbits)) : 0);
749 else
751 /* by default, networks are /24 */
752 lan_addr->mask.s_addr = htonl(0xffffff00u);
754 #ifdef MULTIPLE_EXTERNAL_IP
755 /* skip spaces */
756 while(*p && isspace(*p))
757 p++;
758 if(*p) {
759 /* parse the exteral ip address to associate with this subnet */
760 n = 0;
761 while(p[n] && !isspace(*p))
762 n++;
763 if(n<=15) {
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)) {
767 /* error */
768 fprintf(stderr, "Error parsing address : %s\n", lan_addr->ext_ip_str);
772 #endif
773 #ifdef ENABLE_IPV6
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",
779 lan_addr->ifname);
781 #endif
782 return 0;
783 parselan_error:
784 fprintf(stderr, "Error parsing address/mask (or interface name) : %s\n",
785 str);
786 return -1;
789 /* init phase :
790 * 1) read configuration file
791 * 2) read command line arguments
792 * 3) daemonize
793 * 4) open syslog
794 * 5) check and write pid file
795 * 6) set startup time stamp
796 * 7) compute presentation URL
797 * 8) set signal handlers */
798 static int
799 init(int argc, char * * argv, struct runtime_vars * v)
801 int i;
802 int pid;
803 int debug_flag = 0;
804 int openlog_option;
805 struct sigaction sa;
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"))
819 goto print_usage;
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];
828 options_flag = 1;
829 break;
832 #endif /* DISABLE_CONFIG_FILE */
834 /* set initial values */
835 SETFLAG(ENABLEUPNPMASK); /* UPnP is enabled by default */
837 LIST_INIT(&lan_addrs);
838 v->port = -1;
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);
851 else
853 for(i=0; i<(int)num_options; i++)
855 switch(ary_options[i].id)
857 case UPNPEXT_IFNAME:
858 ext_if_name = ary_options[i].value;
859 break;
860 case UPNPEXT_IP:
861 use_ext_ip_addr = ary_options[i].value;
862 break;
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");
868 break;
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);
873 free(lan_addr);
874 break;
876 LIST_INSERT_HEAD(&lan_addrs, lan_addr, list);
877 break;
878 case UPNPPORT:
879 v->port = atoi(ary_options[i].value);
880 break;
881 case UPNPBITRATE_UP:
882 upstream_bitrate = strtoul(ary_options[i].value, 0, 0);
883 break;
884 case UPNPBITRATE_DOWN:
885 downstream_bitrate = strtoul(ary_options[i].value, 0, 0);
886 break;
887 case UPNPPRESENTATIONURL:
888 presurl = ary_options[i].value;
889 break;
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';
893 break;
894 #ifdef USE_NETFILTER
895 case UPNPFORWARDCHAIN:
896 miniupnpd_forward_chain = ary_options[i].value;
897 break;
898 case UPNPNATCHAIN:
899 miniupnpd_nat_chain = ary_options[i].value;
900 break;
901 #endif
902 case UPNPNOTIFY_INTERVAL:
903 v->notify_interval = atoi(ary_options[i].value);
904 break;
905 case UPNPSYSTEM_UPTIME:
906 if(strcmp(ary_options[i].value, "yes") == 0)
907 SETFLAG(SYSUPTIMEMASK); /*sysuptime = 1;*/
908 break;
909 #if defined(USE_PF) || defined(USE_IPF)
910 case UPNPPACKET_LOG:
911 if(strcmp(ary_options[i].value, "yes") == 0)
912 SETFLAG(LOGPACKETSMASK); /*logpackets = 1;*/
913 break;
914 #endif
915 case UPNPUUID:
916 strncpy(uuidvalue+5, ary_options[i].value,
917 strlen(uuidvalue+5) + 1);
918 break;
919 case UPNPSERIAL:
920 strncpy(serialnumber, ary_options[i].value, SERIALNUMBER_MAX_LEN);
921 serialnumber[SERIALNUMBER_MAX_LEN-1] = '\0';
922 break;
923 case UPNPMODEL_NUMBER:
924 strncpy(modelnumber, ary_options[i].value, MODELNUMBER_MAX_LEN);
925 modelnumber[MODELNUMBER_MAX_LEN-1] = '\0';
926 break;
927 case UPNPCLEANTHRESHOLD:
928 v->clean_ruleset_threshold = atoi(ary_options[i].value);
929 break;
930 case UPNPCLEANINTERVAL:
931 v->clean_ruleset_interval = atoi(ary_options[i].value);
932 break;
933 #ifdef USE_PF
934 case UPNPANCHOR:
935 anchor_name = ary_options[i].value;
936 break;
937 case UPNPQUEUE:
938 queue = ary_options[i].value;
939 break;
940 case UPNPTAG:
941 tag = ary_options[i].value;
942 break;
943 #endif
944 #ifdef ENABLE_NATPMP
945 case UPNPENABLENATPMP:
946 if(strcmp(ary_options[i].value, "yes") == 0)
947 SETFLAG(ENABLENATPMPMASK); /*enablenatpmp = 1;*/
948 else
949 if(atoi(ary_options[i].value))
950 SETFLAG(ENABLENATPMPMASK);
951 /*enablenatpmp = atoi(ary_options[i].value);*/
952 break;
953 #endif
954 #ifdef PF_ENABLE_FILTER_RULES
955 case UPNPQUICKRULES:
956 if(strcmp(ary_options[i].value, "no") == 0)
957 SETFLAG(PFNOQUICKRULESMASK);
958 break;
959 #endif
960 case UPNPENABLE:
961 if(strcmp(ary_options[i].value, "yes") != 0)
962 CLEARFLAG(ENABLEUPNPMASK);
963 break;
964 case UPNPSECUREMODE:
965 if(strcmp(ary_options[i].value, "yes") == 0)
966 SETFLAG(SECUREMODEMASK);
967 break;
968 #ifdef ENABLE_LEASEFILE
969 case UPNPLEASEFILE:
970 lease_file = ary_options[i].value;
971 break;
972 #endif
973 case UPNPMINISSDPDSOCKET:
974 minissdpdsocketpath = ary_options[i].value;
975 break;
976 default:
977 fprintf(stderr, "Unknown option in file %s\n",
978 optionsfile);
982 #endif /* DISABLE_CONFIG_FILE */
984 /* command line arguments processing */
985 for(i=1; i<argc; i++)
987 if(argv[i][0]!='-')
989 fprintf(stderr, "Unknown option: %s\n", argv[i]);
991 else switch(argv[i][1])
993 case 'o':
994 if(i+1 < argc)
995 use_ext_ip_addr = argv[++i];
996 else
997 fprintf(stderr, "Option -%c takes one argument.\n", argv[i][1]);
998 break;
999 case 't':
1000 if(i+1 < argc)
1001 v->notify_interval = atoi(argv[++i]);
1002 else
1003 fprintf(stderr, "Option -%c takes one argument.\n", argv[i][1]);
1004 break;
1005 case 'r':
1006 if(i+1 < argc)
1007 v->clean_ruleset_interval = atoi(argv[++i]);
1008 else
1009 fprintf(stderr, "Option -%c takes one argument.\n", argv[i][1]);
1010 break;
1011 case 'u':
1012 if(i+1 < argc)
1013 strncpy(uuidvalue+5, argv[++i], strlen(uuidvalue+5) + 1);
1014 else
1015 fprintf(stderr, "Option -%c takes one argument.\n", argv[i][1]);
1016 break;
1017 case 'z':
1018 if(i+1 < argc)
1019 strncpy(friendly_name, argv[++i], FRIENDLY_NAME_MAX_LEN);
1020 else
1021 fprintf(stderr, "Option -%c takes one argument.\n", argv[i][1]);
1022 friendly_name[FRIENDLY_NAME_MAX_LEN-1] = '\0';
1023 break;
1024 case 's':
1025 if(i+1 < argc)
1026 strncpy(serialnumber, argv[++i], SERIALNUMBER_MAX_LEN);
1027 else
1028 fprintf(stderr, "Option -%c takes one argument.\n", argv[i][1]);
1029 serialnumber[SERIALNUMBER_MAX_LEN-1] = '\0';
1030 break;
1031 case 'm':
1032 if(i+1 < argc)
1033 strncpy(modelnumber, argv[++i], MODELNUMBER_MAX_LEN);
1034 else
1035 fprintf(stderr, "Option -%c takes one argument.\n", argv[i][1]);
1036 modelnumber[MODELNUMBER_MAX_LEN-1] = '\0';
1037 break;
1038 #ifdef ENABLE_NATPMP
1039 case 'N':
1040 /*enablenatpmp = 1;*/
1041 SETFLAG(ENABLENATPMPMASK);
1042 break;
1043 #endif
1044 case 'U':
1045 /*sysuptime = 1;*/
1046 SETFLAG(SYSUPTIMEMASK);
1047 break;
1048 /*case 'l':
1049 logfilename = argv[++i];
1050 break;*/
1051 #if defined(USE_PF) || defined(USE_IPF)
1052 case 'L':
1053 /*logpackets = 1;*/
1054 SETFLAG(LOGPACKETSMASK);
1055 break;
1056 #endif
1057 case 'S':
1058 SETFLAG(SECUREMODEMASK);
1059 break;
1060 case 'i':
1061 if(i+1 < argc)
1062 ext_if_name = argv[++i];
1063 else
1064 fprintf(stderr, "Option -%c takes one argument.\n", argv[i][1]);
1065 break;
1066 #ifdef USE_PF
1067 case 'q':
1068 if(i+1 < argc)
1069 queue = argv[++i];
1070 else
1071 fprintf(stderr, "Option -%c takes one argument.\n", argv[i][1]);
1072 break;
1073 case 'T':
1074 if(i+1 < argc)
1075 tag = argv[++i];
1076 else
1077 fprintf(stderr, "Option -%c takes one argument.\n", argv[i][1]);
1078 break;
1079 #endif
1080 case 'p':
1081 if(i+1 < argc)
1082 v->port = atoi(argv[++i]);
1083 else
1084 #ifdef ENABLE_NFQUEUE
1085 case 'Q':
1086 if(i+1<argc)
1088 nfqueue = atoi(argv[++i]);
1090 else
1091 fprintf(stderr, "Option -%c takes one argument.\n", argv[i][1]);
1092 break;
1093 case 'n':
1094 if (i+1 < argc) {
1095 i++;
1096 if(n_nfqix < MAX_LAN_ADDR) {
1097 nfqix[n_nfqix++] = if_nametoindex(argv[i]);
1098 } else {
1099 fprintf(stderr,"Too many nfq interfaces. Ignoring %s\n", argv[i]);
1101 } else {
1102 fprintf(stderr, "Option -%c takes one argument.\n", argv[i][1]);
1104 break;
1105 #endif
1106 fprintf(stderr, "Option -%c takes one argument.\n", argv[i][1]);
1107 break;
1108 case 'P':
1109 if(i+1 < argc)
1110 pidfilename = argv[++i];
1111 else
1112 fprintf(stderr, "Option -%c takes one argument.\n", argv[i][1]);
1113 break;
1114 case 'd':
1115 debug_flag = 1;
1116 break;
1117 case 'w':
1118 if(i+1 < argc)
1119 presurl = argv[++i];
1120 else
1121 fprintf(stderr, "Option -%c takes one argument.\n", argv[i][1]);
1122 break;
1123 case 'B':
1124 if(i+2<argc)
1126 downstream_bitrate = strtoul(argv[++i], 0, 0);
1127 upstream_bitrate = strtoul(argv[++i], 0, 0);
1129 else
1130 fprintf(stderr, "Option -%c takes two arguments.\n", argv[i][1]);
1131 break;
1132 case 'a':
1133 #ifndef MULTIPLE_EXTERNAL_IP
1134 if(i+1 < argc)
1136 i++;
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");
1141 break;
1143 if(parselanaddr(lan_addr, argv[i]) != 0)
1145 fprintf(stderr, "can't parse \"%s\" as valid lan address\n", argv[i]);
1146 free(lan_addr);
1147 break;
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))
1153 break;
1155 if (lan_addr2 == NULL)
1156 LIST_INSERT_HEAD(&lan_addrs, lan_addr, list);
1158 else
1159 fprintf(stderr, "Option -%c takes one argument.\n", argv[i][1]);
1160 #else
1161 if(i+2 < argc)
1163 char *val=calloc((strlen(argv[i+1]) + strlen(argv[i+2]) + 1), sizeof(char));
1164 if (val == NULL)
1166 fprintf(stderr, "memory allocation error for listen address storage\n");
1167 break;
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");
1175 free(val);
1176 break;
1178 if(parselanaddr(lan_addr, val) != 0)
1180 fprintf(stderr, "can't parse \"%s\" as valid lan address\n", val);
1181 free(lan_addr);
1182 free(val);
1183 break;
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))
1189 break;
1191 if (lan_addr2 == NULL)
1192 LIST_INSERT_HEAD(&lan_addrs, lan_addr, list);
1194 free(val);
1195 i+=2;
1197 else
1198 fprintf(stderr, "Option -%c takes two arguments.\n", argv[i][1]);
1199 #endif
1200 break;
1201 case 'A':
1202 if(i+1 < argc) {
1203 void * tmp;
1204 tmp = realloc(upnppermlist, sizeof(struct upnpperm) * (num_upnpperm+1));
1205 if(tmp == NULL) {
1206 fprintf(stderr, "memory allocation error for permission\n");
1207 } else {
1208 upnppermlist = tmp;
1209 if(read_permission_line(upnppermlist + num_upnpperm, argv[++i]) >= 0) {
1210 num_upnpperm++;
1211 } else {
1212 fprintf(stderr, "Permission rule parsing error :\n%s\n", argv[i]);
1215 } else
1216 fprintf(stderr, "Option -%c takes one argument.\n", argv[i][1]);
1217 break;
1218 case 'f':
1219 i++; /* discarding, the config file is already read */
1220 break;
1221 default:
1222 fprintf(stderr, "Unknown option: %s\n", argv[i]);
1225 if(!ext_if_name || !lan_addrs.lh_first)
1227 /* bad configuration */
1228 goto print_usage;
1231 if(debug_flag)
1233 pid = getpid();
1235 else
1237 #ifdef USE_DAEMON
1238 if(daemon(0, 0)<0) {
1239 perror("daemon()");
1241 pid = getpid();
1242 #else
1243 pid = daemonize();
1244 #endif
1247 openlog_option = LOG_PID|LOG_CONS;
1248 if(debug_flag)
1250 openlog_option |= LOG_PERROR; /* also log on stderr */
1253 openlog("miniupnpd", openlog_option, LOG_MINIUPNPD);
1255 if(!debug_flag)
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");
1264 return 1;
1267 syslog(LOG_NOTICE, "version " MINIUPNPD_VERSION " started");
1269 set_startup_time(GETFLAG(SYSUPTIMEMASK));
1271 /* presentation url */
1272 if(presurl)
1274 strncpy(presentationurl, presurl, PRESENTATIONURL_MAX_LEN);
1275 presentationurl[PRESENTATIONURL_MAX_LEN-1] = '\0';
1277 else
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");
1291 return 1;
1293 if(sigaction(SIGINT, &sa, NULL) < 0)
1295 syslog(LOG_ERR, "Failed to set %s handler. EXITING", "SIGINT");
1296 return 1;
1299 // zzz
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");
1317 return 1;
1319 #ifdef ENABLE_6FC_SERVICE
1320 #ifdef USE_NETFILTER
1321 init_iptpinhole();
1322 #endif
1323 #endif
1325 if(writepidfile(pidfilename, pid) < 0)
1326 pidfilename = NULL;
1328 #ifdef ENABLE_LEASEFILE
1329 /*remove(lease_file);*/
1330 syslog(LOG_INFO, "Reloading rules from lease file");
1331 reload_from_lease_file();
1332 #endif
1333 tomato_load(); // zzz
1335 return 0;
1336 print_usage:
1337 fprintf(stderr, "Usage:\n\t"
1338 "%s "
1339 #ifndef DISABLE_CONFIG_FILE
1340 "[-f config_file] "
1341 #endif
1342 "[-i ext_ifname] [-o ext_ip]\n"
1343 #ifndef MULTIPLE_EXTERNAL_IP
1344 "\t\t[-a listening_ip]"
1345 #else
1346 "\t\t[-a listening_ip ext_ip]"
1347 #endif
1348 " [-p port] [-d]"
1349 #if defined(USE_PF) || defined(USE_IPF)
1350 " [-L]"
1351 #endif
1352 " [-U] [-S]"
1353 #ifdef ENABLE_NATPMP
1354 " [-N]"
1355 #endif
1356 "\n"
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"
1361 #ifdef USE_PF
1362 "\t\t[-q queue] [-T tag]\n"
1363 #endif
1364 #ifdef ENABLE_NFQUEUE
1365 "\t\t[-Q queue] [-n name]\n"
1366 #endif
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"
1375 #endif
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"
1381 #endif
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"
1384 #ifdef USE_PF
1385 "\t-q sets the ALTQ queue in pf.\n"
1386 "\t-T sets the tag name in pf.\n"
1387 #endif
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"
1391 #endif
1392 "\t-A use following syntax for permission rules :\n"
1393 "\t (allow|deny) (external port range) ip/mask (internal port range)\n"
1394 "\texamples :\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);
1399 return 1;
1402 /* === main === */
1403 /* process HTTP or SSDP requests */
1405 main(int argc, char * * argv)
1407 int i;
1408 int shttpl = -1; /* socket for HTTP */
1409 int sudp = -1; /* IP v4 socket for receiving SSDP */
1410 #ifdef ENABLE_IPV6
1411 int sudpv6 = -1; /* IP v6 socket for receiving SSDP */
1412 #endif
1413 #ifdef ENABLE_NATPMP
1414 int * snatpmp = NULL;
1415 #endif
1416 #ifdef ENABLE_NFQUEUE
1417 int nfqh = -1;
1418 #endif
1419 #ifdef USE_IFACEWATCHER
1420 int sifacewatcher = -1;
1421 #endif
1423 int * snotify = NULL;
1424 int addr_count;
1425 LIST_HEAD(httplisthead, upnphttp) upnphttphead;
1426 struct upnphttp * e = 0;
1427 struct upnphttp * next;
1428 fd_set readset; /* for select() */
1429 fd_set writeset;
1430 struct timeval timeout, timeofday, lasttimeofday = {0, 0};
1431 int max_fd = -1;
1432 #ifdef USE_MINIUPNPDCTL
1433 int sctl = -1;
1434 LIST_HEAD(ctlstructhead, ctlelem) ctllisthead;
1435 struct ctlelem * ectl;
1436 struct ctlelem * ectlnext;
1437 #endif
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;
1445 #endif
1447 if(init(argc, argv, &v) != 0)
1448 return 1;
1449 /* count lan addrs */
1450 addr_count = 0;
1451 for(lan_addr = lan_addrs.lh_first; lan_addr != NULL; lan_addr = lan_addr->list.le_next)
1452 addr_count++;
1453 if(addr_count > 0) {
1454 #ifndef ENABLE_IPV6
1455 snotify = calloc(addr_count, sizeof(int));
1456 #else
1457 /* one for IPv4, one for IPv6 */
1458 snotify = calloc(addr_count * 2, sizeof(int));
1459 #endif
1461 #ifdef ENABLE_NATPMP
1462 if(addr_count > 0) {
1463 snatpmp = malloc(addr_count * sizeof(int));
1464 for(i = 0; i < addr_count; i++)
1465 snatpmp[i] = -1;
1467 #endif
1469 LIST_INIT(&upnphttphead);
1470 #ifdef USE_MINIUPNPDCTL
1471 LIST_INIT(&ctllisthead);
1472 #endif
1475 #ifdef ENABLE_NATPMP
1476 !GETFLAG(ENABLENATPMPMASK) &&
1477 #endif
1478 !GETFLAG(ENABLEUPNPMASK) ) {
1479 syslog(LOG_ERR, "Why did you run me anyway?");
1480 return 0;
1483 syslog(LOG_INFO, "Starting%s%swith external interface %s",
1484 #ifdef ENABLE_NATPMP
1485 GETFLAG(ENABLENATPMPMASK) ? " NAT-PMP " : " ",
1486 #else
1487 " ",
1488 #endif
1489 GETFLAG(ENABLEUPNPMASK) ? "UPnP-IGD " : "",
1490 ext_if_name);
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);
1497 if(shttpl < 0)
1499 syslog(LOG_ERR, "Failed to open socket for HTTP. EXITING");
1500 return 1;
1502 if(v.port <= 0) {
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");
1507 return 1;
1509 v.port = ntohs(sockinfo.sin_port);
1511 syslog(LOG_NOTICE, "HTTP listening on port %d", v.port);
1512 #ifdef ENABLE_IPV6
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);
1516 } else {
1517 memcpy(ipv6_addr_for_http_with_brackets, "[::1]", 6);
1518 syslog(LOG_WARNING, "no HTTP IPv6 address");
1520 #endif
1522 /* open socket for SSDP connections */
1523 sudp = OpenAndConfSSDPReceiveSocket(0);
1524 if(sudp < 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");
1529 return 1;
1532 #ifdef ENABLE_IPV6
1533 sudpv6 = OpenAndConfSSDPReceiveSocket(1);
1534 if(sudpv6 < 0)
1536 syslog(LOG_WARNING, "Failed to open socket for receiving SSDP (IP v6).");
1538 #endif
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");
1545 return 1;
1548 #ifdef USE_IFACEWATCHER
1549 /* open socket for kernel notifications about new network interfaces */
1550 if (sudp >= 0)
1552 sifacewatcher = OpenAndConfInterfaceWatchSocket();
1553 if (sifacewatcher < 0)
1555 syslog(LOG_ERR, "Failed to open socket for receiving network interface notifications");
1558 #endif
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.");
1568 } else {
1569 syslog(LOG_NOTICE, "Listening for NAT-PMP traffic on port %u",
1570 NATPMP_PORT);
1572 #if 0
1573 ScanNATPMPforExpiration();
1574 #endif
1576 #endif
1578 /* for miniupnpdctl */
1579 #ifdef USE_MINIUPNPDCTL
1580 sctl = OpenAndConfCtlUnixSocket("/var/run/miniupnpd.ctl");
1581 #endif
1583 #ifdef ENABLE_NFQUEUE
1584 if ( nfqueue != -1 && n_nfqix > 0) {
1585 nfqh = OpenAndConfNFqueue();
1586 if(nfqh < 0) {
1587 syslog(LOG_ERR, "Failed to open fd for NFQUEUE.");
1588 return 1;
1589 } else {
1590 syslog(LOG_NOTICE, "Opened NFQUEUE %d",nfqueue);
1593 #endif
1595 tomato_helper(); // zzz
1597 /* main loop */
1598 while(!quitting)
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);
1612 #endif
1613 #ifdef ENABLE_EVENTS
1614 if(GETFLAG(ENABLEUPNPMASK))
1616 upnp_event_var_change_notify(EWanIPC);
1618 #endif
1619 should_send_public_address_change_notif = 0;
1621 /* Check if we need to send SSDP NOTIFY messages and do it if
1622 * needed */
1623 if(gettimeofday(&timeofday, 0) < 0)
1625 syslog(LOG_ERR, "gettimeofday(): %m");
1626 timeout.tv_sec = v.notify_interval;
1627 timeout.tv_usec = 0;
1629 else
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;
1642 else
1644 timeout.tv_sec = lasttimeofday.tv_sec + v.notify_interval
1645 - timeofday.tv_sec;
1646 if(timeofday.tv_usec > lasttimeofday.tv_usec)
1648 timeout.tv_usec = 1000000 + lasttimeofday.tv_usec
1649 - timeofday.tv_usec;
1650 timeout.tv_sec--;
1652 else
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))
1662 if(rule_list)
1664 remove_unused_rules(rule_list);
1665 rule_list = NULL;
1667 else
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
1690 #if 0
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");
1698 break;
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;
1709 #endif
1710 #endif
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;
1720 #endif
1722 /* select open sockets (SSDP, HTTP listen, and all HTTP soap sockets) */
1723 FD_ZERO(&readset);
1724 FD_ZERO(&writeset);
1726 if (sudp >= 0)
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);
1736 #endif
1738 if (shttpl >= 0)
1740 FD_SET(shttpl, &readset);
1741 max_fd = MAX( max_fd, shttpl);
1743 #ifdef ENABLE_IPV6
1744 if (sudpv6 >= 0)
1746 FD_SET(sudpv6, &readset);
1747 max_fd = MAX( max_fd, sudpv6);
1749 #endif
1751 #ifdef ENABLE_NFQUEUE
1752 if (nfqh >= 0)
1754 FD_SET(nfqh, &readset);
1755 max_fd = MAX( max_fd, nfqh);
1757 #endif
1759 i = 0; /* active HTTP connections count */
1760 for(e = upnphttphead.lh_first; e != NULL; e = e->entries.le_next)
1762 if(e->socket >= 0)
1764 if(e->state <= EWaitingForHttpContent)
1765 FD_SET(e->socket, &readset);
1766 else if(e->state == ESendingAndClosing)
1767 FD_SET(e->socket, &writeset);
1768 else
1769 continue;
1770 max_fd = MAX(max_fd, e->socket);
1771 i++;
1774 /* for debug */
1775 #ifdef DEBUG
1776 if(i > 1)
1778 syslog(LOG_DEBUG, "%d active incoming HTTP connections", i);
1780 #endif
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]);
1788 #endif
1789 #ifdef USE_MINIUPNPDCTL
1790 if(sctl >= 0) {
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);
1802 #endif
1804 #ifdef ENABLE_EVENTS
1805 upnpevents_selectfds(&readset, &writeset, &max_fd);
1806 #endif
1808 if(select(max_fd+1, &readset, &writeset, 0, &timeout) < 0)
1810 if(quitting) goto shutdown;
1811 if (gotusr2) { // zzz
1812 gotusr2 = 0;
1813 tomato_helper();
1814 continue;
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))
1827 char buf[256];
1828 int l;
1829 l = read(ectl->socket, buf, sizeof(buf));
1830 if(l > 0)
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);
1836 #endif
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);
1843 #endif
1844 /* close the socket */
1845 close(ectl->socket);
1846 ectl->socket = -1;
1848 else
1850 close(ectl->socket);
1851 ectl->socket = -1;
1854 if(ectl->socket < 0)
1856 LIST_REMOVE(ectl, entries);
1857 free(ectl);
1859 ectl = ectlnext;
1861 if((sctl >= 0) && FD_ISSET(sctl, &readset))
1863 int s;
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,
1869 &clientnamelen);
1870 syslog(LOG_DEBUG, "sctl! : '%s'", clientname.sun_path);
1871 tmp = malloc(sizeof(struct ctlelem));
1872 if (tmp == NULL)
1874 syslog(LOG_ERR, "Unable to allocate memory for ctlelem in main()");
1875 close(s);
1877 else
1879 tmp->socket = s;
1880 LIST_INSERT_HEAD(&ctllisthead, tmp, entries);
1883 #endif
1884 #ifdef ENABLE_EVENTS
1885 upnpevents_processfds(&readset, &writeset);
1886 #endif
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]);
1896 #endif
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);
1903 #ifdef ENABLE_IPV6
1904 if(sudpv6 >= 0 && FD_ISSET(sudpv6, &readset))
1906 syslog(LOG_INFO, "Received UDP Packet (IPv6)");
1907 ProcessSSDPRequest(sudpv6, (unsigned short)v.port);
1909 #endif
1910 #ifdef USE_IFACEWATCHER
1911 /* process kernel notifications */
1912 if (sifacewatcher >= 0 && FD_ISSET(sifacewatcher, &readset))
1913 ProcessInterfaceWatchNotify(sifacewatcher);
1914 #endif
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)
1920 if(e->socket >= 0)
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))
1932 int shttp;
1933 socklen_t clientnamelen;
1934 #ifdef ENABLE_IPV6
1935 struct sockaddr_storage clientname;
1936 clientnamelen = sizeof(struct sockaddr_storage);
1937 #else
1938 struct sockaddr_in clientname;
1939 clientnamelen = sizeof(struct sockaddr_in);
1940 #endif
1941 shttp = accept(shttpl, (struct sockaddr *)&clientname, &clientnamelen);
1942 if(shttp<0)
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");
1948 else
1950 struct upnphttp * tmp = 0;
1951 char addr_str[64];
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 ! */
1958 syslog(LOG_WARNING,
1959 "HTTP peer %s is not from a LAN, closing the connection",
1960 addr_str);
1961 close(shttp);
1963 else
1965 /* Create a new upnphttp object and add it to
1966 * the active upnphttp object list */
1967 tmp = New_upnphttp(shttp);
1968 if(tmp)
1970 #ifdef ENABLE_IPV6
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],
1984 else
1986 tmp->ipv6 = 1;
1987 memcpy(&tmp->clientaddr_v6,
1988 &addr->sin6_addr,
1989 sizeof(struct in6_addr));
1992 #else
1993 tmp->clientaddr = clientname.sin_addr;
1994 #endif
1995 LIST_INSERT_HEAD(&upnphttphead, tmp, entries);
1997 else
1999 syslog(LOG_ERR, "New_upnphttp() failed");
2000 close(shttp);
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);
2012 #endif
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);
2020 Delete_upnphttp(e);
2022 e = next;
2025 } /* end of main loop */
2027 shutdown:
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);
2035 Delete_upnphttp(e);
2038 if (sudp >= 0) close(sudp);
2039 if (shttpl >= 0) close(shttpl);
2040 #ifdef ENABLE_IPV6
2041 if (sudpv6 >= 0) close(sudpv6);
2042 #endif
2043 #ifdef USE_IFACEWATCHER
2044 if(sifacewatcher >= 0) close(sifacewatcher);
2045 #endif
2046 #ifdef ENABLE_NATPMP
2047 for(i=0; i<addr_count; i++) {
2048 if(snatpmp[i]>=0)
2050 close(snatpmp[i]);
2051 snatpmp[i] = -1;
2054 #endif
2055 #ifdef USE_MINIUPNPDCTL
2056 if(sctl>=0)
2058 close(sctl);
2059 sctl = -1;
2060 if(unlink("/var/run/miniupnpd.ctl") < 0)
2062 syslog(LOG_ERR, "unlink() %m");
2065 #endif
2067 if (GETFLAG(ENABLEUPNPMASK))
2069 #ifndef ENABLE_IPV6
2070 if(SendSSDPGoodbye(snotify, addr_count) < 0)
2071 #else
2072 if(SendSSDPGoodbye(snotify, addr_count * 2) < 0)
2073 #endif
2075 syslog(LOG_ERR, "Failed to broadcast good-bye notifications");
2077 #ifndef ENABLE_IPV6
2078 for(i = 0; i < addr_count; i++)
2079 #else
2080 for(i = 0; i < addr_count * 2; i++)
2081 #endif
2082 close(snotify[i]);
2085 if(pidfilename && (unlink(pidfilename) < 0))
2087 syslog(LOG_ERR, "Failed to remove pidfile %s: %m", pidfilename);
2090 /* delete lists */
2091 while(lan_addrs.lh_first != NULL)
2093 lan_addr = lan_addrs.lh_first;
2094 LIST_REMOVE(lan_addrs.lh_first, list);
2095 free(lan_addr);
2098 #ifdef ENABLE_NATPMP
2099 free(snatpmp);
2100 #endif
2101 free(snotify);
2102 closelog();
2103 #ifndef DISABLE_CONFIG_FILE
2104 freeoptions();
2105 #endif
2107 return 0;