mirror of
https://git.libssh.org/projects/libssh.git
synced 2025-08-05 20:55:46 +03:00
added bases for nonblocking packet sending and receiving. packet_send
and packet_read may return SSH_AGAIN if the session is nonblocking and there is not enough data to be read. I also added a socket buffering through session->in_socket_buffer. It is more low-level than the packet buffer. I should rename in_buffer with in_packet_buffer. There is still work to do with the socket status, (opened, error, closed, ...) and much more work to extend the nonblocking to session opening, messages sending and such. I find the switch(session->packet_state) solution very nice (especially when the nonblocking function may have 10 differents states, like in a connection.) git-svn-id: svn+ssh://svn.berlios.de/svnroot/repos/libssh/trunk@49 7dcaeef0-15fb-0310-b436-a5af3365683c
This commit is contained in:
@@ -90,6 +90,10 @@ typedef uint8_t u8;
|
|||||||
#define SSH_FATAL 2
|
#define SSH_FATAL 2
|
||||||
#define SSH_EINTR 3
|
#define SSH_EINTR 3
|
||||||
|
|
||||||
|
/* error return codes */
|
||||||
|
#define SSH_OK 0 /* No error */
|
||||||
|
#define SSH_ERROR -1 /* error of some kind */
|
||||||
|
#define SSH_AGAIN 1 /* the nonblocking call must be repeated */
|
||||||
|
|
||||||
char *ssh_get_error(void *error);
|
char *ssh_get_error(void *error);
|
||||||
int ssh_get_error_code(void *error);
|
int ssh_get_error_code(void *error);
|
||||||
|
@@ -304,7 +304,7 @@ struct ssh_session {
|
|||||||
not block */
|
not block */
|
||||||
int data_to_write;
|
int data_to_write;
|
||||||
int data_except;
|
int data_except;
|
||||||
int blocking; // functions should not block
|
int blocking; // functions should block
|
||||||
|
|
||||||
STRING *banner; /* that's the issue banner from
|
STRING *banner; /* that's the issue banner from
|
||||||
the server */
|
the server */
|
||||||
@@ -315,6 +315,14 @@ struct ssh_session {
|
|||||||
BUFFER *in_buffer;
|
BUFFER *in_buffer;
|
||||||
PACKET in_packet;
|
PACKET in_packet;
|
||||||
BUFFER *out_buffer;
|
BUFFER *out_buffer;
|
||||||
|
|
||||||
|
BUFFER *out_socket_buffer;
|
||||||
|
BUFFER *in_socket_buffer;
|
||||||
|
|
||||||
|
/* the states are used by the nonblocking stuff to remember */
|
||||||
|
/* where it was before being interrupted */
|
||||||
|
int packet_state;
|
||||||
|
|
||||||
KEX server_kex;
|
KEX server_kex;
|
||||||
KEX client_kex;
|
KEX client_kex;
|
||||||
BUFFER *in_hashbuf;
|
BUFFER *in_hashbuf;
|
||||||
|
@@ -45,7 +45,7 @@ install: all
|
|||||||
$(top_srcdir)/mkinstalldirs $(libdir)
|
$(top_srcdir)/mkinstalldirs $(libdir)
|
||||||
$(LIBTOOL) --mode=install $(INSTALL) libssh.la $(libdir)
|
$(LIBTOOL) --mode=install $(INSTALL) libssh.la $(libdir)
|
||||||
clean:
|
clean:
|
||||||
$(LIBTOOL) --mode=clean rm -f *~ libssh.la *.lo
|
$(LIBTOOL) --mode=clean rm -f *~ libssh.la *.lo *.o
|
||||||
distclean: clean
|
distclean: clean
|
||||||
rm -f Makefile
|
rm -f Makefile
|
||||||
|
|
||||||
|
246
libssh/packet.c
246
libssh/packet.c
@@ -41,7 +41,7 @@ static int completeread(int fd, void *buffer, int len){
|
|||||||
int toread=len;
|
int toread=len;
|
||||||
while((r=read(fd,buffer+total,toread))){
|
while((r=read(fd,buffer+total,toread))){
|
||||||
if(r==-1)
|
if(r==-1)
|
||||||
return -1;
|
return SSH_ERROR;
|
||||||
total += r;
|
total += r;
|
||||||
toread-=r;
|
toread-=r;
|
||||||
if(total==len)
|
if(total==len)
|
||||||
@@ -52,6 +52,63 @@ static int completeread(int fd, void *buffer, int len){
|
|||||||
return total ; /* connection closed */
|
return total ; /* connection closed */
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/* in nonblocking mode, socket_read will read as much as it can, and return */
|
||||||
|
/* SSH_OK if it has read at least len bytes, otherwise, SSH_AGAIN. */
|
||||||
|
/* in blocking mode, it will read at least len bytes and will block until it's ok. */
|
||||||
|
|
||||||
|
static int socket_read(SSH_SESSION *session,int len){
|
||||||
|
int except, can_write;
|
||||||
|
int ret;
|
||||||
|
int to_read;
|
||||||
|
int r;
|
||||||
|
char *buf;
|
||||||
|
char buffer[4096];
|
||||||
|
if(!session->in_socket_buffer)
|
||||||
|
session->in_socket_buffer=buffer_new();
|
||||||
|
to_read=len - buffer_get_rest_len(session->in_socket_buffer);
|
||||||
|
if(to_read <= 0)
|
||||||
|
return SSH_OK;
|
||||||
|
if(session->blocking){
|
||||||
|
buf=malloc(to_read);
|
||||||
|
ret=completeread(session->fd,buf,to_read);
|
||||||
|
session->data_to_read=0;
|
||||||
|
if(ret==SSH_ERROR || ret ==0){
|
||||||
|
ssh_set_error(session,SSH_FATAL,
|
||||||
|
(ret==0)?"Connection closed by remote host" : "Error reading socket");
|
||||||
|
close(session->fd);
|
||||||
|
session->fd=-1;
|
||||||
|
session->data_except=1;
|
||||||
|
return SSH_ERROR;
|
||||||
|
}
|
||||||
|
|
||||||
|
buffer_add_data(session->in_socket_buffer,buf,to_read);
|
||||||
|
free(buf);
|
||||||
|
return SSH_OK;
|
||||||
|
}
|
||||||
|
/* nonblocking read */
|
||||||
|
do {
|
||||||
|
ssh_fd_poll(session,&can_write,&except); /* internally sets data_to_read */
|
||||||
|
if(!session->data_to_read)
|
||||||
|
return SSH_AGAIN;
|
||||||
|
session->data_to_read=0;
|
||||||
|
/* read as much as we can */
|
||||||
|
r=read(session->fd,buffer,sizeof(buffer));
|
||||||
|
if(r<=0){
|
||||||
|
ssh_set_error(session,SSH_FATAL,
|
||||||
|
(ret==0)?"Connection closed by remote host" : "Error reading socket");
|
||||||
|
close(session->fd);
|
||||||
|
session->fd=-1;
|
||||||
|
session->data_except=1;
|
||||||
|
return SSH_ERROR;
|
||||||
|
}
|
||||||
|
buffer_add_data(session->in_socket_buffer,buffer,r);
|
||||||
|
} while(buffer_get_rest_len(session->in_socket_buffer)<len);
|
||||||
|
return SSH_OK;
|
||||||
|
}
|
||||||
|
|
||||||
|
#define PACKET_STATE_INIT 0
|
||||||
|
#define PACKET_STATE_SIZEREAD 1
|
||||||
|
|
||||||
static int packet_read2(SSH_SESSION *session){
|
static int packet_read2(SSH_SESSION *session){
|
||||||
u32 len;
|
u32 len;
|
||||||
void *packet=NULL;
|
void *packet=NULL;
|
||||||
@@ -59,84 +116,69 @@ static int packet_read2(SSH_SESSION *session){
|
|||||||
char buffer[16];
|
char buffer[16];
|
||||||
int be_read,i;
|
int be_read,i;
|
||||||
int to_be_read;
|
int to_be_read;
|
||||||
|
int ret;
|
||||||
u8 padding;
|
u8 padding;
|
||||||
unsigned int blocksize=(session->current_crypto?session->current_crypto->in_cipher->blocksize:8);
|
unsigned int blocksize=(session->current_crypto?session->current_crypto->in_cipher->blocksize:8);
|
||||||
session->data_to_read=0; /* clear the dataavailable flag */
|
int current_macsize=session->current_crypto?macsize:0;
|
||||||
|
if(!session->alive || session->data_except)
|
||||||
|
return SSH_ERROR; // the error message was already set into this session
|
||||||
|
switch(session->packet_state){
|
||||||
|
case PACKET_STATE_INIT:
|
||||||
memset(&session->in_packet,0,sizeof(PACKET));
|
memset(&session->in_packet,0,sizeof(PACKET));
|
||||||
if(session->in_buffer)
|
if(session->in_buffer)
|
||||||
buffer_free(session->in_buffer);
|
buffer_reinit(session->in_buffer);
|
||||||
|
else
|
||||||
session->in_buffer=buffer_new();
|
session->in_buffer=buffer_new();
|
||||||
|
ret=socket_read(session,blocksize);
|
||||||
be_read=completeread(session->fd,buffer,blocksize);
|
if(ret != SSH_OK)
|
||||||
if(be_read!=blocksize){
|
return ret; // can be SSH_ERROR or SSH_AGAIN
|
||||||
if(be_read<=0){
|
// be_read=completeread(session->fd,buffer,blocksize);
|
||||||
session->alive=0;
|
memcpy(buffer,buffer_get_rest(session->in_socket_buffer),blocksize);
|
||||||
close(session->fd);
|
buffer_pass_bytes(session->in_socket_buffer,blocksize); // mark them as read
|
||||||
session->fd=-1;
|
|
||||||
ssh_set_error(session,SSH_FATAL,
|
|
||||||
(be_read==0)?"Connection closed by remote host" : "Error reading socket");
|
|
||||||
return -1;
|
|
||||||
}
|
|
||||||
ssh_set_error(session,SSH_FATAL,"read_packet(): asked %d bytes, received %d",blocksize,be_read);
|
|
||||||
return -1;
|
|
||||||
}
|
|
||||||
len=packet_decrypt_len(session,buffer);
|
len=packet_decrypt_len(session,buffer);
|
||||||
buffer_add_data(session->in_buffer,buffer,blocksize);
|
buffer_add_data(session->in_buffer,buffer,blocksize);
|
||||||
|
|
||||||
if(len> MAX_PACKET_LEN){
|
if(len> MAX_PACKET_LEN){
|
||||||
ssh_set_error(session,SSH_FATAL,"read_packet(): Packet len too high(%uld %.8lx)",len,len);
|
ssh_set_error(session,SSH_FATAL,"read_packet(): Packet len too high(%uld %.8lx)",len,len);
|
||||||
return -1;
|
return SSH_ERROR;
|
||||||
}
|
}
|
||||||
to_be_read=len-be_read+sizeof(u32);
|
to_be_read=len-blocksize+sizeof(u32);
|
||||||
if(to_be_read<0){
|
if(to_be_read<0){
|
||||||
/* remote sshd is trying to get me ?*/
|
/* remote sshd sends invalid sizes?*/
|
||||||
ssh_set_error(session,SSH_FATAL,"given numbers of bytes left to be read <0 (%d)!",to_be_read);
|
ssh_set_error(session,SSH_FATAL,"given numbers of bytes left to be read <0 (%d)!",to_be_read);
|
||||||
return -1;
|
return SSH_ERROR;
|
||||||
}
|
}
|
||||||
/* handle the case in which the whole packet size = blocksize */
|
/* saves the status of the current operations */
|
||||||
if(to_be_read !=0){
|
session->in_packet.len=len;
|
||||||
|
session->packet_state=PACKET_STATE_SIZEREAD;
|
||||||
|
case PACKET_STATE_SIZEREAD:
|
||||||
|
len=session->in_packet.len;
|
||||||
|
to_be_read=len-blocksize+sizeof(u32) + current_macsize;
|
||||||
|
/* if to_be_read is zero, the whole packet was blocksize bytes. */
|
||||||
|
if(to_be_read != 0){
|
||||||
|
ret=socket_read(session,to_be_read);
|
||||||
|
if(ret!=SSH_OK)
|
||||||
|
return ret;
|
||||||
packet=malloc(to_be_read);
|
packet=malloc(to_be_read);
|
||||||
i=completeread(session->fd,packet,to_be_read);
|
memcpy(packet,buffer_get_rest(session->in_socket_buffer),to_be_read-current_macsize);
|
||||||
if(i<=0){
|
buffer_pass_bytes(session->in_socket_buffer,to_be_read-current_macsize);
|
||||||
session->alive=0;
|
|
||||||
close(session->fd);
|
|
||||||
session->fd=-1;
|
|
||||||
ssh_set_error(session,SSH_FATAL,"Server closed connection");
|
|
||||||
return -1;
|
|
||||||
}
|
|
||||||
if(i!=to_be_read){
|
|
||||||
free(packet);
|
|
||||||
packet=NULL;
|
|
||||||
ssh_say(3,"Read only %d, wanted %d\n",i,to_be_read);
|
|
||||||
ssh_set_error(session,SSH_FATAL,"read_packet(): read only %d, wanted %d",i,to_be_read);
|
|
||||||
return -1;
|
|
||||||
}
|
|
||||||
ssh_say(3,"Read a %d bytes packet\n",len);
|
ssh_say(3,"Read a %d bytes packet\n",len);
|
||||||
buffer_add_data(session->in_buffer,packet,to_be_read);
|
buffer_add_data(session->in_buffer,packet,to_be_read-current_macsize);
|
||||||
free(packet);
|
free(packet);
|
||||||
}
|
}
|
||||||
if(session->current_crypto){
|
if(session->current_crypto){
|
||||||
|
/* decrypt the rest of the packet (blocksize bytes already have been decrypted */
|
||||||
packet_decrypt(session,buffer_get(session->in_buffer)+blocksize,buffer_get_len(session->in_buffer)-blocksize);
|
packet_decrypt(session,buffer_get(session->in_buffer)+blocksize,buffer_get_len(session->in_buffer)-blocksize);
|
||||||
if((i=completeread(session->fd,mac,macsize))!=macsize){
|
memcpy(mac,buffer_get_rest(session->in_socket_buffer),macsize);
|
||||||
if(i<=0){
|
buffer_pass_bytes(session->in_socket_buffer,macsize);
|
||||||
session->alive=0;
|
|
||||||
close(session->fd);
|
|
||||||
session->fd=-1;
|
|
||||||
ssh_set_error(session,SSH_FATAL,"Server closed connection");
|
|
||||||
return -1;
|
|
||||||
}
|
|
||||||
ssh_set_error(session,SSH_FATAL,"read_packet(): wanted %d, had %d",i,macsize);
|
|
||||||
return -1;
|
|
||||||
}
|
|
||||||
if(packet_hmac_verify(session,session->in_buffer,mac)){
|
if(packet_hmac_verify(session,session->in_buffer,mac)){
|
||||||
ssh_set_error(session,SSH_FATAL,"HMAC error");
|
ssh_set_error(session,SSH_FATAL,"HMAC error");
|
||||||
return -1;
|
return SSH_ERROR;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
buffer_pass_bytes(session->in_buffer,sizeof(u32)); /*pass the size which has been processed before*/
|
buffer_pass_bytes(session->in_buffer,sizeof(u32)); /*pass the size which has been processed before*/
|
||||||
if(!buffer_get_u8(session->in_buffer,&padding)){
|
if(!buffer_get_u8(session->in_buffer,&padding)){
|
||||||
ssh_set_error(session,SSH_FATAL,"Packet too short to read padding");
|
ssh_set_error(session,SSH_FATAL,"Packet too short to read padding");
|
||||||
return -1;
|
return SSH_ERROR;
|
||||||
}
|
}
|
||||||
ssh_say(3,"%hhd bytes padding, %d bytes left in buffer\n",padding,buffer_get_rest_len(session->in_buffer));
|
ssh_say(3,"%hhd bytes padding, %d bytes left in buffer\n",padding,buffer_get_rest_len(session->in_buffer));
|
||||||
if(padding > buffer_get_rest_len(session->in_buffer)){
|
if(padding > buffer_get_rest_len(session->in_buffer)){
|
||||||
@@ -144,7 +186,7 @@ static int packet_read2(SSH_SESSION *session){
|
|||||||
#ifdef DEBUG_CRYPTO
|
#ifdef DEBUG_CRYPTO
|
||||||
ssh_print_hexa("incrimined packet",buffer_get(session->in_buffer),buffer_get_len(session->in_buffer));
|
ssh_print_hexa("incrimined packet",buffer_get(session->in_buffer),buffer_get_len(session->in_buffer));
|
||||||
#endif
|
#endif
|
||||||
return -1;
|
return SSH_ERROR;
|
||||||
}
|
}
|
||||||
buffer_pass_bytes_end(session->in_buffer,padding);
|
buffer_pass_bytes_end(session->in_buffer,padding);
|
||||||
ssh_say(3,"After padding, %d bytes left in buffer\n",buffer_get_rest_len(session->in_buffer));
|
ssh_say(3,"After padding, %d bytes left in buffer\n",buffer_get_rest_len(session->in_buffer));
|
||||||
@@ -155,7 +197,11 @@ static int packet_read2(SSH_SESSION *session){
|
|||||||
}
|
}
|
||||||
#endif
|
#endif
|
||||||
session->recv_seq++;
|
session->recv_seq++;
|
||||||
return 0;
|
session->packet_state=PACKET_STATE_INIT;
|
||||||
|
return SSH_OK;
|
||||||
|
}
|
||||||
|
ssh_set_error(session,SSH_FATAL,"Invalid state into packet_read2() : %d",session->packet_state);
|
||||||
|
return SSH_ERROR;
|
||||||
}
|
}
|
||||||
|
|
||||||
#ifdef HAVE_SSH1
|
#ifdef HAVE_SSH1
|
||||||
@@ -171,6 +217,8 @@ static int packet_read1(SSH_SESSION *session){
|
|||||||
ssh_say(3,"packet_read1()\n");
|
ssh_say(3,"packet_read1()\n");
|
||||||
// unsigned int blocksize=8;
|
// unsigned int blocksize=8;
|
||||||
session->data_to_read=0; /* clear the dataavailable flag */
|
session->data_to_read=0; /* clear the dataavailable flag */
|
||||||
|
if(!session->alive || session->data_except)
|
||||||
|
return -1; // the error message was already set
|
||||||
memset(&session->in_packet,0,sizeof(PACKET));
|
memset(&session->in_packet,0,sizeof(PACKET));
|
||||||
if(session->in_buffer)
|
if(session->in_buffer)
|
||||||
buffer_free(session->in_buffer);
|
buffer_free(session->in_buffer);
|
||||||
@@ -180,6 +228,7 @@ static int packet_read1(SSH_SESSION *session){
|
|||||||
if(be_read!=sizeof(u32)){
|
if(be_read!=sizeof(u32)){
|
||||||
if(be_read<=0){
|
if(be_read<=0){
|
||||||
session->alive=0;
|
session->alive=0;
|
||||||
|
session->data_except=1;
|
||||||
close(session->fd);
|
close(session->fd);
|
||||||
session->fd=-1;
|
session->fd=-1;
|
||||||
ssh_set_error(session,SSH_FATAL,
|
ssh_set_error(session,SSH_FATAL,
|
||||||
@@ -206,6 +255,7 @@ static int packet_read1(SSH_SESSION *session){
|
|||||||
i=completeread(session->fd,packet,to_be_read);
|
i=completeread(session->fd,packet,to_be_read);
|
||||||
if(i<=0){
|
if(i<=0){
|
||||||
session->alive=0;
|
session->alive=0;
|
||||||
|
session->data_except=1;
|
||||||
close(session->fd);
|
close(session->fd);
|
||||||
session->fd=-1;
|
session->fd=-1;
|
||||||
ssh_set_error(session,SSH_FATAL,"Server closed connection");
|
ssh_set_error(session,SSH_FATAL,"Server closed connection");
|
||||||
@@ -297,18 +347,68 @@ int packet_translate(SSH_SESSION *session){
|
|||||||
|
|
||||||
static int atomic_write(int fd, void *buffer, int len){
|
static int atomic_write(int fd, void *buffer, int len){
|
||||||
int written;
|
int written;
|
||||||
int total=0;
|
|
||||||
do {
|
do {
|
||||||
written=write(fd,buffer,len);
|
written=write(fd,buffer,len);
|
||||||
if(written==0)
|
if(written==0 || written==-1)
|
||||||
return 0;
|
return -1;
|
||||||
if(written==-1)
|
|
||||||
return total;
|
|
||||||
total+=written;
|
|
||||||
len-=written;
|
len-=written;
|
||||||
buffer+=written;
|
buffer+=written;
|
||||||
} while (len > 0);
|
} while (len > 0);
|
||||||
return total;
|
return SSH_OK;
|
||||||
|
}
|
||||||
|
|
||||||
|
int packet_nonblocking_flush(SSH_SESSION *session){
|
||||||
|
int except, can_write;
|
||||||
|
int w;
|
||||||
|
ssh_fd_poll(session,&can_write,&except); /* internally sets data_to_write */
|
||||||
|
while(session->data_to_write && buffer_get_rest_len(session->out_socket_buffer)>0){
|
||||||
|
w=write(session->fd,buffer_get_rest(session->out_socket_buffer),
|
||||||
|
buffer_get_rest_len(session->out_socket_buffer));
|
||||||
|
if(w<0){
|
||||||
|
session->data_to_write=0;
|
||||||
|
session->data_except=1;
|
||||||
|
session->alive=0;
|
||||||
|
close(session->fd);
|
||||||
|
session->fd=-1;
|
||||||
|
ssh_set_error(session,SSH_FATAL,"Writing packet : error on socket (or connection closed): %s",
|
||||||
|
strerror(errno));
|
||||||
|
return SSH_ERROR;
|
||||||
|
}
|
||||||
|
buffer_pass_bytes(session->out_socket_buffer,w);
|
||||||
|
}
|
||||||
|
if(buffer_get_rest_len(session->out_socket_buffer)>0)
|
||||||
|
return SSH_AGAIN; /* there is data pending */
|
||||||
|
return SSH_OK; // all data written
|
||||||
|
}
|
||||||
|
|
||||||
|
int packet_flush(SSH_SESSION *session){
|
||||||
|
if(atomic_write(session->fd,buffer_get_rest(session->out_socket_buffer),
|
||||||
|
buffer_get_rest_len(session->out_socket_buffer))){
|
||||||
|
session->data_to_write=0;
|
||||||
|
session->data_except=1;
|
||||||
|
session->alive=0;
|
||||||
|
close(session->fd);
|
||||||
|
session->fd=-1;
|
||||||
|
ssh_set_error(session,SSH_FATAL,"Writing packet : error on socket (or connection closed): %s",
|
||||||
|
strerror(errno));
|
||||||
|
return SSH_ERROR;
|
||||||
|
}
|
||||||
|
session->data_to_write=0;
|
||||||
|
buffer_reinit(session->out_socket_buffer);
|
||||||
|
return SSH_OK; // no data pending
|
||||||
|
}
|
||||||
|
|
||||||
|
/* this function places the outgoing packet buffer into an outgoing socket buffer */
|
||||||
|
static int socket_write(SSH_SESSION *session){
|
||||||
|
if(!session->out_socket_buffer){
|
||||||
|
session->out_socket_buffer=buffer_new();
|
||||||
|
}
|
||||||
|
buffer_add_data(session->out_socket_buffer,
|
||||||
|
buffer_get(session->out_buffer),buffer_get_len(session->out_buffer));
|
||||||
|
if(!session->blocking){
|
||||||
|
return packet_nonblocking_flush(session);
|
||||||
|
} else
|
||||||
|
return packet_flush(session);
|
||||||
}
|
}
|
||||||
|
|
||||||
static int packet_send2(SSH_SESSION *session){
|
static int packet_send2(SSH_SESSION *session){
|
||||||
@@ -342,17 +442,10 @@ static int packet_send2(SSH_SESSION *session){
|
|||||||
hmac=packet_encrypt(session,buffer_get(session->out_buffer),buffer_get_len(session->out_buffer));
|
hmac=packet_encrypt(session,buffer_get(session->out_buffer),buffer_get_len(session->out_buffer));
|
||||||
if(hmac)
|
if(hmac)
|
||||||
buffer_add_data(session->out_buffer,hmac,20);
|
buffer_add_data(session->out_buffer,hmac,20);
|
||||||
if(atomic_write(session->fd,buffer_get(session->out_buffer),buffer_get_len(session->out_buffer))!=buffer_get_len(session->out_buffer)){
|
ret=socket_write(session);
|
||||||
session->alive=0;
|
|
||||||
close(session->fd);
|
|
||||||
session->fd=-1;
|
|
||||||
ssh_set_error(session,SSH_FATAL,"Writing packet : error on socket (or connection closed): %s",
|
|
||||||
strerror(errno));
|
|
||||||
ret=-1;
|
|
||||||
}
|
|
||||||
session->send_seq++;
|
session->send_seq++;
|
||||||
buffer_reinit(session->out_buffer);
|
buffer_reinit(session->out_buffer);
|
||||||
return ret;
|
return ret; /* SSH_OK, AGAIN or ERROR */
|
||||||
}
|
}
|
||||||
|
|
||||||
#ifdef HAVE_SSH1
|
#ifdef HAVE_SSH1
|
||||||
@@ -393,17 +486,10 @@ static int packet_send1(SSH_SESSION *session){
|
|||||||
ssh_print_hexa("encrypted packet",buffer_get(session->out_buffer),
|
ssh_print_hexa("encrypted packet",buffer_get(session->out_buffer),
|
||||||
buffer_get_len(session->out_buffer));
|
buffer_get_len(session->out_buffer));
|
||||||
#endif
|
#endif
|
||||||
if(atomic_write(session->fd,buffer_get(session->out_buffer),buffer_get_len(session->out_buffer))!=buffer_get_len(session->out_buffer)){
|
ret=socket_write(session);
|
||||||
session->alive=0;
|
|
||||||
close(session->fd);
|
|
||||||
session->fd=-1;
|
|
||||||
ssh_set_error(session,SSH_FATAL,"Writing packet : error on socket (or connection closed): %s",
|
|
||||||
strerror(errno));
|
|
||||||
ret=-1;
|
|
||||||
}
|
|
||||||
session->send_seq++;
|
session->send_seq++;
|
||||||
buffer_reinit(session->out_buffer);
|
buffer_reinit(session->out_buffer);
|
||||||
return ret;
|
return ret; /* SSH_OK, AGAIN or ERROR */
|
||||||
}
|
}
|
||||||
|
|
||||||
#endif /* HAVE_SSH1 */
|
#endif /* HAVE_SSH1 */
|
||||||
|
@@ -34,6 +34,7 @@ SSH_SESSION *ssh_new() {
|
|||||||
session->next_crypto=crypto_new();
|
session->next_crypto=crypto_new();
|
||||||
session->maxchannel=FIRST_CHANNEL;
|
session->maxchannel=FIRST_CHANNEL;
|
||||||
session->fd=-1;
|
session->fd=-1;
|
||||||
|
session->blocking=1;
|
||||||
return session;
|
return session;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
Reference in New Issue
Block a user