mirror of
https://github.com/Dasharo/systemd.git
synced 2026-03-06 15:02:31 -08:00
Merge pull request #29247 from naraghavan/naraghavan/dhcpv6-vendor-options
networkd: Add DHCP vendor specific sub options to dbus API
This commit is contained in:
@@ -12,6 +12,7 @@
|
||||
#include "dhcp6-option.h"
|
||||
#include "dhcp6-protocol.h"
|
||||
#include "macro.h"
|
||||
#include "set.h"
|
||||
#include "time-util.h"
|
||||
|
||||
struct sd_dhcp6_lease {
|
||||
@@ -45,6 +46,8 @@ struct sd_dhcp6_lease {
|
||||
size_t sntp_count;
|
||||
char *fqdn;
|
||||
char *captive_portal;
|
||||
struct sd_dhcp6_option **sorted_vendor_options;
|
||||
Set *vendor_options;
|
||||
};
|
||||
|
||||
int dhcp6_lease_set_clientid(sd_dhcp6_lease *lease, const uint8_t *id, size_t len);
|
||||
|
||||
@@ -587,6 +587,83 @@ int sd_dhcp6_lease_get_captive_portal(sd_dhcp6_lease *lease, const char **ret) {
|
||||
return 0;
|
||||
}
|
||||
|
||||
int sd_dhcp6_lease_get_vendor_options(sd_dhcp6_lease *lease, sd_dhcp6_option ***ret) {
|
||||
int r;
|
||||
|
||||
assert_return(lease, -EINVAL);
|
||||
|
||||
if (set_isempty(lease->vendor_options))
|
||||
return -ENODATA;
|
||||
|
||||
if (ret) {
|
||||
if (!lease->sorted_vendor_options) {
|
||||
r = set_dump_sorted(lease->vendor_options, (void***) &lease->sorted_vendor_options, NULL);
|
||||
if (r < 0)
|
||||
return r;
|
||||
}
|
||||
|
||||
*ret = lease->sorted_vendor_options;
|
||||
}
|
||||
|
||||
return set_size(lease->vendor_options);
|
||||
}
|
||||
|
||||
static int dhcp6_lease_insert_vendor_option(
|
||||
sd_dhcp6_lease *lease,
|
||||
uint16_t option_code,
|
||||
const void *data,
|
||||
size_t len,
|
||||
uint16_t enterprise_id) {
|
||||
|
||||
_cleanup_(sd_dhcp6_option_unrefp) sd_dhcp6_option *option = NULL;
|
||||
|
||||
assert(lease);
|
||||
|
||||
option = new(sd_dhcp6_option, 1);
|
||||
if (!option)
|
||||
return -ENOMEM;
|
||||
|
||||
*option = (sd_dhcp6_option) {
|
||||
.n_ref = 1,
|
||||
.enterprise_identifier = enterprise_id,
|
||||
.option = option_code,
|
||||
.length = len,
|
||||
};
|
||||
option->data = memdup_suffix0(data, len);
|
||||
if (!option->data)
|
||||
return -ENOMEM;
|
||||
|
||||
return set_ensure_consume(&lease->vendor_options, &dhcp6_option_hash_ops, TAKE_PTR(option));
|
||||
}
|
||||
|
||||
static int dhcp6_lease_add_vendor_option(sd_dhcp6_lease *lease, const uint8_t *optval, size_t optlen) {
|
||||
int r;
|
||||
uint32_t enterprise_id;
|
||||
|
||||
assert(lease);
|
||||
assert(optval || optlen == 0);
|
||||
|
||||
if (optlen < sizeof(be32_t))
|
||||
return -EBADMSG;
|
||||
|
||||
enterprise_id = unaligned_read_be32(optval);
|
||||
|
||||
for (size_t offset = 4; offset < optlen;) {
|
||||
const uint8_t *subval;
|
||||
size_t sublen;
|
||||
uint16_t subopt;
|
||||
|
||||
r = dhcp6_option_parse(optval, optlen, &offset, &subopt, &sublen, &subval);
|
||||
if (r < 0)
|
||||
return r;
|
||||
|
||||
r = dhcp6_lease_insert_vendor_option(lease, subopt, subval, sublen, enterprise_id);
|
||||
if (r < 0)
|
||||
return r;
|
||||
}
|
||||
return 0;
|
||||
}
|
||||
|
||||
static int dhcp6_lease_parse_message(
|
||||
sd_dhcp6_client *client,
|
||||
sd_dhcp6_lease *lease,
|
||||
@@ -772,6 +849,13 @@ static int dhcp6_lease_parse_message(
|
||||
|
||||
irt = unaligned_be32_sec_to_usec(optval, /* max_as_infinity = */ false);
|
||||
break;
|
||||
|
||||
case SD_DHCP6_OPTION_VENDOR_OPTS:
|
||||
r = dhcp6_lease_add_vendor_option(lease, optval, optlen);
|
||||
if (r < 0)
|
||||
log_dhcp6_client_errno(client, r, "Failed to parse vendor option, ignoring: %m");
|
||||
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
@@ -812,6 +896,8 @@ static sd_dhcp6_lease *dhcp6_lease_free(sd_dhcp6_lease *lease) {
|
||||
if (!lease)
|
||||
return NULL;
|
||||
|
||||
set_free(lease->vendor_options);
|
||||
free(lease->sorted_vendor_options);
|
||||
free(lease->clientid);
|
||||
free(lease->serverid);
|
||||
dhcp6_ia_free(lease->ia_na);
|
||||
|
||||
@@ -53,6 +53,8 @@
|
||||
0x00, 0x02, 0x00, 0x00, 0xab, 0x11, 0x61, 0x77, 0x40, 0xde, 0x13, 0x42, 0xc3, 0xa2
|
||||
#define SERVER_ID_BYTES \
|
||||
0x00, 0x01, 0x00, 0x01, 0x19, 0x40, 0x5c, 0x53, 0x78, 0x2b, 0xcb, 0xb3, 0x6d, 0x53
|
||||
#define VENDOR_SUBOPTION_BYTES \
|
||||
0x01
|
||||
|
||||
static const struct in6_addr local_address =
|
||||
{ { { 0xfe, 0x80, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x01, } } };
|
||||
@@ -70,10 +72,18 @@ static const struct in6_addr ntp1 = { { { NTP1_BYTES } } };
|
||||
static const struct in6_addr ntp2 = { { { NTP2_BYTES } } };
|
||||
static const uint8_t client_id[] = { CLIENT_ID_BYTES };
|
||||
static const uint8_t server_id[] = { SERVER_ID_BYTES };
|
||||
static uint8_t vendor_suboption_data[] = { VENDOR_SUBOPTION_BYTES };
|
||||
static const struct ether_addr mac = {
|
||||
.ether_addr_octet = { 'A', 'B', 'C', '1', '2', '3' },
|
||||
};
|
||||
static int test_fd[2] = EBADF_PAIR;
|
||||
static sd_dhcp6_option vendor_suboption = {
|
||||
.n_ref = 1,
|
||||
.enterprise_identifier = 32,
|
||||
.option = 247,
|
||||
.data = vendor_suboption_data,
|
||||
.length = 1,
|
||||
};
|
||||
static int test_ifindex = 42;
|
||||
static unsigned test_client_sent_message_count = 0;
|
||||
static sd_dhcp6_client *client_ref = NULL;
|
||||
@@ -100,6 +110,7 @@ TEST(client_basic) {
|
||||
assert_se(sd_dhcp6_client_set_request_option(client, SD_DHCP6_OPTION_DNS_SERVER) >= 0);
|
||||
assert_se(sd_dhcp6_client_set_request_option(client, SD_DHCP6_OPTION_NTP_SERVER) >= 0);
|
||||
assert_se(sd_dhcp6_client_set_request_option(client, SD_DHCP6_OPTION_SNTP_SERVER) >= 0);
|
||||
assert_se(sd_dhcp6_client_set_request_option(client, SD_DHCP6_OPTION_VENDOR_OPTS) >= 0);
|
||||
assert_se(sd_dhcp6_client_set_request_option(client, SD_DHCP6_OPTION_DOMAIN) >= 0);
|
||||
assert_se(sd_dhcp6_client_set_request_option(client, 10) == -EINVAL);
|
||||
assert_se(sd_dhcp6_client_set_request_option(client, SD_DHCP6_OPTION_NIS_SERVER) >= 0);
|
||||
@@ -736,6 +747,9 @@ static const uint8_t msg_reply[] = {
|
||||
/* Client FQDN */
|
||||
0x00, SD_DHCP6_OPTION_CLIENT_FQDN, 0x00, 0x12,
|
||||
0x01, 0x06, 'c', 'l', 'i', 'e', 'n', 't', 0x03, 'l', 'a', 'b', 0x05, 'i', 'n', 't', 'r', 'a',
|
||||
/* Vendor specific options */
|
||||
0x00, SD_DHCP6_OPTION_VENDOR_OPTS, 0x00, 0x09,
|
||||
0x00, 0x00, 0x00, 0x20, 0x00, 0xf7, 0x00, 0x01, VENDOR_SUBOPTION_BYTES,
|
||||
};
|
||||
|
||||
static const uint8_t msg_advertise[] = {
|
||||
@@ -815,6 +829,9 @@ static const uint8_t msg_advertise[] = {
|
||||
/* Client FQDN */
|
||||
0x00, SD_DHCP6_OPTION_CLIENT_FQDN, 0x00, 0x12,
|
||||
0x01, 0x06, 'c', 'l', 'i', 'e', 'n', 't', 0x03, 'l', 'a', 'b', 0x05, 'i', 'n', 't', 'r', 'a',
|
||||
/* Vendor specific options */
|
||||
0x00, SD_DHCP6_OPTION_VENDOR_OPTS, 0x00, 0x09,
|
||||
0x00, 0x00, 0x00, 0x20, 0x00, 0xf7, 0x00, 0x01, VENDOR_SUBOPTION_BYTES,
|
||||
};
|
||||
|
||||
static void test_client_verify_information_request(const DHCP6Message *msg, size_t len) {
|
||||
@@ -855,6 +872,7 @@ static void test_client_verify_request(const DHCP6Message *msg, size_t len) {
|
||||
|
||||
static void test_lease_common(sd_dhcp6_client *client) {
|
||||
sd_dhcp6_lease *lease;
|
||||
sd_dhcp6_option **suboption;
|
||||
const struct in6_addr *addrs;
|
||||
const char *str;
|
||||
char **strv;
|
||||
@@ -888,6 +906,11 @@ static void test_lease_common(sd_dhcp6_client *client) {
|
||||
assert_se(lease->sntp_count == 2);
|
||||
assert_se(in6_addr_equal(&lease->sntp[0], &sntp1));
|
||||
assert_se(in6_addr_equal(&lease->sntp[1], &sntp2));
|
||||
|
||||
assert_se(sd_dhcp6_lease_get_vendor_options(lease, &suboption) > 0);
|
||||
assert_se((*suboption)->enterprise_identifier == vendor_suboption.enterprise_identifier);
|
||||
assert_se((*suboption)->option == vendor_suboption.option);
|
||||
assert_se(*(uint8_t*)(*suboption)->data == *(uint8_t*)vendor_suboption.data);
|
||||
}
|
||||
|
||||
static void test_lease_managed(sd_dhcp6_client *client) {
|
||||
|
||||
@@ -3,6 +3,7 @@
|
||||
#include <linux/nexthop.h>
|
||||
|
||||
#include "dhcp-server-internal.h"
|
||||
#include "dhcp6-internal.h"
|
||||
#include "dhcp6-lease-internal.h"
|
||||
#include "dns-domain.h"
|
||||
#include "ip-protocol-list.h"
|
||||
@@ -1036,6 +1037,32 @@ static int dhcp_server_append_json(Link *link, JsonVariant **v) {
|
||||
return json_variant_set_field_non_null(v, "DHCPServer", w);
|
||||
}
|
||||
|
||||
static int dhcp6_client_vendor_options_append_json(Link *link, JsonVariant **v) {
|
||||
_cleanup_(json_variant_unrefp) JsonVariant *array = NULL;
|
||||
sd_dhcp6_option **options = NULL;
|
||||
int r, n_vendor_options;
|
||||
|
||||
assert(link);
|
||||
assert(v);
|
||||
|
||||
if (!link->dhcp6_lease)
|
||||
return 0;
|
||||
|
||||
n_vendor_options = sd_dhcp6_lease_get_vendor_options(link->dhcp6_lease, &options);
|
||||
|
||||
FOREACH_ARRAY(option, options, n_vendor_options) {
|
||||
r = json_variant_append_arrayb(&array,
|
||||
JSON_BUILD_OBJECT(
|
||||
JSON_BUILD_PAIR_UNSIGNED("EnterpriseId", (*option)->enterprise_identifier),
|
||||
JSON_BUILD_PAIR_UNSIGNED("SubOptionCode", (*option)->option),
|
||||
JSON_BUILD_PAIR_HEX("SubOptionData", (*option)->data, (*option)->length)));
|
||||
if (r < 0)
|
||||
return 0;
|
||||
}
|
||||
|
||||
return json_variant_set_field_non_null(v, "VendorSpecificOptions", array);
|
||||
}
|
||||
|
||||
static int dhcp6_client_lease_append_json(Link *link, JsonVariant **v) {
|
||||
_cleanup_(json_variant_unrefp) JsonVariant *w = NULL;
|
||||
usec_t ts, t1, t2;
|
||||
@@ -1125,6 +1152,10 @@ static int dhcp6_client_append_json(Link *link, JsonVariant **v) {
|
||||
if (r < 0)
|
||||
return r;
|
||||
|
||||
r = dhcp6_client_vendor_options_append_json(link, &w);
|
||||
if (r < 0)
|
||||
return r;
|
||||
|
||||
return json_variant_set_field_non_null(v, "DHCPv6Client", w);
|
||||
}
|
||||
|
||||
|
||||
@@ -23,6 +23,8 @@
|
||||
#include <netinet/in.h>
|
||||
#include <sys/types.h>
|
||||
|
||||
#include "sd-dhcp6-option.h"
|
||||
|
||||
#include "_sd-common.h"
|
||||
|
||||
_SD_BEGIN_DECLARATIONS;
|
||||
@@ -77,6 +79,7 @@ int sd_dhcp6_lease_get_ntp_addrs(sd_dhcp6_lease *lease, const struct in6_addr **
|
||||
int sd_dhcp6_lease_get_ntp_fqdn(sd_dhcp6_lease *lease, char ***ret);
|
||||
int sd_dhcp6_lease_get_fqdn(sd_dhcp6_lease *lease, const char **ret);
|
||||
int sd_dhcp6_lease_get_captive_portal(sd_dhcp6_lease *lease, const char **ret);
|
||||
int sd_dhcp6_lease_get_vendor_options(sd_dhcp6_lease *lease, sd_dhcp6_option ***ret);
|
||||
|
||||
sd_dhcp6_lease *sd_dhcp6_lease_ref(sd_dhcp6_lease *lease);
|
||||
sd_dhcp6_lease *sd_dhcp6_lease_unref(sd_dhcp6_lease *lease);
|
||||
|
||||
Reference in New Issue
Block a user