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

📄 upnpsoap.c

📁 很小的linux下的upnp服务器端代码适合嵌入式系统
💻 C
📖 第 1 页 / 共 2 页
字号:
/* $Id: upnpsoap.c,v 1.55 2007/06/05 20:53:40 nanard Exp $ *//* MiniUPnP project * http://miniupnp.free.fr/ or http://miniupnp.tuxfamily.org/ * (c) 2006 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 "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\"?>\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>";	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){	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){	int r;	static const char resp[] =		"<u:GetTotalBytesSentResponse "		"xmlns:u=\"urn:schemas-upnp-org:service:WANCommonInterfaceConfig:1\">"		"<NewTotalBytesSent>%lu</NewTotalBytesSent>"		"</u:GetTotalBytesSentResponse>";	char body[2048];	int bodylen;	struct ifdata data;	r = getifstats(ext_if_name, &data);	bodylen = snprintf(body, sizeof(body), resp, r<0?0:data.obytes);	BuildSendAndCloseSoapResp(h, body, bodylen);}static voidGetTotalBytesReceived(struct upnphttp * h){	int r;	static const char resp[] =		"<u:GetTotalBytesReceivedResponse "		"xmlns:u=\"urn:schemas-upnp-org:service:WANCommonInterfaceConfig:1\">"		"<NewTotalBytesReceived>%lu</NewTotalBytesReceived>"		"</u:GetTotalBytesReceivedResponse>";	char body[2048];	int bodylen;	struct ifdata data;	r = getifstats(ext_if_name, &data);	bodylen = snprintf(body, sizeof(body), resp, r<0?0:data.ibytes);	BuildSendAndCloseSoapResp(h, body, bodylen);}static voidGetTotalPacketsSent(struct upnphttp * h){	int r;	static const char resp[] =		"<u:GetTotalPacketsSentResponse "		"xmlns:u=\"urn:schemas-upnp-org:service:WANCommonInterfaceConfig:1\">"		"<NewTotalPacketsSent>%lu</NewTotalPacketsSent>"		"</u:GetTotalPacketsSentResponse>";	char body[2048];	int bodylen;	struct ifdata data;	r = getifstats(ext_if_name, &data);	bodylen = snprintf(body, sizeof(body), resp, r<0?0:data.opackets);	BuildSendAndCloseSoapResp(h, body, bodylen);}static voidGetTotalPacketsReceived(struct upnphttp * h){	int r;	static const char resp[] =		"<u:GetTotalPacketsReceivedResponse "		"xmlns:u=\"urn:schemas-upnp-org:service:WANCommonInterfaceConfig:1\">"		"<NewTotalPacketsReceived>%lu</NewTotalPacketsReceived>"		"</u:GetTotalPacketsReceivedResponse>";	char body[2048];	int bodylen;	struct ifdata data;	r = getifstats(ext_if_name, &data);	bodylen = snprintf(body, sizeof(body), resp, r<0?0:data.ipackets);	BuildSendAndCloseSoapResp(h, body, bodylen);}static voidGetCommonLinkProperties(struct upnphttp * h){	static const char resp[] =		"<u:GetCommonLinkPropertiesResponse "		"xmlns:u=\"urn:schemas-upnp-org:service:WANCommonInterfaceConfig:1\">"		/*"<NewWANAccessType>DSL</NewWANAccessType>"*/		"<NewWANAccessType>Cable</NewWANAccessType>"		"<NewLayer1UpstreamMaxBitRate>%lu</NewLayer1UpstreamMaxBitRate>"		"<NewLayer1DownstreamMaxBitRate>%lu</NewLayer1DownstreamMaxBitRate>"		"<NewPhysicalLinkStatus>Up</NewPhysicalLinkStatus>"		"</u:GetCommonLinkPropertiesResponse>";	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,		upstream_bitrate, downstream_bitrate);	BuildSendAndCloseSoapResp(h, body, bodylen);}static voidGetStatusInfo(struct upnphttp * h){	static const char resp[] =		"<u:GetStatusInfoResponse "		"xmlns:u=\"urn:schemas-upnp-org:service:WANIPConnection:1\">"		"<NewConnectionStatus>Connected</NewConnectionStatus>"		"<NewLastConnectionError>ERROR_NONE</NewLastConnectionError>"		"<NewUptime>%ld</NewUptime>"		"</u:GetStatusInfoResponse>";	char body[512];	int bodylen;	time_t uptime;	uptime = (time(NULL) - startup_time);	bodylen = snprintf(body, sizeof(body), resp, (long)uptime);		BuildSendAndCloseSoapResp(h, body, bodylen);}static voidGetNATRSIPStatus(struct upnphttp * h){	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){	static const char resp[] =		"<u:GetExternalIPAddressResponse "		"xmlns:u=\"urn:schemas-upnp-org:service:WANIPConnection:1\">"		"<NewExternalIPAddress>%s</NewExternalIPAddress>"		"</u:GetExternalIPAddressResponse>";	char body[512];	int bodylen;	char ext_ip_addr[INET_ADDRSTRLEN];	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);	}	bodylen = snprintf(body, sizeof(body), resp, ext_ip_addr);	BuildSendAndCloseSoapResp(h, body, bodylen);}static voidAddPortMapping(struct upnphttp * h){	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;	unsigned short iport, eport;	struct hostent *hp; /* getbyhostname() */	char ** ptr; /* getbyhostname() */	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));				/* 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;		}					}	int_port = GetValueFromNameValueList(&data, "NewInternalPort");	ext_port = GetValueFromNameValueList(&data, "NewExternalPort");	protocol = GetValueFromNameValueList(&data, "NewProtocol");	desc = GetValueFromNameValueList(&data, "NewPortMappingDescription");	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);	syslog(LOG_INFO, "AddPortMapping: external port %hu to %s:%hu protocol %s for: %s",			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 */	switch(r)	{	case 0:	/* success */		BuildSendAndCloseSoapResp(h, resp, sizeof(resp)-1);		break;	case -2:	/* already redirected */		SoapError(h, 718, "ConflictInMappingEntry");		break;	default:		SoapError(h, 501, "ActionFailed");	}}static voidGetSpecificPortMappingEntry(struct upnphttp * h){	int r;	static const char resp[] =		"<u:GetSpecificPortMappingEntryResponse "		"xmlns:u=\"urn:schemas-upnp-org:service:WANIPConnection:1\">"		"<NewInternalPort>%u</NewInternalPort>"		"<NewInternalClient>%s</NewInternalClient>"		"<NewEnabled>1</NewEnabled>"		"<NewPortMappingDescription>%s</NewPortMappingDescription>"		"<NewLeaseDuration>0</NewLeaseDuration>"		"</u:GetSpecificPortMappingEntryResponse>";	char body[2048];

⌨️ 快捷键说明

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