Script 'mail_helper' called by obssrc
Hello community,

here is the log from the commit of package ubridge for openSUSE:Factory checked 
in at 2026-09-08 16:54:03
++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++
Comparing /work/SRC/openSUSE:Factory/ubridge (Old)
 and      /work/SRC/openSUSE:Factory/.ubridge.new.1265 (New)
++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++

Package is "ubridge"

Tue Sep  8 16:54:03 2026 rev:8 rq:1376085 version:1.2.3

Changes:
--------
--- /work/SRC/openSUSE:Factory/ubridge/ubridge.changes  2026-09-04 
12:39:44.426173544 +0200
+++ /work/SRC/openSUSE:Factory/.ubridge.new.1265/ubridge.changes        
2026-09-08 16:55:05.486415127 +0200
@@ -1,0 +2,6 @@
+Sun Sep  6 16:36:58 UTC 2026 - Martin Hauke <[email protected]>
+
+- Update to version 1.2.3
+  * feat: Add TAP carrier control support.
+
+-------------------------------------------------------------------

Old:
----
  ubridge-1.2.2.tar.gz

New:
----
  ubridge-1.2.3.tar.gz

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

Other differences:
------------------
++++++ ubridge.spec ++++++
--- /var/tmp/diff_new_pack.W5QtSu/_old  2026-09-08 16:55:06.268447376 +0200
+++ /var/tmp/diff_new_pack.W5QtSu/_new  2026-09-08 16:55:06.271447499 +0200
@@ -17,7 +17,7 @@
 
 
 Name:           ubridge
-Version:        1.2.2
+Version:        1.2.3
 Release:        0
 Summary:        Bridging between UDP tunnels, Ethernet and TAP interfaces
 License:        GPL-3.0-only

++++++ ubridge-1.2.2.tar.gz -> ubridge-1.2.3.tar.gz ++++++
diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn' 
'--exclude=.svnignore' old/ubridge-1.2.2/README.md new/ubridge-1.2.3/README.md
--- old/ubridge-1.2.2/README.md 2026-08-31 12:02:31.000000000 +0200
+++ new/ubridge-1.2.3/README.md 2026-09-04 20:17:34.000000000 +0200
@@ -120,7 +120,8 @@
 101 start_capture (min/max args: 2/3)
 101 add_nio_linux_raw (min/max args: 2/2)
 101 add_nio_ethernet (min/max args: 2/2)
-101 add_nio_tap (min/max args: 2/2)
+101 set_nio_tap_carrier (min/max args: 2/2)
+101 add_nio_tap (min/max args: 2/3)
 101 add_nio_unix (min/max args: 3/3)
 101 delete_nio_udp (min/max args: 4/4)
 101 remove_nio_udp (min/max args: 4/4)
