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