/* SPDX-License-Identifier: LGPL-2.1+ */
+#include <linux/if_infiniband.h>
+
#include "libudev.h"
#include "sd-id128.h"
#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;
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;
#include "macro.h"
#include "sparse-endian.h"
+#include "time-util.h"
#include "unaligned.h"
typedef enum DUIDType {
} _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);
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 +
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;