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