Script 'mail_helper' called by obssrc
Hello community,

here is the log from the commit of package smcroute for openSUSE:Factory 
checked in at 2021-09-14 21:14:45
++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++
Comparing /work/SRC/openSUSE:Factory/smcroute (Old)
 and      /work/SRC/openSUSE:Factory/.smcroute.new.1899 (New)
++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++

Package is "smcroute"

Tue Sep 14 21:14:45 2021 rev:5 rq:918874 version:2.5.2

Changes:
--------
--- /work/SRC/openSUSE:Factory/smcroute/smcroute.changes        2021-08-23 
10:09:49.624130443 +0200
+++ /work/SRC/openSUSE:Factory/.smcroute.new.1899/smcroute.changes      
2021-09-14 21:15:05.552446425 +0200
@@ -1,0 +2,24 @@
+Fri Aug 27 16:26:10 UTC 2021 - Martin Hauke <mar...@gmx.de>
+
+- Update to version 2.5.2
+  Changes
+  * Allow installing routes with no outbound interfaces.
+  * Reinitialize VIFs on reload in case of new interfaces.
+  * Handle cases when interfaces change ifindex, i.e. they've first
+    been * removed and then re-added with the same name.
+  Fixes
+  * Fix VIF leak when deleting interfaces with MRDISC enabled.
+  * Fix handling when an (S,G) moves to another IIF. This fixes
+    issues where the SMCRoute kernel cache was out of sync with
+    the kernel MFC.
+  * Fix handling of lost/disabled interfaces at reload. This fixes
+    a couple of issues where routes were not updated properly at
+    runtime.
+  * Update interface flags on reload, this fixes issues when
+    SMCRoute failed to detect interfaces that had their MULTICAST
+    flag set or cleared at runtime.
+  * Skip setsockopt() for IPC sockets. This fixes warnings in
+    syslog about failing to disable MULTICAST_LOOP and
+    MULTICAST_ALL.
+
+-------------------------------------------------------------------

Old:
----
  smcroute-2.5.1.tar.gz

New:
----
  smcroute-2.5.2.tar.gz

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

Other differences:
------------------
++++++ smcroute.spec ++++++
--- /var/tmp/diff_new_pack.9mOkaY/_old  2021-09-14 21:15:06.068446932 +0200
+++ /var/tmp/diff_new_pack.9mOkaY/_new  2021-09-14 21:15:06.072446936 +0200
@@ -18,7 +18,7 @@
 
 
 Name:           smcroute
-Version:        2.5.1
+Version:        2.5.2
 Release:        0
 Summary:        Static multicast routing for UNIX
 License:        GPL-3.0-only

++++++ smcroute-2.5.1.tar.gz -> smcroute-2.5.2.tar.gz ++++++
diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn' 
'--exclude=.svnignore' old/smcroute-2.5.1/.github/workflows/release.yml 
new/smcroute-2.5.2/.github/workflows/release.yml
--- old/smcroute-2.5.1/.github/workflows/release.yml    2021-08-22 
09:36:54.000000000 +0200
+++ new/smcroute-2.5.2/.github/workflows/release.yml    2021-08-27 
17:55:39.000000000 +0200
@@ -50,7 +50,8 @@
           ./configure --prefix= --enable-mrdisc --enable-test
       - name: Build release ...
         run: |
