]> git.ipfire.org Git - thirdparty/cups.git/blame - scheduler/listen.c
Update copyright notices, addresses, etc.
[thirdparty/cups.git] / scheduler / listen.c
CommitLineData
e82646f2 1/*
c9d3f842 2 * "$Id$"
e82646f2 3 *
4 * Server listening routines for the Common UNIX Printing System (CUPS)
5 * scheduler.
6 *
c9d3f842 7 * Copyright 1997-2005 by Easy Software Products, all rights reserved.
e82646f2 8 *
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
14 * at:
15 *
16 * Attn: CUPS Licensing Information
17 * Easy Software Products
8784b6a6 18 * 44141 Airport View Drive, Suite 204
8650fcf2 19 * Hollywood, Maryland 20636 USA
e82646f2 20 *
edfd3c3d 21 * Voice: (301) 373-9600
e82646f2 22 * EMail: cups-info@cups.org
23 * WWW: http://www.cups.org
24 *
25 * Contents:
26 *
d236cb49 27 * PauseListening() - Clear input polling on all listening sockets...
28 * ResumeListening() - Set input polling on all listening sockets...
29 * StartListening() - Create all listening sockets...
30 * StopListening() - Close all listening sockets...
e82646f2 31 */
32
33/*
34 * Include necessary headers...
35 */
36
37#include "cupsd.h"
38
39
d236cb49 40/*
41 * 'PauseListening()' - Clear input polling on all listening sockets...
42 */
43
44void
45PauseListening(void)
46{
47 int i; /* Looping var */
48 listener_t *lis; /* Current listening socket */
49
50
5073e3f8 51 if (NumListeners < 1 || !FD_ISSET(Listeners[0].fd, InputSet))
d236cb49 52 return;
53
676cde07 54 if (NumClients == MaxClients)
55 LogMessage(L_WARN, "Max clients reached, holding new connections...");
56
18fe941f 57 LogMessage(L_DEBUG, "PauseListening: Clearing input bits...");
d236cb49 58
59 for (i = NumListeners, lis = Listeners; i > 0; i --, lis ++)
18fe941f 60 {
61 LogMessage(L_DEBUG2, "PauseListening: Removing fd %d from InputSet...",
62 lis->fd);
63
f3bc1068 64 FD_CLR(lis->fd, InputSet);
18fe941f 65 }
d236cb49 66}
67
68
69/*
70 * 'ResumeListening()' - Set input polling on all listening sockets...
71 */
72
73void
74ResumeListening(void)
75{
76 int i; /* Looping var */
77 listener_t *lis; /* Current listening socket */
78
79
5073e3f8 80 if (NumListeners < 1 || FD_ISSET(Listeners[0].fd, InputSet))
d236cb49 81 return;
82
676cde07 83 if (NumClients >= (MaxClients - 1))
84 LogMessage(L_WARN, "Resuming new connection processing...");
85
18fe941f 86 LogMessage(L_DEBUG, "ResumeListening: Setting input bits...");
d236cb49 87
88 for (i = NumListeners, lis = Listeners; i > 0; i --, lis ++)
18fe941f 89 {
90 LogMessage(L_DEBUG2, "ResumeListening: Adding fd %d to InputSet...",
91 lis->fd);
f3bc1068 92 FD_SET(lis->fd, InputSet);
18fe941f 93 }
d236cb49 94}
95
96
e82646f2 97/*
98 * 'StartListening()' - Create all listening sockets...
99 */
100
101void
102StartListening(void)
103{
c6075312 104 int status; /* Bind result */
105 int i, /* Looping var */
106 p, /* Port number */
107 val; /* Parameter value */
108 listener_t *lis; /* Current listening socket */
109 struct hostent *host; /* Host entry for server address */
110 char s[256]; /* String addresss */
111 int have_domain; /* Have a domain socket */
e82646f2 112
113
676cde07 114 LogMessage(L_DEBUG, "StartListening: NumListeners=%d", NumListeners);
d236cb49 115
2bdd1992 116 /*
117 * Get the server's IP address...
118 */
119
120 memset(&ServerAddr, 0, sizeof(ServerAddr));
121
753453e4 122 if ((host = httpGetHostByName(ServerName)) != NULL)
2bdd1992 123 {
124 /*
125 * Found the server's address!
126 */
127
99de6da0 128 httpAddrLoad(host, 0, 0, &ServerAddr);
2bdd1992 129 }
130 else
131 {
132 /*
133 * Didn't find it! Use an address of 0...
134 */
135
7e3ba0af 136 LogMessage(L_ERROR, "StartListening: Unable to find IP address for server name \"%s\" - %s\n",
137 ServerName, hstrerror(h_errno));
2bdd1992 138
99de6da0 139 ServerAddr.ipv4.sin_family = AF_INET;
2bdd1992 140 }
141
e82646f2 142 /*
143 * Setup socket listeners...
144 */
145
c6075312 146 for (i = NumListeners, lis = Listeners, LocalPort = 0, have_domain = 0;
147 i > 0; i --, lis ++)
e82646f2 148 {
99de6da0 149 httpAddrString(&(lis->address), s, sizeof(s));
150
151#ifdef AF_INET6
152 if (lis->address.addr.sa_family == AF_INET6)
11009aea 153 p = ntohs(lis->address.ipv6.sin6_port);
99de6da0 154 else
155#endif /* AF_INET6 */
c6075312 156#ifdef AF_LOCAL
157 if (lis->address.addr.sa_family == AF_LOCAL)
158 {
159 have_domain = 1;
160 p = 0;
161 }
162 else
163#endif /* AF_LOCAL */
11009aea 164 p = ntohs(lis->address.ipv4.sin_port);
165
166 LogMessage(L_DEBUG, "StartListening: address=%s port=%d", s, p);
99de6da0 167
0f71c41e 168 /*
169 * Save the first port that is bound to the local loopback or
170 * "any" address...
171 */
172
c6075312 173 if (!LocalPort && p > 0 &&
e673c4b4 174 (httpAddrLocalhost(&(lis->address)) ||
175 httpAddrAny(&(lis->address))))
41d6188e 176 {
177 LocalPort = p;
178 LocalEncryption = lis->encryption;
179 }
0f71c41e 180
181 /*
182 * Create a socket for listening...
183 */
184
99de6da0 185 if ((lis->fd = socket(lis->address.addr.sa_family, SOCK_STREAM, 0)) == -1)
e82646f2 186 {
11009aea 187 LogMessage(L_ERROR, "StartListening: Unable to open listen socket for address %s:%d - %s.",
188 s, p, strerror(errno));
e82646f2 189 exit(errno);
190 }
191
18fe941f 192 LogMessage(L_DEBUG2, "StartListening: fd=%d", lis->fd);
193
e82646f2 194 fcntl(lis->fd, F_SETFD, fcntl(lis->fd, F_GETFD) | FD_CLOEXEC);
195
196 /*
197 * Set things up to reuse the local address for this port.
198 */
199
200 val = 1;
201#ifdef __sun
202 setsockopt(lis->fd, SOL_SOCKET, SO_REUSEADDR, (char *)&val, sizeof(val));
203#else
204 setsockopt(lis->fd, SOL_SOCKET, SO_REUSEADDR, &val, sizeof(val));
205#endif /* __sun */
206
207 /*
208 * Bind to the port we found...
209 */
210
a09840c5 211#ifdef AF_INET6
c6075312 212 if (lis->address.addr.sa_family == AF_INET6)
213 status = bind(lis->fd, (struct sockaddr *)&(lis->address),
214 sizeof(lis->address.ipv6));
215 else
216#endif /* AF_INET6 */
217#ifdef AF_LOCAL
218 if (lis->address.addr.sa_family == AF_LOCAL)
219 {
220 mode_t mask; /* Umask setting */
221
222
223 /*
224 * Remove any existing domain socket file...
225 */
226
227 unlink(lis->address.un.sun_path);
228
229 /*
230 * Save the curent umask and set it to 0...
231 */
232
233 mask = umask(0);
234
235 /*
236 * Bind the domain socket...
237 */
238
239 status = bind(lis->fd, (struct sockaddr *)&(lis->address),
240 SUN_LEN(&(lis->address.un)));
241
242 /*
243 * Restore the umask...
244 */
245
246 umask(mask);
247 }
248 else
249#endif /* AF_LOCAL */
250 status = bind(lis->fd, (struct sockaddr *)&(lis->address),
251 sizeof(lis->address.ipv4));
252
253 if (status < 0)
e82646f2 254 {
11009aea 255 LogMessage(L_ERROR, "StartListening: Unable to bind socket for address %s:%d - %s.",
256 s, p, strerror(errno));
e82646f2 257 exit(errno);
258 }
259
260 /*
261 * Listen for new clients.
262 */
263
27eba2dd 264 if (listen(lis->fd, ListenBackLog) < 0)
e82646f2 265 {
11009aea 266 LogMessage(L_ERROR, "StartListening: Unable to listen for clients on address %s:%d - %s.",
267 s, p, strerror(errno));
e82646f2 268 exit(errno);
269 }
e82646f2 270 }
271
e673c4b4 272 /*
273 * Make sure that we are listening on localhost!
274 */
275
c6075312 276 if (!LocalPort && !have_domain)
e673c4b4 277 {
278 LogMessage(L_EMERG, "No Listen or Port lines were found to allow access via localhost!");
279
280 /*
281 * Commit suicide...
282 */
283
284 kill(getpid(), SIGTERM);
285 }
286
d236cb49 287 ResumeListening();
e82646f2 288}
289
290
291/*
292 * 'StopListening()' - Close all listening sockets...
293 */
294
295void
296StopListening(void)
297{
298 int i; /* Looping var */
299 listener_t *lis; /* Current listening socket */
300
301
676cde07 302 LogMessage(L_DEBUG, "StopListening: closing all listen sockets.");
d236cb49 303
304 PauseListening();
305
e82646f2 306 for (i = NumListeners, lis = Listeners; i > 0; i --, lis ++)
c6075312 307 {
c3026ddc 308#ifdef WIN32
e82646f2 309 closesocket(lis->fd);
310#else
311 close(lis->fd);
c3026ddc 312#endif /* WIN32 */
c6075312 313
314#ifdef AF_LOCAL
315 /*
316 * Remove domain sockets...
317 */
318
319 if (lis->address.addr.sa_family == AF_LOCAL)
320 unlink(lis->address.un.sun_path);
321#endif /* AF_LOCAL */
322 }
e82646f2 323}
324
325
326/*
c9d3f842 327 * End of "$Id$".
e82646f2 328 */