Skip to content

Commit

Permalink
dhcp4: initial support to request custom options
Browse files Browse the repository at this point in the history
  • Loading branch information
mtomaschewski committed Jul 21, 2016
1 parent 599ff47 commit 0f5e990
Show file tree
Hide file tree
Showing 8 changed files with 118 additions and 32 deletions.
17 changes: 17 additions & 0 deletions client/compat.c
Expand Up @@ -180,6 +180,7 @@ ni_compat_netdev_free(ni_compat_netdev_t *compat)
ni_string_free(&compat->dhcp4.client_id);
ni_string_free(&compat->dhcp4.vendor_class);
ni_string_array_destroy(&compat->dhcp4.user_class.class_id);
ni_string_array_destroy(&compat->dhcp4.request_options);

ni_string_free(&compat->dhcp6.hostname);
ni_string_free(&compat->dhcp6.client_id);
Expand Down Expand Up @@ -1981,6 +1982,22 @@ __ni_compat_generate_dhcp4_addrconf(xml_node_t *ifnode, const ni_compat_netdev_t
__ni_compat_generate_dhcp4_user_class(dhcp, &compat->dhcp4.user_class);
}

if (compat->dhcp4.request_options.count) {
xml_node_t *req;
unsigned int i;

req = xml_node_new("request-options", NULL);
for (i = 0; req && i < compat->dhcp4.request_options.count; ++i) {
const char *opt = compat->dhcp4.request_options.data[i];
xml_node_new_element("option", req, opt);
}
if (req->children) {
xml_node_add_child(dhcp, req);
} else {
xml_node_free(req);
}
}

return dhcp;
}

Expand Down
28 changes: 28 additions & 0 deletions client/suse/compat-suse.c
Expand Up @@ -4628,6 +4628,32 @@ __ni_suse_parse_dhcp4_user_class(const ni_sysconfig_t *sc, ni_compat_netdev_t *c
return TRUE;
}

static void
__ni_suse_parse_dhcp4_req_options(const ni_sysconfig_t *sc, ni_compat_netdev_t *compat, const char *prefix)
{
ni_string_array_t vars = NI_STRING_ARRAY_INIT;
ni_string_array_t opts = NI_STRING_ARRAY_INIT;
const char *value;
unsigned int i, j;
unsigned int code;

ni_sysconfig_find_matching(sc, prefix, &vars);
for (i = 0; i < vars.count; ++i) {
value = ni_sysconfig_get_value(sc, vars.data[i]);
ni_string_split(&opts, value, " ", 0);
for (j = 0; j < opts.count; ++j) {
const char *opt = opts.data[j];

/* numeric option codes only for now */
if (ni_parse_uint(opt, &code, 10) || !code || code >= 255)
continue;
ni_string_array_append(&compat->dhcp4.request_options, opt);
}
ni_string_array_destroy(&opts);
}
ni_string_array_destroy(&vars);
}

/*
* Process DHCPv4 addrconf
*/
Expand Down Expand Up @@ -4714,6 +4740,8 @@ __ni_suse_addrconf_dhcp4_options(const ni_sysconfig_t *sc, ni_compat_netdev_t *c
}
}

__ni_suse_parse_dhcp4_req_options(sc, compat, "DHCLIENT_REQUEST_OPTION");

return ret;
}

