Hello community,

here is the log from the commit of package smcroute for openSUSE:Factory 
checked in at 2018-11-26 10:21:27
++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++
Comparing /work/SRC/openSUSE:Factory/smcroute (Old)
 and      /work/SRC/openSUSE:Factory/.smcroute.new.19453 (New)
++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++

Package is "smcroute"

Mon Nov 26 10:21:27 2018 rev:2 rq:648973 version:2.4.3

Changes:
--------
--- /work/SRC/openSUSE:Factory/smcroute/smcroute.changes        2018-07-02 
23:31:27.605397304 +0200
+++ /work/SRC/openSUSE:Factory/.smcroute.new.19453/smcroute.changes     
2018-11-26 10:22:38.193568393 +0100
@@ -1,0 +2,39 @@
+Wed Nov 14 13:02:17 UTC 2018 - Tomáš Chvátal <[email protected]>
+
+- Remove ip_route.h for the license clash
+
+-------------------------------------------------------------------
+Sat Nov 10 17:51:15 UTC 2018 - [email protected]
+
+- Update to version 2.4.3
+  Changes
+  * Add strlcat() replacement from OpenBSD, use instead of strcat()
+  * smcrouted should never log to system console, proposed by Westermo
+  Fixes
+  * smcrouted fails to join multicast groups on interfaces that do not
+    yet have an IP address when smcrouted starts up, or when it receives
+    SIGHUP, e.g. DHCP client interfaces. This patch release adds a timer
+    refresh of interface addresses that retries multicast group joins
+    until an address is set. This is similar to issue #55, but does not
+    handle interfaces that do not exist yet.
+  * Make sure Linux alias interfaces (baseif:num) are registered as
+    baseif. Westermo found that use of alias interfaces cause multiple
+    VIFs to be registered for the same base interface causing multicast
+    routes to use the wrong inbound or outbound VIF. Alias interfaces
+    use the same underlying physical interface so only one VIF needed.
+  * Fix display of route counters and column alignment
+  * Simplify utimensat() replacement, AT_SYMLINK_NOFOLLOW unused
+
+-------------------------------------------------------------------
+Mon Sep 10 20:09:44 UTC 2018 - [email protected]
+
+- Update to version 2.4.2
+  Changes
+  * Add wrapper script smcroute for use with old style startup scripts
+  * Add symlinks to man pages for smcrouted.8 and smcroutectl.8
+  * Update SysV init script, daemon now called smcrouted
+  Fixes
+  * Fix #96: A .conf line may be missing final newline, this is fine
+  * Spellcheck smcroute.conf example
+
+-------------------------------------------------------------------

Old:
----
  smcroute-2.4.1.tar.gz

New:
----
  smcroute-2.4.3.tar.gz

++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++

Other differences:
------------------
++++++ smcroute.spec ++++++
--- /var/tmp/diff_new_pack.yqWW0i/_old  2018-11-26 10:22:38.685567814 +0100
+++ /var/tmp/diff_new_pack.yqWW0i/_new  2018-11-26 10:22:38.685567814 +0100
@@ -1,6 +1,7 @@
 #
 # spec file for package smcroute
 #
+# Copyright (c) 2018 SUSE LINUX GmbH, Nuernberg, Germany.
 # Copyright (c) 2018, Martin Hauke <[email protected]>
 #
 # All modifications and additions to the file contributed by third parties
@@ -12,12 +13,12 @@
 # license that conforms to the Open Source Definition (Version 1.9)
 # published by the Open Source Initiative.
 
-# Please submit bugfixes or comments via http://bugs.opensuse.org/
+# Please submit bugfixes or comments via https://bugs.opensuse.org/
 #
 
 
 Name:           smcroute
-Version:        2.4.1
+Version:        2.4.3
 Release:        0
 Summary:        Static multicast routing for UNIX
 License:        GPL-3.0-only
@@ -47,9 +48,14 @@
 %setup -q
 sed -i 's|@DOCDIR@|%{_docdir}/smcroute/|g' smcroute.service.in
 
+# remove file not used by Linux with incompatible Apple license
+rm src/ip_mroute.h
+
 %build
 autoreconf -fiv
-%configure --with-systemd
+%configure \
+    --with-systemd \
+    --disable-silent-rules
 make %{?_smp_mflags}
 
 %install
@@ -79,9 +85,12 @@
 %license COPYING
 %{_sbindir}/smcroutectl
 %{_sbindir}/smcrouted
+%{_sbindir}/smcroute
 %{_sbindir}/rcsmcroute
 %config %{_sysconfdir}/smcroute.conf
 %{_mandir}/man8/smcroute.8%{?ext_man}
+%{_mandir}/man8/smcroutectl.8%{?ext_man}
+%{_mandir}/man8/smcrouted.8%{?ext_man}
 %{_unitdir}/%{name}.service
 
 %changelog

++++++ smcroute-2.4.1.tar.gz -> smcroute-2.4.3.tar.gz ++++++
diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn' 
'--exclude=.svnignore' old/smcroute-2.4.1/.gitignore 
new/smcroute-2.4.3/.gitignore
--- old/smcroute-2.4.1/.gitignore       2018-06-16 13:40:28.000000000 +0200
+++ new/smcroute-2.4.3/.gitignore       2018-11-07 01:34:48.000000000 +0100
@@ -20,8 +20,9 @@
 install-sh
 mcsender
 missing
-smcroute
 smcrouted
 smcroutectl
 smcroute.service
 stamp-h1
+*.tar.*
+.dirstamp
diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn' 
'--exclude=.svnignore' old/smcroute-2.4.1/ChangeLog.md 
new/smcroute-2.4.3/ChangeLog.md
--- old/smcroute-2.4.1/ChangeLog.md     2018-06-16 13:40:28.000000000 +0200
+++ new/smcroute-2.4.3/ChangeLog.md     2018-11-07 01:34:48.000000000 +0100
@@ -3,6 +3,46 @@
 
 All notable changes to the project are documented in this file.
 
+[v2.4.3][]
+----------
+
+The Lyon release.
+
+### Changes
+- Add `strlcat()` replacement from OpenBSD, use instead of `strcat()`
+- `smcrouted` should never log to system console, proposed by Westermo
+
+### Fixes
+- `smcrouted` fails to join multicast groups on interfaces that do not
+  yet have an IP address when `smcrouted` starts up, or when it receives
+  `SIGHUP`, e.g. DHCP client interfaces.  This patch release adds a timer
+  refresh of interface addresses that retries multicast group joins until
+  an address is set.  This is similar to issue #55, but does not handle
+  interfaces that do not exist yet
+- Make sure Linux alias interfaces (baseif:num) are registered as
+  baseif.  Westermo found that use of alias interfaces cause multiple
+  VIFs to be registered for the same base interface causing multicast
+  routes to use the wrong inbound or outbound VIF.  Alias interfaces
+  use the same underlying physical interface so only one VIF needed
+- Fix display of route counters and column alignment
+- Minor spelling fixes, found by Debian
+- Add missing status command to SysV init script, found by Debian
+- Simplify `utimensat()` replacement, `AT_SYMLINK_NOFOLLOW` unused
+
+
+[v2.4.2][] - 2018-09-09
+-----------------------
+
+### Changes
+- Add wrapper script `smcroute` for use with old style startup scripts
+- Add symlinks to man pages for `smcrouted.8 and` `smcroutectl.8`
+- Update SysV init script, daemon now called `smcrouted`
+
+### Fixes
+- Fix #96: A `.conf` line may be missing final newline, this is fine
+- Spellcheck `smcroute.conf` example
+- Fix Lintian warning (Debian) for unbreakable line in man page
+
 
 [v2.4.1][] - 2018-06-16
 -----------------------
@@ -433,7 +473,9 @@
 
 [mrdisc]:     https://github.com/troglobit/mrdisc
 [RFC4286]:    https://tools.ietf.org/html/rfc4286