-          make release
+          sudo chmod a+rw /var/run/xtables.lock
+          make release || (cat test/test-suite.log; false)
           ls -lF ../
           mkdir -p artifacts/
           mv ../*.tar.* artifacts/
diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn' 
'--exclude=.svnignore' old/smcroute-2.5.1/ChangeLog.md 
new/smcroute-2.5.2/ChangeLog.md
--- old/smcroute-2.5.1/ChangeLog.md     2021-08-22 09:36:54.000000000 +0200
+++ new/smcroute-2.5.2/ChangeLog.md     2021-08-27 17:55:39.000000000 +0200
@@ -3,6 +3,28 @@
 
 All notable changes to the project are documented in this file.
 
+[v2.5.2][] - 2021-08-27
+-----------------------
+
+### Changes
+- Allow installing routes with no outbound interfaces
+- Reinitialize VIFs on reload in case of new interfaces
+- Handle cases when interfaces change ifindex, i.e. they've first been
+  removed and then re-added with the same name
+
+### Fixes
+- Fix VIF leak when deleting interfaces with MRDISC enabled
+- Fix handling when an (S,G) moves to another IIF.  This fixes issues
+  where the SMCRoute kernel cache was out of sync with the kernel MFC
+- Fix handling of lost/disabled interfaces at reload.  This fixes a
+  couple of issues where routes were not updated properly at runtime
+- Update interface flags on reload, this fixes issues when SMCRoute
+  failed to detect interfaces that had their MULTICAST flag set or
+  cleared at runtime
+. Skip `setsockopt()` for IPC sockets.  This fixes warnings in syslog
+  about failing to disable `MULTICAST_LOOP` and `MULTICAST_ALL`
+
+
 [v2.5.1][] - 2021-08-22
 -----------------------
 
@@ -552,8 +574,9 @@
 
 [mrdisc]:     https://github.com/troglobit/mrdisc
 [RFC4286]:    https://tools.ietf.org/html/rfc4286
-[UNRELEASED]: https://github.com/troglobit/smcroute/compare/2.5.1...HEAD
-[v2.5.1]:     https://github.com/troglobit/smcroute/compare/2.5.1...2.5.1
+[UNRELEASED]: https://github.com/troglobit/smcroute/compare/2.5.2...HEAD
+[v2.5.2]:     https://github.com/troglobit/smcroute/compare/2.5.1...2.5.2
+[v2.5.1]:     https://github.com/troglobit/smcroute/compare/2.5.0...2.5.1
 [v2.5.0]:     https://github.com/troglobit/smcroute/compare/2.4.4...2.5.0
 [v2.4.4]:     https://github.com/troglobit/smcroute/compare/2.4.3...2.4.4
 [v2.4.3]:     https://github.com/troglobit/smcroute/compare/2.4.2...2.4.3
diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn' 
'--exclude=.svnignore' old/smcroute-2.5.1/README.md new/smcroute-2.5.2/README.md
--- old/smcroute-2.5.1/README.md        2021-08-22 09:36:54.000000000 +0200
+++ new/smcroute-2.5.2/README.md        2021-08-27 17:55:39.000000000 +0200
@@ -227,8 +227,8 @@
 
     smcroutectl help
 
-**Note:** Root privileges are required by default for `smcroutectl` due
-  to the IPC socket permissions.
+> **Note:** Root privileges are required by default for `smcroutectl` due
+> to the IPC socket permissions.
 
 
 Wildcard Routes
diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn' 
'--exclude=.svnignore' old/smcroute-2.5.1/configure.ac 
new/smcroute-2.5.2/configure.ac
--- old/smcroute-2.5.1/configure.ac     2021-08-22 09:36:54.000000000 +0200
+++ new/smcroute-2.5.2/configure.ac     2021-08-27 17:55:39.000000000 +0200
@@ -2,7 +2,7 @@
 # Process this file with autoconf to produce a configure script.
 
 AC_PREREQ(2.61)
-AC_INIT(SMCRoute, 2.5.1, https://github.com/troglobit/smcroute/issues, 
smcroute, https://troglobit.com/smcroute.html)
+AC_INIT(SMCRoute, 2.5.2, 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])
diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn' 
'--exclude=.svnignore' old/smcroute-2.5.1/src/conf.c 
new/smcroute-2.5.2/src/conf.c
--- old/smcroute-2.5.1/src/conf.c       2021-08-22 09:36:54.000000000 +0200
+++ new/smcroute-2.5.2/src/conf.c       2021-08-27 17:55:39.000000000 +0200
@@ -216,13 +216,12 @@
        DEBUG("mroute: checking for input iface %s ...", iif);
        while (iface_match_vif_by_name(iif, &state_in, &iface_in) != NO_VIF) {
                char src[INET_ADDRSTR_LEN], grp[INET_ADDRSTR_LEN];
-               int i, total = 0;
 
                vif = iface_get_vif(family, iface_in);
                DEBUG("mroute: input iface %s has vif %d", iif, vif);
                mroute.inbound = vif;
 
-               for (i = 0; i < num; i++) {
+               for (int i = 0; i < num; i++) {
                        iface_match_init(&state_out);
 
                        DEBUG("mroute: checking for %s ...", oif[i]);
@@ -237,7 +236,6 @@
 
                                /* Use configured TTL threshold for the output 
phyint */
                                mroute.ttl[vif] = iface->threshold;
