📄 upnpsoap.c
字号:
int bodylen; struct NameValueParserData data; const char * r_host, * ext_port, * protocol; unsigned short eport, iport; char int_ip[32]; char desc[64]; ParseNameValue(h->req_buf + h->req_contentoff, h->req_contentlen, &data); r_host = GetValueFromNameValueList(&data, "NewRemoteHost"); ext_port = GetValueFromNameValueList(&data, "NewExternalPort"); protocol = GetValueFromNameValueList(&data, "NewProtocol"); if(!ext_port || !protocol) { ClearNameValueList(&data); SoapError(h, 402, "Invalid Args"); return; } eport = (unsigned short)atoi(ext_port); r = upnp_get_redirection_infos(eport, protocol, &iport, int_ip, sizeof(int_ip), desc, sizeof(desc)); if(r < 0) { SoapError(h, 714, "NoSuchEntryInArray"); } else { syslog(LOG_INFO, "GetSpecificPortMappingEntry: rhost='%s' %s %s found => %s:%u desc='%s'", r_host, ext_port, protocol, int_ip, (unsigned int)iport, desc); bodylen = snprintf(body, sizeof(body), resp, (unsigned int)iport, int_ip, desc); BuildSendAndCloseSoapResp(h, body, bodylen); } ClearNameValueList(&data);}static voidDeletePortMapping(struct upnphttp * h){ int r; static const char resp[] = "<u:DeletePortMappingResponse " "xmlns:u=\"urn:schemas-upnp-org:service:WANIPConnection:1\">" "</u:DeletePortMappingResponse>"; struct NameValueParserData data; const char * r_host, * ext_port, * protocol; unsigned short eport; ParseNameValue(h->req_buf + h->req_contentoff, h->req_contentlen, &data); r_host = GetValueFromNameValueList(&data, "NewRemoteHost"); ext_port = GetValueFromNameValueList(&data, "NewExternalPort"); protocol = GetValueFromNameValueList(&data, "NewProtocol"); if(!ext_port || !protocol) { ClearNameValueList(&data); SoapError(h, 402, "Invalid Args"); return; } eport = (unsigned short)atoi(ext_port); syslog(LOG_INFO, "DeletePortMapping: external port: %hu, protocol: %s", eport, protocol); r = upnp_delete_redirection(eport, protocol); if(r < 0) { SoapError(h, 714, "NoSuchEntryInArray"); } else { BuildSendAndCloseSoapResp(h, resp, sizeof(resp)-1); } ClearNameValueList(&data);}static voidGetGenericPortMappingEntry(struct upnphttp * h){ int r; static const char resp[] = "<u:GetGenericPortMappingEntryResponse " "xmlns:u=\"urn:schemas-upnp-org:service:WANIPConnection:1\">" "<NewRemoteHost></NewRemoteHost>" "<NewExternalPort>%u</NewExternalPort>" "<NewProtocol>%s</NewProtocol>" "<NewInternalPort>%u</NewInternalPort>" "<NewInternalClient>%s</NewInternalClient>" "<NewEnabled>1</NewEnabled>" "<NewPortMappingDescription>%s</NewPortMappingDescription>" "<NewLeaseDuration>0</NewLeaseDuration>" "</u:GetGenericPortMappingEntryResponse>"; int index = 0; unsigned short eport, iport; const char * m_index; char protocol[4], iaddr[32]; char desc[64]; struct NameValueParserData data; ParseNameValue(h->req_buf + h->req_contentoff, h->req_contentlen, &data); m_index = GetValueFromNameValueList(&data, "NewPortMappingIndex"); if(!m_index) { ClearNameValueList(&data); SoapError(h, 402, "Invalid Args"); return; } index = (int)atoi(m_index); syslog(LOG_INFO, "GetGenericPortMappingEntry: index=%d", index); r = upnp_get_redirection_infos_by_index(index, &eport, protocol, &iport, iaddr, sizeof(iaddr), desc, sizeof(desc)); if(r < 0) { SoapError(h, 713, "SpecifiedArrayIndexInvalid"); } else { int bodylen; char body[2048]; bodylen = snprintf(body, sizeof(body), resp, (unsigned int)eport, protocol, (unsigned int)iport, iaddr, desc); BuildSendAndCloseSoapResp(h, body, bodylen); } ClearNameValueList(&data);}/*If a control point calls QueryStateVariable on a state variable that is notbuffered in memory within (or otherwise available from) the service,the service must return a SOAP fault with an errorCode of 404 Invalid Var.QueryStateVariable remains useful as a limited test tool but may not bepart of some future versions of UPnP.*/static voidQueryStateVariable(struct upnphttp * h){ static const char resp[] = "<u:QueryStateVariableResponse " "xmlns:u=\"urn:schemas-upnp-org:control-1-0\">" "<return>%s</return>" "</u:QueryStateVariableResponse>"; char body[2048]; int bodylen; struct NameValueParserData data; const char * var_name; ParseNameValue(h->req_buf + h->req_contentoff, h->req_contentlen, &data); /*var_name = GetValueFromNameValueList(&data, "QueryStateVariable"); */ /*var_name = GetValueFromNameValueListIgnoreNS(&data, "varName");*/ var_name = GetValueFromNameValueList(&data, "varName"); /*syslog(LOG_INFO, "QueryStateVariable(%.40s)", var_name); */ if(!var_name) { SoapError(h, 402, "Invalid Args"); } else if(strcmp(var_name, "ConnectionStatus") == 0) { bodylen = snprintf(body, sizeof(body), resp, "Connected"); BuildSendAndCloseSoapResp(h, body, bodylen); }#if 0 /* not usefull */ else if(strcmp(var_name, "ConnectionType") == 0) { bodylen = snprintf(body, sizeof(body), resp, "IP_Routed"); BuildSendAndCloseSoapResp(h, body, bodylen); } else if(strcmp(var_name, "LastConnectionError") == 0) { bodylen = snprintf(body, sizeof(body), resp, "ERROR_NONE"); BuildSendAndCloseSoapResp(h, body, bodylen); }#endif else if(strcmp(var_name, "PortMappingNumberOfEntries") == 0) { int r = 0, index = 0; unsigned short eport, iport; char protocol[4], iaddr[32], desc[64]; char strindex[10]; do { protocol[0] = '\0'; iaddr[0] = '\0'; desc[0] = '\0'; r = upnp_get_redirection_infos_by_index(index, &eport, protocol, &iport, iaddr, sizeof(iaddr), desc, sizeof(desc)); index++; } while(r==0); snprintf(strindex, sizeof(strindex), "%i", index - 1); bodylen = snprintf(body, sizeof(body), resp, strindex); BuildSendAndCloseSoapResp(h, body, bodylen); } else { syslog(LOG_NOTICE, "QueryStateVariable: Unknown: %s", var_name?var_name:""); SoapError(h, 404, "Invalid Var"); } ClearNameValueList(&data); }/* Windows XP as client send the following requests : * GetConnectionTypeInfo * GetNATRSIPStatus * ? GetTotalBytesSent - WANCommonInterfaceConfig * ? GetTotalBytesReceived - idem * ? GetTotalPacketsSent - idem * ? GetTotalPacketsReceived - idem * GetCommonLinkProperties - idem * GetStatusInfo - WANIPConnection * GetExternalIPAddress * QueryStateVariable / ConnectionStatus! */static const struct { const char * methodName; void (*methodImpl)(struct upnphttp *);}soapMethods[] ={ { "GetConnectionTypeInfo", GetConnectionTypeInfo }, { "GetNATRSIPStatus", GetNATRSIPStatus}, { "GetExternalIPAddress", GetExternalIPAddress}, { "AddPortMapping", AddPortMapping}, { "DeletePortMapping", DeletePortMapping}, { "GetGenericPortMappingEntry", GetGenericPortMappingEntry}, { "GetSpecificPortMappingEntry", GetSpecificPortMappingEntry}, { "QueryStateVariable", QueryStateVariable}, { "GetTotalBytesSent", GetTotalBytesSent}, { "GetTotalBytesReceived", GetTotalBytesReceived}, { "GetTotalPacketsSent", GetTotalPacketsSent}, { "GetTotalPacketsReceived", GetTotalPacketsReceived}, { "GetCommonLinkProperties", GetCommonLinkProperties}, { "GetStatusInfo", GetStatusInfo}, { 0, 0 }};voidExecuteSoapAction(struct upnphttp * h, const char * action, int n){ char * p; char method[2048]; int i, len, methodlen; i = 0; p = strchr(action, '#'); methodlen = strchr(p, '"') - p - 1; if(p) { p++; while(soapMethods[i].methodName) { len = strlen(soapMethods[i].methodName); if(strncmp(p, soapMethods[i].methodName, len) == 0) { soapMethods[i].methodImpl(h); return; } i++; } memset(method, 0, 2048); memcpy(method, p, methodlen); syslog(LOG_NOTICE, "SoapMethod: Unknown: %s", method); } SoapError(h, 401, "Invalid Action");}/* Standard Errors: * * errorCode errorDescription Description * -------- ---------------- ----------- * 401 Invalid Action No action by that name at this service. * 402 Invalid Args Could be any of the following: not enough in args, * too many in args, no in arg by that name, * one or more in args are of the wrong data type. * 403 Out of Sync Out of synchronization. * 501 Action Failed May be returned in current state of service prevents * invoking that action. * 600-699 TBD Common action errors. Defined by UPnP Forum Technical * Committee. * 700-799 TBD Action-specific errors for standard actions. Defined * by UPnP Forum working committee. * 800-899 TBD Action-specific errors for non-standard actions. * Defined by UPnP vendor.*/voidSoapError(struct upnphttp * h, int errCode, const char * errDesc){ static const char resp[] = "<s:Envelope " "xmlns:s=\"http://schemas.xmlsoap.org/soap/envelope/\" " "s:encodingStyle=\"http://schemas.xmlsoap.org/soap/encoding/\">" "<s:Body>" "<s:Fault>" "<faultcode>s:Client</faultcode>" "<faultstring>UPnPError</faultstring>" "<detail>" "<UPnPError xmlns=\"urn:schemas-upnp-org:control-1-0\">" "<errorCode>%d</errorCode>" "<errorDescription>%s</errorDescription>" "</UPnPError>" "</detail>" "</s:Fault>" "</s:Body>" "</s:Envelope>"; char body[2048]; int bodylen; syslog(LOG_INFO, "Returning UPnPError %d: %s", errCode, errDesc); bodylen = snprintf(body, sizeof(body), resp, errCode, errDesc); BuildResp2_upnphttp(h, 500, "Internal Server Error", body, bodylen); SendResp_upnphttp(h); CloseSocket_upnphttp(h);}
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -