UPnP envelopes from scratch not really working

647 views Asked by At

UPnP has always been one of the things I wanted to test out, so I decided to do it an a no fuzz language just to test it out. Now my problem seems to be, that I can't really find any information on the internet regarding UPnP, I have found out that it runs over UDP and that it uses SOAP envelopes to communicate, but that is all the information I can find. Now my goal is that I would like to be able to do dynamic port forwarding and possibly later some information gathering from my router. Here is the code I have been testing on so far:

;;This is the UDP Server
;;Start this first

; Start The UDP Services
;==============================================
UDPStartup()

; Register the cleanup function.
OnAutoItExitRegister("Cleanup")

; Bind to a SOCKET
;==============================================
Local $socket = UDPBind("239.255.255.250", 1900)
If @error <> 0 Then
   MsgBox(0, "UDP Fail", @error, 1)
   Exit;
EndIf;

While 1
    Local $data = UDPRecv($socket, 1024)
    If $data <> "" Then
        MsgBox(0, "UDP DATA", $data, 1)
    EndIf
    Sleep(100)
WEnd

Func Cleanup()
    UDPCloseSocket($socket)
    UDPShutdown()
EndFunc   ;==>Cleanup

For the record this is just an attempt to listen in on the UPnP communication. This just results in me getting the error code 10049 also known as address not available. So I am asking you dear stackers, what exactly is it I am doing wrong?

1

There are 1 answers

1
AudioBubble On BEST ANSWER

So I found the solution to this question myself for anyone that would like to toy around with this. UPnP protocols can apparently be very picky with their setup, so one needs to pay close attention to the way it is set up:

This is the discover message, it needs to look exactly like this, even with the double line shift at the end. However the ST message can be changed, i.e. 'ST:ssdp:all' would make it find all services for all devices, the current one makes sure to just get the rootdevice data. The discover message is sent to the multicast address 239.255.255.250 on port 1900 over UDP.

$strUpnpDiscover = 'M-SEARCH * HTTP/1.1' & @CRLF & 'HOST: 239.255.255.250:1900' & @CRLF & 'ST:upnp:rootdevice' & @CRLF & 'MAN:"ssdp:discover"' & @CRLF & 'MX:10' & @CRLF & @CRLF

Now in order to receive the reply from your rootdevice, you need to set up a listener to the source port you used to send the command, as this varies, you will either have to get it from your port object or by using a shell command to get the data, like so(@autoitpid gets the parent id of the program):

$netstat = _getDOSOutput("netstat -aonp udp")
$sourceport = StringReplace(StringMid($netstat, StringInStr($netstat, '*:*' & @AutoItPID)-5, 5), ':' , '')

But once you get this port, all you have to do is to set up an UDP listener to the found port on your network interface and you will receive the response from you UPnP unit.

Now once you receive a response, all the data on how to communicate with the device and alter settings will be in the data you receive, look for

LOCATION: http://192.168.1.1:49152/wps_device.xml

this URL will contain the datasheet for your device. From here it is just to formulate a proper SOAP envelope to make the device do your mischievous bidding. :P

For more on how to build the SOAP envelopes you can look here: http://www.upnp-hacks.org/upnp.html

I hope this stuff really helps anyone else that wants to build a lightweight UPnP port forwarding interface. :)