Miniupnpd vet 1.8 (20130207)
[tomato.git] / release / src / router / miniupnpd / miniupnpd.c
blob76c2991e363a2fd39661e111aff592f1fb416bf2
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 sa.sa_handler = SIG_IGN;
1300 if(sigaction(SIGPIPE, &sa, NULL) < 0)
1302 syslog(LOG_ERR, "Failed to ignore SIGPIPE signals");
1305 sa.sa_handler = sigusr1;
1306 if(sigaction(SIGUSR1, &sa, NULL) < 0)
1308 syslog(LOG_NOTICE, "Failed to set %s handler", "SIGUSR1");
1311 if(init_redirect() < 0)
1313 syslog(LOG_ERR, "Failed to init redirection engine. EXITING");
1314 return 1;
1316 #ifdef ENABLE_6FC_SERVICE
1317 #ifdef USE_NETFILTER
1318 init_iptpinhole();
1319 #endif
1320 #endif
1322 if(writepidfile(pidfilename, pid) < 0)
1323 pidfilename = NULL;
1325 #ifdef ENABLE_LEASEFILE
1326 /*remove(lease_file);*/
1327 syslog(LOG_INFO, "Reloading rules from lease file");
1328 reload_from_lease_file();
1329 #endif
1330 tomato_load(); // zzz
1332 return 0;
1333 print_usage:
1334 fprintf(stderr, "Usage:\n\t"
1335 "%s "
1336 #ifndef DISABLE_CONFIG_FILE
1337 "[-f config_file] "
1338 #endif
1339 "[-i ext_ifname] [-o ext_ip]\n"
1340 #ifndef MULTIPLE_EXTERNAL_IP
1341 "\t\t[-a listening_ip]"
1342 #else
1343 "\t\t[-a listening_ip ext_ip]"
1344 #endif
1345 " [-p port] [-d]"
1346 #if defined(USE_PF) || defined(USE_IPF)
1347 " [-L]"
1348 #endif
1349 " [-U] [-S]"
1350 #ifdef ENABLE_NATPMP
1351 " [-N]"
1352 #endif
1353 "\n"
1354 /*"[-l logfile] " not functionnal */
1355 "\t\t[-u uuid] [-s serial] [-m model_number] \n"
1356 "\t\t[-t notify_interval] [-P pid_filename] [-z fiendly_name]\n"
1357 "\t\t[-B down up] [-w url] [-r clean_ruleset_interval]\n"
1358 #ifdef USE_PF
1359 "\t\t[-q queue] [-T tag]\n"
1360 #endif
1361 #ifdef ENABLE_NFQUEUE
1362 "\t\t[-Q queue] [-n name]\n"
1363 #endif
1364 "\t\t[-A \"permission rule\"]\n"
1365 "\nNotes:\n\tThere can be one or several listening_ips.\n"
1366 "\tNotify interval is in seconds. Default is 30 seconds.\n"
1367 "\tDefault pid file is '%s'.\n"
1368 "\tDefault config file is '%s'.\n"
1369 "\tWith -d miniupnpd will run as a standard program.\n"
1370 #if defined(USE_PF) || defined(USE_IPF)
1371 "\t-L sets packet log in pf and ipf on.\n"
1372 #endif
1373 "\t-S sets \"secure\" mode : clients can only add mappings to their own ip\n"
1374 "\t-U causes miniupnpd to report system uptime instead "
1375 "of daemon uptime.\n"
1376 #ifdef ENABLE_NATPMP
1377 "\t-N enable NAT-PMP functionality.\n"
1378 #endif
1379 "\t-B sets bitrates reported by daemon in bits per second.\n"
1380 "\t-w sets the presentation url. Default is http address on port 80\n"
1381 #ifdef USE_PF
1382 "\t-q sets the ALTQ queue in pf.\n"
1383 "\t-T sets the tag name in pf.\n"
1384 #endif
1385 #ifdef ENABLE_NFQUEUE
1386 "\t-Q sets the queue number that is used by NFQUEUE.\n"
1387 "\t-n sets the name of the interface(s) that packets will arrive on.\n"
1388 #endif
1389 "\t-A use following syntax for permission rules :\n"
1390 "\t (allow|deny) (external port range) ip/mask (internal port range)\n"
1391 "\texamples :\n"
1392 "\t \"allow 1024-65535 192.168.1.0/24 1024-65535\"\n"
1393 "\t \"deny 0-65535 0.0.0.0/0 0-65535\"\n"
1394 "\t-h prints this help and quits.\n"
1395 "", argv[0], pidfilename, DEFAULT_CONFIG);
1396 return 1;
1399 /* === main === */
1400 /* process HTTP or SSDP requests */
1402 main(int argc, char * * argv)
1404 int i;
1405 int shttpl = -1; /* socket for HTTP */
1406 int sudp = -1; /* IP v4 socket for receiving SSDP */
1407 #ifdef ENABLE_IPV6
1408 int sudpv6 = -1; /* IP v6 socket for receiving SSDP */
1409 #endif
1410 #ifdef ENABLE_NATPMP
1411 int * snatpmp = NULL;
1412 #endif
1413 #ifdef ENABLE_NFQUEUE
1414 int nfqh = -1;
1415 #endif
1416 #ifdef USE_IFACEWATCHER
1417 int sifacewatcher = -1;
1418 #endif
1420 int * snotify = NULL;
1421 int addr_count;
1422 LIST_HEAD(httplisthead, upnphttp) upnphttphead;
1423 struct upnphttp * e = 0;
1424 struct upnphttp * next;
1425 fd_set readset; /* for select() */
1426 fd_set writeset;
1427 struct timeval timeout, timeofday, lasttimeofday = {0, 0};
1428 int max_fd = -1;
1429 #ifdef USE_MINIUPNPDCTL
1430 int sctl = -1;
1431 LIST_HEAD(ctlstructhead, ctlelem) ctllisthead;
1432 struct ctlelem * ectl;
1433 struct ctlelem * ectlnext;
1434 #endif
1435 struct runtime_vars v;
1436 /* variables used for the unused-rule cleanup process */
1437 struct rule_state * rule_list = 0;
1438 struct timeval checktime = {0, 0};
1439 struct lan_addr_s * lan_addr;
1440 #ifdef ENABLE_6FC_SERVICE
1441 unsigned int next_pinhole_ts;
1442 #endif
1444 if(init(argc, argv, &v) != 0)
1445 return 1;
1446 /* count lan addrs */
1447 addr_count = 0;
1448 for(lan_addr = lan_addrs.lh_first; lan_addr != NULL; lan_addr = lan_addr->list.le_next)
1449 addr_count++;
1450 if(addr_count > 0) {
1451 #ifndef ENABLE_IPV6
1452 snotify = calloc(addr_count, sizeof(int));
1453 #else
1454 /* one for IPv4, one for IPv6 */
1455 snotify = calloc(addr_count * 2, sizeof(int));
1456 #endif
1458 #ifdef ENABLE_NATPMP
1459 if(addr_count > 0) {
1460 snatpmp = malloc(addr_count * sizeof(int));
1461 for(i = 0; i < addr_count; i++)
1462 snatpmp[i] = -1;
1464 #endif
1466 LIST_INIT(&upnphttphead);
1467 #ifdef USE_MINIUPNPDCTL
1468 LIST_INIT(&ctllisthead);
1469 #endif
1472 #ifdef ENABLE_NATPMP
1473 !GETFLAG(ENABLENATPMPMASK) &&
1474 #endif
1475 !GETFLAG(ENABLEUPNPMASK) ) {
1476 syslog(LOG_ERR, "Why did you run me anyway?");
1477 return 0;
1480 syslog(LOG_INFO, "Starting%s%swith external interface %s",
1481 #ifdef ENABLE_NATPMP
1482 GETFLAG(ENABLENATPMPMASK) ? " NAT-PMP " : " ",
1483 #else
1484 " ",
1485 #endif
1486 GETFLAG(ENABLEUPNPMASK) ? "UPnP-IGD " : "",
1487 ext_if_name);
1489 if(GETFLAG(ENABLEUPNPMASK))
1492 /* open socket for HTTP connections. Listen on the 1st LAN address */
1493 shttpl = OpenAndConfHTTPSocket((v.port > 0) ? v.port : 0);
1494 if(shttpl < 0)
1496 syslog(LOG_ERR, "Failed to open socket for HTTP. EXITING");
1497 return 1;
1499 if(v.port <= 0) {
1500 struct sockaddr_in sockinfo;
1501 socklen_t len = sizeof(struct sockaddr_in);
1502 if (getsockname(shttpl, (struct sockaddr *)&sockinfo, &len) < 0) {
1503 syslog(LOG_ERR, "getsockname(): %m");
1504 return 1;
1506 v.port = ntohs(sockinfo.sin_port);
1508 syslog(LOG_NOTICE, "HTTP listening on port %d", v.port);
1509 #ifdef ENABLE_IPV6
1510 if(find_ipv6_addr(NULL, ipv6_addr_for_http_with_brackets, sizeof(ipv6_addr_for_http_with_brackets)) > 0) {
1511 syslog(LOG_NOTICE, "HTTP IPv6 address given to control points : %s",
1512 ipv6_addr_for_http_with_brackets);
1513 } else {
1514 memcpy(ipv6_addr_for_http_with_brackets, "[::1]", 6);
1515 syslog(LOG_WARNING, "no HTTP IPv6 address");
1517 #endif
1519 /* open socket for SSDP connections */
1520 sudp = OpenAndConfSSDPReceiveSocket(0);
1521 if(sudp < 0)
1523 syslog(LOG_NOTICE, "Failed to open socket for receiving SSDP. Trying to use MiniSSDPd");
1524 if(SubmitServicesToMiniSSDPD(lan_addrs.lh_first->str, v.port) < 0) {
1525 syslog(LOG_ERR, "Failed to connect to MiniSSDPd. EXITING");
1526 return 1;
1529 #ifdef ENABLE_IPV6
1530 sudpv6 = OpenAndConfSSDPReceiveSocket(1);
1531 if(sudpv6 < 0)
1533 syslog(LOG_WARNING, "Failed to open socket for receiving SSDP (IP v6).");
1535 #endif
1537 /* open socket for sending notifications */
1538 if(OpenAndConfSSDPNotifySockets(snotify) < 0)
1540 syslog(LOG_ERR, "Failed to open sockets for sending SSDP notify "
1541 "messages. EXITING");
1542 return 1;
1545 #ifdef USE_IFACEWATCHER
1546 /* open socket for kernel notifications about new network interfaces */
1547 if (sudp >= 0)
1549 sifacewatcher = OpenAndConfInterfaceWatchSocket();
1550 if (sifacewatcher < 0)
1552 syslog(LOG_ERR, "Failed to open socket for receiving network interface notifications");
1555 #endif
1558 #ifdef ENABLE_NATPMP
1559 /* open socket for NAT PMP traffic */
1560 if(GETFLAG(ENABLENATPMPMASK))
1562 if(OpenAndConfNATPMPSockets(snatpmp) < 0)
1564 syslog(LOG_ERR, "Failed to open sockets for NAT PMP.");
1565 } else {
1566 syslog(LOG_NOTICE, "Listening for NAT-PMP traffic on port %u",
1567 NATPMP_PORT);
1569 #if 0
1570 ScanNATPMPforExpiration();
1571 #endif
1573 #endif
1575 /* for miniupnpdctl */
1576 #ifdef USE_MINIUPNPDCTL
1577 sctl = OpenAndConfCtlUnixSocket("/var/run/miniupnpd.ctl");
1578 #endif
1580 #ifdef ENABLE_NFQUEUE
1581 if ( nfqueue != -1 && n_nfqix > 0) {
1582 nfqh = OpenAndConfNFqueue();
1583 if(nfqh < 0) {
1584 syslog(LOG_ERR, "Failed to open fd for NFQUEUE.");
1585 return 1;
1586 } else {
1587 syslog(LOG_NOTICE, "Opened NFQUEUE %d",nfqueue);
1590 #endif
1592 tomato_helper(); // zzz
1594 /* main loop */
1595 while(!quitting)
1597 /* Correct startup_time if it was set with a RTC close to 0 */
1598 if((startup_time<60*60*24) && (time(NULL)>60*60*24))
1600 set_startup_time(GETFLAG(SYSUPTIMEMASK));
1602 /* send public address change notifications if needed */
1603 if(should_send_public_address_change_notif)
1605 syslog(LOG_DEBUG, "should send external iface address change notification(s)");
1606 #ifdef ENABLE_NATPMP
1607 if(GETFLAG(ENABLENATPMPMASK))
1608 SendNATPMPPublicAddressChangeNotification(snatpmp, addr_count);
1609 #endif
1610 #ifdef ENABLE_EVENTS
1611 if(GETFLAG(ENABLEUPNPMASK))
1613 upnp_event_var_change_notify(EWanIPC);
1615 #endif
1616 should_send_public_address_change_notif = 0;
1618 /* Check if we need to send SSDP NOTIFY messages and do it if
1619 * needed */
1620 if(gettimeofday(&timeofday, 0) < 0)
1622 syslog(LOG_ERR, "gettimeofday(): %m");
1623 timeout.tv_sec = v.notify_interval;
1624 timeout.tv_usec = 0;
1626 else
1628 /* the comparaison is not very precise but who cares ? */
1629 if(timeofday.tv_sec >= (lasttimeofday.tv_sec + v.notify_interval))
1631 if (GETFLAG(ENABLEUPNPMASK))
1632 SendSSDPNotifies2(snotify,
1633 (unsigned short)v.port,
1634 v.notify_interval << 1);
1635 memcpy(&lasttimeofday, &timeofday, sizeof(struct timeval));
1636 timeout.tv_sec = v.notify_interval;
1637 timeout.tv_usec = 0;
1639 else
1641 timeout.tv_sec = lasttimeofday.tv_sec + v.notify_interval
1642 - timeofday.tv_sec;
1643 if(timeofday.tv_usec > lasttimeofday.tv_usec)
1645 timeout.tv_usec = 1000000 + lasttimeofday.tv_usec
1646 - timeofday.tv_usec;
1647 timeout.tv_sec--;
1649 else
1651 timeout.tv_usec = lasttimeofday.tv_usec - timeofday.tv_usec;
1655 /* remove unused rules */
1656 if( v.clean_ruleset_interval
1657 && (timeofday.tv_sec >= checktime.tv_sec + v.clean_ruleset_interval))
1659 if(rule_list)
1661 remove_unused_rules(rule_list);
1662 rule_list = NULL;
1664 else
1666 rule_list = get_upnp_rules_state_list(v.clean_ruleset_threshold);
1668 memcpy(&checktime, &timeofday, sizeof(struct timeval));
1670 /* Remove expired port mappings, based on UPnP IGD LeaseDuration
1671 * or NAT-PMP lifetime) */
1672 if(nextruletoclean_timestamp
1673 && ((unsigned int)timeofday.tv_sec >= nextruletoclean_timestamp))
1675 syslog(LOG_DEBUG, "cleaning expired Port Mappings");
1676 get_upnp_rules_state_list(0);
1678 if(nextruletoclean_timestamp
1679 && ((unsigned int)timeout.tv_sec >= (nextruletoclean_timestamp - timeofday.tv_sec)))
1681 timeout.tv_sec = nextruletoclean_timestamp - timeofday.tv_sec;
1682 timeout.tv_usec = 0;
1683 syslog(LOG_DEBUG, "setting timeout to %u sec",
1684 (unsigned)timeout.tv_sec);
1686 #ifdef ENABLE_NATPMP
1687 #if 0
1688 /* Remove expired NAT-PMP mappings */
1689 while(nextnatpmptoclean_timestamp
1690 && (timeofday.tv_sec >= nextnatpmptoclean_timestamp + startup_time))
1692 /*syslog(LOG_DEBUG, "cleaning expired NAT-PMP mappings");*/
1693 if(CleanExpiredNATPMP() < 0) {
1694 syslog(LOG_ERR, "CleanExpiredNATPMP() failed");
1695 break;
1698 if(nextnatpmptoclean_timestamp
1699 && timeout.tv_sec >= (nextnatpmptoclean_timestamp + startup_time - timeofday.tv_sec))
1701 /*syslog(LOG_DEBUG, "setting timeout to %d sec",
1702 nextnatpmptoclean_timestamp + startup_time - timeofday.tv_sec);*/
1703 timeout.tv_sec = nextnatpmptoclean_timestamp + startup_time - timeofday.tv_sec;
1704 timeout.tv_usec = 0;
1706 #endif
1707 #endif
1708 #ifdef ENABLE_6FC_SERVICE
1709 /* Clean up expired IPv6 PinHoles */
1710 next_pinhole_ts = 0;
1711 upnp_clean_expired_pinholes(&next_pinhole_ts);
1712 if(next_pinhole_ts &&
1713 timeout.tv_sec >= (int)(next_pinhole_ts - timeofday.tv_sec)) {
1714 timeout.tv_sec = next_pinhole_ts - timeofday.tv_sec;
1715 timeout.tv_usec = 0;
1717 #endif
1719 /* select open sockets (SSDP, HTTP listen, and all HTTP soap sockets) */
1720 FD_ZERO(&readset);
1721 FD_ZERO(&writeset);
1723 if (sudp >= 0)
1725 FD_SET(sudp, &readset);
1726 max_fd = MAX( max_fd, sudp);
1727 #ifdef USE_IFACEWATCHER
1728 if (sifacewatcher >= 0)
1730 FD_SET(sifacewatcher, &readset);
1731 max_fd = MAX(max_fd, sifacewatcher);
1733 #endif
1735 if (shttpl >= 0)
1737 FD_SET(shttpl, &readset);
1738 max_fd = MAX( max_fd, shttpl);
1740 #ifdef ENABLE_IPV6
1741 if (sudpv6 >= 0)
1743 FD_SET(sudpv6, &readset);
1744 max_fd = MAX( max_fd, sudpv6);
1746 #endif
1748 #ifdef ENABLE_NFQUEUE
1749 if (nfqh >= 0)
1751 FD_SET(nfqh, &readset);
1752 max_fd = MAX( max_fd, nfqh);
1754 #endif
1756 i = 0; /* active HTTP connections count */
1757 for(e = upnphttphead.lh_first; e != NULL; e = e->entries.le_next)
1759 if(e->socket >= 0)
1761 if(e->state <= EWaitingForHttpContent)
1762 FD_SET(e->socket, &readset);
1763 else if(e->state == ESendingAndClosing)
1764 FD_SET(e->socket, &writeset);
1765 else
1766 continue;
1767 max_fd = MAX(max_fd, e->socket);
1768 i++;
1771 /* for debug */
1772 #ifdef DEBUG
1773 if(i > 1)
1775 syslog(LOG_DEBUG, "%d active incoming HTTP connections", i);
1777 #endif
1778 #ifdef ENABLE_NATPMP
1779 for(i=0; i<addr_count; i++) {
1780 if(snatpmp[i] >= 0) {
1781 FD_SET(snatpmp[i], &readset);
1782 max_fd = MAX( max_fd, snatpmp[i]);
1785 #endif
1786 #ifdef USE_MINIUPNPDCTL
1787 if(sctl >= 0) {
1788 FD_SET(sctl, &readset);
1789 max_fd = MAX( max_fd, sctl);
1792 for(ectl = ctllisthead.lh_first; ectl; ectl = ectl->entries.le_next)
1794 if(ectl->socket >= 0) {
1795 FD_SET(ectl->socket, &readset);
1796 max_fd = MAX( max_fd, ectl->socket);
1799 #endif
1801 #ifdef ENABLE_EVENTS
1802 upnpevents_selectfds(&readset, &writeset, &max_fd);
1803 #endif
1805 if(select(max_fd+1, &readset, &writeset, 0, &timeout) < 0)
1807 if(quitting) goto shutdown;
1808 if (gotusr2) { // zzz
1809 gotusr2 = 0;
1810 tomato_helper();
1811 continue;
1813 if(errno == EINTR) continue; /* interrupted by a signal, start again */
1814 syslog(LOG_ERR, "select(all): %m");
1815 syslog(LOG_ERR, "Failed to select open sockets. EXITING");
1816 return 1; /* very serious cause of error */
1818 #ifdef USE_MINIUPNPDCTL
1819 for(ectl = ctllisthead.lh_first; ectl;)
1821 ectlnext = ectl->entries.le_next;
1822 if((ectl->socket >= 0) && FD_ISSET(ectl->socket, &readset))
1824 char buf[256];
1825 int l;
1826 l = read(ectl->socket, buf, sizeof(buf));
1827 if(l > 0)
1829 /*write(ectl->socket, buf, l);*/
1830 write_command_line(ectl->socket, argc, argv);
1831 #ifndef DISABLE_CONFIG_FILE
1832 write_option_list(ectl->socket);
1833 #endif
1834 write_permlist(ectl->socket, upnppermlist, num_upnpperm);
1835 write_upnphttp_details(ectl->socket, upnphttphead.lh_first);
1836 write_ctlsockets_list(ectl->socket, ctllisthead.lh_first);
1837 write_ruleset_details(ectl->socket);
1838 #ifdef ENABLE_EVENTS
1839 write_events_details(ectl->socket);
1840 #endif
1841 /* close the socket */
1842 close(ectl->socket);
1843 ectl->socket = -1;
1845 else
1847 close(ectl->socket);
1848 ectl->socket = -1;
1851 if(ectl->socket < 0)
1853 LIST_REMOVE(ectl, entries);
1854 free(ectl);
1856 ectl = ectlnext;
1858 if((sctl >= 0) && FD_ISSET(sctl, &readset))
1860 int s;
1861 struct sockaddr_un clientname;
1862 struct ctlelem * tmp;
1863 socklen_t clientnamelen = sizeof(struct sockaddr_un);
1864 /*syslog(LOG_DEBUG, "sctl!");*/
1865 s = accept(sctl, (struct sockaddr *)&clientname,
1866 &clientnamelen);
1867 syslog(LOG_DEBUG, "sctl! : '%s'", clientname.sun_path);
1868 tmp = malloc(sizeof(struct ctlelem));
1869 if (tmp == NULL)
1871 syslog(LOG_ERR, "Unable to allocate memory for ctlelem in main()");
1872 close(s);
1874 else
1876 tmp->socket = s;
1877 LIST_INSERT_HEAD(&ctllisthead, tmp, entries);
1880 #endif
1881 #ifdef ENABLE_EVENTS
1882 upnpevents_processfds(&readset, &writeset);
1883 #endif
1884 #ifdef ENABLE_NATPMP
1885 /* process NAT-PMP packets */
1886 for(i=0; i<addr_count; i++)
1888 if((snatpmp[i] >= 0) && FD_ISSET(snatpmp[i], &readset))
1890 ProcessIncomingNATPMPPacket(snatpmp[i]);
1893 #endif
1894 /* process SSDP packets */
1895 if(sudp >= 0 && FD_ISSET(sudp, &readset))
1897 /*syslog(LOG_INFO, "Received UDP Packet");*/
1898 ProcessSSDPRequest(sudp, (unsigned short)v.port);
1900 #ifdef ENABLE_IPV6
1901 if(sudpv6 >= 0 && FD_ISSET(sudpv6, &readset))
1903 syslog(LOG_INFO, "Received UDP Packet (IPv6)");
1904 ProcessSSDPRequest(sudpv6, (unsigned short)v.port);
1906 #endif
1907 #ifdef USE_IFACEWATCHER
1908 /* process kernel notifications */
1909 if (sifacewatcher >= 0 && FD_ISSET(sifacewatcher, &readset))
1910 ProcessInterfaceWatchNotify(sifacewatcher);
1911 #endif
1913 /* process active HTTP connections */
1914 /* LIST_FOREACH macro is not available under linux */
1915 for(e = upnphttphead.lh_first; e != NULL; e = e->entries.le_next)
1917 if(e->socket >= 0)
1919 if(FD_ISSET(e->socket, &readset) ||
1920 FD_ISSET(e->socket, &writeset))
1922 Process_upnphttp(e);
1926 /* process incoming HTTP connections */
1927 if(shttpl >= 0 && FD_ISSET(shttpl, &readset))
1929 int shttp;
1930 socklen_t clientnamelen;
1931 #ifdef ENABLE_IPV6
1932 struct sockaddr_storage clientname;
1933 clientnamelen = sizeof(struct sockaddr_storage);
1934 #else
1935 struct sockaddr_in clientname;
1936 clientnamelen = sizeof(struct sockaddr_in);
1937 #endif
1938 shttp = accept(shttpl, (struct sockaddr *)&clientname, &clientnamelen);
1939 if(shttp<0)
1941 /* ignore EAGAIN, EWOULDBLOCK, EINTR, we just try again later */
1942 if(errno != EAGAIN && errno != EWOULDBLOCK && errno != EINTR)
1943 syslog(LOG_ERR, "accept(http): %m");
1945 else
1947 struct upnphttp * tmp = 0;
1948 char addr_str[64];
1950 sockaddr_to_string((struct sockaddr *)&clientname, addr_str, sizeof(addr_str));
1951 syslog(LOG_INFO, "HTTP connection from %s", addr_str);
1952 if(get_lan_for_peer((struct sockaddr *)&clientname) == NULL)
1954 /* The peer is not a LAN ! */
1955 syslog(LOG_WARNING,
1956 "HTTP peer %s is not from a LAN, closing the connection",
1957 addr_str);
1958 close(shttp);
1960 else
1962 /* Create a new upnphttp object and add it to
1963 * the active upnphttp object list */
1964 tmp = New_upnphttp(shttp);
1965 if(tmp)
1967 #ifdef ENABLE_IPV6
1968 if(clientname.ss_family == AF_INET)
1970 tmp->clientaddr = ((struct sockaddr_in *)&clientname)->sin_addr;
1972 else if(clientname.ss_family == AF_INET6)
1974 struct sockaddr_in6 * addr = (struct sockaddr_in6 *)&clientname;
1975 if(IN6_IS_ADDR_V4MAPPED(&addr->sin6_addr))
1977 memcpy(&tmp->clientaddr,
1978 &addr->sin6_addr.s6_addr[12],
1981 else
1983 tmp->ipv6 = 1;
1984 memcpy(&tmp->clientaddr_v6,
1985 &addr->sin6_addr,
1986 sizeof(struct in6_addr));
1989 #else
1990 tmp->clientaddr = clientname.sin_addr;
1991 #endif
1992 LIST_INSERT_HEAD(&upnphttphead, tmp, entries);
1994 else
1996 syslog(LOG_ERR, "New_upnphttp() failed");
1997 close(shttp);
2002 #ifdef ENABLE_NFQUEUE
2003 /* process NFQ packets */
2004 if(nfqh >= 0 && FD_ISSET(nfqh, &readset))
2006 /* syslog(LOG_INFO, "Received NFQUEUE Packet");*/
2007 ProcessNFQUEUE(nfqh);
2009 #endif
2010 /* delete finished HTTP connections */
2011 for(e = upnphttphead.lh_first; e != NULL; )
2013 next = e->entries.le_next;
2014 if(e->state >= EToDelete)
2016 LIST_REMOVE(e, entries);
2017 Delete_upnphttp(e);
2019 e = next;
2022 } /* end of main loop */
2024 shutdown:
2025 tomato_save("/etc/upnp/data"); // zzz
2027 /* close out open sockets */
2028 while(upnphttphead.lh_first != NULL)
2030 e = upnphttphead.lh_first;
2031 LIST_REMOVE(e, entries);
2032 Delete_upnphttp(e);
2035 if (sudp >= 0) close(sudp);
2036 if (shttpl >= 0) close(shttpl);
2037 #ifdef ENABLE_IPV6
2038 if (sudpv6 >= 0) close(sudpv6);
2039 #endif
2040 #ifdef USE_IFACEWATCHER
2041 if(sifacewatcher >= 0) close(sifacewatcher);
2042 #endif
2043 #ifdef ENABLE_NATPMP
2044 for(i=0; i<addr_count; i++) {
2045 if(snatpmp[i]>=0)
2047 close(snatpmp[i]);
2048 snatpmp[i] = -1;
2051 #endif
2052 #ifdef USE_MINIUPNPDCTL
2053 if(sctl>=0)
2055 close(sctl);
2056 sctl = -1;
2057 if(unlink("/var/run/miniupnpd.ctl") < 0)
2059 syslog(LOG_ERR, "unlink() %m");
2062 #endif
2064 if (GETFLAG(ENABLEUPNPMASK))
2066 #ifndef ENABLE_IPV6
2067 if(SendSSDPGoodbye(snotify, addr_count) < 0)
2068 #else
2069 if(SendSSDPGoodbye(snotify, addr_count * 2) < 0)
2070 #endif
2072 syslog(LOG_ERR, "Failed to broadcast good-bye notifications");
2074 #ifndef ENABLE_IPV6
2075 for(i = 0; i < addr_count; i++)
2076 #else
2077 for(i = 0; i < addr_count * 2; i++)
2078 #endif
2079 close(snotify[i]);
2082 if(pidfilename && (unlink(pidfilename) < 0))
2084 syslog(LOG_ERR, "Failed to remove pidfile %s: %m", pidfilename);
2087 /* delete lists */
2088 while(lan_addrs.lh_first != NULL)
2090 lan_addr = lan_addrs.lh_first;
2091 LIST_REMOVE(lan_addrs.lh_first, list);
2092 free(lan_addr);
2095 #ifdef ENABLE_NATPMP
2096 free(snatpmp);
2097 #endif
2098 free(snotify);
2099 closelog();
2100 #ifndef DISABLE_CONFIG_FILE
2101 freeoptions();
2102 #endif
2104 return 0;