dhcpv6: potential bug fix for checking DHCPV6_OPT_STATUS
authorPaul Donald <[email protected]>
Tue, 4 Nov 2025 18:30:58 +0000 (19:30 +0100)
committerÁlvaro Fernández Rojas <[email protected]>
Wed, 5 Nov 2025 07:12:13 +0000 (08:12 +0100)
follow-up to b65ff293a96924f9b19dff8855232bfb9054b976

The previous logic checked that the DHCPV6_OPT_STATUS was more than 2 bytes,
which meant that it would only be evaluated if the options *also* contained a
status message. We should handle this option being exactly 2 bytes, so that
DHCPV6_OPT_STATUS lacking a status message are correctly handled.

The relevant RFC section does not state that status message can be absent
https://www.rfc-editor.org/rfc/rfc8415#section-21.13
but the status message field is variable length and sets no mandates on its
size.

This ensures differing interpretations of this portion are handled adequately.
It's not uncommon that various options behave in this 'can be zero length' way,
so let's handle this option similarly.

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

index 9c424ff0e9db8aab992f24d91bf30cff31a0f973..6aed871d4fb73eb3c729a50c6b3438e3ce818ea4 100644 (file)
@@ -1626,13 +1626,13 @@ static unsigned int dhcpv6_parse_ia(void *opt, void *end, int *ret)
                        bool update_state = true;
                        dhcpv6_for_each_option(odata + sizeof(*prefix) - 4U,
                                        odata + olen, stype, slen, sdata) {
-                               if (stype == DHCPV6_OPT_STATUS && slen > 2) {
+                               if (stype == DHCPV6_OPT_STATUS && slen >= 2) {
                                        /* RFC 8415 §21.22
                                        The status of any operations involving this IA Prefix option is
                                        indicated in a Status Code option (see Section 21.13) in the
                                        IAprefix-options field. */
-                                       uint8_t *status_msg = &sdata[2];
-                                       uint16_t msg_len = slen - 2;
+                                       uint8_t *status_msg = (slen > 2) ? &sdata[2] : NULL;
+                                       uint16_t msg_len = (slen > 2) ? slen - 2 : 0;
                                        uint16_t code = ((int)sdata[0]) << 8 | ((int)sdata[1]);
 
                                        if (code == DHCPV6_Success)
@@ -1709,13 +1709,13 @@ static unsigned int dhcpv6_parse_ia(void *opt, void *end, int *ret)
                        bool update_state = true;
                        dhcpv6_for_each_option(odata + sizeof(*addr) - 4U,
                                        odata + olen, stype, slen, sdata) {
-                               if (stype == DHCPV6_OPT_STATUS && slen > 2) {
+                               if (stype == DHCPV6_OPT_STATUS && slen >= 2) {
                                        /* RFC 8415 §21.6
                                        The status of any operations involving this IA Address is indicated
                                        in a Status Code option in the IAaddr-options field, as specified in
                                        Section 21.13. */
-                                       uint8_t *status_msg = &sdata[2];
-                                       uint16_t msg_len = slen - 2;
+                                       uint8_t *status_msg = (slen > 2) ? &sdata[2] : NULL;
+                                       uint16_t msg_len = (slen > 2) ? slen - 2 : 0;
                                        uint16_t code = ((int)sdata[0]) << 8 | ((int)sdata[1]);
 
                                        if (code == DHCPV6_Success)