diff options
| author | Michael Biebl <biebl@debian.org> | 2019-08-06 22:46:20 +0200 |
|---|---|---|
| committer | Michael Biebl <biebl@debian.org> | 2019-08-06 22:46:20 +0200 |
| commit | 5c79b900b59a5ad162ecc836e424468207ff031e (patch) | |
| tree | 2f529ff5c2d8531a2bf2973d96e316786eee9799 /src | |
| parent | 2e5fa45ddfbb5cffa1e78221f1cea706e2f298af (diff) | |
New upstream version 1.20.0 upstream/1.20.0
Diffstat (limited to 'src')
| -rw-r--r-- | src/devices/adsl/nm-device-adsl.c | 3 | ||||
| -rw-r--r-- | src/devices/bluetooth/nm-bluez5-dun.c | 2 | ||||
| -rw-r--r-- | src/devices/nm-device-bond.c | 6 | ||||
| -rw-r--r-- | src/devices/nm-device-bridge.c | 6 | ||||
| -rw-r--r-- | src/devices/nm-device-wireguard.c | 244 | ||||
| -rw-r--r-- | src/devices/nm-device.c | 27 | ||||
| -rw-r--r-- | src/devices/nm-lldp-listener.c | 16 | ||||
| -rw-r--r-- | src/devices/team/nm-device-team.c | 6 | ||||
| -rw-r--r-- | src/devices/wwan/nm-modem-broadband.c | 2 | ||||
| -rw-r--r-- | src/initrd/nmi-cmdline-reader.c | 2 | ||||
| -rw-r--r-- | src/nm-ip4-config.c | 6 | ||||
| -rw-r--r-- | src/nm-ip6-config.c | 3 | ||||
| -rw-r--r-- | src/nm-manager.c | 46 | ||||
| -rw-r--r-- | src/platform/tests/test-link.c | 2 | ||||
| -rw-r--r-- | src/platform/wifi/nm-wifi-utils-nl80211.c | 22 | ||||
| -rw-r--r-- | src/settings/nm-agent-manager.c | 10 | ||||
| -rw-r--r-- | src/settings/nm-settings.c | 6 | ||||
| -rw-r--r-- | src/settings/plugins/ifcfg-rh/nms-ifcfg-rh-reader.c | 19 | ||||
| -rw-r--r-- | src/settings/plugins/ifupdown/nms-ifupdown-plugin.c | 2 | ||||
| -rw-r--r-- | src/supplicant/nm-supplicant-config.c | 14 | ||||
| -rw-r--r-- | src/supplicant/nm-supplicant-settings-verify.c | 100 |
21 files changed, 259 insertions, 285 deletions
diff --git a/src/devices/adsl/nm-device-adsl.c b/src/devices/adsl/nm-device-adsl.c index 59c87851..34efdb01 100644 --- a/src/devices/adsl/nm-device-adsl.c +++ b/src/devices/adsl/nm-device-adsl.c @@ -155,6 +155,7 @@ br2684_assign_vcc (NMDeviceAdsl *self, NMSettingAdsl *s_adsl) if (priv->brfd < 0) { errsv = errno; _LOGE (LOGD_ADSL, "failed to open ATM control socket (%d)", errsv); + priv->brfd = -1; return FALSE; } @@ -206,7 +207,7 @@ br2684_assign_vcc (NMDeviceAdsl *self, NMSettingAdsl *s_adsl) memset (&be, 0, sizeof (be)); be.backend_num = ATM_BACKEND_BR2684; be.ifspec.method = BR2684_FIND_BYIFNAME; - strcpy (be.ifspec.spec.ifname, priv->nas_ifname); + nm_utils_ifname_cpy (be.ifspec.spec.ifname, priv->nas_ifname); be.fcs_in = BR2684_FCSIN_NO; be.fcs_out = BR2684_FCSOUT_NO; be.encaps = is_llc ? BR2684_ENCAPS_LLC : BR2684_ENCAPS_VC; diff --git a/src/devices/bluetooth/nm-bluez5-dun.c b/src/devices/bluetooth/nm-bluez5-dun.c index 04859f9a..b9a1fa0a 100644 --- a/src/devices/bluetooth/nm-bluez5-dun.c +++ b/src/devices/bluetooth/nm-bluez5-dun.c @@ -386,7 +386,7 @@ nm_bluez5_dun_cleanup (NMBluez5DunContext *context) struct rfcomm_dev_req req = { 0 }; req.dev_id = context->rfcomm_id; - ioctl (context->rfcomm_fd, RFCOMMRELEASEDEV, &req); + (void) ioctl (context->rfcomm_fd, RFCOMMRELEASEDEV, &req); context->rfcomm_id = -1; } nm_close (context->rfcomm_fd); diff --git a/src/devices/nm-device-bond.c b/src/devices/nm-device-bond.c index fd79348d..50494526 100644 --- a/src/devices/nm-device-bond.c +++ b/src/devices/nm-device-bond.c @@ -414,6 +414,12 @@ release_slave (NMDevice *device, gboolean success; gs_free char *address = NULL; int ifindex_slave; + int ifindex; + + ifindex = nm_device_get_ifindex (device); + if ( ifindex <= 0 + || !nm_platform_link_get (nm_device_get_platform (device), ifindex)) + configure = FALSE; ifindex_slave = nm_device_get_ip_ifindex (slave); diff --git a/src/devices/nm-device-bridge.c b/src/devices/nm-device-bridge.c index ade9eb0d..91d824b3 100644 --- a/src/devices/nm-device-bridge.c +++ b/src/devices/nm-device-bridge.c @@ -626,6 +626,12 @@ release_slave (NMDevice *device, NMDeviceBridge *self = NM_DEVICE_BRIDGE (device); gboolean success; int ifindex_slave; + int ifindex; + + ifindex = nm_device_get_ifindex (device); + if ( ifindex <= 0 + || !nm_platform_link_get (nm_device_get_platform (device), ifindex)) + configure = FALSE; ifindex_slave = nm_device_get_ip_ifindex (slave); diff --git a/src/devices/nm-device-wireguard.c b/src/devices/nm-device-wireguard.c index d36573cf..e3b8e8b4 100644 --- a/src/devices/nm-device-wireguard.c +++ b/src/devices/nm-device-wireguard.c @@ -265,157 +265,51 @@ done: *out_enabled_v6 = (enabled_v6 == TRUE); } +#define AUTO_RANDOM_RANGE 500u + static guint32 -_auto_default_route_find_unused_table (NMPlatform *platform) +_auto_default_route_get_auto_fwmark (const char *uuid) { - guint32 table; - int is_ipv4; - - for (table = 51820; TRUE; table++) { - const NMDedupMultiHeadEntry *head_entry; - const guint32 table_coerced = nm_platform_route_table_coerce (table); - NMDedupMultiIter iter; - const NMPObject *plobj; - - /* find a table/fwmark that is not yet in use. */ - - for (is_ipv4 = 0; is_ipv4 < 2; is_ipv4++) { - head_entry = nm_platform_lookup_object (platform, - is_ipv4 - ? NMP_OBJECT_TYPE_IP4_ROUTE - : NMP_OBJECT_TYPE_IP6_ROUTE, - -1); - nmp_cache_iter_for_each (&iter, head_entry, &plobj) { - if (NMP_OBJECT_CAST_IP_ROUTE (plobj)->table_coerced == table_coerced) - goto try_next_table; - } - } - - head_entry = nm_platform_lookup_object_by_addr_family (platform, - NMP_OBJECT_TYPE_ROUTING_RULE, - AF_UNSPEC); - nmp_cache_iter_for_each (&iter, head_entry, &plobj) { - const NMPlatformRoutingRule *rr = NMP_OBJECT_CAST_ROUTING_RULE (plobj); - - if (rr->fwmark == table) - goto try_next_table; - } - - head_entry = nm_platform_lookup_obj_type (platform, NMP_OBJECT_TYPE_LINK); - nmp_cache_iter_for_each (&iter, head_entry, &plobj) { - const NMPObject *lnk_wg; - - if (plobj->link.type != NM_LINK_TYPE_WIREGUARD) - continue; - - lnk_wg = plobj->_link.netlink.lnk; - - if (!lnk_wg) - continue; + guint64 rnd_seed; - if (NMP_OBJECT_GET_TYPE (lnk_wg) != NMP_OBJECT_TYPE_LNK_WIREGUARD) - continue; + /* we use the generated number as fwmark but also as routing table for + * the default-route. + * + * We pick a number + * + * - based on the connection's UUID (as stable seed). + * - larger than 51820u (arbitrarily) + * - one out of AUTO_RANDOM_RANGE + */ - if (NMP_OBJECT_CAST_LNK_WIREGUARD (lnk_wg)->fwmark == table) - goto try_next_table; - } + rnd_seed = c_siphash_hash (NM_HASH_SEED_16 (0xb9, 0x39, 0x8e, 0xed, 0x15, 0xb3, 0xd1, 0xc4, 0x5f, 0x45, 0x00, 0x4f, 0xec, 0xc2, 0x2b, 0x7e), + (const guint8 *) uuid, + uuid ? strlen (uuid) + 1u : 0u); - return table; -try_next_table: - ; - } + return 51820u + (rnd_seed % AUTO_RANDOM_RANGE); } -#define PRIO_WIDTH ((guint32) 2) - -static gboolean -_auto_default_route_find_priority_exists (const NMDedupMultiHeadEntry *head_entry, - guint32 priority) -{ - NMDedupMultiIter iter; - const NMPObject *plobj; - - nmp_cache_iter_for_each (&iter, head_entry, &plobj) { - const NMPlatformRoutingRule *rr = NMP_OBJECT_CAST_ROUTING_RULE (plobj); - - /* we don't differenciate between IPv4 vs. IPv6. There should be no - * conflicting rules with the same priority. */ - if ( rr->priority >= priority - && rr->priority < priority + PRIO_WIDTH) - return TRUE; - } - - return FALSE; -} +#define PRIO_WIDTH 2u static guint32 -_auto_default_route_find_priority (NMPlatform *platform, - const char *uuid) +_auto_default_route_get_auto_priority (const char *uuid) { - const NMDedupMultiHeadEntry *head_entry; + const guint32 RANGE_TOP = 32766u - 1000u; guint64 rnd_seed; - const guint32 PRIME_NUMBER = 1111567573u; - const guint32 RANGE_TOP = ((32766u - 2u * PRIO_WIDTH) / PRIO_WIDTH); - const guint32 RANGE_LEN1 = 200u; - const guint32 RANGE_LEN2 = (RANGE_TOP - 100u) - RANGE_LEN1; - guint32 range_len; - guint32 range_top; - guint32 prio_candidate = 0; - guint32 i_step; - guint32 i; - - /* For the auto-default-route policy routing rule we add 4 rules (2 Ipv4 and 2 IPv6). - * Hence, we choose a priority for the first (of the two rules) and the second - * rule gets priority + 1. - * We want a priority that is - * - unused so far. - * - smaller than 32766u (which is the priority of the default rules for IPv4 and IPv6) - * - stable for each connection but different between connections (we hash the UUID - * as a "random" seed) - * - if possible, close to 32766u (RANGE_LEN1). Only otherwise fallback to the entire - * range (RANGE_LEN2). - */ - rnd_seed = c_siphash_hash ((const guint8 [16]) { 0xb9, 0x39, 0x8e, 0xed, 0x15, 0xb3, 0xd1, 0xc4, 0x5f, 0x45, 0x00, 0x4f, 0xec, 0xc2, 0x2b, 0x7e }, + /* we pick a priority for the routing rules as follows: + * + * - use the connection's UUID as stable seed for the "random" number. + * - have it smaller than RANGE_TOP (32766u - 1000u), where 32766u is the priority of the default + * rules + * - we add 2 rules (PRIO_WIDTH). Hence only pick even priorites. + * - pick one out of AUTO_RANDOM_RANGE. */ + + rnd_seed = c_siphash_hash (NM_HASH_SEED_16 (0x99, 0x22, 0x4d, 0x7c, 0x37, 0xda, 0x8e, 0x7b, 0x2f, 0x55, 0x16, 0x7b, 0x75, 0xda, 0x42, 0xdc), (const guint8 *) uuid, uuid ? strlen (uuid) + 1u : 0u); - head_entry = nm_platform_lookup_object_by_addr_family (platform, - NMP_OBJECT_TYPE_ROUTING_RULE, - AF_UNSPEC); - - range_len = RANGE_LEN1; - range_top = RANGE_TOP; - -again: - i_step = ((guint32) rnd_seed) % range_len; - for (i = 0; i < range_len; i++) { - - /* we sample the range in a stable, but somewhat arbitrary order to - * find an unused priority. */ - i_step = (i_step + PRIME_NUMBER) % range_len; - - nm_assert (i_step < range_top); - - prio_candidate = (range_top - i_step) * PRIO_WIDTH; - - nm_assert (prio_candidate < 32766u); - - if (!_auto_default_route_find_priority_exists (head_entry, prio_candidate)) - return prio_candidate; - } - - if (range_len == RANGE_LEN1) { - /* within the narrow range close to RANGE_TOP we couldn't find any unused - * priority. Retry with the entire range... */ - range_len = RANGE_LEN2; - range_top -= RANGE_LEN1; - goto again; - } - - /* Couldn't find an unused one? Very odd, this really should not happen unless there - * are thousands of rules already. Just pick the last one we sampled. */ - return prio_candidate; + return RANGE_TOP - (((rnd_seed % (PRIO_WIDTH * AUTO_RANDOM_RANGE)) / PRIO_WIDTH) * PRIO_WIDTH); } static void @@ -423,10 +317,10 @@ _auto_default_route_init (NMDeviceWireGuard *self) { NMDeviceWireGuardPrivate *priv = NM_DEVICE_WIREGUARD_GET_PRIVATE (self); NMConnection *connection; - NMSettingWireGuard *s_wg; - gboolean enabled_v4; - gboolean enabled_v6; + gboolean enabled_v4 = FALSE; + gboolean enabled_v6 = FALSE; gboolean refreshing_only; + guint32 new_fwmark = 0; guint32 old_fwmark; char sbuf1[100]; @@ -436,40 +330,47 @@ _auto_default_route_init (NMDeviceWireGuard *self) refreshing_only = priv->auto_default_route_initialized && priv->auto_default_route_refresh; - priv->auto_default_route_refresh = FALSE; + + old_fwmark = priv->auto_default_route_fwmark; connection = nm_device_get_applied_connection (NM_DEVICE (self)); + if (connection) { + NMSettingWireGuard *s_wg; - s_wg = _nm_connection_get_setting (connection, NM_TYPE_SETTING_WIREGUARD); + s_wg = _nm_connection_get_setting (connection, NM_TYPE_SETTING_WIREGUARD); - old_fwmark = priv->auto_default_route_fwmark; + new_fwmark = nm_setting_wireguard_get_fwmark (s_wg); + + _auto_default_route_get_enabled (s_wg, + connection, + &enabled_v4, + &enabled_v6); + } - priv->auto_default_route_fwmark = nm_setting_wireguard_get_fwmark (s_wg); + if ( ( enabled_v4 + || enabled_v6) + && new_fwmark == 0u) { + if (refreshing_only) + new_fwmark = old_fwmark; + else + new_fwmark = _auto_default_route_get_auto_fwmark (nm_connection_get_uuid (connection)); + } - _auto_default_route_get_enabled (s_wg, - connection, - &enabled_v4, - &enabled_v6); + priv->auto_default_route_refresh = FALSE; + priv->auto_default_route_fwmark = new_fwmark; priv->auto_default_route_enabled_4 = enabled_v4; priv->auto_default_route_enabled_6 = enabled_v6; priv->auto_default_route_initialized = TRUE; - if ( ( priv->auto_default_route_enabled_4 - || priv->auto_default_route_enabled_6) - && priv->auto_default_route_fwmark == 0u) { - if (refreshing_only) - priv->auto_default_route_fwmark = old_fwmark; - else - priv->auto_default_route_fwmark = _auto_default_route_find_unused_table (nm_device_get_platform (NM_DEVICE (self))); + if (connection) { + _LOGT (LOGD_DEVICE, + "auto-default-route is %s for IPv4 and %s for IPv6%s", + priv->auto_default_route_enabled_4 ? "enabled" : "disabled", + priv->auto_default_route_enabled_6 ? "enabled" : "disabled", + priv->auto_default_route_enabled_4 || priv->auto_default_route_enabled_6 + ? nm_sprintf_buf (sbuf1, " (fwmark 0x%x)", priv->auto_default_route_fwmark) + : ""); } - - _LOGT (LOGD_DEVICE, - "auto-default-route is %s for IPv4 and %s for IPv6%s", - priv->auto_default_route_enabled_4 ? "enabled" : "disabled", - priv->auto_default_route_enabled_6 ? "enabled" : "disabled", - priv->auto_default_route_enabled_4 || priv->auto_default_route_enabled_6 - ? nm_sprintf_buf (sbuf1, " (fwmark 0x%x)", priv->auto_default_route_fwmark) - : ""); } static GPtrArray * @@ -506,8 +407,7 @@ get_extra_rules (NMDevice *device) if (priv->auto_default_route_priority_initialized) priority = priv->auto_default_route_priority; else { - priority = _auto_default_route_find_priority (nm_device_get_platform (device), - nm_connection_get_uuid (connection)); + priority = _auto_default_route_get_auto_priority (nm_connection_get_uuid (connection)); priv->auto_default_route_priority = priority; priv->auto_default_route_priority_initialized = TRUE; } @@ -624,7 +524,7 @@ _peers_remove (NMDeviceWireGuardPrivate *priv, nm_clear_g_cancellable (&peer_data->ep_resolv.cancellable); g_slice_free (PeerData, peer_data); - if (c_list_is_empty (&peer_data->lst_peers)) { + if (c_list_is_empty (&priv->lst_peers_head)) { nm_clear_g_source (&priv->resolve_next_try_id); nm_clear_g_source (&priv->link_config_delayed_id); } @@ -1567,7 +1467,7 @@ link_config (NMDeviceWireGuard *self, plpeers_len, wg_change_flags); - nm_explicit_bzero (plpeers, sizeof (plpeers) * plpeers_len); + nm_explicit_bzero (plpeers, sizeof (plpeers[0]) * plpeers_len); if (r < 0) { NM_SET_OUT (out_failure_reason, NM_DEVICE_STATE_REASON_CONFIG_FAILED); @@ -1618,6 +1518,17 @@ link_config_delayed_resolver_cb (gpointer user_data) } static NMActStageReturn +act_stage1_prepare (NMDevice *device, NMDeviceStateReason *out_failure_reason) +{ + NMDeviceWireGuardPrivate *priv = NM_DEVICE_WIREGUARD_GET_PRIVATE (device); + + priv->auto_default_route_initialized = FALSE; + priv->auto_default_route_priority_initialized = FALSE; + + return NM_DEVICE_CLASS (nm_device_wireguard_parent_class)->act_stage1_prepare (device, out_failure_reason); +} + +static NMActStageReturn act_stage2_config (NMDevice *device, NMDeviceStateReason *out_failure_reason) { @@ -2057,6 +1968,7 @@ nm_device_wireguard_class_init (NMDeviceWireGuardClass *klass) device_class->connection_type_check_compatible = NM_SETTING_WIREGUARD_SETTING_NAME; device_class->link_types = NM_DEVICE_DEFINE_LINK_TYPES (NM_LINK_TYPE_WIREGUARD); + device_class->act_stage1_prepare = act_stage1_prepare; device_class->state_changed = device_state_changed; device_class->create_and_realize = create_and_realize; device_class->act_stage2_config = act_stage2_config; diff --git a/src/devices/nm-device.c b/src/devices/nm-device.c index feb5110d..f07c4f09 100644 --- a/src/devices/nm-device.c +++ b/src/devices/nm-device.c @@ -3186,14 +3186,11 @@ nm_device_check_connectivity (NMDevice *self, NMDeviceConnectivityCallback callback, gpointer user_data) { - NMDeviceConnectivityHandle *handle; - if (!concheck_is_possible (self)) return NULL; concheck_periodic_schedule_set (self, addr_family, CONCHECK_SCHEDULE_CHECK_EXTERNAL); - handle = concheck_start (self, addr_family, callback, user_data, FALSE); - return handle; + return concheck_start (self, addr_family, callback, user_data, FALSE); } void @@ -4153,13 +4150,14 @@ nm_device_create_and_realize (NMDevice *self, { nm_auto_nmpobj const NMPObject *plink_keep_alive = NULL; NMDevicePrivate *priv = NM_DEVICE_GET_PRIVATE (self); - const NMPlatformLink *plink = NULL; + const NMPlatformLink *plink; /* Must be set before device is realized */ - priv->nm_owned = !nm_platform_link_get_by_ifname (nm_device_get_platform (self), priv->iface); - + plink = nm_platform_link_get_by_ifname (nm_device_get_platform (self), priv->iface); + priv->nm_owned = !plink || !link_type_compatible (self, plink->type, NULL, NULL); _LOGD (LOGD_DEVICE, "create (is %snm-owned)", priv->nm_owned ? "" : "not "); + plink = NULL; /* Create any resources the device needs */ if (NM_DEVICE_GET_CLASS (self)->create_and_realize) { if (!NM_DEVICE_GET_CLASS (self)->create_and_realize (self, connection, parent, &plink, error)) @@ -4986,7 +4984,6 @@ nm_device_master_release_slaves (NMDevice *self) { NMDevicePrivate *priv = NM_DEVICE_GET_PRIVATE (self); NMDeviceStateReason reason; - gboolean configure = TRUE; CList *iter, *safe; /* Don't release the slaves if this connection doesn't belong to NM. */ @@ -4997,14 +4994,10 @@ nm_device_master_release_slaves (NMDevice *self) if (priv->state == NM_DEVICE_STATE_FAILED) reason = NM_DEVICE_STATE_REASON_DEPENDENCY_FAILED; - if ( priv->ifindex <= 0 - || !nm_platform_link_get (nm_device_get_platform (self), priv->ifindex)) - configure = FALSE; - c_list_for_each_safe (iter, safe, &priv->slaves) { SlaveInfo *info = c_list_entry (iter, SlaveInfo, lst_slave); - nm_device_master_release_one_slave (self, info->slave, configure, reason); + nm_device_master_release_one_slave (self, info->slave, TRUE, reason); } } @@ -15121,6 +15114,7 @@ _set_state_full (NMDevice *self, gboolean no_firmware = FALSE; NMSettingsConnection *sett_conn; NMSettingSriov *s_sriov; + gboolean concheck_now; g_return_if_fail (NM_IS_DEVICE (self)); @@ -15456,8 +15450,11 @@ _set_state_full (NMDevice *self, if (ip_config_valid (old_state) && !ip_config_valid (state)) notify_ip_properties (self); - concheck_update_interval (self, AF_INET, state == NM_DEVICE_STATE_ACTIVATED); - concheck_update_interval (self, AF_INET6, state == NM_DEVICE_STATE_ACTIVATED); + concheck_now = NM_IN_SET (state, NM_DEVICE_STATE_ACTIVATED, + NM_DEVICE_STATE_DISCONNECTED) + || old_state >= NM_DEVICE_STATE_ACTIVATED; + concheck_update_interval (self, AF_INET, concheck_now); + concheck_update_interval (self, AF_INET6, concheck_now); /* Dispose of the cached activation request */ if (req) diff --git a/src/devices/nm-lldp-listener.c b/src/devices/nm-lldp-listener.c index c0d78315..469ccce1 100644 --- a/src/devices/nm-lldp-listener.c +++ b/src/devices/nm-lldp-listener.c @@ -224,7 +224,7 @@ _lldp_attr_set_str (LldpAttrData *pdata, LldpAttrId attr_id, const char *v_strin } static void -_lldp_attr_take_str_ptr (LldpAttrData *pdata, LldpAttrId attr_id, char *str) +_lldp_attr_set_str_take (LldpAttrData *pdata, LldpAttrId attr_id, char *str) { nm_assert (pdata); nm_assert (_lldp_attr_id_to_type (attr_id) == LLDP_ATTR_TYPE_STRING); @@ -232,8 +232,10 @@ _lldp_attr_take_str_ptr (LldpAttrData *pdata, LldpAttrId attr_id, char *str) pdata = &pdata[attr_id]; /* we ignore duplicate fields silently. */ - if (pdata->attr_type != LLDP_ATTR_TYPE_NONE) + if (pdata->attr_type != LLDP_ATTR_TYPE_NONE) { + g_free (str); return; + } pdata->attr_type = LLDP_ATTR_TYPE_STRING; pdata->v_string = str; @@ -265,8 +267,7 @@ _lldp_attr_set_vardict (LldpAttrData *pdata, LldpAttrId attr_id, GVariant *varia /* we ignore duplicate fields silently */ if (pdata->attr_type != LLDP_ATTR_TYPE_NONE) { - if (g_variant_is_floating (variant)) - g_variant_unref (variant); + nm_g_variant_unref_floating (variant); return; } @@ -685,9 +686,10 @@ lldp_neighbor_new (sd_lldp_neighbor *neighbor_sd, GError **error) g_variant_dict_end (&dict)); _lldp_attr_set_uint32 (neigh->attrs, LLDP_ATTR_ID_IEEE_802_1_VID, vid); - _lldp_attr_take_str_ptr (neigh->attrs, - LLDP_ATTR_ID_IEEE_802_1_VLAN_NAME, - name_to_free ?: g_strdup (name)); + if (name_to_free) + _lldp_attr_set_str_take (neigh->attrs, LLDP_ATTR_ID_IEEE_802_1_VLAN_NAME, name_to_free); + else + _lldp_attr_set_str (neigh->attrs, LLDP_ATTR_ID_IEEE_802_1_VLAN_NAME, name); break; } default: diff --git a/src/devices/team/nm-device-team.c b/src/devices/team/nm-device-team.c index a60a9fda..4661a840 100644 --- a/src/devices/team/nm-device-team.c +++ b/src/devices/team/nm-device-team.c @@ -775,6 +775,12 @@ release_slave (NMDevice *device, NMDeviceTeamPrivate *priv = NM_DEVICE_TEAM_GET_PRIVATE (self); gboolean success; int ifindex_slave; + int ifindex; + + ifindex = nm_device_get_ifindex (device); + if ( ifindex <= 0 + || !nm_platform_link_get (nm_device_get_platform (device), ifindex)) + configure = FALSE; ifindex_slave = nm_device_get_ip_ifindex (slave); diff --git a/src/devices/wwan/nm-modem-broadband.c b/src/devices/wwan/nm-modem-broadband.c index 5716500a..216fedfe 100644 --- a/src/devices/wwan/nm-modem-broadband.c +++ b/src/devices/wwan/nm-modem-broadband.c @@ -1134,7 +1134,7 @@ simple_disconnect_ready (GObject *source_object, { MMModemSimple *modem_iface = MM_MODEM_SIMPLE (source_object); DisconnectContext *ctx = user_data; - GError *error = NULL; + gs_free_error GError *error = NULL; if (!mm_modem_simple_disconnect_finish (modem_iface, res, &error)) { if ( ctx->warn diff --git a/src/initrd/nmi-cmdline-reader.c b/src/initrd/nmi-cmdline-reader.c index ccdd1f29..7a3af8d6 100644 --- a/src/initrd/nmi-cmdline-reader.c +++ b/src/initrd/nmi-cmdline-reader.c @@ -244,7 +244,7 @@ parse_ip (GHashTable *connections, const char *sysfs_dir, char *argument) dns[0] = tmp; dns[1] = get_word (&argument, ':'); dns_addr_family[1] = guess_ip_address_family (dns[1]); - if (argument && *argument) + if (*argument) _LOGW (LOGD_CORE, "Ignoring extra: '%s'.", argument); } else { mtu = tmp; diff --git a/src/nm-ip4-config.c b/src/nm-ip4-config.c index 86c82925..36e75bb2 100644 --- a/src/nm-ip4-config.c +++ b/src/nm-ip4-config.c @@ -544,6 +544,9 @@ _addresses_sort_cmp (gconstpointer a, gconstpointer b, gpointer user_data) const NMPlatformIP4Address *a2 = NMP_OBJECT_CAST_IP4_ADDRESS (*((const NMPObject **) b)); guint32 n1, n2; + nm_assert (a1); + nm_assert (a2); + /* Sort by address type. For example link local will * be sorted *after* a global address. */ p1 = _addresses_sort_cmp_get_prio (a1->address); @@ -577,6 +580,9 @@ sort_captured_addresses (const CList *lst_a, const CList *lst_b, gconstpointer u const NMPlatformIP4Address *addr_a = NMP_OBJECT_CAST_IP4_ADDRESS (c_list_entry (lst_a, NMDedupMultiEntry, lst_entries)->obj); const NMPlatformIP4Address *addr_b = NMP_OBJECT_CAST_IP4_ADDRESS (c_list_entry (lst_b, NMDedupMultiEntry, lst_entries)->obj); + nm_assert (addr_a); + nm_assert (addr_b); + /* Primary addresses first */ return NM_FLAGS_HAS (addr_a->n_ifa_flags, IFA_F_SECONDARY) - NM_FLAGS_HAS (addr_b->n_ifa_flags, IFA_F_SECONDARY); diff --git a/src/nm-ip6-config.c b/src/nm-ip6-config.c index 1096fb42..1810d511 100644 --- a/src/nm-ip6-config.c +++ b/src/nm-ip6-config.c @@ -318,6 +318,9 @@ sort_captured_addresses (const CList *lst_a, const CList *lst_b, gconstpointer u const NMPlatformIP6Address *addr_a = NMP_OBJECT_CAST_IP6_ADDRESS (c_list_entry (lst_a, NMDedupMultiEntry, lst_entries)->obj); const NMPlatformIP6Address *addr_b = NMP_OBJECT_CAST_IP6_ADDRESS (c_list_entry (lst_b, NMDedupMultiEntry, lst_entries)->obj); + nm_assert (addr_a); + nm_assert (addr_b); + return _addresses_sort_cmp (addr_a, addr_b, ((NMSettingIP6ConfigPrivacy) GPOINTER_TO_INT (user_data)) == NM_SETTING_IP6_CONFIG_PRIVACY_PREFER_TEMP_ADDR); } diff --git a/src/nm-manager.c b/src/nm-manager.c index 6ea53502..64cdb9ae 100644 --- a/src/nm-manager.c +++ b/src/nm-manager.c @@ -2698,6 +2698,7 @@ recheck_assume_connection (NMManager *self, gboolean was_unmanaged = FALSE; gboolean generated = FALSE; NMDeviceState state; + gboolean activation_type_assume; g_return_val_if_fail (NM_IS_MANAGER (self), FALSE); g_return_val_if_fail (NM_IS_DEVICE (device), FALSE); @@ -2721,10 +2722,42 @@ recheck_assume_connection (NMManager *self, if (!sett_conn) return FALSE; + activation_type_assume = !generated; + + if (state == NM_DEVICE_STATE_UNMANAGED) { + gs_free char *initramfs_lease = g_strdup_printf (RUNSTATEDIR "/initramfs/net.%s.lease", + nm_device_get_iface (device)); + gs_free char *connection_lease = g_strdup_printf (NMRUNDIR "/dhclient-%s-%s.lease", + nm_settings_connection_get_uuid (sett_conn), + nm_device_get_iface (device)); + + if (rename (initramfs_lease, connection_lease) == 0) { + /* + * We've managed to steal the lease used by initramfs before it + * killed off the dhclient. We need to take ownership of the configured + * connection and act like the device was configured by us. + * Otherwise the address would just expire. + */ + _LOG2I (LOGD_DEVICE, device, "assume: taking over an initramfs-configured connection"); + activation_type_assume = TRUE; + + if (generated) { + nm_settings_connection_update (sett_conn, + NULL, + NM_SETTINGS_CONNECTION_PERSIST_MODE_KEEP, + 0, + NM_SETTINGS_CONNECTION_INT_FLAGS_VOLATILE, + NM_SETTINGS_CONNECTION_UPDATE_REASON_NONE, + "assume-initrd", + NULL); + } + } + } + nm_device_sys_iface_state_set (device, - generated - ? NM_DEVICE_SYS_IFACE_STATE_EXTERNAL - : NM_DEVICE_SYS_IFACE_STATE_ASSUME); + activation_type_assume + ? NM_DEVICE_SYS_IFACE_STATE_ASSUME + : NM_DEVICE_SYS_IFACE_STATE_EXTERNAL); /* Move device to DISCONNECTED to activate the connection */ if (state == NM_DEVICE_STATE_UNMANAGED) { @@ -2768,8 +2801,8 @@ recheck_assume_connection (NMManager *self, NULL, device, subject, - generated ? NM_ACTIVATION_TYPE_EXTERNAL : NM_ACTIVATION_TYPE_ASSUME, - generated ? NM_ACTIVATION_REASON_EXTERNAL : NM_ACTIVATION_REASON_ASSUME, + activation_type_assume ? NM_ACTIVATION_TYPE_ASSUME : NM_ACTIVATION_TYPE_EXTERNAL, + activation_type_assume ? NM_ACTIVATION_REASON_ASSUME : NM_ACTIVATION_REASON_EXTERNAL, NM_ACTIVATION_STATE_FLAG_LIFETIME_BOUND_TO_PROFILE_VISIBILITY, &error); @@ -2785,7 +2818,8 @@ recheck_assume_connection (NMManager *self, NM_DEVICE_STATE_REASON_CONFIG_FAILED); } - if (generated) { + if ( generated + && !activation_type_assume) { _LOG2D (LOGD_DEVICE, device, "assume: deleting generated connection after assuming failed"); nm_settings_connection_delete (sett_conn, FALSE); } else { diff --git a/src/platform/tests/test-link.c b/src/platform/tests/test-link.c index 5926dac1..27ec3f07 100644 --- a/src/platform/tests/test-link.c +++ b/src/platform/tests/test-link.c @@ -257,7 +257,7 @@ test_slave (int master, int type, SignalData *master_changed) case NM_LINK_TYPE_TEAM: g_assert (nm_platform_link_set_down (NM_PLATFORM_GET, ifindex)); accept_signal (link_changed); - accept_signals (master_changed, 0, 2); + accept_signals (master_changed, 0, 3); break; default: break; diff --git a/src/platform/wifi/nm-wifi-utils-nl80211.c b/src/platform/wifi/nm-wifi-utils-nl80211.c index 164dada4..84a93f4f 100644 --- a/src/platform/wifi/nm-wifi-utils-nl80211.c +++ b/src/platform/wifi/nm-wifi-utils-nl80211.c @@ -284,8 +284,8 @@ nl80211_get_wake_on_wlan_handler (struct nl_msg *msg, void *arg) struct genlmsghdr *gnlh = nlmsg_data (nlmsg_hdr (msg)); nla_parse_arr (attrs, - genlmsg_attrdata(gnlh, 0), - genlmsg_attrlen(gnlh, 0), + genlmsg_attrdata (gnlh, 0), + genlmsg_attrlen (gnlh, 0), NULL); if (!attrs[NL80211_ATTR_WOWLAN_TRIGGERS]) @@ -343,10 +343,10 @@ wifi_nl80211_set_wake_on_wlan (NMWifiUtils *data, NMSettingWirelessWakeOnWLan wo return TRUE; msg = nl80211_alloc_msg (self, NL80211_CMD_SET_WOWLAN, 0); - if (!msg) - return FALSE; triggers = nla_nest_start (msg, NL80211_ATTR_WOWLAN_TRIGGERS); + if (!triggers) + goto nla_put_failure; if (NM_FLAGS_HAS (wowl, NM_SETTING_WIRELESS_WAKE_ON_WLAN_ANY)) NLA_PUT_FLAG (msg, NL80211_WOWLAN_TRIG_ANY); @@ -363,7 +363,7 @@ wifi_nl80211_set_wake_on_wlan (NMWifiUtils *data, NMSettingWirelessWakeOnWLan wo if (NM_FLAGS_HAS (wowl, NM_SETTING_WIRELESS_WAKE_ON_WLAN_RFKILL_RELEASE)) NLA_PUT_FLAG (msg, NL80211_WOWLAN_TRIG_RFKILL_RELEASE); - nla_nest_end(msg, triggers); + nla_nest_end (msg, triggers); err = nl80211_send_and_recv (self, msg, NULL, NULL); @@ -634,14 +634,12 @@ nl80211_get_ap_info (NMWifiUtilsNl80211 *self, return; msg = nl80211_alloc_msg (self, NL80211_CMD_GET_STATION, 0); - if (msg) { - NLA_PUT (msg, NL80211_ATTR_MAC, ETH_ALEN, bss_info.bssid); + NLA_PUT (msg, NL80211_ATTR_MAC, ETH_ALEN, bss_info.bssid); - nl80211_send_and_recv (self, msg, nl80211_station_handler, sta_info); - if (!sta_info->signal_valid) { - /* Fall back to bss_info signal quality (both are in percent) */ - sta_info->signal = bss_info.beacon_signal; - } + nl80211_send_and_recv (self, msg, nl80211_station_handler, sta_info); + if (!sta_info->signal_valid) { + /* Fall back to bss_info signal quality (both are in percent) */ + sta_info->signal = bss_info.beacon_signal; } return; diff --git a/src/settings/nm-agent-manager.c b/src/settings/nm-agent-manager.c index d361c06a..2f9827d5 100644 --- a/src/settings/nm-agent-manager.c +++ b/src/settings/nm-agent-manager.c @@ -1593,16 +1593,6 @@ static const NMDBusInterfaceInfoExtended interface_info_agent_manager = { ), NM_DEFINE_DBUS_METHOD_INFO_EXTENDED ( NM_DEFINE_GDBUS_METHOD_INFO_INIT ( - "RegisterWithCapabilities", - .in_args = NM_DEFINE_GDBUS_ARG_INFOS ( - NM_DEFINE_GDBUS_ARG_INFO ("identifier", "s"), - NM_DEFINE_GDBUS_ARG_INFO ("capabilities", "u"), - ), - ), - .handle = impl_agent_manager_register_with_capabilities, - ), - NM_DEFINE_DBUS_METHOD_INFO_EXTENDED ( - NM_DEFINE_GDBUS_METHOD_INFO_INIT ( "Unregister", ), .handle = impl_agent_manager_unregister, diff --git a/src/settings/nm-settings.c b/src/settings/nm-settings.c index 430d2776..42a7bca0 100644 --- a/src/settings/nm-settings.c +++ b/src/settings/nm-settings.c @@ -1455,7 +1455,7 @@ _add_connection_to_first_plugin (NMSettings *self, GError **error) { NMSettingsPrivate *priv = NM_SETTINGS_GET_PRIVATE (self); - GError *first_error = NULL; + gs_free_error GError *first_error = NULL; GSList *iter; const char *uuid; @@ -1561,7 +1561,7 @@ _add_connection_to_first_plugin (NMSettings *self, } nm_assert (first_error); - g_propagate_error (error, first_error); + g_propagate_error (error, g_steal_pointer (&first_error)); return FALSE; } @@ -2866,7 +2866,7 @@ _clear_connections_cached_list (NMSettingsPrivate *priv) * it. That is a bug, this code just tries to make it blow up * more eagerly. */ memset (priv->connections_cached_list, - 0xdeaddead, + 0x43, sizeof (NMSettingsConnection *) * (priv->connections_len + 1)); #endif diff --git a/src/settings/plugins/ifcfg-rh/nms-ifcfg-rh-reader.c b/src/settings/plugins/ifcfg-rh/nms-ifcfg-rh-reader.c index 900a3fc1..9c3ae10a 100644 --- a/src/settings/plugins/ifcfg-rh/nms-ifcfg-rh-reader.c +++ b/src/settings/plugins/ifcfg-rh/nms-ifcfg-rh-reader.c @@ -3629,7 +3629,10 @@ make_wpa_setting (shvarFile *ifcfg, wpa_sae = nm_streq0 (v, "SAE"); wpa_eap = nm_streq0 (v, "WPA-EAP"); ieee8021x = nm_streq0 (v, "IEEE8021X"); - if (!wpa_psk && !wpa_sae && !wpa_eap && !ieee8021x) + if ( !wpa_psk + && !wpa_sae + && !wpa_eap + && !ieee8021x) return NULL; /* Not WPA or Dynamic WEP */ /* WPS */ @@ -3689,11 +3692,13 @@ make_wpa_setting (shvarFile *ifcfg, g_object_set (wsec, NM_SETTING_WIRELESS_SECURITY_KEY_MGMT, "wpa-none", NULL); else if (wpa_psk) g_object_set (wsec, NM_SETTING_WIRELESS_SECURITY_KEY_MGMT, "wpa-psk", NULL); - else if (wpa_sae) + else { + nm_assert (wpa_sae); g_object_set (wsec, NM_SETTING_WIRELESS_SECURITY_KEY_MGMT, "sae", NULL); - else - g_assert_not_reached (); - } else if (wpa_eap || ieee8021x) { + } + } else { + nm_assert (wpa_eap || ieee8021x); + /* Adhoc mode is mutually exclusive with any 802.1x-based authentication */ if (adhoc) { g_set_error (error, NM_SETTINGS_ERROR, NM_SETTINGS_ERROR_INVALID_CONNECTION, @@ -3710,10 +3715,6 @@ make_wpa_setting (shvarFile *ifcfg, g_object_set (wsec, NM_SETTING_WIRELESS_SECURITY_KEY_MGMT, lower, NULL); } - } else { - g_set_error (error, NM_SETTINGS_ERROR, NM_SETTINGS_ERROR_INVALID_CONNECTION, - "Unknown wireless KEY_MGMT type '%s'", v); - return NULL; } i_val = NM_SETTING_WIRELESS_SECURITY_PMF_DEFAULT; diff --git a/src/settings/plugins/ifupdown/nms-ifupdown-plugin.c b/src/settings/plugins/ifupdown/nms-ifupdown-plugin.c index 93f1813c..475ecbb6 100644 --- a/src/settings/plugins/ifupdown/nms-ifupdown-plugin.c +++ b/src/settings/plugins/ifupdown/nms-ifupdown-plugin.c @@ -321,10 +321,10 @@ load_eni_ifaces (NMSIfupdownPlugin *self) sd_repl = g_hash_table_lookup (eni_ifaces, block->name); if (sd_repl) { - storage = g_steal_pointer (&sd_repl->storage); _LOGD ("parse: replace connection \"%s\" (%s)", block->name, nm_settings_storage_get_uuid (sd_repl->storage)); + storage = g_steal_pointer (&sd_repl->storage); g_hash_table_remove (eni_ifaces, block->name); } diff --git a/src/supplicant/nm-supplicant-config.c b/src/supplicant/nm-supplicant-config.c index 806c087c..f6e3c7da 100644 --- a/src/supplicant/nm-supplicant-config.c +++ b/src/supplicant/nm-supplicant-config.c @@ -139,11 +139,17 @@ nm_supplicant_config_add_option_with_type (NMSupplicantConfig *self, else { type = nm_supplicant_settings_verify_setting (key, value, len); if (type == TYPE_INVALID) { - char buf[255]; - memset (&buf[0], 0, sizeof (buf)); - memcpy (&buf[0], value, len > 254 ? 254 : len); + gs_free char *str_free = NULL; + const char *str; + + str = nm_utils_buf_utf8safe_escape (value, len, NM_UTILS_STR_UTF8_SAFE_FLAG_ESCAPE_CTRL, &str_free); + + str = nm_strquote_a (255, str); + g_set_error (error, NM_SUPPLICANT_ERROR, NM_SUPPLICANT_ERROR_CONFIG, - "key '%s' and/or value '%s' invalid", key, hidden ?: buf); + "key '%s' and/or value %s invalid", + key, + hidden ?: str); return FALSE; } } diff --git a/src/supplicant/nm-supplicant-settings-verify.c b/src/supplicant/nm-supplicant-settings-verify.c index 1bd71320..b37fae9e 100644 --- a/src/supplicant/nm-supplicant-settings-verify.c +++ b/src/supplicant/nm-supplicant-settings-verify.c @@ -30,7 +30,7 @@ struct Opt { const gint32 int_low; /* Inclusive */ const gint32 int_high; /* Inclusive; max length for strings */ const gboolean str_allowed_multiple; - const char ** str_allowed; + const char *const*str_allowed; }; static gboolean validate_type_int (const struct Opt * opt, @@ -63,31 +63,31 @@ static const struct validate_entry validate_table[] = { { TYPE_KEYWORD, validate_type_keyword }, }; -const char * pairwise_allowed[] = { "CCMP", "TKIP", "NONE", NULL }; -const char * group_allowed[] = { "CCMP", "TKIP", "WEP104", "WEP40", NULL }; -const char * proto_allowed[] = { "WPA", "RSN", NULL }; -const char * key_mgmt_allowed[] = { "WPA-PSK", "WPA-PSK-SHA256", "FT-PSK", - "WPA-EAP", "WPA-EAP-SHA256", "FT-EAP", "FT-EAP-SHA384", - "FILS-SHA256", "FILS-SHA384", - "IEEE8021X", "WPA-NONE", "SAE", - "NONE", NULL }; -const char * auth_alg_allowed[] = { "OPEN", "SHARED", "LEAP", NULL }; -const char * eap_allowed[] = { "LEAP", "MD5", "TLS", "PEAP", "TTLS", "SIM", - "PSK", "FAST", "PWD", NULL }; - -const char * phase1_allowed[] = {"peapver=0", "peapver=1", "peaplabel=1", - "peap_outer_success=0", "include_tls_length=1", - "sim_min_num_chal=3", "fast_provisioning=0", - "fast_provisioning=1", "fast_provisioning=2", - "fast_provisioning=3", "tls_disable_tlsv1_0=0", - "tls_disable_tlsv1_0=1", "tls_disable_tlsv1_1=0", - "tls_disable_tlsv1_1=1", "tls_disable_tlsv1_2=0", - "tls_disable_tlsv1_2=1", NULL }; -const char * phase2_allowed[] = {"auth=PAP", "auth=CHAP", "auth=MSCHAP", - "auth=MSCHAPV2", "auth=GTC", "auth=OTP", - "auth=MD5", "auth=TLS", "autheap=MD5", - "autheap=MSCHAPV2", "autheap=OTP", - "autheap=GTC", "autheap=TLS", NULL }; +static const char *const pairwise_allowed[] = { "CCMP", "TKIP", "NONE", NULL }; +static const char *const group_allowed[] = { "CCMP", "TKIP", "WEP104", "WEP40", NULL }; +static const char *const proto_allowed[] = { "WPA", "RSN", NULL }; +static const char *const key_mgmt_allowed[] = { "WPA-PSK", "WPA-PSK-SHA256", "FT-PSK", + "WPA-EAP", "WPA-EAP-SHA256", "FT-EAP", "FT-EAP-SHA384", + "FILS-SHA256", "FILS-SHA384", + "IEEE8021X", "WPA-NONE", "SAE", + "NONE", NULL }; +static const char *const auth_alg_allowed[] = { "OPEN", "SHARED", "LEAP", NULL }; +static const char *const eap_allowed[] = { "LEAP", "MD5", "TLS", "PEAP", "TTLS", "SIM", + "PSK", "FAST", "PWD", NULL }; + +static const char *const phase1_allowed[] = { "peapver=0", "peapver=1", "peaplabel=1", + "peap_outer_success=0", "include_tls_length=1", + "sim_min_num_chal=3", "fast_provisioning=0", + "fast_provisioning=1", "fast_provisioning=2", + "fast_provisioning=3", "tls_disable_tlsv1_0=0", + "tls_disable_tlsv1_0=1", "tls_disable_tlsv1_1=0", + "tls_disable_tlsv1_1=1", "tls_disable_tlsv1_2=0", + "tls_disable_tlsv1_2=1", NULL }; +static const char *const phase2_allowed[] = { "auth=PAP", "auth=CHAP", "auth=MSCHAP", + "auth=MSCHAPV2", "auth=GTC", "auth=OTP", + "auth=MD5", "auth=TLS", "autheap=MD5", + "autheap=MSCHAPV2", "autheap=OTP", + "autheap=GTC", "autheap=TLS", NULL }; static const struct Opt opt_table[] = { { "ssid", TYPE_BYTES, 0, 32,FALSE, NULL }, @@ -206,10 +206,7 @@ validate_type_keyword (const struct Opt * opt, const char * value, const guint32 len) { - char **allowed; - char **candidates = NULL; - char **candidate; - gboolean found = FALSE; + gs_free char *value_free = NULL; g_return_val_if_fail (opt != NULL, FALSE); g_return_val_if_fail (value != NULL, FALSE); @@ -218,26 +215,33 @@ validate_type_keyword (const struct Opt * opt, if (!opt->str_allowed) return TRUE; - candidates = g_strsplit (value, " ", 0); - if (!candidates) - goto out; + value = nm_strndup_a (300, value, len, &value_free); /* validate each space-separated word in 'value' */ - for (candidate = candidates; *candidate; candidate++) { - found = FALSE; - for (allowed = (char **) opt->str_allowed; *allowed; allowed++) { - if (strcmp (*candidate, *allowed) == 0) { - found = TRUE; - break; - } + + while (TRUE) { + char *s; + + while (value[0] == ' ') + value++; + + if (value[0] == '\0') + return TRUE; + + s = strchr (value, ' '); + if (s) { + s[0] = '\0'; + s++; } - if (!found) - break; - } -out: - g_strfreev (candidates); - return found; + if (nm_utils_strv_find_first ((char **) opt->str_allowed, -1, value) < 0) + return FALSE; + + if (!s) + return TRUE; + + value = s; + } } OptType @@ -254,7 +258,9 @@ nm_supplicant_settings_verify_setting (const char * key, g_return_val_if_fail (value != NULL, FALSE); if (strcmp (key, "mode") == 0) { - if (strcmp (value, "1") && strcmp (value, "2") && strcmp (value, "5")) + if (len != 1) + return TYPE_INVALID; + if (!NM_IN_SET (value[0], '1', '2', '5')) return TYPE_INVALID; return TYPE_INT; } |