/*

packet.h

Author: Tatu Ylonen <ylo@cs.hut.fi>

Copyright (c) 1995 Tatu Ylonen <ylo@cs.hut.fi>, Espoo, Finland
                   All rights reserved

Created: Sat Mar 18 02:02:14 1995 ylo

Interface for the packet protocol functions.

*/

/*
 * $Id: packet.h,v 1.6 1998/03/27 16:59:16 kivinen Exp $
 * $Log: packet.h,v $
 * Revision 1.6  1998/03/27  16:59:16  kivinen
 * 	Added socks.h include.
 *
 * Revision 1.5  1997/04/05 17:29:14  ylo
 * 	Added packet_get_len (returns the remaining length of incoming
 * 	packet).
 *
 * Revision 1.4  1997/03/26 07:11:41  kivinen
 * 	Fixed prototypes.
 *
 * Revision 1.3  1997/03/19 19:26:16  kivinen
 * 	Added packet_get_all prototype.
 *
 * Revision 1.2  1996/11/24 08:24:14  kivinen
 * 	Fixed the comment of packet_send_debug.
 *
 * Revision 1.1.1.1  1996/02/18 21:38:10  ylo
 * 	Imported ssh-1.2.13.
 *
 * Revision 1.4  1995/09/24  23:59:20  ylo
 * 	Added packet_get_protocol_flags.
 *
 * Revision 1.3  1995/07/27  02:17:53  ylo
 * 	Pass as argument to packet_set_encryption_key whether running
 * 	as the client or the server.
 *
 * Revision 1.2  1995/07/13  01:27:54  ylo
 * 	Removed "Last modified" header.
 * 	Added cvs log.
 *
 * $Endlog$
 */

#ifndef PACKET_H
#define PACKET_H

#include <gmp.h>
#include "randoms.h"

#if defined(SOCKS5) && defined(HAVE_SOCKS_H)
#include <socks.h>
#endif

/* Sets the socket used for communication.  Disables encryption until
   packet_set_encryption_key is called.  It is permissible that fd_in
   and fd_out are the same descriptor; in that case it is assumed to
   be a socket. */
void packet_set_connection(int fd_in, int fd_out, RandomState *state);

/* just set the file descriptors */
void packet_set_fds(int fd_in, int fd_out);

/* Initialize the packet mechanism */
void packet_init(RandomState *state);

/* Puts the connection file descriptors into non-blocking mode. */
void packet_set_nonblocking(void);

/* Returns the file descriptor used for input. */
int packet_get_connection_in(void);

/* Returns the file descriptor used for output. */
int packet_get_connection_out(void);

/* Closes the connection (both descriptors) and clears and frees
   internal data structures. */ 
void packet_close(void);

/* Causes any further packets to be encrypted using the given key.  The same
   key is used for both sending and reception.  However, both directions
   are encrypted independently of each other.  Cipher types are
   defined in ssh.h. */
void packet_set_encryption_key(const unsigned char *key, unsigned int keylen,
			       int cipher_type, int is_client);

/* Sets remote side protocol flags for the current connection.  This can
   be called at any time. */
void packet_set_protocol_flags(unsigned int flags);

/* Returns the remote protocol flags set earlier by the above function. */
unsigned int packet_get_protocol_flags(void);

/* Enables compression in both directions starting from the next packet. */
void packet_start_compression(int level);
int  packet_get_compression(void);

/* Informs that the current session is interactive.  Sets IP flags for optimal
   performance in interactive use. */
void packet_set_interactive(int interactive, int keepalives);

/* Returns true if the current connection is interactive. */
int packet_is_interactive(void);

/* Starts constructing a packet to send. */
void packet_start(int type);

/* Appends a character to the packet data. */
void packet_put_char(int ch);

/* Appends an integer to the packet data. */
void packet_put_int(unsigned int value);

/* Appends an arbitrary precision integer to packet data. */
void packet_put_mp_int(MP_INT *value);

/* Appends a string to packet data. */
void packet_put_string(const char *buf, unsigned int len);

/* Finalizes and sends the packet.  If the encryption key has been set,
   encrypts the packet before sending. */
void packet_send(void);

/* Waits until a packet has been received, and returns its type. */
int packet_read(void);

/* This is just packet_read wrapped with a timer */
int packet_read_timer(unsigned long timer);

/* This is just packet_read_expect wrapped with a timer */
int packet_read_expect_timer(int type, unsigned long timer);

