Book a Demo!
CoCalc Logo Icon
StoreFeaturesDocsShareSupportNewsAboutPoliciesSign UpSign In
srohatgi01
GitHub Repository: srohatgi01/cups
Path: blob/master/scheduler/listen.c
1090 views
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
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
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
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
119
cupsdStartListening(void)
120
{
121
int p; /* Port number */
122
cupsd_listener_t *lis; /* Current listening socket */
123
char s[256]; /* String address */
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(errno == EAFNOSUPPORT ? CUPSD_LOG_INFO : 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
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
297