]> git.ipfire.org Git - thirdparty/glibc.git/blame - nscd/connections.c
Update.
[thirdparty/glibc.git] / nscd / connections.c
CommitLineData
d67281a7
UD
1/* Copyright (c) 1998 Free Software Foundation, Inc.
2 This file is part of the GNU C Library.
3 Contributed by Thorsten Kukuk <kukuk@vt.uni-paderborn.de>, 1998.
4
5 The GNU C Library is free software; you can redistribute it and/or
6 modify it under the terms of the GNU Library General Public License as
7 published by the Free Software Foundation; either version 2 of the
8 License, or (at your option) any later version.
9
10 The GNU C Library is distributed in the hope that it will be useful,
11 but WITHOUT ANY WARRANTY; without even the implied warranty of
12 MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
13 Library General Public License for more details.
14
15 You should have received a copy of the GNU Library General Public
16 License along with the GNU C Library; see the file COPYING.LIB. If not,
17 write to the Free Software Foundation, Inc., 59 Temple Place - Suite 330,
18 Boston, MA 02111-1307, USA. */
19
20#include <errno.h>
21#include <error.h>
22#include <fcntl.h>
23#include <libintl.h>
24#include <locale.h>
25#include <pthread.h>
26#include <pwd.h>
27#include <stdio.h>
28#include <stdlib.h>
29#include <unistd.h>
a53bad16 30#include <sys/poll.h>
d67281a7
UD
31#include <sys/socket.h>
32#include <sys/stat.h>
33#include <sys/types.h>
34#include <sys/uio.h>
35#include <sys/un.h>
36
37#include "nscd.h"
38#include "dbg_log.h"
39
40/* Socket 0 in the array is named and exported into the file namespace
a53bad16
UD
41 as a connection point for clients. There's a one to one
42 correspondence between sock[i] and read_polls[i]. */
d67281a7
UD
43static int sock[MAX_NUM_CONNECTIONS];
44static int socks_active;
a53bad16 45static struct pollfd read_polls[MAX_NUM_CONNECTIONS];
d67281a7
UD
46static pthread_mutex_t sock_lock = PTHREAD_MUTEX_INITIALIZER;
47
48
49/* Cleanup. */
50void
51close_sockets (void)
52{
53 int i;
54
55 if (debug_flag)
56 dbg_log (_("close_sockets called"));
57
58 pthread_mutex_lock (&sock_lock);
59
60 /* Close sockets. */
61 for (i = 0; i < MAX_NUM_CONNECTIONS; ++i)
62 if (sock[i] != 0)
63 {
64 if (close (sock[i]))
65 dbg_log (_("socket [%d|%d] close: %s"), strerror (errno));
66
67 sock[i] = 0;
a53bad16 68 read_polls[i].fd = -1;
d67281a7
UD
69 --socks_active;
70 }
71
72 pthread_mutex_unlock (&sock_lock);
73}
74
75void
76close_socket (int conn)
77{
78 if (debug_flag > 2)
79 dbg_log (_("close socket (%d|%d)"), conn, sock[conn]);
80
81 pthread_mutex_lock (&sock_lock);
82
83 close (sock[conn]);
84 sock[conn] = 0;
a53bad16 85 read_polls[conn].fd = -1;
d67281a7
UD
86 --socks_active;
87
88 pthread_mutex_unlock (&sock_lock);
89}
90
a53bad16 91/* Local routine, assigns a socket to a new connection request. */
d67281a7
UD
92static void
93handle_new_connection (void)
94{
95 int i;
96
97 if (debug_flag > 2)
98 dbg_log (_("handle_new_connection"));
99
100 pthread_mutex_lock (&sock_lock);
101
102 if (socks_active < MAX_NUM_CONNECTIONS)
103 /* Find a free socket entry to use. */
104 for (i = 1; i < MAX_NUM_CONNECTIONS; ++i)
105 {
106 if (sock[i] == 0)
107 {
108 if ((sock[i] = accept (sock[0], NULL, NULL)) < 0)
109 {
110 dbg_log (_("socket accept: %s"), strerror (errno));
111 return;
112 }
113 ++socks_active;
a53bad16
UD
114 read_polls[i].fd = sock[i];
115 read_polls[i].events = POLLRDNORM;
d67281a7
UD
116 if (debug_flag > 2)
117 dbg_log (_("handle_new_connection used socket %d|%d"), i,
118 sock[i]);
119 break;
120 }
121 }
122 else
123 {
124 int black_widow_sock;
125 dbg_log (_("Supported number of simultainious connections exceeded"));
126 dbg_log (_("Ignoring client connect request"));
127 /* There has to be a better way to ignore a connection request,..
128 when I get my hands on a sockets wiz I'll modify this. */
129 black_widow_sock = accept (sock[0], NULL, NULL);
130 close (black_widow_sock);
131 }
132 pthread_mutex_unlock (&sock_lock);
133}
134
a53bad16 135/* Local routine, reads a request off a socket indicated by read_polls. */
d67281a7 136static int
a53bad16 137handle_new_request (int **connp, request_header **reqp, char **key)
d67281a7
UD
138{
139 ssize_t nbytes;
140 int i;
141
142 if (debug_flag)
143 dbg_log ("handle_new_request");
144
145 /* Find the descriptor. */
146 for (i = 1; i < MAX_NUM_CONNECTIONS; ++i)
a53bad16 147 if (read_polls[i].revents & (POLLRDNORM|POLLERR))
d67281a7
UD
148 break;
149
150 if (debug_flag > 2)
151 dbg_log (_("handle_new_request uses socket %d"), i);
152
153 /* Read from it. */
154 nbytes = read (sock[i], *reqp, sizeof (request_header));
155 if (nbytes != sizeof (request_header))
156 {
157 /* Handle non-data read cases. */
158 if (nbytes == 0)
159 {
160 /* Close socket down. */
161 if (debug_flag > 2)
162 dbg_log (_("Real close socket %d|%d"), i, sock[i]);
163
164 pthread_mutex_lock (&sock_lock);
a53bad16 165 read_polls[i].fd = -1;
d67281a7
UD
166 close (sock[i]);
167 sock[i] = 0;
168 --socks_active;
169 pthread_mutex_unlock (&sock_lock);
170 }
171 else
172 if (nbytes < 0)
173 {
174 dbg_log (_("Read(%d|%d) error on get request: %s"),
175 i, sock[i], strerror (errno));
176 exit (1);
177 }
178 else
179 dbg_log (_("Read, data < request buf size, ignoring data"));
180
181 return -1;
182 }
183 else
184 {
185 *key = malloc ((*reqp)->key_len + 1);
186 /* Read the key from it */
187 nbytes = read (sock[i], *key, (*reqp)->key_len);
188 if (nbytes != (*reqp)->key_len)
189 {
190 /* Handle non-data read cases. */
191 if (nbytes == 0)
192 {
193 /* Close socket down. */
194 if (debug_flag > 2)
195 dbg_log (_("Real close socket %d|%d"), i, sock[i]);
196
197 pthread_mutex_lock (&sock_lock);
a53bad16 198 read_polls[i].fd = -1;
d67281a7
UD
199 close (sock[i]);
200 sock[i] = 0;
201 --socks_active;
202 pthread_mutex_unlock (&sock_lock);
203 }
204 else
205 if (nbytes < 0)
206 {
207 perror (_("Read() error on get request"));
208 return 0;
209 }
210 else
211 fputs (_("Read, data < request buf size, ignoring data"),
212 stderr);
213
214 free (*key);
215 return -1;
216 }
217 else
218 {
219 /* Ok, have a live one, A real data req buf has been obtained. */
220 (*key)[(*reqp)->key_len] = '\0';
221 **connp = i;
222 return 0;
223 }
224 }
225}
226
227void
228get_request (int *conn, request_header *req, char **key)
229{
a53bad16
UD
230 int done = 0;
231 int nr;
d67281a7
UD
232
233 if (debug_flag)
234 dbg_log ("get_request");
235
236 /* loop, processing new connection requests until a client buffer
237 is read in on an existing connection. */
238 while (!done)
239 {
a53bad16
UD
240 /* Poll active connections. */
241 nr = poll (read_polls, MAX_NUM_CONNECTIONS, -1);
d67281a7
UD
242 if (nr <= 0)
243 {
a53bad16 244 perror (_("Poll new reads"));
d67281a7
UD
245 exit (1);
246 }
a53bad16 247 if (read_polls[0].revents & (POLLRDNORM|POLLERR))
d67281a7
UD
248 /* Handle the case of a new connection request on the named socket. */
249 handle_new_connection ();
250 else
251 {
252 /* Read data from client specific descriptor. */
a53bad16
UD
253 if (handle_new_request (&conn, &req, key) == 0)
254 done = 1;
d67281a7
UD
255 }
256 } /* While not_done. */
257}
258
259void
260init_sockets (void)
261{
262 struct sockaddr_un sock_addr;
a53bad16 263 int i;
d67281a7
UD
264
265 /* Initialize the connections db. */
266 socks_active = 0;
a53bad16
UD
267
268 /* Initialize the poll array. */
269 for (i = 0; i < MAX_NUM_CONNECTIONS; i++)
270 read_polls[i].fd = -1;
d67281a7
UD
271
272 /* Create the socket. */
273 sock[0] = socket (AF_UNIX, SOCK_STREAM, 0);
274 if (sock[0] < 0)
275 {
276 perror (_("cannot create socket"));
277 exit (1);
278 }
279 /* Bind a name to the socket. */
280 sock_addr.sun_family = AF_UNIX;
281 strcpy (sock_addr.sun_path, _PATH_NSCDSOCKET);
282 if (bind (sock[0], (struct sockaddr *) &sock_addr, sizeof (sock_addr)) < 0)
283 {
284 dbg_log ("%s: %s", _PATH_NSCDSOCKET, strerror (errno));
285 exit (1);
286 }
287 /* Set permissions for the socket. */
288 chmod (_PATH_NSCDSOCKET, 0666);
289
290 /* Set the socket up to accept connections. */
291 if (listen (sock[0], MAX_NUM_CONNECTIONS) < 0)
292 {
293 perror (_("cannot enable socket to accept connections"));
294 exit (1);
295 }
296
297 /* Add the socket to the server's set of active sockets. */
a53bad16
UD
298 read_polls[0].fd = sock[0];
299 read_polls[0].events = POLLRDNORM;
d67281a7
UD
300 ++socks_active;
301}
302
303void
304pw_send_answer (int conn, struct passwd *pwd)
305{
306 pw_response_header resp;
307
308 resp.version = NSCD_VERSION;
309 if (pwd != NULL)
310 {
311 resp.found = 1;
312 resp.pw_name_len = strlen (pwd->pw_name);
313 resp.pw_passwd_len = strlen (pwd->pw_passwd);
314 resp.pw_uid = pwd->pw_uid;
315 resp.pw_gid = pwd->pw_gid;
316 resp.pw_gecos_len = strlen (pwd->pw_gecos);
317 resp.pw_dir_len = strlen (pwd->pw_dir);
318 resp.pw_shell_len = strlen (pwd->pw_shell);
319 }
320 else
321 {
322 resp.found = 0;
323 resp.pw_name_len = 0;
324 resp.pw_passwd_len = 0;
325 resp.pw_uid = -1;
326 resp.pw_gid = -1;
327 resp.pw_gecos_len = 0;
328 resp.pw_dir_len = 0;
329 resp.pw_shell_len = 0;
330 }
331 if (sock[conn] == 0)
332 {
333 dbg_log (_("bad connection id on send response [%d|%d]"),
334 conn, sock[conn]);
335 return;
336 }
337
338 /* Send response header. */
339 if (write (sock[conn], &resp, sizeof (pw_response_header)) !=
340 sizeof (pw_response_header))
341 {
342 dbg_log (_("write incomplete on send response: %s"), strerror (errno));
343 return;
344 }
345
346 if (resp.found)
347 {
348 struct iovec vec[5];
349
350 /* Send pw_name. */
351 vec[0].iov_base = pwd->pw_name;
352 vec[0].iov_len = resp.pw_name_len;
353 /* Send pw_passwd. */
354 vec[1].iov_base = pwd->pw_passwd;
355 vec[1].iov_len = resp.pw_passwd_len;
356 /* Send pw_gecos. */
357 vec[2].iov_base = pwd->pw_gecos;
358 vec[2].iov_len = resp.pw_gecos_len;
359 /* Send pw_dir. */
360 vec[3].iov_base = pwd->pw_dir;
361 vec[3].iov_len = resp.pw_dir_len;
362 /* Send pw_shell. */
363 vec[4].iov_base = pwd->pw_shell;
364 vec[4].iov_len = resp.pw_shell_len;
365
366 if (writev (sock[conn], vec, 5) != (resp.pw_name_len + resp.pw_passwd_len
367 + resp.pw_gecos_len + resp.pw_dir_len
368 + resp.pw_shell_len))
369 dbg_log (_("write incomplete on send passwd answer: %s"),
370 strerror (errno));
371 }
372}
373
374void
375pw_send_disabled (int conn)
376{
377 pw_response_header resp;
378
379 resp.version = NSCD_VERSION;
380 resp.found = -1;
381 resp.pw_name_len = 0;
382 resp.pw_passwd_len = 0;
383 resp.pw_uid = -1;
384 resp.pw_gid = -1;
385 resp.pw_gecos_len = 0;
386 resp.pw_dir_len = 0;
387 resp.pw_shell_len = 0;
388
389 if (sock[conn] == 0)
390 {
14e9dd67 391 dbg_log (_("bad connection id on send response [%d|%d]"),
d67281a7
UD
392 conn, sock[conn]);
393 return;
394 }
395
396 /* Send response header. */
397 if (write (sock[conn], &resp, sizeof (pw_response_header))
398 != sizeof (pw_response_header))
399 dbg_log (_("write incomplete on send response: %s"), strerror (errno));
400}
401
402void
403gr_send_answer (int conn, struct group *grp)
404{
405 gr_response_header resp;
406
407 resp.version = NSCD_VERSION;
408 if (grp != NULL)
409 {
410 resp.found = 1;
411 resp.gr_name_len = strlen (grp->gr_name);
412 resp.gr_passwd_len = strlen (grp->gr_passwd);
413 resp.gr_gid = grp->gr_gid;
414 resp.gr_mem_len = 0;
415 while (grp->gr_mem[resp.gr_mem_len])
416 ++resp.gr_mem_len;
417 }
418 else
419 {
420 resp.found = 0;
421 resp.gr_name_len = 0;
422 resp.gr_passwd_len = 0;
423 resp.gr_gid = -1;
424 resp.gr_mem_len = 0;
425 }
426 if (sock[conn] == 0)
427 {
428 dbg_log (_("bad connection id on send response [%d|%d]"),
429 conn, sock[conn]);
430 return;
431 }
432
433 /* Send response header. */
434 if (write (sock[conn], &resp, sizeof (gr_response_header))
435 != sizeof (gr_response_header))
436 {
437 dbg_log (_("write incomplete on send response: %s"), strerror (errno));
438 return;
439 }
440
441 if (resp.found)
442 {
443 unsigned int l = 0;
444
445 /* Send gr_name. */
446 if (write (sock[conn], grp->gr_name, resp.gr_name_len)
447 != resp.gr_name_len)
448 {
449 dbg_log (_("write incomplete on send response: %s"),
450 strerror (errno));
451 return;
452 }
453 /* Send gr_passwd. */
454 if (write (sock[conn], grp->gr_passwd, resp.gr_passwd_len)
455 != resp.gr_passwd_len)
456 {
457 dbg_log (_("write incomplete on send response: %s"),
458 strerror (errno));
459 return;
460 }
461
462 while (grp->gr_mem[l])
463 {
464 size_t len = strlen (grp->gr_mem[l]);
465
466 if (write (sock[conn], &len, sizeof (len)) != sizeof (len))
467 {
468 dbg_log (_("write incomplete on send response: %s"),
469 strerror (errno));
470 return;
471 }
472 if (write (sock[conn], grp->gr_mem[l], len) != len)
473 {
474 dbg_log (_("write incomplete on send response: %s"),
475 strerror (errno));
476 return;
477 }
478 ++l;
479 }
480 }
481}
482
483void
484gr_send_disabled (int conn)
485{
486 gr_response_header resp;
487
488 resp.version = NSCD_VERSION;
489 resp.found = -1;
490 resp.gr_name_len = 0;
491 resp.gr_passwd_len = 0;
492 resp.gr_gid = -1;
493 resp.gr_mem_len = 0;
494
495 if (sock[conn] == 0)
496 {
497 dbg_log (_("bad connection id on send gr_disabled response [%d|%d]"),
498 conn, sock[conn]);
499 return;
500 }
501
502 /* Send response header. */
503 if (write (sock[conn], &resp, sizeof (gr_response_header))
504 != sizeof (gr_response_header))
505 dbg_log (_("write incomplete on send gr_disabled response: %s"),
506 strerror (errno));
507}
508
509void
510stat_send (int conn, stat_response_header *resp)
511{
512 if (sock[conn] == 0)
513 {
514 dbg_log (_("bad connection id on send stat response [%d|%d]"),
515 conn, sock[conn]);
516 return;
517 }
518
519 /* send response header. */
520 if (write (sock[conn], resp, sizeof (stat_response_header))
521 != sizeof (stat_response_header))
522 dbg_log (_("write incomplete on send stat response: %s"),
523 strerror (errno));
524}