static NMDevice * create_device (NMDeviceFactory *factory, const char *iface, const NMPlatformLink *plink, NMConnection *connection, gboolean *out_ignore) { NMSettingIPTunnel *s_ip_tunnel; NMIPTunnelMode mode; NMLinkType link_type; if (connection) { s_ip_tunnel = nm_connection_get_setting_ip_tunnel (connection); mode = nm_setting_ip_tunnel_get_mode (s_ip_tunnel); link_type = tunnel_mode_to_link_type (mode); } else { link_type = plink->type; mode = platform_link_to_tunnel_mode (plink); } if (mode == NM_IP_TUNNEL_MODE_UNKNOWN) return NULL; return (NMDevice *) g_object_new (NM_TYPE_DEVICE_IP_TUNNEL, NM_DEVICE_IFACE, iface, NM_DEVICE_TYPE_DESC, "IPTunnel", NM_DEVICE_DEVICE_TYPE, NM_DEVICE_TYPE_IP_TUNNEL, NM_DEVICE_LINK_TYPE, link_type, NM_DEVICE_IP_TUNNEL_MODE, mode, NULL); }
static gboolean check_connection_compatible (NMDevice *device, NMConnection *connection) { NMDeviceIPTunnel *self = NM_DEVICE_IP_TUNNEL (device); NMDeviceIPTunnelPrivate *priv = NM_DEVICE_IP_TUNNEL_GET_PRIVATE (self); NMSettingIPTunnel *s_ip_tunnel; const char *parent; if (!NM_DEVICE_CLASS (nm_device_ip_tunnel_parent_class)->check_connection_compatible (device, connection)) return FALSE; s_ip_tunnel = nm_connection_get_setting_ip_tunnel (connection); if (!s_ip_tunnel) return FALSE; if (nm_setting_ip_tunnel_get_mode (s_ip_tunnel) != priv->mode) return FALSE; if (nm_device_is_real (device)) { /* Check parent interface; could be an interface name or a UUID */ parent = nm_setting_ip_tunnel_get_parent (s_ip_tunnel); if (parent) { if (!match_parent (priv->parent, parent)) return FALSE; } if (!address_equal_pp (priv->addr_family, nm_setting_ip_tunnel_get_local (s_ip_tunnel), priv->local)) return FALSE; if (!address_equal_pp (priv->addr_family, nm_setting_ip_tunnel_get_remote (s_ip_tunnel), priv->remote)) return FALSE; if (nm_setting_ip_tunnel_get_ttl (s_ip_tunnel) != priv->ttl) return FALSE; if (nm_setting_ip_tunnel_get_tos (s_ip_tunnel) != priv->tos) return FALSE; if (priv->addr_family == AF_INET) { if (nm_setting_ip_tunnel_get_path_mtu_discovery (s_ip_tunnel) != priv->path_mtu_discovery) return FALSE; } else { if (nm_setting_ip_tunnel_get_encapsulation_limit (s_ip_tunnel) != priv->encap_limit) return FALSE; if (nm_setting_ip_tunnel_get_flow_label (s_ip_tunnel) != priv->flow_label) return FALSE; } } return TRUE; }
static void mode_changed (GObject *object, GParamSpec *pspec, gpointer user_data) { NMSettingIPTunnel *s_ip_tunnel = NM_SETTING_IP_TUNNEL (object); NmtPageIPTunnel *ip_tunnel = NMT_PAGE_IP_TUNNEL (user_data); NmtPageIPTunnelPrivate *priv = NMT_PAGE_IP_TUNNEL_GET_PRIVATE (ip_tunnel); NMIPTunnelMode mode; gboolean enable_keys; mode = nm_setting_ip_tunnel_get_mode (s_ip_tunnel); enable_keys = NM_IN_SET (mode, NM_IP_TUNNEL_MODE_GRE, NM_IP_TUNNEL_MODE_IP6GRE); nmt_newt_widget_set_visible (NMT_NEWT_WIDGET (priv->input_key), enable_keys); nmt_newt_widget_set_visible (NMT_NEWT_WIDGET (priv->output_key), enable_keys); if (!enable_keys) { nmt_newt_entry_set_text (priv->input_key, ""); nmt_newt_entry_set_text (priv->output_key, ""); } }
static gboolean create_and_realize (NMDevice *device, NMConnection *connection, NMDevice *parent, const NMPlatformLink **out_plink, GError **error) { const char *iface = nm_device_get_iface (device); NMSettingIPTunnel *s_ip_tunnel; NMPlatformError plerr; NMPlatformLnkGre lnk_gre = { }; NMPlatformLnkSit lnk_sit = { }; NMPlatformLnkIpIp lnk_ipip = { }; NMPlatformLnkIp6Tnl lnk_ip6tnl = { }; const char *str; gint64 val; s_ip_tunnel = nm_connection_get_setting_ip_tunnel (connection); g_assert (s_ip_tunnel); switch (nm_setting_ip_tunnel_get_mode (s_ip_tunnel)) { case NM_IP_TUNNEL_MODE_GRE: if (parent) lnk_gre.parent_ifindex = nm_device_get_ifindex (parent); str = nm_setting_ip_tunnel_get_local (s_ip_tunnel); if (str) inet_pton (AF_INET, str, &lnk_gre.local); str = nm_setting_ip_tunnel_get_remote (s_ip_tunnel); g_assert (str); inet_pton (AF_INET, str, &lnk_gre.remote); lnk_gre.ttl = nm_setting_ip_tunnel_get_ttl (s_ip_tunnel); lnk_gre.tos = nm_setting_ip_tunnel_get_tos (s_ip_tunnel); lnk_gre.path_mtu_discovery = nm_setting_ip_tunnel_get_path_mtu_discovery (s_ip_tunnel); val = _nm_utils_ascii_str_to_int64 (nm_setting_ip_tunnel_get_input_key (s_ip_tunnel), 10, 0, G_MAXUINT32, -1); if (val != -1) { lnk_gre.input_key = val; lnk_gre.input_flags = NM_GRE_KEY; } val = _nm_utils_ascii_str_to_int64 (nm_setting_ip_tunnel_get_output_key (s_ip_tunnel), 10, 0, G_MAXUINT32, -1); if (val != -1) { lnk_gre.output_key = val; lnk_gre.output_flags = NM_GRE_KEY; } plerr = nm_platform_link_gre_add (NM_PLATFORM_GET, iface, &lnk_gre, out_plink); if (plerr != NM_PLATFORM_ERROR_SUCCESS) { g_set_error (error, NM_DEVICE_ERROR, NM_DEVICE_ERROR_CREATION_FAILED, "Failed to create GRE interface '%s' for '%s': %s", iface, nm_connection_get_id (connection), nm_platform_error_to_string (plerr)); return FALSE; } break; case NM_IP_TUNNEL_MODE_SIT: if (parent) lnk_sit.parent_ifindex = nm_device_get_ifindex (parent); str = nm_setting_ip_tunnel_get_local (s_ip_tunnel); if (str) inet_pton (AF_INET, str, &lnk_sit.local); str = nm_setting_ip_tunnel_get_remote (s_ip_tunnel); g_assert (str); inet_pton (AF_INET, str, &lnk_sit.remote); lnk_sit.ttl = nm_setting_ip_tunnel_get_ttl (s_ip_tunnel); lnk_sit.tos = nm_setting_ip_tunnel_get_tos (s_ip_tunnel); lnk_sit.path_mtu_discovery = nm_setting_ip_tunnel_get_path_mtu_discovery (s_ip_tunnel); plerr = nm_platform_link_sit_add (NM_PLATFORM_GET, iface, &lnk_sit, out_plink); if (plerr != NM_PLATFORM_ERROR_SUCCESS) { g_set_error (error, NM_DEVICE_ERROR, NM_DEVICE_ERROR_CREATION_FAILED, "Failed to create SIT interface '%s' for '%s': %s", iface, nm_connection_get_id (connection), nm_platform_error_to_string (plerr)); return FALSE; } break; case NM_IP_TUNNEL_MODE_IPIP: if (parent) lnk_ipip.parent_ifindex = nm_device_get_ifindex (parent); str = nm_setting_ip_tunnel_get_local (s_ip_tunnel); if (str) inet_pton (AF_INET, str, &lnk_ipip.local); str = nm_setting_ip_tunnel_get_remote (s_ip_tunnel); g_assert (str); inet_pton (AF_INET, str, &lnk_ipip.remote); lnk_ipip.ttl = nm_setting_ip_tunnel_get_ttl (s_ip_tunnel); lnk_ipip.tos = nm_setting_ip_tunnel_get_tos (s_ip_tunnel); lnk_ipip.path_mtu_discovery = nm_setting_ip_tunnel_get_path_mtu_discovery (s_ip_tunnel); plerr = nm_platform_link_ipip_add (NM_PLATFORM_GET, iface, &lnk_ipip, out_plink); if (plerr != NM_PLATFORM_ERROR_SUCCESS) { g_set_error (error, NM_DEVICE_ERROR, NM_DEVICE_ERROR_CREATION_FAILED, "Failed to create IPIP interface '%s' for '%s': %s", iface, nm_connection_get_id (connection), nm_platform_error_to_string (plerr)); return FALSE; } break; case NM_IP_TUNNEL_MODE_IPIP6: case NM_IP_TUNNEL_MODE_IP6IP6: if (parent) lnk_ip6tnl.parent_ifindex = nm_device_get_ifindex (parent); str = nm_setting_ip_tunnel_get_local (s_ip_tunnel); if (str) inet_pton (AF_INET6, str, &lnk_ip6tnl.local); str = nm_setting_ip_tunnel_get_remote (s_ip_tunnel); g_assert (str); inet_pton (AF_INET6, str, &lnk_ip6tnl.remote); lnk_ip6tnl.ttl = nm_setting_ip_tunnel_get_ttl (s_ip_tunnel); lnk_ip6tnl.tclass = nm_setting_ip_tunnel_get_tos (s_ip_tunnel); lnk_ip6tnl.encap_limit = nm_setting_ip_tunnel_get_encapsulation_limit (s_ip_tunnel); lnk_ip6tnl.flow_label = nm_setting_ip_tunnel_get_flow_label (s_ip_tunnel); lnk_ip6tnl.proto = nm_setting_ip_tunnel_get_mode (s_ip_tunnel) == NM_IP_TUNNEL_MODE_IPIP6 ? IPPROTO_IPIP : IPPROTO_IPV6; plerr = nm_platform_link_ip6tnl_add (NM_PLATFORM_GET, iface, &lnk_ip6tnl, out_plink); if (plerr != NM_PLATFORM_ERROR_SUCCESS) { g_set_error (error, NM_DEVICE_ERROR, NM_DEVICE_ERROR_CREATION_FAILED, "Failed to create IPIP interface '%s' for '%s': %s", iface, nm_connection_get_id (connection), nm_platform_error_to_string (plerr)); return FALSE; } break; default: g_set_error (error, NM_DEVICE_ERROR, NM_DEVICE_ERROR_CREATION_FAILED, "Failed to create IP tunnel interface '%s' for '%s': mode %d not supported", iface, nm_connection_get_id (connection), (int) nm_setting_ip_tunnel_get_mode (s_ip_tunnel)); return FALSE; } return TRUE; }
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 nmt_page_ip_tunnel_constructed (GObject *object) { NmtPageIPTunnel *ip_tunnel = NMT_PAGE_IP_TUNNEL (object); NmtPageIPTunnelPrivate *priv = NMT_PAGE_IP_TUNNEL_GET_PRIVATE (ip_tunnel); NmtEditorSection *section; NmtEditorGrid *grid; NMSettingIPTunnel *s_ip_tunnel; NmtNewtWidget *widget, *parent; NMConnection *conn; GClosure *s2w, *w2s; conn = nmt_editor_page_get_connection (NMT_EDITOR_PAGE (ip_tunnel)); s_ip_tunnel = nm_connection_get_setting_ip_tunnel (conn); if (!s_ip_tunnel) { nm_connection_add_setting (conn, nm_setting_ip_tunnel_new ()); s_ip_tunnel = nm_connection_get_setting_ip_tunnel (conn); } /* Initialize the mode for new connections */ if (nm_setting_ip_tunnel_get_mode (s_ip_tunnel) == NM_IP_TUNNEL_MODE_UNKNOWN) { g_object_set (s_ip_tunnel, NM_SETTING_IP_TUNNEL_MODE, (guint) NM_IP_TUNNEL_MODE_IPIP, NULL); } section = nmt_editor_section_new (_("IP tunnel"), NULL, TRUE); grid = nmt_editor_section_get_body (section); /* To convert between widget index (0-based) and setting index (1-based) */ s2w = g_cclosure_new (G_CALLBACK (add_offset), GINT_TO_POINTER (-1), NULL); w2s = g_cclosure_new (G_CALLBACK (add_offset), GINT_TO_POINTER (1), NULL); widget = nmt_newt_popup_new (tunnel_mode); g_object_bind_property_with_closures (s_ip_tunnel, NM_SETTING_IP_TUNNEL_MODE, widget, "active", G_BINDING_BIDIRECTIONAL | G_BINDING_SYNC_CREATE, s2w, w2s); nmt_editor_grid_append (grid, _("Mode"), widget, NULL); widget = parent = nmt_device_entry_new (_("Parent"), 40, G_TYPE_NONE); g_object_bind_property (s_ip_tunnel, NM_SETTING_IP_TUNNEL_PARENT, widget, "interface-name", G_BINDING_BIDIRECTIONAL | G_BINDING_SYNC_CREATE); nmt_editor_grid_append (grid, NULL, widget, NULL); widget = nmt_newt_entry_new (40, 0); nmt_editor_grid_append (grid, _("Local IP"), widget, NULL); g_object_bind_property (s_ip_tunnel, NM_SETTING_IP_TUNNEL_LOCAL, widget, "text", G_BINDING_SYNC_CREATE | G_BINDING_BIDIRECTIONAL); widget = nmt_newt_entry_new (40, 0); nmt_editor_grid_append (grid, _("Remote IP"), widget, NULL); g_object_bind_property (s_ip_tunnel, NM_SETTING_IP_TUNNEL_REMOTE, widget, "text", G_BINDING_SYNC_CREATE | G_BINDING_BIDIRECTIONAL); widget = nmt_newt_entry_new (40, 0); nmt_editor_grid_append (grid, _("Input key"), widget, NULL); g_object_bind_property (s_ip_tunnel, NM_SETTING_IP_TUNNEL_INPUT_KEY, widget, "text", G_BINDING_SYNC_CREATE | G_BINDING_BIDIRECTIONAL); priv->input_key = NMT_NEWT_ENTRY (widget); widget = nmt_newt_entry_new (40, 0); nmt_editor_grid_append (grid, _("Output key"), widget, NULL); g_object_bind_property (s_ip_tunnel, NM_SETTING_IP_TUNNEL_OUTPUT_KEY, widget, "text", G_BINDING_SYNC_CREATE | G_BINDING_BIDIRECTIONAL); priv->output_key = NMT_NEWT_ENTRY (widget); widget = nmt_mtu_entry_new (); g_object_bind_property (s_ip_tunnel, NM_SETTING_IP_TUNNEL_MTU, widget, "mtu", G_BINDING_BIDIRECTIONAL | G_BINDING_SYNC_CREATE); nmt_editor_grid_append (grid, _("MTU"), widget, NULL); g_signal_connect (s_ip_tunnel, "notify::" NM_SETTING_IP_TUNNEL_MODE, G_CALLBACK (mode_changed), ip_tunnel); mode_changed (G_OBJECT (s_ip_tunnel), NULL, ip_tunnel); nmt_editor_page_add_section (NMT_EDITOR_PAGE (ip_tunnel), section); G_OBJECT_CLASS (nmt_page_ip_tunnel_parent_class)->constructed (object); }