Script 'mail_helper' called by obssrc
Hello community,

here is the log from the commit of package smcroute for openSUSE:Factory 
checked in at 2022-12-03 10:04:03
++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++
Comparing /work/SRC/openSUSE:Factory/smcroute (Old)
 and      /work/SRC/openSUSE:Factory/.smcroute.new.1835 (New)
++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++

Package is "smcroute"

Sat Dec  3 10:04:03 2022 rev:9 rq:1039756 version:2.5.6

Changes:
--------
--- /work/SRC/openSUSE:Factory/smcroute/smcroute.changes        2021-11-21 
23:52:46.122139466 +0100
+++ /work/SRC/openSUSE:Factory/.smcroute.new.1835/smcroute.changes      
2022-12-03 10:04:16.899455387 +0100
@@ -1,0 +2,7 @@
+Mon Nov 28 17:57:31 UTC 2022 - Martin Hauke <mar...@gmx.de>
+
+- Update to version 2.5.6
+  * Add smcroutectl batch support.
+  * Fix removing group config.
+
+-------------------------------------------------------------------

Old:
----
  smcroute-2.5.5.tar.gz

New:
----
  smcroute-2.5.6.tar.gz

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

Other differences:
------------------
++++++ smcroute.spec ++++++
--- /var/tmp/diff_new_pack.ArvIZO/_old  2022-12-03 10:04:17.499458721 +0100
+++ /var/tmp/diff_new_pack.ArvIZO/_new  2022-12-03 10:04:17.503458743 +0100
@@ -1,8 +1,8 @@
 #
 # spec file for package smcroute
 #
-# Copyright (c) 2021 SUSE LLC
-# Copyright (c) 2018-2021, Martin Hauke <mar...@gmx.de>
+# Copyright (c) 2022 SUSE LLC
+# Copyright (c) 2018-2022, Martin Hauke <mar...@gmx.de>
 #
 # All modifications and additions to the file contributed by third parties
 # remain the property of their copyright owners, unless otherwise agreed
@@ -18,7 +18,7 @@
 
 
 Name:           smcroute
-Version:        2.5.5
+Version:        2.5.6
 Release:        0
 Summary:        Static multicast routing for UNIX
 License:        GPL-3.0-only

++++++ smcroute-2.5.5.tar.gz -> smcroute-2.5.6.tar.gz ++++++
diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn' 
'--exclude=.svnignore' old/smcroute-2.5.5/.github/workflows/build.yml 
new/smcroute-2.5.6/.github/workflows/build.yml
--- old/smcroute-2.5.5/.github/workflows/build.yml      2021-11-21 
09:38:26.000000000 +0100
+++ new/smcroute-2.5.6/.github/workflows/build.yml      2022-11-28 
08:00:09.000000000 +0100
@@ -29,7 +29,7 @@
           sudo modprobe ip_gre
           sudo apt-get -y update
           sudo apt-get -y install pkg-config libsystemd-dev libcap-dev tshark 
iptables valgrind
-      - uses: actions/checkout@v2
+      - uses: actions/checkout@v3
       - name: Configure
         # Build in a sub-directory so we can safely set a+w on all
         # directories.  Needed for `make check` since it runs with
@@ -67,7 +67,7 @@
           sudo chmod a+rw /var/run/xtables.lock
           make check || (cat test/test-suite.log; false)
       - name: Upload Test Results
-        uses: actions/upload-artifact@v2
+        uses: actions/upload-artifact@v3
         with:
           name: smcroute-test-${{ matrix.compiler }}
           path: test/*
diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn' 
'--exclude=.svnignore' old/smcroute-2.5.5/.github/workflows/coverity.yml 
new/smcroute-2.5.6/.github/workflows/coverity.yml
--- old/smcroute-2.5.5/.github/workflows/coverity.yml   2021-11-21 
09:38:26.000000000 +0100
+++ new/smcroute-2.5.6/.github/workflows/coverity.yml   2022-11-28 
08:00:09.000000000 +0100
@@ -15,7 +15,7 @@
   coverity:
     runs-on: ubuntu-latest
     steps:
-      - uses: actions/checkout@v2
+      - uses: actions/checkout@v3
       - name: Fetch latest Coverity Scan MD5
         id: var
         env:
@@ -27,7 +27,7 @@
           export MD5=$(cat coverity-latest.tar.gz.md5)
           echo "Got MD5 $MD5"
           echo ::set-output name=md5::${MD5}
-      - uses: actions/cache@v2
+      - uses: actions/cache@v3
         id: cache
         with:
           path: coverity-latest.tar.gz
@@ -76,7 +76,7 @@
             --form description="${PROJECT_NAME} $(git rev-parse HEAD)" \
             https://scan.coverity.com/builds?project=${COVERITY_PROJ}
       - name: Upload build.log
-        uses: actions/upload-artifact@v2
+        uses: actions/upload-artifact@v3
         with:
           name: coverity-build.log
           path: cov-int/build-log.txt
diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn' 
'--exclude=.svnignore' old/smcroute-2.5.5/.github/workflows/release.yml 
new/smcroute-2.5.6/.github/workflows/release.yml
--- old/smcroute-2.5.5/.github/workflows/release.yml    2021-11-21 
09:38:26.000000000 +0100
+++ new/smcroute-2.5.6/.github/workflows/release.yml    2022-11-28 
08:00:09.000000000 +0100
@@ -7,38 +7,11 @@
 
 jobs:
   release:
-    name: Create GitHub release
-    runs-on: ubuntu-latest
-    if: startsWith(github.ref, 'refs/tags/')
-    outputs:
-      upload_url: ${{ steps.create_release.outputs.upload_url }}
-      release_id: ${{ steps.create_release.outputs.id }}
-    steps:
-      - uses: actions/checkout@v2
-      - name: Extract ChangeLog entry ...
-        # Hack to extract latest entry for body_path below
-        run: |
-          awk '/-----*/{if (x == 1) exit; x=1;next}x' ChangeLog.md \
-              |head -n -1 > release.md
-          cat release.md
-      - name: Create release ...
-        id: create_release
-        uses: actions/create-release@v1
-        env:
-          GITHUB_TOKEN: ${{ secrets.GITHUB_TOKEN }}
-        with:
-          tag_name: ${{ github.ref }}
-          release_name: SMCRoute v${{ github.ref }}
-          body_path: release.md
-          draft: false
-          prerelease: false
-  tarball:
     name: Build and upload release tarball