-[UNRELEASED]: https://github.com/troglobit/smcroute/compare/2.4.1...HEAD
+[UNRELEASED]: https://github.com/troglobit/smcroute/compare/2.4.3...HEAD
+[v2.4.2]:     https://github.com/troglobit/smcroute/compare/2.4.2...2.4.3
+[v2.4.2]:     https://github.com/troglobit/smcroute/compare/2.4.1...2.4.2
 [v2.4.1]:     https://github.com/troglobit/smcroute/compare/2.4.1...2.4.1
 [v2.4.0]:     https://github.com/troglobit/smcroute/compare/2.3.1...2.4.0
 [v2.3.1]:     https://github.com/troglobit/smcroute/compare/2.3.0...2.3.1
diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn' 
'--exclude=.svnignore' old/smcroute-2.4.1/Makefile.am 
new/smcroute-2.4.3/Makefile.am
--- old/smcroute-2.4.1/Makefile.am      2018-06-16 13:40:28.000000000 +0200
+++ new/smcroute-2.4.3/Makefile.am      2018-11-07 01:34:48.000000000 +0100
@@ -1,9 +1,12 @@
 ## SMCRoute - A static multicast routing tool             -*-Makefile-*-
 ACLOCAL_AMFLAGS           = -I m4
 DISTCHECK_CONFIGURE_FLAGS = --with-systemd=$$dc_install_base/$(systemd)
+
 SUBDIRS                 = src
 DISTCLEANFILES         = *~ DEADJOE semantic.cache *.gdb *.elf core core.* *.d
+dist_sbin_SCRIPTS       = smcroute
 dist_man8_MANS         = smcroute.8
+SYMLINKS                = smcrouted.8 smcroutectl.8
 doc_DATA               = README.md COPYING smcroute.conf
 EXTRA_DIST             = README.md AUTHORS ChangeLog.md autogen.sh 
smcroute.conf smcroute.init
 
@@ -11,6 +14,19 @@
 systemd_DATA            = smcroute.service
 endif
 
+# Hook in install to add smcroute.8 --> smcrouted.8, smcroutectl.8 symlinks
+install-data-hook:
+       @for file in $(SYMLINKS); do                    \
+               link=$(DESTDIR)$(man8dir)/$$file;       \
+               test -e $$link && continue;             \
+               $(LN_S) $(dist_man8_MANS) $$link;       \
+       done
+
+uninstall-hook:
+       @for file in $(SYMLINKS); do                    \
+               $(RM) $(DESTDIR)$(mandir)/$$file;       \
+       done
+
 ## Generate detached signature file (ascii-armored), like OpenVPN does
 GPG = gpg
 gpg-dist:
diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn' 
'--exclude=.svnignore' old/smcroute-2.4.1/README.md new/smcroute-2.4.3/README.md
--- old/smcroute-2.4.1/README.md        2018-06-16 13:40:28.000000000 +0200
+++ new/smcroute-2.4.3/README.md        2018-11-07 01:34:48.000000000 +0100
@@ -86,8 +86,8 @@
 **Note:** To test the above you can use ping from another device.  The
    multicast should be visible as long as your IP# matches the source
    above and you ping 225.1.2.3 -- **REMEMBER TO SET THE TTL >1**
-   
-    $ ping -I eth0 -t 2 225.1.2.3
+
+    ping -I eth0 -t 2 225.1.2.3
 
 The TTL is what usually bites people first trying out multicast routing.
 Most TCP/IP stacks default to a TTL of 1 for multicast frames, e.g. ping
@@ -100,12 +100,15 @@
 because the TTL is the only thing that helps prevent routing loops!  On
 Linux the following `iptables` command can be used to change the TTL:
 
-    # iptables -t mangle -A PREROUTING -i eth0 -d 225.1.2.3 -j TTL --ttl-inc 1
+    iptables -t mangle -A PREROUTING -i eth0 -d 225.1.2.3 -j TTL --ttl-inc 1
+
+Some commands, like this one, must usually be run with root privileges
+or the correct set of capabilities.
 
 
 ### Action Scripts
 
-    # smcrouted -e /path/to/script
+    smcrouted -e /path/to/script
 
 With `-e CMD` a user script or command can be called when `smcrouted`
 receives a `SIGHUP` or installs a multicast route to the kernel.  This
@@ -115,7 +118,7 @@
 
 ### Many Interfaces
 
-    # smcrouted -N
+    smcrouted -N
 
 With the `-N` command line option SMCRoute does *not* prepare all system
 interfaces for multicast routing.  Very useful if your system has a lot
@@ -135,8 +138,8 @@
 its support for multiple multicast routing tables.  In such setups it
 may be useful to change the default identity of SMCRoute:
 
-    # smcrouted -I mrt1 -t 1
-    # smcrouted -I mrt2 -t 2
+    smcrouted -I mrt1 -t 1
+    smcrouted -I mrt2 -t 2
 
 The `-I NAME` option alters the default syslog name, config file, PID
 file, and client socket file name used.  In the first instance above,
@@ -154,19 +157,19 @@
 
 SMCRoute also has a client interface to interact with the daemon:
 
-    # smcroutectl join eth0 225.1.2.3
-    # smcroutectl add  eth0 192.168.1.42 225.1.2.3 eth1 eth2
+    smcroutectl join eth0 225.1.2.3
+    smcroutectl add  eth0 192.168.1.42 225.1.2.3 eth1 eth2
 
 If the daemon runs with a different identity the client needs to be
 called using the same identity:
 
-    # smcrouted   -I mrt
-    # smcroutectl -I mrt show
+    smcrouted   -I mrt
+    smcroutectl -I mrt show
 
 There are more commands.  See the man page or the online help for
 details:
 
-    # smcroutectl help
+    smcroutectl help
 
 **Note:** Root privileges are required by default for `smcroutectl` due
   to the IPC socket permissions.
@@ -248,22 +251,34 @@
 
 ### Configure & Build
 
-As of SMCRoute v2.2, the `libcap` library is used to gain full privilege
-separation using POSIX capabilities.  At startup this library is used to
-drop full root privileges, retaining only `CAP_NET_ADMIN` for managing
-the multicast routes.  Use `--without-libcap` to disable this feature.
-
-**Note:** On RHEL/CentOS 6 you must `configure --without-libcap`
-
-    $ ./configure --prefix=/usr --sysconfdir=/etc --localstatedir=/var
-    $ make -j5
-    $ sudo make install-strip
+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 and cache files will also use that same prefix.  Most users have
+come to expect those files in `/etc/` and `/var/run/` and configure has
+a few useful options that are recommended to use:
+
+    ./configure --prefix=/usr --sysconfdir=/etc --localstatedir=/var
+    make -j5
+    sudo make install-strip
+
+### Privilege Separation
+
+As of SMCRoute v2.2 support for privilege separation using the `libcap`
+library was added.  It is used to drop full root privileges at startup,
+retaining only `CAP_NET_ADMIN` for managing the multicast routes.
+
+The build system searches for the `libcap` library and header file(s).
+Bith `libcap-dev` and `pkg-config` are required.
+
+**Note:** Although support is automatically detected, the build system
+          will issue a warning if `libcap` is missing.  This can be
+          silenced with `configure --without-libcap`
 
 ### Integration with systemd
 
-For systemd integration you need to install `pkg-config`, which helps
-the SMCRoute build system figure out the systemd paths.  When installed
-simply call `systemctl` to enable and start `smcrouted`:
+For systemd integration `libsystemd-dev` and `pkg-config` are required.
+When the unit file is installed, `systemctl` can be used to enable and
+start `smcrouted`:
 
     $ sudo systemctl enable smcroute.service
     $ sudo systemctl start smcroute.service
@@ -278,7 +293,7 @@
 following `LDFLAGS=` *after* the configure script.  You may also need to
 add `LIBS=...`, which will depend on your particular system:
 
