source: trunk/third/ssh/packet.c @ 10564

Revision 10564, 23.3 KB checked in by danw, 27 years ago (diff)
This commit was generated by cvs2svn to compensate for changes in r10563, which included commits to RCS files with non-trunk default branches.
Line 
1/*
2
3packet.c
4
5Author: Tatu Ylonen <ylo@cs.hut.fi>
6
7Copyright (c) 1995 Tatu Ylonen <ylo@cs.hut.fi>, Espoo, Finland
8                   All rights reserved
9
10Created: Sat Mar 18 02:40:40 1995 ylo
11
12This file contains code implementing the packet protocol and communication
13with the other side.  This same code is used both on client and server side.
14
15*/
16
17/*
18 * $Id: packet.c,v 1.1.1.1 1997-10-17 22:26:03 danw Exp $
19 * $Log: not supported by cvs2svn $
20 * Revision 1.7  1997/04/05 17:29:21  ylo
21 *      Added packet_get_len (returns the remaining length of incoming
22 *      packet).
23 *
24 * Revision 1.6  1997/03/19 19:26:58  kivinen
25 *      Added packet_get_all function. Added checks to
26 *      packet_read_poll that previous packet buffer must be empty
27 *      before starting to put new packet in.
28 *
29 * Revision 1.5  1996/11/24 08:23:46  kivinen
30 *      Changed all code that checked EAGAIN to check EWOULDBLOCK too.
31 *      Added support for debug messages that are printed always (if
32 *      the first character of debug message is * it is printed with
33 *      error function instead of debug).
34 *
35 * Revision 1.4  1996/10/07 11:53:24  ttsalo
36 *      From "Charles M. Hannum" <mycroft@gnu.ai.mit.edu>:
37 *      Made the use of TCP_NODELAY conditional.
38 *
39 * Revision 1.3  1996/09/22 21:58:38  ylo
40 *      Added code to clear keepalives properly when requested.
41 *
42 * Revision 1.2  1996/05/28 16:42:13  ylo
43 *      Workaround for Solaris select() bug while reading version id.
44 *
45 * Revision 1.1.1.1  1996/02/18 21:38:12  ylo
46 *      Imported ssh-1.2.13.
47 *
48 * Revision 1.6  1995/09/24  23:59:12  ylo
49 *      Added packet_get_protocol_flags.
50 *
51 * Revision 1.5  1995/09/09  21:26:43  ylo
52 * /m/shadows/u2/users/ylo/ssh/README
53 *
54 * Revision 1.4  1995/07/27  03:59:37  ylo
55 *      Fixed a bug in new arcfour keying.
56 *
57 * Revision 1.3  1995/07/27  02:17:11  ylo
58 *      Changed keying for arcfour to avoid using the same key for both
59 *      directions.
60 *
61 * Revision 1.2  1995/07/13  01:27:33  ylo
62 *      Removed "Last modified" header.
63 *      Added cvs log.
64 *
65 * $Endlog$
66 */
67
68#include "includes.h"
69#include "xmalloc.h"
70#include "randoms.h"
71#include "buffer.h"
72#include "packet.h"
73#include "bufaux.h"
74#include "ssh.h"
75#include "crc32.h"
76#include "cipher.h"
77#include "getput.h"
78#include "compress.h"
79
80/* This variable contains the file descriptors used for communicating with
81   the other side.  connection_in is used for reading; connection_out
82   for writing.  These can be the same descriptor, in which case it is
83   assumed to be a socket. */
84static int connection_in = -1;
85static int connection_out = -1;
86
87/* Cipher type.  This value is only used to determine whether to pad the
88   packets with zeroes or random data. */
89static int cipher_type = SSH_CIPHER_NONE;
90
91/* Protocol flags for the remote side. */
92static unsigned int remote_protocol_flags = 0;
93
94/* Encryption context for receiving data.  This is only used for decryption. */
95static CipherContext receive_context;
96/* Encryption coontext for sending data.  This is only used for encryption. */
97static CipherContext send_context;
98
99/* Buffer for raw input data from the socket. */
100static Buffer input;
101
102/* Buffer for raw output data going to the socket. */
103static Buffer output;
104
105/* Buffer for the partial outgoing packet being constructed. */
106static Buffer outgoing_packet;
107
108/* Buffer for the incoming packet currently being processed. */
109static Buffer incoming_packet;
110
111/* Scratch buffer for packet compression/decompression. */
112static Buffer compression_buffer;
113
114/* Flag indicating whether packet compression/decompression is enabled. */
115static int packet_compression = 0;
116
117/* Pointer to the random number generator state. */
118static RandomState *random_state;
119
120/* Flag indicating whether this module has been initialized. */
121static int initialized = 0;
122
123/* Set to true if the connection is interactive. */
124static int interactive_mode = 0;
125
126/* Maximum size of a packet. */
127static unsigned int max_packet_size = (sizeof(int) < 4) ? 32000 : 256000;
128
129/* Sets the descriptors used for communication.  Disables encryption until
130   packet_set_encryption_key is called. */
131
132void packet_set_connection(int fd_in, int fd_out, RandomState *state)
133{
134  connection_in = fd_in;
135  connection_out = fd_out;
136  random_state = state;
137  cipher_type = SSH_CIPHER_NONE;
138  cipher_set_key(&send_context, SSH_CIPHER_NONE, (unsigned char *)"", 0, 1);
139  cipher_set_key(&receive_context, SSH_CIPHER_NONE, (unsigned char *)"", 0, 0);
140  if (!initialized)
141    {
142      initialized = 1;
143      buffer_init(&input);
144      buffer_init(&output);
145      buffer_init(&outgoing_packet);
146      buffer_init(&incoming_packet);
147    }
148
149  /* Kludge: arrange the close function to be called from fatal(). */
150  fatal_add_cleanup((void (*)(void *))packet_close, NULL);
151
152  /* Initially set the connection interactive and enable keepalives.  The
153     values will be reset to their final values later (after
154     authentication). */
155  packet_set_interactive(1, 1);
156}
157
158/* Sets the connection into non-blocking mode. */
159
160void packet_set_nonblocking()
161{
162  /* Set the socket into non-blocking mode. */
163#if defined(O_NONBLOCK) && !defined(O_NONBLOCK_BROKEN)
164  if (fcntl(connection_in, F_SETFL, O_NONBLOCK) < 0)
165    error("fcntl O_NONBLOCK: %.100s", strerror(errno));
166#else /* O_NONBLOCK && !O_NONBLOCK_BROKEN */
167  if (fcntl(connection_in, F_SETFL, O_NDELAY) < 0)
168    error("fcntl O_NDELAY: %.100s", strerror(errno));
169#endif /* O_NONBLOCK && !O_NONBLOCK_BROKEN */
170
171  if (connection_out != connection_in)
172    {
173#if defined(O_NONBLOCK) && !defined(O_NONBLOCK_BROKEN)
174      if (fcntl(connection_out, F_SETFL, O_NONBLOCK) < 0)
175        error("fcntl O_NONBLOCK: %.100s", strerror(errno));
176#else /* O_NONBLOCK && !O_NONBLOCK_BROKEN */ 
177      if (fcntl(connection_out, F_SETFL, O_NDELAY) < 0)
178        error("fcntl O_NDELAY: %.100s", strerror(errno));
179#endif /* O_NONBLOCK && !O_NONBLOCK_BROKEN */
180    }
181}
182
183/* Returns the socket used for reading. */
184
185int packet_get_connection_in()
186{
187  return connection_in;
188}
189
190/* Returns the descriptor used for writing. */
191
192int packet_get_connection_out()
193{
194  return connection_out;
195}
196
197/* Closes the connection and clears and frees internal data structures. */
198
199void packet_close()
200{
201  if (!initialized)
202    return;
203  initialized = 0;
204  if (connection_in == connection_out)
205    {
206      shutdown(connection_out, 2);
207      close(connection_out);
208    }
209  else
210    {
211      close(connection_in);
212      close(connection_out);
213    }
214  buffer_free(&input);
215  buffer_free(&output);
216  buffer_free(&outgoing_packet);
217  buffer_free(&incoming_packet);
218  if (packet_compression)
219    {
220      buffer_free(&compression_buffer);
221      buffer_compress_uninit();
222    }
223}
224
225/* Sets remote side protocol flags. */
226
227void packet_set_protocol_flags(unsigned int protocol_flags)
228{
229  remote_protocol_flags = protocol_flags;
230  channel_set_options((protocol_flags & SSH_PROTOFLAG_HOST_IN_FWD_OPEN) != 0);
231}
232
233/* Returns the remote protocol flags set earlier by the above function. */
234
235unsigned int packet_get_protocol_flags()
236{
237  return remote_protocol_flags;
238}
239
240/* Starts packet compression from the next packet on in both directions.
241   Level is compression level 1 (fastest) - 9 (slow, best) as in gzip. */
242
243void packet_start_compression(int level)
244{
245  if (packet_compression)
246    fatal("Compression already enabled.");
247  packet_compression = 1;
248  buffer_init(&compression_buffer);
249  buffer_compress_init(level);
250}
251
252/* Encrypts the given number of bytes, copying from src to dest.
253   bytes is known to be a multiple of 8. */
254
255void packet_encrypt(CipherContext *cc, void *dest, void *src,
256                    unsigned int bytes)
257{
258  assert((bytes % 8) == 0);
259  cipher_encrypt(cc, dest, src, bytes);
260}
261
262/* Decrypts the given number of bytes, copying from src to dest.
263   bytes is known to be a multiple of 8. */
264
265void packet_decrypt(CipherContext *cc, void *dest, void *src,
266                    unsigned int bytes)
267{
268  assert((bytes % 8) == 0);
269  cipher_decrypt(cc, dest, src, bytes);
270}
271
272/* Causes any further packets to be encrypted using the given key.  The same
273   key is used for both sending and reception.  However, both directions
274   are encrypted independently of each other. */
275
276void packet_set_encryption_key(const unsigned char *key, unsigned int keylen,
277                               int cipher, int is_client)
278{
279  cipher_type = cipher;
280  if (cipher == SSH_CIPHER_ARCFOUR)
281    {
282      if (is_client)
283        { /* In client: use first half for receiving, second for sending. */
284          cipher_set_key(&receive_context, cipher, key, keylen / 2, 0);
285          cipher_set_key(&send_context, cipher, key + keylen / 2,
286                         keylen / 2, 1);
287        }
288      else
289        { /* In server: use first half for sending, second for receiving. */
290          cipher_set_key(&receive_context, cipher, key + keylen / 2,
291                         keylen / 2, 0);
292          cipher_set_key(&send_context, cipher, key, keylen / 2, 1);
293        }
294    }
295  else
296    {
297      /* All other ciphers use the same key in both directions for now. */
298      cipher_set_key(&receive_context, cipher, key, keylen, 0);
299      cipher_set_key(&send_context, cipher, key, keylen, 1);
300    }
301}
302
303/* Starts constructing a packet to send. */
304
305void packet_start(int type)
306{
307  char buf[9];
308
309  buffer_clear(&outgoing_packet);
310  memset(buf, 0, 8);
311  buf[8] = type;
312  buffer_append(&outgoing_packet, buf, 9);
313}
314
315/* Appends a character to the packet data. */
316
317void packet_put_char(int value)
318{
319  char ch = value;
320  buffer_append(&outgoing_packet, &ch, 1);
321}
322
323/* Appends an integer to the packet data. */
324
325void packet_put_int(unsigned int value)
326{
327  buffer_put_int(&outgoing_packet, value);
328}
329
330/* Appends a string to packet data. */
331
332void packet_put_string(const char *buf, unsigned int len)
333{
334  buffer_put_string(&outgoing_packet, buf, len);
335}
336
337/* Appends an arbitrary precision integer to packet data. */
338
339void packet_put_mp_int(MP_INT *value)
340{
341  buffer_put_mp_int(&outgoing_packet, value);
342}
343
344/* Finalizes and sends the packet.  If the encryption key has been set,
345   encrypts the packet before sending. */
346 
347void packet_send()
348{
349  char buf[8], *cp;
350  int i, padding, len;
351  unsigned long checksum;
352
353  if (buffer_len(&outgoing_packet) >= max_packet_size - 30)
354    fatal("packet_send: sending too big a packet: size %u, limit %u.",
355          buffer_len(&outgoing_packet), max_packet_size);
356
357  /* If using packet compression, compress the payload of the outgoing
358     packet. */
359  if (packet_compression)
360    {
361      buffer_clear(&compression_buffer);
362      buffer_consume(&outgoing_packet, 8); /* Skip padding. */
363      buffer_append(&compression_buffer, "\0\0\0\0\0\0\0\0", 8); /* padding */
364      buffer_compress(&outgoing_packet, &compression_buffer);
365      buffer_clear(&outgoing_packet);
366      buffer_append(&outgoing_packet, buffer_ptr(&compression_buffer),
367                    buffer_len(&compression_buffer));
368    }
369
370  /* Compute packet length without padding (add checksum, remove padding). */
371  len = buffer_len(&outgoing_packet) + 4 - 8;
372 
373  /* Insert padding. */
374  padding = 8 - len % 8;
375  if (cipher_type != SSH_CIPHER_NONE)
376    {
377      cp = buffer_ptr(&outgoing_packet);
378      for (i = 0; i < padding; i++)
379        cp[7 - i] = random_get_byte(random_state);
380    }
381  buffer_consume(&outgoing_packet, 8 - padding);
382 
383  /* Add check bytes. */
384  checksum = crc32((unsigned char *)buffer_ptr(&outgoing_packet),
385                   buffer_len(&outgoing_packet));
386  PUT_32BIT(buf, checksum);
387  buffer_append(&outgoing_packet, buf, 4);
388
389#ifdef PACKET_DEBUG
390  fprintf(stderr, "packet_send plain: ");
391  buffer_dump(&outgoing_packet);
392#endif
393
394  /* Append to output. */
395  PUT_32BIT(buf, len);
396  buffer_append(&output, buf, 4);
397  buffer_append_space(&output, &cp, buffer_len(&outgoing_packet));
398  packet_encrypt(&send_context, cp, buffer_ptr(&outgoing_packet),
399                 buffer_len(&outgoing_packet));
400 
401#ifdef PACKET_DEBUG
402  fprintf(stderr, "encrypted: "); buffer_dump(&output);
403#endif
404
405  buffer_clear(&outgoing_packet);
406
407  /* Note that the packet is now only buffered in output.  It won\'t be
408     actually sent until packet_write_wait or packet_write_poll is called. */
409}
410
411/* Waits until a packet has been received, and returns its type.  Note that
412   no other data is processed until this returns, so this function should
413   not be used during the interactive session. */
414
415int packet_read()
416{
417  int type, len;
418  fd_set set;
419  char buf[8192];
420
421  /* Since we are blocking, ensure that all written packets have been sent. */
422  packet_write_wait();
423
424  /* Stay in the loop until we have received a complete packet. */
425  for (;;)
426    {
427      /* Try to read a packet from the buffer. */
428      type = packet_read_poll();
429      /* If we got a packet, return it. */
430      if (type != SSH_MSG_NONE)
431        return type;
432      /* Otherwise, wait for some data to arrive, add it to the buffer,
433         and try again. */
434      FD_ZERO(&set);
435      FD_SET(connection_in, &set);
436      /* Wait for some data to arrive. */
437      select(connection_in + 1, &set, NULL, NULL, NULL);
438      /* Read data from the socket. */
439      len = read(connection_in, buf, sizeof(buf));
440      if (len == 0)
441        fatal_severity(SYSLOG_SEVERITY_INFO,
442                       "Connection closed by remote host.");
443      if (len < 0)
444        {
445          if (errno == EAGAIN || errno == EWOULDBLOCK)
446            continue;
447          fatal_severity(SYSLOG_SEVERITY_INFO,
448                         "Read from socket failed: %.100s", strerror(errno));
449        }
450      /* Append it to the buffer. */
451      packet_process_incoming(buf, len);
452    }
453  /*NOTREACHED*/
454}
455
456/* Waits until a packet has been received, verifies that its type matches
457   that given, and gives a fatal error and exits if there is a mismatch. */
458
459void packet_read_expect(int expected_type)
460{
461  int type;
462
463  type = packet_read();
464  if (type != expected_type)
465    packet_disconnect("Protocol error: expected packet type %d, got %d",
466                      expected_type, type);
467}
468
469/* Checks if a full packet is available in the data received so far via
470   packet_process_incoming.  If so, reads the packet; otherwise returns
471   SSH_MSG_NONE.  This does not wait for data from the connection.
472   
473   SSH_MSG_DISCONNECT is handled specially here.  Also,
474   SSH_MSG_IGNORE messages are skipped by this function and are never returned
475   to higher levels. */
476
477int packet_read_poll()
478{
479  unsigned int len, padded_len;
480  unsigned char *ucp;
481  char buf[8], *cp;
482  unsigned long checksum, stored_checksum;
483 
484 restart:
485
486  /* Check if input size is less than minimum packet size. */
487  if (buffer_len(&input) < 4 + 8)
488    return SSH_MSG_NONE;
489  /* Get length of incoming packet. */
490  ucp = (unsigned char *)buffer_ptr(&input);
491  len = GET_32BIT(ucp);
492  if (len < 1 + 2 + 2 || len > 256*1024)
493    packet_disconnect("Bad packet length %u.", len);
494  padded_len = (len + 8) & ~7;
495
496  /* Check if the packet has been entirely received. */
497  if (buffer_len(&input) < 4 + padded_len)
498    return SSH_MSG_NONE;
499
500  /* The entire packet is in buffer. */
501
502  /* Consume packet length. */
503  buffer_consume(&input, 4);
504
505/* Confirm that packet is empty after all data is processed from it. Calls
506   fatal buffer is not empty. */
507  if (buffer_len(&incoming_packet) != 0)
508    packet_disconnect("Junk data left to incoming packet buffer after all data processed");
509 
510  /* Copy data to incoming_packet. */
511  buffer_clear(&incoming_packet);
512  buffer_append_space(&incoming_packet, &cp, padded_len);
513  packet_decrypt(&receive_context, cp, buffer_ptr(&input), padded_len);
514  buffer_consume(&input, padded_len);
515
516#ifdef PACKET_DEBUG
517  fprintf(stderr, "read_poll plain: "); buffer_dump(&incoming_packet);
518#endif
519 
520  /* Compute packet checksum. */
521  checksum = crc32((unsigned char *)buffer_ptr(&incoming_packet),
522                   buffer_len(&incoming_packet) - 4);
523
524  /* Skip padding. */
525  buffer_consume(&incoming_packet, 8 - len % 8);
526
527  /* Test check bytes. */
528  assert(len == buffer_len(&incoming_packet));
529  ucp = (unsigned char *)buffer_ptr(&incoming_packet) + len - 4;
530  stored_checksum = GET_32BIT(ucp);
531  if (checksum != stored_checksum)
532    packet_disconnect("Corrupted check bytes on input.");
533  buffer_consume_end(&incoming_packet, 4);
534
535  /* If using packet compression, decompress the packet. */
536  if (packet_compression)
537    {
538      buffer_clear(&compression_buffer);
539      buffer_uncompress(&incoming_packet, &compression_buffer);
540      buffer_clear(&incoming_packet);
541      buffer_append(&incoming_packet, buffer_ptr(&compression_buffer),
542                    buffer_len(&compression_buffer));
543    }
544
545  /* Get packet type. */
546  buffer_get(&incoming_packet, &buf[0], 1);
547
548  /* Handle disconnect message. */
549  if ((unsigned char)buf[0] == SSH_MSG_DISCONNECT)
550    fatal_severity(SYSLOG_SEVERITY_INFO, "%.900s", packet_get_string(NULL));
551
552  /* Ignore ignore messages. */
553  if ((unsigned char)buf[0] == SSH_MSG_IGNORE)
554    goto restart;
555
556  /* Send debug messages as debugging output. */
557  if ((unsigned char)buf[0] == SSH_MSG_DEBUG)
558    {
559      char *str;
560
561      str = packet_get_string(NULL);
562      if (*str == '*')          /* Magical kludge to force displaying
563                                   debug messages with '*' anyway, even
564                                   if not in verbose mode. */
565        {
566          error("Remote: %.900s", str);
567        }
568      else
569        {
570          debug("Remote: %.900s", str);
571        }
572      xfree(str);
573      goto restart;
574    }
575
576  /* Return type. */
577  return (unsigned char)buf[0];
578}
579 
580/* Buffers the given amount of input characters.  This is intended to be
581   used together with packet_read_poll. */
582
583void packet_process_incoming(const char *buf, unsigned int len)
584{
585  buffer_append(&input, buf, len);
586}
587
588/* Returns the number of bytes left in the incoming packet. */
589
590unsigned int packet_get_len()
591{
592  return buffer_len(&incoming_packet);
593}
594
595/* Returns a character from the packet. */
596
597unsigned int packet_get_char()
598{
599  char ch;
600  buffer_get(&incoming_packet, &ch, 1);
601  return (unsigned char)ch;
602}
603
604/* Returns an integer from the packet data. */
605
606unsigned int packet_get_int()
607{
608  return buffer_get_int(&incoming_packet);
609}
610
611/* Returns an arbitrary precision integer from the packet data.  The integer
612   must have been initialized before this call. */
613
614void packet_get_mp_int(MP_INT *value)
615{
616  buffer_get_mp_int(&incoming_packet, value);
617}
618
619/* Returns a string from the packet data.  The string is allocated using
620   xmalloc; it is the responsibility of the calling program to free it when
621   no longer needed.  The length_ptr argument may be NULL, or point to an
622   integer into which the length of the string is stored. */
623
624char *packet_get_string(unsigned int *length_ptr)
625{
626  return buffer_get_string(&incoming_packet, length_ptr);
627}
628
629/* Clears incoming data buffer */
630
631void packet_get_all()
632{
633  buffer_clear(&incoming_packet);
634}
635
636/* Sends a diagnostic message from the server to the client.  This message
637   can be sent at any time (but not while constructing another message).
638   The message is printed immediately, but only if the client is being
639   executed in verbose mode.  These messages are primarily intended to
640   ease debugging authentication problems.   The length of the formatted
641   message must not exceed 1024 bytes.  This will automatically call
642   packet_write_wait. */
643
644void packet_send_debug(const char *fmt, ...)
645{
646  char buf[1024];
647  va_list args;
648 
649  va_start(args, fmt);
650  vsprintf(buf, fmt, args);
651  va_end(args);
652 
653  packet_start(SSH_MSG_DEBUG);
654  packet_put_string(buf, strlen(buf));
655  packet_send();
656  packet_write_wait();
657}
658
659/* Logs the error plus constructs and sends a disconnect
660   packet, closes the connection, and exits.  This function never returns.
661   The error message should not contain a newline.  The length of the
662   formatted message must not exceed 1024 bytes. */
663
664void packet_disconnect(const char *fmt, ...)
665{
666  char buf[1024];
667  va_list args;
668  static int disconnecting = 0;
669  if (disconnecting) /* Guard against recursive invocations. */
670    fatal("packet_disconnect called recursively.");
671  disconnecting = 1;
672
673  /* Format the message.  Note that the caller must make sure the message
674     is of limited size. */
675  va_start(args, fmt);
676  vsprintf(buf, fmt, args);
677  va_end(args);
678
679  /* Send the disconnect message to the other side, and wait for it to get
680     sent. */
681  packet_start(SSH_MSG_DISCONNECT);
682  packet_put_string(buf, strlen(buf));
683  packet_send();
684  packet_write_wait();
685
686  /* Stop listening for connections. */
687  channel_stop_listening();
688 
689  /* Close the connection. */
690  packet_close();
691
692  /* Display the error locally and exit. */
693  fatal("Local: %.100s", buf);
694}
695
696/* Checks if there is any buffered output, and tries to write some of the
697   output. */
698
699void packet_write_poll()
700{
701  int len = buffer_len(&output);
702  if (len > 0)
703    {
704      len = write(connection_out, buffer_ptr(&output), len);
705      if (len <= 0)
706        if (errno == EAGAIN || errno == EWOULDBLOCK)
707          return;
708        else
709          fatal_severity(SYSLOG_SEVERITY_INFO,
710                         "Write failed: %.100s", strerror(errno));
711      buffer_consume(&output, len);
712    }
713}
714
715/* Calls packet_write_poll repeatedly until all pending output data has
716   been written. */
717
718void packet_write_wait()
719{
720  packet_write_poll();
721  while (packet_have_data_to_write())
722    {
723      fd_set set;
724      FD_ZERO(&set);
725      FD_SET(connection_out, &set);
726      select(connection_out + 1, NULL, &set, NULL, NULL);
727      packet_write_poll();
728    }
729}
730
731/* Returns true if there is buffered data to write to the connection. */
732
733int packet_have_data_to_write()
734{
735  return buffer_len(&output) != 0;
736}
737
738/* Returns true if there is not too much data to write to the connection. */
739
740int packet_not_very_much_data_to_write()
741{
742  if (interactive_mode || sizeof(int) < 4)
743    return buffer_len(&output) < 16384;
744  else
745    return buffer_len(&output) < 128*1024;
746}
747
748/* Informs that the current session is interactive.  Sets IP flags for that. */
749
750void packet_set_interactive(int interactive, int keepalives)
751{
752  int on = 1, off = 0;
753
754  /* Record that we are in interactive mode. */
755  interactive_mode = interactive;
756
757  /* Only set socket options if using a socket (as indicated by the descriptors
758     being the same). */
759  if (connection_in != connection_out)
760    return;
761
762  if (keepalives)
763    {
764      /* Set keepalives if requested. */
765      if (setsockopt(connection_in, SOL_SOCKET, SO_KEEPALIVE, (void *)&on,
766                     sizeof(on)) < 0)
767        error("setsockopt SO_KEEPALIVE: %.100s", strerror(errno));
768    }
769  else
770    {
771      /* Clear keepalives if we don't want them. */
772      if (setsockopt(connection_in, SOL_SOCKET, SO_KEEPALIVE, (void *)&off,
773                     sizeof(off)) < 0)
774        error("setsockopt SO_KEEPALIVE off: %.100s", strerror(errno));
775    }
776 
777  if (interactive)
778    {
779      /* Set IP options for an interactive connection.  Use IPTOS_LOWDELAY
780         and TCP_NODELAY. */
781#ifdef IPTOS_LOWDELAY
782      int lowdelay = IPTOS_LOWDELAY;
783      if (setsockopt(connection_in, IPPROTO_IP, IP_TOS, (void *)&lowdelay,
784                     sizeof(lowdelay)) < 0)
785        error("setsockopt IPTOS_LOWDELAY: %.100s", strerror(errno));
786#endif /* IPTOS_LOWDELAY */
787#ifdef TCP_NODELAY
788      if (setsockopt(connection_in, IPPROTO_TCP, TCP_NODELAY, (void *)&on,
789                     sizeof(on)) < 0)
790        error("setsockopt TCP_NODELAY: %.100s", strerror(errno));
791#endif /* TCP_NODELAY */
792    }
793  else
794    {
795      /* Set IP options for a non-interactive connection.  Use
796         IPTOS_THROUGHPUT. */
797#ifdef IPTOS_THROUGHPUT
798      int throughput = IPTOS_THROUGHPUT;
799      if (setsockopt(connection_in, IPPROTO_IP, IP_TOS, (void *)&throughput,
800                     sizeof(throughput)) < 0)
801        error("setsockopt IPTOS_THROUGHPUT: %.100s", strerror(errno));
802#endif /* IPTOS_THROUGHPUT */
803#ifdef TCP_NODELAY
804      if (setsockopt(connection_in, IPPROTO_TCP, TCP_NODELAY, (void *)&off,
805                     sizeof(off)) < 0)
806        error("setsockopt TCP_NODELAY: %.100s", strerror(errno));
807#endif /* TCP_NODELAY */
808    }
809}
810
811/* Returns true if the current connection is interactive. */
812
813int packet_is_interactive()
814{
815  return interactive_mode;
816}
817
818/* Sets the maximum packet size that can be sent to the other side. */
819
820void packet_set_max_size(unsigned int max_size)
821{
822  max_packet_size = max_size;
823}
824
825/* Returns the maximum packet size that can be sent to the other side. */
826
827unsigned int packet_max_size()
828{
829  return max_packet_size;
830}
Note: See TracBrowser for help on using the repository browser.