Miniupnpd: update to 1.9 (20150430)
[tomato.git] / release / src / router / miniupnpd / miniupnpd.c
blob6517a304a120562f44e6243c80a1acfda12f20db
1 /* $Id: miniupnpd.c,v 1.207 2015/03/07 15:53:50 nanard Exp $ */
2 /* MiniUPnP project
3 * http://miniupnp.free.fr/ or http://miniupnp.tuxfamily.org/
4 * (c) 2006-2015 Thomas Bernard
5 * This software is subject to the conditions detailed
6 * in the LICENCE file provided within the distribution */
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 #elif !defined(__linux__)
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 <sys/stat.h>
53 #include "macros.h"
54 #include "upnpglobalvars.h"
55 #include "upnphttp.h"
56 #include "upnpdescgen.h"
57 #include "miniupnpdpath.h"
58 #include "getifaddr.h"
59 #include "upnpsoap.h"
60 #include "options.h"
61 #include "minissdp.h"
62 #include "upnpredirect.h"
63 #include "upnppinhole.h"
64 #include "miniupnpdtypes.h"
65 #include "daemonize.h"
66 #include "upnpevents.h"
67 #include "asyncsendto.h"
68 #ifdef ENABLE_NATPMP
69 #include "natpmp.h"
70 #ifdef ENABLE_PCP
71 #include "pcpserver.h"
72 #else
73 #define PCP_MAX_LEN 32
74 #endif
75 #endif
76 #include "commonrdr.h"
77 #include "upnputils.h"
78 #ifdef USE_IFACEWATCHER
79 #include "ifacewatcher.h"
80 #endif
81 #ifdef ENABLE_UPNPPINHOLE
82 #ifdef USE_NETFILTER
83 void init_iptpinhole(void);
84 #endif
85 #endif
87 #ifndef DEFAULT_CONFIG
88 #define DEFAULT_CONFIG "/etc/miniupnpd.conf"
89 #endif
91 #ifdef USE_MINIUPNPDCTL
92 struct ctlelem {
93 int socket;
94 LIST_ENTRY(ctlelem) entries;
96 #endif
98 #ifdef ENABLE_NFQUEUE
99 /* globals */
100 static struct nfq_handle *nfqHandle;
101 static struct sockaddr_in ssdp;
103 /* prototypes */
104 static int nfqueue_cb( struct nfq_q_handle *qh, struct nfgenmsg *nfmsg, struct nfq_data *nfa, void *data) ;
105 int identify_ip_protocol (char *payload);
106 int get_udp_dst_port (char *payload);
107 #endif
109 /* variables used by signals */
110 static volatile sig_atomic_t quitting = 0;
111 volatile sig_atomic_t should_send_public_address_change_notif = 0;
114 #if 1
115 static volatile int gotusr2 = 0;
117 static void sigusr2(int sig)
119 gotusr2 = 1;
122 static void tomato_save(const char *fname)
124 unsigned short eport;
125 unsigned short iport;
126 unsigned int leaseduration;
127 unsigned int timestamp;
128 char proto[4];
129 char iaddr[32];
130 char desc[64];
131 char rhost[32];
132 int n;
133 FILE *f;
134 int t;
135 char tmp[128];
137 strcpy(tmp, "/etc/upnp/saveXXXXXX");
138 if ((t = mkstemp(tmp)) != -1) {
139 if ((f = fdopen(t, "w")) != NULL) {
140 n = 0;
141 while (upnp_get_redirection_infos_by_index(n, &eport, proto, &iport, iaddr, sizeof(iaddr), desc, sizeof(desc), rhost, sizeof(rhost), &leaseduration) == 0) {
142 timestamp = (leaseduration > 0) ? time(NULL) + leaseduration : 0;
143 fprintf(f, "%s %u %s %u [%s] %u\n", proto, eport, iaddr, iport, desc, timestamp);
144 ++n;
146 fclose(f);
147 rename(tmp, fname);
149 else {
150 close(t);
152 unlink(tmp);
156 static void tomato_load(void)
158 FILE *f;
159 char s[256];
160 unsigned short eport;
161 unsigned short iport;
162 unsigned int leaseduration;
163 unsigned int timestamp;
164 time_t current_time;
165 char proto[4];
166 char iaddr[32];
167 char *rhost;
168 char *a, *b;
170 if ((f = fopen("/etc/upnp/data", "r")) != NULL) {
171 current_time = time(NULL);
172 s[sizeof(s) - 1] = 0;
173 while (fgets(s, sizeof(s) - 1, f)) {
174 if (sscanf(s, "%3s %hu %31s %hu [%*s] %u", proto, &eport, iaddr, &iport, &timestamp) >= 4) {
175 if (((a = strchr(s, '[')) != NULL) && ((b = strrchr(a, ']')) != NULL)) {
176 if (timestamp > 0) {
177 if (timestamp > current_time)
178 leaseduration = current_time - timestamp;
179 else
180 continue;
181 } else {
182 leaseduration = 0; /* default value */
184 *b = 0;
185 rhost = NULL;
186 upnp_redirect(rhost, eport, iaddr, iport, proto, a + 1, leaseduration);
190 fclose(f);
192 #ifdef ENABLE_NATPMP
193 #if 0
194 ScanNATPMPforExpiration();
195 #endif
196 #endif
197 unlink("/etc/upnp/load");
200 static void tomato_delete(void)
202 FILE *f;
203 char s[128];
204 unsigned short eport;
205 unsigned short iport;
206 unsigned int leaseduration;
207 char proto[4];
208 char iaddr[32];
209 char desc[64];
210 char rhost[32];
211 int n;
213 if ((f = fopen("/etc/upnp/delete", "r")) != NULL) {
214 s[sizeof(s) - 1] = 0;
215 while (fgets(s, sizeof(s) - 1, f)) {
216 if (sscanf(s, "%3s %hu", proto, &eport) == 2) {
217 if (proto[0] == '*') {
218 n = upnp_get_portmapping_number_of_entries();
219 while (--n >= 0) {
220 if (upnp_get_redirection_infos_by_index(n, &eport, proto, &iport, iaddr, sizeof(iaddr), desc, sizeof(desc), rhost, sizeof(rhost), &leaseduration) == 0) {
221 upnp_delete_redirection(eport, proto);
224 break;
226 else {
227 upnp_delete_redirection(eport, proto);
231 fclose(f);
232 unlink("/etc/upnp/delete");
236 static void tomato_helper(void)
238 struct stat st;
240 if (stat("/etc/upnp/delete", &st) == 0) {
241 tomato_delete();
244 if (stat("/etc/upnp/load", &st) == 0) {
245 tomato_load();
248 if (stat("/etc/upnp/save", &st) == 0) {
249 tomato_save("/etc/upnp/data");
250 unlink("/etc/upnp/save");
253 if (stat("/etc/upnp/info", &st) == 0) {
254 tomato_save("/etc/upnp/data.info");
255 unlink("/etc/upnp/info");
258 #endif /* 1 (tomato) */
261 /* OpenAndConfHTTPSocket() :
262 * setup the socket used to handle incoming HTTP connections. */
263 static int
264 #ifdef ENABLE_IPV6
265 OpenAndConfHTTPSocket(unsigned short * port, int ipv6)
266 #else
267 OpenAndConfHTTPSocket(unsigned short * port)
268 #endif
270 int s;
271 int i = 1;
272 #ifdef ENABLE_IPV6
273 struct sockaddr_in6 listenname6;
274 struct sockaddr_in listenname4;
275 #else
276 struct sockaddr_in listenname;
277 #endif
278 socklen_t listenname_len;
280 s = socket(
281 #ifdef ENABLE_IPV6
282 ipv6 ? PF_INET6 : PF_INET,
283 #else
284 PF_INET,
285 #endif
286 SOCK_STREAM, 0);
287 #ifdef ENABLE_IPV6
288 if(s < 0 && ipv6 && errno == EAFNOSUPPORT)
290 /* the system doesn't support IPV6 */
291 syslog(LOG_WARNING, "socket(PF_INET6, ...) failed with EAFNOSUPPORT, disabling IPv6");
292 SETFLAG(IPV6DISABLEDMASK);
293 ipv6 = 0;
294 s = socket(PF_INET, SOCK_STREAM, 0);
296 #endif
297 if(s < 0)
299 syslog(LOG_ERR, "socket(http): %m");
300 return -1;
303 if(setsockopt(s, SOL_SOCKET, SO_REUSEADDR, &i, sizeof(i)) < 0)
305 syslog(LOG_WARNING, "setsockopt(http, SO_REUSEADDR): %m");
307 #if 0
308 /* enable this to force IPV6 only for IPV6 socket.
309 * see http://www.ietf.org/rfc/rfc3493.txt section 5.3 */
310 if(setsockopt(s, IPPROTO_IPV6, IPV6_V6ONLY, &i, sizeof(i)) < 0)
312 syslog(LOG_WARNING, "setsockopt(http, IPV6_V6ONLY): %m");
314 #endif
316 if(!set_non_blocking(s))
318 syslog(LOG_WARNING, "set_non_blocking(http): %m");
321 #ifdef ENABLE_IPV6
322 if(ipv6)
324 memset(&listenname6, 0, sizeof(struct sockaddr_in6));
325 listenname6.sin6_family = AF_INET6;
326 listenname6.sin6_port = htons(*port);
327 listenname6.sin6_addr = ipv6_bind_addr;
328 listenname_len = sizeof(struct sockaddr_in6);
329 } else {
330 memset(&listenname4, 0, sizeof(struct sockaddr_in));
331 listenname4.sin_family = AF_INET;
332 listenname4.sin_port = htons(*port);
333 listenname4.sin_addr.s_addr = htonl(INADDR_ANY);
334 listenname_len = sizeof(struct sockaddr_in);
336 #else
337 memset(&listenname, 0, sizeof(struct sockaddr_in));
338 listenname.sin_family = AF_INET;
339 listenname.sin_port = htons(*port);
340 listenname.sin_addr.s_addr = htonl(INADDR_ANY);
341 listenname_len = sizeof(struct sockaddr_in);
342 #endif
344 #ifdef ENABLE_IPV6
345 if(bind(s,
346 ipv6 ? (struct sockaddr *)&listenname6 : (struct sockaddr *)&listenname4,
347 listenname_len) < 0)
348 #else
349 if(bind(s, (struct sockaddr *)&listenname, listenname_len) < 0)
350 #endif
352 syslog(LOG_ERR, "bind(http): %m");
353 close(s);
354 return -1;
357 if(listen(s, 5) < 0)
359 syslog(LOG_ERR, "listen(http): %m");
360 close(s);
361 return -1;
364 if(*port == 0) {
365 #ifdef ENABLE_IPV6
366 if(ipv6) {
367 struct sockaddr_in6 sockinfo;
368 socklen_t len = sizeof(struct sockaddr_in6);
369 if (getsockname(s, (struct sockaddr *)&sockinfo, &len) < 0) {
370 syslog(LOG_ERR, "getsockname(): %m");
371 } else {
372 *port = ntohs(sockinfo.sin6_port);
374 } else {
375 #endif /* ENABLE_IPV6 */
376 struct sockaddr_in sockinfo;
377 socklen_t len = sizeof(struct sockaddr_in);
378 if (getsockname(s, (struct sockaddr *)&sockinfo, &len) < 0) {
379 syslog(LOG_ERR, "getsockname(): %m");
380 } else {
381 *port = ntohs(sockinfo.sin_port);
383 #ifdef ENABLE_IPV6
385 #endif /* ENABLE_IPV6 */
387 return s;
390 static struct upnphttp *
391 ProcessIncomingHTTP(int shttpl, const char * protocol)
393 int shttp;
394 socklen_t clientnamelen;
395 #ifdef ENABLE_IPV6
396 struct sockaddr_storage clientname;
397 clientnamelen = sizeof(struct sockaddr_storage);
398 #else
399 struct sockaddr_in clientname;
400 clientnamelen = sizeof(struct sockaddr_in);
401 #endif
402 shttp = accept(shttpl, (struct sockaddr *)&clientname, &clientnamelen);
403 if(shttp<0)
405 /* ignore EAGAIN, EWOULDBLOCK, EINTR, we just try again later */
406 if(errno != EAGAIN && errno != EWOULDBLOCK && errno != EINTR)
407 syslog(LOG_ERR, "accept(http): %m");
409 else
411 struct upnphttp * tmp = 0;
412 char addr_str[64];
414 sockaddr_to_string((struct sockaddr *)&clientname, addr_str, sizeof(addr_str));
415 syslog(LOG_INFO, "%s connection from %s", protocol, addr_str);
416 if(get_lan_for_peer((struct sockaddr *)&clientname) == NULL)
418 /* The peer is not a LAN ! */
419 syslog(LOG_WARNING,
420 "%s peer %s is not from a LAN, closing the connection",
421 protocol, addr_str);
422 close(shttp);
424 else
426 /* Create a new upnphttp object and add it to
427 * the active upnphttp object list */
428 tmp = New_upnphttp(shttp);
429 if(tmp)
431 #ifdef ENABLE_IPV6
432 if(clientname.ss_family == AF_INET)
434 tmp->clientaddr = ((struct sockaddr_in *)&clientname)->sin_addr;
436 else if(clientname.ss_family == AF_INET6)
438 struct sockaddr_in6 * addr = (struct sockaddr_in6 *)&clientname;
439 if(IN6_IS_ADDR_V4MAPPED(&addr->sin6_addr))
441 memcpy(&tmp->clientaddr,
442 &addr->sin6_addr.s6_addr[12],
445 else
447 tmp->ipv6 = 1;
448 memcpy(&tmp->clientaddr_v6,
449 &addr->sin6_addr,
450 sizeof(struct in6_addr));
453 #else
454 tmp->clientaddr = clientname.sin_addr;
455 #endif
456 return tmp;
458 else
460 syslog(LOG_ERR, "New_upnphttp() failed");
461 close(shttp);
465 return NULL;
468 #ifdef ENABLE_NFQUEUE
470 int identify_ip_protocol(char *payload) {
471 return payload[9];
476 * This function returns the destination port of the captured packet UDP
478 int get_udp_dst_port(char *payload) {
479 char *pkt_data_ptr = NULL;
480 pkt_data_ptr = payload + sizeof(struct ip);
482 /* Cast the UDP Header from the raw packet */
483 struct udphdr *udp = (struct udphdr *) pkt_data_ptr;
485 /* get the dst port of the packet */
486 return(ntohs(udp->dest));
489 static int
490 OpenAndConfNFqueue(){
492 struct nfq_q_handle *myQueue;
493 struct nfnl_handle *netlinkHandle;
495 int fd = 0, e = 0;
497 inet_pton(AF_INET, "239.255.255.250", &(ssdp.sin_addr));
499 /* Get a queue connection handle from the module */
500 if (!(nfqHandle = nfq_open())) {
501 syslog(LOG_ERR, "Error in nfq_open(): %m");
502 return -1;
505 /* Unbind the handler from processing any IP packets
506 Not totally sure why this is done, or if it's necessary... */
507 if ((e = nfq_unbind_pf(nfqHandle, AF_INET)) < 0) {
508 syslog(LOG_ERR, "Error in nfq_unbind_pf(): %m");
509 return -1;
512 /* Bind this handler to process IP packets... */
513 if (nfq_bind_pf(nfqHandle, AF_INET) < 0) {
514 syslog(LOG_ERR, "Error in nfq_bind_pf(): %m");
515 return -1;
518 /* Install a callback on queue -Q */
519 if (!(myQueue = nfq_create_queue(nfqHandle, nfqueue, &nfqueue_cb, NULL))) {
520 syslog(LOG_ERR, "Error in nfq_create_queue(): %m");
521 return -1;
524 /* Turn on packet copy mode */
525 if (nfq_set_mode(myQueue, NFQNL_COPY_PACKET, 0xffff) < 0) {
526 syslog(LOG_ERR, "Error setting packet copy mode (): %m");
527 return -1;
530 netlinkHandle = nfq_nfnlh(nfqHandle);
531 fd = nfnl_fd(netlinkHandle);
533 return fd;
538 static int nfqueue_cb(
539 struct nfq_q_handle *qh,
540 struct nfgenmsg *nfmsg,
541 struct nfq_data *nfa,
542 void *data) {
544 char *pkt;
545 struct nfqnl_msg_packet_hdr *ph;
546 ph = nfq_get_msg_packet_hdr(nfa);
548 if ( ph ) {
550 int id = 0, size = 0;
551 id = ntohl(ph->packet_id);
553 size = nfq_get_payload(nfa, &pkt);
555 struct ip *iph = (struct ip *) pkt;
557 int id_protocol = identify_ip_protocol(pkt);
559 int dport = get_udp_dst_port(pkt);
561 int x = sizeof (struct ip) + sizeof (struct udphdr);
563 /* packets we are interested in are UDP multicast to 239.255.255.250:1900
564 * and start with a data string M-SEARCH
566 if ( (dport == 1900) && (id_protocol == IPPROTO_UDP)
567 && (ssdp.sin_addr.s_addr == iph->ip_dst.s_addr) ) {
569 /* get the index that the packet came in on */
570 u_int32_t idx = nfq_get_indev(nfa);
571 int i = 0;
572 for ( ;i < n_nfqix ; i++) {
573 if ( nfqix[i] == idx ) {
575 struct udphdr *udp = (struct udphdr *) (pkt + sizeof(struct ip));
577 char *dd = pkt + x;
579 struct sockaddr_in sendername;
580 sendername.sin_family = AF_INET;
581 sendername.sin_port = udp->source;
582 sendername.sin_addr.s_addr = iph->ip_src.s_addr;
584 /* printf("pkt found %s\n",dd);*/
585 ProcessSSDPData (sudp, dd, size - x,
586 &sendername, (unsigned short) 5555);
591 nfq_set_verdict(qh, id, NF_ACCEPT, 0, NULL);
593 } else {
594 syslog(LOG_ERR,"nfq_get_msg_packet_hdr failed");
595 return 1;
596 /* from nfqueue source: 0 = ok, >0 = soft error, <0 hard error */
599 return 0;
602 static void ProcessNFQUEUE(int fd){
603 char buf[4096];
605 socklen_t len_r;
606 struct sockaddr_in sendername;
607 len_r = sizeof(struct sockaddr_in);
609 int res = recvfrom(fd, buf, sizeof(buf), 0,
610 (struct sockaddr *)&sendername, &len_r);
612 nfq_handle_packet(nfqHandle, buf, res);
614 #endif
616 /* Functions used to communicate with miniupnpdctl */
617 #ifdef USE_MINIUPNPDCTL
618 static int
619 OpenAndConfCtlUnixSocket(const char * path)
621 struct sockaddr_un localun;
622 int s;
623 s = socket(AF_UNIX, SOCK_STREAM, 0);
624 localun.sun_family = AF_UNIX;
625 strncpy(localun.sun_path, path,
626 sizeof(localun.sun_path));
627 if(bind(s, (struct sockaddr *)&localun,
628 sizeof(struct sockaddr_un)) < 0)
630 syslog(LOG_ERR, "bind(sctl): %m");
631 close(s);
632 s = -1;
634 else if(listen(s, 5) < 0)
636 syslog(LOG_ERR, "listen(sctl): %m");
637 close(s);
638 s = -1;
640 return s;
643 static void
644 write_upnphttp_details(int fd, struct upnphttp * e)
646 char buffer[256];
647 int len;
648 write(fd, "HTTP :\n", 7);
649 while(e)
651 len = snprintf(buffer, sizeof(buffer),
652 "%d %d %s req_buf=%p(%dbytes) res_buf=%p(%dbytes alloc)\n",
653 e->socket, e->state, e->HttpVer,
654 e->req_buf, e->req_buflen,
655 e->res_buf, e->res_buf_alloclen);
656 write(fd, buffer, len);
657 e = e->entries.le_next;
661 static void
662 write_ctlsockets_list(int fd, struct ctlelem * e)
664 char buffer[256];
665 int len;
666 write(fd, "CTL :\n", 6);
667 while(e)
669 len = snprintf(buffer, sizeof(buffer),
670 "struct ctlelem: socket=%d\n", e->socket);
671 write(fd, buffer, len);
672 e = e->entries.le_next;
676 #ifndef DISABLE_CONFIG_FILE
677 static void
678 write_option_list(int fd)
680 char buffer[256];
681 int len;
682 unsigned int i;
683 write(fd, "Options :\n", 10);
684 for(i=0; i<num_options; i++)
686 len = snprintf(buffer, sizeof(buffer),
687 "opt=%02d %s\n",
688 ary_options[i].id, ary_options[i].value);
689 write(fd, buffer, len);
692 #endif
694 static void
695 write_command_line(int fd, int argc, char * * argv)
697 char buffer[256];
698 int len;
699 int i;
700 write(fd, "Command Line :\n", 15);
701 for(i=0; i<argc; i++)
703 len = snprintf(buffer, sizeof(buffer),
704 "argv[%02d]='%s'\n",
705 i, argv[i]);
706 write(fd, buffer, len);
710 #endif
712 /* Handler for the SIGTERM signal (kill)
713 * SIGINT is also handled */
714 static void
715 sigterm(int sig)
717 UNUSED(sig);
718 /*int save_errno = errno; */
719 /*signal(sig, SIG_IGN);*/ /* Ignore this signal while we are quitting */
720 /* Note : isn't it useless ? */
722 #if 0
723 /* calling syslog() is forbidden in signal handler according to
724 * signal(3) */
725 syslog(LOG_NOTICE, "received signal %d, good-bye", sig);
726 #endif
728 quitting = 1;
729 /*errno = save_errno;*/
732 /* Handler for the SIGUSR1 signal indicating public IP address change. */
733 static void
734 sigusr1(int sig)
736 UNUSED(sig);
737 #if 0
738 /* calling syslog() is forbidden in signal handler according to
739 * signal(3) */
740 syslog(LOG_INFO, "received signal %d, public ip address change", sig);
741 #endif
743 should_send_public_address_change_notif = 1;
746 /* record the startup time, for returning uptime */
747 static void
748 set_startup_time(int sysuptime)
750 startup_time = time(NULL);
751 #ifdef USE_TIME_AS_BOOTID
752 if(startup_time > 60*60*24 && upnp_bootid == 1) {
753 /* We know we are not January the 1st 1970 */
754 upnp_bootid = (unsigned int)startup_time;
755 /* from UDA v1.1 :
756 * A convenient mechanism is to set this field value to the time
757 * that the device sends its initial announcement, expressed as
758 * seconds elapsed since midnight January 1, 1970; */
760 #endif /* USE_TIME_AS_BOOTID */
761 if(sysuptime)
763 /* use system uptime instead of daemon uptime */
764 #if defined(__linux__)
765 char buff[64];
766 int uptime = 0, fd;
767 fd = open("/proc/uptime", O_RDONLY);
768 if(fd < 0)
770 syslog(LOG_ERR, "open(\"/proc/uptime\" : %m");
772 else
774 memset(buff, 0, sizeof(buff));
775 if(read(fd, buff, sizeof(buff) - 1) < 0)
777 syslog(LOG_ERR, "read(\"/proc/uptime\" : %m");
779 else
781 uptime = atoi(buff);
782 syslog(LOG_INFO, "system uptime is %d seconds", uptime);
784 close(fd);
785 startup_time -= uptime;
787 #elif defined(SOLARIS_KSTATS)
788 kstat_ctl_t *kc;
789 kc = kstat_open();
790 if(kc != NULL)
792 kstat_t *ksp;
793 ksp = kstat_lookup(kc, "unix", 0, "system_misc");
794 if(ksp && (kstat_read(kc, ksp, NULL) != -1))
796 void *ptr = kstat_data_lookup(ksp, "boot_time");
797 if(ptr)
798 memcpy(&startup_time, ptr, sizeof(startup_time));
799 else
800 syslog(LOG_ERR, "cannot find boot_time kstat");
802 else
803 syslog(LOG_ERR, "cannot open kstats for unix/0/system_misc: %m");
804 kstat_close(kc);
806 #else
807 struct timeval boottime;
808 size_t size = sizeof(boottime);
809 int name[2] = { CTL_KERN, KERN_BOOTTIME };
810 if(sysctl(name, 2, &boottime, &size, NULL, 0) < 0)
812 syslog(LOG_ERR, "sysctl(\"kern.boottime\") failed");
814 else
816 startup_time = boottime.tv_sec;
818 #endif
822 /* structure containing variables used during "main loop"
823 * that are filled during the init */
824 struct runtime_vars {
825 /* LAN IP addresses for SSDP traffic and HTTP */
826 /* moved to global vars */
827 int port; /* HTTP Port */
828 #ifdef ENABLE_HTTPS
829 int https_port; /* HTTPS Port */
830 #endif
831 int notify_interval; /* seconds between SSDP announces */
832 /* unused rules cleaning related variables : */
833 int clean_ruleset_threshold; /* threshold for removing unused rules */
834 int clean_ruleset_interval; /* (minimum) interval between checks */
837 /* parselanaddr()
838 * parse address with mask
839 * ex: 192.168.1.1/24 or 192.168.1.1/255.255.255.0
840 * When MULTIPLE_EXTERNAL_IP is enabled, the ip address of the
841 * external interface associated with the lan subnet follows.
842 * ex : 192.168.1.1/24 81.21.41.11
844 * Can also use the interface name (ie eth0)
846 * return value :
847 * 0 : ok
848 * -1 : error */
849 static int
850 parselanaddr(struct lan_addr_s * lan_addr, const char * str)
852 const char * p;
853 int n;
854 char tmp[16];
856 memset(lan_addr, 0, sizeof(struct lan_addr_s));
857 p = str;
858 while(*p && *p != '/' && !isspace(*p))
859 p++;
860 n = p - str;
861 if(!isdigit(str[0]) && n < (int)sizeof(lan_addr->ifname))
863 /* not starting with a digit : suppose it is an interface name */
864 memcpy(lan_addr->ifname, str, n);
865 lan_addr->ifname[n] = '\0';
866 if(getifaddr(lan_addr->ifname, lan_addr->str, sizeof(lan_addr->str),
867 &lan_addr->addr, &lan_addr->mask) < 0) {
868 #ifdef ENABLE_IPV6
869 fprintf(stderr, "interface \"%s\" has no IPv4 address\n", str);
870 lan_addr->str[0] = '\0';
871 lan_addr->addr.s_addr = htonl(0x00000000u);
872 lan_addr->mask.s_addr = htonl(0xffffffffu);
873 #else /* ENABLE_IPV6 */
874 goto parselan_error;
875 #endif /* ENABLE_IPV6 */
877 /*printf("%s => %s\n", lan_addr->ifname, lan_addr->str);*/
879 else
881 if(n>15)
882 goto parselan_error;
883 memcpy(lan_addr->str, str, n);
884 lan_addr->str[n] = '\0';
885 if(!inet_aton(lan_addr->str, &lan_addr->addr))
886 goto parselan_error;
888 if(*p == '/')
890 const char * q = ++p;
891 while(*p && isdigit(*p))
892 p++;
893 if(*p=='.')
895 /* parse mask in /255.255.255.0 format */
896 while(*p && (*p=='.' || isdigit(*p)))
897 p++;
898 n = p - q;
899 if(n>15)
900 goto parselan_error;
901 memcpy(tmp, q, n);
902 tmp[n] = '\0';
903 if(!inet_aton(tmp, &lan_addr->mask))
904 goto parselan_error;
906 else
908 /* it is a /24 format */
909 int nbits = atoi(q);
910 if(nbits > 32 || nbits < 0)
911 goto parselan_error;
912 lan_addr->mask.s_addr = htonl(nbits ? (0xffffffffu << (32 - nbits)) : 0);
915 else if(lan_addr->mask.s_addr == 0)
917 /* by default, networks are /24 */
918 lan_addr->mask.s_addr = htonl(0xffffff00u);
920 #ifdef MULTIPLE_EXTERNAL_IP
921 /* skip spaces */
922 while(*p && isspace(*p))
923 p++;
924 if(*p) {
925 /* parse the exteral ip address to associate with this subnet */
926 n = 0;
927 while(p[n] && !isspace(*p))
928 n++;
929 if(n<=15) {
930 memcpy(lan_addr->ext_ip_str, p, n);
931 lan_addr->ext_ip_str[n] = '\0';
932 if(!inet_aton(lan_addr->ext_ip_str, &lan_addr->ext_ip_addr)) {
933 /* error */
934 fprintf(stderr, "Error parsing address : %s\n", lan_addr->ext_ip_str);
938 #endif
939 #ifdef ENABLE_IPV6
940 if(lan_addr->ifname[0] != '\0')
942 lan_addr->index = if_nametoindex(lan_addr->ifname);
943 if(lan_addr->index == 0)
944 fprintf(stderr, "Cannot get index for network interface %s",
945 lan_addr->ifname);
947 else
949 fprintf(stderr,
950 "Error: please specify LAN network interface by name instead of IPv4 address : %s\n",
951 str);
952 return -1;
954 #endif
955 return 0;
956 parselan_error:
957 fprintf(stderr, "Error parsing address/mask (or interface name) : %s\n",
958 str);
959 return -1;
962 /* fill uuidvalue_wan and uuidvalue_wcd based on uuidvalue_igd */
963 void complete_uuidvalues(void)
965 size_t len;
966 len = strlen(uuidvalue_igd);
967 memcpy(uuidvalue_wan, uuidvalue_igd, len+1);
968 switch(uuidvalue_wan[len-1]) {
969 case '9':
970 uuidvalue_wan[len-1] = 'a';
971 break;
972 case 'f':
973 uuidvalue_wan[len-1] = '0';
974 break;
975 default:
976 uuidvalue_wan[len-1]++;
978 memcpy(uuidvalue_wcd, uuidvalue_wan, len+1);
979 switch(uuidvalue_wcd[len-1]) {
980 case '9':
981 uuidvalue_wcd[len-1] = 'a';
982 break;
983 case 'f':
984 uuidvalue_wcd[len-1] = '0';
985 break;
986 default:
987 uuidvalue_wcd[len-1]++;
991 /* init phase :
992 * 1) read configuration file
993 * 2) read command line arguments
994 * 3) daemonize
995 * 4) open syslog
996 * 5) check and write pid file
997 * 6) set startup time stamp
998 * 7) compute presentation URL
999 * 8) set signal handlers
1000 * 9) init random generator (srandom())
1001 * 10) init redirection engine
1002 * 11) reload mapping from leasefile */
1003 static int
1004 init(int argc, char * * argv, struct runtime_vars * v)
1006 int i;
1007 int pid;
1008 int debug_flag = 0;
1009 int openlog_option;
1010 struct sigaction sa;
1011 /*const char * logfilename = 0;*/
1012 const char * presurl = 0;
1013 #ifndef DISABLE_CONFIG_FILE
1014 int options_flag = 0;
1015 const char * optionsfile = DEFAULT_CONFIG;
1016 #endif /* DISABLE_CONFIG_FILE */
1017 struct lan_addr_s * lan_addr;
1018 struct lan_addr_s * lan_addr2;
1020 /* only print usage if -h is used */
1021 for(i=1; i<argc; i++)
1023 if(0 == strcmp(argv[i], "-h"))
1024 goto print_usage;
1026 #ifndef DISABLE_CONFIG_FILE
1027 /* first check if "-f" option is used */
1028 for(i=2; i<argc; i++)
1030 if(0 == strcmp(argv[i-1], "-f"))
1032 optionsfile = argv[i];
1033 options_flag = 1;
1034 break;
1037 #endif /* DISABLE_CONFIG_FILE */
1039 /* set initial values */
1040 SETFLAG(ENABLEUPNPMASK); /* UPnP is enabled by default */
1041 #ifdef ENABLE_IPV6
1042 ipv6_bind_addr = in6addr_any;
1043 #endif /* ENABLE_IPV6 */
1045 LIST_INIT(&lan_addrs);
1046 v->port = -1;
1047 #ifdef ENABLE_HTTPS
1048 v->https_port = -1;
1049 #endif
1050 v->notify_interval = 30; /* seconds between SSDP announces */
1051 v->clean_ruleset_threshold = 20;
1052 v->clean_ruleset_interval = 0; /* interval between ruleset check. 0=disabled */
1053 #ifndef DISABLE_CONFIG_FILE
1054 /* read options file first since
1055 * command line arguments have final say */
1056 if(readoptionsfile(optionsfile) < 0)
1058 /* only error if file exists or using -f */
1059 if(access(optionsfile, F_OK) == 0 || options_flag)
1060 fprintf(stderr, "Error reading configuration file %s\n", optionsfile);
1062 else
1064 for(i=0; i<(int)num_options; i++)
1066 switch(ary_options[i].id)
1068 case UPNPEXT_IFNAME:
1069 ext_if_name = ary_options[i].value;
1070 break;
1071 case UPNPEXT_IP:
1072 use_ext_ip_addr = ary_options[i].value;
1073 break;
1074 case UPNPLISTENING_IP:
1075 lan_addr = (struct lan_addr_s *) malloc(sizeof(struct lan_addr_s));
1076 if (lan_addr == NULL)
1078 fprintf(stderr, "malloc(sizeof(struct lan_addr_s)): %m");
1079 break;
1081 if(parselanaddr(lan_addr, ary_options[i].value) != 0)
1083 fprintf(stderr, "can't parse \"%s\" as a valid "
1084 #ifndef ENABLE_IPV6
1085 "LAN address or "
1086 #endif
1087 "interface name\n", ary_options[i].value);
1088 free(lan_addr);
1089 break;
1091 LIST_INSERT_HEAD(&lan_addrs, lan_addr, list);
1092 break;
1093 #ifdef ENABLE_IPV6
1094 case UPNPIPV6_LISTENING_IP:
1095 if (inet_pton(AF_INET6, ary_options[i].value, &ipv6_bind_addr) < 1)
1097 fprintf(stderr, "can't parse \"%s\" as valid IPv6 listening address", ary_options[i].value);
1099 break;
1100 #endif /* ENABLE_IPV6 */
1101 case UPNPPORT:
1102 v->port = atoi(ary_options[i].value);
1103 break;
1104 #ifdef ENABLE_HTTPS
1105 case UPNPHTTPSPORT:
1106 v->https_port = atoi(ary_options[i].value);
1107 break;
1108 #endif
1109 case UPNPBITRATE_UP:
1110 upstream_bitrate = strtoul(ary_options[i].value, 0, 0);
1111 break;
1112 case UPNPBITRATE_DOWN:
1113 downstream_bitrate = strtoul(ary_options[i].value, 0, 0);
1114 break;
1115 case UPNPPRESENTATIONURL:
1116 presurl = ary_options[i].value;
1117 break;
1118 #ifdef ENABLE_MANUFACTURER_INFO_CONFIGURATION
1119 case UPNPFRIENDLY_NAME:
1120 strncpy(friendly_name, ary_options[i].value, FRIENDLY_NAME_MAX_LEN);
1121 friendly_name[FRIENDLY_NAME_MAX_LEN-1] = '\0';
1122 break;
1123 case UPNPMANUFACTURER_NAME:
1124 strncpy(manufacturer_name, ary_options[i].value, MANUFACTURER_NAME_MAX_LEN);
1125 manufacturer_name[MANUFACTURER_NAME_MAX_LEN-1] = '\0';
1126 break;
1127 case UPNPMANUFACTURER_URL:
1128 strncpy(manufacturer_url, ary_options[i].value, MANUFACTURER_URL_MAX_LEN);
1129 manufacturer_url[MANUFACTURER_URL_MAX_LEN-1] = '\0';
1130 break;
1131 case UPNPMODEL_NAME:
1132 strncpy(model_name, ary_options[i].value, MODEL_NAME_MAX_LEN);
1133 model_name[MODEL_NAME_MAX_LEN-1] = '\0';
1134 break;
1135 case UPNPMODEL_DESCRIPTION:
1136 strncpy(model_description, ary_options[i].value, MODEL_DESCRIPTION_MAX_LEN);
1137 model_description[MODEL_DESCRIPTION_MAX_LEN-1] = '\0';
1138 break;
1139 case UPNPMODEL_URL:
1140 strncpy(model_url, ary_options[i].value, MODEL_URL_MAX_LEN);
1141 model_url[MODEL_URL_MAX_LEN-1] = '\0';
1142 break;
1143 #endif
1144 #ifdef USE_NETFILTER
1145 case UPNPFORWARDCHAIN:
1146 miniupnpd_forward_chain = ary_options[i].value;
1147 break;
1148 case UPNPNATCHAIN:
1149 miniupnpd_nat_chain = ary_options[i].value;
1150 break;
1151 #endif
1152 case UPNPNOTIFY_INTERVAL:
1153 v->notify_interval = atoi(ary_options[i].value);
1154 break;
1155 case UPNPSYSTEM_UPTIME:
1156 if(strcmp(ary_options[i].value, "yes") == 0)
1157 SETFLAG(SYSUPTIMEMASK); /*sysuptime = 1;*/
1158 break;
1159 #if defined(USE_PF) || defined(USE_IPF)
1160 case UPNPPACKET_LOG:
1161 if(strcmp(ary_options[i].value, "yes") == 0)
1162 SETFLAG(LOGPACKETSMASK); /*logpackets = 1;*/
1163 break;
1164 #endif
1165 case UPNPUUID:
1166 strncpy(uuidvalue_igd+5, ary_options[i].value,
1167 strlen(uuidvalue_igd+5) + 1);
1168 complete_uuidvalues();
1169 break;
1170 case UPNPSERIAL:
1171 strncpy(serialnumber, ary_options[i].value, SERIALNUMBER_MAX_LEN);
1172 serialnumber[SERIALNUMBER_MAX_LEN-1] = '\0';
1173 break;
1174 case UPNPMODEL_NUMBER:
1175 strncpy(modelnumber, ary_options[i].value, MODELNUMBER_MAX_LEN);
1176 modelnumber[MODELNUMBER_MAX_LEN-1] = '\0';
1177 break;
1178 case UPNPCLEANTHRESHOLD:
1179 v->clean_ruleset_threshold = atoi(ary_options[i].value);
1180 break;
1181 case UPNPCLEANINTERVAL:
1182 v->clean_ruleset_interval = atoi(ary_options[i].value);
1183 break;
1184 #ifdef USE_PF
1185 case UPNPANCHOR:
1186 anchor_name = ary_options[i].value;
1187 break;
1188 case UPNPQUEUE:
1189 queue = ary_options[i].value;
1190 break;
1191 case UPNPTAG:
1192 tag = ary_options[i].value;
1193 break;
1194 #endif
1195 #ifdef ENABLE_NATPMP
1196 case UPNPENABLENATPMP:
1197 if(strcmp(ary_options[i].value, "yes") == 0)
1198 SETFLAG(ENABLENATPMPMASK); /*enablenatpmp = 1;*/
1199 else
1200 if(atoi(ary_options[i].value))
1201 SETFLAG(ENABLENATPMPMASK);
1202 /*enablenatpmp = atoi(ary_options[i].value);*/
1203 break;
1204 #endif
1205 #ifdef ENABLE_PCP
1206 case UPNPPCPMINLIFETIME:
1207 min_lifetime = atoi(ary_options[i].value);
1208 if (min_lifetime > 120 ) {
1209 min_lifetime = 120;
1211 break;
1212 case UPNPPCPMAXLIFETIME:
1213 max_lifetime = atoi(ary_options[i].value);
1214 if (max_lifetime > 86400 ) {
1215 max_lifetime = 86400;
1217 break;
1218 case UPNPPCPALLOWTHIRDPARTY:
1219 if(strcmp(ary_options[i].value, "yes") == 0)
1220 SETFLAG(PCP_ALLOWTHIRDPARTYMASK);
1221 break;
1222 #endif
1223 #ifdef PF_ENABLE_FILTER_RULES
1224 case UPNPQUICKRULES:
1225 if(strcmp(ary_options[i].value, "no") == 0)
1226 SETFLAG(PFNOQUICKRULESMASK);
1227 break;
1228 #endif
1229 case UPNPENABLE:
1230 if(strcmp(ary_options[i].value, "yes") != 0)
1231 CLEARFLAG(ENABLEUPNPMASK);
1232 break;
1233 case UPNPSECUREMODE:
1234 if(strcmp(ary_options[i].value, "yes") == 0)
1235 SETFLAG(SECUREMODEMASK);
1236 break;
1237 #ifdef ENABLE_LEASEFILE
1238 case UPNPLEASEFILE:
1239 lease_file = ary_options[i].value;
1240 break;
1241 #endif
1242 case UPNPMINISSDPDSOCKET:
1243 minissdpdsocketpath = ary_options[i].value;
1244 break;
1245 default:
1246 fprintf(stderr, "Unknown option in file %s\n",
1247 optionsfile);
1250 #ifdef ENABLE_PCP
1251 /* if lifetimes are inverse */
1252 if (min_lifetime >= max_lifetime) {
1253 fprintf(stderr, "Minimum lifetime (%lu) is greater than or equal to maximum lifetime (%lu).\n", min_lifetime, max_lifetime);
1254 fprintf(stderr, "Check your configuration file.\n");
1255 return 1;
1257 #endif
1259 #endif /* DISABLE_CONFIG_FILE */
1261 /* command line arguments processing */
1262 for(i=1; i<argc; i++)
1264 if(argv[i][0]!='-')
1266 fprintf(stderr, "Unknown option: %s\n", argv[i]);
1268 else switch(argv[i][1])
1270 case 'b':
1271 if(i+1 < argc) {
1272 upnp_bootid = (unsigned int)strtoul(argv[++i], NULL, 10);
1273 } else
1274 fprintf(stderr, "Option -%c takes one argument.\n", argv[i][1]);
1275 break;
1276 case 'o':
1277 if(i+1 < argc)
1278 use_ext_ip_addr = argv[++i];
1279 else
1280 fprintf(stderr, "Option -%c takes one argument.\n", argv[i][1]);
1281 break;
1282 case 't':
1283 if(i+1 < argc)
1284 v->notify_interval = atoi(argv[++i]);
1285 else
1286 fprintf(stderr, "Option -%c takes one argument.\n", argv[i][1]);
1287 break;
1288 case 'r':
1289 if(i+1 < argc)
1290 v->clean_ruleset_interval = atoi(argv[++i]);
1291 else
1292 fprintf(stderr, "Option -%c takes one argument.\n", argv[i][1]);
1293 break;
1294 case 'u':
1295 if(i+1 < argc) {
1296 strncpy(uuidvalue_igd+5, argv[++i], strlen(uuidvalue_igd+5) + 1);
1297 complete_uuidvalues();
1298 } else
1299 fprintf(stderr, "Option -%c takes one argument.\n", argv[i][1]);
1300 break;
1301 #ifdef ENABLE_MANUFACTURER_INFO_CONFIGURATION
1302 case 'z':
1303 if(i+1 < argc)
1304 strncpy(friendly_name, argv[++i], FRIENDLY_NAME_MAX_LEN);
1305 else
1306 fprintf(stderr, "Option -%c takes one argument.\n", argv[i][1]);
1307 friendly_name[FRIENDLY_NAME_MAX_LEN-1] = '\0';
1308 break;
1309 #endif
1310 case 's':
1311 if(i+1 < argc)
1312 strncpy(serialnumber, argv[++i], SERIALNUMBER_MAX_LEN);
1313 else
1314 fprintf(stderr, "Option -%c takes one argument.\n", argv[i][1]);
1315 serialnumber[SERIALNUMBER_MAX_LEN-1] = '\0';
1316 break;
1317 case 'm':
1318 if(i+1 < argc)
1319 strncpy(modelnumber, argv[++i], MODELNUMBER_MAX_LEN);
1320 else
1321 fprintf(stderr, "Option -%c takes one argument.\n", argv[i][1]);
1322 modelnumber[MODELNUMBER_MAX_LEN-1] = '\0';
1323 break;
1324 #ifdef ENABLE_NATPMP
1325 case 'N':
1326 /*enablenatpmp = 1;*/
1327 SETFLAG(ENABLENATPMPMASK);
1328 break;
1329 #endif
1330 case 'U':
1331 /*sysuptime = 1;*/
1332 SETFLAG(SYSUPTIMEMASK);
1333 break;
1334 /*case 'l':
1335 logfilename = argv[++i];
1336 break;*/
1337 #if defined(USE_PF) || defined(USE_IPF)
1338 case 'L':
1339 /*logpackets = 1;*/
1340 SETFLAG(LOGPACKETSMASK);
1341 break;
1342 #endif
1343 case 'S':
1344 SETFLAG(SECUREMODEMASK);
1345 break;
1346 case 'i':
1347 if(i+1 < argc)
1348 ext_if_name = argv[++i];
1349 else
1350 fprintf(stderr, "Option -%c takes one argument.\n", argv[i][1]);
1351 break;
1352 #ifdef USE_PF
1353 case 'q':
1354 if(i+1 < argc)
1355 queue = argv[++i];
1356 else
1357 fprintf(stderr, "Option -%c takes one argument.\n", argv[i][1]);
1358 break;
1359 case 'T':
1360 if(i+1 < argc)
1361 tag = argv[++i];
1362 else
1363 fprintf(stderr, "Option -%c takes one argument.\n", argv[i][1]);
1364 break;
1365 #endif
1366 case 'p':
1367 if(i+1 < argc)
1368 v->port = atoi(argv[++i]);
1369 else
1370 fprintf(stderr, "Option -%c takes one argument.\n", argv[i][1]);
1371 break;
1372 #ifdef ENABLE_HTTPS
1373 case 'H':
1374 if(i+1 < argc)
1375 v->https_port = atoi(argv[++i]);
1376 else
1377 fprintf(stderr, "Option -%c takes one argument.\n", argv[i][1]);
1378 break;
1379 #endif
1380 #ifdef ENABLE_NFQUEUE
1381 case 'Q':
1382 if(i+1<argc)
1384 nfqueue = atoi(argv[++i]);
1386 else
1387 fprintf(stderr, "Option -%c takes one argument.\n", argv[i][1]);
1388 break;
1389 case 'n':
1390 if (i+1 < argc) {
1391 i++;
1392 if(n_nfqix < MAX_LAN_ADDR) {
1393 nfqix[n_nfqix++] = if_nametoindex(argv[i]);
1394 } else {
1395 fprintf(stderr,"Too many nfq interfaces. Ignoring %s\n", argv[i]);
1397 } else {
1398 fprintf(stderr, "Option -%c takes one argument.\n", argv[i][1]);
1400 break;
1401 #endif
1402 case 'P':
1403 if(i+1 < argc)
1404 pidfilename = argv[++i];
1405 else
1406 fprintf(stderr, "Option -%c takes one argument.\n", argv[i][1]);
1407 break;
1408 case 'd':
1409 debug_flag = 1;
1410 break;
1411 case 'w':
1412 if(i+1 < argc)
1413 presurl = argv[++i];
1414 else
1415 fprintf(stderr, "Option -%c takes one argument.\n", argv[i][1]);
1416 break;
1417 case 'B':
1418 if(i+2<argc)
1420 downstream_bitrate = strtoul(argv[++i], 0, 0);
1421 upstream_bitrate = strtoul(argv[++i], 0, 0);
1423 else
1424 fprintf(stderr, "Option -%c takes two arguments.\n", argv[i][1]);
1425 break;
1426 case 'a':
1427 #ifndef MULTIPLE_EXTERNAL_IP
1428 if(i+1 < argc)
1430 i++;
1431 lan_addr = (struct lan_addr_s *) malloc(sizeof(struct lan_addr_s));
1432 if (lan_addr == NULL)
1434 fprintf(stderr, "malloc(sizeof(struct lan_addr_s)): %m");
1435 break;
1437 if(parselanaddr(lan_addr, argv[i]) != 0)
1439 fprintf(stderr, "can't parse \"%s\" as a valid "
1440 #ifndef ENABLE_IPV6
1441 "LAN address or "
1442 #endif
1443 "interface name\n", argv[i]);
1444 free(lan_addr);
1445 break;
1447 /* check if we already have this address */
1448 for(lan_addr2 = lan_addrs.lh_first; lan_addr2 != NULL; lan_addr2 = lan_addr2->list.le_next)
1450 if (0 == strncmp(lan_addr2->str, lan_addr->str, 15))
1451 break;
1453 if (lan_addr2 == NULL)
1454 LIST_INSERT_HEAD(&lan_addrs, lan_addr, list);
1456 else
1457 fprintf(stderr, "Option -%c takes one argument.\n", argv[i][1]);
1458 #else
1459 if(i+2 < argc)
1461 char *val=calloc((strlen(argv[i+1]) + strlen(argv[i+2]) + 1), sizeof(char));
1462 if (val == NULL)
1464 fprintf(stderr, "memory allocation error for listen address storage\n");
1465 break;
1467 sprintf(val, "%s %s", argv[i+1], argv[i+2]);
1469 lan_addr = (struct lan_addr_s *) malloc(sizeof(struct lan_addr_s));
1470 if (lan_addr == NULL)
1472 fprintf(stderr, "malloc(sizeof(struct lan_addr_s)): %m");
1473 free(val);
1474 break;
1476 if(parselanaddr(lan_addr, val) != 0)
1478 fprintf(stderr, "can't parse \"%s\" as a valid LAN address or interface name\n", val);
1479 free(lan_addr);
1480 free(val);
1481 break;
1483 /* check if we already have this address */
1484 for(lan_addr2 = lan_addrs.lh_first; lan_addr2 != NULL; lan_addr2 = lan_addr2->list.le_next)
1486 if (0 == strncmp(lan_addr2->str, lan_addr->str, 15))
1487 break;
1489 if (lan_addr2 == NULL)
1490 LIST_INSERT_HEAD(&lan_addrs, lan_addr, list);
1492 free(val);
1493 i+=2;
1495 else
1496 fprintf(stderr, "Option -%c takes two arguments.\n", argv[i][1]);
1497 #endif
1498 break;
1499 case 'A':
1500 if(i+1 < argc) {
1501 void * tmp;
1502 tmp = realloc(upnppermlist, sizeof(struct upnpperm) * (num_upnpperm+1));
1503 if(tmp == NULL) {
1504 fprintf(stderr, "memory allocation error for permission\n");
1505 } else {
1506 upnppermlist = tmp;
1507 if(read_permission_line(upnppermlist + num_upnpperm, argv[++i]) >= 0) {
1508 num_upnpperm++;
1509 } else {
1510 fprintf(stderr, "Permission rule parsing error :\n%s\n", argv[i]);
1513 } else
1514 fprintf(stderr, "Option -%c takes one argument.\n", argv[i][1]);
1515 break;
1516 case 'f':
1517 i++; /* discarding, the config file is already read */
1518 break;
1519 default:
1520 fprintf(stderr, "Unknown option: %s\n", argv[i]);
1523 if(!ext_if_name || !lan_addrs.lh_first)
1525 /* bad configuration */
1526 goto print_usage;
1529 if(debug_flag)
1531 pid = getpid();
1533 else
1535 #ifdef USE_DAEMON
1536 if(daemon(0, 0)<0) {
1537 perror("daemon()");
1539 pid = getpid();
1540 #else
1541 pid = daemonize();
1542 #endif
1545 openlog_option = LOG_PID|LOG_CONS;
1546 if(debug_flag)
1548 openlog_option |= LOG_PERROR; /* also log on stderr */
1551 openlog("miniupnpd", openlog_option, LOG_MINIUPNPD);
1553 if(!debug_flag)
1555 /* speed things up and ignore LOG_INFO and LOG_DEBUG */
1556 setlogmask(LOG_UPTO(LOG_NOTICE));
1559 if(checkforrunning(pidfilename) < 0)
1561 syslog(LOG_ERR, "MiniUPnPd is already running. EXITING");
1562 return 1;
1565 syslog(LOG_NOTICE, "version " MINIUPNPD_VERSION " started");
1567 set_startup_time(GETFLAG(SYSUPTIMEMASK));
1569 /* presentation url */
1570 if(presurl)
1572 strncpy(presentationurl, presurl, PRESENTATIONURL_MAX_LEN);
1573 presentationurl[PRESENTATIONURL_MAX_LEN-1] = '\0';
1575 else
1577 snprintf(presentationurl, PRESENTATIONURL_MAX_LEN,
1578 "http://%s/", lan_addrs.lh_first->str);
1579 /*"http://%s:%d/", lan_addrs.lh_first->str, 80);*/
1582 /* set signal handler */
1583 memset(&sa, 0, sizeof(struct sigaction));
1584 sa.sa_handler = sigterm;
1586 if(sigaction(SIGTERM, &sa, NULL) < 0)
1588 syslog(LOG_ERR, "Failed to set %s handler. EXITING", "SIGTERM");
1589 return 1;
1591 if(sigaction(SIGINT, &sa, NULL) < 0)
1593 syslog(LOG_ERR, "Failed to set %s handler. EXITING", "SIGINT");
1594 return 1;
1597 // zzz
1598 sa.sa_handler = sigusr2;
1599 sigaction(SIGUSR2, &sa, NULL);
1601 if(signal(SIGPIPE, SIG_IGN) == SIG_ERR)
1603 syslog(LOG_ERR, "Failed to ignore SIGPIPE signals");
1606 sa.sa_handler = sigusr1;
1607 if(sigaction(SIGUSR1, &sa, NULL) < 0)
1609 syslog(LOG_NOTICE, "Failed to set %s handler", "SIGUSR1");
1612 /* initialize random number generator */
1613 srandom((unsigned int)time(NULL));
1615 /* initialize redirection engine (and pinholes) */
1616 if(init_redirect() < 0)
1618 syslog(LOG_ERR, "Failed to init redirection engine. EXITING");
1619 return 1;
1621 #ifdef ENABLE_UPNPPINHOLE
1622 #ifdef USE_NETFILTER
1623 init_iptpinhole();
1624 #endif
1625 #endif
1627 if(writepidfile(pidfilename, pid) < 0)
1628 pidfilename = NULL;
1630 #ifdef ENABLE_LEASEFILE
1631 /*remove(lease_file);*/
1632 syslog(LOG_INFO, "Reloading rules from lease file");
1633 reload_from_lease_file();
1634 #endif
1635 tomato_load(); // zzz
1637 return 0;
1638 print_usage:
1639 fprintf(stderr, "Usage:\n\t"
1640 "%s "
1641 #ifndef DISABLE_CONFIG_FILE
1642 "[-f config_file] "
1643 #endif
1644 "[-i ext_ifname] [-o ext_ip]\n"
1645 #ifndef MULTIPLE_EXTERNAL_IP
1646 "\t\t[-a listening_ip]"
1647 #else
1648 "\t\t[-a listening_ip ext_ip]"
1649 #endif
1650 #ifdef ENABLE_HTTPS
1651 " [-H https_port]"
1652 #endif
1653 " [-p port] [-d]"
1654 #if defined(USE_PF) || defined(USE_IPF)
1655 " [-L]"
1656 #endif
1657 " [-U] [-S]"
1658 #ifdef ENABLE_NATPMP
1659 " [-N]"
1660 #endif
1661 "\n"
1662 /*"[-l logfile] " not functionnal */
1663 "\t\t[-u uuid] [-s serial] [-m model_number] \n"
1664 "\t\t[-t notify_interval] [-P pid_filename] "
1665 #ifdef ENABLE_MANUFACTURER_INFO_CONFIGURATION
1666 "[-z fiendly_name]"
1667 #endif
1668 "\n\t\t[-B down up] [-w url] [-r clean_ruleset_interval]\n"
1669 #ifdef USE_PF
1670 "\t\t[-q queue] [-T tag]\n"
1671 #endif
1672 #ifdef ENABLE_NFQUEUE
1673 "\t\t[-Q queue] [-n name]\n"
1674 #endif
1675 "\t\t[-A \"permission rule\"] [-b BOOTID]\n"
1676 "\nNotes:\n\tThere can be one or several listening_ips.\n"
1677 "\tNotify interval is in seconds. Default is 30 seconds.\n"
1678 "\tDefault pid file is '%s'.\n"
1679 "\tDefault config file is '%s'.\n"
1680 "\tWith -d miniupnpd will run as a standard program.\n"
1681 #if defined(USE_PF) || defined(USE_IPF)
1682 "\t-L sets packet log in pf and ipf on.\n"
1683 #endif
1684 "\t-S sets \"secure\" mode : clients can only add mappings to their own ip\n"
1685 "\t-U causes miniupnpd to report system uptime instead "
1686 "of daemon uptime.\n"
1687 #ifdef ENABLE_NATPMP
1688 "\t-N enables NAT-PMP functionality.\n"
1689 #endif
1690 "\t-B sets bitrates reported by daemon in bits per second.\n"
1691 "\t-w sets the presentation url. Default is http address on port 80\n"
1692 #ifdef USE_PF
1693 "\t-q sets the ALTQ queue in pf.\n"
1694 "\t-T sets the tag name in pf.\n"
1695 #endif
1696 #ifdef ENABLE_NFQUEUE
1697 "\t-Q sets the queue number that is used by NFQUEUE.\n"
1698 "\t-n sets the name of the interface(s) that packets will arrive on.\n"
1699 #endif
1700 "\t-A use following syntax for permission rules :\n"
1701 "\t (allow|deny) (external port range) ip/mask (internal port range)\n"
1702 "\texamples :\n"
1703 "\t \"allow 1024-65535 192.168.1.0/24 1024-65535\"\n"
1704 "\t \"deny 0-65535 0.0.0.0/0 0-65535\"\n"
1705 "\t-b sets the value of BOOTID.UPNP.ORG SSDP header\n"
1706 "\t-h prints this help and quits.\n"
1707 "", argv[0], pidfilename, DEFAULT_CONFIG);
1708 return 1;
1711 /* === main === */
1712 /* process HTTP or SSDP requests */
1714 main(int argc, char * * argv)
1716 int i;
1717 int shttpl = -1; /* socket for HTTP */
1718 #if defined(V6SOCKETS_ARE_V6ONLY) && defined(ENABLE_IPV6)
1719 int shttpl_v4 = -1; /* socket for HTTP (ipv4 only) */
1720 #endif
1721 #ifdef ENABLE_HTTPS
1722 int shttpsl = -1; /* socket for HTTPS */
1723 #if defined(V6SOCKETS_ARE_V6ONLY) && defined(ENABLE_IPV6)
1724 int shttpsl_v4 = -1; /* socket for HTTPS (ipv4 only) */
1725 #endif
1726 #endif /* ENABLE_HTTPS */
1727 int sudp = -1; /* IP v4 socket for receiving SSDP */
1728 #ifdef ENABLE_IPV6
1729 int sudpv6 = -1; /* IP v6 socket for receiving SSDP */
1730 #endif
1731 #ifdef ENABLE_NATPMP
1732 int * snatpmp = NULL; /* also used for PCP */
1733 #endif
1734 #if defined(ENABLE_IPV6) && defined(ENABLE_PCP)
1735 int spcp_v6 = -1;
1736 #endif
1737 #ifdef ENABLE_NFQUEUE
1738 int nfqh = -1;
1739 #endif
1740 #ifdef USE_IFACEWATCHER
1741 int sifacewatcher = -1;
1742 #endif
1744 int * snotify = NULL;
1745 int addr_count;
1746 LIST_HEAD(httplisthead, upnphttp) upnphttphead;
1747 struct upnphttp * e = 0;
1748 struct upnphttp * next;
1749 fd_set readset; /* for select() */
1750 fd_set writeset;
1751 struct timeval timeout, timeofday, lasttimeofday = {0, 0};
1752 int max_fd = -1;
1753 #ifdef USE_MINIUPNPDCTL
1754 int sctl = -1;
1755 LIST_HEAD(ctlstructhead, ctlelem) ctllisthead;
1756 struct ctlelem * ectl;
1757 struct ctlelem * ectlnext;
1758 #endif
1759 struct runtime_vars v;
1760 /* variables used for the unused-rule cleanup process */
1761 struct rule_state * rule_list = 0;
1762 struct timeval checktime = {0, 0};
1763 struct lan_addr_s * lan_addr;
1764 #ifdef ENABLE_UPNPPINHOLE
1765 unsigned int next_pinhole_ts;
1766 #endif
1768 if(init(argc, argv, &v) != 0)
1769 return 1;
1770 #ifdef ENABLE_HTTPS
1771 if(init_ssl() < 0)
1772 return 1;
1773 #endif /* ENABLE_HTTPS */
1774 /* count lan addrs */
1775 addr_count = 0;
1776 for(lan_addr = lan_addrs.lh_first; lan_addr != NULL; lan_addr = lan_addr->list.le_next)
1777 addr_count++;
1778 if(addr_count > 0) {
1779 #ifndef ENABLE_IPV6
1780 snotify = calloc(addr_count, sizeof(int));
1781 #else
1782 /* one for IPv4, one for IPv6 */
1783 snotify = calloc(addr_count * 2, sizeof(int));
1784 #endif
1786 #ifdef ENABLE_NATPMP
1787 if(addr_count > 0) {
1788 snatpmp = malloc(addr_count * sizeof(int));
1789 for(i = 0; i < addr_count; i++)
1790 snatpmp[i] = -1;
1792 #endif
1794 LIST_INIT(&upnphttphead);
1795 #ifdef USE_MINIUPNPDCTL
1796 LIST_INIT(&ctllisthead);
1797 #endif
1800 #ifdef ENABLE_NATPMP
1801 !GETFLAG(ENABLENATPMPMASK) &&
1802 #endif
1803 !GETFLAG(ENABLEUPNPMASK) ) {
1804 syslog(LOG_ERR, "Why did you run me anyway?");
1805 return 0;
1808 syslog(LOG_INFO, "version " MINIUPNPD_VERSION " starting%s%sext if %s BOOTID=%u",
1809 #ifdef ENABLE_NATPMP
1810 #ifdef ENABLE_PCP
1811 GETFLAG(ENABLENATPMPMASK) ? " NAT-PMP/PCP " : " ",
1812 #else
1813 GETFLAG(ENABLENATPMPMASK) ? " NAT-PMP " : " ",
1814 #endif
1815 #else
1816 " ",
1817 #endif
1818 GETFLAG(ENABLEUPNPMASK) ? "UPnP-IGD " : "",
1819 ext_if_name, upnp_bootid);
1821 if(GETFLAG(ENABLEUPNPMASK))
1823 unsigned short listen_port;
1824 listen_port = (v.port > 0) ? v.port : 0;
1825 /* open socket for HTTP connections. Listen on the 1st LAN address */
1826 #ifdef ENABLE_IPV6
1827 shttpl = OpenAndConfHTTPSocket(&listen_port, 1);
1828 #else /* ENABLE_IPV6 */
1829 shttpl = OpenAndConfHTTPSocket(&listen_port);
1830 #endif /* ENABLE_IPV6 */
1831 if(shttpl < 0)
1833 syslog(LOG_ERR, "Failed to open socket for HTTP. EXITING");
1834 return 1;
1836 v.port = listen_port;
1837 syslog(LOG_NOTICE, "HTTP listening on port %d", v.port);
1838 #if defined(V6SOCKETS_ARE_V6ONLY) && defined(ENABLE_IPV6)
1839 if(!GETFLAG(IPV6DISABLEDMASK))
1841 shttpl_v4 = OpenAndConfHTTPSocket(&listen_port, 0);
1842 if(shttpl_v4 < 0)
1844 syslog(LOG_ERR, "Failed to open socket for HTTP on port %hu (IPv4). EXITING", v.port);
1845 return 1;
1848 #endif /* V6SOCKETS_ARE_V6ONLY */
1849 #ifdef ENABLE_HTTPS
1850 /* https */
1851 listen_port = (v.https_port > 0) ? v.https_port : 0;
1852 #ifdef ENABLE_IPV6
1853 shttpsl = OpenAndConfHTTPSocket(&listen_port, 1);
1854 #else /* ENABLE_IPV6 */
1855 shttpsl = OpenAndConfHTTPSocket(&listen_port);
1856 #endif /* ENABLE_IPV6 */
1857 if(shttpl < 0)
1859 syslog(LOG_ERR, "Failed to open socket for HTTPS. EXITING");
1860 return 1;
1862 v.https_port = listen_port;
1863 syslog(LOG_NOTICE, "HTTPS listening on port %d", v.https_port);
1864 #if defined(V6SOCKETS_ARE_V6ONLY) && defined(ENABLE_IPV6)
1865 shttpsl_v4 = OpenAndConfHTTPSocket(&listen_port, 0);
1866 if(shttpsl_v4 < 0)
1868 syslog(LOG_ERR, "Failed to open socket for HTTPS on port %hu (IPv4). EXITING", v.https_port);
1869 return 1;
1871 #endif /* V6SOCKETS_ARE_V6ONLY */
1872 #endif /* ENABLE_HTTPS */
1873 #ifdef ENABLE_IPV6
1874 if(find_ipv6_addr(NULL, ipv6_addr_for_http_with_brackets, sizeof(ipv6_addr_for_http_with_brackets)) > 0) {
1875 syslog(LOG_NOTICE, "HTTP IPv6 address given to control points : %s",
1876 ipv6_addr_for_http_with_brackets);
1877 } else {
1878 memcpy(ipv6_addr_for_http_with_brackets, "[::1]", 6);
1879 syslog(LOG_WARNING, "no HTTP IPv6 address, disabling IPv6");
1880 SETFLAG(IPV6DISABLEDMASK);
1882 #endif
1884 /* open socket for SSDP connections */
1885 sudp = OpenAndConfSSDPReceiveSocket(0);
1886 if(sudp < 0)
1888 syslog(LOG_NOTICE, "Failed to open socket for receiving SSDP. Trying to use MiniSSDPd");
1889 if(SubmitServicesToMiniSSDPD(lan_addrs.lh_first->str, v.port) < 0) {
1890 syslog(LOG_ERR, "Failed to connect to MiniSSDPd. EXITING");
1891 return 1;
1894 #ifdef ENABLE_IPV6
1895 if(!GETFLAG(IPV6DISABLEDMASK))
1897 sudpv6 = OpenAndConfSSDPReceiveSocket(1);
1898 if(sudpv6 < 0)
1900 syslog(LOG_WARNING, "Failed to open socket for receiving SSDP (IP v6).");
1903 #endif
1905 /* open socket for sending notifications */
1906 if(OpenAndConfSSDPNotifySockets(snotify) < 0)
1908 syslog(LOG_ERR, "Failed to open sockets for sending SSDP notify "
1909 "messages. EXITING");
1910 return 1;
1913 #ifdef USE_IFACEWATCHER
1914 /* open socket for kernel notifications about new network interfaces */
1915 if (sudp >= 0)
1917 sifacewatcher = OpenAndConfInterfaceWatchSocket();
1918 if (sifacewatcher < 0)
1920 syslog(LOG_ERR, "Failed to open socket for receiving network interface notifications");
1923 #endif
1926 #ifdef ENABLE_NATPMP
1927 /* open socket for NAT PMP traffic */
1928 if(GETFLAG(ENABLENATPMPMASK))
1930 if(OpenAndConfNATPMPSockets(snatpmp) < 0)
1931 #ifdef ENABLE_PCP
1933 syslog(LOG_ERR, "Failed to open sockets for NAT-PMP/PCP.");
1934 } else {
1935 syslog(LOG_NOTICE, "Listening for NAT-PMP/PCP traffic on port %u",
1936 NATPMP_PORT);
1938 #else
1940 syslog(LOG_ERR, "Failed to open sockets for NAT PMP.");
1941 } else {
1942 syslog(LOG_NOTICE, "Listening for NAT-PMP traffic on port %u",
1943 NATPMP_PORT);
1945 #endif
1947 #endif
1949 #if defined(ENABLE_IPV6) && defined(ENABLE_PCP)
1950 spcp_v6 = OpenAndConfPCPv6Socket();
1951 #endif
1953 /* for miniupnpdctl */
1954 #ifdef USE_MINIUPNPDCTL
1955 sctl = OpenAndConfCtlUnixSocket("/var/run/miniupnpd.ctl");
1956 #endif
1958 #ifdef ENABLE_NFQUEUE
1959 if ( nfqueue != -1 && n_nfqix > 0) {
1960 nfqh = OpenAndConfNFqueue();
1961 if(nfqh < 0) {
1962 syslog(LOG_ERR, "Failed to open fd for NFQUEUE.");
1963 return 1;
1964 } else {
1965 syslog(LOG_NOTICE, "Opened NFQUEUE %d",nfqueue);
1968 #endif
1970 tomato_helper(); // zzz
1972 /* main loop */
1973 while(!quitting)
1975 /* Correct startup_time if it was set with a RTC close to 0 */
1976 if((startup_time<60*60*24) && (time(NULL)>60*60*24))
1978 set_startup_time(GETFLAG(SYSUPTIMEMASK));
1980 /* send public address change notifications if needed */
1981 if(should_send_public_address_change_notif)
1983 syslog(LOG_INFO, "should send external iface address change notification(s)");
1984 #ifdef ENABLE_NATPMP
1985 if(GETFLAG(ENABLENATPMPMASK))
1986 SendNATPMPPublicAddressChangeNotification(snatpmp, addr_count);
1987 #endif
1988 #ifdef ENABLE_EVENTS
1989 if(GETFLAG(ENABLEUPNPMASK))
1991 upnp_event_var_change_notify(EWanIPC);
1993 #endif
1994 should_send_public_address_change_notif = 0;
1996 /* Check if we need to send SSDP NOTIFY messages and do it if
1997 * needed */
1998 if(gettimeofday(&timeofday, 0) < 0)
2000 syslog(LOG_ERR, "gettimeofday(): %m");
2001 timeout.tv_sec = v.notify_interval;
2002 timeout.tv_usec = 0;
2004 else
2006 /* the comparaison is not very precise but who cares ? */
2007 if(timeofday.tv_sec >= (lasttimeofday.tv_sec + v.notify_interval))
2009 if (GETFLAG(ENABLEUPNPMASK))
2010 SendSSDPNotifies2(snotify,
2011 (unsigned short)v.port,
2012 #ifdef ENABLE_HTTPS
2013 (unsigned short)v.https_port,
2014 #endif
2015 v.notify_interval << 1);
2016 memcpy(&lasttimeofday, &timeofday, sizeof(struct timeval));
2017 timeout.tv_sec = v.notify_interval;
2018 timeout.tv_usec = 0;
2020 else
2022 timeout.tv_sec = lasttimeofday.tv_sec + v.notify_interval
2023 - timeofday.tv_sec;
2024 if(timeofday.tv_usec > lasttimeofday.tv_usec)
2026 timeout.tv_usec = 1000000 + lasttimeofday.tv_usec
2027 - timeofday.tv_usec;
2028 timeout.tv_sec--;
2030 else
2032 timeout.tv_usec = lasttimeofday.tv_usec - timeofday.tv_usec;
2036 /* remove unused rules */
2037 if( v.clean_ruleset_interval
2038 && (timeofday.tv_sec >= checktime.tv_sec + v.clean_ruleset_interval))
2040 if(rule_list)
2042 remove_unused_rules(rule_list);
2043 rule_list = NULL;
2045 else
2047 rule_list = get_upnp_rules_state_list(v.clean_ruleset_threshold);
2049 memcpy(&checktime, &timeofday, sizeof(struct timeval));
2051 /* Remove expired port mappings, based on UPnP IGD LeaseDuration
2052 * or NAT-PMP lifetime) */
2053 if(nextruletoclean_timestamp
2054 && ((unsigned int)timeofday.tv_sec >= nextruletoclean_timestamp))
2056 syslog(LOG_DEBUG, "cleaning expired Port Mappings");
2057 get_upnp_rules_state_list(0);
2059 if(nextruletoclean_timestamp
2060 && ((unsigned int)timeout.tv_sec >= (nextruletoclean_timestamp - timeofday.tv_sec)))
2062 timeout.tv_sec = nextruletoclean_timestamp - timeofday.tv_sec;
2063 timeout.tv_usec = 0;
2064 syslog(LOG_DEBUG, "setting timeout to %u sec",
2065 (unsigned)timeout.tv_sec);
2067 #ifdef ENABLE_UPNPPINHOLE
2068 /* Clean up expired IPv6 PinHoles */
2069 next_pinhole_ts = 0;
2070 upnp_clean_expired_pinholes(&next_pinhole_ts);
2071 if(next_pinhole_ts &&
2072 timeout.tv_sec >= (int)(next_pinhole_ts - timeofday.tv_sec)) {
2073 timeout.tv_sec = next_pinhole_ts - timeofday.tv_sec;
2074 timeout.tv_usec = 0;
2076 #endif /* ENABLE_UPNPPINHOLE */
2078 /* select open sockets (SSDP, HTTP listen, and all HTTP soap sockets) */
2079 FD_ZERO(&readset);
2080 FD_ZERO(&writeset);
2082 if (sudp >= 0)
2084 FD_SET(sudp, &readset);
2085 max_fd = MAX( max_fd, sudp);
2086 #ifdef USE_IFACEWATCHER
2087 if (sifacewatcher >= 0)
2089 FD_SET(sifacewatcher, &readset);
2090 max_fd = MAX(max_fd, sifacewatcher);
2092 #endif
2094 if (shttpl >= 0)
2096 FD_SET(shttpl, &readset);
2097 max_fd = MAX( max_fd, shttpl);
2099 #if defined(V6SOCKETS_ARE_V6ONLY) && defined(ENABLE_IPV6)
2100 if (shttpl_v4 >= 0)
2102 FD_SET(shttpl_v4, &readset);
2103 max_fd = MAX( max_fd, shttpl_v4);
2105 #endif
2106 #ifdef ENABLE_HTTPS
2107 if (shttpsl >= 0)
2109 FD_SET(shttpsl, &readset);
2110 max_fd = MAX( max_fd, shttpsl);
2112 #if defined(V6SOCKETS_ARE_V6ONLY) && defined(ENABLE_IPV6)
2113 if (shttpsl_v4 >= 0)
2115 FD_SET(shttpsl_v4, &readset);
2116 max_fd = MAX( max_fd, shttpsl_v4);
2118 #endif
2119 #endif /* ENABLE_HTTPS */
2120 #ifdef ENABLE_IPV6
2121 if (sudpv6 >= 0)
2123 FD_SET(sudpv6, &readset);
2124 max_fd = MAX( max_fd, sudpv6);
2126 #endif
2128 #ifdef ENABLE_NFQUEUE
2129 if (nfqh >= 0)
2131 FD_SET(nfqh, &readset);
2132 max_fd = MAX( max_fd, nfqh);
2134 #endif
2136 i = 0; /* active HTTP connections count */
2137 for(e = upnphttphead.lh_first; e != NULL; e = e->entries.le_next)
2139 if(e->socket >= 0)
2141 if(e->state <= EWaitingForHttpContent)
2142 FD_SET(e->socket, &readset);
2143 else if(e->state == ESendingAndClosing)
2144 FD_SET(e->socket, &writeset);
2145 else
2146 continue;
2147 max_fd = MAX(max_fd, e->socket);
2148 i++;
2151 /* for debug */
2152 #ifdef DEBUG
2153 if(i > 1)
2155 syslog(LOG_DEBUG, "%d active incoming HTTP connections", i);
2157 #endif
2158 #ifdef ENABLE_NATPMP
2159 for(i=0; i<addr_count; i++) {
2160 if(snatpmp[i] >= 0) {
2161 FD_SET(snatpmp[i], &readset);
2162 max_fd = MAX( max_fd, snatpmp[i]);
2165 #endif
2166 #if defined(ENABLE_IPV6) && defined(ENABLE_PCP)
2167 if(spcp_v6 >= 0) {
2168 FD_SET(spcp_v6, &readset);
2169 max_fd = MAX(max_fd, spcp_v6);
2171 #endif
2172 #ifdef USE_MINIUPNPDCTL
2173 if(sctl >= 0) {
2174 FD_SET(sctl, &readset);
2175 max_fd = MAX( max_fd, sctl);
2178 for(ectl = ctllisthead.lh_first; ectl; ectl = ectl->entries.le_next)
2180 if(ectl->socket >= 0) {
2181 FD_SET(ectl->socket, &readset);
2182 max_fd = MAX( max_fd, ectl->socket);
2185 #endif
2187 #ifdef ENABLE_EVENTS
2188 upnpevents_selectfds(&readset, &writeset, &max_fd);
2189 #endif
2191 /* queued "sendto" */
2193 struct timeval next_send;
2194 i = get_next_scheduled_send(&next_send);
2195 if(i > 0) {
2196 #ifdef DEBUG
2197 syslog(LOG_DEBUG, "%d queued sendto", i);
2198 #endif
2199 i = get_sendto_fds(&writeset, &max_fd, &timeofday);
2200 if(timeofday.tv_sec > next_send.tv_sec ||
2201 (timeofday.tv_sec == next_send.tv_sec && timeofday.tv_usec >= next_send.tv_usec)) {
2202 if(i > 0) {
2203 timeout.tv_sec = 0;
2204 timeout.tv_usec = 0;
2206 } else {
2207 struct timeval tmp_timeout;
2208 tmp_timeout.tv_sec = (next_send.tv_sec - timeofday.tv_sec);
2209 tmp_timeout.tv_usec = (next_send.tv_usec - timeofday.tv_usec);
2210 if(tmp_timeout.tv_usec < 0) {
2211 tmp_timeout.tv_usec += 1000000;
2212 tmp_timeout.tv_sec--;
2214 if(timeout.tv_sec > tmp_timeout.tv_sec
2215 || (timeout.tv_sec == tmp_timeout.tv_sec && timeout.tv_usec > tmp_timeout.tv_usec)) {
2216 timeout.tv_sec = tmp_timeout.tv_sec;
2217 timeout.tv_usec = tmp_timeout.tv_usec;
2223 if(select(max_fd+1, &readset, &writeset, 0, &timeout) < 0)
2225 if(quitting) goto shutdown;
2226 if (gotusr2) { // zzz
2227 gotusr2 = 0;
2228 tomato_helper();
2229 continue;
2231 if(errno == EINTR) continue; /* interrupted by a signal, start again */
2232 syslog(LOG_ERR, "select(all): %m");
2233 syslog(LOG_ERR, "Failed to select open sockets. EXITING");
2234 return 1; /* very serious cause of error */
2236 i = try_sendto(&writeset);
2237 if(i < 0) {
2238 syslog(LOG_ERR, "try_sendto failed to send %d packets", -i);
2240 #ifdef USE_MINIUPNPDCTL
2241 for(ectl = ctllisthead.lh_first; ectl;)
2243 ectlnext = ectl->entries.le_next;
2244 if((ectl->socket >= 0) && FD_ISSET(ectl->socket, &readset))
2246 char buf[256];
2247 int l;
2248 l = read(ectl->socket, buf, sizeof(buf));
2249 if(l > 0)
2251 /*write(ectl->socket, buf, l);*/
2252 write_command_line(ectl->socket, argc, argv);
2253 #ifndef DISABLE_CONFIG_FILE
2254 write_option_list(ectl->socket);
2255 #endif
2256 write_permlist(ectl->socket, upnppermlist, num_upnpperm);
2257 write_upnphttp_details(ectl->socket, upnphttphead.lh_first);
2258 write_ctlsockets_list(ectl->socket, ctllisthead.lh_first);
2259 write_ruleset_details(ectl->socket);
2260 #ifdef ENABLE_EVENTS
2261 write_events_details(ectl->socket);
2262 #endif
2263 /* close the socket */
2264 close(ectl->socket);
2265 ectl->socket = -1;
2267 else
2269 close(ectl->socket);
2270 ectl->socket = -1;
2273 if(ectl->socket < 0)
2275 LIST_REMOVE(ectl, entries);
2276 free(ectl);
2278 ectl = ectlnext;
2280 if((sctl >= 0) && FD_ISSET(sctl, &readset))
2282 int s;
2283 struct sockaddr_un clientname;
2284 struct ctlelem * tmp;
2285 socklen_t clientnamelen = sizeof(struct sockaddr_un);
2286 /*syslog(LOG_DEBUG, "sctl!");*/
2287 s = accept(sctl, (struct sockaddr *)&clientname,
2288 &clientnamelen);
2289 syslog(LOG_DEBUG, "sctl! : '%s'", clientname.sun_path);
2290 tmp = malloc(sizeof(struct ctlelem));
2291 if (tmp == NULL)
2293 syslog(LOG_ERR, "Unable to allocate memory for ctlelem in main()");
2294 close(s);
2296 else
2298 tmp->socket = s;
2299 LIST_INSERT_HEAD(&ctllisthead, tmp, entries);
2302 #endif
2303 #ifdef ENABLE_EVENTS
2304 upnpevents_processfds(&readset, &writeset);
2305 #endif
2306 #ifdef ENABLE_NATPMP
2307 /* process NAT-PMP packets */
2308 for(i=0; i<addr_count; i++)
2310 if((snatpmp[i] >= 0) && FD_ISSET(snatpmp[i], &readset))
2312 unsigned char msg_buff[PCP_MAX_LEN];
2313 struct sockaddr_in senderaddr;
2314 socklen_t senderaddrlen;
2315 int len;
2316 memset(msg_buff, 0, PCP_MAX_LEN);
2317 senderaddrlen = sizeof(senderaddr);
2318 len = ReceiveNATPMPOrPCPPacket(snatpmp[i],
2319 (struct sockaddr *)&senderaddr,
2320 &senderaddrlen,
2321 NULL,
2322 msg_buff, sizeof(msg_buff));
2323 if (len < 1)
2324 continue;
2325 #ifdef ENABLE_PCP
2326 if (msg_buff[0]==0) { /* version equals to 0 -> means NAT-PMP */
2327 /* Check if the packet is coming from a LAN to enforce RFC6886 :
2328 * The NAT gateway MUST NOT accept mapping requests destined to the NAT
2329 * gateway's external IP address or received on its external network
2330 * interface. Only packets received on the internal interface(s) with a
2331 * destination address matching the internal address(es) of the NAT
2332 * gateway should be allowed. */
2333 /* TODO : move to ProcessIncomingNATPMPPacket() ? */
2334 lan_addr = get_lan_for_peer((struct sockaddr *)&senderaddr);
2335 if(lan_addr == NULL) {
2336 char sender_str[64];
2337 sockaddr_to_string((struct sockaddr *)&senderaddr, sender_str, sizeof(sender_str));
2338 syslog(LOG_WARNING, "NAT-PMP packet sender %s not from a LAN, ignoring",
2339 sender_str);
2340 continue;
2342 ProcessIncomingNATPMPPacket(snatpmp[i], msg_buff, len,
2343 &senderaddr);
2344 } else { /* everything else can be PCP */
2345 ProcessIncomingPCPPacket(snatpmp[i], msg_buff, len,
2346 (struct sockaddr *)&senderaddr, NULL);
2349 #else
2350 /* Check if the packet is coming from a LAN to enforce RFC6886 :
2351 * The NAT gateway MUST NOT accept mapping requests destined to the NAT
2352 * gateway's external IP address or received on its external network
2353 * interface. Only packets received on the internal interface(s) with a
2354 * destination address matching the internal address(es) of the NAT
2355 * gateway should be allowed. */
2356 /* TODO : move to ProcessIncomingNATPMPPacket() ? */
2357 lan_addr = get_lan_for_peer((struct sockaddr *)&senderaddr);
2358 if(lan_addr == NULL) {
2359 char sender_str[64];
2360 sockaddr_to_string((struct sockaddr *)&senderaddr, sender_str, sizeof(sender_str));
2361 syslog(LOG_WARNING, "NAT-PMP packet sender %s not from a LAN, ignoring",
2362 sender_str);
2363 continue;
2365 ProcessIncomingNATPMPPacket(snatpmp[i], msg_buff, len, &senderaddr);
2366 #endif
2369 #endif
2370 #if defined(ENABLE_IPV6) && defined(ENABLE_PCP)
2371 /* in IPv6, only PCP is supported, not NAT-PMP */
2372 if(spcp_v6 >= 0 && FD_ISSET(spcp_v6, &readset))
2374 unsigned char msg_buff[PCP_MAX_LEN];
2375 struct sockaddr_in6 senderaddr;
2376 socklen_t senderaddrlen;
2377 struct sockaddr_in6 receiveraddr;
2378 int len;
2379 memset(msg_buff, 0, PCP_MAX_LEN);
2380 senderaddrlen = sizeof(senderaddr);
2381 len = ReceiveNATPMPOrPCPPacket(spcp_v6,
2382 (struct sockaddr *)&senderaddr,
2383 &senderaddrlen,
2384 &receiveraddr,
2385 msg_buff, sizeof(msg_buff));
2386 if(len >= 1)
2387 ProcessIncomingPCPPacket(spcp_v6, msg_buff, len,
2388 (struct sockaddr *)&senderaddr,
2389 &receiveraddr);
2391 #endif
2392 /* process SSDP packets */
2393 if(sudp >= 0 && FD_ISSET(sudp, &readset))
2395 /*syslog(LOG_INFO, "Received UDP Packet");*/
2396 #ifdef ENABLE_HTTPS
2397 ProcessSSDPRequest(sudp, (unsigned short)v.port, (unsigned short)v.https_port);
2398 #else
2399 ProcessSSDPRequest(sudp, (unsigned short)v.port);
2400 #endif
2402 #ifdef ENABLE_IPV6
2403 if(sudpv6 >= 0 && FD_ISSET(sudpv6, &readset))
2405 syslog(LOG_INFO, "Received UDP Packet (IPv6)");
2406 #ifdef ENABLE_HTTPS
2407 ProcessSSDPRequest(sudpv6, (unsigned short)v.port, (unsigned short)v.https_port);
2408 #else
2409 ProcessSSDPRequest(sudpv6, (unsigned short)v.port);
2410 #endif
2412 #endif
2413 #ifdef USE_IFACEWATCHER
2414 /* process kernel notifications */
2415 if (sifacewatcher >= 0 && FD_ISSET(sifacewatcher, &readset))
2416 ProcessInterfaceWatchNotify(sifacewatcher);
2417 #endif
2419 /* process active HTTP connections */
2420 /* LIST_FOREACH macro is not available under linux */
2421 for(e = upnphttphead.lh_first; e != NULL; e = e->entries.le_next)
2423 if(e->socket >= 0)
2425 if(FD_ISSET(e->socket, &readset) ||
2426 FD_ISSET(e->socket, &writeset))
2428 Process_upnphttp(e);
2432 /* process incoming HTTP connections */
2433 if(shttpl >= 0 && FD_ISSET(shttpl, &readset))
2435 struct upnphttp * tmp;
2436 tmp = ProcessIncomingHTTP(shttpl, "HTTP");
2437 if(tmp)
2439 LIST_INSERT_HEAD(&upnphttphead, tmp, entries);
2442 #if defined(V6SOCKETS_ARE_V6ONLY) && defined(ENABLE_IPV6)
2443 if(shttpl_v4 >= 0 && FD_ISSET(shttpl_v4, &readset))
2445 struct upnphttp * tmp;
2446 tmp = ProcessIncomingHTTP(shttpl_v4, "HTTP");
2447 if(tmp)
2449 LIST_INSERT_HEAD(&upnphttphead, tmp, entries);
2452 #endif
2453 #ifdef ENABLE_HTTPS
2454 if(shttpsl >= 0 && FD_ISSET(shttpsl, &readset))
2456 struct upnphttp * tmp;
2457 tmp = ProcessIncomingHTTP(shttpsl, "HTTPS");
2458 if(tmp)
2460 InitSSL_upnphttp(tmp);
2461 LIST_INSERT_HEAD(&upnphttphead, tmp, entries);
2464 #if defined(V6SOCKETS_ARE_V6ONLY) && defined(ENABLE_IPV6)
2465 if(shttpsl_v4 >= 0 && FD_ISSET(shttpsl_v4, &readset))
2467 struct upnphttp * tmp;
2468 tmp = ProcessIncomingHTTP(shttpsl_v4, "HTTPS");
2469 if(tmp)
2471 InitSSL_upnphttp(tmp);
2472 LIST_INSERT_HEAD(&upnphttphead, tmp, entries);
2475 #endif
2476 #endif /* ENABLE_HTTPS */
2477 #ifdef ENABLE_NFQUEUE
2478 /* process NFQ packets */
2479 if(nfqh >= 0 && FD_ISSET(nfqh, &readset))
2481 /* syslog(LOG_INFO, "Received NFQUEUE Packet");*/
2482 ProcessNFQUEUE(nfqh);
2484 #endif
2485 /* delete finished HTTP connections */
2486 for(e = upnphttphead.lh_first; e != NULL; )
2488 next = e->entries.le_next;
2489 if(e->state >= EToDelete)
2491 LIST_REMOVE(e, entries);
2492 Delete_upnphttp(e);
2494 e = next;
2497 } /* end of main loop */
2499 shutdown:
2500 syslog(LOG_NOTICE, "shutting down MiniUPnPd");
2501 /* send good-bye */
2502 if (GETFLAG(ENABLEUPNPMASK))
2504 #ifndef ENABLE_IPV6
2505 if(SendSSDPGoodbye(snotify, addr_count) < 0)
2506 #else
2507 if(SendSSDPGoodbye(snotify, addr_count * 2) < 0)
2508 #endif
2510 syslog(LOG_ERR, "Failed to broadcast good-bye notifications");
2513 /* try to send pending packets */
2514 finalize_sendto();
2516 tomato_save("/etc/upnp/data"); // zzz
2518 /* close out open sockets */
2519 while(upnphttphead.lh_first != NULL)
2521 e = upnphttphead.lh_first;
2522 LIST_REMOVE(e, entries);
2523 Delete_upnphttp(e);
2526 if (sudp >= 0) close(sudp);
2527 if (shttpl >= 0) close(shttpl);
2528 #if defined(V6SOCKETS_ARE_V6ONLY) && defined(ENABLE_IPV6)
2529 if (shttpl_v4 >= 0) close(shttpl_v4);
2530 #endif
2531 #ifdef ENABLE_IPV6
2532 if (sudpv6 >= 0) close(sudpv6);
2533 #endif
2534 #ifdef USE_IFACEWATCHER
2535 if(sifacewatcher >= 0) close(sifacewatcher);
2536 #endif
2537 #ifdef ENABLE_NATPMP
2538 for(i=0; i<addr_count; i++) {
2539 if(snatpmp[i]>=0)
2541 close(snatpmp[i]);
2542 snatpmp[i] = -1;
2545 #endif
2546 #if defined(ENABLE_IPV6) && defined(ENABLE_PCP)
2547 if(spcp_v6 >= 0)
2549 close(spcp_v6);
2550 spcp_v6 = -1;
2552 #endif
2553 #ifdef USE_MINIUPNPDCTL
2554 if(sctl>=0)
2556 close(sctl);
2557 sctl = -1;
2558 if(unlink("/var/run/miniupnpd.ctl") < 0)
2560 syslog(LOG_ERR, "unlink() %m");
2563 #endif
2565 if (GETFLAG(ENABLEUPNPMASK))
2567 #ifndef ENABLE_IPV6
2568 for(i = 0; i < addr_count; i++)
2569 #else
2570 for(i = 0; i < addr_count * 2; i++)
2571 #endif
2572 close(snotify[i]);
2575 /* remove pidfile */
2576 if(pidfilename && (unlink(pidfilename) < 0))
2578 syslog(LOG_ERR, "Failed to remove pidfile %s: %m", pidfilename);
2581 /* delete lists */
2582 while(lan_addrs.lh_first != NULL)
2584 lan_addr = lan_addrs.lh_first;
2585 LIST_REMOVE(lan_addrs.lh_first, list);
2586 free(lan_addr);
2589 #ifdef ENABLE_HTTPS
2590 free_ssl();
2591 #endif
2592 #ifdef ENABLE_NATPMP
2593 free(snatpmp);
2594 #endif
2595 free(snotify);
2596 closelog();
2597 #ifndef DISABLE_CONFIG_FILE
2598 freeoptions();
2599 #endif
2601 return 0;