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

📄 gatedevice.c

📁 linuxigd
💻 C
📖 第 1 页 / 共 2 页
字号:
#include <syslog.h>#include <stdlib.h>#include <upnp/ixml.h>#include <string.h>#include <time.h>#include <upnp/upnp.h>#include <upnp/upnptools.h>#include <upnp/TimerThread.h>#include "globals.h"#include "gatedevice.h"#include "pmlist.h"#include "util.h"//Definitions for mapping expiration timer threadstatic TimerThread gExpirationTimerThread;static ThreadPool gExpirationThreadPool;// MUTEX for locking shared state variables whenver they are changedstatic ithread_mutex_t DevMutex = PTHREAD_MUTEX_INITIALIZER;// Main event handler for callbacks from the SDK.  Determine type of event// and dispatch to the appropriate handler (Note: Get Var Request deprecatedint EventHandler(Upnp_EventType EventType, void *Event, void *Cookie){	switch (EventType)	{		case UPNP_EVENT_SUBSCRIPTION_REQUEST:			HandleSubscriptionRequest((struct Upnp_Subscription_Request *) Event);			break;		// -- Deprecated --		case UPNP_CONTROL_GET_VAR_REQUEST:			HandleGetVarRequest((struct Upnp_State_Var_Request *) Event);			break;		case UPNP_CONTROL_ACTION_REQUEST:			HandleActionRequest((struct Upnp_Action_Request *) Event);			break;		default:			trace(1, "Error in EventHandler: Unknown event type %d",						EventType);	}	return (0);}// Grab our UDN from the Description Document.  This may not be needed, // the UDN comes with the request, but we leave this for other device initializationsint StateTableInit(char *descDocUrl){	IXML_Document *ixmlDescDoc;	int ret;	if ((ret = UpnpDownloadXmlDoc(descDocUrl, &ixmlDescDoc)) != UPNP_E_SUCCESS)	{		syslog(LOG_ERR, "Could not parse description document. Exiting ...");		UpnpFinish();		exit(0);	}	// Get the UDN from the description document, then free the DescDoc's memory	gateUDN = GetFirstDocumentItem(ixmlDescDoc, "UDN");	ixmlDocument_free(ixmlDescDoc);			// Initialize our linked list of port mappings.	pmlist_Head = pmlist_Current = NULL;	PortMappingNumberOfEntries = 0;	return (ret);}// Handles subscription request for state variable notificationsint HandleSubscriptionRequest(struct Upnp_Subscription_Request *sr_event){	IXML_Document *propSet = NULL;		ithread_mutex_lock(&DevMutex);	if (strcmp(sr_event->UDN, gateUDN) == 0)	{		// WAN Common Interface Config Device Notifications		if (strcmp(sr_event->ServiceId, "urn:upnp-org:serviceId:WANCommonIFC1") == 0)		{		        trace(3, "Recieved request to subscribe to WANCommonIFC1");			UpnpAddToPropertySet(&propSet, "PhysicalLinkStatus", "Up");			UpnpAcceptSubscriptionExt(deviceHandle, sr_event->UDN, sr_event->ServiceId,						  propSet, sr_event->Sid);			ixmlDocument_free(propSet);		}		// WAN IP Connection Device Notifications		else if (strcmp(sr_event->ServiceId, "urn:upnp-org:serviceId:WANIPConn1") == 0)		{			GetIpAddressStr(ExternalIPAddress, g_vars.extInterfaceName);			trace(3, "Received request to subscribe to WANIPConn1");			UpnpAddToPropertySet(&propSet, "PossibleConnectionTypes","IP_Routed");			UpnpAddToPropertySet(&propSet, "ConnectionStatus","Connected");			UpnpAddToPropertySet(&propSet, "ExternalIPAddress", ExternalIPAddress);			UpnpAddToPropertySet(&propSet, "PortMappingNumberOfEntries","0");			UpnpAcceptSubscriptionExt(deviceHandle, sr_event->UDN, sr_event->ServiceId,						  propSet, sr_event->Sid);			ixmlDocument_free(propSet);		}	}	ithread_mutex_unlock(&DevMutex);	return(1);}int HandleGetVarRequest(struct Upnp_State_Var_Request *gv_request){	// GET VAR REQUEST DEPRECATED FROM UPnP SPECIFICATIONS 	// Report this in debug and ignore requests.  If anyone experiences problems	// please let us know.        trace(3, "Deprecated Get Variable Request received. Ignoring.");	return 1;}int HandleActionRequest(struct Upnp_Action_Request *ca_event){	int result = 0;	ithread_mutex_lock(&DevMutex);		if (strcmp(ca_event->DevUDN, gateUDN) == 0)	{		// Common debugging info, hopefully gets removed soon.	        trace(3, "ActionName = %s", ca_event->ActionName);				if (strcmp(ca_event->ServiceID, "urn:upnp-org:serviceId:WANIPConn1") == 0)		{			if (strcmp(ca_event->ActionName,"GetConnectionTypeInfo") == 0)			  result = GetConnectionTypeInfo(ca_event);			else if (strcmp(ca_event->ActionName,"GetNATRSIPStatus") == 0)			  result = GetNATRSIPStatus(ca_event);			else if (strcmp(ca_event->ActionName,"SetConnectionType") == 0)			  result = SetConnectionType(ca_event);			else if (strcmp(ca_event->ActionName,"RequestConnection") == 0)			  result = RequestConnection(ca_event);			else if (strcmp(ca_event->ActionName,"AddPortMapping") == 0)			  result = AddPortMapping(ca_event);			else if (strcmp(ca_event->ActionName,"GetGenericPortMappingEntry") == 0)			  result = GetGenericPortMappingEntry(ca_event);			else if (strcmp(ca_event->ActionName,"GetSpecificPortMappingEntry") == 0)			  result = GetSpecificPortMappingEntry(ca_event);			else if (strcmp(ca_event->ActionName,"GetExternalIPAddress") == 0)			  result = GetExternalIPAddress(ca_event);			else if (strcmp(ca_event->ActionName,"DeletePortMapping") == 0)			  result = DeletePortMapping(ca_event);			else if (strcmp(ca_event->ActionName,"GetStatusInfo") == 0)			  result = GetStatusInfo(ca_event);				// Intentionally Non-Implemented Functions -- To be added later			/*else if (strcmp(ca_event->ActionName,"RequestTermination") == 0)				result = RequestTermination(ca_event);			else if (strcmp(ca_event->ActionName,"ForceTermination") == 0)				result = ForceTermination(ca_event);			else if (strcmp(ca_event->ActionName,"SetAutoDisconnectTime") == 0)				result = SetAutoDisconnectTime(ca_event);			else if (strcmp(ca_event->ActionName,"SetIdleDisconnectTime") == 0)				result = SetIdleDisconnectTime(ca_event);			else if (strcmp(ca_event->ActionName,"SetWarnDisconnectDelay") == 0)				result = SetWarnDisconnectDelay(ca_event);			else if (strcmp(ca_event->ActionName,"GetAutoDisconnectTime") == 0)				result = GetAutoDisconnectTime(ca_event);			else if (strcmp(ca_event->ActionName,"GetIdleDisconnectTime") == 0)				result = GetIdleDisconnectTime(ca_event);			else if (strcmp(ca_event->ActionName,"GetWarnDisconnectDelay") == 0)				result = GetWarnDisconnectDelay(ca_event);*/			else result = InvalidAction(ca_event);		}		else if (strcmp(ca_event->ServiceID,"urn:upnp-org:serviceId:WANCommonIFC1") == 0)		{			if (strcmp(ca_event->ActionName,"GetTotalBytesSent") == 0)				result = GetTotal(ca_event, STATS_TX_BYTES);			else if (strcmp(ca_event->ActionName,"GetTotalBytesReceived") == 0)				result = GetTotal(ca_event, STATS_RX_BYTES);			else if (strcmp(ca_event->ActionName,"GetTotalPacketsSent") == 0)				result = GetTotal(ca_event, STATS_TX_PACKETS);			else if (strcmp(ca_event->ActionName,"GetTotalPacketsReceived") == 0)				result = GetTotal(ca_event, STATS_RX_PACKETS);			else if (strcmp(ca_event->ActionName,"GetCommonLinkProperties") == 0)				result = GetCommonLinkProperties(ca_event);			else 			{				trace(1, "Invalid Action Request : %s",ca_event->ActionName);				result = InvalidAction(ca_event);			}		} 	}		ithread_mutex_unlock(&DevMutex);	return (result);}// Default Action when we receive unknown Action Requestsint InvalidAction(struct Upnp_Action_Request *ca_event){        ca_event->ErrCode = 401;        strcpy(ca_event->ErrStr, "Invalid Action");        ca_event->ActionResult = NULL;        return (ca_event->ErrCode);}// As IP_Routed is the only relevant Connection Type for Linux-IGD// we respond with IP_Routed as both current type and only typeint GetConnectionTypeInfo (struct Upnp_Action_Request *ca_event){	char resultStr[RESULT_LEN];	IXML_Document *result;	snprintf(resultStr, RESULT_LEN,		"<u:GetConnectionTypeInfoResponse xmlns:u=\"urn:schemas-upnp-org:service:WANIPConnection:1\">\n"		"<NewConnectionType>IP_Routed</NewConnectionType>\n"		"<NewPossibleConnectionTypes>IP_Routed</NewPossibleConnectionTypes>"		"</u:GetConnectionTypeInfoResponse>");   // Create a IXML_Document from resultStr and return with ca_event   if ((result = ixmlParseBuffer(resultStr)) != NULL)   {      ca_event->ActionResult = result;      ca_event->ErrCode = UPNP_E_SUCCESS;   }   else   {      trace(1, "Error parsing Response to GetConnectionTypeinfo: %s", resultStr);      ca_event->ActionResult = NULL;      ca_event->ErrCode = 402;   }	return(ca_event->ErrCode);}// Linux-IGD does not support RSIP.  However NAT is of course// so respond with NewNATEnabled = 1int GetNATRSIPStatus(struct Upnp_Action_Request *ca_event){   char resultStr[RESULT_LEN];	IXML_Document *result;   snprintf(resultStr, RESULT_LEN, "<u:GetNATRSIPStatusResponse xmlns:u=\"urn:schemas-upnp-org:service:WANIPConnection:1\">\n"      							"<NewRSIPAvailable>0</NewRSIPAvailable>\n"									"<NewNATEnabled>1</NewNATEnabled>\n"								"</u:GetNATRSIPStatusResponse>");	// Create a IXML_Document from resultStr and return with ca_event	if ((result = ixmlParseBuffer(resultStr)) != NULL)	{		ca_event->ActionResult = result;		ca_event->ErrCode = UPNP_E_SUCCESS;		}   else	{	        trace(1, "Error parsing Response to GetNATRSIPStatus: %s", resultStr);		ca_event->ActionResult = NULL;		ca_event->ErrCode = 402;	}	return(ca_event->ErrCode);}// Connection Type is a Read Only Variable as linux-igd is only// a device that supports a NATing IP router (not an Ethernet// bridge).  Possible other uses may be explored.int SetConnectionType(struct Upnp_Action_Request *ca_event){	// Ignore requests	ca_event->ActionResult = NULL;	ca_event->ErrCode = UPNP_E_SUCCESS;	return ca_event->ErrCode;}// This function should set the state variable ConnectionStatus to// connecting, and then return synchronously, firing off a thread// asynchronously to actually change the status to connected.  However, here we// assume that the external WAN device is configured and connected// outside of linux igd.int RequestConnection(struct Upnp_Action_Request *ca_event){		IXML_Document *propSet = NULL;		//Immediatley Set connectionstatus to connected, and lastconnectionerror to none.	strcpy(ConnectionStatus,"Connected");	strcpy(LastConnectionError, "ERROR_NONE");	trace(2, "RequestConnection recieved ... Setting Status to %s.", ConnectionStatus);	// Build DOM Document with state variable connectionstatus and event it	UpnpAddToPropertySet(&propSet, "ConnectionStatus", ConnectionStatus);		// Send off notifications of state change	UpnpNotifyExt(deviceHandle, ca_event->DevUDN, ca_event->ServiceID, propSet);	ca_event->ErrCode = UPNP_E_SUCCESS;	return ca_event->ErrCode;}int GetCommonLinkProperties(struct Upnp_Action_Request *ca_event){   char resultStr[RESULT_LEN];	IXML_Document *result;        	ca_event->ErrCode = UPNP_E_SUCCESS;	snprintf(resultStr, RESULT_LEN,		"<u:GetCommonLinkPropertiesResponse xmlns:u=\"urn:schemas-upnp-org:service:WANCommonInterfaceConfig:1\">\n"		"<NewWANAccessType>Cable</NewWANAccessType>\n"		"<NewLayer1UpstreamMaxBitRate>%s</NewLayer1UpstreamMaxBitRate>\n"		"<NewLayer1DownstreamMaxBitRate>%s</NewLayer1DownstreamMaxBitRate>\n"		"<NewPhysicalLinkStatus>Up</NewPhysicalLinkStatus>\n"		"</u:GetCommonLinkPropertiesResponse>",g_vars.upstreamBitrate,g_vars.downstreamBitrate);   // Create a IXML_Document from resultStr and return with ca_event   if ((result = ixmlParseBuffer(resultStr)) != NULL)   {      ca_event->ActionResult = result;      ca_event->ErrCode = UPNP_E_SUCCESS;   }   else   {      trace(1, "Error parsing Response to GetCommonLinkProperties: %s", resultStr);      ca_event->ActionResult = NULL;      ca_event->ErrCode = 402;   }	return(ca_event->ErrCode);}/* get specified statistic from /proc/net/dev */int GetTotal(struct Upnp_Action_Request *ca_event, stats_t stat){	char dev[IFNAMSIZ], resultStr[RESULT_LEN];	const char *methods[STATS_LIMIT] =		{ "BytesSent", "BytesReceived", "PacketsSent", "PacketsReceived" };	unsigned long stats[STATS_LIMIT];	FILE *proc;	IXML_Document *result;	int read;		proc = fopen("/proc/net/dev", "r");	if (!proc)	{		fprintf(stderr, "failed to open\n");		return 0;	}	/* skip first two lines */	fscanf(proc, "%*[^\n]\n%*[^\n]\n");	/* parse stats */	do		read = fscanf(proc, "%[^:]:%lu %lu %*u %*u %*u %*u %*u %*u %lu %lu %*u %*u %*u %*u %*u %*u\n", dev, &stats[STATS_RX_BYTES], &stats[STATS_RX_PACKETS], &stats[STATS_TX_BYTES], &stats[STATS_TX_PACKETS]);	while (read != EOF && (read == 5 && strncmp(dev, g_vars.extInterfaceName, IFNAMSIZ) != 0));	fclose(proc);	snprintf(resultStr, RESULT_LEN,		"<u:GetTotal%sResponse xmlns:u=\"urn:schemas-upnp-org:service:WANCommonInterfaceConfig:1\">\n"		"<NewTotal%s>%lu</NewTotal%s>\n"		"</u:GetTotal%sResponse>", 		methods[stat], methods[stat], stats[stat], methods[stat], methods[stat]);	// Create a IXML_Document from resultStr and return with ca_event	if ((result = ixmlParseBuffer(resultStr)) != NULL)	{		ca_event->ActionResult = result;		ca_event->ErrCode = UPNP_E_SUCCESS;	}	else	{		trace(1, "Error parsing response to GetTotal: %s", resultStr);		ca_event->ActionResult = NULL;		ca_event->ErrCode = 402;	}	return (ca_event->ErrCode);}// Returns connection status related information to the control pointsint GetStatusInfo(struct Upnp_Action_Request *ca_event){   long int uptime;   char resultStr[RESULT_LEN];	IXML_Document *result = NULL;   uptime = (time(NULL) - startup_time);   	snprintf(resultStr, RESULT_LEN,		"<u:GetStatusInfoResponse xmlns:u=\"urn:schemas-upnp-org:service:GetStatusInfo:1\">\n"		"<NewConnectionStatus>Connected</NewConnectionStatus>\n"		"<NewLastConnectionError>ERROR_NONE</NewLastConnectionError>\n"		"<NewUptime>%li</NewUptime>\n"		"</u:GetStatusInfoResponse>", 		uptime);   	// Create a IXML_Document from resultStr and return with ca_event   if ((result = ixmlParseBuffer(resultStr)) != NULL)   {      ca_event->ActionResult = result;      ca_event->ErrCode = UPNP_E_SUCCESS;   }   else   {     trace(1, "Error parsing Response to GetStatusInfo: %s", resultStr);      ca_event->ActionResult = NULL;      ca_event->ErrCode = 402;   }   return(ca_event->ErrCode);}// Add New Port Map to the IGDint AddPortMapping(struct Upnp_Action_Request *ca_event){	char *remote_host=NULL;	char *ext_port=NULL;	char *proto=NULL;	char *int_port=NULL;	char *int_ip=NULL;	char *int_duration=NULL;	char *bool_enabled=NULL;	char *desc=NULL;  	struct portMap *ret, *new;	int result;	char num[5]; // Maximum number of port mapping entries 9999	IXML_Document *propSet = NULL;	int action_succeeded = 0;	char resultStr[RESULT_LEN];	if ( (ext_port = GetFirstDocumentItem(ca_event->ActionRequest, "NewExternalPort") )	     && (proto = GetFirstDocumentItem(ca_event->ActionRequest, "NewProtocol") )	     && (int_port = GetFirstDocumentItem(ca_event->ActionRequest, "NewInternalPort") )	     && (int_ip = GetFirstDocumentItem(ca_event->ActionRequest, "NewInternalClient") )	     && (int_duration = GetFirstDocumentItem(ca_event->ActionRequest, "NewLeaseDuration") )	     && (bool_enabled = GetFirstDocumentItem(ca_event->ActionRequest, "NewEnabled") )	     && (desc = GetFirstDocumentItem(ca_event->ActionRequest, "NewPortMappingDescription") ))	{	  remote_host = GetFirstDocumentItem(ca_event->ActionRequest, "NewRemoteHost");		// If port map with the same External Port, Protocol, and Internal Client exists		// then, as per spec, we overwrite it (for simplicity, we delete and re-add at end of list)		// Note: This may cause problems with GetGernericPortMappingEntry if a CP expects the overwritten		// to be in the same place.

⌨️ 快捷键说明

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