1/*++
2/* NAME
3/*	master_listen 3
4/* SUMMARY
5/*	Postfix master - start/stop listeners
6/* SYNOPSIS
7/*	#include "master.h"
8/*
9/*	void	master_listen_init(serv)
10/*	MASTER_SERV *serv;
11/*
12/*	void	master_listen_cleanup(serv)
13/*	MASTER_SERV *serv;
14/* DESCRIPTION
15/*	master_listen_init() turns on the listener implemented by the
16/*	named process. FIFOs and UNIX-domain sockets are created with
17/*	mode 0622 and with ownership mail_owner.
18/*
19/*	master_listen_cleanup() turns off the listener implemented by the
20/*	named process.
21/* DIAGNOSTICS
22/* BUGS
23/* SEE ALSO
24/*	inet_listen(3), internet-domain listener
25/*	unix_listen(3), unix-domain listener
26/*	fifo_listen(3), named-pipe listener
27/*	upass_listen(3), file descriptor passing listener
28/*	set_eugid(3), set effective user/group attributes
29/* LICENSE
30/* .ad
31/* .fi
32/*	The Secure Mailer license must be distributed with this software.
33/* AUTHOR(S)
34/*	Wietse Venema
35/*	IBM T.J. Watson Research
36/*	P.O. Box 704
37/*	Yorktown Heights, NY 10598, USA
38/*--*/
39
40/* System library. */
41
42#include <sys_defs.h>
43#include <sys/socket.h>
44#include <netinet/in.h>
45#include <arpa/inet.h>
46#include <unistd.h>
47#include <string.h>
48
49/* Utility library. */
50
51#include <msg.h>
52#include <listen.h>
53#include <mymalloc.h>
54#include <stringops.h>
55#include <inet_addr_list.h>
56#include <set_eugid.h>
57#include <set_ugid.h>
58#include <iostuff.h>
59#include <myaddrinfo.h>
60#include <sock_addr.h>
61
62/* Global library. */
63
64#include <mail_params.h>
65
66/* Application-specific. */
67
68#include "master.h"
69
70/* master_listen_init - enable connection requests */
71
72void    master_listen_init(MASTER_SERV *serv)
73{
74    const char *myname = "master_listen_init";
75    char   *end_point;
76    int     n;
77    MAI_HOSTADDR_STR hostaddr;
78    struct sockaddr *sa;
79
80    /*
81     * Find out what transport we should use, then create one or more
82     * listener sockets. Make the listener sockets non-blocking, so that
83     * child processes don't block in accept() when multiple processes are
84     * selecting on the same socket and only one of them gets the connection.
85     */
86    switch (serv->type) {
87
88	/*
89	 * UNIX-domain or stream listener endpoints always come as singlets.
90	 */
91    case MASTER_SERV_TYPE_UNIX:
92	set_eugid(var_owner_uid, var_owner_gid);
93	serv->listen_fd[0] =
94	    LOCAL_LISTEN(serv->name, serv->max_proc > var_proc_limit ?
95			 serv->max_proc : var_proc_limit, NON_BLOCKING);
96	close_on_exec(serv->listen_fd[0], CLOSE_ON_EXEC);
97	set_ugid(getuid(), getgid());
98	break;
99
100	/*
101	 * FIFO listener endpoints always come as singlets.
102	 */
103    case MASTER_SERV_TYPE_FIFO:
104	set_eugid(var_owner_uid, var_owner_gid);
105	serv->listen_fd[0] = fifo_listen(serv->name, 0622, NON_BLOCKING);
106	close_on_exec(serv->listen_fd[0], CLOSE_ON_EXEC);
107	set_ugid(getuid(), getgid());
108	break;
109
110	/*
111	 * INET-domain listener endpoints can be wildcarded (the default) or
112	 * bound to specific interface addresses.
113	 *
114	 * With dual-stack IPv4/6 systems it does not matter, we have to specify
115	 * the addresses anyway, either explicit or wild-card.
116	 */
117    case MASTER_SERV_TYPE_INET:
118	for (n = 0; n < serv->listen_fd_count; n++) {
119	    sa = SOCK_ADDR_PTR(MASTER_INET_ADDRLIST(serv)->addrs + n);
120	    SOCKADDR_TO_HOSTADDR(sa, SOCK_ADDR_LEN(sa), &hostaddr,
121				 (MAI_SERVPORT_STR *) 0, 0);
122	    end_point = concatenate(hostaddr.buf,
123				    ":", MASTER_INET_PORT(serv), (char *) 0);
124	    serv->listen_fd[n]
125		= inet_listen(end_point, serv->max_proc > var_proc_limit ?
126			      serv->max_proc : var_proc_limit, NON_BLOCKING);
127	    close_on_exec(serv->listen_fd[n], CLOSE_ON_EXEC);
128	    myfree(end_point);
129	}
130	break;
131
132	/*
133	 * Descriptor passing endpoints always come as singlets.
134	 */
135#ifdef MASTER_SERV_TYPE_PASS
136    case MASTER_SERV_TYPE_PASS:
137	set_eugid(var_owner_uid, var_owner_gid);
138	serv->listen_fd[0] =
139	    LOCAL_LISTEN(serv->name, serv->max_proc > var_proc_limit ?
140			serv->max_proc : var_proc_limit, NON_BLOCKING);
141	close_on_exec(serv->listen_fd[0], CLOSE_ON_EXEC);
142	set_ugid(getuid(), getgid());
143	break;
144#endif
145    default:
146	msg_panic("%s: unknown service type: %d", myname, serv->type);
147    }
148}
149
150/* master_listen_cleanup - disable connection requests */
151
152void    master_listen_cleanup(MASTER_SERV *serv)
153{
154    const char *myname = "master_listen_cleanup";
155    int     n;
156
157    /*
158     * XXX The listen socket is shared with child processes. Closing the
159     * socket in the master process does not really disable listeners in
160     * child processes. There seems to be no documented way to turn off a
161     * listener. The 4.4BSD shutdown(2) man page promises an ENOTCONN error
162     * when shutdown(2) is applied to a socket that is not connected.
163     */
164    for (n = 0; n < serv->listen_fd_count; n++) {
165	if (close(serv->listen_fd[n]) < 0)
166	    msg_warn("%s: close listener socket %d: %m",
167		     myname, serv->listen_fd[n]);
168	serv->listen_fd[n] = -1;
169    }
170}
171