Annotation of embedaddon/miniupnpd/miniupnpd.c, revision 1.1.1.3
1.1.1.3 ! misho 1: /* $Id: miniupnpd.c,v 1.173 2013/02/06 10:50:04 nanard Exp $ */
1.1 misho 2: /* MiniUPnP project
3: * http://miniupnp.free.fr/ or http://miniupnp.tuxfamily.org/
1.1.1.3 ! misho 4: * (c) 2006-2013 Thomas Bernard
1.1 misho 5: * This software is subject to the conditions detailed
6: * in the LICENCE file provided within the distribution */
7:
8: #include "config.h"
9:
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>
1.1.1.3 ! misho 15: #if 0
! 16: #include <linux/netfilter_ipv4.h> /* Defines verdicts (NF_ACCEPT, etc) */
! 17: #endif
1.1 misho 18: #include <linux/netfilter.h>
19: #include <libnetfilter_queue/libnetfilter_queue.h>
20: #include <linux/netfilter/nfnetlink_queue.h>
21: #endif
22:
23: #include <stdlib.h>
24: #include <unistd.h>
25: #include <string.h>
26: #include <stdio.h>
27: #include <ctype.h>
28: #include <sys/types.h>
29: #include <sys/socket.h>
30: #include <netinet/in.h>
31: #include <arpa/inet.h>
32: #include <fcntl.h>
33: #include <sys/file.h>
34: #include <syslog.h>
35: #include <sys/time.h>
36: #include <time.h>
37: #include <signal.h>
38: #include <errno.h>
39: #include <sys/param.h>
40: #if defined(sun)
41: #include <kstat.h>
42: #else
43: /* for BSD's sysctl */
44: #include <sys/sysctl.h>
45: #endif
46:
47: /* unix sockets */
48: #ifdef USE_MINIUPNPDCTL
49: #include <sys/un.h>
50: #endif
51:
1.1.1.3 ! misho 52: #include "macros.h"
1.1 misho 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"
1.1.1.3 ! misho 62: #include "upnppinhole.h"
1.1 misho 63: #include "miniupnpdtypes.h"
64: #include "daemonize.h"
65: #include "upnpevents.h"
66: #ifdef ENABLE_NATPMP
67: #include "natpmp.h"
68: #endif
69: #include "commonrdr.h"
1.1.1.2 misho 70: #include "upnputils.h"
71: #ifdef USE_IFACEWATCHER
72: #include "ifacewatcher.h"
73: #endif
1.1.1.3 ! misho 74: #ifdef ENABLE_6FC_SERVICE
! 75: #ifdef USE_NETFILTER
! 76: void init_iptpinhole(void);
! 77: #endif
! 78: #endif
1.1 misho 79:
80: #ifndef DEFAULT_CONFIG
81: #define DEFAULT_CONFIG "/etc/miniupnpd.conf"
82: #endif
83:
84: #ifdef USE_MINIUPNPDCTL
85: struct ctlelem {
86: int socket;
87: LIST_ENTRY(ctlelem) entries;
88: };
89: #endif
90:
91: #ifdef ENABLE_NFQUEUE
92: /* globals */
93: static struct nfq_handle *nfqHandle;
94: static struct sockaddr_in ssdp;
95:
96: /* prototypes */
97: static int nfqueue_cb( struct nfq_q_handle *qh, struct nfgenmsg *nfmsg, struct nfq_data *nfa, void *data) ;
98: int identify_ip_protocol (char *payload);
99: int get_udp_dst_port (char *payload);
100: #endif
101:
1.1.1.2 misho 102: /* variables used by signals */
1.1.1.3 ! misho 103: static volatile sig_atomic_t quitting = 0;
! 104: volatile sig_atomic_t should_send_public_address_change_notif = 0;
1.1 misho 105:
106: /* OpenAndConfHTTPSocket() :
107: * setup the socket used to handle incoming HTTP connections. */
108: static int
109: OpenAndConfHTTPSocket(unsigned short port)
110: {
111: int s;
112: int i = 1;
1.1.1.2 misho 113: #ifdef ENABLE_IPV6
114: struct sockaddr_in6 listenname;
115: #else
1.1 misho 116: struct sockaddr_in listenname;
1.1.1.2 misho 117: #endif
118: socklen_t listenname_len;
1.1 misho 119:
1.1.1.2 misho 120: if( (s = socket(
121: #ifdef ENABLE_IPV6
122: PF_INET6,
123: #else
124: PF_INET,
125: #endif
126: SOCK_STREAM, 0)) < 0)
1.1 misho 127: {
128: syslog(LOG_ERR, "socket(http): %m");
129: return -1;
130: }
131:
132: if(setsockopt(s, SOL_SOCKET, SO_REUSEADDR, &i, sizeof(i)) < 0)
133: {
134: syslog(LOG_WARNING, "setsockopt(http, SO_REUSEADDR): %m");
135: }
1.1.1.2 misho 136: #if 0
137: /* enable this to force IPV6 only for IPV6 socket.
138: * see http://www.ietf.org/rfc/rfc3493.txt section 5.3 */
139: if(setsockopt(s, IPPROTO_IPV6, IPV6_V6ONLY, &i, sizeof(i)) < 0)
140: {
141: syslog(LOG_WARNING, "setsockopt(http, IPV6_V6ONLY): %m");
142: }
143: #endif
1.1 misho 144:
1.1.1.3 ! misho 145: if(!set_non_blocking(s))
! 146: {
! 147: syslog(LOG_WARNING, "set_non_blocking(http): %m");
! 148: }
! 149:
1.1.1.2 misho 150: #ifdef ENABLE_IPV6
151: memset(&listenname, 0, sizeof(struct sockaddr_in6));
152: listenname.sin6_family = AF_INET6;
153: listenname.sin6_port = htons(port);
154: listenname.sin6_addr = in6addr_any;
155: listenname_len = sizeof(struct sockaddr_in6);
156: #else
1.1 misho 157: listenname.sin_family = AF_INET;
158: listenname.sin_port = htons(port);
159: listenname.sin_addr.s_addr = htonl(INADDR_ANY);
1.1.1.2 misho 160: listenname_len = sizeof(struct sockaddr_in);
161: #endif
1.1 misho 162:
1.1.1.2 misho 163: if(bind(s, (struct sockaddr *)&listenname, listenname_len) < 0)
1.1 misho 164: {
165: syslog(LOG_ERR, "bind(http): %m");
166: close(s);
167: return -1;
168: }
169:
1.1.1.2 misho 170: if(listen(s, 5) < 0)
1.1 misho 171: {
172: syslog(LOG_ERR, "listen(http): %m");
173: close(s);
174: return -1;
175: }
176:
177: return s;
178: }
179: #ifdef ENABLE_NFQUEUE
180:
181: int identify_ip_protocol(char *payload) {
182: return payload[9];
183: }
184:
185:
186: /*
187: * This function returns the destination port of the captured packet UDP
188: */
189: int get_udp_dst_port(char *payload) {
190: char *pkt_data_ptr = NULL;
191: pkt_data_ptr = payload + sizeof(struct ip);
192:
193: /* Cast the UDP Header from the raw packet */
194: struct udphdr *udp = (struct udphdr *) pkt_data_ptr;
195:
196: /* get the dst port of the packet */
197: return(ntohs(udp->dest));
198:
199: }
200: static int
201: OpenAndConfNFqueue(){
202:
203: struct nfq_q_handle *myQueue;
204: struct nfnl_handle *netlinkHandle;
205:
206: int fd = 0, e = 0;
207:
208: inet_pton(AF_INET, "239.255.255.250", &(ssdp.sin_addr));
209:
1.1.1.3 ! misho 210: /* Get a queue connection handle from the module */
1.1 misho 211: if (!(nfqHandle = nfq_open())) {
212: syslog(LOG_ERR, "Error in nfq_open(): %m");
213: return -1;
214: }
215:
1.1.1.3 ! misho 216: /* Unbind the handler from processing any IP packets
! 217: Not totally sure why this is done, or if it's necessary... */
1.1 misho 218: if ((e = nfq_unbind_pf(nfqHandle, AF_INET)) < 0) {
219: syslog(LOG_ERR, "Error in nfq_unbind_pf(): %m");
220: return -1;
221: }
222:
1.1.1.3 ! misho 223: /* Bind this handler to process IP packets... */
1.1 misho 224: if (nfq_bind_pf(nfqHandle, AF_INET) < 0) {
225: syslog(LOG_ERR, "Error in nfq_bind_pf(): %m");
226: return -1;
227: }
228:
1.1.1.3 ! misho 229: /* Install a callback on queue -Q */
1.1 misho 230: if (!(myQueue = nfq_create_queue(nfqHandle, nfqueue, &nfqueue_cb, NULL))) {
231: syslog(LOG_ERR, "Error in nfq_create_queue(): %m");
232: return -1;
233: }
234:
1.1.1.3 ! misho 235: /* Turn on packet copy mode */
1.1 misho 236: if (nfq_set_mode(myQueue, NFQNL_COPY_PACKET, 0xffff) < 0) {
237: syslog(LOG_ERR, "Error setting packet copy mode (): %m");
238: return -1;
239: }
240:
241: netlinkHandle = nfq_nfnlh(nfqHandle);
242: fd = nfnl_fd(netlinkHandle);
243:
244: return fd;
245:
246: }
247:
248:
249: static int nfqueue_cb(
250: struct nfq_q_handle *qh,
251: struct nfgenmsg *nfmsg,
252: struct nfq_data *nfa,
253: void *data) {
254:
255: char *pkt;
256: struct nfqnl_msg_packet_hdr *ph;
257: ph = nfq_get_msg_packet_hdr(nfa);
258:
259: if ( ph ) {
260:
261: int id = 0, size = 0;
262: id = ntohl(ph->packet_id);
263:
264: size = nfq_get_payload(nfa, &pkt);
265:
266: struct ip *iph = (struct ip *) pkt;
267:
268: int id_protocol = identify_ip_protocol(pkt);
269:
270: int dport = get_udp_dst_port(pkt);
271:
272: int x = sizeof (struct ip) + sizeof (struct udphdr);
1.1.1.3 ! misho 273:
! 274: /* packets we are interested in are UDP multicast to 239.255.255.250:1900
1.1 misho 275: * and start with a data string M-SEARCH
276: */
1.1.1.3 ! misho 277: if ( (dport == 1900) && (id_protocol == IPPROTO_UDP)
1.1 misho 278: && (ssdp.sin_addr.s_addr == iph->ip_dst.s_addr) ) {
1.1.1.3 ! misho 279:
1.1 misho 280: /* get the index that the packet came in on */
281: u_int32_t idx = nfq_get_indev(nfa);
282: int i = 0;
283: for ( ;i < n_nfqix ; i++) {
284: if ( nfqix[i] == idx ) {
285:
286: struct udphdr *udp = (struct udphdr *) (pkt + sizeof(struct ip));
287:
288: char *dd = pkt + x;
1.1.1.3 ! misho 289:
1.1 misho 290: struct sockaddr_in sendername;
291: sendername.sin_family = AF_INET;
292: sendername.sin_port = udp->source;
293: sendername.sin_addr.s_addr = iph->ip_src.s_addr;
294:
295: /* printf("pkt found %s\n",dd);*/
1.1.1.2 misho 296: ProcessSSDPData (sudp, dd, size - x,
297: &sendername, (unsigned short) 5555);
1.1 misho 298: }
299: }
300: }
1.1.1.3 ! misho 301:
1.1 misho 302: nfq_set_verdict(qh, id, NF_ACCEPT, 0, NULL);
303:
304: } else {
305: syslog(LOG_ERR,"nfq_get_msg_packet_hdr failed");
1.1.1.3 ! misho 306: return 1;
! 307: /* from nfqueue source: 0 = ok, >0 = soft error, <0 hard error */
1.1 misho 308: }
309:
310: return 0;
311: }
312:
313: static void ProcessNFQUEUE(int fd){
314: char buf[4096];
315:
316: socklen_t len_r;
317: struct sockaddr_in sendername;
318: len_r = sizeof(struct sockaddr_in);
319:
320: int res = recvfrom(fd, buf, sizeof(buf), 0,
321: (struct sockaddr *)&sendername, &len_r);
322:
323: nfq_handle_packet(nfqHandle, buf, res);
324: }
325: #endif
326:
327: /* Functions used to communicate with miniupnpdctl */
328: #ifdef USE_MINIUPNPDCTL
329: static int
330: OpenAndConfCtlUnixSocket(const char * path)
331: {
332: struct sockaddr_un localun;
333: int s;
334: s = socket(AF_UNIX, SOCK_STREAM, 0);
335: localun.sun_family = AF_UNIX;
336: strncpy(localun.sun_path, path,
337: sizeof(localun.sun_path));
338: if(bind(s, (struct sockaddr *)&localun,
339: sizeof(struct sockaddr_un)) < 0)
340: {
341: syslog(LOG_ERR, "bind(sctl): %m");
342: close(s);
343: s = -1;
344: }
345: else if(listen(s, 5) < 0)
346: {
347: syslog(LOG_ERR, "listen(sctl): %m");
348: close(s);
349: s = -1;
350: }
351: return s;
352: }
353:
354: static void
355: write_upnphttp_details(int fd, struct upnphttp * e)
356: {
357: char buffer[256];
358: int len;
359: write(fd, "HTTP :\n", 7);
360: while(e)
361: {
362: len = snprintf(buffer, sizeof(buffer),
363: "%d %d %s req_buf=%p(%dbytes) res_buf=%p(%dbytes alloc)\n",
364: e->socket, e->state, e->HttpVer,
365: e->req_buf, e->req_buflen,
366: e->res_buf, e->res_buf_alloclen);
367: write(fd, buffer, len);
368: e = e->entries.le_next;
369: }
370: }
371:
372: static void
373: write_ctlsockets_list(int fd, struct ctlelem * e)
374: {
375: char buffer[256];
376: int len;
377: write(fd, "CTL :\n", 6);
378: while(e)
379: {
380: len = snprintf(buffer, sizeof(buffer),
381: "struct ctlelem: socket=%d\n", e->socket);
382: write(fd, buffer, len);
383: e = e->entries.le_next;
384: }
385: }
386:
1.1.1.3 ! misho 387: #ifndef DISABLE_CONFIG_FILE
1.1 misho 388: static void
389: write_option_list(int fd)
390: {
391: char buffer[256];
392: int len;
1.1.1.3 ! misho 393: unsigned int i;
1.1 misho 394: write(fd, "Options :\n", 10);
395: for(i=0; i<num_options; i++)
396: {
397: len = snprintf(buffer, sizeof(buffer),
398: "opt=%02d %s\n",
399: ary_options[i].id, ary_options[i].value);
400: write(fd, buffer, len);
401: }
402: }
1.1.1.3 ! misho 403: #endif
1.1 misho 404:
405: static void
406: write_command_line(int fd, int argc, char * * argv)
407: {
408: char buffer[256];
409: int len;
410: int i;
411: write(fd, "Command Line :\n", 15);
412: for(i=0; i<argc; i++)
413: {
414: len = snprintf(buffer, sizeof(buffer),
415: "argv[%02d]='%s'\n",
416: i, argv[i]);
417: write(fd, buffer, len);
418: }
419: }
420:
421: #endif
422:
1.1.1.3 ! misho 423: /* Handler for the SIGTERM signal (kill)
1.1 misho 424: * SIGINT is also handled */
425: static void
426: sigterm(int sig)
427: {
1.1.1.3 ! misho 428: UNUSED(sig);
! 429: /*int save_errno = errno; */
! 430: /*signal(sig, SIG_IGN);*/ /* Ignore this signal while we are quitting */
! 431: /* Note : isn't it useless ? */
1.1 misho 432:
1.1.1.3 ! misho 433: #if 0
! 434: /* calling syslog() is forbidden in signal handler according to
! 435: * signal(3) */
1.1 misho 436: syslog(LOG_NOTICE, "received signal %d, good-bye", sig);
1.1.1.3 ! misho 437: #endif
1.1 misho 438:
439: quitting = 1;
440: /*errno = save_errno;*/
441: }
442:
443: /* Handler for the SIGUSR1 signal indicating public IP address change. */
444: static void
445: sigusr1(int sig)
446: {
1.1.1.3 ! misho 447: UNUSED(sig);
! 448: #if 0
! 449: /* calling syslog() is forbidden in signal handler according to
! 450: * signal(3) */
1.1 misho 451: syslog(LOG_INFO, "received signal %d, public ip address change", sig);
1.1.1.3 ! misho 452: #endif
1.1 misho 453:
454: should_send_public_address_change_notif = 1;
455: }
456:
457: /* record the startup time, for returning uptime */
458: static void
459: set_startup_time(int sysuptime)
460: {
461: startup_time = time(NULL);
462: if(sysuptime)
463: {
464: /* use system uptime instead of daemon uptime */
465: #if defined(__linux__)
466: char buff[64];
467: int uptime = 0, fd;
468: fd = open("/proc/uptime", O_RDONLY);
469: if(fd < 0)
470: {
471: syslog(LOG_ERR, "open(\"/proc/uptime\" : %m");
472: }
473: else
474: {
475: memset(buff, 0, sizeof(buff));
476: if(read(fd, buff, sizeof(buff) - 1) < 0)
477: {
478: syslog(LOG_ERR, "read(\"/proc/uptime\" : %m");
479: }
480: else
481: {
482: uptime = atoi(buff);
483: syslog(LOG_INFO, "system uptime is %d seconds", uptime);
484: }
485: close(fd);
486: startup_time -= uptime;
487: }
488: #elif defined(SOLARIS_KSTATS)
489: kstat_ctl_t *kc;
490: kc = kstat_open();
491: if(kc != NULL)
492: {
493: kstat_t *ksp;
494: ksp = kstat_lookup(kc, "unix", 0, "system_misc");
495: if(ksp && (kstat_read(kc, ksp, NULL) != -1))
496: {
497: void *ptr = kstat_data_lookup(ksp, "boot_time");
498: if(ptr)
499: memcpy(&startup_time, ptr, sizeof(startup_time));
500: else
501: syslog(LOG_ERR, "cannot find boot_time kstat");
502: }
503: else
504: syslog(LOG_ERR, "cannot open kstats for unix/0/system_misc: %m");
505: kstat_close(kc);
506: }
507: #else
508: struct timeval boottime;
509: size_t size = sizeof(boottime);
510: int name[2] = { CTL_KERN, KERN_BOOTTIME };
511: if(sysctl(name, 2, &boottime, &size, NULL, 0) < 0)
512: {
513: syslog(LOG_ERR, "sysctl(\"kern.boottime\") failed");
514: }
515: else
516: {
517: startup_time = boottime.tv_sec;
518: }
519: #endif
520: }
521: }
522:
523: /* structure containing variables used during "main loop"
524: * that are filled during the init */
525: struct runtime_vars {
526: /* LAN IP addresses for SSDP traffic and HTTP */
527: /* moved to global vars */
528: int port; /* HTTP Port */
529: int notify_interval; /* seconds between SSDP announces */
530: /* unused rules cleaning related variables : */
531: int clean_ruleset_threshold; /* threshold for removing unused rules */
532: int clean_ruleset_interval; /* (minimum) interval between checks */
533: };
534:
535: /* parselanaddr()
536: * parse address with mask
1.1.1.3 ! misho 537: * ex: 192.168.1.1/24 or 192.168.1.1/255.255.255.0
1.1 misho 538: * When MULTIPLE_EXTERNAL_IP is enabled, the ip address of the
539: * external interface associated with the lan subnet follows.
540: * ex : 192.168.1.1/24 81.21.41.11
541: *
1.1.1.3 ! misho 542: * Can also use the interface name (ie eth0)
! 543: *
! 544: * return value :
1.1 misho 545: * 0 : ok
546: * -1 : error */
547: static int
548: parselanaddr(struct lan_addr_s * lan_addr, const char * str)
549: {
550: const char * p;
551: int n;
1.1.1.3 ! misho 552: char tmp[16];
! 553:
! 554: memset(lan_addr, 0, sizeof(struct lan_addr_s));
1.1 misho 555: p = str;
556: while(*p && *p != '/' && !isspace(*p))
557: p++;
558: n = p - str;
1.1.1.3 ! misho 559: if(!isdigit(str[0]) && n < (int)sizeof(lan_addr->ifname))
1.1 misho 560: {
1.1.1.3 ! misho 561: /* not starting with a digit : suppose it is an interface name */
! 562: memcpy(lan_addr->ifname, str, n);
! 563: lan_addr->ifname[n] = '\0';
! 564: if(getifaddr(lan_addr->ifname, lan_addr->str, sizeof(lan_addr->str)) < 0)
! 565: goto parselan_error;
1.1 misho 566: }
1.1.1.3 ! misho 567: else
1.1 misho 568: {
1.1.1.3 ! misho 569: if(n>15)
! 570: goto parselan_error;
! 571: memcpy(lan_addr->str, str, n);
! 572: lan_addr->str[n] = '\0';
1.1 misho 573: }
574: if(!inet_aton(lan_addr->str, &lan_addr->addr))
1.1.1.3 ! misho 575: goto parselan_error;
! 576: if(*p == '/')
1.1 misho 577: {
1.1.1.3 ! misho 578: const char * q = ++p;
! 579: while(*p && isdigit(*p))
! 580: p++;
! 581: if(*p=='.')
! 582: {
! 583: while(*p && (*p=='.' || isdigit(*p)))
! 584: p++;
! 585: n = p - q;
! 586: if(n>15)
! 587: goto parselan_error;
! 588: memcpy(tmp, q, n);
! 589: tmp[n] = '\0';
! 590: if(!inet_aton(tmp, &lan_addr->mask))
! 591: goto parselan_error;
! 592: }
! 593: else
! 594: {
! 595: int nbits = atoi(q);
! 596: if(nbits > 32 || nbits < 0)
! 597: goto parselan_error;
! 598: lan_addr->mask.s_addr = htonl(nbits ? (0xffffffffu << (32 - nbits)) : 0);
! 599: }
! 600: }
! 601: else
! 602: {
! 603: /* by default, networks are /24 */
! 604: lan_addr->mask.s_addr = htonl(0xffffff00u);
1.1 misho 605: }
606: #ifdef MULTIPLE_EXTERNAL_IP
607: /* skip spaces */
608: while(*p && isspace(*p))
609: p++;
610: if(*p) {
611: /* parse the exteral ip address to associate with this subnet */
612: n = 0;
613: while(p[n] && !isspace(*p))
614: n++;
615: if(n<=15) {
616: memcpy(lan_addr->ext_ip_str, p, n);
617: lan_addr->ext_ip_str[n] = '\0';
618: if(!inet_aton(lan_addr->ext_ip_str, &lan_addr->ext_ip_addr)) {
619: /* error */
620: fprintf(stderr, "Error parsing address : %s\n", lan_addr->ext_ip_str);
621: }
622: }
623: }
624: #endif
1.1.1.3 ! misho 625: #ifdef ENABLE_IPV6
! 626: if(lan_addr->ifname[0] != '\0')
! 627: {
! 628: lan_addr->index = if_nametoindex(lan_addr->ifname);
! 629: if(lan_addr->index == 0)
! 630: fprintf(stderr, "Cannot get index for network interface %s",
! 631: lan_addr->ifname);
! 632: }
! 633: #endif
1.1 misho 634: return 0;
1.1.1.3 ! misho 635: parselan_error:
! 636: fprintf(stderr, "Error parsing address/mask (or interface name) : %s\n",
! 637: str);
! 638: return -1;
1.1 misho 639: }
640:
641: /* init phase :
642: * 1) read configuration file
643: * 2) read command line arguments
644: * 3) daemonize
645: * 4) open syslog
646: * 5) check and write pid file
647: * 6) set startup time stamp
648: * 7) compute presentation URL
649: * 8) set signal handlers */
650: static int
651: init(int argc, char * * argv, struct runtime_vars * v)
652: {
653: int i;
654: int pid;
655: int debug_flag = 0;
656: int openlog_option;
657: struct sigaction sa;
658: /*const char * logfilename = 0;*/
659: const char * presurl = 0;
1.1.1.3 ! misho 660: #ifndef DISABLE_CONFIG_FILE
! 661: int options_flag = 0;
1.1 misho 662: const char * optionsfile = DEFAULT_CONFIG;
1.1.1.3 ! misho 663: #endif /* DISABLE_CONFIG_FILE */
1.1.1.2 misho 664: struct lan_addr_s * lan_addr;
665: struct lan_addr_s * lan_addr2;
1.1 misho 666:
667: /* only print usage if -h is used */
668: for(i=1; i<argc; i++)
669: {
670: if(0 == strcmp(argv[i], "-h"))
671: goto print_usage;
672: }
1.1.1.3 ! misho 673: #ifndef DISABLE_CONFIG_FILE
1.1 misho 674: /* first check if "-f" option is used */
675: for(i=2; i<argc; i++)
676: {
677: if(0 == strcmp(argv[i-1], "-f"))
678: {
679: optionsfile = argv[i];
680: options_flag = 1;
681: break;
682: }
683: }
1.1.1.3 ! misho 684: #endif /* DISABLE_CONFIG_FILE */
1.1 misho 685:
686: /* set initial values */
1.1.1.3 ! misho 687: SETFLAG(ENABLEUPNPMASK); /* UPnP is enabled by default */
1.1 misho 688:
1.1.1.2 misho 689: LIST_INIT(&lan_addrs);
1.1 misho 690: v->port = -1;
691: v->notify_interval = 30; /* seconds between SSDP announces */
692: v->clean_ruleset_threshold = 20;
693: v->clean_ruleset_interval = 0; /* interval between ruleset check. 0=disabled */
1.1.1.3 ! misho 694: #ifndef DISABLE_CONFIG_FILE
1.1 misho 695: /* read options file first since
696: * command line arguments have final say */
697: if(readoptionsfile(optionsfile) < 0)
698: {
699: /* only error if file exists or using -f */
700: if(access(optionsfile, F_OK) == 0 || options_flag)
701: fprintf(stderr, "Error reading configuration file %s\n", optionsfile);
702: }
703: else
704: {
1.1.1.3 ! misho 705: for(i=0; i<(int)num_options; i++)
1.1 misho 706: {
707: switch(ary_options[i].id)
708: {
709: case UPNPEXT_IFNAME:
710: ext_if_name = ary_options[i].value;
711: break;
712: case UPNPEXT_IP:
713: use_ext_ip_addr = ary_options[i].value;
714: break;
715: case UPNPLISTENING_IP:
1.1.1.2 misho 716: lan_addr = (struct lan_addr_s *) malloc(sizeof(struct lan_addr_s));
717: if (lan_addr == NULL)
1.1 misho 718: {
1.1.1.2 misho 719: fprintf(stderr, "malloc(sizeof(struct lan_addr_s)): %m");
720: break;
1.1 misho 721: }
1.1.1.2 misho 722: if(parselanaddr(lan_addr, ary_options[i].value) != 0)
1.1 misho 723: {
1.1.1.2 misho 724: fprintf(stderr, "can't parse \"%s\" as valid lan address\n", ary_options[i].value);
725: free(lan_addr);
726: break;
1.1 misho 727: }
1.1.1.2 misho 728: LIST_INSERT_HEAD(&lan_addrs, lan_addr, list);
1.1 misho 729: break;
730: case UPNPPORT:
731: v->port = atoi(ary_options[i].value);
732: break;
733: case UPNPBITRATE_UP:
734: upstream_bitrate = strtoul(ary_options[i].value, 0, 0);
735: break;
736: case UPNPBITRATE_DOWN:
737: downstream_bitrate = strtoul(ary_options[i].value, 0, 0);
738: break;
739: case UPNPPRESENTATIONURL:
740: presurl = ary_options[i].value;
741: break;
1.1.1.3 ! misho 742: case UPNPFRIENDLY_NAME:
! 743: strncpy(friendly_name, ary_options[i].value, FRIENDLY_NAME_MAX_LEN);
! 744: friendly_name[FRIENDLY_NAME_MAX_LEN-1] = '\0';
! 745: break;
1.1 misho 746: #ifdef USE_NETFILTER
747: case UPNPFORWARDCHAIN:
748: miniupnpd_forward_chain = ary_options[i].value;
749: break;
750: case UPNPNATCHAIN:
751: miniupnpd_nat_chain = ary_options[i].value;
752: break;
753: #endif
754: case UPNPNOTIFY_INTERVAL:
755: v->notify_interval = atoi(ary_options[i].value);
756: break;
757: case UPNPSYSTEM_UPTIME:
758: if(strcmp(ary_options[i].value, "yes") == 0)
759: SETFLAG(SYSUPTIMEMASK); /*sysuptime = 1;*/
760: break;
1.1.1.3 ! misho 761: #if defined(USE_PF) || defined(USE_IPF)
1.1 misho 762: case UPNPPACKET_LOG:
763: if(strcmp(ary_options[i].value, "yes") == 0)
764: SETFLAG(LOGPACKETSMASK); /*logpackets = 1;*/
765: break;
1.1.1.3 ! misho 766: #endif
1.1 misho 767: case UPNPUUID:
768: strncpy(uuidvalue+5, ary_options[i].value,
769: strlen(uuidvalue+5) + 1);
770: break;
771: case UPNPSERIAL:
772: strncpy(serialnumber, ary_options[i].value, SERIALNUMBER_MAX_LEN);
773: serialnumber[SERIALNUMBER_MAX_LEN-1] = '\0';
1.1.1.3 ! misho 774: break;
1.1 misho 775: case UPNPMODEL_NUMBER:
776: strncpy(modelnumber, ary_options[i].value, MODELNUMBER_MAX_LEN);
777: modelnumber[MODELNUMBER_MAX_LEN-1] = '\0';
778: break;
779: case UPNPCLEANTHRESHOLD:
780: v->clean_ruleset_threshold = atoi(ary_options[i].value);
781: break;
782: case UPNPCLEANINTERVAL:
783: v->clean_ruleset_interval = atoi(ary_options[i].value);
784: break;
785: #ifdef USE_PF
1.1.1.3 ! misho 786: case UPNPANCHOR:
! 787: anchor_name = ary_options[i].value;
! 788: break;
1.1 misho 789: case UPNPQUEUE:
790: queue = ary_options[i].value;
791: break;
792: case UPNPTAG:
793: tag = ary_options[i].value;
794: break;
795: #endif
796: #ifdef ENABLE_NATPMP
797: case UPNPENABLENATPMP:
798: if(strcmp(ary_options[i].value, "yes") == 0)
799: SETFLAG(ENABLENATPMPMASK); /*enablenatpmp = 1;*/
800: else
801: if(atoi(ary_options[i].value))
802: SETFLAG(ENABLENATPMPMASK);
803: /*enablenatpmp = atoi(ary_options[i].value);*/
804: break;
805: #endif
806: #ifdef PF_ENABLE_FILTER_RULES
807: case UPNPQUICKRULES:
808: if(strcmp(ary_options[i].value, "no") == 0)
809: SETFLAG(PFNOQUICKRULESMASK);
810: break;
811: #endif
812: case UPNPENABLE:
813: if(strcmp(ary_options[i].value, "yes") != 0)
814: CLEARFLAG(ENABLEUPNPMASK);
815: break;
816: case UPNPSECUREMODE:
817: if(strcmp(ary_options[i].value, "yes") == 0)
818: SETFLAG(SECUREMODEMASK);
819: break;
820: #ifdef ENABLE_LEASEFILE
821: case UPNPLEASEFILE:
822: lease_file = ary_options[i].value;
823: break;
824: #endif
825: case UPNPMINISSDPDSOCKET:
826: minissdpdsocketpath = ary_options[i].value;
827: break;
828: default:
829: fprintf(stderr, "Unknown option in file %s\n",
830: optionsfile);
831: }
832: }
833: }
1.1.1.3 ! misho 834: #endif /* DISABLE_CONFIG_FILE */
1.1 misho 835:
836: /* command line arguments processing */
837: for(i=1; i<argc; i++)
838: {
839: if(argv[i][0]!='-')
840: {
841: fprintf(stderr, "Unknown option: %s\n", argv[i]);
842: }
843: else switch(argv[i][1])
844: {
845: case 'o':
846: if(i+1 < argc)
847: use_ext_ip_addr = argv[++i];
848: else
849: fprintf(stderr, "Option -%c takes one argument.\n", argv[i][1]);
850: break;
851: case 't':
852: if(i+1 < argc)
853: v->notify_interval = atoi(argv[++i]);
854: else
855: fprintf(stderr, "Option -%c takes one argument.\n", argv[i][1]);
856: break;
1.1.1.3 ! misho 857: case 'r':
! 858: if(i+1 < argc)
! 859: v->clean_ruleset_interval = atoi(argv[++i]);
! 860: else
! 861: fprintf(stderr, "Option -%c takes one argument.\n", argv[i][1]);
! 862: break;
1.1 misho 863: case 'u':
864: if(i+1 < argc)
865: strncpy(uuidvalue+5, argv[++i], strlen(uuidvalue+5) + 1);
866: else
867: fprintf(stderr, "Option -%c takes one argument.\n", argv[i][1]);
868: break;
1.1.1.3 ! misho 869: case 'z':
! 870: if(i+1 < argc)
! 871: strncpy(friendly_name, argv[++i], FRIENDLY_NAME_MAX_LEN);
! 872: else
! 873: fprintf(stderr, "Option -%c takes one argument.\n", argv[i][1]);
! 874: friendly_name[FRIENDLY_NAME_MAX_LEN-1] = '\0';
! 875: break;
1.1 misho 876: case 's':
877: if(i+1 < argc)
878: strncpy(serialnumber, argv[++i], SERIALNUMBER_MAX_LEN);
879: else
880: fprintf(stderr, "Option -%c takes one argument.\n", argv[i][1]);
881: serialnumber[SERIALNUMBER_MAX_LEN-1] = '\0';
882: break;
883: case 'm':
884: if(i+1 < argc)
885: strncpy(modelnumber, argv[++i], MODELNUMBER_MAX_LEN);
886: else
887: fprintf(stderr, "Option -%c takes one argument.\n", argv[i][1]);
888: modelnumber[MODELNUMBER_MAX_LEN-1] = '\0';
889: break;
890: #ifdef ENABLE_NATPMP
891: case 'N':
892: /*enablenatpmp = 1;*/
893: SETFLAG(ENABLENATPMPMASK);
894: break;
895: #endif
896: case 'U':
897: /*sysuptime = 1;*/
898: SETFLAG(SYSUPTIMEMASK);
899: break;
900: /*case 'l':
901: logfilename = argv[++i];
902: break;*/
1.1.1.3 ! misho 903: #if defined(USE_PF) || defined(USE_IPF)
1.1 misho 904: case 'L':
905: /*logpackets = 1;*/
906: SETFLAG(LOGPACKETSMASK);
907: break;
1.1.1.3 ! misho 908: #endif
1.1 misho 909: case 'S':
910: SETFLAG(SECUREMODEMASK);
911: break;
912: case 'i':
913: if(i+1 < argc)
914: ext_if_name = argv[++i];
915: else
916: fprintf(stderr, "Option -%c takes one argument.\n", argv[i][1]);
917: break;
918: #ifdef USE_PF
919: case 'q':
920: if(i+1 < argc)
921: queue = argv[++i];
922: else
923: fprintf(stderr, "Option -%c takes one argument.\n", argv[i][1]);
924: break;
925: case 'T':
926: if(i+1 < argc)
927: tag = argv[++i];
928: else
929: fprintf(stderr, "Option -%c takes one argument.\n", argv[i][1]);
930: break;
931: #endif
932: case 'p':
933: if(i+1 < argc)
934: v->port = atoi(argv[++i]);
935: else
936: #ifdef ENABLE_NFQUEUE
937: case 'Q':
938: if(i+1<argc)
939: {
940: nfqueue = atoi(argv[++i]);
941: }
942: else
943: fprintf(stderr, "Option -%c takes one argument.\n", argv[i][1]);
944: break;
945: case 'n':
946: if (i+1 < argc) {
947: i++;
948: if(n_nfqix < MAX_LAN_ADDR) {
949: nfqix[n_nfqix++] = if_nametoindex(argv[i]);
950: } else {
951: fprintf(stderr,"Too many nfq interfaces. Ignoring %s\n", argv[i]);
952: }
953: } else {
954: fprintf(stderr, "Option -%c takes one argument.\n", argv[i][1]);
955: }
956: break;
957: #endif
958: fprintf(stderr, "Option -%c takes one argument.\n", argv[i][1]);
959: break;
960: case 'P':
961: if(i+1 < argc)
962: pidfilename = argv[++i];
963: else
964: fprintf(stderr, "Option -%c takes one argument.\n", argv[i][1]);
965: break;
966: case 'd':
967: debug_flag = 1;
968: break;
969: case 'w':
970: if(i+1 < argc)
971: presurl = argv[++i];
972: else
973: fprintf(stderr, "Option -%c takes one argument.\n", argv[i][1]);
974: break;
975: case 'B':
976: if(i+2<argc)
977: {
978: downstream_bitrate = strtoul(argv[++i], 0, 0);
979: upstream_bitrate = strtoul(argv[++i], 0, 0);
980: }
981: else
982: fprintf(stderr, "Option -%c takes two arguments.\n", argv[i][1]);
983: break;
984: case 'a':
1.1.1.3 ! misho 985: #ifndef MULTIPLE_EXTERNAL_IP
1.1 misho 986: if(i+1 < argc)
987: {
988: i++;
1.1.1.2 misho 989: lan_addr = (struct lan_addr_s *) malloc(sizeof(struct lan_addr_s));
990: if (lan_addr == NULL)
1.1 misho 991: {
1.1.1.2 misho 992: fprintf(stderr, "malloc(sizeof(struct lan_addr_s)): %m");
1.1 misho 993: break;
1.1.1.2 misho 994: }
995: if(parselanaddr(lan_addr, argv[i]) != 0)
1.1 misho 996: {
1.1.1.2 misho 997: fprintf(stderr, "can't parse \"%s\" as valid lan address\n", argv[i]);
998: free(lan_addr);
999: break;
1.1 misho 1000: }
1.1.1.2 misho 1001: /* check if we already have this address */
1002: for(lan_addr2 = lan_addrs.lh_first; lan_addr2 != NULL; lan_addr2 = lan_addr2->list.le_next)
1.1 misho 1003: {
1.1.1.2 misho 1004: if (0 == strncmp(lan_addr2->str, lan_addr->str, 15))
1005: break;
1.1 misho 1006: }
1.1.1.2 misho 1007: if (lan_addr2 == NULL)
1008: LIST_INSERT_HEAD(&lan_addrs, lan_addr, list);
1.1 misho 1009: }
1010: else
1011: fprintf(stderr, "Option -%c takes one argument.\n", argv[i][1]);
1.1.1.3 ! misho 1012: #else
! 1013: if(i+2 < argc)
! 1014: {
! 1015: char *val=calloc((strlen(argv[i+1]) + strlen(argv[i+2]) + 1), sizeof(char));
! 1016: if (val == NULL)
! 1017: {
! 1018: fprintf(stderr, "memory allocation error for listen address storage\n");
! 1019: break;
! 1020: }
! 1021: sprintf(val, "%s %s", argv[i+1], argv[i+2]);
! 1022:
! 1023: lan_addr = (struct lan_addr_s *) malloc(sizeof(struct lan_addr_s));
! 1024: if (lan_addr == NULL)
! 1025: {
! 1026: fprintf(stderr, "malloc(sizeof(struct lan_addr_s)): %m");
! 1027: free(val);
! 1028: break;
! 1029: }
! 1030: if(parselanaddr(lan_addr, val) != 0)
! 1031: {
! 1032: fprintf(stderr, "can't parse \"%s\" as valid lan address\n", val);
! 1033: free(lan_addr);
! 1034: free(val);
! 1035: break;
! 1036: }
! 1037: /* check if we already have this address */
! 1038: for(lan_addr2 = lan_addrs.lh_first; lan_addr2 != NULL; lan_addr2 = lan_addr2->list.le_next)
! 1039: {
! 1040: if (0 == strncmp(lan_addr2->str, lan_addr->str, 15))
! 1041: break;
! 1042: }
! 1043: if (lan_addr2 == NULL)
! 1044: LIST_INSERT_HEAD(&lan_addrs, lan_addr, list);
! 1045:
! 1046: free(val);
! 1047: i+=2;
! 1048: }
! 1049: else
! 1050: fprintf(stderr, "Option -%c takes two arguments.\n", argv[i][1]);
! 1051: #endif
! 1052: break;
! 1053: case 'A':
! 1054: if(i+1 < argc) {
! 1055: void * tmp;
! 1056: tmp = realloc(upnppermlist, sizeof(struct upnpperm) * (num_upnpperm+1));
! 1057: if(tmp == NULL) {
! 1058: fprintf(stderr, "memory allocation error for permission\n");
! 1059: } else {
! 1060: upnppermlist = tmp;
! 1061: if(read_permission_line(upnppermlist + num_upnpperm, argv[++i]) >= 0) {
! 1062: num_upnpperm++;
! 1063: } else {
! 1064: fprintf(stderr, "Permission rule parsing error :\n%s\n", argv[i]);
! 1065: }
! 1066: }
! 1067: } else
! 1068: fprintf(stderr, "Option -%c takes one argument.\n", argv[i][1]);
1.1 misho 1069: break;
1070: case 'f':
1071: i++; /* discarding, the config file is already read */
1072: break;
1073: default:
1074: fprintf(stderr, "Unknown option: %s\n", argv[i]);
1075: }
1076: }
1.1.1.2 misho 1077: if(!ext_if_name || !lan_addrs.lh_first)
1.1 misho 1078: {
1079: /* bad configuration */
1080: goto print_usage;
1081: }
1082:
1083: if(debug_flag)
1084: {
1085: pid = getpid();
1086: }
1087: else
1088: {
1089: #ifdef USE_DAEMON
1090: if(daemon(0, 0)<0) {
1091: perror("daemon()");
1092: }
1093: pid = getpid();
1094: #else
1095: pid = daemonize();
1096: #endif
1097: }
1098:
1099: openlog_option = LOG_PID|LOG_CONS;
1100: if(debug_flag)
1101: {
1102: openlog_option |= LOG_PERROR; /* also log on stderr */
1103: }
1104:
1105: openlog("miniupnpd", openlog_option, LOG_MINIUPNPD);
1106:
1107: if(!debug_flag)
1108: {
1109: /* speed things up and ignore LOG_INFO and LOG_DEBUG */
1110: setlogmask(LOG_UPTO(LOG_NOTICE));
1111: }
1112:
1113: if(checkforrunning(pidfilename) < 0)
1114: {
1115: syslog(LOG_ERR, "MiniUPnPd is already running. EXITING");
1116: return 1;
1.1.1.3 ! misho 1117: }
1.1 misho 1118:
1119: set_startup_time(GETFLAG(SYSUPTIMEMASK));
1120:
1121: /* presentation url */
1122: if(presurl)
1123: {
1124: strncpy(presentationurl, presurl, PRESENTATIONURL_MAX_LEN);
1125: presentationurl[PRESENTATIONURL_MAX_LEN-1] = '\0';
1126: }
1127: else
1128: {
1129: snprintf(presentationurl, PRESENTATIONURL_MAX_LEN,
1.1.1.2 misho 1130: "http://%s/", lan_addrs.lh_first->str);
1131: /*"http://%s:%d/", lan_addrs.lh_first->str, 80);*/
1.1 misho 1132: }
1133:
1134: /* set signal handler */
1135: memset(&sa, 0, sizeof(struct sigaction));
1136: sa.sa_handler = sigterm;
1137:
1.1.1.3 ! misho 1138: if(sigaction(SIGTERM, &sa, NULL) < 0)
1.1 misho 1139: {
1140: syslog(LOG_ERR, "Failed to set %s handler. EXITING", "SIGTERM");
1141: return 1;
1142: }
1.1.1.3 ! misho 1143: if(sigaction(SIGINT, &sa, NULL) < 0)
1.1 misho 1144: {
1145: syslog(LOG_ERR, "Failed to set %s handler. EXITING", "SIGINT");
1146: return 1;
1147: }
1.1.1.3 ! misho 1148: sa.sa_handler = SIG_IGN;
! 1149: if(sigaction(SIGPIPE, &sa, NULL) < 0)
! 1150: {
1.1 misho 1151: syslog(LOG_ERR, "Failed to ignore SIGPIPE signals");
1152: }
1153: sa.sa_handler = sigusr1;
1.1.1.3 ! misho 1154: if(sigaction(SIGUSR1, &sa, NULL) < 0)
1.1 misho 1155: {
1156: syslog(LOG_NOTICE, "Failed to set %s handler", "SIGUSR1");
1157: }
1158:
1159: if(init_redirect() < 0)
1160: {
1161: syslog(LOG_ERR, "Failed to init redirection engine. EXITING");
1162: return 1;
1163: }
1.1.1.3 ! misho 1164: #ifdef ENABLE_6FC_SERVICE
! 1165: #ifdef USE_NETFILTER
! 1166: init_iptpinhole();
! 1167: #endif
! 1168: #endif
1.1 misho 1169:
1.1.1.3 ! misho 1170: if(writepidfile(pidfilename, pid) < 0)
! 1171: pidfilename = NULL;
1.1 misho 1172:
1173: #ifdef ENABLE_LEASEFILE
1174: /*remove(lease_file);*/
1175: syslog(LOG_INFO, "Reloading rules from lease file");
1176: reload_from_lease_file();
1177: #endif
1178:
1179: return 0;
1180: print_usage:
1181: fprintf(stderr, "Usage:\n\t"
1.1.1.3 ! misho 1182: "%s "
! 1183: #ifndef DISABLE_CONFIG_FILE
! 1184: "[-f config_file] "
! 1185: #endif
! 1186: "[-i ext_ifname] [-o ext_ip]\n"
! 1187: #ifndef MULTIPLE_EXTERNAL_IP
! 1188: "\t\t[-a listening_ip]"
1.1 misho 1189: #else
1.1.1.3 ! misho 1190: "\t\t[-a listening_ip ext_ip]"
! 1191: #endif
! 1192: " [-p port] [-d]"
! 1193: #if defined(USE_PF) || defined(USE_IPF)
! 1194: " [-L]"
! 1195: #endif
! 1196: " [-U] [-S]"
! 1197: #ifdef ENABLE_NATPMP
! 1198: " [-N]"
1.1 misho 1199: #endif
1.1.1.3 ! misho 1200: "\n"
1.1 misho 1201: /*"[-l logfile] " not functionnal */
1202: "\t\t[-u uuid] [-s serial] [-m model_number] \n"
1.1.1.3 ! misho 1203: "\t\t[-t notify_interval] [-P pid_filename] [-z fiendly_name]\n"
! 1204: "\t\t[-B down up] [-w url] [-r clean_ruleset_interval]\n"
1.1 misho 1205: #ifdef USE_PF
1206: "\t\t[-q queue] [-T tag]\n"
1207: #endif
1208: #ifdef ENABLE_NFQUEUE
1209: "\t\t[-Q queue] [-n name]\n"
1210: #endif
1.1.1.3 ! misho 1211: "\t\t[-A \"permission rule\"]\n"
1.1 misho 1212: "\nNotes:\n\tThere can be one or several listening_ips.\n"
1213: "\tNotify interval is in seconds. Default is 30 seconds.\n"
1214: "\tDefault pid file is '%s'.\n"
1215: "\tDefault config file is '%s'.\n"
1216: "\tWith -d miniupnpd will run as a standard program.\n"
1.1.1.3 ! misho 1217: #if defined(USE_PF) || defined(USE_IPF)
1.1 misho 1218: "\t-L sets packet log in pf and ipf on.\n"
1.1.1.3 ! misho 1219: #endif
1.1 misho 1220: "\t-S sets \"secure\" mode : clients can only add mappings to their own ip\n"
1221: "\t-U causes miniupnpd to report system uptime instead "
1222: "of daemon uptime.\n"
1223: #ifdef ENABLE_NATPMP
1.1.1.3 ! misho 1224: "\t-N enable NAT-PMP functionality.\n"
1.1 misho 1225: #endif
1226: "\t-B sets bitrates reported by daemon in bits per second.\n"
1227: "\t-w sets the presentation url. Default is http address on port 80\n"
1228: #ifdef USE_PF
1229: "\t-q sets the ALTQ queue in pf.\n"
1230: "\t-T sets the tag name in pf.\n"
1231: #endif
1232: #ifdef ENABLE_NFQUEUE
1.1.1.3 ! misho 1233: "\t-Q sets the queue number that is used by NFQUEUE.\n"
! 1234: "\t-n sets the name of the interface(s) that packets will arrive on.\n"
1.1 misho 1235: #endif
1.1.1.3 ! misho 1236: "\t-A use following syntax for permission rules :\n"
! 1237: "\t (allow|deny) (external port range) ip/mask (internal port range)\n"
! 1238: "\texamples :\n"
! 1239: "\t \"allow 1024-65535 192.168.1.0/24 1024-65535\"\n"
! 1240: "\t \"deny 0-65535 0.0.0.0/0 0-65535\"\n"
1.1 misho 1241: "\t-h prints this help and quits.\n"
1242: "", argv[0], pidfilename, DEFAULT_CONFIG);
1243: return 1;
1244: }
1245:
1246: /* === main === */
1247: /* process HTTP or SSDP requests */
1248: int
1249: main(int argc, char * * argv)
1250: {
1251: int i;
1.1.1.2 misho 1252: int shttpl = -1; /* socket for HTTP */
1253: int sudp = -1; /* IP v4 socket for receiving SSDP */
1254: #ifdef ENABLE_IPV6
1255: int sudpv6 = -1; /* IP v6 socket for receiving SSDP */
1256: #endif
1.1 misho 1257: #ifdef ENABLE_NATPMP
1.1.1.3 ! misho 1258: int * snatpmp = NULL;
1.1.1.2 misho 1259: #endif
1.1 misho 1260: #ifdef ENABLE_NFQUEUE
1261: int nfqh = -1;
1262: #endif
1.1.1.2 misho 1263: #ifdef USE_IFACEWATCHER
1264: int sifacewatcher = -1;
1.1 misho 1265: #endif
1.1.1.2 misho 1266:
1.1.1.3 ! misho 1267: int * snotify = NULL;
1.1.1.2 misho 1268: int addr_count;
1.1 misho 1269: LIST_HEAD(httplisthead, upnphttp) upnphttphead;
1270: struct upnphttp * e = 0;
1271: struct upnphttp * next;
1272: fd_set readset; /* for select() */
1273: fd_set writeset;
1274: struct timeval timeout, timeofday, lasttimeofday = {0, 0};
1275: int max_fd = -1;
1276: #ifdef USE_MINIUPNPDCTL
1277: int sctl = -1;
1278: LIST_HEAD(ctlstructhead, ctlelem) ctllisthead;
1279: struct ctlelem * ectl;
1280: struct ctlelem * ectlnext;
1281: #endif
1282: struct runtime_vars v;
1283: /* variables used for the unused-rule cleanup process */
1284: struct rule_state * rule_list = 0;
1285: struct timeval checktime = {0, 0};
1.1.1.2 misho 1286: struct lan_addr_s * lan_addr;
1.1.1.3 ! misho 1287: #ifdef ENABLE_6FC_SERVICE
! 1288: unsigned int next_pinhole_ts;
! 1289: #endif
1.1 misho 1290:
1.1.1.2 misho 1291: if(init(argc, argv, &v) != 0)
1292: return 1;
1293: /* count lan addrs */
1294: addr_count = 0;
1295: for(lan_addr = lan_addrs.lh_first; lan_addr != NULL; lan_addr = lan_addr->list.le_next)
1296: addr_count++;
1.1.1.3 ! misho 1297: if(addr_count > 0) {
! 1298: #ifndef ENABLE_IPV6
! 1299: snotify = calloc(addr_count, sizeof(int));
! 1300: #else
! 1301: /* one for IPv4, one for IPv6 */
! 1302: snotify = calloc(addr_count * 2, sizeof(int));
! 1303: #endif
! 1304: }
1.1 misho 1305: #ifdef ENABLE_NATPMP
1.1.1.3 ! misho 1306: if(addr_count > 0) {
! 1307: snatpmp = malloc(addr_count * sizeof(int));
! 1308: for(i = 0; i < addr_count; i++)
! 1309: snatpmp[i] = -1;
! 1310: }
1.1 misho 1311: #endif
1312:
1313: LIST_INIT(&upnphttphead);
1314: #ifdef USE_MINIUPNPDCTL
1315: LIST_INIT(&ctllisthead);
1316: #endif
1317:
1318: if(
1319: #ifdef ENABLE_NATPMP
1320: !GETFLAG(ENABLENATPMPMASK) &&
1321: #endif
1322: !GETFLAG(ENABLEUPNPMASK) ) {
1323: syslog(LOG_ERR, "Why did you run me anyway?");
1324: return 0;
1325: }
1326:
1.1.1.3 ! misho 1327: syslog(LOG_INFO, "Starting%s%swith external interface %s",
! 1328: #ifdef ENABLE_NATPMP
! 1329: GETFLAG(ENABLENATPMPMASK) ? " NAT-PMP " : " ",
! 1330: #else
! 1331: " ",
! 1332: #endif
! 1333: GETFLAG(ENABLEUPNPMASK) ? "UPnP-IGD " : "",
! 1334: ext_if_name);
! 1335:
1.1 misho 1336: if(GETFLAG(ENABLEUPNPMASK))
1337: {
1338:
1339: /* open socket for HTTP connections. Listen on the 1st LAN address */
1340: shttpl = OpenAndConfHTTPSocket((v.port > 0) ? v.port : 0);
1341: if(shttpl < 0)
1342: {
1343: syslog(LOG_ERR, "Failed to open socket for HTTP. EXITING");
1344: return 1;
1345: }
1346: if(v.port <= 0) {
1347: struct sockaddr_in sockinfo;
1348: socklen_t len = sizeof(struct sockaddr_in);
1349: if (getsockname(shttpl, (struct sockaddr *)&sockinfo, &len) < 0) {
1350: syslog(LOG_ERR, "getsockname(): %m");
1351: return 1;
1352: }
1353: v.port = ntohs(sockinfo.sin_port);
1354: }
1355: syslog(LOG_NOTICE, "HTTP listening on port %d", v.port);
1.1.1.2 misho 1356: #ifdef ENABLE_IPV6
1357: if(find_ipv6_addr(NULL, ipv6_addr_for_http_with_brackets, sizeof(ipv6_addr_for_http_with_brackets)) > 0) {
1358: syslog(LOG_NOTICE, "HTTP IPv6 address given to control points : %s",
1359: ipv6_addr_for_http_with_brackets);
1360: } else {
1361: memcpy(ipv6_addr_for_http_with_brackets, "[::1]", 6);
1362: syslog(LOG_WARNING, "no HTTP IPv6 address");
1363: }
1364: #endif
1.1 misho 1365:
1366: /* open socket for SSDP connections */
1.1.1.2 misho 1367: sudp = OpenAndConfSSDPReceiveSocket(0);
1.1 misho 1368: if(sudp < 0)
1369: {
1.1.1.3 ! misho 1370: syslog(LOG_NOTICE, "Failed to open socket for receiving SSDP. Trying to use MiniSSDPd");
1.1.1.2 misho 1371: if(SubmitServicesToMiniSSDPD(lan_addrs.lh_first->str, v.port) < 0) {
1.1 misho 1372: syslog(LOG_ERR, "Failed to connect to MiniSSDPd. EXITING");
1373: return 1;
1374: }
1375: }
1.1.1.2 misho 1376: #ifdef ENABLE_IPV6
1377: sudpv6 = OpenAndConfSSDPReceiveSocket(1);
1378: if(sudpv6 < 0)
1379: {
1.1.1.3 ! misho 1380: syslog(LOG_WARNING, "Failed to open socket for receiving SSDP (IP v6).");
1.1.1.2 misho 1381: }
1382: #endif
1.1 misho 1383:
1384: /* open socket for sending notifications */
1385: if(OpenAndConfSSDPNotifySockets(snotify) < 0)
1386: {
1387: syslog(LOG_ERR, "Failed to open sockets for sending SSDP notify "
1388: "messages. EXITING");
1389: return 1;
1390: }
1.1.1.2 misho 1391:
1392: #ifdef USE_IFACEWATCHER
1393: /* open socket for kernel notifications about new network interfaces */
1394: if (sudp >= 0)
1395: {
1396: sifacewatcher = OpenAndConfInterfaceWatchSocket();
1397: if (sifacewatcher < 0)
1398: {
1399: syslog(LOG_ERR, "Failed to open socket for receiving network interface notifications");
1400: }
1401: }
1402: #endif
1.1 misho 1403: }
1404:
1405: #ifdef ENABLE_NATPMP
1406: /* open socket for NAT PMP traffic */
1407: if(GETFLAG(ENABLENATPMPMASK))
1408: {
1409: if(OpenAndConfNATPMPSockets(snatpmp) < 0)
1410: {
1411: syslog(LOG_ERR, "Failed to open sockets for NAT PMP.");
1412: } else {
1413: syslog(LOG_NOTICE, "Listening for NAT-PMP traffic on port %u",
1414: NATPMP_PORT);
1415: }
1.1.1.2 misho 1416: #if 0
1.1 misho 1417: ScanNATPMPforExpiration();
1.1.1.2 misho 1418: #endif
1.1 misho 1419: }
1420: #endif
1421:
1422: /* for miniupnpdctl */
1423: #ifdef USE_MINIUPNPDCTL
1424: sctl = OpenAndConfCtlUnixSocket("/var/run/miniupnpd.ctl");
1425: #endif
1426:
1427: #ifdef ENABLE_NFQUEUE
1428: if ( nfqueue != -1 && n_nfqix > 0) {
1429: nfqh = OpenAndConfNFqueue();
1430: if(nfqh < 0) {
1431: syslog(LOG_ERR, "Failed to open fd for NFQUEUE.");
1432: return 1;
1433: } else {
1434: syslog(LOG_NOTICE, "Opened NFQUEUE %d",nfqueue);
1435: }
1436: }
1437: #endif
1.1.1.3 ! misho 1438:
1.1 misho 1439: /* main loop */
1440: while(!quitting)
1441: {
1442: /* Correct startup_time if it was set with a RTC close to 0 */
1443: if((startup_time<60*60*24) && (time(NULL)>60*60*24))
1444: {
1445: set_startup_time(GETFLAG(SYSUPTIMEMASK));
1.1.1.3 ! misho 1446: }
1.1.1.2 misho 1447: /* send public address change notifications if needed */
1448: if(should_send_public_address_change_notif)
1449: {
1450: syslog(LOG_DEBUG, "should send external iface address change notification(s)");
1451: #ifdef ENABLE_NATPMP
1452: if(GETFLAG(ENABLENATPMPMASK))
1453: SendNATPMPPublicAddressChangeNotification(snatpmp, addr_count);
1454: #endif
1455: #ifdef ENABLE_EVENTS
1456: if(GETFLAG(ENABLEUPNPMASK))
1457: {
1458: upnp_event_var_change_notify(EWanIPC);
1459: }
1460: #endif
1461: should_send_public_address_change_notif = 0;
1462: }
1.1 misho 1463: /* Check if we need to send SSDP NOTIFY messages and do it if
1464: * needed */
1465: if(gettimeofday(&timeofday, 0) < 0)
1466: {
1467: syslog(LOG_ERR, "gettimeofday(): %m");
1468: timeout.tv_sec = v.notify_interval;
1469: timeout.tv_usec = 0;
1470: }
1471: else
1472: {
1473: /* the comparaison is not very precise but who cares ? */
1474: if(timeofday.tv_sec >= (lasttimeofday.tv_sec + v.notify_interval))
1475: {
1476: if (GETFLAG(ENABLEUPNPMASK))
1477: SendSSDPNotifies2(snotify,
1478: (unsigned short)v.port,
1479: v.notify_interval << 1);
1480: memcpy(&lasttimeofday, &timeofday, sizeof(struct timeval));
1481: timeout.tv_sec = v.notify_interval;
1482: timeout.tv_usec = 0;
1483: }
1484: else
1485: {
1486: timeout.tv_sec = lasttimeofday.tv_sec + v.notify_interval
1487: - timeofday.tv_sec;
1488: if(timeofday.tv_usec > lasttimeofday.tv_usec)
1489: {
1490: timeout.tv_usec = 1000000 + lasttimeofday.tv_usec
1491: - timeofday.tv_usec;
1492: timeout.tv_sec--;
1493: }
1494: else
1495: {
1496: timeout.tv_usec = lasttimeofday.tv_usec - timeofday.tv_usec;
1497: }
1498: }
1499: }
1500: /* remove unused rules */
1501: if( v.clean_ruleset_interval
1502: && (timeofday.tv_sec >= checktime.tv_sec + v.clean_ruleset_interval))
1503: {
1504: if(rule_list)
1505: {
1506: remove_unused_rules(rule_list);
1507: rule_list = NULL;
1508: }
1509: else
1510: {
1511: rule_list = get_upnp_rules_state_list(v.clean_ruleset_threshold);
1512: }
1513: memcpy(&checktime, &timeofday, sizeof(struct timeval));
1514: }
1.1.1.2 misho 1515: /* Remove expired port mappings, based on UPnP IGD LeaseDuration
1516: * or NAT-PMP lifetime) */
1517: if(nextruletoclean_timestamp
1.1.1.3 ! misho 1518: && ((unsigned int)timeofday.tv_sec >= nextruletoclean_timestamp))
1.1.1.2 misho 1519: {
1520: syslog(LOG_DEBUG, "cleaning expired Port Mappings");
1521: get_upnp_rules_state_list(0);
1522: }
1523: if(nextruletoclean_timestamp
1.1.1.3 ! misho 1524: && ((unsigned int)timeout.tv_sec >= (nextruletoclean_timestamp - timeofday.tv_sec)))
1.1.1.2 misho 1525: {
1526: timeout.tv_sec = nextruletoclean_timestamp - timeofday.tv_sec;
1527: timeout.tv_usec = 0;
1528: syslog(LOG_DEBUG, "setting timeout to %u sec",
1529: (unsigned)timeout.tv_sec);
1530: }
1.1 misho 1531: #ifdef ENABLE_NATPMP
1.1.1.2 misho 1532: #if 0
1.1 misho 1533: /* Remove expired NAT-PMP mappings */
1.1.1.2 misho 1534: while(nextnatpmptoclean_timestamp
1535: && (timeofday.tv_sec >= nextnatpmptoclean_timestamp + startup_time))
1.1 misho 1536: {
1537: /*syslog(LOG_DEBUG, "cleaning expired NAT-PMP mappings");*/
1538: if(CleanExpiredNATPMP() < 0) {
1539: syslog(LOG_ERR, "CleanExpiredNATPMP() failed");
1540: break;
1541: }
1542: }
1.1.1.2 misho 1543: if(nextnatpmptoclean_timestamp
1544: && timeout.tv_sec >= (nextnatpmptoclean_timestamp + startup_time - timeofday.tv_sec))
1.1 misho 1545: {
1.1.1.2 misho 1546: /*syslog(LOG_DEBUG, "setting timeout to %d sec",
1547: nextnatpmptoclean_timestamp + startup_time - timeofday.tv_sec);*/
1.1 misho 1548: timeout.tv_sec = nextnatpmptoclean_timestamp + startup_time - timeofday.tv_sec;
1549: timeout.tv_usec = 0;
1550: }
1551: #endif
1.1.1.2 misho 1552: #endif
1.1.1.3 ! misho 1553: #ifdef ENABLE_6FC_SERVICE
! 1554: /* Clean up expired IPv6 PinHoles */
! 1555: next_pinhole_ts = 0;
! 1556: upnp_clean_expired_pinholes(&next_pinhole_ts);
! 1557: if(next_pinhole_ts &&
! 1558: timeout.tv_sec >= (int)(next_pinhole_ts - timeofday.tv_sec)) {
! 1559: timeout.tv_sec = next_pinhole_ts - timeofday.tv_sec;
! 1560: timeout.tv_usec = 0;
! 1561: }
! 1562: #endif
1.1 misho 1563:
1564: /* select open sockets (SSDP, HTTP listen, and all HTTP soap sockets) */
1565: FD_ZERO(&readset);
1.1.1.3 ! misho 1566: FD_ZERO(&writeset);
1.1 misho 1567:
1.1.1.3 ! misho 1568: if (sudp >= 0)
1.1 misho 1569: {
1570: FD_SET(sudp, &readset);
1571: max_fd = MAX( max_fd, sudp);
1.1.1.2 misho 1572: #ifdef USE_IFACEWATCHER
1573: if (sifacewatcher >= 0)
1574: {
1575: FD_SET(sifacewatcher, &readset);
1576: max_fd = MAX(max_fd, sifacewatcher);
1577: }
1578: #endif
1.1 misho 1579: }
1.1.1.3 ! misho 1580: if (shttpl >= 0)
1.1 misho 1581: {
1582: FD_SET(shttpl, &readset);
1583: max_fd = MAX( max_fd, shttpl);
1584: }
1.1.1.2 misho 1585: #ifdef ENABLE_IPV6
1586: if (sudpv6 >= 0)
1587: {
1588: FD_SET(sudpv6, &readset);
1589: max_fd = MAX( max_fd, sudpv6);
1590: }
1591: #endif
1592:
1593: #ifdef ENABLE_NFQUEUE
1.1.1.3 ! misho 1594: if (nfqh >= 0)
1.1.1.2 misho 1595: {
1596: FD_SET(nfqh, &readset);
1597: max_fd = MAX( max_fd, nfqh);
1598: }
1599: #endif
1.1 misho 1600:
1601: i = 0; /* active HTTP connections count */
1602: for(e = upnphttphead.lh_first; e != NULL; e = e->entries.le_next)
1603: {
1.1.1.3 ! misho 1604: if(e->socket >= 0)
1.1 misho 1605: {
1.1.1.3 ! misho 1606: if(e->state <= EWaitingForHttpContent)
! 1607: FD_SET(e->socket, &readset);
! 1608: else if(e->state == ESendingAndClosing)
! 1609: FD_SET(e->socket, &writeset);
! 1610: else
! 1611: continue;
! 1612: max_fd = MAX(max_fd, e->socket);
1.1 misho 1613: i++;
1614: }
1615: }
1616: /* for debug */
1617: #ifdef DEBUG
1618: if(i > 1)
1619: {
1620: syslog(LOG_DEBUG, "%d active incoming HTTP connections", i);
1621: }
1622: #endif
1623: #ifdef ENABLE_NATPMP
1.1.1.2 misho 1624: for(i=0; i<addr_count; i++) {
1.1 misho 1625: if(snatpmp[i] >= 0) {
1626: FD_SET(snatpmp[i], &readset);
1627: max_fd = MAX( max_fd, snatpmp[i]);
1628: }
1629: }
1630: #endif
1631: #ifdef USE_MINIUPNPDCTL
1632: if(sctl >= 0) {
1633: FD_SET(sctl, &readset);
1634: max_fd = MAX( max_fd, sctl);
1635: }
1.1.1.3 ! misho 1636:
1.1 misho 1637: for(ectl = ctllisthead.lh_first; ectl; ectl = ectl->entries.le_next)
1638: {
1639: if(ectl->socket >= 0) {
1640: FD_SET(ectl->socket, &readset);
1641: max_fd = MAX( max_fd, ectl->socket);
1642: }
1643: }
1644: #endif
1645:
1646: #ifdef ENABLE_EVENTS
1647: upnpevents_selectfds(&readset, &writeset, &max_fd);
1648: #endif
1649:
1650: if(select(max_fd+1, &readset, &writeset, 0, &timeout) < 0)
1651: {
1652: if(quitting) goto shutdown;
1653: if(errno == EINTR) continue; /* interrupted by a signal, start again */
1654: syslog(LOG_ERR, "select(all): %m");
1655: syslog(LOG_ERR, "Failed to select open sockets. EXITING");
1656: return 1; /* very serious cause of error */
1657: }
1658: #ifdef USE_MINIUPNPDCTL
1659: for(ectl = ctllisthead.lh_first; ectl;)
1660: {
1661: ectlnext = ectl->entries.le_next;
1662: if((ectl->socket >= 0) && FD_ISSET(ectl->socket, &readset))
1663: {
1664: char buf[256];
1665: int l;
1666: l = read(ectl->socket, buf, sizeof(buf));
1667: if(l > 0)
1668: {
1669: /*write(ectl->socket, buf, l);*/
1670: write_command_line(ectl->socket, argc, argv);
1.1.1.3 ! misho 1671: #ifndef DISABLE_CONFIG_FILE
1.1 misho 1672: write_option_list(ectl->socket);
1.1.1.3 ! misho 1673: #endif
1.1 misho 1674: write_permlist(ectl->socket, upnppermlist, num_upnpperm);
1675: write_upnphttp_details(ectl->socket, upnphttphead.lh_first);
1676: write_ctlsockets_list(ectl->socket, ctllisthead.lh_first);
1677: write_ruleset_details(ectl->socket);
1678: #ifdef ENABLE_EVENTS
1679: write_events_details(ectl->socket);
1680: #endif
1681: /* close the socket */
1682: close(ectl->socket);
1683: ectl->socket = -1;
1684: }
1685: else
1686: {
1687: close(ectl->socket);
1688: ectl->socket = -1;
1689: }
1690: }
1691: if(ectl->socket < 0)
1692: {
1693: LIST_REMOVE(ectl, entries);
1694: free(ectl);
1695: }
1696: ectl = ectlnext;
1697: }
1698: if((sctl >= 0) && FD_ISSET(sctl, &readset))
1699: {
1700: int s;
1701: struct sockaddr_un clientname;
1702: struct ctlelem * tmp;
1703: socklen_t clientnamelen = sizeof(struct sockaddr_un);
1.1.1.3 ! misho 1704: /*syslog(LOG_DEBUG, "sctl!");*/
1.1 misho 1705: s = accept(sctl, (struct sockaddr *)&clientname,
1706: &clientnamelen);
1707: syslog(LOG_DEBUG, "sctl! : '%s'", clientname.sun_path);
1708: tmp = malloc(sizeof(struct ctlelem));
1.1.1.3 ! misho 1709: if (tmp == NULL)
! 1710: {
! 1711: syslog(LOG_ERR, "Unable to allocate memory for ctlelem in main()");
! 1712: close(s);
! 1713: }
! 1714: else
! 1715: {
! 1716: tmp->socket = s;
! 1717: LIST_INSERT_HEAD(&ctllisthead, tmp, entries);
! 1718: }
1.1 misho 1719: }
1720: #endif
1721: #ifdef ENABLE_EVENTS
1722: upnpevents_processfds(&readset, &writeset);
1723: #endif
1724: #ifdef ENABLE_NATPMP
1725: /* process NAT-PMP packets */
1.1.1.2 misho 1726: for(i=0; i<addr_count; i++)
1.1 misho 1727: {
1728: if((snatpmp[i] >= 0) && FD_ISSET(snatpmp[i], &readset))
1729: {
1730: ProcessIncomingNATPMPPacket(snatpmp[i]);
1731: }
1732: }
1733: #endif
1734: /* process SSDP packets */
1735: if(sudp >= 0 && FD_ISSET(sudp, &readset))
1736: {
1737: /*syslog(LOG_INFO, "Received UDP Packet");*/
1738: ProcessSSDPRequest(sudp, (unsigned short)v.port);
1739: }
1.1.1.2 misho 1740: #ifdef ENABLE_IPV6
1741: if(sudpv6 >= 0 && FD_ISSET(sudpv6, &readset))
1742: {
1743: syslog(LOG_INFO, "Received UDP Packet (IPv6)");
1744: ProcessSSDPRequest(sudpv6, (unsigned short)v.port);
1745: }
1746: #endif
1747: #ifdef USE_IFACEWATCHER
1748: /* process kernel notifications */
1749: if (sifacewatcher >= 0 && FD_ISSET(sifacewatcher, &readset))
1750: ProcessInterfaceWatchNotify(sifacewatcher);
1751: #endif
1752:
1.1 misho 1753: /* process active HTTP connections */
1754: /* LIST_FOREACH macro is not available under linux */
1755: for(e = upnphttphead.lh_first; e != NULL; e = e->entries.le_next)
1756: {
1.1.1.3 ! misho 1757: if(e->socket >= 0)
1.1 misho 1758: {
1.1.1.3 ! misho 1759: if(FD_ISSET(e->socket, &readset) ||
! 1760: FD_ISSET(e->socket, &writeset))
! 1761: {
! 1762: Process_upnphttp(e);
! 1763: }
1.1 misho 1764: }
1765: }
1766: /* process incoming HTTP connections */
1767: if(shttpl >= 0 && FD_ISSET(shttpl, &readset))
1768: {
1769: int shttp;
1770: socklen_t clientnamelen;
1.1.1.2 misho 1771: #ifdef ENABLE_IPV6
1772: struct sockaddr_storage clientname;
1773: clientnamelen = sizeof(struct sockaddr_storage);
1774: #else
1.1 misho 1775: struct sockaddr_in clientname;
1776: clientnamelen = sizeof(struct sockaddr_in);
1.1.1.2 misho 1777: #endif
1.1 misho 1778: shttp = accept(shttpl, (struct sockaddr *)&clientname, &clientnamelen);
1779: if(shttp<0)
1780: {
1.1.1.3 ! misho 1781: /* ignore EAGAIN, EWOULDBLOCK, EINTR, we just try again later */
! 1782: if(errno != EAGAIN && errno != EWOULDBLOCK && errno != EINTR)
! 1783: syslog(LOG_ERR, "accept(http): %m");
1.1 misho 1784: }
1785: else
1786: {
1787: struct upnphttp * tmp = 0;
1.1.1.2 misho 1788: char addr_str[64];
1789:
1790: sockaddr_to_string((struct sockaddr *)&clientname, addr_str, sizeof(addr_str));
1791: syslog(LOG_INFO, "HTTP connection from %s", addr_str);
1.1.1.3 ! misho 1792: if(get_lan_for_peer((struct sockaddr *)&clientname) == NULL)
1.1 misho 1793: {
1.1.1.3 ! misho 1794: /* The peer is not a LAN ! */
! 1795: syslog(LOG_WARNING,
! 1796: "HTTP peer %s is not from a LAN, closing the connection",
! 1797: addr_str);
! 1798: close(shttp);
! 1799: }
! 1800: else
! 1801: {
! 1802: /* Create a new upnphttp object and add it to
! 1803: * the active upnphttp object list */
! 1804: tmp = New_upnphttp(shttp);
! 1805: if(tmp)
1.1.1.2 misho 1806: {
1.1.1.3 ! misho 1807: #ifdef ENABLE_IPV6
! 1808: if(clientname.ss_family == AF_INET)
1.1.1.2 misho 1809: {
1.1.1.3 ! misho 1810: tmp->clientaddr = ((struct sockaddr_in *)&clientname)->sin_addr;
1.1.1.2 misho 1811: }
1.1.1.3 ! misho 1812: else if(clientname.ss_family == AF_INET6)
1.1.1.2 misho 1813: {
1.1.1.3 ! misho 1814: struct sockaddr_in6 * addr = (struct sockaddr_in6 *)&clientname;
! 1815: if(IN6_IS_ADDR_V4MAPPED(&addr->sin6_addr))
! 1816: {
! 1817: memcpy(&tmp->clientaddr,
! 1818: &addr->sin6_addr.s6_addr[12],
! 1819: 4);
! 1820: }
! 1821: else
! 1822: {
! 1823: tmp->ipv6 = 1;
! 1824: memcpy(&tmp->clientaddr_v6,
! 1825: &addr->sin6_addr,
! 1826: sizeof(struct in6_addr));
! 1827: }
1.1.1.2 misho 1828: }
1829: #else
1.1.1.3 ! misho 1830: tmp->clientaddr = clientname.sin_addr;
1.1.1.2 misho 1831: #endif
1.1.1.3 ! misho 1832: LIST_INSERT_HEAD(&upnphttphead, tmp, entries);
! 1833: }
! 1834: else
! 1835: {
! 1836: syslog(LOG_ERR, "New_upnphttp() failed");
! 1837: close(shttp);
! 1838: }
1.1 misho 1839: }
1840: }
1841: }
1.1.1.2 misho 1842: #ifdef ENABLE_NFQUEUE
1843: /* process NFQ packets */
1844: if(nfqh >= 0 && FD_ISSET(nfqh, &readset))
1845: {
1846: /* syslog(LOG_INFO, "Received NFQUEUE Packet");*/
1847: ProcessNFQUEUE(nfqh);
1848: }
1849: #endif
1.1 misho 1850: /* delete finished HTTP connections */
1851: for(e = upnphttphead.lh_first; e != NULL; )
1852: {
1853: next = e->entries.le_next;
1.1.1.3 ! misho 1854: if(e->state >= EToDelete)
1.1 misho 1855: {
1856: LIST_REMOVE(e, entries);
1857: Delete_upnphttp(e);
1858: }
1859: e = next;
1860: }
1861:
1862: } /* end of main loop */
1863:
1864: shutdown:
1865: /* close out open sockets */
1866: while(upnphttphead.lh_first != NULL)
1867: {
1868: e = upnphttphead.lh_first;
1869: LIST_REMOVE(e, entries);
1870: Delete_upnphttp(e);
1871: }
1872:
1873: if (sudp >= 0) close(sudp);
1874: if (shttpl >= 0) close(shttpl);
1.1.1.2 misho 1875: #ifdef ENABLE_IPV6
1876: if (sudpv6 >= 0) close(sudpv6);
1877: #endif
1878: #ifdef USE_IFACEWATCHER
1879: if(sifacewatcher >= 0) close(sifacewatcher);
1880: #endif
1.1 misho 1881: #ifdef ENABLE_NATPMP
1.1.1.2 misho 1882: for(i=0; i<addr_count; i++) {
1.1 misho 1883: if(snatpmp[i]>=0)
1884: {
1885: close(snatpmp[i]);
1886: snatpmp[i] = -1;
1887: }
1888: }
1889: #endif
1890: #ifdef USE_MINIUPNPDCTL
1891: if(sctl>=0)
1892: {
1893: close(sctl);
1894: sctl = -1;
1895: if(unlink("/var/run/miniupnpd.ctl") < 0)
1896: {
1897: syslog(LOG_ERR, "unlink() %m");
1898: }
1899: }
1900: #endif
1.1.1.3 ! misho 1901:
1.1 misho 1902: if (GETFLAG(ENABLEUPNPMASK))
1903: {
1.1.1.3 ! misho 1904: #ifndef ENABLE_IPV6
1.1.1.2 misho 1905: if(SendSSDPGoodbye(snotify, addr_count) < 0)
1.1.1.3 ! misho 1906: #else
! 1907: if(SendSSDPGoodbye(snotify, addr_count * 2) < 0)
! 1908: #endif
1.1 misho 1909: {
1910: syslog(LOG_ERR, "Failed to broadcast good-bye notifications");
1911: }
1.1.1.3 ! misho 1912: #ifndef ENABLE_IPV6
! 1913: for(i = 0; i < addr_count; i++)
! 1914: #else
! 1915: for(i = 0; i < addr_count * 2; i++)
! 1916: #endif
1.1 misho 1917: close(snotify[i]);
1918: }
1919:
1.1.1.3 ! misho 1920: if(pidfilename && (unlink(pidfilename) < 0))
1.1 misho 1921: {
1922: syslog(LOG_ERR, "Failed to remove pidfile %s: %m", pidfilename);
1923: }
1924:
1.1.1.2 misho 1925: /* delete lists */
1926: while(lan_addrs.lh_first != NULL)
1927: {
1928: lan_addr = lan_addrs.lh_first;
1929: LIST_REMOVE(lan_addrs.lh_first, list);
1930: free(lan_addr);
1931: }
1932:
1933: #ifdef ENABLE_NATPMP
1934: free(snatpmp);
1935: #endif
1936: free(snotify);
1.1.1.3 ! misho 1937: closelog();
! 1938: #ifndef DISABLE_CONFIG_FILE
1.1 misho 1939: freeoptions();
1.1.1.3 ! misho 1940: #endif
! 1941:
1.1 misho 1942: return 0;
1943: }
1944:
FreeBSD-CVSweb <freebsd-cvsweb@FreeBSD.org>