]> git.ipfire.org Git - thirdparty/cups.git/blame - scheduler/listen.c
Import CUPS v2.0.0
[thirdparty/cups.git] / scheduler / listen.c
CommitLineData
ef416fc2 1/*
b9367124 2 * "$Id: listen.c 12178 2014-09-30 18:56:48Z msweet $"
ef416fc2 3 *
1a18c85c 4 * Server listening routines for the CUPS scheduler.
ef416fc2 5 *
1a18c85c
MS
6 * Copyright 2007-2014 by Apple Inc.
7 * Copyright 1997-2006 by Easy Software Products, all rights reserved.
ef416fc2 8 *
1a18c85c
MS
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/".
ef416fc2 14 */
15
16/*
17 * Include necessary headers...
18 */
19
20#include "cupsd.h"
21
22
23/*
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...
26 */
27
28#if defined(__linux) && !defined(IPV6_V6ONLY)
29# define IPV6_V6ONLY 26
30#endif /* __linux && !IPV6_V6ONLY */
31
32
bd7854cb 33/*
34 * 'cupsdDeleteAllListeners()' - Delete all listeners.
35 */
36
37void
38cupsdDeleteAllListeners(void)
39{
40 cupsd_listener_t *lis; /* Current listening socket */
41
42
43 for (lis = (cupsd_listener_t *)cupsArrayFirst(Listeners);
44 lis;
45 lis = (cupsd_listener_t *)cupsArrayNext(Listeners))
b9367124
MS
46#if defined(HAVE_LAUNCHD) || defined(HAVE_SYSTEMD)
47 if (!lis->on_demand)
48#endif /* HAVE_LAUNCHD || HAVE_SYSTEMD */
49 {
50 cupsArrayRemove(Listeners, lis);
51 free(lis);
52 }
bd7854cb 53
b9367124
MS
54 if (cupsArrayCount(Listeners) == 0)
55 {
56 cupsArrayDelete(Listeners);
57 Listeners = NULL;
58 }
bd7854cb 59}
60
61
ef416fc2 62/*
63 * 'cupsdPauseListening()' - Clear input polling on all listening sockets...
64 */
65
66void
67cupsdPauseListening(void)
68{
ef416fc2 69 cupsd_listener_t *lis; /* Current listening socket */
70
71
bd7854cb 72 if (cupsArrayCount(Listeners) < 1)
ef416fc2 73 return;
74
bd7854cb 75 if (cupsArrayCount(Clients) == MaxClients)
ef416fc2 76 cupsdLogMessage(CUPSD_LOG_WARN,
77 "Max clients reached, holding new connections...");
76cd9e37
MS
78 else if (errno == ENFILE || errno == EMFILE)
79 cupsdLogMessage(CUPSD_LOG_WARN,
80 "Too many open files, holding new connections for "
81 "30 seconds...");
ef416fc2 82
bd7854cb 83 cupsdLogMessage(CUPSD_LOG_DEBUG2, "cupsdPauseListening: Clearing input bits...");
ef416fc2 84
bd7854cb 85 for (lis = (cupsd_listener_t *)cupsArrayFirst(Listeners);
86 lis;
87 lis = (cupsd_listener_t *)cupsArrayNext(Listeners))
f7deaa1a 88 cupsdRemoveSelect(lis->fd);
76cd9e37
MS
89
90 ListeningPaused = time(NULL) + 30;
ef416fc2 91}
92
93
94/*
95 * 'cupsdResumeListening()' - Set input polling on all listening sockets...
96 */
97
98void
99cupsdResumeListening(void)
100{
ef416fc2 101 cupsd_listener_t *lis; /* Current listening socket */
102
103
bd7854cb 104 if (cupsArrayCount(Listeners) < 1)
ef416fc2 105 return;
106
76cd9e37 107 cupsdLogMessage(CUPSD_LOG_INFO, "Resuming new connection processing...");
bd7854cb 108 cupsdLogMessage(CUPSD_LOG_DEBUG2,
109 "cupsdResumeListening: Setting input bits...");
ef416fc2 110
bd7854cb 111 for (lis = (cupsd_listener_t *)cupsArrayFirst(Listeners);
112 lis;
113 lis = (cupsd_listener_t *)cupsArrayNext(Listeners))
f7deaa1a 114 cupsdAddSelect(lis->fd, (cupsd_selfunc_t)cupsdAcceptClient, NULL, lis);
76cd9e37
MS
115
116 ListeningPaused = 0;
ef416fc2 117}
118
119
120/*
121 * 'cupsdStartListening()' - Create all listening sockets...
122 */
123
124void
125cupsdStartListening(void)
126{
1a18c85c 127 int p; /* Port number */
ef416fc2 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 */
133 "IfRequested",
134 "Never",
135 "Required",
136 "Always"
137 };
138
139
bd7854cb 140 cupsdLogMessage(CUPSD_LOG_DEBUG2, "cupsdStartListening: %d Listeners",
141 cupsArrayCount(Listeners));
ef416fc2 142
ef416fc2 143 /*
144 * Setup socket listeners...
145 */
146
bd7854cb 147 for (lis = (cupsd_listener_t *)cupsArrayFirst(Listeners), LocalPort = 0,
148 have_domain = NULL;
149 lis;
150 lis = (cupsd_listener_t *)cupsArrayNext(Listeners))
ef416fc2 151 {
152 httpAddrString(&(lis->address), s, sizeof(s));
a469f8a5 153 p = httpAddrPort(&(lis->address));
ef416fc2 154
155 /*
a4d04587 156 * If needed, create a socket for listening...
ef416fc2 157 */
158
ef416fc2 159 if (lis->fd == -1)
160 {
ef416fc2 161 /*
a4d04587 162 * Create a socket for listening...
ef416fc2 163 */
bd7854cb 164
1a18c85c 165 lis->fd = httpAddrListen(&(lis->address), p);
bd7854cb 166
a4d04587 167 if (lis->fd == -1)
168 {
169 cupsdLogMessage(CUPSD_LOG_ERROR,
bd7854cb 170 "Unable to open listen socket for address %s:%d - %s.",
a4d04587 171 s, p, strerror(errno));
49d87452
MS
172
173#ifdef AF_INET6
174 /*
175 * IPv6 is often disabled while DNS returns IPv6 addresses...
176 */
177
178 if (lis->address.addr.sa_family != AF_INET6 &&
179 (FatalErrors & CUPSD_FATAL_LISTEN))
180 cupsdEndProcess(getpid(), 0);
181#else
182 if (FatalErrors & CUPSD_FATAL_LISTEN)
183 cupsdEndProcess(getpid(), 0);
184#endif /* AF_INET6 */
185
a4d04587 186 continue;
187 }
ef416fc2 188 }
ef416fc2 189
ef416fc2 190 if (p)
bd7854cb 191 cupsdLogMessage(CUPSD_LOG_INFO, "Listening to %s:%d on fd %d...",
ef416fc2 192 s, p, lis->fd);
193 else
bd7854cb 194 cupsdLogMessage(CUPSD_LOG_INFO, "Listening to %s on fd %d...",
ef416fc2 195 s, lis->fd);
196
197 /*
198 * Save the first port that is bound to the local loopback or
199 * "any" address...
200 */
201
8ca02f3c 202 if ((!LocalPort || LocalEncryption == HTTP_ENCRYPT_ALWAYS) && p > 0 &&
ef416fc2 203 (httpAddrLocalhost(&(lis->address)) ||
204 httpAddrAny(&(lis->address))))
205 {
206 LocalPort = p;
207 LocalEncryption = lis->encryption;
208 }
209
210#ifdef AF_LOCAL
211 if (lis->address.addr.sa_family == AF_LOCAL && !have_domain)
212 have_domain = lis->address.un.sun_path;
213#endif /* AF_LOCAL */
214 }
215
216 /*
217 * Make sure that we are listening on localhost!
218 */
219
220 if (!LocalPort && !have_domain)
221 {
222 cupsdLogMessage(CUPSD_LOG_EMERG,
07725fee 223 "No Listen or Port lines were found to allow access via "
1a18c85c 224 "localhost.");
ef416fc2 225
49d87452
MS
226 if (FatalErrors & (CUPSD_FATAL_CONFIG | CUPSD_FATAL_LISTEN))
227 cupsdEndProcess(getpid(), 0);
ef416fc2 228 }
229
230 /*
231 * Set the CUPS_SERVER, IPP_PORT, and CUPS_ENCRYPTION variables based on
232 * the listeners...
233 */
234
235 if (have_domain)
236 {
237 /*
238 * Use domain sockets for the local connection...
239 */
240
241 cupsdSetEnv("CUPS_SERVER", have_domain);
8ca02f3c 242
243 LocalEncryption = HTTP_ENCRYPT_IF_REQUESTED;
ef416fc2 244 }
245 else
246 {
247 /*
248 * Use the default local loopback address for the server...
249 */
250
251 cupsdSetEnv("CUPS_SERVER", "localhost");
252 }
253
254 cupsdSetEnv("CUPS_ENCRYPTION", encryptions[LocalEncryption]);
07725fee 255
256 if (LocalPort)
257 cupsdSetEnvf("IPP_PORT", "%d", LocalPort);
ef416fc2 258
259 /*
260 * Resume listening for connections...
261 */
262
263 cupsdResumeListening();
264}
265
266
267/*
268 * 'cupsdStopListening()' - Close all listening sockets...
269 */
270
271void
272cupsdStopListening(void)
273{
ef416fc2 274 cupsd_listener_t *lis; /* Current listening socket */
275
276
bd7854cb 277 cupsdLogMessage(CUPSD_LOG_DEBUG2,
ef416fc2 278 "cupsdStopListening: closing all listen sockets.");
279
280 cupsdPauseListening();
281
bd7854cb 282 for (lis = (cupsd_listener_t *)cupsArrayFirst(Listeners);
283 lis;
284 lis = (cupsd_listener_t *)cupsArrayNext(Listeners))
ef416fc2 285 {
5d2cc5d3 286#if defined(HAVE_LAUNCHD) || defined(HAVE_SYSTEMD)
b9367124
MS
287 if (!lis->on_demand && lis->fd != -1)
288 {
1a18c85c 289 httpAddrClose(&(lis->address), lis->fd);
b9367124
MS
290 lis->fd = -1;
291 }
1a18c85c 292
1a18c85c
MS
293#else
294 if (lis->fd != -1)
b9367124 295 {
1a18c85c 296 httpAddrClose(&(lis->address), lis->fd);
b9367124
MS
297 lis->fd = -1;
298 }
5d2cc5d3 299#endif /* HAVE_LAUNCHD || HAVE_SYSTEMD */
ef416fc2 300 }
301}
302
303
304/*
b9367124 305 * End of "$Id: listen.c 12178 2014-09-30 18:56:48Z msweet $".
ef416fc2 306 */