-    needs: release
     if: startsWith(github.ref, 'refs/tags/')
     runs-on: ubuntu-latest
     steps:
-      - uses: actions/checkout@v2
+      - uses: actions/checkout@v3
       - name: Installing dependencies ...
         run: |
           sudo modprobe ip_gre
@@ -55,10 +28,13 @@
           ls -lF ../
           mkdir -p artifacts/
           mv ../*.tar.* artifacts/
-      - name: Upload release artifacts ...
-        uses: skx/github-action-publish-binaries@release-0.15
-        env:
-          GITHUB_TOKEN: ${{ secrets.GITHUB_TOKEN }}
+      - name: Extract ChangeLog entry ...
+        run: |
+          awk '/-----*/{if (x == 1) exit; x=1;next}x' ChangeLog.md \
+              |head -n -1 > release.md
+          cat release.md
+      - uses: ncipollo/release-action@v1
         with:
-          releaseId: ${{ needs.release.outputs.release_id }}
-          args: artifacts/*
+          name: SMCRoute v${{ github.ref_name }}
+          bodyFile: "release.md"
+          artifacts: "artifacts/*"
diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn' 
'--exclude=.svnignore' old/smcroute-2.5.5/ChangeLog.md 
new/smcroute-2.5.6/ChangeLog.md
--- old/smcroute-2.5.5/ChangeLog.md     2021-11-21 09:38:26.000000000 +0100
+++ new/smcroute-2.5.6/ChangeLog.md     2022-11-28 08:00:09.000000000 +0100
@@ -3,6 +3,36 @@
 
 All notable changes to the project are documented in this file.
 
+[v2.5.6][] - 2022-11-28
+-----------------------
+
+Despite the new `smcroutectl` batch mode feature, this is primarily a
+bug fix release.  Most notably #183 and #187.
+
+### Changes
+- Add `smcroutectl` batch support, issue #189.  Based on the IPC support
+  added in issue #185, by Alexey Smirnov:
+
+        ~$ sudo smcroutectl -b <<-EOF
+               join eth0 225.1.2.3
+               add eth0 192.168.1.42 225.1.2.3 eth1 eth2
+               rem eth1 225.3.4.5 eth3
+               leave eth1 225.3.4.5
+               EOF
+        ~$
+
+### Fixes
+- Fix #178: invalid systemd daemon type Simple/Notify vs simple/notify
+- Fix #179: typo in wildcard routes section of README
+- Fix #180: minor typo in file and directory names in documentation
+- Fix #183: casting in IPC code hides error handling of `recv()`
+- Fix #186: NULL pointer dereference in `utimensat()` replacement
+  function.  Found accidentally by Alexey Smirnov.  Only triggered on
+  systems that don't have a native `utimensat()` in their C-library, or
+  if you try to build SMCRoute without using its own build system ...
+- Fix #187: strange behavior joining/leaving the same group
+- Fix #192: typo in README
+
 
 [v2.5.5][] - 2021-11-21
 -----------------------
@@ -617,7 +647,8 @@
 
 [mrdisc]:     https://github.com/troglobit/mrdisc
 [RFC4286]:    https://tools.ietf.org/html/rfc4286
-[UNRELEASED]: https://github.com/troglobit/smcroute/compare/2.5.5...HEAD
+[UNRELEASED]: https://github.com/troglobit/smcroute/compare/2.5.6...HEAD
+[v2.5.6]:     https://github.com/troglobit/smcroute/compare/2.5.5...2.5.6
 [v2.5.5]:     https://github.com/troglobit/smcroute/compare/2.5.4...2.5.5
 [v2.5.4]:     https://github.com/troglobit/smcroute/compare/2.5.3...2.5.4
 [v2.5.3]:     https://github.com/troglobit/smcroute/compare/2.5.2...2.5.3
diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn' 
'--exclude=.svnignore' old/smcroute-2.5.5/README.md new/smcroute-2.5.6/README.md
--- old/smcroute-2.5.5/README.md        2021-11-21 09:38:26.000000000 +0100
+++ new/smcroute-2.5.6/README.md        2022-11-28 08:00:09.000000000 +0100
@@ -88,7 +88,7 @@
 to run the daemon in the foreground, as required by modern init daemons
 like systemd and [Finit][].
 
-When started from systemd, `smcrouted` rusn with the `-n -s` options,
+When started from systemd, `smcrouted` runs with the `-n -s` options,
 i.e. supervised in the foreground and uses syslog for logging output.
 The default log level is `INFO`, this can be adjusted using the file
 `/etc/default/smcroute`:
@@ -246,7 +246,7 @@
 
     phyint eth0 enable mrdisc
     phyint eth1 enable
-    phyint eth1 enable
+    phyint eth2 enable
     
     mgroup from eth0 group 225.1.2.3
     mroute from eth0 group 225.1.2.3 to eth1 eth2
diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn' 
'--exclude=.svnignore' old/smcroute-2.5.5/configure.ac 
new/smcroute-2.5.6/configure.ac
--- old/smcroute-2.5.5/configure.ac     2021-11-21 09:38:26.000000000 +0100
+++ new/smcroute-2.5.6/configure.ac     2022-11-28 08:00:09.000000000 +0100
@@ -2,13 +2,14 @@
 # Process this file with autoconf to produce a configure script.
 
 AC_PREREQ(2.61)
-AC_INIT(SMCRoute, 2.5.5, https://github.com/troglobit/smcroute/issues, 
smcroute, https://troglobit.com/smcroute.html)
+AC_INIT([SMCRoute], [2.5.6], [https://github.com/troglobit/smcroute/issues],
+        [smcroute], [https://troglobit.com/smcroute.html])
 AC_CONFIG_AUX_DIR(aux)
 AM_INIT_AUTOMAKE([1.11 foreign])
 AM_SILENT_RULES([yes])
 
 AC_CONFIG_SRCDIR([src/smcrouted.c])
-AC_CONFIG_HEADER([config.h])
+AC_CONFIG_HEADERS([config.h])
 AC_CONFIG_FILES([Makefile man/Makefile src/Makefile test/Makefile 
smcroute.service])
 
 # Older versions of autoconf (<2.58) do not have AC_CONFIG_MACRO_DIR()
@@ -22,16 +23,25 @@
 AC_PROG_INSTALL
 
 # The pidfile() code needs asprintf(), which relies on -D_GNU_SOURCE
-AC_GNU_SOURCE
+AC_USE_SYSTEM_EXTENSIONS
 
 # Checks for typedefs, structures, and compiler characteristics.
 AC_C_CONST
 AC_C_INLINE
+AC_TYPE_MODE_T
+AC_TYPE_SIZE_T
+AC_TYPE_SSIZE_T
+AC_TYPE_UID_T
+AC_TYPE_UINT8_T
+AC_TYPE_UINT16_T
 AC_TYPE_UINT32_T
 
 # Checks for library functions.
 AC_FUNC_FORK
-AC_CHECK_FUNCS([atexit dup2 memset select socket strchr strerror strrchr 
asprintf])
+AC_FUNC_CHOWN
+AC_FUNC_MALLOC
+AC_CHECK_FUNCS([atexit clock_gettime dup2 memset select setenv socket strchr \
+       strdup strerror strncasecmp strrchr asprintf])
 
 # Check for usually missing API's
 AC_REPLACE_FUNCS([strlcpy strlcat tempfile utimensat])
@@ -59,11 +69,10 @@
        [with_systemd=auto])
 
 # Checks for header files.
-AC_HEADER_STDC
-AC_CHECK_HEADERS([arpa/inet.h fcntl.h glob.h ifaddrs.h linux/sockios.h 
net/if.h        \
-                 netinet/in.h netinet/in_var.h net/route.h sys/capability.h    
\
-                 sys/ioctl.h sys/param.h sys/prctl.h sys/socket.h sys/stat.h   
\
-                 sys/time.h sys/types.h syslog.h termios.h unistd.h], [], [],[
+AC_CHECK_HEADERS([arpa/inet.h fcntl.h glob.h ifaddrs.h limits.h 
linux/sockios.h \
+       net/if.h netinet/in.h netinet/in_var.h net/route.h paths.h stddef.h     
\
+       sys/capability.h sys/ioctl.h sys/param.h sys/prctl.h sys/socket.h       
\
+       sys/stat.h sys/time.h sys/types.h syslog.h termios.h unistd.h], [], [],[
        #ifdef HAVE_SYS_SOCKET_H
        # include <sys/socket.h>
        #endif
@@ -104,8 +113,8 @@
 
 AS_IF([test "x$with_libsystemd" != "xno"], [
        AC_DEFINE([HAVE_LIBSYSTEMD], [1], [Define to 1 if you have 
libsystemd-dev])
-       AC_SUBST([DAEMON_TYPE], "Notify")], [
-       AC_SUBST([DAEMON_TYPE], "Simple")])
+       AC_SUBST([DAEMON_TYPE], "notify")], [
+       AC_SUBST([DAEMON_TYPE], "simple")])
 AM_CONDITIONAL([HAVE_LIBSYSTEMD], [test "x$with_libsystemd" != "xno"])
 
 # Check if we need -lpthread (building statically) and -lrt (older GLIBC)
@@ -154,14 +163,14 @@
 
 # Mac OS does not (yet) support SOCK_CLOEXEC
 AC_CACHE_CHECK([for SOCK_CLOEXEC support], [ac_cv_sock_cloexec],
-       [AC_TRY_RUN([
+       [AC_RUN_IFELSE([AC_LANG_SOURCE([[
 #include <sys/types.h>
 #include <sys/socket.h>
 
 int main()
 {
     return socket(AF_INET, SOCK_STREAM|SOCK_CLOEXEC, 0) == -1;
-}], [ac_cv_sock_cloexec=yes], [ac_cv_sock_cloexec=no], 
[ac_cv_sock_cloexec=no])])
+}]])],[ac_cv_sock_cloexec=yes],[ac_cv_sock_cloexec=no],[ac_cv_sock_cloexec=no])])
 
 AS_IF([test "$ac_cv_sock_cloexec" = "yes" ],
    AC_DEFINE([HAVE_SOCK_CLOEXEC], 1, [Define if the SOCK_CLOEXEC flag is 
supported]))
@@ -177,6 +186,9 @@
 #       install" into account, unfortunately.
 test "x$prefix" = xNONE && prefix=$ac_default_prefix
 test "x$exec_prefix" = xNONE && exec_prefix='${prefix}'
+SYSCONFDIR=`eval echo $sysconfdir`
+SYSCONFDIR=`eval echo $SYSCONFDIR`
+AC_SUBST(SYSCONFDIR)
 SBINDIR=`eval echo $sbindir`
 SBINDIR=`eval echo $SBINDIR`
 AC_SUBST(SBINDIR)
diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn' 
'--exclude=.svnignore' old/smcroute-2.5.5/lib/malloc.c 
new/smcroute-2.5.6/lib/malloc.c
--- old/smcroute-2.5.5/lib/malloc.c     1970-01-01 01:00:00.000000000 +0100
+++ new/smcroute-2.5.6/lib/malloc.c     2022-11-28 08:00:09.000000000 +0100
@@ -0,0 +1,20 @@
+#if HAVE_CONFIG_H
+# include <config.h>
+#endif
+#undef malloc
+
+#include <sys/types.h>
+
+void *malloc ();
+
+/*
+ * Allocate an N-byte block of memory from the heap.
+ * If N is zero, allocate a 1-byte block.
+ */
+void *rpl_malloc (size_t n)
+{
+       if (n == 0)
+               n = 1;
+
+       return malloc (n);
+}
diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn' 
'--exclude=.svnignore' old/smcroute-2.5.5/lib/utimensat.c 
new/smcroute-2.5.6/lib/utimensat.c
--- old/smcroute-2.5.5/lib/utimensat.c  2021-11-21 09:38:26.000000000 +0100
+++ new/smcroute-2.5.6/lib/utimensat.c  2022-11-28 08:00:09.000000000 +0100
@@ -21,18 +21,28 @@
 #ifdef HAVE_FCNTL_H
 #include <fcntl.h>
 #endif
