Merge pull request #24221 from yuwata/dhcp-client-cleanups

dhcp: use struct hw_addr_data
This commit is contained in:
Yu Watanabe
2022-08-08 23:59:58 +09:00
committed by GitHub
14 changed files with 227 additions and 213 deletions
+9
View File
@@ -33,6 +33,15 @@ char *hw_addr_to_string_full(
return buffer;
}
struct hw_addr_data *hw_addr_set(struct hw_addr_data *addr, const uint8_t *bytes, size_t length) {
assert(addr);
assert(length <= HW_ADDR_MAX_SIZE);
addr->length = length;
memcpy_safe(addr->bytes, bytes, length);
return addr;
}
int hw_addr_compare(const struct hw_addr_data *a, const struct hw_addr_data *b) {
int r;
+2
View File
@@ -52,6 +52,8 @@ static inline char *hw_addr_to_string(const struct hw_addr_data *addr, char buff
#define HW_ADDR_NULL ((const struct hw_addr_data){})
struct hw_addr_data *hw_addr_set(struct hw_addr_data *addr, const uint8_t *bytes, size_t length);
void hw_addr_hash_func(const struct hw_addr_data *p, struct siphash *state);
int hw_addr_compare(const struct hw_addr_data *a, const struct hw_addr_data *b);
static inline bool hw_addr_equal(const struct hw_addr_data *a, const struct hw_addr_data *b) {
+34 -21
View File
@@ -63,20 +63,26 @@ int dhcp_validate_duid_len(DUIDType duid_type, size_t duid_len, bool strict) {
return 0;
}
static int dhcp_identifier_set_duid_llt(const uint8_t *addr, size_t addr_len, uint16_t arp_type, usec_t t, struct duid *ret_duid, size_t *ret_len) {
static int dhcp_identifier_set_duid_llt(
const struct hw_addr_data *hw_addr,
uint16_t arp_type,
usec_t t,
struct duid *ret_duid,
size_t *ret_len) {
uint16_t time_from_2000y;
assert(addr);
assert(hw_addr);
assert(ret_duid);
assert(ret_len);
if (addr_len == 0)
if (hw_addr->length == 0)
return -EOPNOTSUPP;
if (arp_type == ARPHRD_ETHER)
assert_return(addr_len == ETH_ALEN, -EINVAL);
assert_return(hw_addr->length == ETH_ALEN, -EINVAL);
else if (arp_type == ARPHRD_INFINIBAND)
assert_return(addr_len == INFINIBAND_ALEN, -EINVAL);
assert_return(hw_addr->length == INFINIBAND_ALEN, -EINVAL);
else
return -EOPNOTSUPP;
@@ -88,33 +94,38 @@ static int dhcp_identifier_set_duid_llt(const uint8_t *addr, size_t addr_len, ui
unaligned_write_be16(&ret_duid->type, DUID_TYPE_LLT);
unaligned_write_be16(&ret_duid->llt.htype, arp_type);
unaligned_write_be32(&ret_duid->llt.time, time_from_2000y);
memcpy(ret_duid->llt.haddr, addr, addr_len);
memcpy(ret_duid->llt.haddr, hw_addr->bytes, hw_addr->length);
*ret_len = offsetof(struct duid, llt.haddr) + addr_len;
*ret_len = offsetof(struct duid, llt.haddr) + hw_addr->length;
return 0;
}
static int dhcp_identifier_set_duid_ll(const uint8_t *addr, size_t addr_len, uint16_t arp_type, struct duid *ret_duid, size_t *ret_len) {
assert(addr);
static int dhcp_identifier_set_duid_ll(
const struct hw_addr_data *hw_addr,
uint16_t arp_type,
struct duid *ret_duid,
size_t *ret_len) {
assert(hw_addr);
assert(ret_duid);
assert(ret_len);
if (addr_len == 0)
if (hw_addr->length == 0)
return -EOPNOTSUPP;
if (arp_type == ARPHRD_ETHER)
assert_return(addr_len == ETH_ALEN, -EINVAL);
assert_return(hw_addr->length == ETH_ALEN, -EINVAL);
else if (arp_type == ARPHRD_INFINIBAND)
assert_return(addr_len == INFINIBAND_ALEN, -EINVAL);
assert_return(hw_addr->length == INFINIBAND_ALEN, -EINVAL);
else
return -EOPNOTSUPP;
unaligned_write_be16(&ret_duid->type, DUID_TYPE_LL);
unaligned_write_be16(&ret_duid->ll.htype, arp_type);
memcpy(ret_duid->ll.haddr, addr, addr_len);
memcpy(ret_duid->ll.haddr, hw_addr->bytes, hw_addr->length);
*ret_len = offsetof(struct duid, ll.haddr) + addr_len;
*ret_len = offsetof(struct duid, ll.haddr) + hw_addr->length;
return 0;
}
@@ -174,8 +185,7 @@ static int dhcp_identifier_set_duid_uuid(struct duid *ret_duid, size_t *ret_len)
int dhcp_identifier_set_duid(
DUIDType duid_type,
const uint8_t *addr,
size_t addr_len,
const struct hw_addr_data *hw_addr,
uint16_t arp_type,
usec_t llt_time,
bool test_mode,
@@ -184,11 +194,11 @@ int dhcp_identifier_set_duid(
switch (duid_type) {
case DUID_TYPE_LLT:
return dhcp_identifier_set_duid_llt(addr, addr_len, arp_type, llt_time, ret_duid, ret_len);
return dhcp_identifier_set_duid_llt(hw_addr, arp_type, llt_time, ret_duid, ret_len);
case DUID_TYPE_EN:
return dhcp_identifier_set_duid_en(test_mode, ret_duid, ret_len);
case DUID_TYPE_LL:
return dhcp_identifier_set_duid_ll(addr, addr_len, arp_type, ret_duid, ret_len);
return dhcp_identifier_set_duid_ll(hw_addr, arp_type, ret_duid, ret_len);
case DUID_TYPE_UUID:
return dhcp_identifier_set_duid_uuid(ret_duid, ret_len);
default:
@@ -198,8 +208,7 @@ int dhcp_identifier_set_duid(
int dhcp_identifier_set_iaid(
int ifindex,
const uint8_t *mac,
size_t mac_len,
const struct hw_addr_data *hw_addr,
bool legacy_unstable_byteorder,
bool use_mac,
void *ret) {
@@ -212,6 +221,10 @@ int dhcp_identifier_set_iaid(
uint64_t id;
int r;
assert(ifindex > 0);
assert(hw_addr);
assert(ret);
if (udev_available() && !use_mac) {
/* udev should be around */
@@ -240,7 +253,7 @@ int dhcp_identifier_set_iaid(
id = siphash24(name, strlen(name), HASH_KEY.bytes);
else
/* fall back to MAC address if no predictable name available */
id = siphash24(mac, mac_len, HASH_KEY.bytes);
id = siphash24(hw_addr->bytes, hw_addr->length, HASH_KEY.bytes);
id32 = (id & 0xffffffff) ^ (id >> 32);
+3 -4
View File
@@ -3,6 +3,7 @@
#include "sd-id128.h"
#include "ether-addr-util.h"
#include "macro.h"
#include "sparse-endian.h"
#include "time-util.h"
@@ -58,8 +59,7 @@ int dhcp_validate_duid_len(DUIDType duid_type, size_t duid_len, bool strict);
int dhcp_identifier_set_duid_en(bool test_mode, struct duid *ret_duid, size_t *ret_len);
int dhcp_identifier_set_duid(
DUIDType duid_type,
const uint8_t *addr,
size_t addr_len,
const struct hw_addr_data *hw_addr,
uint16_t arp_type,
usec_t llt_time,
bool test_mode,
@@ -67,8 +67,7 @@ int dhcp_identifier_set_duid(
size_t *ret_len);
int dhcp_identifier_set_iaid(
int ifindex,
const uint8_t *mac,
size_t mac_len,
const struct hw_addr_data *hw_addr,
bool legacy_unstable_byteorder,
bool use_mac,
void *ret);
+9 -4
View File
@@ -12,6 +12,7 @@
#include "sd-dhcp-client.h"
#include "dhcp-protocol.h"
#include "ether-addr-util.h"
#include "network-common.h"
#include "socket-util.h"
@@ -32,10 +33,14 @@ extern const struct hash_ops dhcp_option_hash_ops;
typedef struct sd_dhcp_client sd_dhcp_client;
int dhcp_network_bind_raw_socket(int ifindex, union sockaddr_union *link, uint32_t xid,
const uint8_t *mac_addr, size_t mac_addr_len,
const uint8_t *bcast_addr, size_t bcast_addr_len,
uint16_t arp_type, uint16_t port);
int dhcp_network_bind_raw_socket(
int ifindex,
union sockaddr_union *link,
uint32_t xid,
const struct hw_addr_data *hw_addr,
const struct hw_addr_data *bcast_addr,
uint16_t arp_type,
uint16_t port);
int dhcp_network_bind_udp_socket(int ifindex, be32_t address, uint16_t port, int ip_service_type);
int dhcp_network_send_raw_socket(int s, const union sockaddr_union *link,
const void *packet, size_t len);
+69 -55
View File
@@ -18,13 +18,34 @@
#include "socket-util.h"
#include "unaligned.h"
static int _bind_raw_socket(int ifindex, union sockaddr_union *link,
uint32_t xid,
const uint8_t *bcast_addr,
size_t bcast_addr_len,
const struct ether_addr *eth_mac,
uint16_t arp_type, uint8_t dhcp_hlen,
uint16_t port) {
static int _bind_raw_socket(
int ifindex,
union sockaddr_union *link,
uint32_t xid,
const struct hw_addr_data *hw_addr,
const struct hw_addr_data *bcast_addr,
uint16_t arp_type,
uint16_t port) {
assert(ifindex > 0);
assert(link);
assert(hw_addr);
assert(bcast_addr);
assert(IN_SET(arp_type, ARPHRD_ETHER, ARPHRD_INFINIBAND));
switch (arp_type) {
case ARPHRD_ETHER:
assert(hw_addr->length == ETH_ALEN);
assert(bcast_addr->length == ETH_ALEN);
break;
case ARPHRD_INFINIBAND:
assert(hw_addr->length == 0);
assert(bcast_addr->length == INFINIBAND_ALEN);
break;
default:
assert_not_reached();
}
struct sock_filter filter[] = {
BPF_STMT(BPF_LD + BPF_W + BPF_LEN, 0), /* A <- packet length */
BPF_JUMP(BPF_JMP + BPF_JGE + BPF_K, sizeof(DHCPPacket), 1, 0), /* packet >= DHCPPacket ? */
@@ -53,20 +74,20 @@ static int _bind_raw_socket(int ifindex, union sockaddr_union *link,
BPF_JUMP(BPF_JMP + BPF_JEQ + BPF_K, xid, 1, 0), /* client identifier == xid ? */
BPF_STMT(BPF_RET + BPF_K, 0), /* ignore */
BPF_STMT(BPF_LD + BPF_B + BPF_ABS, offsetof(DHCPPacket, dhcp.hlen)), /* A <- MAC address length */
BPF_JUMP(BPF_JMP + BPF_JEQ + BPF_K, dhcp_hlen, 1, 0), /* address length == dhcp_hlen ? */
BPF_JUMP(BPF_JMP + BPF_JEQ + BPF_K, (uint8_t) hw_addr->length, 1, 0), /* address length == hw_addr->length ? */
BPF_STMT(BPF_RET + BPF_K, 0), /* ignore */
/* We only support MAC address length to be either 0 or 6 (ETH_ALEN). Optionally
* compare chaddr for ETH_ALEN bytes. */
BPF_JUMP(BPF_JMP + BPF_JEQ + BPF_K, ETH_ALEN, 0, 8), /* A (the MAC address length) == ETH_ALEN ? */
BPF_STMT(BPF_LDX + BPF_IMM, unaligned_read_be32(&eth_mac->ether_addr_octet[0])), /* X <- 4 bytes of client's MAC */
BPF_STMT(BPF_LD + BPF_W + BPF_ABS, offsetof(DHCPPacket, dhcp.chaddr)), /* A <- 4 bytes of MAC from dhcp.chaddr */
BPF_JUMP(BPF_JMP + BPF_JEQ + BPF_X, 0, 1, 0), /* A == X ? */
BPF_STMT(BPF_RET + BPF_K, 0), /* ignore */
BPF_STMT(BPF_LDX + BPF_IMM, unaligned_read_be16(&eth_mac->ether_addr_octet[4])), /* X <- remainder of client's MAC */
BPF_STMT(BPF_LD + BPF_H + BPF_ABS, offsetof(DHCPPacket, dhcp.chaddr) + 4), /* A <- remainder of MAC from dhcp.chaddr */
BPF_JUMP(BPF_JMP + BPF_JEQ + BPF_X, 0, 1, 0), /* A == X ? */
BPF_STMT(BPF_RET + BPF_K, 0), /* ignore */
BPF_JUMP(BPF_JMP + BPF_JEQ + BPF_K, ETH_ALEN, 0, 8), /* A (the MAC address length) == ETH_ALEN ? */
BPF_STMT(BPF_LDX + BPF_IMM, unaligned_read_be32(hw_addr->bytes)), /* X <- 4 bytes of client's MAC */
BPF_STMT(BPF_LD + BPF_W + BPF_ABS, offsetof(DHCPPacket, dhcp.chaddr)), /* A <- 4 bytes of MAC from dhcp.chaddr */
BPF_JUMP(BPF_JMP + BPF_JEQ + BPF_X, 0, 1, 0), /* A == X ? */
BPF_STMT(BPF_RET + BPF_K, 0), /* ignore */
BPF_STMT(BPF_LDX + BPF_IMM, unaligned_read_be16(hw_addr->bytes + 4)), /* X <- remainder of client's MAC */
BPF_STMT(BPF_LD + BPF_H + BPF_ABS, offsetof(DHCPPacket, dhcp.chaddr) + 4), /* A <- remainder of MAC from dhcp.chaddr */
BPF_JUMP(BPF_JMP + BPF_JEQ + BPF_X, 0, 1, 0), /* A == X ? */
BPF_STMT(BPF_RET + BPF_K, 0), /* ignore */
BPF_STMT(BPF_LD + BPF_W + BPF_ABS, offsetof(DHCPPacket, dhcp.magic)), /* A <- DHCP magic cookie */
BPF_JUMP(BPF_JMP + BPF_JEQ + BPF_K, DHCP_MAGIC_COOKIE, 1, 0), /* cookie == DHCP magic cookie ? */
@@ -80,9 +101,6 @@ static int _bind_raw_socket(int ifindex, union sockaddr_union *link,
_cleanup_close_ int s = -1;
int r;
assert(ifindex > 0);
assert(link);
s = socket(AF_PACKET, SOCK_DGRAM | SOCK_CLOEXEC | SOCK_NONBLOCK, 0);
if (s < 0)
return -errno;
@@ -100,9 +118,10 @@ static int _bind_raw_socket(int ifindex, union sockaddr_union *link,
.sll_protocol = htobe16(ETH_P_IP),
.sll_ifindex = ifindex,
.sll_hatype = htobe16(arp_type),
.sll_halen = bcast_addr_len,
.sll_halen = bcast_addr->length,
};
memcpy(link->ll.sll_addr, bcast_addr, bcast_addr_len); /* We may overflow link->ll. link->ll_buffer ensures we have enough space. */
/* We may overflow link->ll. link->ll_buffer ensures we have enough space. */
memcpy(link->ll.sll_addr, bcast_addr->bytes, bcast_addr->length);
r = bind(s, &link->sa, SOCKADDR_LL_LEN(link->ll));
if (r < 0)
@@ -115,47 +134,42 @@ int dhcp_network_bind_raw_socket(
int ifindex,
union sockaddr_union *link,
uint32_t xid,
const uint8_t *mac_addr,
size_t mac_addr_len,
const uint8_t *bcast_addr,
size_t bcast_addr_len,
const struct hw_addr_data *hw_addr,
const struct hw_addr_data *bcast_addr,
uint16_t arp_type,
uint16_t port) {
static const uint8_t eth_bcast[] = { 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF };
/* Default broadcast address for IPoIB */
static const uint8_t ib_bcast[] = {
0x00, 0xff, 0xff, 0xff, 0xff, 0x12, 0x40, 0x1b,
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
0xff, 0xff, 0xff, 0xff
static struct hw_addr_data default_eth_bcast = {
.length = ETH_ALEN,
.ether = {{ 0xff, 0xff, 0xff, 0xff, 0xff, 0xff }},
}, default_ib_bcast = {
.length = INFINIBAND_ALEN,
.infiniband = {
0x00, 0xff, 0xff, 0xff, 0xff, 0x12, 0x40, 0x1b,
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
0xff, 0xff, 0xff, 0xff
},
};
struct ether_addr eth_mac = { { 0, 0, 0, 0, 0, 0 } };
const uint8_t *default_bcast_addr;
size_t expected_bcast_addr_len;
uint8_t dhcp_hlen = 0;
if (arp_type == ARPHRD_ETHER) {
assert_return(mac_addr_len == ETH_ALEN, -EINVAL);
memcpy(&eth_mac, mac_addr, ETH_ALEN);
dhcp_hlen = ETH_ALEN;
assert(ifindex > 0);
assert(link);
assert(hw_addr);
default_bcast_addr = eth_bcast;
expected_bcast_addr_len = ETH_ALEN;
} else if (arp_type == ARPHRD_INFINIBAND) {
default_bcast_addr = ib_bcast;
expected_bcast_addr_len = INFINIBAND_ALEN;
} else
switch (arp_type) {
case ARPHRD_ETHER:
return _bind_raw_socket(ifindex, link, xid,
hw_addr,
(bcast_addr && !hw_addr_is_null(bcast_addr)) ? bcast_addr : &default_eth_bcast,
arp_type, port);
case ARPHRD_INFINIBAND:
return _bind_raw_socket(ifindex, link, xid,
&HW_ADDR_NULL,
(bcast_addr && !hw_addr_is_null(bcast_addr)) ? bcast_addr : &default_ib_bcast,
arp_type, port);
default:
return -EINVAL;
if (bcast_addr && bcast_addr_len > 0)
assert_return(bcast_addr_len == expected_bcast_addr_len, -EINVAL);
else {
bcast_addr = default_bcast_addr;
bcast_addr_len = expected_bcast_addr_len;
}
return _bind_raw_socket(ifindex, link, xid, bcast_addr, bcast_addr_len,
&eth_mac, arp_type, dhcp_hlen, port);
}
int dhcp_network_bind_udp_socket(int ifindex, be32_t address, uint16_t port, int ip_service_type) {
+4 -3
View File
@@ -43,9 +43,10 @@ typedef struct DHCPPacket DHCPPacket;
#define DHCP_IP_SIZE (int32_t)(sizeof(struct iphdr))
#define DHCP_IP_UDP_SIZE (int32_t)(sizeof(struct udphdr) + DHCP_IP_SIZE)
#define DHCP_MESSAGE_SIZE (int32_t)(sizeof(DHCPMessage))
#define DHCP_DEFAULT_MIN_SIZE 576 /* the minimum internet hosts must be able to receive */
#define DHCP_MIN_OPTIONS_SIZE (DHCP_DEFAULT_MIN_SIZE - DHCP_IP_UDP_SIZE - DHCP_MESSAGE_SIZE)
#define DHCP_HEADER_SIZE (int32_t)(sizeof(DHCPMessage))
#define DHCP_MIN_MESSAGE_SIZE 576 /* the minimum internet hosts must be able to receive, see RFC 2132 Section 9.10 */
#define DHCP_MIN_OPTIONS_SIZE (DHCP_MIN_MESSAGE_SIZE - DHCP_HEADER_SIZE)
#define DHCP_MIN_PACKET_SIZE (DHCP_MIN_MESSAGE_SIZE + DHCP_IP_UDP_SIZE)
#define DHCP_MAGIC_COOKIE (uint32_t)(0x63825363)
enum {
+2 -2
View File
@@ -14,8 +14,8 @@ int dhcp_network_bind_raw_socket(
int ifindex,
union sockaddr_union *link,
uint32_t id,
const uint8_t *addr, size_t addr_len,
const uint8_t *bcaddr, size_t bcaddr_len,
const struct hw_addr_data *hw_addr,
const struct hw_addr_data *bcast_addr,
uint16_t arp_type, uint16_t port) {
int fd;
+49 -100
View File
@@ -19,6 +19,7 @@
#include "dhcp-lease-internal.h"
#include "dhcp-protocol.h"
#include "dns-domain.h"
#include "ether-addr-util.h"
#include "event-util.h"
#include "fd-util.h"
#include "hostname-util.h"
@@ -86,10 +87,8 @@ struct sd_dhcp_client {
Set *req_opts;
bool anonymize;
be32_t last_addr;
uint8_t mac_addr[MAX_MAC_ADDR_LEN];
size_t mac_addr_len;
uint8_t bcast_addr[MAX_MAC_ADDR_LEN];
size_t bcast_addr_len;
struct hw_addr_data hw_addr;
struct hw_addr_data bcast_addr;
uint16_t arp_type;
sd_dhcp_client_id client_id;
size_t client_id_len;
@@ -237,6 +236,7 @@ int sd_dhcp_client_set_callback(
int sd_dhcp_client_set_request_broadcast(sd_dhcp_client *client, int broadcast) {
assert_return(client, -EINVAL);
assert_return(!sd_dhcp_client_is_running(client), -EBUSY);
client->request_broadcast = broadcast;
@@ -245,7 +245,7 @@ int sd_dhcp_client_set_request_broadcast(sd_dhcp_client *client, int broadcast)
int sd_dhcp_client_set_request_option(sd_dhcp_client *client, uint8_t option) {
assert_return(client, -EINVAL);
assert_return(IN_SET(client->state, DHCP_STATE_INIT, DHCP_STATE_STOPPED), -EBUSY);
assert_return(!sd_dhcp_client_is_running(client), -EBUSY);
switch (option) {
@@ -268,7 +268,7 @@ int sd_dhcp_client_set_request_address(
const struct in_addr *last_addr) {
assert_return(client, -EINVAL);
assert_return(IN_SET(client->state, DHCP_STATE_INIT, DHCP_STATE_STOPPED), -EBUSY);
assert_return(!sd_dhcp_client_is_running(client), -EBUSY);
if (last_addr)
client->last_addr = last_addr->s_addr;
@@ -280,7 +280,7 @@ int sd_dhcp_client_set_request_address(
int sd_dhcp_client_set_ifindex(sd_dhcp_client *client, int ifindex) {
assert_return(client, -EINVAL);
assert_return(IN_SET(client->state, DHCP_STATE_INIT, DHCP_STATE_STOPPED), -EBUSY);
assert_return(!sd_dhcp_client_is_running(client), -EBUSY);
assert_return(ifindex > 0, -EINVAL);
client->ifindex = ifindex;
@@ -314,54 +314,20 @@ int sd_dhcp_client_get_ifname(sd_dhcp_client *client, const char **ret) {
int sd_dhcp_client_set_mac(
sd_dhcp_client *client,
const uint8_t *addr,
const uint8_t *hw_addr,
const uint8_t *bcast_addr,
size_t addr_len,
uint16_t arp_type) {
DHCP_CLIENT_DONT_DESTROY(client);
bool need_restart = false;
int r;
assert_return(client, -EINVAL);
assert_return(addr, -EINVAL);
assert_return(addr_len > 0 && addr_len <= MAX_MAC_ADDR_LEN, -EINVAL);
assert_return(arp_type > 0, -EINVAL);
assert_return(!sd_dhcp_client_is_running(client), -EBUSY);
assert_return(IN_SET(arp_type, ARPHRD_ETHER, ARPHRD_INFINIBAND), -EINVAL);
assert_return(hw_addr, -EINVAL);
assert_return(addr_len == (arp_type == ARPHRD_ETHER ? ETH_ALEN : INFINIBAND_ALEN), -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
return -EINVAL;
if (client->mac_addr_len == addr_len &&
memcmp(&client->mac_addr, addr, addr_len) == 0 &&
(client->bcast_addr_len > 0) == !!bcast_addr &&
(!bcast_addr || memcmp(&client->bcast_addr, bcast_addr, addr_len) == 0))
return 0;
if (!IN_SET(client->state, DHCP_STATE_INIT, DHCP_STATE_STOPPED)) {
log_dhcp_client(client, "Changing MAC address on running DHCP client, restarting");
need_restart = true;
client_stop(client, SD_DHCP_CLIENT_EVENT_STOP);
}
memcpy(&client->mac_addr, addr, addr_len);
client->mac_addr_len = addr_len;
client->arp_type = arp_type;
client->bcast_addr_len = 0;
if (bcast_addr) {
memcpy(&client->bcast_addr, bcast_addr, addr_len);
client->bcast_addr_len = addr_len;
}
if (need_restart && client->state != DHCP_STATE_STOPPED) {
r = sd_dhcp_client_start(client);
if (r < 0)
return log_dhcp_client_errno(client, r, "Failed to restart DHCPv4 client: %m");
}
hw_addr_set(&client->hw_addr, hw_addr, addr_len);
hw_addr_set(&client->bcast_addr, bcast_addr, bcast_addr ? addr_len : 0);
return 0;
}
@@ -396,19 +362,11 @@ int sd_dhcp_client_set_client_id(
const uint8_t *data,
size_t data_len) {
DHCP_CLIENT_DONT_DESTROY(client);
bool need_restart = false;
int r;
assert_return(client, -EINVAL);
assert_return(!sd_dhcp_client_is_running(client), -EBUSY);
assert_return(data, -EINVAL);
assert_return(data_len > 0 && data_len <= MAX_CLIENT_ID_LEN, -EINVAL);
if (client->client_id_len == data_len + sizeof(client->client_id.type) &&
client->client_id.type == type &&
memcmp(&client->client_id.raw.data, data, data_len) == 0)
return 0;
/* For hardware types, log debug message about unexpected data length.
*
* Note that infiniband's INFINIBAND_ALEN is 20 bytes long, but only
@@ -420,23 +378,10 @@ int sd_dhcp_client_set_client_id(
"unexpected address length %zu",
type, data_len);
if (!IN_SET(client->state, DHCP_STATE_INIT, DHCP_STATE_STOPPED)) {
log_dhcp_client(client, "Changing client ID on running DHCP "
"client, restarting");
need_restart = true;
client_stop(client, SD_DHCP_CLIENT_EVENT_STOP);
}
client->client_id.type = type;
memcpy(&client->client_id.raw.data, data, data_len);
client->client_id_len = data_len + sizeof (client->client_id.type);
if (need_restart && client->state != DHCP_STATE_STOPPED) {
r = sd_dhcp_client_start(client);
if (r < 0)
return log_dhcp_client_errno(client, r, "Failed to restart DHCPv4 client: %m");
}
return 0;
}
@@ -455,11 +400,11 @@ static int dhcp_client_set_iaid_duid_internal(
size_t duid_len,
usec_t llt_time) {
DHCP_CLIENT_DONT_DESTROY(client);
int r;
size_t len;
int r;
assert_return(client, -EINVAL);
assert_return(!sd_dhcp_client_is_running(client), -EBUSY);
assert_return(duid_len == 0 || duid, -EINVAL);
if (duid) {
@@ -475,8 +420,7 @@ static int dhcp_client_set_iaid_duid_internal(
if (iaid_set)
client->client_id.ns.iaid = htobe32(iaid);
else {
r = dhcp_identifier_set_iaid(client->ifindex, client->mac_addr,
client->mac_addr_len,
r = dhcp_identifier_set_iaid(client->ifindex, &client->hw_addr,
/* legacy_unstable_byteorder = */ true,
/* use_mac = */ client->test_mode,
&client->client_id.ns.iaid);
@@ -491,7 +435,7 @@ static int dhcp_client_set_iaid_duid_internal(
len = sizeof(client->client_id.ns.duid.type) + duid_len;
} else {
r = dhcp_identifier_set_duid(duid_type, client->mac_addr, client->mac_addr_len,
r = dhcp_identifier_set_duid(duid_type, &client->hw_addr,
client->arp_type, llt_time, client->test_mode,
&client->client_id.ns.duid, &len);
if (r == -EOPNOTSUPP)
@@ -507,14 +451,6 @@ static int dhcp_client_set_iaid_duid_internal(
client->client_id_len = sizeof(client->client_id.type) + len +
(iaid_append ? sizeof(client->client_id.ns.iaid) : 0);
if (!IN_SET(client->state, DHCP_STATE_INIT, DHCP_STATE_STOPPED)) {
log_dhcp_client(client, "Configured %sDUID, restarting.", iaid_append ? "IAID+" : "");
client_stop(client, SD_DHCP_CLIENT_EVENT_STOP);
r = sd_dhcp_client_start(client);
if (r < 0)
return log_dhcp_client_errno(client, r, "Failed to restart DHCPv4 client: %m");
}
return 0;
}
@@ -561,6 +497,7 @@ int sd_dhcp_client_set_hostname(
const char *hostname) {
assert_return(client, -EINVAL);
assert_return(!sd_dhcp_client_is_running(client), -EBUSY);
/* Make sure hostnames qualify as DNS and as Linux hostnames */
if (hostname &&
@@ -575,6 +512,7 @@ int sd_dhcp_client_set_vendor_class_identifier(
const char *vci) {
assert_return(client, -EINVAL);
assert_return(!sd_dhcp_client_is_running(client), -EBUSY);
return free_and_strdup(&client->vendor_class_identifier, vci);
}
@@ -584,6 +522,7 @@ int sd_dhcp_client_set_mud_url(
const char *mudurl) {
assert_return(client, -EINVAL);
assert_return(!sd_dhcp_client_is_running(client), -EBUSY);
assert_return(mudurl, -EINVAL);
assert_return(strlen(mudurl) <= 255, -EINVAL);
assert_return(http_url_is_valid(mudurl), -EINVAL);
@@ -598,6 +537,7 @@ int sd_dhcp_client_set_user_class(
char **s = NULL;
assert_return(client, -EINVAL);
assert_return(!sd_dhcp_client_is_running(client), -EBUSY);
assert_return(!strv_isempty(user_class), -EINVAL);
STRV_FOREACH(p, user_class) {
@@ -619,6 +559,7 @@ int sd_dhcp_client_set_client_port(
uint16_t port) {
assert_return(client, -EINVAL);
assert_return(!sd_dhcp_client_is_running(client), -EBUSY);
client->port = port;
@@ -627,7 +568,10 @@ int sd_dhcp_client_set_client_port(
int sd_dhcp_client_set_mtu(sd_dhcp_client *client, uint32_t mtu) {
assert_return(client, -EINVAL);
assert_return(mtu >= DHCP_DEFAULT_MIN_SIZE, -ERANGE);
assert_return(mtu >= DHCP_MIN_PACKET_SIZE, -ERANGE);
/* MTU may be changed by the acquired lease. Hence, we cannot require that the client is stopped here.
* Please do not add assertion for !sd_dhcp_client_is_running(client) here. */
client->mtu = mtu;
@@ -636,6 +580,7 @@ int sd_dhcp_client_set_mtu(sd_dhcp_client *client, uint32_t mtu) {
int sd_dhcp_client_set_max_attempts(sd_dhcp_client *client, uint64_t max_attempts) {
assert_return(client, -EINVAL);
assert_return(!sd_dhcp_client_is_running(client), -EBUSY);
client->max_attempts = max_attempts;
@@ -646,6 +591,7 @@ int sd_dhcp_client_add_option(sd_dhcp_client *client, sd_dhcp_option *v) {
int r;
assert_return(client, -EINVAL);
assert_return(!sd_dhcp_client_is_running(client), -EBUSY);
assert_return(v, -EINVAL);
r = ordered_hashmap_ensure_put(&client->extra_options, &dhcp_option_hash_ops, UINT_TO_PTR(v->option), v);
@@ -660,6 +606,7 @@ int sd_dhcp_client_add_vendor_option(sd_dhcp_client *client, sd_dhcp_option *v)
int r;
assert_return(client, -EINVAL);
assert_return(!sd_dhcp_client_is_running(client), -EBUSY);
assert_return(v, -EINVAL);
r = ordered_hashmap_ensure_allocated(&client->vendor_options, &dhcp_option_hash_ops);
@@ -689,6 +636,7 @@ int sd_dhcp_client_get_lease(sd_dhcp_client *client, sd_dhcp_lease **ret) {
int sd_dhcp_client_set_service_type(sd_dhcp_client *client, int type) {
assert_return(client, -EINVAL);
assert_return(!sd_dhcp_client_is_running(client), -EBUSY);
client->ip_service_type = type;
@@ -697,6 +645,7 @@ int sd_dhcp_client_set_service_type(sd_dhcp_client *client, int type) {
int sd_dhcp_client_set_fallback_lease_lifetime(sd_dhcp_client *client, uint32_t fallback_lease_lifetime) {
assert_return(client, -EINVAL);
assert_return(!sd_dhcp_client_is_running(client), -EBUSY);
assert_return(fallback_lease_lifetime > 0, -EINVAL);
client->fallback_lease_lifetime = fallback_lease_lifetime;
@@ -794,7 +743,6 @@ static int client_message_init(
_cleanup_free_ DHCPPacket *packet = NULL;
size_t optlen, optoffset, size;
be16_t max_size;
usec_t time_now;
uint16_t secs;
int r;
@@ -814,7 +762,7 @@ static int client_message_init(
return -ENOMEM;
r = dhcp_message_init(&packet->dhcp, BOOTREQUEST, client->xid, type,
client->arp_type, client->mac_addr_len, client->mac_addr,
client->arp_type, client->hw_addr.length, client->hw_addr.bytes,
optlen, &optoffset);
if (r < 0)
return r;
@@ -851,7 +799,7 @@ static int client_message_init(
client->client_id.type = 255;
r = dhcp_identifier_set_iaid(client->ifindex, client->mac_addr, client->mac_addr_len,
r = dhcp_identifier_set_iaid(client->ifindex, &client->hw_addr,
/* legacy_unstable_byteorder = */ true,
/* use_mac = */ client->test_mode,
&client->client_id.ns.iaid);
@@ -937,9 +885,9 @@ static int client_message_init(
*/
/* RFC7844 section 3:
SHOULD NOT contain any other option. */
if (!client->anonymize && type != DHCP_RELEASE) {
max_size = htobe16(size);
r = dhcp_option_append(&packet->dhcp, client->mtu, &optoffset, 0,
if (!client->anonymize && IN_SET(type, DHCP_DISCOVER, DHCP_REQUEST)) {
be16_t max_size = htobe16(MIN(client->mtu - DHCP_IP_UDP_SIZE, (uint32_t) UINT16_MAX));
r = dhcp_option_append(&packet->dhcp, optlen, &optoffset, 0,
SD_DHCP_OPTION_MAXIMUM_MESSAGE_SIZE,
2, &max_size);
if (r < 0)
@@ -1430,8 +1378,7 @@ static int client_start_delayed(sd_dhcp_client *client) {
client->xid = random_u32();
r = dhcp_network_bind_raw_socket(client->ifindex, &client->link, client->xid,
client->mac_addr, client->mac_addr_len,
client->bcast_addr, client->bcast_addr_len,
&client->hw_addr, &client->bcast_addr,
client->arp_type, client->port);
if (r < 0) {
client_stop(client, r);
@@ -1481,8 +1428,7 @@ static int client_timeout_t2(sd_event_source *s, uint64_t usec, void *userdata)
client->attempt = 0;
r = dhcp_network_bind_raw_socket(client->ifindex, &client->link, client->xid,
client->mac_addr, client->mac_addr_len,
client->bcast_addr, client->bcast_addr_len,
&client->hw_addr, &client->bcast_addr,
client->arp_type, client->port);
if (r < 0) {
client_stop(client, r);
@@ -1946,7 +1892,7 @@ static int client_receive_message_udp(
if (client->arp_type == ARPHRD_ETHER) {
expected_hlen = ETH_ALEN;
expected_chaddr = &client->mac_addr[0];
expected_chaddr = client->hw_addr.bytes;
}
if (message->hlen != expected_hlen) {
@@ -2042,6 +1988,7 @@ static int client_receive_message_raw(
int sd_dhcp_client_send_renew(sd_dhcp_client *client) {
assert_return(client, -EINVAL);
assert_return(sd_dhcp_client_is_running(client), -ESTALE);
assert_return(client->fd >= 0, -EINVAL);
if (!client->lease)
@@ -2089,7 +2036,7 @@ int sd_dhcp_client_start(sd_dhcp_client *client) {
int sd_dhcp_client_send_release(sd_dhcp_client *client) {
assert_return(client, -EINVAL);
assert_return(client->state != DHCP_STATE_STOPPED, -ESTALE);
assert_return(sd_dhcp_client_is_running(client), -ESTALE);
assert_return(client->lease, -EUNATCH);
_cleanup_free_ DHCPPacket *release = NULL;
@@ -2102,7 +2049,7 @@ int sd_dhcp_client_send_release(sd_dhcp_client *client) {
/* Fill up release IP and MAC */
release->dhcp.ciaddr = client->lease->address;
memcpy(&release->dhcp.chaddr, &client->mac_addr, client->mac_addr_len);
memcpy(&release->dhcp.chaddr, client->hw_addr.bytes, client->hw_addr.length);
r = dhcp_option_append(&release->dhcp, optlen, &optoffset, 0,
SD_DHCP_OPTION_END, 0, NULL);
@@ -2124,7 +2071,7 @@ int sd_dhcp_client_send_release(sd_dhcp_client *client) {
int sd_dhcp_client_send_decline(sd_dhcp_client *client) {
assert_return(client, -EINVAL);
assert_return(client->state != DHCP_STATE_STOPPED, -ESTALE);
assert_return(sd_dhcp_client_is_running(client), -ESTALE);
assert_return(client->lease, -EUNATCH);
_cleanup_free_ DHCPPacket *release = NULL;
@@ -2136,7 +2083,7 @@ int sd_dhcp_client_send_decline(sd_dhcp_client *client) {
return r;
release->dhcp.ciaddr = client->lease->address;
memcpy(&release->dhcp.chaddr, &client->mac_addr, client->mac_addr_len);
memcpy(&release->dhcp.chaddr, client->hw_addr.bytes, client->hw_addr.length);
r = dhcp_option_append(&release->dhcp, optlen, &optoffset, 0,
SD_DHCP_OPTION_END, 0, NULL);
@@ -2181,6 +2128,7 @@ int sd_dhcp_client_attach_event(sd_dhcp_client *client, sd_event *event, int64_t
assert_return(client, -EINVAL);
assert_return(!client->event, -EBUSY);
assert_return(!sd_dhcp_client_is_running(client), -EBUSY);
if (event)
client->event = sd_event_ref(event);
@@ -2197,6 +2145,7 @@ int sd_dhcp_client_attach_event(sd_dhcp_client *client, sd_event *event, int64_t
int sd_dhcp_client_detach_event(sd_dhcp_client *client) {
assert_return(client, -EINVAL);
assert_return(!sd_dhcp_client_is_running(client), -EBUSY);
client->event = sd_event_unref(client->event);
@@ -2253,7 +2202,7 @@ int sd_dhcp_client_new(sd_dhcp_client **ret, int anonymize) {
.state = DHCP_STATE_INIT,
.ifindex = -1,
.fd = -1,
.mtu = DHCP_DEFAULT_MIN_SIZE,
.mtu = DHCP_MIN_PACKET_SIZE,
.port = DHCP_PORT_CLIENT,
.anonymize = !!anonymize,
.max_attempts = UINT64_MAX,
+3 -3
View File
@@ -713,9 +713,9 @@ int dhcp_lease_parse_options(uint8_t code, uint8_t len, const void *option, void
r = lease_parse_u16(option, len, &lease->mtu, 68);
if (r < 0)
log_debug_errno(r, "Failed to parse MTU, ignoring: %m");
if (lease->mtu < DHCP_DEFAULT_MIN_SIZE) {
log_debug("MTU value of %" PRIu16 " too small. Using default MTU value of %d instead.", lease->mtu, DHCP_DEFAULT_MIN_SIZE);
lease->mtu = DHCP_DEFAULT_MIN_SIZE;
if (lease->mtu < DHCP_MIN_PACKET_SIZE) {
log_debug("MTU value of %" PRIu16 " too small. Using default MTU value of %d instead.", lease->mtu, DHCP_MIN_PACKET_SIZE);
lease->mtu = DHCP_MIN_PACKET_SIZE;
}
break;
+4 -5
View File
@@ -116,9 +116,8 @@ int sd_dhcp6_client_set_mac(
return 0;
}
memcpy(client->hw_addr.bytes, addr, addr_len);
client->hw_addr.length = addr_len;
client->arp_type = arp_type;
hw_addr_set(&client->hw_addr, addr, addr_len);
return 0;
}
@@ -216,8 +215,8 @@ static int dhcp6_client_set_duid_internal(
client->duid_len = sizeof(client->duid.type) + duid_len;
} else {
r = dhcp_identifier_set_duid(duid_type, client->hw_addr.bytes, client->hw_addr.length,
client->arp_type, llt_time, client->test_mode, &client->duid, &client->duid_len);
r = dhcp_identifier_set_duid(duid_type, &client->hw_addr, client->arp_type, llt_time,
client->test_mode, &client->duid, &client->duid_len);
if (r == -EOPNOTSUPP)
return log_dhcp6_client_errno(client, r,
"Failed to set %s. MAC address is not set or "
@@ -300,7 +299,7 @@ static int client_ensure_iaid(sd_dhcp6_client *client) {
if (client->iaid_set)
return 0;
r = dhcp_identifier_set_iaid(client->ifindex, client->hw_addr.bytes, client->hw_addr.length,
r = dhcp_identifier_set_iaid(client->ifindex, &client->hw_addr,
/* legacy_unstable_byteorder = */ true,
/* use_mac = */ client->test_mode,
&iaid);
+18 -13
View File
@@ -17,14 +17,19 @@
#include "dhcp-identifier.h"
#include "dhcp-internal.h"
#include "dhcp-protocol.h"
#include "ether-addr-util.h"
#include "fd-util.h"
#include "random-util.h"
#include "tests.h"
#include "util.h"
static uint8_t mac_addr[] = {'A', 'B', 'C', '1', '2', '3'};
static uint8_t bcast_addr[] = { 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF };
static struct hw_addr_data hw_addr = {
.length = ETH_ALEN,
.ether = {{ 'A', 'B', 'C', '1', '2', '3' }},
}, bcast_addr = {
.length = ETH_ALEN,
.ether = {{ 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF }},
};
typedef int (*test_callback_recv_t)(size_t size, DHCPMessage *dhcp);
static bool verbose = true;
@@ -139,9 +144,9 @@ static void test_dhcp_identifier_set_iaid(void) {
uint32_t iaid_legacy;
be32_t iaid;
assert_se(dhcp_identifier_set_iaid(42, mac_addr, sizeof(mac_addr), /* legacy = */ true,
assert_se(dhcp_identifier_set_iaid(42, &hw_addr, /* legacy = */ true,
/* use_mac = */ true, &iaid_legacy) >= 0);
assert_se(dhcp_identifier_set_iaid(42, mac_addr, sizeof(mac_addr), /* legacy = */ false,
assert_se(dhcp_identifier_set_iaid(42, &hw_addr, /* legacy = */ false,
/* use_mac = */ true, &iaid) >= 0);
/* we expect, that the MAC address was hashed. The legacy value is in native
@@ -164,7 +169,7 @@ static int check_options(uint8_t code, uint8_t len, const void *option, void *us
size_t duid_len;
assert_se(dhcp_identifier_set_duid_en(/* test_mode = */ true, &duid, &duid_len) >= 0);
assert_se(dhcp_identifier_set_iaid(42, mac_addr, ETH_ALEN, true, /* use_mac = */ true, &iaid) >= 0);
assert_se(dhcp_identifier_set_iaid(42, &hw_addr, /* legacy = */ true, /* use_mac = */ true, &iaid) >= 0);
assert_se(len == sizeof(uint8_t) + sizeof(uint32_t) + duid_len);
assert_se(len == 19);
@@ -217,7 +222,7 @@ int dhcp_network_send_raw_socket(int s, const union sockaddr_union *link, const
assert_se(ip_check == 0xffff);
assert_se(discover->dhcp.xid);
assert_se(memcmp(discover->dhcp.chaddr, &mac_addr, ETH_ALEN) == 0);
assert_se(memcmp(discover->dhcp.chaddr, hw_addr.bytes, hw_addr.length) == 0);
size = len - sizeof(struct iphdr) - sizeof(struct udphdr);
@@ -231,8 +236,8 @@ int dhcp_network_bind_raw_socket(
int ifindex,
union sockaddr_union *link,
uint32_t id,
const uint8_t *addr, size_t addr_len,
const uint8_t *bcaddr, size_t bcaddr_len,
const struct hw_addr_data *_hw_addr,
const struct hw_addr_data *_bcast_addr,
uint16_t arp_type, uint16_t port) {
if (socketpair(AF_UNIX, SOCK_STREAM | SOCK_CLOEXEC | SOCK_NONBLOCK, 0, test_fd) < 0)
@@ -282,7 +287,7 @@ static void test_discover_message(sd_event *e) {
assert_se(r >= 0);
assert_se(sd_dhcp_client_set_ifindex(client, 42) >= 0);
assert_se(sd_dhcp_client_set_mac(client, mac_addr, bcast_addr, ETH_ALEN, ARPHRD_ETHER) >= 0);
assert_se(sd_dhcp_client_set_mac(client, hw_addr.bytes, bcast_addr.bytes, hw_addr.length, ARPHRD_ETHER) >= 0);
dhcp_client_set_test_mode(client, true);
assert_se(sd_dhcp_client_set_request_option(client, 248) >= 0);
@@ -440,7 +445,7 @@ static int test_addr_acq_recv_request(size_t size, DHCPMessage *request) {
memcpy(&test_addr_acq_ack[26], &udp_check, sizeof(udp_check));
memcpy(&test_addr_acq_ack[32], &xid, sizeof(xid));
memcpy(&test_addr_acq_ack[56], &mac_addr, ETHER_ADDR_LEN);
memcpy(&test_addr_acq_ack[56], hw_addr.bytes, hw_addr.length);
callback_recv = NULL;
@@ -471,7 +476,7 @@ static int test_addr_acq_recv_discover(size_t size, DHCPMessage *discover) {
memcpy(&test_addr_acq_offer[26], &udp_check, sizeof(udp_check));
memcpy(&test_addr_acq_offer[32], &xid, sizeof(xid));
memcpy(&test_addr_acq_offer[56], &mac_addr, ETHER_ADDR_LEN);
memcpy(&test_addr_acq_offer[56], hw_addr.bytes, hw_addr.length);
callback_recv = test_addr_acq_recv_request;
@@ -500,7 +505,7 @@ static void test_addr_acq(sd_event *e) {
assert_se(r >= 0);
assert_se(sd_dhcp_client_set_ifindex(client, 42) >= 0);
assert_se(sd_dhcp_client_set_mac(client, mac_addr, bcast_addr, ETH_ALEN, ARPHRD_ETHER) >= 0);
assert_se(sd_dhcp_client_set_mac(client, hw_addr.bytes, bcast_addr.bytes, hw_addr.length, ARPHRD_ETHER) >= 0);
dhcp_client_set_test_mode(client, true);
assert_se(sd_dhcp_client_set_callback(client, test_addr_acq_acquired, e) >= 0);
+20 -2
View File
@@ -1506,6 +1506,7 @@ static int dhcp4_configure(Link *link) {
}
int dhcp4_update_mac(Link *link) {
bool restart;
int r;
assert(link);
@@ -1513,13 +1514,30 @@ int dhcp4_update_mac(Link *link) {
if (!link->dhcp_client)
return 0;
r = sd_dhcp_client_set_mac(link->dhcp_client, link->hw_addr.bytes,
restart = sd_dhcp_client_is_running(link->dhcp_client);
r = sd_dhcp_client_stop(link->dhcp_client);
if (r < 0)
return r;
r = sd_dhcp_client_set_mac(link->dhcp_client,
link->hw_addr.bytes,
link->bcast_addr.length > 0 ? link->bcast_addr.bytes : NULL,
link->hw_addr.length, link->iftype);
if (r < 0)
return r;
return dhcp4_set_client_identifier(link);
r = dhcp4_set_client_identifier(link);
if (r < 0)
return r;
if (restart) {
r = sd_dhcp_client_start(link->dhcp_client);
if (r < 0)
return r;
}
return 0;
}
int dhcp4_start(Link *link) {
+1 -1
View File
@@ -247,7 +247,7 @@ int sd_dhcp_client_set_ifname(
int sd_dhcp_client_get_ifname(sd_dhcp_client *client, const char **ret);
int sd_dhcp_client_set_mac(
sd_dhcp_client *client,
const uint8_t *addr,
const uint8_t *hw_addr,
const uint8_t *bcast_addr,
size_t addr_len,
uint16_t arp_type);