xref: /openbsd-src/usr.sbin/lpd/io.c (revision 3b188dab47094e37e38dcd2dcd35528ab7a95e4d)
1*3b188dabSeric /*	$OpenBSD: io.c,v 1.1.1.1 2018/04/27 16:14:36 eric Exp $	*/
2*3b188dabSeric 
3*3b188dabSeric /*
4*3b188dabSeric  * Copyright (c) 2012 Eric Faurot <eric@openbsd.org>
5*3b188dabSeric  *
6*3b188dabSeric  * Permission to use, copy, modify, and distribute this software for any
7*3b188dabSeric  * purpose with or without fee is hereby granted, provided that the above
8*3b188dabSeric  * copyright notice and this permission notice appear in all copies.
9*3b188dabSeric  *
10*3b188dabSeric  * THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES
11*3b188dabSeric  * WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF
12*3b188dabSeric  * MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR
13*3b188dabSeric  * ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES
14*3b188dabSeric  * WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN
15*3b188dabSeric  * ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF
16*3b188dabSeric  * OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.
17*3b188dabSeric  */
18*3b188dabSeric 
19*3b188dabSeric #include <sys/types.h>
20*3b188dabSeric #include <sys/queue.h>
21*3b188dabSeric #include <sys/socket.h>
22*3b188dabSeric 
23*3b188dabSeric #include <errno.h>
24*3b188dabSeric #include <fcntl.h>
25*3b188dabSeric #include <inttypes.h>
26*3b188dabSeric #include <netdb.h>
27*3b188dabSeric #include <stdlib.h>
28*3b188dabSeric #include <string.h>
29*3b188dabSeric #include <stdio.h>
30*3b188dabSeric #include <unistd.h>
31*3b188dabSeric 
32*3b188dabSeric #include "io.h"
33*3b188dabSeric #include "iobuf.h"
34*3b188dabSeric #include "log.h"
35*3b188dabSeric 
36*3b188dabSeric #ifdef IO_SSL
37*3b188dabSeric #include <openssl/err.h>
38*3b188dabSeric #include <openssl/ssl.h>
39*3b188dabSeric #endif
40*3b188dabSeric 
41*3b188dabSeric enum {
42*3b188dabSeric 	IO_STATE_DOWN,
43*3b188dabSeric 	IO_STATE_UP,
44*3b188dabSeric 	IO_STATE_CONNECT,
45*3b188dabSeric 	IO_STATE_CONNECT_TLS,
46*3b188dabSeric 	IO_STATE_ACCEPT_TLS
47*3b188dabSeric };
48*3b188dabSeric 
49*3b188dabSeric #define IO_PAUSE_IN		IO_IN
50*3b188dabSeric #define IO_PAUSE_OUT		IO_OUT
51*3b188dabSeric 
52*3b188dabSeric #define IO_READ			0x0100
53*3b188dabSeric #define IO_WRITE		0x0200
54*3b188dabSeric #define IO_RW			(IO_READ | IO_WRITE)
55*3b188dabSeric #define IO_RESET		0x1000
56*3b188dabSeric #define IO_HELD			0x2000
57*3b188dabSeric 
58*3b188dabSeric struct io {
59*3b188dabSeric 	int		 sock;
60*3b188dabSeric 	void		*arg;
61*3b188dabSeric 	void		(*cb)(struct io*, int, void *);
62*3b188dabSeric 	struct iobuf	 iobuf;
63*3b188dabSeric 	size_t		 lowat;
64*3b188dabSeric 	int		 timeout;
65*3b188dabSeric 	int		 flags;
66*3b188dabSeric 	int		 state;
67*3b188dabSeric 	struct event	 ev;
68*3b188dabSeric 	void		*tls;
69*3b188dabSeric 	const char	*error; /* only valid immediately on callback */
70*3b188dabSeric 	struct sockaddr *bind;
71*3b188dabSeric 	struct addrinfo	*ai;	/* for connecting */
72*3b188dabSeric };
73*3b188dabSeric 
74*3b188dabSeric static const char* io_strflags(int);
75*3b188dabSeric static const char* io_strevents(short);
76*3b188dabSeric 
77*3b188dabSeric static void io_reload(struct io *);
78*3b188dabSeric static void io_reset(struct io *, short, void (*)(int, short, void*));
79*3b188dabSeric static void io_frame_enter(const char *, struct io *, int);
80*3b188dabSeric static void io_frame_leave(struct io *);
81*3b188dabSeric static void io_hold(struct io *);
82*3b188dabSeric static void io_release(struct io *);
83*3b188dabSeric static void io_callback(struct io*, int);
84*3b188dabSeric static void io_dispatch(int, short, void *);
85*3b188dabSeric static void io_dispatch_connect(int, short, void *);
86*3b188dabSeric static int io_connect_next(struct io *);
87*3b188dabSeric 
88*3b188dabSeric #ifdef IO_SSL
89*3b188dabSeric void ssl_error(const char *); /* XXX external */
90*3b188dabSeric static const char* io_ssl_error(void);
91*3b188dabSeric static void io_dispatch_accept_tls(int, short, void *);
92*3b188dabSeric static void io_dispatch_connect_tls(int, short, void *);
93*3b188dabSeric static void io_dispatch_read_tls(int, short, void *);
94*3b188dabSeric static void io_dispatch_write_tls(int, short, void *);
95*3b188dabSeric static void io_reload_tls(struct io *io);
96*3b188dabSeric #endif
97*3b188dabSeric 
98*3b188dabSeric static struct io *current = NULL;
99*3b188dabSeric static long long unsigned frame = 0;
100*3b188dabSeric static int _io_trace = 0;
101*3b188dabSeric 
102*3b188dabSeric static const char *states[] = {
103*3b188dabSeric     "DOWN",
104*3b188dabSeric     "UP",
105*3b188dabSeric     "CONNECT",
106*3b188dabSeric     "CONNECT_TLS",
107*3b188dabSeric     "ACCEPT_TLS"
108*3b188dabSeric };
109*3b188dabSeric 
110*3b188dabSeric #define io_debug(args...) do { if (_io_trace) log_debug(args); } while(0)
111*3b188dabSeric #define IO_READING(io) (((io)->flags & IO_RW) != IO_WRITE)
112*3b188dabSeric #define IO_WRITING(io) (((io)->flags & IO_RW) != IO_READ)
113*3b188dabSeric 
114*3b188dabSeric void
io_trace(int on)115*3b188dabSeric io_trace(int on)
116*3b188dabSeric {
117*3b188dabSeric 	_io_trace = on;
118*3b188dabSeric }
119*3b188dabSeric 
120*3b188dabSeric const char*
io_strio(struct io * io)121*3b188dabSeric io_strio(struct io *io)
122*3b188dabSeric {
123*3b188dabSeric 	static char buf[128];
124*3b188dabSeric 	char ssl[128];
125*3b188dabSeric 
126*3b188dabSeric 	ssl[0] = '\0';
127*3b188dabSeric #ifdef IO_SSL
128*3b188dabSeric 	if (io->tls) {
129*3b188dabSeric 		(void)snprintf(ssl, sizeof ssl, " ssl=%s:%s:%d",
130*3b188dabSeric 		    SSL_get_version(io->tls),
131*3b188dabSeric 		    SSL_get_cipher_name(io->tls),
132*3b188dabSeric 		    SSL_get_cipher_bits(io->tls, NULL));
133*3b188dabSeric 	}
134*3b188dabSeric #endif
135*3b188dabSeric 	(void)snprintf(buf, sizeof buf,
136*3b188dabSeric 	    "<io:%p st=%s, fd=%d to=%d fl=%s%s ib=%zu ob=%zu>",
137*3b188dabSeric 	    io, states[io->state], io->sock, io->timeout,
138*3b188dabSeric 	    io_strflags(io->flags), ssl, io_datalen(io), io_queued(io));
139*3b188dabSeric 
140*3b188dabSeric 	return buf;
141*3b188dabSeric }
142*3b188dabSeric 
143*3b188dabSeric const char*
io_strevent(int evt)144*3b188dabSeric io_strevent(int evt)
145*3b188dabSeric {
146*3b188dabSeric 	static char buf[32];
147*3b188dabSeric 
148*3b188dabSeric 	switch (evt) {
149*3b188dabSeric 	case IO_CONNECTED:
150*3b188dabSeric 		return "IO_CONNECTED";
151*3b188dabSeric 	case IO_TLSREADY:
152*3b188dabSeric 		return "IO_TLSREADY";
153*3b188dabSeric 	case IO_DATAIN:
154*3b188dabSeric 		return "IO_DATAIN";
155*3b188dabSeric 	case IO_LOWAT:
156*3b188dabSeric 		return "IO_LOWAT";
157*3b188dabSeric 	case IO_CLOSED:
158*3b188dabSeric 		return "IO_CLOSED";
159*3b188dabSeric 	case IO_DISCONNECTED:
160*3b188dabSeric 		return "IO_DISCONNECTED";
161*3b188dabSeric 	case IO_TIMEOUT:
162*3b188dabSeric 		return "IO_TIMEOUT";
163*3b188dabSeric 	case IO_ERROR:
164*3b188dabSeric 		return "IO_ERROR";
165*3b188dabSeric 	case IO_TLSERROR:
166*3b188dabSeric 		return "IO_TLSERROR";
167*3b188dabSeric 	default:
168*3b188dabSeric 		(void)snprintf(buf, sizeof(buf), "IO_? %d", evt);
169*3b188dabSeric 		return buf;
170*3b188dabSeric 	}
171*3b188dabSeric }
172*3b188dabSeric 
173*3b188dabSeric struct io *
io_new(void)174*3b188dabSeric io_new(void)
175*3b188dabSeric {
176*3b188dabSeric 	struct io *io;
177*3b188dabSeric 
178*3b188dabSeric 	io = calloc(1, sizeof(*io));
179*3b188dabSeric 	if (io == NULL)
180*3b188dabSeric 		return NULL;
181*3b188dabSeric 
182*3b188dabSeric 	iobuf_init(&io->iobuf, 0, 0);
183*3b188dabSeric 	io->sock = -1;
184*3b188dabSeric 	io->timeout = -1;
185*3b188dabSeric 
186*3b188dabSeric 	return io;
187*3b188dabSeric }
188*3b188dabSeric 
189*3b188dabSeric void
io_free(struct io * io)190*3b188dabSeric io_free(struct io *io)
191*3b188dabSeric {
192*3b188dabSeric 	io_debug("%s(%p)", __func__, io);
193*3b188dabSeric 
194*3b188dabSeric 	/* the current io is virtually dead */
195*3b188dabSeric 	if (io == current)
196*3b188dabSeric 		current = NULL;
197*3b188dabSeric 
198*3b188dabSeric #ifdef IO_SSL
199*3b188dabSeric 	if (io->tls) {
200*3b188dabSeric 		SSL_free(io->tls);
201*3b188dabSeric 		io->tls = NULL;
202*3b188dabSeric 	}
203*3b188dabSeric #endif
204*3b188dabSeric 
205*3b188dabSeric 	if (io->ai)
206*3b188dabSeric 		freeaddrinfo(io->ai);
207*3b188dabSeric 	if (event_initialized(&io->ev))
208*3b188dabSeric 		event_del(&io->ev);
209*3b188dabSeric 	if (io->sock != -1) {
210*3b188dabSeric 		(void)close(io->sock);
211*3b188dabSeric 		io->sock = -1;
212*3b188dabSeric 	}
213*3b188dabSeric 
214*3b188dabSeric 	iobuf_clear(&io->iobuf);
215*3b188dabSeric 	free(io->bind);
216*3b188dabSeric 	free(io);
217*3b188dabSeric }
218*3b188dabSeric 
219*3b188dabSeric int
io_set_callback(struct io * io,void (* cb)(struct io *,int,void *),void * arg)220*3b188dabSeric io_set_callback(struct io *io, void(*cb)(struct io *, int, void *), void *arg)
221*3b188dabSeric {
222*3b188dabSeric 	io->cb = cb;
223*3b188dabSeric 	io->arg = arg;
224*3b188dabSeric 
225*3b188dabSeric 	return 0;
226*3b188dabSeric }
227*3b188dabSeric 
228*3b188dabSeric int
io_set_bindaddr(struct io * io,const struct sockaddr * sa)229*3b188dabSeric io_set_bindaddr(struct io *io, const struct sockaddr *sa)
230*3b188dabSeric {
231*3b188dabSeric 	struct sockaddr *t;
232*3b188dabSeric 
233*3b188dabSeric 	if (io->state != IO_STATE_DOWN) {
234*3b188dabSeric 		errno = EISCONN;
235*3b188dabSeric 		return -1;
236*3b188dabSeric 	}
237*3b188dabSeric 
238*3b188dabSeric 	t = malloc(sa->sa_len);
239*3b188dabSeric 	if (t == NULL)
240*3b188dabSeric 		return -1;
241*3b188dabSeric 	memmove(t, sa, sa->sa_len);
242*3b188dabSeric 
243*3b188dabSeric 	free(io->bind);
244*3b188dabSeric 	io->bind = t;
245*3b188dabSeric 
246*3b188dabSeric 	return 0;
247*3b188dabSeric }
248*3b188dabSeric 
249*3b188dabSeric int
io_set_bufsize(struct io * io,size_t sz)250*3b188dabSeric io_set_bufsize(struct io *io, size_t sz)
251*3b188dabSeric {
252*3b188dabSeric 	errno = ENOSYS;
253*3b188dabSeric 	return -1;
254*3b188dabSeric }
255*3b188dabSeric 
256*3b188dabSeric void
io_set_timeout(struct io * io,int msec)257*3b188dabSeric io_set_timeout(struct io *io, int msec)
258*3b188dabSeric {
259*3b188dabSeric 	io_debug("%s(%p, %d)", __func__, io, msec);
260*3b188dabSeric 
261*3b188dabSeric 	io->timeout = msec;
262*3b188dabSeric }
263*3b188dabSeric 
264*3b188dabSeric void
io_set_lowat(struct io * io,size_t lowat)265*3b188dabSeric io_set_lowat(struct io *io, size_t lowat)
266*3b188dabSeric {
267*3b188dabSeric 	io_debug("%s(%p, %zu)", __func__, io, lowat);
268*3b188dabSeric 
269*3b188dabSeric 	io->lowat = lowat;
270*3b188dabSeric }
271*3b188dabSeric 
272*3b188dabSeric const char *
io_error(struct io * io)273*3b188dabSeric io_error(struct io *io)
274*3b188dabSeric {
275*3b188dabSeric 	const char *e;
276*3b188dabSeric 
277*3b188dabSeric 	e = io->error;
278*3b188dabSeric 	io->error = NULL;
279*3b188dabSeric 	return e;
280*3b188dabSeric }
281*3b188dabSeric 
282*3b188dabSeric int
io_fileno(struct io * io)283*3b188dabSeric io_fileno(struct io *io)
284*3b188dabSeric {
285*3b188dabSeric 	return io->sock;
286*3b188dabSeric }
287*3b188dabSeric 
288*3b188dabSeric int
io_attach(struct io * io,int sock)289*3b188dabSeric io_attach(struct io *io, int sock)
290*3b188dabSeric {
291*3b188dabSeric 	if (io->state != IO_STATE_DOWN) {
292*3b188dabSeric 		errno = EISCONN;
293*3b188dabSeric 		return -1;
294*3b188dabSeric 	}
295*3b188dabSeric 
296*3b188dabSeric 	io->state = IO_STATE_UP;
297*3b188dabSeric 	io->sock = sock;
298*3b188dabSeric 	io_reload(io);
299*3b188dabSeric 	return 0;
300*3b188dabSeric }
301*3b188dabSeric 
302*3b188dabSeric int
io_detach(struct io * io)303*3b188dabSeric io_detach(struct io *io)
304*3b188dabSeric {
305*3b188dabSeric 	errno = ENOSYS;
306*3b188dabSeric 	return -1;
307*3b188dabSeric }
308*3b188dabSeric 
309*3b188dabSeric int
io_close(struct io * io)310*3b188dabSeric io_close(struct io *io)
311*3b188dabSeric {
312*3b188dabSeric 	errno = ENOSYS;
313*3b188dabSeric 	return -1;
314*3b188dabSeric }
315*3b188dabSeric 
316*3b188dabSeric int
io_connect(struct io * io,struct addrinfo * ai)317*3b188dabSeric io_connect(struct io *io, struct addrinfo *ai)
318*3b188dabSeric {
319*3b188dabSeric 	if (ai == NULL) {
320*3b188dabSeric 		errno = EINVAL;
321*3b188dabSeric 		fatal("%s", __func__);
322*3b188dabSeric 		return -1;
323*3b188dabSeric 	}
324*3b188dabSeric 
325*3b188dabSeric 	if (io->state != IO_STATE_DOWN) {
326*3b188dabSeric 		freeaddrinfo(ai);
327*3b188dabSeric 		errno = EISCONN;
328*3b188dabSeric 		fatal("%s", __func__);
329*3b188dabSeric 		return -1;
330*3b188dabSeric 	}
331*3b188dabSeric 
332*3b188dabSeric 	io->ai = ai;
333*3b188dabSeric 	return io_connect_next(io);
334*3b188dabSeric }
335*3b188dabSeric 
336*3b188dabSeric int
io_disconnect(struct io * io)337*3b188dabSeric io_disconnect(struct io *io)
338*3b188dabSeric {
339*3b188dabSeric 	errno = ENOSYS;
340*3b188dabSeric 	fatal("%s", __func__);
341*3b188dabSeric 	return -1;
342*3b188dabSeric }
343*3b188dabSeric 
344*3b188dabSeric int
io_starttls(struct io * io,void * ssl)345*3b188dabSeric io_starttls(struct io *io, void *ssl)
346*3b188dabSeric {
347*3b188dabSeric #ifdef IO_SSL
348*3b188dabSeric 	int mode;
349*3b188dabSeric 
350*3b188dabSeric 	mode = io->flags & IO_RW;
351*3b188dabSeric 	if (mode == 0 || mode == IO_RW)
352*3b188dabSeric 		fatalx("%s: full-duplex or unset", __func__);
353*3b188dabSeric 
354*3b188dabSeric 	if (io->tls)
355*3b188dabSeric 		fatalx("%s: SSL already started", __func__);
356*3b188dabSeric 	io->tls = ssl;
357*3b188dabSeric 
358*3b188dabSeric 	if (SSL_set_fd(io->tls, io->sock) == 0) {
359*3b188dabSeric 		ssl_error("io_start_tls:SSL_set_fd");
360*3b188dabSeric 		return -1;
361*3b188dabSeric 	}
362*3b188dabSeric 
363*3b188dabSeric 	if (mode == IO_WRITE) {
364*3b188dabSeric 		io->state = IO_STATE_CONNECT_TLS;
365*3b188dabSeric 		SSL_set_connect_state(io->tls);
366*3b188dabSeric 		io_reset(io, EV_WRITE, io_dispatch_connect_tls);
367*3b188dabSeric 	} else {
368*3b188dabSeric 		io->state = IO_STATE_ACCEPT_TLS;
369*3b188dabSeric 		SSL_set_accept_state(io->tls);
370*3b188dabSeric 		io_reset(io, EV_READ, io_dispatch_accept_tls);
371*3b188dabSeric 	}
372*3b188dabSeric 
373*3b188dabSeric 	return 0;
374*3b188dabSeric #else
375*3b188dabSeric 	errno = ENOSYS;
376*3b188dabSeric 	return -1;
377*3b188dabSeric #endif
378*3b188dabSeric }
379*3b188dabSeric 
380*3b188dabSeric void
io_pause(struct io * io,int dir)381*3b188dabSeric io_pause(struct io *io, int dir)
382*3b188dabSeric {
383*3b188dabSeric 	io_debug("%s(%p, %x)", __func__, io, dir);
384*3b188dabSeric 
385*3b188dabSeric 	io->flags |= dir & (IO_IN | IO_OUT);
386*3b188dabSeric 	io_reload(io);
387*3b188dabSeric }
388*3b188dabSeric 
389*3b188dabSeric void
io_resume(struct io * io,int dir)390*3b188dabSeric io_resume(struct io *io, int dir)
391*3b188dabSeric {
392*3b188dabSeric 	io_debug("%s(%p, %x)", __func__, io, dir);
393*3b188dabSeric 
394*3b188dabSeric 	io->flags &= ~(dir & (IO_IN | IO_OUT));
395*3b188dabSeric 	io_reload(io);
396*3b188dabSeric }
397*3b188dabSeric 
398*3b188dabSeric void
io_set_read(struct io * io)399*3b188dabSeric io_set_read(struct io *io)
400*3b188dabSeric {
401*3b188dabSeric 	int mode;
402*3b188dabSeric 
403*3b188dabSeric 	io_debug("%s(%p)", __func__, io);
404*3b188dabSeric 
405*3b188dabSeric 	mode = io->flags & IO_RW;
406*3b188dabSeric 	if (!(mode == 0 || mode == IO_WRITE))
407*3b188dabSeric 		fatalx("%s: full-duplex or reading", __func__);
408*3b188dabSeric 
409*3b188dabSeric 	io->flags &= ~IO_RW;
410*3b188dabSeric 	io->flags |= IO_READ;
411*3b188dabSeric 	io_reload(io);
412*3b188dabSeric }
413*3b188dabSeric 
414*3b188dabSeric void
io_set_write(struct io * io)415*3b188dabSeric io_set_write(struct io *io)
416*3b188dabSeric {
417*3b188dabSeric 	int mode;
418*3b188dabSeric 
419*3b188dabSeric 	io_debug("%s(%p)", __func__, io);
420*3b188dabSeric 
421*3b188dabSeric 	mode = io->flags & IO_RW;
422*3b188dabSeric 	if (!(mode == 0 || mode == IO_READ))
423*3b188dabSeric 		fatalx("%s: full-duplex or writing", __func__);
424*3b188dabSeric 
425*3b188dabSeric 	io->flags &= ~IO_RW;
426*3b188dabSeric 	io->flags |= IO_WRITE;
427*3b188dabSeric 	io_reload(io);
428*3b188dabSeric }
429*3b188dabSeric 
430*3b188dabSeric int
io_write(struct io * io,const void * buf,size_t len)431*3b188dabSeric io_write(struct io *io, const void *buf, size_t len)
432*3b188dabSeric {
433*3b188dabSeric 	int r;
434*3b188dabSeric 
435*3b188dabSeric 	r = iobuf_queue(&io->iobuf, buf, len);
436*3b188dabSeric 
437*3b188dabSeric 	io_reload(io);
438*3b188dabSeric 
439*3b188dabSeric 	return r;
440*3b188dabSeric }
441*3b188dabSeric 
442*3b188dabSeric int
io_writev(struct io * io,const struct iovec * iov,int iovcount)443*3b188dabSeric io_writev(struct io *io, const struct iovec *iov, int iovcount)
444*3b188dabSeric {
445*3b188dabSeric 	int r;
446*3b188dabSeric 
447*3b188dabSeric 	r = iobuf_queuev(&io->iobuf, iov, iovcount);
448*3b188dabSeric 
449*3b188dabSeric 	io_reload(io);
450*3b188dabSeric 
451*3b188dabSeric 	return r;
452*3b188dabSeric }
453*3b188dabSeric 
454*3b188dabSeric int
io_print(struct io * io,const char * s)455*3b188dabSeric io_print(struct io *io, const char *s)
456*3b188dabSeric {
457*3b188dabSeric 	return io_write(io, s, strlen(s));
458*3b188dabSeric }
459*3b188dabSeric 
460*3b188dabSeric int
io_printf(struct io * io,const char * fmt,...)461*3b188dabSeric io_printf(struct io *io, const char *fmt, ...)
462*3b188dabSeric {
463*3b188dabSeric 	va_list ap;
464*3b188dabSeric 	int r;
465*3b188dabSeric 
466*3b188dabSeric 	va_start(ap, fmt);
467*3b188dabSeric 	r = io_vprintf(io, fmt, ap);
468*3b188dabSeric 	va_end(ap);
469*3b188dabSeric 
470*3b188dabSeric 	return r;
471*3b188dabSeric }
472*3b188dabSeric 
473*3b188dabSeric int
io_vprintf(struct io * io,const char * fmt,va_list ap)474*3b188dabSeric io_vprintf(struct io *io, const char *fmt, va_list ap)
475*3b188dabSeric {
476*3b188dabSeric 
477*3b188dabSeric 	char *buf;
478*3b188dabSeric 	int len;
479*3b188dabSeric 
480*3b188dabSeric 	len = vasprintf(&buf, fmt, ap);
481*3b188dabSeric 	if (len == -1)
482*3b188dabSeric 		return -1;
483*3b188dabSeric 
484*3b188dabSeric 	len = io_write(io, buf, len);
485*3b188dabSeric 	free(buf);
486*3b188dabSeric 
487*3b188dabSeric 	return len;
488*3b188dabSeric }
489*3b188dabSeric 
490*3b188dabSeric size_t
io_queued(struct io * io)491*3b188dabSeric io_queued(struct io *io)
492*3b188dabSeric {
493*3b188dabSeric 	return iobuf_queued(&io->iobuf);
494*3b188dabSeric }
495*3b188dabSeric 
496*3b188dabSeric void *
io_data(struct io * io)497*3b188dabSeric io_data(struct io *io)
498*3b188dabSeric {
499*3b188dabSeric 	return iobuf_data(&io->iobuf);
500*3b188dabSeric }
501*3b188dabSeric 
502*3b188dabSeric size_t
io_datalen(struct io * io)503*3b188dabSeric io_datalen(struct io *io)
504*3b188dabSeric {
505*3b188dabSeric 	return iobuf_len(&io->iobuf);
506*3b188dabSeric }
507*3b188dabSeric 
508*3b188dabSeric char *
io_getline(struct io * io,size_t * sz)509*3b188dabSeric io_getline(struct io *io, size_t *sz)
510*3b188dabSeric {
511*3b188dabSeric 	return iobuf_getline(&io->iobuf, sz);
512*3b188dabSeric }
513*3b188dabSeric 
514*3b188dabSeric void
io_drop(struct io * io,size_t sz)515*3b188dabSeric io_drop(struct io *io, size_t sz)
516*3b188dabSeric {
517*3b188dabSeric 	return iobuf_drop(&io->iobuf, sz);
518*3b188dabSeric }
519*3b188dabSeric 
520*3b188dabSeric const char*
io_strflags(int flags)521*3b188dabSeric io_strflags(int flags)
522*3b188dabSeric {
523*3b188dabSeric 	static char buf[64];
524*3b188dabSeric 
525*3b188dabSeric 	buf[0] = '\0';
526*3b188dabSeric 
527*3b188dabSeric 	switch (flags & IO_RW) {
528*3b188dabSeric 	case 0:
529*3b188dabSeric 		(void)strlcat(buf, "rw", sizeof buf);
530*3b188dabSeric 		break;
531*3b188dabSeric 	case IO_READ:
532*3b188dabSeric 		(void)strlcat(buf, "R", sizeof buf);
533*3b188dabSeric 		break;
534*3b188dabSeric 	case IO_WRITE:
535*3b188dabSeric 		(void)strlcat(buf, "W", sizeof buf);
536*3b188dabSeric 		break;
537*3b188dabSeric 	case IO_RW:
538*3b188dabSeric 		(void)strlcat(buf, "RW", sizeof buf);
539*3b188dabSeric 		break;
540*3b188dabSeric 	}
541*3b188dabSeric 
542*3b188dabSeric 	if (flags & IO_PAUSE_IN)
543*3b188dabSeric 		(void)strlcat(buf, ",F_PI", sizeof buf);
544*3b188dabSeric 	if (flags & IO_PAUSE_OUT)
545*3b188dabSeric 		(void)strlcat(buf, ",F_PO", sizeof buf);
546*3b188dabSeric 
547*3b188dabSeric 	return buf;
548*3b188dabSeric }
549*3b188dabSeric 
550*3b188dabSeric const char*
io_strevents(short ev)551*3b188dabSeric io_strevents(short ev)
552*3b188dabSeric {
553*3b188dabSeric 	static char buf[64];
554*3b188dabSeric 	char buf2[16];
555*3b188dabSeric 	int n;
556*3b188dabSeric 
557*3b188dabSeric 	n = 0;
558*3b188dabSeric 	buf[0] = '\0';
559*3b188dabSeric 
560*3b188dabSeric 	if (ev == 0) {
561*3b188dabSeric 		(void)strlcat(buf, "<NONE>", sizeof(buf));
562*3b188dabSeric 		return buf;
563*3b188dabSeric 	}
564*3b188dabSeric 
565*3b188dabSeric 	if (ev & EV_TIMEOUT) {
566*3b188dabSeric 		(void)strlcat(buf, "EV_TIMEOUT", sizeof(buf));
567*3b188dabSeric 		ev &= ~EV_TIMEOUT;
568*3b188dabSeric 		n++;
569*3b188dabSeric 	}
570*3b188dabSeric 
571*3b188dabSeric 	if (ev & EV_READ) {
572*3b188dabSeric 		if (n)
573*3b188dabSeric 			(void)strlcat(buf, "|", sizeof(buf));
574*3b188dabSeric 		(void)strlcat(buf, "EV_READ", sizeof(buf));
575*3b188dabSeric 		ev &= ~EV_READ;
576*3b188dabSeric 		n++;
577*3b188dabSeric 	}
578*3b188dabSeric 
579*3b188dabSeric 	if (ev & EV_WRITE) {
580*3b188dabSeric 		if (n)
581*3b188dabSeric 			(void)strlcat(buf, "|", sizeof(buf));
582*3b188dabSeric 		(void)strlcat(buf, "EV_WRITE", sizeof(buf));
583*3b188dabSeric 		ev &= ~EV_WRITE;
584*3b188dabSeric 		n++;
585*3b188dabSeric 	}
586*3b188dabSeric 
587*3b188dabSeric 	if (ev & EV_SIGNAL) {
588*3b188dabSeric 		if (n)
589*3b188dabSeric 			(void)strlcat(buf, "|", sizeof(buf));
590*3b188dabSeric 		(void)strlcat(buf, "EV_SIGNAL", sizeof(buf));
591*3b188dabSeric 		ev &= ~EV_SIGNAL;
592*3b188dabSeric 		n++;
593*3b188dabSeric 	}
594*3b188dabSeric 
595*3b188dabSeric 	if (ev) {
596*3b188dabSeric 		if (n)
597*3b188dabSeric 			(void)strlcat(buf, "|", sizeof(buf));
598*3b188dabSeric 		(void)strlcat(buf, "EV_?=0x", sizeof(buf));
599*3b188dabSeric 		(void)snprintf(buf2, sizeof(buf2), "%hx", ev);
600*3b188dabSeric 		(void)strlcat(buf, buf2, sizeof(buf));
601*3b188dabSeric 	}
602*3b188dabSeric 
603*3b188dabSeric 	return buf;
604*3b188dabSeric }
605*3b188dabSeric 
606*3b188dabSeric /*
607*3b188dabSeric  * Setup the necessary events as required by the current io state,
608*3b188dabSeric  * honouring duplex mode and i/o pause.
609*3b188dabSeric  */
610*3b188dabSeric static void
io_reload(struct io * io)611*3b188dabSeric io_reload(struct io *io)
612*3b188dabSeric {
613*3b188dabSeric 	short events;
614*3b188dabSeric 
615*3b188dabSeric 	/* The io will be reloaded at release time. */
616*3b188dabSeric 	if (io->flags & IO_HELD)
617*3b188dabSeric 		return;
618*3b188dabSeric 
619*3b188dabSeric 	/* Do nothing if no socket. */
620*3b188dabSeric 	if (io->sock == -1)
621*3b188dabSeric 		return;
622*3b188dabSeric 
623*3b188dabSeric #ifdef IO_SSL
624*3b188dabSeric 	if (io->tls) {
625*3b188dabSeric 		io_reload_tls(io);
626*3b188dabSeric 		return;
627*3b188dabSeric 	}
628*3b188dabSeric #endif
629*3b188dabSeric 
630*3b188dabSeric 	io_debug("%s(%p)", __func__, io);
631*3b188dabSeric 
632*3b188dabSeric 	events = 0;
633*3b188dabSeric 	if (IO_READING(io) && !(io->flags & IO_PAUSE_IN))
634*3b188dabSeric 		events = EV_READ;
635*3b188dabSeric 	if (IO_WRITING(io) && !(io->flags & IO_PAUSE_OUT) && io_queued(io))
636*3b188dabSeric 		events |= EV_WRITE;
637*3b188dabSeric 
638*3b188dabSeric 	io_reset(io, events, io_dispatch);
639*3b188dabSeric }
640*3b188dabSeric 
641*3b188dabSeric static void
io_reset(struct io * io,short events,void (* dispatch)(int,short,void *))642*3b188dabSeric io_reset(struct io *io, short events, void (*dispatch)(int, short, void*))
643*3b188dabSeric {
644*3b188dabSeric 	struct timeval tv, *ptv;
645*3b188dabSeric 
646*3b188dabSeric 	io_debug("%s(%p, %s, %p) -> %s", __func__, io,
647*3b188dabSeric 	    io_strevents(events), dispatch, io_strio(io));
648*3b188dabSeric 
649*3b188dabSeric 	/*
650*3b188dabSeric 	 * Indicate that the event has already been reset so that reload
651*3b188dabSeric 	 * is not called on frame_leave.
652*3b188dabSeric 	 */
653*3b188dabSeric 	io->flags |= IO_RESET;
654*3b188dabSeric 
655*3b188dabSeric 	if (event_initialized(&io->ev))
656*3b188dabSeric 		event_del(&io->ev);
657*3b188dabSeric 
658*3b188dabSeric 	/*
659*3b188dabSeric 	 * The io is paused by the user, so we don't want the timeout to be
660*3b188dabSeric 	 * effective.
661*3b188dabSeric 	 */
662*3b188dabSeric 	if (events == 0)
663*3b188dabSeric 		return;
664*3b188dabSeric 
665*3b188dabSeric 	event_set(&io->ev, io->sock, events, dispatch, io);
666*3b188dabSeric 	if (io->timeout >= 0) {
667*3b188dabSeric 		tv.tv_sec = io->timeout / 1000;
668*3b188dabSeric 		tv.tv_usec = (io->timeout % 1000) * 1000;
669*3b188dabSeric 		ptv = &tv;
670*3b188dabSeric 	} else
671*3b188dabSeric 		ptv = NULL;
672*3b188dabSeric 
673*3b188dabSeric 	event_add(&io->ev, ptv);
674*3b188dabSeric }
675*3b188dabSeric 
676*3b188dabSeric static void
io_frame_enter(const char * where,struct io * io,int ev)677*3b188dabSeric io_frame_enter(const char *where, struct io *io, int ev)
678*3b188dabSeric {
679*3b188dabSeric 	io_debug("io: BEGIN %llu", frame);
680*3b188dabSeric 	io_debug("%s(%s, %s, %s)", __func__, where, io_strevents(ev),
681*3b188dabSeric 	    io_strio(io));
682*3b188dabSeric 
683*3b188dabSeric 	if (current)
684*3b188dabSeric 		fatalx("%s: interleaved frames", __func__);
685*3b188dabSeric 
686*3b188dabSeric 	current = io;
687*3b188dabSeric 
688*3b188dabSeric 	io_hold(io);
689*3b188dabSeric }
690*3b188dabSeric 
691*3b188dabSeric static void
io_frame_leave(struct io * io)692*3b188dabSeric io_frame_leave(struct io *io)
693*3b188dabSeric {
694*3b188dabSeric 	io_debug("%s(%llu)", __func__, frame);
695*3b188dabSeric 
696*3b188dabSeric 	if (current && current != io)
697*3b188dabSeric 		fatalx("%s: io mismatch", __func__);
698*3b188dabSeric 
699*3b188dabSeric 	/* The io has been cleared. */
700*3b188dabSeric 	if (current == NULL)
701*3b188dabSeric 		goto done;
702*3b188dabSeric 
703*3b188dabSeric 	/*
704*3b188dabSeric 	 * TODO: There is a possible optimization there:
705*3b188dabSeric 	 * In a typical half-duplex request/response scenario,
706*3b188dabSeric 	 * the io is waiting to read a request, and when done, it queues
707*3b188dabSeric 	 * the response in the output buffer and goes to write mode.
708*3b188dabSeric 	 * There, the write event is set and will be triggered in the next
709*3b188dabSeric 	 * event frame.  In most case, the write call could be done
710*3b188dabSeric 	 * immediately as part of the last read frame, thus avoiding to go
711*3b188dabSeric 	 * through the event loop machinery. So, as an optimisation, we
712*3b188dabSeric 	 * could detect that case here and force an event dispatching.
713*3b188dabSeric 	 */
714*3b188dabSeric 
715*3b188dabSeric 	/* Reload the io if it has not been reset already. */
716*3b188dabSeric 	io_release(io);
717*3b188dabSeric 	current = NULL;
718*3b188dabSeric     done:
719*3b188dabSeric 	io_debug("io: END %llu", frame);
720*3b188dabSeric 
721*3b188dabSeric 	frame += 1;
722*3b188dabSeric }
723*3b188dabSeric 
724*3b188dabSeric static void
io_hold(struct io * io)725*3b188dabSeric io_hold(struct io *io)
726*3b188dabSeric {
727*3b188dabSeric 	io_debug("%s(%p)", __func__, io);
728*3b188dabSeric 
729*3b188dabSeric 	if (io->flags & IO_HELD)
730*3b188dabSeric 		fatalx("%s: already held", __func__);
731*3b188dabSeric 
732*3b188dabSeric 	io->flags &= ~IO_RESET;
733*3b188dabSeric 	io->flags |= IO_HELD;
734*3b188dabSeric }
735*3b188dabSeric 
736*3b188dabSeric static void
io_release(struct io * io)737*3b188dabSeric io_release(struct io *io)
738*3b188dabSeric {
739*3b188dabSeric 	io_debug("%s(%p)", __func__, io);
740*3b188dabSeric 
741*3b188dabSeric 	if (!(io->flags & IO_HELD))
742*3b188dabSeric 		fatalx("%s: not held", __func__);
743*3b188dabSeric 
744*3b188dabSeric 	io->flags &= ~IO_HELD;
745*3b188dabSeric 	if (!(io->flags & IO_RESET))
746*3b188dabSeric 		io_reload(io);
747*3b188dabSeric }
748*3b188dabSeric 
749*3b188dabSeric static void
io_callback(struct io * io,int evt)750*3b188dabSeric io_callback(struct io *io, int evt)
751*3b188dabSeric {
752*3b188dabSeric 	io_debug("%s(%s, %s)", __func__, io_strio(io), io_strevent(evt));
753*3b188dabSeric 
754*3b188dabSeric 	io->cb(io, evt, io->arg);
755*3b188dabSeric }
756*3b188dabSeric 
757*3b188dabSeric static void
io_dispatch(int fd,short ev,void * arg)758*3b188dabSeric io_dispatch(int fd, short ev, void *arg)
759*3b188dabSeric {
760*3b188dabSeric 	struct io *io = arg;
761*3b188dabSeric 	size_t w;
762*3b188dabSeric 	ssize_t n;
763*3b188dabSeric 	int saved_errno;
764*3b188dabSeric 
765*3b188dabSeric 	io_frame_enter(__func__, io, ev);
766*3b188dabSeric 
767*3b188dabSeric 	if (ev == EV_TIMEOUT) {
768*3b188dabSeric 		io_callback(io, IO_TIMEOUT);
769*3b188dabSeric 		goto leave;
770*3b188dabSeric 	}
771*3b188dabSeric 
772*3b188dabSeric 	if (ev & EV_WRITE && (w = io_queued(io))) {
773*3b188dabSeric 		if ((n = iobuf_write(&io->iobuf, io->sock)) < 0) {
774*3b188dabSeric 			if (n == IOBUF_WANT_WRITE) /* kqueue bug? */
775*3b188dabSeric 				goto read;
776*3b188dabSeric 			if (n == IOBUF_CLOSED)
777*3b188dabSeric 				io_callback(io, IO_DISCONNECTED);
778*3b188dabSeric 			else {
779*3b188dabSeric 				log_warn("%s: iobuf_write", __func__);
780*3b188dabSeric 				saved_errno = errno;
781*3b188dabSeric 				io->error = strerror(errno);
782*3b188dabSeric 				errno = saved_errno;
783*3b188dabSeric 				io_callback(io, IO_ERROR);
784*3b188dabSeric 			}
785*3b188dabSeric 			goto leave;
786*3b188dabSeric 		}
787*3b188dabSeric 		if (w > io->lowat && w - n <= io->lowat)
788*3b188dabSeric 			io_callback(io, IO_LOWAT);
789*3b188dabSeric 	}
790*3b188dabSeric     read:
791*3b188dabSeric 
792*3b188dabSeric 	if (ev & EV_READ) {
793*3b188dabSeric 		iobuf_normalize(&io->iobuf);
794*3b188dabSeric 		if ((n = iobuf_read(&io->iobuf, io->sock)) < 0) {
795*3b188dabSeric 			if (n == IOBUF_CLOSED)
796*3b188dabSeric 				io_callback(io, IO_DISCONNECTED);
797*3b188dabSeric 			else {
798*3b188dabSeric 				log_warn("%s: iobuf_read", __func__);
799*3b188dabSeric 				saved_errno = errno;
800*3b188dabSeric 				io->error = strerror(errno);
801*3b188dabSeric 				errno = saved_errno;
802*3b188dabSeric 				io_callback(io, IO_ERROR);
803*3b188dabSeric 			}
804*3b188dabSeric 			goto leave;
805*3b188dabSeric 		}
806*3b188dabSeric 		if (n)
807*3b188dabSeric 			io_callback(io, IO_DATAIN);
808*3b188dabSeric 	}
809*3b188dabSeric 
810*3b188dabSeric leave:
811*3b188dabSeric 	io_frame_leave(io);
812*3b188dabSeric }
813*3b188dabSeric 
814*3b188dabSeric static void
io_dispatch_connect(int fd,short ev,void * arg)815*3b188dabSeric io_dispatch_connect(int fd, short ev, void *arg)
816*3b188dabSeric {
817*3b188dabSeric 	struct io *io = arg;
818*3b188dabSeric 	socklen_t sl;
819*3b188dabSeric 	int r, e;
820*3b188dabSeric 
821*3b188dabSeric 	io_frame_enter(__func__, io, ev);
822*3b188dabSeric 
823*3b188dabSeric 	if (ev == EV_TIMEOUT)
824*3b188dabSeric 		e = ETIMEDOUT;
825*3b188dabSeric 	else {
826*3b188dabSeric 		sl = sizeof(e);
827*3b188dabSeric 		r = getsockopt(fd, SOL_SOCKET, SO_ERROR, &e, &sl);
828*3b188dabSeric 		if (r == -1)  {
829*3b188dabSeric 			log_warn("%s: getsockopt", __func__);
830*3b188dabSeric 			e = errno;
831*3b188dabSeric 		}
832*3b188dabSeric 		else if (e) {
833*3b188dabSeric 			errno = e;
834*3b188dabSeric 			log_warn("%s: (connect)", __func__);
835*3b188dabSeric 		}
836*3b188dabSeric 	}
837*3b188dabSeric 
838*3b188dabSeric 	if (e == 0) {
839*3b188dabSeric 		io->state = IO_STATE_UP;
840*3b188dabSeric 		io_callback(io, IO_CONNECTED);
841*3b188dabSeric 		goto done;
842*3b188dabSeric 	}
843*3b188dabSeric 
844*3b188dabSeric 	while (io->ai) {
845*3b188dabSeric 		r = io_connect_next(io);
846*3b188dabSeric 		if (r == 0)
847*3b188dabSeric 			goto done;
848*3b188dabSeric 		e = errno;
849*3b188dabSeric 	}
850*3b188dabSeric 
851*3b188dabSeric 	(void)close(fd);
852*3b188dabSeric 	io->sock = -1;
853*3b188dabSeric 	io->error = strerror(e);
854*3b188dabSeric 	io->state = IO_STATE_DOWN;
855*3b188dabSeric 	io_callback(io, e == ETIMEDOUT ? IO_TIMEOUT : IO_ERROR);
856*3b188dabSeric     done:
857*3b188dabSeric 	io_frame_leave(io);
858*3b188dabSeric }
859*3b188dabSeric 
860*3b188dabSeric static int
io_connect_next(struct io * io)861*3b188dabSeric io_connect_next(struct io *io)
862*3b188dabSeric {
863*3b188dabSeric 	struct addrinfo *ai;
864*3b188dabSeric 	struct linger l;
865*3b188dabSeric 	int saved_errno;
866*3b188dabSeric 
867*3b188dabSeric 	while ((ai = io->ai)) {
868*3b188dabSeric 		io->ai = ai->ai_next;
869*3b188dabSeric 		ai->ai_next = NULL;
870*3b188dabSeric 		if (ai->ai_socktype == SOCK_STREAM)
871*3b188dabSeric 			break;
872*3b188dabSeric 		freeaddrinfo(ai);
873*3b188dabSeric 	}
874*3b188dabSeric 
875*3b188dabSeric 	if (ai == NULL) {
876*3b188dabSeric 		errno = ESOCKTNOSUPPORT;
877*3b188dabSeric 		log_warn("%s", __func__);
878*3b188dabSeric 		return -1;
879*3b188dabSeric 	}
880*3b188dabSeric 
881*3b188dabSeric 	if ((io->sock = socket(ai->ai_family, ai->ai_socktype | SOCK_NONBLOCK,
882*3b188dabSeric 	    0)) == -1) {
883*3b188dabSeric 		log_warn("%s: socket", __func__);
884*3b188dabSeric 		goto fail;
885*3b188dabSeric 	}
886*3b188dabSeric 
887*3b188dabSeric 	memset(&l, 0, sizeof(l));
888*3b188dabSeric 	if (setsockopt(io->sock, SOL_SOCKET, SO_LINGER, &l, sizeof(l)) == -1) {
889*3b188dabSeric 		log_warn("%s: setsockopt", __func__);
890*3b188dabSeric 		goto fail;
891*3b188dabSeric 	}
892*3b188dabSeric 
893*3b188dabSeric 	if (io->bind && bind(io->sock, io->bind, io->bind->sa_len) == -1) {
894*3b188dabSeric 		log_warn("%s: bind", __func__);
895*3b188dabSeric 		goto fail;
896*3b188dabSeric 	}
897*3b188dabSeric 
898*3b188dabSeric 	if (connect(io->sock, ai->ai_addr, ai->ai_addr->sa_len) == -1)
899*3b188dabSeric 		if (errno != EINPROGRESS) {
900*3b188dabSeric 			log_warn("%s: connect", __func__);
901*3b188dabSeric 			goto fail;
902*3b188dabSeric 		}
903*3b188dabSeric 
904*3b188dabSeric 	freeaddrinfo(ai);
905*3b188dabSeric 	io->state = IO_STATE_CONNECT;
906*3b188dabSeric 	io_reset(io, EV_WRITE, io_dispatch_connect);
907*3b188dabSeric 	return 0;
908*3b188dabSeric 
909*3b188dabSeric     fail:
910*3b188dabSeric 	if (io->sock != -1) {
911*3b188dabSeric 		saved_errno = errno;
912*3b188dabSeric 		close(io->sock);
913*3b188dabSeric 		errno = saved_errno;
914*3b188dabSeric 		io->error = strerror(errno);
915*3b188dabSeric 		io->sock = -1;
916*3b188dabSeric 	}
917*3b188dabSeric 	freeaddrinfo(ai);
918*3b188dabSeric 	if (io->ai) {
919*3b188dabSeric 		freeaddrinfo(io->ai);
920*3b188dabSeric 		io->ai = NULL;
921*3b188dabSeric 	}
922*3b188dabSeric 	return -1;
923*3b188dabSeric }
924*3b188dabSeric 
925*3b188dabSeric #ifdef IO_SSL
926*3b188dabSeric 
927*3b188dabSeric static const char*
io_ssl_error(void)928*3b188dabSeric io_ssl_error(void)
929*3b188dabSeric {
930*3b188dabSeric 	static char buf[128];
931*3b188dabSeric 	unsigned long e;
932*3b188dabSeric 
933*3b188dabSeric 	e = ERR_peek_last_error();
934*3b188dabSeric 	if (e) {
935*3b188dabSeric 		ERR_error_string(e, buf);
936*3b188dabSeric 		return buf;
937*3b188dabSeric 	}
938*3b188dabSeric 
939*3b188dabSeric 	return "No SSL error";
940*3b188dabSeric }
941*3b188dabSeric 
942*3b188dabSeric static void
io_dispatch_accept_tls(int fd,short event,void * arg)943*3b188dabSeric io_dispatch_accept_tls(int fd, short event, void *arg)
944*3b188dabSeric {
945*3b188dabSeric 	struct io *io = arg;
946*3b188dabSeric 	int e, ret;
947*3b188dabSeric 
948*3b188dabSeric 	io_frame_enter(__func__, io, event);
949*3b188dabSeric 
950*3b188dabSeric 	if (event == EV_TIMEOUT) {
951*3b188dabSeric 		io_callback(io, IO_TIMEOUT);
952*3b188dabSeric 		goto leave;
953*3b188dabSeric 	}
954*3b188dabSeric 
955*3b188dabSeric 	if ((ret = SSL_accept(io->tls)) > 0) {
956*3b188dabSeric 		io->state = IO_STATE_UP;
957*3b188dabSeric 		io_callback(io, IO_TLSREADY);
958*3b188dabSeric 		goto leave;
959*3b188dabSeric 	}
960*3b188dabSeric 
961*3b188dabSeric 	switch ((e = SSL_get_error(io->tls, ret))) {
962*3b188dabSeric 	case SSL_ERROR_WANT_READ:
963*3b188dabSeric 		io_reset(io, EV_READ, io_dispatch_accept_tls);
964*3b188dabSeric 		break;
965*3b188dabSeric 	case SSL_ERROR_WANT_WRITE:
966*3b188dabSeric 		io_reset(io, EV_WRITE, io_dispatch_accept_tls);
967*3b188dabSeric 		break;
968*3b188dabSeric 	default:
969*3b188dabSeric 		io->error = io_ssl_error();
970*3b188dabSeric 		ssl_error("io_dispatch_accept_tls:SSL_accept");
971*3b188dabSeric 		io_callback(io, IO_TLSERROR);
972*3b188dabSeric 		break;
973*3b188dabSeric 	}
974*3b188dabSeric 
975*3b188dabSeric     leave:
976*3b188dabSeric 	io_frame_leave(io);
977*3b188dabSeric }
978*3b188dabSeric 
979*3b188dabSeric static void
io_dispatch_connect_tls(int fd,short event,void * arg)980*3b188dabSeric io_dispatch_connect_tls(int fd, short event, void *arg)
981*3b188dabSeric {
982*3b188dabSeric 	struct io *io = arg;
983*3b188dabSeric 	int e, ret;
984*3b188dabSeric 
985*3b188dabSeric 	io_frame_enter(__func__, io, event);
986*3b188dabSeric 
987*3b188dabSeric 	if (event == EV_TIMEOUT) {
988*3b188dabSeric 		io_callback(io, IO_TIMEOUT);
989*3b188dabSeric 		goto leave;
990*3b188dabSeric 	}
991*3b188dabSeric 
992*3b188dabSeric 	if ((ret = SSL_connect(io->tls)) > 0) {
993*3b188dabSeric 		io->state = IO_STATE_UP;
994*3b188dabSeric 		io_callback(io, IO_TLSREADY);
995*3b188dabSeric 		goto leave;
996*3b188dabSeric 	}
997*3b188dabSeric 
998*3b188dabSeric 	switch ((e = SSL_get_error(io->tls, ret))) {
999*3b188dabSeric 	case SSL_ERROR_WANT_READ:
1000*3b188dabSeric 		io_reset(io, EV_READ, io_dispatch_connect_tls);
1001*3b188dabSeric 		break;
1002*3b188dabSeric 	case SSL_ERROR_WANT_WRITE:
1003*3b188dabSeric 		io_reset(io, EV_WRITE, io_dispatch_connect_tls);
1004*3b188dabSeric 		break;
1005*3b188dabSeric 	default:
1006*3b188dabSeric 		io->error = io_ssl_error();
1007*3b188dabSeric 		ssl_error("io_dispatch_connect_tls:SSL_connect");
1008*3b188dabSeric 		io_callback(io, IO_TLSERROR);
1009*3b188dabSeric 		break;
1010*3b188dabSeric 	}
1011*3b188dabSeric 
1012*3b188dabSeric     leave:
1013*3b188dabSeric 	io_frame_leave(io);
1014*3b188dabSeric }
1015*3b188dabSeric 
1016*3b188dabSeric static void
io_dispatch_read_tls(int fd,short event,void * arg)1017*3b188dabSeric io_dispatch_read_tls(int fd, short event, void *arg)
1018*3b188dabSeric {
1019*3b188dabSeric 	struct io *io = arg;
1020*3b188dabSeric 	int n, saved_errno;
1021*3b188dabSeric 
1022*3b188dabSeric 	io_frame_enter(__func__, io, event);
1023*3b188dabSeric 
1024*3b188dabSeric 	if (event == EV_TIMEOUT) {
1025*3b188dabSeric 		io_callback(io, IO_TIMEOUT);
1026*3b188dabSeric 		goto leave;
1027*3b188dabSeric 	}
1028*3b188dabSeric 
1029*3b188dabSeric again:
1030*3b188dabSeric 	iobuf_normalize(&io->iobuf);
1031*3b188dabSeric 	switch ((n = iobuf_read_ssl(&io->iobuf, (SSL*)io->tls))) {
1032*3b188dabSeric 	case IOBUF_WANT_READ:
1033*3b188dabSeric 		io_reset(io, EV_READ, io_dispatch_read_tls);
1034*3b188dabSeric 		break;
1035*3b188dabSeric 	case IOBUF_WANT_WRITE:
1036*3b188dabSeric 		io_reset(io, EV_WRITE, io_dispatch_read_tls);
1037*3b188dabSeric 		break;
1038*3b188dabSeric 	case IOBUF_CLOSED:
1039*3b188dabSeric 		io_callback(io, IO_DISCONNECTED);
1040*3b188dabSeric 		break;
1041*3b188dabSeric 	case IOBUF_ERROR:
1042*3b188dabSeric 		saved_errno = errno;
1043*3b188dabSeric 		io->error = strerror(errno);
1044*3b188dabSeric 		errno = saved_errno;
1045*3b188dabSeric 		log_warn("%s: iobuf_read_ssl", __func__);
1046*3b188dabSeric 		io_callback(io, IO_ERROR);
1047*3b188dabSeric 		break;
1048*3b188dabSeric 	case IOBUF_SSLERROR:
1049*3b188dabSeric 		io->error = io_ssl_error();
1050*3b188dabSeric 		ssl_error("io_dispatch_read_tls:SSL_read");
1051*3b188dabSeric 		io_callback(io, IO_TLSERROR);
1052*3b188dabSeric 		break;
1053*3b188dabSeric 	default:
1054*3b188dabSeric 		io_debug("%s(...) -> r=%d", __func__, n);
1055*3b188dabSeric 		io_callback(io, IO_DATAIN);
1056*3b188dabSeric 		if (current == io && IO_READING(io) && SSL_pending(io->tls))
1057*3b188dabSeric 			goto again;
1058*3b188dabSeric 	}
1059*3b188dabSeric 
1060*3b188dabSeric     leave:
1061*3b188dabSeric 	io_frame_leave(io);
1062*3b188dabSeric }
1063*3b188dabSeric 
1064*3b188dabSeric static void
io_dispatch_write_tls(int fd,short event,void * arg)1065*3b188dabSeric io_dispatch_write_tls(int fd, short event, void *arg)
1066*3b188dabSeric {
1067*3b188dabSeric 	struct io *io = arg;
1068*3b188dabSeric 	size_t w2, w;
1069*3b188dabSeric 	int n, saved_errno;
1070*3b188dabSeric 
1071*3b188dabSeric 	io_frame_enter(__func__, io, event);
1072*3b188dabSeric 
1073*3b188dabSeric 	if (event == EV_TIMEOUT) {
1074*3b188dabSeric 		io_callback(io, IO_TIMEOUT);
1075*3b188dabSeric 		goto leave;
1076*3b188dabSeric 	}
1077*3b188dabSeric 
1078*3b188dabSeric 	w = io_queued(io);
1079*3b188dabSeric 	switch ((n = iobuf_write_ssl(&io->iobuf, (SSL*)io->tls))) {
1080*3b188dabSeric 	case IOBUF_WANT_READ:
1081*3b188dabSeric 		io_reset(io, EV_READ, io_dispatch_write_tls);
1082*3b188dabSeric 		break;
1083*3b188dabSeric 	case IOBUF_WANT_WRITE:
1084*3b188dabSeric 		io_reset(io, EV_WRITE, io_dispatch_write_tls);
1085*3b188dabSeric 		break;
1086*3b188dabSeric 	case IOBUF_CLOSED:
1087*3b188dabSeric 		io_callback(io, IO_DISCONNECTED);
1088*3b188dabSeric 		break;
1089*3b188dabSeric 	case IOBUF_ERROR:
1090*3b188dabSeric 		saved_errno = errno;
1091*3b188dabSeric 		io->error = strerror(errno);
1092*3b188dabSeric 		errno = saved_errno;
1093*3b188dabSeric 		log_warn("%s: iobuf_write_ssl", __func__);
1094*3b188dabSeric 		io_callback(io, IO_ERROR);
1095*3b188dabSeric 		break;
1096*3b188dabSeric 	case IOBUF_SSLERROR:
1097*3b188dabSeric 		io->error = io_ssl_error();
1098*3b188dabSeric 		ssl_error("io_dispatch_write_tls:SSL_write");
1099*3b188dabSeric 		io_callback(io, IO_TLSERROR);
1100*3b188dabSeric 		break;
1101*3b188dabSeric 	default:
1102*3b188dabSeric 		io_debug("%s(...) -> w=%d", __func__, n);
1103*3b188dabSeric 		w2 = io_queued(io);
1104*3b188dabSeric 		if (w > io->lowat && w2 <= io->lowat)
1105*3b188dabSeric 			io_callback(io, IO_LOWAT);
1106*3b188dabSeric 		break;
1107*3b188dabSeric 	}
1108*3b188dabSeric 
1109*3b188dabSeric     leave:
1110*3b188dabSeric 	io_frame_leave(io);
1111*3b188dabSeric }
1112*3b188dabSeric 
1113*3b188dabSeric static void
io_reload_tls(struct io * io)1114*3b188dabSeric io_reload_tls(struct io *io)
1115*3b188dabSeric {
1116*3b188dabSeric 	short ev = 0;
1117*3b188dabSeric 	void (*dispatch)(int, short, void*) = NULL;
1118*3b188dabSeric 
1119*3b188dabSeric 	switch (io->state) {
1120*3b188dabSeric 	case IO_STATE_CONNECT_TLS:
1121*3b188dabSeric 		ev = EV_WRITE;
1122*3b188dabSeric 		dispatch = io_dispatch_connect_tls;
1123*3b188dabSeric 		break;
1124*3b188dabSeric 	case IO_STATE_ACCEPT_TLS:
1125*3b188dabSeric 		ev = EV_READ;
1126*3b188dabSeric 		dispatch = io_dispatch_accept_tls;
1127*3b188dabSeric 		break;
1128*3b188dabSeric 	case IO_STATE_UP:
1129*3b188dabSeric 		ev = 0;
1130*3b188dabSeric 		if (IO_READING(io) && !(io->flags & IO_PAUSE_IN)) {
1131*3b188dabSeric 			ev = EV_READ;
1132*3b188dabSeric 			dispatch = io_dispatch_read_tls;
1133*3b188dabSeric 		}
1134*3b188dabSeric 		else if (IO_WRITING(io) && !(io->flags & IO_PAUSE_OUT) &&
1135*3b188dabSeric 		    io_queued(io)) {
1136*3b188dabSeric 			ev = EV_WRITE;
1137*3b188dabSeric 			dispatch = io_dispatch_write_tls;
1138*3b188dabSeric 		}
1139*3b188dabSeric 		if (!ev)
1140*3b188dabSeric 			return; /* paused */
1141*3b188dabSeric 		break;
1142*3b188dabSeric 	default:
1143*3b188dabSeric 		fatalx("%s: unexpected state %d", __func__, io->state);
1144*3b188dabSeric 	}
1145*3b188dabSeric 
1146*3b188dabSeric 	io_reset(io, ev, dispatch);
1147*3b188dabSeric }
1148*3b188dabSeric 
1149*3b188dabSeric #endif /* IO_SSL */
1150