dhcpv4: use iovec for NTP
authorDavid Härdeman <[email protected]>
Mon, 6 Oct 2025 10:23:18 +0000 (12:23 +0200)
committerÁlvaro Fernández Rojas <[email protected]>
Tue, 21 Oct 2025 17:05:02 +0000 (19:05 +0200)
Note that the previous code would send out several NTP options if
the client requested the option more than once, and would also send
out zero-sized options (against RFC2132, §8.3).

Signed-off-by: David Härdeman <[email protected]>
Link: https://github.com/openwrt/odhcpd/pull/278
Signed-off-by: Álvaro Fernández Rojas <[email protected]>
src/dhcpv4.c
src/dhcpv4.h

index 7201c4a6ea9607c1cb450674de94f6ab8774ebaf..62f68538bab2bc995ea1d71b22e0525f960eb2d6 100644 (file)
@@ -621,6 +621,8 @@ enum {
        IOV_HEADER = 0,
        IOV_MESSAGE,
        IOV_SERVERID,
+       IOV_NTP,
+       IOV_NTP_ADDR,
        IOV_END,
        IOV_TOTAL
 };
@@ -664,13 +666,19 @@ void dhcpv4_handle_msg(void *src_addr, void *data, size_t len,
                .len = sizeof(struct in_addr),
                .data = iface->dhcpv4_local.s_addr,
        };
+       struct dhcpv4_option reply_ntp = {
+               .code = DHCPV4_OPT_NTPSERVER,
+               .len = iface->dhcpv4_ntp_cnt * sizeof(*iface->dhcpv4_ntp),
+       };
        uint8_t reply_end = DHCPV4_OPT_END;
 
        struct iovec iov[IOV_TOTAL] = {
-               [IOV_HEADER] = { &reply, 0 },
-               [IOV_MESSAGE] = { &reply_msg, sizeof(reply_msg) },
-               [IOV_SERVERID] = { &reply_serverid, sizeof(reply_serverid) },
-               [IOV_END] = { &reply_end, sizeof(reply_end) },
+               [IOV_HEADER]    = { &reply, 0 },
+               [IOV_MESSAGE]   = { &reply_msg, sizeof(reply_msg) },
+               [IOV_SERVERID]  = { &reply_serverid, sizeof(reply_serverid) },
+               [IOV_NTP]       = { &reply_ntp, 0 },
+               [IOV_NTP_ADDR]  = { iface->dhcpv4_ntp, 0 },
+               [IOV_END]       = { &reply_end, sizeof(reply_end) },
        };
 
        /* Misc */
@@ -905,8 +913,10 @@ void dhcpv4_handle_msg(void *src_addr, void *data, size_t len,
        for (size_t opt = 0; a && opt < req_opts_len; opt++) {
                switch (req_opts[opt]) {
                case DHCPV4_OPT_NTPSERVER:
-                       dhcpv4_put(&reply, &cursor, DHCPV4_OPT_NTPSERVER,
-                                  4 * iface->dhcpv4_ntp_cnt, iface->dhcpv4_ntp);
+                       if (!a)
+                               break;
+                       iov[IOV_NTP].iov_len = sizeof(reply_ntp);
+                       iov[IOV_NTP_ADDR].iov_len = iface->dhcpv4_ntp_cnt * sizeof(*iface->dhcpv4_ntp);
                        break;
 
                case DHCPV4_OPT_DNR:
index f96e5bf4169e362223062a74586ce00bf22e8f23..089a626ee04956308ce0e8037da6aa831076afc7 100644 (file)
@@ -151,7 +151,7 @@ struct dhcpv4_option_u32 {
        uint8_t code;
        uint8_t len;
        uint32_t data;
-};
+} _packed;
 
 /* DNR */
 struct dhcpv4_dnr {