Skip to content
Snippets Groups Projects
Commit 19e1afbd authored by Matt Johnston's avatar Matt Johnston
Browse files

Fix no-writev fallback

parent fee32054
No related branches found
No related tags found
No related merge requests found
Loading
@@ -8,7 +8,7 @@ The majority of code is written by Matt Johnston, under the license below.
Loading
@@ -8,7 +8,7 @@ The majority of code is written by Matt Johnston, under the license below.
Portions of the client-mode work are (c) 2004 Mihnea Stoenescu, under the Portions of the client-mode work are (c) 2004 Mihnea Stoenescu, under the
same license: same license:
   
Copyright (c) 2002-2014 Matt Johnston Copyright (c) 2002-2015 Matt Johnston
Portions copyright (c) 2004 Mihnea Stoenescu Portions copyright (c) 2004 Mihnea Stoenescu
All rights reserved. All rights reserved.
   
Loading
Loading
Loading
@@ -67,23 +67,6 @@ unsigned int cbuf_getavail(circbuffer * cbuf) {
Loading
@@ -67,23 +67,6 @@ unsigned int cbuf_getavail(circbuffer * cbuf) {
   
} }
   
unsigned int cbuf_readlen(circbuffer *cbuf) {
dropbear_assert(((2*cbuf->size)+cbuf->writepos-cbuf->readpos)%cbuf->size == cbuf->used%cbuf->size);
dropbear_assert(((2*cbuf->size)+cbuf->readpos-cbuf->writepos)%cbuf->size == (cbuf->size-cbuf->used)%cbuf->size);
if (cbuf->used == 0) {
TRACE(("cbuf_readlen: unused buffer"))
return 0;
}
if (cbuf->readpos < cbuf->writepos) {
return cbuf->writepos - cbuf->readpos;
}
return cbuf->size - cbuf->readpos;
}
unsigned int cbuf_writelen(circbuffer *cbuf) { unsigned int cbuf_writelen(circbuffer *cbuf) {
   
dropbear_assert(cbuf->used <= cbuf->size); dropbear_assert(cbuf->used <= cbuf->size);
Loading
@@ -102,14 +85,6 @@ unsigned int cbuf_writelen(circbuffer *cbuf) {
Loading
@@ -102,14 +85,6 @@ unsigned int cbuf_writelen(circbuffer *cbuf) {
return cbuf->size - cbuf->writepos; return cbuf->size - cbuf->writepos;
} }
   
unsigned char* cbuf_readptr(circbuffer *cbuf, unsigned int len) {
if (len > cbuf_readlen(cbuf)) {
dropbear_exit("Bad cbuf read");
}
return &cbuf->data[cbuf->readpos];
}
void cbuf_readptrs(circbuffer *cbuf, void cbuf_readptrs(circbuffer *cbuf,
unsigned char **p1, unsigned int *len1, unsigned char **p1, unsigned int *len1,
unsigned char **p2, unsigned int *len2) { unsigned char **p2, unsigned int *len2) {
Loading
@@ -146,12 +121,6 @@ void cbuf_incrwrite(circbuffer *cbuf, unsigned int len) {
Loading
@@ -146,12 +121,6 @@ void cbuf_incrwrite(circbuffer *cbuf, unsigned int len) {
   
   
void cbuf_incrread(circbuffer *cbuf, unsigned int len) { void cbuf_incrread(circbuffer *cbuf, unsigned int len) {
#if 0
if (len > cbuf_readlen(cbuf)) {
dropbear_exit("Bad cbuf read");
}
#endif
dropbear_assert(cbuf->used >= len); dropbear_assert(cbuf->used >= len);
cbuf->used -= len; cbuf->used -= len;
cbuf->readpos = (cbuf->readpos + len) % cbuf->size; cbuf->readpos = (cbuf->readpos + len) % cbuf->size;
Loading
Loading
Loading
@@ -40,10 +40,9 @@ void cbuf_free(circbuffer * cbuf);
Loading
@@ -40,10 +40,9 @@ void cbuf_free(circbuffer * cbuf);
   
unsigned int cbuf_getused(circbuffer * cbuf); /* how much data stored */ unsigned int cbuf_getused(circbuffer * cbuf); /* how much data stored */
unsigned int cbuf_getavail(circbuffer * cbuf); /* how much we can write */ unsigned int cbuf_getavail(circbuffer * cbuf); /* how much we can write */
unsigned int cbuf_readlen(circbuffer *cbuf); /* max linear read len */
unsigned int cbuf_writelen(circbuffer *cbuf); /* max linear write len */ unsigned int cbuf_writelen(circbuffer *cbuf); /* max linear write len */
   
unsigned char* cbuf_readptr(circbuffer *cbuf, unsigned int len); /* returns pointers to the two portions of the circular buffer that can be read */
void cbuf_readptrs(circbuffer *cbuf, void cbuf_readptrs(circbuffer *cbuf,
unsigned char **p1, unsigned int *len1, unsigned char **p1, unsigned int *len1,
unsigned char **p2, unsigned int *len2); unsigned char **p2, unsigned int *len2);
Loading
Loading
Loading
@@ -434,10 +434,36 @@ static void send_msg_channel_eof(struct Channel *channel) {
Loading
@@ -434,10 +434,36 @@ static void send_msg_channel_eof(struct Channel *channel) {
TRACE(("leave send_msg_channel_eof")) TRACE(("leave send_msg_channel_eof"))
} }
   
/* Called to write data out to the local side of the channel. #ifndef HAVE_WRITEV
Writes the circular buffer contents and also the "moredata" buffer static void writechannel_fallback(struct Channel* channel, int fd, circbuffer *cbuf,
if not null. Will ignore EAGAIN */ const unsigned char *UNUSED(moredata), unsigned int *morelen) {
static void writechannel(struct Channel* channel, int fd, circbuffer *cbuf,
unsigned char *circ_p1, *circ_p2;
unsigned int circ_len1, circ_len2;
ssize_t written;
if (morelen) {
/* fallback doesn't consume moredata */
*morelen = 0;
}
/* Write the first portion of the circular buffer */
cbuf_readptrs(cbuf, &circ_p1, &circ_len1, &circ_p2, &circ_len2);
written = write(fd, circ_p1, circ_len1);
if (written < 0) {
if (errno != EINTR && errno != EAGAIN) {
TRACE(("channel IO write error fd %d %s", fd, strerror(errno)))
close_chan_fd(channel, fd, SHUT_WR);
}
} else {
cbuf_incrread(cbuf, written);
channel->recvdonelen += written;
}
}
#endif /* !HAVE_WRITEV */
#ifdef HAVE_WRITEV
static void writechannel_writev(struct Channel* channel, int fd, circbuffer *cbuf,
const unsigned char *moredata, unsigned int *morelen) { const unsigned char *moredata, unsigned int *morelen) {
   
struct iovec iov[3]; struct iovec iov[3];
Loading
@@ -445,9 +471,7 @@ static void writechannel(struct Channel* channel, int fd, circbuffer *cbuf,
Loading
@@ -445,9 +471,7 @@ static void writechannel(struct Channel* channel, int fd, circbuffer *cbuf,
unsigned int circ_len1, circ_len2; unsigned int circ_len1, circ_len2;
int io_count = 0; int io_count = 0;
   
int written; ssize_t written;
TRACE(("enter writechannel fd %d", fd))
   
cbuf_readptrs(cbuf, &circ_p1, &circ_len1, &circ_p2, &circ_len2); cbuf_readptrs(cbuf, &circ_p1, &circ_len1, &circ_p2, &circ_len2);
   
Loading
@@ -502,24 +526,19 @@ static void writechannel(struct Channel* channel, int fd, circbuffer *cbuf,
Loading
@@ -502,24 +526,19 @@ static void writechannel(struct Channel* channel, int fd, circbuffer *cbuf,
channel->recvdonelen += written; channel->recvdonelen += written;
} }
   
#if 0 }
#endif /* HAVE_WRITEV */
maxlen = cbuf_readlen(cbuf);
/* Write the data out */
len = write(fd, cbuf_readptr(cbuf, maxlen), maxlen);
if (len <= 0) {
TRACE(("errno %d len %d", errno, len))
if (len < 0 && errno != EINTR) {
close_chan_fd(channel, fd, SHUT_WR);
}
TRACE(("leave writechannel: len <= 0"))
return;
}
TRACE(("writechannel wrote %d", len))
   
cbuf_incrread(cbuf, len); /* Called to write data out to the local side of the channel.
channel->recvdonelen += len; Writes the circular buffer contents and also the "moredata" buffer
if not null. Will ignore EAGAIN */
static void writechannel(struct Channel* channel, int fd, circbuffer *cbuf,
const unsigned char *moredata, unsigned int *morelen) {
TRACE(("enter writechannel fd %d", fd))
#ifdef HAVE_WRITEV
writechannel_writev(channel, fd, cbuf, moredata, morelen);
#else
writechannel_fallback(channel, fd, cbuf, moredata, morelen);
#endif #endif
   
/* Window adjust handling */ /* Window adjust handling */
Loading
@@ -537,6 +556,7 @@ static void writechannel(struct Channel* channel, int fd, circbuffer *cbuf,
Loading
@@ -537,6 +556,7 @@ static void writechannel(struct Channel* channel, int fd, circbuffer *cbuf,
TRACE(("leave writechannel")) TRACE(("leave writechannel"))
} }
   
/* Set the file descriptors for the main select in session.c /* Set the file descriptors for the main select in session.c
* This avoid channels which don't have any window available, are closed, etc*/ * This avoid channels which don't have any window available, are closed, etc*/
void setchannelfds(fd_set *readfds, fd_set *writefds, int allow_reads) { void setchannelfds(fd_set *readfds, fd_set *writefds, int allow_reads) {
Loading
Loading
/* /*
* Dropbear - a SSH2 server * Dropbear - a SSH2 server
* *
* Copyright (c) 2002,2003 Matt Johnston * Copyright (c) Matt Johnston
* All rights reserved. * All rights reserved.
* *
* Permission is hereby granted, free of charge, to any person obtaining a copy * Permission is hereby granted, free of charge, to any person obtaining a copy
Loading
@@ -280,7 +280,7 @@ void session_cleanup() {
Loading
@@ -280,7 +280,7 @@ void session_cleanup() {
return; return;
} }
   
/* Beware of changing order of functions here. */ /* BEWARE of changing order of functions here. */
   
/* Must be before extra_session_cleanup() */ /* Must be before extra_session_cleanup() */
chancleanup(); chancleanup();
Loading
@@ -289,7 +289,7 @@ void session_cleanup() {
Loading
@@ -289,7 +289,7 @@ void session_cleanup() {
ses.extra_session_cleanup(); ses.extra_session_cleanup();
} }
   
/* After these are freed most functions will exit */ /* After these are freed most functions will fail */
#ifdef DROPBEAR_CLEANUP #ifdef DROPBEAR_CLEANUP
/* listeners call cleanup functions, this should occur before /* listeners call cleanup functions, this should occur before
other session state is freed. */ other session state is freed. */
Loading
Loading
Loading
@@ -61,6 +61,10 @@ void write_packet() {
Loading
@@ -61,6 +61,10 @@ void write_packet() {
/* 50 is somewhat arbitrary */ /* 50 is somewhat arbitrary */
unsigned int iov_count = 50; unsigned int iov_count = 50;
struct iovec iov[50]; struct iovec iov[50];
#else
int len;
buffer* writebuf;
int packet_type;
#endif #endif
TRACE2(("enter write_packet")) TRACE2(("enter write_packet"))
Loading
@@ -97,6 +101,8 @@ void write_packet() {
Loading
@@ -97,6 +101,8 @@ void write_packet() {
* a cleartext packet_type indicator */ * a cleartext packet_type indicator */
packet_type = writebuf->data[writebuf->len-1]; packet_type = writebuf->data[writebuf->len-1];
len = writebuf->len - 1 - writebuf->pos; len = writebuf->len - 1 - writebuf->pos;
TRACE2(("write_packet type %d len %d/%d", packet_type,
len, writebuf->len-1))
dropbear_assert(len > 0); dropbear_assert(len > 0);
/* Try to write as much as possible */ /* Try to write as much as possible */
written = write(ses.sock_out, buf_getptr(writebuf, len), len); written = write(ses.sock_out, buf_getptr(writebuf, len), len);
Loading
Loading
0% Loading or .
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment