summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
-rw-r--r--src/libsystemd-network/sd-dhcp-client.c91
-rw-r--r--src/libsystemd-network/test-dhcp-client.c44
2 files changed, 74 insertions, 61 deletions
diff --git a/src/libsystemd-network/sd-dhcp-client.c b/src/libsystemd-network/sd-dhcp-client.c
index 65e888adf2..5f90617b9e 100644
--- a/src/libsystemd-network/sd-dhcp-client.c
+++ b/src/libsystemd-network/sd-dhcp-client.c
@@ -36,9 +36,10 @@
#include "dhcp-protocol.h"
#include "dhcp-internal.h"
#include "dhcp-lease-internal.h"
+#include "dhcp-identifier.h"
#include "sd-dhcp-client.h"
-#define MAX_CLIENT_ID_LEN 64 /* Arbitrary limit */
+#define MAX_CLIENT_ID_LEN (sizeof(uint32_t) + MAX_DUID_LEN) /* Arbitrary limit */
#define MAX_MAC_ADDR_LEN INFINIBAND_ALEN
struct sd_dhcp_client {
@@ -60,29 +61,31 @@ struct sd_dhcp_client {
uint8_t mac_addr[MAX_MAC_ADDR_LEN];
size_t mac_addr_len;
uint16_t arp_type;
- union {
- struct {
- uint8_t type; /* 0: Generic (non-LL) (RFC 2132) */
- uint8_t data[MAX_CLIENT_ID_LEN];
- } _packed_ gen;
- struct {
- uint8_t type; /* 1: Ethernet Link-Layer (RFC 2132) */
- uint8_t haddr[ETH_ALEN];
- } _packed_ eth;
- struct {
- uint8_t type; /* 2 - 254: ARP/Link-Layer (RFC 2132) */
- uint8_t haddr[0];
- } _packed_ ll;
- struct {
- uint8_t type; /* 255: Node-specific (RFC 4361) */
- uint8_t iaid[4];
- uint8_t duid[MAX_CLIENT_ID_LEN - 4];
- } _packed_ ns;
- struct {
- uint8_t type;
- uint8_t data[MAX_CLIENT_ID_LEN];
- } _packed_ raw;
- } client_id;
+ struct {
+ uint8_t type;
+ union {
+ struct {
+ /* 0: Generic (non-LL) (RFC 2132) */
+ uint8_t data[MAX_CLIENT_ID_LEN];
+ } _packed_ gen;
+ struct {
+ /* 1: Ethernet Link-Layer (RFC 2132) */
+ uint8_t haddr[ETH_ALEN];
+ } _packed_ eth;
+ struct {
+ /* 2 - 254: ARP/Link-Layer (RFC 2132) */
+ uint8_t haddr[0];
+ } _packed_ ll;
+ struct {
+ /* 255: Node-specific (RFC 4361) */
+ uint32_t iaid;
+ struct duid duid;
+ } _packed_ ns;
+ struct {
+ uint8_t data[MAX_CLIENT_ID_LEN];
+ } _packed_ raw;
+ };
+ } _packed_ client_id;
size_t client_id_len;
char *hostname;
char *vendor_class_identifier;
@@ -239,10 +242,9 @@ int sd_dhcp_client_get_client_id(sd_dhcp_client *client, uint8_t *type,
*data = NULL;
*data_len = 0;
if (client->client_id_len) {
- *type = client->client_id.raw.type;
+ *type = client->client_id.type;
*data = client->client_id.raw.data;
- *data_len = client->client_id_len -
- sizeof (client->client_id.raw.type);
+ *data_len = client->client_id_len - sizeof(client->client_id.type);
}
return 0;
@@ -270,8 +272,8 @@ int sd_dhcp_client_set_client_id(sd_dhcp_client *client, uint8_t type,
break;
}
- if (client->client_id_len == data_len + sizeof (client->client_id.raw.type) &&
- client->client_id.raw.type == type &&
+ if (client->client_id_len == data_len + sizeof(client->client_id.type) &&
+ client->client_id.type == type &&
memcmp(&client->client_id.raw.data, data, data_len) == 0)
return 0;
@@ -282,9 +284,9 @@ int sd_dhcp_client_set_client_id(sd_dhcp_client *client, uint8_t type,
client_stop(client, DHCP_EVENT_STOP);
}
- client->client_id.raw.type = type;
+ client->client_id.type = type;
memcpy(&client->client_id.raw.data, data, data_len);
- client->client_id_len = data_len + sizeof (client->client_id.raw.type);
+ client->client_id_len = data_len + sizeof (client->client_id.type);
if (need_restart && client->state != DHCP_STATE_STOPPED)
sd_dhcp_client_start(client);
@@ -461,12 +463,21 @@ static int client_message_init(sd_dhcp_client *client, DHCPPacket **ret,
if (client->arp_type == ARPHRD_ETHER)
memcpy(&packet->dhcp.chaddr, &client->mac_addr, ETH_ALEN);
- /* If no client identifier exists, construct one from an ethernet
- address if present */
- if (client->client_id_len == 0 && client->arp_type == ARPHRD_ETHER) {
- client->client_id.eth.type = ARPHRD_ETHER;
- memcpy(&client->client_id.eth.haddr, &client->mac_addr, ETH_ALEN);
- client->client_id_len = sizeof (client->client_id.eth);
+ /* If no client identifier exists, construct an RFC 4361-compliant one */
+ if (client->client_id_len == 0) {
+ size_t duid_len;
+
+ client->client_id.type = 255;
+
+ r = dhcp_identifier_set_iaid(client->index, client->mac_addr, client->mac_addr_len, &client->client_id.ns.iaid);
+ if (r < 0)
+ return r;
+
+ r = dhcp_identifier_set_duid_en(&client->client_id.ns.duid, &duid_len);
+ if (r < 0)
+ return r;
+
+ client->client_id_len = sizeof(client->client_id.type) + sizeof(client->client_id.ns.iaid) + duid_len;
}
/* Some DHCP servers will refuse to issue an DHCP lease if the Client
@@ -475,7 +486,7 @@ static int client_message_init(sd_dhcp_client *client, DHCPPacket **ret,
r = dhcp_option_append(&packet->dhcp, optlen, &optoffset, 0,
DHCP_OPTION_CLIENT_IDENTIFIER,
client->client_id_len,
- &client->client_id.raw);
+ &client->client_id);
if (r < 0)
return r;
}
@@ -1031,7 +1042,7 @@ static int client_handle_offer(sd_dhcp_client *client, DHCPMessage *offer,
if (client->client_id_len) {
r = dhcp_lease_set_client_id(lease,
- (uint8_t *) &client->client_id.raw,
+ (uint8_t *) &client->client_id,
client->client_id_len);
if (r < 0)
return r;
@@ -1098,7 +1109,7 @@ static int client_handle_ack(sd_dhcp_client *client, DHCPMessage *ack,
if (client->client_id_len) {
r = dhcp_lease_set_client_id(lease,
- (uint8_t *) &client->client_id.raw,
+ (uint8_t *) &client->client_id,
client->client_id_len);
if (r < 0)
return r;
diff --git a/src/libsystemd-network/test-dhcp-client.c b/src/libsystemd-network/test-dhcp-client.c
index 0515440e4e..a3d69f338c 100644
--- a/src/libsystemd-network/test-dhcp-client.c
+++ b/src/libsystemd-network/test-dhcp-client.c
@@ -32,17 +32,16 @@
#include "sd-event.h"
#include "event-util.h"
+#include "dhcp-identifier.h"
#include "dhcp-protocol.h"
#include "dhcp-internal.h"
#include "sd-dhcp-client.h"
-static struct ether_addr mac_addr = {
- .ether_addr_octet = {'A', 'B', 'C', '1', '2', '3'}
-};
+static uint8_t mac_addr[] = {'A', 'B', 'C', '1', '2', '3'};
typedef int (*test_callback_recv_t)(size_t size, DHCPMessage *dhcp);
-static bool verbose = false;
+static bool verbose = true;
static int test_fd[2];
static test_callback_recv_t callback_recv;
static be32_t xid;
@@ -136,10 +135,22 @@ static int check_options(uint8_t code, uint8_t len, const uint8_t *option,
{
switch(code) {
case DHCP_OPTION_CLIENT_IDENTIFIER:
- assert_se(len == 7);
- assert_se(option[0] == 0x01);
- assert_se(memcmp(&option[1], &mac_addr, ETH_ALEN) == 0);
+ {
+ uint32_t iaid;
+ struct duid duid;
+ size_t duid_len;
+
+ assert_se(dhcp_identifier_set_duid_en(&duid, &duid_len) >= 0);
+ assert_se(dhcp_identifier_set_iaid(42, mac_addr, ETH_ALEN, &iaid) >= 0);
+
+ assert_se(len == sizeof(uint8_t) + sizeof(uint32_t) + duid_len);
+ assert_se(len == 19);
+ assert_se(option[0] == 0xff);
+
+ assert_se(memcmp(&option[1], &iaid, sizeof(iaid)) == 0);
+ assert_se(memcmp(&option[5], &duid, duid_len) == 0);
break;
+ }
default:
break;
@@ -185,8 +196,7 @@ int dhcp_network_send_raw_socket(int s, const union sockaddr_union *link,
assert_se(ip_check == 0xffff);
assert_se(discover->dhcp.xid);
- assert_se(memcmp(discover->dhcp.chaddr,
- &mac_addr.ether_addr_octet, 6) == 0);
+ assert_se(memcmp(discover->dhcp.chaddr, &mac_addr, ETH_ALEN) == 0);
size = len - sizeof(struct iphdr) - sizeof(struct udphdr);
@@ -246,10 +256,7 @@ static void test_discover_message(sd_event *e)
assert_se(r >= 0);
assert_se(sd_dhcp_client_set_index(client, 42) >= 0);
- assert_se(sd_dhcp_client_set_mac(client,
- (const uint8_t *) &mac_addr,
- sizeof (mac_addr),
- ARPHRD_ETHER) >= 0);
+ assert_se(sd_dhcp_client_set_mac(client, mac_addr, ETH_ALEN, ARPHRD_ETHER) >= 0);
assert_se(sd_dhcp_client_set_request_option(client, 248) >= 0);
@@ -404,8 +411,7 @@ static int test_addr_acq_recv_request(size_t size, DHCPMessage *request) {
memcpy(&test_addr_acq_ack[26], &udp_check, sizeof(udp_check));
memcpy(&test_addr_acq_ack[32], &xid, sizeof(xid));
- memcpy(&test_addr_acq_ack[56], &mac_addr.ether_addr_octet,
- ETHER_ADDR_LEN);
+ memcpy(&test_addr_acq_ack[56], &mac_addr, ETHER_ADDR_LEN);
callback_recv = NULL;
@@ -436,8 +442,7 @@ static int test_addr_acq_recv_discover(size_t size, DHCPMessage *discover) {
memcpy(&test_addr_acq_offer[26], &udp_check, sizeof(udp_check));
memcpy(&test_addr_acq_offer[32], &xid, sizeof(xid));
- memcpy(&test_addr_acq_offer[56], &mac_addr.ether_addr_octet,
- ETHER_ADDR_LEN);
+ memcpy(&test_addr_acq_offer[56], &mac_addr, ETHER_ADDR_LEN);
callback_recv = test_addr_acq_recv_request;
@@ -467,10 +472,7 @@ static void test_addr_acq(sd_event *e) {
assert_se(r >= 0);
assert_se(sd_dhcp_client_set_index(client, 42) >= 0);
- assert_se(sd_dhcp_client_set_mac(client,
- (const uint8_t *) &mac_addr,
- sizeof (mac_addr),
- ARPHRD_ETHER) >= 0);
+ assert_se(sd_dhcp_client_set_mac(client, mac_addr, ETH_ALEN, ARPHRD_ETHER) >= 0);
assert_se(sd_dhcp_client_set_callback(client, test_addr_acq_acquired, e)
>= 0);