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