]>
Commit | Line | Data |
---|---|---|
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 | * |
e3101897 | 7 | * Licensed under Apache License v2.0. See the file "LICENSE" for more information. |
ef416fc2 | 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 | ||
bd7854cb | 27 | /* |
28 | * 'cupsdDeleteAllListeners()' - Delete all listeners. | |
29 | */ | |
30 | ||
31 | 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)) | |
1166bf58 | 40 | #ifdef HAVE_ONDEMAND |
6e6adc4f | 41 | if (!lis->on_demand) |
c187d9ab | 42 | #endif /* HAVE_ONDEMAND */ |
6e6adc4f MS |
43 | { |
44 | cupsArrayRemove(Listeners, lis); | |
45 | free(lis); | |
46 | } | |
bd7854cb | 47 | |
6e6adc4f MS |
48 | if (cupsArrayCount(Listeners) == 0) |
49 | { | |
50 | cupsArrayDelete(Listeners); | |
51 | Listeners = NULL; | |
52 | } | |
bd7854cb | 53 | } |
54 | ||
55 | ||
ef416fc2 | 56 | /* |
57 | * 'cupsdPauseListening()' - Clear input polling on all listening sockets... | |
58 | */ | |
59 | ||
60 | void | |
61 | cupsdPauseListening(void) | |
62 | { | |
ef416fc2 | 63 | cupsd_listener_t *lis; /* Current listening socket */ |
64 | ||
65 | ||
bd7854cb | 66 | if (cupsArrayCount(Listeners) < 1) |
ef416fc2 | 67 | return; |
68 | ||
bd7854cb | 69 | if (cupsArrayCount(Clients) == MaxClients) |
ef416fc2 | 70 | cupsdLogMessage(CUPSD_LOG_WARN, |
71 | "Max clients reached, holding new connections..."); | |
76cd9e37 MS |
72 | else if (errno == ENFILE || errno == EMFILE) |
73 | cupsdLogMessage(CUPSD_LOG_WARN, | |
74 | "Too many open files, holding new connections for " | |
75 | "30 seconds..."); | |
ef416fc2 | 76 | |
bd7854cb | 77 | cupsdLogMessage(CUPSD_LOG_DEBUG2, "cupsdPauseListening: Clearing input bits..."); |
ef416fc2 | 78 | |
bd7854cb | 79 | for (lis = (cupsd_listener_t *)cupsArrayFirst(Listeners); |
80 | lis; | |
81 | lis = (cupsd_listener_t *)cupsArrayNext(Listeners)) | |
f7deaa1a | 82 | cupsdRemoveSelect(lis->fd); |
76cd9e37 MS |
83 | |
84 | ListeningPaused = time(NULL) + 30; | |
ef416fc2 | 85 | } |
86 | ||
87 | ||
88 | /* | |
89 | * 'cupsdResumeListening()' - Set input polling on all listening sockets... | |
90 | */ | |
91 | ||
92 | void | |
93 | cupsdResumeListening(void) | |
94 | { | |
ef416fc2 | 95 | cupsd_listener_t *lis; /* Current listening socket */ |
96 | ||
97 | ||
bd7854cb | 98 | if (cupsArrayCount(Listeners) < 1) |
ef416fc2 | 99 | return; |
100 | ||
76cd9e37 | 101 | cupsdLogMessage(CUPSD_LOG_INFO, "Resuming new connection processing..."); |
bd7854cb | 102 | cupsdLogMessage(CUPSD_LOG_DEBUG2, |
103 | "cupsdResumeListening: Setting input bits..."); | |
ef416fc2 | 104 | |
bd7854cb | 105 | for (lis = (cupsd_listener_t *)cupsArrayFirst(Listeners); |
106 | lis; | |
107 | lis = (cupsd_listener_t *)cupsArrayNext(Listeners)) | |
f7deaa1a | 108 | cupsdAddSelect(lis->fd, (cupsd_selfunc_t)cupsdAcceptClient, NULL, lis); |
76cd9e37 MS |
109 | |
110 | ListeningPaused = 0; | |
ef416fc2 | 111 | } |
112 | ||
113 | ||
114 | /* | |
115 | * 'cupsdStartListening()' - Create all listening sockets... | |
116 | */ | |
117 | ||
118 | void | |
119 | cupsdStartListening(void) | |
120 | { | |
87e98392 | 121 | int p; /* Port number */ |
ef416fc2 | 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 | ||
bd7854cb | 134 | cupsdLogMessage(CUPSD_LOG_DEBUG2, "cupsdStartListening: %d Listeners", |
135 | cupsArrayCount(Listeners)); | |
ef416fc2 | 136 | |
ef416fc2 | 137 | /* |
138 | * Setup socket listeners... | |
139 | */ | |
140 | ||
bd7854cb | 141 | for (lis = (cupsd_listener_t *)cupsArrayFirst(Listeners), LocalPort = 0, |
142 | have_domain = NULL; | |
143 | lis; | |
144 | lis = (cupsd_listener_t *)cupsArrayNext(Listeners)) | |
ef416fc2 | 145 | { |
146 | httpAddrString(&(lis->address), s, sizeof(s)); | |
a469f8a5 | 147 | p = httpAddrPort(&(lis->address)); |
ef416fc2 | 148 | |
149 | /* | |
a4d04587 | 150 | * If needed, create a socket for listening... |
ef416fc2 | 151 | */ |
152 | ||
ef416fc2 | 153 | if (lis->fd == -1) |
154 | { | |
ef416fc2 | 155 | /* |
a4d04587 | 156 | * Create a socket for listening... |
ef416fc2 | 157 | */ |
bd7854cb | 158 | |
87e98392 | 159 | lis->fd = httpAddrListen(&(lis->address), p); |
bd7854cb | 160 | |
a4d04587 | 161 | if (lis->fd == -1) |
162 | { | |
163 | cupsdLogMessage(CUPSD_LOG_ERROR, | |
bd7854cb | 164 | "Unable to open listen socket for address %s:%d - %s.", |
a4d04587 | 165 | s, p, strerror(errno)); |
49d87452 MS |
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 | ||
a4d04587 | 180 | continue; |
181 | } | |
ef416fc2 | 182 | } |
ef416fc2 | 183 | |
ef416fc2 | 184 | if (p) |
bd7854cb | 185 | cupsdLogMessage(CUPSD_LOG_INFO, "Listening to %s:%d on fd %d...", |
ef416fc2 | 186 | s, p, lis->fd); |
187 | else | |
bd7854cb | 188 | cupsdLogMessage(CUPSD_LOG_INFO, "Listening to %s on fd %d...", |
ef416fc2 | 189 | s, lis->fd); |
190 | ||
191 | /* | |
192 | * Save the first port that is bound to the local loopback or | |
193 | * "any" address... | |
194 | */ | |
195 | ||
8ca02f3c | 196 | if ((!LocalPort || LocalEncryption == HTTP_ENCRYPT_ALWAYS) && p > 0 && |
ef416fc2 | 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, | |
07725fee | 217 | "No Listen or Port lines were found to allow access via " |
87e98392 | 218 | "localhost."); |
ef416fc2 | 219 | |
49d87452 MS |
220 | if (FatalErrors & (CUPSD_FATAL_CONFIG | CUPSD_FATAL_LISTEN)) |
221 | cupsdEndProcess(getpid(), 0); | |
ef416fc2 | 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); | |
8ca02f3c | 236 | |
237 | LocalEncryption = HTTP_ENCRYPT_IF_REQUESTED; | |
ef416fc2 | 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]); | |
07725fee | 249 | |
250 | if (LocalPort) | |
251 | cupsdSetEnvf("IPP_PORT", "%d", LocalPort); | |
ef416fc2 | 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 | |
266 | cupsdStopListening(void) | |
267 | { | |
ef416fc2 | 268 | cupsd_listener_t *lis; /* Current listening socket */ |
269 | ||
270 | ||
bd7854cb | 271 | cupsdLogMessage(CUPSD_LOG_DEBUG2, |
ef416fc2 | 272 | "cupsdStopListening: closing all listen sockets."); |
273 | ||
274 | cupsdPauseListening(); | |
275 | ||
bd7854cb | 276 | for (lis = (cupsd_listener_t *)cupsArrayFirst(Listeners); |
277 | lis; | |
278 | lis = (cupsd_listener_t *)cupsArrayNext(Listeners)) | |
ef416fc2 | 279 | { |
1166bf58 | 280 | #ifdef HAVE_ONDEMAND |
6e6adc4f MS |
281 | if (!lis->on_demand && lis->fd != -1) |
282 | { | |
1720786e | 283 | httpAddrClose(&(lis->address), lis->fd); |
6e6adc4f MS |
284 | lis->fd = -1; |
285 | } | |
1720786e | 286 | |
ef416fc2 | 287 | #else |
1720786e | 288 | if (lis->fd != -1) |
6e6adc4f | 289 | { |
87e98392 | 290 | httpAddrClose(&(lis->address), lis->fd); |
6e6adc4f MS |
291 | lis->fd = -1; |
292 | } | |
c187d9ab | 293 | #endif /* HAVE_ONDEMAND */ |
ef416fc2 | 294 | } |
295 | } |