Giter VIP home page Giter VIP logo

ssdp-responder's Introduction

SSDP Responder for Linux/UNIX

License Badge GitHub Status Coverity Status

Simple Service Discovery Protocol daemon (SSDP) for networked Linux and UNIX devices. Useful in any setup, big or small, but targeted more at embedded systems that need to announce themselves to Windows systems.

ssdpd is a stand-alone UNIX daemon with no external dependencies but the standard C library. It has a built-in web server for serving the UPnP XML description which Windows use to present the icon, by default an InternetGatewayDevice is announced.

Also included is the ssdp-scan tool, which continuously scans for SSDP capable hosts on the network. Take care only to use this for debugging since it scans the network quite aggressively.

Note: when ssdpd is started as root it will drop privileges as soon as it has created its UUID cache and PID file. It is recommended to have a dedicated ssdp user (and group) available in the system for this purpose. As a fallback, user nobody (and nogroup) is used. When started as non-root, make sure to provide a path for the cache file with the -c FILE option.

Usage

Usage: ssdpd [-hnsvw] [-c FILE] [-d URL] [-i SEC] [-l LEVEL] [-m NAME] [-M URL]
                      [-p URL] [-P FILE] [-r SEC] [-R NUM] [-t TTL] [-u UUID]
                      [IFACE [IFACE ...]]

    -c FILE   Path to alternate ssdpd.cache to store and/or read the UUID
    -d URL    Override UPnP description.xml URL in announcements.  The '%s' in
              the URL is replaced with the IP, e.g. https://%s:1901/main.xml
    -h        This help text
    -i SEC    SSDP notify interval (30-900), default 300 sec
    -l LVL    Set log level: none, err, notice (default), info, debug
    -m NAME   Override manufacturer in the default description.xml
    -M URL    Override manufacturerURL in the default description.xml
    -n        Run in foreground, do not daemonize by default
    -r SEC    Interface refresh interval (5-1800), default 600 sec
    -R NUM    Initial retries, using 10 sec refresh interval, default 3 times
    -p URL    Override presentationURL (WebUI) in the default description.xml
              The '%s' is replaced with the IP address.  Default: http://%s/
    -P FILE   Override PID file location, absolute path required
    -s        Use syslog, default unless running in foreground, -n
    -t TTL    TTL for multicast frames, default 2, according to the UDA
    -u UUID   Custom UUID instead of auto-generating one
    -v        Show program version
    -w        Disable built-in micro HTTP server on port 1901

Bug report address : https://github.com/troglobit/ssdp-responder/issues
Project homepage   : https://github.com/troglobit/ssdp-responder

The -d URL argument can contain one %s modifier which is replaced with the IP address of the interface the SSDP notification or reply is sent on. For example:

ssdpd -d https://%s:1901/description.xml

See configure --help for some build time options.

Example

The following example assumes the system eth0 interface is connected to an ISP and eth1 to the LAN. Every 300 sec the list of addresses for eth1 are updated, if a new address is added a NOTIFY * message is sent, otherwise NOTIFY * messages are sent every 30 seconds.

ssdpd -i 30 -r 300 eth1

Configure & Build

The GNU Configure & Build system use /usr/local as the default install prefix. In many cases this is useful, but this means the configuration files, cache, and PID files will also use that prefix. Most users have come to expect those files in /etc/ and /var/ and configure has a few useful options that are recommended to use. Hence, you may want to use something like this:

./configure --prefix=/usr --sysconfdir=/etc --runstatedir=/var/run
make -j$(($(nproc) + 1))
sudo make install-strip

Usually your system reserves /usr for native pacakges, so most users drop --prefix, installing to /usr/local, or use --prefix=/opt.

Note: On some systems --runstatedir may not be available in the configure script, try --localstatedir=/var instead.

Building from GIT

The configure script and the Makefile.in files are generated for release tarballs and not stored in GIT. When you work with the GIT source tree you need the GNU automake and autoconf tools:

$ sudo apt install automake autoconf

Now, from the top directory of the cloned GIT tree, call:

$ ./autogen.sh

Static Build

Some people want to build statically, to do this with autoconf add the following LDFLAGS= after the configure script. You may also need to add LIBS=..., which will depend on your particular system:

./configure LDFLAGS="-static" ...

Integration with systemd

For systemd integration libsystemd-dev and pkg-config are required. When the unit file is installed, systemctl can be used to enable and start the daemon:

$ sudo systemctl enable ssdpd.service
$ sudo systemctl start  ssdpd.service

Check that it started properly by inspecting the system log, or:

$ sudo systemctl status ssdpd.service

To stop the service:

$ sudo systemctl stop   ssdpd.service

Origin

Cloned from mrdisc and whacked at with a bat until it replies to SSDP "MSEARCH *" messages used by Windows.

ssdp-responder's People

Contributors

jackuess avatar microfcorp avatar mmaret avatar raulporancea avatar shrief-rizkalla avatar troglobit avatar

Stargazers

 avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar

Watchers

 avatar  avatar  avatar  avatar  avatar

ssdp-responder's Issues

Add IPv6 support

Refactoring the base support for IPv4 into also supporting IPv6 is a bit of work. Fortunately there is experience to be gained from other code bases such as the SMCRoute, mcjoin, and mping projects.

IPv6 has been supported since UPnP v1.1, and as of v2.0 is accepted as a primary address family (not just secondary to IPv4 as in v1.1).

The wording in v2.0 around IPv6 is a lot better and is worth citing here:

2012 IPv6 Support Update: This revision to the UPnP Device Architecture Annex A is motivated by operational experience gained since the previous update. There are four high level goals addressed with these latest changes:

  1. IPv6 support needs to be required in order for new and existing devices to interoperate with each other
  2. GUA and ULA should be treated with equal weight, with address selection performed according to IETF guidance
  3. IPv6 needs to be preferred over IPv4 whenever it is available, per IETF guidance
  4. The IPv6 updates need to be applicable to UDA 1.0, UDA 1.1 and UDA 2.0 implementations

UPnP devices and control points need to be encouraged to support IPv6. The IPv4 public address space is effectively exhausted, and the move towards IPv6 is considered inevitable. Service providers and on-line content providers are all adding support of IPv6. Consumer electronics devices that are capable of accessing on-line services and content will also need to move to IPv6. In fact, the IETF has signaled its opinion on the deployment of IPv6 in RFC 6540, titled “IPv6 Support Required for all IP-capable Nodes.” Also, as IPv6 standards and support progress, there may be additional benefit to having UPnP supported over IPv6. There are potential advantages to the Remote Access architecture, as well as possible future benefits for traversal of multiple routers inside a home network. IPv6 support is being encouraged by CEA through the efforts of a new CEA Working Group focused on IPv6 and the transition from IPv4. UPnP needs to stay relevant in the evolving IP world, which demands that IPv6 interoperability be enabled. Legacy UDA 1.0 certified devices are allowed to remain non-IPv6 compliant, however it is highly recommended that all UPnP devices and control points support IPv6 and dual-stack operation.

Invalid UDN in description.xml

The UDN in description.xml is invalid, double uuid: prefix the UUID.

$ curl http://192.168.1.234:1901/description.xml
<?xml version="1.0"?>
<root xmlns="urn:schemas-upnp-org:device-1-0">
 <specVersion>
   <major>1</major>
   <minor>0</minor>
 </specVersion>
 <device>
  <deviceType>urn:schemas-upnp-org:device:InternetGatewayDevice:1</deviceType>
  <friendlyName>luthien</friendlyName>
  <manufacturer>Troglobit Software Systems</manufacturer>
  <manufacturerURL></manufacturerURL>
  <modelName>Generic</modelName>
  <UDN>uuid:uuid:5b2c664a-68d7-41e0-8e9a-088d02b0436</UDN>
  <presentationURL>http://192.168.1.234</presentationURL>
 </device>
</root>

Stack-based buffer overflow in ssdp_recv

SSDP responder (from version 1.0 up to latest 1.5) incorrectly handles incoming network messages leading to a stack-based buffer overwrite by 1 byte.
This will result in crash of the server, but only when strict stack checking is enabled.

Error message WITH Address Sanitizer:

sudo ./ssdpd -d
ssdpd[19693]: URN: uuid:4010435a-cc9d-43cf-9d09-ab12fd9d127
ssdpd[19693]: Server: ........ UPnP/1.0 ssdpd/1.5
ssdpd[19693]: Updating interfaces ...
ssdpd[19693]: No interfaces to filter, using all with an IP address.
ssdpd[19693]: No interfaces to filter, using all with an IP address.
ssdpd[19693]: No interfaces to filter, using all with an IP address.
ssdpd[19693]: No interfaces to filter, using all with an IP address.
ssdpd[19693]: No interfaces to filter, using all with an IP address.
ssdpd[19693]: Adding new interface ___ with address _____________
ssdpd[19693]: No interfaces to filter, using all with an IP address.
ssdpd[19693]: No interfaces to filter, using all with an IP address.
ssdpd[19693]: No interfaces to filter, using all with an IP address.
ssdpd[19693]: No interfaces to filter, using all with an IP address.
ssdpd[19693]: Sending SSDP NOTIFY new:1 ...
ssdpd[19693]: Sending notify from ___________ ...
ssdpd[19693]: M-SEARCH * ST: upnp:rootdevice from ___.___.___.___ port _____
ssdpd[19693]: Sending reply from ___.___.___.___ ...
=================================================================
==19693==ERROR: AddressSanitizer: stack-buffer-overflow on address 0x7ffc5146a7d0 at pc 0x000000404828 bp 0x7ffc5146a510 sp 0x7ffc5146a500
WRITE of size 1 at 0x7ffc5146a7d0 thread T0
    #0 0x404827 in ssdp_recv ssdp-responder-master/ssdpd.c:440
    #1 0x403ad9 in handle_message ssdp-responder-master/ssdpd.c:644
    #2 0x403ad9 in wait_message ssdp-responder-master/ssdpd.c:684
    #3 0x402655 in main ssdp-responder-master/ssdpd.c:891
    #4 0x7fd45054782f in __libc_start_main (/lib/x86_64-linux-gnu/libc.so.6+0x2082f)
    #5 0x403748 in _start (ssdp-responder-master/ssdpd+0x403748)

Address 0x7ffc5146a7d0 is located in stack of thread T0 at offset 672 in frame
    #0 0x4043af in ssdp_recv ssdp-responder-master/ssdpd.c:431

  This frame has 3 object(s):
    [32, 36) 'salen'
    [96, 112) 'sa'
    [160, 672) 'buf' <== Memory access at offset 672 overflows this variable
HINT: this may be a false positive if your program uses some custom stack unwind mechanism or swapcontext
      (longjmp and C++ exceptions *are* supported)
SUMMARY: AddressSanitizer: stack-buffer-overflow ssdp-responder-master/ssdpd.c:440 ssdp_recv
Shadow bytes around the buggy address:
  0x10000a2854a0: 00 00 00 00 00 00 f1 f1 f1 f1 04 f4 f4 f4 f2 f2
  0x10000a2854b0: f2 f2 00 00 f4 f4 f2 f2 f2 f2 00 00 00 00 00 00
  0x10000a2854c0: 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00
  0x10000a2854d0: 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00
  0x10000a2854e0: 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00
=>0x10000a2854f0: 00 00 00 00 00 00 00 00 00 00[f3]f3 f3 f3 f3 f3
  0x10000a285500: f3 f3 00 00 00 00 00 00 00 00 00 00 00 00 f1 f1
  0x10000a285510: f1 f1 00 00 00 00 00 00 00 00 00 00 00 00 00 00
  0x10000a285520: 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00
  0x10000a285530: 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00
  0x10000a285540: 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00
Shadow byte legend (one shadow byte represents 8 application bytes):
  Addressable:           00
  Partially addressable: 01 02 03 04 05 06 07 
  Heap left redzone:       fa
  Heap right redzone:      fb
  Freed heap region:       fd
  Stack left redzone:      f1
  Stack mid redzone:       f2
  Stack right redzone:     f3
  Stack partial redzone:   f4
  Stack after return:      f5
  Stack use after scope:   f8
  Global redzone:          f9
  Global init order:       f6
  Poisoned by user:        f7
  Container overflow:      fc
  Array cookie:            ac
  Intra object redzone:    bb
  ASan internal:           fe
==19693==ABORTING

