Back to index

lightdm  1.3.2
Classes | Defines | Enumerations | Functions | Variables
xdmcp-client.c File Reference
#include <stdlib.h>
#include <stdio.h>
#include <string.h>
#include <errno.h>
#include <sys/types.h>
#include <sys/socket.h>
#include <gio/gio.h>
#include "x-common.h"
#include "xdmcp-client.h"

Go to the source code of this file.

Classes

struct  XDMCPClientPrivate

Defines

#define MAXIMUM_REQUEST_LENGTH   65535

Enumerations

enum  XDMCPOpcode {
  XDMCP_BroadcastQuery = 1, XDMCP_Query = 2, XDMCP_IndirectQuery = 3, XDMCP_ForwardQuery = 4,
  XDMCP_Willing = 5, XDMCP_Unwilling = 6, XDMCP_Request = 7, XDMCP_Accept = 8,
  XDMCP_Decline = 9, XDMCP_Manage = 10, XDMCP_Refuse = 11, XDMCP_Failed = 12,
  XDMCP_KeepAlive = 13, XDMCP_Alive = 14, XDMCP_BroadcastQuery = 1, XDMCP_Query = 2,
  XDMCP_IndirectQuery = 3, XDMCP_ForwardQuery = 4, XDMCP_Willing = 5, XDMCP_Unwilling = 6,
  XDMCP_Request = 7, XDMCP_Accept = 8, XDMCP_Decline = 9, XDMCP_Manage = 10,
  XDMCP_Refuse = 11, XDMCP_Failed = 12, XDMCP_KeepAlive = 13, XDMCP_Alive = 14
}
enum  {
  XDMCP_CLIENT_QUERY, XDMCP_CLIENT_WILLING, XDMCP_CLIENT_ACCEPT, XDMCP_CLIENT_DECLINE,
  XDMCP_CLIENT_FAILED, XDMCP_CLIENT_LAST_SIGNAL
}

Functions

 G_DEFINE_TYPE (XDMCPClient, xdmcp_client, G_TYPE_OBJECT)
static void xdmcp_write (XDMCPClient *client, const guint8 *buffer, gssize buffer_length)
static void decode_willing (XDMCPClient *client, const guint8 *buffer, gssize buffer_length)
static void decode_accept (XDMCPClient *client, const guint8 *buffer, gssize buffer_length)
static void decode_decline (XDMCPClient *client, const guint8 *buffer, gssize buffer_length)
static void decode_failed (XDMCPClient *client, const guint8 *buffer, gssize buffer_length)
static gboolean xdmcp_data_cb (GIOChannel *channel, GIOCondition condition, gpointer data)
static gboolean xdmcp_query_cb (gpointer data)
XDMCPClientxdmcp_client_new (void)
void xdmcp_client_set_hostname (XDMCPClient *client, const gchar *hostname)
void xdmcp_client_set_port (XDMCPClient *client, guint16 port)
gboolean xdmcp_client_start (XDMCPClient *client)
GInetAddress * xdmcp_client_get_local_address (XDMCPClient *client)
static void xdmcp_client_init (XDMCPClient *client)
void xdmcp_client_send_query (XDMCPClient *client)
void xdmcp_client_send_request (XDMCPClient *client, guint16 display_number, GInetAddress **addresses, const gchar *authentication_name, const guint8 *authentication_data, guint16 authentication_data_length, gchar **authorization_names, const gchar *mfid)
void xdmcp_client_send_manage (XDMCPClient *client, guint32 session_id, guint16 display_number, gchar *display_class)
static void xdmcp_client_finalize (GObject *object)
static void xdmcp_client_class_init (XDMCPClientClass *klass)

Variables

static guint xdmcp_client_signals [XDMCP_CLIENT_LAST_SIGNAL] = { 0 }

Class Documentation

struct XDMCPClientPrivate

Definition at line 34 of file xdmcp-client.c.

Class Members
guint8 * authorization_data
gint authorization_data_length
gchar * authorization_name
gchar * host
gint port
guint query_timer
GSocket * socket

Define Documentation

#define MAXIMUM_REQUEST_LENGTH   65535

Definition at line 14 of file xdmcp-client.c.


Enumeration Type Documentation

