1 /* $NetBSD: master_listen.c,v 1.1.1.1 2009/06/23 10:08:49 tron 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 42 /* System library. */ 43 44 #include <sys_defs.h> 45 #include <sys/socket.h> 46 #include <netinet/in.h> 47 #include <arpa/inet.h> 48 #include <unistd.h> 49 #include <string.h> 50 51 /* Utility library. */ 52 53 #include <msg.h> 54 #include <listen.h> 55 #include <mymalloc.h> 56 #include <stringops.h> 57 #include <inet_addr_list.h> 58 #include <set_eugid.h> 59 #include <set_ugid.h> 60 #include <iostuff.h> 61 #include <myaddrinfo.h> 62 #include <sock_addr.h> 63 64 /* Global library. */ 65 66 #include <mail_params.h> 67 68 /* Application-specific. */ 69 70 #include "master.h" 71 72 /* master_listen_init - enable connection requests */ 73 74 void master_listen_init(MASTER_SERV *serv) 75 { 76 const char *myname = "master_listen_init"; 77 char *end_point; 78 int n; 79 MAI_HOSTADDR_STR hostaddr; 80 struct sockaddr *sa; 81 82 /* 83 * Find out what transport we should use, then create one or more 84 * listener sockets. Make the listener sockets non-blocking, so that 85 * child processes don't block in accept() when multiple processes are 86 * selecting on the same socket and only one of them gets the connection. 87 */ 88 switch (serv->type) { 89 90 /* 91 * UNIX-domain or stream listener endpoints always come as singlets. 92 */ 93 case MASTER_SERV_TYPE_UNIX: 94 set_eugid(var_owner_uid, var_owner_gid); 95 serv->listen_fd[0] = 96 LOCAL_LISTEN(serv->name, serv->max_proc > var_proc_limit ? 97 serv->max_proc : var_proc_limit, NON_BLOCKING); 98 close_on_exec(serv->listen_fd[0], CLOSE_ON_EXEC); 99 set_ugid(getuid(), getgid()); 100 break; 101 102 /* 103 * FIFO listener endpoints always come as singlets. 104 */ 105 case MASTER_SERV_TYPE_FIFO: 106 set_eugid(var_owner_uid, var_owner_gid); 107 serv->listen_fd[0] = fifo_listen(serv->name, 0622, NON_BLOCKING); 108 close_on_exec(serv->listen_fd[0], CLOSE_ON_EXEC); 109 set_ugid(getuid(), getgid()); 110 break; 111 112 /* 113 * INET-domain listener endpoints can be wildcarded (the default) or 114 * bound to specific interface addresses. 115 * 116 * With dual-stack IPv4/6 systems it does not matter, we have to specify 117 * the addresses anyway, either explicit or wild-card. 118 */ 119 case MASTER_SERV_TYPE_INET: 120 for (n = 0; n < serv->listen_fd_count; n++) { 121 sa = SOCK_ADDR_PTR(MASTER_INET_ADDRLIST(serv)->addrs + n); 122 SOCKADDR_TO_HOSTADDR(sa, SOCK_ADDR_LEN(sa), &hostaddr, 123 (MAI_SERVPORT_STR *) 0, 0); 124 end_point = concatenate(hostaddr.buf, 125 ":", MASTER_INET_PORT(serv), (char *) 0); 126 serv->listen_fd[n] 127 = inet_listen(end_point, serv->max_proc > var_proc_limit ? 128 serv->max_proc : var_proc_limit, NON_BLOCKING); 129 close_on_exec(serv->listen_fd[n], CLOSE_ON_EXEC); 130 myfree(end_point); 131 } 132 break; 133 134 /* 135 * Descriptor passing endpoints always come as singlets. 136 */ 137 #ifdef MASTER_SERV_TYPE_PASS 138 case MASTER_SERV_TYPE_PASS: 139 set_eugid(var_owner_uid, var_owner_gid); 140 serv->listen_fd[0] = 141 PASS_LISTEN(serv->name, serv->max_proc > var_proc_limit ? 142 serv->max_proc : var_proc_limit, NON_BLOCKING); 143 close_on_exec(serv->listen_fd[0], CLOSE_ON_EXEC); 144 set_ugid(getuid(), getgid()); 145 break; 146 #endif 147 default: 148 msg_panic("%s: unknown service type: %d", myname, serv->type); 149 } 150 } 151 152 /* master_listen_cleanup - disable connection requests */ 153 154 void master_listen_cleanup(MASTER_SERV *serv) 155 { 156 const char *myname = "master_listen_cleanup"; 157 int n; 158 159 /* 160 * XXX The listen socket is shared with child processes. Closing the 161 * socket in the master process does not really disable listeners in 162 * child processes. There seems to be no documented way to turn off a 163 * listener. The 4.4BSD shutdown(2) man page promises an ENOTCONN error 164 * when shutdown(2) is applied to a socket that is not connected. 165 */ 166 for (n = 0; n < serv->listen_fd_count; n++) { 167 if (close(serv->listen_fd[n]) < 0) 168 msg_warn("%s: close listener socket %d: %m", 169 myname, serv->listen_fd[n]); 170 serv->listen_fd[n] = -1; 171 } 172 } 173