/[rdesktop]/sourceforge.net/trunk/rdesktop/mcs.c
This is repository of my old source code which isn't updated any more. Go to git.rot13.org for current projects!
ViewVC logotype

Diff of /sourceforge.net/trunk/rdesktop/mcs.c

Parent Directory Parent Directory | Revision Log Revision Log | View Patch Patch

sourceforge.net/branches/RDESKTOP/rdesktop/mcs.c revision 3 by matty, Wed May 10 07:36:34 2000 UTC sourceforge.net/trunk/rdesktop/mcs.c revision 1372 by jsorg71, Mon Jan 8 04:47:06 2007 UTC
# Line 1  Line 1 
1  /*  /* -*- c-basic-offset: 8 -*-
2     rdesktop: A Remote Desktop Protocol client.     rdesktop: A Remote Desktop Protocol client.
3     Protocol services - Multipoint Communications Service     Protocol services - Multipoint Communications Service
4     Copyright (C) Matthew Chapman 1999-2000     Copyright (C) Matthew Chapman 1999-2007
5      
6     This program is free software; you can redistribute it and/or modify     This program is free software; you can redistribute it and/or modify
7     it under the terms of the GNU General Public License as published by     it under the terms of the GNU General Public License as published by
8     the Free Software Foundation; either version 2 of the License, or     the Free Software Foundation; either version 2 of the License, or
9     (at your option) any later version.     (at your option) any later version.
10      
11     This program is distributed in the hope that it will be useful,     This program is distributed in the hope that it will be useful,
12     but WITHOUT ANY WARRANTY; without even the implied warranty of     but WITHOUT ANY WARRANTY; without even the implied warranty of
13     MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the     MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
14     GNU General Public License for more details.     GNU General Public License for more details.
15      
16     You should have received a copy of the GNU General Public License     You should have received a copy of the GNU General Public License
17     along with this program; if not, write to the Free Software     along with this program; if not, write to the Free Software
18     Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.     Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
19  */  */
20    
21  #include "includes.h"  #include "rdesktop.h"
22    
23  /* Establish a connection up to the MCS layer */  uint16 g_mcs_userid;
24  HCONN mcs_connect(char *server)  extern VCHANNEL g_channels[];
25  {  extern unsigned int g_num_channels;
         HCONN conn;  
         MCS_CONNECT_RESPONSE mcr;  
         MCS_AUCF aucf;  
26    
27          if ((conn = iso_connect(server)) == NULL)  /* Parse an ASN.1 BER header */
28                  return NULL;  static RD_BOOL
29    ber_parse_header(STREAM s, int tagval, int *length)
30    {
31            int tag, len;
32    
33          mcs_send_connect_initial(conn);          if (tagval > 0xff)
         if (!iso_recv(conn) || !mcs_io_connect_response(&conn->in, &mcr))  
34          {          {
35                  fprintf(stderr, "MCS error, expected Connect-Response\n");                  in_uint16_be(s, tag);
                 iso_disconnect(conn);  
                 return NULL;  
36          }          }
37            else
         if (mcr.result != 0)  
38          {          {
39                  fprintf(stderr, "MCS-Connect-Initial failed, result %d\n",          in_uint8(s, tag)}
                         mcr.result);  
                 iso_disconnect(conn);  
                 return NULL;  
         }  
40    
41          mcs_send_edrq(conn);          if (tag != tagval)
   
         mcs_send_aurq(conn);  
         if (!iso_recv(conn) || !mcs_io_aucf(&conn->in, &aucf))  
42          {          {
43                  fprintf(stderr, "MCS error, expected AUcf\n");                  error("expected tag %d, got %d\n", tagval, tag);
44                  mcs_disconnect(conn);                  return False;
                 return NULL;  
         }  
   
         if (aucf.result != 0)  
         {  
                 fprintf(stderr, "AUrq failed, result %d\n", mcr.result);  
                 mcs_disconnect(conn);  
                 return NULL;  
45          }          }
46    
47          conn->mcs_userid = aucf.userid;          in_uint8(s, len);
48    
49          if (!mcs_join_channel(conn, aucf.userid + 1001)          if (len & 0x80)
             || !mcs_join_channel(conn, MCS_GLOBAL_CHANNEL))  
50          {          {
51                  mcs_disconnect(conn);                  len &= ~0x80;
52                  return NULL;                  *length = 0;
53                    while (len--)
54                            next_be(s, *length);
55          }          }
56            else
57                    *length = len;
58    
59          return conn;          return s_check(s);
60  }  }
61    
62  BOOL mcs_join_channel(HCONN conn, uint16 chanid)  /* Output an ASN.1 BER header */
63    static void
64    ber_out_header(STREAM s, int tagval, int length)
65  {  {
66          MCS_CJCF cjcf;          if (tagval > 0xff)
   
         mcs_send_cjrq(conn, chanid);  
         if (!iso_recv(conn) || !mcs_io_cjcf(&conn->in, &cjcf))  
67          {          {
68                  fprintf(stderr, "MCS error, expected CJcf\n");                  out_uint16_be(s, tagval);
                 return False;  
69          }          }
70            else
         if (cjcf.result != 0)  
71          {          {
72                  fprintf(stderr, "CJrq failed, result %d\n", cjcf.result);                  out_uint8(s, tagval);
                 return False;  
73          }          }
74    
75          return True;          if (length >= 0x80)
76            {
77                    out_uint8(s, 0x82);
78                    out_uint16_be(s, length);
79            }
80            else
81                    out_uint8(s, length);
82  }  }
83    
84  /* Disconnect from the MCS layer */  /* Output an ASN.1 BER integer */
85  void mcs_disconnect(HCONN conn)  static void
86    ber_out_integer(STREAM s, int value)
87  {  {
88          /* Not complete */          ber_out_header(s, BER_TAG_INTEGER, 2);
89          iso_disconnect(conn);          out_uint16_be(s, value);
90  }  }
91    
92  /* Send a Connect-Initial message */  /* Output a DOMAIN_PARAMS structure (ASN.1 BER) */
93  void mcs_send_connect_initial(HCONN conn)  static void
94    mcs_out_domain_params(STREAM s, int max_channels, int max_users, int max_tokens, int max_pdusize)
95  {  {
96          MCS_CONNECT_INITIAL mci;          ber_out_header(s, MCS_TAG_DOMAIN_PARAMS, 32);
97            ber_out_integer(s, max_channels);
98          iso_init(conn);          ber_out_integer(s, max_users);
99          mcs_make_connect_initial(&mci);          ber_out_integer(s, max_tokens);
100          mcs_io_connect_initial(&conn->out, &mci);          ber_out_integer(s, 1);  /* num_priorities */
101          MARK_END(conn->out);          ber_out_integer(s, 0);  /* min_throughput */
102          iso_send(conn);          ber_out_integer(s, 1);  /* max_height */
103            ber_out_integer(s, max_pdusize);
104            ber_out_integer(s, 2);  /* ver_protocol */
105  }  }
106    
107  /* Send a EDrq message */  /* Parse a DOMAIN_PARAMS structure (ASN.1 BER) */
108  void mcs_send_edrq(HCONN conn)  static RD_BOOL
109    mcs_parse_domain_params(STREAM s)
110  {  {
111          MCS_EDRQ edrq;          int length;
   
         iso_init(conn);  
         edrq.height = edrq.interval = 1;  
         mcs_io_edrq(&conn->out, &edrq);  
         MARK_END(conn->out);  
         iso_send(conn);  
 }  
112    
113  /* Send a AUrq message */          ber_parse_header(s, MCS_TAG_DOMAIN_PARAMS, &length);
114  void mcs_send_aurq(HCONN conn)          in_uint8s(s, length);
 {  
         MCS_AURQ aurq;  
115    
116          iso_init(conn);          return s_check(s);
         mcs_io_aurq(&conn->out, &aurq);  
         MARK_END(conn->out);  
         iso_send(conn);  
117  }  }
118    
119  /* Send a CJrq message */  /* Send an MCS_CONNECT_INITIAL message (ASN.1 BER) */
120  void mcs_send_cjrq(HCONN conn, uint16 chanid)  static void
121    mcs_send_connect_initial(STREAM mcs_data)
122  {  {
123          MCS_CJRQ cjrq;          int datalen = mcs_data->end - mcs_data->data;
124            int length = 9 + 3 * 34 + 4 + datalen;
125            STREAM s;
126    
127          iso_init(conn);          s = iso_init(length + 5);
         cjrq.userid = conn->mcs_userid;  
         cjrq.chanid = chanid;  
         mcs_io_cjrq(&conn->out, &cjrq);  
         MARK_END(conn->out);  
         iso_send(conn);  
 }  
128    
129  /* Initialise MCS transport data packet */          ber_out_header(s, MCS_CONNECT_INITIAL, length);
130  void mcs_init_data(HCONN conn)          ber_out_header(s, BER_TAG_OCTET_STRING, 1);     /* calling domain */
131  {          out_uint8(s, 1);
132          iso_init(conn);          ber_out_header(s, BER_TAG_OCTET_STRING, 1);     /* called domain */
133          PUSH_LAYER(conn->out, mcs_offset, 8);          out_uint8(s, 1);
 }  
134    
135  /* Transmit MCS transport data packet */          ber_out_header(s, BER_TAG_BOOLEAN, 1);
136  void mcs_send_data(HCONN conn, uint16 chanid, BOOL request)          out_uint8(s, 0xff);     /* upward flag */
 {  
         MCS_DATA dt;  
137    
138          POP_LAYER(conn->out, mcs_offset);          mcs_out_domain_params(s, 34, 2, 0, 0xffff);     /* target params */
139          dt.userid = conn->mcs_userid;          mcs_out_domain_params(s, 1, 1, 1, 0x420);       /* min params */
140          dt.chanid = chanid;          mcs_out_domain_params(s, 0xffff, 0xfc17, 0xffff, 0xffff);       /* max params */
         dt.flags = 0x70;  
         dt.length = conn->out.end - conn->out.offset - 8;  
         mcs_io_data(&conn->out, &dt, request);  
         iso_send(conn);  
 }  
141    
142  /* Receive a message on the MCS layer */          ber_out_header(s, BER_TAG_OCTET_STRING, datalen);
143  BOOL mcs_recv(HCONN conn, BOOL request)          out_uint8p(s, mcs_data->data, datalen);
 {  
         MCS_DATA data;  
144    
145          return (iso_recv(conn)) && mcs_io_data(&conn->in, &data, request);          s_mark_end(s);
146            iso_send(s);
147  }  }
148    
149  /* Initialise a DOMAIN_PARAMS structure */  /* Expect a MCS_CONNECT_RESPONSE message (ASN.1 BER) */
150  void mcs_make_domain_params(DOMAIN_PARAMS *dp, uint16 max_channels,  static RD_BOOL
151                uint16 max_users, uint16 max_tokens, uint16 max_pdusize)  mcs_recv_connect_response(STREAM mcs_data)
152  {  {
153          dp->max_channels   = max_channels;          uint8 result;
154          dp->max_users      = max_users;          int length;
155          dp->max_tokens     = max_tokens;          STREAM s;
         dp->num_priorities = 1;  
         dp->min_throughput = 0;  
         dp->max_height     = 1;  
         dp->max_pdusize    = max_pdusize;  
         dp->ver_protocol   = 2;  
 }  
156    
157  /* RDP-specific 'user data'. Let's just get this right for now - to be          s = iso_recv(NULL);
158     decoded later. */          if (s == NULL)
159  char precanned_connect_userdata[] = {                  return False;
    0x00,0x05,0x00,0x14,0x7c,0x00,0x01,0x80,0x9e,0x00,0x08,0x00,0x10,0x00,  
    0x01,0xc0,0x00,0x44,0x75,0x63,0x61,0x80,0x90,0x01,0xc0,0x88,0x00,0x01,  
    0x00,0x08,0x00,0x80,0x02,0xe0,0x01,0x01,0xca,0x03,0xaa,0x09,0x04,0x00,  
    0x00,0xa3,0x01,0x00,0x00,0x52,0x00,0x45,0x00,0x53,0x00,0x31,0x00,0x2d,  
    0x00,0x4e,0x00,0x45,0x00,0x57,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,  
    0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x04,0x00,0x00,0x00,0x00,  
    0x00,0x00,0x00,0x0c,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,  
    0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,  
    0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,  
    0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,  
    0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,  
    0x00,0x01,0xca,0x00,0x00,0x02,0xc0,0x08,0x00,0x00,0x00,0x00,0x00 };  
160    
161  /* Initialise a MCS_CONNECT_INITIAL structure */          ber_parse_header(s, MCS_CONNECT_RESPONSE, &length);
 void mcs_make_connect_initial(MCS_CONNECT_INITIAL *mci)  
 {  
         mci->calling_domain.length = 0;  
         mci->calling_domain.data = NULL;  
162    
163          mci->called_domain.length = 0;          ber_parse_header(s, BER_TAG_RESULT, &length);
164          mci->called_domain.data = NULL;          in_uint8(s, result);
165            if (result != 0)
166            {
167                    error("MCS connect: %d\n", result);
168                    return False;
169            }
170    
171          mci->upward_flag = 0xff;          ber_parse_header(s, BER_TAG_INTEGER, &length);
172            in_uint8s(s, length);   /* connect id */
173            mcs_parse_domain_params(s);
174    
175          mcs_make_domain_params(&mci->target_params,  2, 2, 0, 0xffff);          ber_parse_header(s, BER_TAG_OCTET_STRING, &length);
         mcs_make_domain_params(&mci->minimum_params, 1, 1, 1, 0x420);  
         mcs_make_domain_params(&mci->maximum_params, 0xffff, 0xfc17, 0xffff,  
                                0xffff);  
176    
177          mci->user_data.length = sizeof(precanned_connect_userdata);          sec_process_mcs_data(s);
178          mci->user_data.data = precanned_connect_userdata;          /*
179               if (length > mcs_data->size)
180               {
181               error("MCS data length %d, expected %d\n", length,
182               mcs_data->size);
183               length = mcs_data->size;
184               }
185    
186          mci->length = 2*2 + 3 + 3*34 + 4 + mci->user_data.length;             in_uint8a(s, mcs_data->data, length);
187               mcs_data->p = mcs_data->data;
188               mcs_data->end = mcs_data->data + length;
189             */
190            return s_check_end(s);
191  }  }
192    
193  /* Marshall/demarshall an ASN.1 BER header */  /* Send an EDrq message (ASN.1 PER) */
194  BOOL ber_io_header(STREAM s, BOOL islong, int tagval, int *length)  static void
195    mcs_send_edrq(void)
196  {  {
197          uint16 word_tag;          STREAM s;
         uint8 byte_tag;  
         uint16 word_len;  
         uint8 byte_len;  
         uint8 byte_int;  
         int tag;  
         BOOL res;  
198    
199          /* Read/write tag */          s = iso_init(5);
         if (islong) {  
                 word_tag = tagval;  
                 res = msb_io_uint16(s, &word_tag);  
                 tag = word_tag;  
         } else {  
                 byte_tag = tagval;  
                 res = prs_io_uint8(s, &byte_tag);  
                 tag = byte_tag;  
         }  
200    
201          if (!res || (tag != tagval)) {          out_uint8(s, (MCS_EDRQ << 2));
202                  fprintf(stderr, "Invalid ASN.1 tag\n");          out_uint16_be(s, 1);    /* height */
203                  return False;          out_uint16_be(s, 1);    /* interval */
         }  
204    
205          /* Read/write length */          s_mark_end(s);
206          if (s->marshall)          iso_send(s);
207          {  }
                 if (*length >= 0x80)  
                 {  
                         byte_len = 0x82;  
                         word_len = (uint16)*length;  
                         res = prs_io_uint8(s, &byte_len);  
                         res = res ? msb_io_uint16(s, &word_len) : False;  
                 }  
                 else  
                 {  
                         byte_len = (uint8)*length;  
                         res = prs_io_uint8(s, &byte_len);  
                 }  
         }  
         else  
         {  
                 if (!prs_io_uint8(s, &byte_len))  
                         return False;  
208    
209                  if (byte_len & 0x80)  /* Send an AUrq message (ASN.1 PER) */
210                  {  static void
211                          byte_len &= ~0x80;  mcs_send_aurq(void)
212                          *length = 0;  {
213                          while (byte_len--)          STREAM s;
214                          {  
215                                  if (!prs_io_uint8(s, &byte_int))          s = iso_init(1);
                                         return False;  
   
                                 *length <<= 8;  
                                 *length += byte_int;  
                         }  
                 }  
                 else *length = byte_len;  
         }  
216    
217          return res;          out_uint8(s, (MCS_AURQ << 2));
218    
219            s_mark_end(s);
220            iso_send(s);
221  }  }
222    
223  /* Marshall/demarshall an octet string (ASN.1 BER) */  /* Expect a AUcf message (ASN.1 PER) */
224  BOOL ber_io_octet_string(STREAM s, OCTET_STRING *os)  static RD_BOOL
225    mcs_recv_aucf(uint16 * mcs_userid)
226  {  {
227          if (!ber_io_header(s, False, 4, &os->length))          uint8 opcode, result;
228                  return False;          STREAM s;
229    
230          if (os->length > s->end - s->offset)          s = iso_recv(NULL);
231            if (s == NULL)
232                  return False;                  return False;
233    
234          if (s->marshall)          in_uint8(s, opcode);
235            if ((opcode >> 2) != MCS_AUCF)
236          {          {
237                  memcpy(s->data + s->offset, os->data, os->length);                  error("expected AUcf, got %d\n", opcode);
238                    return False;
239          }          }
240          else  
241            in_uint8(s, result);
242            if (result != 0)
243          {          {
244                  os->data = malloc(os->length);                  error("AUrq: %d\n", result);
245                  memcpy(os->data, s->data + s->offset, os->length);                  return False;
246          }          }
247    
248          s->offset += os->length;          if (opcode & 2)
249          return True;                  in_uint16_be(s, *mcs_userid);
250    
251            return s_check_end(s);
252  }  }
253    
254  /* Marshall/demarshall an integer (ASN.1 BER) */  /* Send a CJrq message (ASN.1 PER) */
255  BOOL ber_io_integer(STREAM s, uint16 *word_int)  static void
256    mcs_send_cjrq(uint16 chanid)
257  {  {
258          int length = 2;          STREAM s;
         uint8 byte_int;  
         BOOL res;  
259    
260          if (!ber_io_header(s, False, 2, &length))          DEBUG_RDP5(("Sending CJRQ for channel #%d\n", chanid));
                 return False;  
261    
262          if (s->marshall)          s = iso_init(5);
         {  
                 res = msb_io_uint16(s, word_int);  
         }  
         else  
         {  
                 *word_int = 0;  
                 while (length--)  
                 {  
                         if (!prs_io_uint8(s, &byte_int))  
                                 return False;  
263    
264                          *word_int <<= 8;          out_uint8(s, (MCS_CJRQ << 2));
265                          *word_int += byte_int;          out_uint16_be(s, g_mcs_userid);
266                  }          out_uint16_be(s, chanid);
         }  
267    
268          return res;          s_mark_end(s);
269            iso_send(s);
270  }  }
271    
272  /* Marshall/demarshall a simple uint8 type (ASN.1 BER) */  /* Expect a CJcf message (ASN.1 PER) */
273  BOOL ber_io_uint8(STREAM s, uint8 *i, int tagval)  static RD_BOOL
274    mcs_recv_cjcf(void)
275  {  {
276          int length = 1;          uint8 opcode, result;
277            STREAM s;
278    
279            s = iso_recv(NULL);
280            if (s == NULL)
281                    return False;
282    
283          if (!ber_io_header(s, False, tagval, &length))          in_uint8(s, opcode);
284            if ((opcode >> 2) != MCS_CJCF)
285            {
286                    error("expected CJcf, got %d\n", opcode);
287                  return False;                  return False;
288            }
289    
290          if (length != 1)          in_uint8(s, result);
291            if (result != 0)
292          {          {
293                  fprintf(stderr, "Wrong length for simple type\n");                  error("CJrq: %d\n", result);
294                  return False;                  return False;
295          }          }
296    
297          return prs_io_uint8(s, i);          in_uint8s(s, 4);        /* mcs_userid, req_chanid */
298            if (opcode & 2)
299                    in_uint8s(s, 2);        /* join_chanid */
300    
301            return s_check_end(s);
302  }  }
303    
304  /* Marshall/demarshall a DOMAIN_PARAMS structure (ASN.1 BER) */  /* Initialise an MCS transport data packet */
305  BOOL mcs_io_domain_params(STREAM s, DOMAIN_PARAMS *dp)  STREAM
306    mcs_init(int length)
307  {  {
308          int length = 32;          STREAM s;
         BOOL res;  
309    
310          res = ber_io_header(s, False, 0x30, &length);          s = iso_init(length + 8);
311          res = res ? ber_io_integer(s, &dp->max_channels  ) : False;          s_push_layer(s, mcs_hdr, 8);
         res = res ? ber_io_integer(s, &dp->max_users     ) : False;  
         res = res ? ber_io_integer(s, &dp->max_tokens    ) : False;  
         res = res ? ber_io_integer(s, &dp->num_priorities) : False;  
         res = res ? ber_io_integer(s, &dp->min_throughput) : False;  
         res = res ? ber_io_integer(s, &dp->max_height    ) : False;  
         res = res ? ber_io_integer(s, &dp->max_pdusize   ) : False;  
         res = res ? ber_io_integer(s, &dp->ver_protocol  ) : False;  
312    
313          return res;          return s;
314  }  }
315    
316  /* Marshall/demarshall a MCS_CONNECT_INITIAL structure (ASN.1 BER) */  /* Send an MCS transport data packet to a specific channel */
317  BOOL mcs_io_connect_initial(STREAM s, MCS_CONNECT_INITIAL *mci)  void
318    mcs_send_to_channel(STREAM s, uint16 channel)
319  {  {
320          BOOL res;          uint16 length;
321    
322            s_pop_layer(s, mcs_hdr);
323            length = s->end - s->p - 8;
324            length |= 0x8000;
325    
326          res = ber_io_header(s, True, 0x7f65, &mci->length);          out_uint8(s, (MCS_SDRQ << 2));
327          res = res ? ber_io_octet_string (s, &mci->calling_domain) : False;          out_uint16_be(s, g_mcs_userid);
328          res = res ? ber_io_octet_string (s, &mci->called_domain ) : False;          out_uint16_be(s, channel);
329          res = res ? ber_io_uint8        (s, &mci->upward_flag, 1) : False;          out_uint8(s, 0x70);     /* flags */
330          res = res ? mcs_io_domain_params(s, &mci->target_params ) : False;          out_uint16_be(s, length);
         res = res ? mcs_io_domain_params(s, &mci->minimum_params) : False;  
         res = res ? mcs_io_domain_params(s, &mci->maximum_params) : False;  
         res = res ? ber_io_octet_string (s, &mci->user_data     ) : False;  
331    
332          return res;          iso_send(s);
333  }  }
334    
335  /* Marshall/demarshall a MCS_CONNECT_RESPONSE structure (ASN.1 BER) */  /* Send an MCS transport data packet to the global channel */
336  BOOL mcs_io_connect_response(STREAM s, MCS_CONNECT_RESPONSE *mcr)  void
337    mcs_send(STREAM s)
338  {  {
339          BOOL res;          mcs_send_to_channel(s, MCS_GLOBAL_CHANNEL);
   
         res = ber_io_header(s, True, 0x7f66, &mcr->length);  
         res = res ? ber_io_uint8        (s, &mcr->result, 10   ) : False;  
         res = res ? ber_io_integer      (s, &mcr->connect_id   ) : False;  
         res = res ? mcs_io_domain_params(s, &mcr->domain_params) : False;  
         res = res ? ber_io_octet_string (s, &mcr->user_data    ) : False;  
   
         return res;  
340  }  }
341    
342  /* Marshall/demarshall an EDrq structure (ASN.1 PER) */  /* Receive an MCS transport data packet */
343  BOOL mcs_io_edrq(STREAM s, MCS_EDRQ *edrq)  STREAM
344    mcs_recv(uint16 * channel, uint8 * rdpver)
345  {  {
346          uint8 opcode = (1) << 2;          uint8 opcode, appid, length;
347          uint8 pkt_opcode = opcode;          STREAM s;
         BOOL res;  
348    
349          res = prs_io_uint8(s, &pkt_opcode);          s = iso_recv(rdpver);
350          if (pkt_opcode != opcode)          if (s == NULL)
351                    return NULL;
352            if (rdpver != NULL)
353                    if (*rdpver != 3)
354                            return s;
355            in_uint8(s, opcode);
356            appid = opcode >> 2;
357            if (appid != MCS_SDIN)
358          {          {
359                  fprintf(stderr, "Expected EDrq, received %x\n", pkt_opcode);                  if (appid != MCS_DPUM)
360                  return False;                  {
361                            error("expected data, got %d\n", opcode);
362                    }
363                    return NULL;
364          }          }
365            in_uint8s(s, 2);        /* userid */
366          res = res ? msb_io_uint16(s, &edrq->height  ) : False;          in_uint16_be(s, *channel);
367          res = res ? msb_io_uint16(s, &edrq->interval) : False;          in_uint8s(s, 1);        /* flags */
368            in_uint8(s, length);
369          return res;          if (length & 0x80)
370                    in_uint8s(s, 1);        /* second byte of length */
371            return s;
372  }  }
373    
374  /* Marshall/demarshall an AUrq structure (ASN.1 PER) */  /* Establish a connection up to the MCS layer */
375  BOOL mcs_io_aurq(STREAM s, MCS_AURQ *aurq)  RD_BOOL
376    mcs_connect(char *server, STREAM mcs_data, char *username)
377  {  {
378          uint8 opcode = (10) << 2;          unsigned int i;
         uint8 pkt_opcode = opcode;  
         BOOL res;  
379    
380          res = prs_io_uint8(s, &pkt_opcode);          if (!iso_connect(server, username))
         if (pkt_opcode != opcode)  
         {  
                 fprintf(stderr, "Expected AUrq, received %x\n", pkt_opcode);  
381                  return False;                  return False;
         }  
382    
383          return res;          mcs_send_connect_initial(mcs_data);
384  }          if (!mcs_recv_connect_response(mcs_data))
385                    goto error;
386    
387  /* Marshall/demarshall an AUcf structure (ASN.1 PER) */          mcs_send_edrq();
 BOOL mcs_io_aucf(STREAM s, MCS_AUCF *aucf)  
 {  
         uint8 opcode = (11) << 2;  
         uint8 pkt_opcode = opcode | 2;  
         BOOL res;  
388    
389          res = prs_io_uint8(s, &pkt_opcode);          mcs_send_aurq();
390          if ((pkt_opcode & 0xfc) != opcode)          if (!mcs_recv_aucf(&g_mcs_userid))
391          {                  goto error;
                 fprintf(stderr, "Expected AUcf, received %x\n", pkt_opcode);  
                 return False;  
         }  
392    
393          res = res ? prs_io_uint8 (s, &aucf->result) : False;          mcs_send_cjrq(g_mcs_userid + MCS_USERCHANNEL_BASE);
         if (pkt_opcode & 2)  
                 res = res ? msb_io_uint16(s, &aucf->userid) : False;  
394    
395          return res;          if (!mcs_recv_cjcf())
396  }                  goto error;
397    
398  /* Marshall/demarshall an CJrq structure (ASN.1 PER) */          mcs_send_cjrq(MCS_GLOBAL_CHANNEL);
399  BOOL mcs_io_cjrq(STREAM s, MCS_CJRQ *cjrq)          if (!mcs_recv_cjcf())
400  {                  goto error;
         uint8 opcode = (14) << 2;  
         uint8 pkt_opcode = opcode;  
         BOOL res;  
401    
402          res = prs_io_uint8(s, &pkt_opcode);          for (i = 0; i < g_num_channels; i++)
         if (pkt_opcode != opcode)  
403          {          {
404                  fprintf(stderr, "Expected CJrq, received %x\n", pkt_opcode);                  mcs_send_cjrq(g_channels[i].mcs_id);
405                  return False;                  if (!mcs_recv_cjcf())
406                            goto error;
407          }          }
408            return True;
409    
410          res = res ? msb_io_uint16(s, &cjrq->userid) : False;        error:
411          res = res ? msb_io_uint16(s, &cjrq->chanid) : False;          iso_disconnect();
412            return False;
         return res;  
413  }  }
414    
415  /* Marshall/demarshall an CJcf structure (ASN.1 PER) */  /* Establish a connection up to the MCS layer */
416  BOOL mcs_io_cjcf(STREAM s, MCS_CJCF *cjcf)  RD_BOOL
417    mcs_reconnect(char *server, STREAM mcs_data)
418  {  {
419          uint8 opcode = (15) << 2;          unsigned int i;
         uint8 pkt_opcode = opcode | 2;  
         BOOL res;  
420    
421          res = prs_io_uint8(s, &pkt_opcode);          if (!iso_reconnect(server))
         if ((pkt_opcode & 0xfc) != opcode)  
         {  
                 fprintf(stderr, "Expected CJcf, received %x\n", pkt_opcode);  
422                  return False;                  return False;
         }  
423    
424          res = res ? prs_io_uint8 (s, &cjcf->result) : False;          mcs_send_connect_initial(mcs_data);
425          res = res ? msb_io_uint16(s, &cjcf->userid) : False;          if (!mcs_recv_connect_response(mcs_data))
426          res = res ? msb_io_uint16(s, &cjcf->req_chanid) : False;                  goto error;
         if (pkt_opcode & 2)  
                 res = res ? msb_io_uint16(s, &cjcf->join_chanid) : False;  
427    
428          return res;          mcs_send_edrq();
 }  
429    
430  /* Marshall/demarshall an SDrq or SDin packet (ASN.1 PER) */          mcs_send_aurq();
431  BOOL mcs_io_data(STREAM s, MCS_DATA *dt, BOOL request)          if (!mcs_recv_aucf(&g_mcs_userid))
432  {                  goto error;
433          uint8 opcode = (request ? 25 : 26) << 2;  
434          uint8 pkt_opcode = opcode;          mcs_send_cjrq(g_mcs_userid + MCS_USERCHANNEL_BASE);
435          BOOL res;  
436            if (!mcs_recv_cjcf())
437                    goto error;
438    
439            mcs_send_cjrq(MCS_GLOBAL_CHANNEL);
440            if (!mcs_recv_cjcf())
441                    goto error;
442    
443          res = prs_io_uint8(s, &pkt_opcode);          for (i = 0; i < g_num_channels; i++)
         if (pkt_opcode != opcode)  
444          {          {
445                  fprintf(stderr, "Expected MCS data, received %x\n", pkt_opcode);                  mcs_send_cjrq(g_channels[i].mcs_id);
446                  return False;                  if (!mcs_recv_cjcf())
447                            goto error;
448          }          }
449            return True;
450    
451          dt->length |= 0x8000;        error:
452            iso_disconnect();
453            return False;
454    }
455    
456          res = res ? msb_io_uint16(s, &dt->userid) : False;  /* Disconnect from the MCS layer */
457          res = res ? msb_io_uint16(s, &dt->chanid) : False;  void
458          res = res ? prs_io_uint8 (s, &dt->flags ) : False;  mcs_disconnect(void)
459          res = res ? msb_io_uint16(s, &dt->length) : False;  {
460            iso_disconnect();
461    }
462    
463          return res;  /* reset the state of the mcs layer */
464    void
465    mcs_reset_state(void)
466    {
467            g_mcs_userid = 0;
468            iso_reset_state();
469  }  }

Legend:
Removed from v.3  
changed lines
  Added in v.1372

  ViewVC Help
Powered by ViewVC 1.1.26