anonymous enum
Enumerator:
XDMCP_CLIENT_QUERY 
XDMCP_CLIENT_WILLING 
XDMCP_CLIENT_ACCEPT 
XDMCP_CLIENT_DECLINE 
XDMCP_CLIENT_FAILED 
XDMCP_CLIENT_LAST_SIGNAL 

Definition at line 45 of file xdmcp-client.c.

Enumerator:
XDMCP_BroadcastQuery 
XDMCP_Query 
XDMCP_IndirectQuery 
XDMCP_ForwardQuery 
XDMCP_Willing 
XDMCP_Unwilling 
XDMCP_Request 
XDMCP_Accept 
XDMCP_Decline 
XDMCP_Manage 
XDMCP_Refuse 
XDMCP_Failed 
XDMCP_KeepAlive 
XDMCP_Alive 
XDMCP_BroadcastQuery 
XDMCP_Query 
XDMCP_IndirectQuery 
XDMCP_ForwardQuery 
XDMCP_Willing 
XDMCP_Unwilling 
XDMCP_Request 
XDMCP_Accept 
XDMCP_Decline 
XDMCP_Manage 
XDMCP_Refuse 
XDMCP_Failed 
XDMCP_KeepAlive 
XDMCP_Alive 

Definition at line 16 of file xdmcp-client.c.


Function Documentation

static void decode_accept ( XDMCPClient client,
const guint8 *  buffer,
gssize  buffer_length 
) [static]

Definition at line 104 of file xdmcp-client.c.

{
    XDMCPAccept *message;
    gsize offset = 0;
    guint16 length;

    message = g_malloc (sizeof (XDMCPAccept));

    message->session_id = read_card32 (buffer, buffer_length, X_BYTE_ORDER_MSB, &offset);
    length = read_card16 (buffer, buffer_length, X_BYTE_ORDER_MSB, &offset);
    message->authentication_name = read_string (buffer, buffer_length, length, &offset);
    length = read_card16 (buffer, buffer_length, X_BYTE_ORDER_MSB, &offset);
    read_string8 (buffer, buffer_length, length, &offset);
    length = read_card16 (buffer, buffer_length, X_BYTE_ORDER_MSB, &offset);
    message->authorization_name = read_string (buffer, buffer_length, length, &offset);
    message->authorization_data_length = read_card16 (buffer, buffer_length, X_BYTE_ORDER_MSB, &offset);
    message->authorization_data = read_string8 (buffer, buffer_length, length, &offset);

    g_signal_emit (client, xdmcp_client_signals[XDMCP_CLIENT_ACCEPT], 0, message);

    g_free (message->authentication_name);
    g_free (message->authorization_name);
    g_free (message->authorization_data);
    g_free (message);
}

Here is the call graph for this function:

Here is the caller graph for this function:

static void decode_decline ( XDMCPClient client,
const guint8 *  buffer,
gssize  buffer_length 
) [static]

Definition at line 131 of file xdmcp-client.c.

{
    XDMCPDecline *message;
    gsize offset = 0;
    guint16 length;
  
    message = g_malloc0 (sizeof (XDMCPDecline));

    length = read_card16 (buffer, buffer_length, X_BYTE_ORDER_MSB, &offset);
    message->status = read_string (buffer, buffer_length, length, &offset);
    length = read_card16 (buffer, buffer_length, X_BYTE_ORDER_MSB, &offset);
    message->authentication_name = read_string (buffer, buffer_length, length, &offset);
    length = read_card16 (buffer, buffer_length, X_BYTE_ORDER_MSB, &offset);
    read_string8 (buffer, buffer_length, length, &offset);
  
    g_signal_emit (client, xdmcp_client_signals[XDMCP_CLIENT_DECLINE], 0, message);

    g_free (message->status);
    g_free (message->authentication_name);
    g_free (message);
}

Here is the call graph for this function:

Here is the caller graph for this function:

static void decode_failed ( XDMCPClient client,
const guint8 *  buffer,
gssize  buffer_length 
) [static]

Definition at line 154 of file xdmcp-client.c.

