This is for e.g. User Class option.
return dhcp_message_append_option(message, code, iov.iov_len, iov.iov_base);
}
+int dhcp_message_append_option_length_prefixed_data(
+ sd_dhcp_message *message,
+ uint8_t code,
+ size_t length_size,
+ const struct iovec_wrapper *iovw) {
+
+ int r;
+
+ assert(message);
+
+ _cleanup_(iovec_done) struct iovec iov = {};
+ r = iovw_merge(iovw, length_size, &iov);
+ if (r < 0)
+ return r;
+
+ if (!iovec_is_set(&iov))
+ return 0;
+
+ return dhcp_message_append_option(message, code, iov.iov_len, iov.iov_base);
+}
+
int dhcp_message_get_option(sd_dhcp_message *message, uint8_t code, size_t length, void *ret) {
int r;
return 0;
}
+int dhcp_message_get_option_length_prefixed_data(
+ sd_dhcp_message *message,
+ uint8_t code,
+ size_t length_size,
+ struct iovec_wrapper *ret) {
+
+ int r;
+
+ assert(message);
+
+ _cleanup_(iovec_done) struct iovec iov = {};
+ r = dhcp_message_get_option_alloc(message, code, &iov);
+ if (r < 0)
+ return r;
+
+ _cleanup_(iovw_done_free) struct iovec_wrapper iovw = {};
+ r = iovec_split(&iov, length_size, &iovw);
+ if (r < 0)
+ return r;
+
+ if (iovw_isempty(&iovw))
+ return -ENODATA;
+
+ if (ret)
+ *ret = TAKE_STRUCT(iovw);
+ return 0;
+}
+
static int dhcp_message_verify_header(
const struct iovec *iov,
uint8_t op,
int dhcp_message_append_option_parameter_request_list(sd_dhcp_message *message, Set *prl);
int dhcp_message_append_option_hostname(sd_dhcp_message *message, uint8_t flags, bool is_client, const char *hostname);
int dhcp_message_append_option_sub_tlv(sd_dhcp_message *message, uint8_t code, const TLV *tlv);
+int dhcp_message_append_option_length_prefixed_data(sd_dhcp_message *message, uint8_t code, size_t length_size, const struct iovec_wrapper *iovw);
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_dns_name(sd_dhcp_message *message, uint8_t code, char **ret);
int dhcp_message_get_option_hostname(sd_dhcp_message *message, char **ret);
int dhcp_message_get_option_sub_tlv(sd_dhcp_message *message, uint8_t code, TLVFlag flags, TLV **ret);
+int dhcp_message_get_option_length_prefixed_data(sd_dhcp_message *message, uint8_t code, size_t length_size, struct iovec_wrapper *ret);
int dhcp_message_parse(
const struct iovec *iov,
ASSERT_TRUE(iovec_equal(&iov, &iov_expected));
}
+static void verify_length_prefixed_data(sd_dhcp_message *m, const struct iovec_wrapper *expected) {
+ _cleanup_(iovw_done_free) struct iovec_wrapper iovw = {};
+ ASSERT_OK(dhcp_message_get_option_length_prefixed_data(m, SD_DHCP_OPTION_USER_CLASS, 1, &iovw));
+ ASSERT_TRUE(iovw_equal(&iovw, expected));
+}
+
TEST(dhcp_message) {
_cleanup_(sd_dhcp_message_unrefp) sd_dhcp_message *m = NULL;
const char *vendor_class = "hogehoge";
char **root_path = STRV_MAKE("/path/to/root", "/hogehoge/foofoo");
+ _cleanup_(iovw_done_free) struct iovec_wrapper user_class = {}, user_class_1 = {}, user_class_2 = {};
+ FOREACH_STRING(s, "hoge", "foo", "bar") {
+ ASSERT_OK(iovw_extend(&user_class, s, strlen(s)));
+ ASSERT_OK(iovw_extend(&user_class_1, s, strlen(s)));
+ }
+ FOREACH_STRING(s, "aaa", "bbb", "ccc") {
+ ASSERT_OK(iovw_extend(&user_class, s, strlen(s)));
+ ASSERT_OK(iovw_extend(&user_class_2, s, strlen(s)));
+ }
+
_cleanup_(tlv_done) TLV vendor = TLV_INIT(TLV_DHCP4_SUBOPTION);
for (unsigned i = 0; i < 3; i++) {
uint8_t buf[255];
ASSERT_ERROR(dhcp_message_append_option_sub_tlv(m, SD_DHCP_OPTION_VENDOR_SPECIFIC_INFORMATION, &vendor), EEXIST);
verify_sub_tlv(m, &vendor);
+ /* user class */
+ ASSERT_OK(dhcp_message_append_option_length_prefixed_data(m, SD_DHCP_OPTION_USER_CLASS, 1, &user_class_1));
+ ASSERT_OK(dhcp_message_append_option_length_prefixed_data(m, SD_DHCP_OPTION_USER_CLASS, 1, &user_class_2));
+ verify_length_prefixed_data(m, &user_class);
+
/* build and parse */
_cleanup_(iovw_done_free) struct iovec_wrapper iovw = {};
ASSERT_OK(dhcp_message_build(m, &iovw));
verify_prl(m2, prl);
verify_hostname(m2, hostname);
verify_sub_tlv(m2, &vendor);
+ verify_length_prefixed_data(m2, &user_class);
/* build again, and verify the packet */
_cleanup_(iovw_done_free) struct iovec_wrapper iovw2 = {};