Reproduction:

  1. Download and compile ssdp-responder with Address Sanitizer
    by adding -fsanitize=address to ssdpd_CFLAGS

  2. Run ssdp-responder:
    ./ssdpd -d

  3. Unzip and send attached crafted message e.g. using netcat (to the same network segment where responder is listening):
    netcat -u 239.255.255.250 1900 < payload_ssdp-resp_000.raw

payload_ssdp-resp_000.raw.zip

Buildroot autobuilder reports multiple build problems

Autobuilder failures

Below is a list of build failures reported by the Buildroot autobuilders
in relation to packages or CPU architectures you are in charge of.
Please help us improving the quality of Buildroot by investigating those
build failures and sending patches to fix them.

Results for the 'master' branch

Build failures related to your packages:

arch reason url
aarch64 ssdp-responder-1.9 http://autobuild.buildroot.net/results/f6912d6f79155c5d12811beeb6cb43860e37e7e7
sparc64 ssdp-responder-1.9 http://autobuild.buildroot.net/results/7ee4ed26de7e45b52a9f6f36b839e578d2319247
sh4a ssdp-responder-1.9 http://autobuild.buildroot.net/results/33d9c10ea58a7cd3b3e2ed75d586007a92ccdaf0
arc ssdp-responder-1.9 http://autobuild.buildroot.net/results/f1238081fc94e3004aebb8e849fdd567a92a2d39
nios2 ssdp-responder-1.9 http://autobuild.buildroot.net/results/f7f2cf790f51e6224dca258c52bd31d21d621074

Please include instructions and examples on how to compile in README.md

Please include basic instructions on how to compile this package. I know all systems are different, and preferences play a large part in how one wants to granularly control ./configure however I feel it is helpful to share basic method to compile your code. This maybe straight forward for other developers. However anyone that is not accustomed to using Linux or programming may not know how what to do after they clone the repo. Would recommend including the following:

To compile the code and install do the following

$ ./autogen.sh
$ ./configure
$ ./make
$ sudo ./make install

To check install run

$ systemctl status ssdp.service
$ ./check.sh

To start the service

$ sudo systemctl start ssdpd.service

To stop

$ sudo systemctl stop ssdp.service

ssdp-scan

Hi,
I have download the opensource you provide and i want to use ssdp-scan, but there is no response and said command not found. Do i miss something?
Thank you.

Failure to cache UUID on systems with uclibc

From log file:

Apr 22 05:15:32 buildroot ssdpd[99]: Cannot create UUID cache, /var/db//ssdpd.cache: No such file or 
directory

To make matters worse, this system ran systemd and also did not have the Linux canonical /var/lib/misc (replaces /var/db on Linux, c.f., *BSD), but it does have a /var/cache directory.

Periodic high CPU load, due to busy looping

Hi and thank you for yet another great Troglobit project! ❤️

I have observed that ssdpd, periodically, eats quite a lot of cpu. This behavior is quite easy to amplify by setting the interface refresh value low, while monitoring system load - with something like top -o '%CPU' | grep ssdpd. On an embedded system with few cores available it's easy to observe that ssdpd hogs the cpu periodically, but even on my PC laptop I can see it.

I think the issue is that wait_message will busy loop for a whole second when it has reached its timeout, happily eating all the cycles it can get a hold of. This can be observed by adding a trace log somewhere in the in the wait_message loop, like with this patch:

diff --git a/src/ssdpd.c b/src/ssdpd.c
index b02cc1c..0076f12 100644
--- a/src/ssdpd.c
+++ b/src/ssdpd.c
@@ -245,6 +245,7 @@ static void wait_message(time_t tmo)
 
 			err(1, "Unrecoverable error");
 		}
+		logit(LOG_INFO, "LOOP");
 	}
 }

...and run ssdp with 5 sec refresh interval:

 $ ssdpd -nlinfo -i5 2>&1 | ts
