summaryrefslogtreecommitdiff
path: root/src/libsystemd-network/sd-dhcp6-client.c
diff options
context:
space:
mode:
authorDan Williams <dcbw@redhat.com>2014-10-08 14:15:45 -0500
committerTom Gundersen <teg@jklm.no>2014-10-11 12:15:54 +0200
commit76253e73f9c9c24fec755e485516f3b55d0707b4 (patch)
treeae99dc09b50a8d8de2428dbc6e6b57f51ef6776c /src/libsystemd-network/sd-dhcp6-client.c
parent5482192e5774f52f2af0665a3b58539295e9c0a4 (diff)
sd-dhcp-client: support non-Ethernet hardware addresses
Like Infiniband. See RFC 4390 section 2.1 for details on DHCP and Infiniband; chaddr is zeroed, hlen is set to 0, and htype is set to ARPHRD_INFINIBAND because IB hardware addresses are 20 bytes in length.
Diffstat (limited to 'src/libsystemd-network/sd-dhcp6-client.c')
-rw-r--r--src/libsystemd-network/sd-dhcp6-client.c36
1 files changed, 27 insertions, 9 deletions
diff --git a/src/libsystemd-network/sd-dhcp6-client.c b/src/libsystemd-network/sd-dhcp6-client.c
index 6ea68c915f..fa4f9b5dc2 100644
--- a/src/libsystemd-network/sd-dhcp6-client.c
+++ b/src/libsystemd-network/sd-dhcp6-client.c
@@ -22,6 +22,7 @@
#include <errno.h>
#include <string.h>
#include <sys/ioctl.h>
+#include <linux/if_infiniband.h>
#include "udev.h"
#include "udev-util.h"
@@ -44,6 +45,8 @@
*/
#define MAX_DUID_LEN 128
+#define MAX_MAC_ADDR_LEN INFINIBAND_ALEN
+
struct sd_dhcp6_client {
RefCount n_ref;
@@ -51,7 +54,9 @@ struct sd_dhcp6_client {
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;
@@ -160,15 +165,28 @@ int sd_dhcp6_client_set_index(sd_dhcp6_client *client, int interface_index)
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;
}
@@ -646,8 +664,8 @@ static int client_ensure_iaid(sd_dhcp6_client *client) {
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);