static NMActStageReturn act_stage1_prepare (NMDevice *device, NMDeviceStateReason *reason) { NMDeviceOlpcMesh *self = NM_DEVICE_OLPC_MESH (device); NMDeviceOlpcMeshPrivate *priv = NM_DEVICE_OLPC_MESH_GET_PRIVATE (device); NMActStageReturn ret; gboolean scanning; ret = NM_DEVICE_CLASS (nm_device_olpc_mesh_parent_class)->act_stage1_prepare (device, reason); if (ret != NM_ACT_STAGE_RETURN_SUCCESS) return ret; /* disconnect companion device, if it is connected */ if (nm_device_get_act_request (NM_DEVICE (priv->companion))) { _LOGI (LOGD_OLPC, "disconnecting companion device %s", nm_device_get_iface (priv->companion)); /* FIXME: VPN stuff here is a bug; but we can't really change API now... */ nm_device_state_changed (NM_DEVICE (priv->companion), NM_DEVICE_STATE_DISCONNECTED, NM_DEVICE_STATE_REASON_USER_REQUESTED); _LOGI (LOGD_OLPC, "companion %s disconnected", nm_device_get_iface (priv->companion)); } /* wait with continuing configuration untill the companion device is done scanning */ g_object_get (priv->companion, "scanning", &scanning, NULL); if (scanning) { priv->stage1_waiting = TRUE; return NM_ACT_STAGE_RETURN_POSTPONE; } return NM_ACT_STAGE_RETURN_SUCCESS; }
/** * nm_device_olpc_mesh_get_companion: * @device: a #NMDeviceOlpcMesh * * Gets the companion device of the #NMDeviceOlpcMesh. * * Returns: (transfer none): the companion of the device of %NULL **/ NMDeviceWifi * nm_device_olpc_mesh_get_companion (NMDeviceOlpcMesh *device) { g_return_val_if_fail (NM_IS_DEVICE_OLPC_MESH (device), NULL); return NM_DEVICE_OLPC_MESH_GET_PRIVATE (device)->companion; }
static gboolean check_companion_cb (gpointer user_data) { NMDeviceOlpcMesh *self = NM_DEVICE_OLPC_MESH (user_data); NMDeviceOlpcMeshPrivate *priv = NM_DEVICE_OLPC_MESH_GET_PRIVATE (self); NMManager *manager; GSList *list; if (priv->companion != NULL) { nm_device_state_changed (NM_DEVICE (user_data), NM_DEVICE_STATE_DISCONNECTED, NM_DEVICE_STATE_REASON_NONE); return FALSE; } if (priv->device_added_id != 0) return FALSE; manager = nm_manager_get (); priv->device_added_id = g_signal_connect (manager, "device-added", G_CALLBACK (device_added_cb), self); /* Try to find the companion if it's already known to the NMManager */ for (list = nm_manager_get_devices (manager); list ; list = g_slist_next (list)) { if (is_companion (self, NM_DEVICE (list->data))) break; } g_object_unref (manager); return FALSE; }
static void dispose (GObject *object) { NMDeviceOlpcMesh *self = NM_DEVICE_OLPC_MESH (object); NMDeviceOlpcMeshPrivate *priv = NM_DEVICE_OLPC_MESH_GET_PRIVATE (self); NMManager *manager; if (priv->dispose_has_run) { G_OBJECT_CLASS (nm_device_olpc_mesh_parent_class)->dispose (object); return; } priv->dispose_has_run = TRUE; if (priv->wifi_data) wifi_utils_deinit (priv->wifi_data); device_cleanup (self); manager = nm_manager_get (); if (priv->device_added_id) g_signal_handler_disconnect (manager, priv->device_added_id); g_object_unref (manager); G_OBJECT_CLASS (nm_device_olpc_mesh_parent_class)->dispose (object); }
static void get_property (GObject *object, guint prop_id, GValue *value, GParamSpec *pspec) { NMDeviceOlpcMesh *device = NM_DEVICE_OLPC_MESH (object); NMDeviceOlpcMeshPrivate *priv = NM_DEVICE_OLPC_MESH_GET_PRIVATE (device); struct ether_addr hw_addr; switch (prop_id) { case PROP_HW_ADDRESS: nm_device_olpc_mesh_get_address (device, &hw_addr); g_value_take_string (value, nm_utils_hwaddr_ntoa (&hw_addr, ARPHRD_ETHER)); break; case PROP_COMPANION: if (priv->companion) g_value_set_boxed (value, nm_device_get_path (priv->companion)); else g_value_set_boxed (value, "/"); break; case PROP_ACTIVE_CHANNEL: g_value_set_uint (value, wifi_utils_get_mesh_channel (priv->wifi_data)); break; default: G_OBJECT_WARN_INVALID_PROPERTY_ID (object, prop_id, pspec); break; } }
static void real_update_hw_address (NMDevice *dev) { NMDeviceOlpcMesh *self = NM_DEVICE_OLPC_MESH (dev); NMDeviceOlpcMeshPrivate *priv = NM_DEVICE_OLPC_MESH_GET_PRIVATE (self); struct ifreq req; int ret, fd; fd = socket (PF_INET, SOCK_DGRAM, 0); if (fd < 0) { nm_log_warn (LOGD_OLPC_MESH, "could not open control socket."); return; } memset (&req, 0, sizeof (struct ifreq)); strncpy (req.ifr_name, nm_device_get_iface (dev), IFNAMSIZ); ret = ioctl (fd, SIOCGIFHWADDR, &req); if (ret) { nm_log_warn (LOGD_OLPC_MESH, "(%s): error getting hardware address: %d", nm_device_get_iface (dev), errno); goto out; } if (memcmp (&priv->hw_addr, &req.ifr_hwaddr.sa_data, sizeof (struct ether_addr))) { memcpy (&priv->hw_addr, &req.ifr_hwaddr.sa_data, sizeof (struct ether_addr)); g_object_notify (G_OBJECT (dev), NM_DEVICE_OLPC_MESH_HW_ADDRESS); } out: close (fd); }
static NMActStageReturn real_act_stage2_config (NMDevice *dev, NMDeviceStateReason *reason) { NMDeviceOlpcMesh *self = NM_DEVICE_OLPC_MESH (dev); NMDeviceOlpcMeshPrivate *priv = NM_DEVICE_OLPC_MESH_GET_PRIVATE (self); NMConnection *connection; NMSettingOlpcMesh *s_mesh; NMActRequest *req; guint32 channel; const GByteArray *anycast_addr_array; guint8 *anycast_addr = NULL; req = nm_device_get_act_request (dev); g_assert (req); connection = nm_act_request_get_connection (req); g_assert (connection); s_mesh = NM_SETTING_OLPC_MESH (nm_connection_get_setting (connection, NM_TYPE_SETTING_OLPC_MESH)); g_assert (s_mesh); channel = nm_setting_olpc_mesh_get_channel (s_mesh); if (channel != 0) _mesh_set_channel (self, channel); wifi_utils_set_mesh_ssid (priv->wifi_data, nm_setting_olpc_mesh_get_ssid (s_mesh)); anycast_addr_array = nm_setting_olpc_mesh_get_dhcp_anycast_address (s_mesh); if (anycast_addr_array) anycast_addr = anycast_addr_array->data; nm_device_set_dhcp_anycast_address (dev, anycast_addr); return NM_ACT_STAGE_RETURN_SUCCESS; }
static NMActStageReturn real_act_stage1_prepare (NMDevice *dev, NMDeviceStateReason *reason) { NMDeviceOlpcMeshPrivate *priv = NM_DEVICE_OLPC_MESH_GET_PRIVATE (dev); gboolean scanning; /* disconnect companion device, if it is connected */ if (nm_device_get_act_request (NM_DEVICE (priv->companion))) { nm_log_info (LOGD_OLPC_MESH, "(%s): disconnecting companion device %s", nm_device_get_iface (dev), nm_device_get_iface (priv->companion)); /* FIXME: VPN stuff here is a bug; but we can't really change API now... */ nm_device_state_changed (NM_DEVICE (priv->companion), NM_DEVICE_STATE_DISCONNECTED, NM_VPN_CONNECTION_STATE_REASON_USER_DISCONNECTED); nm_log_info (LOGD_OLPC_MESH, "(%s): companion %s disconnected", nm_device_get_iface (dev), nm_device_get_iface (priv->companion)); } /* wait with continuing configuration untill the companion device is done scanning */ g_object_get (priv->companion, "scanning", &scanning, NULL); if (scanning) { priv->stage1_waiting = TRUE; return NM_ACT_STAGE_RETURN_POSTPONE; } return NM_ACT_STAGE_RETURN_SUCCESS; }
/** * nm_device_olpc_mesh_get_active_channel: * @device: a #NMDeviceOlpcMesh * * Returns the active channel of the #NMDeviceOlpcMesh device. * * Returns: active channel of the device **/ guint32 nm_device_olpc_mesh_get_active_channel (NMDeviceOlpcMesh *device) { g_return_val_if_fail (NM_IS_DEVICE_OLPC_MESH (device), 0); return NM_DEVICE_OLPC_MESH_GET_PRIVATE (device)->active_channel; }
/** * nm_device_olpc_mesh_get_hw_address: * @device: a #NMDeviceOlpcMesh * * Gets the hardware (MAC) address of the #NMDeviceOlpcMesh * * Returns: the hardware address. This is the internal string used by the * device, and must not be modified. **/ const char * nm_device_olpc_mesh_get_hw_address (NMDeviceOlpcMesh *device) { g_return_val_if_fail (NM_IS_DEVICE_OLPC_MESH (device), NULL); return NM_DEVICE_OLPC_MESH_GET_PRIVATE (device)->hw_address; }
static gboolean real_is_up (NMDevice *device) { NMDeviceOlpcMesh *self = NM_DEVICE_OLPC_MESH (device); NMDeviceOlpcMeshPrivate *priv = NM_DEVICE_OLPC_MESH_GET_PRIVATE (self); return priv->up; }
/** * nm_device_olpc_mesh_get_active_channel: * @device: a #NMDeviceOlpcMesh * * Returns the active channel of the #NMDeviceOlpcMesh device. * * Returns: active channel of the device **/ guint32 nm_device_olpc_mesh_get_active_channel (NMDeviceOlpcMesh *device) { g_return_val_if_fail (NM_IS_DEVICE_OLPC_MESH (device), 0); _nm_object_ensure_inited (NM_OBJECT (device)); return NM_DEVICE_OLPC_MESH_GET_PRIVATE (device)->active_channel; }
/** * nm_device_olpc_mesh_get_hw_address: * @device: a #NMDeviceOlpcMesh * * Gets the hardware (MAC) address of the #NMDeviceOlpcMesh * * Returns: the hardware address. This is the internal string used by the * device, and must not be modified. **/ const char * nm_device_olpc_mesh_get_hw_address (NMDeviceOlpcMesh *device) { g_return_val_if_fail (NM_IS_DEVICE_OLPC_MESH (device), NULL); _nm_object_ensure_inited (NM_OBJECT (device)); return NM_DEVICE_OLPC_MESH_GET_PRIVATE (device)->hw_address; }
static void device_removed_cb (NMManager *manager, NMDevice *other, gpointer user_data) { NMDeviceOlpcMesh *self = NM_DEVICE_OLPC_MESH (user_data); if (other == NM_DEVICE_OLPC_MESH_GET_PRIVATE (self)->companion) companion_cleanup (self); }
/** * nm_device_olpc_mesh_get_companion: * @device: a #NMDeviceOlpcMesh * * Gets the companion device of the #NMDeviceOlpcMesh. * * Returns: (transfer none): the companion of the device of %NULL **/ NMDeviceWifi * nm_device_olpc_mesh_get_companion (NMDeviceOlpcMesh *device) { g_return_val_if_fail (NM_IS_DEVICE_OLPC_MESH (device), NULL); _nm_object_ensure_inited (NM_OBJECT (device)); return NM_DEVICE_OLPC_MESH_GET_PRIVATE (device)->companion; }
static gboolean real_bring_up (NMDevice *dev) { NMDeviceOlpcMesh *self = NM_DEVICE_OLPC_MESH (dev); NMDeviceOlpcMeshPrivate *priv = NM_DEVICE_OLPC_MESH_GET_PRIVATE (self); priv->up = TRUE; return TRUE; }
static void finalize (GObject *object) { NMDeviceOlpcMeshPrivate *priv = NM_DEVICE_OLPC_MESH_GET_PRIVATE (object); g_free (priv->hw_address); G_OBJECT_CLASS (nm_device_olpc_mesh_parent_class)->finalize (object); }
static void dispose (GObject *object) { NMDeviceOlpcMeshPrivate *priv = NM_DEVICE_OLPC_MESH_GET_PRIVATE (object); g_clear_object (&priv->companion); G_OBJECT_CLASS (nm_device_olpc_mesh_parent_class)->dispose (object); }
static void constructed (GObject *object) { NMDeviceOlpcMeshPrivate *priv = NM_DEVICE_OLPC_MESH_GET_PRIVATE (object); G_OBJECT_CLASS (nm_device_olpc_mesh_parent_class)->constructed (object); priv->proxy = _nm_object_new_proxy (NM_OBJECT (object), NULL, NM_DBUS_INTERFACE_DEVICE_OLPC_MESH); register_properties (NM_DEVICE_OLPC_MESH (object)); }
/* * nm_device_olpc_mesh_get_address * * Get a device's hardware address * */ static void nm_device_olpc_mesh_get_address (NMDeviceOlpcMesh *self, struct ether_addr *addr) { NMDeviceOlpcMeshPrivate *priv = NM_DEVICE_OLPC_MESH_GET_PRIVATE (self); g_return_if_fail (self != NULL); g_return_if_fail (addr != NULL); memcpy (addr, &(priv->hw_addr), sizeof (struct ether_addr)); }
static void _mesh_set_channel (NMDeviceOlpcMesh *self, guint32 channel) { NMDeviceOlpcMeshPrivate *priv = NM_DEVICE_OLPC_MESH_GET_PRIVATE (self); if (wifi_utils_get_mesh_channel (priv->wifi_data) != channel) { if (wifi_utils_set_mesh_channel (priv->wifi_data, channel)) g_object_notify (G_OBJECT (self), NM_DEVICE_OLPC_MESH_ACTIVE_CHANNEL); } }
static void device_cleanup (NMDeviceOlpcMesh *self) { NMDeviceOlpcMeshPrivate *priv = NM_DEVICE_OLPC_MESH_GET_PRIVATE (self); if (priv->ssid) { g_byte_array_free (priv->ssid, TRUE); priv->ssid = NULL; } priv->up = FALSE; }
static void companion_cleanup (NMDeviceOlpcMesh *self) { NMDeviceOlpcMeshPrivate *priv = NM_DEVICE_OLPC_MESH_GET_PRIVATE (self); if (priv->companion) { g_signal_handlers_disconnect_by_data (priv->companion, self); g_clear_object (&priv->companion); } g_object_notify (G_OBJECT (self), NM_DEVICE_OLPC_MESH_COMPANION); }
static void nm_device_olpc_mesh_init (NMDeviceOlpcMesh * self) { NMDeviceOlpcMeshPrivate *priv = NM_DEVICE_OLPC_MESH_GET_PRIVATE (self); priv->dispose_has_run = FALSE; priv->companion = NULL; priv->stage1_waiting = FALSE; memset (&(priv->hw_addr), 0, sizeof (struct ether_addr)); }
static gboolean is_available (NMDevice *device) { NMDeviceOlpcMesh *self = NM_DEVICE_OLPC_MESH (device); if (!NM_DEVICE_OLPC_MESH_GET_PRIVATE (self)->companion) { _LOGD (LOGD_WIFI, "not available because companion not found"); return FALSE; } return TRUE; }
static void device_added_cb (NMManager *manager, NMDevice *other, gpointer user_data) { NMDeviceOlpcMesh *self = NM_DEVICE_OLPC_MESH (user_data); NMDeviceOlpcMeshPrivate *priv = NM_DEVICE_OLPC_MESH_GET_PRIVATE (self); if (!priv->companion && check_companion (self, other)) { nm_device_state_changed (NM_DEVICE (self), NM_DEVICE_STATE_DISCONNECTED, NM_DEVICE_STATE_REASON_NONE); nm_device_remove_pending_action (NM_DEVICE (self), "waiting for companion", TRUE); } }
static gboolean is_companion (NMDeviceOlpcMesh *self, NMDevice *other) { NMDeviceOlpcMeshPrivate *priv = NM_DEVICE_OLPC_MESH_GET_PRIVATE (self); struct ether_addr their_addr; NMManager *manager; if (!NM_IS_DEVICE_WIFI (other)) return FALSE; nm_device_wifi_get_address (NM_DEVICE_WIFI (other), &their_addr); if (memcmp (priv->hw_addr.ether_addr_octet, their_addr.ether_addr_octet, ETH_ALEN) != 0) { return FALSE; } /* FIXME detect when our companion leaves */ priv->companion = other; /* When we've found the companion, stop listening for other devices */ manager = nm_manager_get (); if (priv->device_added_id) { g_signal_handler_disconnect (manager, priv->device_added_id); priv->device_added_id = 0; } g_object_unref (manager); nm_device_state_changed (NM_DEVICE (self), NM_DEVICE_STATE_DISCONNECTED, NM_DEVICE_STATE_REASON_NONE); nm_log_info (LOGD_OLPC_MESH, "(%s): found companion WiFi device %s", nm_device_get_iface (NM_DEVICE (self)), nm_device_get_iface (other)); g_signal_connect (G_OBJECT (other), "state-changed", G_CALLBACK (companion_state_changed_cb), self); g_signal_connect (G_OBJECT (other), "notify::scanning", G_CALLBACK (companion_notify_cb), self); g_signal_connect (G_OBJECT (other), "scanning-allowed", G_CALLBACK (companion_scan_allowed_cb), self); g_signal_connect (G_OBJECT (other), "autoconnect-allowed", G_CALLBACK (companion_autoconnect_allowed_cb), self); g_object_notify (G_OBJECT (self), NM_DEVICE_OLPC_MESH_COMPANION); return TRUE; }
static void register_properties (NMDeviceOlpcMesh *device) { NMDeviceOlpcMeshPrivate *priv = NM_DEVICE_OLPC_MESH_GET_PRIVATE (device); const NMPropertiesInfo property_info[] = { { NM_DEVICE_OLPC_MESH_HW_ADDRESS, &priv->hw_address }, { NM_DEVICE_OLPC_MESH_COMPANION, &priv->companion, NULL, NM_TYPE_DEVICE_WIFI }, { NM_DEVICE_OLPC_MESH_ACTIVE_CHANNEL, &priv->active_channel }, { NULL }, }; _nm_object_register_properties (NM_OBJECT (device), priv->proxy, property_info); }
static void companion_notify_cb (NMDeviceWifi *companion, GParamSpec *pspec, gpointer user_data) { NMDeviceOlpcMesh *self = NM_DEVICE_OLPC_MESH (user_data); NMDeviceOlpcMeshPrivate *priv = NM_DEVICE_OLPC_MESH_GET_PRIVATE (self); gboolean scanning; if (!priv->stage1_waiting) return; g_object_get (companion, "scanning", &scanning, NULL); if (!scanning) { priv->stage1_waiting = FALSE; nm_device_activate_schedule_stage2_device_config (NM_DEVICE (self)); } }
static void init_dbus (NMObject *object) { NMDeviceOlpcMeshPrivate *priv = NM_DEVICE_OLPC_MESH_GET_PRIVATE (object); const NMPropertiesInfo property_info[] = { { NM_DEVICE_OLPC_MESH_HW_ADDRESS, &priv->hw_address }, { NM_DEVICE_OLPC_MESH_COMPANION, &priv->companion, NULL, NM_TYPE_DEVICE_WIFI }, { NM_DEVICE_OLPC_MESH_ACTIVE_CHANNEL, &priv->active_channel }, { NULL }, }; NM_OBJECT_CLASS (nm_device_olpc_mesh_parent_class)->init_dbus (object); _nm_object_register_properties (object, NM_DBUS_INTERFACE_DEVICE_OLPC_MESH, property_info); }