84ac7bea360cd369df26910e9685a7eed2327088Lennart Poettering This file is part of systemd.
84ac7bea360cd369df26910e9685a7eed2327088Lennart Poettering Copyright (C) 2014-2015 Intel Corporation. All rights reserved.
84ac7bea360cd369df26910e9685a7eed2327088Lennart Poettering systemd is free software; you can redistribute it and/or modify it
84ac7bea360cd369df26910e9685a7eed2327088Lennart Poettering under the terms of the GNU Lesser General Public License as published by
84ac7bea360cd369df26910e9685a7eed2327088Lennart Poettering the Free Software Foundation; either version 2.1 of the License, or
84ac7bea360cd369df26910e9685a7eed2327088Lennart Poettering (at your option) any later version.
84ac7bea360cd369df26910e9685a7eed2327088Lennart Poettering systemd is distributed in the hope that it will be useful, but
84ac7bea360cd369df26910e9685a7eed2327088Lennart Poettering WITHOUT ANY WARRANTY; without even the implied warranty of
84ac7bea360cd369df26910e9685a7eed2327088Lennart Poettering MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
84ac7bea360cd369df26910e9685a7eed2327088Lennart Poettering Lesser General Public License for more details.
84ac7bea360cd369df26910e9685a7eed2327088Lennart Poettering You should have received a copy of the GNU Lesser General Public License
84ac7bea360cd369df26910e9685a7eed2327088Lennart Poettering along with systemd; If not, see <http://www.gnu.org/licenses/>.
84ac7bea360cd369df26910e9685a7eed2327088Lennart Poetteringstatic int option_append_hdr(uint8_t **buf, size_t *buflen, uint16_t optcode,
84ac7bea360cd369df26910e9685a7eed2327088Lennart Poettering DHCP6Option *option = (DHCP6Option*) *buf;
93de9eb76d628cf731120d97332e03600c167271Filipe Brandenburger if (optlen > 0xffff || *buflen < optlen + sizeof(DHCP6Option))
b85e1c2534ca3b396c2aaa7de384995b42d12e1bFilipe Brandenburgerint dhcp6_option_append(uint8_t **buf, size_t *buflen, uint16_t code,
b85e1c2534ca3b396c2aaa7de384995b42d12e1bFilipe Brandenburger assert_return(optval || optlen == 0, -EINVAL);
93de9eb76d628cf731120d97332e03600c167271Filipe Brandenburger r = option_append_hdr(buf, buflen, code, optlen);
b85e1c2534ca3b396c2aaa7de384995b42d12e1bFilipe Brandenburgerint dhcp6_option_append_ia(uint8_t **buf, size_t *buflen, DHCP6IA *ia) {
84ac7bea360cd369df26910e9685a7eed2327088Lennart Poettering assert_return(buf && *buf && buflen && ia, -EINVAL);
3ff13c298d6d53293680c383768c3054fb9fcc30Filipe Brandenburger LIST_FOREACH(addresses, addr, ia->addresses) {
3ff13c298d6d53293680c383768c3054fb9fcc30Filipe Brandenburger r = option_append_hdr(buf, buflen, SD_DHCP6_OPTION_IAADDR,
84ac7bea360cd369df26910e9685a7eed2327088Lennart Poettering memcpy(*buf, &addr->iaaddr, sizeof(addr->iaaddr));
84ac7bea360cd369df26910e9685a7eed2327088Lennart Poettering ia_addrlen += sizeof(DHCP6Option) + sizeof(addr->iaaddr);
27fc921b658adc5baa988c4c213888b016a60b18Filipe Brandenburger r = option_append_hdr(&ia_hdr, &ia_buflen, ia->type, len + ia_addrlen);
27fc921b658adc5baa988c4c213888b016a60b18Filipe Brandenburgerstatic int option_parse_hdr(uint8_t **buf, size_t *buflen, uint16_t *optcode, size_t *optlen) {
27fc921b658adc5baa988c4c213888b016a60b18Filipe Brandenburger DHCP6Option *option = (DHCP6Option*) *buf;
0247447e96f1385cf0c48e3e6b696214fbe36802Filipe Brandenburgerint dhcp6_option_parse(uint8_t **buf, size_t *buflen, uint16_t *optcode,
0247447e96f1385cf0c48e3e6b696214fbe36802Filipe Brandenburger assert_return(buf && buflen && optcode && optlen && optvalue, -EINVAL);
0247447e96f1385cf0c48e3e6b696214fbe36802Filipe Brandenburger r = option_parse_hdr(buf, buflen, optcode, optlen);
84ac7bea360cd369df26910e9685a7eed2327088Lennart Poetteringint dhcp6_option_parse_ia(uint8_t **buf, size_t *buflen, uint16_t iatype,
84ac7bea360cd369df26910e9685a7eed2327088Lennart Poettering uint32_t lt_t1, lt_t2, lt_valid, lt_pref, lt_min = ~0;
84ac7bea360cd369df26910e9685a7eed2327088Lennart Poettering if (*buflen < DHCP6_OPTION_IA_NA_LEN + sizeof(DHCP6Option) +
dea7b6b043f0cd9e34ee719b9b612c3a4776387eLennart Poettering log_dhcp6_client(client, "IA T1 %ds > T2 %ds",
dea7b6b043f0cd9e34ee719b9b612c3a4776387eLennart Poettering if (*buflen < DHCP6_OPTION_IA_TA_LEN + sizeof(DHCP6Option) +
84ac7bea360cd369df26910e9685a7eed2327088Lennart Poettering while ((r = option_parse_hdr(buf, buflen, &opt, &optlen)) >= 0) {
84ac7bea360cd369df26910e9685a7eed2327088Lennart Poettering memcpy(&addr->iaaddr, *buf, sizeof(addr->iaaddr));
84ac7bea360cd369df26910e9685a7eed2327088Lennart Poettering lt_valid = be32toh(addr->iaaddr.lifetime_valid);
84ac7bea360cd369df26910e9685a7eed2327088Lennart Poettering lt_pref = be32toh(addr->iaaddr.lifetime_valid);
84ac7bea360cd369df26910e9685a7eed2327088Lennart Poettering log_dhcp6_client(client, "IA preferred %ds > valid %ds",
84ac7bea360cd369df26910e9685a7eed2327088Lennart Poettering LIST_PREPEND(addresses, ia->addresses, addr);
84ac7bea360cd369df26910e9685a7eed2327088Lennart Poettering log_dhcp6_client(client, "Unknown IA option %d", opt);
if (r == -ENOMSG)
if (*buflen)
r = -ENOMSG;
*buflen = 0;
return -EINVAL;
return -ENOMEM;
return count;
uint8_t c;
pos += c;
return -EMSGSIZE;
r = -ENOMEM;
goto fail;
if (first)
first = false;
goto fail;
r = -EBADMSG;
goto fail;
r = -ENOMEM;
goto fail;
ret[n] = 0;
goto fail;
idx++;
return idx;
fail: