Back to index

lightdm  1.3.2
Classes | Functions
xdmcp-protocol.c File Reference
#include <string.h>
#include "xdmcp-protocol.h"

Go to the source code of this file.

Classes

struct  PacketReader
struct  PacketWriter

Functions

static guint8 read_card8 (PacketReader *reader)
static guint16 read_card16 (PacketReader *reader)
static guint32 read_card32 (PacketReader *reader)
static void read_data (PacketReader *reader, XDMCPData *data)
static gchar * read_string (PacketReader *reader)
static gchar ** read_string_array (PacketReader *reader)
static void write_card8 (PacketWriter *writer, guint8 value)
static void write_card16 (PacketWriter *writer, guint16 value)
static void write_card32 (PacketWriter *writer, guint16 value)
static void write_data (PacketWriter *writer, const XDMCPData *value)
static void write_string (PacketWriter *writer, const gchar *value)
static void write_string_array (PacketWriter *writer, gchar **values)
XDMCPPacketxdmcp_packet_alloc (XDMCPOpcode opcode)
XDMCPPacketxdmcp_packet_decode (const guint8 *data, gsize data_length)
gssize xdmcp_packet_encode (XDMCPPacket *packet, guint8 *data, gsize max_length)
static gchar * data_tostring (XDMCPData *data)
static gchar * string_list_tostring (gchar **strings)
gchar * xdmcp_packet_tostring (XDMCPPacket *packet)
void xdmcp_packet_free (XDMCPPacket *packet)

Class Documentation

struct PacketReader

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

Class Members
const guint8 * data
gboolean overflow
guint16 remaining
struct PacketWriter

Definition at line 94 of file xdmcp-protocol.c.

Class Members
guint8 * data
gboolean overflow
guint16 remaining

Function Documentation

static gchar* data_tostring ( XDMCPData data) [static]

Definition at line 407 of file xdmcp-protocol.c.

{
    GString *s;
    guint16 i;
    gchar *string;

    s = g_string_new ("");
    for (i = 0; i < data->length; i++)
        g_string_append_printf (s, "%02X", data->data[i]);
    string = s->str;
    g_string_free (s, FALSE);

    return string;
}

Here is the caller graph for this function:

static guint16 read_card16 ( PacketReader reader) [static]

Definition at line 42 of file xdmcp-protocol.c.

{
    return read_card8 (reader) << 8 | read_card8 (reader);
}

Here is the call graph for this function:

Here is the caller graph for this function:

static guint32 read_card32 ( PacketReader reader) [static]

Definition at line 48 of file xdmcp-protocol.c.

{
    return read_card8 (reader) << 24 | read_card8 (reader) << 16 | read_card8 (reader) << 8 | read_card8 (reader);
}

Here is the call graph for this function:

Here is the caller graph for this function:

static guint8 read_card8 ( PacketReader reader) [static]

Definition at line 24 of file xdmcp-protocol.c.

{
    guint8 value;

    if (reader->remaining < 1)
    {
        reader->overflow = TRUE;
        return 0;
    }

    value = reader->data[0];
    reader->data++;
    reader->remaining--;

    return value;
}

Here is the caller graph for this function:

static void read_data ( PacketReader reader,
XDMCPData data 
) [static]

Definition at line 54 of file xdmcp-protocol.c.

{
    guint16 i;

    data->length = read_card16 (reader);
    data->data = g_malloc (sizeof (guint8) * data->length);
    for (i = 0; i < data->length; i++)
        data->data[i] = read_card8 (reader);
}

Here is the call graph for this function:

Here is the caller graph for this function:

static gchar* read_string ( PacketReader reader) [static]

Definition at line 65 of file xdmcp-protocol.c.

{
    guint16 length, i;
    gchar *string;

    length = read_card16 (reader);
    string = g_malloc (sizeof (gchar) * (length + 1));
    for (i = 0; i < length; i++)
        string[i] = (gchar) read_card8 (reader);
    string[i] = '\0';

    return string;
}

Here is the call graph for this function:

static gchar** read_string_array ( PacketReader reader) [static]

Definition at line 80 of file xdmcp-protocol.c.

{
    guint8 n_strings, i;
    gchar **strings;

    n_strings = read_card8 (reader);
    strings = g_malloc (sizeof (gchar *) * (n_strings + 1));
    for (i = 0; i < n_strings; i++)
        strings[i] = read_string (reader);
    strings[i] = NULL;

    return strings;
}

Here is the call graph for this function:

Here is the caller graph for this function:

static gchar* string_list_tostring ( gchar **  strings) [static]

Definition at line 423 of file xdmcp-protocol.c.

{
    GString *s;
    gchar *string;
    gchar **i;
  
    s = g_string_new ("");  
    for (i = strings; *i; i++)
    {
        if (i != strings)
           g_string_append (s, " ");
        g_string_append_printf (s, "'%s'", *i);
    }
    string = s->str;
    g_string_free (s, FALSE);

    return string;
}

Here is the caller graph for this function:

static void write_card16 ( PacketWriter writer,
guint16  value 
) [static]

Definition at line 116 of file xdmcp-protocol.c.

{
    write_card8 (writer, value >> 8);
    write_card8 (writer, value & 0xFF);
}

Here is the call graph for this function:

Here is the caller graph for this function:

static void write_card32 ( PacketWriter writer,
guint16  value 
) [static]

Definition at line 123 of file xdmcp-protocol.c.

{
    write_card8 (writer, (value >> 24) & 0xFF);
    write_card8 (writer, (value >> 16) & 0xFF);
    write_card8 (writer, (value >> 8) & 0xFF);
    write_card8 (writer, value & 0xFF);
}

Here is the call graph for this function:

Here is the caller graph for this function:

static void write_card8 ( PacketWriter writer,
guint8  value 
) [static]

Definition at line 102 of file xdmcp-protocol.c.

{
    if (writer->remaining < 1)
    {
        writer->overflow = TRUE;
        return;
    }

    writer->data[0] = value;
    writer->data++;
    writer->remaining--;
}

Here is the caller graph for this function:

static void write_data ( PacketWriter writer,
const XDMCPData value 
) [static]

Definition at line 132 of file xdmcp-protocol.c.

{
    guint16 i;

    write_card16 (writer, value->length);
    for (i = 0; i < value->length; i++)
        write_card8 (writer, value->data[i]);
}

Here is the call graph for this function:

Here is the caller graph for this function:

static void write_string ( PacketWriter writer,
const gchar *  value 
) [static]

Definition at line 142 of file xdmcp-protocol.c.

{
    const gchar *c;

    write_card16 (writer, strlen (value));
    for (c = value; *c; c++)
        write_card8 (writer, *c);
}

Here is the call graph for this function:

static void write_string_array ( PacketWriter writer,
gchar **  values 
) [static]

Definition at line 152 of file xdmcp-protocol.c.

{
    gchar **value;

    write_card8 (writer, g_strv_length (values));
    for (value = values; *value; value++)
        write_string (writer, *value);
}

Here is the call graph for this function:

Here is the caller graph for this function:

Definition at line 162 of file xdmcp-protocol.c.

{
    XDMCPPacket *packet;

    packet = g_malloc0 (sizeof (XDMCPPacket));
    packet->opcode = opcode;

    return packet;
}

Here is the caller graph for this function:

XDMCPPacket* xdmcp_packet_decode ( const guint8 *  data,
gsize  data_length 
)

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

{
    XDMCPPacket *packet;
    guint16 version, opcode, length;
    PacketReader reader;
    int i;
    gboolean failed = FALSE;

    reader.data = data;
    reader.remaining = data_length;
    reader.overflow = FALSE;

    version = read_card16 (&reader);
    opcode = read_card16 (&reader);
    length = read_card16 (&reader);

    if (reader.overflow)
    {      
        g_warning ("Ignoring short packet"); // FIXME: Use GError
        return NULL;
    }
    if (version != XDMCP_VERSION)
    {
        g_warning ("Ignoring packet from unknown version %d", version);
        return NULL;
    }
    if (length != reader.remaining)
    {
        g_warning ("Ignoring packet of wrong length");
        return NULL;
    }

    packet = xdmcp_packet_alloc (opcode);
    switch (packet->opcode)
    {
    case XDMCP_BroadcastQuery:
    case XDMCP_Query:
    case XDMCP_IndirectQuery:
        packet->Query.authentication_names = read_string_array (&reader);
        break;
    case XDMCP_ForwardQuery:
        packet->ForwardQuery.client_address = read_string (&reader);
        packet->ForwardQuery.client_port = read_string (&reader);
        packet->ForwardQuery.authentication_names = read_string_array (&reader);
        break;
    case XDMCP_Willing:
        packet->Willing.authentication_name = read_string (&reader);
        packet->Willing.hostname = read_string (&reader);
        packet->Willing.status = read_string (&reader);
        break;
    case XDMCP_Unwilling:
        packet->Unwilling.hostname = read_string (&reader);
        packet->Unwilling.status = read_string (&reader);
        break;
    case XDMCP_Request:
        packet->Request.display_number = read_card16 (&reader);
        packet->Request.n_connections = read_card8 (&reader);
        packet->Request.connections = g_malloc (sizeof (XDMCPConnection) * packet->Request.n_connections);
        for (i = 0; i < packet->Request.n_connections; i++)
            packet->Request.connections[i].type = read_card16 (&reader);
        if (read_card8 (&reader) != packet->Request.n_connections)
        {
            g_warning ("Number of connection types does not match number of connection addresses");
            failed = TRUE;
        }
        for (i = 0; i < packet->Request.n_connections; i++)
            read_data (&reader, &packet->Request.connections[i].address);
        packet->Request.authentication_name = read_string (&reader);
        read_data (&reader, &packet->Request.authentication_data);
        packet->Request.authorization_names = read_string_array (&reader);
        packet->Request.manufacturer_display_id = read_string (&reader);
        break;
    case XDMCP_Accept:
        packet->Accept.session_id = read_card32 (&reader);
        packet->Accept.authentication_name = read_string (&reader);
        read_data (&reader, &packet->Accept.authentication_data);
        packet->Accept.authorization_name = read_string (&reader);
        read_data (&reader, &packet->Accept.authorization_data);
        break;
    case XDMCP_Decline:
        packet->Decline.status = read_string (&reader);
        packet->Decline.authentication_name = read_string (&reader);
        read_data (&reader, &packet->Decline.authentication_data);
        break;
    case XDMCP_Manage:
        packet->Manage.session_id = read_card32 (&reader);
        packet->Manage.display_number = read_card16 (&reader);
        packet->Manage.display_class = read_string (&reader);
        break;
    case XDMCP_Refuse:
        packet->Refuse.session_id = read_card32 (&reader);
        break;
    case XDMCP_Failed:
        packet->Failed.session_id = read_card32 (&reader);
        packet->Failed.status = read_string (&reader);
        break;
    case XDMCP_KeepAlive:
        packet->KeepAlive.display_number = read_card16 (&reader);
        packet->KeepAlive.session_id = read_card32 (&reader);
        break;
    case XDMCP_Alive:
        packet->Alive.session_running = read_card8 (&reader) == 0 ? FALSE : TRUE;
        packet->Alive.session_id = read_card32 (&reader);
        break;
    default:
        g_warning ("Unable to encode unknown opcode %d", packet->opcode);
        failed = TRUE;
        break;
    }

    if (!failed)
    {
        if (reader.overflow)
        {
            g_warning ("Short packet received");
            failed = TRUE;
        }
        else if (reader.remaining != 0)
        {
            g_warning ("Extra data on end of message");
            failed = TRUE;
        }
    }
    if (failed)
    {
        xdmcp_packet_free (packet);
        return NULL;
    }

    return packet;
}

Here is the call graph for this function:

Here is the caller graph for this function:

gssize xdmcp_packet_encode ( XDMCPPacket packet,
guint8 *  data,
gsize  max_length 
)

Definition at line 306 of file xdmcp-protocol.c.

{
    guint16 length;
    PacketWriter writer;
    int i;

    if (max_length < 6)
        return -1;

    writer.data = data + 6;
    writer.remaining = max_length - 6;
    writer.overflow = FALSE;

    switch (packet->opcode)
    {
    case XDMCP_BroadcastQuery:
    case XDMCP_Query:
    case XDMCP_IndirectQuery:
        write_string_array (&writer, packet->Query.authentication_names);
        break;
    case XDMCP_ForwardQuery:
        write_string (&writer, packet->ForwardQuery.client_address);
        write_string (&writer, packet->ForwardQuery.client_port);
        write_string_array (&writer, packet->ForwardQuery.authentication_names);
        break;
    case XDMCP_Willing:
        write_string (&writer, packet->Willing.authentication_name);
        write_string (&writer, packet->Willing.hostname);
        write_string (&writer, packet->Willing.status);
        break;
    case XDMCP_Unwilling:
        write_string (&writer, packet->Unwilling.hostname);
        write_string (&writer, packet->Unwilling.status);
        break;
    case XDMCP_Request:
        write_card16 (&writer, packet->Request.display_number);
        write_card8 (&writer, packet->Request.n_connections);
        for (i = 0; i < packet->Request.n_connections; i++)
            write_card16 (&writer, packet->Request.connections[i].type);
        write_card8 (&writer, packet->Request.n_connections);
        for (i = 0; i < packet->Request.n_connections; i++)
            write_data (&writer, &packet->Request.connections[i].address);
        write_string (&writer, packet->Request.authentication_name);
        write_data (&writer, &packet->Request.authentication_data);
        write_string_array (&writer, packet->Request.authorization_names);
        write_string (&writer, packet->Request.manufacturer_display_id);
        break;
    case XDMCP_Accept:
        write_card32 (&writer, packet->Accept.session_id);      
        write_string (&writer, packet->Accept.authentication_name);
        write_data (&writer, &packet->Accept.authentication_data);
        write_string (&writer, packet->Accept.authorization_name);
        write_data (&writer, &packet->Accept.authorization_data);
        break;
    case XDMCP_Decline:
        write_string (&writer, packet->Decline.status);
        write_string (&writer, packet->Decline.authentication_name);
        write_data (&writer, &packet->Decline.authentication_data);
        break;
    case XDMCP_Manage:
        write_card32 (&writer, packet->Manage.session_id);
        write_card16 (&writer, packet->Manage.display_number);
        write_string (&writer, packet->Manage.display_class);
        break;
    case XDMCP_Refuse:
        write_card32 (&writer, packet->Refuse.session_id);
        break;
    case XDMCP_Failed:
        write_card32 (&writer, packet->Failed.session_id);
        write_string (&writer, packet->Failed.status);
        break;
    case XDMCP_KeepAlive:
        write_card16 (&writer, packet->KeepAlive.display_number);
        write_card32 (&writer, packet->KeepAlive.session_id);
        break;
    case XDMCP_Alive:
        write_card8 (&writer, packet->Alive.session_running ? 1 : 0);
        write_card32 (&writer, packet->Alive.session_id);
        break;
    }

    length = max_length - 6 - writer.remaining;

    /* Write header */
    writer.data = data;
    writer.remaining = 6;
    writer.overflow = FALSE;
    write_card16(&writer, XDMCP_VERSION);
    write_card16(&writer, packet->opcode);
    write_card16(&writer, length);

    if (writer.overflow)
    {
        g_warning ("Overflow writing response");
        return -1;
    }
  
    return length + 6;
}

Here is the call graph for this function:

Here is the caller graph for this function:

void xdmcp_packet_free ( XDMCPPacket packet)

Definition at line 533 of file xdmcp-protocol.c.

{
    gint i;

    if (packet == NULL)
        return;

    switch (packet->opcode)
    {
    case XDMCP_BroadcastQuery:
    case XDMCP_Query:
    case XDMCP_IndirectQuery:
        g_strfreev (packet->Query.authentication_names);
        break;
    case XDMCP_ForwardQuery:
        g_free (packet->ForwardQuery.client_address);
        g_free (packet->ForwardQuery.client_port);
        g_strfreev (packet->ForwardQuery.authentication_names);
        break;
    case XDMCP_Willing:
        g_free (packet->Willing.authentication_name);
        g_free (packet->Willing.hostname);
        g_free (packet->Willing.status);
        break;
    case XDMCP_Unwilling:
        g_free (packet->Unwilling.hostname);
        g_free (packet->Unwilling.status);
        break;
    case XDMCP_Request:
        for (i = 0; i < packet->Request.n_connections; i++)
            g_free (packet->Request.connections[i].address.data);
        g_free (packet->Request.connections);
        g_free (packet->Request.authentication_name);
        g_free (packet->Request.authentication_data.data);
        g_strfreev (packet->Request.authorization_names);
        g_free (packet->Request.manufacturer_display_id);
        break;
    case XDMCP_Accept:
        g_free (packet->Accept.authentication_name);
        g_free (packet->Accept.authentication_data.data);
        g_free (packet->Accept.authorization_name);
        g_free (packet->Accept.authorization_data.data);
        break;
    case XDMCP_Decline:
        g_free (packet->Decline.status);
        g_free (packet->Decline.authentication_name);
        g_free (packet->Decline.authentication_data.data);
        break;
    case XDMCP_Manage:
        g_free (packet->Manage.display_class);
        break;
    case XDMCP_Refuse:
        break;
    case XDMCP_Failed:
        g_free (packet->Failed.status);
        break;
    case XDMCP_KeepAlive:
        break;
    case XDMCP_Alive:
        break;
    }
    g_free (packet);
}

Here is the caller graph for this function:

gchar* xdmcp_packet_tostring ( XDMCPPacket packet)

Definition at line 443 of file xdmcp-protocol.c.

{
    gchar *string, *t, *t2;
    gint i;
    GString *t3;

    switch (packet->opcode)
    {
    case XDMCP_BroadcastQuery:
        t = string_list_tostring (packet->Query.authentication_names);
        string = g_strdup_printf ("BroadcastQuery(authentication_names=[%s])", t);
        g_free (t);
        return string;
    case XDMCP_Query:
        t = string_list_tostring (packet->Query.authentication_names);
        string = g_strdup_printf ("Query(authentication_names=[%s])", t);
        g_free (t);
        return string;
    case XDMCP_IndirectQuery:
        t = string_list_tostring (packet->Query.authentication_names);
        string = g_strdup_printf ("IndirectQuery(authentication_names=[%s])", t);
        g_free (t);
        return string;
    case XDMCP_ForwardQuery:
        t = string_list_tostring (packet->ForwardQuery.authentication_names);
        string = g_strdup_printf ("ForwardQuery(client_address='%s' client_port='%s' authentication_names=[%s])",
                                  packet->ForwardQuery.client_address, packet->ForwardQuery.client_port, t);
        g_free (t);
        return string;
    case XDMCP_Willing:
        return g_strdup_printf ("Willing(authentication_name='%s' hostname='%s' status='%s')",
                                packet->Willing.authentication_name, packet->Willing.hostname, packet->Willing.status);
    case XDMCP_Unwilling:
        return g_strdup_printf ("Unwilling(hostname='%s' status='%s')",
                                packet->Unwilling.hostname, packet->Unwilling.status);      
    case XDMCP_Request:
        t = string_list_tostring (packet->Request.authorization_names);
        t2 = data_tostring (&packet->Request.authentication_data);
        t3 = g_string_new ("");
        for (i = 0; i < packet->Request.n_connections; i++)
        {
            gchar *t4;

            if (i != 0)
               g_string_append (t3, " ");
            t4 = data_tostring (&packet->Request.connections[i].address);
            g_string_append_printf (t3, "(%d, %s)", packet->Request.connections[i].type, t4);
            g_free (t4);
        }
        string = g_strdup_printf ("Request(display_number=%d connections=[%s] authentication_name='%s' authentication_data=%s authorization_names=[%s] manufacturer_display_id='%s')",
                                  packet->Request.display_number, t3->str, packet->Request.authentication_name, t2,
                                  t, packet->Request.manufacturer_display_id);
        g_free (t);
        g_free (t2);
        g_string_free (t3, TRUE);
        return string;
    case XDMCP_Accept:
        t = data_tostring (&packet->Accept.authentication_data);
        t2 = data_tostring (&packet->Accept.authorization_data);
        string =  g_strdup_printf ("Accept(session_id=%d authentication_name='%s' authentication_data=%s authorization_name='%s' authorization_data=%s)",
                                   packet->Accept.session_id, packet->Accept.authentication_name, t,
                                   packet->Accept.authorization_name, t2);
        g_free (t);
        g_free (t2);
        return string;
    case XDMCP_Decline:
        t = data_tostring (&packet->Decline.authentication_data);
        string = g_strdup_printf ("Decline(status='%s' authentication_name='%s' authentication_data=%s)",
                                  packet->Decline.status, packet->Decline.authentication_name, t);
        g_free (t);
        return string;
    case XDMCP_Manage:
        return g_strdup_printf ("Manage(session_id=%d display_number=%d display_class='%s')",
                                packet->Manage.session_id, packet->Manage.display_number, packet->Manage.display_class);
    case XDMCP_Refuse:
        return g_strdup_printf ("Refuse(session_id=%d)", packet->Refuse.session_id);
    case XDMCP_Failed:
        return g_strdup_printf ("Failed(session_id=%d status='%s')", packet->Failed.session_id, packet->Failed.status);
    case XDMCP_KeepAlive:
        return g_strdup_printf ("KeepAlive(display_number=%d session_id=%d)",
                                packet->KeepAlive.display_number, packet->KeepAlive.session_id);
    case XDMCP_Alive:
        return g_strdup_printf ("Alive(session_running=%s session_id=%d)",
                                packet->Alive.session_running ? "true" : "false", packet->Alive.session_id);
    default:
        return g_strdup_printf ("XDMCPPacket(opcode=%d)", packet->opcode);
    }
}

Here is the call graph for this function:

Here is the caller graph for this function: