X-Git-Url: http://www.chiark.greenend.org.uk/ucgi/~ianmdlvl/git?a=blobdiff_plain;f=src%2Flibsystemd-network%2Fdhcp6-option.c;fp=src%2Flibsystemd-network%2Fdhcp6-option.c;h=0000000000000000000000000000000000000000;hb=e418908760d8b7826017b07b2a5d2e365152e7ae;hp=ea863f45e4ea13a400461949a62cbce71c913379;hpb=a2109619cd5c28c4739e659e40b6b524c7c0d488;p=elogind.git diff --git a/src/libsystemd-network/dhcp6-option.c b/src/libsystemd-network/dhcp6-option.c deleted file mode 100644 index ea863f45e..000000000 --- a/src/libsystemd-network/dhcp6-option.c +++ /dev/null @@ -1,319 +0,0 @@ -/*-*- Mode: C; c-basic-offset: 8; indent-tabs-mode: nil -*-*/ - -/*** - This file is part of systemd. - - Copyright (C) 2014 Intel Corporation. All rights reserved. - - systemd is free software; you can redistribute it and/or modify it - under the terms of the GNU Lesser General Public License as published by - the Free Software Foundation; either version 2.1 of the License, or - (at your option) any later version. - - systemd is distributed in the hope that it will be useful, but - WITHOUT ANY WARRANTY; without even the implied warranty of - MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU - Lesser General Public License for more details. - - You should have received a copy of the GNU Lesser General Public License - along with systemd; If not, see . -***/ - -#include -#include -#include - -#include "sparse-endian.h" -#include "unaligned.h" -#include "util.h" - -#include "dhcp6-internal.h" -#include "dhcp6-protocol.h" - -#define DHCP6_OPTION_IA_NA_LEN 12 -#define DHCP6_OPTION_IA_TA_LEN 4 - -typedef struct DHCP6Option { - be16_t code; - be16_t len; - uint8_t data[]; -} _packed_ DHCP6Option; - -static int option_append_hdr(uint8_t **buf, size_t *buflen, uint16_t optcode, - size_t optlen) { - DHCP6Option *option = (DHCP6Option*) *buf; - - assert_return(buf, -EINVAL); - assert_return(*buf, -EINVAL); - assert_return(buflen, -EINVAL); - - if (optlen > 0xffff || *buflen < optlen + sizeof(DHCP6Option)) - return -ENOBUFS; - - option->code = htobe16(optcode); - option->len = htobe16(optlen); - - *buf += sizeof(DHCP6Option); - *buflen -= sizeof(DHCP6Option); - - return 0; -} - -int dhcp6_option_append(uint8_t **buf, size_t *buflen, uint16_t code, - size_t optlen, const void *optval) { - int r; - - assert_return(optval || optlen == 0, -EINVAL); - - r = option_append_hdr(buf, buflen, code, optlen); - if (r < 0) - return r; - - if (optval) - memcpy(*buf, optval, optlen); - - *buf += optlen; - *buflen -= optlen; - - return 0; -} - -int dhcp6_option_append_ia(uint8_t **buf, size_t *buflen, DHCP6IA *ia) { - uint16_t len; - uint8_t *ia_hdr; - size_t ia_buflen, ia_addrlen = 0; - DHCP6Address *addr; - int r; - - assert_return(buf && *buf && buflen && ia, -EINVAL); - - switch (ia->type) { - case DHCP6_OPTION_IA_NA: - len = DHCP6_OPTION_IA_NA_LEN; - break; - - case DHCP6_OPTION_IA_TA: - len = DHCP6_OPTION_IA_TA_LEN; - break; - - default: - return -EINVAL; - } - - if (*buflen < len) - return -ENOBUFS; - - ia_hdr = *buf; - ia_buflen = *buflen; - - *buf += sizeof(DHCP6Option); - *buflen -= sizeof(DHCP6Option); - - memcpy(*buf, &ia->id, len); - - *buf += len; - *buflen -= len; - - LIST_FOREACH(addresses, addr, ia->addresses) { - r = option_append_hdr(buf, buflen, DHCP6_OPTION_IAADDR, - sizeof(addr->iaaddr)); - if (r < 0) - return r; - - memcpy(*buf, &addr->iaaddr, sizeof(addr->iaaddr)); - - *buf += sizeof(addr->iaaddr); - *buflen -= sizeof(addr->iaaddr); - - ia_addrlen += sizeof(DHCP6Option) + sizeof(addr->iaaddr); - } - - r = option_append_hdr(&ia_hdr, &ia_buflen, ia->type, len + ia_addrlen); - if (r < 0) - return r; - - return 0; -} - - -static int option_parse_hdr(uint8_t **buf, size_t *buflen, uint16_t *optcode, size_t *optlen) { - DHCP6Option *option = (DHCP6Option*) *buf; - uint16_t len; - - assert_return(buf, -EINVAL); - assert_return(optcode, -EINVAL); - assert_return(optlen, -EINVAL); - - if (*buflen < sizeof(DHCP6Option)) - return -ENOMSG; - - len = be16toh(option->len); - - if (len > *buflen) - return -ENOMSG; - - *optcode = be16toh(option->code); - *optlen = len; - - *buf += 4; - *buflen -= 4; - - return 0; -} - -int dhcp6_option_parse(uint8_t **buf, size_t *buflen, uint16_t *optcode, - size_t *optlen, uint8_t **optvalue) { - int r; - - assert_return(buf && buflen && optcode && optlen && optvalue, -EINVAL); - - r = option_parse_hdr(buf, buflen, optcode, optlen); - if (r < 0) - return r; - - if (*optlen > *buflen) - return -ENOBUFS; - - *optvalue = *buf; - *buflen -= *optlen; - *buf += *optlen; - - return 0; -} - -int dhcp6_option_parse_ia(uint8_t **buf, size_t *buflen, uint16_t iatype, - DHCP6IA *ia) { - int r; - uint16_t opt, status; - size_t optlen; - size_t iaaddr_offset; - DHCP6Address *addr; - uint32_t lt_t1, lt_t2, lt_valid, lt_pref, lt_min = ~0; - - assert_return(ia, -EINVAL); - assert_return(!ia->addresses, -EINVAL); - - switch (iatype) { - case DHCP6_OPTION_IA_NA: - - if (*buflen < DHCP6_OPTION_IA_NA_LEN + sizeof(DHCP6Option) + - sizeof(addr->iaaddr)) { - r = -ENOBUFS; - goto error; - } - - iaaddr_offset = DHCP6_OPTION_IA_NA_LEN; - memcpy(&ia->id, *buf, iaaddr_offset); - - lt_t1 = be32toh(ia->lifetime_t1); - lt_t2 = be32toh(ia->lifetime_t2); - - if (lt_t1 && lt_t2 && lt_t1 > lt_t2) { - log_dhcp6_client(client, "IA T1 %ds > T2 %ds", - lt_t1, lt_t2); - r = -EINVAL; - goto error; - } - - break; - - case DHCP6_OPTION_IA_TA: - if (*buflen < DHCP6_OPTION_IA_TA_LEN + sizeof(DHCP6Option) + - sizeof(addr->iaaddr)) { - r = -ENOBUFS; - goto error; - } - - iaaddr_offset = DHCP6_OPTION_IA_TA_LEN; - memcpy(&ia->id, *buf, iaaddr_offset); - - ia->lifetime_t1 = 0; - ia->lifetime_t2 = 0; - - break; - - default: - r = -ENOMSG; - goto error; - } - - ia->type = iatype; - - *buflen -= iaaddr_offset; - *buf += iaaddr_offset; - - while ((r = option_parse_hdr(buf, buflen, &opt, &optlen)) >= 0) { - - switch (opt) { - case DHCP6_OPTION_IAADDR: - - addr = new0(DHCP6Address, 1); - if (!addr) { - r = -ENOMEM; - goto error; - } - - LIST_INIT(addresses, addr); - - memcpy(&addr->iaaddr, *buf, sizeof(addr->iaaddr)); - - lt_valid = be32toh(addr->iaaddr.lifetime_valid); - lt_pref = be32toh(addr->iaaddr.lifetime_valid); - - if (!lt_valid || lt_pref > lt_valid) { - log_dhcp6_client(client, "IA preferred %ds > valid %ds", - lt_pref, lt_valid); - free(addr); - } else { - LIST_PREPEND(addresses, ia->addresses, addr); - if (lt_valid < lt_min) - lt_min = lt_valid; - } - - break; - - case DHCP6_OPTION_STATUS_CODE: - if (optlen < sizeof(status)) - break; - - status = (*buf)[0] << 8 | (*buf)[1]; - if (status) { - log_dhcp6_client(client, "IA status %d", - status); - r = -EINVAL; - goto error; - } - - break; - - default: - log_dhcp6_client(client, "Unknown IA option %d", opt); - break; - } - - *buflen -= optlen; - *buf += optlen; - } - - if (r == -ENOMSG) - r = 0; - - if (!ia->lifetime_t1 && !ia->lifetime_t2) { - lt_t1 = lt_min / 2; - lt_t2 = lt_min / 10 * 8; - ia->lifetime_t1 = htobe32(lt_t1); - ia->lifetime_t2 = htobe32(lt_t2); - - log_dhcp6_client(client, "Computed IA T1 %ds and T2 %ds as both were zero", - lt_t1, lt_t2); - } - - if (*buflen) - r = -ENOMSG; - -error: - *buf += *buflen; - *buflen = 0; - - return r; -}