File:  [ELWIX - Embedded LightWeight unIX -] / embedaddon / miniupnpd / miniupnpd.c
Revision 1.1.1.2 (vendor branch): download - view: text, annotated - select for diffs - revision graph
Tue May 29 12:55:57 2012 UTC (12 years, 2 months ago) by misho
Branches: miniupnpd, elwix, MAIN
CVS tags: v1_6elwix, HEAD
miniupnpd 1.6+patches

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

FreeBSD-CVSweb <freebsd-cvsweb@FreeBSD.org>