]> git.ipfire.org Git - thirdparty/systemd.git/commitdiff
sd-dhcp6-client: unify IA option header
authorYu Watanabe <watanabe.yu+github@gmail.com>
Sun, 6 Feb 2022 04:38:08 +0000 (13:38 +0900)
committerYu Watanabe <watanabe.yu+github@gmail.com>
Mon, 14 Feb 2022 05:43:45 +0000 (14:43 +0900)
This also fixes possible unaligned read of message.

src/libsystemd-network/dhcp6-internal.h
src/libsystemd-network/dhcp6-option.c
src/libsystemd-network/sd-dhcp6-client.c
src/libsystemd-network/sd-dhcp6-lease.c
src/libsystemd-network/test-dhcp6-client.c

index f9434098566aae57bdcf8518a2c2c0953a25f129..7ceb3a8b28137c254e7fdf9b4be455c2e0072db1 100644 (file)
@@ -62,32 +62,15 @@ struct DHCP6Address {
         };
 };
 
-/* Non-temporary Address option */
-struct ia_na {
+struct ia_header {
         be32_t id;
         be32_t lifetime_t1;
         be32_t lifetime_t2;
 } _packed_;
 
-/* Prefix Delegation option */
-struct ia_pd {
-        be32_t id;
-        be32_t lifetime_t1;
-        be32_t lifetime_t2;
-} _packed_;
-
-/* Temporary Address option */
-struct ia_ta {
-        be32_t id;
-} _packed_;
-
 typedef struct DHCP6IA {
         uint16_t type;
-        union {
-                struct ia_na ia_na;
-                struct ia_pd ia_pd;
-                struct ia_ta ia_ta;
-        };
+        struct ia_header header;
 
         LIST_HEAD(DHCP6Address, addresses);
 } DHCP6IA;
index 2ba6bd2aaa8302ebdac9e064e8ed28b80bdd41b8..e7a55c1b0226951a203a1ccaaeca522529e73a6a 100644 (file)
@@ -284,12 +284,10 @@ int dhcp6_option_append_vendor_option(uint8_t **buf, size_t *buflen, OrderedHash
 
 int dhcp6_option_append_ia(uint8_t **buf, size_t *buflen, const DHCP6IA *ia) {
         size_t ia_buflen, ia_addrlen = 0;
-        struct ia_na ia_na;
-        struct ia_ta ia_ta;
+        struct ia_header header;
         DHCP6Address *addr;
         uint8_t *ia_hdr;
         uint16_t len;
-        void *p;
         int r;
 
         assert_return(buf, -EINVAL);
@@ -301,19 +299,17 @@ int dhcp6_option_append_ia(uint8_t **buf, size_t *buflen, const DHCP6IA *ia) {
 
         switch (ia->type) {
         case SD_DHCP6_OPTION_IA_NA:
-                len = DHCP6_OPTION_IA_NA_LEN;
-                ia_na = (struct ia_na) {
-                        .id = ia->ia_na.id,
+                len = sizeof(struct ia_header);
+                header = (struct ia_header) {
+                        .id = ia->header.id,
                 };
-                p = &ia_na;
                 break;
 
         case SD_DHCP6_OPTION_IA_TA:
-                len = DHCP6_OPTION_IA_TA_LEN;
-                ia_ta = (struct ia_ta) {
-                        .id = ia->ia_ta.id,
+                len = sizeof(be32_t); /* IA_TA does not have lifetime. */
+                header = (struct ia_header) {
+                        .id = ia->header.id,
                 };
-                p = &ia_ta;
                 break;
 
         default:
@@ -329,7 +325,7 @@ int dhcp6_option_append_ia(uint8_t **buf, size_t *buflen, const DHCP6IA *ia) {
         *buf += offsetof(DHCP6Option, data);
         *buflen -= offsetof(DHCP6Option, data);
 
-        memcpy(*buf, p, len);
+        memcpy(*buf, &header, len);
 
         *buf += len;
         *buflen -= len;
@@ -386,7 +382,7 @@ static int option_append_pd_prefix(uint8_t **buf, size_t *buflen, const DHCP6Add
 }
 
 int dhcp6_option_append_pd(uint8_t **buf, size_t *buflen, const DHCP6IA *pd, const DHCP6Address *hint_pd_prefix) {
-        struct ia_pd ia_pd;
+        struct ia_header header;
         size_t len, pd_buflen;
         uint8_t *pd_hdr;
         int r;
@@ -398,10 +394,10 @@ int dhcp6_option_append_pd(uint8_t **buf, size_t *buflen, const DHCP6IA *pd, con
         assert_return(pd->type == SD_DHCP6_OPTION_IA_PD, -EINVAL);
 
         /* Do not set T1 and T2. */
-        ia_pd = (struct ia_pd) {
-                .id = pd->ia_pd.id,
+        len = sizeof(struct ia_header);
+        header = (struct ia_header) {
+                .id = pd->header.id,
         };
-        len = sizeof(struct ia_pd);
 
         if (*buflen < offsetof(DHCP6Option, data) + len)
                 return -ENOBUFS;
@@ -413,10 +409,9 @@ int dhcp6_option_append_pd(uint8_t **buf, size_t *buflen, const DHCP6IA *pd, con
         *buf += offsetof(DHCP6Option, data);
         *buflen -= offsetof(DHCP6Option, data);
 
-        memcpy(*buf, &ia_pd, len);
-
-        *buf += sizeof(struct ia_pd);
-        *buflen -= sizeof(struct ia_pd);
+        memcpy(*buf, &header, len);
+        *buf += len;
+        *buflen -= len;
 
         DHCP6Address *prefix;
         LIST_FOREACH(addresses, prefix, pd->addresses) {
@@ -601,7 +596,7 @@ int dhcp6_option_parse_status(const uint8_t *data, size_t data_len, char **ret_s
 static int dhcp6_option_parse_ia_options(sd_dhcp6_client *client, const uint8_t *buf, size_t buflen) {
         int r;
 
-        assert(buf);
+        assert(buf || buflen == 0);
 
         for(size_t offset = 0; offset < buflen;) {
                 const uint8_t *data;
@@ -619,15 +614,15 @@ static int dhcp6_option_parse_ia_options(sd_dhcp6_client *client, const uint8_t
                         r = dhcp6_option_parse_status(data, data_len, &msg);
                         if (r == -ENOMEM)
                                 return r;
-                        if (r < 0)
-                                /* Let's log but ignore the invalid status option. */
-                                log_dhcp6_client_errno(client, r,
-                                                       "Received an IA address or PD prefix option with an invalid status sub option, ignoring: %m");
-                        else if (r > 0)
+                        if (r > 0)
                                 return log_dhcp6_client_errno(client, SYNTHETIC_ERRNO(EINVAL),
                                                               "Received an IA address or PD prefix option with non-zero status: %s%s%s",
                                                               strempty(msg), isempty(msg) ? "" : ": ",
                                                               dhcp6_message_status_to_string(r));
+                        if (r < 0)
+                                /* Let's log but ignore the invalid status option. */
+                                log_dhcp6_client_errno(client, r,
+                                                       "Received an IA address or PD prefix option with an invalid status sub option, ignoring: %m");
                         break;
                 }
                 default:
@@ -638,19 +633,29 @@ static int dhcp6_option_parse_ia_options(sd_dhcp6_client *client, const uint8_t
         return 0;
 }
 
-static int dhcp6_option_parse_ia_address(sd_dhcp6_client *client, const uint8_t *data, size_t len, DHCP6Address **ret) {
+static int dhcp6_option_parse_ia_address(sd_dhcp6_client *client, DHCP6IA *ia, const uint8_t *data, size_t len) {
+        _cleanup_free_ DHCP6Address *a = NULL;
         uint32_t lt_valid, lt_pref;
-        DHCP6Address *a;
         int r;
 
-        assert(data);
-        assert(ret);
+        assert(ia);
+        assert(data || len == 0);
+
+        if (!IN_SET(ia->type, SD_DHCP6_OPTION_IA_NA, SD_DHCP6_OPTION_IA_TA))
+                return log_dhcp6_client_errno(client, SYNTHETIC_ERRNO(EINVAL),
+                                              "Received an IA address sub-option in an invalid option, ignoring.");
 
         if (len < sizeof(struct iaaddr))
                 return -EBADMSG;
 
-        lt_valid = be32toh(((const struct iaaddr*) data)->lifetime_valid);
-        lt_pref = be32toh(((const struct iaaddr*) data)->lifetime_preferred);
+        a = new(DHCP6Address, 1);
+        if (!a)
+                return -ENOMEM;
+
+        memcpy(&a->iaaddr, data, sizeof(struct iaaddr));
+
+        lt_valid = be32toh(a->iaaddr.lifetime_valid);
+        lt_pref = be32toh(a->iaaddr.lifetime_preferred);
 
         if (lt_valid == 0)
                 return log_dhcp6_client_errno(client, SYNTHETIC_ERRNO(EINVAL),
@@ -667,27 +672,33 @@ static int dhcp6_option_parse_ia_address(sd_dhcp6_client *client, const uint8_t
                         return r;
         }
 
-        a = new(DHCP6Address, 1);
-        if (!a)
-                return -ENOMEM;
-
-        LIST_INIT(addresses, a);
-        memcpy(&a->iaaddr, data, sizeof(struct iaaddr));
-
-        *ret = a;
+        LIST_PREPEND(addresses, ia->addresses, TAKE_PTR(a));
         return 0;
 }
 
-static int dhcp6_option_parse_ia_pdprefix(sd_dhcp6_client *client, const uint8_t *data, size_t len, DHCP6Address **ret) {
+static int dhcp6_option_parse_ia_pdprefix(sd_dhcp6_client *client, DHCP6IA *ia, const uint8_t *data, size_t len) {
+        _cleanup_free_ DHCP6Address *a = NULL;
         uint32_t lt_valid, lt_pref;
-        DHCP6Address *a;
         int r;
 
+        assert(ia);
+        assert(data || len == 0);
+
+        if (ia->type != SD_DHCP6_OPTION_IA_PD)
+                return log_dhcp6_client_errno(client, SYNTHETIC_ERRNO(EINVAL),
+                                              "Received an PD prefix sub-option in an invalid option, ignoring");
+
         if (len < sizeof(struct iapdprefix))
-                return -ENOMSG;
+                return -EBADMSG;
+
+        a = new(DHCP6Address, 1);
+        if (!a)
+                return -ENOMEM;
+
+        memcpy(&a->iapdprefix, data, sizeof(struct iapdprefix));
 
-        lt_valid = be32toh(((const struct iapdprefix*) data)->lifetime_valid);
-        lt_pref = be32toh(((const struct iapdprefix*) data)->lifetime_preferred);
+        lt_valid = be32toh(a->iapdprefix.lifetime_valid);
+        lt_pref = be32toh(a->iapdprefix.lifetime_preferred);
 
         if (lt_valid == 0)
                 return log_dhcp6_client_errno(client, SYNTHETIC_ERRNO(EINVAL),
@@ -704,14 +715,7 @@ static int dhcp6_option_parse_ia_pdprefix(sd_dhcp6_client *client, const uint8_t
                         return r;
         }
 
-        a = new(DHCP6Address, 1);
-        if (!a)
-                return -ENOMEM;
-
-        LIST_INIT(addresses, a);
-        memcpy(&a->iapdprefix, data, sizeof(struct iapdprefix));
-
-        *ret = a;
+        LIST_PREPEND(addresses, ia->addresses, TAKE_PTR(a));
         return 0;
 }
 
@@ -725,12 +729,11 @@ int dhcp6_option_parse_ia(
 
         _cleanup_(dhcp6_lease_free_ia) DHCP6IA ia = {};
         uint32_t lt_t1, lt_t2, lt_min = UINT32_MAX;
-        be32_t received_iaid;
-        size_t offset;
+        size_t header_len;
         int r;
 
         assert(IN_SET(option_code, SD_DHCP6_OPTION_IA_NA, SD_DHCP6_OPTION_IA_TA, SD_DHCP6_OPTION_IA_PD));
-        assert(option_data);
+        assert(option_data || option_data_len == 0);
         assert(ret);
 
         /* This will return the following:
@@ -743,56 +746,45 @@ int dhcp6_option_parse_ia(
 
         switch (option_code) {
         case SD_DHCP6_OPTION_IA_NA:
-
-                if (option_data_len < DHCP6_OPTION_IA_NA_LEN)
-                        return -EBADMSG;
-
-                offset = DHCP6_OPTION_IA_NA_LEN;
-
-                received_iaid = ((const struct ia_na*) option_data)->id;
-                lt_t1 = be32toh(((const struct ia_na*) option_data)->lifetime_t1);
-                lt_t2 = be32toh(((const struct ia_na*) option_data)->lifetime_t2);
-                break;
-
         case SD_DHCP6_OPTION_IA_PD:
-
-                if (option_data_len < DHCP6_OPTION_IA_PD_LEN)
-                        return -EBADMSG;
-
-                offset = DHCP6_OPTION_IA_PD_LEN;
-
-                received_iaid = ((const struct ia_pd*) option_data)->id;
-                lt_t1 = be32toh(((const struct ia_pd*) option_data)->lifetime_t1);
-                lt_t2 = be32toh(((const struct ia_pd*) option_data)->lifetime_t2);
+                header_len = sizeof(struct ia_header);
                 break;
 
         case SD_DHCP6_OPTION_IA_TA:
-                if (option_data_len < DHCP6_OPTION_IA_TA_LEN)
-                        return -ENOMSG;
-
-                offset = DHCP6_OPTION_IA_TA_LEN;
-
-                received_iaid = ((const struct ia_ta*) option_data)->id;
-                lt_t1 = lt_t2 = 0; /* No lifetime for IA_TA. */
+                header_len = sizeof(be32_t); /* IA_TA does not have lifetime. */
                 break;
 
         default:
                 assert_not_reached();
         }
 
+        if (option_data_len < header_len)
+                return -EBADMSG;
+
+        ia.type = option_code;
+        memcpy(&ia.header, option_data, header_len);
+
         /* According to RFC8415, IAs which do not match the client's IAID should be ignored,
          * but not necessary to ignore or refuse the whole message. */
-        if (received_iaid != iaid)
+        if (ia.header.id != iaid)
                 return log_dhcp6_client_errno(client, SYNTHETIC_ERRNO(ENOANO),
                                               "Received an IA option with a different IAID "
                                               "from the one chosen by the client, ignoring.");
 
+        /* It is not necessary to check if the lifetime_t2 is zero here, as in that case it will be updated later. */
+        lt_t1 = be32toh(ia.header.lifetime_t1);
+        lt_t2 = be32toh(ia.header.lifetime_t2);
+
         if (lt_t1 > lt_t2)
                 return log_dhcp6_client_errno(client, SYNTHETIC_ERRNO(EINVAL),
                                               "Received an IA option with T1 %"PRIu32"sec > T2 %"PRIu32"sec, ignoring.",
                                               lt_t1, lt_t2);
+        if (lt_t1 == 0 && lt_t2 > 0)
+                return log_dhcp6_client_errno(client, SYNTHETIC_ERRNO(EINVAL),
+                                              "Received an IA option with zero T1 and non-zero T2 (%"PRIu32"sec), ignoring.",
+                                              lt_t2);
 
-        for (; offset < option_data_len;) {
+        for (size_t offset = header_len; offset < option_data_len;) {
                 const uint8_t *subdata;
                 size_t subdata_len;
                 uint16_t subopt;
@@ -803,41 +795,25 @@ int dhcp6_option_parse_ia(
 
                 switch (subopt) {
                 case SD_DHCP6_OPTION_IAADDR: {
-                        DHCP6Address *a;
-
-                        if (!IN_SET(option_code, SD_DHCP6_OPTION_IA_NA, SD_DHCP6_OPTION_IA_TA)) {
-                                log_dhcp6_client(client, "Received an IA_PD option with an IA address, ignoring.");
-                                continue;
-                        }
-
-                        r = dhcp6_option_parse_ia_address(client, subdata, subdata_len, &a);
+                        r = dhcp6_option_parse_ia_address(client, &ia, subdata, subdata_len);
                         if (r == -ENOMEM)
                                 return r;
                         if (r < 0)
-                                /* Ignore the sub-option on non-critical errors. */
+                                /* Ignore non-critical errors in the sub-option. */
                                 continue;
 
-                        lt_min = MIN(lt_min, be32toh(a->iaaddr.lifetime_valid));
-                        LIST_PREPEND(addresses, ia.addresses, a);
+                        lt_min = MIN(lt_min, be32toh(ia.addresses->iaaddr.lifetime_valid));
                         break;
                 }
                 case SD_DHCP6_OPTION_IA_PD_PREFIX: {
-                        DHCP6Address *a;
-
-                        if (option_code != SD_DHCP6_OPTION_IA_PD) {
-                                log_dhcp6_client(client, "Received an IA_NA or IA_TA option with an PD prefix, ignoring");
-                                continue;
-                        }
-
-                        r = dhcp6_option_parse_ia_pdprefix(client, subdata, subdata_len, &a);
+                        r = dhcp6_option_parse_ia_pdprefix(client, &ia, subdata, subdata_len);
                         if (r == -ENOMEM)
                                 return r;
                         if (r < 0)
-                                /* Ignore the sub-option on non-critical errors. */
+                                /* Ignore non-critical errors in the sub-option. */
                                 continue;
 
-                        lt_min = MIN(lt_min, be32toh(a->iapdprefix.lifetime_valid));
-                        LIST_PREPEND(addresses, ia.addresses, a);
+                        lt_min = MIN(lt_min, be32toh(ia.addresses->iapdprefix.lifetime_valid));
                         break;
                 }
                 case SD_DHCP6_OPTION_STATUS_CODE: {
@@ -846,14 +822,14 @@ int dhcp6_option_parse_ia(
                         r = dhcp6_option_parse_status(subdata, subdata_len, &msg);
                         if (r == -ENOMEM)
                                 return r;
-                        if (r < 0)
-                                log_dhcp6_client_errno(client, r,
-                                                       "Received an IA option with an invalid status sub option, ignoring: %m");
-                        else if (r > 0)
+                        if (r > 0)
                                 return log_dhcp6_client_errno(client, SYNTHETIC_ERRNO(EINVAL),
                                                               "Received an IA option with non-zero status: %s%s%s",
                                                               strempty(msg), isempty(msg) ? "" : ": ",
                                                               dhcp6_message_status_to_string(r));
+                        if (r < 0)
+                                log_dhcp6_client_errno(client, r,
+                                                       "Received an IA option with an invalid status sub option, ignoring: %m");
                         break;
                 }
                 default:
@@ -865,46 +841,24 @@ int dhcp6_option_parse_ia(
                 return log_dhcp6_client_errno(client, SYNTHETIC_ERRNO(ENODATA),
                                               "Received an IA option without valid IA addresses or PD prefixes, ignoring.");
 
-        if (IN_SET(option_code, SD_DHCP6_OPTION_IA_NA, SD_DHCP6_OPTION_IA_PD) &&
-            lt_t1 == 0 && lt_t2 == 0 && lt_min != UINT32_MAX) {
+        if (lt_t2 == 0 && IN_SET(option_code, SD_DHCP6_OPTION_IA_NA, SD_DHCP6_OPTION_IA_PD)) {
+
+                /* addresses or prefixes with zero valid lifetime are already ignored. */
+                assert(lt_min != UINT32_MAX);
+
                 lt_t1 = lt_min / 2;
                 lt_t2 = lt_min / 10 * 8;
 
+                ia.header.lifetime_t1 = htobe32(lt_t1);
+                ia.header.lifetime_t1 = htobe32(lt_t2);
+
                 log_dhcp6_client(client, "Received an IA option with both T1 and T2 equal to zero. "
                                  "Adjusting them based on the minimum valid lifetime of IA addresses or PD prefixes: "
                                  "T1=%"PRIu32"sec, T2=%"PRIu32"sec", lt_t1, lt_t2);
         }
 
-        switch(option_code) {
-        case SD_DHCP6_OPTION_IA_NA:
-                *ret = (DHCP6IA) {
-                        .type = option_code,
-                        .ia_na.id = iaid,
-                        .ia_na.lifetime_t1 = htobe32(lt_t1),
-                        .ia_na.lifetime_t2 = htobe32(lt_t2),
-                        .addresses = TAKE_PTR(ia.addresses),
-                };
-                break;
-        case SD_DHCP6_OPTION_IA_TA:
-                *ret = (DHCP6IA) {
-                        .type = option_code,
-                        .ia_ta.id = iaid,
-                        .addresses = TAKE_PTR(ia.addresses),
-                };
-                break;
-        case SD_DHCP6_OPTION_IA_PD:
-                *ret = (DHCP6IA) {
-                        .type = option_code,
-                        .ia_pd.id = iaid,
-                        .ia_pd.lifetime_t1 = htobe32(lt_t1),
-                        .ia_pd.lifetime_t2 = htobe32(lt_t2),
-                        .addresses = TAKE_PTR(ia.addresses),
-                };
-                break;
-        default:
-                assert_not_reached();
-        }
-
+        *ret = ia;
+        ret->addresses = TAKE_PTR(ia.addresses);
         return 0;
 }
 
index eb3b0037221ca44323fb0c7dbd6feed3a2be8397..65b8cce16574fa74ff1df0bf17ba5823a0b9d045 100644 (file)
@@ -421,8 +421,8 @@ int sd_dhcp6_client_set_iaid(sd_dhcp6_client *client, uint32_t iaid) {
         assert_return(client, -EINVAL);
         assert_return(client->state == DHCP6_STATE_STOPPED, -EBUSY);
 
-        client->ia_na.ia_na.id = htobe32(iaid);
-        client->ia_pd.ia_pd.id = htobe32(iaid);
+        client->ia_na.header.id = htobe32(iaid);
+        client->ia_pd.header.id = htobe32(iaid);
         client->iaid_set = true;
 
         return 0;
@@ -441,7 +441,7 @@ int sd_dhcp6_client_get_iaid(sd_dhcp6_client *client, uint32_t *iaid) {
         if (!client->iaid_set)
                 return -ENODATA;
 
-        *iaid = be32toh(client->ia_na.ia_na.id);
+        *iaid = be32toh(client->ia_na.header.id);
 
         return 0;
 }
@@ -1065,8 +1065,8 @@ static int client_ensure_iaid(sd_dhcp6_client *client) {
         if (r < 0)
                 return r;
 
-        client->ia_na.ia_na.id = iaid;
-        client->ia_pd.ia_pd.id = iaid;
+        client->ia_na.header.id = iaid;
+        client->ia_pd.header.id = iaid;
         client->iaid_set = true;
 
         return 0;
@@ -1153,7 +1153,7 @@ int client_parse_message(
                                 break;
                         }
 
-                        r = dhcp6_option_parse_ia(client, client->ia_na.ia_na.id, optcode, optlen, optval, &ia);
+                        r = dhcp6_option_parse_ia(client, client->ia_na.header.id, optcode, optlen, optval, &ia);
                         if (r == -ENOMEM)
                                 return r;
                         if (r < 0)
@@ -1167,8 +1167,8 @@ int client_parse_message(
                         lease->ia_na = ia;
                         ia = (DHCP6IA) {};
 
-                        lt_t1 = MIN(lt_t1, be32toh(lease->ia_na.ia_na.lifetime_t1));
-                        lt_t2 = MIN(lt_t2, be32toh(lease->ia_na.ia_na.lifetime_t2));
+                        lt_t1 = MIN(lt_t1, be32toh(lease->ia_na.header.lifetime_t1));
+                        lt_t2 = MIN(lt_t2, be32toh(lease->ia_na.header.lifetime_t2));
 
                         break;
                 }
@@ -1180,7 +1180,7 @@ int client_parse_message(
                                 break;
                         }
 
-                        r = dhcp6_option_parse_ia(client, client->ia_pd.ia_pd.id, optcode, optlen, optval, &ia);
+                        r = dhcp6_option_parse_ia(client, client->ia_pd.header.id, optcode, optlen, optval, &ia);
                         if (r == -ENOMEM)
                                 return r;
                         if (r < 0)
@@ -1194,8 +1194,8 @@ int client_parse_message(
                         lease->ia_pd = ia;
                         ia = (DHCP6IA) {};
 
-                        lt_t1 = MIN(lt_t1, be32toh(lease->ia_pd.ia_pd.lifetime_t1));
-                        lt_t2 = MIN(lt_t2, be32toh(lease->ia_pd.ia_pd.lifetime_t2));
+                        lt_t1 = MIN(lt_t1, be32toh(lease->ia_pd.header.lifetime_t1));
+                        lt_t2 = MIN(lt_t2, be32toh(lease->ia_pd.header.lifetime_t2));
 
                         break;
                 }
@@ -1271,13 +1271,13 @@ int client_parse_message(
                         return log_dhcp6_client_errno(client, SYNTHETIC_ERRNO(EINVAL), "No IA_PD prefix or IA_NA address received. Ignoring.");
 
                 if (lease->ia_na.addresses) {
-                        lease->ia_na.ia_na.lifetime_t1 = htobe32(lt_t1);
-                        lease->ia_na.ia_na.lifetime_t2 = htobe32(lt_t2);
+                        lease->ia_na.header.lifetime_t1 = htobe32(lt_t1);
+                        lease->ia_na.header.lifetime_t2 = htobe32(lt_t2);
                 }
 
                 if (lease->ia_pd.addresses) {
-                        lease->ia_pd.ia_pd.lifetime_t1 = htobe32(lt_t1);
-                        lease->ia_pd.ia_pd.lifetime_t2 = htobe32(lt_t2);
+                        lease->ia_pd.header.lifetime_t1 = htobe32(lt_t1);
+                        lease->ia_pd.header.lifetime_t2 = htobe32(lt_t2);
                 }
         }
 
@@ -1545,15 +1545,15 @@ static int client_get_lifetime(sd_dhcp6_client *client, uint32_t *lifetime_t1,
         assert_return(client->lease, -EINVAL);
 
         if (FLAGS_SET(client->request_ia, DHCP6_REQUEST_IA_NA) && client->lease->ia_na.addresses) {
-                *lifetime_t1 = be32toh(client->lease->ia_na.ia_na.lifetime_t1);
-                *lifetime_t2 = be32toh(client->lease->ia_na.ia_na.lifetime_t2);
+                *lifetime_t1 = be32toh(client->lease->ia_na.header.lifetime_t1);
+                *lifetime_t2 = be32toh(client->lease->ia_na.header.lifetime_t2);
 
                 return 0;
         }
 
         if (FLAGS_SET(client->request_ia, DHCP6_REQUEST_IA_PD) && client->lease->ia_pd.addresses) {
-                *lifetime_t1 = be32toh(client->lease->ia_pd.ia_pd.lifetime_t1);
-                *lifetime_t2 = be32toh(client->lease->ia_pd.ia_pd.lifetime_t2);
+                *lifetime_t1 = be32toh(client->lease->ia_pd.header.lifetime_t1);
+                *lifetime_t2 = be32toh(client->lease->ia_pd.header.lifetime_t2);
 
                 return 0;
         }
index 7d6a6f7f9cbb95fcd0ac213248fb977205f01b0a..96c32cf8f9762cc236efed0f22a024f8f0c1b733 100644 (file)
@@ -45,7 +45,7 @@ int dhcp6_lease_ia_rebind_expire(const DHCP6IA *ia, uint32_t *expire) {
                         valid = t;
         }
 
-        t = be32toh(ia->ia_na.lifetime_t2);
+        t = be32toh(ia->header.lifetime_t2);
         if (t > valid)
                 return -EINVAL;
 
index 274109d13a8ae4b83dfcee661149de5f1cc6c195..91eec940589b1d48696628ac280c7fce8bf52b9b 100644 (file)
@@ -351,9 +351,9 @@ static void test_option_status(void) {
         r = dhcp6_option_parse_ia(NULL, iaid, be16toh(option->code), be16toh(option->len), option->data, &pd);
         assert_se(r >= 0);
         assert_se(pd.addresses);
-        assert_se(memcmp(&pd.ia_pd.id, &option4[4], 4) == 0);
-        assert_se(memcmp(&pd.ia_pd.lifetime_t1, &option4[8], 4) == 0);
-        assert_se(memcmp(&pd.ia_pd.lifetime_t2, &option4[12], 4) == 0);
+        assert_se(memcmp(&pd.header.id, &option4[4], 4) == 0);
+        assert_se(memcmp(&pd.header.lifetime_t1, &option4[8], 4) == 0);
+        assert_se(memcmp(&pd.header.lifetime_t2, &option4[12], 4) == 0);
         dhcp6_lease_free_ia(&pd);
 
         zero(pd);