In this lab we will learn about about Universal Plug And Play (UPnP) protocol. UPnP protocol is used in many household devices, the purpose of this protocol is to discover devices, their capabilities and interact with devices. UPnP operates over UDP protocol using HTTP also known as HTTPU. UPnP protocol standard can be found here
UPnP technology defines an architecture for pervasive peer-to-peer network connectivity of intelligent appliances, wireless devices, and PCs of all form factors. It is designed to bring easy-to-use, flexible, standards-based connectivity to ad-hoc or unmanaged networks whether in the home, in a small business, public spaces, or attached to the Internet. UPnP technology provides a distributed, open networking architecture that leverages TCP/IP and Web technologies to enable seamless proximity networking in addition to control and data transfer among networked devices
UPnP protocol uses Simple Service Discovery Protocol (SSDP) for device discovery. SSDP is a text-based protocol based on HTTPU (HTTP over UDP). It uses UDP as the underlying transport protocol. Services are announced by devices with multicast addressing
to a specifically designated IP multicast address at UDP port number 1900. In IPv4, the multicast address is 239.255.255.250.
UPnP protocol terminology:
action: Command exposed by a service. Takes one or more input or output arguments. May have a return value control point: Retrieves device and service descriptions, sends actions to services, polls for service state variables, and receives events from services device description: Formal definition of a logical device, expressed in the UPnP Template Language. Written in XML syntax. Specified by a UPnP vendor by filling in the placeholders in a UPnP Device Template, including, e.g., manufacturer name, model name, model number, serial number, and URLs for control, eventing, and presentation service description: Formal definition of a logical service, expressed in the UPnP Template language. Written in XML syntax. Specified by a UPnP vendor by filling in any placeholders in a UPnP Service Templat service type: Standard service types are denoted by urn:schemas-upnp-org:service: followed by a unique name assigned by a UPnP forum working committee, colon, and an integer version number SOAP Simple Object Access Protocol: A remote-procedure call mechanism based on XML that sends commands and receives values over HTTP SSDP Simple Service Discovery Protocol: A multicast discovery and search mechanism that uses a multicast variant of HTTP over UDP
Protocol is broken down in three steps 1) Discovery 2) Description and 3) Control. Let’s go over each steps and see what function they perform
Step-1: Discovery
Discovery is the step 1 in UPnP networking. When a device is added to the network, the UPnP discovery protocol allows that device to advertise its services to control points on the network. Similarly, when a control point is added to the network, the UPnP discovery protocol allows that control point to search for devices of interest on the network. UPnP uses Simple Service Discovery Protocol (SSDP) for discovery.
Below picture taken from standard show discovery architecture. On the right hand side we have devices and left hand side machine interested in devices and fetching info from devices, it can be another device or PC
Note: A physical can have multiple virtual devices and services
Devices advertises its services using NOTIFY discovery message. Client search for services using M-SEARCH message. Basically there are three message types related to discovery and they start with these lines:
NOTIFY * HTTP/1.1\r\n M-SEARCH * HTTP/1.1\r\n HTTP/1.1 200 OK\r\n
Advertisement with NOTIFY
When a device is added to the network, it shall send a multicast message with method NOTIFY and ssdp:alive in the NTS header field in the following format. Values in italics are placeholders for actual values
Each message contains information specific to the embedded device (or service) as well as information about its enclosing device. Messages shall include duration until the advertisements expire (max-age); if the device remains available, the advertisements shall be re-sent (with new duration). If the device becomes unavailable, the device should explicitly cancel its advertisements, but if the device is unable to do this, the advertisements will expire on their own
Search request with M-SEARCH
When a control point desires to search the network for devices, it shall send a multicast request with method M-SEARCH in the following format. Control points that know the address of a specific device are allowed to also use a similar format to send unicast requests with method M-SEARCH. For multicast M-SEARCH, the message format is defined below. Values in italics are placeholders for actual values.
Note: No body is present in requests with method M-SEARCH, but note that the message shall have a blank line following the last header field. Note: The TTL for the IP packet should default to 2 and should be configurable.
Search response
To be found by a network search, a device shall send a unicast UDP response to the source IP address and port that sent the request to the multicast address. Any device responding to a unicast M-SEARCH should respond within 1 second.
The URL specified in the LOCATION header field of the M-SEARCH response shall be reachable by the control point to which the response is directed
The response shall be sent in the following format. Values in italics are placeholders for actual values.
Devices responding to a multicast M-SEARCH should wait a random period of time between 0 seconds and the number of seconds specified in the MX field value of the search request before responding, in order to avoid flooding the requesting control point with search responses from multiple devices
Device unavailable — NOTIFY
When a device and its services are going to be removed from the network, the device should multicast an ssdp:byebye message
Note: No body is present for messages with method NOTIFY, but note that the message shall have a blank line following the last header field. The TTL for the IP packet should default to 2 and should be configurable.
Step-2: Description
After a control point has discovered a device, the control point still knows very little about the device — only the information that was in the discovery message, i.e., the device’s (or service’s) UPnP type, the device’s universally-unique identifier, and a URL to the device’s UPnP description. For the control point to learn more about the device and its capabilities, or to interact with the device, the control point shall retrieve a description of the device and its capabilities from the URL provided by the device in the discovery message
The UPnP description for a device is partitioned into two logical parts: a device description describing the physical and logical containers, and service descriptions describing the capabilities exposed by the device. A UPnP device description is written by a UPnP vendor. The description is in XML syntax and is usually based on a standard UPnP Device Template.
A UPnP service description includes a list of commands, or actions, to which the service responds, and parameters, or arguments for each action. A service description also includes a list of variables. These variables model the state of the service at run time, and are described in terms of their data type, range, and event characteristics
This is how my device description looks like:
This is how service description looks like in my device:
Step-3: Control
Given knowledge of a device and its services, a control point can ask those services to invoke actions and receive responses indicating the result of the action. Invoking actions is a kind of remote procedure call; a control point sends the action to the device’s service, and when the action has completed (or failed), the service returns any results or errors.
To control a device, a control point invokes an action on the device’s service. To do this, a control point sends a suitable control message to the fully qualified control URL for the service obtained from the controlURL sub element of the service element of the device description
Below is a listing of a control message sent using the POST method followed by an explanation of the header fields and body. To invoke an action on a device’s service, a control point shall send a request with method POST in the following format. Values in italics are placeholders for actual values
UPnP profiles SOAP 1.1, NOT REQUIRING that all devices support all allowed features of SOAP 1.1, but devices and control points shall support all mandatory features of SOAP 1.1
Demo
Demo is divided in 3 steps 1) Discovery 2) Description and 3) Control.
Step-1: Discovery
You can do discovery manually or using Python script.
Manual Discovery
For manual discovery launch Wireshark and filter for protocol SSDP. In my case I saw SSDP response message came from my set top box at address 192.168.0.1. On inspecting the the message you will find the attribute LOCATION: http://192.168.0.1/rootDesc.xml, note it down we will need it in next step. This is where root device service description is listed
Automatic Discovery using Python script
Copy & paste below Python code in the file UPnP_Discovery.py. This script will send M-SEARCH message and print the response received from the device
import socket msg = \ 'M-SEARCH * HTTP/1.1\r\n' \ 'HOST:239.255.255.250:1900\r\n' \ 'ST:upnp:rootdevice\r\n' \ 'MX:2\r\n' \ 'MAN:"ssdp:discover"\r\n' \ '\r\n' # Set up UDP socket s = socket.socket(socket.AF_INET, socket.SOCK_DGRAM, socket.IPPROTO_UDP) s.settimeout(10) s.sendto(msg, ('239.255.255.250', 1900) ) try: while True: data, addr = s.recvfrom(65507) print addr, data except socket.timeout: pass
Execute the script, you will find LOCATION: http://192.168.0.1/rootDesc.xml in response, note it down we will need it in next step
c:\Python27>python UPnP_Discovery.py
('192.168.0.1', 1900) HTTP/1.1 200 OK
CACHE-CONTROL: max-age=3600
ST: upnp:rootdevice
USN: uuid:52d57227-22ac-4f46-9a50-1a63ff84b88a::upnp:rootdevice
EXT:
SERVER: Linux/2.6.18_pro500 UPnP/1.0 MiniUPnPd/1.5
LOCATION: http://192.168.0.1:5000/rootDesc.xml
OPT: "http://schemas.upnp.org/upnp/1/0/";
01-NLS: 1
BOOTID.UPNP.ORG: 1
CONFIGID.UPNP.ORG: 1337
Step-2: Description
On web browser type in the LOCATION from step-1, http://192.168.0.1/rootDesc.xml. This web page provides device and service description, in my case it is my set top box from company called ARRIS.
We are interested in couple of things in this web page 1) Servicetype 2) ControlURL and 3) SCPDURL. SCPDURL (or Service Description URL) provide service commands (or action) and arguments for the command. ControlURL provides the url needed to invoke commands
In my case these are the settings for above three attributes:
Service type: WANCommonInterfaceConfig controlURL: /ctl/CmnIfCfg SCPDURL: /WANCfg.xml
In browser type in the <base url> + <SCPDURL>, http://192.168.0.1:5000/WANCfg.xml. Here we will find SOAP Actions, I am interested in SOAP Action GetCommonLinkProperties which has four output arguments. This action provide link status of my set top box
As you can see action GetCommonLinkProperties provides four output arguments
Note: Output arguments are specified as <direction>out</direction> and input arguments are specified as <direction>in</direction>
As you can see each argument is tied to <relatedStateVariable> which tell us what kind of output format we can expect
Now we know what SOAP Action (or command) to execute and the arguments it takes. In my case it is a read action so I will not provide any argument with SOAP request. Next step is to execute SOAP request
Step-3: Control
In Control step we will execute SOAP request with the action. We have two options to execute SOAP request 1) Manually using POSTMAN or 2) using Python script
Manual execution of SOAP request using POSTMAN
It is going to be a POST request so select request type POST. If you are not familiar with POSTMAN refer to Lab-44
POSTMAN url: <base url> + <controlUrl>. http://192.168.0.1:5000/ctl/CmnIfCfg
Copy and paste below SOAP envelope in POSTMAN body. Specify SOAP Action: GetCommonLinkProperties and Service type: WANCommonInterfaceConfig
Note: Replace bold italics text with your setting
<s:Envelope xmlns:s="http://schemas.xmlsoap.org/soap/envelope/" s:encodingStyle="http://schemas.xmlsoap.org/soap/encoding/"> <s:Body> <u:GetCommonLinkProperties xmlns:u="urn:schemas-upnp-org:service:WANCommonInterfaceConfig:1"> </u:GetCommonLinkProperties> </s:Body> </s:Envelope>
Create header with SOAP Action and Service type
Note: Replace bold italics text with your setting
Content-type: text/xml SOAPACTION: urn:schemas-upnp-org:service:WANCommonInterfaceConfig:1#GetCommonLinkProperties
Click on Send button, set top box respond back with link status.
Automatic execution of SOAP Action using Python script
Copy and paste below Python code in file UPnP_SOAP_Request.py. I used the code from this blog
Note: Replace bold italics text with your setting
import sys import httplib, urllib import re action = sys.argv[1] conn = httplib.HTTPConnection("192.168.0.1:5000") soap_data = '<s:Envelope xmlns: s="http://schemas.xmlsoap.org/soap/envelope" s:encodingStyle="http://schemas.xmlsoap.org/soap/encoding"><s:Body><u:'+action+' xmlns:u="urn:schemas-upnp-org:service:WANCommonInterfaceConfig:1"></u:'+action+'></s:Body></s:Envelope>' params = urllib.urlencode({'q': 'set'}) headers = { "Content-Type": "text/xml", "Content-Length": "%d" % len(soap_data), "SOAPACTION": "urn:schemas-upnp-org:service:WANCommonInterfaceConfig:1#"+action+'"' } conn.request("POST", "/ctl/CmnIfCfg", "", headers) conn.send(soap_data) response = conn.getresponse() #FOR DEBUG print response.status, response.reason print response.read()
Execute the script with argument like this with action as argument:
c:\Python27>python UPnP_SOAP_Request.py GetCommonLinkProperties
You will see the Link status output similar to what we saw in POSTMAN
200 OK <?xml version="1.0"?> <s:Envelope xmlns:s="http://schemas.xmlsoap.org/soap/envelope/" s:encodingStyle="http://schemas.xmlsoap.org/soap/encoding/"> <s:Body><u:GetCommonLinkPropertiesResponse xmlns:u="urn:schemas-upnp-org:service:WANCommonInterfaceConfig:1"> <NewWANAccessType>Cable</NewWANAccessType> <NewLayer1UpstreamMaxBitRate>1000000</NewLayer1UpstreamMaxBitRate> <NewLayer1DownstreamMaxBitRate>10000000</NewLayer1DownstreamMaxBitRate> <NewPhysicalLinkStatus>Up</NewPhysicalLinkStatus> </u:GetCommonLinkPropertiesResponse> </s:Body> </s:Envelope>