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 * 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
11 * file is missing or damaged, see the license at "http://www.cups.org/".
15 * Include necessary headers...
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...
26 #if defined(__linux) && !defined(IPV6_V6ONLY)
27 # define IPV6_V6ONLY 26
28 #endif /* __linux && !IPV6_V6ONLY */
32 * 'cupsdDeleteAllListeners()' - Delete all listeners.
36 cupsdDeleteAllListeners(void)
38 cupsd_listener_t
*lis
; /* Current listening socket */
41 for (lis
= (cupsd_listener_t
*)cupsArrayFirst(Listeners
);
43 lis
= (cupsd_listener_t
*)cupsArrayNext(Listeners
))
46 #endif /* HAVE_ONDEMAND */
48 cupsArrayRemove(Listeners
, lis
);
52 if (cupsArrayCount(Listeners
) == 0)
54 cupsArrayDelete(Listeners
);
61 * 'cupsdPauseListening()' - Clear input polling on all listening sockets...
65 cupsdPauseListening(void)
67 cupsd_listener_t
*lis
; /* Current listening socket */
70 if (cupsArrayCount(Listeners
) < 1)
73 if (cupsArrayCount(Clients
) == MaxClients
)
74 cupsdLogMessage(CUPSD_LOG_WARN
,
75 "Max clients reached, holding new connections...");
76 else if (errno
== ENFILE
|| errno
== EMFILE
)
77 cupsdLogMessage(CUPSD_LOG_WARN
,
78 "Too many open files, holding new connections for "
81 cupsdLogMessage(CUPSD_LOG_DEBUG2
, "cupsdPauseListening: Clearing input bits...");
83 for (lis
= (cupsd_listener_t
*)cupsArrayFirst(Listeners
);
85 lis
= (cupsd_listener_t
*)cupsArrayNext(Listeners
))
86 cupsdRemoveSelect(lis
->fd
);
88 ListeningPaused
= time(NULL
) + 30;
93 * 'cupsdResumeListening()' - Set input polling on all listening sockets...
97 cupsdResumeListening(void)
99 cupsd_listener_t
*lis
; /* Current listening socket */
102 if (cupsArrayCount(Listeners
) < 1)
105 cupsdLogMessage(CUPSD_LOG_INFO
, "Resuming new connection processing...");
106 cupsdLogMessage(CUPSD_LOG_DEBUG2
,
107 "cupsdResumeListening: Setting input bits...");
109 for (lis
= (cupsd_listener_t
*)cupsArrayFirst(Listeners
);
111 lis
= (cupsd_listener_t
*)cupsArrayNext(Listeners
))
112 cupsdAddSelect(lis
->fd
, (cupsd_selfunc_t
)cupsdAcceptClient
, NULL
, lis
);
119 * 'cupsdStartListening()' - Create all listening sockets...
123 cupsdStartListening(void)
125 int p
; /* Port number */
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 */
138 cupsdLogMessage(CUPSD_LOG_DEBUG2
, "cupsdStartListening: %d Listeners",
139 cupsArrayCount(Listeners
));
142 * Setup socket listeners...
145 for (lis
= (cupsd_listener_t
*)cupsArrayFirst(Listeners
), LocalPort
= 0,
148 lis
= (cupsd_listener_t
*)cupsArrayNext(Listeners
))
150 httpAddrString(&(lis
->address
), s
, sizeof(s
));
151 p
= httpAddrPort(&(lis
->address
));
154 * If needed, create a socket for listening...
160 * Create a socket for listening...
163 lis
->fd
= httpAddrListen(&(lis
->address
), p
);
167 cupsdLogMessage(CUPSD_LOG_ERROR
,
168 "Unable to open listen socket for address %s:%d - %s.",
169 s
, p
, strerror(errno
));
173 * IPv6 is often disabled while DNS returns IPv6 addresses...
176 if (lis
->address
.addr
.sa_family
!= AF_INET6
&&
177 (FatalErrors
& CUPSD_FATAL_LISTEN
))
178 cupsdEndProcess(getpid(), 0);
180 if (FatalErrors
& CUPSD_FATAL_LISTEN
)
181 cupsdEndProcess(getpid(), 0);
182 #endif /* AF_INET6 */
189 cupsdLogMessage(CUPSD_LOG_INFO
, "Listening to %s:%d on fd %d...",
192 cupsdLogMessage(CUPSD_LOG_INFO
, "Listening to %s on fd %d...",
196 * Save the first port that is bound to the local loopback or
200 if ((!LocalPort
|| LocalEncryption
== HTTP_ENCRYPT_ALWAYS
) && p
> 0 &&
201 (httpAddrLocalhost(&(lis
->address
)) ||
202 httpAddrAny(&(lis
->address
))))
205 LocalEncryption
= lis
->encryption
;
209 if (lis
->address
.addr
.sa_family
== AF_LOCAL
&& !have_domain
)
210 have_domain
= lis
->address
.un
.sun_path
;
211 #endif /* AF_LOCAL */
215 * Make sure that we are listening on localhost!
218 if (!LocalPort
&& !have_domain
)
220 cupsdLogMessage(CUPSD_LOG_EMERG
,
221 "No Listen or Port lines were found to allow access via "
224 if (FatalErrors
& (CUPSD_FATAL_CONFIG
| CUPSD_FATAL_LISTEN
))
225 cupsdEndProcess(getpid(), 0);
229 * Set the CUPS_SERVER, IPP_PORT, and CUPS_ENCRYPTION variables based on
236 * Use domain sockets for the local connection...
239 cupsdSetEnv("CUPS_SERVER", have_domain
);
241 LocalEncryption
= HTTP_ENCRYPT_IF_REQUESTED
;
246 * Use the default local loopback address for the server...
249 cupsdSetEnv("CUPS_SERVER", "localhost");
252 cupsdSetEnv("CUPS_ENCRYPTION", encryptions
[LocalEncryption
]);
255 cupsdSetEnvf("IPP_PORT", "%d", LocalPort
);
258 * Resume listening for connections...
261 cupsdResumeListening();
266 * 'cupsdStopListening()' - Close all listening sockets...
270 cupsdStopListening(void)
272 cupsd_listener_t
*lis
; /* Current listening socket */
275 cupsdLogMessage(CUPSD_LOG_DEBUG2
,
276 "cupsdStopListening: closing all listen sockets.");
278 cupsdPauseListening();
280 for (lis
= (cupsd_listener_t
*)cupsArrayFirst(Listeners
);
282 lis
= (cupsd_listener_t
*)cupsArrayNext(Listeners
))
285 if (!lis
->on_demand
&& lis
->fd
!= -1)
287 httpAddrClose(&(lis
->address
), lis
->fd
);
294 httpAddrClose(&(lis
->address
), lis
->fd
);
297 #endif /* HAVE_ONDEMAND */