-    $ ./configure LDFLAGS="-static" ...
+    ./configure LDFLAGS="-static" ...
 
 ### Building from GIT
 
diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn' 
'--exclude=.svnignore' old/smcroute-2.4.1/configure.ac 
new/smcroute-2.4.3/configure.ac
--- old/smcroute-2.4.1/configure.ac     2018-06-16 13:40:28.000000000 +0200
+++ new/smcroute-2.4.3/configure.ac     2018-11-07 01:34:48.000000000 +0100
@@ -2,7 +2,7 @@
 # Process this file with autoconf to produce a configure script.
 
 AC_PREREQ(2.61)
-AC_INIT(SMCRoute, 2.4.1, https://github.com/troglobit/smcroute/issues, 
smcroute, http://troglobit.com/smcroute.html)
+AC_INIT(SMCRoute, 2.4.3, https://github.com/troglobit/smcroute/issues, 
smcroute, http://troglobit.com/smcroute.html)
 AM_INIT_AUTOMAKE([1.11 foreign dist-xz])
 AM_SILENT_RULES([yes])
 
@@ -17,6 +17,7 @@
 
 # Checks for programs.
 AC_PROG_CC
+AC_PROG_LN_S
 AC_PROG_INSTALL
 
 # The pidfile() code needs asprintf(), which relies on -D_GNU_SOURCE
@@ -32,7 +33,7 @@
 AC_CHECK_FUNCS([atexit dup2 memset select socket strchr strerror strrchr 
asprintf])
 
 # Check for usually missing API's
-AC_REPLACE_FUNCS([strlcpy utimensat])
+AC_REPLACE_FUNCS([strlcpy strlcat utimensat])
 AC_CONFIG_LIBOBJ_DIR([lib])
 
 # Check for sun_len in struct sockaddr_un
diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn' 
'--exclude=.svnignore' old/smcroute-2.4.1/lib/strlcat.c 
new/smcroute-2.4.3/lib/strlcat.c
--- old/smcroute-2.4.1/lib/strlcat.c    1970-01-01 01:00:00.000000000 +0100
+++ new/smcroute-2.4.3/lib/strlcat.c    2018-11-07 01:34:48.000000000 +0100
@@ -0,0 +1,55 @@
+/*     $OpenBSD: strlcat.c,v 1.15 2015/03/02 21:41:08 millert Exp $    */
+
+/*
+ * Copyright (c) 1998, 2015 Todd C. Miller <[email protected]>
+ *
+ * Permission to use, copy, modify, and distribute this software for any
+ * purpose with or without fee is hereby granted, provided that the above
+ * copyright notice and this permission notice appear in all copies.
+ *
+ * THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES
+ * WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF
+ * MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR
+ * ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES
+ * WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN
+ * ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF
+ * OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.
+ */
+
+#include <sys/types.h>
+#include <string.h>
+
+/*
+ * Appends src to string dst of size dsize (unlike strncat, dsize is the
+ * full size of dst, not space left).  At most dsize-1 characters
+ * will be copied.  Always NUL terminates (unless dsize <= strlen(dst)).
+ * Returns strlen(src) + MIN(dsize, strlen(initial dst)).
+ * If retval >= dsize, truncation occurred.
+ */
+size_t
+strlcat(char *dst, const char *src, size_t dsize)
+{
+       const char *odst = dst;
+       const char *osrc = src;
+       size_t n = dsize;
+       size_t dlen;
+
+       /* Find the end of dst and adjust bytes left but don't go past end. */
+       while (n-- != 0 && *dst != '\0')
+               dst++;
+       dlen = dst - odst;
+       n = dsize - dlen;
+
+       if (n-- == 0)
+               return(dlen + strlen(src));
+       while (*src != '\0') {
+               if (n != 0) {
+                       *dst++ = *src;
+                       n--;
+               }
+               src++;
+       }
+       *dst = '\0';
+
+       return(dlen + (src - osrc));    /* count does not include NUL */
+}
diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn' 
'--exclude=.svnignore' old/smcroute-2.4.1/lib/utimensat.c 
new/smcroute-2.4.3/lib/utimensat.c
--- old/smcroute-2.4.1/lib/utimensat.c  2018-06-16 13:40:28.000000000 +0200
+++ new/smcroute-2.4.3/lib/utimensat.c  2018-11-07 01:34:48.000000000 +0100
@@ -1,20 +1,18 @@
 /* Replacement in case utimensat(2) is missing
  *
- * Copyright (C) 2017  Joachim Nilsson <[email protected]>
+ * Copyright (C) 2017-2018  Joachim Nilsson <[email protected]>
  *
- * This program is free software; you can redistribute it and/or modify
- * it under the terms of the GNU General Public License as published by
- * the Free Software Foundation; either version 2 of the License, or
- * (at your option) any later version.
+ * Permission to use, copy, modify, and/or distribute this software for any
+ * purpose with or without fee is hereby granted, provided that the above
+ * copyright notice and this permission notice appear in all copies.
  *
- * This program is distributed in the hope that it will be useful,
- * but WITHOUT ANY WARRANTY; without even the implied warranty of
- * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
- * GNU General Public License for more details.
- *
- * You should have received a copy of the GNU General Public License
- * along with this program; if not, write to the Free Software
- * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA  02110-1301 USA
+ * THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES
+ * WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF
+ * MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR
+ * ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES
+ * WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN
+ * ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF
+ * OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.
  */
 
 #include "config.h"
@@ -38,17 +36,12 @@
        TIMESPEC_TO_TIMEVAL(&tv[0], &ts[0]);
        TIMESPEC_TO_TIMEVAL(&tv[1], &ts[1]);
 
+#ifdef AT_SYMLINK_NOFOLLOW
        if ((flags & AT_SYMLINK_NOFOLLOW) == AT_SYMLINK_NOFOLLOW)
                ret = lutimes(pathname, tv);
        else
+#endif
                ret = utimes(pathname, tv);
 
        return ret;
 }
-
-/**
- * Local Variables:
- *  indent-tabs-mode: t
- *  c-file-style: "linux"
- * End:
- */
diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn' 
'--exclude=.svnignore' old/smcroute-2.4.1/smcroute new/smcroute-2.4.3/smcroute
--- old/smcroute-2.4.1/smcroute 1970-01-01 01:00:00.000000000 +0100
+++ new/smcroute-2.4.3/smcroute 2018-11-07 01:34:48.000000000 +0100
@@ -0,0 +1,59 @@
+#!/bin/sh
+# Compatibility wrapper for users with old startup scripts
+# Written by Joachim Nilsson, placed in the public domain
+
+OP=$1
+shift
+
+case "$OP" in
+    -d)
+       smcrouted $*
+       ;;
+    -h)
+       echo "Usage: smcroute [OPTIONS] [ARGS]"
+       echo
+       echo "  -d       Start daemon"
+       echo "  -k       Kill a running daemon"
+       echo
+       echo "  -h       This help text"
+       echo "  -v       Show version"
+       echo
+       echo "  -a ARGS  Add a multicast route"
+       echo "  -r ARGS  Remove a multicast route"
+       echo
+       echo "  -j ARGS  Join a multicast group"
+       echo "  -l ARGS  Leave a multicast group"
+       echo
+       echo "     <------------- INBOUND -------------->  <----- OUTBOUND 
------>"
+       echo "  -a <IFNAME> <SOURCE-IP> <MULTICAST-GROUP>  <IFNAME> [<IFNAME> 
...]"
+       echo "  -r <IFNAME> <SOURCE-IP> <MULTICAST-GROUP>"
+       echo
+       echo "  -j <IFNAME> <MULTICAST-GROUP>"
+       echo "  -l <IFNAME> <MULTICAST-GROUP>"
+       echo
+       echo "NOTE: This is a compatibility wrapper script for SMCRoute.  
Intended for"
+       echo "      use with old style startup scripts.   It is recommended to 
migrate"
+       echo "      to /etc/smcroute.conf, see the smcroute(8) man page for 
help."
+       return 0
+       ;;
+    -k)
+       smcroutectl kill
+       ;;
+    -v)
+       smcroutectl version
+       ;;
+    -a)
+       smcroutectl add $*
+       ;;
+    -r)
+       smcroutectl remove $*
+       ;;
+    -j)
+       smcroutectl join $*
+       ;;
+    *)
+       echo "Unknown command or option to the SMCRoute compatiblity wrapper 
script."
+       echo "See the smcroute(8) man page for help on available commands."
+       return 1
+       ;;
+esac
diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn' 
'--exclude=.svnignore' old/smcroute-2.4.1/smcroute.8 
new/smcroute-2.4.3/smcroute.8
--- old/smcroute-2.4.1/smcroute.8       2018-06-16 13:40:28.000000000 +0200
+++ new/smcroute-2.4.3/smcroute.8       2018-11-07 01:34:48.000000000 +0100
@@ -20,14 +20,16 @@
 .Op Fl dtv
 .Op Fl I Ar NAME
 .Op Ar COMMAND
-.Oo Ao add | rem Ac Ao ROUTE Ac Oc Oo Ao join | leave Ac Ao GROUP Ac Oc
 .Pp
 .Nm smcroutectl
-.Op help | flush | kill | restart | version | show [groups|routes]
+.Ao help | flush | kill | restart | version Ac
 .Nm smcroutectl
-.Oo \ add | \ \ rem Oc Ao IFNAME Ac Oo SOURCE Oc Ar GROUP[/LEN] IFNAME Op 
IFNAME ...
+.Ao show Ac
+.Op groups | routes
 .Nm smcroutectl
-.Oo join | leave Oc Ao IFNAME Ac Oo SOURCE Oc Ar GROUP
+.Ao add \ | \ \ rem Ac Ao IFNAME Ac Oo SOURCE Oc Ar GROUP[/LEN] IFNAME Op 
IFNAME ...
+.Nm smcroutectl
+.Ao join | leave Ac Ao IFNAME Ac Oo SOURCE Oc Ar GROUP
 .Sh DESCRIPTION
 .Nm
 is both a daemon and command line tool to manipulate the multicast
diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn' 
'--exclude=.svnignore' old/smcroute-2.4.1/smcroute.conf 
new/smcroute-2.4.3/smcroute.conf
--- old/smcroute-2.4.1/smcroute.conf    2018-06-16 13:40:28.000000000 +0200
+++ new/smcroute-2.4.3/smcroute.conf    2018-11-07 01:34:48.000000000 +0100
@@ -9,9 +9,12 @@
 # NOTE: Use of the mgroup command should be avoided if possible.
 #       Instead configure "router ports" or similar on the switches
 #       or bridges on your LAN.  This to have them direct all the
-#       multicast to your router, or direct select groups they have
+#       multicast to your router, or select groups if they have
 #       such capabilities.  Usually MAC multicast filters exist.
 #
+#       Some switch manufacturers support mrdisc, RFC4286, which
+#       SMCRoute can use to advertise itself on source interfaces.
+#
 #       The UNIX kernel usually limits the number of multicast groups
 #       a socket/client can join.  In Linux, 20 mgroup lines can be
 #       configured by default, but this can be changed with sysctl:
diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn' 
'--exclude=.svnignore' old/smcroute-2.4.1/smcroute.init 
new/smcroute-2.4.3/smcroute.init
--- old/smcroute-2.4.1/smcroute.init    2018-06-16 13:40:28.000000000 +0200
+++ new/smcroute-2.4.3/smcroute.init    2018-11-07 01:34:48.000000000 +0100
@@ -9,17 +9,17 @@
 # Default-Start:     2 3 4 5
 # Default-Stop:      0 1 6
 # Short-Description: Static multicast router daemon
-# Description:       SMCRoute is a tool to manipulate the multicast routes
-#                    of the Linux kernel. It can be used as an alternative
-#                    to dynamic multicast routers like mrouted in situation
-#                    where static multicast routes should be maintained
-#                    and/or no proper IGMP signaling exists.
+# Description:       SMCRoute is a daemon and command line tool to manipulate
+#                    the multicast routing table of a UNIX kernel.  It can be
+#                    used as an alternative to dynamic multicast routers like
+#                    pimd or mrouted in situations where static routes should
+#                    be maintained and/or no proper IGMP signaling exists.
 ### END INIT INFO
 
 PATH=/usr/local/sbin:/usr/local/bin:/sbin:/bin:/usr/sbin:/usr/bin
-DAEMON=/usr/sbin/smcroute
-DAEMON_OPTS=-d
-NAME=smcroute
+DAEMON=/usr/sbin/smcrouted
+DAEMON_OPTS=
+NAME=smcrouted
 DESC="static multicast router daemon"
 
 test -x $DAEMON || exit 0
@@ -72,6 +72,9 @@
        stop
        start
        ;;
+  status)
+       status_of_proc "$DAEMON" "$DESC" && exit 0 || exit $?
+       ;;
   *)
        N=/etc/init.d/$NAME
        echo "Usage: $N {start|stop|restart|force-reload}" >&2
diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn' 
'--exclude=.svnignore' old/smcroute-2.4.1/src/conf.c 
new/smcroute-2.4.3/src/conf.c
--- old/smcroute-2.4.1/src/conf.c       2018-06-16 13:40:28.000000000 +0200
+++ new/smcroute-2.4.3/src/conf.c       2018-11-07 01:34:48.000000000 +0100
@@ -29,8 +29,11 @@
 #include "mcgroup.h"
 
 #define MAX_LINE_LEN 512
+#define DEBUG(fmt, args...)                    \
+       smclog(LOG_DEBUG, "%s:%02d: " fmt, conf, lineno, ##args)
 #define WARN(fmt, args...)                     \
        smclog(LOG_WARNING, "%s:%02d: " fmt, conf, lineno, ##args)
+
 static const char *conf = NULL;
 
 static char *pop_token(char **line)
@@ -52,7 +55,7 @@
        end = token;
        while (*end && !isspace((int)*end))
                end++;
-       if (*end == 0 || end == token) {
+       if (end == token) {
                *line = NULL;
                return NULL;
        }
@@ -307,6 +310,7 @@
                char *group  = NULL;
                char *dest[32];
 
+               DEBUG("Read line: '%s'", line);
                while ((token = pop_token(&line))) {
                        /* Strip comments. */
                        if (match("#", token))
diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn' 
'--exclude=.svnignore' old/smcroute-2.4.1/src/ifvc.c 
new/smcroute-2.4.3/src/ifvc.c
--- old/smcroute-2.4.1/src/ifvc.c       2018-06-16 13:40:28.000000000 +0200
+++ new/smcroute-2.4.3/src/ifvc.c       2018-11-07 01:34:48.000000000 +0100
@@ -33,33 +33,35 @@
 
 #include "log.h"
 #include "ifvc.h"
+#include "mcgroup.h"
+#include "timer.h"
 #include "util.h"
 
 static unsigned int num_ifaces = 0, num_ifaces_alloc = 0;
 static struct iface *iface_list = NULL;
 
 /**
- * iface_init - Setup vector of active interfaces
+ * iface_update - Periodic check of new interfaces or addresses
+ * @refresh: Only update interface addresses
  *
- * Builds up a vector with active system interfaces.  Must be called
- * before any other interface functions in this module!
+ * This functions is not only called by iface_init() at startup or
+ * SIGHUP, it is also called periodically to check if known ifaces
+ * have changed or gained an IP address.  This is required because
+ * on Linux (and possibly other UNICES too) it is not possible to
+ * join a multicast group without an address (YMMV).
+ *
+ * Note:
+ * For now we only return %TRUE for interface updates.
+ *
+ * Returns:
+ * %TRUE(1), at least one interface added or updated, otherwise
+ * %FALSE(0) if there was no change.
  */
-void iface_init(void)
+int iface_update(int refresh)
 {
-       struct iface *iface;
        struct ifaddrs *ifaddr, *ifa;
-
-       num_ifaces = 0;
-
-       if (iface_list)
-               free(iface_list);
-
-       num_ifaces_alloc = 1;
-       iface_list = calloc(num_ifaces_alloc, sizeof(struct iface));
-       if (!iface_list) {
-               smclog(LOG_ERR, "Failed allocating space for interfaces: %s", 
strerror(errno));
-               exit(255);
-       }
+       struct iface *iface;
+       int change = 0;
 
        if (getifaddrs(&ifaddr) == -1) {
                smclog(LOG_ERR, "Failed retrieving interface addresses: %s", 
strerror(errno));
@@ -69,11 +71,16 @@
        for (ifa = ifaddr; ifa; ifa = ifa->ifa_next) {
                /* Check if already added? */
                if ((iface = iface_find_by_name(ifa->ifa_name))) {
-                       if (!iface->inaddr.s_addr && ifa->ifa_addr && 
ifa->ifa_addr->sa_family == AF_INET)
+                       if (!iface->inaddr.s_addr && ifa->ifa_addr && 
ifa->ifa_addr->sa_family == AF_INET) {
                                iface->inaddr = ((struct sockaddr_in 
*)ifa->ifa_addr)->sin_addr;
+                               change = 1;
+                       }
                        continue;
                }
 
+               if (refresh)
+                       continue;
+
                /* Allocate more space? */
                if (num_ifaces == num_ifaces_alloc) {
                        num_ifaces_alloc *= 2;
@@ -107,6 +114,46 @@
                iface->threshold = DEFAULT_THRESHOLD;
        }
        freeifaddrs(ifaddr);
+
+       return change;
+}
+
+/**
+ * iface_init - Setup vector of active interfaces
+ *
+ * Builds up a vector with active system interfaces.  Must be called
+ * before any other interface functions in this module!
+ */
+void iface_init(void)
+{
+       num_ifaces = 0;
+
+       if (iface_list)
+               free(iface_list);
+
+       num_ifaces_alloc = 1;
+       iface_list = calloc(num_ifaces_alloc, sizeof(struct iface));
+       if (!iface_list) {
+               smclog(LOG_ERR, "Failed allocating space for interfaces: %s", 
strerror(errno));
+               exit(255);
+       }
+
+       iface_update(0);
+
+       /* In case of addresses being added later ... */
+       if (timer_add(5, iface_refresh, NULL) < 0 && errno != EEXIST)
+               smclog(LOG_WARNING, "failed creating iface refresh timer: %s", 
strerror(errno));
+}
+
+void iface_refresh(void *arg)
+{
+       (void)arg;
+
+       if (!iface_update(1))
+               return;
+
+       if (mcgroup_refresh())
+               timer_del(iface_refresh, arg);
 }
 
 /**
@@ -134,20 +181,34 @@
        unsigned int i;
        struct iface *iface;
        struct iface *candidate = NULL;
+       char *nm, *ptr;
 
        if (!ifname)
                return NULL;
 
+       nm = strdup(ifname);
+       if (!nm)
+               return NULL;
+
+       /* Alias interfaces should use the same VIF/MIF as parent */
+       ptr = strchr(nm, ':');
+       if (ptr)
+               *ptr = 0;
+
        for (i = 0; i < num_ifaces; i++) {
                iface = &iface_list[i];
-               if (!strcmp(ifname, iface->name)) {
-                       if (iface->vif >= 0)
+               if (!strcmp(nm, iface->name)) {
+                       if (iface->vif >= 0) {
+                               free(nm);
                                return iface;
+                       }
 
                        candidate = iface;
                }
        }
 
+       free(nm);
+
        return candidate;
 }
 
diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn' 
'--exclude=.svnignore' old/smcroute-2.4.1/src/ifvc.h 
new/smcroute-2.4.3/src/ifvc.h
--- old/smcroute-2.4.1/src/ifvc.h       2018-06-16 13:40:28.000000000 +0200
+++ new/smcroute-2.4.3/src/ifvc.h       2018-11-07 01:34:48.000000000 +0100
@@ -25,6 +25,7 @@
 };
 
 void          iface_init              (void);
+void          iface_refresh           (void *arg);
 void          iface_exit              (void);
 
 struct iface *iface_iterator          (int first);
diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn' 
'--exclude=.svnignore' old/smcroute-2.4.1/src/ipc.c new/smcroute-2.4.3/src/ipc.c
--- old/smcroute-2.4.1/src/ipc.c        2018-06-16 13:40:28.000000000 +0200
+++ new/smcroute-2.4.3/src/ipc.c        2018-11-07 01:34:48.000000000 +0100
@@ -52,13 +52,13 @@
        if (!msg) {
                /* Skip logging client disconnects */
                if (errno != ECONNRESET)
-                       smclog(LOG_WARNING, "Failed receving IPC message from 
client: %s", strerror(errno));
+                       smclog(LOG_WARNING, "Failed receiving IPC message from 
client: %s", strerror(errno));
                return;
        }
 
        if (msg_do(sd, msg)) {
                if (EINVAL == errno)
-                       smclog(LOG_WARNING, "Unkown or malformed IPC message 
'%c' from client.", msg->cmd);
+                       smclog(LOG_WARNING, "Unknown or malformed IPC message 
'%c' from client.", msg->cmd);
                errno = 0;
                ipc_send(sd, log_message, strlen(log_message) + 1);
        } else {
diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn' 
'--exclude=.svnignore' old/smcroute-2.4.1/src/mcgroup.c 
new/smcroute-2.4.3/src/mcgroup.c
--- old/smcroute-2.4.1/src/mcgroup.c    2018-06-16 13:40:28.000000000 +0200
+++ new/smcroute-2.4.3/src/mcgroup.c    2018-11-07 01:34:48.000000000 +0100
@@ -52,6 +52,11 @@
  */
 LIST_HEAD(, mgroup) mgroup_static_list = LIST_HEAD_INITIALIZER();
 
+/*
+ * Failed joins due to no-ip-address on iface yet ...
+ */
+LIST_HEAD(, mgroup) mgroup_retry_list  = LIST_HEAD_INITIALIZER();
+
 static int mcgroup4_socket = -1;
 
 #ifdef HAVE_LINUX_FILTER_H
@@ -67,6 +72,7 @@
 };
 #endif /* HAVE_LINUX_FILTER_H */
 
+
 static struct iface *match_valid_iface(const char *ifname, struct ifmatch 
*state)
 {
        struct iface *iface = iface_match_by_name(ifname, state);
@@ -77,7 +83,7 @@
        return iface;
 }
 
-static void list_add(struct iface *iface, struct in_addr source, struct 
in_addr group)
+static void list_add(struct iface *iface, struct in_addr source, struct 
in_addr group, int fail)
 {
        struct mgroup *entry;
 
@@ -91,7 +97,11 @@
        entry->inbound = iface->vif;
        entry->source  = source;
        entry->group   = group;
-       LIST_INSERT_HEAD(&mgroup_static_list, entry, link);
+
+       if (fail)
+               LIST_INSERT_HEAD(&mgroup_retry_list, entry, link);
+       else
+               LIST_INSERT_HEAD(&mgroup_static_list, entry, link);
 }
 
 static void list_rem(struct iface *iface, struct in_addr source, struct 
in_addr group)
@@ -126,35 +136,105 @@
        }
 }
 
-static int mcgroup_join_leave_ipv4(int sd, int cmd, const char *ifname, struct 
in_addr group)
+static int join_leave_ipv4(int sd, int cmd, struct iface *iface, struct 
in_addr group)
 {
-       int opt, ret = 0;
        struct ip_mreq mreq;
-       struct iface *iface;
+       int opt, retry = 0;
+
+       if (!cmd) {
+               cmd = 'j';
+               retry = 1;
+       }
+
+       if (cmd == 'j')
+               opt = IP_ADD_MEMBERSHIP;
+       else
+               opt = IP_DROP_MEMBERSHIP;
+
+       mreq.imr_multiaddr.s_addr = group.s_addr;
+       mreq.imr_interface.s_addr = iface->inaddr.s_addr;
+       if (setsockopt(sd, IPPROTO_IP, opt, &mreq, sizeof(mreq))) {
+               char grp[16];
+
+               if (retry)
+                       return 1;
+
+               inet_ntop(AF_INET, &group, grp, sizeof(grp));
+               if (EADDRNOTAVAIL == errno && cmd == 'l')
+                       smclog(LOG_DEBUG, "failed leave (*,%s), not a member", 
grp);
+               else if (EADDRINUSE == errno && cmd == 'j')
+                       smclog(LOG_DEBUG, "failed join (*,%s), already member", 
grp);
+               else if (ENODEV == errno && cmd == 'j')
+                       smclog(LOG_ERR, "failed join (*,%s) on %s, no interface 
address.", grp, iface);
+               else
+                       smclog(LOG_ERR, "failed %s (*,%s) on iface %s.  Error 
%d: %s",
+                              cmd == 'j' ? "join" : "leave", grp, iface->name, 
errno, strerror(errno));
+
+               return 1;
+       }
+
+       return 0;
+}
+
+static int join_leave_ssm_ipv4(int sd, int cmd, struct iface *iface, struct 
in_addr source, struct in_addr group)
+{
+       struct ip_mreq_source mreqsrc;
+       int opt, retry = 0;
+
+       if (!cmd) {
+               cmd = 'j';
+               retry = 1;
+       }
+
+       if (cmd == 'j')
+               opt = IP_ADD_SOURCE_MEMBERSHIP;
+       else
+               opt = IP_DROP_SOURCE_MEMBERSHIP;
+
+       mreqsrc.imr_multiaddr.s_addr = group.s_addr;
+       mreqsrc.imr_sourceaddr.s_addr = source.s_addr;
+       mreqsrc.imr_interface.s_addr = iface->inaddr.s_addr;
+       if (setsockopt(sd, IPPROTO_IP, opt, &mreqsrc, sizeof(mreqsrc))) {
+               char *src, grp[16];
+
+               if (retry)
+                       return 1;
+
+               src = inet_ntoa(source);
+               inet_ntop(AF_INET, &group, grp, sizeof(grp));
+
+               if (EADDRNOTAVAIL == errno && cmd == 'j')
+                       smclog(LOG_DEBUG, "failed join (%s,%s), already 
member", src, grp);
+               else if (EADDRNOTAVAIL == errno && cmd == 'l')
+                       smclog(LOG_DEBUG, "failed leave (%s,%s), not a member 
from that source", src, grp);
+               else if (EINVAL == errno && cmd == 'l')
+                       smclog(LOG_DEBUG, "failed leave (%s,%s), not a member", 
src, grp);
+               else
+                       smclog(LOG_WARNING, "failed %s (%s,%s) on iface %s.  
Error %d: %s",
+                              cmd == 'j' ? "join" : "leave", src, grp, 
iface->name, errno, strerror(errno));
+
+               return 1;
+       }
+
+       return 0;
+}
+
+static int mcgroup_join_leave_ipv4(int sd, int cmd, const char *ifname, struct 
in_addr group)
+{
        struct ifmatch state;
        struct in_addr any_src;
+       struct iface *iface;
+       int ret = 0;
 
        any_src.s_addr = htonl(INADDR_ANY);
        iface_match_init(&state);
        while ((iface = match_valid_iface(ifname, &state))) {
-               if (cmd == 'j') {
-                       list_add(iface, any_src, group);
-                       opt = IP_ADD_MEMBERSHIP;
-               } else {
+               ret += join_leave_ipv4(sd, cmd, iface, group);
+
+               if (cmd == 'j')
+                       list_add(iface, any_src, group, ret);
+               else
                        list_rem(iface, any_src, group);
-                       opt = IP_DROP_MEMBERSHIP;
-               }
-               mreq.imr_multiaddr.s_addr = group.s_addr;
-               mreq.imr_interface.s_addr = iface->inaddr.s_addr;
-               if (setsockopt(sd, IPPROTO_IP, opt, &mreq, sizeof(mreq))) {
-                       if (EADDRNOTAVAIL == errno && cmd == 'l')
-                               smclog(LOG_DEBUG, "failed leaving group, not a 
member of %s", inet_ntoa(group));
-                       else if (EADDRINUSE == errno && cmd == 'j')
-                               smclog(LOG_DEBUG, "failed joining group, 
already member of %s", inet_ntoa(group));
-                       else
-                               smclog(LOG_DEBUG, "failed group %s: %s", cmd == 
'j' ? "join" : "leave", strerror(errno));
-                       ret = 1;
-               }
        }
 
        if (!state.match_count)
@@ -169,34 +249,18 @@
        smclog(LOG_WARNING, "Source specific join/leave not supported, ignoring 
source %s", inet_ntoa(source));
        return mcgroup_join_leave_ipv4(sd, cmd, ifname, group);
 #else
-       int opt, ret = 0;
-       struct ip_mreq_source mreqsrc;
        struct iface *iface;
        struct ifmatch state;
+       int ret = 0;
 
        iface_match_init(&state);
        while ((iface = match_valid_iface(ifname, &state))) {
-               if (cmd == 'j') {
-                       list_add(iface, source, group);
-                       opt = IP_ADD_SOURCE_MEMBERSHIP;
-               } else {
+               ret += join_leave_ssm_ipv4(sd, cmd, iface, source, group);
+
+               if (cmd == 'j')
+                       list_add(iface, source, group, ret);
+               else
                        list_rem(iface, source, group);
-                       opt = IP_DROP_SOURCE_MEMBERSHIP;
-               }
-               mreqsrc.imr_multiaddr.s_addr = group.s_addr;
-               mreqsrc.imr_sourceaddr.s_addr = source.s_addr;
-               mreqsrc.imr_interface.s_addr = iface->inaddr.s_addr;
-               if (setsockopt(sd, IPPROTO_IP, opt, &mreqsrc, sizeof(mreqsrc))) 
{
-                       if (EADDRNOTAVAIL == errno && cmd == 'j')
-                               smclog(LOG_DEBUG, "failed join, already member 
of %s", inet_ntoa(group));
-                       else if (EADDRNOTAVAIL == errno && cmd == 'l')
-                               smclog(LOG_DEBUG, "failed leave, not a member 
of %s from that source", inet_ntoa(group));
-                       else if (EINVAL == errno && cmd == 'l')
-                               smclog(LOG_DEBUG, "failed leave, not a member 
of %s", inet_ntoa(group));
-                       else
-                               smclog(LOG_WARNING, "failed %s: %s", cmd == 'j' 
? "join" : "leave", strerror(errno));
-                       ret = 1;
-               }
        }
 
        if (!state.match_count)
@@ -256,7 +320,54 @@
                LIST_REMOVE(entry, link);
                free(entry);
        }
+}
+
+/*
+ * Retry join of previously failed joins, called by iface_update()
+ */
+static void mcgroup4_retry(void)
+{
+       struct in_addr any_src;
+       struct mgroup *entry, *tmp;
+
+       any_src.s_addr = htonl(INADDR_ANY);
+
+       LIST_FOREACH_SAFE(entry, &mgroup_retry_list, link, tmp) {
+               struct iface *iface;
+               char grp[16];
+               int is_any = 0;
+               int rc;
+
+               iface = iface_find_by_vif(entry->inbound);
+               if (!iface)
+                       continue;
+
+               if (!memcmp(&entry->source, &any_src, sizeof(any_src))) {
+                       is_any = 1;
+                       rc = join_leave_ipv4(mcgroup4_socket, 0, iface, 
entry->group);
+               } else
+                       rc = join_leave_ssm_ipv4(mcgroup4_socket, 0, iface, 
entry->source, entry->group);
+               if (rc)
+                       continue;
+
+               inet_ntop(AF_INET, &entry->group, grp, sizeof(grp));
+               smclog(LOG_NOTICE, "successful join (%s,%s) on iface %s.",
+                      is_any ? "*" : inet_ntoa(entry->source), grp, 
iface->name,
+                      errno, strerror(errno));
+
+               /* Move to list of joined groups */
+               LIST_REMOVE(entry, link);
+               LIST_INSERT_HEAD(&mgroup_static_list, entry, link);
+       }
+}
+
+int mcgroup_refresh(void)
+{
+       mcgroup4_retry();
+       if (LIST_EMPTY(&mgroup_retry_list))
+               return 1;
 
+       return 0;
 }
 
 #ifdef HAVE_IPV6_MULTICAST_HOST
diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn' 
'--exclude=.svnignore' old/smcroute-2.4.1/src/mcgroup.h 
new/smcroute-2.4.3/src/mcgroup.h
--- old/smcroute-2.4.1/src/mcgroup.h    2018-06-16 13:40:28.000000000 +0200
+++ new/smcroute-2.4.3/src/mcgroup.h    2018-11-07 01:34:48.000000000 +0100
@@ -2,6 +2,8 @@
 #ifndef SMCROUTE_MCGROUP_H_
 #define SMCROUTE_MCGROUP_H_
 
+int  mcgroup_refresh    (void);
+
 int  mcgroup4_join      (const char *ifname, struct in_addr  source, struct 
in_addr  group);
 int  mcgroup4_leave     (const char *ifname, struct in_addr  source, struct 
in_addr  group);
 void mcgroup4_disable   (void);
diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn' 
'--exclude=.svnignore' old/smcroute-2.4.1/src/mrdisc.c 
new/smcroute-2.4.3/src/mrdisc.c
--- old/smcroute-2.4.1/src/mrdisc.c     2018-06-16 13:40:28.000000000 +0200
+++ new/smcroute-2.4.3/src/mrdisc.c     2018-11-07 01:34:48.000000000 +0100
@@ -74,7 +74,7 @@
 int mrdisc_init(int period)
 {
        interval = period;
-       if (timer_add(interval, mrdisc_send, NULL) < 0) {
+       if (timer_add(interval, mrdisc_send, NULL) < 0 && errno != EEXIST) {
                smclog(LOG_ERR, "Failed starting mrdisc announcement timer.");
                return -1;
        }
diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn' 
'--exclude=.svnignore' old/smcroute-2.4.1/src/mroute.c 
new/smcroute-2.4.3/src/mroute.c
--- old/smcroute-2.4.1/src/mroute.c     2018-06-16 13:40:28.000000000 +0200
+++ new/smcroute-2.4.3/src/mroute.c     2018-11-07 01:34:48.000000000 +0100
@@ -561,8 +561,8 @@
        return 0;
 }
 
-/* 
- * Query kernel for install MFC entry usage statistics
+/*
+ * Query kernel for route usage statistics
  */
 static int get_stats4(struct mroute4 *route, unsigned long *pktcnt, unsigned 
long *bytecnt, unsigned long *wrong_if)
 {
@@ -1204,12 +1204,12 @@
        snprintf(buf, sizeof(buf), "%-34s %-16s", sg, i->name);
 
        if (detail) {
-               char stats[25];
+               char stats[30];
                unsigned long p = 0, b = 0;
 
                get_stats4(r, &p, &b, NULL);
-               snprintf(stats, sizeof(stats), " %10.10lu %10.10lu ", p, b);
-               strcat(buf, stats);
+               snprintf(stats, sizeof(stats), " %10lu %10lu ", p, b);
+               strlcat(buf, stats, sizeof(buf));
        }
 
        for (vif = 0; vif < MAX_MC_VIFS; vif++) {
@@ -1223,9 +1223,9 @@
                        continue;
 
                snprintf(tmp, sizeof(tmp), " %s", i->name);
-               strcat(buf, tmp);
+               strlcat(buf, tmp, sizeof(buf));
        }
-       strcat(buf, "\n");
+       strlcat(buf, "\n", sizeof(buf));
 
        if (ipc_send(sd, buf, strlen(buf)) < 0) {
                smclog(LOG_ERR, "Failed sending reply to client: %s", 
strerror(errno));
diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn' 
'--exclude=.svnignore' old/smcroute-2.4.1/src/pidfile.c 
new/smcroute-2.4.3/src/pidfile.c
--- old/smcroute-2.4.1/src/pidfile.c    2018-06-16 13:40:28.000000000 +0200
+++ new/smcroute-2.4.3/src/pidfile.c    2018-11-07 01:34:48.000000000 +0100
@@ -47,14 +47,20 @@
 static char *pidfile_path = NULL;
 static pid_t pidfile_pid  = 0;
 
-static void pidfile_cleanup(void);
-
 const  char *__pidfile_path = LOCALSTATEDIR "/run";
 const  char *__pidfile_name = NULL;
 extern char *prognm;
 
-int
-pidfile(const char *basename, uid_t uid, gid_t gid)
+static void pidfile_cleanup(void)
+{
+       if (pidfile_path != NULL && pidfile_pid == getpid()) {
+               (void) unlink(pidfile_path);
+               free(pidfile_path);
+               pidfile_path = NULL;
+       }
+}
+
+int pidfile_create(const char *basename, uid_t uid, gid_t gid)
 {
        int save_errno;
        int atexit_already;
@@ -70,7 +76,7 @@
        if (pidfile_path != NULL) {
                if (!access(pidfile_path, R_OK) && pid == pidfile_pid) {
                        utimensat(0, pidfile_path, NULL, 0);
-                       return (0);
+                       return 0;
                }
                free(pidfile_path);
                pidfile_path = NULL;
@@ -80,10 +86,10 @@
 
        if (basename[0] != '/') {
                if (asprintf(&pidfile_path, "%s/%s.pid", __pidfile_path, 
basename) == -1)
-                       return (-1);
+                       return -1;
        } else {
                if (asprintf(&pidfile_path, "%s", basename) == -1)
-                       return (-1);
+                       return -1;
        }
 
        smclog(LOG_DEBUG, "Creating PID file %s", pidfile_path);
@@ -92,7 +98,7 @@
                free(pidfile_path);
                pidfile_path = NULL;
                errno = save_errno;
-               return (-1);
+               return -1;
        }
 
        if (fprintf(f, "%ld\n", (long)pid) <= 0 || fflush(f) != 0) {
@@ -102,20 +108,20 @@
                free(pidfile_path);
                pidfile_path = NULL;
                errno = save_errno;
-               return (-1);
+               return -1;
        }
        (void) fclose(f);
        __pidfile_name = pidfile_path;
 
        if (chown(pidfile_path, uid, gid))
-               return (-1);
+               return -1;
 
        /*
         * LITE extension, no need to set up another atexit() handler
         * if user only called us to update the mtime of the PID file
         */
        if (atexit_already)
-               return (0);
+               return 0;
 
        pidfile_pid = pid;
        if (atexit(pidfile_cleanup) < 0) {
@@ -125,18 +131,8 @@
                pidfile_path = NULL;
                pidfile_pid = 0;
                errno = save_errno;
-               return (-1);
+               return -1;
        }
 
-       return (0);
-}
-
-static void
-pidfile_cleanup(void)
-{
-       if (pidfile_path != NULL && pidfile_pid == getpid()) {
-               (void) unlink(pidfile_path);
-               free(pidfile_path);
-               pidfile_path = NULL;
-       }
+       return 0;
 }
diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn' 
'--exclude=.svnignore' old/smcroute-2.4.1/src/smcroutectl.c 
new/smcroute-2.4.3/src/smcroutectl.c
--- old/smcroute-2.4.1/src/smcroutectl.c        2018-06-16 13:40:28.000000000 
+0200
+++ new/smcroute-2.4.3/src/smcroutectl.c        2018-11-07 01:34:48.000000000 
+0100
@@ -149,7 +149,7 @@
        if (count && argv[0][0] == 'g')
                snprintf(line, sizeof(line), "\e[7m%-34s %-16s", g, i);
        else if (detail)
-               snprintf(line, sizeof(line), "\e[7m%-34s %-16s %10s %10s %-8s", 
r, i, p, b, o);
+               snprintf(line, sizeof(line), "\e[7m%-34s %-16s %10s %10s  
%-8s", r, i, p, b, o);
        else
                snprintf(line, sizeof(line), "\e[7m%-34s %-16s %-8s", r, i, o);
 
diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn' 
'--exclude=.svnignore' old/smcroute-2.4.1/src/smcrouted.c 
new/smcroute-2.4.3/src/smcrouted.c
--- old/smcroute-2.4.1/src/smcrouted.c  2018-06-16 13:40:28.000000000 +0200
+++ new/smcroute-2.4.3/src/smcrouted.c  2018-11-07 01:34:48.000000000 +0100
@@ -98,7 +98,7 @@
        conf_read(conf_file, do_vifs);
 
        /* Acknowledge client SIGHUP/reload by touching the pidfile */
-       pidfile(NULL, uid, gid);
+       pidfile_create(NULL, uid, gid);
 }
 
 /*
@@ -176,14 +176,14 @@
        }
 
        /*
-        * Build list of multicast-capable physical interfaces
+        * Timer API needs to be initilized before mroute4_enable()
         */
-       iface_init();
+       timer_init();
 
        /*
-        * Timer API needs to be initilized before mroute4_enable()
+        * Build list of multicast-capable physical interfaces
         */
-       timer_init();
+       iface_init();
 
        if (mroute4_enable(do_vifs, table_id, cache_tmo)) {
                if (errno == EADDRINUSE)
@@ -214,8 +214,8 @@
        conf_read(conf_file, do_vifs);
 
        /* Everything setup, notify any clients by creating the pidfile */
-       if (pidfile(pid_file, uid, gid))
-               smclog(LOG_WARNING, "Failed create/chown pidfile: %s", 
strerror(errno));
+       if (pidfile_create(pid_file, uid, gid))
+               smclog(LOG_WARNING, "Failed create/chown PID file: %s", 
strerror(errno));
 
        /* Drop root privileges before entering the server loop */
        cap_drop_root(uid, gid);
@@ -333,7 +333,7 @@
 int main(int argc, char *argv[])
 {
        int c;
-       int log_opts = LOG_CONS | LOG_PID;
+       int log_opts = LOG_NDELAY | LOG_PID;
 
        prognm = progname(argv[0]);
        while ((c = getopt(argc, argv, "c:d:e:f:hI:l:m:nNp:P:st:v")) != EOF) {
diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn' 
'--exclude=.svnignore' old/smcroute-2.4.1/src/timer.c 
new/smcroute-2.4.3/src/timer.c
--- old/smcroute-2.4.1/src/timer.c      2018-06-16 13:40:28.000000000 +0200
+++ new/smcroute-2.4.3/src/timer.c      2018-11-07 01:34:48.000000000 +0100
@@ -27,6 +27,7 @@
 #include "log.h"
 #include "queue.h"
 #include "socket.h"
+#include "timer.h"
 
 /*
  * TODO
@@ -35,6 +36,7 @@
  */
 struct timer {
        LIST_ENTRY(timer) link;
+       int             active; /* Set to 0 to delete */
 
        int             period; /* period time in seconds */
        struct timespec timeout;
@@ -77,6 +79,21 @@
        return b;
 }
 
+static struct timer *find(void (*cb), void *arg)
+{
+       struct timer *entry;
+
+       LIST_FOREACH(entry, &tl, link) {
+               if (entry->cb != cb || entry->arg != arg)
+                       continue;
+
+               return entry;
+       }
+
+       return NULL;
+}
+
+
 static int start(struct timespec *now)
 {
        struct timer *next, *entry;
@@ -102,19 +119,24 @@
 {
        char dummy;
        struct timespec now;
-       struct timer *entry;
+       struct timer *entry, *tmp;
 
        (void)arg;
        if (read(sd, &dummy, 1) < 0)
                smclog(LOG_DEBUG, "Failed read(pipe): %s", strerror(errno));
 
        clock_gettime(CLOCK_MONOTONIC, &now);
-       LIST_FOREACH(entry, &tl, link) {
+       LIST_FOREACH_SAFE(entry, &tl, link, tmp) {
                if (expired(entry, &now)) {
                        if (entry->cb)
                                entry->cb(entry->arg);
                        set(entry, &now);
                }
+
+               if (!entry->active) {
+                       LIST_REMOVE(entry, link);
+                       free(entry);
+               }
        }
 
        start(&now);
@@ -165,6 +187,12 @@
        struct timer *t;
        struct timespec now;
 
+       t = find(cb, arg);
+       if (t && t->active) {
+               errno = EEXIST;
+               return -1;
+       }
+
        if (clock_gettime(CLOCK_MONOTONIC, &now) < 0)
                return -1;
 
@@ -172,6 +200,7 @@
        if (!t)
                return -1;
 
+       t->active = 1;
        t->period = period;
        t->cb     = cb;
        t->arg    = arg;
@@ -183,6 +212,24 @@
        return start(&now);
 }
 
+/*
+ * delete a timer
+ */
+int timer_del(void (*cb)(void *), void *arg)
+{
+       struct timer *entry;
+
+       entry = find(cb, arg);
+       if (!entry)
+               return 1;
+
+       /* Mark for deletion and issue a new run */
+       entry->active = 0;
+       handler(0);
+
+       return 0;
+}
+
 /**
  * Local Variables:
  *  indent-tabs-mode: t
diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn' 
'--exclude=.svnignore' old/smcroute-2.4.1/src/timer.h 
new/smcroute-2.4.3/src/timer.h
--- old/smcroute-2.4.1/src/timer.h      2018-06-16 13:40:28.000000000 +0200
+++ new/smcroute-2.4.3/src/timer.h      2018-11-07 01:34:48.000000000 +0100
@@ -3,6 +3,8 @@
 #define SMCROUTE_TIMER_H_
 
 int timer_init (void);
+
 int timer_add  (int period, void (*cb)(void *), void *arg);
+int timer_del  (void (*cb)(void *), void *arg);
 
 #endif /* SMCROUTE_TIMER_H_ */
diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn' 
'--exclude=.svnignore' old/smcroute-2.4.1/src/util.h 
new/smcroute-2.4.3/src/util.h
--- old/smcroute-2.4.1/src/util.h       2018-06-16 13:40:28.000000000 +0200
+++ new/smcroute-2.4.3/src/util.h       2018-11-07 01:34:48.000000000 +0100
@@ -18,12 +18,18 @@
 #define NELEMS(array) (sizeof(array) / sizeof(array[0]))
 #endif
 
-int pidfile(const char *basename, uid_t uid, gid_t gid);
+int pidfile_create(const char *basename, uid_t uid, gid_t gid);
+
 #ifndef HAVE_UTIMENSAT
 int utimensat(int dirfd, const char *pathname, const struct timespec ts[2], 
int flags);
 #endif
+
 #ifndef HAVE_STRLCPY
 size_t strlcpy(char *dst, const char *src, size_t len);
 #endif
 
+#ifndef HAVE_STRLCAT
+size_t strlcat(char *dst, const char *src, size_t dsize);
+#endif
+
 #endif /* SMCROUTE_UTIL_H_ */


Reply via email to