]>
Commit | Line | Data |
---|---|---|
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 | ||
37 | void | |
38 | cupsdDeleteAllListeners(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 | ||
57 | void | |
58 | cupsdPauseListening(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 | ||
89 | void | |
90 | cupsdResumeListening(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 | ||
115 | void | |
116 | cupsdStartListening(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 | ||
262 | void | |
263 | cupsdStopListening(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 | */ |