File:  [ELWIX - Embedded LightWeight unIX -] / embedaddon / miniupnpd / miniupnpd.c
Revision 1.1.1.3 (vendor branch): download - view: text, annotated - select for diffs - revision graph
Mon Jul 22 00:32:35 2013 UTC (10 years, 10 months ago) by misho
Branches: miniupnpd, elwix, MAIN
CVS tags: v1_8p0, v1_8, HEAD
1.8

    1: /* $Id: miniupnpd.c,v 1.1.1.3 2013/07/22 00:32:35 misho Exp $ */
    2: /* MiniUPnP project
    3:  * http://miniupnp.free.fr/ or http://miniupnp.tuxfamily.org/
    4:  * (c) 2006-2013 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: #if 0
   16: #include <linux/netfilter_ipv4.h>  /* Defines verdicts (NF_ACCEPT, etc) */
   17: #endif
   18: #include <linux/netfilter.h>
   19: #include <libnetfilter_queue/libnetfilter_queue.h>
   20: #include <linux/netfilter/nfnetlink_queue.h>
   21: #endif
   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: 
   52: #include "macros.h"
   53: #include "upnpglobalvars.h"
   54: #include "upnphttp.h"
   55: #include "upnpdescgen.h"
   56: #include "miniupnpdpath.h"
   57: #include "getifaddr.h"
   58: #include "upnpsoap.h"
   59: #include "options.h"
   60: #include "minissdp.h"
   61: #include "upnpredirect.h"
   62: #include "upnppinhole.h"
   63: #include "miniupnpdtypes.h"
   64: #include "daemonize.h"
   65: #include "upnpevents.h"
   66: #ifdef ENABLE_NATPMP
   67: #include "natpmp.h"
   68: #endif
   69: #include "commonrdr.h"
   70: #include "upnputils.h"
   71: #ifdef USE_IFACEWATCHER
   72: #include "ifacewatcher.h"
   73: #endif
   74: #ifdef ENABLE_6FC_SERVICE
   75: #ifdef USE_NETFILTER
   76: void init_iptpinhole(void);
   77: #endif
   78: #endif
   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: 
  102: /* variables used by signals */
  103: static volatile sig_atomic_t quitting = 0;
  104: volatile sig_atomic_t should_send_public_address_change_notif = 0;
  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;
  113: #ifdef ENABLE_IPV6
  114: 	struct sockaddr_in6 listenname;
  115: #else
  116: 	struct sockaddr_in listenname;
  117: #endif
  118: 	socklen_t listenname_len;
  119: 
  120: 	if( (s = socket(
  121: #ifdef ENABLE_IPV6
  122: 	                PF_INET6,
  123: #else
  124: 	                PF_INET,
  125: #endif
  126: 	                SOCK_STREAM, 0)) < 0)
  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: 	}
  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
  144: 
  145: 	if(!set_non_blocking(s))
  146: 	{
  147: 		syslog(LOG_WARNING, "set_non_blocking(http): %m");
  148: 	}
  149: 
  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
  157: 	listenname.sin_family = AF_INET;
  158: 	listenname.sin_port = htons(port);
  159: 	listenname.sin_addr.s_addr = htonl(INADDR_ANY);
  160: 	listenname_len =  sizeof(struct sockaddr_in);
  161: #endif
  162: 
  163: 	if(bind(s, (struct sockaddr *)&listenname, listenname_len) < 0)
  164: 	{
  165: 		syslog(LOG_ERR, "bind(http): %m");
  166: 		close(s);
  167: 		return -1;
  168: 	}
  169: 
  170: 	if(listen(s, 5) < 0)
  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: 
  210:         /* Get a queue connection handle from the module */
  211:         if (!(nfqHandle = nfq_open())) {
  212: 		syslog(LOG_ERR, "Error in nfq_open(): %m");
  213:                 return -1;
  214:         }
  215: 
  216:         /* Unbind the handler from processing any IP packets
  217:            Not totally sure why this is done, or if it's necessary... */
  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: 
  223:         /* Bind this handler to process IP packets... */
  224:         if (nfq_bind_pf(nfqHandle, AF_INET) < 0) {
  225: 		syslog(LOG_ERR, "Error in nfq_bind_pf(): %m");
  226:                 return -1;
  227:         }
  228: 
  229:         /*      Install a callback on queue -Q */
  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: 
  235:         /*      Turn on packet copy mode */
  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);
  273: 
  274: 		/* packets we are interested in are UDP multicast to 239.255.255.250:1900
  275: 		 * and start with a data string M-SEARCH
  276: 		 */
  277: 		if ( (dport == 1900) && (id_protocol == IPPROTO_UDP)
  278: 			&& (ssdp.sin_addr.s_addr == iph->ip_dst.s_addr) ) {
  279: 
  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;
  289: 
  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);*/
  296: 					ProcessSSDPData (sudp, dd, size - x,
  297: 					                 &sendername, (unsigned short) 5555);
  298: 				}
  299: 			}
  300: 		}
  301: 
  302: 		nfq_set_verdict(qh, id, NF_ACCEPT, 0, NULL);
  303: 
  304: 	} else {
  305: 		syslog(LOG_ERR,"nfq_get_msg_packet_hdr failed");
  306: 		return 1;
  307: 		/* from nfqueue source: 0 = ok, >0 = soft error, <0 hard error */
  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: 
  387: #ifndef DISABLE_CONFIG_FILE
  388: static void
  389: write_option_list(int fd)
  390: {
  391: 	char buffer[256];
  392: 	int len;
  393: 	unsigned int i;
  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: }
  403: #endif
  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: 
  423: /* Handler for the SIGTERM signal (kill)
  424:  * SIGINT is also handled */
  425: static void
  426: sigterm(int sig)
  427: {
  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 ? */
  432: 
  433: #if 0
  434: 	/* calling syslog() is forbidden in signal handler according to
  435: 	 * signal(3) */
  436: 	syslog(LOG_NOTICE, "received signal %d, good-bye", sig);
  437: #endif
  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: {
  447: 	UNUSED(sig);
  448: #if 0
  449: 	/* calling syslog() is forbidden in signal handler according to
  450: 	 * signal(3) */
  451: 	syslog(LOG_INFO, "received signal %d, public ip address change", sig);
  452: #endif
  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
  537:  * ex: 192.168.1.1/24 or 192.168.1.1/255.255.255.0
  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:  *
  542:  * Can also use the interface name (ie eth0)
  543:  *
  544:  * return value :
  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;
  552: 	char tmp[16];
  553: 
  554: 	memset(lan_addr, 0, sizeof(struct lan_addr_s));
  555: 	p = str;
  556: 	while(*p && *p != '/' && !isspace(*p))
  557: 		p++;
  558: 	n = p - str;
  559: 	if(!isdigit(str[0]) && n < (int)sizeof(lan_addr->ifname))
  560: 	{
  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;
  566: 	}
  567: 	else
  568: 	{
  569: 		if(n>15)
  570: 			goto parselan_error;
  571: 		memcpy(lan_addr->str, str, n);
  572: 		lan_addr->str[n] = '\0';
  573: 	}
  574: 	if(!inet_aton(lan_addr->str, &lan_addr->addr))
  575: 		goto parselan_error;
  576: 	if(*p == '/')
  577: 	{
  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);
  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
  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
  634: 	return 0;
  635: parselan_error:
  636: 	fprintf(stderr, "Error parsing address/mask (or interface name) : %s\n",
  637: 	        str);
  638: 	return -1;
  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;
  660: #ifndef DISABLE_CONFIG_FILE
  661: 	int options_flag = 0;
  662: 	const char * optionsfile = DEFAULT_CONFIG;
  663: #endif /* DISABLE_CONFIG_FILE */
  664: 	struct lan_addr_s * lan_addr;
  665: 	struct lan_addr_s * lan_addr2;
  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: 	}
  673: #ifndef DISABLE_CONFIG_FILE
  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: 	}
  684: #endif /* DISABLE_CONFIG_FILE */
  685: 
  686: 	/* set initial values */
  687: 	SETFLAG(ENABLEUPNPMASK);	/* UPnP is enabled by default */
  688: 
  689: 	LIST_INIT(&lan_addrs);
  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 */
  694: #ifndef DISABLE_CONFIG_FILE
  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: 	{
  705: 		for(i=0; i<(int)num_options; i++)
  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:
  716: 				lan_addr = (struct lan_addr_s *) malloc(sizeof(struct lan_addr_s));
  717: 				if (lan_addr == NULL)
  718: 				{
  719: 					fprintf(stderr, "malloc(sizeof(struct lan_addr_s)): %m");
  720: 					break;
  721: 				}
  722: 				if(parselanaddr(lan_addr, ary_options[i].value) != 0)
  723: 				{
  724: 					fprintf(stderr, "can't parse \"%s\" as valid lan address\n", ary_options[i].value);
  725: 					free(lan_addr);
  726: 					break;
  727: 				}
  728: 				LIST_INSERT_HEAD(&lan_addrs, lan_addr, list);
  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;
  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;
  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;
  761: #if defined(USE_PF) || defined(USE_IPF)
  762: 			case UPNPPACKET_LOG:
  763: 				if(strcmp(ary_options[i].value, "yes") == 0)
  764: 					SETFLAG(LOGPACKETSMASK);	/*logpackets = 1;*/
  765: 				break;
  766: #endif
  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';
  774: 				break;
  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
  786: 			case UPNPANCHOR:
  787: 				anchor_name = ary_options[i].value;
  788: 				break;
  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: 	}
  834: #endif /* DISABLE_CONFIG_FILE */
  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;
  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;
  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;
  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;
  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;*/
  903: #if defined(USE_PF) || defined(USE_IPF)
  904: 		case 'L':
  905: 			/*logpackets = 1;*/
  906: 			SETFLAG(LOGPACKETSMASK);
  907: 			break;
  908: #endif
  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':
  985: #ifndef MULTIPLE_EXTERNAL_IP
  986: 			if(i+1 < argc)
  987: 			{
  988: 				i++;
  989: 				lan_addr = (struct lan_addr_s *) malloc(sizeof(struct lan_addr_s));
  990: 				if (lan_addr == NULL)
  991: 				{
  992: 					fprintf(stderr, "malloc(sizeof(struct lan_addr_s)): %m");
  993: 					break;
  994: 				}
  995: 				if(parselanaddr(lan_addr, argv[i]) != 0)
  996: 				{
  997: 					fprintf(stderr, "can't parse \"%s\" as valid lan address\n", argv[i]);
  998: 					free(lan_addr);
  999: 					break;
 1000: 				}
 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)
 1003: 				{
 1004: 					if (0 == strncmp(lan_addr2->str, lan_addr->str, 15))
 1005: 						break;
 1006: 				}
 1007: 				if (lan_addr2 == NULL)
 1008: 					LIST_INSERT_HEAD(&lan_addrs, lan_addr, list);
 1009: 			}
 1010: 			else
 1011: 				fprintf(stderr, "Option -%c takes one argument.\n", argv[i][1]);
 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]);
 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: 	}
 1077: 	if(!ext_if_name || !lan_addrs.lh_first)
 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;
 1117: 	}
 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,
 1130: 		         "http://%s/", lan_addrs.lh_first->str);
 1131: 		         /*"http://%s:%d/", lan_addrs.lh_first->str, 80);*/
 1132: 	}
 1133: 
 1134: 	/* set signal handler */
 1135: 	memset(&sa, 0, sizeof(struct sigaction));
 1136: 	sa.sa_handler = sigterm;
 1137: 
 1138: 	if(sigaction(SIGTERM, &sa, NULL) < 0)
 1139: 	{
 1140: 		syslog(LOG_ERR, "Failed to set %s handler. EXITING", "SIGTERM");
 1141: 		return 1;
 1142: 	}
 1143: 	if(sigaction(SIGINT, &sa, NULL) < 0)
 1144: 	{
 1145: 		syslog(LOG_ERR, "Failed to set %s handler. EXITING", "SIGINT");
 1146: 		return 1;
 1147: 	}
 1148: 	sa.sa_handler = SIG_IGN;
 1149: 	if(sigaction(SIGPIPE, &sa, NULL) < 0)
 1150: 	{
 1151: 		syslog(LOG_ERR, "Failed to ignore SIGPIPE signals");
 1152: 	}
 1153: 	sa.sa_handler = sigusr1;
 1154: 	if(sigaction(SIGUSR1, &sa, NULL) < 0)
 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: 	}
 1164: #ifdef ENABLE_6FC_SERVICE
 1165: #ifdef USE_NETFILTER
 1166: 	init_iptpinhole();
 1167: #endif
 1168: #endif
 1169: 
 1170: 	if(writepidfile(pidfilename, pid) < 0)
 1171: 		pidfilename = NULL;
 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"
 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]"
 1189: #else
 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]"
 1199: #endif
 1200: 			"\n"
 1201: 			/*"[-l logfile] " not functionnal */
 1202: 			"\t\t[-u uuid] [-s serial] [-m model_number] \n"
 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"
 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
 1211: 			"\t\t[-A \"permission rule\"]\n"
 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"
 1217: #if defined(USE_PF) || defined(USE_IPF)
 1218: 			"\t-L sets packet log in pf and ipf on.\n"
 1219: #endif
 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
 1224: 			"\t-N enable NAT-PMP functionality.\n"
 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
 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"
 1235: #endif
 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"
 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;
 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
 1257: #ifdef ENABLE_NATPMP
 1258: 	int * snatpmp = NULL;
 1259: #endif
 1260: #ifdef ENABLE_NFQUEUE
 1261: 	int nfqh = -1;
 1262: #endif
 1263: #ifdef USE_IFACEWATCHER
 1264: 	int sifacewatcher = -1;
 1265: #endif
 1266: 
 1267: 	int * snotify = NULL;
 1268: 	int addr_count;
 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};
 1286: 	struct lan_addr_s * lan_addr;
 1287: #ifdef ENABLE_6FC_SERVICE
 1288: 	unsigned int next_pinhole_ts;
 1289: #endif
 1290: 
 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++;
 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: 	}
 1305: #ifdef ENABLE_NATPMP
 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: 	}
 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: 
 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: 
 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);
 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
 1365: 
 1366: 		/* open socket for SSDP connections */
 1367: 		sudp = OpenAndConfSSDPReceiveSocket(0);
 1368: 		if(sudp < 0)
 1369: 		{
 1370: 			syslog(LOG_NOTICE, "Failed to open socket for receiving SSDP. Trying to use MiniSSDPd");
 1371: 			if(SubmitServicesToMiniSSDPD(lan_addrs.lh_first->str, v.port) < 0) {
 1372: 				syslog(LOG_ERR, "Failed to connect to MiniSSDPd. EXITING");
 1373: 				return 1;
 1374: 			}
 1375: 		}
 1376: #ifdef ENABLE_IPV6
 1377: 		sudpv6 = OpenAndConfSSDPReceiveSocket(1);
 1378: 		if(sudpv6 < 0)
 1379: 		{
 1380: 			syslog(LOG_WARNING, "Failed to open socket for receiving SSDP (IP v6).");
 1381: 		}
 1382: #endif
 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: 		}
 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
 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: 		}
 1416: #if 0
 1417: 		ScanNATPMPforExpiration();
 1418: #endif
 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
 1438: 
 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));
 1446: 		}
 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: 		}
 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: 		}
 1515: 		/* Remove expired port mappings, based on UPnP IGD LeaseDuration
 1516: 		 * or NAT-PMP lifetime) */
 1517: 		if(nextruletoclean_timestamp
 1518: 		  && ((unsigned int)timeofday.tv_sec >= nextruletoclean_timestamp))
 1519: 		{
 1520: 			syslog(LOG_DEBUG, "cleaning expired Port Mappings");
 1521: 			get_upnp_rules_state_list(0);
 1522: 		}
 1523: 		if(nextruletoclean_timestamp
 1524: 		  && ((unsigned int)timeout.tv_sec >= (nextruletoclean_timestamp - timeofday.tv_sec)))
 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: 		}
 1531: #ifdef ENABLE_NATPMP
 1532: #if 0
 1533: 		/* Remove expired NAT-PMP mappings */
 1534: 		while(nextnatpmptoclean_timestamp
 1535: 		     && (timeofday.tv_sec >= nextnatpmptoclean_timestamp + startup_time))
 1536: 		{
 1537: 			/*syslog(LOG_DEBUG, "cleaning expired NAT-PMP mappings");*/
 1538: 			if(CleanExpiredNATPMP() < 0) {
 1539: 				syslog(LOG_ERR, "CleanExpiredNATPMP() failed");
 1540: 				break;
 1541: 			}
 1542: 		}
 1543: 		if(nextnatpmptoclean_timestamp
 1544: 		  && timeout.tv_sec >= (nextnatpmptoclean_timestamp + startup_time - timeofday.tv_sec))
 1545: 		{
 1546: 			/*syslog(LOG_DEBUG, "setting timeout to %d sec",
 1547: 			       nextnatpmptoclean_timestamp + startup_time - timeofday.tv_sec);*/
 1548: 			timeout.tv_sec = nextnatpmptoclean_timestamp + startup_time - timeofday.tv_sec;
 1549: 			timeout.tv_usec = 0;
 1550: 		}
 1551: #endif
 1552: #endif
 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
 1563: 
 1564: 		/* select open sockets (SSDP, HTTP listen, and all HTTP soap sockets) */
 1565: 		FD_ZERO(&readset);
 1566: 		FD_ZERO(&writeset);
 1567: 
 1568: 		if (sudp >= 0)
 1569: 		{
 1570: 			FD_SET(sudp, &readset);
 1571: 			max_fd = MAX( max_fd, sudp);
 1572: #ifdef USE_IFACEWATCHER
 1573: 			if (sifacewatcher >= 0)
 1574: 			{
 1575: 				FD_SET(sifacewatcher, &readset);
 1576: 				max_fd = MAX(max_fd, sifacewatcher);
 1577: 			}
 1578: #endif
 1579: 		}
 1580: 		if (shttpl >= 0)
 1581: 		{
 1582: 			FD_SET(shttpl, &readset);
 1583: 			max_fd = MAX( max_fd, shttpl);
 1584: 		}
 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
 1594: 		if (nfqh >= 0)
 1595: 		{
 1596: 			FD_SET(nfqh, &readset);
 1597: 			max_fd = MAX( max_fd, nfqh);
 1598: 		}
 1599: #endif
 1600: 
 1601: 		i = 0;	/* active HTTP connections count */
 1602: 		for(e = upnphttphead.lh_first; e != NULL; e = e->entries.le_next)
 1603: 		{
 1604: 			if(e->socket >= 0)
 1605: 			{
 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);
 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
 1624: 		for(i=0; i<addr_count; i++) {
 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: 		}
 1636: 
 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);
 1671: #ifndef DISABLE_CONFIG_FILE
 1672: 					write_option_list(ectl->socket);
 1673: #endif
 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);
 1704: 			/*syslog(LOG_DEBUG, "sctl!");*/
 1705: 			s = accept(sctl, (struct sockaddr *)&clientname,
 1706: 			           &clientnamelen);
 1707: 			syslog(LOG_DEBUG, "sctl! : '%s'", clientname.sun_path);
 1708: 			tmp = malloc(sizeof(struct ctlelem));
 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: 			}
 1719: 		}
 1720: #endif
 1721: #ifdef ENABLE_EVENTS
 1722: 		upnpevents_processfds(&readset, &writeset);
 1723: #endif
 1724: #ifdef ENABLE_NATPMP
 1725: 		/* process NAT-PMP packets */
 1726: 		for(i=0; i<addr_count; i++)
 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: 		}
 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: 
 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: 		{
 1757: 			if(e->socket >= 0)
 1758: 			{
 1759: 				if(FD_ISSET(e->socket, &readset) ||
 1760: 				   FD_ISSET(e->socket, &writeset))
 1761: 				{
 1762: 					Process_upnphttp(e);
 1763: 				}
 1764: 			}
 1765: 		}
 1766: 		/* process incoming HTTP connections */
 1767: 		if(shttpl >= 0 && FD_ISSET(shttpl, &readset))
 1768: 		{
 1769: 			int shttp;
 1770: 			socklen_t clientnamelen;
 1771: #ifdef ENABLE_IPV6
 1772: 			struct sockaddr_storage clientname;
 1773: 			clientnamelen = sizeof(struct sockaddr_storage);
 1774: #else
 1775: 			struct sockaddr_in clientname;
 1776: 			clientnamelen = sizeof(struct sockaddr_in);
 1777: #endif
 1778: 			shttp = accept(shttpl, (struct sockaddr *)&clientname, &clientnamelen);
 1779: 			if(shttp<0)
 1780: 			{
 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");
 1784: 			}
 1785: 			else
 1786: 			{
 1787: 				struct upnphttp * tmp = 0;
 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);
 1792: 				if(get_lan_for_peer((struct sockaddr *)&clientname) == NULL)
 1793: 				{
 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)
 1806: 					{
 1807: #ifdef ENABLE_IPV6
 1808: 						if(clientname.ss_family == AF_INET)
 1809: 						{
 1810: 							tmp->clientaddr = ((struct sockaddr_in *)&clientname)->sin_addr;
 1811: 						}
 1812: 						else if(clientname.ss_family == AF_INET6)
 1813: 						{
 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: 							}
 1828: 						}
 1829: #else
 1830: 						tmp->clientaddr = clientname.sin_addr;
 1831: #endif
 1832: 						LIST_INSERT_HEAD(&upnphttphead, tmp, entries);
 1833: 					}
 1834: 					else
 1835: 					{
 1836: 						syslog(LOG_ERR, "New_upnphttp() failed");
 1837: 						close(shttp);
 1838: 					}
 1839: 				}
 1840: 			}
 1841: 		}
 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
 1850: 		/* delete finished HTTP connections */
 1851: 		for(e = upnphttphead.lh_first; e != NULL; )
 1852: 		{
 1853: 			next = e->entries.le_next;
 1854: 			if(e->state >= EToDelete)
 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);
 1875: #ifdef ENABLE_IPV6
 1876: 	if (sudpv6 >= 0) close(sudpv6);
 1877: #endif
 1878: #ifdef USE_IFACEWATCHER
 1879: 	if(sifacewatcher >= 0) close(sifacewatcher);
 1880: #endif
 1881: #ifdef ENABLE_NATPMP
 1882: 	for(i=0; i<addr_count; i++) {
 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
 1901: 
 1902: 	if (GETFLAG(ENABLEUPNPMASK))
 1903: 	{
 1904: #ifndef ENABLE_IPV6
 1905: 		if(SendSSDPGoodbye(snotify, addr_count) < 0)
 1906: #else
 1907: 		if(SendSSDPGoodbye(snotify, addr_count * 2) < 0)
 1908: #endif
 1909: 		{
 1910: 			syslog(LOG_ERR, "Failed to broadcast good-bye notifications");
 1911: 		}
 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
 1917: 			close(snotify[i]);
 1918: 	}
 1919: 
 1920: 	if(pidfilename && (unlink(pidfilename) < 0))
 1921: 	{
 1922: 		syslog(LOG_ERR, "Failed to remove pidfile %s: %m", pidfilename);
 1923: 	}
 1924: 
 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);
 1937: 	closelog();
 1938: #ifndef DISABLE_CONFIG_FILE
 1939: 	freeoptions();
 1940: #endif
 1941: 
 1942: 	return 0;
 1943: }
 1944: 

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