summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorThomas Haller <thaller@redhat.com>2018-10-16 14:06:43 +0200
committerThomas Haller <thaller@redhat.com>2018-10-17 16:22:34 +0200
commita600b3a3b26660ad519ed2ffb0c0cd1d0f41df08 (patch)
treef2c47b8190a7f0fc9f8262708367e62e49dbec41
parentc0d292d2551622f656a6eee7ccab7dfa2fc50b9a (diff)
downloadNetworkManager-a600b3a3b26660ad519ed2ffb0c0cd1d0f41df08.tar.gz
cli: fix handling uint64 connection property "serial.send-delay"
libnm currently has only one GObject property of type uint64: "serial.send-delay". However, it's broken because uint64 handling is not implemented. $ nmcli connection add type gsm autoconnect no con-name t ifname '*' apn 'xyz' serial.baud 5 Connection 't' (4c929f17-9fda-41d6-8f90-897f6d46b078) successfully added. $ nmcli connection show t ... ipv6.dhcp-duid: -- ipv6.dhcp-send-hostname: yes ipv6.dhcp-hostname: -- ipv6.token: -- (process:14016): libnmc-CRITICAL **: 14:08:32.591: file clients/common/nm-meta-setting-desc.c: line 811 (_get_fcn_gobject_int): should not be reached serial.baud: 5 serial.bits: 8 serial.parity: none serial.stopbits: 1 serial.send-delay: -- gsm.number: *99# ... $ nmcli connection add type gsm autoconnect no con-name t ifname '*' apn 'xyz' serial.baud 5 serial.send-delay 100 (process:14852): libnmc-CRITICAL **: 14:12:24.259: file clients/common/nm-meta-setting-desc.c: line 1131 (_set_fcn_gobject_int): should not be reached Segmentation fault (core dumped) Fixes: b6d9bdcee86fc6d52b2aa1bc8a0dcfa64bec86e8
-rw-r--r--clients/common/nm-meta-setting-desc.c153
-rw-r--r--clients/common/nm-meta-setting-desc.h11
2 files changed, 104 insertions, 60 deletions
diff --git a/clients/common/nm-meta-setting-desc.c b/clients/common/nm-meta-setting-desc.c
index 29ce89f740..bd58e31370 100644
--- a/clients/common/nm-meta-setting-desc.c
+++ b/clients/common/nm-meta-setting-desc.c
@@ -783,7 +783,8 @@ _get_fcn_gobject_int (ARGS_GET_FCN)
{
GParamSpec *pspec;
nm_auto_unset_gvalue GValue gval = G_VALUE_INIT;
- gint64 v;
+ gboolean is_uint64 = FALSE;
+ NMMetaSignUnsignInt64 v;
guint base = 10;
const NMMetaUtilsIntValueInfo *value_infos;
char *return_str;
@@ -799,13 +800,18 @@ _get_fcn_gobject_int (ARGS_GET_FCN)
NM_SET_OUT (out_is_default, g_param_value_defaults (pspec, &gval));
switch (pspec->value_type) {
case G_TYPE_INT:
- v = g_value_get_int (&gval);
+ v.i64 = g_value_get_int (&gval);
break;
case G_TYPE_UINT:
- v = g_value_get_uint (&gval);
+ v.u64 = g_value_get_uint (&gval);
+ is_uint64 = TRUE;
break;
case G_TYPE_INT64:
- v = g_value_get_int64 (&gval);
+ v.i64 = g_value_get_int64 (&gval);
+ break;
+ case G_TYPE_UINT64:
+ v.u64 = g_value_get_uint64 (&gval);
+ is_uint64 = TRUE;
break;
default:
g_return_val_if_reached (NULL);
@@ -819,10 +825,16 @@ _get_fcn_gobject_int (ARGS_GET_FCN)
switch (base) {
case 10:
- return_str = g_strdup_printf ("%"G_GINT64_FORMAT, v);
+ if (is_uint64)
+ return_str = g_strdup_printf ("%"G_GUINT64_FORMAT, v.u64);
+ else
+ return_str = g_strdup_printf ("%"G_GINT64_FORMAT, v.i64);
break;
case 16:
- return_str = g_strdup_printf ("0x%"G_GINT64_MODIFIER"x", v);
+ if (is_uint64)
+ return_str = g_strdup_printf ("0x%"G_GINT64_MODIFIER"x", v.u64);
+ else
+ return_str = g_strdup_printf ("0x%"G_GINT64_MODIFIER"x", (guint64) v.i64);
break;
default:
return_str = NULL;
@@ -833,7 +845,8 @@ _get_fcn_gobject_int (ARGS_GET_FCN)
&& property_info->property_typ_data
&& (value_infos = property_info->property_typ_data->subtype.gobject_int.value_infos)) {
for (; value_infos->nick; value_infos++) {
- if (value_infos->value == v) {
+ if ( ( is_uint64 && value_infos->value.u64 == v.u64)
+ || (!is_uint64 && value_infos->value.i64 == v.i64)) {
char *old_str = return_str;
return_str = g_strdup_printf ("%s (%s)", old_str, value_infos->nick);
@@ -1060,16 +1073,21 @@ _set_fcn_gobject_int (ARGS_SET_FCN)
int errsv;
const GParamSpec *pspec;
nm_auto_unset_gvalue GValue gval = G_VALUE_INIT;
- gint64 v = 0;
+ gboolean is_uint64;
+ NMMetaSignUnsignInt64 v;
gboolean has_minmax = FALSE;
- gint64 min = G_MININT64;
- gint64 max = G_MAXINT64;
+ NMMetaSignUnsignInt64 min = { 0 };
+ NMMetaSignUnsignInt64 max = { 0 };
guint base = 10;
- const NMMetaUtilsIntValueInfo *value_infos = NULL;
- gboolean has_value = FALSE;
+ const NMMetaUtilsIntValueInfo *value_infos;
- if (property_info->property_typ_data) {
+ pspec = g_object_class_find_property (G_OBJECT_GET_CLASS (G_OBJECT (setting)), property_info->property_name);
+ if (!G_IS_PARAM_SPEC (pspec))
+ g_return_val_if_reached (FALSE);
+ is_uint64 = NM_IN_SET (pspec->value_type, G_TYPE_UINT, G_TYPE_UINT64);
+
+ if (property_info->property_typ_data) {
if ( value
&& (value_infos = property_info->property_typ_data->subtype.gobject_int.value_infos)) {
gs_free char *vv_stripped = NULL;
@@ -1083,85 +1101,106 @@ _set_fcn_gobject_int (ARGS_SET_FCN)
for (; value_infos->nick; value_infos++) {
if (nm_streq (value_infos->nick, vv)) {
v = value_infos->value;
- has_value = TRUE;
- break;
+ goto have_value_from_nick;
}
}
}
if (property_info->property_typ_data->subtype.gobject_int.base > 0)
base = property_info->property_typ_data->subtype.gobject_int.base;
- if ( property_info->property_typ_data->subtype.gobject_int.min
- || property_info->property_typ_data->subtype.gobject_int.max) {
+
+ if ( ( is_uint64
+ && ( property_info->property_typ_data->subtype.gobject_int.min.u64
+ || property_info->property_typ_data->subtype.gobject_int.max.u64))
+ || ( !is_uint64
+ && ( property_info->property_typ_data->subtype.gobject_int.min.i64
+ || property_info->property_typ_data->subtype.gobject_int.max.i64))) {
min = property_info->property_typ_data->subtype.gobject_int.min;
max = property_info->property_typ_data->subtype.gobject_int.max;
has_minmax = TRUE;
}
}
- pspec = g_object_class_find_property (G_OBJECT_GET_CLASS (G_OBJECT (setting)), property_info->property_name);
- if (!G_IS_PARAM_SPEC (pspec))
- g_return_val_if_reached (FALSE);
- switch (pspec->value_type) {
- case G_TYPE_INT:
- if (!has_minmax) {
- const GParamSpecInt *p = (GParamSpecInt *) pspec;
+ if (!has_minmax) {
+ switch (pspec->value_type) {
+ case G_TYPE_INT:
+ {
+ const GParamSpecInt *p = (GParamSpecInt *) pspec;
- min = p->minimum;
- max = p->maximum;
- }
- break;
- case G_TYPE_UINT:
- if (!has_minmax) {
- const GParamSpecUInt *p = (GParamSpecUInt *) pspec;
+ min.i64 = p->minimum;
+ max.i64 = p->maximum;
+ }
+ break;
+ case G_TYPE_UINT:
+ {
+ const GParamSpecUInt *p = (GParamSpecUInt *) pspec;
- min = p->minimum;
- max = p->maximum;
- }
- break;
- case G_TYPE_INT64:
- if (!has_minmax) {
- const GParamSpecInt64 *p = (GParamSpecInt64 *) pspec;
+ min.u64 = p->minimum;
+ max.u64 = p->maximum;
+ }
+ break;
+ case G_TYPE_INT64:
+ {
+ const GParamSpecInt64 *p = (GParamSpecInt64 *) pspec;
+
+ min.i64 = p->minimum;
+ max.i64 = p->maximum;
+ }
+ break;
+ case G_TYPE_UINT64:
+ {
+ const GParamSpecUInt64 *p = (GParamSpecUInt64 *) pspec;
- min = p->minimum;
- max = p->maximum;
+ min.u64 = p->minimum;
+ max.u64 = p->maximum;
+ }
+ break;
+ default:
+ g_return_val_if_reached (FALSE);
}
- break;
- default:
- g_return_val_if_reached (FALSE);
}
- if (!has_value) {
- v = _nm_utils_ascii_str_to_int64 (value, base, min, max, 0);
+ if (is_uint64)
+ v.u64 = _nm_utils_ascii_str_to_uint64 (value, base, min.u64, max.u64, 0);
+ else
+ v.i64 = _nm_utils_ascii_str_to_int64 (value, base, min.i64, max.i64, 0);
- if ((errsv = errno) != 0) {
- if (errsv == ERANGE) {
+ if ((errsv = errno) != 0) {
+ if (errsv == ERANGE) {
+ if (is_uint64) {
g_set_error (error, NM_UTILS_ERROR, NM_UTILS_ERROR_INVALID_ARGUMENT,
- _("'%s' is out of range [%lli, %lli]"),
- value,
- (long long) min,
- (long long) max);
+ _("'%s' is out of range [%"G_GUINT64_FORMAT", %"G_GUINT64_FORMAT"]"),
+ value, min.u64, max.u64);
} else {
g_set_error (error, NM_UTILS_ERROR, NM_UTILS_ERROR_INVALID_ARGUMENT,
- _("'%s' is not a valid number"), value);
+ _("'%s' is out of range [%"G_GINT64_FORMAT", %"G_GINT64_FORMAT"]"),
+ value, min.i64, max.i64);
}
- return FALSE;
+ } else {
+ g_set_error (error, NM_UTILS_ERROR, NM_UTILS_ERROR_INVALID_ARGUMENT,
+ _("'%s' is not a valid number"), value);
}
+ return FALSE;
}
+have_value_from_nick:
+
g_value_init (&gval, pspec->value_type);
switch (pspec->value_type) {
case G_TYPE_INT:
- g_value_set_int (&gval, v);
+ g_value_set_int (&gval, v.i64);
break;
case G_TYPE_UINT:
- g_value_set_uint (&gval, v);
+ g_value_set_uint (&gval, v.u64);
break;
case G_TYPE_INT64:
- g_value_set_int64 (&gval, v);
+ g_value_set_int64 (&gval, v.i64);
+ break;
+ case G_TYPE_UINT64:
+ g_value_set_uint64 (&gval, v.u64);
break;
default:
- nm_assert_not_reached ();
+ g_return_val_if_reached (FALSE);
break;
}
diff --git a/clients/common/nm-meta-setting-desc.h b/clients/common/nm-meta-setting-desc.h
index 415ad32647..7129870a25 100644
--- a/clients/common/nm-meta-setting-desc.h
+++ b/clients/common/nm-meta-setting-desc.h
@@ -232,9 +232,14 @@ struct _NMMetaPropertyType {
struct _NMUtilsEnumValueInfo;
+typedef union {
+ gint64 i64;
+ guint64 u64;
+} NMMetaSignUnsignInt64;
+
typedef struct {
const char *nick;
- gint64 value;
+ NMMetaSignUnsignInt64 value;
} NMMetaUtilsIntValueInfo;
struct _NMMetaPropertyTypData {
@@ -255,8 +260,8 @@ struct _NMMetaPropertyTypData {
int value);
} gobject_enum;
struct {
- gint64 min;
- gint64 max;
+ NMMetaSignUnsignInt64 min;
+ NMMetaSignUnsignInt64 max;
guint base;
const NMMetaUtilsIntValueInfo *value_infos;
} gobject_int;