#ifndef _CHANNELS_H_d5a6e5ac_ #define _CHANNELS_H_d5a6e5ac_ typedef struct chanops CHANOPS; typedef struct nonchanops NONCHANOPS; typedef struct chanopen_ret CHANOPEN_RET; #include "bpp.h" #include "str.h" /* * Operations on a channel. * * These have a void * "arg". This is an arbitrary callback argument, * passed in when the channel is created, to keep the channel client * from having to constantly look things up by channel number. It is * omitted from the individual descriptions of the callbacks. */ struct chanops { /* * Called when the open succeeds or fails. Arglist: * (void *arg, int channel_number, int status) * where status is an OPENSTAT_* from below. It is safe to assume * that a zero status constitutes success and a nonzero status * failure; also, it is safe to call the other channel functions * while inside a success callback call - the channel is completely * ready to operate at that point. When a failure callback is made, * the channel is not functional and has already been destroyed; the * channel number passed is no longer a valid channel number. */ void (*opendone)(void *, int, int); /* * Called to handle received data. Arglist: * (void *arg, int chan, int ext, unsigned int code, const void *buf, int len) * chan is the channel number. For normal data, ext is zero and * code is meaningless; for extended data, ext is nonzero and code * is the data type code. buf and len describe the data itself. * * len will never be zero in normal operation. When EOF is received, * this is called once with all but the first argument 0. */ void (*gotdata)(void *, int, int, unsigned int, const void *, int); /* * Called when a window adjustment is received. Arglist: * (void *arg, int chan, unsigned int addl, unsigned int newwin) * chan is the channel number. addl is the number of bytes of * window added; newwin is the new send window. On a successful * open this will be called immedately after the success callback, * as if the connection started with a zero window. Note that addl * may occasionally be zero (and the window unchanged). */ void (*morewin)(void *, int, unsigned int, unsigned int); /* * Called when a CHANNEL_REQUEST is received. Arglist: * (void *arg, int chan, ROSTR req, int wantreply, const void *rest, int restlen) * chan is the channel number. req is a ROSTR giving the request * string. wantreply is nonzero if a reply is requested, or zero if * no specific reply is requested. rest and restlen describe the * request-specific portion of the packet, suitable for passing to * parse_data(). * * The storage areas pointed to by the second and fourth arguments * are owned by the caller and must not be modified; they must be * considered to go invalid once the function returns - they must be * copied if they are to be saved. * * Return value is one of the CHANREQRET_* values. */ int (*chanreq)(void *, int, ROSTR, int, const void *, int); /* Request completely processed, including sending any reply. */ #define CHANREQRET_DONE 1 /* Request successful, no reply yet sent. */ #define CHANREQRET_OK 2 /* Request failed, no reply yet sent. */ #define CHANREQRET_FAIL 3 /* Request not recognized. */ #define CHANREQRET_UNK 4 /* * Called when a CHANNEL_CLOSE is received. Arglist: * (void *arg, int chan, int final) * chan is the channel number. If chan_close() has already been * called on the channel, final will be nonzero, and the channel has * finally been destroyed; if not, final will be zero, and the * channel remains active for output until chan_close() is called on * it (which may be done from within this routine). */ void (*closed)(void *, int, int); } ; /* * Operations that are not channel-specific. */ struct nonchanops { /* * Called when a CHANNEL_OPEN packet is received. Arglist: * (ROSTR type, int chan, const void *rest, int restlen) * type is the type string from the request; rest and restlen are * the type-specific data blob, suitable for passing to parse_data. * chan is the local channel number which has been assigned for this * channel. * * This call returns nothing itself. To complete the open * transaction, a call to chan_open_ok or chan_open_fail must be * made (which may be done from within this routine). */ void (*chanopen)(ROSTR, int, const void *, int); /* * Called when a GLOBAL_REQUEST packet is received. Arglist: * (ROSTR name, int wantrepl, const void *rest, int restlen) * where name is the request name, wantrepl is the want-reply * boolean, and rest and restlen are the request-specific part of * the packet, suitable for passing to parse_data. * * The return value is one of the GLOBALREQ_* values. */ int (*globalreq)(ROSTR, int, const void *, int); /* Completely processed, including sending any reply called for. */ #define GLOBALREQ_DONE 1 /* Request OK, no reply sent; if want-reply is true, send an empty success. */ #define GLOBALREQ_OK 2 /* Request failed, no reply sent. */ #define GLOBALREQ_FAIL 3 /* Request unrecognized. */ #define GLOBALREQ_UNK 4 } ; /* * Open a channel to the peer. * * Values for first arg are CHANTYPE_* from below. Second arg is a * void * passed to callbacks as described in the comment above * "struct chanops". Third arg is a (pointer to a) CHANOPS function * vector. The remaining args, if any, depend on the first argument. * * The channel number is returned from chan_open as well as being * passed to the callback routines. If the open completion callback * indicates failure, the channel number is has become invalid and * must not be used. Channel numbers are arbitrary ints; code should * not assume anything about them, except that CHAN_NO_CHANNEL is * available as a value which will never be a valid channel number. */ #define CHAN_NO_CHANNEL (-1) extern int chan_open(int, void *, const CHANOPS *, ...); /* Complete a remote channel-open request successfully. Arguments: channel number, type-specific body data, and the ops vector and callback arg for the new channel. */ extern void chan_open_ok(int, ROSTR, const CHANOPS *, void *); /* Complete a remote channel-open request unsuccessfully. Arguments: channel number, result code, additional text string, and language tag string. */ extern void chan_open_fail(int, unsigned int, ROSTR, ROSTR); /* CHANTYPE_* values */ /* Interactive session. No args. */ #define CHANTYPE_SESSION 1 /* Forwarded X connection. Args: const char * Source address (string form, eg "10.20.30.40") unsigned short int Source port */ #define CHANTYPE_X 2 /* Forwarded TCP connection, forwarded by peer request. Args: const char * Address connected to unsigned short int Port connected to const char * Originator address unsigned short int Originator port */ #define CHANTYPE_FWD_TCP 3 /* Forwarded TCP conenction, forwarded by local decision. Args: const char * Host to connect to (FQDN or address string) unsigned short int Port to connect to const char * Originator address unsigned short int Originator port */ #define CHANTYPE_DIR_TCP 4 /* OPENSTAT_* values */ /* Success. Channel is available for use. */ #define OPENSTAT_SUCCESS 0 /* Failure. The reason code was SSH_OPEN_ADMINISTRATIVELY_PROHIBITED. */ #define OPENSTAT_ADMIN_PROHIB 1 /* Failure. The reason code was SSH_OPEN_CONNECT_FAILED. */ #define OPENSTAT_CONNECT_FAILED 2 /* Failure. The reason code was SSH_OPEN_UNKNOWN_CHANNEL_TYPE */ #define OPENSTAT_BAD_TYPE 3 /* Failure. The reason code was SSH_OPEN_RESOURCE_SHORTAGE */ #define OPENSTAT_RESOURCE 4 /* Failure. The reason code was not recognized. */ #define OPENSTAT_UNKNOWN 5 /* * Calls to manipulate an established channel. It is an error to call * these before the channel's open has succeeded. */ /* Query window space. Returns the number of bytes receivable before window enlargement. Argument: channel number. */ extern unsigned int chan_get_rwin(int); /* Add window space. Channels start with zero window advertised. Arguments: (int chan_no, unsigned int additional_space) It is an error to call this such as to increase the abstract window-available value above 0xffffffff. It is also an error to call this after receiving EOF. */ extern void chan_add_rwin(int, unsigned int); /* Query window space. Returns the number of bytes sendable before window enlargement. Argument: channel number. It is not an error to call this after sending EOF, but it always returns zero then. */ extern unsigned int chan_get_wwin(int); /* Construct the beginning of a CHANNEL_REQUEST message. Returns a pointer to just after the request-independent part of the message. The ROSTR is the request type. The want-reply boolean is not specified here, but rather by the choice of send routine. */ extern unsigned char *chan_req_hdr(int, ROSTR); /* Send a CHANNEL_REQUEST message, with reply expected. First arg is channel number. Second arg points at end of message. Third arg is a callback, called when the request succeeds (with arg CREQ_OK) or fails (with arg CREQ_FAIL), or if the channel is destroyed before either happens, with arg CREQ_CLOSE. The fourth arg to chan_send_req_reply forms the second arg to the callback. */ extern void chan_send_req_reply(int, unsigned char *, void (*)(int, void *), void *); #define CREQ_OK 1 #define CREQ_FAIL 2 #define CREQ_CLOSE 3 /* Send a CHANNEL_REQUEST message, with no reply expected. First arg is channel number. Second arg points at end of message. */ extern void chan_send_req_blind(int, unsigned char *); /* Send data on a channel. Args are as for the data callback argument to chan_open(), above, except as noted. It is an error to try to send more data than the peer has window space for (see chan_get_wwin(), above). Sending zero bytes is not an error and does not send anything (in particular, does not send EOF). It is an error to call this after sending EOF. */ extern void chan_send_data(int, int, unsigned int, const void *, int); /* Declare EOF for sending on a channel. Arg is channel number. */ extern void chan_send_eof(int); /* Send a CHANNEL_SUCCESS (second arg nonzero) or CHANNEL_FAILURE (zero) on a channel. (First arg is channel number.) */ extern void chan_reqrep(int, int); /* Send a close on a channel. If a close has been received on the channel (indicated by a call through the closed member of the ops vector), this does final channel teardown and returns nonzero; otherwise, this initiates the process, the channel remains valid until the peer's close arrives (at which point teardown occurs), and this call returns zero. (Either way, no further output calls on the channel may be done.) */ extern int chan_close(int); /* * Calls not related to specific channels. */ /* Return the LAYER pointer for the channels layer. */ extern LAYER *chan_layer(void); /* Set the non-channel-specific ops vector. */ extern void set_globalops(const NONCHANOPS *); /* Construct the beginning of a GLOBAL_REQUEST message. Returns a pointer to just after the header. First arg is the request name. want-reply is always true, to ensure we can tell which reply goes with which request. */ extern unsigned char *global_req_hdr(ROSTR); /* Send a GLOBAL_REQUEST message. First arg points at end of message. Second arg is a callback, called when the request succeeds (with first arg GREQ_OK) or fails (GREQ_FAIL) and second arg equal to the third arg to global_send_req(). In the GREQ_OK case, the request-specific data from the reply are passed in the third and fourth callback args; in the GREQ_FAIL case, those arguments are meaningless. The fourth callback arg is the third arg to global_send_req(). */ extern void global_send_req(unsigned char *, void (*)(int, void *, const void *, int), void *); #define GREQ_OK 1 #define GREQ_FAIL 2 extern LAYERDESC layer_channels; #endif