{
    XDMCPFailed *message;
    gsize offset = 0;
    guint16 length;

    message = g_malloc0 (sizeof (XDMCPFailed));

    message->session_id = read_card32 (buffer, buffer_length, X_BYTE_ORDER_MSB, &offset);
    length = read_card16 (buffer, buffer_length, X_BYTE_ORDER_MSB, &offset);
    message->status = read_string (buffer, buffer_length, length, &offset);

    g_signal_emit (client, xdmcp_client_signals[XDMCP_CLIENT_FAILED], 0, message);

    g_free (message->status);
    g_free (message);
}

Here is the call graph for this function:

Here is the caller graph for this function:

static void decode_willing ( XDMCPClient client,
const guint8 *  buffer,
gssize  buffer_length 
) [static]

Definition at line 70 of file xdmcp-client.c.

{
    XDMCPWilling *message;
    gsize offset = 0;
    guint16 length;

    if (client->priv->query_timer == 0)
    {
        g_debug ("Ignoring XDMCP unrequested/duplicate Willing");
        return;
    }

    /* Stop sending queries */
    g_source_remove (client->priv->query_timer);
    client->priv->query_timer = 0;
  
    message = g_malloc0 (sizeof (XDMCPWilling));

    length = read_card16 (buffer, buffer_length, X_BYTE_ORDER_MSB, &offset);
    message->authentication_name = read_string (buffer, buffer_length, length, &offset);
    length = read_card16 (buffer, buffer_length, X_BYTE_ORDER_MSB, &offset);
    message->hostname = read_string (buffer, buffer_length, length, &offset);
    length = read_card16 (buffer, buffer_length, X_BYTE_ORDER_MSB, &offset);
    message->status = read_string (buffer, buffer_length, length, &offset);

    g_signal_emit (client, xdmcp_client_signals[XDMCP_CLIENT_WILLING], 0, message);
  
    g_free (message->authentication_name);
    g_free (message->hostname);
    g_free (message->status);
    g_free (message);
}

Here is the call graph for this function:

Here is the caller graph for this function:

G_DEFINE_TYPE ( XDMCPClient  ,
xdmcp_client  ,
G_TYPE_OBJECT   
)
static void xdmcp_client_class_init ( XDMCPClientClass klass) [static]

Definition at line 411 of file xdmcp-client.c.

{
    GObjectClass *object_class = G_OBJECT_CLASS (klass);
    object_class->finalize = xdmcp_client_finalize;
    g_type_class_add_private (klass, sizeof (XDMCPClientPrivate));
    xdmcp_client_signals[XDMCP_CLIENT_QUERY] =
        g_signal_new ("query",
                      G_TYPE_FROM_CLASS (klass),
                      G_SIGNAL_RUN_LAST,
                      G_STRUCT_OFFSET (XDMCPClientClass, query),
                      NULL, NULL,
                      g_cclosure_marshal_VOID__VOID,
                      G_TYPE_NONE, 0);
    xdmcp_client_signals[XDMCP_CLIENT_WILLING] =
        g_signal_new ("willing",
                      G_TYPE_FROM_CLASS (klass),
                      G_SIGNAL_RUN_LAST,
                      G_STRUCT_OFFSET (XDMCPClientClass, willing),
                      NULL, NULL,
                      g_cclosure_marshal_VOID__POINTER,
                      G_TYPE_NONE, 1, G_TYPE_POINTER);
    xdmcp_client_signals[XDMCP_CLIENT_ACCEPT] =
        g_signal_new ("accept",
                      G_TYPE_FROM_CLASS (klass),
                      G_SIGNAL_RUN_LAST,
                      G_STRUCT_OFFSET (XDMCPClientClass, accept),
                      NULL, NULL,
                      g_cclosure_marshal_VOID__POINTER,
                      G_TYPE_NONE, 1, G_TYPE_POINTER);
    xdmcp_client_signals[XDMCP_CLIENT_DECLINE] =
        g_signal_new ("decline",
                      G_TYPE_FROM_CLASS (klass),
                      G_SIGNAL_RUN_LAST,
                      G_STRUCT_OFFSET (XDMCPClientClass, decline),
                      NULL, NULL,
                      g_cclosure_marshal_VOID__POINTER,
                      G_TYPE_NONE, 1, G_TYPE_POINTER);
    xdmcp_client_signals[XDMCP_CLIENT_FAILED] =
        g_signal_new ("failed",
                      G_TYPE_FROM_CLASS (klass),
                      G_SIGNAL_RUN_LAST,
                      G_STRUCT_OFFSET (XDMCPClientClass, failed),
                      NULL, NULL,
                      g_cclosure_marshal_VOID__POINTER,
                      G_TYPE_NONE, 1, G_TYPE_POINTER);
}

