These are for DHCP option 55 (parameter request list).
#include "iovec-wrapper.h"
#include "ip-util.h"
#include "network-common.h"
+#include "set.h"
+#include "sort-util.h"
#include "string-util.h"
static sd_dhcp_message* dhcp_message_free(sd_dhcp_message *message) {
return dhcp_message_append_option(message, SD_DHCP_OPTION_CLIENT_IDENTIFIER, id->size, id->raw);
}
+static int cmp_uint8(const uint8_t *a, const uint8_t *b) {
+ assert(a);
+ assert(b);
+
+ return CMP(*a, *b);
+}
+
+int dhcp_message_append_option_parameter_request_list(sd_dhcp_message *message, Set *prl) {
+ assert(message);
+
+ size_t len = set_size(prl);
+ if (len == 0)
+ return 0;
+
+ _cleanup_free_ uint8_t *buf = new(uint8_t, len);
+ if (!buf)
+ return -ENOMEM;
+
+ uint8_t *p = buf;
+ void *q;
+ SET_FOREACH(q, prl)
+ *p++ = PTR_TO_UINT8(q);
+
+ /* Sort the options to make the message reproducible. */
+ typesafe_qsort(buf, len, cmp_uint8);
+
+ return dhcp_message_append_option(message, SD_DHCP_OPTION_PARAMETER_REQUEST_LIST, len, buf);
+}
+
int dhcp_message_get_option(sd_dhcp_message *message, uint8_t code, size_t length, void *ret) {
int r;
return sd_dhcp_client_id_set_raw(ret, iov.iov_base, iov.iov_len);
}
+int dhcp_message_get_option_parameter_request_list(sd_dhcp_message *message, Set **ret) {
+ int r;
+
+ assert(message);
+
+ _cleanup_(iovec_done) struct iovec iov = {};
+ r = dhcp_message_get_option_alloc(message, SD_DHCP_OPTION_PARAMETER_REQUEST_LIST, &iov);
+ if (r < 0)
+ return r;
+
+ if (!iovec_is_set(&iov))
+ return -ENODATA;
+
+ if (!ret)
+ return 0;
+
+ _cleanup_set_free_ Set *prl = NULL;
+ for (struct iovec i = iov; iovec_is_set(&i); iovec_inc(&i, 1)) {
+ r = set_ensure_put(&prl, /* hash_ops= */ NULL, UINT8_TO_PTR(*(uint8_t*) i.iov_base));
+ if (r < 0)
+ return r;
+ }
+
+ *ret = TAKE_PTR(prl);
+ return 0;
+}
+
static int dhcp_message_verify_header(
const struct iovec *iov,
uint8_t op,
int dhcp_message_append_option_addresses(sd_dhcp_message *message, uint8_t code, size_t n_addr, const struct in_addr *addr);
int dhcp_message_append_option_string(sd_dhcp_message *message, uint8_t code, const char *data);
int dhcp_message_append_option_client_id(sd_dhcp_message *message, const sd_dhcp_client_id *id);
+int dhcp_message_append_option_parameter_request_list(sd_dhcp_message *message, Set *prl);
int dhcp_message_get_option(sd_dhcp_message *message, uint8_t code, size_t length, void *ret);
int dhcp_message_get_option_alloc(sd_dhcp_message *message, uint8_t code, struct iovec *ret);
int dhcp_message_get_option_addresses(sd_dhcp_message *message, uint8_t code, size_t *ret_n_addr, struct in_addr **ret_addr);
int dhcp_message_get_option_string(sd_dhcp_message *message, uint8_t code, char **ret);
int dhcp_message_get_option_client_id(sd_dhcp_message *message, sd_dhcp_client_id *ret);
+int dhcp_message_get_option_parameter_request_list(sd_dhcp_message *message, Set **ret);
int dhcp_message_parse(
const struct iovec *iov,
#include "iovec-util.h"
#include "iovec-wrapper.h"
#include "random-util.h"
+#include "set.h"
#include "strv.h"
#include "tests.h"
ASSERT_EQ(client_id_compare_func(&id, expected), 0);
}
+static void verify_prl(sd_dhcp_message *m, Set *expected) {
+ _cleanup_set_free_ Set *set = NULL;
+ ASSERT_OK(dhcp_message_get_option_parameter_request_list(m, &set));
+ ASSERT_TRUE(set_equal(set, expected));
+}
+
TEST(dhcp_message) {
_cleanup_(sd_dhcp_message_unrefp) sd_dhcp_message *m = NULL;
.size = 7,
};
+ _cleanup_set_free_ Set *prl = NULL;
+ for (uint8_t i = SD_DHCP_OPTION_PRIVATE_BASE; i <= SD_DHCP_OPTION_PRIVATE_LAST; i++)
+ ASSERT_OK(set_ensure_put(&prl, /* hash_ops= */ NULL, UINT_TO_PTR(i)));
+
const char *vendor_class = "hogehoge";
char **root_path = STRV_MAKE("/path/to/root", "/hogehoge/foofoo");
ASSERT_OK(dhcp_message_append_option_client_id(m, &id));
verify_client_id(m, &id);
+ /* parameter request list */
+ ASSERT_OK(dhcp_message_append_option_parameter_request_list(m, prl));
+ ASSERT_OK(dhcp_message_append_option_parameter_request_list(m, prl));
+ verify_prl(m, prl);
+
/* build and parse */
_cleanup_(iovw_done_free) struct iovec_wrapper iovw = {};
ASSERT_OK(dhcp_message_build(m, &iovw));
verify_addresses(m2, ELEMENTSOF(ntp), ntp);
verify_string(m2, vendor_class);
verify_client_id(m2, &id);
+ verify_prl(m2, prl);
/* build again, and verify the packet */
_cleanup_(iovw_done_free) struct iovec_wrapper iovw2 = {};