@@ -234,14 +235,24 @@
 100-NIO UNIX added to bridge 'br0'
 ```
 
-- **bridge add_nio_tap** *\<bridge_name\>* *\<tap_device\>*:
-    Add a TAP NIO to a bridge. TAP devices require root access.
+- **bridge add_nio_tap** *\<bridge_name\>* *\<tap_device\>* *[on|off]*:
+    Add a TAP NIO to a bridge. TAP devices require root access. The optional
+    state controls the initial carrier state and defaults to `on`.
 
 ``` {.bash}
 bridge add_nio_tap br0 tap0
 100-NIO TAP added to bridge 'br0'
 ```
 
+- **bridge set_nio_tap_carrier** *\<bridge_name\>* *\<on|off\>*:
+    Change the carrier state of a TAP NIO without changing its administrative
+    state. This can be used to emulate plugging or unplugging a cable.
+
+``` {.bash}
+bridge set_nio_tap_carrier br0 off
+100-TAP carrier set off on bridge 'br0'
+```
+
 - **bridge add_nio_ethernet** *\<bridge_name\>*
     *\<eth_device\>*: Add a generic Ethernet NIO to a bridge, using
     PCAP (0.9.4 and greater). It requires root access.
diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn' 
'--exclude=.svnignore' old/ubridge-1.2.2/src/hypervisor_bridge.c 
new/ubridge-1.2.3/src/hypervisor_bridge.c
--- old/ubridge-1.2.2/src/hypervisor_bridge.c   2026-08-31 12:02:31.000000000 
+0200
+++ new/ubridge-1.2.3/src/hypervisor_bridge.c   2026-09-04 20:17:34.000000000 
+0200
@@ -426,6 +426,7 @@
 
 static int cmd_add_nio_tap(hypervisor_conn_t *conn, int argc, char *argv[])
 {
+   int carrier = TRUE;
    nio_t *nio;
    bridge_t *bridge;
 
@@ -435,7 +436,18 @@
       return (-1);
    }
 
-   nio = create_nio_tap(argv[1]);
+   if (argc == 3) {
+      if (!strcmp(argv[2], "on"))
+         carrier = TRUE;
+      else if (!strcmp(argv[2], "off"))
+         carrier = FALSE;
+      else {
+         hypervisor_send_reply(conn, HSC_ERR_INV_PARAM, 1, "invalid TAP 
carrier state '%s'", argv[2]);
+         return (-1);
+      }
+   }
+
+   nio = create_nio_tap_with_carrier(argv[1], carrier);
    if (!nio) {
       hypervisor_send_reply(conn, HSC_ERR_CREATE, 1, "unable to create NIO TAP 
for bridge '%s'", argv[0]);
       return (-1);
@@ -452,6 +464,47 @@
    return (0);
 }
 
+static int cmd_set_nio_tap_carrier(hypervisor_conn_t *conn, int argc, char 
*argv[])
+{
+   int carrier;
+   nio_t *nio = NULL;
+   bridge_t *bridge;
+
+   bridge = find_bridge(argv[0]);
+   if (bridge == NULL) {
+      hypervisor_send_reply(conn, HSC_ERR_NOT_FOUND, 1, "bridge '%s' doesn't 
exist", argv[0]);
+      return (-1);
+   }
+
+   if (!strcmp(argv[1], "on"))
+      carrier = TRUE;
+   else if (!strcmp(argv[1], "off"))
+      carrier = FALSE;
+   else {
+      hypervisor_send_reply(conn, HSC_ERR_INV_PARAM, 1, "invalid TAP carrier 
state '%s'", argv[1]);
+      return (-1);
+   }
+
+   if (bridge->source_nio && bridge->source_nio->type == NIO_TYPE_TAP)
+      nio = bridge->source_nio;
+   else if (bridge->destination_nio && bridge->destination_nio->type == 
NIO_TYPE_TAP)
+      nio = bridge->destination_nio;
+
+   if (nio == NULL) {
+      hypervisor_send_reply(conn, HSC_ERR_NOT_FOUND, 1, "bridge '%s' has no 
TAP NIO", argv[0]);
+      return (-1);
+   }
+
+   if (nio_tap_set_carrier(nio, carrier) < 0) {
+      hypervisor_send_reply(conn, HSC_ERR_CREATE, 1, "unable to set TAP 
carrier %s on bridge '%s': %s",
+                            argv[1], argv[0], strerror(errno));
+      return (-1);
+   }
+
+   hypervisor_send_reply(conn, HSC_INFO_OK, 1, "TAP carrier set %s on bridge 
'%s'", argv[1], argv[0]);
+   return (0);
+}
+
 static int cmd_add_nio_ethernet(hypervisor_conn_t *conn, int argc, char 
*argv[])
 {
    nio_t *nio;
@@ -697,7 +750,8 @@
    { "remove_nio_udp", 4, 4, cmd_delete_nio_udp, NULL }, /* kept for 
compatibility */
    { "delete_nio_udp", 4, 4, cmd_delete_nio_udp, NULL },
    { "add_nio_unix", 3, 3, cmd_add_nio_unix, NULL },
-   { "add_nio_tap", 2, 2, cmd_add_nio_tap, NULL },
+   { "add_nio_tap", 2, 3, cmd_add_nio_tap, NULL },
+   { "set_nio_tap_carrier", 2, 2, cmd_set_nio_tap_carrier, NULL },
    { "add_nio_ethernet", 2, 2, cmd_add_nio_ethernet, NULL },
    { "add_nio_linux_raw", 2, 2, cmd_add_nio_linux_raw, NULL },
    { "start_capture", 2, 3, cmd_start_capture_bridge, NULL },
@@ -722,4 +776,3 @@
    hypervisor_register_cmd_array(module, bridge_cmd_array);
    return(0);
 }
-
diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn' 
'--exclude=.svnignore' old/ubridge-1.2.2/src/nio_tap.c 
new/ubridge-1.2.3/src/nio_tap.c
--- old/ubridge-1.2.2/src/nio_tap.c     2026-08-31 12:02:31.000000000 +0200
+++ new/ubridge-1.2.3/src/nio_tap.c     2026-09-04 20:17:34.000000000 +0200
@@ -34,7 +34,7 @@
 
 
 /* Open a TAP device */
-static int nio_tap_open(char *tap_devname)
+static int nio_tap_open(char *tap_devname, int carrier)
 {
    struct ifreq ifr;
    int err, fd;
@@ -66,6 +66,10 @@
 
       memset(&ifr,0,sizeof(ifr));
       ifr.ifr_flags = IFF_TAP | IFF_NO_PI;
+#ifdef IFF_NO_CARRIER
+      if (!carrier)
+         ifr.ifr_flags |= IFF_NO_CARRIER;
+#endif
       if (*tap_devname)
          strncpy(ifr.ifr_name, tap_devname, IFNAMSIZ);
 
@@ -76,6 +80,13 @@
 
       strcpy(tap_devname, ifr.ifr_name);
    }
+
+   if (!carrier && ioctl(fd, TUNSETCARRIER, &carrier) < 0) {
+      err = errno;
+      close(fd);
+      errno = err;
+      return(-1);
+   }
    return(fd);
 }
 
@@ -96,7 +107,7 @@
 }
 
 /* Create a new NIO TAP */
-nio_t *create_nio_tap(char *tap_name)
+nio_t *create_nio_tap_with_carrier(char *tap_name, int carrier)
 {
    nio_tap_t *nio_tap;
    nio_t *nio;
@@ -113,7 +124,7 @@
    }
 
    memset(nio_tap, 0, sizeof(*nio_tap));
-   nio_tap->fd = nio_tap_open(tap_name);
+   nio_tap->fd = nio_tap_open(tap_name, carrier);
 
    if (nio_tap->fd == -1) {
       fprintf(stderr,"create_nio_tap: unable to open TAP device %s (%s)\n", 
tap_name, strerror(errno));
@@ -128,3 +139,19 @@
    nio->dptr = &nio->u.nio_tap;
    return nio;
 }
+
+nio_t *create_nio_tap(char *tap_name)
+{
+   return create_nio_tap_with_carrier(tap_name, TRUE);
+}
+
+int nio_tap_set_carrier(nio_t *nio, int carrier)
+{
+   if (nio == NULL || nio->type != NIO_TYPE_TAP) {
+      errno = EINVAL;
+      return(-1);
+   }
+
+   carrier = carrier ? 1 : 0;
+   return ioctl(nio->u.nio_tap.fd, TUNSETCARRIER, &carrier);
+}
diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn' 
'--exclude=.svnignore' old/ubridge-1.2.2/src/nio_tap.h 
new/ubridge-1.2.3/src/nio_tap.h
--- old/ubridge-1.2.2/src/nio_tap.h     2026-08-31 12:02:31.000000000 +0200
+++ new/ubridge-1.2.3/src/nio_tap.h     2026-09-04 20:17:34.000000000 +0200
@@ -24,5 +24,7 @@
 #include "nio.h"
 
 nio_t *create_nio_tap(char *tap_name);
+nio_t *create_nio_tap_with_carrier(char *tap_name, int carrier);
+int nio_tap_set_carrier(nio_t *nio, int carrier);
 
 #endif /* !NIO_TAP_H_ */
diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn' 
'--exclude=.svnignore' old/ubridge-1.2.2/src/ubridge.h 
new/ubridge-1.2.3/src/ubridge.h
--- old/ubridge-1.2.2/src/ubridge.h     2026-08-31 12:02:31.000000000 +0200
+++ new/ubridge-1.2.3/src/ubridge.h     2026-09-04 20:17:34.000000000 +0200
@@ -31,7 +31,7 @@
 #include "packet_filter.h"
 
 #define NAME          "ubridge"
-#define VERSION       "1.2.2"
+#define VERSION       "1.2.3"
 #define CONFIG_FILE   "ubridge.ini"
 
 #ifndef FALSE
diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn' 
'--exclude=.svnignore' old/ubridge-1.2.2/tests/tap/run_all.py 
new/ubridge-1.2.3/tests/tap/run_all.py
--- old/ubridge-1.2.2/tests/tap/run_all.py      2026-08-31 12:02:31.000000000 
+0200
+++ new/ubridge-1.2.3/tests/tap/run_all.py      2026-09-04 20:17:34.000000000 
+0200
@@ -4,6 +4,7 @@
 
 SUITES = [
     "test_basic",
+    "test_carrier",
 ]
 
 
diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn' 
'--exclude=.svnignore' old/ubridge-1.2.2/tests/tap/test_carrier.py 
new/ubridge-1.2.3/tests/tap/test_carrier.py
--- old/ubridge-1.2.2/tests/tap/test_carrier.py 1970-01-01 01:00:00.000000000 
+0100
+++ new/ubridge-1.2.3/tests/tap/test_carrier.py 2026-09-04 20:17:34.000000000 
+0200
@@ -0,0 +1,77 @@
+"""Regression tests for TAP carrier control. Requires CAP_NET_ADMIN."""
+
+import os
+import subprocess
+import sys
+
+sys.path.insert(0, os.path.join(os.path.dirname(os.path.abspath(__file__)), 
"..", "brctl"))
+from common import Ubridge, Results  # noqa: E402
+
+PORT = 13031
+BRIDGE = "carrier-test"
+TAP = "ubcarrier0"
+DEFAULT_BRIDGE = "carrier-default-test"
+DEFAULT_TAP = "ubcarrier1"
+
+
+def _ip(*args):
+    return subprocess.run(["ip"] + list(args), capture_output=True, text=True)
+
+
+def _carrier_for(tap=TAP):
+    try:
+        with open("/sys/class/net/%s/carrier" % tap, encoding="ascii") as 
stream:
+            return stream.read().strip()
+    except OSError:
+        return None
+
+
+def main():
+    r = Results()
+
+    with Ubridge(port=PORT) as ub:
+        c = ub.connect()
+        try:
+            r.check("create bridge", c.code("bridge create %s" % BRIDGE) == 
"100")
+            r.check("set carrier without TAP rejected",
+                    c.code("bridge set_nio_tap_carrier %s off" % BRIDGE) == 
"214")
+            r.check("invalid initial state rejected",
+                    c.code("bridge add_nio_tap %s %s invalid" % (BRIDGE, TAP)) 
== "204")
+            r.check("add TAP with carrier off",
+                    c.code("bridge add_nio_tap %s %s off" % (BRIDGE, TAP)) == 
"100")
+            r.check("bring TAP administratively up",
+                    c.code("link set %s up" % TAP) == "100")
+            carrier = _carrier_for()
+            r.check("initial carrier is off", carrier == "0", "carrier=%r" % 
carrier)
+            r.check("set carrier on",
+                    c.code("bridge set_nio_tap_carrier %s on" % BRIDGE) == 
"100")
+            carrier = _carrier_for()
+            r.check("carrier is on", carrier == "1", "carrier=%r" % carrier)
+            r.check("set carrier off",
+                    c.code("bridge set_nio_tap_carrier %s off" % BRIDGE) == 
"100")
+            carrier = _carrier_for()
+            r.check("carrier is off", carrier == "0", "carrier=%r" % carrier)
+            r.check("invalid state rejected",
+                    c.code("bridge set_nio_tap_carrier %s invalid" % BRIDGE) 
== "204")
+
+            r.check("create default bridge",
+                    c.code("bridge create %s" % DEFAULT_BRIDGE) == "100")
+            r.check("legacy add TAP defaults carrier on",
+                    c.code("bridge add_nio_tap %s %s" % (DEFAULT_BRIDGE, 
DEFAULT_TAP)) == "100")
+            r.check("bring default TAP administratively up",
+                    c.code("link set %s up" % DEFAULT_TAP) == "100")
+            default_carrier = _carrier_for(DEFAULT_TAP)
+            r.check("default carrier is on", default_carrier == "1",
+                    "carrier=%r" % default_carrier)
+        finally:
+            c.send("bridge delete %s" % BRIDGE)
+            c.send("bridge delete %s" % DEFAULT_BRIDGE)
+            c.close()
+            _ip("link", "delete", TAP)
+            _ip("link", "delete", DEFAULT_TAP)
+
+    return 0 if r.summary() else 1
+
+
+if __name__ == "__main__":
+    raise SystemExit(main())

Reply via email to