Here is the call graph for this function:

static void xdmcp_client_finalize ( GObject *  object) [static]

Definition at line 400 of file xdmcp-client.c.

{
    XDMCPClient *client = (XDMCPClient *) object;
    g_free (client->priv->host);
    if (client->priv->socket)
        g_object_unref (client->priv->socket);
    g_free (client->priv->authorization_name);
    g_free (client->priv->authorization_data);
}

Here is the caller graph for this function:

GInetAddress* xdmcp_client_get_local_address ( XDMCPClient client)

Definition at line 288 of file xdmcp-client.c.

{
    GSocketAddress *socket_address;
  
    if (!client->priv->socket)
        return NULL;

    socket_address = g_socket_get_local_address (client->priv->socket, NULL);
    return g_inet_socket_address_get_address (G_INET_SOCKET_ADDRESS (socket_address));
}

Here is the caller graph for this function:

static void xdmcp_client_init ( XDMCPClient client) [static]

Definition at line 300 of file xdmcp-client.c.

{
    client->priv = G_TYPE_INSTANCE_GET_PRIVATE (client, xdmcp_client_get_type (), XDMCPClientPrivate);
    client->priv->port = XDMCP_PORT;
}

Here is the call graph for this function:

Definition at line 243 of file xdmcp-client.c.

{
    return g_object_new (xdmcp_client_get_type (), NULL);
}

Here is the call graph for this function:

Here is the caller graph for this function:

void xdmcp_client_send_manage ( XDMCPClient client,
guint32  session_id,
guint16  display_number,
gchar *  display_class 
)

Definition at line 382 of file xdmcp-client.c.

{
    guint8 buffer[MAXIMUM_REQUEST_LENGTH];
    gsize offset = 0;

    write_card16 (buffer, MAXIMUM_REQUEST_LENGTH, X_BYTE_ORDER_MSB, XDMCP_VERSION, &offset);
    write_card16 (buffer, MAXIMUM_REQUEST_LENGTH, X_BYTE_ORDER_MSB, XDMCP_Manage, &offset);
    write_card16 (buffer, MAXIMUM_REQUEST_LENGTH, X_BYTE_ORDER_MSB, 8 + strlen (display_class), &offset);

    write_card32 (buffer, MAXIMUM_REQUEST_LENGTH, X_BYTE_ORDER_MSB, session_id, &offset);
    write_card16 (buffer, MAXIMUM_REQUEST_LENGTH, X_BYTE_ORDER_MSB, display_number, &offset);
    write_card16 (buffer, MAXIMUM_REQUEST_LENGTH, X_BYTE_ORDER_MSB, strlen (display_class), &offset);
    write_string (buffer, MAXIMUM_REQUEST_LENGTH, display_class, &offset);

    xdmcp_write (client, buffer, offset); 
}

Here is the call graph for this function:

Here is the caller graph for this function:

Definition at line 307 of file xdmcp-client.c.

{
    guint8 buffer[MAXIMUM_REQUEST_LENGTH];
    gsize offset = 0;

    write_card16 (buffer, MAXIMUM_REQUEST_LENGTH, X_BYTE_ORDER_MSB, XDMCP_VERSION, &offset);
    write_card16 (buffer, MAXIMUM_REQUEST_LENGTH, X_BYTE_ORDER_MSB, XDMCP_Query, &offset);
    write_card16 (buffer, MAXIMUM_REQUEST_LENGTH, X_BYTE_ORDER_MSB, 1, &offset);
    write_card8 (buffer, MAXIMUM_REQUEST_LENGTH, 0, &offset);

    xdmcp_write (client, buffer, offset);   
}

Here is the call graph for this function:

Here is the caller graph for this function:

void xdmcp_client_send_request ( XDMCPClient client,
guint16  display_number,
GInetAddress **  addresses,
const gchar *  authentication_name,
const guint8 *  authentication_data,
guint16  authentication_data_length,
gchar **  authorization_names,
const gchar *  mfid 
)

Definition at line 321 of file xdmcp-client.c.

{
    guint8 buffer[MAXIMUM_REQUEST_LENGTH];
    gsize length = 0, offset = 0, n_addresses = 0, n_names = 0;
    GInetAddress **address;
    gchar **name;

    length = 11 + strlen (authentication_name) + authentication_data_length + strlen (mfid);
    for (address = addresses; *address; address++)
    {
        gssize native_address_length = g_inet_address_get_native_size (*address);
        length += 4 + native_address_length;
        n_addresses++;
    }
    for (name = authorization_names; *name; name++)
    {
        length += 2 + strlen (*name);
        n_names++;
    }

    write_card16 (buffer, MAXIMUM_REQUEST_LENGTH, X_BYTE_ORDER_MSB, XDMCP_VERSION, &offset);
    write_card16 (buffer, MAXIMUM_REQUEST_LENGTH, X_BYTE_ORDER_MSB, XDMCP_Request, &offset);
    write_card16 (buffer, MAXIMUM_REQUEST_LENGTH, X_BYTE_ORDER_MSB, length, &offset);

    write_card16 (buffer, MAXIMUM_REQUEST_LENGTH, X_BYTE_ORDER_MSB, display_number, &offset);
    write_card8 (buffer, MAXIMUM_REQUEST_LENGTH, n_addresses, &offset);
    for (address = addresses; *address; address++)
        write_card16 (buffer, MAXIMUM_REQUEST_LENGTH, X_BYTE_ORDER_MSB, 0, &offset); /* FamilyInternet */
    write_card8 (buffer, MAXIMUM_REQUEST_LENGTH, n_addresses, &offset);
    for (address = addresses; *address; address++)
    {
        gssize native_address_length;
        const guint8 *native_address;

        native_address_length = g_inet_address_get_native_size (*address);
        native_address = g_inet_address_to_bytes (*address);
        write_card16 (buffer, MAXIMUM_REQUEST_LENGTH, X_BYTE_ORDER_MSB, native_address_length, &offset);
        write_string8 (buffer, MAXIMUM_REQUEST_LENGTH, native_address, native_address_length, &offset);
    }
    write_card16 (buffer, MAXIMUM_REQUEST_LENGTH, X_BYTE_ORDER_MSB, strlen (authentication_name), &offset);
    write_string (buffer, MAXIMUM_REQUEST_LENGTH, authentication_name, &offset);
    write_card16 (buffer, MAXIMUM_REQUEST_LENGTH, X_BYTE_ORDER_MSB, authentication_data_length, &offset);
    write_string8 (buffer, MAXIMUM_REQUEST_LENGTH, authentication_data, authentication_data_length, &offset);
    write_card8 (buffer, MAXIMUM_REQUEST_LENGTH, n_names, &offset);
    for (name = authorization_names; *name; name++)
    {
        write_card16 (buffer, MAXIMUM_REQUEST_LENGTH, X_BYTE_ORDER_MSB, strlen (*name), &offset);
        write_string (buffer, MAXIMUM_REQUEST_LENGTH, *name, &offset);
    }
    write_card16 (buffer, MAXIMUM_REQUEST_LENGTH, X_BYTE_ORDER_MSB, strlen (mfid), &offset);
    write_string (buffer, MAXIMUM_REQUEST_LENGTH, mfid, &offset);

    xdmcp_write (client, buffer, offset);
}

Here is the call graph for this function:

Here is the caller graph for this function:

void xdmcp_client_set_hostname ( XDMCPClient client,
const gchar *  hostname 
)

Definition at line 249 of file xdmcp-client.c.

{
    g_free (client->priv->host);
    client->priv->host = g_strdup (hostname);
}

Here is the caller graph for this function:

void xdmcp_client_set_port ( XDMCPClient client,
guint16  port 
)

Definition at line 256 of file xdmcp-client.c.

{
    client->priv->port = port;
}

Here is the caller graph for this function:

gboolean xdmcp_client_start ( XDMCPClient client)

Definition at line 262 of file xdmcp-client.c.

