static void set_property (GObject *object, guint prop_id, const GValue *value, GParamSpec *pspec) { NMDeviceTun *self = NM_DEVICE_TUN (object); NMDeviceTunPrivate *priv = NM_DEVICE_TUN_GET_PRIVATE (self); const char *str; switch (prop_id) { case PROP_MODE: /* construct-only */ str = g_value_get_string (value); /* mode is G_PARAM_STATIC_STRINGS */ if (g_strcmp0 (str, "tun") == 0) priv->mode = "tun"; else if (g_strcmp0 (str, "tap") == 0) priv->mode = "tap"; else g_return_if_fail (FALSE); break; default: G_OBJECT_WARN_INVALID_PROPERTY_ID (object, prop_id, pspec); break; } }
static void link_changed (NMDevice *device, NMPlatformLink *info) { NM_DEVICE_CLASS (nm_device_tun_parent_class)->link_changed (device, info); reload_tun_properties (NM_DEVICE_TUN (device)); }
static void get_property (GObject *object, guint prop_id, GValue *value, GParamSpec *pspec) { NMDeviceTun *self = NM_DEVICE_TUN (object); NMDeviceTunPrivate *priv = NM_DEVICE_TUN_GET_PRIVATE (self); switch (prop_id) { case PROP_OWNER: g_value_set_int64 (value, priv->props.owner); break; case PROP_GROUP: g_value_set_int64 (value, priv->props.group); break; case PROP_MODE: g_value_set_string (value, priv->mode); break; case PROP_NO_PI: g_value_set_boolean (value, priv->props.no_pi); break; case PROP_VNET_HDR: g_value_set_boolean (value, priv->props.vnet_hdr); break; case PROP_MULTI_QUEUE: g_value_set_boolean (value, priv->props.multi_queue); break; default: G_OBJECT_WARN_INVALID_PROPERTY_ID (object, prop_id, pspec); break; } }
static NMActStageReturn act_stage1_prepare (NMDevice *device, NMDeviceStateReason *reason) { NMDeviceTun *self = NM_DEVICE_TUN (device); NMDeviceTunPrivate *priv = NM_DEVICE_TUN_GET_PRIVATE (self); NMSettingWired *s_wired; const char *cloned_mac; NMActStageReturn ret; g_return_val_if_fail (reason != NULL, NM_ACT_STAGE_RETURN_FAILURE); ret = NM_DEVICE_CLASS (nm_device_tun_parent_class)->act_stage1_prepare (device, reason); if (ret != NM_ACT_STAGE_RETURN_SUCCESS) return ret; /* Nothing to do for TUN devices */ if (g_strcmp0 (priv->mode, "tap")) return NM_ACT_STAGE_RETURN_SUCCESS; s_wired = (NMSettingWired *) nm_device_get_applied_setting (device, NM_TYPE_SETTING_WIRED); if (s_wired) { /* Set device MAC address if the connection wants to change it */ cloned_mac = nm_setting_wired_get_cloned_mac_address (s_wired); nm_device_set_hw_addr (device, cloned_mac, "set", LOGD_DEVICE); } return NM_ACT_STAGE_RETURN_SUCCESS; }
static void setup (NMDevice *device, NMPlatformLink *plink) { NMDeviceTun *self = NM_DEVICE_TUN (device); NMDeviceTunPrivate *priv = NM_DEVICE_TUN_GET_PRIVATE (self); NM_DEVICE_CLASS (nm_device_tun_parent_class)->setup (device, plink); priv->mode = NULL; if (plink->type == NM_LINK_TYPE_TUN) priv->mode = "tun"; else if (plink->type == NM_LINK_TYPE_TAP) priv->mode = "tap"; else g_assert_not_reached (); g_object_notify (G_OBJECT (device), NM_DEVICE_TUN_MODE); reload_tun_properties (NM_DEVICE_TUN (device)); }
static void update_connection (NMDevice *device, NMConnection *connection) { NMDeviceTun *self = NM_DEVICE_TUN (device); NMSettingTun *s_tun = nm_connection_get_setting_tun (connection); NMPlatformTunProperties props; NMSettingTunMode mode; gint64 user, group; char *str; if (!s_tun) { s_tun = (NMSettingTun *) nm_setting_tun_new (); nm_connection_add_setting (connection, (NMSetting *) s_tun); } if (!nm_platform_link_tun_get_properties (NM_PLATFORM_GET, nm_device_get_ifindex (device), &props)) { _LOGW (LOGD_HW, "failed to get TUN interface info while updating connection."); return; } mode = tun_mode_from_string (props.mode); if (mode != nm_setting_tun_get_mode (s_tun)) g_object_set (G_OBJECT (s_tun), NM_SETTING_TUN_MODE, mode, NULL); user = _nm_utils_ascii_str_to_int64 (nm_setting_tun_get_owner (s_tun), 10, 0, G_MAXINT32, -1); group = _nm_utils_ascii_str_to_int64 (nm_setting_tun_get_group (s_tun), 10, 0, G_MAXINT32, -1); if (props.owner != user) { str = props.owner >= 0 ? g_strdup_printf ("%" G_GINT32_FORMAT, (gint32) props.owner) : NULL; g_object_set (G_OBJECT (s_tun), NM_SETTING_TUN_OWNER, str, NULL); g_free (str); } if (props.group != group) { str = props.group >= 0 ? g_strdup_printf ("%" G_GINT32_FORMAT, (gint32) props.group) : NULL; g_object_set (G_OBJECT (s_tun), NM_SETTING_TUN_GROUP, str, NULL); g_free (str); } if ((!props.no_pi) != nm_setting_tun_get_pi (s_tun)) g_object_set (G_OBJECT (s_tun), NM_SETTING_TUN_PI, !props.no_pi, NULL); if (props.vnet_hdr != nm_setting_tun_get_vnet_hdr (s_tun)) g_object_set (G_OBJECT (s_tun), NM_SETTING_TUN_VNET_HDR, props.vnet_hdr, NULL); if (props.multi_queue != nm_setting_tun_get_multi_queue (s_tun)) g_object_set (G_OBJECT (s_tun), NM_SETTING_TUN_MULTI_QUEUE, props.multi_queue, NULL); }
static void unrealize_notify (NMDevice *device) { NMDeviceTun *self = NM_DEVICE_TUN (device); NMDeviceTunPrivate *priv = NM_DEVICE_TUN_GET_PRIVATE (self); GParamSpec **properties; guint n_properties, i; NM_DEVICE_CLASS (nm_device_tun_parent_class)->unrealize_notify (device); memset (&priv->props, 0, sizeof (NMPlatformTunProperties)); properties = g_object_class_list_properties (G_OBJECT_GET_CLASS (self), &n_properties); for (i = 0; i < n_properties; i++) g_object_notify_by_pspec (G_OBJECT (self), properties[i]); g_free (properties); }
static gboolean check_connection_compatible (NMDevice *device, NMConnection *connection) { NMDeviceTun *self = NM_DEVICE_TUN (device); NMDeviceTunPrivate *priv = NM_DEVICE_TUN_GET_PRIVATE (self); NMSettingTunMode mode; NMSettingTun *s_tun; gint64 user, group; if (!NM_DEVICE_CLASS (nm_device_tun_parent_class)->check_connection_compatible (device, connection)) return FALSE; s_tun = nm_connection_get_setting_tun (connection); if (!s_tun) return FALSE; if (nm_device_is_real (device)) { mode = tun_mode_from_string (priv->mode); if (mode != nm_setting_tun_get_mode (s_tun)) return FALSE; user = _nm_utils_ascii_str_to_int64 (nm_setting_tun_get_owner (s_tun), 10, 0, G_MAXINT32, -1); group = _nm_utils_ascii_str_to_int64 (nm_setting_tun_get_group (s_tun), 10, 0, G_MAXINT32, -1); if (user != priv->props.owner) return FALSE; if (group != priv->props.group) return FALSE; if (nm_setting_tun_get_pi (s_tun) == priv->props.no_pi) return FALSE; if (nm_setting_tun_get_vnet_hdr (s_tun) != priv->props.vnet_hdr) return FALSE; if (nm_setting_tun_get_multi_queue (s_tun) != priv->props.multi_queue) return FALSE; } return TRUE; }
static void get_property (GObject *object, guint prop_id, GValue *value, GParamSpec *pspec) { NMDeviceTun *device = NM_DEVICE_TUN (object); switch (prop_id) { case PROP_HW_ADDRESS: g_value_set_string (value, nm_device_tun_get_hw_address (device)); break; case PROP_MODE: g_value_set_string (value, nm_device_tun_get_mode (device)); break; case PROP_OWNER: g_value_set_int64 (value, nm_device_tun_get_owner (device)); break; case PROP_GROUP: g_value_set_int64 (value, nm_device_tun_get_group (device)); break; case PROP_NO_PI: g_value_set_boolean (value, nm_device_tun_get_no_pi (device)); break; case PROP_VNET_HDR: g_value_set_boolean (value, nm_device_tun_get_vnet_hdr (device)); break; case PROP_MULTI_QUEUE: g_value_set_boolean (value, nm_device_tun_get_multi_queue (device)); break; default: G_OBJECT_WARN_INVALID_PROPERTY_ID (object, prop_id, pspec); break; } }
static const char * get_hw_address (NMDevice *device) { return nm_device_tun_get_hw_address (NM_DEVICE_TUN (device)); }