Merge pull request #24221 from yuwata/dhcp-client-cleanups
dhcp: use struct hw_addr_data
This commit is contained in:
@@ -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;
|
||||
|
||||
|
||||
@@ -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) {
|
||||
|
||||
@@ -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,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);
|
||||
|
||||
@@ -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);
|
||||
|
||||
@@ -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(ð_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(ð_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(ð_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,
|
||||
ð_mac, arp_type, dhcp_hlen, port);
|
||||
}
|
||||
|
||||
int dhcp_network_bind_udp_socket(int ifindex, be32_t address, uint16_t port, int ip_service_type) {
|
||||
|
||||
@@ -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 {
|
||||
|
||||
@@ -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;
|
||||
|
||||
@@ -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,
|
||||
|
||||
@@ -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;
|
||||
|
||||
@@ -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);
|
||||
|
||||
@@ -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);
|
||||
|
||||
@@ -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) {
|
||||
|
||||
@@ -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);
|
||||
|
||||
Reference in New Issue
Block a user