</listitem>
</varlistentry>
+ <varlistentry>
+ <term><varname>UserClass=</varname></term>
+ <listitem>
+ <para>A DHCPv4 client can use UserClass option to identify the type or category of user or applications
+ it represents. The information contained in this option is a string that represents the user class of which
+ the client is a member. Each class sets an identifying string of information to be used by the DHCP
+ service to classify clients. Takes a whitespace-separated list of strings.</para>
+ </listitem>
+ </varlistentry>
+
<varlistentry>
<term><varname>DUIDType=</varname></term>
<listitem>
#include "alloc-util.h"
#include "utf8.h"
+#include "strv.h"
#include "dhcp-internal.h"
*offset += 1;
break;
+ case SD_DHCP_OPTION_USER_CLASS: {
+ size_t len = 0;
+ char **s;
+
+ STRV_FOREACH(s, (char **) optval)
+ len += strlen(*s) + 1;
+
+ if (size < *offset + len + 2)
+ return -ENOBUFS;
+
+ options[*offset] = code;
+ options[*offset + 1] = len;
+ *offset += 2;
+
+ STRV_FOREACH(s, (char **) optval) {
+ len = strlen(*s);
+
+ if (len > 255)
+ return -ENAMETOOLONG;
+
+ options[*offset] = len;
+
+ memcpy_safe(&options[*offset + 1], *s, len);
+ *offset += len + 1;
+ }
+
+ break;
+ }
default:
if (size < *offset + optlen + 2)
return -ENOBUFS;
#include "random-util.h"
#include "string-util.h"
#include "util.h"
+#include "strv.h"
#define MAX_CLIENT_ID_LEN (sizeof(uint32_t) + MAX_DUID_LEN) /* Arbitrary limit */
#define MAX_MAC_ADDR_LEN CONST_MAX(INFINIBAND_ALEN, ETH_ALEN)
size_t client_id_len;
char *hostname;
char *vendor_class_identifier;
+ char **user_class;
uint32_t mtu;
uint32_t xid;
usec_t start_time;
return free_and_strdup(&client->vendor_class_identifier, vci);
}
+int sd_dhcp_client_set_user_class(
+ sd_dhcp_client *client,
+ const char* const* user_class) {
+
+ _cleanup_strv_free_ char **s = NULL;
+ char **p;
+
+ STRV_FOREACH(p, (char **) user_class)
+ if (strlen(*p) > 255)
+ return -ENAMETOOLONG;
+
+ s = strv_copy((char **) user_class);
+ if (!s)
+ return -ENOMEM;
+
+ client->user_class = TAKE_PTR(s);
+
+ return 0;
+}
+
int sd_dhcp_client_set_client_port(
sd_dhcp_client *client,
uint16_t port) {
return r;
}
+ if (client->user_class) {
+ r = dhcp_option_append(&discover->dhcp, optlen, &optoffset, 0,
+ SD_DHCP_OPTION_USER_CLASS,
+ strv_length(client->user_class),
+ client->user_class);
+ if (r < 0)
+ return r;
+ }
+
r = dhcp_option_append(&discover->dhcp, optlen, &optoffset, 0,
SD_DHCP_OPTION_END, 0, NULL);
if (r < 0)
free(client->req_opts);
free(client->hostname);
free(client->vendor_class_identifier);
+ client->user_class = strv_free(client->user_class);
return mfree(client);
}
return r;
}
+ if (link->network->dhcp_user_class) {
+ r = sd_dhcp_client_set_user_class(link->dhcp_client, (const char **) link->network->dhcp_user_class);
+ if (r < 0)
+ return r;
+ }
+
if (link->network->dhcp_client_port) {
r = sd_dhcp_client_set_client_port(link->dhcp_client, link->network->dhcp_client_port);
if (r < 0)
DHCP.RequestBroadcast, config_parse_bool, 0, offsetof(Network, dhcp_broadcast)
DHCP.CriticalConnection, config_parse_bool, 0, offsetof(Network, dhcp_critical)
DHCP.VendorClassIdentifier, config_parse_string, 0, offsetof(Network, dhcp_vendor_class_identifier)
+DHCP.UserClass, config_parse_dhcp_user_class, 0, offsetof(Network, dhcp_user_class)
DHCP.DUIDType, config_parse_duid_type, 0, offsetof(Network, duid.type)
DHCP.DUIDRawData, config_parse_duid_rawdata, 0, offsetof(Network, duid)
DHCP.RouteMetric, config_parse_unsigned, 0, offsetof(Network, dhcp_route_metric)
free(network->description);
free(network->dhcp_vendor_class_identifier);
+ strv_free(network->dhcp_user_class);
free(network->dhcp_hostname);
free(network->mac);
return 0;
}
+int config_parse_dhcp_user_class(
+ const char *unit,
+ const char *filename,
+ unsigned line,
+ const char *section,
+ unsigned section_line,
+ const char *lvalue,
+ int ltype,
+ const char *rvalue,
+ void *data,
+ void *userdata) {
+
+ char ***l = data;
+ int r;
+
+ assert(l);
+ assert(lvalue);
+ assert(rvalue);
+
+ if (isempty(rvalue)) {
+ *l = strv_free(*l);
+ return 0;
+ }
+
+ for (;;) {
+ _cleanup_free_ char *w = NULL;
+
+ r = extract_first_word(&rvalue, &w, NULL, 0);
+ if (r == -ENOMEM)
+ return log_oom();
+ if (r < 0) {
+ log_syntax(unit, LOG_ERR, filename, line, r, "Failed to split user classes option, ignoring: %s", rvalue);
+ break;
+ }
+ if (r == 0)
+ break;
+
+ if (strlen(w) > 255) {
+ log_syntax(unit, LOG_ERR, filename, line, r, "%s length is not in the range 1-255, ignoring.", w);
+ continue;
+ }
+
+ r = strv_push(l, w);
+ if (r < 0)
+ return log_oom();
+
+ w = NULL;
+ }
+
+ return 0;
+}
+
int config_parse_dhcp_route_table(const char *unit,
const char *filename,
unsigned line,
AddressFamilyBoolean dhcp;
DHCPClientIdentifier dhcp_client_identifier;
char *dhcp_vendor_class_identifier;
+ char **dhcp_user_class;
char *dhcp_hostname;
unsigned dhcp_route_metric;
uint32_t dhcp_route_table;
int config_parse_dnssec_negative_trust_anchors(const char *unit, const char *filename, unsigned line, const char *section, unsigned section_line, const char *lvalue, int ltype, const char *rvalue, void *data, void *userdata);
int config_parse_dhcp_use_domains(const char *unit, const char *filename, unsigned line, const char *section, unsigned section_line, const char *lvalue, int ltype, const char *rvalue, void *data, void *userdata);
int config_parse_lldp_mode(const char *unit, const char *filename, unsigned line, const char *section, unsigned section_line, const char *lvalue, int ltype, const char *rvalue, void *data, void *userdata);
-int config_parse_dhcp_route_table(const char *unit, const char *filename, unsigned line, const char *section, unsigned section_line, const char *lvalue, int ltype, const char *rvalue, void *data, void *userdata);
+int config_parse_dhcp_route_table(const char *unit, const char *filename, unsigned line, const char *section, unsigned section_line, const char *lvalue, int ltype, const char *rvalue, void *data, void *userdata);int config_parse_dhcp_user_class(const char *unit, const char *filename, unsigned line, const char *section, unsigned section_line, const char *lvalue, int ltype, const char *rvalue, void *data, void *userdata);
int config_parse_ntp(const char *unit, const char *filename, unsigned line, const char *section, unsigned section_line, const char *lvalue, int ltype, const char *rvalue, void *data, void *userdata);
/* Legacy IPv4LL support */
int config_parse_ipv4ll(const char *unit, const char *filename, unsigned line, const char *section, unsigned section_line, const char *lvalue, int ltype, const char *rvalue, void *data, void *userdata);
SD_DHCP_OPTION_REBINDING_T2_TIME = 59,
SD_DHCP_OPTION_VENDOR_CLASS_IDENTIFIER = 60,
SD_DHCP_OPTION_CLIENT_IDENTIFIER = 61,
+ SD_DHCP_OPTION_USER_CLASS = 77,
SD_DHCP_OPTION_FQDN = 81,
SD_DHCP_OPTION_NEW_POSIX_TIMEZONE = 100,
SD_DHCP_OPTION_NEW_TZDB_TIMEZONE = 101,
int sd_dhcp_client_set_vendor_class_identifier(
sd_dhcp_client *client,
const char *vci);
+int sd_dhcp_client_set_user_class(
+ sd_dhcp_client *client,
+ const char* const *user_class);
int sd_dhcp_client_get_lease(
sd_dhcp_client *client,
sd_dhcp_lease **ret);