#include "network-internal.h"
#include "siphash24.h"
#include "sparse-endian.h"
+#include "stdio-util.h"
#include "virt.h"
#define SYSTEMD_PEN 43793
#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) {
+int dhcp_validate_duid_len(uint16_t duid_type, size_t duid_len, bool strict) {
struct duid d;
assert_cc(sizeof(d.raw) >= MAX_DUID_LEN);
if (duid_len > MAX_DUID_LEN)
return -EINVAL;
+ if (!strict) {
+ /* Strict validation is not requested. We only ensure that the
+ * DUID is not too long. */
+ return 0;
+ }
+
switch (duid_type) {
case DUID_TYPE_LLT:
if (duid_len <= sizeof(d.llt))
return 0;
}
-int dhcp_identifier_set_iaid(int ifindex, uint8_t *mac, size_t mac_len, void *_id) {
+int dhcp_identifier_set_iaid(
+ int ifindex,
+ const uint8_t *mac,
+ size_t mac_len,
+ bool legacy_unstable_byteorder,
+ void *_id) {
/* name is a pointer to memory in the sd_device struct, so must
* have the same scope */
_cleanup_(sd_device_unrefp) sd_device *device = NULL;
const char *name = NULL;
uint64_t id;
+ uint32_t id32;
if (detect_container() <= 0) {
/* not in a container, udev will be around */
- char ifindex_str[2 + DECIMAL_STR_MAX(int)];
- int initialized, r;
+ char ifindex_str[1 + DECIMAL_STR_MAX(int)];
+ int r;
- sprintf(ifindex_str, "n%d", ifindex);
+ xsprintf(ifindex_str, "n%d", ifindex);
if (sd_device_new_from_device_id(&device, ifindex_str) >= 0) {
- r = sd_device_get_is_initialized(device, &initialized);
+ r = sd_device_get_is_initialized(device);
if (r < 0)
return r;
- if (!initialized)
+ if (r == 0)
/* not yet ready */
return -EBUSY;
/* fall back to MAC address if no predictable name available */
id = siphash24(mac, mac_len, HASH_KEY.bytes);
- id = htole64(id);
+ id32 = (id & 0xffffffff) ^ (id >> 32);
- /* fold into 32 bits */
- unaligned_write_be32(_id, (id & 0xffffffff) ^ (id >> 32));
+ if (legacy_unstable_byteorder)
+ /* for historical reasons (a bug), the bits were swapped and thus
+ * the result was endianness dependent. Preserve that behavior. */
+ id32 = __bswap_32(id32);
+ else
+ /* the fixed behavior returns a stable byte order. Since LE is expected
+ * to be more common, swap the bytes on LE to give the same as legacy
+ * behavior. */
+ id32 = be32toh(id32);
+ unaligned_write_ne32(_id, id32);
return 0;
}