Merge pull request #24002 from yuwata/network-hw-addr

network: fix hardware address handling
This commit is contained in:
Luca Boccassi
2022-07-14 11:22:55 +01:00
committed by GitHub
9 changed files with 89 additions and 53 deletions
+7 -7
View File
@@ -508,7 +508,7 @@ int dhcp6_option_parse(
if (buflen < offsetof(DHCP6Option, data))
return -EBADMSG;
if (*offset >= buflen - offsetof(DHCP6Option, data))
if (*offset > buflen - offsetof(DHCP6Option, data))
return -EBADMSG;
len = unaligned_read_be16(buf + *offset + offsetof(DHCP6Option, len));
@@ -518,14 +518,14 @@ int dhcp6_option_parse(
*ret_option_code = unaligned_read_be16(buf + *offset + offsetof(DHCP6Option, code));
*ret_option_data_len = len;
*ret_option_data = buf + *offset + offsetof(DHCP6Option, data);
*ret_option_data = len == 0 ? NULL : buf + *offset + offsetof(DHCP6Option, data);
*offset += offsetof(DHCP6Option, data) + len;
return 0;
}
int dhcp6_option_parse_status(const uint8_t *data, size_t data_len, char **ret_status_message) {
assert(data);
assert(data || data_len == 0);
if (data_len < sizeof(uint16_t))
return -EBADMSG;
@@ -803,7 +803,7 @@ int dhcp6_option_parse_addresses(
struct in6_addr **addrs,
size_t *count) {
assert(optval);
assert(optval || optlen == 0);
assert(addrs);
assert(count);
@@ -826,8 +826,8 @@ static int parse_domain(const uint8_t **data, size_t *len, char **ret) {
int r;
assert(data);
assert(*data);
assert(len);
assert(*data || *len == 0);
assert(ret);
optval = *data;
@@ -891,7 +891,7 @@ int dhcp6_option_parse_domainname(const uint8_t *optval, size_t optlen, char **r
_cleanup_free_ char *domain = NULL;
int r;
assert(optval);
assert(optval || optlen == 0);
assert(ret);
r = parse_domain(&optval, &optlen, &domain);
@@ -910,7 +910,7 @@ int dhcp6_option_parse_domainname_list(const uint8_t *optval, size_t optlen, cha
_cleanup_strv_free_ char **names = NULL;
int r;
assert(optval);
assert(optval || optlen == 0);
assert(ret);
if (optlen <= 1)
+22 -12
View File
@@ -467,7 +467,9 @@ static int dhcp6_lease_parse_message(
r = dhcp6_option_parse(message->options, len, &offset, &optcode, &optlen, &optval);
if (r < 0)
return r;
return log_dhcp6_client_errno(client, r,
"Failed to parse option header at offset %zu of total length %zu: %m",
offset, len);
switch (optcode) {
case SD_DHCP6_OPTION_CLIENTID:
@@ -477,7 +479,7 @@ static int dhcp6_lease_parse_message(
r = dhcp6_lease_set_clientid(lease, optval, optlen);
if (r < 0)
return r;
return log_dhcp6_client_errno(client, r, "Failed to set client ID: %m");
break;
@@ -488,17 +490,17 @@ static int dhcp6_lease_parse_message(
r = dhcp6_lease_set_serverid(lease, optval, optlen);
if (r < 0)
return r;
return log_dhcp6_client_errno(client, r, "Failed to set server ID: %m");
break;
case SD_DHCP6_OPTION_PREFERENCE:
if (optlen != 1)
return -EINVAL;
return log_dhcp6_client_errno(client, SYNTHETIC_ERRNO(EINVAL), "Received invalid length for preference.");
r = dhcp6_lease_set_preference(lease, optval[0]);
if (r < 0)
return r;
return log_dhcp6_client_errno(client, r, "Failed to set preference: %m");
break;
@@ -507,7 +509,7 @@ static int dhcp6_lease_parse_message(
r = dhcp6_option_parse_status(optval, optlen, &msg);
if (r < 0)
return r;
return log_dhcp6_client_errno(client, r, "Failed to parse status code: %m");
if (r > 0)
return log_dhcp6_client_errno(client, SYNTHETIC_ERRNO(EINVAL),
@@ -527,9 +529,11 @@ static int dhcp6_lease_parse_message(
r = dhcp6_option_parse_ia(client, client->ia_na.header.id, optcode, optlen, optval, &ia);
if (r == -ENOMEM)
return r;
if (r < 0)
return log_oom_debug();
if (r < 0) {
log_dhcp6_client_errno(client, r, "Failed to parse IA_NA option, ignoring: %m");
continue;
}
if (lease->ia_na) {
log_dhcp6_client(client, "Received duplicate matching IA_NA option, ignoring.");
@@ -550,9 +554,11 @@ static int dhcp6_lease_parse_message(
r = dhcp6_option_parse_ia(client, client->ia_pd.header.id, optcode, optlen, optval, &ia);
if (r == -ENOMEM)
return r;
if (r < 0)
return log_oom_debug();
if (r < 0) {
log_dhcp6_client_errno(client, r, "Failed to parse IA_PD option, ignoring: %m");
continue;
}
if (lease->ia_pd) {
log_dhcp6_client(client, "Received duplicate matching IA_PD option, ignoring.");
@@ -564,9 +570,12 @@ static int dhcp6_lease_parse_message(
break;
}
case SD_DHCP6_OPTION_RAPID_COMMIT:
if (optlen != 0)
log_dhcp6_client(client, "Received rapid commit option with an invalid length (%zu), ignoring.", optlen);
r = dhcp6_lease_set_rapid_commit(lease);
if (r < 0)
return r;
return log_dhcp6_client_errno(client, r, "Failed to set rapid commit flag: %m");
break;
@@ -607,7 +616,8 @@ static int dhcp6_lease_parse_message(
case SD_DHCP6_OPTION_INFORMATION_REFRESH_TIME:
if (optlen != 4)
return -EINVAL;
return log_dhcp6_client_errno(client, SYNTHETIC_ERRNO(EINVAL),
"Received information refresh time option with an invalid length (%zu).", optlen);
irt = unaligned_read_be32((be32_t *) optval) * USEC_PER_SEC;
break;
@@ -443,6 +443,48 @@ TEST(client_parse_message_issue_22099) {
assert_se(dhcp6_lease_new_from_message(client, (const DHCP6Message*) msg, sizeof(msg), NULL, NULL, &lease) >= 0);
}
TEST(client_parse_message_issue_24002) {
static const uint8_t msg[] = {
/* Message Type */
0x07,
/* Transaction ID */
0x0e, 0xa5, 0x7c,
/* Client ID */
0x00, SD_DHCP6_OPTION_CLIENTID, 0x00, 0x0e,
0x00, 0x02, /* DUID-EN */
0x00, 0x00, 0xab, 0x11, /* pen */
0x5c, 0x6b, 0xaa, 0xbb, 0xcc, 0xdd, 0xee, 0xff, /* id */
/* Server ID */
0x00, 0x02, 0x00, 0x1a,
0x00, 0x02, 0x00, 0x00, 0x05, 0x83, 0x30, 0x63, 0x3a, 0x38, 0x00, 0x11, 0x22, 0x33, 0x44, 0x55,
0x66, 0x77, 0x88, 0x99, 0xaa, 0xbb, 0xcc, 0xdd, 0xee, 0xff,
/* IA_PD */
0x00, 0x19, 0x00, 0x29,
0xaa, 0xbb, 0xcc, 0xdd, /* iaid */
0x00, 0x00, 0x03, 0x84, /* lifetime (T1) */
0x00, 0x00, 0x05, 0xa0, /* lifetime (T2) */
/* IA_PD (iaprefix suboption) */
0x00, 0x1a, 0x00, 0x19,
0x00, 0x00, 0x07, 0x08, /* preferred lifetime */
0x00, 0x00, 0x38, 0x40, /* valid lifetime */
0x38, /* prefixlen */
0x20, 0x03, 0x00, 0xff, 0xaa, 0xbb, 0xcc, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, /* prefix */
/* Rapid commit */
0x00, 0x0e, 0x00, 0x00,
};
static const uint8_t duid[] = {
0x00, 0x00, 0xab, 0x11, 0x5c, 0x6b, 0xaa, 0xbb, 0xcc, 0xdd, 0xee, 0xff,
};
_cleanup_(sd_dhcp6_client_unrefp) sd_dhcp6_client *client = NULL;
_cleanup_(sd_dhcp6_lease_unrefp) sd_dhcp6_lease *lease = NULL;
assert_se(sd_dhcp6_client_new(&client) >= 0);
assert_se(sd_dhcp6_client_set_iaid(client, 0xaabbccdd) >= 0);
assert_se(sd_dhcp6_client_set_duid(client, 2, duid, sizeof(duid)) >= 0);
assert_se(dhcp6_lease_new_from_message(client, (const DHCP6Message*) msg, sizeof(msg), NULL, NULL, &lease) >= 0);
}
static const uint8_t msg_information_request[] = {
/* Message type */
DHCP6_MESSAGE_INFORMATION_REQUEST,
+4 -7
View File
@@ -52,6 +52,10 @@ bool link_dhcp_enabled(Link *link, int family) {
assert(link);
assert(IN_SET(family, AF_INET, AF_INET6));
/* Currently, sd-dhcp-client supports only ethernet and infiniband. */
if (family == AF_INET && !IN_SET(link->iftype, ARPHRD_ETHER, ARPHRD_INFINIBAND))
return false;
if (family == AF_INET6 && !socket_ipv6_is_supported())
return false;
@@ -61,13 +65,6 @@ bool link_dhcp_enabled(Link *link, int family) {
if (link->iftype == ARPHRD_CAN)
return false;
if (!IN_SET(link->hw_addr.length, ETH_ALEN, INFINIBAND_ALEN) &&
!streq_ptr(link->kind, "wwan"))
/* Currently, only interfaces whose MAC address length is ETH_ALEN or INFINIBAND_ALEN
* are supported. Note, wwan interfaces may be assigned MAC address slightly later.
* Hence, let's wait for a while.*/
return false;
if (!link->network)
return false;
-5
View File
@@ -1545,11 +1545,6 @@ static int dhcp4_process_request(Request *req, Link *link, void *userdata) {
if (!IN_SET(link->state, LINK_STATE_CONFIGURING, LINK_STATE_CONFIGURED))
return 0;
if (!IN_SET(link->hw_addr.length, ETH_ALEN, INFINIBAND_ALEN) ||
hw_addr_is_null(&link->hw_addr))
/* No MAC address is assigned to the hardware, or non-supported MAC address length. */
return 0;
r = dhcp4_configure_duid(link);
if (r <= 0)
return r;
-5
View File
@@ -738,11 +738,6 @@ static int dhcp6_process_request(Request *req, Link *link, void *userdata) {
if (!IN_SET(link->state, LINK_STATE_CONFIGURING, LINK_STATE_CONFIGURED))
return 0;
if (!IN_SET(link->hw_addr.length, ETH_ALEN, INFINIBAND_ALEN) ||
hw_addr_is_null(&link->hw_addr))
/* No MAC address is assigned to the hardware, or non-supported MAC address length. */
return 0;
r = dhcp_configure_duid(link, link_get_dhcp6_duid(link));
if (r <= 0)
return r;
+1 -1
View File
@@ -2192,7 +2192,7 @@ static int link_update_hardware_address(Link *link, sd_netlink_message *message)
if (r < 0)
return log_link_debug_errno(link, r, "Could not update MAC address for Router Advertisement: %m");
if (link->ndisc) {
if (link->ndisc && link->hw_addr.length == ETH_ALEN) {
r = sd_ndisc_set_mac(link->ndisc, &link->hw_addr.ether);
if (r < 0)
return log_link_debug_errno(link, r, "Could not update MAC for NDisc: %m");
+5 -13
View File
@@ -38,12 +38,6 @@ bool link_ipv6_accept_ra_enabled(Link *link) {
if (link->iftype == ARPHRD_CAN)
return false;
if (link->hw_addr.length != ETH_ALEN && !streq_ptr(link->kind, "wwan"))
/* Currently, only interfaces whose MAC address length is ETH_ALEN are supported.
* Note, wwan interfaces may be assigned MAC address slightly later.
* Hence, let's wait for a while.*/
return false;
if (!link->network)
return false;
@@ -1060,9 +1054,11 @@ static int ndisc_configure(Link *link) {
if (r < 0)
return r;
r = sd_ndisc_set_mac(link->ndisc, &link->hw_addr.ether);
if (r < 0)
return r;
if (link->hw_addr.length == ETH_ALEN) {
r = sd_ndisc_set_mac(link->ndisc, &link->hw_addr.ether);
if (r < 0)
return r;
}
r = sd_ndisc_set_ifindex(link->ndisc, link->ifindex);
if (r < 0)
@@ -1106,10 +1102,6 @@ static int ndisc_process_request(Request *req, Link *link, void *userdata) {
if (!IN_SET(link->state, LINK_STATE_CONFIGURING, LINK_STATE_CONFIGURED))
return 0;
if (link->hw_addr.length != ETH_ALEN || hw_addr_is_null(&link->hw_addr))
/* No MAC address is assigned to the hardware, or non-supported MAC address length. */
return 0;
r = ndisc_configure(link);
if (r < 0)
return log_link_warning_errno(link, r, "Failed to configure IPv6 Router Discovery: %m");
+8 -3
View File
@@ -458,9 +458,11 @@ static int radv_configure(Link *link) {
if (r < 0)
return r;
r = sd_radv_set_mac(link->radv, &link->hw_addr.ether);
if (r < 0)
return r;
if (link->hw_addr.length == ETH_ALEN) {
r = sd_radv_set_mac(link->radv, &link->hw_addr.ether);
if (r < 0)
return r;
}
r = sd_radv_set_ifindex(link->radv, link->ifindex);
if (r < 0)
@@ -518,6 +520,9 @@ int radv_update_mac(Link *link) {
if (!link->radv)
return 0;
if (link->hw_addr.length != ETH_ALEN)
return 0;
restart = sd_radv_is_running(link->radv);
r = sd_radv_stop(link->radv);