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