/* < internal >
 * _g_dbus_method_invocation_new:
 * @sender: The bus name that invoked the method or %NULL if @connection is not a bus connection.
 * @object_path: The object path the method was invoked on.
 * @interface_name: The name of the D-Bus interface the method was invoked on.
 * @method_name: The name of the method that was invoked.
 * @method_info: Information about the method call or %NULL.
 * @connection: The #GDBusConnection the method was invoked on.
 * @message: The D-Bus message as a #GDBusMessage.
 * @parameters: The parameters as a #GVariant tuple.
 * @user_data: The @user_data #gpointer passed to g_dbus_connection_register_object().
 *
 * Creates a new #GDBusMethodInvocation object.
 *
 * Returns: A #GDBusMethodInvocation. Free with g_object_unref().
 *
 * Since: 2.26
 */
GDBusMethodInvocation *
_g_dbus_method_invocation_new (const gchar           *sender,
                               const gchar           *object_path,
                               const gchar           *interface_name,
                               const gchar           *method_name,
                               const GDBusMethodInfo *method_info,
                               GDBusConnection       *connection,
                               GDBusMessage          *message,
                               GVariant              *parameters,
                               gpointer               user_data)
{
  GDBusMethodInvocation *invocation;

  g_return_val_if_fail (sender == NULL || g_dbus_is_name (sender), NULL);
  g_return_val_if_fail (g_variant_is_object_path (object_path), NULL);
  g_return_val_if_fail (interface_name == NULL || g_dbus_is_interface_name (interface_name), NULL);
  g_return_val_if_fail (g_dbus_is_member_name (method_name), NULL);
  g_return_val_if_fail (G_IS_DBUS_CONNECTION (connection), NULL);
  g_return_val_if_fail (G_IS_DBUS_MESSAGE (message), NULL);
  g_return_val_if_fail (g_variant_is_of_type (parameters, G_VARIANT_TYPE_TUPLE), NULL);

  invocation = G_DBUS_METHOD_INVOCATION (g_object_new (G_TYPE_DBUS_METHOD_INVOCATION, NULL));
  invocation->sender = g_strdup (sender);
  invocation->object_path = g_strdup (object_path);
  invocation->interface_name = g_strdup (interface_name);
  invocation->method_name = g_strdup (method_name);
  invocation->method_info = g_dbus_method_info_ref ((GDBusMethodInfo *)method_info);
  invocation->connection = g_object_ref (connection);
  invocation->message = g_object_ref (message);
  invocation->parameters = g_variant_ref (parameters);
  invocation->user_data = user_data;

  return invocation;
}
static gboolean
register_portal (const char *path, GError **error)
{
  g_autoptr(GKeyFile) keyfile = g_key_file_new ();
  g_autoptr(PortalImplementation) impl = g_new0 (PortalImplementation, 1);
  int i;

  g_debug ("loading %s", path);

  if (!g_key_file_load_from_file (keyfile, path, G_KEY_FILE_NONE, error))
    return FALSE;

  impl->dbus_name = g_key_file_get_string (keyfile, "portal", "DBusName", error);
  if (impl->dbus_name == NULL)
    return FALSE;
  if (!g_dbus_is_name (impl->dbus_name))
    {
      g_set_error (error, G_KEY_FILE_ERROR, G_KEY_FILE_ERROR_INVALID_VALUE,
                   "Not a valid bus name: %s", impl->dbus_name);
      return FALSE;
    }

  impl->interfaces = g_key_file_get_string_list (keyfile, "portal", "Interfaces", NULL, error);
  if (impl->interfaces == NULL)
    return FALSE;
  for (i = 0; impl->interfaces[i]; i++)
    {
      if (!g_dbus_is_interface_name (impl->interfaces[i]))
        {
          g_set_error (error, G_KEY_FILE_ERROR, G_KEY_FILE_ERROR_INVALID_VALUE,
                       "Not a valid interface name: %s", impl->interfaces[i]);
          return FALSE;
        }
      if (!g_str_has_prefix (impl->interfaces[i], "org.freedesktop.impl.portal."))
        {
          g_set_error (error, G_KEY_FILE_ERROR, G_KEY_FILE_ERROR_INVALID_VALUE,
                       "Not a portal backend interface: %s", impl->interfaces[i]);
          return FALSE;
        }
    }

  impl->use_in = g_key_file_get_string_list (keyfile, "portal", "UseIn", NULL, error);
  if (impl->use_in == NULL)
    return FALSE;

  if (opt_verbose)
    {
      g_autofree char *uses = g_strjoinv (", ", impl->use_in);
      g_debug ("portal implementation for %s", uses);
      for (i = 0; impl->interfaces[i]; i++)
        g_debug ("portal implementation supports %s", impl->interfaces[i]);
    }

  implementations = g_list_prepend (implementations, impl);
  impl = NULL;

  return TRUE;
}
/**
 * g_bus_own_name:
 * @bus_type: The type of bus to own a name on.
 * @name: The well-known name to own.
 * @flags: A set of flags from the #GBusNameOwnerFlags enumeration.
 * @bus_acquired_handler: Handler to invoke when connected to the bus of type @bus_type or %NULL.
 * @name_acquired_handler: Handler to invoke when @name is acquired or %NULL.
 * @name_lost_handler: Handler to invoke when @name is lost or %NULL.
 * @user_data: User data to pass to handlers.
 * @user_data_free_func: Function for freeing @user_data or %NULL.
 *
 * Starts acquiring @name on the bus specified by @bus_type and calls
 * @name_acquired_handler and @name_lost_handler when the name is
 * acquired respectively lost. Callbacks will be invoked in the <link
 * linkend="g-main-context-push-thread-default">thread-default main
 * loop</link> of the thread you are calling this function from.
 *
 * You are guaranteed that one of the @name_acquired_handler and @name_lost_handler
 * callbacks will be invoked after calling this function - there are three
 * possible cases:
 * <itemizedlist>
 *   <listitem><para>
 *     @name_lost_handler with a %NULL connection (if a connection to the bus can't be made).
 *   </para></listitem>
 *   <listitem><para>
 *     @bus_acquired_handler then @name_lost_handler (if the name can't be obtained)
 *   </para></listitem>
 *   <listitem><para>
 *     @bus_acquired_handler then @name_acquired_handler (if the name was obtained).
 *   </para></listitem>
 * </itemizedlist>
 * When you are done owning the name, just call g_bus_unown_name()
 * with the owner id this function returns.
 *
 * If the name is acquired or lost (for example another application
 * could acquire the name if you allow replacement or the application
 * currently owning the name exits), the handlers are also invoked. If the
 * #GDBusConnection that is used for attempting to own the name
 * closes, then @name_lost_handler is invoked since it is no
 * longer possible for other processes to access the process.
 *
 * You cannot use g_bus_own_name() several times for the same name (unless
 * interleaved with calls to g_bus_unown_name()) - only the first call
 * will work.
 *
 * Another guarantee is that invocations of @name_acquired_handler
 * and @name_lost_handler are guaranteed to alternate; that
 * is, if @name_acquired_handler is invoked then you are
 * guaranteed that the next time one of the handlers is invoked, it
 * will be @name_lost_handler. The reverse is also true.
 *
 * If you plan on exporting objects (using e.g.
 * g_dbus_connection_register_object()), note that it is generally too late
 * to export the objects in @name_acquired_handler. Instead, you can do this
 * in @bus_acquired_handler since you are guaranteed that this will run
 * before @name is requested from the bus.
 *
 * This behavior makes it very simple to write applications that wants
 * to own names and export objects, see <xref linkend="gdbus-owning-names"/>.
 * Simply register objects to be exported in @bus_acquired_handler and
 * unregister the objects (if any) in @name_lost_handler.
 *
 * Returns: An identifier (never 0) that an be used with
 * g_bus_unown_name() to stop owning the name.
 *
 * Since: 2.26
 */
guint
g_bus_own_name (GBusType                  bus_type,
                const gchar              *name,
                GBusNameOwnerFlags        flags,
                GBusAcquiredCallback      bus_acquired_handler,
                GBusNameAcquiredCallback  name_acquired_handler,
                GBusNameLostCallback      name_lost_handler,
                gpointer                  user_data,
                GDestroyNotify            user_data_free_func)
{
  Client *client;

  g_return_val_if_fail (g_dbus_is_name (name) && !g_dbus_is_unique_name (name), 0);

  G_LOCK (lock);

  client = g_new0 (Client, 1);
  client->ref_count = 1;
  client->id = next_global_id++; /* TODO: uh oh, handle overflow */
  client->name = g_strdup (name);
  client->flags = flags;
  client->bus_acquired_handler = bus_acquired_handler;
  client->name_acquired_handler = name_acquired_handler;
  client->name_lost_handler = name_lost_handler;
  client->user_data = user_data;
  client->user_data_free_func = user_data_free_func;
  client->main_context = g_main_context_get_thread_default ();
  if (client->main_context != NULL)
    g_main_context_ref (client->main_context);

  if (map_id_to_client == NULL)
    {
      map_id_to_client = g_hash_table_new (g_direct_hash, g_direct_equal);
    }
  g_hash_table_insert (map_id_to_client,
                       GUINT_TO_POINTER (client->id),
                       client);

  g_bus_get (bus_type,
             NULL,
             connection_get_cb,
             client_ref (client));

  G_UNLOCK (lock);

  return client->id;
}
示例#4
0
static gboolean
app_check_name (gchar       **args,
                const gchar  *command)
{
  if (args[0] == NULL)
    {
      g_printerr (_("%s command requires an application id to directly follow\n\n"), command);
      return FALSE;
    }

  if (!g_dbus_is_name (args[0]))
    {
      g_printerr (_("invalid application id: '%s'\n"), args[0]);
      return FALSE;
    }

  return TRUE;
}
示例#5
0
/**
 * g_bus_watch_name:
 * @bus_type: The type of bus to watch a name on.
 * @name: The name (well-known or unique) to watch.
 * @flags: Flags from the #GBusNameWatcherFlags enumeration.
 * @name_appeared_handler: (nullable): Handler to invoke when @name is known to exist or %NULL.
 * @name_vanished_handler: (nullable): Handler to invoke when @name is known to not exist or %NULL.
 * @user_data: User data to pass to handlers.
 * @user_data_free_func: (nullable): Function for freeing @user_data or %NULL.
 *
 * Starts watching @name on the bus specified by @bus_type and calls
 * @name_appeared_handler and @name_vanished_handler when the name is
 * known to have a owner respectively known to lose its
 * owner. Callbacks will be invoked in the
 * [thread-default main context][g-main-context-push-thread-default]
 * of the thread you are calling this function from.
 *
 * You are guaranteed that one of the handlers will be invoked after
 * calling this function. When you are done watching the name, just
 * call g_bus_unwatch_name() with the watcher id this function
 * returns.
 *
 * If the name vanishes or appears (for example the application owning
 * the name could restart), the handlers are also invoked. If the
 * #GDBusConnection that is used for watching the name disconnects, then
 * @name_vanished_handler is invoked since it is no longer
 * possible to access the name.
 *
 * Another guarantee is that invocations of @name_appeared_handler
 * and @name_vanished_handler are guaranteed to alternate; that
 * is, if @name_appeared_handler is invoked then you are
 * guaranteed that the next time one of the handlers is invoked, it
 * will be @name_vanished_handler. The reverse is also true.
 *
 * This behavior makes it very simple to write applications that want
 * to take action when a certain [name exists][gdbus-watching-names].
 * Basically, the application should create object proxies in
 * @name_appeared_handler and destroy them again (if any) in
 * @name_vanished_handler.
 *
 * Returns: An identifier (never 0) that an be used with
 * g_bus_unwatch_name() to stop watching the name.
 *
 * Since: 2.26
 */