+#include <time.h>
 #include <sys/time.h>          /* lutimes(), utimes(), utimensat() */
 
-int utimensat(int dirfd, const char *pathname, const struct timespec ts[2], 
int flags)
+int utimensat(int dirfd, const char *pathname, const struct timespec times[2], 
int flags)
 {
-       int ret = -1;
+       struct timespec ts[2];
        struct timeval tv[2];
+       int ret = -1;
 
        if (dirfd != 0) {
                errno = ENOTSUP;
                return -1;
        }
 
+       if (!times) {
+               clock_gettime(CLOCK_REALTIME, &ts[0]);
+               ts[1] = ts[0];
+       } else {
+               ts[0] = times[0];
+               ts[1] = times[1];
+       }
+
        TIMESPEC_TO_TIMEVAL(&tv[0], &ts[0]);
        TIMESPEC_TO_TIMEVAL(&tv[1], &ts[1]);
 
@@ -45,3 +55,37 @@
 
        return ret;
 }
+
+#ifdef UNITTEST
+#include <err.h>
+#include <stdio.h>
+#include <unistd.h>
+
+int main(int argc, char *argv[])
+{
+       char *fn;
+
+       if (argc < 2)
+               errx(1, "Usage: touch FILENAME");
+       fn = argv[1];
+
+       if (access(fn, F_OK)) {
+               FILE *fp;
+
+               fp = fopen(fn, "w");
+               if (!fp)
+                       err(1, "Failed creating %s", fn);
+               fclose(fp);
+       }
+       utimensat(0, fn, NULL, 0);
+
+       return 0;
+}
+#endif
+/**
+ * Local Variables:
+ *  compile-command: "gcc -W -Wall -Wextra -I.. -DUNITTEST -o touch 
utimensat.c"
+ *  indent-tabs-mode: t
+ *  c-file-style: "linux"
+ * End:
+ */
diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn' 
'--exclude=.svnignore' old/smcroute-2.5.5/man/smcroute.conf.5 
new/smcroute-2.5.6/man/smcroute.conf.5
--- old/smcroute-2.5.5/man/smcroute.conf.5      2021-11-21 09:38:26.000000000 
+0100
+++ new/smcroute-2.5.6/man/smcroute.conf.5      2022-11-28 08:00:09.000000000 
+0100
@@ -22,15 +22,15 @@
 .Pp
 On most systems the configuration file(s) are available in:
 .Bl -tag -offset indent
