]> git.sesse.net Git - rdpsrv/blobdiff - iso.c
Pull in lots of protocol stuff from rdesktop.
[rdpsrv] / iso.c
diff --git a/iso.c b/iso.c
new file mode 100644 (file)
index 0000000..26e967b
--- /dev/null
+++ b/iso.c
@@ -0,0 +1,215 @@
+/* -*- c-basic-offset: 8 -*-
+   rdesktop: A Remote Desktop Protocol client.
+   Protocol services - ISO layer
+   Copyright (C) Matthew Chapman 1999-2002
+   
+   This program is free software; you can redistribute it and/or modify
+   it under the terms of the GNU General Public License as published by
+   the Free Software Foundation; either version 2 of the License, or
+   (at your option) any later version.
+   
+   This program is distributed in the hope that it will be useful,
+   but WITHOUT ANY WARRANTY; without even the implied warranty of
+   MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+   GNU General Public License for more details.
+   
+   You should have received a copy of the GNU General Public License
+   along with this program; if not, write to the Free Software
+   Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
+*/
+
+#include "rdesktop.h"
+
+/* Send a self-contained ISO PDU */
+static void
+iso_send_msg(uint8 code)
+{
+       STREAM s;
+
+       s = tcp_init(11);
+
+       out_uint8(s, 3);        /* version */
+       out_uint8(s, 0);        /* reserved */
+       out_uint16_be(s, 11);   /* length */
+
+       out_uint8(s, 6);        /* hdrlen */
+       out_uint8(s, code);
+       out_uint16(s, 0);       /* dst_ref */
+       out_uint16(s, 0);       /* src_ref */
+       out_uint8(s, 0);        /* class */
+
+       s_mark_end(s);
+       tcp_send(s);
+}
+
+static void
+iso_send_connection_request(char *username)
+{
+       STREAM s;
+       int length = 30 + strlen(username);
+
+       s = tcp_init(length);
+
+       out_uint8(s, 3);        /* version */
+       out_uint8(s, 0);        /* reserved */
+       out_uint16_be(s, length);       /* length */
+
+       out_uint8(s, length - 5);       /* hdrlen */
+       out_uint8(s, ISO_PDU_CR);
+       out_uint16(s, 0);       /* dst_ref */
+       out_uint16(s, 0);       /* src_ref */
+       out_uint8(s, 0);        /* class */
+
+       out_uint8p(s, "Cookie: mstshash=", strlen("Cookie: mstshash="));
+       out_uint8p(s, username, strlen(username));
+
+       out_uint8(s, 0x0d);     /* Unknown */
+       out_uint8(s, 0x0a);     /* Unknown */
+
+       s_mark_end(s);
+       tcp_send(s);
+}
+
+/* Receive a message on the ISO layer, return code */
+static STREAM
+iso_recv_msg(uint8 * code)
+{
+       STREAM s;
+       uint16 length;
+       uint8 version;
+
+      next_packet:
+       s = tcp_recv(NULL, 4);
+       if (s == NULL)
+               return NULL;
+
+       in_uint8(s, version);
+       switch (version & 3)
+       {
+               case 0:
+                       in_uint8(s, length);
+                       if (length & 0x80)
+                       {
+                               length &= ~0x80;
+                               next_be(s, length);
+                       }
+                       break;
+
+               case 3:
+                       in_uint8s(s, 1);        /* pad */
+                       in_uint16_be(s, length);
+                       break;
+
+               default:
+                       error("TPKT v%d\n", version);
+                       return NULL;
+       }
+
+       s = tcp_recv(s, length - 4);
+       if (s == NULL)
+               return NULL;
+
+       if ((version & 3) == 0)
+       {
+               // FIXME :-)
+               //              rdp5_process(s, version & 0x80);
+               printf("rdp5_process()\n");
+               goto next_packet;
+       }
+
+       in_uint8s(s, 1);        /* hdrlen */
+       in_uint8(s, *code);
+
+       if (*code == ISO_PDU_DT)
+       {
+               in_uint8s(s, 1);        /* eot */
+               return s;
+       }
+
+       in_uint8s(s, 5);        /* dst_ref, src_ref, class */
+       return s;
+}
+
+/* Initialise ISO transport data packet */
+STREAM
+iso_init(int length)
+{
+       STREAM s;
+
+       s = tcp_init(length + 7);
+       s_push_layer(s, iso_hdr, 7);
+
+       return s;
+}
+
+/* Send an ISO data PDU */
+void
+iso_send(STREAM s)
+{
+       uint16 length;
+
+       s_pop_layer(s, iso_hdr);
+       length = s->end - s->p;
+
+       out_uint8(s, 3);        /* version */
+       out_uint8(s, 0);        /* reserved */
+       out_uint16_be(s, length);
+
+       out_uint8(s, 2);        /* hdrlen */
+       out_uint8(s, ISO_PDU_DT);       /* code */
+       out_uint8(s, 0x80);     /* eot */
+
+       tcp_send(s);
+}
+
+/* Receive ISO transport data packet */
+STREAM
+iso_recv(void)
+{
+       STREAM s;
+       uint8 code;
+
+       s = iso_recv_msg(&code);
+       if (s == NULL)
+               return NULL;
+
+       if (code != ISO_PDU_DT)
+       {
+               error("expected DT, got 0x%x\n", code);
+               return NULL;
+       }
+
+       return s;
+}
+
+/* Establish a connection up to the ISO layer */
+BOOL
+iso_connect(char *server, char *username)
+{
+       uint8 code;
+
+       if (!tcp_connect(server))
+               return False;
+
+       iso_send_connection_request(username);
+
+       if (iso_recv_msg(&code) == NULL)
+               return False;
+
+       if (code != ISO_PDU_CC)
+       {
+               error("expected CC, got 0x%x\n", code);
+               tcp_disconnect();
+               return False;
+       }
+
+       return True;
+}
+
+/* Disconnect from the ISO layer */
+void
+iso_disconnect(void)
+{
+       iso_send_msg(ISO_PDU_DR);
+       tcp_disconnect();
+}