Re: [systemd-devel] [PATCH v2 05/26] dhcp: Add option appending and parsing
Hi, On Tue, 2013-11-26 at 00:08 +0100, Lennart Poettering wrote: On Mon, 25.11.13 09:13, Patrik Flykt (patrik.fl...@linux.intel.com) wrote: +#include stdint.h + +#include protocol.h + +int dhcp_option_append(uint8_t **buf, int *buflen, uint8_t code, This is a memory size, right? It should be size_t rather than int, then, no? size_t it is. +static int parse_options(uint8_t *buf, int32_t buflen, int *overload, ^^ const missing? Here the idea was to go over the whole buffer and calling the callback with the proper code, len and value. Start of 'buf', i.e. 'code' in the function, needs to be advanced to the next option, so its not a const value. + int *message_type, dhcp_option_cb_t cb, + void *user_data) +{ +uint8_t *code = buf; +uint8_t *len; + +while (buflen 0) { +switch (*code) { +case DHCP_OPTION_PAD: +buflen -= 1; +code++; +break; + +case DHCP_OPTION_END: +return 0; + +case DHCP_OPTION_MESSAGE_TYPE: +buflen -= 3; +if (buflen 0) +return -ENOBUFS; + +len = code + 1; +if (*len != 1) +return -EINVAL; + +if (message_type) +*message_type = *(len + 1); Feels weird that message_type is an int, but you fill an uint8_t into it, no? +if (buflen 0) +return -EINVAL; + +if (cb) +cb(*code, *len, len + 1, user_data); I'd always be careful with callback functions like this, since people might alter the objects you rely on while you iterate through things and then you are seriously confused... I'd always do iterator-like interfaces instead. (Doesn't matter here though, as this is an internal interface only...) True. I'll take this as a warning for future code. +int dhcp_option_parse(DHCPMessage *message, int32_t len, Hmm, an int32_t length? Signed? And shouldn't it be size_t again? size_t. + dhcp_option_cb_t cb, void *user_data) +{ +int overload = 0; +int message_type = -ENOMSG; +uint8_t *opt = (uint8_t *)(message + 1); +int res; + +if (message == NULL || len 0) +return -EINVAL; + +len -= sizeof(DHCPMessage); +len -= 4; +if (len 0) +return -EINVAL; Wouldn't it be better to check len = sizeof(DHCPMessage) + 4 first? Sounds more logical than relying on a signed size... With the size_t changes, yes. Cheers, Patrik ___ systemd-devel mailing list systemd-devel@lists.freedesktop.org http://lists.freedesktop.org/mailman/listinfo/systemd-devel
Re: [systemd-devel] [PATCH v2 05/26] dhcp: Add option appending and parsing
On Wed, Nov 27, 2013 at 04:51:42PM +0200, Patrik Flykt wrote: On Tue, 2013-11-26 at 00:08 +0100, Lennart Poettering wrote: On Mon, 25.11.13 09:13, Patrik Flykt (patrik.fl...@linux.intel.com) wrote: +static int parse_options(uint8_t *buf, int32_t buflen, int *overload, ^^ const missing? Here the idea was to go over the whole buffer and calling the callback with the proper code, len and value. Start of 'buf', i.e. 'code' in the function, needs to be advanced to the next option, so its not a const value. It's the uint8_t's that are supposed to be const, not the pointer. I.e. 'const uint8_t *buf', not 'uint8_t* const buf'. Zbyszek ___ systemd-devel mailing list systemd-devel@lists.freedesktop.org http://lists.freedesktop.org/mailman/listinfo/systemd-devel
Re: [systemd-devel] [PATCH v2 05/26] dhcp: Add option appending and parsing
On Wed, 27.11.13 16:51, Patrik Flykt (patrik.fl...@linux.intel.com) wrote: On Tue, 2013-11-26 at 00:08 +0100, Lennart Poettering wrote: On Mon, 25.11.13 09:13, Patrik Flykt (patrik.fl...@linux.intel.com) wrote: +#include stdint.h + +#include protocol.h + +int dhcp_option_append(uint8_t **buf, int *buflen, uint8_t code, This is a memory size, right? It should be size_t rather than int, then, no? size_t it is. +static int parse_options(uint8_t *buf, int32_t buflen, int *overload, ^^ const missing? Here the idea was to go over the whole buffer and calling the callback with the proper code, len and value. Start of 'buf', i.e. 'code' in the function, needs to be advanced to the next option, so its not a const value. The const in const uint8_t *buf declares that the buffer this points *to* is constant, not the pointer itself. You are welcome to alter the pointer as much as you want if you do this. Note the difference between const uint8_t * buf and uint8_t * const buf... The latter makes little sense, but the former makes a lot of sense. A function declared as void foo(const int a); makes little sense, as this just means that the function internally won't change the internal copy of a, which is pretty useless information. void foo(const int *a); however makes a ton of sense, since it indicates that the buffer passed in won't be changed, while the function can do whatever it likes with the pointer copy it got internally... Lennart -- Lennart Poettering, Red Hat ___ systemd-devel mailing list systemd-devel@lists.freedesktop.org http://lists.freedesktop.org/mailman/listinfo/systemd-devel
Re: [systemd-devel] [PATCH v2 05/26] dhcp: Add option appending and parsing
On Mon, 25.11.13 09:13, Patrik Flykt (patrik.fl...@linux.intel.com) wrote: +#include stdint.h + +#include protocol.h + +int dhcp_option_append(uint8_t **buf, int *buflen, uint8_t code, This is a memory size, right? It should be size_t rather than int, then, no? +static int parse_options(uint8_t *buf, int32_t buflen, int *overload, ^^ const missing? + int *message_type, dhcp_option_cb_t cb, + void *user_data) +{ +uint8_t *code = buf; +uint8_t *len; + +while (buflen 0) { +switch (*code) { +case DHCP_OPTION_PAD: +buflen -= 1; +code++; +break; + +case DHCP_OPTION_END: +return 0; + +case DHCP_OPTION_MESSAGE_TYPE: +buflen -= 3; +if (buflen 0) +return -ENOBUFS; + +len = code + 1; +if (*len != 1) +return -EINVAL; + +if (message_type) +*message_type = *(len + 1); Feels weird that message_type is an int, but you fill an uint8_t into it, no? +if (buflen 0) +return -EINVAL; + +if (cb) +cb(*code, *len, len + 1, user_data); I'd always be careful with callback functions like this, since people might alter the objects you rely on while you iterate through things and then you are seriously confused... I'd always do iterator-like interfaces instead. (Doesn't matter here though, as this is an internal interface only...) +int dhcp_option_parse(DHCPMessage *message, int32_t len, Hmm, an int32_t length? Signed? And shouldn't it be size_t again? + dhcp_option_cb_t cb, void *user_data) +{ +int overload = 0; +int message_type = -ENOMSG; +uint8_t *opt = (uint8_t *)(message + 1); +int res; + +if (message == NULL || len 0) +return -EINVAL; + +len -= sizeof(DHCPMessage); +len -= 4; +if (len 0) +return -EINVAL; Wouldn't it be better to check len = sizeof(DHCPMessage) + 4 first? Sounds more logical than relying on a signed size... Lennart -- Lennart Poettering, Red Hat ___ systemd-devel mailing list systemd-devel@lists.freedesktop.org http://lists.freedesktop.org/mailman/listinfo/systemd-devel
[systemd-devel] [PATCH v2 05/26] dhcp: Add option appending and parsing
Add functions to append and parse DHCP options. Not all options are passed to the callback function, the ones not exposed are pad, end, message type and overload. If indicated by the overload option, file and sname fields will be examined for more options. The option functions are internal to DHCP, add a new header files for interal function prototypes. --- v2: fix __ prefix src/dhcp/internal.h | 34 ++ src/dhcp/option.c | 181 +++ 2 files changed, 215 insertions(+) create mode 100644 src/dhcp/internal.h create mode 100644 src/dhcp/option.c diff --git a/src/dhcp/internal.h b/src/dhcp/internal.h new file mode 100644 index 000..328ef1c --- /dev/null +++ b/src/dhcp/internal.h @@ -0,0 +1,34 @@ +/*-*- Mode: C; c-basic-offset: 8; indent-tabs-mode: nil -*-*/ + +#pragma once + +/*** + This file is part of systemd. + + Copyright (C) 2013 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 http://www.gnu.org/licenses/. +***/ + +#include stdint.h + +#include protocol.h + +int dhcp_option_append(uint8_t **buf, int *buflen, uint8_t code, + uint8_t optlen, const void *optval); + +typedef int (*dhcp_option_cb_t)(uint8_t code, uint8_t len, uint8_t *option, +void *user_data); +int dhcp_option_parse(DHCPMessage *message, int32_t len, + dhcp_option_cb_t cb, void *user_data); diff --git a/src/dhcp/option.c b/src/dhcp/option.c new file mode 100644 index 000..34aa98a --- /dev/null +++ b/src/dhcp/option.c @@ -0,0 +1,181 @@ +/*-*- Mode: C; c-basic-offset: 8; indent-tabs-mode: nil -*-*/ + +/*** + This file is part of systemd. + + Copyright (C) 2013 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 http://www.gnu.org/licenses/. +***/ + +#include stdint.h +#include string.h +#include errno.h +#include stdio.h + +#include internal.h + +int dhcp_option_append(uint8_t **buf, int *buflen, uint8_t code, + uint8_t optlen, const void *optval) +{ +if (!buf || !buflen) +return -EINVAL; + +switch (code) { + +case DHCP_OPTION_PAD: +case DHCP_OPTION_END: +if (*buflen 1) +return -ENOBUFS; + +(*buf)[0] = code; +*buf += 1; +*buflen -= 1; +break; + +default: +if (*buflen optlen + 2) +return -ENOBUFS; + +if (!optval) +return -EINVAL; + +(*buf)[0] = code; +(*buf)[1] = optlen; +memcpy((*buf)[2], optval, optlen); + +*buf += optlen + 2; +*buflen -= (optlen + 2); + +break; +} + +return 0; +} + +static int parse_options(uint8_t *buf, int32_t buflen, int *overload, + int *message_type, dhcp_option_cb_t cb, + void *user_data) +{ +uint8_t *code = buf; +uint8_t *len; + +while (buflen 0) { +switch (*code) { +case DHCP_OPTION_PAD: +buflen -= 1; +code++; +break; + +case DHCP_OPTION_END: +return 0; + +case DHCP_OPTION_MESSAGE_TYPE: +buflen -= 3; +if (buflen 0) +return -ENOBUFS; + +len = code + 1; +if (*len != 1) +return -EINVAL; + +if (message_type) +*message_type = *(len + 1); + +