{
    GSocketConnectable *address;
    GSocketAddress *socket_address;
    GError *error = NULL;

    client->priv->socket = g_socket_new (G_SOCKET_FAMILY_IPV4, G_SOCKET_TYPE_DATAGRAM, G_SOCKET_PROTOCOL_UDP, &error);

    address = g_network_address_new (client->priv->host, client->priv->port);
    socket_address = g_socket_address_enumerator_next (g_socket_connectable_enumerate (address), NULL, NULL);
  
    if (!client->priv->socket ||
        !g_socket_connect (client->priv->socket, socket_address, NULL, &error) ||
        !g_io_add_watch (g_io_channel_unix_new (g_socket_get_fd (client->priv->socket)), G_IO_IN, xdmcp_data_cb, client))
    {
        g_warning ("Error creating XDMCP socket: %s", error->message);
        return FALSE;
    }

    client->priv->query_timer = g_timeout_add (2000, xdmcp_query_cb, client);
    xdmcp_query_cb (client); 

    return TRUE;
}

Here is the call graph for this function:

Here is the caller graph for this function:

static gboolean xdmcp_data_cb ( GIOChannel *  channel,
GIOCondition  condition,
gpointer  data 
) [static]

Definition at line 173 of file xdmcp-client.c.

{
    XDMCPClient *client = data;
    guint8 buffer[MAXIMUM_REQUEST_LENGTH];
    gssize n_read;

    n_read = recv (g_io_channel_unix_get_fd (channel), buffer, MAXIMUM_REQUEST_LENGTH, 0);
    if (n_read < 0)
        g_warning ("Error reading from XDMCP socket: %s", strerror (errno));
    else if (n_read == 0)
    {
        g_debug ("EOF");
        return FALSE;
    }
    else
    {
        gsize offset = 0;
        guint16 version, opcode, length;

        version = read_card16 (buffer, n_read, X_BYTE_ORDER_MSB, &offset);
        opcode = read_card16 (buffer, n_read, X_BYTE_ORDER_MSB, &offset);
        length = read_card16 (buffer, n_read, X_BYTE_ORDER_MSB, &offset);

        if (version != 1)
        {
            g_debug ("Ignoring XDMCP version %d message", version);
            return TRUE;
        }
        if (6 + length > n_read)
        {
            g_debug ("Ignoring XDMCP message of length %zi with invalid length field %d", n_read, length);
            return TRUE;
        }
        switch (opcode)
        {
        case XDMCP_Willing:
            decode_willing (client, buffer + offset, n_read - offset);
            break;

        case XDMCP_Accept:
            decode_accept (client, buffer + offset, n_read - offset);
            break;

        case XDMCP_Decline:
            decode_decline (client, buffer + offset, n_read - offset);
            break;

        case XDMCP_Failed:
            decode_failed (client, buffer + offset, n_read - offset);
            break;

        default:
            g_debug ("Ignoring unknown XDMCP opcode %d", opcode);
            break;
        }
    }

    return TRUE;
}

Here is the call graph for this function:

Here is the caller graph for this function:

static gboolean xdmcp_query_cb ( gpointer  data) [static]

Definition at line 234 of file xdmcp-client.c.

{
    XDMCPClient *client = data;
    g_signal_emit (client, xdmcp_client_signals[XDMCP_CLIENT_QUERY], 0);
    xdmcp_client_send_query (client);
    return TRUE;
}

Here is the call graph for this function:

Here is the caller graph for this function:

static void xdmcp_write ( XDMCPClient client,
const guint8 *  buffer,
gssize  buffer_length 
) [static]

Definition at line 56 of file xdmcp-client.c.

{
    gssize n_written;
    GError *error = NULL;

    n_written = g_socket_send (client->priv->socket, (const gchar *) buffer, buffer_length, NULL, &error);
    if (n_written < 0)
        g_warning ("Failed to send XDMCP request: %s", error->message);
    else if (n_written != buffer_length)
        g_warning ("Partial write for XDMCP request, wrote %zi, expected %zi", n_written, buffer_length);
    g_clear_error (&error);
}

Here is the caller graph for this function:


Variable Documentation

Definition at line 53 of file xdmcp-client.c.