diff options
Diffstat (limited to 'src/libsystemd-network/sd-dhcp-client.c')
-rw-r--r-- | src/libsystemd-network/sd-dhcp-client.c | 103 |
1 files changed, 68 insertions, 35 deletions
diff --git a/src/libsystemd-network/sd-dhcp-client.c b/src/libsystemd-network/sd-dhcp-client.c index 33f3469f07..ff434f8ce7 100644 --- a/src/libsystemd-network/sd-dhcp-client.c +++ b/src/libsystemd-network/sd-dhcp-client.c @@ -1,21 +1,6 @@ /* SPDX-License-Identifier: LGPL-2.1+ */ /*** - This file is part of systemd. - - Copyright (C) 2013 Intel Corporation. All rights reserved. - - systemd is free software; you can redistribute it and/or modify it - under the terms of the GNU Lesser General Public License as published by - the Free Software Foundation; either version 2.1 of the License, or - (at your option) any later version. - - systemd is distributed in the hope that it will be useful, but - WITHOUT ANY WARRANTY; without even the implied warranty of - MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU - Lesser General Public License for more details. - - You should have received a copy of the GNU Lesser General Public License - along with systemd; If not, see <http://www.gnu.org/licenses/>. + Copyright © 2013 Intel Corporation. All rights reserved. ***/ #include <errno.h> @@ -40,6 +25,7 @@ #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) @@ -96,6 +82,7 @@ struct sd_dhcp_client { size_t client_id_len; char *hostname; char *vendor_class_identifier; + char **user_class; uint32_t mtu; uint32_t xid; usec_t start_time; @@ -354,9 +341,10 @@ int sd_dhcp_client_set_client_id( * without further modification. Otherwise, if duid_type is supported, DUID * is set based on that type. Otherwise, an error is returned. */ -int sd_dhcp_client_set_iaid_duid( +static int dhcp_client_set_iaid_duid( sd_dhcp_client *client, uint32_t iaid, + bool append_iaid, uint16_t duid_type, const void *duid, size_t duid_len) { @@ -377,15 +365,17 @@ int sd_dhcp_client_set_iaid_duid( zero(client->client_id); client->client_id.type = 255; - /* If IAID is not configured, generate it. */ - if (iaid == 0) { - r = dhcp_identifier_set_iaid(client->ifindex, client->mac_addr, - client->mac_addr_len, - &client->client_id.ns.iaid); - if (r < 0) - return r; - } else - client->client_id.ns.iaid = htobe32(iaid); + if (append_iaid) { + /* If IAID is not configured, generate it. */ + if (iaid == 0) { + r = dhcp_identifier_set_iaid(client->ifindex, client->mac_addr, + client->mac_addr_len, + &client->client_id.ns.iaid); + if (r < 0) + return r; + } else + client->client_id.ns.iaid = htobe32(iaid); + } if (duid != NULL) { client->client_id.ns.duid.type = htobe16(duid_type); @@ -399,7 +389,7 @@ int sd_dhcp_client_set_iaid_duid( return -EOPNOTSUPP; client->client_id_len = sizeof(client->client_id.type) + len + - sizeof(client->client_id.ns.iaid); + (append_iaid ? sizeof(client->client_id.ns.iaid) : 0); if (!IN_SET(client->state, DHCP_STATE_INIT, DHCP_STATE_STOPPED)) { log_dhcp_client(client, "Configured IAID+DUID, restarting."); @@ -410,6 +400,23 @@ int sd_dhcp_client_set_iaid_duid( return 0; } +int sd_dhcp_client_set_iaid_duid( + sd_dhcp_client *client, + uint32_t iaid, + uint16_t duid_type, + const void *duid, + size_t duid_len) { + return dhcp_client_set_iaid_duid(client, iaid, true, duid_type, duid, duid_len); +} + +int sd_dhcp_client_set_duid( + sd_dhcp_client *client, + uint16_t duid_type, + const void *duid, + size_t duid_len) { + return dhcp_client_set_iaid_duid(client, 0, false, duid_type, duid, duid_len); +} + int sd_dhcp_client_set_hostname( sd_dhcp_client *client, const char *hostname) { @@ -433,6 +440,26 @@ int sd_dhcp_client_set_vendor_class_identifier( 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) { @@ -662,8 +689,7 @@ static int client_message_init( *_optlen = optlen; *_optoffset = optoffset; - *ret = packet; - packet = NULL; + *ret = TAKE_PTR(packet); return 0; } @@ -757,6 +783,15 @@ static int client_send_discover(sd_dhcp_client *client) { 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) @@ -1268,8 +1303,7 @@ static int client_handle_offer(sd_dhcp_client *client, DHCPMessage *offer, size_ } sd_dhcp_lease_unref(client->lease); - client->lease = lease; - lease = NULL; + client->lease = TAKE_PTR(lease); log_dhcp_client(client, "OFFER"); @@ -1350,8 +1384,7 @@ static int client_handle_ack(sd_dhcp_client *client, DHCPMessage *ack, size_t le client->lease = sd_dhcp_lease_unref(client->lease); } - client->lease = lease; - lease = NULL; + client->lease = TAKE_PTR(lease); log_dhcp_client(client, "ACK"); @@ -1914,6 +1947,7 @@ sd_dhcp_client *sd_dhcp_client_unref(sd_dhcp_client *client) { free(client->req_opts); free(client->hostname); free(client->vendor_class_identifier); + client->user_class = strv_free(client->user_class); return mfree(client); } @@ -1946,8 +1980,7 @@ int sd_dhcp_client_new(sd_dhcp_client **ret, int anonymize) { if (!client->req_opts) return -ENOMEM; - *ret = client; - client = NULL; + *ret = TAKE_PTR(client); return 0; } |