Expand Down
2 changes: 2 additions & 0 deletions client/wicked-client.h
Expand Up @@ -76,6 +76,8 @@ typedef struct ni_compat_netdev {

unsigned int route_priority;
unsigned int update;

ni_string_array_t request_options;
} dhcp4;
struct {
ni_bool_t enabled;
Expand Down
5 changes: 5 additions & 0 deletions dhcp4/dbus-api.c
Expand Up @@ -265,6 +265,8 @@ static ni_dbus_class_t ni_objectmodel_dhcp4req_class = {
NI_DBUS_GENERIC_BOOL_PROPERTY(dhcp4_request, dbus_name, member_name, rw)
#define DHCP4REQ_PROPERTY_SIGNATURE(signature, __name, rw) \
__NI_DBUS_PROPERTY(signature, __name, __dhcp4_request, rw)
#define DHCP4REQ_STRING_ARRAY_PROPERTY(dbus_name, member_name, rw) \
NI_DBUS_GENERIC_STRING_ARRAY_PROPERTY(dhcp4_request, dbus_name, member_name, rw)

static ni_dhcp4_request_t *
__ni_objectmodel_get_dhcp4_request(const ni_dbus_object_t *object, DBusError *error)
Expand Down Expand Up @@ -403,6 +405,9 @@ static ni_dbus_property_t dhcp4_request_properties[] = {
DHCP4REQ_UINT_PROPERTY(update, update, RO),
DHCP4REQ_STRING_PROPERTY(hostname, hostname, RO),
DHCP4REQ_UINT_PROPERTY(route-priority, route_priority, RO),

DHCP4REQ_STRING_ARRAY_PROPERTY(request-options, request_options, RO),

{ NULL },
};

Expand Down
2 changes: 2 additions & 0 deletions schema/addrconf.xml
Expand Up @@ -198,6 +198,8 @@
<update type="builtin-addrconf-update-mask" />
<hostname type="string" />
<route-priority type="uint32" />

<request-options class="array" element-type="string" element-name="option" />
</define>
<define name="properties" type="interface:addrconf-lease"/>

Expand Down
20 changes: 18 additions & 2 deletions src/dhcp4/device.c
Expand Up @@ -113,9 +113,11 @@ ni_dhcp4_device_stop(ni_dhcp4_device_t *dev)
void
ni_dhcp4_device_set_config(ni_dhcp4_device_t *dev, ni_dhcp4_config_t *config)
{
if (dev->config && dev->config->user_class.class_id.count)
if (dev->config) {
ni_string_array_destroy(&dev->config->user_class.class_id);
free(dev->config);
ni_uint_array_destroy(&dev->config->request_options);
free(dev->config);
}
dev->config = config;
}

Expand Down Expand Up @@ -256,6 +258,7 @@ ni_dhcp4_acquire(ni_dhcp4_device_t *dev, const ni_dhcp4_request_t *info)
{
ni_dhcp4_config_t *config;
const char *classid;
unsigned int i, n;
size_t len;
int rv;

Expand Down Expand Up @@ -333,6 +336,18 @@ ni_dhcp4_acquire(ni_dhcp4_device_t *dev, const ni_dhcp4_request_t *info)
ni_trace(" recover_lease %s", config->recover_lease ? "true" : "false");
ni_trace(" release_lease %s", config->release_lease ? "true" : "false");
}
for (n = i = 0; i < info->request_options.count; ++i) {
const char *option = info->request_options.data[i];
unsigned int code;

if (ni_parse_uint(option, &code, 10) || !code || code >= 255)
continue;

if (!ni_uint_array_contains(&config->request_options, code)) {
ni_debug_dhcp(" request-option[%u]: %u", n++, code);
ni_uint_array_append(&config->request_options, code);
}
}

ni_dhcp4_device_set_config(dev, config);

Expand Down Expand Up @@ -839,6 +854,7 @@ ni_dhcp4_request_free(ni_dhcp4_request_t *req)
ni_string_free(&req->clientid);
ni_string_free(&req->vendor_class);
ni_string_array_destroy(&req->user_class.class_id);
ni_string_array_destroy(&req->request_options);
free(req);
}

Expand Down
3 changes: 3 additions & 0 deletions src/dhcp4/dhcp4.h
Expand Up @@ -154,6 +154,8 @@ struct ni_dhcp4_request {
char * hostname;
unsigned int route_priority;

ni_string_array_t request_options;

/* Options what to update based on the info received from
* the DHCP4 server.
* This is a bitmap; individual bits correspond to
Expand Down Expand Up @@ -188,6 +190,7 @@ struct ni_dhcp4_config {
/* A combination of DHCP4_DO_* flags above */
unsigned int update;
unsigned int doflags;
ni_uint_array_t request_options;

unsigned int route_priority;

Expand Down
73 changes: 43 additions & 30 deletions src/dhcp4/protocol.c
Expand Up @@ -369,6 +369,8 @@ __ni_dhcp4_build_msg_put_option_request(const ni_dhcp4_device_t *dev,
{
const ni_dhcp4_config_t *options = dev->config;
unsigned int params_begin;
ni_uint_array_t oro = NI_UINT_ARRAY_INIT;
unsigned int i, code;

switch (msg_code) {
case DHCP4_DISCOVER:
Expand All @@ -381,13 +383,13 @@ __ni_dhcp4_build_msg_put_option_request(const ni_dhcp4_device_t *dev,

params_begin = ni_dhcp4_option_begin(msgbuf, DHCP4_PARAMETERREQUESTLIST);
if (msg_code != DHCP4_INFORM) {
ni_buffer_putc(msgbuf, DHCP4_RENEWALTIME);
ni_buffer_putc(msgbuf, DHCP4_REBINDTIME);
ni_uint_array_append(&oro, DHCP4_RENEWALTIME);
ni_uint_array_append(&oro, DHCP4_REBINDTIME);
}
ni_buffer_putc(msgbuf, DHCP4_NETMASK);
ni_buffer_putc(msgbuf, DHCP4_BROADCAST);
ni_uint_array_append(&oro, DHCP4_NETMASK);
ni_uint_array_append(&oro, DHCP4_BROADCAST);
if (options->doflags & DHCP4_DO_MTU) {
ni_buffer_putc(msgbuf, DHCP4_MTU);
ni_uint_array_append(&oro, DHCP4_MTU);
}

/*
Expand All @@ -396,66 +398,77 @@ __ni_dhcp4_build_msg_put_option_request(const ni_dhcp4_device_t *dev,
* Keep them in front also on request... just in case.
*/
if (options->doflags & DHCP4_DO_CSR) {
ni_buffer_putc(msgbuf, DHCP4_CSR);
ni_uint_array_append(&oro, DHCP4_CSR);
}
if (options->doflags & DHCP4_DO_MSCSR) {
ni_buffer_putc(msgbuf, DHCP4_MSCSR);
ni_uint_array_append(&oro, DHCP4_MSCSR);
}
if (options->doflags & DHCP4_DO_GATEWAY) {
ni_buffer_putc(msgbuf, DHCP4_STATICROUTE);
ni_buffer_putc(msgbuf, DHCP4_ROUTERS);
ni_uint_array_append(&oro, DHCP4_STATICROUTE);
ni_uint_array_append(&oro, DHCP4_ROUTERS);
}
if (options->doflags & DHCP4_DO_HOSTNAME) {
if (options->fqdn == FQDN_DISABLE) {
ni_buffer_putc(msgbuf, DHCP4_HOSTNAME);
ni_uint_array_append(&oro, DHCP4_HOSTNAME);
} else {
ni_buffer_putc(msgbuf, DHCP4_FQDN);
ni_uint_array_append(&oro, DHCP4_FQDN);
}
}
if (options->doflags & DHCP4_DO_DNS) {
ni_buffer_putc(msgbuf, DHCP4_DNSSEARCH);
ni_buffer_putc(msgbuf, DHCP4_DNSDOMAIN);
ni_buffer_putc(msgbuf, DHCP4_DNSSERVER);
ni_uint_array_append(&oro, DHCP4_DNSSEARCH);
ni_uint_array_append(&oro, DHCP4_DNSDOMAIN);
ni_uint_array_append(&oro, DHCP4_DNSSERVER);
}
if (options->doflags & DHCP4_DO_NIS) {
ni_buffer_putc(msgbuf, DHCP4_NISDOMAIN);
ni_buffer_putc(msgbuf, DHCP4_NISSERVER);
ni_uint_array_append(&oro, DHCP4_NISDOMAIN);
ni_uint_array_append(&oro, DHCP4_NISSERVER);
}
if (options->doflags & DHCP4_DO_NTP) {
ni_buffer_putc(msgbuf, DHCP4_NTPSERVER);
ni_uint_array_append(&oro, DHCP4_NTPSERVER);
}
if (options->doflags & DHCP4_DO_ROOT) {
ni_buffer_putc(msgbuf, DHCP4_ROOTPATH);
ni_uint_array_append(&oro, DHCP4_ROOTPATH);
}
if (options->doflags & DHCP4_DO_LPR) {
ni_buffer_putc(msgbuf, DHCP4_LPRSERVER);
ni_uint_array_append(&oro, DHCP4_LPRSERVER);
}
if (options->doflags & DHCP4_DO_LOG) {
ni_buffer_putc(msgbuf, DHCP4_LOGSERVER);
ni_uint_array_append(&oro, DHCP4_LOGSERVER);
}
if (options->doflags & DHCP4_DO_NDS) {
ni_buffer_putc(msgbuf, DHCP4_NDS_SERVER);
ni_buffer_putc(msgbuf, DHCP4_NDS_TREE);
ni_buffer_putc(msgbuf, DHCP4_NDS_CTX);
ni_uint_array_append(&oro, DHCP4_NDS_SERVER);
ni_uint_array_append(&oro, DHCP4_NDS_TREE);
ni_uint_array_append(&oro, DHCP4_NDS_CTX);
}
if (options->doflags & DHCP4_DO_SIP) {
ni_buffer_putc(msgbuf, DHCP4_SIPSERVER);
ni_uint_array_append(&oro, DHCP4_SIPSERVER);
}
if (options->doflags & DHCP4_DO_SMB) {
ni_buffer_putc(msgbuf, DHCP4_NETBIOSNAMESERVER);
ni_buffer_putc(msgbuf, DHCP4_NETBIOSDDSERVER);
ni_buffer_putc(msgbuf, DHCP4_NETBIOSNODETYPE);
ni_buffer_putc(msgbuf, DHCP4_NETBIOSSCOPE);
ni_uint_array_append(&oro, DHCP4_NETBIOSNAMESERVER);
ni_uint_array_append(&oro, DHCP4_NETBIOSDDSERVER);
ni_uint_array_append(&oro, DHCP4_NETBIOSNODETYPE);
ni_uint_array_append(&oro, DHCP4_NETBIOSSCOPE);
}
if (options->doflags & DHCP4_DO_POSIX_TZ) {
ni_buffer_putc(msgbuf, DHCP4_POSIX_TZ_STRING);
ni_buffer_putc(msgbuf, DHCP4_POSIX_TZ_DBNAME);
ni_uint_array_append(&oro, DHCP4_POSIX_TZ_STRING);
ni_uint_array_append(&oro, DHCP4_POSIX_TZ_DBNAME);
}

for (i = 0; i < options->request_options.count; ++i) {
code = options->request_options.data[i];
if (!ni_uint_array_contains(&oro, code))
ni_uint_array_append(&oro, code);
}
for (i = 0; i < oro.count; ++i) {
code = oro.data[i];
ni_buffer_putc(msgbuf, code);
}
ni_dhcp4_option_end(msgbuf, params_begin);

ni_debug_verbose(NI_LOG_DEBUG1, NI_TRACE_DHCP,
"%s: using an option request", dev->ifname);

ni_uint_array_destroy(&oro);
return 0;
}

Expand Down

0 comments on commit 0f5e990

Please sign in to comment.