⭐ 欢迎来到虫虫下载站! | 📦 资源下载 📁 资源专辑 ℹ️ 关于我们
⭐ 虫虫下载站

📄 miniupnpd.c

📁 miniupnpd可以在嵌入式linux中实现upnp功能
💻 C
📖 第 1 页 / 共 2 页
字号:
			break;		case 'B':			if(i+2<argc)			{				downstream_bitrate = strtoul(argv[++i], 0, 0);				upstream_bitrate = strtoul(argv[++i], 0, 0);			}			else				fprintf(stderr, "Option -%c takes two arguments.\n", argv[i][1]);			break;		case 'a':			if(i+1 < argc)			{				int address_already_there = 0;				int j;				i++;				for(j=0; j<n_lan_addr; j++)/* for(j=0; j<v->n_lan_addr; j++)*/				{					struct lan_addr_s tmpaddr;					parselanaddr(&tmpaddr, argv[i]);					/*if(0 == strcmp(v->lan_addr[j].str, tmpaddr.str))*/					if(0 == strcmp(lan_addr[j].str, tmpaddr.str))						address_already_there = 1;				}				if(address_already_there)					break;				if(n_lan_addr < MAX_LAN_ADDR) /*if(v->n_lan_addr < MAX_LAN_ADDR)*/				{					/*v->lan_addr[v->n_lan_addr++] = argv[i];*/					/*if(parselanaddr(&v->lan_addr[v->n_lan_addr], argv[i]) == 0)*/					if(parselanaddr(&lan_addr[n_lan_addr], argv[i]) == 0)						n_lan_addr++; /*v->n_lan_addr++;*/				}				else				{					fprintf(stderr, "Too many listening ips (max: %d), ignoring %s\n",				    	    MAX_LAN_ADDR, argv[i]);				}			}			else				fprintf(stderr, "Option -%c takes one argument.\n", argv[i][1]);			break;		case 'f':			i++;	/* discarding, the config file is already read */			break;		default:			fprintf(stderr, "Unknown option: %s\n", argv[i]);		}	}	if(!ext_if_name || (/*v->*/n_lan_addr==0) || v->port<=0)	{		fprintf(stderr, "Usage:\n\t"		        "%s [-f config_file] [-i ext_ifname] [-o ext_ip]\n"#ifndef ENABLE_NATPMP				"\t\t[-a listening_ip] [-p port] [-d] [-L] [-U] [-S]\n"#else				"\t\t[-a listening_ip] [-p port] [-d] [-L] [-U] [-S] [-N]\n"#endif				/*"[-l logfile] " not functionnal */				"\t\t[-u uuid] [-s serial] [-m model_number] \n"				"\t\t[-t notify_interval] [-P pid_filename]\n"#ifdef USE_PF				"\t\t[-B down up] [-w url] [-q queue] [-T tag]\n"#else				"\t\t[-B down up] [-w url]\n"#endif		        "\nNotes:\n\tThere can be one or several listening_ips.\n"		        "\tNotify interval is in seconds. Default is 30 seconds.\n"				"\tDefault pid file is %s.\n"				"\tWith -d miniupnpd will run as a standard program.\n"				"\t-L sets packet log in pf and ipf on.\n"				"\t-S sets \"secure\" mode : clients can only add mappings to their own ip\n"				"\t-U causes miniupnpd to report system uptime instead "				"of daemon uptime.\n"				"\t-B sets bitrates reported by daemon in bits per second.\n"				"\t-w sets the presentation url. Default is http address on port 80\n"#ifdef USE_PF				"\t-q sets the ALTQ queue in pf.\n"				"\t-T sets the tag name in pf.\n"#endif		        "", argv[0], pidfilename);		return 1;	}	if(debug_flag)	{		pid = getpid();	}	else	{#ifdef USE_DAEMON		if(daemon(0, 0)<0) {			perror("daemon()");		}		pid = getpid();#else		pid = daemonize();#endif	}	openlog_option = LOG_PID|LOG_CONS;	if(debug_flag)	{		openlog_option |= LOG_PERROR;	/* also log on stderr */	}	openlog("miniupnpd", openlog_option, LOG_MINIUPNPD);	if(!debug_flag)	{		/* speed things up and ignore LOG_INFO and LOG_DEBUG */		setlogmask(LOG_UPTO(LOG_NOTICE));	}	if(checkforrunning(pidfilename) < 0)	{		syslog(LOG_ERR, "MiniUPnPd is already running. EXITING");		return 1;	}		set_startup_time(GETFLAG(SYSUPTIMEMASK)/*sysuptime*/);	/* presentation url */	if(presurl)	{		strncpy(presentationurl, presurl, PRESENTATIONURL_MAX_LEN);		presentationurl[PRESENTATIONURL_MAX_LEN-1] = '\0';	}	else	{		snprintf(presentationurl, PRESENTATIONURL_MAX_LEN,		         "http://%s/", lan_addr[0].str);		         /*"http://%s:%d/", lan_addr[0].str, 80);*/		         /*"http://%s:%d/", v->lan_addr[0].str, 80);*/	}	/* set signal handler */	memset(&sa, 0, sizeof(struct sigaction));	sa.sa_handler = sigterm;	if (sigaction(SIGTERM, &sa, NULL))	{		syslog(LOG_ERR, "Failed to set %s handler. EXITING", "SIGTERM");		return 1;	}	if (sigaction(SIGINT, &sa, NULL))	{		syslog(LOG_ERR, "Failed to set %s handler. EXITING", "SIGINT");		return 1;	}	if(signal(SIGPIPE, SIG_IGN) == SIG_ERR) {		syslog(LOG_ERR, "Failed to ignore SIGPIPE signals");	}	if(init_redirect() < 0)	{		syslog(LOG_ERR, "Failed to init redirection engine. EXITING");		return 1;	}	writepidfile(pidfilename, pid);	return 0;}/* === main === *//* process HTTP or SSDP requests */intmain(int argc, char * * argv){	int i;	int sudp = -1, shttpl = -1;#ifdef ENABLE_NATPMP	int snatpmp = -1;#endif	int snotify[MAX_LAN_ADDR];	LIST_HEAD(httplisthead, upnphttp) upnphttphead;	struct upnphttp * e = 0;	struct upnphttp * next;	fd_set readset;	/* for select() */#ifdef ENABLE_EVENTS	fd_set writeset;#endif	struct timeval timeout, timeofday, lasttimeofday = {0, 0};	int max_fd = -1;#ifdef USE_MINIUPNPDCTL	int sctl = -1;	LIST_HEAD(ctlstructhead, ctlelem) ctllisthead;	struct ctlelem * ectl;	struct ctlelem * ectlnext;#endif	struct runtime_vars v;	/* variables used for the unused-rule cleanup process */	struct rule_state * rule_list = 0;	struct timeval checktime = {0, 0};	if(init(argc, argv, &v) != 0)		return 1;	LIST_INIT(&upnphttphead);#ifdef USE_MINIUPNPDCTL	LIST_INIT(&ctllisthead);#endif	if(#ifdef ENABLE_NATPMP        !GETFLAG(ENABLENATPMPMASK) &&#endif        !GETFLAG(ENABLEUPNPMASK) ) {		syslog(LOG_ERR, "Why did you run me anyway?");		return 0;	}	if(GETFLAG(ENABLEUPNPMASK)/*enableupnp*/)	{		/* open socket for SSDP connections */		/*sudp = OpenAndConfSSDPReceiveSocket(v.n_lan_addr, v.lan_addr);*/		sudp = OpenAndConfSSDPReceiveSocket(n_lan_addr, lan_addr);		if(sudp < 0)		{			syslog(LOG_ERR, "Failed to open socket for receiving SSDP. EXITING");			return 1;		}		/* open socket for HTTP connections. Listen on the 1st LAN address */		shttpl = OpenAndConfHTTPSocket(v.port);		if(shttpl < 0)		{			syslog(LOG_ERR, "Failed to open socket for HTTP. EXITING");			return 1;		}		syslog(LOG_NOTICE, "HTTP listening on port %d", v.port);		/* open socket for sending notifications */		if(OpenAndConfSSDPNotifySockets(snotify) < 0)		{			syslog(LOG_ERR, "Failed to open sockets for sending SSDP notify "		                "messages. EXITING");			return 1;		}	}#ifdef ENABLE_NATPMP	/* open socket for NAT PMP traffic */	if(GETFLAG(ENABLENATPMPMASK))	{		snatpmp = OpenAndConfNATPMPSocket();		if(snatpmp < 0)		{			syslog(LOG_ERR, "Failed to open socket for NAT PMP.");			/*syslog(LOG_ERR, "Failed to open socket for NAT PMP. EXITING");			return 1;*/		} else {			syslog(LOG_NOTICE, "Listening for NAT-PMP traffic on port %u",			       NATPMP_PORT);		}		ScanNATPMPforExpiration();	}#endif	/* for miniupnpdctl */#ifdef USE_MINIUPNPDCTL	sctl = OpenAndConfCtlUnixSocket("/var/run/miniupnpd.ctl");#endif	/* main loop */	while(!quitting)	{		/* Check if we need to send SSDP NOTIFY messages and do it if		 * needed */		if(gettimeofday(&timeofday, 0) < 0)		{			syslog(LOG_ERR, "gettimeofday(): %m");			timeout.tv_sec = v.notify_interval;			timeout.tv_usec = 0;		}		else		{			/* the comparaison is not very precise but who cares ? */			if(timeofday.tv_sec >= (lasttimeofday.tv_sec + v.notify_interval))			{				if (GETFLAG(ENABLEUPNPMASK))					SendSSDPNotifies2(snotify,				                  (unsigned short)v.port,				                  v.notify_interval << 1);				memcpy(&lasttimeofday, &timeofday, sizeof(struct timeval));				timeout.tv_sec = v.notify_interval;				timeout.tv_usec = 0;			}			else			{				timeout.tv_sec = lasttimeofday.tv_sec + v.notify_interval				                 - timeofday.tv_sec;				if(timeofday.tv_usec > lasttimeofday.tv_usec)				{					timeout.tv_usec = 1000000 + lasttimeofday.tv_usec					                  - timeofday.tv_usec;					timeout.tv_sec--;				}				else				{					timeout.tv_usec = lasttimeofday.tv_usec - timeofday.tv_usec;				}			}		}		/* remove unused rules */		if( v.clean_ruleset_interval		  && (timeofday.tv_sec >= checktime.tv_sec + v.clean_ruleset_interval))		{			if(rule_list)			{				remove_unused_rules(rule_list);				rule_list = NULL;			}			else			{				rule_list = get_upnp_rules_state_list(v.clean_ruleset_threshold);			}			memcpy(&checktime, &timeofday, sizeof(struct timeval));		}#ifdef ENABLE_NATPMP		/* Remove expired NAT-PMP mappings */		while( nextnatpmptoclean_timestamp && (timeofday.tv_sec >= nextnatpmptoclean_timestamp + startup_time))		{			/*syslog(LOG_DEBUG, "cleaning expired NAT-PMP mappings");*/			if(CleanExpiredNATPMP() < 0) {				syslog(LOG_ERR, "CleanExpiredNATPMP() failed");				break;			}		}		if(nextnatpmptoclean_timestamp && timeout.tv_sec >= (nextnatpmptoclean_timestamp + startup_time - timeofday.tv_sec))		{			/*syslog(LOG_DEBUG, "setting timeout to %d sec", nextnatpmptoclean_timestamp + startup_time - timeofday.tv_sec);*/			timeout.tv_sec = nextnatpmptoclean_timestamp + startup_time - timeofday.tv_sec;			timeout.tv_usec = 0;		}#endif		/* select open sockets (SSDP, HTTP listen, and all HTTP soap sockets) */		FD_ZERO(&readset);		if (sudp >= 0) 		{			FD_SET(sudp, &readset);			max_fd = MAX( max_fd, sudp);		}				if (shttpl >= 0) 		{			FD_SET(shttpl, &readset);			max_fd = MAX( max_fd, shttpl);		}		i = 0;	/* active HTTP connections count */		for(e = upnphttphead.lh_first; e != NULL; e = e->entries.le_next)		{			if((e->socket >= 0) && (e->state <= 2))			{				FD_SET(e->socket, &readset);				max_fd = MAX( max_fd, e->socket);				i++;			}		}		/* for debug */#ifdef DEBUG		if(i > 1)		{			syslog(LOG_DEBUG, "%d active incoming HTTP connections", i);		}#endif#ifdef ENABLE_NATPMP		if(snatpmp >= 0) {			FD_SET(snatpmp, &readset);			max_fd = MAX( max_fd, snatpmp);		}#endif#ifdef USE_MINIUPNPDCTL		if(sctl >= 0) {			FD_SET(sctl, &readset);			max_fd = MAX( max_fd, sctl);		}				for(ectl = ctllisthead.lh_first; ectl; ectl = ectl->entries.le_next)		{			if(ectl->socket >= 0) {				FD_SET(ectl->socket, &readset);				max_fd = MAX( max_fd, ectl->socket);			}		}#endif#ifdef ENABLE_EVENTS		FD_ZERO(&writeset);		upnpevents_selectfds(&readset, &writeset, &max_fd);#endif#ifdef ENABLE_EVENTS		if(select(max_fd+1, &readset, &writeset, 0, &timeout) < 0)#else		if(select(max_fd+1, &readset, 0, 0, &timeout) < 0)#endif		{			if(quitting) goto shutdown;			syslog(LOG_ERR, "select(all): %m");			syslog(LOG_ERR, "Failed to select open sockets. EXITING");			return 1;	/* very serious cause of error */		}#ifdef USE_MINIUPNPDCTL		for(ectl = ctllisthead.lh_first; ectl;)		{			ectlnext =  ectl->entries.le_next;			if((ectl->socket >= 0) && FD_ISSET(ectl->socket, &readset))			{				char buf[256];				int l;				l = read(ectl->socket, buf, sizeof(buf));				if(l > 0)				{					/*write(ectl->socket, buf, l);*/					write_option_list(ectl->socket);					write_permlist(ectl->socket, upnppermlist, num_upnpperm);					write_upnphttp_details(ectl->socket, upnphttphead.lh_first);					write_ctlsockets_list(ectl->socket, ctllisthead.lh_first);					write_ruleset_details(ectl->socket);#ifdef ENABLE_EVENTS					write_events_details(ectl->socket);#endif					/* close the socket */					close(ectl->socket);					ectl->socket = -1;				}				else				{					close(ectl->socket);					ectl->socket = -1;				}			}			if(ectl->socket < 0)			{				LIST_REMOVE(ectl, entries);				free(ectl);			}			ectl = ectlnext;		}		if((sctl >= 0) && FD_ISSET(sctl, &readset))		{			int s;			struct sockaddr_un clientname;			struct ctlelem * tmp;			socklen_t clientnamelen = sizeof(struct sockaddr_un);			//syslog(LOG_DEBUG, "sctl!");			s = accept(sctl, (struct sockaddr *)&clientname,			           &clientnamelen);			syslog(LOG_DEBUG, "sctl! : '%s'", clientname.sun_path);			tmp = malloc(sizeof(struct ctlelem));			tmp->socket = s;			LIST_INSERT_HEAD(&ctllisthead, tmp, entries);		}#endif#ifdef ENABLE_EVENTS		upnpevents_processfds(&readset, &writeset);#endif#ifdef ENABLE_NATPMP		/* process NAT-PMP packets */		if((snatpmp >= 0) && FD_ISSET(snatpmp, &readset))		{			ProcessIncomingNATPMPPacket(snatpmp);		}#endif		/* process SSDP packets */		if(sudp >= 0 && FD_ISSET(sudp, &readset))		{			/*syslog(LOG_INFO, "Received UDP Packet");*/			/*ProcessSSDPRequest(sudp, v.lan_addr, v.n_lan_addr,*/			ProcessSSDPRequest(sudp, (unsigned short)v.port);		}		/* process active HTTP connections */		/* LIST_FOREACH macro is not available under linux */		for(e = upnphttphead.lh_first; e != NULL; e = e->entries.le_next)		{			if(  (e->socket >= 0) && (e->state <= 2)				&&(FD_ISSET(e->socket, &readset)) )			{				Process_upnphttp(e);			}		}		/* process incoming HTTP connections */		if(shttpl >= 0 && FD_ISSET(shttpl, &readset))		{			int shttp;			socklen_t clientnamelen;			struct sockaddr_in clientname;			clientnamelen = sizeof(struct sockaddr_in);			shttp = accept(shttpl, (struct sockaddr *)&clientname, &clientnamelen);			if(shttp<0)			{				syslog(LOG_ERR, "accept(http): %m");			}			else			{				struct upnphttp * tmp = 0;				syslog(LOG_INFO, "HTTP connection from %s:%d",					inet_ntoa(clientname.sin_addr),					ntohs(clientname.sin_port) );				/*if (fcntl(shttp, F_SETFL, O_NONBLOCK) < 0) {					syslog(LOG_ERR, "fcntl F_SETFL, O_NONBLOCK");				}*/				/* Create a new upnphttp object and add it to				 * the active upnphttp object list */				tmp = New_upnphttp(shttp);				if(tmp)				{					tmp->clientaddr = clientname.sin_addr;					LIST_INSERT_HEAD(&upnphttphead, tmp, entries);				}				else				{					syslog(LOG_ERR, "New_upnphttp() failed");					close(shttp);				}			}		}		/* delete finished HTTP connections */		for(e = upnphttphead.lh_first; e != NULL; )		{			next = e->entries.le_next;			if(e->state >= 100)			{				LIST_REMOVE(e, entries);				Delete_upnphttp(e);			}			e = next;		}	}shutdown:	/* close out open sockets */	while(upnphttphead.lh_first != NULL)	{		e = upnphttphead.lh_first;		LIST_REMOVE(e, entries);		Delete_upnphttp(e);	}	if (sudp >= 0) close(sudp);	if (shttpl >= 0) close(shttpl);#ifdef ENABLE_NATPMP	if(snatpmp>=0)	{		close(snatpmp);		snatpmp = -1;	}#endif#ifdef USE_MINIUPNPDCTL	if(sctl>=0)	{		close(sctl);		sctl = -1;		if(unlink("/var/run/miniupnpd.ctl") < 0)		{			syslog(LOG_ERR, "unlink() %m");		}	}#endif		/*if(SendSSDPGoodbye(snotify, v.n_lan_addr) < 0)*/	if (GETFLAG(ENABLEUPNPMASK))	{		if(SendSSDPGoodbye(snotify, n_lan_addr) < 0)		{			syslog(LOG_ERR, "Failed to broadcast good-bye notifications");		}		for(i=0; i<n_lan_addr; i++)/* for(i=0; i<v.n_lan_addr; i++)*/			close(snotify[i]);	}	if(unlink(pidfilename) < 0)	{		syslog(LOG_ERR, "Failed to remove pidfile %s: %m", pidfilename);	}	closelog();		freeoptions();		return 0;}

⌨️ 快捷键说明

复制代码 Ctrl + C
搜索代码 Ctrl + F
全屏模式 F11
切换主题 Ctrl + Shift + D
显示快捷键 ?
增大字号 Ctrl + =
减小字号 Ctrl + -