Hi, After the recent series of cleanups, it is now possible to make struct io opaque:
- move struct io definition in ioev.c - replace io_init/io_clear with io_new/io_free - allocate an iobuf for each new io internally - use struct io pointer in the rest of the code - remove remaining uses of iobuf_* The diff is mostly mechanical. Eric. Index: bounce.c =================================================================== RCS file: /cvs/src/usr.sbin/smtpd/bounce.c,v retrieving revision 1.76 diff -u -p -r1.76 bounce.c --- bounce.c 22 Nov 2016 07:28:42 -0000 1.76 +++ bounce.c 28 Nov 2016 12:51:26 -0000 @@ -80,8 +80,7 @@ struct bounce_session { struct bounce_message *msg; FILE *msgfp; int state; - struct iobuf iobuf; - struct io io; + struct io *io; uint64_t boundary; }; @@ -229,12 +228,11 @@ bounce_fd(int fd) s = xcalloc(1, sizeof(*s), "bounce_fd"); s->smtpname = xstrdup(msg->smtpname, "bounce_fd"); s->state = BOUNCE_EHLO; - iobuf_xinit(&s->iobuf, 0, 0, "bounce_run"); - io_init(&s->io, &s->iobuf); - io_set_callback(&s->io, bounce_io, s); - io_set_fd(&s->io, fd); - io_set_timeout(&s->io, 30000); - io_set_read(&s->io); + s->io = io_new(); + io_set_callback(s->io, bounce_io, s); + io_set_fd(s->io, fd); + io_set_timeout(s->io, 30000); + io_set_read(s->io); s->boundary = generate_uid(); log_debug("debug: bounce: new session %p", s); @@ -313,7 +311,7 @@ bounce_send(struct bounce_session *s, co log_trace(TRACE_BOUNCE, "bounce: %p: >>> %s", s, p); - io_xprintf(&s->io, "%s\n", p); + io_xprintf(s->io, "%s\n", p); free(p); } @@ -452,7 +450,7 @@ bounce_next(struct bounce_session *s) case BOUNCE_DATA_NOTICE: /* Construct an appropriate notice. */ - io_xprintf(&s->io, + io_xprintf(s->io, "Subject: Delivery status notification: %s\n" "From: Mailer Daemon <MAILER-DAEMON@%s>\n" "To: %s\n" @@ -470,7 +468,7 @@ bounce_next(struct bounce_session *s) s->boundary, s->smtpname); - io_xprintf(&s->io, + io_xprintf(s->io, "--%16" PRIu64 "/%s\n" "Content-Description: Notification\n" "Content-Type: text/plain; charset=us-ascii\n" @@ -481,14 +479,14 @@ bounce_next(struct bounce_session *s) switch (s->msg->bounce.type) { case B_ERROR: - io_xprint(&s->io, notice_error); + io_xprint(s->io, notice_error); break; case B_WARNING: - io_xprintf(&s->io, notice_warning, + io_xprintf(s->io, notice_warning, bounce_duration(s->msg->bounce.delay)); break; case B_DSN: - io_xprint(&s->io, s->msg->bounce.mta_without_dsn ? + io_xprint(s->io, s->msg->bounce.mta_without_dsn ? notice_relay : notice_success); break; default: @@ -496,32 +494,32 @@ bounce_next(struct bounce_session *s) } TAILQ_FOREACH(evp, &s->msg->envelopes, entry) { - io_xprint(&s->io, evp->report); + io_xprint(s->io, evp->report); } - io_xprint(&s->io, "\n"); + io_xprint(s->io, "\n"); if (s->msg->bounce.type == B_WARNING) - io_xprintf(&s->io, notice_warning2, + io_xprintf(s->io, notice_warning2, bounce_duration(s->msg->bounce.expire)); - io_xprintf(&s->io, + io_xprintf(s->io, " Below is a copy of the original message:\n" "\n"); - io_xprintf(&s->io, + io_xprintf(s->io, "--%16" PRIu64 "/%s\n" "Content-Description: Delivery Report\n" "Content-Type: message/delivery-status\n" "\n", s->boundary, s->smtpname); - io_xprintf(&s->io, + io_xprintf(s->io, "Reporting-MTA: dns; %s\n" "\n", s->smtpname); TAILQ_FOREACH(evp, &s->msg->envelopes, entry) { - io_xprintf(&s->io, + io_xprintf(s->io, "Final-Recipient: rfc822; %s@%s\n" "Action: %s\n" "Status: %s\n" @@ -533,21 +531,21 @@ bounce_next(struct bounce_session *s) } log_trace(TRACE_BOUNCE, "bounce: %p: >>> [... %zu bytes ...]", - s, io_queued(&s->io)); + s, io_queued(s->io)); s->state = BOUNCE_DATA_MESSAGE; break; case BOUNCE_DATA_MESSAGE: - io_xprintf(&s->io, + io_xprintf(s->io, "--%16" PRIu64 "/%s\n" "Content-Description: Message headers\n" "Content-Type: text/rfc822-headers\n" "\n", s->boundary, s->smtpname); - n = io_queued(&s->io); - while (io_queued(&s->io) < BOUNCE_HIWAT) { + n = io_queued(s->io); + while (io_queued(s->io) < BOUNCE_HIWAT) { if ((len = getline(&line, &sz, s->msgfp)) == -1) break; if (len == 1 && line[0] == '\n' && /* end of headers */ @@ -556,7 +554,7 @@ bounce_next(struct bounce_session *s) free(line); fclose(s->msgfp); s->msgfp = NULL; - io_xprintf(&s->io, + io_xprintf(s->io, "\n--%16" PRIu64 "/%s--\n", s->boundary, s->smtpname); bounce_send(s, "."); @@ -564,7 +562,7 @@ bounce_next(struct bounce_session *s) return (0); } line[len - 1] = '\0'; - io_xprintf(&s->io, "%s%s\n", + io_xprintf(s->io, "%s%s\n", (len == 2 && line[0] == '.') ? "." : "", line); } free(line); @@ -578,11 +576,11 @@ bounce_next(struct bounce_session *s) return (-1); } - io_xprintf(&s->io, + io_xprintf(s->io, "\n--%16" PRIu64 "/%s--\n", s->boundary, s->smtpname); log_trace(TRACE_BOUNCE, "bounce: %p: >>> [... %zu bytes ...]", - s, io_queued(&s->io) - n); + s, io_queued(s->io) - n); if (feof(s->msgfp)) { fclose(s->msgfp); @@ -695,8 +693,7 @@ bounce_free(struct bounce_session *s) { log_debug("debug: bounce: %p: deleting session", s); - iobuf_clear(&s->iobuf); - io_clear(&s->io); + io_free(s->io); free(s->smtpname); free(s); @@ -721,8 +718,8 @@ bounce_io(struct io *io, int evt, void * switch (evt) { case IO_DATAIN: nextline: - line = io_getline(&s->io, &len); - if (line == NULL && io_datalen(&s->io) >= LINE_MAX) { + line = io_getline(s->io, &len); + if (line == NULL && io_datalen(s->io) >= LINE_MAX) { bounce_status(s, "Input too long"); bounce_free(s); return; @@ -767,7 +764,7 @@ bounce_io(struct io *io, int evt, void * bounce_free(s); return; } - if (io_queued(&s->io) == 0) + if (io_queued(s->io) == 0) io_set_read(io); break; Index: filter.c =================================================================== RCS file: /cvs/src/usr.sbin/smtpd/filter.c,v retrieving revision 1.23 diff -u -p -r1.23 filter.c --- filter.c 22 Nov 2016 07:28:42 -0000 1.23 +++ filter.c 28 Nov 2016 12:51:27 -0000 @@ -70,8 +70,7 @@ struct filter_session { struct filter *fcurr; int error; - struct io iev; - struct iobuf ibuf; + struct io *iev; size_t idatalen; FILE *ofile; @@ -295,8 +294,8 @@ filter_event(uint64_t id, int event) filter_post_event(id, event, TAILQ_FIRST(s->filters), NULL); if (event == EVENT_DISCONNECT) { - io_clear(&s->iev); - iobuf_clear(&s->ibuf); + if (s->iev) + io_free(s->iev); if (s->ofile) fclose(s->ofile); free(s); @@ -315,7 +314,6 @@ filter_connect(uint64_t id, const struct if (filter == NULL) filter = "<no-filter>"; s->filters = dict_xget(&chains, filter); - io_init(&s->iev, NULL); tree_xset(&sessions, s->id, s); filter_event(id, EVENT_CONNECT); @@ -670,11 +668,10 @@ filter_tx(struct filter_session *s, int io_set_nonblocking(sp[0]); io_set_nonblocking(sp[1]); - iobuf_init(&s->ibuf, 0, 0); - io_init(&s->iev, &s->ibuf); - io_set_callback(&s->iev, filter_tx_io, s); - io_set_fd(&s->iev, sp[0]); - io_set_read(&s->iev); + s->iev = io_new(); + io_set_callback(s->iev, filter_tx_io, s); + io_set_fd(s->iev, sp[0]); + io_set_read(s->iev); return (sp[1]); } @@ -691,8 +688,8 @@ filter_tx_io(struct io *io, int evt, voi switch (evt) { case IO_DATAIN: - data = io_data(&s->iev); - len = io_datalen(&s->iev); + data = io_data(s->iev); + len = io_datalen(s->iev); log_trace(TRACE_FILTERS, "filter: filter_tx_io: datain (%zu) for req %016"PRIx64"", @@ -705,7 +702,7 @@ filter_tx_io(struct io *io, int evt, voi break; } s->idatalen += n; - io_drop(&s->iev, n); + io_drop(s->iev, n); return; case IO_DISCONNECTED: @@ -721,8 +718,8 @@ filter_tx_io(struct io *io, int evt, voi break; } - io_clear(&s->iev); - iobuf_clear(&s->ibuf); + io_free(s->iev); + s->iev = NULL; fclose(s->ofile); s->ofile = NULL; Index: ioev.c =================================================================== RCS file: /cvs/src/usr.sbin/smtpd/ioev.c,v retrieving revision 1.37 diff -u -p -r1.37 ioev.c --- ioev.c 25 Nov 2016 16:17:41 -0000 1.37 +++ ioev.c 28 Nov 2016 12:51:27 -0000 @@ -21,6 +21,7 @@ #include <err.h> #include <errno.h> +#include <event.h> #include <fcntl.h> #include <inttypes.h> #include <stdlib.h> @@ -46,6 +47,20 @@ enum { IO_STATE_MAX, }; +struct io { + int sock; + void *arg; + void (*cb)(struct io*, int, void *); + struct iobuf *iobuf; + size_t lowat; + int timeout; + int flags; + int state; + struct event ev; + void *ssl; + const char *error; /* only valid immediately on callback */ +}; + const char* io_strflags(int); const char* io_evstr(short); @@ -223,20 +238,36 @@ _io_init() _io_debug = getenv("IO_DEBUG") != NULL; } -void -io_init(struct io *io, struct iobuf *iobuf) +struct io * +io_new(void) { + struct io *io; + _io_init(); - memset(io, 0, sizeof *io); + if ((io = calloc(1, sizeof(*io))) == NULL) + return NULL; io->sock = -1; io->timeout = -1; - io->iobuf = iobuf; + io->iobuf = calloc(1, sizeof(*io->iobuf)); + + if (io->iobuf == NULL) { + free(io); + return NULL; + } + + if (iobuf_init(io->iobuf, 0, 0) == -1) { + free(io->iobuf); + free(io); + return NULL; + } + + return io; } void -io_clear(struct io *io) +io_free(struct io *io) { io_debug("io_clear(%p)\n", io); @@ -257,6 +288,10 @@ io_clear(struct io *io) close(io->sock); io->sock = -1; } + + iobuf_clear(io->iobuf); + free(io->iobuf); + free(io); } void Index: ioev.h =================================================================== RCS file: /cvs/src/usr.sbin/smtpd/ioev.h,v retrieving revision 1.14 diff -u -p -r1.14 ioev.h --- ioev.h 24 Nov 2016 21:25:21 -0000 1.14 +++ ioev.h 28 Nov 2016 12:51:27 -0000 @@ -15,8 +15,6 @@ * OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE. */ -#include <event.h> - enum { IO_CONNECTED = 0, /* connection successful */ IO_TLSREADY, /* TLS started successfully */ @@ -36,26 +34,13 @@ enum { #define IO_RESET 0x10 /* internal */ #define IO_HELD 0x20 /* internal */ -struct iobuf; -struct io { - int sock; - void *arg; - void (*cb)(struct io*, int, void *); - struct iobuf *iobuf; - size_t lowat; - int timeout; - int flags; - int state; - struct event ev; - void *ssl; - const char *error; /* only valid immediately on callback */ -}; +struct io; void io_set_nonblocking(int); void io_set_nolinger(int); -void io_init(struct io*, struct iobuf*); -void io_clear(struct io*); +struct io *io_new(void); +void io_free(struct io *); void io_set_read(struct io *); void io_set_write(struct io *); void io_set_fd(struct io *, int); Index: mda.c =================================================================== RCS file: /cvs/src/usr.sbin/smtpd/mda.c,v retrieving revision 1.124 diff -u -p -r1.124 mda.c --- mda.c 24 Nov 2016 12:58:27 -0000 1.124 +++ mda.c 28 Nov 2016 12:51:27 -0000 @@ -79,8 +79,7 @@ struct mda_session { uint64_t id; struct mda_user *user; struct mda_envelope *evp; - struct io io; - struct iobuf iobuf; + struct io *io; FILE *datafp; }; @@ -253,10 +252,10 @@ mda_imsg(struct mproc *p, struct imsg *i if (e->method == A_MDA || e->method == A_FILENAME) { time(&now); if (e->sender[0]) - n = io_printf(&s->io, "From %s %s", + n = io_printf(s->io, "From %s %s", e->sender, ctime(&now)); else - n = io_printf(&s->io, + n = io_printf(s->io, "From MAILER-DAEMON@%s %s", env->sc_hostname, ctime(&now)); } @@ -267,13 +266,13 @@ mda_imsg(struct mproc *p, struct imsg *i * XXX: remove existing Return-Path, * if any */ - n = io_printf(&s->io, + n = io_printf(s->io, "Return-Path: %s\n" "Delivered-To: %s\n", e->sender, e->rcpt ? e->rcpt : e->dest); else - n = io_printf(&s->io, + n = io_printf(s->io, "Delivered-To: %s\n", e->rcpt ? e->rcpt : e->dest); } @@ -431,8 +430,8 @@ mda_imsg(struct mproc *p, struct imsg *i imsg->fd, s->id, s->evp->id); io_set_nonblocking(imsg->fd); - io_set_fd(&s->io, imsg->fd); - io_set_write(&s->io); + io_set_fd(s->io, imsg->fd); + io_set_write(s->io); return; case IMSG_MDA_DONE: @@ -456,7 +455,7 @@ mda_imsg(struct mproc *p, struct imsg *i */ error = NULL; if (strcmp(parent_error, "exited okay") == 0) { - if (s->datafp || io_queued(&s->io)) + if (s->datafp || (s->io && io_queued(s->io))) error = "mda exited prematurely"; } else error = out[0] ? out : parent_error; @@ -514,14 +513,15 @@ mda_io(struct io *io, int evt, void *arg log_debug("debug: mda: all data sent for session" " %016"PRIx64 " evpid %016"PRIx64, s->id, s->evp->id); - io_clear(io); + io_free(io); + s->io = NULL; return; } - while (io_queued(&s->io) < MDA_HIWAT) { + while (io_queued(s->io) < MDA_HIWAT) { if ((len = getline(&ln, &sz, s->datafp)) == -1) break; - if (io_write(&s->io, ln, len) == -1) { + if (io_write(s->io, ln, len) == -1) { m_create(p_parent, IMSG_MDA_KILL, 0, 0, -1); m_add_id(p_parent, s->id); @@ -552,7 +552,7 @@ mda_io(struct io *io, int evt, void *arg s->id, s->evp->id); fclose(s->datafp); s->datafp = NULL; - if (io_queued(&s->io) == 0) + if (io_queued(s->io) == 0) goto done; } return; @@ -747,8 +747,8 @@ mda_done(struct mda_session *s) if (s->datafp) fclose(s->datafp); - io_clear(&s->io); - iobuf_clear(&s->iobuf); + if (s->io) + io_free(s->io); free(s); @@ -954,10 +954,8 @@ mda_session(struct mda_user * u) s = xcalloc(1, sizeof *s, "mda_session"); s->id = generate_uid(); s->user = u; - if (iobuf_init(&s->iobuf, 0, 0) == -1) - fatal("mda_session"); - io_init(&s->io, &s->iobuf); - io_set_callback(&s->io, mda_io, s); + s->io = io_new(); + io_set_callback(s->io, mda_io, s); tree_xset(&sessions, s->id, s); Index: mta_session.c =================================================================== RCS file: /cvs/src/usr.sbin/smtpd/mta_session.c,v retrieving revision 1.94 diff -u -p -r1.94 mta_session.c --- mta_session.c 25 Nov 2016 11:43:55 -0000 1.94 +++ mta_session.c 28 Nov 2016 12:51:28 -0000 @@ -115,8 +115,7 @@ struct mta_session { int ready; struct event ev; - struct iobuf iobuf; - struct io io; + struct io *io; int ext; size_t msgtried; @@ -196,7 +195,6 @@ mta_session(struct mta_relay *relay, str s->id = generate_uid(); s->relay = relay; s->route = route; - io_init(&s->io, NULL); if (relay->flags & RELAY_SSL && relay->flags & RELAY_AUTH) s->flags |= MTA_USE_AUTH; @@ -329,7 +327,7 @@ mta_session_imsg(struct mproc *p, struct ssl = ssl_mta_init(NULL, NULL, 0, env->sc_tls_ciphers); if (ssl == NULL) fatal("mta: ssl_mta_init"); - io_start_tls(&s->io, ssl); + io_start_tls(s->io, ssl); return; } } @@ -341,7 +339,7 @@ mta_session_imsg(struct mproc *p, struct resp_ca_cert->cert, resp_ca_cert->cert_len, env->sc_tls_ciphers); if (ssl == NULL) fatal("mta: ssl_mta_init"); - io_start_tls(&s->io, ssl); + io_start_tls(s->io, ssl); explicit_bzero(resp_ca_cert->cert, resp_ca_cert->cert_len); free(resp_ca_cert->cert); @@ -364,7 +362,7 @@ mta_session_imsg(struct mproc *p, struct } mta_tls_verified(s); - io_resume(&s->io, IO_PAUSE_IN); + io_resume(s->io, IO_PAUSE_IN); return; case IMSG_MTA_LOOKUP_HELO: @@ -427,8 +425,8 @@ mta_free(struct mta_session *s) runq_cancel(hangon, NULL, s); } - io_clear(&s->io); - iobuf_clear(&s->iobuf); + if (s->io) + io_free(s->io); if (s->task) fatalx("current task should have been deleted already"); @@ -497,8 +495,10 @@ mta_connect(struct mta_session *s) s->helo = xstrdup(env->sc_hostname, "mta_connect"); } - io_clear(&s->io); - iobuf_clear(&s->iobuf); + if (s->io) { + io_free(s->io); + s->io = NULL; + } s->use_smtps = s->use_starttls = s->use_smtp_tls = 0; @@ -556,20 +556,19 @@ mta_connect(struct mta_session *s) portno, s->route->dst->ptrname); mta_enter_state(s, MTA_INIT); - iobuf_xinit(&s->iobuf, 0, 0, "mta_connect"); - io_init(&s->io, &s->iobuf); - io_set_callback(&s->io, mta_io, s); - io_set_timeout(&s->io, 300000); - if (io_connect(&s->io, sa, s->route->src->sa) == -1) { + s->io = io_new(); + io_set_callback(s->io, mta_io, s); + io_set_timeout(s->io, 300000); + if (io_connect(s->io, sa, s->route->src->sa) == -1) { /* * This error is most likely a "no route", * so there is no need to try again. */ - log_debug("debug: mta: io_connect failed: %s", io_error(&s->io)); + log_debug("debug: mta: io_connect failed: %s", io_error(s->io)); if (errno == EADDRNOTAVAIL) - mta_source_error(s->relay, s->route, io_error(&s->io)); + mta_source_error(s->relay, s->route, io_error(s->io)); else - mta_error(s, "Connection failed: %s", io_error(&s->io)); + mta_error(s, "Connection failed: %s", io_error(s->io)); mta_free(s); } } @@ -842,7 +841,7 @@ mta_enter_state(struct mta_session *s, i case MTA_LMTP_EOM: /* LMTP reports status of each delivery, so enable read */ - io_set_read(&s->io); + io_set_read(s->io); break; case MTA_RSET: @@ -1033,7 +1032,7 @@ mta_response(struct mta_session *s, char */ sa_len = sizeof(ss); sa = (struct sockaddr *)&ss; - if (getsockname(io_fileno(&s->io), sa, &sa_len) < 0) + if (getsockname(io_fileno(s->io), sa, &sa_len) < 0) mta_delivery_log(e, NULL, buf, delivery, line); else mta_delivery_log(e, sa_to_text(sa), @@ -1161,11 +1160,11 @@ mta_io(struct io *io, int evt, void *arg case IO_TLSREADY: log_info("%016"PRIx64" mta event=starttls ciphers=%s", - s->id, ssl_to_text(io_ssl(&s->io))); + s->id, ssl_to_text(io_ssl(s->io))); s->flags |= MTA_TLS; if (mta_verify_certificate(s)) { - io_pause(&s->io, IO_PAUSE_IN); + io_pause(s->io, IO_PAUSE_IN); break; } @@ -1174,9 +1173,9 @@ mta_io(struct io *io, int evt, void *arg case IO_DATAIN: nextline: - line = io_getline(&s->io, &len); + line = io_getline(s->io, &len); if (line == NULL) { - if (io_datalen(&s->io) >= LINE_MAX) { + if (io_datalen(s->io) >= LINE_MAX) { mta_error(s, "Input too long"); mta_free(s); } @@ -1259,7 +1258,7 @@ mta_io(struct io *io, int evt, void *arg return; } - if (io_datalen(&s->io)) { + if (io_datalen(s->io)) { log_debug("debug: mta: remaining data in input buffer"); mta_error(s, "Remote host sent too much data"); if (s->flags & MTA_WAIT) @@ -1278,7 +1277,7 @@ mta_io(struct io *io, int evt, void *arg } } - if (io_queued(&s->io) == 0) + if (io_queued(s->io) == 0) io_set_read(io); break; @@ -1359,7 +1358,7 @@ mta_send(struct mta_session *s, char *fm log_trace(TRACE_MTA, "mta: %p: >>> %s", s, p); - io_xprintf(&s->io, "%s\r\n", p); + io_xprintf(s->io, "%s\r\n", p); free(p); } @@ -1374,14 +1373,14 @@ mta_queue_data(struct mta_session *s) size_t sz = 0, q; ssize_t len; - q = io_queued(&s->io); + q = io_queued(s->io); - while (io_queued(&s->io) < MTA_HIWAT) { + while (io_queued(s->io) < MTA_HIWAT) { if ((len = getline(&ln, &sz, s->datafp)) == -1) break; if (ln[len - 1] == '\n') ln[len - 1] = '\0'; - io_xprintf(&s->io, "%s%s\r\n", *ln == '.' ? "." : "", ln); + io_xprintf(s->io, "%s%s\r\n", *ln == '.' ? "." : "", ln); } free(ln); @@ -1396,7 +1395,7 @@ mta_queue_data(struct mta_session *s) s->datafp = NULL; } - return (io_queued(&s->io) - q); + return (io_queued(s->io) - q); } static void @@ -1433,7 +1432,7 @@ mta_flush_task(struct mta_session *s, in */ sa = (struct sockaddr *)&ss; sa_len = sizeof(ss); - if (getsockname(io_fileno(&s->io), sa, &sa_len) < 0) + if (getsockname(io_fileno(s->io), sa, &sa_len) < 0) mta_delivery_log(e, NULL, relay, delivery, error); else mta_delivery_log(e, sa_to_text(sa), @@ -1560,10 +1559,10 @@ mta_verify_certificate(struct mta_sessio >= sizeof req_ca_vrfy.name) return 0; - x = SSL_get_peer_certificate(io_ssl(&s->io)); + x = SSL_get_peer_certificate(io_ssl(s->io)); if (x == NULL) return 0; - xchain = SSL_get_peer_cert_chain(io_ssl(&s->io)); + xchain = SSL_get_peer_cert_chain(io_ssl(s->io)); /* * Client provided a certificate and possibly a certificate chain. @@ -1657,7 +1656,7 @@ mta_tls_verified(struct mta_session *s) { X509 *x; - x = SSL_get_peer_certificate(io_ssl(&s->io)); + x = SSL_get_peer_certificate(io_ssl(s->io)); if (x) { log_info("smtp-out: Server certificate verification %s " "on session %016"PRIx64, @@ -1668,7 +1667,7 @@ mta_tls_verified(struct mta_session *s) if (s->use_smtps) { mta_enter_state(s, MTA_BANNER); - io_set_read(&s->io); + io_set_read(s->io); } else mta_enter_state(s, MTA_EHLO); Index: smtp_session.c =================================================================== RCS file: /cvs/src/usr.sbin/smtpd/smtp_session.c,v retrieving revision 1.300 diff -u -p -r1.300 smtp_session.c --- smtp_session.c 24 Nov 2016 21:25:21 -0000 1.300 +++ smtp_session.c 28 Nov 2016 12:51:29 -0000 @@ -116,8 +116,7 @@ struct smtp_tx { size_t datain; size_t odatalen; - struct iobuf obuf; - struct io oev; + struct io *oev; int hdrdone; int rcvcount; int dataeom; @@ -131,8 +130,7 @@ struct smtp_tx { struct smtp_session { uint64_t id; - struct iobuf iobuf; - struct io io; + struct io *io; struct listener *listener; void *ssl_ctx; struct sockaddr_storage ss; @@ -642,19 +640,14 @@ smtp_session(struct listener *listener, if ((s = calloc(1, sizeof(*s))) == NULL) return (-1); - if (iobuf_init(&s->iobuf, LINE_MAX, LINE_MAX) == -1) { - free(s); - return (-1); - } - s->id = generate_uid(); s->listener = listener; memmove(&s->ss, ss, sizeof(*ss)); - io_init(&s->io, &s->iobuf); - io_set_callback(&s->io, smtp_io, s); - io_set_fd(&s->io, sock); - io_set_timeout(&s->io, SMTPD_SESSION_TIMEOUT * 1000); - io_set_write(&s->io); + s->io = io_new(); + io_set_callback(s->io, smtp_io, s); + io_set_fd(s->io, sock); + io_set_timeout(s->io, SMTPD_SESSION_TIMEOUT * 1000); + io_set_write(s->io); s->state = STATE_NEW; @@ -966,8 +959,8 @@ smtp_session_imsg(struct mproc *p, struc sizeof *resp_ca_cert, "smtp:ca_cert"); ssl_ctx = dict_get(env->sc_ssl_dict, resp_ca_cert->name); ssl = ssl_smtp_init(ssl_ctx, s->listener->flags & F_TLS_VERIFY); - io_set_read(&s->io); - io_start_tls(&s->io, ssl); + io_set_read(s->io); + io_start_tls(s->io, ssl); explicit_bzero(resp_ca_cert->cert, resp_ca_cert->cert_len); free(resp_ca_cert->cert); @@ -988,7 +981,7 @@ smtp_session_imsg(struct mproc *p, struc return; } smtp_tls_verified(s); - io_resume(&s->io, IO_PAUSE_IN); + io_resume(s->io, IO_PAUSE_IN); return; } @@ -1002,7 +995,7 @@ smtp_tls_verified(struct smtp_session *s { X509 *x; - x = SSL_get_peer_certificate(io_ssl(&s->io)); + x = SSL_get_peer_certificate(io_ssl(s->io)); if (x) { log_info("%016"PRIx64" smtp " "event=client-cert-check address=%s host=%s result=\"%s\"", @@ -1013,7 +1006,7 @@ smtp_tls_verified(struct smtp_session *s if (s->listener->flags & F_SMTPS) { stat_increment("smtp.smtps", 1); - io_set_write(&s->io); + io_set_write(s->io); smtp_send_banner(s); } else { @@ -1185,20 +1178,19 @@ smtp_filter_fd(uint64_t id, int fd) return; } - iobuf_init(&s->tx->obuf, 0, 0); io_set_nonblocking(fd); - io_init(&s->tx->oev, &s->tx->obuf); - io_set_callback(&s->tx->oev, smtp_data_io, s); - io_set_fd(&s->tx->oev, fd); + s->tx->oev = io_new(); + io_set_callback(s->tx->oev, smtp_data_io, s); + io_set_fd(s->tx->oev, fd); - io_print(&s->tx->oev, "Received: "); + io_print(s->tx->oev, "Received: "); if (!(s->listener->flags & F_MASK_SOURCE)) { - io_printf(&s->tx->oev, "from %s (%s [%s])", + io_printf(s->tx->oev, "from %s (%s [%s])", s->helo, s->hostname, ss_to_text(&s->ss)); } - io_printf(&s->tx->oev, "\n\tby %s (%s) with %sSMTP%s%s id %08x", + io_printf(s->tx->oev, "\n\tby %s (%s) with %sSMTP%s%s id %08x", s->smtpname, SMTPD_NAME, s->flags & SF_EHLO ? "E" : "", @@ -1207,33 +1199,33 @@ smtp_filter_fd(uint64_t id, int fd) s->tx->msgid); if (s->flags & SF_SECURE) { - x = SSL_get_peer_certificate(io_ssl(&s->io)); - io_printf(&s->tx->oev, " (%s:%s:%d:%s)", - SSL_get_version(io_ssl(&s->io)), - SSL_get_cipher_name(io_ssl(&s->io)), - SSL_get_cipher_bits(io_ssl(&s->io), NULL), + x = SSL_get_peer_certificate(io_ssl(s->io)); + io_printf(s->tx->oev, " (%s:%s:%d:%s)", + SSL_get_version(io_ssl(s->io)), + SSL_get_cipher_name(io_ssl(s->io)), + SSL_get_cipher_bits(io_ssl(s->io), NULL), (s->flags & SF_VERIFIED) ? "YES" : (x ? "FAIL" : "NO")); if (x) X509_free(x); if (s->listener->flags & F_RECEIVEDAUTH) { - io_printf(&s->tx->oev, " auth=%s", s->username[0] ? "yes" : "no"); + io_printf(s->tx->oev, " auth=%s", s->username[0] ? "yes" : "no"); if (s->username[0]) - io_printf(&s->tx->oev, " user=%s", s->username); + io_printf(s->tx->oev, " user=%s", s->username); } } if (s->tx->rcptcount == 1) { - io_printf(&s->tx->oev, "\n\tfor <%s@%s>", + io_printf(s->tx->oev, "\n\tfor <%s@%s>", s->tx->evp.rcpt.user, s->tx->evp.rcpt.domain); } - io_printf(&s->tx->oev, ";\n\t%s\n", time_to_text(time(NULL))); + io_printf(s->tx->oev, ";\n\t%s\n", time_to_text(time(NULL))); - s->tx->odatalen = io_queued(&s->tx->oev); + s->tx->odatalen = io_queued(s->tx->oev); - io_set_write(&s->tx->oev); + io_set_write(s->tx->oev); smtp_enter_state(s, STATE_BODY); smtp_reply(s, "354 Enter mail, end with \".\"" @@ -1257,13 +1249,13 @@ smtp_io(struct io *io, int evt, void *ar case IO_TLSREADY: log_info("%016"PRIx64" smtp event=starttls address=%s host=%s ciphers=\"%s\"", - s->id, ss_to_text(&s->ss), s->hostname, ssl_to_text(io_ssl(&s->io))); + s->id, ss_to_text(&s->ss), s->hostname, ssl_to_text(io_ssl(s->io))); s->flags |= SF_SECURE; s->helo[0] = '\0'; if (smtp_verify_certificate(s)) { - io_pause(&s->io, IO_PAUSE_IN); + io_pause(s->io, IO_PAUSE_IN); break; } @@ -1280,8 +1272,8 @@ smtp_io(struct io *io, int evt, void *ar case IO_DATAIN: nextline: - line = io_getline(&s->io, &len); - if ((line == NULL && io_datalen(&s->io) >= LINE_MAX) || + line = io_getline(s->io, &len); + if ((line == NULL && io_datalen(s->io) >= LINE_MAX) || (line && len >= LINE_MAX)) { s->flags |= SF_BADINPUT; smtp_reply(s, "500 %s: Line too long", @@ -1302,7 +1294,7 @@ smtp_io(struct io *io, int evt, void *ar } /* Pipelining not supported */ - if (io_datalen(&s->io)) { + if (io_datalen(s->io)) { s->flags |= SF_BADINPUT; smtp_reply(s, "500 %s %s: Pipelining not supported", esc_code(ESC_STATUS_PERMFAIL, ESC_INVALID_COMMAND), @@ -1321,7 +1313,7 @@ smtp_io(struct io *io, int evt, void *ar io_set_write(io); s->tx->dataeom = 1; - if (io_queued(&s->tx->oev) == 0) + if (io_queued(s->tx->oev) == 0) smtp_data_io_done(s); return; } @@ -1400,7 +1392,6 @@ smtp_tx(struct smtp_session *s) return 0; TAILQ_INIT(&tx->rcpts); - io_init(&tx->oev, NULL); s->tx = tx; tx->session = s; @@ -1454,6 +1445,9 @@ smtp_tx_free(struct smtp_tx *tx) free(rcpt); } + if (tx->oev) + io_free(tx->oev); + tx->session->tx = NULL; free(tx); @@ -1472,21 +1466,21 @@ smtp_data_io(struct io *io, int evt, voi case IO_DISCONNECTED: case IO_ERROR: log_debug("debug: smtp: %p: io error on mfa", s); - io_clear(&s->tx->oev); - iobuf_clear(&s->tx->obuf); + io_free(s->tx->oev); + s->tx->oev = NULL; s->tx->msgflags |= MF_ERROR_IO; - if (io_paused(&s->io, IO_PAUSE_IN)) { + if (io_paused(s->io, IO_PAUSE_IN)) { log_debug("debug: smtp: %p: resuming session after mfa error", s); - io_resume(&s->io, IO_PAUSE_IN); + io_resume(s->io, IO_PAUSE_IN); } break; case IO_LOWAT: - if (s->tx->dataeom && io_queued(&s->tx->oev) == 0) { + if (s->tx->dataeom && io_queued(s->tx->oev) == 0) { smtp_data_io_done(s); - } else if (io_paused(&s->io, IO_PAUSE_IN)) { + } else if (io_paused(s->io, IO_PAUSE_IN)) { log_debug("debug: smtp: %p: filter congestion over: resuming session", s); - io_resume(&s->io, IO_PAUSE_IN); + io_resume(s->io, IO_PAUSE_IN); } break; @@ -1499,8 +1493,11 @@ static void smtp_data_io_done(struct smtp_session *s) { log_debug("debug: smtp: %p: data io done (%zu bytes)", s, s->tx->odatalen); - io_clear(&s->tx->oev); - iobuf_clear(&s->tx->obuf); + + if (s->tx->oev) { + io_free(s->tx->oev); + s->tx->oev = NULL; + } if (s->tx->msgflags & MF_ERROR) { @@ -2075,7 +2072,7 @@ smtp_lookup_servername(struct smtp_sessi if (s->listener->hostnametable[0]) { sa_len = sizeof(ss); sa = (struct sockaddr *)&ss; - if (getsockname(io_fileno(&s->io), sa, &sa_len) == -1) { + if (getsockname(io_fileno(s->io), sa, &sa_len) == -1) { log_warn("warn: getsockname()"); } else { @@ -2103,7 +2100,7 @@ smtp_connected(struct smtp_session *s) s->id, ss_to_text(&s->ss), s->hostname); sl = sizeof(ss); - if (getsockname(io_fileno(&s->io), (struct sockaddr*)&ss, &sl) == -1) { + if (getsockname(io_fileno(s->io), (struct sockaddr*)&ss, &sl) == -1) { smtp_free(s, strerror(errno)); return; } @@ -2162,7 +2159,7 @@ smtp_message_printf(struct smtp_session return -1; va_start(ap, fmt); - len = io_vprintf(&s->tx->oev, fmt, ap); + len = io_vprintf(s->tx->oev, fmt, ap); va_end(ap); if (len < 0) { @@ -2192,7 +2189,7 @@ smtp_reply(struct smtp_session *s, char log_trace(TRACE_SMTP, "smtp: %p: >>> %s", s, buf); - io_xprintf(&s->io, "%s\r\n", buf); + io_xprintf(s->io, "%s\r\n", buf); switch (buf[0]) { case '5': @@ -2239,11 +2236,8 @@ smtp_free(struct smtp_session *s, const tree_pop(&wait_filter_data, s->id); if (s->tx) { - if (s->tx->msgid) { + if (s->tx->msgid) smtp_queue_rollback(s); - io_clear(&s->tx->oev); - iobuf_clear(&s->tx->obuf); - } smtp_filter_tx_rollback(s); smtp_tx_free(s->tx); } @@ -2256,8 +2250,7 @@ smtp_free(struct smtp_session *s, const if (s->flags & SF_SECURE && s->listener->flags & F_STARTTLS) stat_decrement("smtp.tls", 1); - io_clear(&s->io); - iobuf_clear(&s->iobuf); + io_free(s->io); free(s); smtp_collect(); @@ -2346,10 +2339,10 @@ smtp_verify_certificate(struct smtp_sess >= sizeof req_ca_vrfy.name) return 0; - x = SSL_get_peer_certificate(io_ssl(&s->io)); + x = SSL_get_peer_certificate(io_ssl(s->io)); if (x == NULL) return 0; - xchain = SSL_get_peer_cert_chain(io_ssl(&s->io)); + xchain = SSL_get_peer_cert_chain(io_ssl(s->io)); /* * Client provided a certificate and possibly a certificate chain. @@ -2635,9 +2628,9 @@ smtp_filter_dataline(struct smtp_session return; } - if (io_queued(&s->tx->oev) > DATA_HIWAT && !io_paused(&s->io, IO_PAUSE_IN)) { + if (io_queued(s->tx->oev) > DATA_HIWAT && !io_paused(s->io, IO_PAUSE_IN)) { log_debug("debug: smtp: %p: filter congestion: pausing session", s); - io_pause(&s->io, IO_PAUSE_IN); + io_pause(s->io, IO_PAUSE_IN); } } Index: smtpd.h =================================================================== RCS file: /cvs/src/usr.sbin/smtpd/smtpd.h,v retrieving revision 1.525 diff -u -p -r1.525 smtpd.h --- smtpd.h 25 Nov 2016 09:21:21 -0000 1.525 +++ smtpd.h 28 Nov 2016 12:51:29 -0000 @@ -22,6 +22,8 @@ #define nitems(_a) (sizeof((_a)) / sizeof((_a)[0])) #endif +#include <event.h> + #include "smtpd-defines.h" #include "smtpd-api.h" #include "ioev.h"