feb 02 20:57:22 Cannot create UUID cache, /var/db//ssdpd.cache: Permission denied
feb 02 20:57:22 No /etc/lsb-release found on system, using built-in server string.
feb 02 20:57:22 Server: POSIX UPnP/1.0 ssdpd/1.9
feb 02 20:57:22 Listening to HTTP connections on 0.0.0.0:1901
feb 02 20:57:22 Updating interfaces ...
feb 02 20:57:22 Sending SSDP NOTIFY on new interfaces ...
feb 02 20:57:22 Sending SSDP NOTIFY ...
feb 02 20:57:27 LOOP
feb 02 20:57:27 LOOP
feb 02 20:57:27 LOOP
...
feb 02 20:57:28 LOOP
feb 02 20:57:28 Updating interfaces ...
feb 02 20:57:33 LOOP
feb 02 20:57:33 LOOP
feb 02 20:57:33 LOOP
...
feb 02 20:57:34 LOOP
feb 02 20:57:34 Updating interfaces ...

I have a solution proposal in PR #11

SSDPD fail with openvpn

Hi,

First, thanks a lot for your software!

I'm trying to use it on a network with openvpn.
It's a TUN Server, and, on the client, the network configuration look like:

ip addr show tun0 
9: tun0: <POINTOPOINT,MULTICAST,NOARP,UP,LOWER_UP> mtu 1500 qdisc fq_codel state UNKNOWN group default qlen 100
    link/none 
    inet 10.8.0.6 peer 10.8.0.5/32 scope global tun0
       valid_lft forever preferred_lft forever
    inet6 fe80::5ad9:1f85:5605:8bd4/64 scope link stable-privacy 
       valid_lft forever preferred_lft forever

As you can see, it's declare as a peer interface so ssdpd detect the netmask as 255.255.255.255.
Even if the route is correct

 ip route
default via 192.168.0.254 dev eno1 proto dhcp metric 100 
10.8.0.0/24 via 10.8.0.5 dev tun0 
...

So when an SSDP request is received, I can see

No matching socket for client 10.8.0.1

To work around this, I use this "as ugly as possible" patch:

diff --git a/src/ssdp.c b/src/ssdp.c
index 9198251..82e8e23 100644
--- a/src/ssdp.c
+++ b/src/ssdp.c
@@ -262,8 +262,13 @@ int ssdp_register(int sd, struct sockaddr *addr, struct sockaddr *mask, void (*c
 	ifs->cb   = cb;
 	if (address)
 		ifs->addr = *address;
-	if (mask)
+	if (mask){
+		if (netmask->sin_addr.s_addr == htonl(INADDR_BROADCAST)){
+			inet_aton("255.255.0.0", &netmask->sin_addr);
+			logit(LOG_DEBUG, "Changing mask");
+		}
 		ifs->mask = *netmask;
+	}
 	LIST_INSERT_HEAD(&il, ifs, link);
 
 	return 0;

Something better could be done, like checking the ifa_flags for IFF_POINTTOPOINT, but you may have some better idea!

Thanks again

Feature request

Would it be possible to add a list of neighbors and maintain it for timeout lookup?

Every time there is a response for msearch add the client details to a list
Compare the list with current time and the last time client notified the network and issue a time out after the timeout interval.

Recommend Projects

  • React photo React

    A declarative, efficient, and flexible JavaScript library for building user interfaces.

  • Vue.js photo Vue.js

    🖖 Vue.js is a progressive, incrementally-adoptable JavaScript framework for building UI on the web.

  • Typescript photo Typescript

    TypeScript is a superset of JavaScript that compiles to clean JavaScript output.

  • TensorFlow photo TensorFlow

    An Open Source Machine Learning Framework for Everyone

  • Django photo Django

    The Web framework for perfectionists with deadlines.

  • D3 photo D3

    Bring data to life with SVG, Canvas and HTML. 📊📈🎉

Recommend Topics

  • javascript

    JavaScript (JS) is a lightweight interpreted programming language with first-class functions.

  • web

    Some thing interesting about web. New door for the world.

  • server

    A server is a program made to process requests and deliver data to clients.

  • Machine learning

    Machine learning is a way of modeling and interpreting data that allows a piece of software to respond intelligently.

  • Game

    Some thing interesting about game, make everyone happy.

Recommend Org

  • Facebook photo Facebook

    We are working to build community through open source technology. NB: members must have two-factor auth.

  • Microsoft photo Microsoft

    Open source projects and samples from Microsoft.

  • Google photo Google

    Google ❤️ Open Source for everyone.

  • D3 photo D3

    Data-Driven Documents codes.