Miniupnpd: update from 1.8 (20140422) to 1.9 (20141209)
[tomato.git] / release / src / router / miniupnpd / miniupnpd.c
blob3c16fd900f468e25ddf43647da48734905e9f662
1 /* $Id: miniupnpd.c,v 1.203 2014/10/30 22:15:46 nanard Exp $ */
2 /* MiniUPnP project
3 * http://miniupnp.free.fr/ or http://miniupnp.tuxfamily.org/
4 * (c) 2006-2014 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 "macros.h"
53 #include "upnpglobalvars.h"
54 #include "upnphttp.h"
55 #include "upnpdescgen.h"
56 #include "miniupnpdpath.h"
57 #include "getifaddr.h"
58 #include "upnpsoap.h"
59 #include "options.h"
60 #include "minissdp.h"
61 #include "upnpredirect.h"
62 #include "upnppinhole.h"
63 #include "miniupnpdtypes.h"
64 #include "daemonize.h"
65 #include "upnpevents.h"
66 #include "asyncsendto.h"
67 #ifdef ENABLE_NATPMP
68 #include "natpmp.h"
69 #ifdef ENABLE_PCP
70 #include "pcpserver.h"
71 #else
72 #define PCP_MAX_LEN 32
73 #endif
74 #endif
75 #include "commonrdr.h"
76 #include "upnputils.h"
77 #ifdef USE_IFACEWATCHER
78 #include "ifacewatcher.h"
79 #endif
80 #ifdef ENABLE_UPNPPINHOLE
81 #ifdef USE_NETFILTER
82 void init_iptpinhole(void);
83 #endif
84 #endif
86 #ifndef DEFAULT_CONFIG
87 #define DEFAULT_CONFIG "/etc/miniupnpd.conf"
88 #endif
90 #ifdef USE_MINIUPNPDCTL
91 struct ctlelem {
92 int socket;
93 LIST_ENTRY(ctlelem) entries;
95 #endif
97 #ifdef ENABLE_NFQUEUE
98 /* globals */
99 static struct nfq_handle *nfqHandle;
100 static struct sockaddr_in ssdp;
102 /* prototypes */
103 static int nfqueue_cb( struct nfq_q_handle *qh, struct nfgenmsg *nfmsg, struct nfq_data *nfa, void *data) ;
104 int identify_ip_protocol (char *payload);
105 int get_udp_dst_port (char *payload);
106 #endif
108 /* variables used by signals */
109 static volatile sig_atomic_t quitting = 0;
110 volatile sig_atomic_t should_send_public_address_change_notif = 0;
113 #if 1
114 static volatile int gotusr2 = 0;
116 static void sigusr2(int sig)
118 gotusr2 = 1;
121 static void tomato_save(const char *fname)
123 unsigned short eport;
124 unsigned short iport;
125 unsigned int leaseduration;
126 unsigned int timestamp;
127 char proto[4];
128 char iaddr[32];
129 char desc[64];
130 char rhost[32];
131 int n;
132 FILE *f;
133 int t;
134 char tmp[128];
136 strcpy(tmp, "/etc/upnp/saveXXXXXX");
137 if ((t = mkstemp(tmp)) != -1) {
138 if ((f = fdopen(t, "w")) != NULL) {
139 n = 0;
140 while (upnp_get_redirection_infos_by_index(n, &eport, proto, &iport, iaddr, sizeof(iaddr), desc, sizeof(desc), rhost, sizeof(rhost), &leaseduration) == 0) {
141 timestamp = (leaseduration > 0) ? time(NULL) + leaseduration : 0;
142 fprintf(f, "%s %u %s %u [%s] %u\n", proto, eport, iaddr, iport, desc, timestamp);
143 ++n;
145 fclose(f);
146 rename(tmp, fname);
148 else {
149 close(t);
151 unlink(tmp);
155 static void tomato_load(void)
157 FILE *f;
158 char s[256];
159 unsigned short eport;
160 unsigned short iport;
161 unsigned int leaseduration;
162 unsigned int timestamp;
163 time_t current_time;
164 char proto[4];
165 char iaddr[32];
166 char *rhost;
167 char *a, *b;
169 if ((f = fopen("/etc/upnp/data", "r")) != NULL) {
170 current_time = time(NULL);
171 s[sizeof(s) - 1] = 0;
172 while (fgets(s, sizeof(s) - 1, f)) {
173 if (sscanf(s, "%3s %hu %31s %hu [%*s] %u", proto, &eport, iaddr, &iport, &timestamp) >= 4) {
174 if (((a = strchr(s, '[')) != NULL) && ((b = strrchr(a, ']')) != NULL)) {
175 if (timestamp > 0) {
176 if (timestamp > current_time)
177 leaseduration = current_time - timestamp;
178 else
179 continue;
180 } else {
181 leaseduration = 0; /* default value */
183 *b = 0;
184 rhost = NULL;
185 upnp_redirect(rhost, eport, iaddr, iport, proto, a + 1, leaseduration);
189 fclose(f);
191 #ifdef ENABLE_NATPMP
192 #if 0
193 ScanNATPMPforExpiration();
194 #endif
195 #endif
196 unlink("/etc/upnp/load");
199 static void tomato_delete(void)
201 FILE *f;
202 char s[128];
203 unsigned short eport;
204 unsigned short iport;
205 unsigned int leaseduration;
206 char proto[4];
207 char iaddr[32];
208 char desc[64];
209 char rhost[32];
210 int n;
212 if ((f = fopen("/etc/upnp/delete", "r")) != NULL) {
213 s[sizeof(s) - 1] = 0;
214 while (fgets(s, sizeof(s) - 1, f)) {
215 if (sscanf(s, "%3s %hu", proto, &eport) == 2) {
216 if (proto[0] == '*') {
217 n = upnp_get_portmapping_number_of_entries();
218 while (--n >= 0) {
219 if (upnp_get_redirection_infos_by_index(n, &eport, proto, &iport, iaddr, sizeof(iaddr), desc, sizeof(desc), rhost, sizeof(rhost), &leaseduration) == 0) {
220 upnp_delete_redirection(eport, proto);
223 break;
225 else {
226 upnp_delete_redirection(eport, proto);
230 fclose(f);
231 unlink("/etc/upnp/delete");
235 static void tomato_helper(void)
237 struct stat st;
239 if (stat("/etc/upnp/delete", &st) == 0) {
240 tomato_delete();
243 if (stat("/etc/upnp/load", &st) == 0) {
244 tomato_load();
247 if (stat("/etc/upnp/save", &st) == 0) {
248 tomato_save("/etc/upnp/data");
249 unlink("/etc/upnp/save");
252 if (stat("/etc/upnp/info", &st) == 0) {
253 tomato_save("/etc/upnp/data.info");
254 unlink("/etc/upnp/info");
257 #endif /* 1 (tomato) */
260 /* OpenAndConfHTTPSocket() :
261 * setup the socket used to handle incoming HTTP connections. */
262 static int
263 #ifdef ENABLE_IPV6
264 OpenAndConfHTTPSocket(unsigned short * port, int ipv6)
265 #else
266 OpenAndConfHTTPSocket(unsigned short * port)
267 #endif
269 int s;
270 int i = 1;
271 #ifdef ENABLE_IPV6
272 struct sockaddr_in6 listenname6;
273 struct sockaddr_in listenname4;
274 #else
275 struct sockaddr_in listenname;
276 #endif
277 socklen_t listenname_len;
279 s = socket(
280 #ifdef ENABLE_IPV6
281 ipv6 ? PF_INET6 : PF_INET,
282 #else
283 PF_INET,
284 #endif
285 SOCK_STREAM, 0);
286 #ifdef ENABLE_IPV6
287 if(s < 0 && ipv6 && errno == EAFNOSUPPORT)
289 /* the system doesn't support IPV6 */
290 syslog(LOG_WARNING, "socket(PF_INET6, ...) failed with EAFNOSUPPORT, disabling IPv6");
291 SETFLAG(IPV6DISABLEDMASK);
292 ipv6 = 0;
293 s = socket(PF_INET, SOCK_STREAM, 0);
295 #endif
296 if(s < 0)
298 syslog(LOG_ERR, "socket(http): %m");
299 return -1;
302 if(setsockopt(s, SOL_SOCKET, SO_REUSEADDR, &i, sizeof(i)) < 0)
304 syslog(LOG_WARNING, "setsockopt(http, SO_REUSEADDR): %m");
306 #if 0
307 /* enable this to force IPV6 only for IPV6 socket.
308 * see http://www.ietf.org/rfc/rfc3493.txt section 5.3 */
309 if(setsockopt(s, IPPROTO_IPV6, IPV6_V6ONLY, &i, sizeof(i)) < 0)
311 syslog(LOG_WARNING, "setsockopt(http, IPV6_V6ONLY): %m");
313 #endif
315 if(!set_non_blocking(s))
317 syslog(LOG_WARNING, "set_non_blocking(http): %m");
320 #ifdef ENABLE_IPV6
321 if(ipv6)
323 memset(&listenname6, 0, sizeof(struct sockaddr_in6));
324 listenname6.sin6_family = AF_INET6;
325 listenname6.sin6_port = htons(*port);
326 listenname6.sin6_addr = ipv6_bind_addr;
327 listenname_len = sizeof(struct sockaddr_in6);
328 } else {
329 memset(&listenname4, 0, sizeof(struct sockaddr_in));
330 listenname4.sin_family = AF_INET;
331 listenname4.sin_port = htons(*port);
332 listenname4.sin_addr.s_addr = htonl(INADDR_ANY);
333 listenname_len = sizeof(struct sockaddr_in);
335 #else
336 memset(&listenname, 0, sizeof(struct sockaddr_in));
337 listenname.sin_family = AF_INET;
338 listenname.sin_port = htons(*port);
339 listenname.sin_addr.s_addr = htonl(INADDR_ANY);
340 listenname_len = sizeof(struct sockaddr_in);
341 #endif
343 #ifdef ENABLE_IPV6
344 if(bind(s,
345 ipv6 ? (struct sockaddr *)&listenname6 : (struct sockaddr *)&listenname4,
346 listenname_len) < 0)
347 #else
348 if(bind(s, (struct sockaddr *)&listenname, listenname_len) < 0)
349 #endif
351 syslog(LOG_ERR, "bind(http): %m");
352 close(s);
353 return -1;
356 if(listen(s, 5) < 0)
358 syslog(LOG_ERR, "listen(http): %m");
359 close(s);
360 return -1;
363 if(*port == 0) {
364 #ifdef ENABLE_IPV6
365 if(ipv6) {
366 struct sockaddr_in6 sockinfo;
367 socklen_t len = sizeof(struct sockaddr_in6);
368 if (getsockname(s, (struct sockaddr *)&sockinfo, &len) < 0) {
369 syslog(LOG_ERR, "getsockname(): %m");
370 } else {
371 *port = ntohs(sockinfo.sin6_port);
373 } else {
374 #endif /* ENABLE_IPV6 */
375 struct sockaddr_in sockinfo;
376 socklen_t len = sizeof(struct sockaddr_in);
377 if (getsockname(s, (struct sockaddr *)&sockinfo, &len) < 0) {
378 syslog(LOG_ERR, "getsockname(): %m");
379 } else {
380 *port = ntohs(sockinfo.sin_port);
382 #ifdef ENABLE_IPV6
384 #endif /* ENABLE_IPV6 */
386 return s;
389 static struct upnphttp *
390 ProcessIncomingHTTP(int shttpl, const char * protocol)
392 int shttp;
393 socklen_t clientnamelen;
394 #ifdef ENABLE_IPV6
395 struct sockaddr_storage clientname;
396 clientnamelen = sizeof(struct sockaddr_storage);
397 #else
398 struct sockaddr_in clientname;
399 clientnamelen = sizeof(struct sockaddr_in);
400 #endif
401 shttp = accept(shttpl, (struct sockaddr *)&clientname, &clientnamelen);
402 if(shttp<0)
404 /* ignore EAGAIN, EWOULDBLOCK, EINTR, we just try again later */
405 if(errno != EAGAIN && errno != EWOULDBLOCK && errno != EINTR)
406 syslog(LOG_ERR, "accept(http): %m");
408 else
410 struct upnphttp * tmp = 0;
411 char addr_str[64];
413 sockaddr_to_string((struct sockaddr *)&clientname, addr_str, sizeof(addr_str));
414 syslog(LOG_INFO, "%s connection from %s", protocol, addr_str);
415 if(get_lan_for_peer((struct sockaddr *)&clientname) == NULL)
417 /* The peer is not a LAN ! */
418 syslog(LOG_WARNING,
419 "%s peer %s is not from a LAN, closing the connection",
420 protocol, addr_str);
421 close(shttp);
423 else
425 /* Create a new upnphttp object and add it to
426 * the active upnphttp object list */
427 tmp = New_upnphttp(shttp);
428 if(tmp)
430 #ifdef ENABLE_IPV6
431 if(clientname.ss_family == AF_INET)
433 tmp->clientaddr = ((struct sockaddr_in *)&clientname)->sin_addr;
435 else if(clientname.ss_family == AF_INET6)
437 struct sockaddr_in6 * addr = (struct sockaddr_in6 *)&clientname;
438 if(IN6_IS_ADDR_V4MAPPED(&addr->sin6_addr))
440 memcpy(&tmp->clientaddr,
441 &addr->sin6_addr.s6_addr[12],
444 else
446 tmp->ipv6 = 1;
447 memcpy(&tmp->clientaddr_v6,
448 &addr->sin6_addr,
449 sizeof(struct in6_addr));
452 #else
453 tmp->clientaddr = clientname.sin_addr;
454 #endif
455 return tmp;
457 else
459 syslog(LOG_ERR, "New_upnphttp() failed");
460 close(shttp);
464 return NULL;
467 #ifdef ENABLE_NFQUEUE
469 int identify_ip_protocol(char *payload) {
470 return payload[9];
475 * This function returns the destination port of the captured packet UDP
477 int get_udp_dst_port(char *payload) {
478 char *pkt_data_ptr = NULL;
479 pkt_data_ptr = payload + sizeof(struct ip);
481 /* Cast the UDP Header from the raw packet */
482 struct udphdr *udp = (struct udphdr *) pkt_data_ptr;
484 /* get the dst port of the packet */
485 return(ntohs(udp->dest));
488 static int
489 OpenAndConfNFqueue(){
491 struct nfq_q_handle *myQueue;
492 struct nfnl_handle *netlinkHandle;
494 int fd = 0, e = 0;
496 inet_pton(AF_INET, "239.255.255.250", &(ssdp.sin_addr));
498 /* Get a queue connection handle from the module */
499 if (!(nfqHandle = nfq_open())) {
500 syslog(LOG_ERR, "Error in nfq_open(): %m");
501 return -1;
504 /* Unbind the handler from processing any IP packets
505 Not totally sure why this is done, or if it's necessary... */
506 if ((e = nfq_unbind_pf(nfqHandle, AF_INET)) < 0) {
507 syslog(LOG_ERR, "Error in nfq_unbind_pf(): %m");
508 return -1;
511 /* Bind this handler to process IP packets... */
512 if (nfq_bind_pf(nfqHandle, AF_INET) < 0) {
513 syslog(LOG_ERR, "Error in nfq_bind_pf(): %m");
514 return -1;
517 /* Install a callback on queue -Q */
518 if (!(myQueue = nfq_create_queue(nfqHandle, nfqueue, &nfqueue_cb, NULL))) {
519 syslog(LOG_ERR, "Error in nfq_create_queue(): %m");
520 return -1;
523 /* Turn on packet copy mode */
524 if (nfq_set_mode(myQueue, NFQNL_COPY_PACKET, 0xffff) < 0) {
525 syslog(LOG_ERR, "Error setting packet copy mode (): %m");
526 return -1;
529 netlinkHandle = nfq_nfnlh(nfqHandle);
530 fd = nfnl_fd(netlinkHandle);
532 return fd;
537 static int nfqueue_cb(
538 struct nfq_q_handle *qh,
539 struct nfgenmsg *nfmsg,
540 struct nfq_data *nfa,
541 void *data) {
543 char *pkt;
544 struct nfqnl_msg_packet_hdr *ph;
545 ph = nfq_get_msg_packet_hdr(nfa);
547 if ( ph ) {
549 int id = 0, size = 0;
550 id = ntohl(ph->packet_id);
552 size = nfq_get_payload(nfa, &pkt);
554 struct ip *iph = (struct ip *) pkt;
556 int id_protocol = identify_ip_protocol(pkt);
558 int dport = get_udp_dst_port(pkt);
560 int x = sizeof (struct ip) + sizeof (struct udphdr);
562 /* packets we are interested in are UDP multicast to 239.255.255.250:1900
563 * and start with a data string M-SEARCH
565 if ( (dport == 1900) && (id_protocol == IPPROTO_UDP)
566 && (ssdp.sin_addr.s_addr == iph->ip_dst.s_addr) ) {
568 /* get the index that the packet came in on */
569 u_int32_t idx = nfq_get_indev(nfa);
570 int i = 0;
571 for ( ;i < n_nfqix ; i++) {
572 if ( nfqix[i] == idx ) {
574 struct udphdr *udp = (struct udphdr *) (pkt + sizeof(struct ip));
576 char *dd = pkt + x;
578 struct sockaddr_in sendername;
579 sendername.sin_family = AF_INET;
580 sendername.sin_port = udp->source;
581 sendername.sin_addr.s_addr = iph->ip_src.s_addr;
583 /* printf("pkt found %s\n",dd);*/
584 ProcessSSDPData (sudp, dd, size - x,
585 &sendername, (unsigned short) 5555);
590 nfq_set_verdict(qh, id, NF_ACCEPT, 0, NULL);
592 } else {
593 syslog(LOG_ERR,"nfq_get_msg_packet_hdr failed");
594 return 1;
595 /* from nfqueue source: 0 = ok, >0 = soft error, <0 hard error */
598 return 0;
601 static void ProcessNFQUEUE(int fd){
602 char buf[4096];
604 socklen_t len_r;
605 struct sockaddr_in sendername;
606 len_r = sizeof(struct sockaddr_in);
608 int res = recvfrom(fd, buf, sizeof(buf), 0,
609 (struct sockaddr *)&sendername, &len_r);
611 nfq_handle_packet(nfqHandle, buf, res);
613 #endif
615 /* Functions used to communicate with miniupnpdctl */
616 #ifdef USE_MINIUPNPDCTL
617 static int
618 OpenAndConfCtlUnixSocket(const char * path)
620 struct sockaddr_un localun;
621 int s;
622 s = socket(AF_UNIX, SOCK_STREAM, 0);
623 localun.sun_family = AF_UNIX;
624 strncpy(localun.sun_path, path,
625 sizeof(localun.sun_path));
626 if(bind(s, (struct sockaddr *)&localun,
627 sizeof(struct sockaddr_un)) < 0)
629 syslog(LOG_ERR, "bind(sctl): %m");
630 close(s);
631 s = -1;
633 else if(listen(s, 5) < 0)
635 syslog(LOG_ERR, "listen(sctl): %m");
636 close(s);
637 s = -1;
639 return s;
642 static void
643 write_upnphttp_details(int fd, struct upnphttp * e)
645 char buffer[256];
646 int len;
647 write(fd, "HTTP :\n", 7);
648 while(e)
650 len = snprintf(buffer, sizeof(buffer),
651 "%d %d %s req_buf=%p(%dbytes) res_buf=%p(%dbytes alloc)\n",
652 e->socket, e->state, e->HttpVer,
653 e->req_buf, e->req_buflen,
654 e->res_buf, e->res_buf_alloclen);
655 write(fd, buffer, len);
656 e = e->entries.le_next;
660 static void
661 write_ctlsockets_list(int fd, struct ctlelem * e)
663 char buffer[256];
664 int len;
665 write(fd, "CTL :\n", 6);
666 while(e)
668 len = snprintf(buffer, sizeof(buffer),
669 "struct ctlelem: socket=%d\n", e->socket);
670 write(fd, buffer, len);
671 e = e->entries.le_next;
675 #ifndef DISABLE_CONFIG_FILE
676 static void
677 write_option_list(int fd)
679 char buffer[256];
680 int len;
681 unsigned int i;
682 write(fd, "Options :\n", 10);
683 for(i=0; i<num_options; i++)
685 len = snprintf(buffer, sizeof(buffer),
686 "opt=%02d %s\n",
687 ary_options[i].id, ary_options[i].value);
688 write(fd, buffer, len);
691 #endif
693 static void
694 write_command_line(int fd, int argc, char * * argv)
696 char buffer[256];
697 int len;
698 int i;
699 write(fd, "Command Line :\n", 15);
700 for(i=0; i<argc; i++)
702 len = snprintf(buffer, sizeof(buffer),
703 "argv[%02d]='%s'\n",
704 i, argv[i]);
705 write(fd, buffer, len);
709 #endif
711 /* Handler for the SIGTERM signal (kill)
712 * SIGINT is also handled */
713 static void
714 sigterm(int sig)
716 UNUSED(sig);
717 /*int save_errno = errno; */
718 /*signal(sig, SIG_IGN);*/ /* Ignore this signal while we are quitting */
719 /* Note : isn't it useless ? */
721 #if 0
722 /* calling syslog() is forbidden in signal handler according to
723 * signal(3) */
724 syslog(LOG_NOTICE, "received signal %d, good-bye", sig);
725 #endif
727 quitting = 1;
728 /*errno = save_errno;*/
731 /* Handler for the SIGUSR1 signal indicating public IP address change. */
732 static void
733 sigusr1(int sig)
735 UNUSED(sig);
736 #if 0
737 /* calling syslog() is forbidden in signal handler according to
738 * signal(3) */
739 syslog(LOG_INFO, "received signal %d, public ip address change", sig);
740 #endif
742 should_send_public_address_change_notif = 1;
745 /* record the startup time, for returning uptime */
746 static void
747 set_startup_time(int sysuptime)
749 startup_time = time(NULL);
750 if(sysuptime)
752 /* use system uptime instead of daemon uptime */
753 #if defined(__linux__)
754 char buff[64];
755 int uptime = 0, fd;
756 fd = open("/proc/uptime", O_RDONLY);
757 if(fd < 0)
759 syslog(LOG_ERR, "open(\"/proc/uptime\" : %m");
761 else
763 memset(buff, 0, sizeof(buff));
764 if(read(fd, buff, sizeof(buff) - 1) < 0)
766 syslog(LOG_ERR, "read(\"/proc/uptime\" : %m");
768 else
770 uptime = atoi(buff);
771 syslog(LOG_INFO, "system uptime is %d seconds", uptime);
773 close(fd);
774 startup_time -= uptime;
776 #elif defined(SOLARIS_KSTATS)
777 kstat_ctl_t *kc;
778 kc = kstat_open();
779 if(kc != NULL)
781 kstat_t *ksp;
782 ksp = kstat_lookup(kc, "unix", 0, "system_misc");
783 if(ksp && (kstat_read(kc, ksp, NULL) != -1))
785 void *ptr = kstat_data_lookup(ksp, "boot_time");
786 if(ptr)
787 memcpy(&startup_time, ptr, sizeof(startup_time));
788 else
789 syslog(LOG_ERR, "cannot find boot_time kstat");
791 else
792 syslog(LOG_ERR, "cannot open kstats for unix/0/system_misc: %m");
793 kstat_close(kc);
795 #else
796 struct timeval boottime;
797 size_t size = sizeof(boottime);
798 int name[2] = { CTL_KERN, KERN_BOOTTIME };
799 if(sysctl(name, 2, &boottime, &size, NULL, 0) < 0)
801 syslog(LOG_ERR, "sysctl(\"kern.boottime\") failed");
803 else
805 startup_time = boottime.tv_sec;
807 #endif
811 /* structure containing variables used during "main loop"
812 * that are filled during the init */
813 struct runtime_vars {
814 /* LAN IP addresses for SSDP traffic and HTTP */
815 /* moved to global vars */
816 int port; /* HTTP Port */
817 #ifdef ENABLE_HTTPS
818 int https_port; /* HTTPS Port */
819 #endif
820 int notify_interval; /* seconds between SSDP announces */
821 /* unused rules cleaning related variables : */
822 int clean_ruleset_threshold; /* threshold for removing unused rules */
823 int clean_ruleset_interval; /* (minimum) interval between checks */
826 /* parselanaddr()
827 * parse address with mask
828 * ex: 192.168.1.1/24 or 192.168.1.1/255.255.255.0
829 * When MULTIPLE_EXTERNAL_IP is enabled, the ip address of the
830 * external interface associated with the lan subnet follows.
831 * ex : 192.168.1.1/24 81.21.41.11
833 * Can also use the interface name (ie eth0)
835 * return value :
836 * 0 : ok
837 * -1 : error */
838 static int
839 parselanaddr(struct lan_addr_s * lan_addr, const char * str)
841 const char * p;
842 int n;
843 char tmp[16];
845 memset(lan_addr, 0, sizeof(struct lan_addr_s));
846 p = str;
847 while(*p && *p != '/' && !isspace(*p))
848 p++;
849 n = p - str;
850 if(!isdigit(str[0]) && n < (int)sizeof(lan_addr->ifname))
852 /* not starting with a digit : suppose it is an interface name */
853 memcpy(lan_addr->ifname, str, n);
854 lan_addr->ifname[n] = '\0';
855 if(getifaddr(lan_addr->ifname, lan_addr->str, sizeof(lan_addr->str),
856 &lan_addr->addr, &lan_addr->mask) < 0)
857 goto parselan_error;
858 /*printf("%s => %s\n", lan_addr->ifname, lan_addr->str);*/
860 else
862 if(n>15)
863 goto parselan_error;
864 memcpy(lan_addr->str, str, n);
865 lan_addr->str[n] = '\0';
866 if(!inet_aton(lan_addr->str, &lan_addr->addr))
867 goto parselan_error;
869 if(*p == '/')
871 const char * q = ++p;
872 while(*p && isdigit(*p))
873 p++;
874 if(*p=='.')
876 /* parse mask in /255.255.255.0 format */
877 while(*p && (*p=='.' || isdigit(*p)))
878 p++;
879 n = p - q;
880 if(n>15)
881 goto parselan_error;
882 memcpy(tmp, q, n);
883 tmp[n] = '\0';
884 if(!inet_aton(tmp, &lan_addr->mask))
885 goto parselan_error;
887 else
889 /* it is a /24 format */
890 int nbits = atoi(q);
891 if(nbits > 32 || nbits < 0)
892 goto parselan_error;
893 lan_addr->mask.s_addr = htonl(nbits ? (0xffffffffu << (32 - nbits)) : 0);
896 else if(lan_addr->mask.s_addr == 0)
898 /* by default, networks are /24 */
899 lan_addr->mask.s_addr = htonl(0xffffff00u);
901 #ifdef MULTIPLE_EXTERNAL_IP
902 /* skip spaces */
903 while(*p && isspace(*p))
904 p++;
905 if(*p) {
906 /* parse the exteral ip address to associate with this subnet */
907 n = 0;
908 while(p[n] && !isspace(*p))
909 n++;
910 if(n<=15) {
911 memcpy(lan_addr->ext_ip_str, p, n);
912 lan_addr->ext_ip_str[n] = '\0';
913 if(!inet_aton(lan_addr->ext_ip_str, &lan_addr->ext_ip_addr)) {
914 /* error */
915 fprintf(stderr, "Error parsing address : %s\n", lan_addr->ext_ip_str);
919 #endif
920 #ifdef ENABLE_IPV6
921 if(lan_addr->ifname[0] != '\0')
923 lan_addr->index = if_nametoindex(lan_addr->ifname);
924 if(lan_addr->index == 0)
925 fprintf(stderr, "Cannot get index for network interface %s",
926 lan_addr->ifname);
928 else
930 fprintf(stderr,
931 "Error: please specify LAN network interface by name instead of IPv4 address : %s\n",
932 str);
933 return -1;
935 #endif
936 return 0;
937 parselan_error:
938 fprintf(stderr, "Error parsing address/mask (or interface name) : %s\n",
939 str);
940 return -1;
943 /* fill uuidvalue_wan and uuidvalue_wcd based on uuidvalue_igd */
944 void complete_uuidvalues(void)
946 size_t len;
947 len = strlen(uuidvalue_igd);
948 memcpy(uuidvalue_wan, uuidvalue_igd, len+1);
949 switch(uuidvalue_wan[len-1]) {
950 case '9':
951 uuidvalue_wan[len-1] = 'a';
952 break;
953 case 'f':
954 uuidvalue_wan[len-1] = '0';
955 break;
956 default:
957 uuidvalue_wan[len-1]++;
959 memcpy(uuidvalue_wcd, uuidvalue_wan, len+1);
960 switch(uuidvalue_wcd[len-1]) {
961 case '9':
962 uuidvalue_wcd[len-1] = 'a';
963 break;
964 case 'f':
965 uuidvalue_wcd[len-1] = '0';
966 break;
967 default:
968 uuidvalue_wcd[len-1]++;
972 /* init phase :
973 * 1) read configuration file
974 * 2) read command line arguments
975 * 3) daemonize
976 * 4) open syslog
977 * 5) check and write pid file
978 * 6) set startup time stamp
979 * 7) compute presentation URL
980 * 8) set signal handlers
981 * 9) init random generator (srandom())
982 * 10) init redirection engine
983 * 11) reload mapping from leasefile */
984 static int
985 init(int argc, char * * argv, struct runtime_vars * v)
987 int i;
988 int pid;
989 int debug_flag = 0;
990 int openlog_option;
991 struct sigaction sa;
992 /*const char * logfilename = 0;*/
993 const char * presurl = 0;
994 #ifndef DISABLE_CONFIG_FILE
995 int options_flag = 0;
996 const char * optionsfile = DEFAULT_CONFIG;
997 #endif /* DISABLE_CONFIG_FILE */
998 struct lan_addr_s * lan_addr;
999 struct lan_addr_s * lan_addr2;
1001 /* only print usage if -h is used */
1002 for(i=1; i<argc; i++)
1004 if(0 == strcmp(argv[i], "-h"))
1005 goto print_usage;
1007 #ifndef DISABLE_CONFIG_FILE
1008 /* first check if "-f" option is used */
1009 for(i=2; i<argc; i++)
1011 if(0 == strcmp(argv[i-1], "-f"))
1013 optionsfile = argv[i];
1014 options_flag = 1;
1015 break;
1018 #endif /* DISABLE_CONFIG_FILE */
1020 /* set initial values */
1021 SETFLAG(ENABLEUPNPMASK); /* UPnP is enabled by default */
1022 #ifdef ENABLE_IPV6
1023 ipv6_bind_addr = in6addr_any;
1024 #endif /* ENABLE_IPV6 */
1026 LIST_INIT(&lan_addrs);
1027 v->port = -1;
1028 #ifdef ENABLE_HTTPS
1029 v->https_port = -1;
1030 #endif
1031 v->notify_interval = 30; /* seconds between SSDP announces */
1032 v->clean_ruleset_threshold = 20;
1033 v->clean_ruleset_interval = 0; /* interval between ruleset check. 0=disabled */
1034 #ifndef DISABLE_CONFIG_FILE
1035 /* read options file first since
1036 * command line arguments have final say */
1037 if(readoptionsfile(optionsfile) < 0)
1039 /* only error if file exists or using -f */
1040 if(access(optionsfile, F_OK) == 0 || options_flag)
1041 fprintf(stderr, "Error reading configuration file %s\n", optionsfile);
1043 else
1045 for(i=0; i<(int)num_options; i++)
1047 switch(ary_options[i].id)
1049 case UPNPEXT_IFNAME:
1050 ext_if_name = ary_options[i].value;
1051 break;
1052 case UPNPEXT_IP:
1053 use_ext_ip_addr = ary_options[i].value;
1054 break;
1055 case UPNPLISTENING_IP:
1056 lan_addr = (struct lan_addr_s *) malloc(sizeof(struct lan_addr_s));
1057 if (lan_addr == NULL)
1059 fprintf(stderr, "malloc(sizeof(struct lan_addr_s)): %m");
1060 break;
1062 if(parselanaddr(lan_addr, ary_options[i].value) != 0)
1064 fprintf(stderr, "can't parse \"%s\" as a valid "
1065 #ifndef ENABLE_IPV6
1066 "LAN address or "
1067 #endif
1068 "interface name\n", ary_options[i].value);
1069 free(lan_addr);
1070 break;
1072 LIST_INSERT_HEAD(&lan_addrs, lan_addr, list);
1073 break;
1074 #ifdef ENABLE_IPV6
1075 case UPNPIPV6_LISTENING_IP:
1076 if (inet_pton(AF_INET6, ary_options[i].value, &ipv6_bind_addr) < 1)
1078 fprintf(stderr, "can't parse \"%s\" as valid IPv6 listening address", ary_options[i].value);
1080 break;
1081 #endif /* ENABLE_IPV6 */
1082 case UPNPPORT:
1083 v->port = atoi(ary_options[i].value);
1084 break;
1085 #ifdef ENABLE_HTTPS
1086 case UPNPHTTPSPORT:
1087 v->https_port = atoi(ary_options[i].value);
1088 break;
1089 #endif
1090 case UPNPBITRATE_UP:
1091 upstream_bitrate = strtoul(ary_options[i].value, 0, 0);
1092 break;
1093 case UPNPBITRATE_DOWN:
1094 downstream_bitrate = strtoul(ary_options[i].value, 0, 0);
1095 break;
1096 case UPNPPRESENTATIONURL:
1097 presurl = ary_options[i].value;
1098 break;
1099 #ifdef ENABLE_MANUFACTURER_INFO_CONFIGURATION
1100 case UPNPFRIENDLY_NAME:
1101 strncpy(friendly_name, ary_options[i].value, FRIENDLY_NAME_MAX_LEN);
1102 friendly_name[FRIENDLY_NAME_MAX_LEN-1] = '\0';
1103 break;
1104 case UPNPMANUFACTURER_NAME:
1105 strncpy(manufacturer_name, ary_options[i].value, MANUFACTURER_NAME_MAX_LEN);
1106 manufacturer_name[MANUFACTURER_NAME_MAX_LEN-1] = '\0';
1107 break;
1108 case UPNPMANUFACTURER_URL:
1109 strncpy(manufacturer_url, ary_options[i].value, MANUFACTURER_URL_MAX_LEN);
1110 manufacturer_url[MANUFACTURER_URL_MAX_LEN-1] = '\0';
1111 break;
1112 case UPNPMODEL_NAME:
1113 strncpy(model_name, ary_options[i].value, MODEL_NAME_MAX_LEN);
1114 model_name[MODEL_NAME_MAX_LEN-1] = '\0';
1115 break;
1116 case UPNPMODEL_DESCRIPTION:
1117 strncpy(model_description, ary_options[i].value, MODEL_DESCRIPTION_MAX_LEN);
1118 model_description[MODEL_DESCRIPTION_MAX_LEN-1] = '\0';
1119 break;
1120 case UPNPMODEL_URL:
1121 strncpy(model_url, ary_options[i].value, MODEL_URL_MAX_LEN);
1122 model_url[MODEL_URL_MAX_LEN-1] = '\0';
1123 break;
1124 #endif
1125 #ifdef USE_NETFILTER
1126 case UPNPFORWARDCHAIN:
1127 miniupnpd_forward_chain = ary_options[i].value;
1128 break;
1129 case UPNPNATCHAIN:
1130 miniupnpd_nat_chain = ary_options[i].value;
1131 break;
1132 #endif
1133 case UPNPNOTIFY_INTERVAL:
1134 v->notify_interval = atoi(ary_options[i].value);
1135 break;
1136 case UPNPSYSTEM_UPTIME:
1137 if(strcmp(ary_options[i].value, "yes") == 0)
1138 SETFLAG(SYSUPTIMEMASK); /*sysuptime = 1;*/
1139 break;
1140 #if defined(USE_PF) || defined(USE_IPF)
1141 case UPNPPACKET_LOG:
1142 if(strcmp(ary_options[i].value, "yes") == 0)
1143 SETFLAG(LOGPACKETSMASK); /*logpackets = 1;*/
1144 break;
1145 #endif
1146 case UPNPUUID:
1147 strncpy(uuidvalue_igd+5, ary_options[i].value,
1148 strlen(uuidvalue_igd+5) + 1);
1149 complete_uuidvalues();
1150 break;
1151 case UPNPSERIAL:
1152 strncpy(serialnumber, ary_options[i].value, SERIALNUMBER_MAX_LEN);
1153 serialnumber[SERIALNUMBER_MAX_LEN-1] = '\0';
1154 break;
1155 case UPNPMODEL_NUMBER:
1156 strncpy(modelnumber, ary_options[i].value, MODELNUMBER_MAX_LEN);
1157 modelnumber[MODELNUMBER_MAX_LEN-1] = '\0';
1158 break;
1159 case UPNPCLEANTHRESHOLD:
1160 v->clean_ruleset_threshold = atoi(ary_options[i].value);
1161 break;
1162 case UPNPCLEANINTERVAL:
1163 v->clean_ruleset_interval = atoi(ary_options[i].value);
1164 break;
1165 #ifdef USE_PF
1166 case UPNPANCHOR:
1167 anchor_name = ary_options[i].value;
1168 break;
1169 case UPNPQUEUE:
1170 queue = ary_options[i].value;
1171 break;
1172 case UPNPTAG:
1173 tag = ary_options[i].value;
1174 break;
1175 #endif
1176 #ifdef ENABLE_NATPMP
1177 case UPNPENABLENATPMP:
1178 if(strcmp(ary_options[i].value, "yes") == 0)
1179 SETFLAG(ENABLENATPMPMASK); /*enablenatpmp = 1;*/
1180 else
1181 if(atoi(ary_options[i].value))
1182 SETFLAG(ENABLENATPMPMASK);
1183 /*enablenatpmp = atoi(ary_options[i].value);*/
1184 break;
1185 #endif
1186 #ifdef ENABLE_PCP
1187 case UPNPPCPMINLIFETIME:
1188 min_lifetime = atoi(ary_options[i].value);
1189 if (min_lifetime > 120 ) {
1190 min_lifetime = 120;
1192 break;
1193 case UPNPPCPMAXLIFETIME:
1194 max_lifetime = atoi(ary_options[i].value);
1195 if (max_lifetime > 86400 ) {
1196 max_lifetime = 86400;
1198 break;
1199 case UPNPPCPALLOWTHIRDPARTY:
1200 if(strcmp(ary_options[i].value, "yes") == 0)
1201 SETFLAG(PCP_ALLOWTHIRDPARTYMASK);
1202 break;
1203 #endif
1204 #ifdef PF_ENABLE_FILTER_RULES
1205 case UPNPQUICKRULES:
1206 if(strcmp(ary_options[i].value, "no") == 0)
1207 SETFLAG(PFNOQUICKRULESMASK);
1208 break;
1209 #endif
1210 case UPNPENABLE:
1211 if(strcmp(ary_options[i].value, "yes") != 0)
1212 CLEARFLAG(ENABLEUPNPMASK);
1213 break;
1214 case UPNPSECUREMODE:
1215 if(strcmp(ary_options[i].value, "yes") == 0)
1216 SETFLAG(SECUREMODEMASK);
1217 break;
1218 #ifdef ENABLE_LEASEFILE
1219 case UPNPLEASEFILE:
1220 lease_file = ary_options[i].value;
1221 break;
1222 #endif
1223 case UPNPMINISSDPDSOCKET:
1224 minissdpdsocketpath = ary_options[i].value;
1225 break;
1226 default:
1227 fprintf(stderr, "Unknown option in file %s\n",
1228 optionsfile);
1231 #ifdef ENABLE_PCP
1232 /* if lifetimes are inverse */
1233 if (min_lifetime >= max_lifetime) {
1234 fprintf(stderr, "Minimum lifetime (%lu) is greater than or equal to maximum lifetime (%lu).\n", min_lifetime, max_lifetime);
1235 fprintf(stderr, "Check your configuration file.\n");
1236 return 1;
1238 #endif
1240 #endif /* DISABLE_CONFIG_FILE */
1242 /* command line arguments processing */
1243 for(i=1; i<argc; i++)
1245 if(argv[i][0]!='-')
1247 fprintf(stderr, "Unknown option: %s\n", argv[i]);
1249 else switch(argv[i][1])
1251 case 'o':
1252 if(i+1 < argc)
1253 use_ext_ip_addr = argv[++i];
1254 else
1255 fprintf(stderr, "Option -%c takes one argument.\n", argv[i][1]);
1256 break;
1257 case 't':
1258 if(i+1 < argc)
1259 v->notify_interval = atoi(argv[++i]);
1260 else
1261 fprintf(stderr, "Option -%c takes one argument.\n", argv[i][1]);
1262 break;
1263 case 'r':
1264 if(i+1 < argc)
1265 v->clean_ruleset_interval = atoi(argv[++i]);
1266 else
1267 fprintf(stderr, "Option -%c takes one argument.\n", argv[i][1]);
1268 break;
1269 case 'u':
1270 if(i+1 < argc) {
1271 strncpy(uuidvalue_igd+5, argv[++i], strlen(uuidvalue_igd+5) + 1);
1272 complete_uuidvalues();
1273 } else
1274 fprintf(stderr, "Option -%c takes one argument.\n", argv[i][1]);
1275 break;
1276 #ifdef ENABLE_MANUFACTURER_INFO_CONFIGURATION
1277 case 'z':
1278 if(i+1 < argc)
1279 strncpy(friendly_name, argv[++i], FRIENDLY_NAME_MAX_LEN);
1280 else
1281 fprintf(stderr, "Option -%c takes one argument.\n", argv[i][1]);
1282 friendly_name[FRIENDLY_NAME_MAX_LEN-1] = '\0';
1283 break;
1284 #endif
1285 case 's':
1286 if(i+1 < argc)
1287 strncpy(serialnumber, argv[++i], SERIALNUMBER_MAX_LEN);
1288 else
1289 fprintf(stderr, "Option -%c takes one argument.\n", argv[i][1]);
1290 serialnumber[SERIALNUMBER_MAX_LEN-1] = '\0';
1291 break;
1292 case 'm':
1293 if(i+1 < argc)
1294 strncpy(modelnumber, argv[++i], MODELNUMBER_MAX_LEN);
1295 else
1296 fprintf(stderr, "Option -%c takes one argument.\n", argv[i][1]);
1297 modelnumber[MODELNUMBER_MAX_LEN-1] = '\0';
1298 break;
1299 #ifdef ENABLE_NATPMP
1300 case 'N':
1301 /*enablenatpmp = 1;*/
1302 SETFLAG(ENABLENATPMPMASK);
1303 break;
1304 #endif
1305 case 'U':
1306 /*sysuptime = 1;*/
1307 SETFLAG(SYSUPTIMEMASK);
1308 break;
1309 /*case 'l':
1310 logfilename = argv[++i];
1311 break;*/
1312 #if defined(USE_PF) || defined(USE_IPF)
1313 case 'L':
1314 /*logpackets = 1;*/
1315 SETFLAG(LOGPACKETSMASK);
1316 break;
1317 #endif
1318 case 'S':
1319 SETFLAG(SECUREMODEMASK);
1320 break;
1321 case 'i':
1322 if(i+1 < argc)
1323 ext_if_name = argv[++i];
1324 else
1325 fprintf(stderr, "Option -%c takes one argument.\n", argv[i][1]);
1326 break;
1327 #ifdef USE_PF
1328 case 'q':
1329 if(i+1 < argc)
1330 queue = argv[++i];
1331 else
1332 fprintf(stderr, "Option -%c takes one argument.\n", argv[i][1]);
1333 break;
1334 case 'T':
1335 if(i+1 < argc)
1336 tag = argv[++i];
1337 else
1338 fprintf(stderr, "Option -%c takes one argument.\n", argv[i][1]);
1339 break;
1340 #endif
1341 case 'p':
1342 if(i+1 < argc)
1343 v->port = atoi(argv[++i]);
1344 else
1345 fprintf(stderr, "Option -%c takes one argument.\n", argv[i][1]);
1346 break;
1347 #ifdef ENABLE_HTTPS
1348 case 'H':
1349 if(i+1 < argc)
1350 v->https_port = atoi(argv[++i]);
1351 else
1352 fprintf(stderr, "Option -%c takes one argument.\n", argv[i][1]);
1353 break;
1354 #endif
1355 #ifdef ENABLE_NFQUEUE
1356 case 'Q':
1357 if(i+1<argc)
1359 nfqueue = atoi(argv[++i]);
1361 else
1362 fprintf(stderr, "Option -%c takes one argument.\n", argv[i][1]);
1363 break;
1364 case 'n':
1365 if (i+1 < argc) {
1366 i++;
1367 if(n_nfqix < MAX_LAN_ADDR) {
1368 nfqix[n_nfqix++] = if_nametoindex(argv[i]);
1369 } else {
1370 fprintf(stderr,"Too many nfq interfaces. Ignoring %s\n", argv[i]);
1372 } else {
1373 fprintf(stderr, "Option -%c takes one argument.\n", argv[i][1]);
1375 break;
1376 #endif
1377 case 'P':
1378 if(i+1 < argc)
1379 pidfilename = argv[++i];
1380 else
1381 fprintf(stderr, "Option -%c takes one argument.\n", argv[i][1]);
1382 break;
1383 case 'd':
1384 debug_flag = 1;
1385 break;
1386 case 'w':
1387 if(i+1 < argc)
1388 presurl = argv[++i];
1389 else
1390 fprintf(stderr, "Option -%c takes one argument.\n", argv[i][1]);
1391 break;
1392 case 'B':
1393 if(i+2<argc)
1395 downstream_bitrate = strtoul(argv[++i], 0, 0);
1396 upstream_bitrate = strtoul(argv[++i], 0, 0);
1398 else
1399 fprintf(stderr, "Option -%c takes two arguments.\n", argv[i][1]);
1400 break;
1401 case 'a':
1402 #ifndef MULTIPLE_EXTERNAL_IP
1403 if(i+1 < argc)
1405 i++;
1406 lan_addr = (struct lan_addr_s *) malloc(sizeof(struct lan_addr_s));
1407 if (lan_addr == NULL)
1409 fprintf(stderr, "malloc(sizeof(struct lan_addr_s)): %m");
1410 break;
1412 if(parselanaddr(lan_addr, argv[i]) != 0)
1414 fprintf(stderr, "can't parse \"%s\" as a valid "
1415 #ifndef ENABLE_IPV6
1416 "LAN address or "
1417 #endif
1418 "interface name\n", argv[i]);
1419 free(lan_addr);
1420 break;
1422 /* check if we already have this address */
1423 for(lan_addr2 = lan_addrs.lh_first; lan_addr2 != NULL; lan_addr2 = lan_addr2->list.le_next)
1425 if (0 == strncmp(lan_addr2->str, lan_addr->str, 15))
1426 break;
1428 if (lan_addr2 == NULL)
1429 LIST_INSERT_HEAD(&lan_addrs, lan_addr, list);
1431 else
1432 fprintf(stderr, "Option -%c takes one argument.\n", argv[i][1]);
1433 #else
1434 if(i+2 < argc)
1436 char *val=calloc((strlen(argv[i+1]) + strlen(argv[i+2]) + 1), sizeof(char));
1437 if (val == NULL)
1439 fprintf(stderr, "memory allocation error for listen address storage\n");
1440 break;
1442 sprintf(val, "%s %s", argv[i+1], argv[i+2]);
1444 lan_addr = (struct lan_addr_s *) malloc(sizeof(struct lan_addr_s));
1445 if (lan_addr == NULL)
1447 fprintf(stderr, "malloc(sizeof(struct lan_addr_s)): %m");
1448 free(val);
1449 break;
1451 if(parselanaddr(lan_addr, val) != 0)
1453 fprintf(stderr, "can't parse \"%s\" as a valid LAN address or interface name\n", val);
1454 free(lan_addr);
1455 free(val);
1456 break;
1458 /* check if we already have this address */
1459 for(lan_addr2 = lan_addrs.lh_first; lan_addr2 != NULL; lan_addr2 = lan_addr2->list.le_next)
1461 if (0 == strncmp(lan_addr2->str, lan_addr->str, 15))
1462 break;
1464 if (lan_addr2 == NULL)
1465 LIST_INSERT_HEAD(&lan_addrs, lan_addr, list);
1467 free(val);
1468 i+=2;
1470 else
1471 fprintf(stderr, "Option -%c takes two arguments.\n", argv[i][1]);
1472 #endif
1473 break;
1474 case 'A':
1475 if(i+1 < argc) {
1476 void * tmp;
1477 tmp = realloc(upnppermlist, sizeof(struct upnpperm) * (num_upnpperm+1));
1478 if(tmp == NULL) {
1479 fprintf(stderr, "memory allocation error for permission\n");
1480 } else {
1481 upnppermlist = tmp;
1482 if(read_permission_line(upnppermlist + num_upnpperm, argv[++i]) >= 0) {
1483 num_upnpperm++;
1484 } else {
1485 fprintf(stderr, "Permission rule parsing error :\n%s\n", argv[i]);
1488 } else
1489 fprintf(stderr, "Option -%c takes one argument.\n", argv[i][1]);
1490 break;
1491 case 'f':
1492 i++; /* discarding, the config file is already read */
1493 break;
1494 default:
1495 fprintf(stderr, "Unknown option: %s\n", argv[i]);
1498 if(!ext_if_name || !lan_addrs.lh_first)
1500 /* bad configuration */
1501 goto print_usage;
1504 if(debug_flag)
1506 pid = getpid();
1508 else
1510 #ifdef USE_DAEMON
1511 if(daemon(0, 0)<0) {
1512 perror("daemon()");
1514 pid = getpid();
1515 #else
1516 pid = daemonize();
1517 #endif
1520 openlog_option = LOG_PID|LOG_CONS;
1521 if(debug_flag)
1523 openlog_option |= LOG_PERROR; /* also log on stderr */
1526 openlog("miniupnpd", openlog_option, LOG_MINIUPNPD);
1528 if(!debug_flag)
1530 /* speed things up and ignore LOG_INFO and LOG_DEBUG */
1531 setlogmask(LOG_UPTO(LOG_NOTICE));
1534 if(checkforrunning(pidfilename) < 0)
1536 syslog(LOG_ERR, "MiniUPnPd is already running. EXITING");
1537 return 1;
1540 syslog(LOG_NOTICE, "version " MINIUPNPD_VERSION " started");
1542 set_startup_time(GETFLAG(SYSUPTIMEMASK));
1544 /* presentation url */
1545 if(presurl)
1547 strncpy(presentationurl, presurl, PRESENTATIONURL_MAX_LEN);
1548 presentationurl[PRESENTATIONURL_MAX_LEN-1] = '\0';
1550 else
1552 snprintf(presentationurl, PRESENTATIONURL_MAX_LEN,
1553 "http://%s/", lan_addrs.lh_first->str);
1554 /*"http://%s:%d/", lan_addrs.lh_first->str, 80);*/
1557 /* set signal handler */
1558 memset(&sa, 0, sizeof(struct sigaction));
1559 sa.sa_handler = sigterm;
1561 if(sigaction(SIGTERM, &sa, NULL) < 0)
1563 syslog(LOG_ERR, "Failed to set %s handler. EXITING", "SIGTERM");
1564 return 1;
1566 if(sigaction(SIGINT, &sa, NULL) < 0)
1568 syslog(LOG_ERR, "Failed to set %s handler. EXITING", "SIGINT");
1569 return 1;
1572 // zzz
1573 sa.sa_handler = sigusr2;
1574 sigaction(SIGUSR2, &sa, NULL);
1576 if(signal(SIGPIPE, SIG_IGN) == SIG_ERR)
1578 syslog(LOG_ERR, "Failed to ignore SIGPIPE signals");
1581 sa.sa_handler = sigusr1;
1582 if(sigaction(SIGUSR1, &sa, NULL) < 0)
1584 syslog(LOG_NOTICE, "Failed to set %s handler", "SIGUSR1");
1587 /* initialize random number generator */
1588 srandom((unsigned int)time(NULL));
1590 /* initialize redirection engine (and pinholes) */
1591 if(init_redirect() < 0)
1593 syslog(LOG_ERR, "Failed to init redirection engine. EXITING");
1594 return 1;
1596 #ifdef ENABLE_UPNPPINHOLE
1597 #ifdef USE_NETFILTER
1598 init_iptpinhole();
1599 #endif
1600 #endif
1602 if(writepidfile(pidfilename, pid) < 0)
1603 pidfilename = NULL;
1605 #ifdef ENABLE_LEASEFILE
1606 /*remove(lease_file);*/
1607 syslog(LOG_INFO, "Reloading rules from lease file");
1608 reload_from_lease_file();
1609 #endif
1610 tomato_load(); // zzz
1612 return 0;
1613 print_usage:
1614 fprintf(stderr, "Usage:\n\t"
1615 "%s "
1616 #ifndef DISABLE_CONFIG_FILE
1617 "[-f config_file] "
1618 #endif
1619 "[-i ext_ifname] [-o ext_ip]\n"
1620 #ifndef MULTIPLE_EXTERNAL_IP
1621 "\t\t[-a listening_ip]"
1622 #else
1623 "\t\t[-a listening_ip ext_ip]"
1624 #endif
1625 #ifdef ENABLE_HTTPS
1626 " [-H https_port]"
1627 #endif
1628 " [-p port] [-d]"
1629 #if defined(USE_PF) || defined(USE_IPF)
1630 " [-L]"
1631 #endif
1632 " [-U] [-S]"
1633 #ifdef ENABLE_NATPMP
1634 " [-N]"
1635 #endif
1636 "\n"
1637 /*"[-l logfile] " not functionnal */
1638 "\t\t[-u uuid] [-s serial] [-m model_number] \n"
1639 "\t\t[-t notify_interval] [-P pid_filename] "
1640 #ifdef ENABLE_MANUFACTURER_INFO_CONFIGURATION
1641 "[-z fiendly_name]\n"
1642 #endif
1643 "\t\t[-B down up] [-w url] [-r clean_ruleset_interval]\n"
1644 #ifdef USE_PF
1645 "\t\t[-q queue] [-T tag]\n"
1646 #endif
1647 #ifdef ENABLE_NFQUEUE
1648 "\t\t[-Q queue] [-n name]\n"
1649 #endif
1650 "\t\t[-A \"permission rule\"]\n"
1651 "\nNotes:\n\tThere can be one or several listening_ips.\n"
1652 "\tNotify interval is in seconds. Default is 30 seconds.\n"
1653 "\tDefault pid file is '%s'.\n"
1654 "\tDefault config file is '%s'.\n"
1655 "\tWith -d miniupnpd will run as a standard program.\n"
1656 #if defined(USE_PF) || defined(USE_IPF)
1657 "\t-L sets packet log in pf and ipf on.\n"
1658 #endif
1659 "\t-S sets \"secure\" mode : clients can only add mappings to their own ip\n"
1660 "\t-U causes miniupnpd to report system uptime instead "
1661 "of daemon uptime.\n"
1662 #ifdef ENABLE_NATPMP
1663 "\t-N enable NAT-PMP functionality.\n"
1664 #endif
1665 "\t-B sets bitrates reported by daemon in bits per second.\n"
1666 "\t-w sets the presentation url. Default is http address on port 80\n"
1667 #ifdef USE_PF
1668 "\t-q sets the ALTQ queue in pf.\n"
1669 "\t-T sets the tag name in pf.\n"
1670 #endif
1671 #ifdef ENABLE_NFQUEUE
1672 "\t-Q sets the queue number that is used by NFQUEUE.\n"
1673 "\t-n sets the name of the interface(s) that packets will arrive on.\n"
1674 #endif
1675 "\t-A use following syntax for permission rules :\n"
1676 "\t (allow|deny) (external port range) ip/mask (internal port range)\n"
1677 "\texamples :\n"
1678 "\t \"allow 1024-65535 192.168.1.0/24 1024-65535\"\n"
1679 "\t \"deny 0-65535 0.0.0.0/0 0-65535\"\n"
1680 "\t-h prints this help and quits.\n"
1681 "", argv[0], pidfilename, DEFAULT_CONFIG);
1682 return 1;
1685 /* === main === */
1686 /* process HTTP or SSDP requests */
1688 main(int argc, char * * argv)
1690 int i;
1691 int shttpl = -1; /* socket for HTTP */
1692 #if defined(V6SOCKETS_ARE_V6ONLY) && defined(ENABLE_IPV6)
1693 int shttpl_v4 = -1; /* socket for HTTP (ipv4 only) */
1694 #endif
1695 #ifdef ENABLE_HTTPS
1696 int shttpsl = -1; /* socket for HTTPS */
1697 #if defined(V6SOCKETS_ARE_V6ONLY) && defined(ENABLE_IPV6)
1698 int shttpsl_v4 = -1; /* socket for HTTPS (ipv4 only) */
1699 #endif
1700 #endif /* ENABLE_HTTPS */
1701 int sudp = -1; /* IP v4 socket for receiving SSDP */
1702 #ifdef ENABLE_IPV6
1703 int sudpv6 = -1; /* IP v6 socket for receiving SSDP */
1704 #endif
1705 #ifdef ENABLE_NATPMP
1706 int * snatpmp = NULL; /* also used for PCP */
1707 #endif
1708 #if defined(ENABLE_IPV6) && defined(ENABLE_PCP)
1709 int spcp_v6 = -1;
1710 #endif
1711 #ifdef ENABLE_NFQUEUE
1712 int nfqh = -1;
1713 #endif
1714 #ifdef USE_IFACEWATCHER
1715 int sifacewatcher = -1;
1716 #endif
1718 int * snotify = NULL;
1719 int addr_count;
1720 LIST_HEAD(httplisthead, upnphttp) upnphttphead;
1721 struct upnphttp * e = 0;
1722 struct upnphttp * next;
1723 fd_set readset; /* for select() */
1724 fd_set writeset;
1725 struct timeval timeout, timeofday, lasttimeofday = {0, 0};
1726 int max_fd = -1;
1727 #ifdef USE_MINIUPNPDCTL
1728 int sctl = -1;
1729 LIST_HEAD(ctlstructhead, ctlelem) ctllisthead;
1730 struct ctlelem * ectl;
1731 struct ctlelem * ectlnext;
1732 #endif
1733 struct runtime_vars v;
1734 /* variables used for the unused-rule cleanup process */
1735 struct rule_state * rule_list = 0;
1736 struct timeval checktime = {0, 0};
1737 struct lan_addr_s * lan_addr;
1738 #ifdef ENABLE_UPNPPINHOLE
1739 unsigned int next_pinhole_ts;
1740 #endif
1742 if(init(argc, argv, &v) != 0)
1743 return 1;
1744 #ifdef ENABLE_HTTPS
1745 if(init_ssl() < 0)
1746 return 1;
1747 #endif /* ENABLE_HTTPS */
1748 /* count lan addrs */
1749 addr_count = 0;
1750 for(lan_addr = lan_addrs.lh_first; lan_addr != NULL; lan_addr = lan_addr->list.le_next)
1751 addr_count++;
1752 if(addr_count > 0) {
1753 #ifndef ENABLE_IPV6
1754 snotify = calloc(addr_count, sizeof(int));
1755 #else
1756 /* one for IPv4, one for IPv6 */
1757 snotify = calloc(addr_count * 2, sizeof(int));
1758 #endif
1760 #ifdef ENABLE_NATPMP
1761 if(addr_count > 0) {
1762 snatpmp = malloc(addr_count * sizeof(int));
1763 for(i = 0; i < addr_count; i++)
1764 snatpmp[i] = -1;
1766 #endif
1768 LIST_INIT(&upnphttphead);
1769 #ifdef USE_MINIUPNPDCTL
1770 LIST_INIT(&ctllisthead);
1771 #endif
1774 #ifdef ENABLE_NATPMP
1775 !GETFLAG(ENABLENATPMPMASK) &&
1776 #endif
1777 !GETFLAG(ENABLEUPNPMASK) ) {
1778 syslog(LOG_ERR, "Why did you run me anyway?");
1779 return 0;
1782 syslog(LOG_INFO, "Starting%s%swith external interface %s",
1783 #ifdef ENABLE_NATPMP
1784 #ifdef ENABLE_PCP
1785 GETFLAG(ENABLENATPMPMASK) ? " NAT-PMP/PCP " : " ",
1786 #else
1787 GETFLAG(ENABLENATPMPMASK) ? " NAT-PMP " : " ",
1788 #endif
1789 #else
1790 " ",
1791 #endif
1792 GETFLAG(ENABLEUPNPMASK) ? "UPnP-IGD " : "",
1793 ext_if_name);
1795 if(GETFLAG(ENABLEUPNPMASK))
1797 unsigned short listen_port;
1798 listen_port = (v.port > 0) ? v.port : 0;
1799 /* open socket for HTTP connections. Listen on the 1st LAN address */
1800 #ifdef ENABLE_IPV6
1801 shttpl = OpenAndConfHTTPSocket(&listen_port, 1);
1802 #else /* ENABLE_IPV6 */
1803 shttpl = OpenAndConfHTTPSocket(&listen_port);
1804 #endif /* ENABLE_IPV6 */
1805 if(shttpl < 0)
1807 syslog(LOG_ERR, "Failed to open socket for HTTP. EXITING");
1808 return 1;
1810 v.port = listen_port;
1811 syslog(LOG_NOTICE, "HTTP listening on port %d", v.port);
1812 #if defined(V6SOCKETS_ARE_V6ONLY) && defined(ENABLE_IPV6)
1813 if(!GETFLAG(IPV6DISABLEDMASK))
1815 shttpl_v4 = OpenAndConfHTTPSocket(&listen_port, 0);
1816 if(shttpl_v4 < 0)
1818 syslog(LOG_ERR, "Failed to open socket for HTTP on port %hu (IPv4). EXITING", v.port);
1819 return 1;
1822 #endif /* V6SOCKETS_ARE_V6ONLY */
1823 #ifdef ENABLE_HTTPS
1824 /* https */
1825 listen_port = (v.https_port > 0) ? v.https_port : 0;
1826 #ifdef ENABLE_IPV6
1827 shttpsl = OpenAndConfHTTPSocket(&listen_port, 1);
1828 #else /* ENABLE_IPV6 */
1829 shttpsl = OpenAndConfHTTPSocket(&listen_port);
1830 #endif /* ENABLE_IPV6 */
1831 if(shttpl < 0)
1833 syslog(LOG_ERR, "Failed to open socket for HTTPS. EXITING");
1834 return 1;
1836 v.https_port = listen_port;
1837 syslog(LOG_NOTICE, "HTTPS listening on port %d", v.https_port);
1838 #if defined(V6SOCKETS_ARE_V6ONLY) && defined(ENABLE_IPV6)
1839 shttpsl_v4 = OpenAndConfHTTPSocket(&listen_port, 0);
1840 if(shttpsl_v4 < 0)
1842 syslog(LOG_ERR, "Failed to open socket for HTTPS on port %hu (IPv4). EXITING", v.https_port);
1843 return 1;
1845 #endif /* V6SOCKETS_ARE_V6ONLY */
1846 #endif /* ENABLE_HTTPS */
1847 #ifdef ENABLE_IPV6
1848 if(find_ipv6_addr(NULL, ipv6_addr_for_http_with_brackets, sizeof(ipv6_addr_for_http_with_brackets)) > 0) {
1849 syslog(LOG_NOTICE, "HTTP IPv6 address given to control points : %s",
1850 ipv6_addr_for_http_with_brackets);
1851 } else {
1852 memcpy(ipv6_addr_for_http_with_brackets, "[::1]", 6);
1853 syslog(LOG_WARNING, "no HTTP IPv6 address, disabling IPv6");
1854 SETFLAG(IPV6DISABLEDMASK);
1856 #endif
1858 /* open socket for SSDP connections */
1859 sudp = OpenAndConfSSDPReceiveSocket(0);
1860 if(sudp < 0)
1862 syslog(LOG_NOTICE, "Failed to open socket for receiving SSDP. Trying to use MiniSSDPd");
1863 if(SubmitServicesToMiniSSDPD(lan_addrs.lh_first->str, v.port) < 0) {
1864 syslog(LOG_ERR, "Failed to connect to MiniSSDPd. EXITING");
1865 return 1;
1868 #ifdef ENABLE_IPV6
1869 if(!GETFLAG(IPV6DISABLEDMASK))
1871 sudpv6 = OpenAndConfSSDPReceiveSocket(1);
1872 if(sudpv6 < 0)
1874 syslog(LOG_WARNING, "Failed to open socket for receiving SSDP (IP v6).");
1877 #endif
1879 /* open socket for sending notifications */
1880 if(OpenAndConfSSDPNotifySockets(snotify) < 0)
1882 syslog(LOG_ERR, "Failed to open sockets for sending SSDP notify "
1883 "messages. EXITING");
1884 return 1;
1887 #ifdef USE_IFACEWATCHER
1888 /* open socket for kernel notifications about new network interfaces */
1889 if (sudp >= 0)
1891 sifacewatcher = OpenAndConfInterfaceWatchSocket();
1892 if (sifacewatcher < 0)
1894 syslog(LOG_ERR, "Failed to open socket for receiving network interface notifications");
1897 #endif
1900 #ifdef ENABLE_NATPMP
1901 /* open socket for NAT PMP traffic */
1902 if(GETFLAG(ENABLENATPMPMASK))
1904 if(OpenAndConfNATPMPSockets(snatpmp) < 0)
1905 #ifdef ENABLE_PCP
1907 syslog(LOG_ERR, "Failed to open sockets for NAT-PMP/PCP.");
1908 } else {
1909 syslog(LOG_NOTICE, "Listening for NAT-PMP/PCP traffic on port %u",
1910 NATPMP_PORT);
1912 #else
1914 syslog(LOG_ERR, "Failed to open sockets for NAT PMP.");
1915 } else {
1916 syslog(LOG_NOTICE, "Listening for NAT-PMP traffic on port %u",
1917 NATPMP_PORT);
1919 #endif
1921 #endif
1923 #if defined(ENABLE_IPV6) && defined(ENABLE_PCP)
1924 spcp_v6 = OpenAndConfPCPv6Socket();
1925 #endif
1927 /* for miniupnpdctl */
1928 #ifdef USE_MINIUPNPDCTL
1929 sctl = OpenAndConfCtlUnixSocket("/var/run/miniupnpd.ctl");
1930 #endif
1932 #ifdef ENABLE_NFQUEUE
1933 if ( nfqueue != -1 && n_nfqix > 0) {
1934 nfqh = OpenAndConfNFqueue();
1935 if(nfqh < 0) {
1936 syslog(LOG_ERR, "Failed to open fd for NFQUEUE.");
1937 return 1;
1938 } else {
1939 syslog(LOG_NOTICE, "Opened NFQUEUE %d",nfqueue);
1942 #endif
1944 tomato_helper(); // zzz
1946 /* main loop */
1947 while(!quitting)
1949 /* Correct startup_time if it was set with a RTC close to 0 */
1950 if((startup_time<60*60*24) && (time(NULL)>60*60*24))
1952 set_startup_time(GETFLAG(SYSUPTIMEMASK));
1954 /* send public address change notifications if needed */
1955 if(should_send_public_address_change_notif)
1957 syslog(LOG_INFO, "should send external iface address change notification(s)");
1958 #ifdef ENABLE_NATPMP
1959 if(GETFLAG(ENABLENATPMPMASK))
1960 SendNATPMPPublicAddressChangeNotification(snatpmp, addr_count);
1961 #endif
1962 #ifdef ENABLE_EVENTS
1963 if(GETFLAG(ENABLEUPNPMASK))
1965 upnp_event_var_change_notify(EWanIPC);
1967 #endif
1968 should_send_public_address_change_notif = 0;
1970 /* Check if we need to send SSDP NOTIFY messages and do it if
1971 * needed */
1972 if(gettimeofday(&timeofday, 0) < 0)
1974 syslog(LOG_ERR, "gettimeofday(): %m");
1975 timeout.tv_sec = v.notify_interval;
1976 timeout.tv_usec = 0;
1978 else
1980 /* the comparaison is not very precise but who cares ? */
1981 if(timeofday.tv_sec >= (lasttimeofday.tv_sec + v.notify_interval))
1983 if (GETFLAG(ENABLEUPNPMASK))
1984 SendSSDPNotifies2(snotify,
1985 (unsigned short)v.port,
1986 #ifdef ENABLE_HTTPS
1987 (unsigned short)v.https_port,
1988 #endif
1989 v.notify_interval << 1);
1990 memcpy(&lasttimeofday, &timeofday, sizeof(struct timeval));
1991 timeout.tv_sec = v.notify_interval;
1992 timeout.tv_usec = 0;
1994 else
1996 timeout.tv_sec = lasttimeofday.tv_sec + v.notify_interval
1997 - timeofday.tv_sec;
1998 if(timeofday.tv_usec > lasttimeofday.tv_usec)
2000 timeout.tv_usec = 1000000 + lasttimeofday.tv_usec
2001 - timeofday.tv_usec;
2002 timeout.tv_sec--;
2004 else
2006 timeout.tv_usec = lasttimeofday.tv_usec - timeofday.tv_usec;
2010 /* remove unused rules */
2011 if( v.clean_ruleset_interval
2012 && (timeofday.tv_sec >= checktime.tv_sec + v.clean_ruleset_interval))
2014 if(rule_list)
2016 remove_unused_rules(rule_list);
2017 rule_list = NULL;
2019 else
2021 rule_list = get_upnp_rules_state_list(v.clean_ruleset_threshold);
2023 memcpy(&checktime, &timeofday, sizeof(struct timeval));
2025 /* Remove expired port mappings, based on UPnP IGD LeaseDuration
2026 * or NAT-PMP lifetime) */
2027 if(nextruletoclean_timestamp
2028 && ((unsigned int)timeofday.tv_sec >= nextruletoclean_timestamp))
2030 syslog(LOG_DEBUG, "cleaning expired Port Mappings");
2031 get_upnp_rules_state_list(0);
2033 if(nextruletoclean_timestamp
2034 && ((unsigned int)timeout.tv_sec >= (nextruletoclean_timestamp - timeofday.tv_sec)))
2036 timeout.tv_sec = nextruletoclean_timestamp - timeofday.tv_sec;
2037 timeout.tv_usec = 0;
2038 syslog(LOG_DEBUG, "setting timeout to %u sec",
2039 (unsigned)timeout.tv_sec);
2041 #ifdef ENABLE_UPNPPINHOLE
2042 /* Clean up expired IPv6 PinHoles */
2043 next_pinhole_ts = 0;
2044 upnp_clean_expired_pinholes(&next_pinhole_ts);
2045 if(next_pinhole_ts &&
2046 timeout.tv_sec >= (int)(next_pinhole_ts - timeofday.tv_sec)) {
2047 timeout.tv_sec = next_pinhole_ts - timeofday.tv_sec;
2048 timeout.tv_usec = 0;
2050 #endif /* ENABLE_UPNPPINHOLE */
2052 /* select open sockets (SSDP, HTTP listen, and all HTTP soap sockets) */
2053 FD_ZERO(&readset);
2054 FD_ZERO(&writeset);
2056 if (sudp >= 0)
2058 FD_SET(sudp, &readset);
2059 max_fd = MAX( max_fd, sudp);
2060 #ifdef USE_IFACEWATCHER
2061 if (sifacewatcher >= 0)
2063 FD_SET(sifacewatcher, &readset);
2064 max_fd = MAX(max_fd, sifacewatcher);
2066 #endif
2068 if (shttpl >= 0)
2070 FD_SET(shttpl, &readset);
2071 max_fd = MAX( max_fd, shttpl);
2073 #if defined(V6SOCKETS_ARE_V6ONLY) && defined(ENABLE_IPV6)
2074 if (shttpl_v4 >= 0)
2076 FD_SET(shttpl_v4, &readset);
2077 max_fd = MAX( max_fd, shttpl_v4);
2079 #endif
2080 #ifdef ENABLE_HTTPS
2081 if (shttpsl >= 0)
2083 FD_SET(shttpsl, &readset);
2084 max_fd = MAX( max_fd, shttpsl);
2086 #if defined(V6SOCKETS_ARE_V6ONLY) && defined(ENABLE_IPV6)
2087 if (shttpsl_v4 >= 0)
2089 FD_SET(shttpsl_v4, &readset);
2090 max_fd = MAX( max_fd, shttpsl_v4);
2092 #endif
2093 #endif /* ENABLE_HTTPS */
2094 #ifdef ENABLE_IPV6
2095 if (sudpv6 >= 0)
2097 FD_SET(sudpv6, &readset);
2098 max_fd = MAX( max_fd, sudpv6);
2100 #endif
2102 #ifdef ENABLE_NFQUEUE
2103 if (nfqh >= 0)
2105 FD_SET(nfqh, &readset);
2106 max_fd = MAX( max_fd, nfqh);
2108 #endif
2110 i = 0; /* active HTTP connections count */
2111 for(e = upnphttphead.lh_first; e != NULL; e = e->entries.le_next)
2113 if(e->socket >= 0)
2115 if(e->state <= EWaitingForHttpContent)
2116 FD_SET(e->socket, &readset);
2117 else if(e->state == ESendingAndClosing)
2118 FD_SET(e->socket, &writeset);
2119 else
2120 continue;
2121 max_fd = MAX(max_fd, e->socket);
2122 i++;
2125 /* for debug */
2126 #ifdef DEBUG
2127 if(i > 1)
2129 syslog(LOG_DEBUG, "%d active incoming HTTP connections", i);
2131 #endif
2132 #ifdef ENABLE_NATPMP
2133 for(i=0; i<addr_count; i++) {
2134 if(snatpmp[i] >= 0) {
2135 FD_SET(snatpmp[i], &readset);
2136 max_fd = MAX( max_fd, snatpmp[i]);
2139 #endif
2140 #if defined(ENABLE_IPV6) && defined(ENABLE_PCP)
2141 if(spcp_v6 >= 0) {
2142 FD_SET(spcp_v6, &readset);
2143 max_fd = MAX(max_fd, spcp_v6);
2145 #endif
2146 #ifdef USE_MINIUPNPDCTL
2147 if(sctl >= 0) {
2148 FD_SET(sctl, &readset);
2149 max_fd = MAX( max_fd, sctl);
2152 for(ectl = ctllisthead.lh_first; ectl; ectl = ectl->entries.le_next)
2154 if(ectl->socket >= 0) {
2155 FD_SET(ectl->socket, &readset);
2156 max_fd = MAX( max_fd, ectl->socket);
2159 #endif
2161 #ifdef ENABLE_EVENTS
2162 upnpevents_selectfds(&readset, &writeset, &max_fd);
2163 #endif
2165 /* queued "sendto" */
2167 struct timeval next_send;
2168 i = get_next_scheduled_send(&next_send);
2169 if(i > 0) {
2170 #ifdef DEBUG
2171 syslog(LOG_DEBUG, "%d queued sendto", i);
2172 #endif
2173 i = get_sendto_fds(&writeset, &max_fd, &timeofday);
2174 if(timeofday.tv_sec > next_send.tv_sec ||
2175 (timeofday.tv_sec == next_send.tv_sec && timeofday.tv_usec >= next_send.tv_usec)) {
2176 if(i > 0) {
2177 timeout.tv_sec = 0;
2178 timeout.tv_usec = 0;
2180 } else {
2181 struct timeval tmp_timeout;
2182 tmp_timeout.tv_sec = (next_send.tv_sec - timeofday.tv_sec);
2183 tmp_timeout.tv_usec = (next_send.tv_usec - timeofday.tv_usec);
2184 if(tmp_timeout.tv_usec < 0) {
2185 tmp_timeout.tv_usec += 1000000;
2186 tmp_timeout.tv_sec--;
2188 if(timeout.tv_sec > tmp_timeout.tv_sec
2189 || (timeout.tv_sec == tmp_timeout.tv_sec && timeout.tv_usec > tmp_timeout.tv_usec)) {
2190 timeout.tv_sec = tmp_timeout.tv_sec;
2191 timeout.tv_usec = tmp_timeout.tv_usec;
2197 if(select(max_fd+1, &readset, &writeset, 0, &timeout) < 0)
2199 if(quitting) goto shutdown;
2200 if (gotusr2) { // zzz
2201 gotusr2 = 0;
2202 tomato_helper();
2203 continue;
2205 if(errno == EINTR) continue; /* interrupted by a signal, start again */
2206 syslog(LOG_ERR, "select(all): %m");
2207 syslog(LOG_ERR, "Failed to select open sockets. EXITING");
2208 return 1; /* very serious cause of error */
2210 i = try_sendto(&writeset);
2211 if(i < 0) {
2212 syslog(LOG_ERR, "try_sendto failed to send %d packets", -i);
2214 #ifdef USE_MINIUPNPDCTL
2215 for(ectl = ctllisthead.lh_first; ectl;)
2217 ectlnext = ectl->entries.le_next;
2218 if((ectl->socket >= 0) && FD_ISSET(ectl->socket, &readset))
2220 char buf[256];
2221 int l;
2222 l = read(ectl->socket, buf, sizeof(buf));
2223 if(l > 0)
2225 /*write(ectl->socket, buf, l);*/
2226 write_command_line(ectl->socket, argc, argv);
2227 #ifndef DISABLE_CONFIG_FILE
2228 write_option_list(ectl->socket);
2229 #endif
2230 write_permlist(ectl->socket, upnppermlist, num_upnpperm);
2231 write_upnphttp_details(ectl->socket, upnphttphead.lh_first);
2232 write_ctlsockets_list(ectl->socket, ctllisthead.lh_first);
2233 write_ruleset_details(ectl->socket);
2234 #ifdef ENABLE_EVENTS
2235 write_events_details(ectl->socket);
2236 #endif
2237 /* close the socket */
2238 close(ectl->socket);
2239 ectl->socket = -1;
2241 else
2243 close(ectl->socket);
2244 ectl->socket = -1;
2247 if(ectl->socket < 0)
2249 LIST_REMOVE(ectl, entries);
2250 free(ectl);
2252 ectl = ectlnext;
2254 if((sctl >= 0) && FD_ISSET(sctl, &readset))
2256 int s;
2257 struct sockaddr_un clientname;
2258 struct ctlelem * tmp;
2259 socklen_t clientnamelen = sizeof(struct sockaddr_un);
2260 /*syslog(LOG_DEBUG, "sctl!");*/
2261 s = accept(sctl, (struct sockaddr *)&clientname,
2262 &clientnamelen);
2263 syslog(LOG_DEBUG, "sctl! : '%s'", clientname.sun_path);
2264 tmp = malloc(sizeof(struct ctlelem));
2265 if (tmp == NULL)
2267 syslog(LOG_ERR, "Unable to allocate memory for ctlelem in main()");
2268 close(s);
2270 else
2272 tmp->socket = s;
2273 LIST_INSERT_HEAD(&ctllisthead, tmp, entries);
2276 #endif
2277 #ifdef ENABLE_EVENTS
2278 upnpevents_processfds(&readset, &writeset);
2279 #endif
2280 #ifdef ENABLE_NATPMP
2281 /* process NAT-PMP packets */
2282 for(i=0; i<addr_count; i++)
2284 if((snatpmp[i] >= 0) && FD_ISSET(snatpmp[i], &readset))
2286 unsigned char msg_buff[PCP_MAX_LEN];
2287 struct sockaddr_in senderaddr;
2288 socklen_t senderaddrlen;
2289 int len;
2290 memset(msg_buff, 0, PCP_MAX_LEN);
2291 senderaddrlen = sizeof(senderaddr);
2292 len = ReceiveNATPMPOrPCPPacket(snatpmp[i],
2293 (struct sockaddr *)&senderaddr,
2294 &senderaddrlen,
2295 NULL,
2296 msg_buff, sizeof(msg_buff));
2297 if (len < 1)
2298 continue;
2299 #ifdef ENABLE_PCP
2300 if (msg_buff[0]==0) { /* version equals to 0 -> means NAT-PMP */
2301 /* Check if the packet is coming from a LAN to enforce RFC6886 :
2302 * The NAT gateway MUST NOT accept mapping requests destined to the NAT
2303 * gateway's external IP address or received on its external network
2304 * interface. Only packets received on the internal interface(s) with a
2305 * destination address matching the internal address(es) of the NAT
2306 * gateway should be allowed. */
2307 /* TODO : move to ProcessIncomingNATPMPPacket() ? */
2308 lan_addr = get_lan_for_peer((struct sockaddr *)&senderaddr);
2309 if(lan_addr == NULL) {
2310 char sender_str[64];
2311 sockaddr_to_string((struct sockaddr *)&senderaddr, sender_str, sizeof(sender_str));
2312 syslog(LOG_WARNING, "NAT-PMP packet sender %s not from a LAN, ignoring",
2313 sender_str);
2314 continue;
2316 ProcessIncomingNATPMPPacket(snatpmp[i], msg_buff, len,
2317 &senderaddr);
2318 } else { /* everything else can be PCP */
2319 ProcessIncomingPCPPacket(snatpmp[i], msg_buff, len,
2320 (struct sockaddr *)&senderaddr, NULL);
2323 #else
2324 /* Check if the packet is coming from a LAN to enforce RFC6886 :
2325 * The NAT gateway MUST NOT accept mapping requests destined to the NAT
2326 * gateway's external IP address or received on its external network
2327 * interface. Only packets received on the internal interface(s) with a
2328 * destination address matching the internal address(es) of the NAT
2329 * gateway should be allowed. */
2330 /* TODO : move to ProcessIncomingNATPMPPacket() ? */
2331 lan_addr = get_lan_for_peer((struct sockaddr *)&senderaddr);
2332 if(lan_addr == NULL) {
2333 char sender_str[64];
2334 sockaddr_to_string((struct sockaddr *)&senderaddr, sender_str, sizeof(sender_str));
2335 syslog(LOG_WARNING, "NAT-PMP packet sender %s not from a LAN, ignoring",
2336 sender_str);
2337 continue;
2339 ProcessIncomingNATPMPPacket(snatpmp[i], msg_buff, len, &senderaddr);
2340 #endif
2343 #endif
2344 #if defined(ENABLE_IPV6) && defined(ENABLE_PCP)
2345 /* in IPv6, only PCP is supported, not NAT-PMP */
2346 if(spcp_v6 >= 0 && FD_ISSET(spcp_v6, &readset))
2348 unsigned char msg_buff[PCP_MAX_LEN];
2349 struct sockaddr_in6 senderaddr;
2350 socklen_t senderaddrlen;
2351 struct sockaddr_in6 receiveraddr;
2352 int len;
2353 memset(msg_buff, 0, PCP_MAX_LEN);
2354 senderaddrlen = sizeof(senderaddr);
2355 len = ReceiveNATPMPOrPCPPacket(spcp_v6,
2356 (struct sockaddr *)&senderaddr,
2357 &senderaddrlen,
2358 &receiveraddr,
2359 msg_buff, sizeof(msg_buff));
2360 if(len >= 1)
2361 ProcessIncomingPCPPacket(spcp_v6, msg_buff, len,
2362 (struct sockaddr *)&senderaddr,
2363 &receiveraddr);
2365 #endif
2366 /* process SSDP packets */
2367 if(sudp >= 0 && FD_ISSET(sudp, &readset))
2369 /*syslog(LOG_INFO, "Received UDP Packet");*/
2370 #ifdef ENABLE_HTTPS
2371 ProcessSSDPRequest(sudp, (unsigned short)v.port, (unsigned short)v.https_port);
2372 #else
2373 ProcessSSDPRequest(sudp, (unsigned short)v.port);
2374 #endif
2376 #ifdef ENABLE_IPV6
2377 if(sudpv6 >= 0 && FD_ISSET(sudpv6, &readset))
2379 syslog(LOG_INFO, "Received UDP Packet (IPv6)");
2380 #ifdef ENABLE_HTTPS
2381 ProcessSSDPRequest(sudpv6, (unsigned short)v.port, (unsigned short)v.https_port);
2382 #else
2383 ProcessSSDPRequest(sudpv6, (unsigned short)v.port);
2384 #endif
2386 #endif
2387 #ifdef USE_IFACEWATCHER
2388 /* process kernel notifications */
2389 if (sifacewatcher >= 0 && FD_ISSET(sifacewatcher, &readset))
2390 ProcessInterfaceWatchNotify(sifacewatcher);
2391 #endif
2393 /* process active HTTP connections */
2394 /* LIST_FOREACH macro is not available under linux */
2395 for(e = upnphttphead.lh_first; e != NULL; e = e->entries.le_next)
2397 if(e->socket >= 0)
2399 if(FD_ISSET(e->socket, &readset) ||
2400 FD_ISSET(e->socket, &writeset))
2402 Process_upnphttp(e);
2406 /* process incoming HTTP connections */
2407 if(shttpl >= 0 && FD_ISSET(shttpl, &readset))
2409 struct upnphttp * tmp;
2410 tmp = ProcessIncomingHTTP(shttpl, "HTTP");
2411 if(tmp)
2413 LIST_INSERT_HEAD(&upnphttphead, tmp, entries);
2416 #if defined(V6SOCKETS_ARE_V6ONLY) && defined(ENABLE_IPV6)
2417 if(shttpl_v4 >= 0 && FD_ISSET(shttpl_v4, &readset))
2419 struct upnphttp * tmp;
2420 tmp = ProcessIncomingHTTP(shttpl_v4, "HTTP");
2421 if(tmp)
2423 LIST_INSERT_HEAD(&upnphttphead, tmp, entries);
2426 #endif
2427 #ifdef ENABLE_HTTPS
2428 if(shttpsl >= 0 && FD_ISSET(shttpsl, &readset))
2430 struct upnphttp * tmp;
2431 tmp = ProcessIncomingHTTP(shttpsl, "HTTPS");
2432 if(tmp)
2434 InitSSL_upnphttp(tmp);
2435 LIST_INSERT_HEAD(&upnphttphead, tmp, entries);
2438 #if defined(V6SOCKETS_ARE_V6ONLY) && defined(ENABLE_IPV6)
2439 if(shttpsl_v4 >= 0 && FD_ISSET(shttpsl_v4, &readset))
2441 struct upnphttp * tmp;
2442 tmp = ProcessIncomingHTTP(shttpsl_v4, "HTTPS");
2443 if(tmp)
2445 InitSSL_upnphttp(tmp);
2446 LIST_INSERT_HEAD(&upnphttphead, tmp, entries);
2449 #endif
2450 #endif /* ENABLE_HTTPS */
2451 #ifdef ENABLE_NFQUEUE
2452 /* process NFQ packets */
2453 if(nfqh >= 0 && FD_ISSET(nfqh, &readset))
2455 /* syslog(LOG_INFO, "Received NFQUEUE Packet");*/
2456 ProcessNFQUEUE(nfqh);
2458 #endif
2459 /* delete finished HTTP connections */
2460 for(e = upnphttphead.lh_first; e != NULL; )
2462 next = e->entries.le_next;
2463 if(e->state >= EToDelete)
2465 LIST_REMOVE(e, entries);
2466 Delete_upnphttp(e);
2468 e = next;
2471 } /* end of main loop */
2473 shutdown:
2474 syslog(LOG_NOTICE, "shutting down MiniUPnPd");
2475 /* send good-bye */
2476 if (GETFLAG(ENABLEUPNPMASK))
2478 #ifndef ENABLE_IPV6
2479 if(SendSSDPGoodbye(snotify, addr_count) < 0)
2480 #else
2481 if(SendSSDPGoodbye(snotify, addr_count * 2) < 0)
2482 #endif
2484 syslog(LOG_ERR, "Failed to broadcast good-bye notifications");
2487 /* try to send pending packets */
2488 finalize_sendto();
2490 tomato_save("/etc/upnp/data"); // zzz
2492 /* close out open sockets */
2493 while(upnphttphead.lh_first != NULL)
2495 e = upnphttphead.lh_first;
2496 LIST_REMOVE(e, entries);
2497 Delete_upnphttp(e);
2500 if (sudp >= 0) close(sudp);
2501 if (shttpl >= 0) close(shttpl);
2502 #if defined(V6SOCKETS_ARE_V6ONLY) && defined(ENABLE_IPV6)
2503 if (shttpl_v4 >= 0) close(shttpl_v4);
2504 #endif
2505 #ifdef ENABLE_IPV6
2506 if (sudpv6 >= 0) close(sudpv6);
2507 #endif
2508 #ifdef USE_IFACEWATCHER
2509 if(sifacewatcher >= 0) close(sifacewatcher);
2510 #endif
2511 #ifdef ENABLE_NATPMP
2512 for(i=0; i<addr_count; i++) {
2513 if(snatpmp[i]>=0)
2515 close(snatpmp[i]);
2516 snatpmp[i] = -1;
2519 #endif
2520 #if defined(ENABLE_IPV6) && defined(ENABLE_PCP)
2521 if(spcp_v6 >= 0)
2523 close(spcp_v6);
2524 spcp_v6 = -1;
2526 #endif
2527 #ifdef USE_MINIUPNPDCTL
2528 if(sctl>=0)
2530 close(sctl);
2531 sctl = -1;
2532 if(unlink("/var/run/miniupnpd.ctl") < 0)
2534 syslog(LOG_ERR, "unlink() %m");
2537 #endif
2539 if (GETFLAG(ENABLEUPNPMASK))
2541 #ifndef ENABLE_IPV6
2542 for(i = 0; i < addr_count; i++)
2543 #else
2544 for(i = 0; i < addr_count * 2; i++)
2545 #endif
2546 close(snotify[i]);
2549 /* remove pidfile */
2550 if(pidfilename && (unlink(pidfilename) < 0))
2552 syslog(LOG_ERR, "Failed to remove pidfile %s: %m", pidfilename);
2555 /* delete lists */
2556 while(lan_addrs.lh_first != NULL)
2558 lan_addr = lan_addrs.lh_first;
2559 LIST_REMOVE(lan_addrs.lh_first, list);
2560 free(lan_addr);
2563 #ifdef ENABLE_HTTPS
2564 free_ssl();
2565 #endif
2566 #ifdef ENABLE_NATPMP
2567 free(snatpmp);
2568 #endif
2569 free(snotify);
2570 closelog();
2571 #ifndef DISABLE_CONFIG_FILE
2572 freeoptions();
2573 #endif
2575 return 0;