xref: /openbsd-src/usr.sbin/smtpd/smtp.c (revision 2b0358df1d88d06ef4139321dd05bd5e05d91eaf)
1 /*	$OpenBSD: smtp.c,v 1.32 2009/03/29 14:18:20 jacekm Exp $	*/
2 
3 /*
4  * Copyright (c) 2008 Gilles Chehade <gilles@openbsd.org>
5  * Copyright (c) 2008 Pierre-Yves Ritschard <pyr@openbsd.org>
6  *
7  * Permission to use, copy, modify, and distribute this software for any
8  * purpose with or without fee is hereby granted, provided that the above
9  * copyright notice and this permission notice appear in all copies.
10  *
11  * THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES
12  * WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF
13  * MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR
14  * ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES
15  * WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN
16  * ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF
17  * OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.
18  */
19 
20 #include <sys/types.h>
21 #include <sys/queue.h>
22 #include <sys/tree.h>
23 #include <sys/param.h>
24 #include <sys/socket.h>
25 
26 #include <ctype.h>
27 #include <event.h>
28 #include <pwd.h>
29 #include <signal.h>
30 #include <stdio.h>
31 #include <stdlib.h>
32 #include <string.h>
33 #include <time.h>
34 #include <unistd.h>
35 
36 #include "smtpd.h"
37 
38 __dead void	smtp_shutdown(void);
39 void		smtp_sig_handler(int, short, void *);
40 void		smtp_dispatch_parent(int, short, void *);
41 void		smtp_dispatch_mfa(int, short, void *);
42 void		smtp_dispatch_lka(int, short, void *);
43 void		smtp_dispatch_queue(int, short, void *);
44 void		smtp_dispatch_control(int, short, void *);
45 void		smtp_setup_events(struct smtpd *);
46 void		smtp_disable_events(struct smtpd *);
47 void		smtp_pause(struct smtpd *);
48 void		smtp_resume(struct smtpd *);
49 void		smtp_accept(int, short, void *);
50 void		session_timeout(int, short, void *);
51 void		session_auth_pickup(struct session *, char *, size_t);
52 
53 struct s_session	s_smtp;
54 
55 void
56 smtp_sig_handler(int sig, short event, void *p)
57 {
58 	switch (sig) {
59 	case SIGINT:
60 	case SIGTERM:
61 		smtp_shutdown();
62 		break;
63 	default:
64 		fatalx("smtp_sig_handler: unexpected signal");
65 	}
66 }
67 
68 void
69 smtp_dispatch_parent(int sig, short event, void *p)
70 {
71 	struct smtpd		*env = p;
72 	struct imsgbuf		*ibuf;
73 	struct imsg		 imsg;
74 	ssize_t			 n;
75 
76 	ibuf = env->sc_ibufs[PROC_PARENT];
77 	switch (event) {
78 	case EV_READ:
79 		if ((n = imsg_read(ibuf)) == -1)
80 			fatal("imsg_read_error");
81 		if (n == 0) {
82 			/* this pipe is dead, so remove the event handler */
83 			event_del(&ibuf->ev);
84 			event_loopexit(NULL);
85 			return;
86 		}
87 		break;
88 	case EV_WRITE:
89 		if (msgbuf_write(&ibuf->w) == -1)
90 			fatal("msgbuf_write");
91 		imsg_event_add(ibuf);
92 		return;
93 	default:
94 		fatalx("unknown event");
95 	}
96 
97 	for (;;) {
98 		if ((n = imsg_get(ibuf, &imsg)) == -1)
99 			fatal("parent_dispatch_smtp: imsg_read error");
100 		if (n == 0)
101 			break;
102 
103 		switch (imsg.hdr.type) {
104 		case IMSG_CONF_START:
105 			if (env->sc_flags & SMTPD_CONFIGURING)
106 				break;
107 			env->sc_flags |= SMTPD_CONFIGURING;
108 			smtp_disable_events(env);
109 			break;
110 		case IMSG_CONF_SSL: {
111 			struct ssl	*s;
112 			struct ssl	*x_ssl;
113 
114 			if (!(env->sc_flags & SMTPD_CONFIGURING))
115 				break;
116 
117 			if ((s = calloc(1, sizeof(*s))) == NULL)
118 				fatal(NULL);
119 			x_ssl = imsg.data;
120 			(void)strlcpy(s->ssl_name, x_ssl->ssl_name,
121 			    sizeof(s->ssl_name));
122 			s->ssl_cert_len = x_ssl->ssl_cert_len;
123 			if ((s->ssl_cert =
124 			    strdup((char *)imsg.data + sizeof(*s))) == NULL)
125 				fatal(NULL);
126 			s->ssl_key_len = x_ssl->ssl_key_len;
127 			if ((s->ssl_key = strdup((char *)imsg.data +
128 			    (sizeof(*s) + s->ssl_cert_len))) == NULL)
129 				fatal(NULL);
130 
131 			SPLAY_INSERT(ssltree, &env->sc_ssl, s);
132 			break;
133 		}
134 		case IMSG_CONF_LISTENER: {
135 			struct listener	*l;
136 			struct ssl	 key;
137 
138 			if (!(env->sc_flags & SMTPD_CONFIGURING))
139 				break;
140 
141 			if ((l = calloc(1, sizeof(*l))) == NULL)
142 				fatal(NULL);
143 			memcpy(l, imsg.data, sizeof(*l));
144 			if ((l->fd = imsg_get_fd(ibuf, &imsg)) == -1)
145 				fatal("cannot get fd");
146 
147 			log_debug("smtp_dispatch_parent: "
148 			    "got fd %d for listener: %p", l->fd, l);
149 
150 			(void)strlcpy(key.ssl_name, l->ssl_cert_name,
151 			    sizeof(key.ssl_name));
152 
153 			if (l->flags & F_SSL)
154 				if ((l->ssl = SPLAY_FIND(ssltree,
155 				    &env->sc_ssl, &key)) == NULL)
156 					fatal("parent and smtp desynchronized");
157 
158 			TAILQ_INSERT_TAIL(&env->sc_listeners, l, entry);
159 			break;
160 		}
161 		case IMSG_CONF_END:
162 			if (!(env->sc_flags & SMTPD_CONFIGURING))
163 				break;
164 			smtp_setup_events(env);
165 			env->sc_flags &= ~SMTPD_CONFIGURING;
166 			break;
167 		case IMSG_PARENT_AUTHENTICATE: {
168 			struct session		*s;
169 			struct session		 key;
170 			struct session_auth_reply *reply;
171 
172 			log_debug("smtp_dispatch_parent: parent handled authentication");
173 			reply = imsg.data;
174 			key.s_id = reply->session_id;
175 			key.s_msg.id = reply->session_id;
176 
177 			s = SPLAY_FIND(sessiontree, &env->sc_sessions, &key);
178 			if (s == NULL)
179 				fatal("smtp_dispatch_parent: session is gone");
180 
181 			if (s->s_flags & F_QUIT) {
182 				session_destroy(s);
183 				break;
184 			}
185 			s->s_flags &= ~F_EVLOCKED;
186 
187 			if (reply->value)
188 				s->s_flags |= F_AUTHENTICATED;
189 
190 			session_auth_pickup(s, NULL, 0);
191 
192 			break;
193 		}
194 		default:
195 			log_warnx("smtp_dispatch_parent: got imsg %d",
196 			    imsg.hdr.type);
197 			fatalx("smtp_dispatch_parent: unexpected imsg");
198 		}
199 		imsg_free(&imsg);
200 	}
201 	imsg_event_add(ibuf);
202 }
203 
204 void
205 smtp_dispatch_mfa(int sig, short event, void *p)
206 {
207 	struct smtpd		*env = p;
208 	struct imsgbuf		*ibuf;
209 	struct imsg		 imsg;
210 	ssize_t			 n;
211 
212 	ibuf = env->sc_ibufs[PROC_MFA];
213 	switch (event) {
214 	case EV_READ:
215 		if ((n = imsg_read(ibuf)) == -1)
216 			fatal("imsg_read_error");
217 		if (n == 0) {
218 			/* this pipe is dead, so remove the event handler */
219 			event_del(&ibuf->ev);
220 			event_loopexit(NULL);
221 			return;
222 		}
223 		break;
224 	case EV_WRITE:
225 		if (msgbuf_write(&ibuf->w) == -1)
226 			fatal("msgbuf_write");
227 		imsg_event_add(ibuf);
228 		return;
229 	default:
230 		fatalx("unknown event");
231 	}
232 
233 	for (;;) {
234 		if ((n = imsg_get(ibuf, &imsg)) == -1)
235 			fatal("smtp_dispatch_mfa: imsg_read error");
236 		if (n == 0)
237 			break;
238 
239 		switch (imsg.hdr.type) {
240 		case IMSG_MFA_MAIL:
241 		case IMSG_MFA_RCPT: {
242 			struct submit_status	*ss;
243 			struct session		*s;
244 			struct session		 key;
245 
246 			log_debug("smtp_dispatch_mfa: mfa handled return path");
247 			ss = imsg.data;
248 			key.s_id = ss->id;
249 			key.s_msg.id = ss->id;
250 
251 			s = SPLAY_FIND(sessiontree, &env->sc_sessions, &key);
252 			if (s == NULL)
253 				fatal("smtp_dispatch_mfa: session is gone");
254 
255 			if (s->s_flags & F_QUIT) {
256 				session_destroy(s);
257 				break;
258 			}
259 			s->s_flags &= ~F_EVLOCKED;
260 
261 			session_pickup(s, ss);
262 			break;
263 		}
264 		default:
265 			log_warnx("smtp_dispatch_mfa: got imsg %d",
266 			    imsg.hdr.type);
267 			fatalx("smtp_dispatch_mfa: unexpected imsg");
268 		}
269 		imsg_free(&imsg);
270 	}
271 	imsg_event_add(ibuf);
272 }
273 
274 void
275 smtp_dispatch_lka(int sig, short event, void *p)
276 {
277 	struct smtpd		*env = p;
278 	struct imsgbuf		*ibuf;
279 	struct imsg		 imsg;
280 	ssize_t			 n;
281 
282 	ibuf = env->sc_ibufs[PROC_LKA];
283 	switch (event) {
284 	case EV_READ:
285 		if ((n = imsg_read(ibuf)) == -1)
286 			fatal("imsg_read_error");
287 		if (n == 0) {
288 			/* this pipe is dead, so remove the event handler */
289 			event_del(&ibuf->ev);
290 			event_loopexit(NULL);
291 			return;
292 		}
293 		break;
294 	case EV_WRITE:
295 		if (msgbuf_write(&ibuf->w) == -1)
296 			fatal("msgbuf_write");
297 		imsg_event_add(ibuf);
298 		return;
299 	default:
300 		fatalx("unknown event");
301 	}
302 
303 	for (;;) {
304 		if ((n = imsg_get(ibuf, &imsg)) == -1)
305 			fatal("smtp_dispatch_lka: imsg_read error");
306 		if (n == 0)
307 			break;
308 
309 		switch (imsg.hdr.type) {
310 		case IMSG_LKA_HOST: {
311 			struct session		 key;
312 			struct session		*s;
313 			struct session		*ss;
314 
315 			ss = imsg.data;
316 			key.s_id = ss->s_id;
317 
318 			s = SPLAY_FIND(sessiontree, &env->sc_sessions, &key);
319 			if (s == NULL)
320 				fatal("smtp_dispatch_lka: session is gone");
321 
322 			strlcpy(s->s_hostname, ss->s_hostname,
323 			    sizeof(s->s_hostname));
324 			strlcpy(s->s_msg.session_hostname, ss->s_hostname,
325 			    sizeof(s->s_msg.session_hostname));
326 
327 			session_init(s->s_l, s);
328 
329 			break;
330 		}
331 		default:
332 			log_warnx("smtp_dispatch_lka: got imsg %d",
333 			    imsg.hdr.type);
334 			fatalx("smtp_dispatch_lka: unexpected imsg");
335 		}
336 		imsg_free(&imsg);
337 	}
338 	imsg_event_add(ibuf);
339 }
340 
341 void
342 smtp_dispatch_queue(int sig, short event, void *p)
343 {
344 	struct smtpd		*env = p;
345 	struct imsgbuf		*ibuf;
346 	struct imsg		 imsg;
347 	ssize_t			 n;
348 
349 	ibuf = env->sc_ibufs[PROC_QUEUE];
350 	switch (event) {
351 	case EV_READ:
352 		if ((n = imsg_read(ibuf)) == -1)
353 			fatal("imsg_read_error");
354 		if (n == 0) {
355 			/* this pipe is dead, so remove the event handler */
356 			event_del(&ibuf->ev);
357 			event_loopexit(NULL);
358 			return;
359 		}
360 		break;
361 	case EV_WRITE:
362 		if (msgbuf_write(&ibuf->w) == -1)
363 			fatal("msgbuf_write");
364 		imsg_event_add(ibuf);
365 		return;
366 	default:
367 		fatalx("unknown event");
368 	}
369 
370 	for (;;) {
371 		if ((n = imsg_get(ibuf, &imsg)) == -1)
372 			fatal("smtp_dispatch_queue: imsg_read error");
373 		if (n == 0)
374 			break;
375 
376 		switch (imsg.hdr.type) {
377 		case IMSG_QUEUE_CREATE_MESSAGE: {
378 			struct submit_status	*ss;
379 			struct session		*s;
380 			struct session		 key;
381 
382 			log_debug("smtp_dispatch_queue: queue handled message creation");
383 			ss = imsg.data;
384 
385 			key.s_id = ss->id;
386 
387 			s = SPLAY_FIND(sessiontree, &env->sc_sessions, &key);
388 			if (s == NULL)
389 				fatal("smtp_dispatch_queue: session is gone");
390 
391 			if (s->s_flags & F_QUIT) {
392 				session_destroy(s);
393 				break;
394 			}
395 			s->s_flags &= ~F_EVLOCKED;
396 
397 			(void)strlcpy(s->s_msg.message_id, ss->u.msgid,
398 			    sizeof(s->s_msg.message_id));
399 			session_pickup(s, ss);
400 			break;
401 		}
402 		case IMSG_QUEUE_MESSAGE_FILE: {
403 			struct submit_status	*ss;
404 			struct session		*s;
405 			struct session		 key;
406 			int			 fd;
407 
408 			log_debug("smtp_dispatch_queue: queue handled message creation");
409 			ss = imsg.data;
410 
411 			key.s_id = ss->id;
412 
413 			s = SPLAY_FIND(sessiontree, &env->sc_sessions, &key);
414 			if (s == NULL)
415 				fatal("smtp_dispatch_queue: session is gone");
416 
417 			fd = imsg_get_fd(ibuf, &imsg);
418 
419 			if (s->s_flags & F_QUIT) {
420 				session_destroy(s);
421 				break;
422 			}
423 			s->s_flags &= ~F_EVLOCKED;
424 
425 			if (fd != -1) {
426 				s->datafp = fdopen(fd, "w");
427 				if (s->datafp == NULL) {
428 					/* no need to handle error, it will be
429 					 * caught in session_pickup()
430 					 */
431 					close(fd);
432 				}
433 			}
434 			session_pickup(s, ss);
435 
436 			break;
437 		}
438 		case IMSG_QUEUE_TEMPFAIL: {
439 			struct submit_status	*ss;
440 			struct session		*s;
441 			struct session		 key;
442 
443 			log_debug("smtp_dispatch_queue: queue acknownedged a temporary failure");
444 			ss = imsg.data;
445 			key.s_id = ss->id;
446 			key.s_msg.id = ss->id;
447 
448 			s = SPLAY_FIND(sessiontree, &env->sc_sessions, &key);
449 			if (s == NULL)
450 				fatal("smtp_dispatch_queue: session is gone");
451 
452 			if (s->s_flags & F_QUIT) {
453 				session_destroy(s);
454 				break;
455 			}
456 			s->s_flags &= ~F_EVLOCKED;
457 			s->s_msg.status |= S_MESSAGE_TEMPFAILURE;
458 			break;
459 		}
460 
461 		case IMSG_QUEUE_COMMIT_ENVELOPES:
462 		case IMSG_QUEUE_COMMIT_MESSAGE: {
463 			struct submit_status	*ss;
464 			struct session		*s;
465 			struct session		 key;
466 
467 			log_debug("smtp_dispatch_queue: queue acknowledged message submission");
468 			ss = imsg.data;
469 			key.s_id = ss->id;
470 			key.s_msg.id = ss->id;
471 
472 			s = SPLAY_FIND(sessiontree, &env->sc_sessions, &key);
473 			if (s == NULL)
474 				fatal("smtp_dispatch_queue: session is gone");
475 
476 			if (s->s_flags & F_QUIT) {
477 				if (imsg.hdr.type == IMSG_QUEUE_COMMIT_MESSAGE) {
478 					s->s_msg.message_id[0] = '\0';
479 					s->s_msg.message_uid[0] = '\0';
480 				}
481 				session_destroy(s);
482 				break;
483 			}
484 			s->s_flags &= ~F_EVLOCKED;
485 
486 			session_pickup(s, ss);
487 			break;
488 		}
489 		default:
490 			log_warnx("smtp_dispatch_queue: got imsg %d",
491 			    imsg.hdr.type);
492 			fatalx("smtp_dispatch_queue: unexpected imsg");
493 		}
494 		imsg_free(&imsg);
495 	}
496 	imsg_event_add(ibuf);
497 }
498 
499 void
500 smtp_dispatch_control(int sig, short event, void *p)
501 {
502 	struct smtpd		*env = p;
503 	struct imsgbuf		*ibuf;
504 	struct imsg		 imsg;
505 	ssize_t			 n;
506 
507 	ibuf = env->sc_ibufs[PROC_CONTROL];
508 	switch (event) {
509 	case EV_READ:
510 		if ((n = imsg_read(ibuf)) == -1)
511 			fatal("imsg_read_error");
512 		if (n == 0) {
513 			/* this pipe is dead, so remove the event handler */
514 			event_del(&ibuf->ev);
515 			event_loopexit(NULL);
516 			return;
517 		}
518 		break;
519 	case EV_WRITE:
520 		if (msgbuf_write(&ibuf->w) == -1)
521 			fatal("msgbuf_write");
522 		imsg_event_add(ibuf);
523 		return;
524 	default:
525 		fatalx("unknown event");
526 	}
527 
528 	for (;;) {
529 		if ((n = imsg_get(ibuf, &imsg)) == -1)
530 			fatal("smtp_dispatch_control: imsg_read error");
531 		if (n == 0)
532 			break;
533 
534 		switch (imsg.hdr.type) {
535 		case IMSG_SMTP_PAUSE:
536 			smtp_pause(env);
537 			break;
538 		case IMSG_SMTP_RESUME:
539 			smtp_resume(env);
540 			break;
541 		case IMSG_STATS: {
542 			struct stats *s;
543 
544 			s = imsg.data;
545 			s->u.smtp = s_smtp;
546 			imsg_compose(ibuf, IMSG_STATS, 0, 0, -1, s, sizeof(*s));
547 			break;
548 		}
549 		default:
550 			log_warnx("smtp_dispatch_control: got imsg %d",
551 			    imsg.hdr.type);
552 			fatalx("smtp_dispatch_control: unexpected imsg");
553 		}
554 		imsg_free(&imsg);
555 	}
556 	imsg_event_add(ibuf);
557 }
558 
559 void
560 smtp_shutdown(void)
561 {
562 	log_info("smtp server exiting");
563 	_exit(0);
564 }
565 
566 pid_t
567 smtp(struct smtpd *env)
568 {
569 	pid_t		 pid;
570 	struct passwd	*pw;
571 
572 	struct event	 ev_sigint;
573 	struct event	 ev_sigterm;
574 
575 	struct peer peers[] = {
576 		{ PROC_PARENT,	smtp_dispatch_parent },
577 		{ PROC_MFA,	smtp_dispatch_mfa },
578 		{ PROC_QUEUE,	smtp_dispatch_queue },
579 		{ PROC_LKA,	smtp_dispatch_lka },
580 		{ PROC_CONTROL,	smtp_dispatch_control }
581 	};
582 
583 	switch (pid = fork()) {
584 	case -1:
585 		fatal("smtp: cannot fork");
586 	case 0:
587 		break;
588 	default:
589 		return (pid);
590 	}
591 
592 	ssl_init();
593 	purge_config(env, PURGE_EVERYTHING);
594 
595 	pw = env->sc_pw;
596 
597 #ifndef DEBUG
598 	if (chroot(pw->pw_dir) == -1)
599 		fatal("smtp: chroot");
600 	if (chdir("/") == -1)
601 		fatal("smtp: chdir(\"/\")");
602 #else
603 #warning disabling privilege revocation and chroot in DEBUG MODE
604 #endif
605 
606 	setproctitle("smtp server");
607 	smtpd_process = PROC_SMTP;
608 
609 #ifndef DEBUG
610 	if (setgroups(1, &pw->pw_gid) ||
611 	    setresgid(pw->pw_gid, pw->pw_gid, pw->pw_gid) ||
612 	    setresuid(pw->pw_uid, pw->pw_uid, pw->pw_uid))
613 		fatal("smtp: cannot drop privileges");
614 #endif
615 
616 	event_init();
617 
618 	signal_set(&ev_sigint, SIGINT, smtp_sig_handler, env);
619 	signal_set(&ev_sigterm, SIGTERM, smtp_sig_handler, env);
620 	signal_add(&ev_sigint, NULL);
621 	signal_add(&ev_sigterm, NULL);
622 	signal(SIGPIPE, SIG_IGN);
623 	signal(SIGHUP, SIG_IGN);
624 
625 	config_pipes(env, peers, 5);
626 	config_peers(env, peers, 5);
627 
628 	smtp_setup_events(env);
629 	event_dispatch();
630 	smtp_shutdown();
631 
632 	return (0);
633 }
634 
635 void
636 smtp_setup_events(struct smtpd *env)
637 {
638 	struct listener *l;
639 	struct timeval	 tv;
640 
641 	TAILQ_FOREACH(l, &env->sc_listeners, entry) {
642 		log_debug("smtp_setup_events: configuring listener: %p%s.",
643 		    l, (l->flags & F_SSL)?" (with ssl)":"");
644 
645 		session_socket_blockmode(l->fd, BM_NONBLOCK);
646 		if (listen(l->fd, SMTPD_BACKLOG) == -1)
647 			fatal("listen");
648 		l->env = env;
649 		event_set(&l->ev, l->fd, EV_READ, smtp_accept, l);
650 		event_add(&l->ev, NULL);
651 		ssl_setup(env, l);
652 	}
653 
654 	evtimer_set(&env->sc_ev, session_timeout, env);
655 	tv.tv_sec = 1;
656 	tv.tv_usec = 0;
657 	evtimer_add(&env->sc_ev, &tv);
658 }
659 
660 void
661 smtp_disable_events(struct smtpd *env)
662 {
663 	struct listener	*l;
664 
665 	log_debug("smtp_disable_events: closing listening sockets");
666 	while ((l = TAILQ_FIRST(&env->sc_listeners)) != NULL) {
667 		TAILQ_REMOVE(&env->sc_listeners, l, entry);
668 		event_del(&l->ev);
669 		close(l->fd);
670 		free(l);
671 	}
672 	TAILQ_INIT(&env->sc_listeners);
673 }
674 
675 void
676 smtp_pause(struct smtpd *env)
677 {
678 	log_debug("smtp_pause_listeners: pausing listening sockets");
679 	smtp_disable_events(env);
680 	env->sc_opts |= SMTPD_SMTP_PAUSED;
681 }
682 
683 void
684 smtp_resume(struct smtpd *env)
685 {
686 	log_debug("smtp_pause_listeners: resuming listening sockets");
687 	imsg_compose(env->sc_ibufs[PROC_PARENT], IMSG_PARENT_SEND_CONFIG,
688 	    0, 0, -1, NULL, 0);
689 	env->sc_opts &= ~SMTPD_SMTP_PAUSED;
690 }
691 
692 void
693 smtp_accept(int fd, short event, void *p)
694 {
695 	int			 s_fd;
696 	struct sockaddr_storage	 ss;
697 	struct listener		*l = p;
698 	struct session		*s;
699 	socklen_t		 len;
700 
701 	log_debug("smtp_accept: incoming client on listener: %p", l);
702 	len = sizeof(struct sockaddr_storage);
703 	if ((s_fd = accept(l->fd, (struct sockaddr *)&ss, &len)) == -1) {
704 		event_del(&l->ev);
705 		return;
706 	}
707 
708 	log_debug("smtp_accept: accepted client on listener: %p", l);
709 	if ((s = calloc(1, sizeof(*s))) == NULL)
710 		fatal(NULL);
711 	len = sizeof(s->s_ss);
712 
713 	s->s_id = queue_generate_id();
714 	s->s_fd = s_fd;
715 	s->s_tm = time(NULL);
716 	s->s_env = l->env;
717 	s->s_l = l;
718 
719 	(void)memcpy(&s->s_ss, &ss, sizeof(s->s_ss));
720 
721 	event_add(&l->ev, NULL);
722 
723 	s_smtp.sessions++;
724 	s_smtp.sessions_active++;
725 
726 	if (s_smtp.sessions_active == s->s_env->sc_maxconn)
727 		event_del(&l->ev);
728 
729 	strlcpy(s->s_hostname, "<unknown>", sizeof(s->s_hostname));
730 	strlcpy(s->s_msg.session_hostname, s->s_hostname,
731 	    sizeof(s->s_msg.session_hostname));
732 	imsg_compose(s->s_env->sc_ibufs[PROC_LKA], IMSG_LKA_HOST, 0, 0, -1, s,
733 	    sizeof(struct session));
734 
735 	SPLAY_INSERT(sessiontree, &s->s_env->sc_sessions, s);
736 }
737 
738 void
739 smtp_listener_setup(struct smtpd *env, struct listener *l)
740 {
741 	int opt;
742 
743 	if ((l->fd = socket(l->ss.ss_family, SOCK_STREAM, 0)) == -1)
744 		fatal("socket");
745 
746 	opt = 1;
747 	setsockopt(l->fd, SOL_SOCKET, SO_REUSEADDR, &opt, sizeof(opt));
748 
749 	if (bind(l->fd, (struct sockaddr *)&l->ss, l->ss.ss_len) == -1)
750 		fatal("bind");
751 }
752