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