]>
Commit | Line | Data |
---|---|---|
e82646f2 | 1 | /* |
e673c4b4 | 2 | * "$Id: listen.c,v 1.9.2.12 2004/02/24 21:36:59 mike Exp $" |
e82646f2 | 3 | * |
4 | * Server listening routines for the Common UNIX Printing System (CUPS) | |
5 | * scheduler. | |
6 | * | |
1d9595ab | 7 | * Copyright 1997-2003 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 |
e82646f2 | 19 | * Hollywood, Maryland 20636-3111 USA |
20 | * | |
21 | * Voice: (301) 373-9603 | |
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 | { | |
104 | int i, /* Looping var */ | |
105 | val; /* Parameter value */ | |
106 | listener_t *lis; /* Current listening socket */ | |
2bdd1992 | 107 | struct hostent *host; /* Host entry for server address */ |
99de6da0 | 108 | char s[256]; /* String addresss */ |
e82646f2 | 109 | |
110 | ||
676cde07 | 111 | LogMessage(L_DEBUG, "StartListening: NumListeners=%d", NumListeners); |
d236cb49 | 112 | |
2bdd1992 | 113 | /* |
114 | * Get the server's IP address... | |
115 | */ | |
116 | ||
117 | memset(&ServerAddr, 0, sizeof(ServerAddr)); | |
118 | ||
753453e4 | 119 | if ((host = httpGetHostByName(ServerName)) != NULL) |
2bdd1992 | 120 | { |
121 | /* | |
122 | * Found the server's address! | |
123 | */ | |
124 | ||
99de6da0 | 125 | httpAddrLoad(host, 0, 0, &ServerAddr); |
2bdd1992 | 126 | } |
127 | else | |
128 | { | |
129 | /* | |
130 | * Didn't find it! Use an address of 0... | |
131 | */ | |
132 | ||
7e3ba0af | 133 | LogMessage(L_ERROR, "StartListening: Unable to find IP address for server name \"%s\" - %s\n", |
134 | ServerName, hstrerror(h_errno)); | |
2bdd1992 | 135 | |
99de6da0 | 136 | ServerAddr.ipv4.sin_family = AF_INET; |
2bdd1992 | 137 | } |
138 | ||
e82646f2 | 139 | /* |
140 | * Setup socket listeners... | |
141 | */ | |
142 | ||
e673c4b4 | 143 | for (i = NumListeners, lis = Listeners, LocalPort = 0; i > 0; i --, lis ++) |
e82646f2 | 144 | { |
99de6da0 | 145 | httpAddrString(&(lis->address), s, sizeof(s)); |
146 | ||
147 | #ifdef AF_INET6 | |
148 | if (lis->address.addr.sa_family == AF_INET6) | |
149 | LogMessage(L_DEBUG, "StartListening: address=%s port=%d (IPv6)", s, | |
150 | ntohs(lis->address.ipv6.sin6_port)); | |
151 | else | |
152 | #endif /* AF_INET6 */ | |
153 | LogMessage(L_DEBUG, "StartListening: address=%s port=%d", s, | |
154 | ntohs(lis->address.ipv4.sin_port)); | |
155 | ||
0f71c41e | 156 | /* |
157 | * Save the first port that is bound to the local loopback or | |
158 | * "any" address... | |
159 | */ | |
160 | ||
e673c4b4 | 161 | if (!LocalPort && |
162 | (httpAddrLocalhost(&(lis->address)) || | |
163 | httpAddrAny(&(lis->address)))) | |
0f71c41e | 164 | { |
165 | #ifdef AF_INET6 | |
166 | if (lis->address.addr.sa_family == AF_INET6) | |
167 | LocalPort = ntohs(lis->address.ipv6.sin6_port); | |
168 | else | |
169 | #endif /* AF_INET6 */ | |
170 | LocalPort = ntohs(lis->address.ipv4.sin_port); | |
171 | } | |
172 | ||
173 | /* | |
174 | * Create a socket for listening... | |
175 | */ | |
176 | ||
99de6da0 | 177 | if ((lis->fd = socket(lis->address.addr.sa_family, SOCK_STREAM, 0)) == -1) |
e82646f2 | 178 | { |
676cde07 | 179 | LogMessage(L_ERROR, "StartListening: Unable to open listen socket - %s.", |
e82646f2 | 180 | strerror(errno)); |
181 | exit(errno); | |
182 | } | |
183 | ||
18fe941f | 184 | LogMessage(L_DEBUG2, "StartListening: fd=%d", lis->fd); |
185 | ||
e82646f2 | 186 | fcntl(lis->fd, F_SETFD, fcntl(lis->fd, F_GETFD) | FD_CLOEXEC); |
187 | ||
188 | /* | |
189 | * Set things up to reuse the local address for this port. | |
190 | */ | |
191 | ||
192 | val = 1; | |
193 | #ifdef __sun | |
194 | setsockopt(lis->fd, SOL_SOCKET, SO_REUSEADDR, (char *)&val, sizeof(val)); | |
195 | #else | |
196 | setsockopt(lis->fd, SOL_SOCKET, SO_REUSEADDR, &val, sizeof(val)); | |
197 | #endif /* __sun */ | |
198 | ||
199 | /* | |
200 | * Bind to the port we found... | |
201 | */ | |
202 | ||
a09840c5 | 203 | #ifdef AF_INET6 |
204 | if (bind(lis->fd, (struct sockaddr *)&(lis->address), | |
205 | lis->address.addr.sa_family == AF_INET ? | |
206 | sizeof(lis->address.ipv4) : | |
207 | sizeof(lis->address.ipv6)) < 0) | |
208 | #else | |
209 | if (bind(lis->fd, (struct sockaddr *)&(lis->address), | |
210 | sizeof(lis->address.ipv4)) < 0) | |
211 | #endif | |
e82646f2 | 212 | { |
99de6da0 | 213 | LogMessage(L_ERROR, "StartListening: Unable to bind socket - %s.", |
214 | strerror(errno)); | |
e82646f2 | 215 | exit(errno); |
216 | } | |
217 | ||
218 | /* | |
219 | * Listen for new clients. | |
220 | */ | |
221 | ||
27eba2dd | 222 | if (listen(lis->fd, ListenBackLog) < 0) |
e82646f2 | 223 | { |
676cde07 | 224 | LogMessage(L_ERROR, "StartListening: Unable to listen for clients - %s.", |
e82646f2 | 225 | strerror(errno)); |
226 | exit(errno); | |
227 | } | |
e82646f2 | 228 | } |
229 | ||
e673c4b4 | 230 | /* |
231 | * Make sure that we are listening on localhost! | |
232 | */ | |
233 | ||
234 | if (!LocalPort) | |
235 | { | |
236 | LogMessage(L_EMERG, "No Listen or Port lines were found to allow access via localhost!"); | |
237 | ||
238 | /* | |
239 | * Commit suicide... | |
240 | */ | |
241 | ||
242 | kill(getpid(), SIGTERM); | |
243 | } | |
244 | ||
d236cb49 | 245 | ResumeListening(); |
e82646f2 | 246 | } |
247 | ||
248 | ||
249 | /* | |
250 | * 'StopListening()' - Close all listening sockets... | |
251 | */ | |
252 | ||
253 | void | |
254 | StopListening(void) | |
255 | { | |
256 | int i; /* Looping var */ | |
257 | listener_t *lis; /* Current listening socket */ | |
258 | ||
259 | ||
676cde07 | 260 | LogMessage(L_DEBUG, "StopListening: closing all listen sockets."); |
d236cb49 | 261 | |
262 | PauseListening(); | |
263 | ||
e82646f2 | 264 | for (i = NumListeners, lis = Listeners; i > 0; i --, lis ++) |
c3026ddc | 265 | #ifdef WIN32 |
e82646f2 | 266 | closesocket(lis->fd); |
267 | #else | |
268 | close(lis->fd); | |
c3026ddc | 269 | #endif /* WIN32 */ |
e82646f2 | 270 | } |
271 | ||
272 | ||
273 | /* | |
e673c4b4 | 274 | * End of "$Id: listen.c,v 1.9.2.12 2004/02/24 21:36:59 mike Exp $". |
e82646f2 | 275 | */ |