diff options
author | Dan Williams <dcbw@redhat.com> | 2014-10-08 14:15:45 -0500 |
---|---|---|
committer | Tom Gundersen <teg@jklm.no> | 2014-10-11 12:15:54 +0200 |
commit | 76253e73f9c9c24fec755e485516f3b55d0707b4 (patch) | |
tree | ae99dc09b50a8d8de2428dbc6e6b57f51ef6776c /src/libsystemd-network/sd-dhcp6-client.c | |
parent | 5482192e5774f52f2af0665a3b58539295e9c0a4 (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.c | 36 |
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); |