guint
g_bus_watch_name (GBusType                  bus_type,
                  const gchar              *name,
                  GBusNameWatcherFlags      flags,
                  GBusNameAppearedCallback  name_appeared_handler,
                  GBusNameVanishedCallback  name_vanished_handler,
                  gpointer                  user_data,
                  GDestroyNotify            user_data_free_func)
{
  Client *client;

  g_return_val_if_fail (g_dbus_is_name (name), 0);

  G_LOCK (lock);

  client = g_new0 (Client, 1);
  client->ref_count = 1;
  client->id = g_atomic_int_add (&next_global_id, 1); /* TODO: uh oh, handle overflow */
  client->name = g_strdup (name);
  client->flags = flags;
  client->name_appeared_handler = name_appeared_handler;
  client->name_vanished_handler = name_vanished_handler;
  client->user_data = user_data;
  client->user_data_free_func = user_data_free_func;
  client->main_context = g_main_context_ref_thread_default ();

  if (map_id_to_client == NULL)
    {
      map_id_to_client = g_hash_table_new (g_direct_hash, g_direct_equal);
    }
  g_hash_table_insert (map_id_to_client,
                       GUINT_TO_POINTER (client->id),
                       client);

  g_bus_get (bus_type,
             NULL,
             connection_get_cb,
             client_ref (client));

  G_UNLOCK (lock);

  return client->id;
}
/**
 * g_bus_watch_name_on_connection:
 * @connection: A #GDBusConnection.
 * @name: The name (well-known or unique) to watch.
 * @flags: Flags from the #GBusNameWatcherFlags enumeration.
 * @name_appeared_handler: (allow-none): Handler to invoke when @name is known to exist or %NULL.
 * @name_vanished_handler: (allow-none): Handler to invoke when @name is known to not exist or %NULL.
 * @user_data: User data to pass to handlers.
 * @user_data_free_func: (allow-none): Function for freeing @user_data or %NULL.
 *
 * Like g_bus_watch_name() but takes a #GDBusConnection instead of a
 * #GBusType.
 *
 * Returns: An identifier (never 0) that an be used with
 * g_bus_unwatch_name() to stop watching the name.
 *
 * Since: 2.26
 */
guint g_bus_watch_name_on_connection (GDBusConnection          *connection,
                                      const gchar              *name,
                                      GBusNameWatcherFlags      flags,
                                      GBusNameAppearedCallback  name_appeared_handler,
                                      GBusNameVanishedCallback  name_vanished_handler,
                                      gpointer                  user_data,
                                      GDestroyNotify            user_data_free_func)
{
  Client *client;

  g_return_val_if_fail (G_IS_DBUS_CONNECTION (connection), 0);
  g_return_val_if_fail (g_dbus_is_name (name), 0);

  G_LOCK (lock);

  client = g_new0 (Client, 1);
  client->ref_count = 1;
  client->id = next_global_id++; /* TODO: uh oh, handle overflow */
  client->name = g_strdup (name);
  client->flags = flags;
  client->name_appeared_handler = name_appeared_handler;
  client->name_vanished_handler = name_vanished_handler;
  client->user_data = user_data;
  client->user_data_free_func = user_data_free_func;
  client->main_context = g_main_context_ref_thread_default ();

  if (map_id_to_client == NULL)
    map_id_to_client = g_hash_table_new (g_direct_hash, g_direct_equal);

  g_hash_table_insert (map_id_to_client,
                       GUINT_TO_POINTER (client->id),
                       client);

  client->connection = g_object_ref (connection);
  G_UNLOCK (lock);

  has_connection (client);

  return client->id;
}
/**
 * g_dbus_method_invocation_return_dbus_error:
 * @invocation: A #GDBusMethodInvocation.
 * @error_name: A valid D-Bus error name.
 * @error_message: A valid D-Bus error message.
 *
 * Finishes handling a D-Bus method call by returning an error.
 *
 * This method will free @invocation, you cannot use it afterwards.
 *
 * Since: 2.26
 */
