dhcpv6: refactor u8 and u16 to u32 to avoid boolean coercion
authorPaul Donald <[email protected]>
Mon, 10 Nov 2025 17:26:16 +0000 (18:26 +0100)
committerÁlvaro Fernández Rojas <[email protected]>
Tue, 11 Nov 2025 07:22:58 +0000 (08:22 +0100)
ubus coerces u8 to boolean, and one workaround suitable is to amend u8
values (despite them being and containing only a u8 int) to u32 values. ubus
coerces u8 to booleans due to historical reasons. Any calls to e.g.

ubus call odhcp6c.eth1 get_state

(and subsequently downstream dependencies which use this invocation)

return booleans(!) where there shall be a number.

Amended calls to blobmsg_add_u8 into blobmsg_add_u32 to resolve this.
Amended calls to blobmsg_add_u16 into blobmsg_add_u32 also.

Apparently u8 and u16 get padded to u32 anyway.

See @nbd168 https://github.com/openwrt/libubox/pull/25#issuecomment-3512957433
"
I'd prefer to just deprecate treating u8 as integer and deprecate using u16 in
blobmsg entirely. That way we can avoid a lot of compatibility mess and JSON
conversion issues. Due to padding, u8, u16 and u32 attributes have the same
effective size anyway, so there isn't really a good reason to use them for
integer values.
"

Signed-off-by: Paul Donald <[email protected]>
Link: https://github.com/openwrt/odhcp6c/pull/117
Signed-off-by: Álvaro Fernández Rojas <[email protected]>
src/ubus.c

index 8aa790a543047a598e0b80297c282dbac3ee2a76..4e127ca5c63672d446a3320a202489f2ea6dee90 100644 (file)
@@ -321,7 +321,7 @@ static int entry_to_blob(const char *name, const void *data, size_t len, enum en
                blobmsg_add_string_buffer(&b);
 
                if (type != ENTRY_HOST) {
-                       blobmsg_add_u8(&b, "length", e[i].length);
+                       blobmsg_add_u32(&b, "length", e[i].length);
                        if (type == ENTRY_ROUTE) {
                                if (!IN6_IS_ADDR_UNSPECIFIED(&e[i].router)) {
                                        buf = blobmsg_alloc_string_buffer(&b, "router", INET6_ADDRSTRLEN);
@@ -331,7 +331,7 @@ static int entry_to_blob(const char *name, const void *data, size_t len, enum en
                                }
 
                                blobmsg_add_u32(&b, "valid", e[i].valid);
-                               blobmsg_add_u16(&b, "priority", e[i].priority);
+                               blobmsg_add_u32(&b, "priority", e[i].priority);
                        } else {
                                blobmsg_add_u32(&b, "valid", e[i].valid);
                                blobmsg_add_u32(&b, "preferred", e[i].preferred);
@@ -349,7 +349,7 @@ static int entry_to_blob(const char *name, const void *data, size_t len, enum en
                                CHECK_ALLOC(buf);
                                inet_ntop(AF_INET6, &e[i].router, buf, INET6_ADDRSTRLEN);
                                blobmsg_add_string_buffer(&b);
-                               blobmsg_add_u16(&b, "excluded_length", e[i].priority);
+                               blobmsg_add_u32(&b, "excluded_length", e[i].priority);
                        }
                }
 
@@ -392,9 +392,9 @@ static int s46_to_blob_portparams(const uint8_t *data, size_t len)
                if (otype == DHCPV6_OPT_S46_PORTPARAMS &&
                                olen == sizeof(struct dhcpv6_s46_portparams)) {
                        struct dhcpv6_s46_portparams *params = (void*)odata;
-                       blobmsg_add_u8(&b, "offset", params->offset);
-                       blobmsg_add_u8(&b, "psidlen", params->psid_len);
-                       blobmsg_add_u16(&b, "psid", ntohs(params->psid));
+                       blobmsg_add_u32(&b, "offset", params->offset);
+                       blobmsg_add_u32(&b, "psidlen", params->psid_len);
+                       blobmsg_add_u32(&b, "psid", ntohs(params->psid));
                }
        }
        return UBUS_STATUS_OK;
@@ -446,11 +446,11 @@ static int s46_to_blob(enum odhcp6c_state state, const uint8_t *data, size_t len
                        inet_ntop(AF_INET6, &in6, buf, INET6_ADDRSTRLEN);
                        blobmsg_add_string_buffer(&b);
 
-                       blobmsg_add_u8(&b, "fmr", rule->flags);
+                       blobmsg_add_u32(&b, "fmr", rule->flags);
                        blobmsg_add_string(&b, "type", type);
-                       blobmsg_add_u8(&b, "ealen", rule->ea_len);
-                       blobmsg_add_u8(&b, "prefix4len", rule->prefix4_len);
-                       blobmsg_add_u8(&b, "prefix6len", rule->prefix6_len);
+                       blobmsg_add_u32(&b, "ealen", rule->ea_len);
+                       blobmsg_add_u32(&b, "prefix4len", rule->prefix4_len);
+                       blobmsg_add_u32(&b, "prefix6len", rule->prefix6_len);
 
                        s46_to_blob_portparams(&rule->ipv6_prefix[prefix6len],
                                        olen - sizeof(*rule) - prefix6len);
@@ -477,7 +477,7 @@ static int s46_to_blob(enum odhcp6c_state state, const uint8_t *data, size_t len
                                        CHECK_ALLOC(buf);
                                        inet_ntop(AF_INET6, &in6, buf, INET6_ADDRSTRLEN);
                                        blobmsg_add_string_buffer(&b);
-                                       blobmsg_add_u8(&b, "dmrprefix6len", dmr->dmr_prefix6_len);
+                                       blobmsg_add_u32(&b, "dmrprefix6len", dmr->dmr_prefix6_len);
                                }
                        }
                } else if (state == STATE_S46_LW && otype == DHCPV6_OPT_S46_V4V6BIND &&
@@ -504,8 +504,8 @@ static int s46_to_blob(enum odhcp6c_state state, const uint8_t *data, size_t len
                        blobmsg_add_string_buffer(&b);
 
                        blobmsg_add_string(&b, "type", type);
-                       blobmsg_add_u8(&b, "prefix4len", 32);
-                       blobmsg_add_u8(&b, "prefix6len", bind->bindprefix6_len);
+                       blobmsg_add_u32(&b, "prefix4len", 32);
+                       blobmsg_add_u32(&b, "prefix6len", bind->bindprefix6_len);
 
                        s46_to_blob_portparams(&bind->bind_ipv6_prefix[prefix6len],
                                        olen - sizeof(*bind) - prefix6len);