?? upnpsoap.c
字號:
/* $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 void{ 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 + -