ubus: connect to UBus backend
authorNicolas BESNARD <[email protected]>
Wed, 20 Nov 2024 13:20:49 +0000 (13:20 +0000)
committerÁlvaro Fernández Rojas <[email protected]>
Mon, 3 Nov 2025 15:21:17 +0000 (16:21 +0100)
Problem:
    odhcp6c is not connected to UBus making communication with other
    processes more difficult.

Solution:
    Connect odhcp6c to UBus back-end when the WITH_UBUS build time
    configuration option is set.

Signed-off-by: Nicolas BESNARD <[email protected]>
Signed-off-by: Paul Donald <[email protected]>
Link: https://github.com/openwrt/odhcp6c/pull/106
Signed-off-by: Álvaro Fernández Rojas <[email protected]>
.github/workflows/ci.yml
CMakeLists.txt
scripts/devel-build.sh
src/odhcp6c.c
src/ubus.c [new file with mode: 0644]
src/ubus.h [new file with mode: 0644]

index a4646582caca7a091274490c86e0ad15b8f4e957..006cfd3f942cc41599384bc94b394d9feec947e1 100644 (file)
@@ -25,10 +25,14 @@ jobs:
             gcc: /usr/bin/x86_64-linux-gnu-gcc
             packages: gcc-x86-64-linux-gnu
     outputs:
-      size-aarch64: ${{ steps.build.outputs.size_aarch64 }}
-      size-arm: ${{ steps.build.outputs.size_arm }}
-      size-mips: ${{ steps.build.outputs.size_mips }}
-      size-x86_64: ${{ steps.build.outputs.size_x86_64 }}
+      size-aarch64-without-ubus: ${{ steps.without_ubus.outputs.size_aarch64 }}
+      size-aarch64-with-ubus: ${{ steps.with_ubus.outputs.size_aarch64 }}
+      size-arm-without-ubus: ${{ steps.without_ubus.outputs.size_arm }}
+      size-arm-with-ubus: ${{ steps.with_ubus.outputs.size_arm }}
+      size-mips-without-ubus: ${{ steps.without_ubus.outputs.size_mips }}
+      size-mips-with-ubus: ${{ steps.with_ubus.outputs.size_mips }}
+      size-x86_64-without-ubus: ${{ steps.without_ubus.outputs.size_x86_64 }}
+      size-x86_64-with-ubus: ${{ steps.with_ubus.outputs.size_x86_64 }}
     steps:
       - name: Checkout odhcp6c
         uses: actions/checkout@v5
@@ -45,6 +49,12 @@ jobs:
           repository: openwrt/libubox
           path: depends/libubox
 
+      - name: Checkout ubus
+        uses: actions/checkout@v5
+        with:
+          repository: openwrt/ubus
+          path: depends/ubus
+
       - name: Install dependencies
         run: |
           sudo apt update
@@ -76,14 +86,38 @@ jobs:
           make
           make install
 
-      - id: build
-        name: Build odhcp6c
+      - name: Build ubus
+        working-directory: depends/ubus
+        run: |
+          cmake \
+            -DCMAKE_C_COMPILER=${{ matrix.gcc }} \
+            -DCMAKE_PREFIX_PATH=${GITHUB_WORKSPACE}/build \
+            -DBUILD_LUA=OFF -DBUILD_EXAMPLES=OFF \
+            --install-prefix ${GITHUB_WORKSPACE}/build
+          make
+          make install
+
+      - id: without_ubus
+        name: Build odhcp6c (w/o ubus)
+        env:
+          BUILD_DIR: build/odhcp6c-without-ubus
+        run: |
+          cmake \
+            -DCMAKE_C_COMPILER=${{ matrix.gcc }} \
+            -DCMAKE_PREFIX_PATH=${GITHUB_WORKSPACE}/build \
+            -B $BUILD_DIR
+          make -C $BUILD_DIR
+          echo "size_${{ matrix.arch }}=$( find $BUILD_DIR -type f -name odhcp6c -printf '%s' )" >> $GITHUB_OUTPUT
+
+      - id: with_ubus
+        name: Build odhcp6c (with ubus)
         env:
-          BUILD_DIR: build/odhcp6c
+          BUILD_DIR: build/odhcp6c-with-ubus
         run: |
           cmake \
             -DCMAKE_C_COMPILER=${{ matrix.gcc }} \
             -DCMAKE_PREFIX_PATH=${GITHUB_WORKSPACE}/build \
+            -DUBUS=ON \
             -B $BUILD_DIR
           make -C $BUILD_DIR
           echo "size_${{ matrix.arch }}=$( find $BUILD_DIR -type f -name odhcp6c -printf '%s' )" >> $GITHUB_OUTPUT
