dhcp: use struct iovec_wrapper to manage user class
This commit is contained in:
@@ -5,6 +5,7 @@
|
||||
|
||||
#include "dhcp-client-id-internal.h"
|
||||
#include "ether-addr-util.h"
|
||||
#include "iovec-wrapper.h"
|
||||
#include "network-common.h"
|
||||
#include "sd-forward.h"
|
||||
#include "socket-util.h"
|
||||
@@ -55,7 +56,7 @@ struct sd_dhcp_client {
|
||||
char *hostname;
|
||||
char *vendor_class_identifier;
|
||||
char *mudurl;
|
||||
char **user_class;
|
||||
struct iovec_wrapper user_class;
|
||||
uint32_t mtu;
|
||||
usec_t fallback_lease_lifetime;
|
||||
uint32_t xid;
|
||||
@@ -93,6 +94,7 @@ int dhcp_client_get_state(sd_dhcp_client *client);
|
||||
|
||||
int dhcp_client_set_extra_options(sd_dhcp_client *client, TLV *options);
|
||||
int dhcp_client_set_vendor_options(sd_dhcp_client *client, TLV *options);
|
||||
int dhcp_client_set_user_class(sd_dhcp_client *client, const struct iovec_wrapper *user_class);
|
||||
|
||||
int client_receive_message_raw(
|
||||
sd_event_source *s,
|
||||
|
||||
@@ -12,7 +12,6 @@
|
||||
#include "hostname-util.h"
|
||||
#include "memory-util.h"
|
||||
#include "string-util.h"
|
||||
#include "strv.h"
|
||||
#include "utf8.h"
|
||||
|
||||
/* Append type-length value structure to the options buffer */
|
||||
@@ -57,43 +56,6 @@ static int option_append(uint8_t options[], size_t size, size_t *offset,
|
||||
*offset += 1;
|
||||
break;
|
||||
|
||||
case SD_DHCP_OPTION_USER_CLASS: {
|
||||
/* When called with raw data (optlen > 0), e.g. from SendOption=, append as a plain TLV.
|
||||
* The structured handling below expects optval to be a strv. */
|
||||
if (optlen > 0)
|
||||
return dhcp_option_append_tlv(options, size, offset, code, optlen, optval);
|
||||
|
||||
size_t total = 0;
|
||||
|
||||
if (strv_isempty((char **) optval))
|
||||
return -EINVAL;
|
||||
|
||||
STRV_FOREACH(s, (const char* const*) optval) {
|
||||
size_t len = strlen(*s);
|
||||
|
||||
if (len > 255 || len == 0)
|
||||
return -EINVAL;
|
||||
|
||||
total += 1 + len;
|
||||
}
|
||||
|
||||
if (*offset + 2 + total > size)
|
||||
return -ENOBUFS;
|
||||
|
||||
options[*offset] = code;
|
||||
options[*offset + 1] = total;
|
||||
*offset += 2;
|
||||
|
||||
STRV_FOREACH(s, (const char* const*) optval) {
|
||||
size_t len = strlen(*s);
|
||||
|
||||
options[*offset] = len;
|
||||
memcpy(&options[*offset + 1], *s, len);
|
||||
*offset += 1 + len;
|
||||
}
|
||||
|
||||
break;
|
||||
}
|
||||
case SD_DHCP_OPTION_SIP_SERVER:
|
||||
if (*offset + 3 + optlen > size)
|
||||
return -ENOBUFS;
|
||||
|
||||
@@ -27,7 +27,6 @@
|
||||
#include "sort-util.h"
|
||||
#include "string-table.h"
|
||||
#include "string-util.h"
|
||||
#include "strv.h"
|
||||
#include "time-util.h"
|
||||
#include "web-util.h"
|
||||
|
||||
@@ -434,28 +433,30 @@ int sd_dhcp_client_set_mud_url(
|
||||
return free_and_strdup(&client->mudurl, mudurl);
|
||||
}
|
||||
|
||||
int sd_dhcp_client_set_user_class(
|
||||
sd_dhcp_client *client,
|
||||
char * const *user_class) {
|
||||
|
||||
char **s = NULL;
|
||||
int dhcp_client_set_user_class(sd_dhcp_client *client, const struct iovec_wrapper *user_class) {
|
||||
int r;
|
||||
|
||||
assert_return(client, -EINVAL);
|
||||
assert_return(!sd_dhcp_client_is_running(client), -EBUSY);
|
||||
assert_return(!strv_isempty(user_class), -EINVAL);
|
||||
|
||||
STRV_FOREACH(p, user_class) {
|
||||
size_t n = strlen(*p);
|
||||
|
||||
if (n > 255 || n == 0)
|
||||
return -EINVAL;
|
||||
if (iovw_isempty(user_class)) {
|
||||
iovw_done_free(&client->user_class);
|
||||
return 0;
|
||||
}
|
||||
|
||||
s = strv_copy(user_class);
|
||||
if (!s)
|
||||
return -ENOMEM;
|
||||
_cleanup_(iovw_done_free) struct iovec_wrapper iovw = {};
|
||||
FOREACH_ARRAY(iovec, user_class->iovec, user_class->count) {
|
||||
if (iovec->iov_len == 0 || iovec->iov_len > UINT8_MAX)
|
||||
return -EINVAL;
|
||||
|
||||
return strv_free_and_replace(client->user_class, s);
|
||||
r = iovw_extend_iov(&iovw, iovec);
|
||||
if (r < 0)
|
||||
return r;
|
||||
}
|
||||
|
||||
iovw_done_free(&client->user_class);
|
||||
client->user_class = TAKE_STRUCT(iovw);
|
||||
return 0;
|
||||
}
|
||||
|
||||
int sd_dhcp_client_set_client_port(
|
||||
@@ -933,12 +934,26 @@ static int client_append_common_discover_request_options(sd_dhcp_client *client,
|
||||
return r;
|
||||
}
|
||||
|
||||
if (client->user_class) {
|
||||
r = dhcp_option_append(&packet->dhcp, optlen, optoffset, 0,
|
||||
SD_DHCP_OPTION_USER_CLASS,
|
||||
/* optlen= */ 0, client->user_class);
|
||||
if (r < 0)
|
||||
return r;
|
||||
if (!iovw_isempty(&client->user_class)) {
|
||||
size_t sz = iovw_size(&client->user_class) + client->user_class.count;
|
||||
if (sz <= UINT8_MAX) {
|
||||
_cleanup_free_ uint8_t *buf = new(uint8_t, sz);
|
||||
if (!buf)
|
||||
return -ENOMEM;
|
||||
|
||||
uint8_t *p = buf;
|
||||
FOREACH_ARRAY(iovec, client->user_class.iovec, client->user_class.count) {
|
||||
assert(iovec->iov_len > 0 && iovec->iov_len <= UINT8_MAX);
|
||||
*p++ = iovec->iov_len;
|
||||
p = mempcpy(p, iovec->iov_base, iovec->iov_len);
|
||||
}
|
||||
|
||||
r = dhcp_option_append(&packet->dhcp, optlen, optoffset, 0,
|
||||
SD_DHCP_OPTION_USER_CLASS,
|
||||
sz, buf);
|
||||
if (r < 0)
|
||||
return r;
|
||||
}
|
||||
}
|
||||
|
||||
if (client->extra_options) {
|
||||
@@ -2297,7 +2312,7 @@ static sd_dhcp_client* dhcp_client_free(sd_dhcp_client *client) {
|
||||
free(client->hostname);
|
||||
free(client->vendor_class_identifier);
|
||||
free(client->mudurl);
|
||||
client->user_class = strv_free(client->user_class);
|
||||
iovw_done_free(&client->user_class);
|
||||
tlv_unref(client->extra_options);
|
||||
tlv_unref(client->vendor_options);
|
||||
free(client->ifname);
|
||||
|
||||
Reference in New Issue
Block a user