static GObject* constructor (GType type, guint n_construct_params, GObjectConstructParam *construct_params) { GObject *object; GObjectClass *klass; NMDeviceOlpcMesh *self; NMDeviceWifiCapabilities caps; klass = G_OBJECT_CLASS (nm_device_olpc_mesh_parent_class); object = klass->constructor (type, n_construct_params, construct_params); if (!object) return NULL; self = NM_DEVICE_OLPC_MESH (object); if (!nm_platform_wifi_get_capabilities (nm_device_get_ifindex (NM_DEVICE (self)), &caps)) { _LOGW (LOGD_HW | LOGD_OLPC, "failed to initialize WiFi driver"); g_object_unref (object); return NULL; } g_signal_connect (nm_manager_get (), "device-added", G_CALLBACK (device_added_cb), self); g_signal_connect (nm_manager_get (), "device-removed", G_CALLBACK (device_removed_cb), self); /* shorter timeout for mesh connectivity */ nm_device_set_dhcp_timeout (NM_DEVICE (self), 20); return object; }
static void dispose (GObject *object) { NMDeviceOlpcMesh *self = NM_DEVICE_OLPC_MESH (object); companion_cleanup (self); g_signal_handlers_disconnect_by_func (nm_manager_get (), G_CALLBACK (device_added_cb), self); g_signal_handlers_disconnect_by_func (nm_manager_get (), G_CALLBACK (device_removed_cb), self); G_OBJECT_CLASS (nm_device_olpc_mesh_parent_class)->dispose (object); }
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) { NMDeviceMacvlanPrivate *priv = NM_DEVICE_MACVLAN_GET_PRIVATE (object); NMDevice *parent; switch (prop_id) { case PROP_PARENT: if (priv->parent_ifindex > 0) parent = nm_manager_get_device_by_ifindex (nm_manager_get (), priv->parent_ifindex); else parent = NULL; nm_utils_g_value_set_object_path (value, parent); break; case PROP_MODE: g_value_set_string (value, priv->props.mode); break; case PROP_NO_PROMISC: g_value_set_boolean (value, priv->props.no_promisc); break; default: G_OBJECT_WARN_INVALID_PROPERTY_ID (object, prop_id, pspec); break; } }
static void update_connection (NMDevice *device, NMConnection *connection) { NMDeviceVlan *self = NM_DEVICE_VLAN (device); NMDeviceVlanPrivate *priv = NM_DEVICE_VLAN_GET_PRIVATE (device); NMSettingVlan *s_vlan = nm_connection_get_setting_vlan (connection); int ifindex = nm_device_get_ifindex (device); int parent_ifindex = -1, vlan_id = -1; NMDevice *parent; const char *setting_parent, *new_parent; if (!s_vlan) { s_vlan = (NMSettingVlan *) nm_setting_vlan_new (); nm_connection_add_setting (connection, (NMSetting *) s_vlan); } if (!nm_platform_vlan_get_info (NM_PLATFORM_GET, ifindex, &parent_ifindex, &vlan_id)) { _LOGW (LOGD_VLAN, "failed to get VLAN interface info while updating connection."); return; } if (priv->vlan_id != vlan_id) { priv->vlan_id = vlan_id; g_object_notify (G_OBJECT (device), NM_DEVICE_VLAN_ID); } if (vlan_id != nm_setting_vlan_get_id (s_vlan)) g_object_set (s_vlan, NM_SETTING_VLAN_ID, priv->vlan_id, NULL); if (parent_ifindex != NM_PLATFORM_LINK_OTHER_NETNS) parent = nm_manager_get_device_by_ifindex (nm_manager_get (), parent_ifindex); else parent = NULL; nm_device_vlan_set_parent (NM_DEVICE_VLAN (device), parent); /* Update parent in the connection; default to parent's interface name */ if (parent) { new_parent = nm_device_get_iface (parent); setting_parent = nm_setting_vlan_get_parent (s_vlan); if (setting_parent && nm_utils_is_uuid (setting_parent)) { NMConnection *parent_connection; /* Don't change a parent specified by UUID if it's still valid */ parent_connection = nm_connection_provider_get_connection_by_uuid (nm_connection_provider_get (), setting_parent); if (parent_connection && nm_device_check_connection_compatible (parent, parent_connection)) new_parent = NULL; } if (new_parent) g_object_set (s_vlan, NM_SETTING_VLAN_PARENT, new_parent, NULL); } else g_object_set (s_vlan, NM_SETTING_VLAN_PARENT, NULL, NULL); }
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 get_property (GObject *object, guint prop_id, GValue *value, GParamSpec *pspec) { NMDeviceIPTunnelPrivate *priv = NM_DEVICE_IP_TUNNEL_GET_PRIVATE (object); NMDevice *parent; switch (prop_id) { case PROP_MODE: g_value_set_uint (value, priv->mode); break; case PROP_PARENT: parent = nm_manager_get_device_by_ifindex (nm_manager_get (), priv->parent_ifindex); nm_utils_g_value_set_object_path (value, parent); break; case PROP_LOCAL: g_value_set_string (value, priv->local); break; case PROP_REMOTE: g_value_set_string (value, priv->remote); break; case PROP_TTL: g_value_set_uchar (value, priv->ttl); break; case PROP_TOS: g_value_set_uchar (value, priv->tos); break; case PROP_PATH_MTU_DISCOVERY: g_value_set_boolean (value, priv->path_mtu_discovery); break; case PROP_INPUT_KEY: g_value_set_string (value, priv->input_key); break; case PROP_OUTPUT_KEY: g_value_set_string (value, priv->output_key); break; case PROP_ENCAPSULATION_LIMIT: g_value_set_uchar (value, priv->encap_limit); break; case PROP_FLOW_LABEL: g_value_set_uint (value, priv->flow_label); break; default: G_OBJECT_WARN_INVALID_PROPERTY_ID (object, prop_id, pspec); break; } }
static gboolean realize (NMDevice *device, NMPlatformLink *plink, GError **error) { NMDeviceVlanPrivate *priv = NM_DEVICE_VLAN_GET_PRIVATE (device); int parent_ifindex = -1, vlan_id = -1; NMDevice *parent; g_return_val_if_fail (plink, FALSE); g_assert (plink->type == NM_LINK_TYPE_VLAN); if (!nm_platform_vlan_get_info (NM_PLATFORM_GET, plink->ifindex, &parent_ifindex, &vlan_id)) { g_set_error (error, NM_DEVICE_ERROR, NM_DEVICE_ERROR_FAILED, "(%s): failed to read VLAN properties", plink->name); return FALSE; } if (vlan_id < 0) { g_set_error (error, NM_DEVICE_ERROR, NM_DEVICE_ERROR_FAILED, "(%s): VLAN ID invalid", plink->name); return FALSE; } if (parent_ifindex != NM_PLATFORM_LINK_OTHER_NETNS) { parent = nm_manager_get_device_by_ifindex (nm_manager_get (), parent_ifindex); if (!parent) { nm_log_dbg (LOGD_HW, "(%s): VLAN parent interface unknown", plink->name); g_set_error (error, NM_DEVICE_ERROR, NM_DEVICE_ERROR_FAILED, "(%s): VLAN parent interface unknown", plink->name); return FALSE; } } else parent = NULL; g_warn_if_fail (priv->parent == NULL); nm_device_vlan_set_parent (NM_DEVICE_VLAN (device), parent); priv->vlan_id = vlan_id; return TRUE; }
static void find_companion (NMDeviceOlpcMesh *self) { NMDeviceOlpcMeshPrivate *priv = NM_DEVICE_OLPC_MESH_GET_PRIVATE (self); const GSList *list; if (priv->companion) return; nm_device_add_pending_action (NM_DEVICE (self), "waiting for companion", TRUE); /* Try to find the companion if it's already known to the NMManager */ for (list = nm_manager_get_devices (nm_manager_get ()); list ; list = g_slist_next (list)) { if (check_companion (self, NM_DEVICE (list->data))) { nm_device_queue_state (NM_DEVICE (self), NM_DEVICE_STATE_DISCONNECTED, NM_DEVICE_STATE_REASON_NONE); nm_device_remove_pending_action (NM_DEVICE (self), "waiting for companion", TRUE); break; } } }
static NMDevice * get_peer (NMDeviceVeth *self) { NMDeviceVethPrivate *priv = NM_DEVICE_VETH_GET_PRIVATE (self); NMDevice *device = NM_DEVICE (self), *peer = NULL; NMPlatformVethProperties props; if (priv->ever_had_peer) return priv->peer; if (!nm_platform_veth_get_properties (nm_device_get_ifindex (device), &props)) { _LOGW (LOGD_HW, "could not read veth properties"); return NULL; } peer = nm_manager_get_device_by_ifindex (nm_manager_get (), props.peer); if (peer && NM_IS_DEVICE_VETH (peer)) { set_peer (self, peer); set_peer (NM_DEVICE_VETH (peer), device); } return priv->peer; }
static void update_properties (NMDevice *device) { NMDeviceMacvlan *self = NM_DEVICE_MACVLAN (device); NMDeviceMacvlanPrivate *priv = NM_DEVICE_MACVLAN_GET_PRIVATE (device); GObject *object = G_OBJECT (device); const NMPlatformLnkMacvlan *props; const NMPlatformLink *plink; NMDevice *parent = NULL; if (priv->props.tap) props = nm_platform_link_get_lnk_macvtap (NM_PLATFORM_GET, nm_device_get_ifindex (device), &plink); else props = nm_platform_link_get_lnk_macvlan (NM_PLATFORM_GET, nm_device_get_ifindex (device), &plink); if (!props) { _LOGW (LOGD_HW, "could not get %s properties", priv->props.tap ? "macvtap" : "macvlan"); return; } g_object_freeze_notify (object); if (priv->parent_ifindex != plink->parent) { parent = nm_manager_get_device_by_ifindex (nm_manager_get (), plink->parent); nm_device_macvlan_set_parent (self, parent); } if (priv->props.mode != props->mode) g_object_notify (object, NM_DEVICE_MACVLAN_MODE); if (priv->props.no_promisc != props->no_promisc) g_object_notify (object, NM_DEVICE_MACVLAN_NO_PROMISC); priv->parent_ifindex = plink->parent; priv->props = *props; g_object_thaw_notify (object); }
G_MODULE_EXPORT NMDeviceFactory * nm_device_factory_create (GError **error) { nm_manager_set_capability (nm_manager_get (), NM_CAPABILITY_TEAM); return (NMDeviceFactory *) g_object_new (NM_TYPE_TEAM_FACTORY, NULL); }
static void update_properties (NMDevice *device) { NMDeviceVxlan *self = NM_DEVICE_VXLAN (device); NMDeviceVxlanPrivate *priv = NM_DEVICE_VXLAN_GET_PRIVATE (device); GObject *object = G_OBJECT (device); const NMPlatformLnkVxlan *props; NMDevice *parent; props = nm_platform_link_get_lnk_vxlan (NM_PLATFORM_GET, nm_device_get_ifindex (device), NULL); if (!props) { _LOGW (LOGD_HW, "could not get vxlan properties"); return; } g_object_freeze_notify (object); if (priv->props.parent_ifindex != props->parent_ifindex) { g_clear_object (&priv->parent); parent = nm_manager_get_device_by_ifindex (nm_manager_get (), props->parent_ifindex); if (parent) priv->parent = g_object_ref (parent); g_object_notify (object, NM_DEVICE_VXLAN_PARENT); } if (priv->props.id != props->id) g_object_notify (object, NM_DEVICE_VXLAN_ID); if (priv->props.local != props->local) g_object_notify (object, NM_DEVICE_VXLAN_LOCAL); if (memcmp (&priv->props.local6, &props->local6, sizeof (props->local6)) != 0) g_object_notify (object, NM_DEVICE_VXLAN_LOCAL); if (priv->props.group != props->group) g_object_notify (object, NM_DEVICE_VXLAN_GROUP); if (memcmp (&priv->props.group6, &props->group6, sizeof (props->group6)) != 0) g_object_notify (object, NM_DEVICE_VXLAN_GROUP); if (priv->props.tos != props->tos) g_object_notify (object, NM_DEVICE_VXLAN_TOS); if (priv->props.ttl != props->ttl) g_object_notify (object, NM_DEVICE_VXLAN_TTL); if (priv->props.learning != props->learning) g_object_notify (object, NM_DEVICE_VXLAN_LEARNING); if (priv->props.ageing != props->ageing) g_object_notify (object, NM_DEVICE_VXLAN_AGEING); if (priv->props.limit != props->limit) g_object_notify (object, NM_DEVICE_VXLAN_LIMIT); if (priv->props.src_port_min != props->src_port_min) g_object_notify (object, NM_DEVICE_VXLAN_SRC_PORT_MIN); if (priv->props.src_port_max != props->src_port_max) g_object_notify (object, NM_DEVICE_VXLAN_SRC_PORT_MAX); if (priv->props.dst_port != props->dst_port) g_object_notify (object, NM_DEVICE_VXLAN_DST_PORT); if (priv->props.proxy != props->proxy) g_object_notify (object, NM_DEVICE_VXLAN_PROXY); if (priv->props.rsc != props->rsc) g_object_notify (object, NM_DEVICE_VXLAN_RSC); if (priv->props.l2miss != props->l2miss) g_object_notify (object, NM_DEVICE_VXLAN_L2MISS); if (priv->props.l3miss != props->l3miss) g_object_notify (object, NM_DEVICE_VXLAN_L3MISS); priv->props = *props; g_object_thaw_notify (object); }
static void get_property (GObject *object, guint prop_id, GValue *value, GParamSpec *pspec) { NMDeviceVxlanPrivate *priv = NM_DEVICE_VXLAN_GET_PRIVATE (object); NMDevice *parent; switch (prop_id) { case PROP_PARENT: parent = nm_manager_get_device_by_ifindex (nm_manager_get (), priv->props.parent_ifindex); nm_utils_g_value_set_object_path (value, parent); break; case PROP_ID: g_value_set_uint (value, priv->props.id); break; case PROP_GROUP: if (priv->props.group) g_value_set_string (value, nm_utils_inet4_ntop (priv->props.group, NULL)); else if (!IN6_IS_ADDR_UNSPECIFIED (&priv->props.group6)) g_value_set_string (value, nm_utils_inet6_ntop (&priv->props.group6, NULL)); break; case PROP_LOCAL: if (priv->props.local) g_value_set_string (value, nm_utils_inet4_ntop (priv->props.local, NULL)); else if (!IN6_IS_ADDR_UNSPECIFIED (&priv->props.local6)) g_value_set_string (value, nm_utils_inet6_ntop (&priv->props.local6, NULL)); break; case PROP_TOS: g_value_set_uchar (value, priv->props.tos); break; case PROP_TTL: g_value_set_uchar (value, priv->props.ttl); break; case PROP_LEARNING: g_value_set_boolean (value, priv->props.learning); break; case PROP_AGEING: g_value_set_uint (value, priv->props.ageing); break; case PROP_LIMIT: g_value_set_uint (value, priv->props.limit); break; case PROP_DST_PORT: g_value_set_uint (value, priv->props.dst_port); break; case PROP_SRC_PORT_MIN: g_value_set_uint (value, priv->props.src_port_min); break; case PROP_SRC_PORT_MAX: g_value_set_uint (value, priv->props.src_port_max); break; case PROP_PROXY: g_value_set_boolean (value, priv->props.proxy); break; case PROP_RSC: g_value_set_boolean (value, priv->props.rsc); break; case PROP_L2MISS: g_value_set_boolean (value, priv->props.l2miss); break; case PROP_L3MISS: g_value_set_boolean (value, priv->props.l3miss); break; default: G_OBJECT_WARN_INVALID_PROPERTY_ID (object, prop_id, pspec); break; } }
static void update_connection (NMDevice *device, NMConnection *connection) { NMDeviceVxlanPrivate *priv = NM_DEVICE_VXLAN_GET_PRIVATE (device); NMSettingVxlan *s_vxlan = nm_connection_get_setting_vxlan (connection); NMDevice *parent = NULL; const char *setting_parent, *new_parent; if (!s_vxlan) { s_vxlan = (NMSettingVxlan *) nm_setting_vxlan_new (); nm_connection_add_setting (connection, (NMSetting *) s_vxlan); } if (priv->props.id != nm_setting_vxlan_get_id (s_vxlan)) g_object_set (G_OBJECT (s_vxlan), NM_SETTING_VXLAN_ID, priv->props.id, NULL); if (priv->props.parent_ifindex != NM_PLATFORM_LINK_OTHER_NETNS) parent = nm_manager_get_device_by_ifindex (nm_manager_get (), priv->props.parent_ifindex); /* Update parent in the connection; default to parent's interface name */ if (parent) { new_parent = nm_device_get_iface (parent); setting_parent = nm_setting_vxlan_get_parent (s_vxlan); if (setting_parent && nm_utils_is_uuid (setting_parent)) { NMConnection *parent_connection; /* Don't change a parent specified by UUID if it's still valid */ parent_connection = (NMConnection *) nm_settings_get_connection_by_uuid (nm_device_get_settings (device), setting_parent); if (parent_connection && nm_device_check_connection_compatible (parent, parent_connection)) new_parent = NULL; } if (new_parent) g_object_set (s_vxlan, NM_SETTING_VXLAN_PARENT, new_parent, NULL); } else g_object_set (s_vxlan, NM_SETTING_VXLAN_PARENT, NULL, NULL); if (!address_matches (nm_setting_vxlan_get_remote (s_vxlan), priv->props.group, &priv->props.group6)) { if (priv->props.group) { g_object_set (s_vxlan, NM_SETTING_VXLAN_REMOTE, nm_utils_inet4_ntop (priv->props.group, NULL), NULL); } else { g_object_set (s_vxlan, NM_SETTING_VXLAN_REMOTE, nm_utils_inet6_ntop (&priv->props.group6, NULL), NULL); } } if (!address_matches (nm_setting_vxlan_get_local (s_vxlan), priv->props.local, &priv->props.local6)) { if (priv->props.local) { g_object_set (s_vxlan, NM_SETTING_VXLAN_LOCAL, nm_utils_inet4_ntop (priv->props.local, NULL), NULL); } else if (memcmp (&priv->props.local6, &in6addr_any, sizeof (in6addr_any))) { g_object_set (s_vxlan, NM_SETTING_VXLAN_LOCAL, nm_utils_inet6_ntop (&priv->props.local6, NULL), NULL); } } if (priv->props.src_port_min != nm_setting_vxlan_get_source_port_min (s_vxlan)) { g_object_set (G_OBJECT (s_vxlan), NM_SETTING_VXLAN_SOURCE_PORT_MIN, priv->props.src_port_min, NULL); } if (priv->props.src_port_max != nm_setting_vxlan_get_source_port_max (s_vxlan)) { g_object_set (G_OBJECT (s_vxlan), NM_SETTING_VXLAN_SOURCE_PORT_MAX, priv->props.src_port_max, NULL); } if (priv->props.dst_port != nm_setting_vxlan_get_destination_port (s_vxlan)) { g_object_set (G_OBJECT (s_vxlan), NM_SETTING_VXLAN_DESTINATION_PORT, priv->props.dst_port, NULL); } if (priv->props.tos != nm_setting_vxlan_get_tos (s_vxlan)) { g_object_set (G_OBJECT (s_vxlan), NM_SETTING_VXLAN_TOS, priv->props.tos, NULL); } if (priv->props.ttl != nm_setting_vxlan_get_ttl (s_vxlan)) { g_object_set (G_OBJECT (s_vxlan), NM_SETTING_VXLAN_TTL, priv->props.ttl, NULL); } if (priv->props.learning != nm_setting_vxlan_get_learning (s_vxlan)) { g_object_set (G_OBJECT (s_vxlan), NM_SETTING_VXLAN_LEARNING, priv->props.learning, NULL); } if (priv->props.ageing != nm_setting_vxlan_get_ageing (s_vxlan)) { g_object_set (G_OBJECT (s_vxlan), NM_SETTING_VXLAN_AGEING, priv->props.ageing, NULL); } if (priv->props.proxy != nm_setting_vxlan_get_proxy (s_vxlan)) { g_object_set (G_OBJECT (s_vxlan), NM_SETTING_VXLAN_PROXY, priv->props.proxy, NULL); } if (priv->props.rsc != nm_setting_vxlan_get_rsc (s_vxlan)) { g_object_set (G_OBJECT (s_vxlan), NM_SETTING_VXLAN_RSC, priv->props.rsc, NULL); } if (priv->props.l2miss != nm_setting_vxlan_get_l2_miss (s_vxlan)) { g_object_set (G_OBJECT (s_vxlan), NM_SETTING_VXLAN_L2_MISS, priv->props.l2miss, NULL); } if (priv->props.l3miss != nm_setting_vxlan_get_l3_miss (s_vxlan)) { g_object_set (G_OBJECT (s_vxlan), NM_SETTING_VXLAN_L3_MISS, priv->props.l3miss, NULL); } }
static void update_connection (NMDevice *device, NMConnection *connection) { NMDeviceIPTunnel *self = NM_DEVICE_IP_TUNNEL (device); NMDeviceIPTunnelPrivate *priv = NM_DEVICE_IP_TUNNEL_GET_PRIVATE (self); NMSettingIPTunnel *s_ip_tunnel = nm_connection_get_setting_ip_tunnel (connection); NMDevice *parent = NULL; const char *setting_parent, *new_parent; if (!s_ip_tunnel) { s_ip_tunnel = (NMSettingIPTunnel *) nm_setting_ip_tunnel_new (); nm_connection_add_setting (connection, (NMSetting *) s_ip_tunnel); } if (nm_setting_ip_tunnel_get_mode (s_ip_tunnel) != priv->mode) g_object_set (G_OBJECT (s_ip_tunnel), NM_SETTING_IP_TUNNEL_MODE, priv->mode, NULL); if (priv->parent_ifindex > 0) parent = nm_manager_get_device_by_ifindex (nm_manager_get (), priv->parent_ifindex); /* Update parent in the connection; default to parent's interface name */ if (parent) { new_parent = nm_device_get_iface (parent); setting_parent = nm_setting_ip_tunnel_get_parent (s_ip_tunnel); if (setting_parent && nm_utils_is_uuid (setting_parent)) { NMConnection *parent_connection; /* Don't change a parent specified by UUID if it's still valid */ parent_connection = nm_connection_provider_get_connection_by_uuid (nm_connection_provider_get (), setting_parent); if (parent_connection && nm_device_check_connection_compatible (parent, parent_connection)) new_parent = NULL; } if (new_parent) g_object_set (s_ip_tunnel, NM_SETTING_IP_TUNNEL_PARENT, new_parent, NULL); } else g_object_set (s_ip_tunnel, NM_SETTING_IP_TUNNEL_PARENT, NULL, NULL); if (!address_equal_pp (priv->addr_family, nm_setting_ip_tunnel_get_local (s_ip_tunnel), priv->local)) g_object_set (G_OBJECT (s_ip_tunnel), NM_SETTING_IP_TUNNEL_LOCAL, priv->local, NULL); if (!address_equal_pp (priv->addr_family, nm_setting_ip_tunnel_get_remote (s_ip_tunnel), priv->remote)) g_object_set (G_OBJECT (s_ip_tunnel), NM_SETTING_IP_TUNNEL_REMOTE, priv->remote, NULL); if (nm_setting_ip_tunnel_get_ttl (s_ip_tunnel) != priv->ttl) g_object_set (G_OBJECT (s_ip_tunnel), NM_SETTING_IP_TUNNEL_TTL, priv->ttl, NULL); if (nm_setting_ip_tunnel_get_tos (s_ip_tunnel) != priv->tos) g_object_set (G_OBJECT (s_ip_tunnel), NM_SETTING_IP_TUNNEL_TOS, priv->tos, NULL); if (nm_setting_ip_tunnel_get_path_mtu_discovery (s_ip_tunnel) != priv->path_mtu_discovery) { g_object_set (G_OBJECT (s_ip_tunnel), NM_SETTING_IP_TUNNEL_PATH_MTU_DISCOVERY, priv->path_mtu_discovery, NULL); } if (nm_setting_ip_tunnel_get_encapsulation_limit (s_ip_tunnel) != priv->encap_limit) { g_object_set (G_OBJECT (s_ip_tunnel), NM_SETTING_IP_TUNNEL_ENCAPSULATION_LIMIT, priv->encap_limit, NULL); } if (nm_setting_ip_tunnel_get_flow_label (s_ip_tunnel) != priv->flow_label) { g_object_set (G_OBJECT (s_ip_tunnel), NM_SETTING_IP_TUNNEL_FLOW_LABEL, priv->flow_label, NULL); } if (priv->mode == NM_IP_TUNNEL_MODE_GRE || priv->mode == NM_IP_TUNNEL_MODE_IP6GRE) { if (g_strcmp0 (nm_setting_ip_tunnel_get_input_key (s_ip_tunnel), priv->input_key)) { g_object_set (G_OBJECT (s_ip_tunnel), NM_SETTING_IP_TUNNEL_INPUT_KEY, priv->input_key, NULL); } if (g_strcmp0 (nm_setting_ip_tunnel_get_output_key (s_ip_tunnel), priv->output_key)) { g_object_set (G_OBJECT (s_ip_tunnel), NM_SETTING_IP_TUNNEL_OUTPUT_KEY, priv->output_key, NULL); } } }
static void update_properties_from_ifindex (NMDevice *device, int ifindex) { NMDeviceIPTunnel *self = NM_DEVICE_IP_TUNNEL (device); NMDeviceIPTunnelPrivate *priv = NM_DEVICE_IP_TUNNEL_GET_PRIVATE (self); GObject *object = G_OBJECT (device); NMDevice *parent; int parent_ifindex; in_addr_t local4, remote4; struct in6_addr local6, remote6; guint8 ttl = 0, tos = 0, encap_limit = 0; gboolean pmtud = FALSE; guint32 flow_label = 0; char *key; if (ifindex <= 0) { clear: if (priv->parent || priv->parent_ifindex) { g_clear_object (&priv->parent); priv->parent_ifindex = 0; g_object_notify (object, NM_DEVICE_IP_TUNNEL_PARENT); } if (priv->local) { g_clear_pointer (&priv->local, g_free); g_object_notify (object, NM_DEVICE_IP_TUNNEL_LOCAL); } if (priv->remote) { g_clear_pointer (&priv->remote, g_free); g_object_notify (object, NM_DEVICE_IP_TUNNEL_REMOTE); } if (priv->input_key) { g_clear_pointer (&priv->input_key, g_free); g_object_notify (object, NM_DEVICE_IP_TUNNEL_INPUT_KEY); } if (priv->output_key) { g_clear_pointer (&priv->output_key, g_free); g_object_notify (object, NM_DEVICE_IP_TUNNEL_OUTPUT_KEY); } goto out; } if (priv->mode == NM_IP_TUNNEL_MODE_GRE) { const NMPlatformLnkGre *lnk; lnk = nm_platform_link_get_lnk_gre (NM_PLATFORM_GET, ifindex, NULL); if (!lnk) { _LOGW (LOGD_HW, "could not read %s properties", "gre"); goto clear; } parent_ifindex = lnk->parent_ifindex; local4 = lnk->local; remote4 = lnk->remote; ttl = lnk->ttl; tos = lnk->tos; pmtud = lnk->path_mtu_discovery; if (NM_FLAGS_HAS (lnk->input_flags, NM_GRE_KEY)) { key = g_strdup_printf ("%u", lnk->input_key); if (g_strcmp0 (priv->input_key, key)) { g_free (priv->input_key); priv->input_key = key; g_object_notify (object, NM_DEVICE_IP_TUNNEL_INPUT_KEY); } else g_free (key); } else { if (priv->input_key) { g_clear_pointer (&priv->input_key, g_free); g_object_notify (object, NM_DEVICE_IP_TUNNEL_INPUT_KEY); } } if (NM_FLAGS_HAS (lnk->output_flags, NM_GRE_KEY)) { key = g_strdup_printf ("%u", lnk->output_key); if (g_strcmp0 (priv->output_key, key)) { g_free (priv->output_key); priv->output_key = key; g_object_notify (object, NM_DEVICE_IP_TUNNEL_OUTPUT_KEY); } else g_free (key); } else { if (priv->output_key) { g_clear_pointer (&priv->output_key, g_free); g_object_notify (object, NM_DEVICE_IP_TUNNEL_OUTPUT_KEY); } } } else if (priv->mode == NM_IP_TUNNEL_MODE_SIT) { const NMPlatformLnkSit *lnk; lnk = nm_platform_link_get_lnk_sit (NM_PLATFORM_GET, ifindex, NULL); if (!lnk) { _LOGW (LOGD_HW, "could not read %s properties", "sit"); goto clear; } parent_ifindex = lnk->parent_ifindex; local4 = lnk->local; remote4 = lnk->remote; ttl = lnk->ttl; tos = lnk->tos; pmtud = lnk->path_mtu_discovery; } else if (priv->mode == NM_IP_TUNNEL_MODE_IPIP) { const NMPlatformLnkIpIp *lnk; lnk = nm_platform_link_get_lnk_ipip (NM_PLATFORM_GET, ifindex, NULL); if (!lnk) { _LOGW (LOGD_HW, "could not read %s properties", "ipip"); goto clear; } parent_ifindex = lnk->parent_ifindex; local4 = lnk->local; remote4 = lnk->remote; ttl = lnk->ttl; tos = lnk->tos; pmtud = lnk->path_mtu_discovery; } else if ( priv->mode == NM_IP_TUNNEL_MODE_IPIP6 || priv->mode == NM_IP_TUNNEL_MODE_IP6IP6) { const NMPlatformLnkIp6Tnl *lnk; lnk = nm_platform_link_get_lnk_ip6tnl (NM_PLATFORM_GET, ifindex, NULL); if (!lnk) { _LOGW (LOGD_HW, "could not read %s properties", "ip6tnl"); goto clear; } parent_ifindex = lnk->parent_ifindex; local6 = lnk->local; remote6 = lnk->remote; ttl = lnk->ttl; tos = lnk->tclass; encap_limit = lnk->encap_limit; flow_label = lnk->flow_label; } else g_return_if_reached (); if (priv->parent_ifindex != parent_ifindex) { g_clear_object (&priv->parent); priv->parent_ifindex = parent_ifindex; parent = nm_manager_get_device_by_ifindex (nm_manager_get (), parent_ifindex); if (parent) priv->parent = g_object_ref (parent); g_object_notify (object, NM_DEVICE_IP_TUNNEL_PARENT); } if (priv->addr_family == AF_INET) { if (!address_equal_pn (AF_INET, priv->local, &local4)) { g_clear_pointer (&priv->local, g_free); if (local4) priv->local = g_strdup (nm_utils_inet4_ntop (local4, NULL)); g_object_notify (object, NM_DEVICE_IP_TUNNEL_LOCAL); } if (!address_equal_pn (AF_INET, priv->remote, &remote4)) { g_clear_pointer (&priv->remote, g_free); if (remote4) priv->remote = g_strdup (nm_utils_inet4_ntop (remote4, NULL)); g_object_notify (object, NM_DEVICE_IP_TUNNEL_REMOTE); } } else { if (!address_equal_pn (AF_INET6, priv->local, &local6)) { g_clear_pointer (&priv->local, g_free); if (memcmp (&local6, &in6addr_any, sizeof (in6addr_any))) priv->local = g_strdup (nm_utils_inet6_ntop (&local6, NULL)); g_object_notify (object, NM_DEVICE_IP_TUNNEL_LOCAL); } if (!address_equal_pn (AF_INET6, priv->remote, &remote6)) { g_clear_pointer (&priv->remote, g_free); if (memcmp (&remote6, &in6addr_any, sizeof (in6addr_any))) priv->remote = g_strdup (nm_utils_inet6_ntop (&remote6, NULL)); g_object_notify (object, NM_DEVICE_IP_TUNNEL_REMOTE); } } out: if (priv->ttl != ttl) { priv->ttl = ttl; g_object_notify (object, NM_DEVICE_IP_TUNNEL_TTL); } if (priv->tos != tos) { priv->tos = tos; g_object_notify (object, NM_DEVICE_IP_TUNNEL_TOS); } if (priv->path_mtu_discovery != pmtud) { priv->path_mtu_discovery = pmtud; g_object_notify (object, NM_DEVICE_IP_TUNNEL_PATH_MTU_DISCOVERY); } if (priv->encap_limit != encap_limit) { priv->encap_limit = encap_limit; g_object_notify (object, NM_DEVICE_IP_TUNNEL_ENCAPSULATION_LIMIT); } if (priv->flow_label != flow_label) { priv->flow_label = flow_label; g_object_notify (object, NM_DEVICE_IP_TUNNEL_FLOW_LABEL); } }
/* * main * */ int main (int argc, char *argv[]) { gboolean wifi_enabled = TRUE, net_enabled = TRUE, wwan_enabled = TRUE; gboolean success = FALSE; NMConfig *config; GError *error = NULL; gboolean wrote_pidfile = FALSE; char *bad_domains = NULL; NMConfigCmdLineOptions *config_cli; nm_g_type_init (); /* Known to cause a possible deadlock upon GDBus initialization: * https://bugzilla.gnome.org/show_bug.cgi?id=674885 */ g_type_ensure (G_TYPE_SOCKET); g_type_ensure (G_TYPE_DBUS_CONNECTION); g_type_ensure (NM_TYPE_BUS_MANAGER); _nm_utils_is_manager_process = TRUE; main_loop = g_main_loop_new (NULL, FALSE); config_cli = nm_config_cmd_line_options_new (); do_early_setup (&argc, &argv, config_cli); if (global_opt.g_fatal_warnings) _set_g_fatal_warnings (); if (global_opt.show_version) { fprintf (stdout, NM_DIST_VERSION "\n"); exit (0); } nm_main_utils_ensure_root (); nm_main_utils_ensure_not_running_pidfile (global_opt.pidfile); /* Ensure state directory exists */ if (g_mkdir_with_parents (NMSTATEDIR, 0755) != 0) { fprintf (stderr, "Cannot create '%s': %s", NMSTATEDIR, strerror (errno)); exit (1); } nm_main_utils_ensure_rundir (); /* When running from the build directory, determine our build directory * base and set helper paths in the build tree */ if (global_opt.run_from_build_dir) { char *path, *slash; int g; /* exe is <basedir>/src/.libs/lt-NetworkManager, so chop off * the last three components */ path = realpath ("/proc/self/exe", NULL); g_assert (path != NULL); for (g = 0; g < 3; ++g) { slash = strrchr (path, '/'); g_assert (slash != NULL); *slash = '\0'; } /* don't free these strings, we need them for the entire * process lifetime */ nm_dhcp_helper_path = g_strdup_printf ("%s/src/dhcp-manager/nm-dhcp-helper", path); g_free (path); } if (!nm_logging_setup (global_opt.opt_log_level, global_opt.opt_log_domains, &bad_domains, &error)) { fprintf (stderr, _("%s. Please use --help to see a list of valid options.\n"), error->message); exit (1); } else if (bad_domains) { fprintf (stderr, _("Ignoring unrecognized log domain(s) '%s' passed on command line.\n"), bad_domains); g_clear_pointer (&bad_domains, g_free); } /* Read the config file and CLI overrides */ config = nm_config_setup (config_cli, NULL, &error); nm_config_cmd_line_options_free (config_cli); config_cli = NULL; if (config == NULL) { fprintf (stderr, _("Failed to read configuration: (%d) %s\n"), error ? error->code : -1, (error && error->message) ? error->message : _("unknown")); exit (1); } _init_nm_debug (nm_config_get_debug (config)); /* Initialize logging from config file *only* if not explicitly * specified by commandline. */ if (global_opt.opt_log_level == NULL && global_opt.opt_log_domains == NULL) { if (!nm_logging_setup (nm_config_get_log_level (config), nm_config_get_log_domains (config), &bad_domains, &error)) { fprintf (stderr, _("Error in configuration file: %s.\n"), error->message); exit (1); } else if (bad_domains) { fprintf (stderr, _("Ignoring unrecognized log domain(s) '%s' from config files.\n"), bad_domains); g_clear_pointer (&bad_domains, g_free); } } if (global_opt.become_daemon && !nm_config_get_is_debug (config)) { if (daemon (0, 0) < 0) { int saved_errno; saved_errno = errno; fprintf (stderr, _("Could not daemonize: %s [error %u]\n"), g_strerror (saved_errno), saved_errno); exit (1); } wrote_pidfile = nm_main_utils_write_pidfile (global_opt.pidfile); } /* Set up unix signal handling - before creating threads, but after daemonizing! */ nm_main_utils_setup_signals (main_loop); nm_logging_syslog_openlog (nm_config_get_is_debug (config) ? "debug" : nm_config_data_get_value_cached (NM_CONFIG_GET_DATA_ORIG, NM_CONFIG_KEYFILE_GROUP_LOGGING, NM_CONFIG_KEYFILE_KEY_LOGGING_BACKEND, NM_CONFIG_GET_VALUE_STRIP | NM_CONFIG_GET_VALUE_NO_EMPTY)); nm_log_info (LOGD_CORE, "NetworkManager (version " NM_DIST_VERSION ") is starting..."); /* Parse the state file */ if (!parse_state_file (global_opt.state_file, &net_enabled, &wifi_enabled, &wwan_enabled, &error)) { nm_log_err (LOGD_CORE, "State file %s parsing failed: (%d) %s", global_opt.state_file, error ? error->code : -1, (error && error->message) ? error->message : _("unknown")); /* Not a hard failure */ } g_clear_error (&error); nm_log_info (LOGD_CORE, "Read config: %s", nm_config_data_get_config_description (nm_config_get_data (config))); nm_config_data_log (nm_config_get_data (config), "CONFIG: "); nm_log_dbg (LOGD_CORE, "WEXT support is %s", #if HAVE_WEXT "enabled" #else "disabled" #endif ); nm_auth_manager_setup (nm_config_get_auth_polkit (config)); nm_manager_setup (global_opt.state_file, net_enabled, wifi_enabled, wwan_enabled); if (!nm_bus_manager_get_connection (nm_bus_manager_get ())) { nm_log_warn (LOGD_CORE, "Failed to connect to D-Bus; only private bus is available"); } else { /* Start our DBus service */ if (!nm_bus_manager_start_service (nm_bus_manager_get ())) { nm_log_err (LOGD_CORE, "failed to start the dbus service."); goto done; } } /* Set up platform interaction layer */ nm_linux_platform_setup (); NM_UTILS_KEEP_ALIVE (config, NM_PLATFORM_GET, "NMConfig-depends-on-NMPlatform"); nm_dispatcher_init (); g_signal_connect (nm_manager_get (), NM_MANAGER_CONFIGURE_QUIT, G_CALLBACK (manager_configure_quit), config); if (!nm_manager_start (nm_manager_get (), &error)) { nm_log_err (LOGD_CORE, "failed to initialize: %s", error->message); goto done; } /* Make sure the loopback interface is up. If interface is down, we bring * it up and kernel will assign it link-local IPv4 and IPv6 addresses. If * it was already up, we assume is in clean state. * * TODO: it might be desirable to check the list of addresses and compare * it with a list of expected addresses (one of the protocol families * could be disabled). The 'lo' interface is sometimes used for assigning * global addresses so their availability doesn't depend on the state of * physical interfaces. */ nm_log_dbg (LOGD_CORE, "setting up local loopback"); nm_platform_link_set_up (NM_PLATFORM_GET, 1, NULL); success = TRUE; if (configure_and_quit == FALSE) g_main_loop_run (main_loop); nm_manager_stop (nm_manager_get ()); done: if (global_opt.pidfile && wrote_pidfile) unlink (global_opt.pidfile); nm_log_info (LOGD_CORE, "exiting (%s)", success ? "success" : "error"); exit (success ? 0 : 1); }