mirror of
https://gitlab.freedesktop.org/NetworkManager/NetworkManager
synced 2024-07-21 10:14:41 +00:00
platform: merge branch 'th/platform-nl-extack-msg'
https://gitlab.freedesktop.org/NetworkManager/NetworkManager/-/merge_requests/1543
This commit is contained in:
commit
206bd71dbc
|
@ -815,7 +815,7 @@ nm_netns_ip_route_ecmp_commit(NMNetns *self,
|
|||
if (changed || is_reapply) {
|
||||
_LOGT("ecmp-route: multi-hop %s",
|
||||
nmp_object_to_string(route_obj, NMP_OBJECT_TO_STRING_PUBLIC, sbuf, sizeof(sbuf)));
|
||||
nm_platform_ip_route_add(priv->platform, NMP_NLM_FLAG_APPEND, route_obj);
|
||||
nm_platform_ip_route_add(priv->platform, NMP_NLM_FLAG_APPEND, route_obj, NULL);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
|
|
@ -102,7 +102,9 @@ static gboolean ip6_address_add(NMPlatform *platform,
|
|||
struct in6_addr peer_addr,
|
||||
guint32 lifetime,
|
||||
guint32 preferred,
|
||||
guint flags);
|
||||
guint flags,
|
||||
char **out_extack_msg);
|
||||
|
||||
static gboolean
|
||||
ip6_address_delete(NMPlatform *platform, int ifindex, struct in6_addr addr, guint8 plen);
|
||||
|
||||
|
@ -542,7 +544,7 @@ link_changed(NMPlatform *platform,
|
|||
nm_platform_cache_update_emit_signal(platform, cache_op, obj_old, device->obj);
|
||||
|
||||
if (!IN6_IS_ADDR_UNSPECIFIED(&device->ip6_lladdr)) {
|
||||
if (device->obj->link.connected)
|
||||
if (device->obj->link.connected) {
|
||||
ip6_address_add(platform,
|
||||
device->obj->link.ifindex,
|
||||
device->ip6_lladdr,
|
||||
|
@ -550,8 +552,9 @@ link_changed(NMPlatform *platform,
|
|||
in6addr_any,
|
||||
NM_PLATFORM_LIFETIME_PERMANENT,
|
||||
NM_PLATFORM_LIFETIME_PERMANENT,
|
||||
0);
|
||||
else
|
||||
0,
|
||||
NULL);
|
||||
} else
|
||||
ip6_address_delete(platform, device->obj->link.ifindex, device->ip6_lladdr, 64);
|
||||
}
|
||||
|
||||
|
@ -865,7 +868,10 @@ mesh_set_ssid(NMPlatform *platform, int ifindex, const guint8 *ssid, gsize len)
|
|||
/*****************************************************************************/
|
||||
|
||||
static gboolean
|
||||
ipx_address_add(NMPlatform *platform, int addr_family, const NMPlatformObject *address)
|
||||
ipx_address_add(NMPlatform *platform,
|
||||
int addr_family,
|
||||
const NMPlatformObject *address,
|
||||
char **out_extack_msg)
|
||||
{
|
||||
nm_auto_nmpobj NMPObject *obj = NULL;
|
||||
NMPCacheOpsType cache_op;
|
||||
|
@ -874,6 +880,7 @@ ipx_address_add(NMPlatform *platform, int addr_family, const NMPlatformObject *a
|
|||
NMPCache *cache = nm_platform_get_cache(platform);
|
||||
|
||||
g_assert(NM_IN_SET(addr_family, AF_INET, AF_INET6));
|
||||
g_assert(!out_extack_msg || !*out_extack_msg);
|
||||
|
||||
obj = nmp_object_new(addr_family == AF_INET ? NMP_OBJECT_TYPE_IP4_ADDRESS
|
||||
: NMP_OBJECT_TYPE_IP6_ADDRESS,
|
||||
|
@ -894,7 +901,8 @@ ip4_address_add(NMPlatform *platform,
|
|||
guint32 lifetime,
|
||||
guint32 preferred,
|
||||
guint32 flags,
|
||||
const char *label)
|
||||
const char *label,
|
||||
char **out_extack_msg)
|
||||
{
|
||||
NMPlatformIP4Address address;
|
||||
|
||||
|
@ -914,7 +922,7 @@ ip4_address_add(NMPlatform *platform,
|
|||
if (label)
|
||||
g_strlcpy(address.label, label, sizeof(address.label));
|
||||
|
||||
return ipx_address_add(platform, AF_INET, (const NMPlatformObject *) &address);
|
||||
return ipx_address_add(platform, AF_INET, (const NMPlatformObject *) &address, out_extack_msg);
|
||||
}
|
||||
|
||||
static gboolean
|
||||
|
@ -925,7 +933,8 @@ ip6_address_add(NMPlatform *platform,
|
|||
struct in6_addr peer_addr,
|
||||
guint32 lifetime,
|
||||
guint32 preferred,
|
||||
guint32 flags)
|
||||
guint32 flags,
|
||||
char **out_extack_msg)
|
||||
{
|
||||
NMPlatformIP6Address address;
|
||||
|
||||
|
@ -942,7 +951,7 @@ ip6_address_add(NMPlatform *platform,
|
|||
address.preferred = preferred;
|
||||
address.n_ifa_flags = flags;
|
||||
|
||||
return ipx_address_add(platform, AF_INET6, (const NMPlatformObject *) &address);
|
||||
return ipx_address_add(platform, AF_INET6, (const NMPlatformObject *) &address, out_extack_msg);
|
||||
}
|
||||
|
||||
static gboolean
|
||||
|
@ -1092,7 +1101,7 @@ object_delete(NMPlatform *platform, const NMPObject *obj)
|
|||
}
|
||||
|
||||
static int
|
||||
ip_route_add(NMPlatform *platform, NMPNlmFlags flags, NMPObject *obj_stack)
|
||||
ip_route_add(NMPlatform *platform, NMPNlmFlags flags, NMPObject *obj_stack, char **out_extack_msg)
|
||||
{
|
||||
NMDedupMultiIter iter;
|
||||
nm_auto_nmpobj NMPObject *obj = NULL;
|
||||
|
@ -1114,6 +1123,7 @@ ip_route_add(NMPlatform *platform, NMPNlmFlags flags, NMPObject *obj_stack)
|
|||
g_assert(NM_IN_SET(NMP_OBJECT_GET_TYPE(obj_stack),
|
||||
NMP_OBJECT_TYPE_IP4_ROUTE,
|
||||
NMP_OBJECT_TYPE_IP6_ROUTE));
|
||||
g_assert(!out_extack_msg || !*out_extack_msg);
|
||||
|
||||
addr_family = NMP_OBJECT_GET_ADDR_FAMILY(obj_stack);
|
||||
|
||||
|
|
|
@ -77,6 +77,7 @@ test_cleanup_internal(void)
|
|||
lifetime,
|
||||
preferred,
|
||||
0,
|
||||
NULL,
|
||||
NULL));
|
||||
g_assert(nm_platform_ip6_address_add(NM_PLATFORM_GET,
|
||||
ifindex,
|
||||
|
@ -85,7 +86,8 @@ test_cleanup_internal(void)
|
|||
in6addr_any,
|
||||
lifetime,
|
||||
preferred,
|
||||
flags));
|
||||
flags,
|
||||
NULL));
|
||||
nmtstp_ip4_route_add(NM_PLATFORM_GET,
|
||||
ifindex,
|
||||
NM_IP_CONFIG_SOURCE_USER,
|
||||
|
|
|
@ -1809,7 +1809,8 @@ _ip_address_add(NMPlatform *platform,
|
|||
lifetime,
|
||||
preferred,
|
||||
flags,
|
||||
label);
|
||||
label,
|
||||
NULL);
|
||||
} else {
|
||||
g_assert(label == NULL);
|
||||
success = nm_platform_ip6_address_add(platform,
|
||||
|
@ -1819,7 +1820,8 @@ _ip_address_add(NMPlatform *platform,
|
|||
peer_address->addr6,
|
||||
lifetime,
|
||||
preferred,
|
||||
flags);
|
||||
flags,
|
||||
NULL);
|
||||
}
|
||||
g_assert(success);
|
||||
}
|
||||
|
|
|
@ -421,7 +421,8 @@ test_ip6_route(void)
|
|||
in6addr_any,
|
||||
NM_PLATFORM_LIFETIME_PERMANENT,
|
||||
NM_PLATFORM_LIFETIME_PERMANENT,
|
||||
0));
|
||||
0,
|
||||
NULL));
|
||||
accept_signals(route_added, 0, 3);
|
||||
|
||||
_wait_for_ipv6_addr_non_tentative(NM_PLATFORM_GET, 200, ifindex, 1, &pref_src);
|
||||
|
@ -706,7 +707,8 @@ test_ip4_route_options(gconstpointer test_data)
|
|||
a->lifetime,
|
||||
a->preferred,
|
||||
a->n_ifa_flags,
|
||||
a->label));
|
||||
a->label,
|
||||
NULL));
|
||||
if (a->peer_address == a->address)
|
||||
_wait_for_ipv4_addr_device_route(NM_PLATFORM_GET, 200, a->ifindex, a->address, a->plen);
|
||||
}
|
||||
|
@ -878,7 +880,8 @@ test_ip6_route_options(gconstpointer test_data)
|
|||
addr[i].peer_address,
|
||||
addr[i].lifetime,
|
||||
addr[i].preferred,
|
||||
addr[i].n_ifa_flags));
|
||||
addr[i].n_ifa_flags,
|
||||
NULL));
|
||||
}
|
||||
_wait_for_ipv6_addr_non_tentative(NM_PLATFORM_GET, 400, IFINDEX, addr_n, addr_in6);
|
||||
|
||||
|
|
|
@ -465,7 +465,7 @@ typedef enum _nm_packed {
|
|||
|
||||
typedef struct {
|
||||
WaitForNlResponseResult *out_seq_result;
|
||||
char **out_errmsg;
|
||||
char **out_extack_msg;
|
||||
union {
|
||||
int *out_refresh_all_in_progress;
|
||||
NMPObject **out_route_get;
|
||||
|
@ -482,9 +482,6 @@ typedef struct {
|
|||
typedef struct {
|
||||
guint32 nlh_seq_next;
|
||||
guint32 nlh_seq_last_seen;
|
||||
#if NM_MORE_LOGGING
|
||||
guint32 nlh_seq_last_handled;
|
||||
#endif
|
||||
} NetlinkProtocolPrivData;
|
||||
|
||||
typedef struct {
|
||||
|
@ -709,7 +706,7 @@ wait_for_nl_response_to_nmerr(WaitForNlResponseResult seq_result)
|
|||
|
||||
static const char *
|
||||
wait_for_nl_response_to_string(WaitForNlResponseResult seq_result,
|
||||
const char *errmsg,
|
||||
const char *extack_msg,
|
||||
char *buf,
|
||||
gsize buf_size)
|
||||
{
|
||||
|
@ -735,8 +732,8 @@ wait_for_nl_response_to_string(WaitForNlResponseResult seq_result,
|
|||
"failure %d (%s%s%s)",
|
||||
-((int) seq_result),
|
||||
nm_strerror_native(-((int) seq_result)),
|
||||
errmsg ? " - " : "",
|
||||
errmsg ?: "");
|
||||
extack_msg ? " - " : "",
|
||||
extack_msg ?: "");
|
||||
} else
|
||||
nm_strbuf_append(&buf, &buf_size, "internal failure %d", (int) seq_result);
|
||||
break;
|
||||
|
@ -6994,7 +6991,7 @@ delayed_action_schedule_WAIT_FOR_RESPONSE(NMPlatform *pla
|
|||
NMPNetlinkProtocol netlink_protocol,
|
||||
guint32 seq_number,
|
||||
WaitForNlResponseResult *out_seq_result,
|
||||
char **out_errmsg,
|
||||
char **out_extack_msg,
|
||||
DelayedActionWaitForNlResponseType response_type,
|
||||
gpointer response_out_data)
|
||||
{
|
||||
|
@ -7003,7 +7000,7 @@ delayed_action_schedule_WAIT_FOR_RESPONSE(NMPlatform *pla
|
|||
.timeout_abs_nsec =
|
||||
nm_utils_get_monotonic_timestamp_nsec() + (200 * (NM_UTILS_NSEC_PER_SEC / 1000)),
|
||||
.out_seq_result = out_seq_result,
|
||||
.out_errmsg = out_errmsg,
|
||||
.out_extack_msg = out_extack_msg,
|
||||
.response_type = response_type,
|
||||
.response.out_data = response_out_data,
|
||||
};
|
||||
|
@ -7362,7 +7359,7 @@ static int
|
|||
_nl_send_nlmsghdr(NMPlatform *platform,
|
||||
struct nlmsghdr *nlhdr,
|
||||
WaitForNlResponseResult *out_seq_result,
|
||||
char **out_errmsg,
|
||||
char **out_extack_msg,
|
||||
DelayedActionWaitForNlResponseType response_type,
|
||||
gpointer response_out_data)
|
||||
{
|
||||
|
@ -7410,7 +7407,7 @@ again:
|
|||
NMP_NETLINK_ROUTE,
|
||||
seq,
|
||||
out_seq_result,
|
||||
out_errmsg,
|
||||
out_extack_msg,
|
||||
response_type,
|
||||
response_out_data);
|
||||
return 0;
|
||||
|
@ -7421,7 +7418,7 @@ _netlink_send_nlmsg(NMPlatform *platform,
|
|||
NMPNetlinkProtocol netlink_protocol,
|
||||
struct nl_msg *nlmsg,
|
||||
WaitForNlResponseResult *out_seq_result,
|
||||
char **out_errmsg,
|
||||
char **out_extack_msg,
|
||||
DelayedActionWaitForNlResponseType response_type,
|
||||
gpointer response_out_data)
|
||||
{
|
||||
|
@ -7444,7 +7441,7 @@ _netlink_send_nlmsg(NMPlatform *platform,
|
|||
netlink_protocol,
|
||||
seq,
|
||||
out_seq_result,
|
||||
out_errmsg,
|
||||
out_extack_msg,
|
||||
response_type,
|
||||
response_out_data);
|
||||
return 0;
|
||||
|
@ -7454,13 +7451,13 @@ static int
|
|||
_netlink_send_nlmsg_rtnl(NMPlatform *platform,
|
||||
struct nl_msg *nlmsg,
|
||||
WaitForNlResponseResult *out_seq_result,
|
||||
char **out_errmsg)
|
||||
char **out_extack_msg)
|
||||
{
|
||||
return _netlink_send_nlmsg(platform,
|
||||
NMP_NETLINK_ROUTE,
|
||||
nlmsg,
|
||||
out_seq_result,
|
||||
out_errmsg,
|
||||
out_extack_msg,
|
||||
DELAYED_ACTION_RESPONSE_TYPE_VOID,
|
||||
NULL);
|
||||
}
|
||||
|
@ -7731,7 +7728,7 @@ event_seq_check(NMPlatform *platform,
|
|||
NMPNetlinkProtocol netlink_protocol,
|
||||
guint32 seq_number,
|
||||
WaitForNlResponseResult seq_result,
|
||||
const char *msg)
|
||||
const char *extack_msg)
|
||||
{
|
||||
NMLinuxPlatformPrivate *priv = NM_LINUX_PLATFORM_GET_PRIVATE(platform);
|
||||
guint i;
|
||||
|
@ -7742,7 +7739,7 @@ event_seq_check(NMPlatform *platform,
|
|||
if (!NM_FLAGS_ANY(
|
||||
priv->delayed_action.flags,
|
||||
nmp_netlink_protocol_info(netlink_protocol)->delayed_action_type_wait_for_response))
|
||||
goto out;
|
||||
return;
|
||||
|
||||
nm_assert(priv->delayed_action.list_wait_for_response_x[netlink_protocol]->len > 0);
|
||||
|
||||
|
@ -7750,30 +7747,23 @@ event_seq_check(NMPlatform *platform,
|
|||
DelayedActionWaitForNlResponseData *data =
|
||||
delayed_action_get_list_wait_for_resonse(priv, netlink_protocol, i);
|
||||
|
||||
if (data->seq_number == seq_number) {
|
||||
/* We potentially receive many parts partial responses for the same sequence number.
|
||||
* Thus, we only remember the result, and collect it later. */
|
||||
if (data->seq_result < 0) {
|
||||
/* we already saw an error for this sequence number.
|
||||
* Preserve it. */
|
||||
} else if (seq_result != WAIT_FOR_NL_RESPONSE_RESULT_RESPONSE_UNKNOWN
|
||||
|| data->seq_result == WAIT_FOR_NL_RESPONSE_RESULT_UNKNOWN)
|
||||
data->seq_result = seq_result;
|
||||
if (data->out_errmsg && !*data->out_errmsg)
|
||||
*data->out_errmsg = g_strdup(msg);
|
||||
return;
|
||||
}
|
||||
if (data->seq_number != seq_number)
|
||||
continue;
|
||||
|
||||
/* We potentially receive many parts partial responses for the same sequence number.
|
||||
* Thus, we only remember the result, and collect it later. */
|
||||
if (data->seq_result < 0) {
|
||||
/* we already saw an error for this sequence number.
|
||||
* Preserve it. */
|
||||
} else if (seq_result != WAIT_FOR_NL_RESPONSE_RESULT_RESPONSE_UNKNOWN
|
||||
|| data->seq_result == WAIT_FOR_NL_RESPONSE_RESULT_UNKNOWN)
|
||||
data->seq_result = seq_result;
|
||||
|
||||
if (extack_msg && data->out_extack_msg && !*data->out_extack_msg)
|
||||
*data->out_extack_msg = g_strdup(extack_msg);
|
||||
|
||||
return;
|
||||
}
|
||||
|
||||
out:
|
||||
|
||||
#if NM_MORE_LOGGING
|
||||
if (seq_number != priv->proto_data_x[netlink_protocol].nlh_seq_last_handled)
|
||||
_LOGt("netlink: recvmsg: unwaited sequence number %u", seq_number);
|
||||
priv->proto_data_x[netlink_protocol].nlh_seq_last_handled = seq_number;
|
||||
#else
|
||||
(void) 0;
|
||||
#endif
|
||||
}
|
||||
|
||||
static void
|
||||
|
@ -8011,14 +8001,14 @@ do_add_link_with_lookup(NMPlatform *platform,
|
|||
{
|
||||
const NMPObject *obj = NULL;
|
||||
WaitForNlResponseResult seq_result = WAIT_FOR_NL_RESPONSE_RESULT_UNKNOWN;
|
||||
gs_free char *errmsg = NULL;
|
||||
gs_free char *extack_msg = NULL;
|
||||
int nle;
|
||||
char s_buf[256];
|
||||
NMPCache *cache = nm_platform_get_cache(platform);
|
||||
|
||||
event_handler_read_netlink(platform, NMP_NETLINK_ROUTE, FALSE);
|
||||
|
||||
nle = _netlink_send_nlmsg_rtnl(platform, nlmsg, &seq_result, &errmsg);
|
||||
nle = _netlink_send_nlmsg_rtnl(platform, nlmsg, &seq_result, &extack_msg);
|
||||
if (nle < 0) {
|
||||
_LOGE("do-add-link[%s/%s]: failed sending netlink request \"%s\" (%d)",
|
||||
name,
|
||||
|
@ -8037,7 +8027,7 @@ do_add_link_with_lookup(NMPlatform *platform,
|
|||
"do-add-link[%s/%s]: %s",
|
||||
name,
|
||||
nm_link_type_to_string(link_type),
|
||||
wait_for_nl_response_to_string(seq_result, errmsg, s_buf, sizeof(s_buf)));
|
||||
wait_for_nl_response_to_string(seq_result, extack_msg, s_buf, sizeof(s_buf)));
|
||||
|
||||
if (out_link) {
|
||||
obj = nmp_cache_lookup_link_full(cache, 0, name, FALSE, link_type, NULL, NULL);
|
||||
|
@ -8051,14 +8041,16 @@ static int
|
|||
do_add_addrroute(NMPlatform *platform,
|
||||
const NMPObject *obj_id,
|
||||
struct nl_msg *nlmsg,
|
||||
gboolean suppress_netlink_failure)
|
||||
gboolean suppress_netlink_failure,
|
||||
char **out_extack_msg)
|
||||
{
|
||||
char sbuf1[NM_UTILS_TO_STRING_BUFFER_SIZE];
|
||||
WaitForNlResponseResult seq_result = WAIT_FOR_NL_RESPONSE_RESULT_UNKNOWN;
|
||||
gs_free char *errmsg = NULL;
|
||||
gs_free char *extack_msg = NULL;
|
||||
int nle;
|
||||
char s_buf[256];
|
||||
|
||||
nm_assert(!out_extack_msg || !*out_extack_msg);
|
||||
nm_assert(NM_IN_SET(NMP_OBJECT_GET_TYPE(obj_id),
|
||||
NMP_OBJECT_TYPE_IP4_ADDRESS,
|
||||
NMP_OBJECT_TYPE_IP6_ADDRESS,
|
||||
|
@ -8067,13 +8059,14 @@ do_add_addrroute(NMPlatform *platform,
|
|||
|
||||
event_handler_read_netlink(platform, NMP_NETLINK_ROUTE, FALSE);
|
||||
|
||||
nle = _netlink_send_nlmsg_rtnl(platform, nlmsg, &seq_result, &errmsg);
|
||||
nle = _netlink_send_nlmsg_rtnl(platform, nlmsg, &seq_result, &extack_msg);
|
||||
if (nle < 0) {
|
||||
_LOGE("do-add-%s[%s]: failure sending netlink request \"%s\" (%d)",
|
||||
NMP_OBJECT_GET_CLASS(obj_id)->obj_type_name,
|
||||
nmp_object_to_string(obj_id, NMP_OBJECT_TO_STRING_ID, sbuf1, sizeof(sbuf1)),
|
||||
nm_strerror(nle),
|
||||
-nle);
|
||||
NM_SET_OUT(out_extack_msg, g_steal_pointer(&extack_msg));
|
||||
return -NME_PL_NETLINK;
|
||||
}
|
||||
|
||||
|
@ -8088,7 +8081,7 @@ do_add_addrroute(NMPlatform *platform,
|
|||
"do-add-%s[%s]: %s",
|
||||
NMP_OBJECT_GET_CLASS(obj_id)->obj_type_name,
|
||||
nmp_object_to_string(obj_id, NMP_OBJECT_TO_STRING_ID, sbuf1, sizeof(sbuf1)),
|
||||
wait_for_nl_response_to_string(seq_result, errmsg, s_buf, sizeof(s_buf)));
|
||||
wait_for_nl_response_to_string(seq_result, extack_msg, s_buf, sizeof(s_buf)));
|
||||
|
||||
if (NMP_OBJECT_GET_TYPE(obj_id) == NMP_OBJECT_TYPE_IP6_ADDRESS) {
|
||||
/* In rare cases, the object is not yet ready as we received the ACK from
|
||||
|
@ -8110,7 +8103,7 @@ do_delete_object(NMPlatform *platform, const NMPObject *obj_id, struct nl_msg *n
|
|||
{
|
||||
char sbuf1[NM_UTILS_TO_STRING_BUFFER_SIZE];
|
||||
WaitForNlResponseResult seq_result = WAIT_FOR_NL_RESPONSE_RESULT_UNKNOWN;
|
||||
gs_free char *errmsg = NULL;
|
||||
gs_free char *extack_msg = NULL;
|
||||
int nle;
|
||||
char s_buf[256];
|
||||
gboolean success;
|
||||
|
@ -8118,7 +8111,7 @@ do_delete_object(NMPlatform *platform, const NMPObject *obj_id, struct nl_msg *n
|
|||
|
||||
event_handler_read_netlink(platform, NMP_NETLINK_ROUTE, FALSE);
|
||||
|
||||
nle = _netlink_send_nlmsg_rtnl(platform, nlmsg, &seq_result, &errmsg);
|
||||
nle = _netlink_send_nlmsg_rtnl(platform, nlmsg, &seq_result, &extack_msg);
|
||||
if (nle < 0) {
|
||||
_LOGE("do-delete-%s[%s]: failure sending netlink request \"%s\" (%d)",
|
||||
NMP_OBJECT_GET_CLASS(obj_id)->obj_type_name,
|
||||
|
@ -8155,7 +8148,7 @@ do_delete_object(NMPlatform *platform, const NMPObject *obj_id, struct nl_msg *n
|
|||
"do-delete-%s[%s]: %s%s",
|
||||
NMP_OBJECT_GET_CLASS(obj_id)->obj_type_name,
|
||||
nmp_object_to_string(obj_id, NMP_OBJECT_TO_STRING_ID, sbuf1, sizeof(sbuf1)),
|
||||
wait_for_nl_response_to_string(seq_result, errmsg, s_buf, sizeof(s_buf)),
|
||||
wait_for_nl_response_to_string(seq_result, extack_msg, s_buf, sizeof(s_buf)),
|
||||
log_detail);
|
||||
|
||||
if (NM_IN_SET(NMP_OBJECT_GET_TYPE(obj_id),
|
||||
|
@ -8186,7 +8179,7 @@ do_change_link(NMPlatform *platform,
|
|||
nm_auto_pop_netns NMPNetns *netns = NULL;
|
||||
int nle;
|
||||
WaitForNlResponseResult seq_result = WAIT_FOR_NL_RESPONSE_RESULT_UNKNOWN;
|
||||
gs_free char *errmsg = NULL;
|
||||
gs_free char *extack_msg = NULL;
|
||||
char s_buf[256];
|
||||
int result;
|
||||
NMLogLevel log_level;
|
||||
|
@ -8207,7 +8200,7 @@ retry:
|
|||
log_detail = "";
|
||||
nm_clear_g_free(&log_detail_free);
|
||||
|
||||
nle = _netlink_send_nlmsg_rtnl(platform, nlmsg, &seq_result, &errmsg);
|
||||
nle = _netlink_send_nlmsg_rtnl(platform, nlmsg, &seq_result, &extack_msg);
|
||||
if (nle < 0) {
|
||||
log_level = LOGL_ERR;
|
||||
log_detail_free =
|
||||
|
@ -8267,7 +8260,7 @@ out:
|
|||
_NMLOG(log_level,
|
||||
"do-change-link[%d]: %s%s",
|
||||
ifindex,
|
||||
wait_for_nl_response_to_string(seq_result, errmsg, s_buf, sizeof(s_buf)),
|
||||
wait_for_nl_response_to_string(seq_result, extack_msg, s_buf, sizeof(s_buf)),
|
||||
log_detail);
|
||||
|
||||
if (result == -EAGAIN)
|
||||
|
@ -9499,7 +9492,8 @@ ip4_address_add(NMPlatform *platform,
|
|||
guint32 lifetime,
|
||||
guint32 preferred,
|
||||
guint32 flags,
|
||||
const char *label)
|
||||
const char *label,
|
||||
char **out_extack_msg)
|
||||
{
|
||||
NMPObject obj_id;
|
||||
nm_auto_nlmsg struct nl_msg *nlmsg = NULL;
|
||||
|
@ -9519,7 +9513,7 @@ ip4_address_add(NMPlatform *platform,
|
|||
label);
|
||||
|
||||
nmp_object_stackinit_id_ip4_address(&obj_id, ifindex, addr, plen, peer_addr);
|
||||
return (do_add_addrroute(platform, &obj_id, nlmsg, FALSE) >= 0);
|
||||
return (do_add_addrroute(platform, &obj_id, nlmsg, FALSE, out_extack_msg) >= 0);
|
||||
}
|
||||
|
||||
static gboolean
|
||||
|
@ -9530,7 +9524,8 @@ ip6_address_add(NMPlatform *platform,
|
|||
struct in6_addr peer_addr,
|
||||
guint32 lifetime,
|
||||
guint32 preferred,
|
||||
guint32 flags)
|
||||
guint32 flags,
|
||||
char **out_extack_msg)
|
||||
{
|
||||
NMPObject obj_id;
|
||||
nm_auto_nlmsg struct nl_msg *nlmsg = NULL;
|
||||
|
@ -9550,7 +9545,7 @@ ip6_address_add(NMPlatform *platform,
|
|||
NULL);
|
||||
|
||||
nmp_object_stackinit_id_ip6_address(&obj_id, ifindex, &addr);
|
||||
return (do_add_addrroute(platform, &obj_id, nlmsg, FALSE) >= 0);
|
||||
return (do_add_addrroute(platform, &obj_id, nlmsg, FALSE, out_extack_msg) >= 0);
|
||||
}
|
||||
|
||||
static gboolean
|
||||
|
@ -9612,7 +9607,7 @@ ip6_address_delete(NMPlatform *platform, int ifindex, struct in6_addr addr, guin
|
|||
/*****************************************************************************/
|
||||
|
||||
static int
|
||||
ip_route_add(NMPlatform *platform, NMPNlmFlags flags, NMPObject *obj_stack)
|
||||
ip_route_add(NMPlatform *platform, NMPNlmFlags flags, NMPObject *obj_stack, char **out_extack_msg)
|
||||
{
|
||||
nm_auto_nlmsg struct nl_msg *nlmsg = NULL;
|
||||
|
||||
|
@ -9622,7 +9617,8 @@ ip_route_add(NMPlatform *platform, NMPNlmFlags flags, NMPObject *obj_stack)
|
|||
return do_add_addrroute(platform,
|
||||
obj_stack,
|
||||
nlmsg,
|
||||
NM_FLAGS_HAS(flags, NMP_NLM_FLAG_SUPPRESS_NETLINK_FAILURE));
|
||||
NM_FLAGS_HAS(flags, NMP_NLM_FLAG_SUPPRESS_NETLINK_FAILURE),
|
||||
out_extack_msg);
|
||||
}
|
||||
|
||||
static gboolean
|
||||
|
@ -9751,7 +9747,7 @@ routing_rule_add(NMPlatform *platform, NMPNlmFlags flags, const NMPlatformRoutin
|
|||
{
|
||||
WaitForNlResponseResult seq_result = WAIT_FOR_NL_RESPONSE_RESULT_UNKNOWN;
|
||||
nm_auto_nlmsg struct nl_msg *msg = NULL;
|
||||
gs_free char *errmsg = NULL;
|
||||
gs_free char *extack_msg = NULL;
|
||||
char s_buf[256];
|
||||
int nle;
|
||||
|
||||
|
@ -9759,7 +9755,7 @@ routing_rule_add(NMPlatform *platform, NMPNlmFlags flags, const NMPlatformRoutin
|
|||
|
||||
event_handler_read_netlink(platform, NMP_NETLINK_ROUTE, FALSE);
|
||||
|
||||
nle = _netlink_send_nlmsg_rtnl(platform, msg, &seq_result, &errmsg);
|
||||
nle = _netlink_send_nlmsg_rtnl(platform, msg, &seq_result, &extack_msg);
|
||||
if (nle < 0) {
|
||||
_LOGE("do-add-rule: failed sending netlink request \"%s\" (%d)", nm_strerror(nle), -nle);
|
||||
return -NME_PL_NETLINK;
|
||||
|
@ -9771,7 +9767,7 @@ routing_rule_add(NMPlatform *platform, NMPNlmFlags flags, const NMPlatformRoutin
|
|||
|
||||
_NMLOG(seq_result == WAIT_FOR_NL_RESPONSE_RESULT_RESPONSE_OK ? LOGL_DEBUG : LOGL_WARN,
|
||||
"do-add-rule: %s",
|
||||
wait_for_nl_response_to_string(seq_result, errmsg, s_buf, sizeof(s_buf)));
|
||||
wait_for_nl_response_to_string(seq_result, extack_msg, s_buf, sizeof(s_buf)));
|
||||
|
||||
if (seq_result == WAIT_FOR_NL_RESPONSE_RESULT_RESPONSE_OK)
|
||||
return 0;
|
||||
|
@ -9786,7 +9782,7 @@ static int
|
|||
qdisc_add(NMPlatform *platform, NMPNlmFlags flags, const NMPlatformQdisc *qdisc)
|
||||
{
|
||||
WaitForNlResponseResult seq_result = WAIT_FOR_NL_RESPONSE_RESULT_UNKNOWN;
|
||||
gs_free char *errmsg = NULL;
|
||||
gs_free char *extack_msg = NULL;
|
||||
int nle;
|
||||
char s_buf[256];
|
||||
nm_auto_nlmsg struct nl_msg *msg = NULL;
|
||||
|
@ -9798,7 +9794,7 @@ qdisc_add(NMPlatform *platform, NMPNlmFlags flags, const NMPlatformQdisc *qdisc)
|
|||
|
||||
event_handler_read_netlink(platform, NMP_NETLINK_ROUTE, FALSE);
|
||||
|
||||
nle = _netlink_send_nlmsg_rtnl(platform, msg, &seq_result, &errmsg);
|
||||
nle = _netlink_send_nlmsg_rtnl(platform, msg, &seq_result, &extack_msg);
|
||||
if (nle < 0) {
|
||||
_LOGE("do-add-qdisc: failed sending netlink request \"%s\" (%d)", nm_strerror(nle), -nle);
|
||||
return -NME_PL_NETLINK;
|
||||
|
@ -9810,7 +9806,7 @@ qdisc_add(NMPlatform *platform, NMPNlmFlags flags, const NMPlatformQdisc *qdisc)
|
|||
|
||||
_NMLOG(seq_result == WAIT_FOR_NL_RESPONSE_RESULT_RESPONSE_OK ? LOGL_DEBUG : LOGL_WARN,
|
||||
"do-add-qdisc: %s",
|
||||
wait_for_nl_response_to_string(seq_result, errmsg, s_buf, sizeof(s_buf)));
|
||||
wait_for_nl_response_to_string(seq_result, extack_msg, s_buf, sizeof(s_buf)));
|
||||
|
||||
if (seq_result == WAIT_FOR_NL_RESPONSE_RESULT_RESPONSE_OK)
|
||||
return 0;
|
||||
|
@ -9827,7 +9823,7 @@ tc_delete(NMPlatform *platform,
|
|||
gboolean log_error)
|
||||
{
|
||||
WaitForNlResponseResult seq_result = WAIT_FOR_NL_RESPONSE_RESULT_UNKNOWN;
|
||||
gs_free char *errmsg = NULL;
|
||||
gs_free char *extack_msg = NULL;
|
||||
int nle;
|
||||
char s_buf[256];
|
||||
const char *log_tag;
|
||||
|
@ -9856,7 +9852,7 @@ tc_delete(NMPlatform *platform,
|
|||
|
||||
event_handler_read_netlink(platform, NMP_NETLINK_ROUTE, FALSE);
|
||||
|
||||
nle = _netlink_send_nlmsg_rtnl(platform, msg, &seq_result, &errmsg);
|
||||
nle = _netlink_send_nlmsg_rtnl(platform, msg, &seq_result, &extack_msg);
|
||||
if (nle < 0) {
|
||||
_NMLOG(log_error ? LOGL_ERR : LOGL_DEBUG,
|
||||
"%s: failed sending netlink request \"%s\" (%d)",
|
||||
|
@ -9874,7 +9870,7 @@ tc_delete(NMPlatform *platform,
|
|||
: LOGL_WARN,
|
||||
"%s: %s",
|
||||
log_tag,
|
||||
wait_for_nl_response_to_string(seq_result, errmsg, s_buf, sizeof(s_buf)));
|
||||
wait_for_nl_response_to_string(seq_result, extack_msg, s_buf, sizeof(s_buf)));
|
||||
|
||||
if (seq_result == WAIT_FOR_NL_RESPONSE_RESULT_RESPONSE_OK)
|
||||
return 0;
|
||||
|
@ -9896,7 +9892,7 @@ static int
|
|||
tfilter_add(NMPlatform *platform, NMPNlmFlags flags, const NMPlatformTfilter *tfilter)
|
||||
{
|
||||
WaitForNlResponseResult seq_result = WAIT_FOR_NL_RESPONSE_RESULT_UNKNOWN;
|
||||
gs_free char *errmsg = NULL;
|
||||
gs_free char *extack_msg = NULL;
|
||||
int nle;
|
||||
char s_buf[256];
|
||||
nm_auto_nlmsg struct nl_msg *msg = NULL;
|
||||
|
@ -9908,7 +9904,7 @@ tfilter_add(NMPlatform *platform, NMPNlmFlags flags, const NMPlatformTfilter *tf
|
|||
|
||||
event_handler_read_netlink(platform, NMP_NETLINK_ROUTE, FALSE);
|
||||
|
||||
nle = _netlink_send_nlmsg_rtnl(platform, msg, &seq_result, &errmsg);
|
||||
nle = _netlink_send_nlmsg_rtnl(platform, msg, &seq_result, &extack_msg);
|
||||
if (nle < 0) {
|
||||
_LOGE("do-add-tfilter: failed sending netlink request \"%s\" (%d)", nm_strerror(nle), -nle);
|
||||
return -NME_PL_NETLINK;
|
||||
|
@ -9920,7 +9916,7 @@ tfilter_add(NMPlatform *platform, NMPNlmFlags flags, const NMPlatformTfilter *tf
|
|||
|
||||
_NMLOG(seq_result == WAIT_FOR_NL_RESPONSE_RESULT_RESPONSE_OK ? LOGL_DEBUG : LOGL_WARN,
|
||||
"do-add-tfilter: %s",
|
||||
wait_for_nl_response_to_string(seq_result, errmsg, s_buf, sizeof(s_buf)));
|
||||
wait_for_nl_response_to_string(seq_result, extack_msg, s_buf, sizeof(s_buf)));
|
||||
|
||||
if (seq_result == WAIT_FOR_NL_RESPONSE_RESULT_RESPONSE_OK)
|
||||
return 0;
|
||||
|
@ -10176,9 +10172,16 @@ continue_reading:
|
|||
int errsv;
|
||||
|
||||
errsv = nlmsg_parse_error(msg.nm_nlh, &extack_msg);
|
||||
if (errsv == 0)
|
||||
if (errsv == 0) {
|
||||
seq_result = WAIT_FOR_NL_RESPONSE_RESULT_RESPONSE_OK;
|
||||
else {
|
||||
if (extack_msg) {
|
||||
_LOGD("%s: recvmsg: warning message from kernel: %s%s%s for request %d",
|
||||
log_prefix,
|
||||
NM_PRINT_FMT_QUOTE_STRING(extack_msg),
|
||||
msg.nm_nlh->nlmsg_seq);
|
||||
extack_msg = NULL;
|
||||
}
|
||||
} else {
|
||||
_LOGD("%s: recvmsg: error message from kernel: %s (%d)%s%s%s for request %d",
|
||||
log_prefix,
|
||||
nm_strerror(errsv),
|
||||
|
@ -10636,9 +10639,10 @@ mptcp_addr_update(NMPlatform *platform, NMOptionBool add, const NMPlatformMptcpA
|
|||
return nle;
|
||||
}
|
||||
|
||||
_LOGT("mptcp: %s address %s: success",
|
||||
_LOGT("mptcp: %s address %s: success%s%s%s",
|
||||
cmd_str,
|
||||
nm_platform_mptcp_addr_to_string(addr, sbuf, sizeof(sbuf)));
|
||||
nm_platform_mptcp_addr_to_string(addr, sbuf, sizeof(sbuf)),
|
||||
NM_PRINT_FMT_QUOTED(extack_msg[0] != '\0', " Warning: \"", extack_msg, "\"", ""));
|
||||
|
||||
return 0;
|
||||
|
||||
|
|
|
@ -313,9 +313,6 @@ nlmsg_parse_error(const struct nlmsghdr *nlh, const char **out_extack_msg)
|
|||
|
||||
e = nlmsg_data(nlh);
|
||||
|
||||
if (!e->error)
|
||||
return 0;
|
||||
|
||||
if (NM_FLAGS_HAS(nlh->nlmsg_flags, NLM_F_ACK_TLVS) && out_extack_msg
|
||||
&& nlh->nlmsg_len >= sizeof(*e) + e->msg.nlmsg_len) {
|
||||
static const struct nla_policy policy[] = {
|
||||
|
@ -328,11 +325,19 @@ nlmsg_parse_error(const struct nlmsghdr *nlh, const char **out_extack_msg)
|
|||
tlvs = NM_CAST_ALIGN(struct nlattr,
|
||||
(((char *) e) + sizeof(*e) + e->msg.nlmsg_len - NLMSG_HDRLEN));
|
||||
if (nla_parse_arr(tb, tlvs, nlh->nlmsg_len - sizeof(*e) - e->msg.nlmsg_len, policy) >= 0) {
|
||||
if (tb[NLMSGERR_ATTR_MSG])
|
||||
*out_extack_msg = nla_get_string(tb[NLMSGERR_ATTR_MSG]);
|
||||
if (tb[NLMSGERR_ATTR_MSG]) {
|
||||
const char *s;
|
||||
|
||||
s = nla_get_string(tb[NLMSGERR_ATTR_MSG]);
|
||||
if (s[0] != '\0')
|
||||
*out_extack_msg = s;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
if (!e->error)
|
||||
return 0;
|
||||
|
||||
return -nm_errno_from_native(e->error);
|
||||
}
|
||||
|
||||
|
@ -488,44 +493,52 @@ nlmsg_put(struct nl_msg *n,
|
|||
}
|
||||
|
||||
size_t
|
||||
nla_strlcpy(char *dst, const struct nlattr *nla, size_t dstsize)
|
||||
_nla_strlcpy_full(char *dst, const struct nlattr *nla, size_t dstsize, gboolean wipe_remainder)
|
||||
{
|
||||
const char *src;
|
||||
const char *src = NULL;
|
||||
size_t srclen;
|
||||
size_t len;
|
||||
size_t cpylen;
|
||||
|
||||
/* - Always writes @dstsize bytes to @dst
|
||||
* - Copies the first non-NUL characters to @dst.
|
||||
* Any characters after the first NUL bytes in @nla are ignored.
|
||||
* - If the string @nla is longer than @dstsize, the string
|
||||
* gets truncated. @dst will always be NUL terminated. */
|
||||
/* Behaves like strlcpy():
|
||||
*
|
||||
* - returns the length of the string in nla (how much it wanted to copy).
|
||||
* - will always NUL terminate dst (unless dstsize is zero).
|
||||
* - if @wipe_remainder, the remaining bytes after the string are set to NUL,
|
||||
* similar to what strncpy() would do. Otherwise the bytes are undefined.
|
||||
* - nla is not required to contain a NUL terminated string (unlike nla_get_string()).
|
||||
* - the function copies the bytes up to the first NUL character in nla.
|
||||
* any remainder in nla is ignored.
|
||||
* - nla may be NULL, which is treated the same as an empty string (copying zero bytes).
|
||||
*/
|
||||
|
||||
if (G_UNLIKELY(dstsize <= 1)) {
|
||||
if (dstsize == 1)
|
||||
dst[0] = '\0';
|
||||
if (nla && (srclen = nla_len(nla)) > 0)
|
||||
return strnlen(nla_data(nla), srclen);
|
||||
return 0;
|
||||
}
|
||||
|
||||
nm_assert(dst);
|
||||
nm_assert(dstsize == 0 || dst);
|
||||
|
||||
if (nla) {
|
||||
srclen = nla_len(nla);
|
||||
if (srclen > 0) {
|
||||
src = nla_data(nla);
|
||||
srclen = strnlen(src, srclen);
|
||||
if (srclen > 0) {
|
||||
len = NM_MIN(dstsize - 1, srclen);
|
||||
memcpy(dst, src, len);
|
||||
memset(&dst[len], 0, dstsize - len);
|
||||
return srclen;
|
||||
}
|
||||
}
|
||||
} else
|
||||
srclen = 0;
|
||||
|
||||
if (dstsize == 0) {
|
||||
/* we cannot NUL terminate. This is potentially dangerous, maybe
|
||||
* we should assert against this case. */
|
||||
return srclen;
|
||||
}
|
||||
|
||||
memset(dst, 0, dstsize);
|
||||
return 0;
|
||||
cpylen = NM_MIN(dstsize - 1u, srclen);
|
||||
|
||||
nm_memcpy(dst, src, cpylen);
|
||||
|
||||
if (wipe_remainder) {
|
||||
/* like strncpy() would do, wipe the rest. */
|
||||
memset(&dst[cpylen], 0, dstsize - cpylen);
|
||||
} else
|
||||
dst[cpylen] = '\0';
|
||||
|
||||
return srclen;
|
||||
}
|
||||
|
||||
size_t
|
||||
|
|
|
@ -238,10 +238,36 @@ nla_get_be64(const struct nlattr *nla)
|
|||
static inline char *
|
||||
nla_get_string(const struct nlattr *nla)
|
||||
{
|
||||
return nla_data(nla);
|
||||
char *s;
|
||||
|
||||
/* nla_get_string() requires that nla contains a NUL terminated string.
|
||||
* It cannot return NULL. Only use it with attributes that validate as NLA_STRING. */
|
||||
|
||||
nm_assert(nla_len(nla) > 0);
|
||||
|
||||
s = nla_data(nla);
|
||||
|
||||
nm_assert(memchr(s, 0, nla_len(nla)));
|
||||
|
||||
return s;
|
||||
}
|
||||
|
||||
size_t nla_strlcpy(char *dst, const struct nlattr *nla, size_t dstsize);
|
||||
size_t
|
||||
_nla_strlcpy_full(char *dst, const struct nlattr *nla, size_t dstsize, gboolean wipe_remainder);
|
||||
|
||||
static inline size_t
|
||||
nla_strlcpy(char *dst, const struct nlattr *nla, size_t dstsize)
|
||||
{
|
||||
return _nla_strlcpy_full(dst, nla, dstsize, FALSE);
|
||||
}
|
||||
|
||||
static inline size_t
|
||||
nla_strlcpy_wipe(char *dst, const struct nlattr *nla, size_t dstsize)
|
||||
{
|
||||
/* Behaves exactly like nla_strlcpy(), but (similar to strncpy()) it fills the
|
||||
* remaining @dstsize bytes with NUL. */
|
||||
return _nla_strlcpy_full(dst, nla, dstsize, TRUE);
|
||||
}
|
||||
|
||||
size_t nla_memcpy(void *dst, const struct nlattr *nla, size_t dstsize);
|
||||
|
||||
|
|
|
@ -3559,7 +3559,8 @@ nm_platform_ip4_address_add(NMPlatform *self,
|
|||
guint32 lifetime,
|
||||
guint32 preferred,
|
||||
guint32 flags,
|
||||
const char *label)
|
||||
const char *label,
|
||||
char **out_extack_msg)
|
||||
{
|
||||
_CHECK_SELF(self, klass, FALSE);
|
||||
|
||||
|
@ -3569,6 +3570,7 @@ nm_platform_ip4_address_add(NMPlatform *self,
|
|||
g_return_val_if_fail(preferred <= lifetime, FALSE);
|
||||
g_return_val_if_fail(!label || strlen(label) < sizeof(((NMPlatformIP4Address *) NULL)->label),
|
||||
FALSE);
|
||||
nm_assert(!out_extack_msg || !*out_extack_msg);
|
||||
|
||||
if (_LOGD_ENABLED()) {
|
||||
char sbuf[NM_UTILS_TO_STRING_BUFFER_SIZE];
|
||||
|
@ -3601,7 +3603,8 @@ nm_platform_ip4_address_add(NMPlatform *self,
|
|||
lifetime,
|
||||
preferred,
|
||||
flags,
|
||||
label);
|
||||
label,
|
||||
out_extack_msg);
|
||||
}
|
||||
|
||||
gboolean
|
||||
|
@ -3612,7 +3615,8 @@ nm_platform_ip6_address_add(NMPlatform *self,
|
|||
struct in6_addr peer_address,
|
||||
guint32 lifetime,
|
||||
guint32 preferred,
|
||||
guint32 flags)
|
||||
guint32 flags,
|
||||
char **out_extack_msg)
|
||||
{
|
||||
_CHECK_SELF(self, klass, FALSE);
|
||||
|
||||
|
@ -3620,6 +3624,7 @@ nm_platform_ip6_address_add(NMPlatform *self,
|
|||
g_return_val_if_fail(plen <= 128, FALSE);
|
||||
g_return_val_if_fail(lifetime > 0, FALSE);
|
||||
g_return_val_if_fail(preferred <= lifetime, FALSE);
|
||||
nm_assert(!out_extack_msg || !*out_extack_msg);
|
||||
|
||||
if (_LOGD_ENABLED()) {
|
||||
char sbuf[NM_UTILS_TO_STRING_BUFFER_SIZE];
|
||||
|
@ -3640,8 +3645,15 @@ nm_platform_ip6_address_add(NMPlatform *self,
|
|||
|
||||
nm_platform_ip6_dadfailed_set(self, ifindex, &address, FALSE);
|
||||
|
||||
return klass
|
||||
->ip6_address_add(self, ifindex, address, plen, peer_address, lifetime, preferred, flags);
|
||||
return klass->ip6_address_add(self,
|
||||
ifindex,
|
||||
address,
|
||||
plen,
|
||||
peer_address,
|
||||
lifetime,
|
||||
preferred,
|
||||
flags,
|
||||
out_extack_msg);
|
||||
}
|
||||
|
||||
gboolean
|
||||
|
@ -4464,7 +4476,8 @@ next_plat:;
|
|||
NM_FLAGS_HAS(flags, NMP_IP_ADDRESS_SYNC_FLAGS_WITH_NOPREFIXROUTE)
|
||||
? IFA_F_NOPREFIXROUTE
|
||||
: 0,
|
||||
known_address->a4.label))
|
||||
known_address->a4.label,
|
||||
NULL))
|
||||
success = FALSE;
|
||||
} else {
|
||||
if (!nm_platform_ip6_address_add(
|
||||
|
@ -4478,7 +4491,8 @@ next_plat:;
|
|||
(NM_FLAGS_HAS(flags, NMP_IP_ADDRESS_SYNC_FLAGS_WITH_NOPREFIXROUTE)
|
||||
? IFA_F_NOPREFIXROUTE
|
||||
: 0)
|
||||
| known_address->a6.n_ifa_flags))
|
||||
| known_address->a6.n_ifa_flags,
|
||||
NULL))
|
||||
success = FALSE;
|
||||
}
|
||||
}
|
||||
|
@ -4520,39 +4534,50 @@ nm_platform_ip_address_flush(NMPlatform *self, int addr_family, int ifindex)
|
|||
/*****************************************************************************/
|
||||
|
||||
static gboolean
|
||||
_err_inval_due_to_ipv6_tentative_pref_src(NMPlatform *self, const NMPObject *obj)
|
||||
_route_is_temporary_not_available(NMPlatform *self,
|
||||
int err,
|
||||
const NMPObject *obj,
|
||||
const char **out_err_reason)
|
||||
{
|
||||
const NMPlatformIP6Route *r;
|
||||
const NMPlatformIPXRoute *rx;
|
||||
const NMPlatformIP6Address *a;
|
||||
|
||||
nm_assert(NM_IS_PLATFORM(self));
|
||||
nm_assert(NMP_OBJECT_IS_VALID(obj));
|
||||
|
||||
/* trying to add an IPv6 route with pref-src fails, if the address is
|
||||
* still tentative (rh#1452684). We need to hack around that.
|
||||
*
|
||||
* Detect it, by guessing whether that's the case. */
|
||||
|
||||
if (NMP_OBJECT_GET_TYPE(obj) != NMP_OBJECT_TYPE_IP6_ROUTE)
|
||||
if (err != -EINVAL)
|
||||
return FALSE;
|
||||
|
||||
r = NMP_OBJECT_CAST_IP6_ROUTE(obj);
|
||||
rx = NMP_OBJECT_CAST_IPX_ROUTE(obj);
|
||||
|
||||
/* we only allow this workaround for routes added manually by the user. */
|
||||
if (r->rt_source != NM_IP_CONFIG_SOURCE_USER)
|
||||
if (rx->rx.rt_source != NM_IP_CONFIG_SOURCE_USER) {
|
||||
/* we only allow this workaround for routes added manually by the user. */
|
||||
return FALSE;
|
||||
}
|
||||
|
||||
if (IN6_IS_ADDR_UNSPECIFIED(&r->pref_src))
|
||||
if (NMP_OBJECT_GET_TYPE(obj) == NMP_OBJECT_TYPE_IP4_ROUTE) {
|
||||
return FALSE;
|
||||
} else {
|
||||
const NMPlatformIP6Route *r = &rx->r6;
|
||||
|
||||
a = nm_platform_ip6_address_get(self, r->ifindex, &r->pref_src);
|
||||
if (!a)
|
||||
return FALSE;
|
||||
if (!NM_FLAGS_HAS(a->n_ifa_flags, IFA_F_TENTATIVE)
|
||||
|| NM_FLAGS_HAS(a->n_ifa_flags, IFA_F_DADFAILED))
|
||||
return FALSE;
|
||||
/* trying to add an IPv6 route with pref-src fails, if the address is
|
||||
* still tentative (rh#1452684). We need to hack around that.
|
||||
*
|
||||
* Detect it, by guessing whether that's the case. */
|
||||
|
||||
return TRUE;
|
||||
if (IN6_IS_ADDR_UNSPECIFIED(&r->pref_src))
|
||||
return FALSE;
|
||||
|
||||
a = nm_platform_ip6_address_get(self, r->ifindex, &r->pref_src);
|
||||
if (!a)
|
||||
return FALSE;
|
||||
if (!NM_FLAGS_HAS(a->n_ifa_flags, IFA_F_TENTATIVE)
|
||||
|| NM_FLAGS_HAS(a->n_ifa_flags, IFA_F_DADFAILED))
|
||||
return FALSE;
|
||||
|
||||
*out_err_reason = "tentative IPv6 src address not ready";
|
||||
return TRUE;
|
||||
}
|
||||
}
|
||||
|
||||
static guint
|
||||
|
@ -4914,8 +4939,10 @@ nm_platform_ip_route_sync(NMPlatform *self,
|
|||
|
||||
for (i_type = 0; routes && i_type < 2; i_type++) {
|
||||
for (i = 0; i < routes->len; i++) {
|
||||
int r, r2;
|
||||
gboolean gateway_route_added = FALSE;
|
||||
gs_free char *extack_msg = NULL;
|
||||
gboolean gateway_route_added = FALSE;
|
||||
int r2;
|
||||
int r;
|
||||
|
||||
conf_o = routes->pdata[i];
|
||||
|
||||
|
@ -4975,8 +5002,11 @@ sync_route_add:
|
|||
r = nm_platform_ip_route_add(self,
|
||||
NMP_NLM_FLAG_APPEND
|
||||
| NMP_NLM_FLAG_SUPPRESS_NETLINK_FAILURE,
|
||||
conf_o);
|
||||
conf_o,
|
||||
&extack_msg);
|
||||
if (r < 0) {
|
||||
const char *err_reason = NULL;
|
||||
|
||||
if (r == -EEXIST) {
|
||||
/* Don't fail for EEXIST. It's not clear that the existing route
|
||||
* is identical to the one that we were about to add. However,
|
||||
|
@ -5015,15 +5045,15 @@ sync_route_add:
|
|||
sbuf1,
|
||||
sizeof(sbuf1)),
|
||||
nm_strerror(r));
|
||||
} else if (r == -EINVAL && out_temporary_not_available
|
||||
&& _err_inval_due_to_ipv6_tentative_pref_src(self, conf_o)) {
|
||||
_LOG3D("route-sync: ignore failure to add IPv6 route with tentative IPv6 "
|
||||
"pref-src: %s: %s",
|
||||
} else if (out_temporary_not_available
|
||||
&& _route_is_temporary_not_available(self, r, conf_o, &err_reason)) {
|
||||
_LOG3D("route-sync: ignore temporary failure to add route (%s, %s): %s",
|
||||
nm_strerror(r),
|
||||
err_reason,
|
||||
nmp_object_to_string(conf_o,
|
||||
NMP_OBJECT_TO_STRING_PUBLIC,
|
||||
sbuf1,
|
||||
sizeof(sbuf1)),
|
||||
nm_strerror(r));
|
||||
sizeof(sbuf1)));
|
||||
if (!*out_temporary_not_available)
|
||||
*out_temporary_not_available =
|
||||
g_ptr_array_new_full(0, (GDestroyNotify) nmp_object_unref);
|
||||
|
@ -5085,7 +5115,8 @@ sync_route_add:
|
|||
r2 = nm_platform_ip_route_add(self,
|
||||
NMP_NLM_FLAG_APPEND
|
||||
| NMP_NLM_FLAG_SUPPRESS_NETLINK_FAILURE,
|
||||
&oo);
|
||||
&oo,
|
||||
NULL);
|
||||
|
||||
if (r2 < 0) {
|
||||
_LOG3D("route-sync: failure to add gateway IPv%c route: %s: %s",
|
||||
|
@ -5250,7 +5281,7 @@ nm_platform_ip_route_normalize(int addr_family, NMPlatformIPRoute *route)
|
|||
}
|
||||
|
||||
static int
|
||||
_ip_route_add(NMPlatform *self, NMPNlmFlags flags, NMPObject *obj_stack)
|
||||
_ip_route_add(NMPlatform *self, NMPNlmFlags flags, NMPObject *obj_stack, char **out_extack_msg)
|
||||
{
|
||||
char sbuf[NM_UTILS_TO_STRING_BUFFER_SIZE];
|
||||
int ifindex;
|
||||
|
@ -5266,6 +5297,7 @@ _ip_route_add(NMPlatform *self, NMPNlmFlags flags, NMPObject *obj_stack)
|
|||
nm_assert(NM_IN_SET(NMP_OBJECT_GET_TYPE(obj_stack),
|
||||
NMP_OBJECT_TYPE_IP4_ROUTE,
|
||||
NMP_OBJECT_TYPE_IP6_ROUTE));
|
||||
nm_assert(!out_extack_msg || !*out_extack_msg);
|
||||
|
||||
nm_assert(NMP_OBJECT_GET_TYPE(obj_stack) != NMP_OBJECT_TYPE_IP4_ROUTE
|
||||
|| obj_stack->ip4_route.n_nexthops <= 1u || obj_stack->_ip4_route.extra_nexthops);
|
||||
|
@ -5287,11 +5319,14 @@ _ip_route_add(NMPlatform *self, NMPNlmFlags flags, NMPObject *obj_stack)
|
|||
* is stack allocated (and the potential "extra_nexthops" array is
|
||||
* guaranteed to stay alive too).
|
||||
*/
|
||||
return klass->ip_route_add(self, flags, obj_stack);
|
||||
return klass->ip_route_add(self, flags, obj_stack, out_extack_msg);
|
||||
}
|
||||
|
||||
int
|
||||
nm_platform_ip_route_add(NMPlatform *self, NMPNlmFlags flags, const NMPObject *obj)
|
||||
nm_platform_ip_route_add(NMPlatform *self,
|
||||
NMPNlmFlags flags,
|
||||
const NMPObject *obj,
|
||||
char **out_extack_msg)
|
||||
{
|
||||
nm_auto_nmpobj const NMPObject *obj_keep_alive = NULL;
|
||||
NMPObject obj_stack;
|
||||
|
@ -5309,7 +5344,7 @@ nm_platform_ip_route_add(NMPlatform *self, NMPNlmFlags flags, const NMPObject *o
|
|||
obj_stack._ip4_route.extra_nexthops = obj->_ip4_route.extra_nexthops;
|
||||
}
|
||||
|
||||
return _ip_route_add(self, flags, &obj_stack);
|
||||
return _ip_route_add(self, flags, &obj_stack, out_extack_msg);
|
||||
}
|
||||
|
||||
int
|
||||
|
@ -5341,7 +5376,7 @@ nm_platform_ip4_route_add(NMPlatform *self,
|
|||
&extra_nexthops_free);
|
||||
}
|
||||
|
||||
return _ip_route_add(self, flags, &obj);
|
||||
return _ip_route_add(self, flags, &obj, NULL);
|
||||
}
|
||||
|
||||
int
|
||||
|
@ -5350,7 +5385,7 @@ nm_platform_ip6_route_add(NMPlatform *self, NMPNlmFlags flags, const NMPlatformI
|
|||
NMPObject obj;
|
||||
|
||||
nmp_object_stackinit(&obj, NMP_OBJECT_TYPE_IP6_ROUTE, (const NMPlatformObject *) route);
|
||||
return _ip_route_add(self, flags, &obj);
|
||||
return _ip_route_add(self, flags, &obj, NULL);
|
||||
}
|
||||
|
||||
gboolean
|
||||
|
|
|
@ -1215,7 +1215,8 @@ typedef struct {
|
|||
guint32 lifetime,
|
||||
guint32 preferred_lft,
|
||||
guint32 flags,
|
||||
const char *label);
|
||||
const char *label,
|
||||
char **out_extack_msg);
|
||||
gboolean (*ip6_address_add)(NMPlatform *self,
|
||||
int ifindex,
|
||||
struct in6_addr address,
|
||||
|
@ -1223,7 +1224,8 @@ typedef struct {
|
|||
struct in6_addr peer_address,
|
||||
guint32 lifetime,
|
||||
guint32 preferred_lft,
|
||||
guint32 flags);
|
||||
guint32 flags,
|
||||
char **out_extack_msg);
|
||||
gboolean (*ip4_address_delete)(NMPlatform *self,
|
||||
int ifindex,
|
||||
in_addr_t address,
|
||||
|
@ -1234,7 +1236,11 @@ typedef struct {
|
|||
struct in6_addr address,
|
||||
guint8 plen);
|
||||
|
||||
int (*ip_route_add)(NMPlatform *self, NMPNlmFlags flags, NMPObject *obj_stack);
|
||||
int (*ip_route_add)(NMPlatform *self,
|
||||
NMPNlmFlags flags,
|
||||
NMPObject *obj_stack,
|
||||
char **out_extack_msg);
|
||||
|
||||
int (*ip_route_get)(NMPlatform *self,
|
||||
int addr_family,
|
||||
gconstpointer address,
|
||||
|
@ -2130,7 +2136,8 @@ gboolean nm_platform_ip4_address_add(NMPlatform *self,
|
|||
guint32 lifetime,
|
||||
guint32 preferred_lft,
|
||||
guint32 flags,
|
||||
const char *label);
|
||||
const char *label,
|
||||
char **out_extack_msg);
|
||||
gboolean nm_platform_ip6_address_add(NMPlatform *self,
|
||||
int ifindex,
|
||||
struct in6_addr address,
|
||||
|
@ -2138,7 +2145,8 @@ gboolean nm_platform_ip6_address_add(NMPlatform *self,
|
|||
struct in6_addr peer_address,
|
||||
guint32 lifetime,
|
||||
guint32 preferred_lft,
|
||||
guint32 flags);
|
||||
guint32 flags,
|
||||
char **out_extack_msg);
|
||||
gboolean nm_platform_ip4_address_delete(NMPlatform *self,
|
||||
int ifindex,
|
||||
in_addr_t address,
|
||||
|
@ -2251,7 +2259,10 @@ nm_platform_ip_route_get_gateway(int addr_family, const NMPlatformIPRoute *route
|
|||
return &((NMPlatformIP6Route *) route)->gateway;
|
||||
}
|
||||
|
||||
int nm_platform_ip_route_add(NMPlatform *self, NMPNlmFlags flags, const NMPObject *route);
|
||||
int nm_platform_ip_route_add(NMPlatform *self,
|
||||
NMPNlmFlags flags,
|
||||
const NMPObject *route,
|
||||
char **out_extack_msg);
|
||||
int nm_platform_ip4_route_add(NMPlatform *self,
|
||||
NMPNlmFlags flags,
|
||||
const NMPlatformIP4Route *route,
|
||||
|
|
|
@ -1101,7 +1101,7 @@ nmp_global_tracker_sync(NMPGlobalTracker *self, NMPObjectType obj_type, gboolean
|
|||
NMP_NLM_FLAG_ADD,
|
||||
NMP_OBJECT_CAST_ROUTING_RULE(obj_data->obj));
|
||||
} else
|
||||
nm_platform_ip_route_add(self->platform, NMP_NLM_FLAG_APPEND, obj_data->obj);
|
||||
nm_platform_ip_route_add(self->platform, NMP_NLM_FLAG_APPEND, obj_data->obj, NULL);
|
||||
}
|
||||
}
|
||||
|
||||
|
|
Loading…
Reference in a new issue