#include <errno.h>
#include <string.h>
#include <sys/ioctl.h>
+#include <linux/if_infiniband.h>
#include "udev.h"
#include "udev-util.h"
*/
#define MAX_DUID_LEN 128
+#define MAX_MAC_ADDR_LEN INFINIBAND_ALEN
+
struct sd_dhcp6_client {
RefCount n_ref;
sd_event *event;
int event_priority;
int index;
- struct ether_addr mac_addr;
+ uint8_t mac_addr[MAX_MAC_ADDR_LEN];
+ size_t mac_addr_len;
+ uint16_t arp_type;
DHCP6IA ia_na;
be32_t transaction_id;
usec_t transaction_start;
sd_dhcp6_client_cb_t cb;
void *userdata;
union {
+ struct {
+ uint16_t type; /* DHCP6_DUID_LLT */
+ uint16_t htype;
+ uint32_t time;
+ uint8_t haddr[0];
+ } _packed_ llt;
struct {
uint16_t type; /* DHCP6_DUID_EN */
uint32_t pen;
uint8_t id[8];
} _packed_ en;
+ struct {
+ uint16_t type; /* DHCP6_DUID_LL */
+ uint16_t htype;
+ uint8_t haddr[0];
+ } _packed_ ll;
+ struct {
+ uint16_t type; /* DHCP6_DUID_UUID */
+ sd_id128_t uuid;
+ } _packed_ uuid;
struct {
uint16_t type;
uint8_t data[MAX_DUID_LEN];
return 0;
}
-int sd_dhcp6_client_set_mac(sd_dhcp6_client *client,
- const struct ether_addr *mac_addr)
+int sd_dhcp6_client_set_mac(sd_dhcp6_client *client, const uint8_t *addr,
+ size_t addr_len, uint16_t arp_type)
{
assert_return(client, -EINVAL);
-
- if (mac_addr)
- memcpy(&client->mac_addr, mac_addr, sizeof(client->mac_addr));
+ assert_return(addr, -EINVAL);
+ assert_return(addr_len > 0 && addr_len <= MAX_MAC_ADDR_LEN, -EINVAL);
+ assert_return(arp_type > 0, -EINVAL);
+
+ 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
- memset(&client->mac_addr, 0x00, sizeof(client->mac_addr));
+ return -EINVAL;
+
+ if (client->mac_addr_len == addr_len &&
+ memcmp(&client->mac_addr, addr, addr_len) == 0)
+ return 0;
+
+ memcpy(&client->mac_addr, addr, addr_len);
+ client->mac_addr_len = addr_len;
+ client->arp_type = arp_type;
return 0;
}
assert_return(duid, -EINVAL);
assert_return(duid_len > 0 && duid_len <= MAX_DUID_LEN, -EINVAL);
+ switch (type) {
+ case DHCP6_DUID_LLT:
+ if (duid_len <= sizeof(client->duid.llt) - 2)
+ return -EINVAL;
+ break;
+ case DHCP6_DUID_EN:
+ if (duid_len != sizeof(client->duid.en) - 2)
+ return -EINVAL;
+ break;
+ case DHCP6_DUID_LL:
+ if (duid_len <= sizeof(client->duid.ll) - 2)
+ return -EINVAL;
+ break;
+ case DHCP6_DUID_UUID:
+ if (duid_len != sizeof(client->duid.uuid) - 2)
+ return -EINVAL;
+ break;
+ default:
+ /* accept unknown type in order to be forward compatible */
+ break;
+ }
+
client->duid.raw.type = htobe16(type);
memcpy(&client->duid.raw.data, duid, duid_len);
- client->duid_len = duid_len;
+ client->duid_len = duid_len + 2; /* +2 for sizeof(type) */
return 0;
}
if (r < 0)
goto error;
- r = sd_event_source_set_name(client->timeout_resend,
- "dhcp6-resend-timer");
+ r = sd_event_source_set_description(client->timeout_resend, "dhcp6-resend-timer");
if (r < 0)
goto error;
if (r < 0)
goto error;
- r = sd_event_source_set_name(client->timeout_resend_expire,
- "dhcp6-resend-expire-timer");
+ r = sd_event_source_set_description(client->timeout_resend_expire, "dhcp6-resend-expire-timer");
if (r < 0)
goto error;
}
siphash24((uint8_t*)&id, name, strlen(name), HASH_KEY.bytes);
else
/* fall back to mac address if no predictable name available */
- siphash24((uint8_t*)&id, &client->mac_addr, ETH_ALEN,
- HASH_KEY.bytes);
+ siphash24((uint8_t*)&id, &client->mac_addr,
+ client->mac_addr_len, HASH_KEY.bytes);
/* fold into 32 bits */
client->ia_na.id = (id & 0xffffffff) ^ (id >> 32);
if (r < 0)
return r;
- r = sd_event_source_set_name(client->receive_message,
- "dhcp6-receive-message");
+ r = sd_event_source_set_description(client->receive_message, "dhcp6-receive-message");
if (r < 0)
return r;
if (r < 0)
return r;
- r = sd_event_source_set_name(client->lease->ia.timeout_t1,
- "dhcp6-t1-timeout");
+ r = sd_event_source_set_description(client->lease->ia.timeout_t1, "dhcp6-t1-timeout");
if (r < 0)
return r;
if (r < 0)
return r;
- r = sd_event_source_set_name(client->lease->ia.timeout_t2,
- "dhcp6-t2-timeout");
+ r = sd_event_source_set_description(client->lease->ia.timeout_t2, "dhcp6-t2-timeout");
if (r < 0)
return r;
if (r < 0)
return r;
- r = sd_event_source_set_name(client->timeout_resend,
- "dhcp6-resend-timeout");
+ r = sd_event_source_set_description(client->timeout_resend, "dhcp6-resend-timeout");
if (r < 0)
return r;