]> git.ipfire.org Git - thirdparty/dhcpcd.git/commitdiff
Add truncate to defintions
authorRoy Marples <roy@marples.name>
Thu, 12 Jun 2025 10:43:48 +0000 (11:43 +0100)
committerRoy Marples <roy@marples.name>
Mon, 16 Jun 2025 21:00:35 +0000 (22:00 +0100)
This indicates an option might be truncated from it's natural
length and will be zero padded on expansion.
Only supported for the ip6address option.

While here, support 1 as a bitflag to just print the bit.

Fixes #508.

src/dhcp-common.c
src/dhcp-common.h
src/dhcpcd-definitions-small.conf
src/dhcpcd-definitions.conf
src/dhcpcd.conf.5.in
src/if-options.c

index 8370addadc000b4922ce1f620fa6e4e8a1edf0fb..14d2d92a8f05d9d428aa141f3ed4a5290552e9eb 100644 (file)
@@ -135,6 +135,8 @@ dhcp_print_option_encoding(const struct dhcp_opt *opt, int cols)
                printf(" request");
        if (opt->type & OT_NOREQ)
                printf(" norequest");
+       if (opt->type & OT_TRUNCATED)
+               printf(" truncated");
        putchar('\n');
        fflush(stdout);
 }
@@ -614,6 +616,8 @@ dhcp_optlen(const struct dhcp_opt *opt, size_t dl)
                return (ssize_t)dl;
        }
        if (dl < sz) {
+               if (opt->type & OT_TRUNCATED)
+                       return (ssize_t)dl;
                errno = EOVERFLOW;
                return -1;
        }
@@ -751,6 +755,11 @@ print_option(FILE *fp, const char *prefix, const struct dhcp_opt *opt,
                    l < sizeof(opt->bitflags);
                    l++, sl--)
                {
+                       if (opt->bitflags[l] == '1') {
+                               if (fprintf(fp, "%d", *data & (1 << sl)) == -1)
+                                       goto err;
+                               continue;
+                       }
                        /* Don't print NULL or 0 flags */
                        if (opt->bitflags[l] != '\0' &&
                            opt->bitflags[l] != '0' &&
@@ -808,9 +817,14 @@ print_option(FILE *fp, const char *prefix, const struct dhcp_opt *opt,
                                goto err;
                        data += sizeof(addr.s_addr);
                } else if (opt->type & OT_ADDRIPV6) {
+                       uint8_t databuf[sizeof(struct in6_addr)] = { 0 };
+                       size_t datalen = e - data >= 16 ? 16 : (size_t)(e - data);
                        char buf[INET6_ADDRSTRLEN];
 
-                       if (inet_ntop(AF_INET6, data, buf, sizeof(buf)) == NULL)
+                       /* avoid inet_ntop going beyond our option space by
+                        * copying out into a temporary buffer. */
+                       memcpy(databuf, data, datalen);
+                       if (inet_ntop(AF_INET6, databuf, buf, sizeof(buf)) == NULL)
                                goto err;
                        if (fprintf(fp, "%s", buf) == -1)
                                goto err;
index 6a1800cf1b727086e83a0222fb62df0e047410ea..ecee7674c25036e91623cc476453f12ef77909ec 100644 (file)
@@ -76,6 +76,7 @@
 #define        OT_BITFLAG              (1 << 27)
 #define        OT_RESERVED             (1 << 28)
 #define        OT_URI                  (1 << 29)
+#define        OT_TRUNCATED            (1 << 30)
 
 #define        DHC_REQ(r, n, o) \
        (has_option_mask((r), (o)) && !has_option_mask((n), (o)))
index 4d39e2eb1a0b2dd5853e3f287141ad025f823f15..3e7091b0eea1d9370b5b6182a6b23c870609b33e 100644 (file)
@@ -71,10 +71,10 @@ embed               uint32                  mtu
 
 definend 24    index embed             route_information
 embed          byte                    length
-# bits 4 and 5 are route preference, but we can't express this
-embed          byte                    reserved
+# bits 4 and 5 are route preference
+embed          bitflags=00011          prf
 embed          uint32                  lifetime
-embed          ip6address              prefix
+embed          truncated ip6address    prefix
 
 # ND6 options, RFC6101
 definend 25    index embed             rdnss
index dc24533763f3dbbc5bf63953e67bb9426ef0229e..f73721148efe5f769fe2b3e643b04989efc45264 100644 (file)
@@ -414,10 +414,10 @@ embed             uint16                  lifetime
 
 definend 24    index embed             route_information
 embed          byte                    length
-# bits 4 and 5 are route preference, but we can't express this
-embed          byte                    reserved
+# bits 4 and 5 are route preference
+embed          bitflags=00011          prf
 embed          uint32                  lifetime
-embed          ip6address              prefix
+embed          truncated ip6address    prefix
 
 # ND6 options, RFC6101
 definend 25    index embed             rdnss
index 6b63c6f751e9ff1d9e015a70b0e0f29e7b52e418..179be73ee3df5b5532f504d7bf896a01674092fd 100644 (file)
@@ -24,7 +24,7 @@
 .\" OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
 .\" SUCH DAMAGE.
 .\"
-.Dd April 15, 2025
+.Dd June 12, 2025
 .Dt DHCPCD.CONF 5
 .Os
 .Sh NAME
@@ -957,6 +957,10 @@ The option can appear more than once and will be indexed.
 .It Ic array
 The option data is split into a space separated array, each element being
 the same type.
+.It Ic truncated
+The option might truncated from its normal length.
+The end of the normal size is zero padded on expansion.
+Currently this is only supported for ip6address where it's a prefix.
 .El
 .Ss Types to define
 The type directly affects the length of data consumed inside the option.
@@ -979,6 +983,7 @@ C 00100000, etc.
 If the bit is not set, the flag is not printed.
 A flag of 0 is not printed even if the bit position is set.
 This is to allow reservation of the first bits while assigning the last bits.
+A flag of 1 prints the bit set or unset.
 .It Ic int16
 A signed 16bit integer, 2 bytes.
 .It Ic uint16
index 1b256fa9afa17970381264632d4ba0ceaa2caaca..3cb89f35e651f4e7730d18d94cb2bb7f0571af38 100644 (file)
@@ -1995,6 +1995,15 @@ err_sla:
                                return -1;
                        }
                        *fp++ = '\0';
+               } else if (strcasecmp(arg, "truncated") == 0) {
+                       t |= OT_TRUNCATED;
+                       arg = strskipwhite(fp);
+                       fp = strwhite(arg);
+                       if (fp == NULL) {
+                               logerrx("incomplete truncated type");
+                               return -1;
+                       }
+                       *fp++ = '\0';
                }
                if (strcasecmp(arg, "ipaddress") == 0)
                        t |= OT_ADDRIPV4;
@@ -2084,6 +2093,10 @@ err_sla:
                                t |= OT_RESERVED;
                        }
                }
+               if (t & OT_TRUNCATED && t != (OT_ADDRIPV6 | OT_TRUNCATED)) {
+                       logerrx("truncated only works for ip6address");
+                       return -1;
+               }
                if (opt != O_EMBED) {
                        for (dl = 0, ndop = *dop; dl < *dop_len; dl++, ndop++)
                        {