@@ -93,7 +127,7 @@ jobs:
         with:
           name: odhcp6c-${{ matrix.arch }}-binaries
           path: |
-            build/odhcp6c/odhcp6c
+            build/odhcp6c-*/odhcp6c
           if-no-files-found: error
 
   summary:
@@ -103,12 +137,17 @@ jobs:
     steps:
       - name: Sizes summary
         env:
-          size_aarch64: ${{needs.build.outputs.size-aarch64}}
-          size_arm: ${{needs.build.outputs.size-arm}}
-          size_mips: ${{needs.build.outputs.size-mips}}
-          size_x86_64: ${{needs.build.outputs.size-x86_64}}
+          size_aarch64_without_ubus: ${{needs.build.outputs.size-aarch64-without-ubus}}
+          size_aarch64_with_ubus: ${{needs.build.outputs.size-aarch64-with-ubus}}
+          size_arm_without_ubus: ${{needs.build.outputs.size-arm-without-ubus}}
+          size_arm_with_ubus: ${{needs.build.outputs.size-arm-with-ubus}}
+          size_mips_without_ubus: ${{needs.build.outputs.size-mips-without-ubus}}
+          size_mips_with_ubus: ${{needs.build.outputs.size-mips-with-ubus}}
+          size_x86_64_without_ubus: ${{needs.build.outputs.size-x86_64-without-ubus}}
+          size_x86_64_with_ubus: ${{needs.build.outputs.size-x86_64-with-ubus}}
         run: |
           echo "### ${GITHUB_WORKFLOW} sizes :floppy_disk:" >> $GITHUB_STEP_SUMMARY
           echo "| Variant | aarch64 | arm | mips | x86_64 |" >> $GITHUB_STEP_SUMMARY
           echo "| :---: | :---: | :---: | :---: | :---: |" >> $GITHUB_STEP_SUMMARY
-          echo "| odhcp6c | ${size_aarch64} | ${size_arm} | ${size_mips} | ${size_x86_64} |" >> $GITHUB_STEP_SUMMARY
+          echo "| w/o ubus | ${size_aarch64_without_ubus} | ${size_arm_without_ubus} | ${size_mips_without_ubus} | ${size_x86_64_without_ubus} |" >> $GITHUB_STEP_SUMMARY
+          echo "| with ubus | ${size_aarch64_with_ubus} | ${size_arm_with_ubus} | ${size_mips_with_ubus} | ${size_x86_64_with_ubus} |" >> $GITHUB_STEP_SUMMARY
index 02d44be8ee7d120fe1268cdb8c32331f73b46b9b..0c3d1be9f3cf0e85a6f8163802f4ea28eeb1ebbd 100644 (file)
@@ -43,6 +43,15 @@ if (${EXT_CER_ID})
        target_compile_definitions(${PROJECT_NAME} PRIVATE EXT_CER_ID=${EXT_CER_ID})
 endif(${EXT_CER_ID})
 
+if(${UBUS})
+       target_compile_definitions(${PROJECT_NAME} PRIVATE WITH_UBUS)
+       target_sources(${PROJECT_NAME} PRIVATE src/ubus.c)
+       find_path(ubus_include_dir libubus.h)
+       target_include_directories(${PROJECT_NAME} PRIVATE ${ubus_include_dir})
+       find_library(libubus ubus)
+       target_link_libraries(${PROJECT_NAME} PRIVATE ${libubus})
+endif(${UBUS})
+
 
 # Installation
 install(TARGETS ${PROJECT_NAME} DESTINATION sbin/)
index 807f2a4379c17b646506c088914c773a80bcbbe1..a100c00164d6a6759dc63d822242d4f625fc4407 100755 (executable)
@@ -27,6 +27,7 @@ DEPSDIR="${BUILDDIR}/depends"
 cd "${DEPSDIR}"
 [ -e "json-c" ] || git clone https://github.com/json-c/json-c.git
 [ -e "libubox" ] || git clone https://github.com/openwrt/libubox.git
+[ -e "ubus" ] || git clone https://github.com/openwrt/ubus.git
 
 # Build json-c
 cd "${DEPSDIR}/json-c"
@@ -52,12 +53,25 @@ cmake                                                       \
 make
 make install
 
+# Build ubus
+cd "${DEPSDIR}/ubus"
+cmake                                                  \
+       -S .                                            \
+       -B .                                            \
+       -DCMAKE_PREFIX_PATH="${BUILDDIR}"               \
+       -DBUILD_LUA=OFF                                 \
+       -DBUILD_EXAMPLES=OFF                            \
+       --install-prefix "${BUILDDIR}"
+make
+make install
+
 # Build odhcp6c
 cd "${ODHCP6CDIR}"
 cmake                                                  \
        -S .                                            \
        -B "${BUILDDIR}"                                \
        -DCMAKE_PREFIX_PATH="${BUILDDIR}"               \
