]>
git.ipfire.org Git - thirdparty/cups.git/blob - scheduler/listen.c
2 * "$Id: listen.c 5053 2006-02-02 18:14:38Z mike $"
4 * Server listening routines for the Common UNIX Printing System (CUPS)
7 * Copyright 1997-2006 by Easy Software Products, all rights reserved.
9 * These coded instructions, statements, and computer programs are the
10 * property of Easy Software Products and are protected by Federal
11 * copyright law. Distribution and use rights are outlined in the file
12 * "LICENSE.txt" which should have been included with this file. If this
13 * file is missing or damaged please contact Easy Software Products
16 * Attn: CUPS Licensing Information
17 * Easy Software Products
18 * 44141 Airport View Drive, Suite 204
19 * Hollywood, Maryland 20636 USA
21 * Voice: (301) 373-9600
22 * EMail: cups-info@cups.org
23 * WWW: http://www.cups.org
27 * cupsdPauseListening() - Clear input polling on all listening sockets...
28 * cupsdResumeListening() - Set input polling on all listening sockets...
29 * cupsdStartListening() - Create all listening sockets...
30 * cupsdStopListening() - Close all listening sockets...
34 * Include necessary headers...
41 * Make sure the IPV6_V6ONLY is defined on Linux - older versions of
42 * glibc don't define it even if the kernel supports it...
45 #if defined(__linux) && !defined(IPV6_V6ONLY)
46 # define IPV6_V6ONLY 26
47 #endif /* __linux && !IPV6_V6ONLY */
51 * 'cupsdPauseListening()' - Clear input polling on all listening sockets...
55 cupsdPauseListening(void)
57 int i
; /* Looping var */
58 cupsd_listener_t
*lis
; /* Current listening socket */
64 if (NumClients
== MaxClients
)
65 cupsdLogMessage(CUPSD_LOG_WARN
,
66 "Max clients reached, holding new connections...");
68 cupsdLogMessage(CUPSD_LOG_DEBUG
, "cupsdPauseListening: Clearing input bits...");
70 for (i
= NumListeners
, lis
= Listeners
; i
> 0; i
--, lis
++)
73 cupsdLogMessage(CUPSD_LOG_DEBUG2
,
74 "cupsdPauseListening: Removing fd %d from InputSet...",
77 FD_CLR(lis
->fd
, InputSet
);
83 * 'cupsdResumeListening()' - Set input polling on all listening sockets...
87 cupsdResumeListening(void)
89 int i
; /* Looping var */
90 cupsd_listener_t
*lis
; /* Current listening socket */
96 if (NumClients
>= (MaxClients
- 1))
97 cupsdLogMessage(CUPSD_LOG_WARN
, "Resuming new connection processing...");
99 cupsdLogMessage(CUPSD_LOG_DEBUG
, "cupsdResumeListening: Setting input bits...");
101 for (i
= NumListeners
, lis
= Listeners
; i
> 0; i
--, lis
++)
104 cupsdLogMessage(CUPSD_LOG_DEBUG2
,
105 "cupsdResumeListening: Adding fd %d to InputSet...",
107 FD_SET(lis
->fd
, InputSet
);
113 * 'cupsdStartListening()' - Create all listening sockets...
117 cupsdStartListening(void)
119 int status
; /* Bind result */
120 int i
, /* Looping var */
122 val
; /* Parameter value */
123 cupsd_listener_t
*lis
; /* Current listening socket */
124 char s
[256]; /* String addresss */
125 const char *have_domain
; /* Have a domain socket? */
126 static const char * const encryptions
[] =
127 { /* Encryption values */
135 cupsdLogMessage(CUPSD_LOG_DEBUG
, "cupsdStartListening: NumListeners=%d",
139 * Get the server's IP address...
143 httpAddrFreeList(ServerAddrs
);
145 if ((ServerAddrs
= httpAddrGetList(ServerName
, AF_UNSPEC
, NULL
)) == NULL
)
146 cupsdLogMessage(CUPSD_LOG_ERROR
,
147 "cupsdStartListening: Unable to find IP address for "
148 "server name \"%s\"!\n", ServerName
);
151 * Setup socket listeners...
154 for (i
= NumListeners
, lis
= Listeners
, LocalPort
= 0, have_domain
= NULL
;
157 httpAddrString(&(lis
->address
), s
, sizeof(s
));
160 if (lis
->address
.addr
.sa_family
== AF_INET6
)
161 p
= ntohs(lis
->address
.ipv6
.sin6_port
);
163 #endif /* AF_INET6 */
165 if (lis
->address
.addr
.sa_family
== AF_LOCAL
)
168 #endif /* AF_LOCAL */
169 p
= ntohs(lis
->address
.ipv4
.sin_port
);
172 * If needed, create a socket for listening...
178 * Create a socket for listening...
181 lis
->fd
= socket(lis
->address
.addr
.sa_family
, SOCK_STREAM
, 0);
185 cupsdLogMessage(CUPSD_LOG_ERROR
,
186 "cupsdStartListening: Unable to open listen socket for address %s:%d - %s.",
187 s
, p
, strerror(errno
));
192 * Set things up to reuse the local address for this port.
197 setsockopt(lis
->fd
, SOL_SOCKET
, SO_REUSEADDR
, (char *)&val
, sizeof(val
));
199 setsockopt(lis
->fd
, SOL_SOCKET
, SO_REUSEADDR
, &val
, sizeof(val
));
203 * Bind to the port we found...
207 if (lis
->address
.addr
.sa_family
== AF_INET6
)
211 * Accept only IPv6 connections on this socket, to avoid
212 * potential security issues and to make all platforms behave
218 setsockopt(lis
->fd
, IPPROTO_IPV6
, IPV6_V6ONLY
, (char *)&val
, sizeof(val
));
220 setsockopt(lis
->fd
, IPPROTO_IPV6
, IPV6_V6ONLY
, &val
, sizeof(val
));
222 # endif /* IPV6_V6ONLY */
224 status
= bind(lis
->fd
, (struct sockaddr
*)&(lis
->address
),
225 httpAddrLength(&(lis
->address
)));
228 #endif /* AF_INET6 */
230 if (lis
->address
.addr
.sa_family
== AF_LOCAL
)
232 mode_t mask
; /* Umask setting */
236 * Remove any existing domain socket file...
239 unlink(lis
->address
.un
.sun_path
);
242 * Save the curent umask and set it to 0...
248 * Bind the domain socket...
251 status
= bind(lis
->fd
, (struct sockaddr
*)&(lis
->address
),
252 httpAddrLength(&(lis
->address
)));
255 * Restore the umask...
261 #endif /* AF_LOCAL */
262 status
= bind(lis
->fd
, (struct sockaddr
*)&(lis
->address
),
263 sizeof(lis
->address
.ipv4
));
267 cupsdLogMessage(CUPSD_LOG_ERROR
,
268 "cupsdStartListening: Unable to bind socket for address %s:%d - %s.",
269 s
, p
, strerror(errno
));
276 * Listen for new clients.
279 if (listen(lis
->fd
, ListenBackLog
) < 0)
281 cupsdLogMessage(CUPSD_LOG_ERROR
,
282 "cupsdStartListening: Unable to listen for clients on address %s:%d - %s.",
283 s
, p
, strerror(errno
));
288 fcntl(lis
->fd
, F_SETFD
, fcntl(lis
->fd
, F_GETFD
) | FD_CLOEXEC
);
292 cupsdLogMessage(CUPSD_LOG_INFO
,
293 "cupsdStartListening: Listening to %s:%d on fd %d...",
297 cupsdLogMessage(CUPSD_LOG_INFO
,
298 "cupsdStartListening: Listening to %s on fd %d...",
301 if (chmod(s
, 0140777))
302 cupsdLogMessage(CUPSD_LOG_ERROR
,
303 "cupsdStartListening: Unable to change permisssions on "
304 "domain socket \"%s\" - %s", s
, strerror(errno
));
308 * Save the first port that is bound to the local loopback or
312 if (!LocalPort
&& p
> 0 &&
313 (httpAddrLocalhost(&(lis
->address
)) ||
314 httpAddrAny(&(lis
->address
))))
317 LocalEncryption
= lis
->encryption
;
321 if (lis
->address
.addr
.sa_family
== AF_LOCAL
&& !have_domain
)
322 have_domain
= lis
->address
.un
.sun_path
;
323 #endif /* AF_LOCAL */
327 * Make sure that we are listening on localhost!
330 if (!LocalPort
&& !have_domain
)
332 cupsdLogMessage(CUPSD_LOG_EMERG
,
333 "No Listen or Port lines were found to allow access via localhost!");
339 cupsdEndProcess(getpid(), 0);
343 * Set the CUPS_SERVER, IPP_PORT, and CUPS_ENCRYPTION variables based on
350 * Use domain sockets for the local connection...
353 cupsdSetEnv("CUPS_SERVER", have_domain
);
358 * Use the default local loopback address for the server...
361 cupsdSetEnv("CUPS_SERVER", "localhost");
364 cupsdSetEnv("CUPS_ENCRYPTION", encryptions
[LocalEncryption
]);
365 cupsdSetEnvf("IPP_PORT", "%d", LocalPort
);
368 * Resume listening for connections...
371 cupsdResumeListening();
376 * 'cupsdStopListening()' - Close all listening sockets...
380 cupsdStopListening(void)
382 int i
; /* Looping var */
383 cupsd_listener_t
*lis
; /* Current listening socket */
386 cupsdLogMessage(CUPSD_LOG_DEBUG
,
387 "cupsdStopListening: closing all listen sockets.");
389 cupsdPauseListening();
391 for (i
= NumListeners
, lis
= Listeners
; i
> 0; i
--, lis
++)
396 closesocket(lis
->fd
);
403 * Remove domain sockets...
406 # ifdef HAVE_LAUNCH_H
407 if (lis
->address
.addr
.sa_family
== AF_LOCAL
&& !Launchd
)
409 if (lis
->address
.addr
.sa_family
== AF_LOCAL
)
410 # endif /* HAVE_LAUNCH_H */
411 unlink(lis
->address
.un
.sun_path
);
412 #endif /* AF_LOCAL */
419 * End of "$Id: listen.c 5053 2006-02-02 18:14:38Z mike $".