#ifndef _CHANNELS_H_3fd89537_ #define _CHANNELS_H_3fd89537_ /* This file is in the public domain. */ #include typedef struct chanops CHANOPS; typedef struct nonchanops NONCHANOPS; typedef struct chanopen_ret CHANOPEN_RET; #include "bpp.h" #include "str.h" /* * Channel numbers in this interface are ints. In the protocol these * are uint32, but we use small nonnegative integers for our channel * numbers, and this interface knows channels by the numbers we choose * for our end, so we can use plain int. */ /* * 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 if a channel open we requested succeeds. Arglist: * (void *arg, int channel_number, ROSTR rest) * The rest argument is the additional data from the * OPEN_CONFIRMATION packet. This callback may call other channel * functions on the channel. The channel's send window has already * been set to the value from the packet; no (*morewin)() call will * be made for this first window. If the send window value is * needed, it can be obtained with chan_get_wwin. * * This may be a nil pointer in CHANOPS structs used only for * channels opened by the remote side. */ void (*opensucc)(void *, int, ROSTR); /* * Called if a channel open we requested fails. Arglist: * (void *arg, int channel_number, unsigned int rcode, ROSTR reason, ROSTR lang) * The channel is not functional and has already been destroyed; the * channel number argument is no longer a valid channel number. * rcode, reason, and lang are the values from the failure packet. * The strings must not be assumed valid after the callback returns. * * This may be a nil pointer in CHANOPS structs used only for * channels opened by the remote side. */ void (*openfail)(void *, int, unsigned int, ROSTR, ROSTR); /* * 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 is not called for the initial send window. Note that * addl may occasionally be zero (and the window unchanged). * * This may be a nil pointer, in which case no call is made. */ 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. * * This may be a nil pointer, in which case it is as if it were a * function which ignores its arguments and returns CHANREQRET_UNK. */ 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 } ; #define CHAN_NO_CHANNEL (-1) /* * Open a channel to the peer. * * First call chan_open_hdr, which constructs the invariant part of the * channel-open message and returns a pointer to just after the * header. After appending the rest of the message, call * chan_open_send, which returns the new channel's number. */ extern void *chan_open_hdr(ROSTR); extern int chan_open_send(void *, const CHANOPS *, void *); /* * Full-detail all-in-one channel open, for use by connection sharing. * * Arguments: * ROSTR type channel type * int maxpkt max packet size * unsigned int rwin initial receive window * const void *data additional packet data blob * int datalen length of additional packet data * const CHANOPS *ops channel operations vector * void *arg argument to ops callbacks * * Return value is the new channel's number. */ extern int chan_open_detail(ROSTR, int, unsigned int, const void *, int, const CHANOPS *, void *); /* * 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 *); /* * Full-detail version of chan_open_ok, for connection sharing. * * Just like chan_open_ok except the initial window size and max packet * size are inserted in the arglist just after the channel number. */ extern void chan_open_ok_detail(int, unsigned int, unsigned 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); /* * Calls to manipulate an established channel. It is an error to call * these before the channel's open has succeeded. */ /* * Change the CHANOPS pointer and/or callback argument for an existing, * established channel. */ extern void chan_set_ops(int, const CHANOPS *, void *); /* * Query window space. * * Returns the number of bytes receivable before window enlargement. * * Argument: channel number. */ extern unsigned int chan_get_rwin(int); /* * Query maximum send packet size. * * Returns the maximum packet size declared by the peer at channel * open. * * Argument: channel number. */ extern unsigned int chan_get_maxpkt(int); /* * Add window space. * * Arguments: (int chan_no, unsigned int additional_space) * * Channels start with zero window advertised. 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 doing so * always returns zero. */ 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 routine called to send * the constructed message (chan_send_req_reply for true, * chan_send_req_blind for false). */ extern unsigned char *chan_req_hdr(int, ROSTR); /* * Send a CHANNEL_REQUEST message, with want-reply true. * * Arguments: channel number, pointer to end of message, callback, * callback argument. * * The callback is 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 callback's first * arg is the channel number; the second is the callback argument. */ 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 want-reply false. * * Arguments: channel number, pointer just past 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 that the void * callback argument is absent. 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 second callback arg is * the third arg to global_send_req(). In the GREQ_OK case, the * memory pointed to by the third argument may not be valid after the * callback returns. */ extern void global_send_req(unsigned char *, void (*)(int, void *, const void *, int), void *); #define GREQ_OK 1 #define GREQ_FAIL 2 /* * Start to send a reply to a GLOBAL_REQUEST message. * * Calling paradigm is similar to global_req_hdr/global_send_req; * differences: * * - global_rep_hdr takes just an argument GREQ_OK or GREQ_FAIL, not a * ROSTR; and if it's GREQ_FAIL, the reply is sent then. * * - global_send_rep doesn't take the callback function and argument * (and is to be called only when GREQ_OK is passed to * global_rep_hdr). */ extern unsigned char *global_rep_hdr(int); extern void global_send_rep(unsigned char *); /* * Print a short text form of the rcode from an open failure. * * The second argument is one of the protocol constants, such as * SSH_OPEN_UNKNOWN_CHANNEL_TYPE or SSH_OPEN_RESOURCE_SHORTAGE. */ extern void print_openfail_rcode(FILE *, unsigned int); /* * The LAYERDESC for the channels layer. */ extern LAYERDESC layer_channels; #endif