/* Oh, here we insist on reading something. What we do here is send
   several packets, as much as retry allows us to, and after each failure
   send an SSH_MSG_IGNORE packet. This is done to stimulate the packet
   loss recovery mechanism */
int packet_read_stimulate(int retry, unsigned long timer);

/* We do the same thing we do in packet_read_stimulate, just in a 
   packet_read_expect kind of interface */
void packet_read_expect_stimulate(int expected_type, int retry, 
				  unsigned long timer);

/* Waits until a packet has been received, verifies that its type matches
   that given, and gives a fatal error and exits if there is a mismatch. */
void packet_read_expect(int type);

/* Checks if a full packet is available in the data received so far via
   packet_process_incoming.  If so, reads the packet; otherwise returns
   SSH_MSG_NONE.  This does not wait for data from the connection. 
   
   SSH_MSG_DISCONNECT is handled specially here.  Also,
   SSH_MSG_IGNORE messages are skipped by this function and are never returned
   to higher levels. */
int packet_read_poll(void);

/* Buffers the given amount of input characters.  This is intended to be
   used together with packet_read_poll. */
void packet_process_incoming(const char *buf, unsigned int len);

/* Returns the remaining number of bytes in the incoming packet. */
unsigned int packet_get_len(void);

/* Returns a character (0-255) from the packet data. */
unsigned int packet_get_char(void);

/* Returns an integer from the packet data. */
unsigned int packet_get_int(void);

/* Returns an arbitrary precision integer from the packet data.  The integer
   must have been initialized before this call. */
void packet_get_mp_int(MP_INT *value);

/* Returns a string from the packet data.  The string is allocated using
   xmalloc; it is the responsibility of the calling program to free it when
   no longer needed.  The length_ptr argument may be NULL, or point to an
   integer into which the length of the string is stored. */
char *packet_get_string(unsigned int *length_ptr);

/* Clears incoming data buffer */
void packet_get_all(void);
     
/* clears the output buffer */
void packet_clear_output(void);

/* Logs the error in syslog using LOG_INFO, constructs and sends a disconnect
   packet, closes the connection, and exits.  This function never returns.
   The error message should not contain a newline.  The total length of the
   message must not exceed 1024 bytes. */
#ifndef NO_LOGGING
void packet_disconnect(const char *fmt, ...);
#else
void _packet_disconnect(const char *fmt, ...);
#define packet_disconnect(format, arg...) _packet_disconnect("big mess of a failure, bye bye")
#endif

/* just set a SSH_MSG_DISCONNECT to the other side */
void packet_say_goodbye(void);

/* Sends a diagnostic message to the other side.  This message
   can be sent at any time (but not while constructing another message).
   The message is printed immediately, but only if the client is being
   executed in verbose mode. If the first character of the message is '*'
   the message is printed to stderr always.
   These messages are primarily intended to ease debugging authentication
   problems. The total length of the message must not exceed 1024 bytes. This
   will automatically call packet_write_wait. If the remote side protocol flags
   do not indicate that it supports SSH_MSG_DEBUG, this will do nothing. */
#ifndef NO_LOGGING
void packet_send_debug(const char *fmt, ...);
#else
#define packet_send_debug(format, args...)
#endif

/* Checks if there is any buffered output, and tries to write some of the
   output. */
int packet_write_poll(void);

/* Waits until all pending output data has been written. */
void packet_write_wait(void);

/* transmit any buffered data through icmp. this is a fragile function
   in certain conditions, so it would be nice if the caller would check
   if connection_out is available for writing */
int packet_esp_transmit(void);

/* recieve data through icmp */
int packet_esp_receive(void);

/* recieve data through icmp */
int packet_esp_pcap_handlepacket(fd_set *readfds);

/* Make a virutal 'icmp' connection. What we do here is exchange 
   transmit and receive ids with the server side. Returns true
   if the exchange worked, else returns zero */
int packet_esp_connect(int sock, struct sockaddr_in *hostaddr, 
			   int proto, int port);

/* Returns true if there is buffered data to write to the connection. */
int packet_have_data_to_write(void);

/* Returns true if there is not too much data to write to the connection. */
int packet_not_very_much_data_to_write(void);

/* Sets the maximum packet size that can be sent to the other side. */
void packet_set_max_size(unsigned int max_size);

/* Returns the maximum packet size that can be sent to the other side. */
unsigned int packet_max_size(void);

/* Stores tty modes from the fd into current packet. */
void tty_make_modes(int fd);

/* Parses tty modes for the fd from the current packet. */
void tty_parse_modes(int fd);


#endif /* PACKET_H */