-.It Pa /etc/smcrotue.conf
+.It Pa /etc/smcroute.conf
 The traditional location, with all routes, group joins, and interfaces.
-.It Pa /etc/smcrotue.d/*.conf
+.It Pa /etc/smcroute.d/*.conf
 Recently an
 .Cm include
 directive was added to
 .Nm ,
 which allows for including other files.  By convention
-.Pa /etc/smcrotue.d/
+.Pa /etc/smcroute.d/
 has been selected as the default in the bundled example
 .Nm .
 See more about the
diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn' 
'--exclude=.svnignore' old/smcroute-2.5.5/man/smcroutectl.8 
new/smcroute-2.5.6/man/smcroutectl.8
--- old/smcroute-2.5.5/man/smcroutectl.8        2021-11-21 09:38:26.000000000 
+0100
+++ new/smcroute-2.5.6/man/smcroutectl.8        2022-11-28 08:00:09.000000000 
+0100
@@ -1,5 +1,5 @@
 .\"  -*- nroff -*-
-.Dd August 15, 2021
+.Dd November 28, 2021
 .Dt SMCROUTECTL 8 SMM
 .Os
 .Sh NAME
@@ -8,7 +8,7 @@
 .Xr smcrouted 8
 .Sh SYNOPSIS
 .Nm smcroutectl
-.Op Fl dptv
+.Op Fl bdptv
 .Op Fl i Ar NAME
 .Op Fl u Ar FILE
 .Op Ar COMMAND
@@ -36,6 +36,16 @@
 .Nm
 options are available:
 .Bl -tag -width Ds
+.It Fl b
+Batch mode, read commands from stdin.
+.Bd -unfilled -offset indent
+$ sudo smcroutectl -b <<-EOF
+       join eth0 225.1.2.3
+       add eth0 192.168.1.42 225.1.2.3 eth1 eth2
+       rem eth1 225.3.4.5 eth3
+       leave eth1 225.3.4.5
+       EOF
+.Ed
 .It Fl d
 Enable detailed output in show commands.
 .It Fl i Ar NAME
@@ -56,6 +66,10 @@
 .Cm show
 command output.  No ANSI control characters are used, not even for
 probing screen width.
+.It Fl t
+Skip table headings entirely in
+.Cm show
+command output.
 .It Fl u Ar FILE
 UNIX domain socket path, used for the IPC between
 .Nm smcrouted
@@ -69,10 +83,6 @@
 .Nm
 is configured at build time, see
 .Sx FILES .
-.It Fl t
-Skip table headings entirely in
-.Cm show
-command output.
 .El
 .Sh OPERATION
 The
diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn' 
'--exclude=.svnignore' old/smcroute-2.5.5/man/smcrouted.8 
new/smcroute-2.5.6/man/smcrouted.8
--- old/smcroute-2.5.5/man/smcrouted.8  2021-11-21 09:38:26.000000000 +0100
+++ new/smcroute-2.5.6/man/smcrouted.8  2022-11-28 08:00:09.000000000 +0100
@@ -1,5 +1,5 @@
 .\"  -*- nroff -*-
-.Dd August 15, 2021
+.Dd November 28, 2021
 .Dt SMCROUTED 8 SMM
 .Os
 .Sh NAME
@@ -59,28 +59,6 @@
 .Sh OPTIONS
 The following command line options are available:
 .Bl -tag -width Ds
-.It Fl n
-Run daemon in foreground, do not detach from controlling terminal
-.It Fl N
-By default
-.Nm
-enables multicast routing on all available, and multicast capable,
-interfaces in the system.  These interfaces are enumerated as VIFs,
-virtual interfaces, of which most UNIX systems have a very limited
-amount, usually 32.  This daemon option inverts the behavior so no
-interfaces are enabled by default.  Useful on systems with many
-interfaces, where multicast routing only makes use of a few.
-.Pp
-The config file setting
-.Ar phyint IFNAME enable
-is required to enable the required interfaces.
-.It Fl f Ar FILE
-Alternate configuration file, default
-.Pa /etc/smcroute.conf
-.It Fl F Ar FILE
-Check configuration file syntax, use
-.Fl l Ar LEVEL
-to increase verbosity.  Returns non-zero on error.
 .It Fl c Ar SEC
 Flush unused dynamic (*,G) multicast routes every
 .Ar SEC
@@ -116,6 +94,15 @@
 .Nm
 has loaded/reloaded all static multicast routes from the configuration
 file, or when a source-less (ANY) rule has been installed.
+.It Fl f Ar FILE
+Alternate configuration file, default
+.Pa /etc/smcroute.conf
+.It Fl F Ar FILE
+Check configuration file syntax, use
+.Fl l Ar LEVEL
+to increase verbosity.  Returns non-zero on error.
+.It Fl h
+Show summary of command line options and exit.
 .It Fl i Ar NAME
 Set daemon identity.  Used to create unique PID, IPC socket, and
 configuration file names, as well as set the syslog identity.  E.g.,
@@ -147,6 +134,21 @@
 Default 20 sec.  This option is only available when
 .Nm
 is built with mrdisc support (Linux, and IPv4, only). RFC4286.
+.It Fl n
+Run daemon in foreground, do not detach from controlling terminal
+.It Fl N
+By default
+.Nm
+enables multicast routing on all available, and multicast capable,
+interfaces in the system.  These interfaces are enumerated as VIFs,
+virtual interfaces, of which most UNIX systems have a very limited
+amount, usually 32.  This daemon option inverts the behavior so no
+interfaces are enabled by default.  Useful on systems with many
+interfaces, where multicast routing only makes use of a few.
+.Pp
+The config file setting
+.Ar phyint IFNAME enable
+is required to enable the required interfaces.
 .It Fl p Ar USER Op :GROUP
 Drop root privileges to USER:GROUP after start and retain CAP_NET_ADMIN
 capabilities only.  The :GROUP is optional.  This option is only
diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn' 
'--exclude=.svnignore' old/smcroute-2.5.5/smcroute.service.in 
new/smcroute-2.5.6/smcroute.service.in
--- old/smcroute-2.5.5/smcroute.service.in      2021-11-21 09:38:26.000000000 
+0100
+++ new/smcroute-2.5.6/smcroute.service.in      2022-11-28 08:00:09.000000000 
+0100
@@ -4,14 +4,14 @@
 Documentation=man:smcroute.conf
 Documentation=man:smcroutectl
 Documentation=file:@DOCDIR@/README.md
-# ConditionPathExists=/etc/smcroute.conf
+# ConditionPathExists=@SYSCONFDIR@/smcroute.conf
 After=network-online.target
 Requires=network-online.target
 
 [Service]
 Type=@DAEMON_TYPE@
-EnvironmentFile=-@sysconfdir@/default/smcroute
-ExecStart=@SBINDIR@/smcrouted -n -s $SMCROUTED_OPTS
+EnvironmentFile=-@SYSCONFDIR@/default/smcroute
+ExecStart=@SBINDIR@/smcrouted -n -s $SMCROUTED_OPTS $SMCROUTED_ARGS
 ExecReload=@SBINDIR@/smcroutectl reload
 NotifyAccess=main
 
diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn' 
'--exclude=.svnignore' old/smcroute-2.5.5/src/iface.c 
new/smcroute-2.5.6/src/iface.c
--- old/smcroute-2.5.5/src/iface.c      2021-11-21 09:38:26.000000000 +0100
+++ new/smcroute-2.5.6/src/iface.c      2022-11-28 08:00:09.000000000 +0100
@@ -437,7 +437,7 @@
 
        inw = iface_ifname_maxlen();
        if (inw < (int)strlen(p))
- inw = (int)strlen(p);
+               inw = (int)strlen(p);
 
        snprintf(line, sizeof(line), " INDEX %-*s  VIF  MIF=\n", inw, p);
        ipc_send(sd, line, strlen(line));
diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn' 
'--exclude=.svnignore' old/smcroute-2.5.5/src/ipc.c new/smcroute-2.5.6/src/ipc.c
--- old/smcroute-2.5.5/src/ipc.c        2021-11-21 09:38:26.000000000 +0100
+++ new/smcroute-2.5.6/src/ipc.c        2022-11-28 08:00:09.000000000 +0100
@@ -43,38 +43,84 @@
 static struct sockaddr_un sun;
 static int ipc_socket = -1;
 
+/*
+ * max word count in one command:
+ * smcroutectl add in1 source group out1 out2 .. out32
+ */
+#define CMD_MAX_WORDS (MAXVIFS + 3)
+
 
 /* Receive command from the smcroutectl */
 static void ipc_read(int sd)
 {
+       /* since command len must be limited by the max number of oifs
+       preallocate ipc_msg only once in advance */  
+       char msg_buf[sizeof(struct ipc_msg) + CMD_MAX_WORDS * sizeof(char *)];
        char buf[MX_CMDPKT_SZ];
-       struct ipc_msg *msg;
+       const char* buf_ptr;
+       ssize_t rx = 0, rx_curr;
+       int first_call = 1;
 
        memset(buf, 0, sizeof(buf));
-       msg = (struct ipc_msg *)ipc_receive(sd, buf, sizeof(buf));
-       if (!msg) {
-               /* Skip logging client disconnects */
-               if (errno != ECONNRESET)
-                       smclog(LOG_WARNING, "Failed receiving IPC message from 
client: %s", strerror(errno));
-               return;
-       }
 
-       if (msg_do(sd, msg)) {
-               if (EINVAL == errno)
-                       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 {
-               ipc_send(sd, "", 1);
-       }
+       /* 
+        * since client message would be big enough and couldn't fit
+        * into buffer we have to make multiple iterations to receive
+        * all data
+        */
+       while (1) {
+               rx_curr = ipc_receive(sd, buf + rx, sizeof(buf) - rx, 
first_call);
+               first_call = 0;
+               if (rx_curr <= 0) {
+                       if (errno == EAGAIN)     /* no more data from client */
+                               return;
+                       if (errno != ECONNRESET) /* Skip logging client 
disconnects */
+                               smclog(LOG_WARNING, "Failed receiving IPC 
message from client: %s", strerror(errno));
+                       return;
+               }
+               rx += rx_curr;
+
+               /* Make sure to always have at least one NUL, for strlen() */
+               buf[rx] = 0;
 
-       free(msg);
+               buf_ptr = buf;
+               while (rx > 0) {
+                       struct ipc_msg* msg = (struct ipc_msg*)msg_buf;
+
+                       /* extract one command at a time */
+                       if (ipc_parse(buf_ptr, rx, msg)) {
+                               if (EAGAIN == errno) {
+                                       /* 
+                                        * need more data from client?  move 
last unused bytes (if any) to
+                                        * the begging of the buffer and lets 
try to receive more data
+                                        */
+                                       memmove(buf, buf_ptr, rx);
+                                       break;
+                               }
+                               smclog(LOG_WARNING, "Failed to parse IPC 
message from client: %s", strerror(errno));
+                               return;
+                       }
+
+                       if (msg_do(sd, msg)) {
+                               if (EINVAL == errno)
+                                       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 {
+                               ipc_send(sd, "", 1);
+                       }
+
+                       /* shift to the next command if any and reduce 
remaining bytes in buffer */
+                       buf_ptr += msg->len;
+                       rx -= msg->len;
+               }
+       }
 }
 
 static void ipc_accept(int sd, void *arg)
 {
-       int client;
        socklen_t socklen = 0;
+       int client;
 
        (void)arg;
        client = accept(sd, NULL, &socklen);
@@ -149,7 +195,7 @@
  * Returns:
  * Number of bytes successfully sent, or -1 with @errno on failure.
  */
-int ipc_send(int sd, char *buf, size_t len)
+int ipc_send(int sd, const char *buf, size_t len)
 {
        if (write(sd, buf, len) != (ssize_t)len)
                return -1;
@@ -162,67 +208,80 @@
  * @sd:  Client socket from ipc_accept()
  * @buf: Buffer for message
  * @len: Size of @buf in bytes
+ * @first_call: non-zero set on first read after accept, 0 - subsequent calls
  *
- * Reads a message from the IPC socket and stores in @buf, respecting
+ * Reads a message(s) from the IPC socket and stores in @buf, respecting
  * the size @len.  Connects and resets connection as necessary.
  *
  * Returns:
- * Pointer to a successfuly read command packet in @buf, or %NULL on error.
+ * Size of a successfuly read command packet in @buf, or 0 on error.
  */
-void *ipc_receive(int sd, char *buf, size_t len)
+ssize_t ipc_receive(int sd, char *buf, size_t len, int first_call)
 {
-       size_t sz;
+       ssize_t sz;
+       /* since we can call this multiple times during receive of multipart
+       command lets pass `don't wait` flag to not block forever
+       when client finish transmission */
+       int flags = first_call ? 0 : MSG_DONTWAIT;
 
-       sz = recv(sd, buf, len - 1, 0);
-       if (!sz) {
+       sz = recv(sd, buf, len - 1, flags);
+       if (!sz)
                errno = ECONNRESET;
-               return NULL;
-       }
+
+       return sz;
+}
+
+/**
+ * ipc_server_parse - Parse IPC message(s) from client
+ * @buf: Buffer of message(s)
+ * @sz: Size of @buf in bytes
+ * @msg_buf: Preallocated ipc_msg
+ *
+ * Parse message(s) from the IPC socket, respecting
+ * the size @sz.
+ *
+ * Returns:
+ * POSIX OK(0) on a successfuly read command in @buf, or non-zero on error.
+ */
+int ipc_parse(const char *buf, size_t sz, void* msg_buf)
+{
+       struct ipc_msg* msg;
 
        /* successful read */
        if (sz >= sizeof(struct ipc_msg)) {
-               struct ipc_msg *msg = (struct ipc_msg *)buf;
+               memcpy(msg_buf, buf, sizeof(struct ipc_msg));
+               msg = (struct ipc_msg*)msg_buf;
 
-               /* Make sure to always have at least one NUL, for strlen() */
-               buf[sz] = 0;
-
-               if (sz == msg->len) {
-                       char *ptr;
+               /* enough bytes to extract just one message? */
+               if (sz >= msg->len) {
                        size_t i, count;
+                       const char *ptr;
 
-                       /* Upper bound: smcroutectl add in1 source group out1 
out2 .. out32 */
                        count = msg->count;
-                       if (count > (MAXVIFS + 3)) {
+                       if (count > CMD_MAX_WORDS) {
                                errno = EINVAL;
-                               return NULL;
+                               return 1;
                        }
 
-                       msg = malloc(sizeof(struct ipc_msg) + msg->count * 
sizeof(char *));
-                       if (!msg)
-                               return NULL;
-
-                       memcpy(msg, buf, sizeof(struct ipc_msg));
-
                        ptr = buf + offsetof(struct ipc_msg, argv);
                        for (i = 0; i < count; i++) {
                                /* Verify ptr, attacker may set too large 
msg->count */
-                               if (ptr >= (buf + len)) {
-                                       free(msg);
+                               if (ptr >= (buf + msg->len)) {
                                        errno = EBADMSG;
-                                       return NULL;
+                                       return 1;
                                }
 
-                               msg->argv[i] = ptr;
+                               msg->argv[i] = (char*)ptr;
                                ptr += strlen(ptr) + 1;
                        }
-                       msg->count = count;
 
-                       return msg;
+                       return 0;
                }
        }
 
+       /* we've parsed all commands or not enough bytes to parse next */
        errno = EAGAIN;
-       return NULL;
+       return 1;
 }
 
 /**
diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn' 
'--exclude=.svnignore' old/smcroute-2.5.5/src/ipc.h new/smcroute-2.5.6/src/ipc.h
--- old/smcroute-2.5.5/src/ipc.h        2021-11-21 09:38:26.000000000 +0100
+++ new/smcroute-2.5.6/src/ipc.h        2022-11-28 08:00:09.000000000 +0100
@@ -7,8 +7,9 @@
 int   ipc_init    (char *path);
 void  ipc_exit    (void);
 
-int   ipc_send    (int sd, char *buf, size_t len);
-void *ipc_receive (int sd, char *buf, size_t len);
+int     ipc_send   (int sd, const char *buf, size_t len);
+ssize_t ipc_receive(int sd, char *buf, size_t len, int first_call);
+int     ipc_parse  (const char *buf, size_t sz, void *msg_buf);
 
 #endif /* SMCROUTE_IPC_H_ */
 
diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn' 
'--exclude=.svnignore' old/smcroute-2.5.5/src/mcgroup.c 
new/smcroute-2.5.6/src/mcgroup.c
--- old/smcroute-2.5.5/src/mcgroup.c    2021-11-21 09:38:26.000000000 +0100
+++ new/smcroute-2.5.6/src/mcgroup.c    2022-11-28 08:00:09.000000000 +0100
@@ -372,7 +372,7 @@
        }
 
        if (!cmd) {
-               TAILQ_REMOVE(&kern_list, mcg, link);
+               TAILQ_REMOVE(&conf_list, mcg, link);
                free_mc_sock(mcg->sd);
                free(mcg);
        }
diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn' 
'--exclude=.svnignore' old/smcroute-2.5.5/src/mrdisc.c 
new/smcroute-2.5.6/src/mrdisc.c
--- old/smcroute-2.5.5/src/mrdisc.c     2021-11-21 09:38:26.000000000 +0100
+++ new/smcroute-2.5.6/src/mrdisc.c     2022-11-28 08:00:09.000000000 +0100
@@ -84,8 +84,8 @@
 /* Checksum routine for Internet Protocol family headers */
 static unsigned short in_cksum(unsigned short *addr, int len)
 {
-       unsigned short *w = addr;
        unsigned short answer = 0;
+       unsigned short *w = addr;
        int nleft = len;
        int sum = 0;
 
@@ -122,9 +122,9 @@
 
 static int inet_send(int sd, uint8_t type, uint8_t interval)
 {
-       ssize_t num;
-       struct igmp igmp;
        struct sockaddr dest;
+       struct igmp igmp;
+       ssize_t num;
 
        memset(&igmp, 0, sizeof(igmp));
        igmp.igmp_type = type;
@@ -143,10 +143,10 @@
 /* If called with interval=0, only read() */
 static int inet_recv(int sd, uint8_t interval)
 {
+       struct igmp *igmp;
        char buf[1530];
-       ssize_t num;
        struct ip *ip;
-       struct igmp *igmp;
+       ssize_t num;
 
        memset(buf, 0, sizeof(buf));
        num = read(sd, buf, sizeof(buf));
@@ -165,11 +165,11 @@
 
 static int inet_open(char *ifname)
 {
-       char loop;
-       int sd, val, rc;
-       struct ifreq ifr;
-       struct ip_mreqn mreq;
        unsigned char ra[4] = { IPOPT_RA, 0x04, 0x00, 0x00 };
+       struct ip_mreqn mreq;
+       struct ifreq ifr;
+       int sd, val, rc;
+       char loop;
 
        sd = socket_create(AF_INET, SOCK_RAW, IPPROTO_IGMP, mrdisc_recv, NULL);
        if (sd < 0) {
diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn' 
'--exclude=.svnignore' old/smcroute-2.5.5/src/smcroutectl.c 
new/smcroute-2.5.6/src/smcroutectl.c
--- old/smcroute-2.5.5/src/smcroutectl.c        2021-11-21 09:38:26.000000000 
+0100
+++ new/smcroute-2.5.6/src/smcroutectl.c        2022-11-28 08:00:09.000000000 
+0100
@@ -44,7 +44,9 @@
 static char *sock_file = NULL;
 static char *prognm = NULL;
 static int   heading = 1;
+static int   detail = 0;
 static int   plain = 0;
+static int   help = 0;
 
 struct arg {
        char *name;
@@ -55,6 +57,7 @@
        char *example;          /* optional */
        int   has_detail;
 } args[] = {
+       { NULL,      0, 'b', NULL,   "Batch mode, read commands from stdin", 
NULL, 0 },
        { NULL,      0, 'd', NULL,   "Detailed output in show command", NULL, 0 
},
        { NULL,      1, 'i', "NAME", "Identity of routing daemon instance, 
default: " PACKAGE, "foo", 0 },
        { NULL,      1, 'I', "NAME", NULL, NULL, 0 }, /* Alias, compat with 
older versions */
@@ -391,64 +394,15 @@
        return 0;
 }
 
-static char *progname(const char *arg0)
+static int parse(int pos, int argc, char *argv[])
 {
-       char *nm;
-
-       nm = strrchr(arg0, '/');
-       if (nm)
-               nm++;
-       else
-               nm = (char *)arg0;
-
-       return nm;
-}
-
-int main(int argc, char *argv[])
-{
-       int help = 0, detail = 0;
-       int c, i, pos = 1, status = 0;
        struct arg *cmd = NULL;
+       int status = 0;
+       int c;
 
-       prognm = progname(argv[0]);
-       while ((c = getopt(argc, argv, "dhI:i:ptu:v")) != EOF) {
-               switch (c) {
-               case 'd':
-                       detail++;
-                       break;
-
-               case 'h':
-                       help++;
-                       break;
-
-               case 'I':       /* compat with previous versions */
-               case 'i':
-                       ident = optarg;
-                       break;
-
-               case 'p':
-                       plain = 1;
-                       break;
-
-               case 't':
-                       heading = 0;
-                       break;
-
-               case 'u':
-                       sock_file = optarg;
-                       break;
-
-               case 'v':
-                       return version();
-
-               default:
-                       return usage(1);
-               }
-       }
-
-       pos = optind;
        while (pos < argc && !cmd) {
                char *arg = argv[pos];
+               int i;
 
                for (i = 0; args[i].val; i++) {
                        char    *nm = args[i].name;
@@ -511,6 +465,95 @@
        return ipc_command(c, &argv[pos], argc - pos);
 }
 
+static int batch(void)
+{
+       char line[512];
+       int rc = 0;
+
+       while (fgets(line, sizeof(line), stdin)) {
+               char *ptr, *token, *args[10];
+               int num = 0;
+
+               ptr = chomp(line);
+               if (ptr[0] == '#')
+                       continue;
+
+               while (num < 9 && (token = strsep(&ptr, " \t")))
+                       args[num++] = token;
+
+               if (!num)
+                       continue;
+
+               rc += parse(0, num, args);
+       }
+
+       return rc;
+}
+
+static char *progname(const char *arg0)
+{
+       char *nm;
+
+       nm = strrchr(arg0, '/');
+       if (nm)
+               nm++;
+       else
+               nm = (char *)arg0;
+
+       return nm;
+}
+
+int main(int argc, char *argv[])
+{
+       int batch_mode = 0;
+       int c;
+
+       prognm = progname(argv[0]);
+       while ((c = getopt(argc, argv, "bdhI:i:ptu:v")) != EOF) {
+               switch (c) {
+               case 'b':
+                       batch_mode = 1;
+                       break;
+
+               case 'd':
+                       detail++;
+                       break;
+
+               case 'h':
+                       help++;
+                       break;
+
+               case 'I':       /* compat with previous versions */
+               case 'i':
+                       ident = optarg;
+                       break;
+
+               case 'p':
+                       plain = 1;
+                       break;
+
+               case 't':
+                       heading = 0;
+                       break;
+
+               case 'u':
+                       sock_file = optarg;
+                       break;
+
+               case 'v':
+                       return version();
+
+               default:
+                       return usage(1);
+               }
+       }
+
+       if (batch_mode)
+               return batch();
+
+       return parse(optind, argc, argv);
+}
+
 /**
  * Local Variables:
  *  indent-tabs-mode: t
diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn' 
'--exclude=.svnignore' old/smcroute-2.5.5/test/Makefile.am 
new/smcroute-2.5.6/test/Makefile.am
--- old/smcroute-2.5.5/test/Makefile.am 2021-11-21 09:38:26.000000000 +0100
+++ new/smcroute-2.5.6/test/Makefile.am 2022-11-28 08:00:09.000000000 +0100
@@ -1,4 +1,4 @@
-EXTRA_DIST         = adv.sh basic.sh bridge.sh dyn.sh expire.sh gre.sh ipv6.sh
+EXTRA_DIST         = adv.sh basic.sh batch.sh bridge.sh dyn.sh expire.sh 
gre.sh ipv6.sh
 EXTRA_DIST        += include.sh isolated.sh join.sh joinlen.sh lib.sh lost.sh
 EXTRA_DIST        += multi.sh mem.sh mrcache.sh mrcache6.sh mrdisc.sh poison.sh
 EXTRA_DIST        += reload.sh reload6.sh vlan.sh vrfy.sh
@@ -9,6 +9,7 @@
 TESTS              = expire.sh
 TESTS             += adv.sh
 TESTS             += basic.sh
+TESTS             += batch.sh
 TESTS             += bridge.sh
 TESTS             += dyn.sh
 TESTS             += gre.sh
diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn' 
'--exclude=.svnignore' old/smcroute-2.5.5/test/README.md 
new/smcroute-2.5.6/test/README.md
--- old/smcroute-2.5.5/test/README.md   2021-11-21 09:38:26.000000000 +0100
+++ new/smcroute-2.5.6/test/README.md   2022-11-28 08:00:09.000000000 +0100
@@ -19,16 +19,17 @@
 
 To run the tests:
 
-       ~$ cd src/smcroute
-       ~/src/smcroute$ ./autogen.sh
-       ~/src/smcroute$ ./configure --enable-test
-       ~/src/smcroute$ make -j9
-       ~/src/smcroute$ make check
+    ~$ sudo modprobe ip_gre      # if you have sudo capabilities
+    ~$ cd src/smcroute
+    ~/src/smcroute$ ./autogen.sh
+    ~/src/smcroute$ ./configure --enable-test --enable-mrdisc
+    ~/src/smcroute$ make -j9
+    ~/src/smcroute$ make check
 
 Each unit test is standalone.  To manually run select tests:
 
     ~/src/smcroute$ cd test/
-       ~/src/smcroute/test$ unshare -mrun ./testname.sh
+    ~/src/smcroute/test$ unshare -mrun ./testname.sh
 
 The tools `ping` and `tshark` are used to create and listen to multicast
 streams "routed by" SMCRoute.
diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn' 
'--exclude=.svnignore' old/smcroute-2.5.5/test/batch.sh 
new/smcroute-2.5.6/test/batch.sh
--- old/smcroute-2.5.5/test/batch.sh    1970-01-01 01:00:00.000000000 +0100
+++ new/smcroute-2.5.6/test/batch.sh    2022-11-28 08:00:09.000000000 +0100
@@ -0,0 +1,37 @@
+#!/bin/sh
+# Verify batch mode, we just want to see the daemon accepting the
+# batched commands.
+
+# shellcheck source=/dev/null
+. "$(dirname "$0")/lib.sh"
+
+print "Creating world ..."
+topo basic
+
+# IP world ...
+ip addr add 10.0.0.1/24  dev a1
+ip addr add 20.0.0.1/24  dev a2
+ip addr add 2001:1::1/64 dev a1
+ip addr add 2001:2::1/64 dev a2
+ip -br a
+
+print "Starting smcrouted ..."
+../src/smcrouted -f "/tmp/$NM/conf" -n -N -P "/tmp/$NM/pid" -l debug -u 
"/tmp/$NM/sock" &
+sleep 1
+
+print "Joining groups (batch)"
+../src/smcroutectl -u "/tmp/$NM/sock" -b <<-EOF
+       join a1 10.0.0.11 225.1.1.1
+       join a2 225.2.2.2
+       join a1 fc00::2 ff04::111
+       join a2 ff2e::22
+       EOF
+
+output=$(../src/smcroutectl -pu "/tmp/$NM/sock" show groups)
+echo "$output"
+[ "$(echo "$output" | grep 225.1.1.1 | sed 's/[[:space:]]*//g')" = 
"(10.0.0.11,225.1.1.1)a1" ] || FAIL "225.1.1.1"
+[ "$(echo "$output" | grep 225.2.2.2 | sed 's/[[:space:]]*//g')" = 
"(*,225.2.2.2)a2" ]         || FAIL "225.2.2.2"
+[ "$(echo "$output" | grep ff04::111 | sed 's/[[:space:]]*//g')" = 
"(fc00::2,ff04::111)a1" ]   || FAIL "ff04::111"
+[ "$(echo "$output" | grep ff2e::22  | sed 's/[[:space:]]*//g')" = 
"(*,ff2e::22)a2" ]          || FAIL "ff2e::22"
+
+OK

Reply via email to