dhcpv4: store reqopts as uint8_t
authorDavid Härdeman <[email protected]>
Sun, 11 Feb 2024 12:09:53 +0000 (13:09 +0100)
committerdedeckeh <[email protected]>
Sun, 29 Dec 2024 11:50:42 +0000 (12:50 +0100)
Storing request options as chars means that it's difficult to handle option
codes > 127 due to the signedness of char (and options aren't chars, they're
binary data).

Signed-off-by: David Härdeman <[email protected]>
src/dhcpv4.c
src/odhcpd.h
src/ubus.c

index cb0484f63dd896e7a08c06e0c16a76edf211f8f4..65a4b41c6d40b8c52781c5700decaf14316d515b 100644 (file)
@@ -22,6 +22,7 @@
 #include <stdlib.h>
 #include <resolv.h>
 #include <limits.h>
+#include <alloca.h>
 #include <net/if.h>
 #include <net/if_arp.h>
 #include <netinet/ip.h>
@@ -53,7 +54,7 @@ static struct dhcp_assignment* dhcpv4_lease(struct interface *iface,
                enum dhcpv4_msg msg, const uint8_t *mac, const uint32_t reqaddr,
                uint32_t *leasetime, const char *hostname, const size_t hostname_len,
                const bool accept_fr_nonce, bool *incl_fr_opt, uint32_t *fr_serverid,
-               const char *reqopts, const size_t reqopts_len);
+               const uint8_t *reqopts, const size_t reqopts_len);
 
 static struct netevent_handler dhcpv4_netevent_handler = { .cb = dhcpv4_netevent_cb, };
 static struct uloop_timeout valid_until_timeout = {.cb = valid_until_cb};
@@ -654,10 +655,10 @@ void dhcpv4_handle_msg(void *addr, void *data, size_t len,
 
        uint32_t reqaddr = INADDR_ANY;
        uint32_t leasetime = 0;
+       char hostname[256];
        size_t hostname_len = 0;
+       uint8_t *reqopts = NULL;
        size_t reqopts_len = 0;
-       char hostname[256];
-       char reqopts[256];
        bool accept_fr_nonce = false;
        bool incl_fr_opt = false;
 
@@ -669,8 +670,8 @@ void dhcpv4_handle_msg(void *addr, void *data, size_t len,
                        reqmsg = opt->data[0];
                else if (opt->type == DHCPV4_OPT_REQOPTS && opt->len > 0) {
                        reqopts_len = opt->len;
+                       reqopts = alloca(reqopts_len);
                        memcpy(reqopts, opt->data, reqopts_len);
-                       reqopts[reqopts_len] = 0;
                } else if (opt->type == DHCPV4_OPT_HOSTNAME && opt->len > 0) {
                        hostname_len = opt->len;
                        memcpy(hostname, opt->data, hostname_len);
@@ -850,8 +851,8 @@ void dhcpv4_handle_msg(void *addr, void *data, size_t len,
                dhcpv4_put(&reply, &cookie, DHCPV4_OPT_DNSSERVER,
                                4 * iface->dhcpv4_dns_cnt, iface->dhcpv4_dns);
 
-       if (a && a->reqopts && iface->dhcpv4_ntp_cnt != 0) {
-               for(size_t opts = 0; a->reqopts[opts]; opts++) {
+       if (a && iface->dhcpv4_ntp_cnt != 0) {
+               for (size_t opts = 0; opts < a->reqopts_len; opts++) {
                        if (a->reqopts[opts] == DHCPV4_OPT_NTPSERVER) {
                                dhcpv4_put(&reply, &cookie, DHCPV4_OPT_NTPSERVER,
                                                4 * iface->dhcpv4_ntp_cnt, iface->dhcpv4_ntp);
@@ -1035,7 +1036,7 @@ static struct dhcp_assignment*
 dhcpv4_lease(struct interface *iface, enum dhcpv4_msg msg, const uint8_t *mac,
             const uint32_t reqaddr, uint32_t *leasetime, const char *hostname,
             const size_t hostname_len, const bool accept_fr_nonce, bool *incl_fr_opt,
-            uint32_t *fr_serverid, const char* reqopts, const size_t reqopts_len)
+            uint32_t *fr_serverid, const uint8_t *reqopts, const size_t reqopts_len)
 {
        struct dhcp_assignment *a = find_assignment_by_hwaddr(iface, mac);
        struct lease *l = config_find_lease_by_mac(mac);
@@ -1127,10 +1128,10 @@ dhcpv4_lease(struct interface *iface, enum dhcpv4_msg msg, const uint8_t *mac,
                                }
 
                                if (reqopts_len > 0) {
-                                       a->reqopts = realloc(a->reqopts, reqopts_len + 1);
+                                       a->reqopts = realloc(a->reqopts, reqopts_len);
                                        if (a->reqopts) {
                                                memcpy(a->reqopts, reqopts, reqopts_len);
-                                               a->reqopts[reqopts_len] = 0;
+                                               a->reqopts_len = reqopts_len;
                                        }
                                }
 
index 7a82e9823edcebd72f0e3f2eced88ca1463b7780..156cec09214d6e4b37ba406046736e401c446736 100644 (file)
@@ -231,7 +231,9 @@ struct dhcp_assignment {
        unsigned int flags;
        uint32_t leasetime;
        char *hostname;
-       char *reqopts;
+       uint8_t *reqopts;
+       size_t reqopts_len;
+
 #define hwaddr         mac
        uint8_t mac[6];
 
index 45b29a4e6459d86d46a6d6f2cd7961ab552fcd51..be3deac4d338f2d4c1fe5b15945b2b3eb6e7d12b 100644 (file)
@@ -3,6 +3,7 @@
 #include <libubox/uloop.h>
 #include <netinet/in.h>
 #include <arpa/inet.h>
+#include <inttypes.h>
 
 #include <libubox/utils.h>
 
@@ -49,13 +50,11 @@ static int handle_dhcpv4_leases(struct ubus_context *ctx, _unused struct ubus_ob
                        blobmsg_add_string(&b, "hostname", (c->hostname) ? c->hostname : "");
                        blobmsg_add_u8(&b, "accept-reconf-nonce", c->accept_fr_nonce);
 
-                       if (c->reqopts) {
-                               int opt = 0;
-                               int chars = 0;
-                               buf = blobmsg_alloc_string_buffer(&b, "reqopts", strlen(c->reqopts) * 4 + 1);
-                               for(; c->reqopts[opt]; opt++)
-                                       chars += snprintf(buf + chars, 6, "%u,", (uint8_t)c->reqopts[opt]);
-                               buf[chars - 1] = '\0';
+                       if (c->reqopts_len > 0) {
+                               buf = blobmsg_alloc_string_buffer(&b, "reqopts", c->reqopts_len * 4 + 1);
+                               for (size_t i = 0; i < c->reqopts_len; i++)
+                                       buf += snprintf(buf, 5, "%" PRIu8 ",", c->reqopts[i]);
+                               buf[-1] = '\0';
                                blobmsg_add_string_buffer(&b);
                        }