1#include "tunala.h" 2 3#ifndef NO_BUFFER 4 5void buffer_init(buffer_t * buf) 6{ 7 buf->used = 0; 8 buf->total_in = buf->total_out = 0; 9} 10 11void buffer_close(buffer_t * buf) 12{ 13 /* Our data is static - nothing needs "release", just reset it */ 14 buf->used = 0; 15} 16 17/* Code these simple ones in compact form */ 18unsigned int buffer_used(buffer_t * buf) 19{ 20 return buf->used; 21} 22 23unsigned int buffer_unused(buffer_t * buf) 24{ 25 return (MAX_DATA_SIZE - buf->used); 26} 27 28int buffer_full(buffer_t * buf) 29{ 30 return (buf->used == MAX_DATA_SIZE ? 1 : 0); 31} 32 33int buffer_notfull(buffer_t * buf) 34{ 35 return (buf->used < MAX_DATA_SIZE ? 1 : 0); 36} 37 38int buffer_empty(buffer_t * buf) 39{ 40 return (buf->used == 0 ? 1 : 0); 41} 42 43int buffer_notempty(buffer_t * buf) 44{ 45 return (buf->used > 0 ? 1 : 0); 46} 47 48unsigned long buffer_total_in(buffer_t * buf) 49{ 50 return buf->total_in; 51} 52 53unsigned long buffer_total_out(buffer_t * buf) 54{ 55 return buf->total_out; 56} 57 58/* 59 * These 3 static (internal) functions don't adjust the "total" variables as 60 * it's not sure when they're called how it should be interpreted. Only the 61 * higher-level "buffer_[to|from]_[fd|SSL|BIO]" functions should alter these 62 * values. 63 */ 64# if 0 /* To avoid "unused" warnings */ 65static unsigned int buffer_adddata(buffer_t * buf, const unsigned char *ptr, 66 unsigned int size) 67{ 68 unsigned int added = MAX_DATA_SIZE - buf->used; 69 if (added > size) 70 added = size; 71 if (added == 0) 72 return 0; 73 memcpy(buf->data + buf->used, ptr, added); 74 buf->used += added; 75 buf->total_in += added; 76 return added; 77} 78 79static unsigned int buffer_tobuffer(buffer_t * to, buffer_t * from, int cap) 80{ 81 unsigned int moved, tomove = from->used; 82 if ((int)tomove > cap) 83 tomove = cap; 84 if (tomove == 0) 85 return 0; 86 moved = buffer_adddata(to, from->data, tomove); 87 if (moved == 0) 88 return 0; 89 buffer_takedata(from, NULL, moved); 90 return moved; 91} 92# endif 93 94static unsigned int buffer_takedata(buffer_t * buf, unsigned char *ptr, 95 unsigned int size) 96{ 97 unsigned int taken = buf->used; 98 if (taken > size) 99 taken = size; 100 if (taken == 0) 101 return 0; 102 if (ptr) 103 memcpy(ptr, buf->data, taken); 104 buf->used -= taken; 105 /* Do we have to scroll? */ 106 if (buf->used > 0) 107 memmove(buf->data, buf->data + taken, buf->used); 108 return taken; 109} 110 111# ifndef NO_IP 112 113int buffer_from_fd(buffer_t * buf, int fd) 114{ 115 int toread = buffer_unused(buf); 116 if (toread == 0) 117 /* Shouldn't be called in this case! */ 118 abort(); 119 toread = read(fd, buf->data + buf->used, toread); 120 if (toread > 0) { 121 buf->used += toread; 122 buf->total_in += toread; 123 } 124 return toread; 125} 126 127int buffer_to_fd(buffer_t * buf, int fd) 128{ 129 int towrite = buffer_used(buf); 130 if (towrite == 0) 131 /* Shouldn't be called in this case! */ 132 abort(); 133 towrite = write(fd, buf->data, towrite); 134 if (towrite > 0) { 135 buffer_takedata(buf, NULL, towrite); 136 buf->total_out += towrite; 137 } 138 return towrite; 139} 140 141# endif /* !defined(NO_IP) */ 142 143# ifndef NO_OPENSSL 144 145static void int_ssl_check(SSL *s, int ret) 146{ 147 int e = SSL_get_error(s, ret); 148 switch (e) { 149 /* 150 * These seem to be harmless and already "dealt with" by our 151 * non-blocking environment. NB: "ZERO_RETURN" is the clean "error" 152 * indicating a successfully closed SSL tunnel. We let this happen 153 * because our IO loop should not appear to have broken on this 154 * condition - and outside the IO loop, the "shutdown" state is 155 * checked. 156 */ 157 case SSL_ERROR_NONE: 158 case SSL_ERROR_WANT_READ: 159 case SSL_ERROR_WANT_WRITE: 160 case SSL_ERROR_WANT_X509_LOOKUP: 161 case SSL_ERROR_ZERO_RETURN: 162 return; 163 /* 164 * These seem to be indications of a genuine error that should result 165 * in the SSL tunnel being regarded as "dead". 166 */ 167 case SSL_ERROR_SYSCALL: 168 case SSL_ERROR_SSL: 169 SSL_set_app_data(s, (char *)1); 170 return; 171 default: 172 break; 173 } 174 /* 175 * For any other errors that (a) exist, and (b) crop up - we need to 176 * interpret what to do with them - so "politely inform" the caller that 177 * the code needs updating here. 178 */ 179 abort(); 180} 181 182void buffer_from_SSL(buffer_t * buf, SSL *ssl) 183{ 184 int ret; 185 if (!ssl || buffer_full(buf)) 186 return; 187 ret = SSL_read(ssl, buf->data + buf->used, buffer_unused(buf)); 188 if (ret > 0) { 189 buf->used += ret; 190 buf->total_in += ret; 191 } 192 if (ret < 0) 193 int_ssl_check(ssl, ret); 194} 195 196void buffer_to_SSL(buffer_t * buf, SSL *ssl) 197{ 198 int ret; 199 if (!ssl || buffer_empty(buf)) 200 return; 201 ret = SSL_write(ssl, buf->data, buf->used); 202 if (ret > 0) { 203 buffer_takedata(buf, NULL, ret); 204 buf->total_out += ret; 205 } 206 if (ret < 0) 207 int_ssl_check(ssl, ret); 208} 209 210void buffer_from_BIO(buffer_t * buf, BIO *bio) 211{ 212 int ret; 213 if (!bio || buffer_full(buf)) 214 return; 215 ret = BIO_read(bio, buf->data + buf->used, buffer_unused(buf)); 216 if (ret > 0) { 217 buf->used += ret; 218 buf->total_in += ret; 219 } 220} 221 222void buffer_to_BIO(buffer_t * buf, BIO *bio) 223{ 224 int ret; 225 if (!bio || buffer_empty(buf)) 226 return; 227 ret = BIO_write(bio, buf->data, buf->used); 228 if (ret > 0) { 229 buffer_takedata(buf, NULL, ret); 230 buf->total_out += ret; 231 } 232} 233 234# endif /* !defined(NO_OPENSSL) */ 235 236#endif /* !defined(NO_BUFFER) */ 237