]>
Commit | Line | Data |
---|---|---|
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 | ||
44 | void | |
45 | PauseListening(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 | ||
73 | void | |
74 | ResumeListening(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 | ||
101 | void | |
102 | StartListening(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 | ||
295 | void | |
296 | StopListening(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 | */ |