+       -DUBUS=ON                                       \
        ${BUILD_ARGS}
 make -C "${BUILDDIR}"
 
index ee8d96a468fd43dc872b31f225101d2243815d06..8ffae84666a2587ae3e86141195cd977cf422bc8 100644 (file)
@@ -37,6 +37,7 @@
 
 #include "odhcp6c.h"
 #include "ra.h"
+#include "ubus.h"
 
 #ifndef IN6_IS_ADDR_UNIQUELOCAL
 #define IN6_IS_ADDR_UNIQUELOCAL(a) \
@@ -489,6 +490,24 @@ int main(_unused int argc, char* const argv[])
        fds[nfds].events = POLLIN;
        nfds++;
 
+#ifdef WITH_UBUS
+       char *err = ubus_init(ifname);
+       if (err) {
+               syslog(LOG_ERR, "ubus error: %s", err);
+               return 1;
+       }
+
+       struct ubus_context *ubus = ubus_get_ctx();
+       int ubus_socket = ubus->sock.fd;
+       if (ubus_socket < 0) {
+               syslog(LOG_ERR, "Invalid ubus file descriptor");
+               return 1;
+       }
+       fds[nfds].fd = ubus_socket;
+       fds[nfds].events = POLLIN;
+       nfds++;
+#endif /* WITH_UBUS */
+
        script_call("started", 0, false);
 
        while (!terminate) { // Main logic
@@ -715,9 +734,18 @@ int main(_unused int argc, char* const argv[])
                if (fds[0].revents & POLLIN)
                        dhcpv6_receive_response(msg_type);
 
+#ifdef WITH_UBUS
+               if (fds[1].revents & POLLIN)
+                       ubus_handle_event(ubus);
+#endif /* WITH_UBUS */
        }
+
        script_call("stopped", 0, true);
 
+#ifdef WITH_UBUS
+       ubus_destroy(ubus);
+#endif /* WITH_UBUS */
+
        return 0;
 }
 
