static gboolean
g_socketpair (GSocketFamily family, GSocketType type, GSocketProtocol protocol,
    GSocket * gsv[2], GError ** error)
{
  int ret;
  int sv[2];

  ret = socketpair (family, type, protocol, sv);
  if (ret != 0) {
    g_set_error (error, G_IO_ERROR, G_IO_ERROR_FAILED, "socketpair failed: %s",
        g_strerror (errno));
    return FALSE;
  }

  gsv[0] = g_socket_new_from_fd (sv[0], error);
  if (gsv[0] == NULL) {
    close (sv[0]);
    close (sv[1]);
    return FALSE;
  }
  gsv[1] = g_socket_new_from_fd (sv[1], error);
  if (gsv[1] == NULL) {
    g_object_unref (gsv[0]);
    gsv[0] = NULL;
    close (sv[1]);
    return FALSE;
  }
  return TRUE;
}
void WorkQueue::registerEventSourceHandler(int fileDescriptor, int condition, PassOwnPtr<WorkItem> item)
{
    GRefPtr<GSocket> socket = adoptGRef(g_socket_new_from_fd(fileDescriptor, 0));
    ASSERT(socket);
    GRefPtr<GCancellable> cancellable = adoptGRef(g_cancellable_new());
    GRefPtr<GSource> dispatchSource = adoptGRef(g_socket_create_source(socket.get(), static_cast<GIOCondition>(condition), cancellable.get()));
    ASSERT(dispatchSource);
    EventSource* eventSource = new EventSource(item, this, cancellable.get());
    ASSERT(eventSource);

    g_source_set_callback(dispatchSource.get(), reinterpret_cast<GSourceFunc>(&WorkQueue::EventSource::performWork),
        eventSource, reinterpret_cast<GDestroyNotify>(&WorkQueue::EventSource::deleteEventSource));

    // Set up the event sources under the mutex since this is shared across multiple threads.
    {
        MutexLocker locker(m_eventSourcesLock);
        Vector<EventSource*> sources;
        EventSourceIterator it = m_eventSources.find(fileDescriptor);
        if (it != m_eventSources.end()) 
            sources = it->second;

        sources.append(eventSource);
        m_eventSources.set(fileDescriptor, sources);
    }

    g_source_attach(dispatchSource.get(), m_eventContext);
}
Example #3
0
static gboolean
connect_to_peer (int fd)
{
  g_autoptr(GSocketConnection) stream = NULL;
  g_autoptr(GSocket) socket = NULL;
  GError *error = NULL;
  g_autofree gchar *guid = NULL;
  gboolean ret = FALSE;

  socket = g_socket_new_from_fd (fd, &error);
  if (error != NULL)
    {
      g_warning ("Couldn't create socket: %s", error->message);
      goto out;
    }

  stream = g_socket_connection_factory_create_connection (socket);
  if (!stream)
    {
      g_warning ("Couldn't create socket stream");
      goto out;
    }

  guid = g_dbus_generate_guid ();
  g_dbus_connection_new (G_IO_STREAM (stream), guid,
                         G_DBUS_CONNECTION_FLAGS_AUTHENTICATION_SERVER |
                         G_DBUS_CONNECTION_FLAGS_DELAY_MESSAGE_PROCESSING,
                         NULL, NULL, on_peer_acquired, NULL);
  ret = TRUE;

out:
  g_clear_error (&error);
  return ret;
}
Example #4
0
static void
_j4status_io_add_systemd(J4statusIOContext *self)
{
#ifdef ENABLE_SYSTEMD
    gint fds = sd_listen_fds(TRUE);
    if ( fds < 0 )
    {
        g_warning("Failed to acquire systemd sockets: %s", g_strerror(-fds));
        return;
    }
    if ( fds == 0 )
        return;

    gboolean socket_added = FALSE;
    _j4status_io_add_server(self);

    GError *error = NULL;
    gint fd;
    for ( fd = SD_LISTEN_FDS_START ; fd < SD_LISTEN_FDS_START + fds ; ++fd )
    {
        gint r;
        r = sd_is_socket(fd, AF_UNSPEC, SOCK_STREAM, 1);
        if ( r < 0 )
        {
            g_warning("Failed to verify systemd socket type: %s", g_strerror(-r));
            continue;
        }

        if ( r == 0 )
            continue;

        GSocket *socket;
        socket = g_socket_new_from_fd(fd, &error);
        if ( socket == NULL )
        {
            g_warning("Failed to take a socket from systemd: %s", error->message);
            g_clear_error(&error);
            continue;
        }

        if ( ! g_socket_listener_add_socket(G_SOCKET_LISTENER(self->server), socket, NULL, &error) )
        {
            g_warning("Failed to add systemd socket to server: %s", error->message);
            g_clear_error(&error);
            continue;
        }

        socket_added = TRUE;
    }

    if ( ! socket_added )
    {
        g_object_unref(self->server);
        self->server = NULL;
    }
#endif /* ENABLE_SYSTEMD */
}
static gboolean
setup_handles (GSocket ** sinkhandle, GSocket ** srchandle)
{
  GError *error = NULL;
  gint sv[3];


//  g_assert (*sinkhandle);
//  g_assert (*srchandle);

  fail_if (socketpair (PF_UNIX, SOCK_STREAM, 0, sv));

  *sinkhandle = g_socket_new_from_fd (sv[1], &error);
  fail_if (error);
  fail_if (*sinkhandle == NULL);
  *srchandle = g_socket_new_from_fd (sv[0], &error);
  fail_if (error);
  fail_if (*srchandle == NULL);

  return TRUE;
}
/* Create a netlink socket, bind to it and wrap it in a GSocket */
static gboolean
create_netlink_socket (GUPnPLinuxContextManager *self, GError **error)
{
        struct sockaddr_nl sa;
        int fd, status;
        GSocket *sock;
        GError *inner_error;

        inner_error = NULL;

        fd = socket (PF_NETLINK, SOCK_DGRAM, NETLINK_ROUTE);
        if (fd == -1) {
                g_set_error_literal (error,
                                     G_IO_ERROR,
                                     g_io_error_from_errno (errno),
                                     "Failed to bind to netlink socket");
                return FALSE;
        }

        memset (&sa, 0, sizeof (sa));
        sa.nl_family = AF_NETLINK;
        /* Listen for interface changes and IP address changes */
        sa.nl_groups = RTMGRP_LINK | RTMGRP_IPV4_IFADDR;

        status = bind (fd, (struct sockaddr *) &sa, sizeof (sa));
        if (status == -1) {
                g_set_error_literal (error,
                                     G_IO_ERROR,
                                     g_io_error_from_errno (errno),
                                     "Failed to bind to netlink socket");
                close (fd);

                return FALSE;
        }

        sock = g_socket_new_from_fd (fd, &inner_error);
        if (sock == NULL) {
                close (fd);
                g_propagate_prefixed_error (error,
                                            inner_error,
                                            "Failed to create GSocket from "
                                            "netlink socket");

                return FALSE;
        }

        g_socket_set_blocking (sock, FALSE);

        self->priv->netlink_socket = sock;

        return TRUE;
}
bool Connection::open()
{
    int flags = fcntl(m_socketDescriptor, F_GETFL, 0);
    while (fcntl(m_socketDescriptor, F_SETFL, flags | O_NONBLOCK) == -1) {
        if (errno != EINTR) {
            ASSERT_NOT_REACHED();
            return false;
        }
    }

    RefPtr<Connection> protectedThis(this);
    m_isConnected = true;
#if PLATFORM(GTK) || PLATFORM(WPE)
    GRefPtr<GSocket> socket = adoptGRef(g_socket_new_from_fd(m_socketDescriptor, nullptr));
    m_socketMonitor.start(socket.get(), G_IO_IN, m_connectionQueue->runLoop(), [protectedThis] (GIOCondition condition) -> gboolean {
        if (condition & G_IO_HUP || condition & G_IO_ERR || condition & G_IO_NVAL) {
            protectedThis->connectionDidClose();
            return G_SOURCE_REMOVE;
        }

        if (condition & G_IO_IN) {
            protectedThis->readyReadHandler();
            return G_SOURCE_CONTINUE;
        }

        ASSERT_NOT_REACHED();
        return G_SOURCE_REMOVE;
    });
#elif PLATFORM(EFL)
    m_connectionQueue->registerSocketEventHandler(m_socketDescriptor,
        [protectedThis] {
            protectedThis->readyReadHandler();
        });
#endif

    // Schedule a call to readyReadHandler. Data may have arrived before installation of the signal handler.
    m_connectionQueue->dispatch([protectedThis] {
        protectedThis->readyReadHandler();
    });

    return true;
}
Example #8
0
void WorkQueue::registerSocketEventHandler(int fileDescriptor, std::function<void ()> function, std::function<void ()> closeFunction)
{
    GRefPtr<GSocket> socket = adoptGRef(g_socket_new_from_fd(fileDescriptor, 0));
    ref();
    m_socketEventSource.schedule("[WebKit] WorkQueue::SocketEventHandler", [function, closeFunction](GIOCondition condition) {
            if (condition & G_IO_HUP || condition & G_IO_ERR || condition & G_IO_NVAL) {
                closeFunction();
                return GMainLoopSource::Stop;
            }

            if (condition & G_IO_IN) {
                function();
                return GMainLoopSource::Continue;
            }

            ASSERT_NOT_REACHED();
            return GMainLoopSource::Stop;
        }, socket.get(), G_IO_IN,
        [this] { deref(); },
        m_eventContext.get());
}
/* coroutine context */
static void *spice_channel_coroutine(void *data)
{
    SpiceChannel *channel = SPICE_CHANNEL(data);
    spice_channel *c = channel->priv;
    int ret;
    guint verify;

    SPICE_DEBUG("Started background coroutine %p", &c->coroutine);

    if (spice_session_get_client_provided_socket(c->session)) {
        if (c->fd < 0) {
            g_critical("fd not provided!");
            goto cleanup;
        }

	if (!(c->sock = g_socket_new_from_fd(c->fd, NULL))) {
		SPICE_DEBUG("Failed to open socket from fd %d", c->fd);
		return FALSE;
	}

	g_socket_set_blocking(c->sock, FALSE);
        goto connected;
    }

reconnect:
    c->sock = spice_session_channel_open_host(c->session, c->tls);
    if (c->sock == NULL) {
        if (!c->tls) {
            SPICE_DEBUG("connection failed, trying with TLS port");
            c->tls = true; /* FIXME: does that really work with provided fd */
            goto reconnect;
        } else {
            SPICE_DEBUG("Connect error");
            emit_main_context(channel, SPICE_CHANNEL_EVENT, SPICE_CHANNEL_ERROR_CONNECT);
            goto cleanup;
        }
    }

    c->has_error = FALSE;

    if (c->tls) {
        int rc;

        c->ctx = SSL_CTX_new(TLSv1_method());
        if (c->ctx == NULL) {
            g_critical("SSL_CTX_new failed");
            goto cleanup;
        }

        verify = spice_session_get_verify(c->session);
        if (verify &
            (SPICE_SESSION_VERIFY_PUBKEY | SPICE_SESSION_VERIFY_HOSTNAME)) {
            gchar *ca_file;

            g_object_get(c->session, "ca-file", &ca_file, NULL);
            if (ca_file) {
                rc = SSL_CTX_load_verify_locations(c->ctx, ca_file, NULL);
                if (rc != 1)
                    g_warning("loading ca certs from %s failed", ca_file);
                g_free(ca_file);

                if (rc != 1) {
                    if (verify & SPICE_SESSION_VERIFY_PUBKEY) {
                        g_warning("only pubkey active");
                        verify = SPICE_SESSION_VERIFY_PUBKEY;
                    } else
                        goto cleanup;
                }
            }
        }

        c->ssl = SSL_new(c->ctx);
        if (c->ssl == NULL) {
            g_critical("SSL_new failed");
            goto cleanup;
        }
        rc = SSL_set_fd(c->ssl, g_socket_get_fd(c->sock));
        if (rc <= 0) {
            g_critical("SSL_set_fd failed");
            goto cleanup;
        }


        {
            gchar *hostname, *subject;
            guint8 *pubkey;
            guint pubkey_len;

            g_object_get(c->session,
                         "host", &hostname,
                         "cert-subject", &subject, NULL);
            spice_session_get_pubkey(c->session, &pubkey, &pubkey_len);
            c->sslverify = spice_openssl_verify_new(c->ssl, verify,
                                                    hostname,
                                                    (char*)pubkey, pubkey_len,
                                                    subject);
            g_free(hostname);
            g_free(subject);
        }

ssl_reconnect:
        rc = SSL_connect(c->ssl);
        if (rc <= 0) {
            rc = SSL_get_error(c->ssl, rc);
            if (rc == SSL_ERROR_WANT_READ || rc == SSL_ERROR_WANT_WRITE) {
                g_io_wait(c->sock, G_IO_OUT|G_IO_ERR|G_IO_HUP);
                goto ssl_reconnect;
            } else {
                g_warning("%s: SSL_connect: %s",
                          c->name, ERR_error_string(rc, NULL));
                emit_main_context(channel, SPICE_CHANNEL_EVENT, SPICE_CHANNEL_ERROR_TLS);
                goto cleanup;
            }
        }
    }

connected:
    c->state = SPICE_CHANNEL_STATE_LINK_HDR;
    spice_channel_send_link(channel);

    while ((ret = spice_channel_iterate(channel)))
        ;

    /* TODO: improve it, this is a bit hairy, c->coroutine will be
       overwritten on (re)connect, so we skip the normal cleanup
       path. Ideally, we shouldn't use the same channel structure? */
    if (c->state == SPICE_CHANNEL_STATE_CONNECTING) {
        g_object_unref(channel);
        goto end;
    }

cleanup:
    SPICE_DEBUG("Coroutine exit");

    SPICE_CHANNEL_GET_CLASS(channel)->channel_disconnect(channel);

    g_idle_add(spice_channel_delayed_unref, data);


end:
    /* Co-routine exits now - the SpiceChannel object may no longer exist,
       so don't do anything else now unless you like SEGVs */

    exit(1);
    return NULL;
}
Example #10
0
static gboolean
cockpit_web_server_initable_init (GInitable *initable,
                                  GCancellable *cancellable,
                                  GError **error)
{
  CockpitWebServer *server = COCKPIT_WEB_SERVER (initable);
  gboolean ret = FALSE;
  gboolean failed = FALSE;
  int n, fd;

  server->socket_service = g_socket_service_new ();

  n = sd_listen_fds (0);
  if (n > 0)
    {
      /* We got file descriptors passed in, use those. */

      for (fd = SD_LISTEN_FDS_START; fd < SD_LISTEN_FDS_START + n; fd++)
        {
          GSocket *s = NULL;
          gboolean b;
          int type;
          socklen_t l = sizeof (type);

          /*
           * HACK: Workaround g_error() happy code in GSocket
           * https://bugzilla.gnome.org/show_bug.cgi?id=746339
           */
          if (getsockopt (fd, SOL_SOCKET, SO_TYPE, &type, &l) < 0)
            {
              g_set_error (error, G_IO_ERROR, G_IO_ERROR_FAILED,
                           "invalid socket passed via systemd activation: %d: %s", fd, g_strerror (errno));
              goto out;
            }

          s = g_socket_new_from_fd (fd, error);
          if (s == NULL)
            {
              g_prefix_error (error, "Failed to acquire passed socket %i: ", fd);
              goto out;
            }

          b = cockpit_web_server_add_socket (server, s, error);
          g_object_unref (s);

          if (!b)
            {
              g_prefix_error (error, "Failed to add listener for socket %i: ", fd);
              goto out;
            }
        }

      server->socket_activated = TRUE;
    }
  else
    {
      /* No fds passed in, let's listen on our own. */
      if (server->port == 0)
        {
          server->port = g_socket_listener_add_any_inet_port (G_SOCKET_LISTENER (server->socket_service),
                                                              NULL, error);
          failed = (server->port == 0);
        }
      else if (server->port > 0)
        {
          failed = !g_socket_listener_add_inet_port (G_SOCKET_LISTENER (server->socket_service),
                                                     server->port, NULL, error);
        }
      if (failed)
        {
          g_prefix_error (error, "Failed to bind to port %d: ", server->port);
          goto out;
        }
    }

  g_signal_connect (server->socket_service,
                    "incoming",
                    G_CALLBACK (on_incoming),
                    server);

  ret = TRUE;

out:
  return ret;
}
static gboolean
g_network_monitor_netlink_initable_init (GInitable     *initable,
                                         GCancellable  *cancellable,
                                         GError       **error)
{
  GNetworkMonitorNetlink *nl = G_NETWORK_MONITOR_NETLINK (initable);
  gint sockfd, val;
  struct sockaddr_nl snl;

  /* We create the socket the old-school way because sockaddr_netlink
   * can't be represented as a GSocketAddress
   */
  sockfd = socket (PF_NETLINK, SOCK_RAW, NETLINK_ROUTE);
  if (sockfd == -1)
    {
      int errsv = errno;
      g_set_error (error, G_IO_ERROR, g_io_error_from_errno (errsv),
                   _("Could not create network monitor: %s"),
                   g_strerror (errno));
      return FALSE;
    }

  snl.nl_family = AF_NETLINK;
  snl.nl_pid = snl.nl_pad = 0;
  snl.nl_groups = RTMGRP_IPV4_ROUTE | RTMGRP_IPV6_ROUTE;
  if (bind (sockfd, (struct sockaddr *)&snl, sizeof (snl)) != 0)
    {
      int errsv = errno;
      g_set_error (error, G_IO_ERROR, g_io_error_from_errno (errsv),
                   _("Could not create network monitor: %s"),
                   g_strerror (errno));
      close (sockfd);
      return FALSE;
    }

  val = 1;
  if (setsockopt (sockfd, SOL_SOCKET, SO_PASSCRED, &val, sizeof (val)) != 0)
    {
      int errsv = errno;
      g_set_error (error, G_IO_ERROR, g_io_error_from_errno (errsv),
                   _("Could not create network monitor: %s"),
                   g_strerror (errno));
      close (sockfd);
      return FALSE;
    }

  nl->priv->sock = g_socket_new_from_fd (sockfd, error);
  if (error)
    {
      g_prefix_error (error, "%s", _("Could not create network monitor: "));
      close (sockfd);
      return FALSE;
    }

  /* Request the current state */
  if (!request_dump (nl, error))
    return FALSE;

  /* And read responses; since we haven't yet marked the socket
   * non-blocking, each call will block until a message is received.
   */
  while (nl->priv->dump_networks)
    {
      if (!read_netlink_messages (NULL, G_IO_IN, nl))
        break;
    }

  g_socket_set_blocking (nl->priv->sock, FALSE);
  nl->priv->source = g_socket_create_source (nl->priv->sock, G_IO_IN, NULL);
  g_source_set_callback (nl->priv->source,
                         (GSourceFunc) read_netlink_messages, nl, NULL);
  g_source_attach (nl->priv->source,
                   g_main_context_get_thread_default ());

  return TRUE;
}
Example #12
0
static gboolean
cockpit_web_server_initable_init (GInitable *initable,
                                  GCancellable *cancellable,
                                  GError **error)
{
  CockpitWebServer *server = COCKPIT_WEB_SERVER (initable);
  gboolean ret = FALSE;
  gboolean failed;
  int n, fd;

  server->socket_service = g_socket_service_new ();

  n = sd_listen_fds (0);
  if (n > 0)
    {
      /* We got file descriptors passed in, use those. */

      for (fd = SD_LISTEN_FDS_START; fd < SD_LISTEN_FDS_START + n; fd++)
        {
          GSocket *s = NULL;
          gboolean b;

          s = g_socket_new_from_fd (fd, error);
          if (s == NULL)
            {
              g_prefix_error (error, "Failed to acquire passed socket %i: ", fd);
              goto out;
            }

          b = g_socket_listener_add_socket (G_SOCKET_LISTENER (server->socket_service),
                                            s,
                                            NULL,
                                            error);

          g_object_unref (s);

          if (!b)
            {
              g_prefix_error (error, "Failed to add listener for socket %i: ", fd);
              goto out;
            }
        }

      server->socket_activated = TRUE;
    }
  else
    {
      /* No fds passed in, let's listen on our own. */
      if (server->port == 0)
        {
          server->port = g_socket_listener_add_any_inet_port (G_SOCKET_LISTENER (server->socket_service),
                                                              NULL, error);
          failed = (server->port == 0);
        }
      else
        {
          failed = !g_socket_listener_add_inet_port (G_SOCKET_LISTENER (server->socket_service),
                                                     server->port, NULL, error);
        }
      if (failed)
        {
          g_prefix_error (error, "Failed to bind to port %d: ", server->port);
          goto out;
        }
    }

  g_signal_connect (server->socket_service,
                    "incoming",
                    G_CALLBACK (on_incoming),
                    server);

  ret = TRUE;

out:
  return ret;
}
static GDBusConnection*
get_connection_for_path (gchar *sysroot,
                         gboolean force_peer,
                         GPid *out_peer_pid,
                         GCancellable *cancellable,
                         GError **error)
{
  glnx_unref_object GDBusConnection *connection = NULL;
  glnx_unref_object GSocketConnection *stream = NULL;
  glnx_unref_object GSocket *socket = NULL;
  _cleanup_peer_ GPid peer_pid = 0;

  gchar buffer[16];

  int pair[2];

  const gchar *args[] = {
    "rpm-ostree",
    "start-daemon",
    "--sysroot", sysroot,
    "--dbus-peer", buffer,
    NULL
  };

  /* This is only intended for use by installed tests.
   * Note that it disregards the 'sysroot' and 'force_peer' options
   * and assumes the service activation command has been configured
   * to use the desired system root path. */
  if (g_getenv ("RPMOSTREE_USE_SESSION_BUS") != NULL)
    {
      if (sysroot != NULL)
        g_warning ("RPMOSTREE_USE_SESSION_BUS set, ignoring --sysroot=%s", sysroot);

      /* NB: as opposed to other early returns, this is _also_ a happy path */
      GDBusConnection *ret = g_bus_get_sync (G_BUS_TYPE_SESSION, cancellable, error);
      if (!ret)
        return glnx_prefix_error_null (error, "Connecting to session bus");
      return ret;
    }

  if (sysroot == NULL)
    sysroot = "/";

  if (g_strcmp0 ("/", sysroot) == 0 && force_peer == FALSE)
    {
      /* NB: as opposed to other early returns, this is _also_ a happy path */
      GDBusConnection *ret = g_bus_get_sync (G_BUS_TYPE_SYSTEM, cancellable, error);
      if (!ret)
        return glnx_prefix_error_null (error, "Connecting to system bus");
      return ret;
    }

  g_print ("Running in single user mode. Be sure no other users are modifying the system\n");
  if (socketpair (AF_UNIX, SOCK_STREAM, 0, pair) < 0)
    return glnx_null_throw_errno_prefix (error, "couldn't create socket pair");

  g_snprintf (buffer, sizeof (buffer), "%d", pair[1]);

  socket = g_socket_new_from_fd (pair[0], error);
  if (socket == NULL)
    {
      close (pair[0]);
      close (pair[1]);
      return NULL;
    }

  if (!g_spawn_async (NULL, (gchar **)args, NULL,
                      G_SPAWN_LEAVE_DESCRIPTORS_OPEN | G_SPAWN_DO_NOT_REAP_CHILD,
                      NULL, NULL, &peer_pid, error))
    {
      close (pair[1]);
      return NULL;
    }

  stream = g_socket_connection_factory_create_connection (socket);
  connection = g_dbus_connection_new_sync (G_IO_STREAM (stream), NULL,
                                           G_DBUS_CONNECTION_FLAGS_AUTHENTICATION_CLIENT,
                                           NULL, cancellable, error);
  if (!connection)
    return NULL;

  *out_peer_pid = peer_pid; peer_pid = 0;
  return connection;
}
Example #14
0
int init_netlink(GMainLoop *loop) {
	GSocket *gsocket = NULL;
	int socket_fd = 0;
	GSource *source;
	struct sockaddr_nl my_nla;
	struct nlmsghdr *nl_hdr;
	char buff[BUFF_SIZE];
	struct cn_msg *cn_hdr;
	enum proc_cn_mcast_op *mcop_msg;


	/* create socket */
	/*
	 * Create an endpoint for communication. Use the kernel user
	 * interface device (PF_NETLINK) which is a datagram oriented
	 * service (SOCK_DGRAM). The protocol used is the connector
	 * protocol (NETLINK_CONNECTOR)
	 */
	socket_fd = socket(PF_NETLINK, SOCK_DGRAM, NETLINK_CONNECTOR);

	if (socket_fd == -1) {
		g_warning ("netlink: failed to create socket: %s", g_strerror(errno));
		return 1;
	}

	my_nla.nl_family = AF_NETLINK;
	my_nla.nl_groups = CN_IDX_PROC;
	my_nla.nl_pid = getpid();
	my_nla.nl_pad = 0;

	if (bind(socket_fd, (struct sockaddr *)&my_nla, sizeof(my_nla)) < 0) {
		g_warning("netlink: binding sk_nl error: %s\n", g_strerror(errno));
		g_warning("netlink: realtime monitoring disabled. compile kernel with PROC_EVENTS enabled");
		goto out;
	}

	gsocket = g_socket_new_from_fd(socket_fd, NULL);
	if(gsocket == NULL) {
		g_warning("netlink: can't create socket");
		goto out;
	}

	nl_hdr = (struct nlmsghdr *)buff;
	cn_hdr = (struct cn_msg *)NLMSG_DATA(nl_hdr);
	mcop_msg = (enum proc_cn_mcast_op*)&cn_hdr->data[0];
	g_debug("netlink: sending proc connector: PROC_CN_MCAST_LISTEN... ");
	memset(buff, 0, sizeof(buff));
	*mcop_msg = PROC_CN_MCAST_LISTEN;

	/* test if PROC_CN_MCAST_LISTEN will success */
	netlink_proc_listening = FALSE;
	g_socket_set_timeout(gsocket, 10);

	/* fill the netlink header */
	nl_hdr->nlmsg_len = SEND_MESSAGE_LEN;
	nl_hdr->nlmsg_type = NLMSG_DONE;
	nl_hdr->nlmsg_flags = 0;
	nl_hdr->nlmsg_seq = 0;
	nl_hdr->nlmsg_pid = getpid();

	/* fill the connector header */
	cn_hdr->id.idx = CN_IDX_PROC;
	cn_hdr->id.val = CN_VAL_PROC;
	cn_hdr->seq = 0;
	cn_hdr->ack = 0;
	cn_hdr->len = sizeof(enum proc_cn_mcast_op);
	g_debug("netlink: sending netlink message len=%d, cn_msg len=%d\n",
		nl_hdr->nlmsg_len, (int) sizeof(struct cn_msg));
	if (send(socket_fd, nl_hdr, nl_hdr->nlmsg_len, 0) != nl_hdr->nlmsg_len) {
		g_warning("netlink: failed to send proc connector mcast ctl op!: %s\n",
			g_strerror(errno));
	}
	g_debug("sent\n");

	/* socket has data */
	source = g_socket_create_source (gsocket, G_IO_IN | G_IO_ERR | G_IO_HUP | G_IO_NVAL, NULL);
	g_source_set_callback (source, (GSourceFunc) nl_connection_handler, loop, NULL);
	g_source_attach (source, NULL);

	return 0;
out:
	return 1;

}