2 * Server listening routines for the CUPS scheduler.
4 * Copyright 2007-2016 by Apple Inc.
5 * Copyright 1997-2006 by Easy Software Products, all rights reserved.
7 * Licensed under Apache License v2.0. See the file "LICENSE" for more information.
11 * Include necessary headers...
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...
22 #if defined(__linux) && !defined(IPV6_V6ONLY)
23 # define IPV6_V6ONLY 26
24 #endif /* __linux && !IPV6_V6ONLY */
28 * 'cupsdDeleteAllListeners()' - Delete all listeners.
32 cupsdDeleteAllListeners(void)
34 cupsd_listener_t
*lis
; /* Current listening socket */
37 for (lis
= (cupsd_listener_t
*)cupsArrayFirst(Listeners
);
39 lis
= (cupsd_listener_t
*)cupsArrayNext(Listeners
))
42 #endif /* HAVE_ONDEMAND */
44 cupsArrayRemove(Listeners
, lis
);
48 if (cupsArrayCount(Listeners
) == 0)
50 cupsArrayDelete(Listeners
);
57 * 'cupsdPauseListening()' - Clear input polling on all listening sockets...
61 cupsdPauseListening(void)
63 cupsd_listener_t
*lis
; /* Current listening socket */
66 if (cupsArrayCount(Listeners
) < 1)
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 "
77 cupsdLogMessage(CUPSD_LOG_DEBUG2
, "cupsdPauseListening: Clearing input bits...");
79 for (lis
= (cupsd_listener_t
*)cupsArrayFirst(Listeners
);
81 lis
= (cupsd_listener_t
*)cupsArrayNext(Listeners
))
82 cupsdRemoveSelect(lis
->fd
);
84 ListeningPaused
= time(NULL
) + 30;
89 * 'cupsdResumeListening()' - Set input polling on all listening sockets...
93 cupsdResumeListening(void)
95 cupsd_listener_t
*lis
; /* Current listening socket */
98 if (cupsArrayCount(Listeners
) < 1)
101 cupsdLogMessage(CUPSD_LOG_INFO
, "Resuming new connection processing...");
102 cupsdLogMessage(CUPSD_LOG_DEBUG2
,
103 "cupsdResumeListening: Setting input bits...");
105 for (lis
= (cupsd_listener_t
*)cupsArrayFirst(Listeners
);
107 lis
= (cupsd_listener_t
*)cupsArrayNext(Listeners
))
108 cupsdAddSelect(lis
->fd
, (cupsd_selfunc_t
)cupsdAcceptClient
, NULL
, lis
);
115 * 'cupsdStartListening()' - Create all listening sockets...
119 cupsdStartListening(void)
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 */
134 cupsdLogMessage(CUPSD_LOG_DEBUG2
, "cupsdStartListening: %d Listeners",
135 cupsArrayCount(Listeners
));
138 * Setup socket listeners...
141 for (lis
= (cupsd_listener_t
*)cupsArrayFirst(Listeners
), LocalPort
= 0,
144 lis
= (cupsd_listener_t
*)cupsArrayNext(Listeners
))
146 httpAddrString(&(lis
->address
), s
, sizeof(s
));
147 p
= httpAddrPort(&(lis
->address
));
150 * If needed, create a socket for listening...
156 * Create a socket for listening...
159 lis
->fd
= httpAddrListen(&(lis
->address
), p
);
163 cupsdLogMessage(CUPSD_LOG_ERROR
,
164 "Unable to open listen socket for address %s:%d - %s.",
165 s
, p
, strerror(errno
));
169 * IPv6 is often disabled while DNS returns IPv6 addresses...
172 if (lis
->address
.addr
.sa_family
!= AF_INET6
&&
173 (FatalErrors
& CUPSD_FATAL_LISTEN
))
174 cupsdEndProcess(getpid(), 0);
176 if (FatalErrors
& CUPSD_FATAL_LISTEN
)
177 cupsdEndProcess(getpid(), 0);
178 #endif /* AF_INET6 */
185 cupsdLogMessage(CUPSD_LOG_INFO
, "Listening to %s:%d on fd %d...",
188 cupsdLogMessage(CUPSD_LOG_INFO
, "Listening to %s on fd %d...",
192 * Save the first port that is bound to the local loopback or
196 if ((!LocalPort
|| LocalEncryption
== HTTP_ENCRYPT_ALWAYS
) && p
> 0 &&
197 (httpAddrLocalhost(&(lis
->address
)) ||
198 httpAddrAny(&(lis
->address
))))
201 LocalEncryption
= lis
->encryption
;
205 if (lis
->address
.addr
.sa_family
== AF_LOCAL
&& !have_domain
)
206 have_domain
= lis
->address
.un
.sun_path
;
207 #endif /* AF_LOCAL */
211 * Make sure that we are listening on localhost!
214 if (!LocalPort
&& !have_domain
)
216 cupsdLogMessage(CUPSD_LOG_EMERG
,
217 "No Listen or Port lines were found to allow access via "
220 if (FatalErrors
& (CUPSD_FATAL_CONFIG
| CUPSD_FATAL_LISTEN
))
221 cupsdEndProcess(getpid(), 0);
225 * Set the CUPS_SERVER, IPP_PORT, and CUPS_ENCRYPTION variables based on
232 * Use domain sockets for the local connection...
235 cupsdSetEnv("CUPS_SERVER", have_domain
);
237 LocalEncryption
= HTTP_ENCRYPT_IF_REQUESTED
;
242 * Use the default local loopback address for the server...
245 cupsdSetEnv("CUPS_SERVER", "localhost");
248 cupsdSetEnv("CUPS_ENCRYPTION", encryptions
[LocalEncryption
]);
251 cupsdSetEnvf("IPP_PORT", "%d", LocalPort
);
254 * Resume listening for connections...
257 cupsdResumeListening();
262 * 'cupsdStopListening()' - Close all listening sockets...
266 cupsdStopListening(void)
268 cupsd_listener_t
*lis
; /* Current listening socket */
271 cupsdLogMessage(CUPSD_LOG_DEBUG2
,
272 "cupsdStopListening: closing all listen sockets.");
274 cupsdPauseListening();
276 for (lis
= (cupsd_listener_t
*)cupsArrayFirst(Listeners
);
278 lis
= (cupsd_listener_t
*)cupsArrayNext(Listeners
))
281 if (!lis
->on_demand
&& lis
->fd
!= -1)
283 httpAddrClose(&(lis
->address
), lis
->fd
);
290 httpAddrClose(&(lis
->address
), lis
->fd
);
293 #endif /* HAVE_ONDEMAND */