diff --git a/src/ubus.c b/src/ubus.c
new file mode 100644 (file)
index 0000000..b380aa2
--- /dev/null
@@ -0,0 +1,139 @@
+/****************************************************************************
+**
+** SPDX-License-Identifier: BSD-2-Clause-Patent
+**
+** SPDX-FileCopyrightText: Copyright (c) 2024 SoftAtHome
+**
+** Redistribution and use in source and binary forms, with or
+** without modification, are permitted provided that the following
+** conditions are met:
+**
+** 1. Redistributions of source code must retain the above copyright
+** notice, this list of conditions and the following disclaimer.
+**
+** 2. Redistributions in binary form must reproduce the above
+** copyright notice, this list of conditions and the following
+** disclaimer in the documentation and/or other materials provided
+** with the distribution.
+**
+** Subject to the terms and conditions of this license, each
+** copyright holder and contributor hereby grants to those receiving
+** rights under this license a perpetual, worldwide, non-exclusive,
+** no-charge, royalty-free, irrevocable (except for failure to
+** satisfy the conditions of this license) patent license to make,
+** have made, use, offer to sell, sell, import, and otherwise
+** transfer this software, where such license applies only to those
+** patent claims, already acquired or hereafter acquired, licensable
+** by such copyright holder or contributor that are necessarily
+** infringed by:
+**
+** (a) their Contribution(s) (the licensed copyrights of copyright
+** holders and non-copyrightable additions of contributors, in
+** source or binary form) alone; or
+**
+** (b) combination of their Contribution(s) with the work of
+** authorship to which such Contribution(s) was added by such
+** copyright holder or contributor, if, at the time the Contribution
+** is added, such addition causes such combination to be necessarily
+** infringed. The patent license shall not apply to any other
+** combinations which include the Contribution.
+**
+** Except as expressly stated above, no rights or licenses from any
+** copyright holder or contributor is granted under this license,
+** whether expressly, by implication, estoppel or otherwise.
+**
+** DISCLAIMER
+**
+** THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND
+** CONTRIBUTORS "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES,
+** INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF
+** MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
+** DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDERS OR
+** CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
+** SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
+** LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF
+** USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED
+** AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
+** LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN
+** ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
+** POSSIBILITY OF SUCH DAMAGE.
+**
+****************************************************************************/
+#include "odhcp6c.h"
+
+
+#include <sys/types.h>
+#include <arpa/inet.h>
+#include <resolv.h>
+#include <stdio.h>
+#include <syslog.h>
+#include <inttypes.h>
+#include <libubox/blobmsg.h>
+
+#include "ubus.h"
+
+struct ubus_context *ubus = NULL;
+static char ubus_name[24];
+
+static int ubus_handle_get_state(struct ubus_context *ctx, struct ubus_object *obj,
+               struct ubus_request_data *req, const char *method, struct blob_attr *msg);
+
+static struct ubus_object_type odhcp6c_object_type = {
+       .name = "odhcp6c"
+};
+
+static struct ubus_object odhcp6c_object = {
+       .name = NULL,
+       .type = &odhcp6c_object_type,
+       .methods = odhcp6c_object_methods,
+       .n_methods = ARRAY_SIZE(odhcp6c_object_methods),
+};
+
+static void ubus_disconnect_cb(struct ubus_context *ubus)
+{
+       int ret;
+
+       ret = ubus_reconnect(ubus, NULL);
+       if (ret) {
+               syslog(LOG_ERR, "Cannot reconnect to ubus: %s", ubus_strerror(ret));
+               ubus_destroy(ubus);
+       }
+}
+
+char *ubus_init(const char* interface) 
+{
+       int ret = 0;
+
+       if (!(ubus = ubus_connect(NULL)))
+               return NULL;
+
+       snprintf(ubus_name, 24, "odhcp6c.%s", interface);
+       odhcp6c_object.name = ubus_name;
+       
+       ret = ubus_add_object(ubus, &odhcp6c_object);
+       if (ret) {
+               ubus_destroy(ubus);
+               return (char *)ubus_strerror(ret);
+       }
+
+       ubus->connection_lost = ubus_disconnect_cb;
+       return NULL;
+}
+
+struct ubus_context *ubus_get_ctx(void)
+{
+       return ubus;
+}
+
+void ubus_destroy(struct ubus_context *ubus)
+{
+       syslog(LOG_NOTICE, "Disconnecting from ubus");
+       
+       if (ubus != NULL)
+               ubus_free(ubus);
+       ubus = NULL;
+
+       /* Forces re-initialization when we're reusing the same definitions later on. */
+       odhcp6c_object.id = 0;
+       odhcp6c_object.id = 0;
+}
diff --git a/src/ubus.h b/src/ubus.h
new file mode 100644 (file)
index 0000000..855770e
--- /dev/null
@@ -0,0 +1,74 @@
+/****************************************************************************
+**
+** SPDX-License-Identifier: BSD-2-Clause-Patent
+**
+** SPDX-FileCopyrightText: Copyright (c) 2024 SoftAtHome
+**
+** Redistribution and use in source and binary forms, with or
+** without modification, are permitted provided that the following
+** conditions are met:
+**
+** 1. Redistributions of source code must retain the above copyright
+** notice, this list of conditions and the following disclaimer.
+**
+** 2. Redistributions in binary form must reproduce the above
+** copyright notice, this list of conditions and the following
+** disclaimer in the documentation and/or other materials provided
+** with the distribution.
+**
+** Subject to the terms and conditions of this license, each
+** copyright holder and contributor hereby grants to those receiving
+** rights under this license a perpetual, worldwide, non-exclusive,
+** no-charge, royalty-free, irrevocable (except for failure to
+** satisfy the conditions of this license) patent license to make,
+** have made, use, offer to sell, sell, import, and otherwise
+** transfer this software, where such license applies only to those
+** patent claims, already acquired or hereafter acquired, licensable
+** by such copyright holder or contributor that are necessarily
+** infringed by:
+**
+** (a) their Contribution(s) (the licensed copyrights of copyright
+** holders and non-copyrightable additions of contributors, in
+** source or binary form) alone; or
+**
+** (b) combination of their Contribution(s) with the work of
+** authorship to which such Contribution(s) was added by such
+** copyright holder or contributor, if, at the time the Contribution
+** is added, such addition causes such combination to be necessarily
+** infringed. The patent license shall not apply to any other
+** combinations which include the Contribution.
+**
+** Except as expressly stated above, no rights or licenses from any
+** copyright holder or contributor is granted under this license,
+** whether expressly, by implication, estoppel or otherwise.
+**
+** DISCLAIMER
+**
+** THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND
+** CONTRIBUTORS "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES,
+** INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF
+** MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
+** DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDERS OR
+** CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
+** SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
+** LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF
+** USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED
+** AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
+** LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN
+** ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
+** POSSIBILITY OF SUCH DAMAGE.
+**
+****************************************************************************/
+
+#ifndef _UBUS_H_
+#define _UBUS_H_
+
+#ifdef WITH_UBUS
+#include <libubus.h>
+#endif /* WITH_UBUS */
+
+char *ubus_init(const char* interface);
+struct ubus_context *ubus_get_ctx(void);
+void ubus_destroy(struct ubus_context *ubus); 
+
+#endif /* _UBUS_H_ */