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

📄 upnpsoap.c

📁 miniupnpd可以在嵌入式linux中实现upnp功能
💻 C
📖 第 1 页 / 共 2 页
字号:
/* $Id: upnpsoap.c,v 1.62 2008/04/25 16:24:12 nanard Exp $ *//* MiniUPnP project * http://miniupnp.free.fr/ or http://miniupnp.tuxfamily.org/ * (c) 2006-2008 Thomas Bernard  * This software is subject to the conditions detailed * in the LICENCE file provided within the distribution */#include <stdio.h>#include <stdlib.h>#include <string.h>#include <sys/socket.h>#include <unistd.h>#include <syslog.h>#include <sys/types.h>#include <arpa/inet.h>#include <netinet/in.h>#include <netdb.h>#include "config.h"#include "upnpglobalvars.h"#include "upnphttp.h"#include "upnpsoap.h"#include "upnpreplyparse.h"#include "upnpredirect.h"#include "getifaddr.h"#include "getifstats.h"static voidBuildSendAndCloseSoapResp(struct upnphttp * h,                          const char * body, int bodylen){	static const char beforebody[] =		"<?xml version=\"1.0\"?>\r\n"		"<s:Envelope xmlns:s=\"http://schemas.xmlsoap.org/soap/envelope/\" "		"s:encodingStyle=\"http://schemas.xmlsoap.org/soap/encoding/\">"		"<s:Body>";	static const char afterbody[] =		"</s:Body>"		"</s:Envelope>\r\n";	BuildHeader_upnphttp(h, 200, "OK",  sizeof(beforebody) - 1		+ sizeof(afterbody) - 1 + bodylen );	memcpy(h->res_buf + h->res_buflen, beforebody, sizeof(beforebody) - 1);	h->res_buflen += sizeof(beforebody) - 1;	memcpy(h->res_buf + h->res_buflen, body, bodylen);	h->res_buflen += bodylen;	memcpy(h->res_buf + h->res_buflen, afterbody, sizeof(afterbody) - 1);	h->res_buflen += sizeof(afterbody) - 1;	SendResp_upnphttp(h);	CloseSocket_upnphttp(h);}static voidGetConnectionTypeInfo(struct upnphttp * h, const char * action){	static const char resp[] =		"<u:GetConnectionTypeInfoResponse "		"xmlns:u=\"urn:schemas-upnp-org:service:WANIPConnection:1\">"		"<NewConnectionType>IP_Routed</NewConnectionType>"		"<NewPossibleConnectionTypes>IP_Routed</NewPossibleConnectionTypes>"		"</u:GetConnectionTypeInfoResponse>";	BuildSendAndCloseSoapResp(h, resp, sizeof(resp)-1);}static voidGetTotalBytesSent(struct upnphttp * h, const char * action){	int r;	static const char resp[] =		"<u:%sResponse "		"xmlns:u=\"%s\">"		"<NewTotalBytesSent>%lu</NewTotalBytesSent>"		"</u:%sResponse>";	char body[512];	int bodylen;	struct ifdata data;	r = getifstats(ext_if_name, &data);	bodylen = snprintf(body, sizeof(body), resp,	         action, "urn:schemas-upnp-org:service:WANCommonInterfaceConfig:1",             r<0?0:data.obytes, action);	BuildSendAndCloseSoapResp(h, body, bodylen);}static voidGetTotalBytesReceived(struct upnphttp * h, const char * action){	int r;	static const char resp[] =		"<u:%sResponse "		"xmlns:u=\"%s\">"		"<NewTotalBytesReceived>%lu</NewTotalBytesReceived>"		"</u:%sResponse>";	char body[512];	int bodylen;	struct ifdata data;	r = getifstats(ext_if_name, &data);	bodylen = snprintf(body, sizeof(body), resp,	         action, "urn:schemas-upnp-org:service:WANCommonInterfaceConfig:1",	         r<0?0:data.ibytes, action);	BuildSendAndCloseSoapResp(h, body, bodylen);}static voidGetTotalPacketsSent(struct upnphttp * h, const char * action){	int r;	static const char resp[] =		"<u:%sResponse "		"xmlns:u=\"%s\">"		"<NewTotalPacketsSent>%lu</NewTotalPacketsSent>"		"</u:%sResponse>";	char body[512];	int bodylen;	struct ifdata data;	r = getifstats(ext_if_name, &data);	bodylen = snprintf(body, sizeof(body), resp,	         action, "urn:schemas-upnp-org:service:WANCommonInterfaceConfig:1",	         r<0?0:data.opackets, action);	BuildSendAndCloseSoapResp(h, body, bodylen);}static voidGetTotalPacketsReceived(struct upnphttp * h, const char * action){	int r;	static const char resp[] =		"<u:%sResponse "		"xmlns:u=\"%s\">"		"<NewTotalPacketsReceived>%lu</NewTotalPacketsReceived>"		"</u:%sResponse>";	char body[512];	int bodylen;	struct ifdata data;	r = getifstats(ext_if_name, &data);	bodylen = snprintf(body, sizeof(body), resp,	         action, "urn:schemas-upnp-org:service:WANCommonInterfaceConfig:1",	         r<0?0:data.ipackets, action);	BuildSendAndCloseSoapResp(h, body, bodylen);}static voidGetCommonLinkProperties(struct upnphttp * h, const char * action){	static const char resp[] =		"<u:%sResponse "		"xmlns:u=\"%s\">"		/*"<NewWANAccessType>DSL</NewWANAccessType>"*/		"<NewWANAccessType>Cable</NewWANAccessType>"		"<NewLayer1UpstreamMaxBitRate>%lu</NewLayer1UpstreamMaxBitRate>"		"<NewLayer1DownstreamMaxBitRate>%lu</NewLayer1DownstreamMaxBitRate>"		"<NewPhysicalLinkStatus>Up</NewPhysicalLinkStatus>"		"</u:%sResponse>";	char body[2048];	int bodylen;	struct ifdata data;	if((downstream_bitrate == 0) || (upstream_bitrate == 0))	{		if(getifstats(ext_if_name, &data) >= 0)		{			if(downstream_bitrate == 0) downstream_bitrate = data.baudrate;			if(upstream_bitrate == 0) upstream_bitrate = data.baudrate;		}	}	bodylen = snprintf(body, sizeof(body), resp,	    action, "urn:schemas-upnp-org:service:WANCommonInterfaceConfig:1",		upstream_bitrate, downstream_bitrate,	    action);	BuildSendAndCloseSoapResp(h, body, bodylen);}static voidGetStatusInfo(struct upnphttp * h, const char * action){	static const char resp[] =		"<u:%sResponse "		"xmlns:u=\"%s\">"		"<NewConnectionStatus>Connected</NewConnectionStatus>"		"<NewLastConnectionError>ERROR_NONE</NewLastConnectionError>"		"<NewUptime>%ld</NewUptime>"		"</u:%sResponse>";	char body[512];	int bodylen;	time_t uptime;	uptime = (time(NULL) - startup_time);	bodylen = snprintf(body, sizeof(body), resp,		action, "urn:schemas-upnp-org:service:WANIPConnection:1",		(long)uptime, action);		BuildSendAndCloseSoapResp(h, body, bodylen);}static voidGetNATRSIPStatus(struct upnphttp * h, const char * action){	static const char resp[] =		"<u:GetNATRSIPStatusResponse "		"xmlns:u=\"urn:schemas-upnp-org:service:WANIPConnection:1\">"		"<NewRSIPAvailable>0</NewRSIPAvailable>"		"<NewNATEnabled>1</NewNATEnabled>"		"</u:GetNATRSIPStatusResponse>";	BuildSendAndCloseSoapResp(h, resp, sizeof(resp)-1);}static voidGetExternalIPAddress(struct upnphttp * h, const char * action){	static const char resp[] =		"<u:%sResponse "		"xmlns:u=\"%s\">"		"<NewExternalIPAddress>%s</NewExternalIPAddress>"		"</u:%sResponse>";	char body[512];	int bodylen;	char ext_ip_addr[INET_ADDRSTRLEN];#ifndef MULTIPLE_EXTERNAL_IP	if(use_ext_ip_addr)	{		strncpy(ext_ip_addr, use_ext_ip_addr, INET_ADDRSTRLEN);	}	else if(getifaddr(ext_if_name, ext_ip_addr, INET_ADDRSTRLEN) < 0)	{		syslog(LOG_ERR, "Failed to get ip address for interface %s",			ext_if_name);		strncpy(ext_ip_addr, "0.0.0.0", INET_ADDRSTRLEN);	}#else	int i;	strncpy(ext_ip_addr, "0.0.0.0", INET_ADDRSTRLEN);	for(i = 0; i<n_lan_addr; i++)	{		if( (h->clientaddr.s_addr & lan_addr[i].mask.s_addr)		   == (lan_addr[i].addr.s_addr & lan_addr[i].mask.s_addr))		{			strncpy(ext_ip_addr, lan_addr[i].ext_ip_str, INET_ADDRSTRLEN);			break;		}	}#endif	bodylen = snprintf(body, sizeof(body), resp,	              action, "urn:schemas-upnp-org:service:WANIPConnection:1",				  ext_ip_addr, action);	BuildSendAndCloseSoapResp(h, body, bodylen);}static voidAddPortMapping(struct upnphttp * h, const char * action){	int r;	static const char resp[] =		"<u:AddPortMappingResponse "		"xmlns:u=\"urn:schemas-upnp-org:service:WANIPConnection:1\"/>";	struct NameValueParserData data;	char * int_ip, * int_port, * ext_port, * protocol, * desc;	char * leaseduration;	unsigned short iport, eport;	struct hostent *hp; /* getbyhostname() */	char ** ptr; /* getbyhostname() */	struct in_addr result_ip;/*unsigned char result_ip[16];*/ /* inet_pton() */	ParseNameValue(h->req_buf + h->req_contentoff, h->req_contentlen, &data);	int_ip = GetValueFromNameValueList(&data, "NewInternalClient");	if (!int_ip)	{		ClearNameValueList(&data);		SoapError(h, 402, "Invalid Args");		return;	}	/* if ip not valid assume hostname and convert */	if (inet_pton(AF_INET, int_ip, &result_ip) <= 0) 	{		hp = gethostbyname(int_ip);		if(hp && hp->h_addrtype == AF_INET) 		{ 			for(ptr = hp->h_addr_list; ptr && *ptr; ptr++)		   	{				int_ip = inet_ntoa(*((struct in_addr *) *ptr));				result_ip = *((struct in_addr *) *ptr);				/* TODO : deal with more than one ip per hostname */				break;			}		} 		else 		{			syslog(LOG_ERR, "Failed to convert hostname '%s' to ip address", int_ip); 			ClearNameValueList(&data);			SoapError(h, 402, "Invalid Args");			return;		}					}	/* check if NewInternalAddress is the client address */	if(GETFLAG(SECUREMODEMASK))	{		if(h->clientaddr.s_addr != result_ip.s_addr)		{			syslog(LOG_INFO, "Client %s tried to redirect port to %s",			       inet_ntoa(h->clientaddr), int_ip);			ClearNameValueList(&data);			SoapError(h, 718, "ConflictInMappingEntry");			return;		}	}	int_port = GetValueFromNameValueList(&data, "NewInternalPort");	ext_port = GetValueFromNameValueList(&data, "NewExternalPort");	protocol = GetValueFromNameValueList(&data, "NewProtocol");	desc = GetValueFromNameValueList(&data, "NewPortMappingDescription");	leaseduration = GetValueFromNameValueList(&data, "NewLeaseDuration");	if (!int_port || !ext_port || !protocol)	{		ClearNameValueList(&data);		SoapError(h, 402, "Invalid Args");		return;	}	eport = (unsigned short)atoi(ext_port);	iport = (unsigned short)atoi(int_port);	if(leaseduration && atoi(leaseduration)) {		syslog(LOG_WARNING, "NewLeaseDuration=%s", leaseduration);	}	syslog(LOG_INFO, "%s: ext port %hu to %s:%hu protocol %s for: %s",			action, eport, int_ip, iport, protocol, desc);	r = upnp_redirect(eport, int_ip, iport, protocol, desc);	ClearNameValueList(&data);	/* possible error codes for AddPortMapping :	 * 402 - Invalid Args	 * 501 - Action Failed	 * 715 - Wildcard not permited in SrcAddr	 * 716 - Wildcard not permited in ExtPort	 * 718 - ConflictInMappingEntry	 * 724 - SamePortValuesRequired     * 725 - OnlyPermanentLeasesSupported             The NAT implementation only supports permanent lease times on             port mappings     * 726 - RemoteHostOnlySupportsWildcard             RemoteHost must be a wildcard and cannot be a specific IP             address or DNS name     * 727 - ExternalPortOnlySupportsWildcard             ExternalPort must be a wildcard and cannot be a specific port             value */	switch(r)	{	case 0:	/* success */		BuildSendAndCloseSoapResp(h, resp, sizeof(resp)-1);		break;	case -2:	/* already redirected */	case -3:	/* not permitted */		SoapError(h, 718, "ConflictInMappingEntry");		break;	default:		SoapError(h, 501, "ActionFailed");	}}static voidGetSpecificPortMappingEntry(struct upnphttp * h, const char * action){	int r;	static const char resp[] =		"<u:%sResponse "		"xmlns:u=\"%s\">"		"<NewInternalPort>%u</NewInternalPort>"

⌨️ 快捷键说明

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