void
g_dbus_method_invocation_return_dbus_error (GDBusMethodInvocation *invocation,
                                            const gchar           *error_name,
                                            const gchar           *error_message)
{
  GDBusMessage *reply;

  g_return_if_fail (G_IS_DBUS_METHOD_INVOCATION (invocation));
  g_return_if_fail (error_name != NULL && g_dbus_is_name (error_name));
  g_return_if_fail (error_message != NULL);

  if (G_UNLIKELY (_g_dbus_debug_return ()))
    {
      _g_dbus_debug_print_lock ();
      g_print ("========================================================================\n"
               "GDBus-debug:Return:\n"
               " >>>> METHOD ERROR %s\n"
               "      message `%s'\n"
               "      in response to %s.%s()\n"
               "      on object %s\n"
               "      to name %s\n"
               "      reply-serial %d\n",
               error_name,
               error_message,
               invocation->interface_name, invocation->method_name,
               invocation->object_path,
               invocation->sender,
               g_dbus_message_get_serial (invocation->message));
      _g_dbus_debug_print_unlock ();
    }

  reply = g_dbus_message_new_method_error_literal (invocation->message,
                                                   error_name,
                                                   error_message);
  g_dbus_connection_send_message (g_dbus_method_invocation_get_connection (invocation), reply, G_DBUS_SEND_MESSAGE_FLAGS_NONE, NULL, NULL);
  g_object_unref (reply);

  g_object_unref (invocation);
}
示例#8
0
/**
 * cockpit_fake_manager_new_for_bus:
 * @bus_type: dbus bus to listen on
 * @flags: flags for the object manager
 * @bus_name: name of service to look for objects on
 * @object_paths: the paths to initially poke
 * @cancellable: optional cancellation object
 * @callback: called when operation finishes
 * @user_data: data for callback
 *
 * Create a new CockpitFakeManager.
 *
 * The @object_paths are poked and introspected. These are added
 * as well as anything else discovered along the way, before the
 * async operation completes.
 *
 * If @object_paths is NULL it will default to the root '/' DBus
 * path. If @object_paths is an empty array, then nothing is
 * poked during initialization.
 */
