1
0
mirror of https://github.com/systemd/systemd.git synced 2024-11-06 08:26:52 +03:00

sd-dhcp: use MAC address when DUIDType=link-layer-time or link-layer but DUIDRawData= is not set

This commit is contained in:
Yu Watanabe 2018-08-07 13:35:58 +09:00
parent f7708f3ffd
commit 335f80a612
4 changed files with 90 additions and 2 deletions

View File

@ -1,5 +1,7 @@
/* SPDX-License-Identifier: LGPL-2.1+ */
#include <linux/if_infiniband.h>
#include "libudev.h"
#include "sd-id128.h"
@ -14,6 +16,7 @@
#define SYSTEMD_PEN 43793
#define HASH_KEY SD_ID128_MAKE(80,11,8c,c2,fe,4a,03,ee,3e,d6,0c,6f,36,39,14,09)
#define APPLICATION_ID SD_ID128_MAKE(a5,0a,d1,12,bf,60,45,77,a2,fb,74,1a,b1,95,5b,03)
#define USEC_2000 ((usec_t) 946684800000000) /* 2000-01-01 00:00:00 UTC */
int dhcp_validate_duid_len(uint16_t duid_type, size_t duid_len) {
struct duid d;
@ -46,6 +49,56 @@ int dhcp_validate_duid_len(uint16_t duid_type, size_t duid_len) {
return 0;
}
int dhcp_identifier_set_duid_llt(struct duid *duid, usec_t t, const uint8_t *addr, size_t addr_len, uint16_t arp_type, size_t *len) {
uint16_t time_from_2000y;
assert(duid);
assert(len);
assert(addr);
if (arp_type == ARPHRD_ETHER)
assert_return(addr_len == ETH_ALEN, -EINVAL);
else if (arp_type == ARPHRD_INFINIBAND)
assert_return(addr_len == INFINIBAND_ALEN, -EINVAL);
else
return -EINVAL;
if (t < USEC_2000)
time_from_2000y = 0;
else
time_from_2000y = (uint16_t) (((t - USEC_2000) / USEC_PER_SEC) & 0xffffffff);
unaligned_write_be16(&duid->type, DUID_TYPE_LLT);
unaligned_write_be16(&duid->llt.htype, arp_type);
unaligned_write_be32(&duid->llt.time, time_from_2000y);
memcpy(duid->llt.haddr, addr, addr_len);
*len = sizeof(duid->type) + sizeof(duid->llt.htype) + sizeof(duid->llt.time) + addr_len;
return 0;
}
int dhcp_identifier_set_duid_ll(struct duid *duid, const uint8_t *addr, size_t addr_len, uint16_t arp_type, size_t *len) {
assert(duid);
assert(len);
assert(addr);
if (arp_type == ARPHRD_ETHER)
assert_return(addr_len == ETH_ALEN, -EINVAL);
else if (arp_type == ARPHRD_INFINIBAND)
assert_return(addr_len == INFINIBAND_ALEN, -EINVAL);
else
return -EINVAL;
unaligned_write_be16(&duid->type, DUID_TYPE_LL);
unaligned_write_be16(&duid->ll.htype, arp_type);
memcpy(duid->ll.haddr, addr, addr_len);
*len = sizeof(duid->type) + sizeof(duid->ll.htype) + addr_len;
return 0;
}
int dhcp_identifier_set_duid_en(struct duid *duid, size_t *len) {
sd_id128_t machine_id;
uint64_t hash;

View File

@ -5,6 +5,7 @@
#include "macro.h"
#include "sparse-endian.h"
#include "time-util.h"
#include "unaligned.h"
typedef enum DUIDType {
@ -52,6 +53,8 @@ struct duid {
} _packed_;
int dhcp_validate_duid_len(uint16_t duid_type, size_t duid_len);
int dhcp_identifier_set_duid_llt(struct duid *duid, usec_t t, const uint8_t *addr, size_t addr_len, uint16_t arp_type, size_t *len);
int dhcp_identifier_set_duid_ll(struct duid *duid, const uint8_t *addr, size_t addr_len, uint16_t arp_type, size_t *len);
int dhcp_identifier_set_duid_en(struct duid *duid, size_t *len);
int dhcp_identifier_set_duid_uuid(struct duid *duid, size_t *len);
int dhcp_identifier_set_iaid(int ifindex, uint8_t *mac, size_t mac_len, void *_id);

View File

@ -383,18 +383,34 @@ static int dhcp_client_set_iaid_duid(
len = sizeof(client->client_id.ns.duid.type) + duid_len;
} else
switch (duid_type) {
case DUID_TYPE_LLT:
if (!client->mac_addr || client->mac_addr_len == 0)
return -EOPNOTSUPP;
r = dhcp_identifier_set_duid_llt(&client->client_id.ns.duid, 0, client->mac_addr, client->mac_addr_len, client->arp_type, &len);
if (r < 0)
return r;
break;
case DUID_TYPE_EN:
r = dhcp_identifier_set_duid_en(&client->client_id.ns.duid, &len);
if (r < 0)
return r;
break;
case DUID_TYPE_LL:
if (!client->mac_addr || client->mac_addr_len == 0)
return -EOPNOTSUPP;
r = dhcp_identifier_set_duid_ll(&client->client_id.ns.duid, client->mac_addr, client->mac_addr_len, client->arp_type, &len);
if (r < 0)
return r;
break;
case DUID_TYPE_UUID:
r = dhcp_identifier_set_duid_uuid(&client->client_id.ns.duid, &len);
if (r < 0)
return r;
break;
default:
return -EOPNOTSUPP;
return -EINVAL;
}
client->client_id_len = sizeof(client->client_id.type) + len +

View File

@ -203,18 +203,34 @@ int sd_dhcp6_client_set_duid(
client->duid_len = sizeof(client->duid.type) + duid_len;
} else
switch (duid_type) {
case DUID_TYPE_LLT:
if (!client->mac_addr || client->mac_addr_len == 0)
return -EOPNOTSUPP;
r = dhcp_identifier_set_duid_llt(&client->duid, 0, client->mac_addr, client->mac_addr_len, client->arp_type, &client->duid_len);
if (r < 0)
return r;
break;
case DUID_TYPE_EN:
r = dhcp_identifier_set_duid_en(&client->duid, &client->duid_len);
if (r < 0)
return r;
break;
case DUID_TYPE_LL:
if (!client->mac_addr || client->mac_addr_len == 0)
return -EOPNOTSUPP;
r = dhcp_identifier_set_duid_ll(&client->duid, client->mac_addr, client->mac_addr_len, client->arp_type, &client->duid_len);
if (r < 0)
return r;
break;
case DUID_TYPE_UUID:
r = dhcp_identifier_set_duid_uuid(&client->duid, &client->duid_len);
if (r < 0)
return r;
break;
default:
return -EOPNOTSUPP;
return -EINVAL;
}
return 0;