Lab-55: Universal Plug And Play (UPnP) protocol

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

upnp_1

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

upnp_4

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.

upnp_2

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.

upnp_3

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

upnp_18

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

upnp_16

upnp_15

This is how my device description looks like:

upnp_17

This is how service description looks like in my device:

upnp_19

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.

upnp_5

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_6

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

upnp_7

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

upnp_9

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>

upnp_10

As you can see each argument is tied to <relatedStateVariable> which tell us what kind of output format we can expect

upnp_11

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>

upnp_12

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

upnp_13

Click on Send button, set top box respond back with link status.

upnp_14

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>

 

 

Leave a comment