If you're looking at this page, you most like use a modem that
ng-upnp2mrtg does not (yet) support.
The following paragraphs
describe the UPnP protocol(s) to an extent that will enable you to
retrieve the missing information.
Discovery
Discovery is the process of determining how to query the UPnP
server.
On the most basic level you need:
the IP address of the modem/router, and the
port number on which the UPnP server is listening.
Usually three values are being retrieved from the UPnP device:
number of bytes received
number of bytes sent, and
the uptime.
As you will see shortly, 4 short strings for each of them are all you need to get the information you want:
the URI within the UPnP server,
the so called 'service' and a corresponding 'action',
and the name of the tag that holds the value in the reply from the server.
In nearly all cases, the IP address is the one you use to open its web interface. The port number is usually located in the 49000 range; the FritzBox uses 49000, the NetCologne Premium Modem uses 49300.
SSDP Notify
A reliable way to find the missing information is to monitor the
network for SSDP notify packets sent by the UPnP devices (SSDP
= Simple Service Discovery Protocol). These are multicast UDP
packets sent to 239.255.255.250 port 1900. You can use a packet
sniffer like Wireshark to
capture those.
When using Wireshark you might want to filter
the packets, showing only those originating from your router:
'ip.addr == a.b.c.d'
Be
patient – it could take a few minutes for the first SSDP packets to
appear. There will be different SSDP packets which will be
repeated after a while. The content of a typical SSDP packet
looks like this:
NOTIFY * HTTP/1.1
HOST: 239.255.255.250:1900
LOCATION:
http://192.168.0.99:49000/igddesc.xml
SERVER:
mynet UPnP/1.0 AVM FRITZ!Box WLAN 3170 49.04.57
CACHE-CONTROL:
max-age=1800
NT:
urn:schemas-upnp-org:device:InternetGatewayDevice:1
NTS:
ssdp:alive
USN:
uuid:75802409-bccb-40e7-8e6c-001C4A50656D::urn:schemas-upnp-org:device:InternetGatewayDevice:1
This
looks like a HTTP message – and it is:
a methode (NOTIFY),
an URI (*) (well...),
and the protocol version (HTTP/1.1),
followed by a few headers containing UPnP related information.
Those are:
LOCATION:
This URL contains the IP number and the port address of the UPnP server. If you enter this URL into your browser you get an XML file describing various services (see below). Even if this URL does not end in .xml, try it anyway.NT: the “service type”
NTS: ssdp:alive = unit present; ssdp:byebye = unit will cease operation shortly
USN: a unique identifier for this service (needed if you want to keep track of this particular service in a caching subroutine, for example).
The values for NT and the information stored in the description XML files will become important later. First, let's have a look at an actual query to see what we are looking for.
A UPnP query
After establishing a TCP connection to the IP and port number
mentioned in the SSDP packet under LOCATION the client sends a query
to the UPnP server. This query is text based and formatted
according to the HTTP protocol. The body includes XML and is a
SOAP message.
Here is a typical example:
POST
/WANCommonInterfaceConfigService/control
HTTP/1.0
HOST: 192.168.0.1:49300
CONTENT-LENGTH: 340
CONTENT-TYPE:
text/xml; charset="utf-8"
SOAPACTION:
"urn:schemas-upnp-org:service:WANCommonInterfaceConfig:1#GetTotalBytesReceived"
<?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:GetTotalBytesReceived
xmlns:u="urn:schemas-upnp-org:service:WANCommonInterfaceConfig:1">
</u:GetTotalBytesReceived>
</s:Body>
</s:Envelope>
The
interesting parts are underlined and printed in italic. Let's have a
look:
POST is an HTTP method followed by an URI (in this
example /WANCommonInterfaceConfigService/control
). This is one piece of information we need.
HOST: IP
and port number of the UPnP server. We just got this
information from the SSDP packet.
CONTENT-LENGTH: length of
the body
CONTENT-TYPE: character encoding of the
body
SOAPACTION: The part in front of the #-sign describes the
service, the part behind an action. More on that later.
After
a blank line (due to the HTTP standard) we find the message body, a
SOAP request, i.e. an XML message. Most of it is boilerplate –
and the variable parts we know already from the headers.
The
UPnP server will answer in the same connection with a message like
this one:
HTTP/1.1 200 OK
EXT:
CONTENT-TYPE: text/xml;
charset="utf-8"
SERVER:
IAD, UPnP/1.0, MicroStack v1.0.2777
<?xml
version="1.0" encoding="utf-8"?>
<s:Envelope
s:encodingStyle="http://schemas.xmlsoap.org/soap/encoding/"
xmlns:s="http://schemas.xmlsoap.org/soap/envelope/">
<s:Body>
<u:GetStatusInfoResponse
xmlns:u="urn:schemas-upnp-org:service:WANIPConnection:1">
<NewConnectionStatus>Connected</NewConnectionStatus>
<NewLastConnectionError>ERROR_NONE</NewLastConnectionError>
<NewUptime>30864</NewUptime>
</u:GetStatusInfoResponse>
</s:Body></s:Envelope>
The first line is a standard HTTP response code (200
means OK), followed by header lines, followed by an empty line,
followed by an XML message. Most of it is SOAP boilerplate,
some of the variable parts we know from the query. The info we
seek is encapsulated in tags <tag>...</tag>,
like the uptime value in <NewUptime>...</NewUptime>.
To
recap.
To query a specific item of information we need
(example values in brackets):
the IP address (192.168.0.1) and the port number (49300) of the UPnP server
the URI within that server (/WANCommonInterfaceConfigService/control)
a service (urn:schemas-upnp-org:service:WANCommonInterfaceConfig:1)
an action for that service (GetTotalBytesReceived)
the tag in the response which holds the information we want (NewUptime)
SSDP revisited
Now that we know what we are looking for, let's look again at
the SSDP packet. Each SSDP packet has a LOCATION
header:
LOCATION:
http://192.168.0.99:49000/igddesc.xml
There will be
most likely different values for LOCATION in the different SSDP
packets. The URI may contain the name of an XML file or it may
not. In either case, enter this URI into your browser.
If
you use Firefox, you will get a nicely formatted XML tree. Look
for entries starting with <serviceList>.
There may be more than one on different levels of the XML
tree.
Example:
...
<serviceList>
<service>
<serviceType>urn:schemas-upnp-org:service:WANCommonInterfaceConfig:1</serviceType>
<serviceId>urn:upnp-org:serviceId:WANCommonIFC1</serviceId>
<SCPDURL>WANCommonInterfaceConfigService/scpd.xml</SCPDURL>
<controlURL>WANCommonInterfaceConfigService/control</controlURL>
...
</service>
...
</serviceList>
Within
a <serviceList> there are one or
more <service> listed.
The <serviceType> is the “service” we need in the UPnP query.
The <controlURL> is the URI needed in the query (add a backslash in front of it).
<SCPDURL> gets you another XML file listing the available actions.
Enter http://<ip-address>:<port>/<value_of_SCPDURL>
into your browser. The resulting XML file looks like
this:
<scpd>
...
<actionList>
<action>
<name>action_name</name>
<argumentList>
<argument>
<name>argument_name_1</name>
<direction>in</direction>
</argument>
<argument>
<name>argument_name_2</name>
<direction>out</direction>
</argument>
...
</argumentList>
</action>
...
</actionList>
</scpd>
Most
of the tags are self-explanatory. Here are the important ones:
action_name is the parameter action of our UPnP query
argument_name is the name of the tag in the UPnP reply
you can only query information which has the direction set to “out”.
The information we are looking for is usually labelled:
“GetTotalBytesReceived”“ and „NewTotalBytesReceived“. For
the uptime, look for „NewUpTime“.