void
cockpit_fake_manager_new_for_bus (GBusType bus_type,
                                  GDBusObjectManagerClientFlags flags,
                                  const gchar *bus_name,
                                  const gchar **object_paths,
                                  GCancellable *cancellable,
                                  GAsyncReadyCallback callback,
                                  gpointer user_data)
{
  g_return_if_fail (g_dbus_is_name (bus_name));

  g_async_initable_new_async (COCKPIT_TYPE_FAKE_MANAGER,
                              G_PRIORITY_DEFAULT,
                              cancellable,
                              callback,
                              user_data,
                              "bus-type", bus_type,
                              "flags", flags,
                              "name", bus_name,
                              "object-paths", object_paths,
                              NULL);
}
示例#9
0
/*
** DBus method call: "InstanceExit" -- Called from an instance
*/
static gboolean on_handle_instance_exit(WarfacebotMngr *wbm,
                                        GDBusMethodInvocation *invocation,
                                        const gchar *BusName)
{
    g_print("Instance wants to exit: %s\n", BusName);

    if (!g_dbus_is_name(BusName))
    {
        g_dbus_method_invocation_return_dbus_error(
            invocation,
            "org.freedesktop.DBus.Error.ServiceUnknown",
            "Invalid BusName");
        return FALSE;
    }

    delete_service_file(BusName);

    warfacebot_mngr_complete_instance_exit(
        wbm,
        invocation);

    return TRUE;
}
示例#10
0
/*
** DBus method call: "InstanceReady" -- Called from an instance
**  - Create an instance interface in the manager bus
**  - Watch the instance bus
*/
static gboolean on_handle_instance_ready(WarfacebotMngr *wbm,
                                         GDBusMethodInvocation *invocation,
                                         const gchar *Nickname,
                                         const gchar *Server,
                                         const gchar *BusName)
{
    ObjectSkeleton *skeleton = NULL;
    WarfacebotMngrInstance *wbi = NULL;
    struct watch_instance *watch = NULL;

    if (!g_dbus_is_name(BusName))
    {
        g_dbus_method_invocation_return_dbus_error(
            invocation,
            "org.freedesktop.DBus.Error.ServiceUnknown",
            "Invalid BusName");
        return FALSE;
    }

    g_print("Notification from instance: %s\n", BusName);

    watch = g_new0(struct watch_instance, 1);

    watch->name = g_strdup(BusName);
    watch->path = g_strdup_printf(API_MNGR_PATH "/%03d", ++uniq_id);
    skeleton = object_skeleton_new(watch->path);

    wbi = warfacebot_mngr_instance_skeleton_new();

    warfacebot_mngr_instance_set_nickname(wbi, Nickname);
    warfacebot_mngr_instance_set_server(wbi, Server);
    warfacebot_mngr_instance_set_bus_name(wbi, BusName);
    warfacebot_mngr_instance_set_starttime(wbi, time(NULL));

    object_skeleton_set_warfacebot_mngr_instance(skeleton, wbi);

    g_dbus_object_manager_server_export(
        manager,
        G_DBUS_OBJECT_SKELETON (skeleton));

    g_object_unref(skeleton);

    create_service_file(BusName, Nickname, Server);

    watch->id = g_bus_watch_name(
        G_BUS_TYPE_SESSION,
        BusName,
        G_BUS_NAME_WATCHER_FLAGS_AUTO_START,
        on_instance_name_appeared,
        on_instance_name_vanished,
        watch,
        NULL);

    g_print("Watching instance: %s\n", BusName);

    warfacebot_mngr_complete_instance_ready(
        wbm,
        invocation);

    return TRUE;
}
int
main (int argc, char *argv[])
{
	NMDBusLibreswanHelper *proxy;
	GVariantBuilder environment;
	GError *err = NULL;
	gchar **env;
	gchar **p;
	const char *bus_name = NM_DBUS_SERVICE_LIBRESWAN;
	char *str = NULL;
	char **i_env;

#if !GLIB_CHECK_VERSION (2, 35, 0)
	g_type_init ();
#endif

	/* support old command line arguments. The only reason for that is to
	 * support update of the plugin while being connected. */
	switch (argc) {
	case 1:
		break;
	case 4:
		gl.log_level = _nm_utils_ascii_str_to_int64 (argv[1], 10, 0, LOG_DEBUG, 0);
		gl.log_prefix_token = argv[2];
		bus_name = argv[3];
		break;
	case 3:
		if (strcmp (argv[1], "--bus-name") == 0) {
			bus_name = argv[2];
			break;
		}
		/* fallthrough */
	default:
		g_printerr ("Usage: %s <LEVEL> <PREFIX_TOKEN> <BUS_NAME>\n", argv[0]);
		exit (1);
	}

	if (!g_dbus_is_name (bus_name)) {
		g_printerr ("Not a valid bus name: '%s'\n", bus_name);
		exit (1);
	}

	_LOGD ("command line: %s", (str = g_strjoinv (" ", argv)));
	g_clear_pointer (&str, g_free);

	for (i_env = environ; i_env && *i_env; i_env++)
		_LOGD ("environment: %s", *i_env);

	proxy = nmdbus_libreswan_helper_proxy_new_for_bus_sync (G_BUS_TYPE_SYSTEM,
	                                                        G_DBUS_PROXY_FLAGS_DO_NOT_LOAD_PROPERTIES,
	                                                        bus_name,
	                                                        NM_DBUS_PATH_LIBRESWAN_HELPER,
	                                                        NULL, &err);
	if (!proxy) {
		_LOGW ("Could not create a D-Bus proxy: %s", err->message);
		g_error_free (err);
		exit (1);
	}

	g_variant_builder_init (&environment, G_VARIANT_TYPE ("a{ss}"));
	env = g_listenv ();
	for (p = env; *p; p++) {
		if (strncmp ("PLUTO_", *p, 6))
			continue;
		g_variant_builder_add (&environment, "{ss}", *p, g_getenv (*p));
	}
	g_strfreev (env);

	if (!nmdbus_libreswan_helper_call_callback_sync (proxy,
	                                                 g_variant_builder_end (&environment),
	                                                 NULL, &err)) {
		_LOGW ("Could not call the plugin: %s", err->message);
		g_error_free (err);
		g_object_unref (proxy);
		exit (1);
	}

	g_object_unref (proxy);

	exit (0);
}
int
main (int argc, char *argv[])
{
	GDBusProxy *proxy;
	GVariantBuilder builder, ip4builder, ip6builder;
	GVariant *ip4config, *ip6config;
	char *tmp;
	GVariant *val;
	int i;
	GError *err = NULL;
	GPtrArray *dns4_list, *dns6_list;
	GPtrArray *nbns_list;
	GPtrArray *dns_domains;
	struct in_addr temp_addr;
	int tapdev = -1;
	char **iter;
	int shift = 0;
	gboolean is_restart;
	gboolean has_ip4_prefix = FALSE;
	gboolean has_ip4_address = FALSE;
	gboolean has_ip6_address = FALSE;
	gchar *bus_name = NM_DBUS_SERVICE_OPENVPN;

#if !GLIB_CHECK_VERSION (2, 35, 0)
	g_type_init ();
#endif

	for (i = 1; i < argc; i++) {
		if (!strcmp (argv[i], "--")) {
			i++;
			break;
		}
		if (nm_streq (argv[i], "--debug")) {
			if (i + 2 >= argc) {
				g_printerr ("Missing debug arguments (requires <LEVEL> <PREFIX_TOKEN>)\n");
				exit (1);
			}
			gl.log_level = _nm_utils_ascii_str_to_int64 (argv[++i], 10, 0, LOG_DEBUG, 0);
			gl.log_prefix_token = argv[++i];
		} else if (!strcmp (argv[i], "--tun"))
			tapdev = 0;
		else if (!strcmp (argv[i], "--tap"))
			tapdev = 1;
		else if (!strcmp (argv[i], "--bus-name")) {
			if (++i == argc) {
				g_printerr ("Missing bus name argument\n");
				exit (1);
			}
			if (!g_dbus_is_name (argv[i])) {
				g_printerr ("Invalid bus name\n");
				exit (1);
			}
			bus_name = argv[i];
		} else
			break;
	}
	shift = i - 1;

	if (_LOGD_enabled ()) {
		GString *args;

		args = g_string_new (NULL);
		for (i = 0; i < argc; i++) {
			if (i > 0)
				g_string_append_c (args, ' ');
			if (shift && 1 + shift == i)
				g_string_append (args, "  ");
			tmp = g_strescape (argv[i], NULL);
			g_string_append_printf (args, "\"%s\"", tmp);
			g_free (tmp);
		}

		_LOGD ("command line: %s", args->str);
		g_string_free (args, TRUE);

		for (iter = environ; iter && *iter; iter++)
			_LOGD ("environment: %s", *iter);
	}

	/* shift the arguments to the right leaving only those provided by openvpn */
	argv[shift] = argv[0];
	argv += shift;
	argc -= shift;

	is_restart = argc >= 7 && !g_strcmp0 (argv[6], "restart");

	proxy = g_dbus_proxy_new_for_bus_sync (G_BUS_TYPE_SYSTEM,
	                                       G_DBUS_PROXY_FLAGS_DO_NOT_LOAD_PROPERTIES,
	                                       NULL,
	                                       bus_name,
	                                       NM_VPN_DBUS_PLUGIN_PATH,
	                                       NM_VPN_DBUS_PLUGIN_INTERFACE,
	                                       NULL, &err);
	if (!proxy) {
		_LOGW ("Could not create a D-Bus proxy: %s", err->message);
		g_error_free (err);
		exit (1);
	}

	g_variant_builder_init (&builder, G_VARIANT_TYPE_VARDICT);
	g_variant_builder_init (&ip4builder, G_VARIANT_TYPE_VARDICT);
	g_variant_builder_init (&ip6builder, G_VARIANT_TYPE_VARDICT);

	/* External world-visible VPN gateway */
	val = trusted_remote_to_gvariant ();
	if (val)
		g_variant_builder_add (&builder, "{sv}", NM_VPN_PLUGIN_CONFIG_EXT_GATEWAY, val);
	else
		helper_failed (proxy, "VPN Gateway");

	/* Internal VPN subnet gateway */
	tmp = getenv ("route_vpn_gateway");
	val = addr4_to_gvariant (tmp);
	if (val)
		g_variant_builder_add (&ip4builder, "{sv}", NM_VPN_PLUGIN_IP4_CONFIG_INT_GATEWAY, val);
	else {
		val = addr6_to_gvariant (tmp);
		if (val)
			g_variant_builder_add (&ip6builder, "{sv}", NM_VPN_PLUGIN_IP6_CONFIG_INT_GATEWAY, val);
	}

	/* VPN device */
	tmp = getenv ("dev");
	val = str_to_gvariant (tmp, FALSE);
	if (val)
		g_variant_builder_add (&builder, "{sv}", NM_VPN_PLUGIN_CONFIG_TUNDEV, val);
	else
		helper_failed (proxy, "Tunnel Device");

	if (tapdev == -1)
		tapdev = strncmp (tmp, "tap", 3) == 0;

	/* IPv4 address */
	tmp = getenv ("ifconfig_local");
	if (!tmp && is_restart)
		tmp = argv[4];
	if (tmp && strlen (tmp)) {
		val = addr4_to_gvariant (tmp);
		if (val) {
			has_ip4_address = TRUE;
			g_variant_builder_add (&ip4builder, "{sv}", NM_VPN_PLUGIN_IP4_CONFIG_ADDRESS, val);
		} else
			helper_failed (proxy, "IP4 Address");
	}

	/* PTP address; for vpnc PTP address == internal IP4 address */
	tmp = getenv ("ifconfig_remote");
	if (!tmp && is_restart)
		tmp = argv[5];
	val = addr4_to_gvariant (tmp);
	if (val) {
		/* Sigh.  Openvpn added 'topology' stuff in 2.1 that changes the meaning
		 * of the ifconfig bits without actually telling you what they are
		 * supposed to mean; basically relying on specific 'ifconfig' behavior.
		 */
		if (tmp && !strncmp (tmp, "255.", 4)) {
			guint32 addr;

			/* probably a netmask, not a PTP address; topology == subnet */
			addr = g_variant_get_uint32 (val);
			g_variant_unref (val);
			val = g_variant_new_uint32 (nm_utils_ip4_netmask_to_prefix (addr));
			g_variant_builder_add (&ip4builder, "{sv}", NM_VPN_PLUGIN_IP4_CONFIG_PREFIX, val);
			has_ip4_prefix = TRUE;
		} else
			g_variant_builder_add (&ip4builder, "{sv}", NM_VPN_PLUGIN_IP4_CONFIG_PTP, val);
	}

	/* Netmask
	 *
	 * Either TAP or TUN modes can have an arbitrary netmask in newer versions
	 * of openvpn, while in older versions only TAP mode would.  So accept a
	 * netmask if passed, otherwise default to /32 for TUN devices since they
	 * are usually point-to-point.
	 */
	tmp = getenv ("ifconfig_netmask");
	if (tmp && inet_pton (AF_INET, tmp, &temp_addr) > 0) {
		val = g_variant_new_uint32 (nm_utils_ip4_netmask_to_prefix (temp_addr.s_addr));
		g_variant_builder_add (&ip4builder, "{sv}", NM_VPN_PLUGIN_IP4_CONFIG_PREFIX, val);
	} else if (!tapdev) {
		if (has_ip4_address && !has_ip4_prefix) {
			val = g_variant_new_uint32 (32);
			g_variant_builder_add (&ip4builder, "{sv}", NM_VPN_PLUGIN_IP4_CONFIG_PREFIX, val);
		}
	} else
		_LOGW ("No IP4 netmask/prefix (missing or invalid 'ifconfig_netmask')");

	val = get_ip4_routes ();
	if (val)
		g_variant_builder_add (&ip4builder, "{sv}", NM_VPN_PLUGIN_IP4_CONFIG_ROUTES, val);
	else if (is_restart) {
		g_variant_builder_add (&ip4builder, "{sv}",
		                       NM_VPN_PLUGIN_IP4_CONFIG_PRESERVE_ROUTES,
		                       g_variant_new_boolean (TRUE));
	}

	/* IPv6 address */
	tmp = getenv ("ifconfig_ipv6_local");
	if (tmp && strlen (tmp)) {
		val = addr6_to_gvariant (tmp);
		if (val) {
			g_variant_builder_add (&ip6builder, "{sv}", NM_VPN_PLUGIN_IP6_CONFIG_ADDRESS, val);
			has_ip6_address = TRUE;
		} else
			helper_failed (proxy, "IP6 Address");
	}

	/* IPv6 remote address */
	tmp = getenv ("ifconfig_ipv6_remote");
	if (tmp && strlen (tmp)) {
		val = addr6_to_gvariant (tmp);
		if (val)
			g_variant_builder_add (&ip6builder, "{sv}", NM_VPN_PLUGIN_IP6_CONFIG_PTP, val);
		else
			helper_failed (proxy, "IP6 PTP Address");
	}

	/* IPv6 netbits */
	tmp = getenv ("ifconfig_ipv6_netbits");
	if (tmp && strlen (tmp)) {
		long int netbits;

		errno = 0;
		netbits = strtol (tmp, NULL, 10);
		if (errno || netbits < 0 || netbits > 128) {
			_LOGW ("Ignoring invalid prefix '%s'", tmp);
		} else {
			val = g_variant_new_uint32 ((guint32) netbits);
			g_variant_builder_add (&ip6builder, "{sv}", NM_VPN_PLUGIN_IP6_CONFIG_PREFIX, val);
		}
	}

	val = get_ip6_routes ();
	if (val)
		g_variant_builder_add (&ip6builder, "{sv}", NM_VPN_PLUGIN_IP6_CONFIG_ROUTES, val);
	else if (is_restart) {
		g_variant_builder_add (&ip6builder, "{sv}",
		                       NM_VPN_PLUGIN_IP6_CONFIG_PRESERVE_ROUTES,
		                       g_variant_new_boolean (TRUE));
	}

	/* DNS and WINS servers */
	dns_domains = g_ptr_array_sized_new (3);
	dns4_list = g_ptr_array_new ();
	dns6_list = g_ptr_array_new ();
	nbns_list = g_ptr_array_new ();

	for (i = 1; i < 256; i++) {
		char *env_name;

		env_name = g_strdup_printf ("foreign_option_%d", i);
		tmp = getenv (env_name);
		g_free (env_name);

		if (!tmp || strlen (tmp) < 1)
			break;

		if (!g_str_has_prefix (tmp, "dhcp-option "))
			continue;

		tmp += 12; /* strlen ("dhcp-option ") */

		if (g_str_has_prefix (tmp, "DNS "))
			parse_addr_list (dns4_list, dns6_list, tmp + 4);
		else if (g_str_has_prefix (tmp, "WINS "))
			parse_addr_list (nbns_list, NULL, tmp + 5);
		else if (g_str_has_prefix (tmp, "DOMAIN ") && is_domain_valid (tmp + 7))
			g_ptr_array_add (dns_domains, tmp + 7);
	}

	if (dns4_list->len) {
		val = g_variant_new_array (G_VARIANT_TYPE_UINT32, (GVariant **) dns4_list->pdata, dns4_list->len);
		g_variant_builder_add (&ip4builder, "{sv}", NM_VPN_PLUGIN_IP4_CONFIG_DNS, val);
	}

	if (has_ip6_address && dns6_list->len) {
		val = g_variant_new_array (G_VARIANT_TYPE ("ay"), (GVariant **) dns6_list->pdata, dns6_list->len);
		g_variant_builder_add (&ip6builder, "{sv}", NM_VPN_PLUGIN_IP6_CONFIG_DNS, val);
	}

	if (nbns_list->len) {
		val = g_variant_new_array (G_VARIANT_TYPE_UINT32, (GVariant **) nbns_list->pdata, nbns_list->len);
		g_variant_builder_add (&ip4builder, "{sv}", NM_VPN_PLUGIN_IP4_CONFIG_NBNS, val);
	}

	if (dns_domains->len) {
		val = g_variant_new_strv ((const gchar **) dns_domains->pdata, dns_domains->len);
		g_variant_builder_add (&ip4builder, "{sv}", NM_VPN_PLUGIN_IP4_CONFIG_DOMAINS, val);

		/* Domains apply to both IPv4 and IPv6 configurations */
		if (has_ip6_address) {
			val = g_variant_new_strv ((const gchar **) dns_domains->pdata, dns_domains->len);
			g_variant_builder_add (&ip6builder, "{sv}", NM_VPN_PLUGIN_IP6_CONFIG_DOMAINS, val);
		}
	}

	g_ptr_array_unref (dns4_list);
	g_ptr_array_unref (dns6_list);
	g_ptr_array_unref (nbns_list);
	g_ptr_array_unref (dns_domains);

	/* Tunnel MTU */
	tmp = getenv ("tun_mtu");
	if (tmp && strlen (tmp)) {
		long int mtu;

		errno = 0;
		mtu = strtol (tmp, NULL, 10);
		if (errno || mtu < 0 || mtu > 20000) {
			_LOGW ("Ignoring invalid tunnel MTU '%s'", tmp);
		} else {
			val = g_variant_new_uint32 ((guint32) mtu);
			g_variant_builder_add (&builder, "{sv}", NM_VPN_PLUGIN_CONFIG_MTU, val);
		}
	}

	ip4config = g_variant_builder_end (&ip4builder);

	if (g_variant_n_children (ip4config)) {
		val = g_variant_new_boolean (TRUE);
		g_variant_builder_add (&builder, "{sv}", NM_VPN_PLUGIN_CONFIG_HAS_IP4, val);
	} else {
		g_variant_unref (ip4config);
		ip4config = NULL;
	}

	ip6config = g_variant_builder_end (&ip6builder);

	if (g_variant_n_children (ip6config)) {
		val = g_variant_new_boolean (TRUE);
		g_variant_builder_add (&builder, "{sv}", NM_VPN_PLUGIN_CONFIG_HAS_IP6, val);
	} else {
		g_variant_unref (ip6config);
		ip6config = NULL;
	}

	if (!ip4config && !ip6config)
		helper_failed (proxy, "IPv4 or IPv6 configuration");

	/* Send the config info to nm-openvpn-service */
	send_config (proxy, g_variant_builder_end (&builder), ip4config, ip6config);

	g_object_unref (proxy);

	return 0;
}
示例#13
0
文件: gtk-launch.c 项目: endlessm/gtk
int
main (int argc, char *argv[])
{
  GError *error = NULL;
  GOptionContext *context = NULL;
  gchar *summary;
  gchar *app_name;
#ifdef G_OS_UNIX
  gchar *desktop_file_name;
  gchar *bus_name = NULL;
#endif
  GAppInfo *info = NULL;
  GAppLaunchContext *launch_context;
  GList *l;
  GFile *f;

  setlocale (LC_ALL, "");

#ifdef ENABLE_NLS
  bindtextdomain (GETTEXT_PACKAGE, GTK_LOCALEDIR);
  textdomain (GETTEXT_PACKAGE);
#ifdef HAVE_BIND_TEXTDOMAIN_CODESET
  bind_textdomain_codeset (GETTEXT_PACKAGE, "UTF-8");
#endif
#endif

  /* Translators: this message will appear immediately after the */
  /* usage string - Usage: COMMAND [OPTION...] <THIS_MESSAGE>    */
  context =
    g_option_context_new (_("APPLICATION [URI...] — launch an APPLICATION"));

  /* Translators: this message will appear after the usage string */
  /* and before the list of options.                              */
  summary = _("Launch an application (specified by its desktop file name),\n"
              "optionally passing one or more URIs as arguments.");
  g_option_context_set_summary (context, summary);
  g_option_context_add_main_entries (context, entries, GETTEXT_PACKAGE);
  g_option_context_add_group (context, gtk_get_option_group (FALSE));

  g_option_context_parse (context, &argc, &argv, &error);

  g_option_context_free (context);

  if (error != NULL)
    {
      g_printerr (_("Error parsing commandline options: %s\n"), error->message);
      g_printerr ("\n");
      g_printerr (_("Try \"%s --help\" for more information."), g_get_prgname ());
      g_printerr ("\n");
      g_error_free (error);
      return 1;
    }

  if (show_version)
    {
      g_print ("%d.%d.%d\n",
               gtk_get_major_version (),
               gtk_get_minor_version (),
               gtk_get_micro_version ());
      return 0;
    }

  if (!args)
    {
      /* Translators: the %s is the program name. This error message */
      /* means the user is calling gtk-launch without any argument.  */
      g_printerr (_("%s: missing application name"), g_get_prgname ());
      g_printerr ("\n");
      g_printerr (_("Try \"%s --help\" for more information."), g_get_prgname ());
      g_printerr ("\n");
      return 1;
    }


  gtk_init (&argc, &argv);

  app_name = *args;
#if defined(HAVE_GIO_UNIX) && !defined(__APPLE__)
  bus_name = g_strdup (app_name);
  if (g_str_has_suffix (app_name, ".desktop"))
    {
      desktop_file_name = g_strdup (app_name);
      bus_name[strlen (bus_name) - strlen(".desktop")] = '\0';
    }
  else
    {
      desktop_file_name = g_strconcat (app_name, ".desktop", NULL);
    }

  if (!g_dbus_is_name (bus_name))
    g_clear_pointer (&bus_name, g_free);
  info = G_APP_INFO (g_desktop_app_info_new (desktop_file_name));
  g_free (desktop_file_name);
#else
#warning Please add support for creating AppInfo from id for your OS
  g_printerr (_("Creating AppInfo from id not supported on non unix operating systems"));
#endif
  args++;

  if (!info)
    {
      /* Translators: the first %s is the program name, the second one */
      /* is the application name.                                      */
      g_printerr (_("%s: no such application %s"),
                  g_get_prgname (), app_name);
      g_printerr ("\n");
      return 2;
    }

  l = NULL;
  for (; *args; args++)
    {
      f = g_file_new_for_commandline_arg (*args);
      l = g_list_append (l, f);
    }

  launch_context = (GAppLaunchContext*) gdk_display_get_app_launch_context (gdk_display_get_default ());
  if (!g_app_info_launch (info, l, launch_context, &error))
    {
       /* Translators: the first %s is the program name, the second one  */
       /* is the error message.                                          */
       g_printerr (_("%s: error launching application: %s\n"),
                   g_get_prgname (), error->message);
       return 3;
    }
  g_object_unref (info);
  g_object_unref (launch_context);

#ifdef G_OS_UNIX
  if (bus_name != NULL)
    {
      GDBusConnection *connection;
      gchar *object_path, *p;

      connection = g_bus_get_sync (G_BUS_TYPE_SESSION, NULL, NULL);

      object_path = g_strdup_printf ("/%s", bus_name);
      for (p = object_path; *p != '\0'; p++)
          if (*p == '.')
              *p = '/';

      if (connection)
        g_dbus_connection_call_sync (connection,
                                     bus_name,
                                     object_path,
                                     "org.freedesktop.DBus.Peer",
                                     "Ping",
                                     NULL, NULL,
                                     G_DBUS_CALL_FLAGS_NONE, -1, NULL, NULL);
      g_clear_pointer (&object_path, g_free);
      g_clear_object (&connection);
      g_clear_pointer (&bus_name, g_free);
    }
#endif
  g_list_free_full (l, g_object_unref);

  return 0;
}