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