2 * "$Id: listen.c 12178 2014-09-30 18:56:48Z msweet $"
4 * Server listening routines for the CUPS scheduler.
6 * Copyright 2007-2014 by Apple Inc.
7 * Copyright 1997-2006 by Easy Software Products, all rights reserved.
9 * These coded instructions, statements, and computer programs are the
10 * property of Apple Inc. and are protected by Federal copyright
11 * law. Distribution and use rights are outlined in the file "LICENSE.txt"
12 * which should have been included with this file. If this file is
13 * file is missing or damaged, see the license at "http://www.cups.org/".
17 * Include necessary headers...
24 * Make sure the IPV6_V6ONLY is defined on Linux - older versions of
25 * glibc don't define it even if the kernel supports it...
28 #if defined(__linux) && !defined(IPV6_V6ONLY)
29 # define IPV6_V6ONLY 26
30 #endif /* __linux && !IPV6_V6ONLY */
34 * 'cupsdDeleteAllListeners()' - Delete all listeners.
38 cupsdDeleteAllListeners(void)
40 cupsd_listener_t *lis; /* Current listening socket */
43 for (lis = (cupsd_listener_t *)cupsArrayFirst(Listeners);
45 lis = (cupsd_listener_t *)cupsArrayNext(Listeners))
46 #if defined(HAVE_LAUNCHD) || defined(HAVE_SYSTEMD)
48 #endif /* HAVE_LAUNCHD || HAVE_SYSTEMD */
50 cupsArrayRemove(Listeners, lis);
54 if (cupsArrayCount(Listeners) == 0)
56 cupsArrayDelete(Listeners);
63 * 'cupsdPauseListening()' - Clear input polling on all listening sockets...
67 cupsdPauseListening(void)
69 cupsd_listener_t *lis; /* Current listening socket */
72 if (cupsArrayCount(Listeners) < 1)
75 if (cupsArrayCount(Clients) == MaxClients)
76 cupsdLogMessage(CUPSD_LOG_WARN,
77 "Max clients reached, holding new connections...");
78 else if (errno == ENFILE || errno == EMFILE)
79 cupsdLogMessage(CUPSD_LOG_WARN,
80 "Too many open files, holding new connections for "
83 cupsdLogMessage(CUPSD_LOG_DEBUG2, "cupsdPauseListening: Clearing input bits...");
85 for (lis = (cupsd_listener_t *)cupsArrayFirst(Listeners);
87 lis = (cupsd_listener_t *)cupsArrayNext(Listeners))
88 cupsdRemoveSelect(lis->fd);
90 ListeningPaused = time(NULL) + 30;
95 * 'cupsdResumeListening()' - Set input polling on all listening sockets...
99 cupsdResumeListening(void)
101 cupsd_listener_t *lis; /* Current listening socket */
104 if (cupsArrayCount(Listeners) < 1)
107 cupsdLogMessage(CUPSD_LOG_INFO, "Resuming new connection processing...");
108 cupsdLogMessage(CUPSD_LOG_DEBUG2,
109 "cupsdResumeListening: Setting input bits...");
111 for (lis = (cupsd_listener_t *)cupsArrayFirst(Listeners);
113 lis = (cupsd_listener_t *)cupsArrayNext(Listeners))
114 cupsdAddSelect(lis->fd, (cupsd_selfunc_t)cupsdAcceptClient, NULL, lis);
121 * 'cupsdStartListening()' - Create all listening sockets...
125 cupsdStartListening(void)
127 int p; /* Port number */
128 cupsd_listener_t *lis; /* Current listening socket */
129 char s[256]; /* String addresss */
130 const char *have_domain; /* Have a domain socket? */
131 static const char * const encryptions[] =
132 { /* Encryption values */
140 cupsdLogMessage(CUPSD_LOG_DEBUG2, "cupsdStartListening: %d Listeners",
141 cupsArrayCount(Listeners));
144 * Setup socket listeners...
147 for (lis = (cupsd_listener_t *)cupsArrayFirst(Listeners), LocalPort = 0,
150 lis = (cupsd_listener_t *)cupsArrayNext(Listeners))
152 httpAddrString(&(lis->address), s, sizeof(s));
153 p = httpAddrPort(&(lis->address));
156 * If needed, create a socket for listening...
162 * Create a socket for listening...
165 lis->fd = httpAddrListen(&(lis->address), p);
169 cupsdLogMessage(CUPSD_LOG_ERROR,
170 "Unable to open listen socket for address %s:%d - %s.",
171 s, p, strerror(errno));
175 * IPv6 is often disabled while DNS returns IPv6 addresses...
178 if (lis->address.addr.sa_family != AF_INET6 &&
179 (FatalErrors & CUPSD_FATAL_LISTEN))
180 cupsdEndProcess(getpid(), 0);
182 if (FatalErrors & CUPSD_FATAL_LISTEN)
183 cupsdEndProcess(getpid(), 0);
184 #endif /* AF_INET6 */
191 cupsdLogMessage(CUPSD_LOG_INFO, "Listening to %s:%d on fd %d...",
194 cupsdLogMessage(CUPSD_LOG_INFO, "Listening to %s on fd %d...",
198 * Save the first port that is bound to the local loopback or
202 if ((!LocalPort || LocalEncryption == HTTP_ENCRYPT_ALWAYS) && p > 0 &&
203 (httpAddrLocalhost(&(lis->address)) ||
204 httpAddrAny(&(lis->address))))
207 LocalEncryption = lis->encryption;
211 if (lis->address.addr.sa_family == AF_LOCAL && !have_domain)
212 have_domain = lis->address.un.sun_path;
213 #endif /* AF_LOCAL */
217 * Make sure that we are listening on localhost!
220 if (!LocalPort && !have_domain)
222 cupsdLogMessage(CUPSD_LOG_EMERG,
223 "No Listen or Port lines were found to allow access via "
226 if (FatalErrors & (CUPSD_FATAL_CONFIG | CUPSD_FATAL_LISTEN))
227 cupsdEndProcess(getpid(), 0);
231 * Set the CUPS_SERVER, IPP_PORT, and CUPS_ENCRYPTION variables based on
238 * Use domain sockets for the local connection...
241 cupsdSetEnv("CUPS_SERVER", have_domain);
243 LocalEncryption = HTTP_ENCRYPT_IF_REQUESTED;
248 * Use the default local loopback address for the server...
251 cupsdSetEnv("CUPS_SERVER", "localhost");
254 cupsdSetEnv("CUPS_ENCRYPTION", encryptions[LocalEncryption]);
257 cupsdSetEnvf("IPP_PORT", "%d", LocalPort);
260 * Resume listening for connections...
263 cupsdResumeListening();
268 * 'cupsdStopListening()' - Close all listening sockets...
272 cupsdStopListening(void)
274 cupsd_listener_t *lis; /* Current listening socket */
277 cupsdLogMessage(CUPSD_LOG_DEBUG2,
278 "cupsdStopListening: closing all listen sockets.");
280 cupsdPauseListening();
282 for (lis = (cupsd_listener_t *)cupsArrayFirst(Listeners);
284 lis = (cupsd_listener_t *)cupsArrayNext(Listeners))
286 #if defined(HAVE_LAUNCHD) || defined(HAVE_SYSTEMD)
287 if (!lis->on_demand && lis->fd != -1)
289 httpAddrClose(&(lis->address), lis->fd);
296 httpAddrClose(&(lis->address), lis->fd);
299 #endif /* HAVE_LAUNCHD || HAVE_SYSTEMD */
305 * End of "$Id: listen.c 12178 2014-09-30 18:56:48Z msweet $".