-                               total++;
                        }
                        if (!state_out.match_count)
                                WARN("mroute: outbound %s is not a known 
phyint, skipping", oif[i]);
@@ -247,15 +245,10 @@
                        continue;
 
                if (cmd) {
-                       if (!total) {
-                               WARN("mroute: no outbound interfaces, cannot 
add multicast route.");
-                               rc += 1;
-                       } else {
-                               smclog(LOG_DEBUG, "mroute: adding route from %s 
(%s/%u,%s/%u)", iface_in->ifname,
-                                      inet_addr2str(&mroute.source, src, 
sizeof(src)), mroute.src_len,
-                                      inet_addr2str(&mroute.group, grp, 
sizeof(grp)), mroute.len);
-                               rc += mroute_add_route(&mroute);
-                       }
+                       smclog(LOG_DEBUG, "mroute: adding route from %s 
(%s/%u,%s/%u)", iface_in->ifname,
+                              inet_addr2str(&mroute.source, src, sizeof(src)), 
mroute.src_len,
+                              inet_addr2str(&mroute.group, grp, sizeof(grp)), 
mroute.len);
+                       rc += mroute_add_route(&mroute);
                } else {
                        smclog(LOG_DEBUG, "mroute: deleting route from %s 
(%s/%u,%s/%u)", iface_in->ifname,
                               inet_addr2str(&mroute.source, src, sizeof(src)), 
mroute.src_len,
@@ -282,7 +275,7 @@
                struct ifmatch ifm;
 
                iface_match_init(&ifm);
-               iface = iface_match_by_name(iif, &ifm);
+               iface = iface_match_by_name(iif, 1, &ifm);
                if (!iface)
                        return 1;
 
diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn' 
'--exclude=.svnignore' old/smcroute-2.5.1/src/iface.c 
new/smcroute-2.5.2/src/iface.c
--- old/smcroute-2.5.1/src/iface.c      2021-08-22 09:36:54.000000000 +0200
+++ new/smcroute-2.5.2/src/iface.c      2021-08-27 17:55:39.000000000 +0200
@@ -41,12 +41,12 @@
 #include "util.h"
 
 static TAILQ_HEAD(iflist, iface) iface_list = 
TAILQ_HEAD_INITIALIZER(iface_list);
+extern int do_vifs;
 
 /**
  * iface_update - Check of new interfaces
- * @do_vifs: If set, then mark all interfaces found as "in use"
  */
-void iface_update(int do_vifs)
+void iface_update(void)
 {
        struct ifaddrs *ifaddr, *ifa;
 
@@ -57,13 +57,25 @@
 
        for (ifa = ifaddr; ifa; ifa = ifa->ifa_next) {
                struct iface *iface;
+               int ifindex;
+
+               ifindex = if_nametoindex(ifa->ifa_name);
 
                /* Check if already added? */
                iface = iface_find_by_name(ifa->ifa_name);
                if (iface) {
                        smclog(LOG_DEBUG, "Found %s, updating ...", 
ifa->ifa_name);
+                       iface->flags = ifa->ifa_flags;
+
+                       if (ifindex != iface->ifindex || (iface->flags & 
IFF_MULTICAST) != IFF_MULTICAST) {
+                               mcgroup_prune(ifa->ifa_name);
+                               mroute_del_vif(ifa->ifa_name);
+                       }
+
+                       iface->ifindex = ifindex;
                        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;
+
                        if (do_vifs)
                                iface->unused = 0;
 
@@ -102,14 +114,13 @@
 
 /**
  * iface_init - Probe for interaces at startup
- * @do_vifs: If set, then mark all interfaces found as "in use"
  *
  * Builds up a vector with active system interfaces.  Must be called
  * before any other interface functions in this module!
  */
-void iface_init(int do_vifs)
+void iface_init(void)
 {
-       iface_update(do_vifs);
+       iface_update();
 }
 
 /**
@@ -260,6 +271,7 @@
 /**
  * iface_match_by_name - Find matching interfaces by name pattern
  * @ifname: Interface name pattern
+ * @reload: Set while reloading .conf
  * @state: Iterator state
  *
  * Interface name patterns use iptables- syntax, i.e. perform prefix
@@ -269,7 +281,7 @@
  * Pointer to a @struct iface of the next matching interface, or %NULL if no
  * (more) interfaces exist (or are up).
  */
-struct iface *iface_match_by_name(const char *ifname, struct ifmatch *state)
+struct iface *iface_match_by_name(const char *ifname, int reload, struct 
ifmatch *state)
 {
        unsigned int match_len = UINT_MAX;
 
@@ -283,10 +295,12 @@
                struct iface *iface = state->iface;
 
                if (!strncmp(ifname, iface->ifname, match_len)) {
-                       state->iface = TAILQ_NEXT(iface, link);
-                       state->match_count++;
+                       if (reload || !iface->unused) {
+                               state->iface = TAILQ_NEXT(iface, link);
+                               state->match_count++;
 
-                       return iface;
+                               return iface;
+                       }
                }
 
                state->iface = TAILQ_NEXT(iface, link);
@@ -365,7 +379,7 @@
 {
        struct iface *iface;
 
-       while ((iface = iface_match_by_name(ifname, state))) {
+       while ((iface = iface_match_by_name(ifname, 0, state))) {
                if (iface->vif != NO_VIF) {
                        if (found)
                                *found = iface;
@@ -394,7 +408,7 @@
 {
        struct iface *iface;
 
-       while ((iface = iface_match_by_name(ifname, state))) {
+       while ((iface = iface_match_by_name(ifname, 0, state))) {
                if (iface->mif != NO_VIF) {
                        if (found)
                                *found = iface;
diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn' 
'--exclude=.svnignore' old/smcroute-2.5.1/src/iface.h 
new/smcroute-2.5.2/src/iface.h
--- old/smcroute-2.5.1/src/iface.h      2021-08-22 09:36:54.000000000 +0200
+++ new/smcroute-2.5.2/src/iface.h      2021-08-27 17:55:39.000000000 +0200
@@ -36,9 +36,9 @@
        size_t match_count;
 };
 
-void          iface_init              (int do_vifs);
+void          iface_init              (void);
 void          iface_exit              (void);
-void          iface_update            (int do_vifs);
+void          iface_update            (void);
 
 struct iface *iface_iterator          (int first);
 struct iface *iface_outbound_iterator (struct mroute *route, int first);
@@ -48,7 +48,7 @@
 struct iface *iface_find_by_inbound   (struct mroute *route);
 
 void          iface_match_init        (struct ifmatch *state);
-struct iface *iface_match_by_name     (const char *ifname, struct ifmatch 
*state);
+struct iface *iface_match_by_name     (const char *ifname, int reload, struct 
ifmatch *state);
 int           ifname_is_wildcard      (const char *ifname);
 
 vifi_t        iface_get_vif           (int af_family, struct iface *iface);
@@ -57,12 +57,15 @@
 
 int           iface_show              (int sd, int detail);
 
+/*
+ * Check if interface exists, at all, on the system
+ */
 static inline int iface_exist(char *ifname)
 {
        struct ifmatch ifm;
 
        iface_match_init(&ifm);
-       return iface_match_by_name(ifname, &ifm) != NULL;
+       return iface_match_by_name(ifname, 1, &ifm) != NULL;
 }
 
 static inline int iface_ifname_maxlen(void)
diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn' 
'--exclude=.svnignore' old/smcroute-2.5.1/src/inet.h 
new/smcroute-2.5.2/src/inet.h
--- old/smcroute-2.5.1/src/inet.h       2021-08-22 09:36:54.000000000 +0200
+++ new/smcroute-2.5.2/src/inet.h       2021-08-27 17:55:39.000000000 +0200
@@ -75,4 +75,14 @@
 
 int                  inet_iter_init (struct inet_iter *iter, inet_addr_t 
*addr, int len);
 int                  inet_iterator  (struct inet_iter *iter, inet_addr_t 
*addr);
+
+static inline int    inet_max_len   (inet_addr_t *addr)
+{
+#ifdef HAVE_IPV6_MULTICAST_HOST
+       if (addr->ss_family == AF_INET6)
+               return 128;
+#endif
+       return 32;
+}
+
 #endif /* SMCROUTE_INET_H_ */
diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn' 
'--exclude=.svnignore' old/smcroute-2.5.1/src/mcgroup.c 
new/smcroute-2.5.2/src/mcgroup.c
--- old/smcroute-2.5.1/src/mcgroup.c    2021-08-22 09:36:54.000000000 +0200
+++ new/smcroute-2.5.2/src/mcgroup.c    2021-08-27 17:55:39.000000000 +0200
@@ -140,7 +140,7 @@
 
 static struct iface *match_valid_iface(const char *ifname, struct ifmatch 
*state)
 {
-       struct iface *iface = iface_match_by_name(ifname, state);
+       struct iface *iface = iface_match_by_name(ifname, 0, state);
 
        if (!iface && !state->match_count)
                smclog(LOG_DEBUG, "unknown interface %s", ifname);
@@ -398,6 +398,16 @@
 void mcgroup_reload_end(void)
 {
        struct mcgroup *entry, *tmp;
+       struct iface *iface;
+       int first = 1;
+
+       while ((iface = iface_iterator(first))) {
+               char  dummy[IFNAMSIZ];
+
+               first = 0;
+               if (iface->unused || !if_indextoname(iface->ifindex, dummy))
+                       mcgroup_prune(iface->ifname);
+       }
 
        TAILQ_FOREACH_SAFE(entry, &conf_list, link, tmp) {
                if (!entry->unused)
@@ -407,62 +417,84 @@
        }
 }
 
+/*
+ * When an interface is removed from the system, or its flags are
+ * changed to exclude the MULTICAST flag, we must prune groups.
+ */
+void mcgroup_prune(char *ifname)
+{
+       struct mcgroup *entry, *tmp;
+
+       TAILQ_FOREACH_SAFE(entry, &conf_list, link, tmp) {
+               if (strcmp(entry->ifname, ifname))
+                       continue;
+
+               mcgroup_action(0, entry->ifname, &entry->source, 
entry->src_len, &entry->group, entry->len);
+       }
+}
+
+static int show_mcgroup(int sd, struct mcgroup *entry)
+{
+       int max_len = inet_max_len(&entry->group);
+       char sg[INET_ADDRSTR_LEN * 2 + 10 + 3];
+       char src[INET_ADDRSTR_LEN] = "*";
+       char grp[INET_ADDRSTR_LEN];
+       char line[256];
+
+       if (!is_anyaddr(&entry->source))
+               inet_addr2str(&entry->source, src, sizeof(src));
+       inet_addr2str(&entry->group, grp, sizeof(grp));
+
+       snprintf(sg, sizeof(sg), "(%s", src);
+       if (entry->src_len != max_len)
+               snprintf(line, sizeof(line), "/%u, ", entry->src_len);
+       else
+               snprintf(line, sizeof(line), ", ");
+       strlcat(sg, line, sizeof(sg));
+
+       if (entry->len != max_len)
+               snprintf(line, sizeof(line), "%s/%u)", grp, entry->len);
+       else
+               snprintf(line, sizeof(line), "%s)", grp);
+       strlcat(sg, line, sizeof(sg));
+
+       snprintf(line, sizeof(line), "%-42s %s\n", sg, entry->ifname);
+       if (ipc_send(sd, line, strlen(line)) < 0) {
+               smclog(LOG_ERR, "Failed sending reply to client: %s", 
strerror(errno));
+               return -1;
+       }
+
+       return 0;
+}
+
 /* Write all joined IGMP/MLD groups to client socket */
 int mcgroup_show(int sd, int detail)
 {
-       char sg[INET_ADDRSTR_LEN * 2 + 10 + 3];
+       char *conf_str = "Group Memberships Table_\n";
+       char *kern_str = "Kernel Group Membership Table_\n";
        struct mcgroup *entry;
        char line[256];
- 
+
        if (TAILQ_EMPTY(&conf_list))
                return 0;
 
+       ipc_send(sd, conf_str, strlen(conf_str));
        snprintf(line, sizeof(line), "%-42s %-16s=\n", "GROUP (S,G)", "IIF");
        ipc_send(sd, line, strlen(line));
 
        TAILQ_FOREACH(entry, &conf_list, link) {
-               char src[INET_ADDRSTR_LEN] = "*";
-               char grp[INET_ADDRSTR_LEN];
-               struct iface *iface;
-               int max_len;
-
-               iface = iface_find_by_name(entry->ifname);
-               if (!iface)
-                       continue;
-
-#ifdef HAVE_IPV6_MULTICAST_HOST
-               if (entry->group.ss_family == AF_INET6)
-                       max_len = 128;
-               else
-#endif
-                       max_len = 32;
-
-               if (!is_anyaddr(&entry->source))
-                       inet_addr2str(&entry->source, src, sizeof(src));
-               inet_addr2str(&entry->group, grp, sizeof(grp));
-
-               snprintf(sg, sizeof(sg), "(%s", src);
-               if (entry->src_len != max_len)
-                       snprintf(line, sizeof(line), "/%u, ", entry->src_len);
-               else
-                       snprintf(line, sizeof(line), ", ");
-               strlcat(sg, line, sizeof(sg));
-
-               if (entry->len != max_len)
-                       snprintf(line, sizeof(line), "%s/%u)", grp, entry->len);
-               else
-                       snprintf(line, sizeof(line), "%s)", grp);
-               strlcat(sg, line, sizeof(sg));
-
-               snprintf(line, sizeof(line), "%-42s %s\n", sg, iface->ifname);
-               if (ipc_send(sd, line, strlen(line)) < 0) {
-                       smclog(LOG_ERR, "Failed sending reply to client: %s", 
strerror(errno));
-                       return -1;
-               }
+               if (show_mcgroup(sd, entry) < 0)
+                   return 1;
        }
 
-       if (detail) {
-               /* XXX: Show all from kern_list as well */
+       if (!detail)
+               return 0;
+
+       ipc_send(sd, kern_str, strlen(kern_str));
+       snprintf(line, sizeof(line), "%-42s %-16s=\n", "GROUP (S,G)", "IIF");
+       TAILQ_FOREACH(entry, &kern_list, link) {
+               if (show_mcgroup(sd, entry) < 0)
+                   return 1;
        }
 
        return 0;
diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn' 
'--exclude=.svnignore' old/smcroute-2.5.1/src/mcgroup.h 
new/smcroute-2.5.2/src/mcgroup.h
--- old/smcroute-2.5.1/src/mcgroup.h    2021-08-22 09:36:54.000000000 +0200
+++ new/smcroute-2.5.2/src/mcgroup.h    2021-08-27 17:55:39.000000000 +0200
@@ -20,6 +20,7 @@
 
 void mcgroup_reload_beg(void);
 void mcgroup_reload_end(void);
+void mcgroup_prune     (char *ifname);
 
 void mcgroup_init      (void);
 void mcgroup_exit      (void);
diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn' 
'--exclude=.svnignore' old/smcroute-2.5.1/src/mroute.c 
new/smcroute-2.5.2/src/mroute.c
--- old/smcroute-2.5.1/src/mroute.c     2021-08-22 09:36:54.000000000 +0200
+++ new/smcroute-2.5.2/src/mroute.c     2021-08-27 17:55:39.000000000 +0200
@@ -59,6 +59,8 @@
 static int  mroute_dyn_add     (struct mroute *route);
 static int  is_match           (struct mroute *rule, struct mroute *cand);
 static int  is_exact_match     (struct mroute *rule, struct mroute *cand);
+static int  mfc_install        (struct mroute *route);
+static int  mfc_uninstall      (struct mroute *route);
 
 /* Check for kernel IGMPMSG_NOCACHE for (*,G) hits. I.e., source-less routes. 
*/
 static void handle_nocache4(int sd, void *arg)
@@ -218,7 +220,6 @@
        if (kern_mroute_exit())
                return;
 
-       /* Free list of (*,G) routes on SIGHUP */
        TAILQ_FOREACH_SAFE(entry, &conf_list, link, tmp) {
                TAILQ_REMOVE(&conf_list, entry, link);
                free(entry);
@@ -229,6 +230,29 @@
        }
 }
 
+/*
+ * Prune VIF from all existing routes and update kernel MFC.  If VIF is
+ * used as inbound, prune entire route, otherwise just the outbound.
+ */
+static void mroute4_prune_vif(int vif)
+{
+       struct mroute *entry, *tmp;
+
+       TAILQ_FOREACH_SAFE(entry, &conf_list, link, tmp) {
+               if (entry->group.ss_family != AF_INET)
+                       continue;
+
+               if (entry->inbound == vif) {
+                       TAILQ_REMOVE(&conf_list, entry, link);
+                       entry->unused = 1;
+                       mfc_uninstall(entry);
+                       free(entry);
+               } else if (entry->ttl[vif] > 0) {
+                       entry->ttl[vif] = 0;
+                       mfc_install(entry);
+               }
+       }
+}
 
 /* Create a virtual interface from @iface so it can be used for IPv4 multicast 
routing. */
 static int mroute4_add_vif(struct iface *iface)
@@ -268,16 +292,28 @@
 
 static int mroute4_del_vif(struct iface *iface)
 {
+       int rc = 0;
+
        if (iface->mrdisc)
-               return mrdisc_deregister(iface->vif);
+               mrdisc_deregister(iface->vif);
 
-       if (kern_vif_del(iface) && errno != ENOENT) {
-               smclog(LOG_ERR, "Failed deleting VIF for iface %s: %s", 
iface->ifname, strerror(errno));
-               return -1;
+       if (kern_vif_del(iface)) {
+               switch (errno) {
+               case ENOENT:
+               case EADDRNOTAVAIL:
+                       break;
+               default:
+                       smclog(LOG_ERR, "Failed deleting VIF for iface %s: %s", 
iface->ifname, strerror(errno));
+                       break;
+               }
+               rc = -1;
        }
+
+       if (iface->vif >= 0 && iface->vif < ALL_VIFS)
+               mroute4_prune_vif(iface->vif);
        iface->vif = -1;
 
-       return 0;
+       return rc;
 }
 
 static int is_exact_match(struct mroute *rule, struct mroute *cand)
@@ -334,14 +370,8 @@
 
 static int is_ssm(struct mroute *route)
 {
-       int max_len;
+       int max_len = inet_max_len(&route->group);
 
-#ifdef HAVE_IPV6_MULTICAST_HOST
-       if (route->group.ss_family == AF_INET6)
-               max_len = 128;
-       else
-#endif
-       max_len = 32;
        return !is_anyaddr(&route->source) && route->src_len == max_len && 
route->len == max_len;
 }
 
@@ -490,20 +520,15 @@
        }
 
        TAILQ_FOREACH(kern, &kern_list, link) {
-               int diff = 0;
-
                if (!is_match(route, kern))
                        continue;
 
                for (size_t i = 0; i < NELEMS(route->ttl); i++) {
-                       if (route->ttl[i] > 0 && kern->ttl[i] != route->ttl[i]) 
{
+                       if (route->ttl[i] > 0 && kern->ttl[i] != route->ttl[i])
                                kern->ttl[i] = route->ttl[i];
-                               diff++;
-                       }
                }
 
-               if (diff)
-                       kern_mroute_add(kern);
+               kern_mroute_add(kern);
        }
 
        return 0;
@@ -812,6 +837,30 @@
 }
 
 #ifdef HAVE_IPV6_MULTICAST_ROUTING
+/*
+ * Prune VIF from all existing routes and update kernel MFC.  If VIF is
+ * used as inbound, prune entire route, otherwise just the outbound.
+ */
+static void mroute6_prune_mif(int mif)
+{
+       struct mroute *entry, *tmp;
+
+       TAILQ_FOREACH_SAFE(entry, &conf_list, link, tmp) {
+               if (entry->group.ss_family != AF_INET6)
+                       continue;
+
+               if (entry->inbound == mif) {
+                       TAILQ_REMOVE(&conf_list, entry, link);
+                       entry->unused = 1;
+                       mfc_uninstall(entry);
+                       free(entry);
+               } else if (entry->ttl[mif] > 0) {
+                       entry->ttl[mif] = 0;
+                       mfc_install(entry);
+               }
+       }
+}
+
 /* Create a virtual interface from @iface so it can be used for IPv6 multicast 
routing. */
 static int mroute6_add_mif(struct iface *iface)
 {
@@ -848,13 +897,25 @@
 
 static int mroute6_del_mif(struct iface *iface)
 {
+       int rc = 0;
+
        if (kern_mif_del(iface) && errno != ENOENT) {
-               smclog(LOG_ERR, "Failed deleting MIF for iface %s: %s", 
iface->ifname, strerror(errno));
-               return -1;
+               switch (errno) {
+               case ENOENT:
+               case EADDRNOTAVAIL:
+                       break;
+               default:
+                       smclog(LOG_ERR, "Failed deleting MIF for iface %s: %s", 
iface->ifname, strerror(errno));
+                       break;
+               }
+               rc = -1;
        }
+
+       if (iface->mif >= 0 && iface->mif < ALL_VIFS)
+               mroute6_prune_mif(iface->mif);
        iface->mif = -1;
 
-       return 0;
+       return rc;
 }
 #endif /* HAVE_IPV6_MULTICAST_ROUTING */
 
@@ -932,11 +993,11 @@
        int rc = 0;
 
        iface_match_init(&state);
-       while ((iface = iface_match_by_name(ifname, &state))) {
+       while ((iface = iface_match_by_name(ifname, 1, &state))) {
                smclog(LOG_DEBUG, "Creating/updating multicast VIF for %s TTL 
%d", iface->ifname, ttl);
-               iface->unused    = 0;
                iface->mrdisc    = mrdisc;
                iface->threshold = ttl;
+               iface->unused    = 0;
                rc += mroute4_add_vif(iface);
 #ifdef HAVE_IPV6_MULTICAST_ROUTING
                rc += mroute6_add_mif(iface);
@@ -959,7 +1020,7 @@
        int rc = 0;
 
        iface_match_init(&state);
-       while ((iface = iface_match_by_name(ifname, &state))) {
+       while ((iface = iface_match_by_name(ifname, 1, &state))) {
                smclog(LOG_DEBUG, "Removing multicast VIFs for %s", 
iface->ifname);
                rc += mroute4_del_vif(iface);
 #ifdef HAVE_IPV6_MULTICAST_ROUTING
@@ -995,24 +1056,30 @@
        }
 }
 
-void mroute_reload_end(void)
+void mroute_reload_end(int do_vifs)
 {
        struct mroute *entry, *tmp;
        struct iface *iface;
        int first = 1;
 
+       while ((iface = iface_iterator(first))) {
+               char  dummy[IFNAMSIZ];
+
+               first = 0;
+               if (iface->unused || !if_indextoname(iface->ifindex, dummy)) {
+                       mroute_del_vif(iface->ifname);
+               } else if (do_vifs)
+                       mroute_add_vif(iface->ifname, iface->mrdisc, 
iface->threshold);
+       }
+
        TAILQ_FOREACH_SAFE(entry, &conf_list, link, tmp) {
                if (entry->unused)
                        mroute_del_route(entry);
        }
 
-       while ((iface = iface_iterator(first))) {
-               first = 0;
-               if (iface->unused) {
-                       mroute_del_vif(iface->ifname);
-                       iface->unused = 0;
-               }
-       }
+       /* retry add if .conf changed IIF for routes, not until del (above) can 
we add */
+       TAILQ_FOREACH(entry, &conf_list, link)
+               mfc_install(entry);
 }
 
 static int show_mroute(int sd, struct mroute *r, int inw, int detail)
@@ -1024,12 +1091,9 @@
        char sg[(INET_ADDRSTRLEN + 3) * 2 + 5];
        char buf[MAX_MC_VIFS * 17 + 80];
        struct iface *iface;
-       int max_len = 32;
+       int max_len;
 
-#ifdef HAVE_IPV6_MULTICAST_ROUTING
-       if (r->group.ss_family == AF_INET6)
-               max_len = 128;
-#endif
+       max_len = inet_max_len(&r->group);
 
        if (!is_anyaddr(&r->source)) {
                inet_addr2str(&r->source, src, sizeof(src));
diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn' 
'--exclude=.svnignore' old/smcroute-2.5.1/src/mroute.h 
new/smcroute-2.5.2/src/mroute.h
--- old/smcroute-2.5.1/src/mroute.h     2021-08-22 09:36:54.000000000 +0200
+++ new/smcroute-2.5.2/src/mroute.h     2021-08-27 17:55:39.000000000 +0200
@@ -116,7 +116,7 @@
 int  mroute_del_route  (struct mroute *mroute);
 
 void mroute_reload_beg (void);
-void mroute_reload_end (void);
+void mroute_reload_end (int do_vifs);
 
 int  mroute_show       (int sd, int detail);
 
diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn' 
'--exclude=.svnignore' old/smcroute-2.5.1/src/smcrouted.c 
new/smcroute-2.5.2/src/smcrouted.c
--- old/smcroute-2.5.1/src/smcrouted.c  2021-08-22 09:36:54.000000000 +0200
+++ new/smcroute-2.5.2/src/smcrouted.c  2021-08-27 17:55:39.000000000 +0200
@@ -89,11 +89,11 @@
        mcgroup_reload_beg();
        mroute_reload_beg();
 
-       iface_update(do_vifs);
+       iface_update();
        conf_read(conf_file, do_vifs);
 
+       mroute_reload_end(do_vifs);
        mcgroup_reload_end();
-       mroute_reload_end();
 
        /* Acknowledge client SIGHUP/reload */
        notify_ready(NULL, uid, gid);
@@ -193,7 +193,7 @@
        /*
         * Build list of multicast-capable physical interfaces
         */
-       iface_init(do_vifs);
+       iface_init();
 
        if (mroute_init(do_vifs, table_id, cache_tmo)) {
                if (errno == EADDRINUSE)
@@ -470,7 +470,7 @@
 
        if (conf_vrfy) {
                smclog(LOG_INFO, "Verifying configuration file %s ...", 
conf_file);
-               iface_init(do_vifs);
+               iface_init();
                c = conf_read(conf_file, do_vifs);
                iface_exit();
 
diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn' 
'--exclude=.svnignore' old/smcroute-2.5.1/src/socket.c 
new/smcroute-2.5.2/src/socket.c
--- old/smcroute-2.5.1/src/socket.c     2021-08-22 09:36:54.000000000 +0200
+++ new/smcroute-2.5.2/src/socket.c     2021-08-27 17:55:39.000000000 +0200
@@ -98,29 +98,29 @@
        if (sd < 0)
                return -1;
 
+       if (domain == AF_UNIX)
+               goto done;
+
 #ifdef HAVE_IPV6_MULTICAST_HOST
-               if (domain == AF_INET6) {
-                       if (setsockopt(sd, IPPROTO_IPV6, IPV6_MULTICAST_LOOP, 
&val, sizeof(val)))
-                               smclog(LOG_WARNING, "failed disabling 
IPV6_MULTICAST_LOOP: %s",
-                                      strerror(errno));
+       if (domain == AF_INET6) {
+               if (setsockopt(sd, IPPROTO_IPV6, IPV6_MULTICAST_LOOP, &val, 
sizeof(val)))
+                       smclog(LOG_WARNING, "failed disabling 
IPV6_MULTICAST_LOOP: %s", strerror(errno));
 #ifdef IPV6_MULTICAST_ALL
-                       if (setsockopt(sd, IPPROTO_IPV6, IPV6_MULTICAST_ALL, 
&val, sizeof(val)))
-                               smclog(LOG_WARNING, "failed disabling 
IPV6_MULTICAST_ALL: %s",
-                                      strerror(errno));
+               if (setsockopt(sd, IPPROTO_IPV6, IPV6_MULTICAST_ALL, &val, 
sizeof(val)))
+                       smclog(LOG_WARNING, "failed disabling 
IPV6_MULTICAST_ALL: %s", strerror(errno));
 #endif
-               } else
+       } else
 #endif /* HAVE_IPV6_MULTICAST_HOST */
-               {
-                       if (setsockopt(sd, IPPROTO_IP, IP_MULTICAST_LOOP, &val, 
sizeof(val)))
-                               smclog(LOG_WARNING, "failed disabling 
IP_MULTICAST_LOOP: %s",
-                                      strerror(errno));
+       {
+
+               if (setsockopt(sd, IPPROTO_IP, IP_MULTICAST_LOOP, &val, 
sizeof(val)))
+                       smclog(LOG_WARNING, "failed disabling 
IP_MULTICAST_LOOP: %s", strerror(errno));
 #ifdef IP_MULTICAST_ALL
-                       if (setsockopt(sd, IPPROTO_IP, IP_MULTICAST_ALL, &val, 
sizeof(val)))
-                               smclog(LOG_WARNING, "failed disabling 
IP_MULTICAST_ALL: %s",
-                                      strerror(errno));
+               if (setsockopt(sd, IPPROTO_IP, IP_MULTICAST_ALL, &val, 
sizeof(val)))
+                       smclog(LOG_WARNING, "failed disabling IP_MULTICAST_ALL: 
%s", strerror(errno));
 #endif
-               }
-
+       }
+done:
        if (socket_register(sd, cb, arg) < 0) {
                close(sd);
                return -1;
diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn' 
'--exclude=.svnignore' old/smcroute-2.5.1/test/Makefile.am 
new/smcroute-2.5.2/test/Makefile.am
--- old/smcroute-2.5.1/test/Makefile.am 2021-08-22 09:36:54.000000000 +0200
+++ new/smcroute-2.5.2/test/Makefile.am 2021-08-27 17:55:39.000000000 +0200
@@ -1,5 +1,5 @@
 EXTRA_DIST         = adv.sh basic.sh bridge.sh dyn.sh expire.sh gre.sh ipv6.sh 
include.sh
-EXTRA_DIST        += isolated.sh join.sh joinlen.sh lib.sh multi.sh mem.sh 
mrdisc.sh
+EXTRA_DIST        += isolated.sh join.sh joinlen.sh lib.sh lost.sh multi.sh 
mem.sh mrdisc.sh
 EXTRA_DIST        += poison.sh reload.sh reload6.sh vlan.sh vrfy.sh
 CLEANFILES         = *~ *.trs *.log
 TEST_EXTENSIONS    = .sh
@@ -16,6 +16,7 @@
 TESTS             += isolated.sh
 TESTS             += join.sh
 TESTS             += joinlen.sh
+TESTS             += lost.sh
 TESTS             += mem.sh
 TESTS             += mrdisc.sh
 TESTS             += multi.sh
diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn' 
'--exclude=.svnignore' old/smcroute-2.5.1/test/lost.sh 
new/smcroute-2.5.2/test/lost.sh
--- old/smcroute-2.5.1/test/lost.sh     1970-01-01 01:00:00.000000000 +0100
+++ new/smcroute-2.5.2/test/lost.sh     2021-08-27 17:55:39.000000000 +0200
@@ -0,0 +1,98 @@
+#!/bin/sh
+# Verify handling when IIF for an (S,G) is changed or lost
+
+#set -x
+
+check_output()
+{
+    echo "ip mroute:"
+    ip mroute
+    ip mroute |tee "/tmp/$NM/result" | grep -q "$2"
+    oif=$?
+    grep -q "$1" "/tmp/$NM/result"
+    iif=$?
+    # shellcheck disable=SC2166
+    [ "$oif" = "0" -a "$iif" = "0" ] || FAIL
+}
+
+# shellcheck source=/dev/null
+. "$(dirname "$0")/lib.sh"
+
+print "Creating world ..."
+topo basic
+ip addr add 10.0.0.1/24 dev a1
+ip addr add 20.0.0.1/24 dev a2
+ip -br a
+
+print "Creating config #1 ..."
+cat <<EOF > "/tmp/$NM/conf"
+phyint a1 enable
+phyint a2 enable
+
+mgroup from a1 group 225.1.2.3
+mroute from a1 group 225.1.2.3 to a2
+
+mgroup from a2 group 225.1.2.4
+mroute from a2 source 1.2.3.4 group 225.1.2.4 to a1
+
+mgroup from a1 group 225.2.2.5
+mroute from a1 group 225.2.2.5 to a1
+
+mgroup from a2 group 225.1.2.6
+mroute from a2 source 1.2.3.5 group 225.1.2.6 to a1
+EOF
+cat "/tmp/$NM/conf"
+
+print "Starting smcrouted ..."
+../src/smcrouted -f "/tmp/$NM/conf" -N -n -P "/tmp/$NM/pid" -l debug -u 
"/tmp/$NM/sock" &
+sleep 1
+
+cat /proc/net/ip_mr_vif
+cat /proc/net/ip_mr_cache
+../src/smcroutectl -pu "/tmp/$NM/sock" show groups
+show_mroute
+
+check_output "(1.2.3.4,225.1.2.4)              Iif: a2         Oifs: a1"
+
+print "Creating config #2 ..."
+cat <<EOF > "/tmp/$NM/conf"
+phyint a1 enable
+phyint a2 enable
+
+mgroup from a1 group 225.1.2.3
+mroute from a1 group 225.1.2.3 to a2
+
+mgroup from a1 group 225.1.2.4
+mroute from a1 source 1.2.3.4 group 225.1.2.4 to a2
+
+mgroup from a2 group 225.2.2.5
+mroute from a2 group 225.2.2.5 to a1
+
+mgroup from a2 group 225.1.2.6
+mroute from a2 source 1.2.3.5 group 225.1.2.6 to a1
+EOF
+cat "/tmp/$NM/conf"
+../src/smcroutectl -u "/tmp/$NM/sock" reload
+sleep 1
+
+check_output "(1.2.3.4,225.1.2.4)              Iif: a1         Oifs: a2"
+
+print "Deleting and restoring interface a1 => new ifindex ..."
+ip link del a1
+ip link add a1 type dummy
+ip link set a1 up
+ip link set a1 multicast on
+ip addr add 10.0.0.1/24 dev a1
+
+../src/smcroutectl -u "/tmp/$NM/sock" reload
+sleep 1
+
+check_output "(1.2.3.4,225.1.2.4)              Iif: a1         Oifs: a2"
+
+print "Deleting interface a1 ..."
+ip link del a1
+../src/smcroutectl -u "/tmp/$NM/sock" reload
+sleep 1
+check_output "(1.2.3.5,225.1.2.6)              Iif: a2          State: 
resolved"
+
+OK

Reply via email to