diff options
author | Patrik Flykt <patrik.flykt@linux.intel.com> | 2018-01-04 15:11:42 +0200 |
---|---|---|
committer | Patrik Flykt <patrik.flykt@linux.intel.com> | 2018-01-04 15:22:43 +0200 |
commit | c6b4f32a507c5ad885265309b2ecb56e618564d5 (patch) | |
tree | d32cb199b81a63d999e8b6aba1cb63e71daa48c3 /src | |
parent | 3bc424a3cc0bacc688ec2f4f93a5560fb4ca393b (diff) | |
download | systemd-c6b4f32a507c5ad885265309b2ecb56e618564d5.tar.gz |
dhcp6: Add function for DHCPv6 Status option
Factor out code to parse a DHCPv6 Status option using a common
function.
Diffstat (limited to 'src')
-rw-r--r-- | src/libsystemd-network/dhcp6-internal.h | 1 | ||||
-rw-r--r-- | src/libsystemd-network/dhcp6-option.c | 25 | ||||
-rw-r--r-- | src/libsystemd-network/sd-dhcp6-client.c | 10 |
3 files changed, 26 insertions, 10 deletions
diff --git a/src/libsystemd-network/dhcp6-internal.h b/src/libsystemd-network/dhcp6-internal.h index 9e7d3976aa..982ce3608a 100644 --- a/src/libsystemd-network/dhcp6-internal.h +++ b/src/libsystemd-network/dhcp6-internal.h @@ -83,6 +83,7 @@ int dhcp6_option_append_ia(uint8_t **buf, size_t *buflen, DHCP6IA *ia); int dhcp6_option_append_fqdn(uint8_t **buf, size_t *buflen, const char *fqdn); int dhcp6_option_parse(uint8_t **buf, size_t *buflen, uint16_t *optcode, size_t *optlen, uint8_t **optvalue); +int dhcp6_option_parse_status(DHCP6Option *option); int dhcp6_option_parse_ia(DHCP6Option *iaoption, DHCP6IA *ia); int dhcp6_option_parse_ip6addrs(uint8_t *optval, uint16_t optlen, struct in6_addr **addrs, size_t count, diff --git a/src/libsystemd-network/dhcp6-option.c b/src/libsystemd-network/dhcp6-option.c index 80925b3948..b18a996d86 100644 --- a/src/libsystemd-network/dhcp6-option.c +++ b/src/libsystemd-network/dhcp6-option.c @@ -26,6 +26,7 @@ #include "alloc-util.h" #include "dhcp6-internal.h" +#include "dhcp6-lease-internal.h" #include "dhcp6-protocol.h" #include "dns-domain.h" #include "sparse-endian.h" @@ -33,6 +34,12 @@ #include "unaligned.h" #include "util.h" +typedef struct DHCP6StatusOption { + struct DHCP6Option option; + be16_t status; + char msg[]; +} _packed_ DHCP6StatusOption; + #define DHCP6_OPTION_IA_NA_LEN 12 #define DHCP6_OPTION_IA_TA_LEN 4 @@ -207,6 +214,15 @@ int dhcp6_option_parse(uint8_t **buf, size_t *buflen, uint16_t *optcode, return 0; } +int dhcp6_option_parse_status(DHCP6Option *option) { + DHCP6StatusOption *statusopt = (DHCP6StatusOption *)option; + + if (be16toh(option->len) + sizeof(DHCP6Option) < sizeof(*statusopt)) + return -ENOBUFS; + + return be16toh(statusopt->status); +} + int dhcp6_option_parse_ia(DHCP6Option *iaoption, DHCP6IA *ia) { uint16_t iatype, optlen; size_t i, len; @@ -302,15 +318,14 @@ int dhcp6_option_parse_ia(DHCP6Option *iaoption, DHCP6IA *ia) { break; case SD_DHCP6_OPTION_STATUS_CODE: - if (optlen < sizeof(status)) { - r = -ENOMSG; - goto error; - } - status = option->data[0] << 8 | option->data[1]; + status = dhcp6_option_parse_status(option); if (status) { log_dhcp6_client(client, "IA status %d", status); + + dhcp6_lease_free_ia(ia); + r = -EINVAL; goto error; } diff --git a/src/libsystemd-network/sd-dhcp6-client.c b/src/libsystemd-network/sd-dhcp6-client.c index 9c758a4d0b..3659356b56 100644 --- a/src/libsystemd-network/sd-dhcp6-client.c +++ b/src/libsystemd-network/sd-dhcp6-client.c @@ -740,7 +740,8 @@ static int client_parse_message( while (pos < len) { DHCP6Option *option = (DHCP6Option *)&message->options[pos]; - uint16_t optcode, optlen, status; + uint16_t optcode, optlen; + int status; uint8_t *optval; be32_t iaid_lease; @@ -795,14 +796,13 @@ static int client_parse_message( break; case SD_DHCP6_OPTION_STATUS_CODE: - if (optlen < 2) - return -EINVAL; - - status = optval[0] << 8 | optval[1]; + status = dhcp6_option_parse_status(option); if (status) { log_dhcp6_client(client, "%s Status %s", dhcp6_message_type_to_string(message->type), dhcp6_message_status_to_string(status)); + dhcp6_lease_free_ia(&lease->ia); + return -EINVAL; } |