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