miniupnpd 1.9 (20160113)
[tomato.git] / release / src / router / miniupnpd / miniupnpd.c
blob45e88fc853d6c0b443fb95658976ffeb5bcfc11b
1 /* $Id: miniupnpd.c,v 1.214 2016/01/01 11:15:56 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 #ifdef TOMATO
53 #include <sys/stat.h>
54 #endif /* TOMATO */
55 #include "macros.h"
56 #include "upnpglobalvars.h"
57 #include "upnphttp.h"
58 #include "upnpdescgen.h"
59 #include "miniupnpdpath.h"
60 #include "getifaddr.h"
61 #include "upnpsoap.h"
62 #include "options.h"
63 #include "minissdp.h"
64 #include "upnpredirect.h"
65 #include "upnppinhole.h"
66 #include "miniupnpdtypes.h"
67 #include "daemonize.h"
68 #include "upnpevents.h"
69 #include "asyncsendto.h"
70 #ifdef ENABLE_NATPMP
71 #include "natpmp.h"
72 #ifdef ENABLE_PCP
73 #include "pcpserver.h"
74 #else
75 #define PCP_MAX_LEN 32
76 #endif
77 #endif
78 #include "commonrdr.h"
79 #include "upnputils.h"
80 #ifdef USE_IFACEWATCHER
81 #include "ifacewatcher.h"
82 #endif
83 #ifdef ENABLE_UPNPPINHOLE
84 #ifdef USE_NETFILTER
85 void init_iptpinhole(void);
86 #endif
87 #endif
89 #ifndef DEFAULT_CONFIG
90 #define DEFAULT_CONFIG "/etc/miniupnpd.conf"
91 #endif
93 #ifdef USE_MINIUPNPDCTL
94 struct ctlelem {
95 int socket;
96 LIST_ENTRY(ctlelem) entries;
98 #endif /* USE_MINIUPNPDCTL */
100 #ifdef ENABLE_NFQUEUE
101 /* globals */
102 static struct nfq_handle *nfqHandle;
103 static struct sockaddr_in ssdp;
105 /* prototypes */
106 static int nfqueue_cb( struct nfq_q_handle *qh, struct nfgenmsg *nfmsg, struct nfq_data *nfa, void *data) ;
107 int identify_ip_protocol (char *payload);
108 int get_udp_dst_port (char *payload);
109 #endif /* ENABLE_NFQUEUE */
111 /* variables used by signals */
112 static volatile sig_atomic_t quitting = 0;
113 volatile sig_atomic_t should_send_public_address_change_notif = 0;
115 #ifdef TOMATO
116 #if 1
117 /* Tomato specific code */
118 static volatile sig_atomic_t gotusr2 = 0;
120 static void
121 sigusr2(int sig)
123 gotusr2 = 1;
126 static void
127 tomato_save(const char *fname)
129 unsigned short eport;
130 unsigned short iport;
131 unsigned int leaseduration;
132 unsigned int timestamp;
133 char proto[4];
134 char iaddr[32];
135 char desc[64];
136 char rhost[32];
137 int n;
138 FILE *f;
139 int t;
140 char tmp[128];
142 strcpy(tmp, "/etc/upnp/saveXXXXXX");
143 if ((t = mkstemp(tmp)) != -1)
145 if ((f = fdopen(t, "w")) != NULL)
147 n = 0;
148 while (upnp_get_redirection_infos_by_index(n, &eport, proto, &iport, iaddr, sizeof(iaddr), desc, sizeof(desc), rhost, sizeof(rhost), &leaseduration) == 0)
150 timestamp = (leaseduration > 0) ? time(NULL) + leaseduration : 0;
151 fprintf(f, "%s %u %s %u [%s] %u\n", proto, eport, iaddr, iport, desc, timestamp);
152 ++n;
154 fclose(f);
155 rename(tmp, fname);
157 else
159 close(t);
161 unlink(tmp);
165 static void
166 tomato_load(void)
168 FILE *f;
169 char s[256];
170 unsigned short eport;
171 unsigned short iport;
172 unsigned int leaseduration;
173 unsigned int timestamp;
174 time_t current_time;
175 char proto[4];
176 char iaddr[32];
177 char *rhost;
178 char *a, *b;
180 if ((f = fopen("/etc/upnp/data", "r")) != NULL)
182 current_time = time(NULL);
183 s[sizeof(s) - 1] = 0;
184 while (fgets(s, sizeof(s) - 1, f)) {
185 if (sscanf(s, "%3s %hu %31s %hu [%*s] %u", proto, &eport, iaddr, &iport, &timestamp) >= 4)
187 if (((a = strchr(s, '[')) != NULL) && ((b = strrchr(a, ']')) != NULL))
189 if (timestamp > 0)
191 if (timestamp > current_time)
192 leaseduration = current_time - timestamp;
193 else
194 continue;
196 else
198 leaseduration = 0; /* default value */
200 *b = 0;
201 rhost = NULL;
202 upnp_redirect(rhost, eport, iaddr, iport, proto, a + 1, leaseduration);
206 fclose(f);
208 #ifdef ENABLE_NATPMP
209 #if 0
210 ScanNATPMPforExpiration();
211 #endif
212 #endif /* ENABLE_NATPMP */
213 unlink("/etc/upnp/load");
216 static void
217 tomato_delete(void)
219 FILE *f;
220 char s[128];
221 unsigned short eport;
222 unsigned short iport;
223 unsigned int leaseduration;
224 char proto[4];
225 char iaddr[32];
226 char desc[64];
227 char rhost[32];
228 int n;
230 if ((f = fopen("/etc/upnp/delete", "r")) != NULL)
232 s[sizeof(s) - 1] = 0;
233 while (fgets(s, sizeof(s) - 1, f))
235 if (sscanf(s, "%3s %hu", proto, &eport) == 2)
237 if (proto[0] == '*')
239 n = upnp_get_portmapping_number_of_entries();
240 while (--n >= 0)
242 if (upnp_get_redirection_infos_by_index(n, &eport, proto, &iport, iaddr, sizeof(iaddr), desc, sizeof(desc), rhost, sizeof(rhost), &leaseduration) == 0)
244 upnp_delete_redirection(eport, proto);
247 break;
249 else
251 upnp_delete_redirection(eport, proto);
255 fclose(f);
256 unlink("/etc/upnp/delete");
260 static void
261 tomato_helper(void)
263 struct stat st;
265 if (stat("/etc/upnp/delete", &st) == 0)
267 tomato_delete();
270 if (stat("/etc/upnp/load", &st) == 0)
272 tomato_load();
275 if (stat("/etc/upnp/save", &st) == 0)
277 tomato_save("/etc/upnp/data");
278 unlink("/etc/upnp/save");
281 if (stat("/etc/upnp/info", &st) == 0)
283 tomato_save("/etc/upnp/data.info");
284 unlink("/etc/upnp/info");
287 #endif /* 1 (tomato) */
288 #endif /* TOMATO */
290 /* OpenAndConfHTTPSocket() :
291 * setup the socket used to handle incoming HTTP connections. */
292 static int
293 #ifdef ENABLE_IPV6
294 OpenAndConfHTTPSocket(unsigned short * port, int ipv6)
295 #else
296 OpenAndConfHTTPSocket(unsigned short * port)
297 #endif
299 int s;
300 int i = 1;
301 #ifdef ENABLE_IPV6
302 struct sockaddr_in6 listenname6;
303 struct sockaddr_in listenname4;
304 #else
305 struct sockaddr_in listenname;
306 #endif
307 socklen_t listenname_len;
309 s = socket(
310 #ifdef ENABLE_IPV6
311 ipv6 ? PF_INET6 : PF_INET,
312 #else
313 PF_INET,
314 #endif
315 SOCK_STREAM, 0);
316 #ifdef ENABLE_IPV6
317 if(s < 0 && ipv6 && errno == EAFNOSUPPORT)
319 /* the system doesn't support IPV6 */
320 syslog(LOG_WARNING, "socket(PF_INET6, ...) failed with EAFNOSUPPORT, disabling IPv6");
321 SETFLAG(IPV6DISABLEDMASK);
322 ipv6 = 0;
323 s = socket(PF_INET, SOCK_STREAM, 0);
325 #endif
326 if(s < 0)
328 syslog(LOG_ERR, "socket(http): %m");
329 return -1;
332 if(setsockopt(s, SOL_SOCKET, SO_REUSEADDR, &i, sizeof(i)) < 0)
334 syslog(LOG_WARNING, "setsockopt(http, SO_REUSEADDR): %m");
336 #if 0
337 /* enable this to force IPV6 only for IPV6 socket.
338 * see http://www.ietf.org/rfc/rfc3493.txt section 5.3 */
339 if(setsockopt(s, IPPROTO_IPV6, IPV6_V6ONLY, &i, sizeof(i)) < 0)
341 syslog(LOG_WARNING, "setsockopt(http, IPV6_V6ONLY): %m");
343 #endif
345 if(!set_non_blocking(s))
347 syslog(LOG_WARNING, "set_non_blocking(http): %m");
350 #ifdef ENABLE_IPV6
351 if(ipv6)
353 memset(&listenname6, 0, sizeof(struct sockaddr_in6));
354 listenname6.sin6_family = AF_INET6;
355 listenname6.sin6_port = htons(*port);
356 listenname6.sin6_addr = ipv6_bind_addr;
357 listenname_len = sizeof(struct sockaddr_in6);
358 } else {
359 memset(&listenname4, 0, sizeof(struct sockaddr_in));
360 listenname4.sin_family = AF_INET;
361 listenname4.sin_port = htons(*port);
362 listenname4.sin_addr.s_addr = htonl(INADDR_ANY);
363 listenname_len = sizeof(struct sockaddr_in);
365 #else
366 memset(&listenname, 0, sizeof(struct sockaddr_in));
367 listenname.sin_family = AF_INET;
368 listenname.sin_port = htons(*port);
369 listenname.sin_addr.s_addr = htonl(INADDR_ANY);
370 listenname_len = sizeof(struct sockaddr_in);
371 #endif
373 #if defined(SO_BINDTODEVICE) && !defined(MULTIPLE_EXTERNAL_IP)
374 /* One and only one LAN interface */
375 if(lan_addrs.lh_first != NULL && lan_addrs.lh_first->list.le_next == NULL
376 && strlen(lan_addrs.lh_first->ifname) > 0)
378 if(setsockopt(s, SOL_SOCKET, SO_BINDTODEVICE,
379 lan_addrs.lh_first->ifname,
380 strlen(lan_addrs.lh_first->ifname)) < 0)
381 syslog(LOG_WARNING, "setsockopt(http, SO_BINDTODEVICE, %s): %m",
382 lan_addrs.lh_first->ifname);
384 #endif /* defined(SO_BINDTODEVICE) && !defined(MULTIPLE_EXTERNAL_IP) */
386 #ifdef ENABLE_IPV6
387 if(bind(s,
388 ipv6 ? (struct sockaddr *)&listenname6 : (struct sockaddr *)&listenname4,
389 listenname_len) < 0)
390 #else
391 if(bind(s, (struct sockaddr *)&listenname, listenname_len) < 0)
392 #endif
394 syslog(LOG_ERR, "bind(http): %m");
395 close(s);
396 return -1;
399 if(listen(s, 5) < 0)
401 syslog(LOG_ERR, "listen(http): %m");
402 close(s);
403 return -1;
406 if(*port == 0) {
407 #ifdef ENABLE_IPV6
408 if(ipv6) {
409 struct sockaddr_in6 sockinfo;
410 socklen_t len = sizeof(struct sockaddr_in6);
411 if (getsockname(s, (struct sockaddr *)&sockinfo, &len) < 0) {
412 syslog(LOG_ERR, "getsockname(): %m");
413 } else {
414 *port = ntohs(sockinfo.sin6_port);
416 } else {
417 #endif /* ENABLE_IPV6 */
418 struct sockaddr_in sockinfo;
419 socklen_t len = sizeof(struct sockaddr_in);
420 if (getsockname(s, (struct sockaddr *)&sockinfo, &len) < 0) {
421 syslog(LOG_ERR, "getsockname(): %m");
422 } else {
423 *port = ntohs(sockinfo.sin_port);
425 #ifdef ENABLE_IPV6
427 #endif /* ENABLE_IPV6 */
429 return s;
432 static struct upnphttp *
433 ProcessIncomingHTTP(int shttpl, const char * protocol)
435 int shttp;
436 socklen_t clientnamelen;
437 #ifdef ENABLE_IPV6
438 struct sockaddr_storage clientname;
439 clientnamelen = sizeof(struct sockaddr_storage);
440 #else
441 struct sockaddr_in clientname;
442 clientnamelen = sizeof(struct sockaddr_in);
443 #endif
444 shttp = accept(shttpl, (struct sockaddr *)&clientname, &clientnamelen);
445 if(shttp<0)
447 /* ignore EAGAIN, EWOULDBLOCK, EINTR, we just try again later */
448 if(errno != EAGAIN && errno != EWOULDBLOCK && errno != EINTR)
449 syslog(LOG_ERR, "accept(http): %m");
451 else
453 struct upnphttp * tmp = 0;
454 char addr_str[64];
456 sockaddr_to_string((struct sockaddr *)&clientname, addr_str, sizeof(addr_str));
457 #ifdef DEBUG
458 syslog(LOG_DEBUG, "%s connection from %s", protocol, addr_str);
459 #endif /* DEBUG */
460 if(get_lan_for_peer((struct sockaddr *)&clientname) == NULL)
462 /* The peer is not a LAN ! */
463 syslog(LOG_WARNING,
464 "%s peer %s is not from a LAN, closing the connection",
465 protocol, addr_str);
466 close(shttp);
468 else
470 /* Create a new upnphttp object and add it to
471 * the active upnphttp object list */
472 tmp = New_upnphttp(shttp);
473 if(tmp)
475 #ifdef ENABLE_IPV6
476 if(clientname.ss_family == AF_INET)
478 tmp->clientaddr = ((struct sockaddr_in *)&clientname)->sin_addr;
480 else if(clientname.ss_family == AF_INET6)
482 struct sockaddr_in6 * addr = (struct sockaddr_in6 *)&clientname;
483 if(IN6_IS_ADDR_V4MAPPED(&addr->sin6_addr))
485 memcpy(&tmp->clientaddr,
486 &addr->sin6_addr.s6_addr[12],
489 else
491 tmp->ipv6 = 1;
492 memcpy(&tmp->clientaddr_v6,
493 &addr->sin6_addr,
494 sizeof(struct in6_addr));
497 #else
498 tmp->clientaddr = clientname.sin_addr;
499 #endif
500 memcpy(tmp->clientaddr_str, addr_str, sizeof(tmp->clientaddr_str));
501 return tmp;
503 else
505 syslog(LOG_ERR, "New_upnphttp() failed");
506 close(shttp);
510 return NULL;
513 #ifdef ENABLE_NFQUEUE
515 int identify_ip_protocol(char *payload) {
516 return payload[9];
521 * This function returns the destination port of the captured packet UDP
523 int get_udp_dst_port(char *payload) {
524 char *pkt_data_ptr = NULL;
525 pkt_data_ptr = payload + sizeof(struct ip);
527 /* Cast the UDP Header from the raw packet */
528 struct udphdr *udp = (struct udphdr *) pkt_data_ptr;
530 /* get the dst port of the packet */
531 return(ntohs(udp->dest));
534 static int
535 OpenAndConfNFqueue(){
537 struct nfq_q_handle *myQueue;
538 struct nfnl_handle *netlinkHandle;
540 int fd = 0, e = 0;
542 inet_pton(AF_INET, "239.255.255.250", &(ssdp.sin_addr));
544 /* Get a queue connection handle from the module */
545 if (!(nfqHandle = nfq_open())) {
546 syslog(LOG_ERR, "Error in nfq_open(): %m");
547 return -1;
550 /* Unbind the handler from processing any IP packets
551 Not totally sure why this is done, or if it's necessary... */
552 if ((e = nfq_unbind_pf(nfqHandle, AF_INET)) < 0) {
553 syslog(LOG_ERR, "Error in nfq_unbind_pf(): %m");
554 return -1;
557 /* Bind this handler to process IP packets... */
558 if (nfq_bind_pf(nfqHandle, AF_INET) < 0) {
559 syslog(LOG_ERR, "Error in nfq_bind_pf(): %m");
560 return -1;
563 /* Install a callback on queue -Q */
564 if (!(myQueue = nfq_create_queue(nfqHandle, nfqueue, &nfqueue_cb, NULL))) {
565 syslog(LOG_ERR, "Error in nfq_create_queue(): %m");
566 return -1;
569 /* Turn on packet copy mode */
570 if (nfq_set_mode(myQueue, NFQNL_COPY_PACKET, 0xffff) < 0) {
571 syslog(LOG_ERR, "Error setting packet copy mode (): %m");
572 return -1;
575 netlinkHandle = nfq_nfnlh(nfqHandle);
576 fd = nfnl_fd(netlinkHandle);
578 return fd;
583 static int nfqueue_cb(
584 struct nfq_q_handle *qh,
585 struct nfgenmsg *nfmsg,
586 struct nfq_data *nfa,
587 void *data) {
589 char *pkt;
590 struct nfqnl_msg_packet_hdr *ph;
591 ph = nfq_get_msg_packet_hdr(nfa);
593 if ( ph ) {
595 int id = 0, size = 0;
596 id = ntohl(ph->packet_id);
598 size = nfq_get_payload(nfa, &pkt);
600 struct ip *iph = (struct ip *) pkt;
602 int id_protocol = identify_ip_protocol(pkt);
604 int dport = get_udp_dst_port(pkt);
606 int x = sizeof (struct ip) + sizeof (struct udphdr);
608 /* packets we are interested in are UDP multicast to 239.255.255.250:1900
609 * and start with a data string M-SEARCH
611 if ( (dport == 1900) && (id_protocol == IPPROTO_UDP)
612 && (ssdp.sin_addr.s_addr == iph->ip_dst.s_addr) ) {
614 /* get the index that the packet came in on */
615 u_int32_t idx = nfq_get_indev(nfa);
616 int i = 0;
617 for ( ;i < n_nfqix ; i++) {
618 if ( nfqix[i] == idx ) {
620 struct udphdr *udp = (struct udphdr *) (pkt + sizeof(struct ip));
622 char *dd = pkt + x;
624 struct sockaddr_in sendername;
625 sendername.sin_family = AF_INET;
626 sendername.sin_port = udp->source;
627 sendername.sin_addr.s_addr = iph->ip_src.s_addr;
629 /* printf("pkt found %s\n",dd);*/
630 ProcessSSDPData (sudp, dd, size - x,
631 &sendername, (unsigned short) 5555);
636 nfq_set_verdict(qh, id, NF_ACCEPT, 0, NULL);
638 } else {
639 syslog(LOG_ERR,"nfq_get_msg_packet_hdr failed");
640 return 1;
641 /* from nfqueue source: 0 = ok, >0 = soft error, <0 hard error */
644 return 0;
647 static void ProcessNFQUEUE(int fd){
648 char buf[4096];
650 socklen_t len_r;
651 struct sockaddr_in sendername;
652 len_r = sizeof(struct sockaddr_in);
654 int res = recvfrom(fd, buf, sizeof(buf), 0,
655 (struct sockaddr *)&sendername, &len_r);
657 nfq_handle_packet(nfqHandle, buf, res);
659 #endif
661 /* Functions used to communicate with miniupnpdctl */
662 #ifdef USE_MINIUPNPDCTL
663 static int
664 OpenAndConfCtlUnixSocket(const char * path)
666 struct sockaddr_un localun;
667 int s;
668 s = socket(AF_UNIX, SOCK_STREAM, 0);
669 localun.sun_family = AF_UNIX;
670 strncpy(localun.sun_path, path,
671 sizeof(localun.sun_path));
672 if(bind(s, (struct sockaddr *)&localun,
673 sizeof(struct sockaddr_un)) < 0)
675 syslog(LOG_ERR, "bind(sctl): %m");
676 close(s);
677 s = -1;
679 else if(listen(s, 5) < 0)
681 syslog(LOG_ERR, "listen(sctl): %m");
682 close(s);
683 s = -1;
685 return s;
688 static void
689 write_upnphttp_details(int fd, struct upnphttp * e)
691 char buffer[256];
692 int len;
693 write(fd, "HTTP :\n", 7);
694 while(e)
696 len = snprintf(buffer, sizeof(buffer),
697 "%d %d %s req_buf=%p(%dbytes) res_buf=%p(%dbytes alloc)\n",
698 e->socket, e->state, e->HttpVer,
699 e->req_buf, e->req_buflen,
700 e->res_buf, e->res_buf_alloclen);
701 write(fd, buffer, len);
702 e = e->entries.le_next;
706 static void
707 write_ctlsockets_list(int fd, struct ctlelem * e)
709 char buffer[256];
710 int len;
711 write(fd, "CTL :\n", 6);
712 while(e)
714 len = snprintf(buffer, sizeof(buffer),
715 "struct ctlelem: socket=%d\n", e->socket);
716 write(fd, buffer, len);
717 e = e->entries.le_next;
721 #ifndef DISABLE_CONFIG_FILE
722 static void
723 write_option_list(int fd)
725 char buffer[256];
726 int len;
727 unsigned int i;
728 write(fd, "Options :\n", 10);
729 for(i=0; i<num_options; i++)
731 len = snprintf(buffer, sizeof(buffer),
732 "opt=%02d %s\n",
733 ary_options[i].id, ary_options[i].value);
734 write(fd, buffer, len);
737 #endif
739 static void
740 write_command_line(int fd, int argc, char * * argv)
742 char buffer[256];
743 int len;
744 int i;
745 write(fd, "Command Line :\n", 15);
746 for(i=0; i<argc; i++)
748 len = snprintf(buffer, sizeof(buffer),
749 "argv[%02d]='%s'\n",
750 i, argv[i]);
751 write(fd, buffer, len);
755 #endif
757 /* Handler for the SIGTERM signal (kill)
758 * SIGINT is also handled */
759 static void
760 sigterm(int sig)
762 UNUSED(sig);
763 /*int save_errno = errno; */
764 /*signal(sig, SIG_IGN);*/ /* Ignore this signal while we are quitting */
765 /* Note : isn't it useless ? */
767 #if 0
768 /* calling syslog() is forbidden in signal handler according to
769 * signal(3) */
770 syslog(LOG_NOTICE, "received signal %d, good-bye", sig);
771 #endif
773 quitting = 1;
774 /*errno = save_errno;*/
777 /* Handler for the SIGUSR1 signal indicating public IP address change. */
778 static void
779 sigusr1(int sig)
781 UNUSED(sig);
782 #if 0
783 /* calling syslog() is forbidden in signal handler according to
784 * signal(3) */
785 syslog(LOG_INFO, "received signal %d, public ip address change", sig);
786 #endif
788 should_send_public_address_change_notif = 1;
791 /* record the startup time, for returning uptime */
792 static void
793 set_startup_time(int sysuptime)
795 startup_time = time(NULL);
796 #ifdef USE_TIME_AS_BOOTID
797 if(startup_time > 60*60*24 && upnp_bootid == 1) {
798 /* We know we are not January the 1st 1970 */
799 upnp_bootid = (unsigned int)startup_time;
800 /* from UDA v1.1 :
801 * A convenient mechanism is to set this field value to the time
802 * that the device sends its initial announcement, expressed as
803 * seconds elapsed since midnight January 1, 1970; */
805 #endif /* USE_TIME_AS_BOOTID */
806 if(sysuptime)
808 /* use system uptime instead of daemon uptime */
809 #if defined(__linux__)
810 char buff[64];
811 int uptime = 0, fd;
812 fd = open("/proc/uptime", O_RDONLY);
813 if(fd < 0)
815 syslog(LOG_ERR, "open(\"/proc/uptime\" : %m");
817 else
819 memset(buff, 0, sizeof(buff));
820 if(read(fd, buff, sizeof(buff) - 1) < 0)
822 syslog(LOG_ERR, "read(\"/proc/uptime\" : %m");
824 else
826 uptime = atoi(buff);
827 syslog(LOG_INFO, "system uptime is %d seconds", uptime);
829 close(fd);
830 startup_time -= uptime;
832 #elif defined(SOLARIS_KSTATS)
833 kstat_ctl_t *kc;
834 kc = kstat_open();
835 if(kc != NULL)
837 kstat_t *ksp;
838 ksp = kstat_lookup(kc, "unix", 0, "system_misc");
839 if(ksp && (kstat_read(kc, ksp, NULL) != -1))
841 void *ptr = kstat_data_lookup(ksp, "boot_time");
842 if(ptr)
843 memcpy(&startup_time, ptr, sizeof(startup_time));
844 else
845 syslog(LOG_ERR, "cannot find boot_time kstat");
847 else
848 syslog(LOG_ERR, "cannot open kstats for unix/0/system_misc: %m");
849 kstat_close(kc);
851 #else
852 struct timeval boottime;
853 size_t size = sizeof(boottime);
854 int name[2] = { CTL_KERN, KERN_BOOTTIME };
855 if(sysctl(name, 2, &boottime, &size, NULL, 0) < 0)
857 syslog(LOG_ERR, "sysctl(\"kern.boottime\") failed");
859 else
861 startup_time = boottime.tv_sec;
863 #endif
867 /* structure containing variables used during "main loop"
868 * that are filled during the init */
869 struct runtime_vars {
870 /* LAN IP addresses for SSDP traffic and HTTP */
871 /* moved to global vars */
872 int port; /* HTTP Port */
873 #ifdef ENABLE_HTTPS
874 int https_port; /* HTTPS Port */
875 #endif
876 int notify_interval; /* seconds between SSDP announces */
877 /* unused rules cleaning related variables : */
878 int clean_ruleset_threshold; /* threshold for removing unused rules */
879 int clean_ruleset_interval; /* (minimum) interval between checks */
882 /* parselanaddr()
883 * parse address with mask
884 * ex: 192.168.1.1/24 or 192.168.1.1/255.255.255.0
885 * When MULTIPLE_EXTERNAL_IP is enabled, the ip address of the
886 * external interface associated with the lan subnet follows.
887 * ex : 192.168.1.1/24 81.21.41.11
889 * Can also use the interface name (ie eth0)
891 * return value :
892 * 0 : ok
893 * -1 : error */
894 static int
895 parselanaddr(struct lan_addr_s * lan_addr, const char * str)
897 const char * p;
898 int n;
899 char tmp[16];
901 memset(lan_addr, 0, sizeof(struct lan_addr_s));
902 p = str;
903 while(*p && *p != '/' && !isspace(*p))
904 p++;
905 n = p - str;
906 if(!isdigit(str[0]) && n < (int)sizeof(lan_addr->ifname))
908 /* not starting with a digit : suppose it is an interface name */
909 memcpy(lan_addr->ifname, str, n);
910 lan_addr->ifname[n] = '\0';
911 if(getifaddr(lan_addr->ifname, lan_addr->str, sizeof(lan_addr->str),
912 &lan_addr->addr, &lan_addr->mask) < 0) {
913 #ifdef ENABLE_IPV6
914 fprintf(stderr, "interface \"%s\" has no IPv4 address\n", str);
915 lan_addr->str[0] = '\0';
916 lan_addr->addr.s_addr = htonl(0x00000000u);
917 lan_addr->mask.s_addr = htonl(0xffffffffu);
918 #else /* ENABLE_IPV6 */
919 goto parselan_error;
920 #endif /* ENABLE_IPV6 */
922 /*printf("%s => %s\n", lan_addr->ifname, lan_addr->str);*/
924 else
926 if(n>15)
927 goto parselan_error;
928 memcpy(lan_addr->str, str, n);
929 lan_addr->str[n] = '\0';
930 if(!inet_aton(lan_addr->str, &lan_addr->addr))
931 goto parselan_error;
933 if(*p == '/')
935 const char * q = ++p;
936 while(*p && isdigit(*p))
937 p++;
938 if(*p=='.')
940 /* parse mask in /255.255.255.0 format */
941 while(*p && (*p=='.' || isdigit(*p)))
942 p++;
943 n = p - q;
944 if(n>15)
945 goto parselan_error;
946 memcpy(tmp, q, n);
947 tmp[n] = '\0';
948 if(!inet_aton(tmp, &lan_addr->mask))
949 goto parselan_error;
951 else
953 /* it is a /24 format */
954 int nbits = atoi(q);
955 if(nbits > 32 || nbits < 0)
956 goto parselan_error;
957 lan_addr->mask.s_addr = htonl(nbits ? (0xffffffffu << (32 - nbits)) : 0);
960 else if(lan_addr->mask.s_addr == 0)
962 /* by default, networks are /24 */
963 lan_addr->mask.s_addr = htonl(0xffffff00u);
965 #ifdef MULTIPLE_EXTERNAL_IP
966 /* skip spaces */
967 while(*p && isspace(*p))
968 p++;
969 if(*p) {
970 /* parse the exteral ip address to associate with this subnet */
971 n = 0;
972 while(p[n] && !isspace(*p))
973 n++;
974 if(n<=15) {
975 memcpy(lan_addr->ext_ip_str, p, n);
976 lan_addr->ext_ip_str[n] = '\0';
977 if(!inet_aton(lan_addr->ext_ip_str, &lan_addr->ext_ip_addr)) {
978 /* error */
979 fprintf(stderr, "Error parsing address : %s\n", lan_addr->ext_ip_str);
983 #endif
984 #ifdef ENABLE_IPV6
985 if(lan_addr->ifname[0] != '\0')
987 lan_addr->index = if_nametoindex(lan_addr->ifname);
988 if(lan_addr->index == 0)
989 fprintf(stderr, "Cannot get index for network interface %s",
990 lan_addr->ifname);
992 else
994 fprintf(stderr,
995 "Error: please specify LAN network interface by name instead of IPv4 address : %s\n",
996 str);
997 return -1;
999 #endif
1000 return 0;
1001 parselan_error:
1002 fprintf(stderr, "Error parsing address/mask (or interface name) : %s\n",
1003 str);
1004 return -1;
1007 /* fill uuidvalue_wan and uuidvalue_wcd based on uuidvalue_igd */
1008 void complete_uuidvalues(void)
1010 size_t len;
1011 len = strlen(uuidvalue_igd);
1012 memcpy(uuidvalue_wan, uuidvalue_igd, len+1);
1013 switch(uuidvalue_wan[len-1]) {
1014 case '9':
1015 uuidvalue_wan[len-1] = 'a';
1016 break;
1017 case 'f':
1018 uuidvalue_wan[len-1] = '0';
1019 break;
1020 default:
1021 uuidvalue_wan[len-1]++;
1023 memcpy(uuidvalue_wcd, uuidvalue_wan, len+1);
1024 switch(uuidvalue_wcd[len-1]) {
1025 case '9':
1026 uuidvalue_wcd[len-1] = 'a';
1027 break;
1028 case 'f':
1029 uuidvalue_wcd[len-1] = '0';
1030 break;
1031 default:
1032 uuidvalue_wcd[len-1]++;
1036 /* init phase :
1037 * 1) read configuration file
1038 * 2) read command line arguments
1039 * 3) daemonize
1040 * 4) open syslog
1041 * 5) check and write pid file
1042 * 6) set startup time stamp
1043 * 7) compute presentation URL
1044 * 8) set signal handlers
1045 * 9) init random generator (srandom())
1046 * 10) init redirection engine
1047 * 11) reload mapping from leasefile */
1048 static int
1049 init(int argc, char * * argv, struct runtime_vars * v)
1051 int i;
1052 int pid;
1053 int debug_flag = 0;
1054 int openlog_option;
1055 struct sigaction sa;
1056 /*const char * logfilename = 0;*/
1057 const char * presurl = 0;
1058 #ifndef DISABLE_CONFIG_FILE
1059 int options_flag = 0;
1060 const char * optionsfile = DEFAULT_CONFIG;
1061 #endif /* DISABLE_CONFIG_FILE */
1062 struct lan_addr_s * lan_addr;
1063 struct lan_addr_s * lan_addr2;
1065 /* only print usage if -h is used */
1066 for(i=1; i<argc; i++)
1068 if(0 == strcmp(argv[i], "-h"))
1069 goto print_usage;
1071 #ifndef DISABLE_CONFIG_FILE
1072 /* first check if "-f" option is used */
1073 for(i=2; i<argc; i++)
1075 if(0 == strcmp(argv[i-1], "-f"))
1077 optionsfile = argv[i];
1078 options_flag = 1;
1079 break;
1082 #endif /* DISABLE_CONFIG_FILE */
1084 /* set initial values */
1085 SETFLAG(ENABLEUPNPMASK); /* UPnP is enabled by default */
1086 #ifdef ENABLE_IPV6
1087 ipv6_bind_addr = in6addr_any;
1088 #endif /* ENABLE_IPV6 */
1090 LIST_INIT(&lan_addrs);
1091 v->port = -1;
1092 #ifdef ENABLE_HTTPS
1093 v->https_port = -1;
1094 #endif
1095 v->notify_interval = 30; /* seconds between SSDP announces */
1096 v->clean_ruleset_threshold = 20;
1097 v->clean_ruleset_interval = 0; /* interval between ruleset check. 0=disabled */
1098 #ifndef DISABLE_CONFIG_FILE
1099 /* read options file first since
1100 * command line arguments have final say */
1101 if(readoptionsfile(optionsfile) < 0)
1103 /* only error if file exists or using -f */
1104 if(access(optionsfile, F_OK) == 0 || options_flag)
1105 fprintf(stderr, "Error reading configuration file %s\n", optionsfile);
1107 else
1109 for(i=0; i<(int)num_options; i++)
1111 switch(ary_options[i].id)
1113 case UPNPEXT_IFNAME:
1114 ext_if_name = ary_options[i].value;
1115 break;
1116 case UPNPEXT_IP:
1117 use_ext_ip_addr = ary_options[i].value;
1118 break;
1119 case UPNPLISTENING_IP:
1120 lan_addr = (struct lan_addr_s *) malloc(sizeof(struct lan_addr_s));
1121 if (lan_addr == NULL)
1123 fprintf(stderr, "malloc(sizeof(struct lan_addr_s)): %m");
1124 break;
1126 if(parselanaddr(lan_addr, ary_options[i].value) != 0)
1128 fprintf(stderr, "can't parse \"%s\" as a valid "
1129 #ifndef ENABLE_IPV6
1130 "LAN address or "
1131 #endif
1132 "interface name\n", ary_options[i].value);
1133 free(lan_addr);
1134 break;
1136 LIST_INSERT_HEAD(&lan_addrs, lan_addr, list);
1137 break;
1138 #ifdef ENABLE_IPV6
1139 case UPNPIPV6_LISTENING_IP:
1140 if (inet_pton(AF_INET6, ary_options[i].value, &ipv6_bind_addr) < 1)
1142 fprintf(stderr, "can't parse \"%s\" as valid IPv6 listening address", ary_options[i].value);
1144 break;
1145 #endif /* ENABLE_IPV6 */
1146 case UPNPPORT:
1147 v->port = atoi(ary_options[i].value);
1148 break;
1149 #ifdef ENABLE_HTTPS
1150 case UPNPHTTPSPORT:
1151 v->https_port = atoi(ary_options[i].value);
1152 break;
1153 #endif
1154 case UPNPBITRATE_UP:
1155 upstream_bitrate = strtoul(ary_options[i].value, 0, 0);
1156 break;
1157 case UPNPBITRATE_DOWN:
1158 downstream_bitrate = strtoul(ary_options[i].value, 0, 0);
1159 break;
1160 case UPNPPRESENTATIONURL:
1161 presurl = ary_options[i].value;
1162 break;
1163 #ifdef ENABLE_MANUFACTURER_INFO_CONFIGURATION
1164 case UPNPFRIENDLY_NAME:
1165 strncpy(friendly_name, ary_options[i].value, FRIENDLY_NAME_MAX_LEN);
1166 friendly_name[FRIENDLY_NAME_MAX_LEN-1] = '\0';
1167 break;
1168 case UPNPMANUFACTURER_NAME:
1169 strncpy(manufacturer_name, ary_options[i].value, MANUFACTURER_NAME_MAX_LEN);
1170 manufacturer_name[MANUFACTURER_NAME_MAX_LEN-1] = '\0';
1171 break;
1172 case UPNPMANUFACTURER_URL:
1173 strncpy(manufacturer_url, ary_options[i].value, MANUFACTURER_URL_MAX_LEN);
1174 manufacturer_url[MANUFACTURER_URL_MAX_LEN-1] = '\0';
1175 break;
1176 case UPNPMODEL_NAME:
1177 strncpy(model_name, ary_options[i].value, MODEL_NAME_MAX_LEN);
1178 model_name[MODEL_NAME_MAX_LEN-1] = '\0';
1179 break;
1180 case UPNPMODEL_DESCRIPTION:
1181 strncpy(model_description, ary_options[i].value, MODEL_DESCRIPTION_MAX_LEN);
1182 model_description[MODEL_DESCRIPTION_MAX_LEN-1] = '\0';
1183 break;
1184 case UPNPMODEL_URL:
1185 strncpy(model_url, ary_options[i].value, MODEL_URL_MAX_LEN);
1186 model_url[MODEL_URL_MAX_LEN-1] = '\0';
1187 break;
1188 #endif /* ENABLE_MANUFACTURER_INFO_CONFIGURATION */
1189 #ifdef USE_NETFILTER
1190 case UPNPFORWARDCHAIN:
1191 miniupnpd_forward_chain = ary_options[i].value;
1192 break;
1193 case UPNPNATCHAIN:
1194 miniupnpd_nat_chain = ary_options[i].value;
1195 break;
1196 #endif /* USE_NETFILTER */
1197 case UPNPNOTIFY_INTERVAL:
1198 v->notify_interval = atoi(ary_options[i].value);
1199 break;
1200 case UPNPSYSTEM_UPTIME:
1201 if(strcmp(ary_options[i].value, "yes") == 0)
1202 SETFLAG(SYSUPTIMEMASK); /*sysuptime = 1;*/
1203 break;
1204 #if defined(USE_PF) || defined(USE_IPF)
1205 case UPNPPACKET_LOG:
1206 if(strcmp(ary_options[i].value, "yes") == 0)
1207 SETFLAG(LOGPACKETSMASK); /*logpackets = 1;*/
1208 break;
1209 #endif /* defined(USE_PF) || defined(USE_IPF) */
1210 case UPNPUUID:
1211 strncpy(uuidvalue_igd+5, ary_options[i].value,
1212 strlen(uuidvalue_igd+5) + 1);
1213 complete_uuidvalues();
1214 break;
1215 case UPNPSERIAL:
1216 strncpy(serialnumber, ary_options[i].value, SERIALNUMBER_MAX_LEN);
1217 serialnumber[SERIALNUMBER_MAX_LEN-1] = '\0';
1218 break;
1219 case UPNPMODEL_NUMBER:
1220 strncpy(modelnumber, ary_options[i].value, MODELNUMBER_MAX_LEN);
1221 modelnumber[MODELNUMBER_MAX_LEN-1] = '\0';
1222 break;
1223 case UPNPCLEANTHRESHOLD:
1224 v->clean_ruleset_threshold = atoi(ary_options[i].value);
1225 break;
1226 case UPNPCLEANINTERVAL:
1227 v->clean_ruleset_interval = atoi(ary_options[i].value);
1228 break;
1229 #ifdef USE_PF
1230 case UPNPANCHOR:
1231 anchor_name = ary_options[i].value;
1232 break;
1233 case UPNPQUEUE:
1234 queue = ary_options[i].value;
1235 break;
1236 case UPNPTAG:
1237 tag = ary_options[i].value;
1238 break;
1239 #endif /* USE_PF */
1240 #ifdef ENABLE_NATPMP
1241 case UPNPENABLENATPMP:
1242 if(strcmp(ary_options[i].value, "yes") == 0)
1243 SETFLAG(ENABLENATPMPMASK); /*enablenatpmp = 1;*/
1244 else
1245 if(atoi(ary_options[i].value))
1246 SETFLAG(ENABLENATPMPMASK);
1247 /*enablenatpmp = atoi(ary_options[i].value);*/
1248 break;
1249 #endif /* ENABLE_NATPMP */
1250 #ifdef ENABLE_PCP
1251 case UPNPPCPMINLIFETIME:
1252 min_lifetime = atoi(ary_options[i].value);
1253 if (min_lifetime > 120 ) {
1254 min_lifetime = 120;
1256 break;
1257 case UPNPPCPMAXLIFETIME:
1258 max_lifetime = atoi(ary_options[i].value);
1259 if (max_lifetime > 86400 ) {
1260 max_lifetime = 86400;
1262 break;
1263 case UPNPPCPALLOWTHIRDPARTY:
1264 if(strcmp(ary_options[i].value, "yes") == 0)
1265 SETFLAG(PCP_ALLOWTHIRDPARTYMASK);
1266 break;
1267 #endif /* ENABLE_PCP */
1268 #ifdef PF_ENABLE_FILTER_RULES
1269 case UPNPQUICKRULES:
1270 if(strcmp(ary_options[i].value, "no") == 0)
1271 SETFLAG(PFNOQUICKRULESMASK);
1272 break;
1273 #endif /* PF_ENABLE_FILTER_RULES */
1274 case UPNPENABLE:
1275 if(strcmp(ary_options[i].value, "yes") != 0)
1276 CLEARFLAG(ENABLEUPNPMASK);
1277 break;
1278 case UPNPSECUREMODE:
1279 if(strcmp(ary_options[i].value, "yes") == 0)
1280 SETFLAG(SECUREMODEMASK);
1281 break;
1282 #ifdef ENABLE_LEASEFILE
1283 case UPNPLEASEFILE:
1284 lease_file = ary_options[i].value;
1285 break;
1286 #endif /* ENABLE_LEASEFILE */
1287 case UPNPMINISSDPDSOCKET:
1288 minissdpdsocketpath = ary_options[i].value;
1289 break;
1290 default:
1291 fprintf(stderr, "Unknown option in file %s\n",
1292 optionsfile);
1295 #ifdef ENABLE_PCP
1296 /* if lifetimes are inverse */
1297 if (min_lifetime >= max_lifetime) {
1298 fprintf(stderr, "Minimum lifetime (%lu) is greater than or equal to maximum lifetime (%lu).\n", min_lifetime, max_lifetime);
1299 fprintf(stderr, "Check your configuration file.\n");
1300 return 1;
1302 #endif /* ENABLE_PCP */
1304 #endif /* DISABLE_CONFIG_FILE */
1306 /* command line arguments processing */
1307 for(i=1; i<argc; i++)
1309 if(argv[i][0]!='-')
1311 fprintf(stderr, "Unknown option: %s\n", argv[i]);
1313 else switch(argv[i][1])
1315 case 'b':
1316 if(i+1 < argc) {
1317 upnp_bootid = (unsigned int)strtoul(argv[++i], NULL, 10);
1318 } else
1319 fprintf(stderr, "Option -%c takes one argument.\n", argv[i][1]);
1320 break;
1321 case 'o':
1322 if(i+1 < argc)
1323 use_ext_ip_addr = argv[++i];
1324 else
1325 fprintf(stderr, "Option -%c takes one argument.\n", argv[i][1]);
1326 break;
1327 case 't':
1328 if(i+1 < argc)
1329 v->notify_interval = atoi(argv[++i]);
1330 else
1331 fprintf(stderr, "Option -%c takes one argument.\n", argv[i][1]);
1332 break;
1333 case 'r':
1334 if(i+1 < argc)
1335 v->clean_ruleset_interval = atoi(argv[++i]);
1336 else
1337 fprintf(stderr, "Option -%c takes one argument.\n", argv[i][1]);
1338 break;
1339 case 'u':
1340 if(i+1 < argc) {
1341 strncpy(uuidvalue_igd+5, argv[++i], strlen(uuidvalue_igd+5) + 1);
1342 complete_uuidvalues();
1343 } else
1344 fprintf(stderr, "Option -%c takes one argument.\n", argv[i][1]);
1345 break;
1346 #ifdef ENABLE_MANUFACTURER_INFO_CONFIGURATION
1347 case 'z':
1348 if(i+1 < argc)
1349 strncpy(friendly_name, argv[++i], FRIENDLY_NAME_MAX_LEN);
1350 else
1351 fprintf(stderr, "Option -%c takes one argument.\n", argv[i][1]);
1352 friendly_name[FRIENDLY_NAME_MAX_LEN-1] = '\0';
1353 break;
1354 #endif /* ENABLE_MANUFACTURER_INFO_CONFIGURATION */
1355 case 's':
1356 if(i+1 < argc)
1357 strncpy(serialnumber, argv[++i], SERIALNUMBER_MAX_LEN);
1358 else
1359 fprintf(stderr, "Option -%c takes one argument.\n", argv[i][1]);
1360 serialnumber[SERIALNUMBER_MAX_LEN-1] = '\0';
1361 break;
1362 case 'm':
1363 if(i+1 < argc)
1364 strncpy(modelnumber, argv[++i], MODELNUMBER_MAX_LEN);
1365 else
1366 fprintf(stderr, "Option -%c takes one argument.\n", argv[i][1]);
1367 modelnumber[MODELNUMBER_MAX_LEN-1] = '\0';
1368 break;
1369 #ifdef ENABLE_NATPMP
1370 case 'N':
1371 /*enablenatpmp = 1;*/
1372 SETFLAG(ENABLENATPMPMASK);
1373 break;
1374 #endif /* ENABLE_NATPMP */
1375 case 'U':
1376 /*sysuptime = 1;*/
1377 SETFLAG(SYSUPTIMEMASK);
1378 break;
1379 /*case 'l':
1380 logfilename = argv[++i];
1381 break;*/
1382 #if defined(USE_PF) || defined(USE_IPF)
1383 case 'L':
1384 /*logpackets = 1;*/
1385 SETFLAG(LOGPACKETSMASK);
1386 break;
1387 #endif /* defined(USE_PF) || defined(USE_IPF) */
1388 case 'S':
1389 SETFLAG(SECUREMODEMASK);
1390 break;
1391 case 'i':
1392 if(i+1 < argc)
1393 ext_if_name = argv[++i];
1394 else
1395 fprintf(stderr, "Option -%c takes one argument.\n", argv[i][1]);
1396 break;
1397 #ifdef USE_PF
1398 case 'q':
1399 if(i+1 < argc)
1400 queue = argv[++i];
1401 else
1402 fprintf(stderr, "Option -%c takes one argument.\n", argv[i][1]);
1403 break;
1404 case 'T':
1405 if(i+1 < argc)
1406 tag = argv[++i];
1407 else
1408 fprintf(stderr, "Option -%c takes one argument.\n", argv[i][1]);
1409 break;
1410 #endif /* USE_PF */
1411 case 'p':
1412 if(i+1 < argc)
1413 v->port = atoi(argv[++i]);
1414 else
1415 fprintf(stderr, "Option -%c takes one argument.\n", argv[i][1]);
1416 break;
1417 #ifdef ENABLE_HTTPS
1418 case 'H':
1419 if(i+1 < argc)
1420 v->https_port = atoi(argv[++i]);
1421 else
1422 fprintf(stderr, "Option -%c takes one argument.\n", argv[i][1]);
1423 break;
1424 #endif /* ENABLE_HTTPS */
1425 #ifdef ENABLE_NFQUEUE
1426 case 'Q':
1427 if(i+1<argc)
1429 nfqueue = atoi(argv[++i]);
1431 else
1432 fprintf(stderr, "Option -%c takes one argument.\n", argv[i][1]);
1433 break;
1434 case 'n':
1435 if (i+1 < argc) {
1436 i++;
1437 if(n_nfqix < MAX_LAN_ADDR) {
1438 nfqix[n_nfqix++] = if_nametoindex(argv[i]);
1439 } else {
1440 fprintf(stderr,"Too many nfq interfaces. Ignoring %s\n", argv[i]);
1442 } else {
1443 fprintf(stderr, "Option -%c takes one argument.\n", argv[i][1]);
1445 break;
1446 #endif /* ENABLE_NFQUEUE */
1447 case 'P':
1448 if(i+1 < argc)
1449 pidfilename = argv[++i];
1450 else
1451 fprintf(stderr, "Option -%c takes one argument.\n", argv[i][1]);
1452 break;
1453 case 'd':
1454 debug_flag = 1;
1455 break;
1456 case 'w':
1457 if(i+1 < argc)
1458 presurl = argv[++i];
1459 else
1460 fprintf(stderr, "Option -%c takes one argument.\n", argv[i][1]);
1461 break;
1462 case 'B':
1463 if(i+2<argc)
1465 downstream_bitrate = strtoul(argv[++i], 0, 0);
1466 upstream_bitrate = strtoul(argv[++i], 0, 0);
1468 else
1469 fprintf(stderr, "Option -%c takes two arguments.\n", argv[i][1]);
1470 break;
1471 case 'a':
1472 #ifndef MULTIPLE_EXTERNAL_IP
1473 if(i+1 < argc)
1475 i++;
1476 lan_addr = (struct lan_addr_s *) malloc(sizeof(struct lan_addr_s));
1477 if (lan_addr == NULL)
1479 fprintf(stderr, "malloc(sizeof(struct lan_addr_s)): %m");
1480 break;
1482 if(parselanaddr(lan_addr, argv[i]) != 0)
1484 fprintf(stderr, "can't parse \"%s\" as a valid "
1485 #ifndef ENABLE_IPV6
1486 "LAN address or "
1487 #endif /* #ifndef ENABLE_IPV6 */
1488 "interface name\n", argv[i]);
1489 free(lan_addr);
1490 break;
1492 /* check if we already have this address */
1493 for(lan_addr2 = lan_addrs.lh_first; lan_addr2 != NULL; lan_addr2 = lan_addr2->list.le_next)
1495 if (0 == strncmp(lan_addr2->str, lan_addr->str, 15))
1496 break;
1498 if (lan_addr2 == NULL)
1499 LIST_INSERT_HEAD(&lan_addrs, lan_addr, list);
1501 else
1502 fprintf(stderr, "Option -%c takes one argument.\n", argv[i][1]);
1503 #else /* #ifndef MULTIPLE_EXTERNAL_IP */
1504 if(i+2 < argc)
1506 char *val = calloc((strlen(argv[i+1]) + strlen(argv[i+2]) + 2), sizeof(char));
1507 if (val == NULL)
1509 fprintf(stderr, "memory allocation error for listen address storage\n");
1510 break;
1512 sprintf(val, "%s %s", argv[i+1], argv[i+2]);
1514 lan_addr = (struct lan_addr_s *) malloc(sizeof(struct lan_addr_s));
1515 if (lan_addr == NULL)
1517 fprintf(stderr, "malloc(sizeof(struct lan_addr_s)): %m");
1518 free(val);
1519 break;
1521 if(parselanaddr(lan_addr, val) != 0)
1523 fprintf(stderr, "can't parse \"%s\" as a valid LAN address or interface name\n", val);
1524 free(lan_addr);
1525 free(val);
1526 break;
1528 /* check if we already have this address */
1529 for(lan_addr2 = lan_addrs.lh_first; lan_addr2 != NULL; lan_addr2 = lan_addr2->list.le_next)
1531 if (0 == strncmp(lan_addr2->str, lan_addr->str, 15))
1532 break;
1534 if (lan_addr2 == NULL)
1535 LIST_INSERT_HEAD(&lan_addrs, lan_addr, list);
1537 free(val);
1538 i+=2;
1540 else
1541 fprintf(stderr, "Option -%c takes two arguments.\n", argv[i][1]);
1542 #endif /* #ifndef MULTIPLE_EXTERNAL_IP */
1543 break;
1544 case 'A':
1545 if(i+1 < argc) {
1546 void * tmp;
1547 tmp = realloc(upnppermlist, sizeof(struct upnpperm) * (num_upnpperm+1));
1548 if(tmp == NULL) {
1549 fprintf(stderr, "memory allocation error for permission\n");
1550 } else {
1551 upnppermlist = tmp;
1552 if(read_permission_line(upnppermlist + num_upnpperm, argv[++i]) >= 0) {
1553 num_upnpperm++;
1554 } else {
1555 fprintf(stderr, "Permission rule parsing error :\n%s\n", argv[i]);
1558 } else
1559 fprintf(stderr, "Option -%c takes one argument.\n", argv[i][1]);
1560 break;
1561 case 'f':
1562 i++; /* discarding, the config file is already read */
1563 break;
1564 default:
1565 fprintf(stderr, "Unknown option: %s\n", argv[i]);
1568 if(!ext_if_name || !lan_addrs.lh_first)
1570 /* bad configuration */
1571 goto print_usage;
1574 if(debug_flag)
1576 pid = getpid();
1578 else
1580 #ifdef USE_DAEMON
1581 if(daemon(0, 0)<0) {
1582 perror("daemon()");
1584 pid = getpid();
1585 #else
1586 pid = daemonize();
1587 #endif
1590 openlog_option = LOG_PID|LOG_CONS;
1591 if(debug_flag)
1593 openlog_option |= LOG_PERROR; /* also log on stderr */
1596 openlog("miniupnpd", openlog_option, LOG_MINIUPNPD);
1598 if(!debug_flag)
1600 /* speed things up and ignore LOG_INFO and LOG_DEBUG */
1601 setlogmask(LOG_UPTO(LOG_NOTICE));
1604 if(checkforrunning(pidfilename) < 0)
1606 syslog(LOG_ERR, "MiniUPnPd is already running. EXITING");
1607 return 1;
1610 #ifdef TOMATO
1611 syslog(LOG_NOTICE, "version " MINIUPNPD_VERSION " started");
1612 #endif /* TOMATO */
1614 set_startup_time(GETFLAG(SYSUPTIMEMASK));
1616 /* presentation url */
1617 if(presurl)
1619 strncpy(presentationurl, presurl, PRESENTATIONURL_MAX_LEN);
1620 presentationurl[PRESENTATIONURL_MAX_LEN-1] = '\0';
1622 else
1624 snprintf(presentationurl, PRESENTATIONURL_MAX_LEN,
1625 "http://%s/", lan_addrs.lh_first->str);
1626 /*"http://%s:%d/", lan_addrs.lh_first->str, 80);*/
1629 /* set signal handler */
1630 memset(&sa, 0, sizeof(struct sigaction));
1631 sa.sa_handler = sigterm;
1633 if(sigaction(SIGTERM, &sa, NULL) < 0)
1635 syslog(LOG_ERR, "Failed to set %s handler. EXITING", "SIGTERM");
1636 return 1;
1638 if(sigaction(SIGINT, &sa, NULL) < 0)
1640 syslog(LOG_ERR, "Failed to set %s handler. EXITING", "SIGINT");
1641 return 1;
1643 #ifdef TOMATO
1644 sa.sa_handler = sigusr2;
1645 sigaction(SIGUSR2, &sa, NULL);
1646 if(signal(SIGPIPE, SIG_IGN) == SIG_ERR)
1647 #else /* TOMATO */
1648 sa.sa_handler = SIG_IGN;
1649 if(sigaction(SIGPIPE, &sa, NULL) < 0)
1650 #endif /* TOMATO */
1652 syslog(LOG_ERR, "Failed to ignore SIGPIPE signals");
1654 sa.sa_handler = sigusr1;
1655 if(sigaction(SIGUSR1, &sa, NULL) < 0)
1657 syslog(LOG_NOTICE, "Failed to set %s handler", "SIGUSR1");
1660 /* initialize random number generator */
1661 srandom((unsigned int)time(NULL));
1663 /* initialize redirection engine (and pinholes) */
1664 if(init_redirect() < 0)
1666 syslog(LOG_ERR, "Failed to init redirection engine. EXITING");
1667 return 1;
1669 #ifdef ENABLE_UPNPPINHOLE
1670 #ifdef USE_NETFILTER
1671 init_iptpinhole();
1672 #endif
1673 #endif
1675 if(writepidfile(pidfilename, pid) < 0)
1676 pidfilename = NULL;
1678 #ifdef ENABLE_LEASEFILE
1679 /*remove(lease_file);*/
1680 syslog(LOG_INFO, "Reloading rules from lease file");
1681 reload_from_lease_file();
1682 #endif
1684 #ifdef TOMATO
1685 tomato_load();
1686 #endif /* TOMATO */
1688 return 0;
1689 print_usage:
1690 fprintf(stderr, "Usage:\n\t"
1691 "%s "
1692 #ifndef DISABLE_CONFIG_FILE
1693 "[-f config_file] "
1694 #endif
1695 "[-i ext_ifname] [-o ext_ip]\n"
1696 #ifndef MULTIPLE_EXTERNAL_IP
1697 "\t\t[-a listening_ip]"
1698 #else
1699 "\t\t[-a listening_ip ext_ip]"
1700 #endif
1701 #ifdef ENABLE_HTTPS
1702 " [-H https_port]"
1703 #endif
1704 " [-p port] [-d]"
1705 #if defined(USE_PF) || defined(USE_IPF)
1706 " [-L]"
1707 #endif
1708 " [-U] [-S]"
1709 #ifdef ENABLE_NATPMP
1710 " [-N]"
1711 #endif
1712 "\n"
1713 /*"[-l logfile] " not functionnal */
1714 "\t\t[-u uuid] [-s serial] [-m model_number] \n"
1715 "\t\t[-t notify_interval] [-P pid_filename] "
1716 #ifdef ENABLE_MANUFACTURER_INFO_CONFIGURATION
1717 "[-z fiendly_name]"
1718 #endif
1719 "\n\t\t[-B down up] [-w url] [-r clean_ruleset_interval]\n"
1720 #ifdef USE_PF
1721 "\t\t[-q queue] [-T tag]\n"
1722 #endif
1723 #ifdef ENABLE_NFQUEUE
1724 "\t\t[-Q queue] [-n name]\n"
1725 #endif
1726 "\t\t[-A \"permission rule\"] [-b BOOTID]\n"
1727 "\nNotes:\n\tThere can be one or several listening_ips.\n"
1728 "\tNotify interval is in seconds. Default is 30 seconds.\n"
1729 "\tDefault pid file is '%s'.\n"
1730 "\tDefault config file is '%s'.\n"
1731 "\tWith -d miniupnpd will run as a standard program.\n"
1732 #if defined(USE_PF) || defined(USE_IPF)
1733 "\t-L sets packet log in pf and ipf on.\n"
1734 #endif
1735 "\t-S sets \"secure\" mode : clients can only add mappings to their own ip\n"
1736 "\t-U causes miniupnpd to report system uptime instead "
1737 "of daemon uptime.\n"
1738 #ifdef ENABLE_NATPMP
1739 "\t-N enables NAT-PMP functionality.\n"
1740 #endif
1741 "\t-B sets bitrates reported by daemon in bits per second.\n"
1742 "\t-w sets the presentation url. Default is http address on port 80\n"
1743 #ifdef USE_PF
1744 "\t-q sets the ALTQ queue in pf.\n"
1745 "\t-T sets the tag name in pf.\n"
1746 #endif
1747 #ifdef ENABLE_NFQUEUE
1748 "\t-Q sets the queue number that is used by NFQUEUE.\n"
1749 "\t-n sets the name of the interface(s) that packets will arrive on.\n"
1750 #endif
1751 "\t-A use following syntax for permission rules :\n"
1752 "\t (allow|deny) (external port range) ip/mask (internal port range)\n"
1753 "\texamples :\n"
1754 "\t \"allow 1024-65535 192.168.1.0/24 1024-65535\"\n"
1755 "\t \"deny 0-65535 0.0.0.0/0 0-65535\"\n"
1756 "\t-b sets the value of BOOTID.UPNP.ORG SSDP header\n"
1757 "\t-h prints this help and quits.\n"
1758 "", argv[0], pidfilename, DEFAULT_CONFIG);
1759 return 1;
1762 /* === main === */
1763 /* process HTTP or SSDP requests */
1765 main(int argc, char * * argv)
1767 int i;
1768 int shttpl = -1; /* socket for HTTP */
1769 #if defined(V6SOCKETS_ARE_V6ONLY) && defined(ENABLE_IPV6)
1770 int shttpl_v4 = -1; /* socket for HTTP (ipv4 only) */
1771 #endif
1772 #ifdef ENABLE_HTTPS
1773 int shttpsl = -1; /* socket for HTTPS */
1774 #if defined(V6SOCKETS_ARE_V6ONLY) && defined(ENABLE_IPV6)
1775 int shttpsl_v4 = -1; /* socket for HTTPS (ipv4 only) */
1776 #endif
1777 #endif /* ENABLE_HTTPS */
1778 int sudp = -1; /* IP v4 socket for receiving SSDP */
1779 #ifdef ENABLE_IPV6
1780 int sudpv6 = -1; /* IP v6 socket for receiving SSDP */
1781 #endif
1782 #ifdef ENABLE_NATPMP
1783 int * snatpmp = NULL; /* also used for PCP */
1784 #endif
1785 #if defined(ENABLE_IPV6) && defined(ENABLE_PCP)
1786 int spcp_v6 = -1;
1787 #endif
1788 #ifdef ENABLE_NFQUEUE
1789 int nfqh = -1;
1790 #endif
1791 #ifdef USE_IFACEWATCHER
1792 int sifacewatcher = -1;
1793 #endif
1795 int * snotify = NULL;
1796 int addr_count;
1797 LIST_HEAD(httplisthead, upnphttp) upnphttphead;
1798 struct upnphttp * e = 0;
1799 struct upnphttp * next;
1800 fd_set readset; /* for select() */
1801 fd_set writeset;
1802 struct timeval timeout, timeofday, lasttimeofday = {0, 0};
1803 int max_fd = -1;
1804 #ifdef USE_MINIUPNPDCTL
1805 int sctl = -1;
1806 LIST_HEAD(ctlstructhead, ctlelem) ctllisthead;
1807 struct ctlelem * ectl;
1808 struct ctlelem * ectlnext;
1809 #endif
1810 struct runtime_vars v;
1811 /* variables used for the unused-rule cleanup process */
1812 struct rule_state * rule_list = 0;
1813 struct timeval checktime = {0, 0};
1814 struct lan_addr_s * lan_addr;
1815 #ifdef ENABLE_UPNPPINHOLE
1816 unsigned int next_pinhole_ts;
1817 #endif
1819 if(init(argc, argv, &v) != 0)
1820 return 1;
1821 #ifdef ENABLE_HTTPS
1822 if(init_ssl() < 0)
1823 return 1;
1824 #endif /* ENABLE_HTTPS */
1825 /* count lan addrs */
1826 addr_count = 0;
1827 for(lan_addr = lan_addrs.lh_first; lan_addr != NULL; lan_addr = lan_addr->list.le_next)
1828 addr_count++;
1829 if(addr_count > 0) {
1830 #ifndef ENABLE_IPV6
1831 snotify = calloc(addr_count, sizeof(int));
1832 #else
1833 /* one for IPv4, one for IPv6 */
1834 snotify = calloc(addr_count * 2, sizeof(int));
1835 #endif
1837 #ifdef ENABLE_NATPMP
1838 if(addr_count > 0) {
1839 snatpmp = malloc(addr_count * sizeof(int));
1840 for(i = 0; i < addr_count; i++)
1841 snatpmp[i] = -1;
1843 #endif
1845 LIST_INIT(&upnphttphead);
1846 #ifdef USE_MINIUPNPDCTL
1847 LIST_INIT(&ctllisthead);
1848 #endif
1851 #ifdef ENABLE_NATPMP
1852 !GETFLAG(ENABLENATPMPMASK) &&
1853 #endif
1854 !GETFLAG(ENABLEUPNPMASK) ) {
1855 syslog(LOG_ERR, "Why did you run me anyway?");
1856 return 0;
1859 syslog(LOG_INFO, "version " MINIUPNPD_VERSION " starting%s%sext if %s BOOTID=%u",
1860 #ifdef ENABLE_NATPMP
1861 #ifdef ENABLE_PCP
1862 GETFLAG(ENABLENATPMPMASK) ? " NAT-PMP/PCP " : " ",
1863 #else
1864 GETFLAG(ENABLENATPMPMASK) ? " NAT-PMP " : " ",
1865 #endif
1866 #else
1867 " ",
1868 #endif
1869 GETFLAG(ENABLEUPNPMASK) ? "UPnP-IGD " : "",
1870 ext_if_name, upnp_bootid);
1872 if(GETFLAG(ENABLEUPNPMASK))
1874 unsigned short listen_port;
1875 listen_port = (v.port > 0) ? v.port : 0;
1876 /* open socket for HTTP connections. Listen on the 1st LAN address */
1877 #ifdef ENABLE_IPV6
1878 shttpl = OpenAndConfHTTPSocket(&listen_port, 1);
1879 #else /* ENABLE_IPV6 */
1880 shttpl = OpenAndConfHTTPSocket(&listen_port);
1881 #endif /* ENABLE_IPV6 */
1882 if(shttpl < 0)
1884 syslog(LOG_ERR, "Failed to open socket for HTTP. EXITING");
1885 return 1;
1887 v.port = listen_port;
1888 syslog(LOG_NOTICE, "HTTP listening on port %d", v.port);
1889 #if defined(V6SOCKETS_ARE_V6ONLY) && defined(ENABLE_IPV6)
1890 if(!GETFLAG(IPV6DISABLEDMASK))
1892 shttpl_v4 = OpenAndConfHTTPSocket(&listen_port, 0);
1893 if(shttpl_v4 < 0)
1895 syslog(LOG_ERR, "Failed to open socket for HTTP on port %hu (IPv4). EXITING", v.port);
1896 return 1;
1899 #endif /* V6SOCKETS_ARE_V6ONLY */
1900 #ifdef ENABLE_HTTPS
1901 /* https */
1902 listen_port = (v.https_port > 0) ? v.https_port : 0;
1903 #ifdef ENABLE_IPV6
1904 shttpsl = OpenAndConfHTTPSocket(&listen_port, 1);
1905 #else /* ENABLE_IPV6 */
1906 shttpsl = OpenAndConfHTTPSocket(&listen_port);
1907 #endif /* ENABLE_IPV6 */
1908 if(shttpl < 0)
1910 syslog(LOG_ERR, "Failed to open socket for HTTPS. EXITING");
1911 return 1;
1913 v.https_port = listen_port;
1914 syslog(LOG_NOTICE, "HTTPS listening on port %d", v.https_port);
1915 #if defined(V6SOCKETS_ARE_V6ONLY) && defined(ENABLE_IPV6)
1916 shttpsl_v4 = OpenAndConfHTTPSocket(&listen_port, 0);
1917 if(shttpsl_v4 < 0)
1919 syslog(LOG_ERR, "Failed to open socket for HTTPS on port %hu (IPv4). EXITING", v.https_port);
1920 return 1;
1922 #endif /* V6SOCKETS_ARE_V6ONLY */
1923 #endif /* ENABLE_HTTPS */
1924 #ifdef ENABLE_IPV6
1925 if(find_ipv6_addr(lan_addrs.lh_first ? lan_addrs.lh_first->ifname : NULL,
1926 ipv6_addr_for_http_with_brackets, sizeof(ipv6_addr_for_http_with_brackets)) > 0) {
1927 syslog(LOG_NOTICE, "HTTP IPv6 address given to control points : %s",
1928 ipv6_addr_for_http_with_brackets);
1929 } else {
1930 memcpy(ipv6_addr_for_http_with_brackets, "[::1]", 6);
1931 syslog(LOG_WARNING, "no HTTP IPv6 address, disabling IPv6");
1932 SETFLAG(IPV6DISABLEDMASK);
1934 #endif
1936 /* open socket for SSDP connections */
1937 sudp = OpenAndConfSSDPReceiveSocket(0);
1938 if(sudp < 0)
1940 syslog(LOG_NOTICE, "Failed to open socket for receiving SSDP. Trying to use MiniSSDPd");
1941 if(SubmitServicesToMiniSSDPD(lan_addrs.lh_first->str, v.port) < 0) {
1942 syslog(LOG_ERR, "Failed to connect to MiniSSDPd. EXITING");
1943 return 1;
1946 #ifdef ENABLE_IPV6
1947 if(!GETFLAG(IPV6DISABLEDMASK))
1949 sudpv6 = OpenAndConfSSDPReceiveSocket(1);
1950 if(sudpv6 < 0)
1952 syslog(LOG_WARNING, "Failed to open socket for receiving SSDP (IP v6).");
1955 #endif
1957 /* open socket for sending notifications */
1958 if(OpenAndConfSSDPNotifySockets(snotify) < 0)
1960 syslog(LOG_ERR, "Failed to open sockets for sending SSDP notify "
1961 "messages. EXITING");
1962 return 1;
1965 #ifdef USE_IFACEWATCHER
1966 /* open socket for kernel notifications about new network interfaces */
1967 if (sudp >= 0)
1969 sifacewatcher = OpenAndConfInterfaceWatchSocket();
1970 if (sifacewatcher < 0)
1972 syslog(LOG_ERR, "Failed to open socket for receiving network interface notifications");
1975 #endif
1978 #ifdef ENABLE_NATPMP
1979 /* open socket for NAT PMP traffic */
1980 if(GETFLAG(ENABLENATPMPMASK))
1982 if(OpenAndConfNATPMPSockets(snatpmp) < 0)
1983 #ifdef ENABLE_PCP
1985 syslog(LOG_ERR, "Failed to open sockets for NAT-PMP/PCP.");
1986 } else {
1987 syslog(LOG_NOTICE, "Listening for NAT-PMP/PCP traffic on port %u",
1988 NATPMP_PORT);
1990 #else
1992 syslog(LOG_ERR, "Failed to open sockets for NAT PMP.");
1993 } else {
1994 syslog(LOG_NOTICE, "Listening for NAT-PMP traffic on port %u",
1995 NATPMP_PORT);
1997 #endif
1999 #endif
2001 #if defined(ENABLE_IPV6) && defined(ENABLE_PCP)
2002 spcp_v6 = OpenAndConfPCPv6Socket();
2003 #endif
2005 /* for miniupnpdctl */
2006 #ifdef USE_MINIUPNPDCTL
2007 sctl = OpenAndConfCtlUnixSocket("/var/run/miniupnpd.ctl");
2008 #endif
2010 #ifdef ENABLE_NFQUEUE
2011 if ( nfqueue != -1 && n_nfqix > 0) {
2012 nfqh = OpenAndConfNFqueue();
2013 if(nfqh < 0) {
2014 syslog(LOG_ERR, "Failed to open fd for NFQUEUE.");
2015 return 1;
2016 } else {
2017 syslog(LOG_NOTICE, "Opened NFQUEUE %d",nfqueue);
2020 #endif
2022 #ifdef TOMATO
2023 tomato_helper();
2024 #endif
2026 /* main loop */
2027 while(!quitting)
2029 /* Correct startup_time if it was set with a RTC close to 0 */
2030 if((startup_time<60*60*24) && (time(NULL)>60*60*24))
2032 set_startup_time(GETFLAG(SYSUPTIMEMASK));
2034 /* send public address change notifications if needed */
2035 if(should_send_public_address_change_notif)
2037 syslog(LOG_INFO, "should send external iface address change notification(s)");
2038 #ifdef ENABLE_NATPMP
2039 if(GETFLAG(ENABLENATPMPMASK))
2040 SendNATPMPPublicAddressChangeNotification(snatpmp, addr_count);
2041 #endif
2042 #ifdef ENABLE_EVENTS
2043 if(GETFLAG(ENABLEUPNPMASK))
2045 upnp_event_var_change_notify(EWanIPC);
2047 #endif
2048 should_send_public_address_change_notif = 0;
2050 /* Check if we need to send SSDP NOTIFY messages and do it if
2051 * needed */
2052 if(gettimeofday(&timeofday, 0) < 0)
2054 syslog(LOG_ERR, "gettimeofday(): %m");
2055 timeout.tv_sec = v.notify_interval;
2056 timeout.tv_usec = 0;
2058 else
2060 /* the comparaison is not very precise but who cares ? */
2061 if(timeofday.tv_sec >= (lasttimeofday.tv_sec + v.notify_interval))
2063 if (GETFLAG(ENABLEUPNPMASK))
2064 SendSSDPNotifies2(snotify,
2065 (unsigned short)v.port,
2066 #ifdef ENABLE_HTTPS
2067 (unsigned short)v.https_port,
2068 #endif
2069 v.notify_interval << 1);
2070 memcpy(&lasttimeofday, &timeofday, sizeof(struct timeval));
2071 timeout.tv_sec = v.notify_interval;
2072 timeout.tv_usec = 0;
2074 else
2076 timeout.tv_sec = lasttimeofday.tv_sec + v.notify_interval
2077 - timeofday.tv_sec;
2078 if(timeofday.tv_usec > lasttimeofday.tv_usec)
2080 timeout.tv_usec = 1000000 + lasttimeofday.tv_usec
2081 - timeofday.tv_usec;
2082 timeout.tv_sec--;
2084 else
2086 timeout.tv_usec = lasttimeofday.tv_usec - timeofday.tv_usec;
2090 /* remove unused rules */
2091 if( v.clean_ruleset_interval
2092 && (timeofday.tv_sec >= checktime.tv_sec + v.clean_ruleset_interval))
2094 if(rule_list)
2096 remove_unused_rules(rule_list);
2097 rule_list = NULL;
2099 else
2101 rule_list = get_upnp_rules_state_list(v.clean_ruleset_threshold);
2103 memcpy(&checktime, &timeofday, sizeof(struct timeval));
2105 /* Remove expired port mappings, based on UPnP IGD LeaseDuration
2106 * or NAT-PMP lifetime) */
2107 if(nextruletoclean_timestamp
2108 && ((unsigned int)timeofday.tv_sec >= nextruletoclean_timestamp))
2110 syslog(LOG_DEBUG, "cleaning expired Port Mappings");
2111 get_upnp_rules_state_list(0);
2113 if(nextruletoclean_timestamp
2114 && ((unsigned int)timeout.tv_sec >= (nextruletoclean_timestamp - timeofday.tv_sec)))
2116 timeout.tv_sec = nextruletoclean_timestamp - timeofday.tv_sec;
2117 timeout.tv_usec = 0;
2118 syslog(LOG_DEBUG, "setting timeout to %u sec",
2119 (unsigned)timeout.tv_sec);
2121 #ifdef ENABLE_UPNPPINHOLE
2122 /* Clean up expired IPv6 PinHoles */
2123 next_pinhole_ts = 0;
2124 upnp_clean_expired_pinholes(&next_pinhole_ts);
2125 if(next_pinhole_ts &&
2126 timeout.tv_sec >= (int)(next_pinhole_ts - timeofday.tv_sec)) {
2127 timeout.tv_sec = next_pinhole_ts - timeofday.tv_sec;
2128 timeout.tv_usec = 0;
2130 #endif /* ENABLE_UPNPPINHOLE */
2132 /* select open sockets (SSDP, HTTP listen, and all HTTP soap sockets) */
2133 FD_ZERO(&readset);
2134 FD_ZERO(&writeset);
2136 if (sudp >= 0)
2138 FD_SET(sudp, &readset);
2139 max_fd = MAX( max_fd, sudp);
2140 #ifdef USE_IFACEWATCHER
2141 if (sifacewatcher >= 0)
2143 FD_SET(sifacewatcher, &readset);
2144 max_fd = MAX(max_fd, sifacewatcher);
2146 #endif
2148 if (shttpl >= 0)
2150 FD_SET(shttpl, &readset);
2151 max_fd = MAX( max_fd, shttpl);
2153 #if defined(V6SOCKETS_ARE_V6ONLY) && defined(ENABLE_IPV6)
2154 if (shttpl_v4 >= 0)
2156 FD_SET(shttpl_v4, &readset);
2157 max_fd = MAX( max_fd, shttpl_v4);
2159 #endif
2160 #ifdef ENABLE_HTTPS
2161 if (shttpsl >= 0)
2163 FD_SET(shttpsl, &readset);
2164 max_fd = MAX( max_fd, shttpsl);
2166 #if defined(V6SOCKETS_ARE_V6ONLY) && defined(ENABLE_IPV6)
2167 if (shttpsl_v4 >= 0)
2169 FD_SET(shttpsl_v4, &readset);
2170 max_fd = MAX( max_fd, shttpsl_v4);
2172 #endif
2173 #endif /* ENABLE_HTTPS */
2174 #ifdef ENABLE_IPV6
2175 if (sudpv6 >= 0)
2177 FD_SET(sudpv6, &readset);
2178 max_fd = MAX( max_fd, sudpv6);
2180 #endif
2182 #ifdef ENABLE_NFQUEUE
2183 if (nfqh >= 0)
2185 FD_SET(nfqh, &readset);
2186 max_fd = MAX( max_fd, nfqh);
2188 #endif
2190 i = 0; /* active HTTP connections count */
2191 for(e = upnphttphead.lh_first; e != NULL; e = e->entries.le_next)
2193 if(e->socket >= 0)
2195 if(e->state <= EWaitingForHttpContent)
2196 FD_SET(e->socket, &readset);
2197 else if(e->state == ESendingAndClosing)
2198 FD_SET(e->socket, &writeset);
2199 else
2200 continue;
2201 max_fd = MAX(max_fd, e->socket);
2202 i++;
2205 /* for debug */
2206 #ifdef DEBUG
2207 if(i > 1)
2209 syslog(LOG_DEBUG, "%d active incoming HTTP connections", i);
2211 #endif
2212 #ifdef ENABLE_NATPMP
2213 for(i=0; i<addr_count; i++) {
2214 if(snatpmp[i] >= 0) {
2215 FD_SET(snatpmp[i], &readset);
2216 max_fd = MAX( max_fd, snatpmp[i]);
2219 #endif
2220 #if defined(ENABLE_IPV6) && defined(ENABLE_PCP)
2221 if(spcp_v6 >= 0) {
2222 FD_SET(spcp_v6, &readset);
2223 max_fd = MAX(max_fd, spcp_v6);
2225 #endif
2226 #ifdef USE_MINIUPNPDCTL
2227 if(sctl >= 0) {
2228 FD_SET(sctl, &readset);
2229 max_fd = MAX( max_fd, sctl);
2232 for(ectl = ctllisthead.lh_first; ectl; ectl = ectl->entries.le_next)
2234 if(ectl->socket >= 0) {
2235 FD_SET(ectl->socket, &readset);
2236 max_fd = MAX( max_fd, ectl->socket);
2239 #endif
2241 #ifdef ENABLE_EVENTS
2242 upnpevents_selectfds(&readset, &writeset, &max_fd);
2243 #endif
2245 /* queued "sendto" */
2247 struct timeval next_send;
2248 i = get_next_scheduled_send(&next_send);
2249 if(i > 0) {
2250 #ifdef DEBUG
2251 syslog(LOG_DEBUG, "%d queued sendto", i);
2252 #endif
2253 i = get_sendto_fds(&writeset, &max_fd, &timeofday);
2254 if(timeofday.tv_sec > next_send.tv_sec ||
2255 (timeofday.tv_sec == next_send.tv_sec && timeofday.tv_usec >= next_send.tv_usec)) {
2256 if(i > 0) {
2257 timeout.tv_sec = 0;
2258 timeout.tv_usec = 0;
2260 } else {
2261 struct timeval tmp_timeout;
2262 tmp_timeout.tv_sec = (next_send.tv_sec - timeofday.tv_sec);
2263 tmp_timeout.tv_usec = (next_send.tv_usec - timeofday.tv_usec);
2264 if(tmp_timeout.tv_usec < 0) {
2265 tmp_timeout.tv_usec += 1000000;
2266 tmp_timeout.tv_sec--;
2268 if(timeout.tv_sec > tmp_timeout.tv_sec
2269 || (timeout.tv_sec == tmp_timeout.tv_sec && timeout.tv_usec > tmp_timeout.tv_usec)) {
2270 timeout.tv_sec = tmp_timeout.tv_sec;
2271 timeout.tv_usec = tmp_timeout.tv_usec;
2277 if(select(max_fd+1, &readset, &writeset, 0, &timeout) < 0)
2279 if(quitting) goto shutdown;
2280 #ifdef TOMATO
2281 if (gotusr2)
2283 gotusr2 = 0;
2284 tomato_helper();
2285 continue;
2287 #endif /* TOMATO */
2288 if(errno == EINTR) continue; /* interrupted by a signal, start again */
2289 syslog(LOG_ERR, "select(all): %m");
2290 syslog(LOG_ERR, "Failed to select open sockets. EXITING");
2291 return 1; /* very serious cause of error */
2293 i = try_sendto(&writeset);
2294 if(i < 0) {
2295 syslog(LOG_ERR, "try_sendto failed to send %d packets", -i);
2297 #ifdef USE_MINIUPNPDCTL
2298 for(ectl = ctllisthead.lh_first; ectl;)
2300 ectlnext = ectl->entries.le_next;
2301 if((ectl->socket >= 0) && FD_ISSET(ectl->socket, &readset))
2303 char buf[256];
2304 int l;
2305 l = read(ectl->socket, buf, sizeof(buf));
2306 if(l > 0)
2308 /*write(ectl->socket, buf, l);*/
2309 write_command_line(ectl->socket, argc, argv);
2310 #ifndef DISABLE_CONFIG_FILE
2311 write_option_list(ectl->socket);
2312 #endif
2313 write_permlist(ectl->socket, upnppermlist, num_upnpperm);
2314 write_upnphttp_details(ectl->socket, upnphttphead.lh_first);
2315 write_ctlsockets_list(ectl->socket, ctllisthead.lh_first);
2316 write_ruleset_details(ectl->socket);
2317 #ifdef ENABLE_EVENTS
2318 write_events_details(ectl->socket);
2319 #endif
2320 /* close the socket */
2321 close(ectl->socket);
2322 ectl->socket = -1;
2324 else
2326 close(ectl->socket);
2327 ectl->socket = -1;
2330 if(ectl->socket < 0)
2332 LIST_REMOVE(ectl, entries);
2333 free(ectl);
2335 ectl = ectlnext;
2337 if((sctl >= 0) && FD_ISSET(sctl, &readset))
2339 int s;
2340 struct sockaddr_un clientname;
2341 struct ctlelem * tmp;
2342 socklen_t clientnamelen = sizeof(struct sockaddr_un);
2343 /*syslog(LOG_DEBUG, "sctl!");*/
2344 s = accept(sctl, (struct sockaddr *)&clientname,
2345 &clientnamelen);
2346 syslog(LOG_DEBUG, "sctl! : '%s'", clientname.sun_path);
2347 tmp = malloc(sizeof(struct ctlelem));
2348 if (tmp == NULL)
2350 syslog(LOG_ERR, "Unable to allocate memory for ctlelem in main()");
2351 close(s);
2353 else
2355 tmp->socket = s;
2356 LIST_INSERT_HEAD(&ctllisthead, tmp, entries);
2359 #endif
2360 #ifdef ENABLE_EVENTS
2361 upnpevents_processfds(&readset, &writeset);
2362 #endif
2363 #ifdef ENABLE_NATPMP
2364 /* process NAT-PMP packets */
2365 for(i=0; i<addr_count; i++)
2367 if((snatpmp[i] >= 0) && FD_ISSET(snatpmp[i], &readset))
2369 unsigned char msg_buff[PCP_MAX_LEN];
2370 struct sockaddr_in senderaddr;
2371 socklen_t senderaddrlen;
2372 int len;
2373 memset(msg_buff, 0, PCP_MAX_LEN);
2374 senderaddrlen = sizeof(senderaddr);
2375 len = ReceiveNATPMPOrPCPPacket(snatpmp[i],
2376 (struct sockaddr *)&senderaddr,
2377 &senderaddrlen,
2378 NULL,
2379 msg_buff, sizeof(msg_buff));
2380 if (len < 1)
2381 continue;
2382 #ifdef ENABLE_PCP
2383 if (msg_buff[0]==0) { /* version equals to 0 -> means NAT-PMP */
2384 /* Check if the packet is coming from a LAN to enforce RFC6886 :
2385 * The NAT gateway MUST NOT accept mapping requests destined to the NAT
2386 * gateway's external IP address or received on its external network
2387 * interface. Only packets received on the internal interface(s) with a
2388 * destination address matching the internal address(es) of the NAT
2389 * gateway should be allowed. */
2390 /* TODO : move to ProcessIncomingNATPMPPacket() ? */
2391 lan_addr = get_lan_for_peer((struct sockaddr *)&senderaddr);
2392 if(lan_addr == NULL) {
2393 char sender_str[64];
2394 sockaddr_to_string((struct sockaddr *)&senderaddr, sender_str, sizeof(sender_str));
2395 syslog(LOG_WARNING, "NAT-PMP packet sender %s not from a LAN, ignoring",
2396 sender_str);
2397 continue;
2399 ProcessIncomingNATPMPPacket(snatpmp[i], msg_buff, len,
2400 &senderaddr);
2401 } else { /* everything else can be PCP */
2402 ProcessIncomingPCPPacket(snatpmp[i], msg_buff, len,
2403 (struct sockaddr *)&senderaddr, NULL);
2406 #else
2407 /* Check if the packet is coming from a LAN to enforce RFC6886 :
2408 * The NAT gateway MUST NOT accept mapping requests destined to the NAT
2409 * gateway's external IP address or received on its external network
2410 * interface. Only packets received on the internal interface(s) with a
2411 * destination address matching the internal address(es) of the NAT
2412 * gateway should be allowed. */
2413 /* TODO : move to ProcessIncomingNATPMPPacket() ? */
2414 lan_addr = get_lan_for_peer((struct sockaddr *)&senderaddr);
2415 if(lan_addr == NULL) {
2416 char sender_str[64];
2417 sockaddr_to_string((struct sockaddr *)&senderaddr, sender_str, sizeof(sender_str));
2418 syslog(LOG_WARNING, "NAT-PMP packet sender %s not from a LAN, ignoring",
2419 sender_str);
2420 continue;
2422 ProcessIncomingNATPMPPacket(snatpmp[i], msg_buff, len, &senderaddr);
2423 #endif
2426 #endif
2427 #if defined(ENABLE_IPV6) && defined(ENABLE_PCP)
2428 /* in IPv6, only PCP is supported, not NAT-PMP */
2429 if(spcp_v6 >= 0 && FD_ISSET(spcp_v6, &readset))
2431 unsigned char msg_buff[PCP_MAX_LEN];
2432 struct sockaddr_in6 senderaddr;
2433 socklen_t senderaddrlen;
2434 struct sockaddr_in6 receiveraddr;
2435 int len;
2436 memset(msg_buff, 0, PCP_MAX_LEN);
2437 senderaddrlen = sizeof(senderaddr);
2438 len = ReceiveNATPMPOrPCPPacket(spcp_v6,
2439 (struct sockaddr *)&senderaddr,
2440 &senderaddrlen,
2441 &receiveraddr,
2442 msg_buff, sizeof(msg_buff));
2443 if(len >= 1)
2444 ProcessIncomingPCPPacket(spcp_v6, msg_buff, len,
2445 (struct sockaddr *)&senderaddr,
2446 &receiveraddr);
2448 #endif
2449 /* process SSDP packets */
2450 if(sudp >= 0 && FD_ISSET(sudp, &readset))
2452 /*syslog(LOG_INFO, "Received UDP Packet");*/
2453 #ifdef ENABLE_HTTPS
2454 ProcessSSDPRequest(sudp, (unsigned short)v.port, (unsigned short)v.https_port);
2455 #else
2456 ProcessSSDPRequest(sudp, (unsigned short)v.port);
2457 #endif
2459 #ifdef ENABLE_IPV6
2460 if(sudpv6 >= 0 && FD_ISSET(sudpv6, &readset))
2462 syslog(LOG_INFO, "Received UDP Packet (IPv6)");
2463 #ifdef ENABLE_HTTPS
2464 ProcessSSDPRequest(sudpv6, (unsigned short)v.port, (unsigned short)v.https_port);
2465 #else
2466 ProcessSSDPRequest(sudpv6, (unsigned short)v.port);
2467 #endif
2469 #endif
2470 #ifdef USE_IFACEWATCHER
2471 /* process kernel notifications */
2472 if (sifacewatcher >= 0 && FD_ISSET(sifacewatcher, &readset))
2473 ProcessInterfaceWatchNotify(sifacewatcher);
2474 #endif
2476 /* process active HTTP connections */
2477 /* LIST_FOREACH macro is not available under linux */
2478 for(e = upnphttphead.lh_first; e != NULL; e = e->entries.le_next)
2480 if(e->socket >= 0)
2482 if(FD_ISSET(e->socket, &readset) ||
2483 FD_ISSET(e->socket, &writeset))
2485 Process_upnphttp(e);
2489 /* process incoming HTTP connections */
2490 if(shttpl >= 0 && FD_ISSET(shttpl, &readset))
2492 struct upnphttp * tmp;
2493 tmp = ProcessIncomingHTTP(shttpl, "HTTP");
2494 if(tmp)
2496 LIST_INSERT_HEAD(&upnphttphead, tmp, entries);
2499 #if defined(V6SOCKETS_ARE_V6ONLY) && defined(ENABLE_IPV6)
2500 if(shttpl_v4 >= 0 && FD_ISSET(shttpl_v4, &readset))
2502 struct upnphttp * tmp;
2503 tmp = ProcessIncomingHTTP(shttpl_v4, "HTTP");
2504 if(tmp)
2506 LIST_INSERT_HEAD(&upnphttphead, tmp, entries);
2509 #endif
2510 #ifdef ENABLE_HTTPS
2511 if(shttpsl >= 0 && FD_ISSET(shttpsl, &readset))
2513 struct upnphttp * tmp;
2514 tmp = ProcessIncomingHTTP(shttpsl, "HTTPS");
2515 if(tmp)
2517 InitSSL_upnphttp(tmp);
2518 LIST_INSERT_HEAD(&upnphttphead, tmp, entries);
2521 #if defined(V6SOCKETS_ARE_V6ONLY) && defined(ENABLE_IPV6)
2522 if(shttpsl_v4 >= 0 && FD_ISSET(shttpsl_v4, &readset))
2524 struct upnphttp * tmp;
2525 tmp = ProcessIncomingHTTP(shttpsl_v4, "HTTPS");
2526 if(tmp)
2528 InitSSL_upnphttp(tmp);
2529 LIST_INSERT_HEAD(&upnphttphead, tmp, entries);
2532 #endif
2533 #endif /* ENABLE_HTTPS */
2534 #ifdef ENABLE_NFQUEUE
2535 /* process NFQ packets */
2536 if(nfqh >= 0 && FD_ISSET(nfqh, &readset))
2538 /* syslog(LOG_INFO, "Received NFQUEUE Packet");*/
2539 ProcessNFQUEUE(nfqh);
2541 #endif
2542 /* delete finished HTTP connections */
2543 for(e = upnphttphead.lh_first; e != NULL; )
2545 next = e->entries.le_next;
2546 if(e->state >= EToDelete)
2548 LIST_REMOVE(e, entries);
2549 Delete_upnphttp(e);
2551 e = next;
2554 } /* end of main loop */
2556 shutdown:
2557 syslog(LOG_NOTICE, "shutting down MiniUPnPd");
2558 /* send good-bye */
2559 if (GETFLAG(ENABLEUPNPMASK))
2561 #ifndef ENABLE_IPV6
2562 if(SendSSDPGoodbye(snotify, addr_count) < 0)
2563 #else
2564 if(SendSSDPGoodbye(snotify, addr_count * 2) < 0)
2565 #endif
2567 syslog(LOG_ERR, "Failed to broadcast good-bye notifications");
2570 /* try to send pending packets */
2571 finalize_sendto();
2573 #ifdef TOMATO
2574 tomato_save("/etc/upnp/data");
2575 #endif /* TOMATO */
2576 /* close out open sockets */
2577 while(upnphttphead.lh_first != NULL)
2579 e = upnphttphead.lh_first;
2580 LIST_REMOVE(e, entries);
2581 Delete_upnphttp(e);
2584 if (sudp >= 0) close(sudp);
2585 if (shttpl >= 0) close(shttpl);
2586 #if defined(V6SOCKETS_ARE_V6ONLY) && defined(ENABLE_IPV6)
2587 if (shttpl_v4 >= 0) close(shttpl_v4);
2588 #endif
2589 #ifdef ENABLE_IPV6
2590 if (sudpv6 >= 0) close(sudpv6);
2591 #endif
2592 #ifdef USE_IFACEWATCHER
2593 if(sifacewatcher >= 0) close(sifacewatcher);
2594 #endif
2595 #ifdef ENABLE_NATPMP
2596 for(i=0; i<addr_count; i++) {
2597 if(snatpmp[i]>=0)
2599 close(snatpmp[i]);
2600 snatpmp[i] = -1;
2603 #endif
2604 #if defined(ENABLE_IPV6) && defined(ENABLE_PCP)
2605 if(spcp_v6 >= 0)
2607 close(spcp_v6);
2608 spcp_v6 = -1;
2610 #endif
2611 #ifdef USE_MINIUPNPDCTL
2612 if(sctl>=0)
2614 close(sctl);
2615 sctl = -1;
2616 if(unlink("/var/run/miniupnpd.ctl") < 0)
2618 syslog(LOG_ERR, "unlink() %m");
2621 #endif
2623 if (GETFLAG(ENABLEUPNPMASK))
2625 #ifndef ENABLE_IPV6
2626 for(i = 0; i < addr_count; i++)
2627 #else
2628 for(i = 0; i < addr_count * 2; i++)
2629 #endif
2630 close(snotify[i]);
2633 /* remove pidfile */
2634 if(pidfilename && (unlink(pidfilename) < 0))
2636 syslog(LOG_ERR, "Failed to remove pidfile %s: %m", pidfilename);
2639 /* delete lists */
2640 while(lan_addrs.lh_first != NULL)
2642 lan_addr = lan_addrs.lh_first;
2643 LIST_REMOVE(lan_addrs.lh_first, list);
2644 free(lan_addr);
2647 #ifdef ENABLE_HTTPS
2648 free_ssl();
2649 #endif
2650 #ifdef ENABLE_NATPMP
2651 free(snatpmp);
2652 #endif
2653 free(snotify);
2654 closelog();
2655 #ifndef DISABLE_CONFIG_FILE
2656 freeoptions();
2657 #endif
2659 return 0;