]> git.8kb.co.uk Git - pgpool-ii/pgpool-ii_2.2.5/blob - child.c
Attempt to send a proper failure message to frontend when authentication
[pgpool-ii/pgpool-ii_2.2.5] / child.c
1 /* -*-pgsql-c-*- */
2 /*
3  * $Header: /cvsroot/pgpool/pgpool-II/child.c,v 1.26.2.8 2009/09/06 03:52:12 t-ishii Exp $
4  *
5  * pgpool: a language independent connection pool server for PostgreSQL
6  * written by Tatsuo Ishii
7  *
8  * Copyright (c) 2003-2009      PgPool Global Development Group
9  *
10  * Permission to use, copy, modify, and distribute this software and
11  * its documentation for any purpose and without fee is hereby
12  * granted, provided that the above copyright notice appear in all
13  * copies and that both that copyright notice and this permission
14  * notice appear in supporting documentation, and that the name of the
15  * author not be used in advertising or publicity pertaining to
16  * distribution of the software without specific, written prior
17  * permission. The author makes no representations about the
18  * suitability of this software for any purpose.  It is provided "as
19  * is" without express or implied warranty.
20  *
21  * child.c: child process main
22  *
23  */
24 #include "config.h"
25
26 #include <sys/types.h>
27 #include <sys/socket.h>
28 #include <netinet/in.h>
29 #include <sys/un.h>
30 #include <arpa/inet.h>
31 #include <netdb.h>
32 #ifdef HAVE_NETINET_TCP_H
33 #include <netinet/tcp.h>
34 #endif
35 #ifdef HAVE_SYS_SELECT_H
36 #include <sys/select.h>
37 #endif
38
39 #include <signal.h>
40
41 #include <stdio.h>
42 #include <errno.h>
43 #include <string.h>
44 #include <unistd.h>
45 #include <stdlib.h>
46 #include <sys/time.h>
47
48 #ifdef HAVE_FCNTL_H
49 #include <fcntl.h>
50 #endif
51
52 #ifdef HAVE_CRYPT_H
53 #include <crypt.h>
54 #endif
55
56 #include "pool.h"
57 #include "pool_ip.h"
58 #include "md5.h"
59
60 static POOL_CONNECTION *do_accept(int unix_fd, int inet_fd, struct timeval *timeout);
61 static StartupPacket *read_startup_packet(POOL_CONNECTION *cp);
62 static POOL_CONNECTION_POOL *connect_backend(StartupPacket *sp, POOL_CONNECTION *frontend);
63 static RETSIGTYPE die(int sig);
64 static RETSIGTYPE close_idle_connection(int sig);
65 static RETSIGTYPE wakeup_handler(int sig);
66 static RETSIGTYPE reload_config_handler(int sig);
67 static RETSIGTYPE authentication_timeout(int sig);
68 static int send_params(POOL_CONNECTION *frontend, POOL_CONNECTION_POOL *backend);
69 static void send_frontend_exits(void);
70 static int s_do_auth(POOL_CONNECTION_POOL_SLOT *cp, char *password);
71 static void connection_count_up(void);
72 static void connection_count_down(void);
73
74 /*
75  * non 0 means SIGTERM(smart shutdown) or SIGINT(fast shutdown) has arrived
76  */
77 static int exit_request;
78
79 static int idle;                /* non 0 means this child is in idle state */
80 static int accepted = 0;
81
82 extern int myargc;
83 extern char **myargv;
84
85 char remote_ps_data[NI_MAXHOST];                /* used for set_ps_display */
86
87 volatile sig_atomic_t got_sighup = 0;
88
89 /*
90 * child main loop
91 */
92 void do_child(int unix_fd, int inet_fd)
93 {
94         POOL_CONNECTION *frontend;
95         POOL_CONNECTION_POOL *backend;
96         struct timeval now;
97         struct timezone tz;
98         int child_idle_sec;
99         struct timeval timeout;
100         static int connected;
101         int connections_count = 0;      /* used if child_max_connections > 0 */
102         int first_ready_for_query_received;             /* for master/slave mode */
103         int found;
104         char psbuf[NI_MAXHOST + 128];
105
106         pool_debug("I am %d", getpid());
107
108         /* Identify myself via ps */
109         init_ps_display("", "", "", "");
110
111         /* set up signal handlers */
112         signal(SIGALRM, SIG_DFL);
113         signal(SIGTERM, die);
114         signal(SIGINT, die);
115         signal(SIGHUP, reload_config_handler);
116         signal(SIGQUIT, die);
117         signal(SIGCHLD, SIG_DFL);
118         signal(SIGUSR1, close_idle_connection);
119         signal(SIGUSR2, wakeup_handler);
120         signal(SIGPIPE, SIG_IGN);
121
122 #ifdef NONE_BLOCK
123         /* set listen fds to none block */
124         pool_set_nonblock(unix_fd);
125         if (inet_fd)
126         {
127                 pool_set_nonblock(inet_fd);
128         }
129 #endif
130
131         /* initialize random seed */
132         gettimeofday(&now, &tz);
133         srandom((unsigned int) now.tv_usec);
134
135         /* initialize systemdb connection */
136         if (pool_config->parallel_mode || pool_config->enable_query_cache)
137         {
138                 system_db_connect();
139                 if (PQstatus(system_db_info->pgconn) != CONNECTION_OK)
140                 {
141                         pool_error("Could not make persistent libpq system DB connection");
142                 }
143
144                 system_db_info->connection = make_persistent_db_connection(pool_config->system_db_hostname,
145                                                                                                                                    pool_config->system_db_port,
146                                                                                                                                    pool_config->system_db_dbname,
147                                                                                                                                    pool_config->system_db_user,
148                                                                                                                                    pool_config->system_db_password);
149                 if (system_db_info->connection == NULL)
150                 {
151                         pool_error("Could not make persistent system DB connection");
152                 }
153         }
154
155         /* initialize connection pool */
156         if (pool_init_cp())
157         {
158                 child_exit(1);
159         }
160
161         child_idle_sec = 0;
162
163         timeout.tv_sec = pool_config->child_life_time;
164         timeout.tv_usec = 0;
165
166         init_prepared_list();
167
168         for (;;)
169         {
170                 int connection_reuse = 1;
171                 int ssl_request = 0;
172                 StartupPacket *sp;
173
174                 /* pgpool stop request already sent? */
175                 if (exit_request)
176                 {
177                         die(0);
178                         child_exit(0);
179                 }
180
181                 idle = 1;
182                 accepted = 0;
183
184                 /* perform accept() */
185                 frontend = do_accept(unix_fd, inet_fd, &timeout);
186
187                 if (frontend == NULL)   /* connection request from frontend timed out */
188                 {
189                         /* check select() timeout */
190                         if (connected && pool_config->child_life_time > 0 &&
191                                 timeout.tv_sec == 0 && timeout.tv_usec == 0)
192                         {
193                                 pool_debug("child life %d seconds expired", pool_config->child_life_time);
194                                 /*
195                                  * Doesn't need to call this. child_exit() calls it.
196                                  * send_frontend_exits();
197                                  */
198                                 child_exit(2);
199                         }
200                         continue;
201                 }
202
203                 /* set frontend fd to blocking */
204                 pool_unset_nonblock(frontend->fd);
205
206                 /* set busy flag and clear child idle timer */
207                 idle = 0;
208                 child_idle_sec = 0;
209
210                 /* check backend timer is expired */
211                 if (backend_timer_expired)
212                 {
213                         pool_backend_timer();
214                         backend_timer_expired = 0;
215                 }
216
217                 /* read the startup packet */
218         retry_startup:
219                 sp = read_startup_packet(frontend);
220                 if (sp == NULL)
221                 {
222                         /* failed to read the startup packet. return to the accept() loop */
223                         pool_close(frontend);
224                         connection_count_down();
225                         continue;
226                 }
227
228                 /* cancel request? */
229                 if (sp->major == 1234 && sp->minor == 5678)
230                 {
231                         cancel_request((CancelPacket *)sp->startup_packet);
232
233                         pool_close(frontend);
234                         pool_free_startup_packet(sp);
235                         connection_count_down();
236                         continue;
237                 }
238
239                 /* SSL? */
240                 if (sp->major == 1234 && sp->minor == 5679)
241                 {
242                         /* SSL not supported */
243                         pool_debug("SSLRequest: sent N; retry startup");
244                         if (ssl_request)
245                         {
246                                 pool_close(frontend);
247                                 pool_free_startup_packet(sp);
248                                 connection_count_down();
249                                 continue;
250                         }
251
252                         /*
253                          * say to the frontend "we do not suppport SSL"
254                          * note that this is not a NOTICE response despite it's an 'N'!
255                          */
256                         pool_write_and_flush(frontend, "N", 1);
257                         ssl_request = 1;
258                         pool_free_startup_packet(sp);
259                         goto retry_startup;
260                 }
261
262                 if (pool_config->enable_pool_hba)
263                 {
264                         /*
265                          * do client authentication.
266                          * Note that ClientAuthentication does not return if frontend
267                          * was rejected; it simply terminates this process.
268                          */
269                         frontend->protoVersion = sp->major;
270                         frontend->database = strdup(sp->database);
271                         if (frontend->database == NULL)
272                         {
273                                 pool_error("do_child: strdup failed: %s\n", strerror(errno));
274                                 child_exit(1);
275                         }
276                         frontend->username = strdup(sp->user);
277                         if (frontend->username == NULL)
278                         {
279                                 pool_error("do_child: strdup failed: %s\n", strerror(errno));
280                                 child_exit(1);
281                         }
282                         ClientAuthentication(frontend);
283                 }
284
285                 /*
286                  * Ok, negotiaton with frontend has been done. Let's go to the next step.
287                  */
288
289                 /*
290                  * if there's no connection associated with user and database,
291                  * we need to connect to the backend and send the startup packet.
292                  */
293
294                 first_ready_for_query_received = 0;             /* for master/slave mode */
295
296                 /* look for existing connection */
297                 found = 0;
298                 backend = pool_get_cp(sp->user, sp->database, sp->major, 1);
299
300                 if (backend != NULL)
301                 {
302                         found = 1;
303
304                         /* existing connection associated with same user/database/major found.
305                          * however we should make sure that the startup packet contents are identical.
306                          * OPTION data and others might be different.
307                          */
308                         if (sp->len != MASTER_CONNECTION(backend)->sp->len)
309                         {
310                                 pool_debug("pool_process_query: connection exists but startup packet length is not identical");
311                                 found = 0;
312                         }
313                         else if(memcmp(sp->startup_packet, MASTER_CONNECTION(backend)->sp->startup_packet, sp->len) != 0)
314                         {
315                                 pool_debug("pool_process_query: connection exists but startup packet contents is not identical");
316                                 found = 0;
317                         }
318
319                         if (found == 0)
320                         {
321                                 /* we need to discard existing connection since startup packet is different */
322                                 pool_discard_cp(sp->user, sp->database, sp->major);
323                                 backend = NULL;
324                         }
325                 }
326
327                 if (backend == NULL)
328                 {
329                         /* create a new connection to backend */
330                         connection_reuse = 0;
331
332                         if ((backend = connect_backend(sp, frontend)) == NULL)
333                         {
334                                 connection_count_down();
335                                 continue;
336                         }
337
338                         /* in master/slave mode, the first "ready for query"
339                          * packet should be treated as if we were not in the
340                          * mode
341                          */
342                         if (MASTER_SLAVE)
343                                 first_ready_for_query_received = 1;
344                 }
345
346                 else
347                 {
348                         int i, freed = 0;
349                         /*
350                          * save startup packet info
351                          */
352                         for (i = 0; i < NUM_BACKENDS; i++)
353                         {
354                                 if (VALID_BACKEND(i))
355                                 {
356                                         if (!freed)
357                                         {
358                                                 pool_free_startup_packet(backend->slots[i]->sp);
359                                                 freed = 1;
360                                         }
361                                         backend->slots[i]->sp = sp;
362                                 }
363                         }
364
365                         /* reuse existing connection to backend */
366
367                         if (pool_do_reauth(frontend, backend))
368                         {
369                                 pool_close(frontend);
370                                 connection_count_down();
371                                 continue;
372                         }
373
374                         if (MAJOR(backend) == 3)
375                         {
376                                 if (send_params(frontend, backend))
377                                 {
378                                         pool_close(frontend);
379                                         connection_count_down();
380                                         continue;
381                                 }
382                         }
383
384                         /* send ReadyForQuery to frontend */
385                         pool_write(frontend, "Z", 1);
386
387                         if (MAJOR(backend) == 3)
388                         {
389                                 int len;
390                                 char tstate;
391
392                                 len = htonl(5);
393                                 pool_write(frontend, &len, sizeof(len));
394                                 tstate = TSTATE(backend);
395                                 pool_write(frontend, &tstate, 1);
396                         }
397
398                         if (pool_flush(frontend) < 0)
399                         {
400                                 pool_close(frontend);
401                                 connection_count_down();
402                                 continue;
403                         }
404
405                 }
406
407                 connected = 1;
408
409                 /* show ps status */
410                 sp = MASTER_CONNECTION(backend)->sp;
411                 snprintf(psbuf, sizeof(psbuf), "%s %s %s idle",
412                                  sp->user, sp->database, remote_ps_data);
413                 set_ps_display(psbuf, false);
414
415                 if (MAJOR(backend) == PROTO_MAJOR_V2)
416                         TSTATE(backend) = 'I';
417
418                 if (pool_config->load_balance_mode)
419                 {
420                         /* select load balancing node */
421                         backend->info->load_balancing_node = select_load_balancing_node();
422                 }
423
424                 /* query process loop */
425                 for (;;)
426                 {
427                         POOL_STATUS status;
428
429                         status = pool_process_query(frontend, backend, 0, first_ready_for_query_received);
430
431                         sp = MASTER_CONNECTION(backend)->sp;
432
433                         switch (status)
434                         {
435                                 /* client exits */
436                                 case POOL_END:
437                                         /*
438                                          * do not cache connection if:
439                                          * pool_config->connection_cahe == 0 or
440                                          * database name is template0, template1, postgres or regression
441                                          */
442                                         if (pool_config->connection_cache == 0 ||
443                                                 !strcmp(sp->database, "template0") ||
444                                                 !strcmp(sp->database, "template1") ||
445                                                 !strcmp(sp->database, "postgres") ||
446                                                 !strcmp(sp->database, "regression"))
447                                         {
448                                                 pool_close(frontend);
449                                                 pool_send_frontend_exits(backend);
450                                                 pool_discard_cp(sp->user, sp->database, sp->major);
451                                         }
452                                         else
453                                         {
454                                                 POOL_STATUS status1;
455
456                                                 /* send reset request to backend */
457                                                 status1 = pool_process_query(frontend, backend, 1, 0);
458                                                 pool_close(frontend);
459
460                                                 /* if we detect errors on resetting connection, we need to discard
461                                                  * this connection since it might be in unknown status
462                                                  */
463                                                 if (status1 != POOL_CONTINUE)
464                                                 {
465                                                         pool_debug("error in resetting connections. discarding connection pools...");
466                                                         pool_send_frontend_exits(backend);
467                                                         pool_discard_cp(sp->user, sp->database, sp->major);
468                                                 }
469                                                 else
470                                                         pool_connection_pool_timer(backend);
471                                         }
472                                         break;
473
474                                 /* error occured. discard backend connection pool
475                    and disconnect connection to the frontend */
476                                 case POOL_ERROR:
477 #ifdef NOT_USED
478                                         pool_discard_cp(sp->user, sp->database);
479                                         pool_close(frontend);
480                                         notice_backend_error();
481 #endif
482                                         pool_log("do_child: exits with status 1 due to error");
483                                         child_exit(1);
484                                         break;
485
486                                 /* fatal error occured. just exit myself... */
487                                 case POOL_FATAL:
488                                         notice_backend_error(1);
489                                         child_exit(1);
490                                         break;
491
492                                 /* not implemented yet */
493                                 case POOL_IDLE:
494                                         do_accept(unix_fd, inet_fd, &timeout);
495                                         pool_debug("accept while idle");
496                                         break;
497
498                                 default:
499                                         break;
500                         }
501
502                         if (status != POOL_CONTINUE)
503                                 break;
504                 }
505
506                 accepted = 0;
507                 connection_count_down();
508
509                 timeout.tv_sec = pool_config->child_life_time;
510                 timeout.tv_usec = 0;
511
512                 /* increment queries counter if necessary */
513                 if ( pool_config->child_max_connections > 0 )
514                         connections_count++;
515
516                 /* check if maximum connections count for this child reached */
517                 if ( ( pool_config->child_max_connections > 0 ) &&
518                         ( connections_count >= pool_config->child_max_connections ) )
519                 {
520                         pool_log("child exiting, %d connections reached", pool_config->child_max_connections);
521                         send_frontend_exits();
522                         child_exit(2);
523                 }
524         }
525         child_exit(0);
526 }
527
528 /* -------------------------------------------------------------------
529  * private functions
530  * -------------------------------------------------------------------
531  */
532
533 /*
534  * set non-block flag
535  */
536 void pool_set_nonblock(int fd)
537 {
538         int var;
539
540         /* set fd to none blocking */
541         var = fcntl(fd, F_GETFL, 0);
542         if (var == -1)
543         {
544                 pool_error("fcntl failed. %s", strerror(errno));
545                 child_exit(1);
546         }
547         if (fcntl(fd, F_SETFL, var | O_NONBLOCK) == -1)
548         {
549                 pool_error("fcntl failed. %s", strerror(errno));
550                 child_exit(1);
551         }
552 }
553
554 /*
555  * unset non-block flag
556  */
557 void pool_unset_nonblock(int fd)
558 {
559         int var;
560
561         /* set fd to none blocking */
562         var = fcntl(fd, F_GETFL, 0);
563         if (var == -1)
564         {
565                 pool_error("fcntl failed. %s", strerror(errno));
566                 child_exit(1);
567         }
568         if (fcntl(fd, F_SETFL, var & ~O_NONBLOCK) == -1)
569         {
570                 pool_error("fcntl failed. %s", strerror(errno));
571                 child_exit(1);
572         }
573 }
574
575 /*
576 * perform accept() and return new fd
577 */
578 static POOL_CONNECTION *do_accept(int unix_fd, int inet_fd, struct timeval *timeout)
579 {
580     fd_set      readmask;
581     int fds;
582         int save_errno;
583
584         SockAddr saddr;
585         int fd = 0;
586         int afd;
587         int inet = 0;
588         POOL_CONNECTION *cp;
589 #ifdef ACCEPT_PERFORMANCE
590         struct timeval now1, now2;
591         static long atime;
592         static int cnt;
593 #endif
594         struct timeval *timeoutval;
595         struct timeval tv1, tv2, tmback = {0, 0};
596
597         char remote_host[NI_MAXHOST];
598         char remote_port[NI_MAXSERV];
599
600         set_ps_display("wait for connection request", false);
601
602         FD_ZERO(&readmask);
603         FD_SET(unix_fd, &readmask);
604         if (inet_fd)
605                 FD_SET(inet_fd, &readmask);
606
607         if (timeout->tv_sec == 0 && timeout->tv_usec == 0)
608                 timeoutval = NULL;
609         else
610         {
611                 timeoutval = timeout;
612                 tmback.tv_sec = timeout->tv_sec;
613                 tmback.tv_usec = timeout->tv_usec;
614                 gettimeofday(&tv1, NULL);
615
616 #ifdef DEBUG
617                 pool_log("before select = {%d, %d}", timeoutval->tv_sec, timeoutval->tv_usec);
618                 pool_log("g:before select = {%d, %d}", tv1.tv_sec, tv1.tv_usec);
619 #endif
620         }
621
622         fds = select(Max(unix_fd, inet_fd)+1, &readmask, NULL, NULL, timeoutval);
623
624         save_errno = errno;
625         /* check backend timer is expired */
626         if (backend_timer_expired)
627         {
628                 pool_backend_timer();
629                 backend_timer_expired = 0;
630         }
631
632         /*
633          * following code fragment computes remaining timeout val in a
634          * portable way. Linux does this automazically but other platforms do not.
635          */
636         if (timeoutval)
637         {
638                 gettimeofday(&tv2, NULL);
639
640                 tmback.tv_usec -= tv2.tv_usec - tv1.tv_usec;
641                 tmback.tv_sec -= tv2.tv_sec - tv1.tv_sec;
642
643                 if (tmback.tv_usec < 0)
644                 {
645                         tmback.tv_sec--;
646                         if (tmback.tv_sec < 0)
647                         {
648                                 timeout->tv_sec = 0;
649                                 timeout->tv_usec = 0;
650                         }
651                         else
652                         {
653                                 tmback.tv_usec += 1000000;
654                                 timeout->tv_sec = tmback.tv_sec;
655                                 timeout->tv_usec = tmback.tv_usec;
656                         }
657                 }
658 #ifdef DEBUG
659                 pool_log("g:after select = {%d, %d}", tv2.tv_sec, tv2.tv_usec);
660                 pool_log("after select = {%d, %d}", timeout->tv_sec, timeout->tv_usec);
661 #endif
662         }
663
664         errno = save_errno;
665
666         if (fds == -1)
667         {
668                 if (errno == EAGAIN || errno == EINTR)
669                         return NULL;
670
671                 pool_error("select() failed. reason %s", strerror(errno));
672                 return NULL;
673         }
674
675         /* timeout */
676         if (fds == 0)
677         {
678                 return NULL;
679         }
680
681         if (FD_ISSET(unix_fd, &readmask))
682         {
683                 fd = unix_fd;
684         }
685
686         if (FD_ISSET(inet_fd, &readmask))
687         {
688                 fd = inet_fd;
689                 inet++;
690         }
691
692         /*
693          * Note that some SysV systems do not work here. For those
694          * systems, we need some locking mechanism for the fd.
695          */
696         memset(&saddr, 0, sizeof(saddr));
697         saddr.salen = sizeof(saddr.addr);
698
699 #ifdef ACCEPT_PERFORMANCE
700         gettimeofday(&now1,0);
701 #endif
702
703  retry_accept:
704
705         /* wait if recovery is started */
706         while (*InRecovery == 1)
707         {
708                 pause();
709         }
710
711         afd = accept(fd, (struct sockaddr *)&saddr.addr, &saddr.salen);
712
713         save_errno = errno;
714         /* check backend timer is expired */
715         if (backend_timer_expired)
716         {
717                 pool_backend_timer();
718                 backend_timer_expired = 0;
719         }
720         errno = save_errno;
721         if (afd < 0)
722         {
723                 if (errno == EINTR && *InRecovery)
724                         goto retry_accept;
725
726                 /*
727                  * "Resource temporarily unavailable" (EAGAIN or EWOULDBLOCK)
728                  * can be silently ignored. And EINTR can be ignored.
729                  */
730                 if (errno != EAGAIN && errno != EWOULDBLOCK && errno != EINTR)
731                         pool_error("accept() failed. reason: %s", strerror(errno));
732                 return NULL;
733         }
734 #ifdef ACCEPT_PERFORMANCE
735         gettimeofday(&now2,0);
736         atime += (now2.tv_sec - now1.tv_sec)*1000000 + (now2.tv_usec - now1.tv_usec);
737         cnt++;
738         if (cnt % 100 == 0)
739         {
740                 pool_log("cnt: %d atime: %ld", cnt, atime);
741         }
742 #endif
743
744         /* reload config file */
745         if (got_sighup)
746         {
747                 pool_get_config(get_config_file_name(), RELOAD_CONFIG);
748                 if (pool_config->enable_pool_hba)
749                         load_hba(get_hba_file_name());
750                 if (pool_config->parallel_mode)
751                         pool_memset_system_db_info(system_db_info->info);
752                 got_sighup = 0;
753         }
754
755         connection_count_up();
756         accepted = 1;
757
758         if (pool_config->parallel_mode)
759         {
760                 /*
761                  * do not accept new connection if any of DB node or SystemDB is down when operating in
762                  * parallel mode
763                  */
764                 int i;
765
766                 for (i=0;i<NUM_BACKENDS;i++)
767                 {
768                         if (BACKEND_INFO(i).backend_status == CON_DOWN || SYSDB_STATUS == CON_DOWN)
769                         {
770                                 StartupPacket *sp;
771                                 char *msg = "pgpool is not available in parallel query mode";
772
773                                 if (SYSDB_STATUS == CON_DOWN)
774                                         pool_log("Cannot accept() new connection. SystemDB is down");
775                                 else
776                                         pool_log("Cannot accept() new connection. %d th backend is down", i);
777
778                                 if ((cp = pool_open(afd)) == NULL)
779                                 {
780                                         close(afd);
781                                         child_exit(1);
782                                 }
783
784                                 sp = read_startup_packet(cp);
785                                 if (sp == NULL)
786                                 {
787                                         /* failed to read the startup packet. return to the accept() loop */
788                                         pool_close(cp);
789                                         child_exit(1);
790                                 }
791
792                                 pool_debug("do_accept: send error message to frontend");
793
794                                 if (sp->major == PROTO_MAJOR_V3)
795                                 {
796                                         char buf[256];
797
798                                         if (SYSDB_STATUS == CON_DOWN)
799                                                 snprintf(buf, sizeof(buf), "SystemDB is down");
800                                         else
801                                                 snprintf(buf, sizeof(buf), "%d th backend is down", i);
802
803                                         pool_send_error_message(cp, sp->major, "08S01",
804                                                                                         msg,
805                                                                                         buf,
806                                                                                         ((SYSDB_STATUS == CON_DOWN) ? "repair the SystemDB and restart pgpool"
807                                                                                                                    : "repair the backend and restart pgpool"),
808                                                                                         __FILE__,
809                                                                                         __LINE__);
810                                 }
811                                 else
812                                 {
813                                         pool_send_error_message(cp, sp->major,
814                                                                                         0,
815                                                                                         msg,
816                                                                                         "",
817                                                                                         "",
818                                                                                         "",
819                                                                                         0);
820                                 }
821                                 pool_close(cp);
822                                 child_exit(1);
823                         }
824                 }
825         }
826         else
827         {
828                 /*
829                  * do not accept new connection if all DB nodes are down when operating in
830                  * non parallel mode
831                  */
832                 int i;
833                 int found = 0;
834
835                 for (i=0;i<NUM_BACKENDS;i++)
836                 {
837                         if (VALID_BACKEND(i))
838                         {
839                                 found = 1;
840                         }
841                 }
842                 if (found == 0)
843                 {
844                         pool_log("Cannot accept() new connection. all backends are down");
845                         child_exit(1);
846                 }
847         }
848
849         pool_debug("I am %d accept fd %d", getpid(), afd);
850
851         pool_getnameinfo_all(&saddr, remote_host, remote_port);
852         snprintf(remote_ps_data, sizeof(remote_ps_data),
853                          remote_port[0] == '\0' ? "%s" : "%s(%s)",
854                          remote_host, remote_port);
855
856         set_ps_display("accept connection", false);
857
858         /* log who is connecting */
859         if (pool_config->log_connections)
860         {
861                 pool_log("connection received: host=%s%s%s",
862                                  remote_host, remote_port[0] ? " port=" : "", remote_port);
863         }
864
865         /* set NODELAY and KEEPALIVE options if INET connection */
866         if (inet)
867         {
868                 int on = 1;
869
870                 if (setsockopt(afd, IPPROTO_TCP, TCP_NODELAY,
871                                            (char *) &on,
872                                            sizeof(on)) < 0)
873                 {
874                         pool_error("do_accept: setsockopt() failed: %s", strerror(errno));
875                         close(afd);
876                         return NULL;
877                 }
878                 if (setsockopt(afd, SOL_SOCKET, SO_KEEPALIVE,
879                                            (char *) &on,
880                                            sizeof(on)) < 0)
881                 {
882                         pool_error("do_accept: setsockopt() failed: %s", strerror(errno));
883                         close(afd);
884                         return NULL;
885                 }
886         }
887
888         if ((cp = pool_open(afd)) == NULL)
889         {
890                 close(afd);
891                 return NULL;
892         }
893
894         /* save ip addres for hba */
895         memcpy(&cp->raddr, &saddr, sizeof(SockAddr));
896         if (cp->raddr.addr.ss_family == 0)
897                 cp->raddr.addr.ss_family = AF_UNIX;
898
899         return cp;
900 }
901
902 /*
903 * read startup packet
904 */
905 static StartupPacket *read_startup_packet(POOL_CONNECTION *cp)
906 {
907         StartupPacket *sp;
908         StartupPacket_v2 *sp2;
909         int protov;
910         int len;
911         char *p;
912
913         sp = (StartupPacket *)calloc(sizeof(*sp), 1);
914         if (!sp)
915         {
916                 pool_error("read_startup_packet: out of memory");
917                 return NULL;
918         }
919
920         if (pool_config->authentication_timeout > 0)
921         {
922                 pool_signal(SIGALRM, authentication_timeout);
923                 alarm(pool_config->authentication_timeout);
924         }
925
926         /* read startup packet length */
927         if (pool_read(cp, &len, sizeof(len)))
928         {
929                 return NULL;
930         }
931         len = ntohl(len);
932         len -= sizeof(len);
933
934         if (len <= 0)
935         {
936                 pool_error("read_startup_packet: incorrect packet length (%d)", len);
937         }
938         else if (len >= MAX_STARTUP_PACKET_LENGTH)
939         {
940                 pool_error("read_startup_packet: invalid startup packet");
941                 pool_free_startup_packet(sp);
942                 return NULL;
943         }
944
945         sp->startup_packet = calloc(len, 1);
946         if (!sp->startup_packet)
947         {
948                 pool_error("read_startup_packet: out of memory");
949                 pool_free_startup_packet(sp);
950                 alarm(0);
951                 pool_signal(SIGALRM, SIG_IGN);
952                 return NULL;
953         }
954
955         /* read startup packet */
956         if (pool_read(cp, sp->startup_packet, len))
957         {
958                 pool_free_startup_packet(sp);
959                 alarm(0);
960                 pool_signal(SIGALRM, SIG_IGN);
961                 return NULL;
962         }
963
964         sp->len = len;
965         memcpy(&protov, sp->startup_packet, sizeof(protov));
966         sp->major = ntohl(protov)>>16;
967         sp->minor = ntohl(protov) & 0x0000ffff;
968         p = sp->startup_packet;
969
970         switch(sp->major)
971         {
972                 case PROTO_MAJOR_V2: /* V2 */
973                         sp2 = (StartupPacket_v2 *)(sp->startup_packet);
974
975                         sp->database = calloc(SM_DATABASE+1, 1);
976                         if (!sp->database)
977                         {
978                                 pool_error("read_startup_packet: out of memory");
979                                 pool_free_startup_packet(sp);
980                                 alarm(0);
981                                 pool_signal(SIGALRM, SIG_IGN);
982                                 return NULL;
983                         }
984                         strncpy(sp->database, sp2->database, SM_DATABASE);
985
986                         sp->user = calloc(SM_USER+1, 1);
987                         if (!sp->user)
988                         {
989                                 pool_error("read_startup_packet: out of memory");
990                                 pool_free_startup_packet(sp);
991                                 alarm(0);
992                                 pool_signal(SIGALRM, SIG_IGN);
993                                 return NULL;
994                         }
995                         strncpy(sp->user, sp2->user, SM_USER);
996
997                         break;
998
999                 case PROTO_MAJOR_V3: /* V3 */
1000                         p += sizeof(int);       /* skip protocol version info */
1001
1002                         while(*p)
1003                         {
1004                                 if (!strcmp("user", p))
1005                                 {
1006                                         p += (strlen(p) + 1);
1007                                         sp->user = strdup(p);
1008                                         if (!sp->user)
1009                                         {
1010                                                 pool_error("read_startup_packet: out of memory");
1011                                                 pool_free_startup_packet(sp);
1012                                                 alarm(0);
1013                                                 pool_signal(SIGALRM, SIG_IGN);
1014                                                 return NULL;
1015                                         }
1016                                 }
1017                                 else if (!strcmp("database", p))
1018                                 {
1019                                         p += (strlen(p) + 1);
1020                                         sp->database = strdup(p);
1021                                         if (!sp->database)
1022                                         {
1023                                                 pool_error("read_startup_packet: out of memory");
1024                                                 pool_free_startup_packet(sp);
1025                                                 alarm(0);
1026                                                 pool_signal(SIGALRM, SIG_IGN);
1027                                                 return NULL;
1028                                         }
1029                                 }
1030                                 p += (strlen(p) + 1);
1031                         }
1032                         break;
1033
1034                 case 1234:              /* cancel or SSL request */
1035                         /* set dummy database, user info */
1036                         sp->database = calloc(1, 1);
1037                         if (!sp->database)
1038                         {
1039                                 pool_error("read_startup_packet: out of memory");
1040                                 pool_free_startup_packet(sp);
1041                                 alarm(0);
1042                                 pool_signal(SIGALRM, SIG_IGN);
1043                                 return NULL;
1044                         }
1045                         sp->user = calloc(1, 1);
1046                         if (!sp->user)
1047                         {
1048                                 pool_error("read_startup_packet: out of memory");
1049                                 pool_free_startup_packet(sp);
1050                                 alarm(0);
1051                                 pool_signal(SIGALRM, SIG_IGN);
1052                                 return NULL;
1053                         }
1054                         break;
1055
1056                 default:
1057                         pool_error("read_startup_packet: invalid major no: %d", sp->major);
1058                         pool_free_startup_packet(sp);
1059                         alarm(0);
1060                         pool_signal(SIGALRM, SIG_IGN);
1061                         return NULL;
1062         }
1063
1064         pool_debug("Protocol Major: %d Minor: %d database: %s user: %s",
1065                            sp->major, sp->minor, sp->database, sp->user);
1066         alarm(0);
1067         pool_signal(SIGALRM, SIG_IGN);
1068         return sp;
1069 }
1070
1071 /*
1072 * send startup packet
1073 */
1074 int send_startup_packet(POOL_CONNECTION_POOL_SLOT *cp)
1075 {
1076         int len;
1077
1078         len = htonl(cp->sp->len + sizeof(len));
1079         pool_write(cp->con, &len, sizeof(len));
1080         return pool_write_and_flush(cp->con, cp->sp->startup_packet, cp->sp->len);
1081 }
1082
1083 /*
1084  * process cancel request
1085  */
1086 void cancel_request(CancelPacket *sp)
1087 {
1088         int     len;
1089         int fd;
1090         POOL_CONNECTION *con;
1091         int i;
1092         ConnectionInfo *c = NULL;
1093         CancelPacket cp;
1094
1095         pool_debug("Cancel request received");
1096
1097         /* look for cancel key from shmem info */
1098         for (i=0;i<pool_config->num_init_children*pool_config->max_pool;i++)
1099         {
1100                 c = &con_info[i];
1101
1102                 if (c->pid == sp->pid && c->key == sp->key)
1103                 {
1104                         pool_debug("found pid:%d key:%d i:%d",c->pid, c->key,i);
1105                         c = &con_info[i/pool_config->max_pool * pool_config->max_pool];
1106                         break;
1107                 }
1108         }
1109         if (i == pool_config->num_init_children*pool_config->max_pool)
1110                 return; /* invalid key */
1111
1112         for (i=0;i<NUM_BACKENDS;i++,c++)
1113         {
1114                 if (!VALID_BACKEND(i))
1115                         continue;
1116
1117                 if (*(BACKEND_INFO(i).backend_hostname) == '\0')
1118                         fd = connect_unix_domain_socket(i);
1119                 else
1120                         fd = connect_inet_domain_socket(i);
1121
1122                 if (fd < 0)
1123                 {
1124                         pool_error("Could not create socket for sending cancel request for backend %d", i);
1125                         return;
1126                 }
1127
1128                 con = pool_open(fd);
1129                 if (con == NULL)
1130                         return;
1131
1132                 len = htonl(sizeof(len) + sizeof(CancelPacket));
1133                 pool_write(con, &len, sizeof(len));
1134
1135                 cp.protoVersion = sp->protoVersion;
1136                 cp.pid = c->pid;
1137                 cp.key = c->key;
1138
1139                 pool_debug("pid:%d key: %d",cp.pid,cp.key);
1140
1141                 if (pool_write_and_flush(con, &cp, sizeof(CancelPacket)) < 0)
1142                         pool_error("Could not send cancel request packet for backend %d", i);
1143
1144                 pool_close(con);
1145
1146                 /*
1147                  * this is needed to enure that the next DB node executes the
1148                  * query supposed to be canceled.
1149                  */
1150                 sleep(1);
1151         }
1152 }
1153
1154 static POOL_CONNECTION_POOL *connect_backend(StartupPacket *sp, POOL_CONNECTION *frontend)
1155 {
1156         POOL_CONNECTION_POOL *backend;
1157         int i;
1158
1159         /* connect to the backend */
1160         backend = pool_create_cp();
1161         if (backend == NULL)
1162         {
1163                 pool_send_error_message(frontend, sp->major, "XX000", "connection cache is full", "",
1164                                                                 "increase max_pool", __FILE__, __LINE__);
1165                 pool_close(frontend);
1166                 pool_free_startup_packet(sp);
1167                 return NULL;
1168         }
1169
1170         for (i=0;i<NUM_BACKENDS;i++)
1171         {
1172                 if (VALID_BACKEND(i))
1173                 {
1174                         /* set DB node id */
1175                         CONNECTION(backend, i)->db_node_id = i;
1176
1177                         /* mark this is a backend connection */
1178                         CONNECTION(backend, i)->isbackend = 1;
1179
1180                         /*
1181                          * save startup packet info
1182                          */
1183                         CONNECTION_SLOT(backend, i)->sp = sp;
1184
1185                         /* send startup packet */
1186                         if (send_startup_packet(CONNECTION_SLOT(backend, i)) < 0)
1187                         {
1188                                 pool_error("do_child: fails to send startup packet to the %d th backend", i);
1189                                 pool_discard_cp(sp->user, sp->database, sp->major);
1190                                 pool_close(frontend);
1191                                 return NULL;
1192                         }
1193                 }
1194         }
1195
1196         /*
1197          * do authentication stuff
1198          */
1199         if (pool_do_auth(frontend, backend))
1200         {
1201                 pool_close(frontend);
1202                 pool_discard_cp(sp->user, sp->database, sp->major);
1203                 return NULL;
1204         }
1205
1206         return backend;
1207 }
1208
1209 /*
1210  * signal handler for SIGINT and SIGQUUT
1211  */
1212 static RETSIGTYPE die(int sig)
1213 {
1214         exit_request = 1;
1215
1216         pool_debug("child receives shutdown request signal %d", sig);
1217
1218         switch (sig)
1219         {
1220                 case SIGTERM:   /* smart shutdown */
1221                         if (idle == 0)
1222                         {
1223                                 pool_debug("child receives smart shutdown request but it's not in idle state");
1224                                 return;
1225                         }
1226                         break;
1227
1228                 case SIGINT:    /* fast shutdown */
1229                 case SIGQUIT:   /* immediate shutdown */
1230                         child_exit(0);
1231                         break;
1232                 default:
1233                         break;
1234         }
1235
1236         /*
1237          * child_exit() does this. So we don't need it.
1238          * send_frontend_exits();
1239          */
1240         child_exit(0);
1241 }
1242
1243 /*
1244  * signal handler for SIGUSR1
1245  * close all idle connections
1246  */
1247 static RETSIGTYPE close_idle_connection(int sig)
1248 {
1249         int i, j;
1250         POOL_CONNECTION_POOL *p = pool_connection_pool;
1251         ConnectionInfo *info;
1252
1253         pool_debug("child receives close connection request");
1254
1255         for (j=0;j<pool_config->max_pool;j++, p++)
1256         {
1257                 if (!MASTER_CONNECTION(p))
1258                         continue;
1259                 if (!MASTER_CONNECTION(p)->sp)
1260                         continue;
1261                 if (MASTER_CONNECTION(p)->sp->user == NULL)
1262                         continue;
1263
1264                 if (MASTER_CONNECTION(p)->closetime > 0)                /* idle connection? */
1265                 {
1266                         pool_debug("close_idle_connection: close idle connection: user %s database %s", MASTER_CONNECTION(p)->sp->user, MASTER_CONNECTION(p)->sp->database);
1267                         pool_send_frontend_exits(p);
1268
1269                         for (i=0;i<NUM_BACKENDS;i++)
1270                         {
1271                                 if (!VALID_BACKEND(i))
1272                                         continue;
1273
1274                                 if (i == 0)
1275                                 {
1276                                         /* only first backend allocated the memory for the start up packet */
1277                                         pool_free_startup_packet(CONNECTION_SLOT(p, i)->sp);
1278                                 }
1279                                 pool_close(CONNECTION(p, i));
1280                         }
1281                         info = p->info;
1282                         memset(p, 0, sizeof(POOL_CONNECTION_POOL));
1283                         p->info = info;
1284                         memset(p->info, 0, sizeof(ConnectionInfo));
1285                 }
1286         }
1287 }
1288
1289 /*
1290  * signal handler for SIGALRM
1291  *
1292  */
1293 static RETSIGTYPE authentication_timeout(int sig)
1294 {
1295         pool_log("authentication is timeout");
1296         child_exit(1);
1297 }
1298
1299 /*
1300  * send frontend exiting messages to all connections.  this is called
1301  * in any case when child process exits, for example failover, child
1302  * life time expires or child max connections expires.
1303  */
1304 static void send_frontend_exits(void)
1305 {
1306         int i;
1307         POOL_CONNECTION_POOL *p = pool_connection_pool;
1308
1309 #ifdef HAVE_SIGPROCMASK
1310         sigset_t oldmask;
1311 #else
1312         int     oldmask;
1313 #endif
1314
1315         POOL_SETMASK2(&BlockSig, &oldmask);
1316
1317         for (i=0;i<pool_config->max_pool;i++, p++)
1318         {
1319                 if (!MASTER_CONNECTION(p))
1320                         continue;
1321                 if (!MASTER_CONNECTION(p)->sp)
1322                         continue;
1323                 if (MASTER_CONNECTION(p)->sp->user == NULL)
1324                         continue;
1325                 pool_send_frontend_exits(p);
1326         }
1327
1328         POOL_SETMASK(&oldmask);
1329 }
1330
1331 static int send_params(POOL_CONNECTION *frontend, POOL_CONNECTION_POOL *backend)
1332 {
1333         int index;
1334         char *name, *value;
1335         int len, sendlen;
1336
1337         index = 0;
1338         while (pool_get_param(&MASTER(backend)->params, index++, &name, &value) == 0)
1339         {
1340                 pool_write(frontend, "S", 1);
1341                 len = sizeof(sendlen) + strlen(name) + 1 + strlen(value) + 1;
1342                 sendlen = htonl(len);
1343                 pool_write(frontend, &sendlen, sizeof(sendlen));
1344                 pool_write(frontend, name, strlen(name) + 1);
1345                 pool_write(frontend, value, strlen(value) + 1);
1346         }
1347
1348         if (pool_flush(frontend))
1349         {
1350                 pool_error("pool_send_params: pool_flush() failed");
1351                 return -1;
1352         }
1353         return 0;
1354 }
1355
1356 void pool_free_startup_packet(StartupPacket *sp)
1357 {
1358         if (sp)
1359         {
1360                 if (sp->startup_packet)
1361                         free(sp->startup_packet);
1362                 if (sp->database)
1363                         free(sp->database);
1364                 if (sp->user)
1365                         free(sp->user);
1366                 free(sp);
1367         }
1368 }
1369
1370 /*
1371  * Do house keeping works when pgpool child process exits
1372  */
1373 void child_exit(int code)
1374 {
1375         /* count down global connection counter */
1376         if (accepted)
1377                 connection_count_down();
1378
1379         /* prepare to shutdown connections to system db */
1380         if(pool_config->parallel_mode || pool_config->enable_query_cache)
1381         {
1382                 if (system_db_info->pgconn)
1383                         pool_close_libpq_connection();
1384                 if (pool_system_db_connection())
1385                         pool_close(pool_system_db_connection()->con);
1386         }
1387
1388         /* let backend know now we are exiting */
1389         send_frontend_exits();
1390
1391         exit(code);
1392 }
1393
1394 /*
1395  * create a persistent connection
1396  */
1397 POOL_CONNECTION_POOL_SLOT *make_persistent_db_connection(
1398         char *hostname, int port, char *dbname, char *user, char *password)
1399 {
1400         POOL_CONNECTION_POOL_SLOT *cp;
1401         int fd;
1402
1403 #define MAX_USER_AND_DATABASE   1024
1404
1405         /* V3 startup packet */
1406         typedef struct {
1407                 int protoVersion;
1408                 char data[MAX_USER_AND_DATABASE];
1409         } StartupPacket_v3;
1410
1411         static StartupPacket_v3 *startup_packet;
1412         int len, len1;
1413         int status;
1414
1415         cp = malloc(sizeof(POOL_CONNECTION_POOL));
1416         if (cp == NULL)
1417         {
1418                 pool_error("make_persistent_db_connection: could not allocate memory");
1419                 return NULL;
1420         }
1421         memset(cp, 0, sizeof(POOL_CONNECTION_POOL));
1422
1423         startup_packet = malloc(sizeof(*startup_packet));
1424         if (startup_packet == NULL)
1425         {
1426                 pool_error("make_persistent_db_connection: could not allocate memory");
1427                 return NULL;
1428         }
1429         memset(startup_packet, 0, sizeof(*startup_packet));
1430         startup_packet->protoVersion = htonl(0x00030000);       /* set V3 proto major/minor */
1431
1432         /*
1433          * create socket
1434          */
1435         if (*hostname == '\0')
1436         {
1437                 fd = connect_unix_domain_socket_by_port(port, pool_config->backend_socket_dir);
1438         }
1439         else
1440         {
1441                 fd = connect_inet_domain_socket_by_port(hostname, port);
1442         }
1443
1444         if (fd < 0)
1445         {
1446                 pool_error("make_persistent_db_connection: connection to %s(%d) failed", hostname, port);
1447                 return NULL;
1448         }
1449
1450         cp->con = pool_open(fd);
1451         cp->closetime = 0;
1452         cp->con->isbackend = 1;
1453
1454         /*
1455          * build V3 startup packet
1456          */
1457         len = snprintf(startup_packet->data, sizeof(startup_packet->data), "user") + 1;
1458         len1 = snprintf(&startup_packet->data[len], sizeof(startup_packet->data)-len, "%s", user) + 1;
1459         if (len1 >= (sizeof(startup_packet->data)-len))
1460         {
1461                 pool_error("make_persistent_db_connection: too long user name");
1462                 return NULL;
1463         }
1464
1465         len += len1;
1466         len1 = snprintf(&startup_packet->data[len], sizeof(startup_packet->data)-len, "database") + 1;
1467         if (len1 >= (sizeof(startup_packet->data)-len))
1468         {
1469                 pool_error("make_persistent_db_connection: too long user name");
1470                 return NULL;
1471         }
1472
1473         len += len1;
1474         len1 = snprintf(&startup_packet->data[len], sizeof(startup_packet->data)-len, "%s", dbname) + 1;
1475         if (len1 >= (sizeof(startup_packet->data)-len))
1476         {
1477                 pool_error("make_persistent_db_connection: too long database name");
1478                 return NULL;
1479         }
1480         len += len1;
1481         startup_packet->data[len++] = '\0';
1482
1483         cp->sp = malloc(sizeof(StartupPacket));
1484         if (cp->sp == NULL)
1485         {
1486                 pool_error("make_persistent_db_connection: could not allocate memory");
1487                 return NULL;
1488         }
1489
1490         cp->sp->startup_packet = (char *)startup_packet;
1491         cp->sp->len = len + 4;
1492         cp->sp->major = 3;
1493         cp->sp->minor = 0;
1494         cp->sp->database = strdup(dbname);
1495         if (cp->sp->database == NULL)
1496         {
1497                 pool_error("make_persistent_db_connection: could not allocate memory");
1498                 return NULL;
1499         }
1500         cp->sp->user = strdup(user);
1501         if (cp->sp->user == NULL)
1502         {
1503                 pool_error("make_persistent_db_connection: could not allocate memory");
1504                 return NULL;
1505         }
1506
1507         /*
1508          * send startup packet
1509          */
1510         status = send_startup_packet(cp);
1511         if (status)
1512         {
1513                 pool_error("make_persistent_db_connection: send_startup_packet failed");
1514                 return NULL;
1515         }
1516
1517         /*
1518          * do authentication
1519          */
1520         if (s_do_auth(cp, password))
1521         {
1522                 pool_error("make_persistent_db_connection: s_do_auth failed");
1523                 return NULL;
1524         }
1525
1526         return cp;
1527 }
1528
1529 /*
1530  * do authentication for cp
1531  */
1532 static int s_do_auth(POOL_CONNECTION_POOL_SLOT *cp, char *password)
1533 {
1534         char kind;
1535         int status;
1536         int length;
1537         int auth_kind;
1538         char state;
1539         char *p;
1540         int pid, key;
1541
1542         /*
1543          * read kind expecting 'R' packet (authentication response)
1544          */
1545         status = pool_read(cp->con, &kind, sizeof(kind));
1546         if (status < 0)
1547         {
1548                 pool_error("s_do_auth: error while reading message kind");
1549                 return -1;
1550         }
1551
1552         if (kind != 'R')
1553         {
1554                 pool_error("s_do_auth: expecting R got %c", kind);
1555                 return -1;
1556         }
1557
1558         /* read message length */
1559         status = pool_read(cp->con, &length, sizeof(length));
1560         if (status < 0)
1561         {
1562                 pool_error("s_do_auth: error while reading message length");
1563                 return -1;
1564         }
1565         length = ntohl(length);
1566
1567         /* read auth kind */
1568         status = pool_read(cp->con, &auth_kind, sizeof(auth_kind));
1569         if (status < 0)
1570         {
1571                 pool_error("s_do_auth: error while reading auth kind");
1572                 return -1;
1573         }
1574         auth_kind = ntohl(auth_kind);
1575         pool_debug("s_do_auth: auth kind: %d", auth_kind);
1576
1577         if (auth_kind == 0)     /* trust authentication? */
1578         {
1579                 cp->con->auth_kind = 0;
1580         }
1581         else if (auth_kind == 3) /* clear text password? */
1582         {
1583                 int size = htonl(strlen(password) + 5);
1584
1585                 pool_write(cp->con, "p", 1);
1586                 pool_write(cp->con, &size, sizeof(size));
1587                 pool_write_and_flush(cp->con, password, strlen(password) + 1);
1588                 status = pool_flush(cp->con);
1589                 if (status > 0)
1590                 {
1591                         pool_error("s_do_auth: error while sending clear text password");
1592                         return -1;
1593                 }
1594                 return s_do_auth(cp, password);
1595         }
1596         else if (auth_kind == 4) /* crypt password? */
1597         {
1598                 int size;
1599                 char salt[3];
1600                 char *crypt_password;
1601
1602                 status = pool_read(cp->con, &salt, 2);
1603                 if (status > 0)
1604                 {
1605                         pool_error("s_do_auth: error while reading crypt salt");
1606                         return -1;
1607                 }
1608                 salt[2] = '\0';
1609
1610                 crypt_password = crypt(password, salt);
1611                 size = htonl(strlen(crypt_password) + 5);
1612                 pool_write(cp->con, "p", 1);
1613                 pool_write(cp->con, &size, sizeof(size));
1614                 pool_write_and_flush(cp->con, crypt_password, strlen(crypt_password) + 1);
1615                 status = pool_flush(cp->con);
1616                 if (status > 0)
1617                 {
1618                         pool_error("s_do_auth: error while sending crypt password");
1619                         return -1;
1620                 }
1621                 return s_do_auth(cp, password);
1622         }
1623         else if (auth_kind == 5) /* md5 password? */
1624         {
1625                 char salt[4];
1626                 char *buf, *buf1;
1627                 int size;
1628
1629                 status = pool_read(cp->con, &salt, 4);
1630                 if (status > 0)
1631                 {
1632                         pool_error("s_do_auth: error while reading md5 salt");
1633                         return -1;
1634                 }
1635
1636                 buf = malloc(2 * (MD5_PASSWD_LEN + 4)); /* hash + "md5" + '\0' */
1637                 if (buf == NULL)
1638                 {
1639                         pool_error("s_do_auth(): malloc failed: %s", strerror(errno));
1640                         return -1;
1641                 }
1642                 memset(buf, 0, 2 * (MD5_PASSWD_LEN + 4));
1643
1644                 /* build md5 password */
1645                 buf1 = buf + MD5_PASSWD_LEN + 4;
1646                 pool_md5_encrypt(password, cp->sp->user, strlen(cp->sp->user), buf1);
1647                 pool_md5_encrypt(buf1, salt, 4, buf + 3);
1648                 memcpy(buf, "md5", 3);
1649
1650                 size = htonl(strlen(buf) + 5);
1651                 pool_write(cp->con, "p", 1);
1652                 pool_write(cp->con, &size, sizeof(size));
1653                 pool_write_and_flush(cp->con, buf, strlen(buf) + 1);
1654                 status = pool_flush(cp->con);
1655                 if (status > 0)
1656                 {
1657                         pool_error("s_do_auth: error while sending md5 password");
1658                         return -1;
1659                 }
1660
1661                 status = s_do_auth(cp, password);
1662                 free(buf);
1663                 return status;
1664         }
1665         else
1666         {
1667                 pool_error("s_do_auth: auth kind %d not supported yet", auth_kind);
1668                 return -1;
1669         }
1670
1671         /*
1672          * read pid etc.
1673          */
1674         for (;;)
1675         {
1676                 status = pool_read(cp->con, &kind, sizeof(kind));
1677                 if (status < 0)
1678                 {
1679                         pool_error("s_do_auth: error while reading message kind");
1680                         return -1;
1681                 }
1682
1683                 switch (kind)
1684                 {
1685                         case 'K':       /* backend key data */
1686                                 pool_debug("s_do_auth: backend key data received");
1687
1688                                 /* read message length */
1689                                 status = pool_read(cp->con, &length, sizeof(length));
1690                                 if (status < 0)
1691                                 {
1692                                         pool_error("s_do_auth: error while reading message length");
1693                                         return -1;
1694                                 }
1695                                 if (ntohl(length) != 12)
1696                                 {
1697                                         pool_error("s_do_auth: backend key data length is not 12 (%d)", ntohl(length));
1698                                 }
1699
1700                                 /* read pid */
1701                                 if (pool_read(cp->con, &pid, sizeof(pid)) < 0)
1702                                 {
1703                                         pool_error("s_do_auth: failed to read pid");
1704                                         return -1;
1705                                 }
1706                                 cp->pid = pid;
1707
1708                                 /* read key */
1709                                 if (pool_read(cp->con, &key, sizeof(key)) < 0)
1710                                 {
1711                                         pool_error("s_do_auth: failed to read key");
1712                                         return -1;
1713                                 }
1714                                 cp->key = key;
1715
1716                                 /* read kind expecting 'Z' (ready for query) */
1717                                 status = pool_read(cp->con, &kind, sizeof(kind));
1718                                 if (status < 0)
1719                                 {
1720                                         pool_error("s_do_auth: error while reading kind");
1721                                         return -1;
1722                                 }
1723
1724                                 if (kind != 'Z')
1725                                 {
1726                                         pool_error("s_do_auth: expecting Z got %c", kind);
1727                                         return -1;
1728                                 }
1729
1730                                 /* read message length */
1731                                 status = pool_read(cp->con, &length, sizeof(length));
1732                                 if (status < 0)
1733                                 {
1734                                         pool_error("s_do_auth: error while reading message length");
1735                                         return -1;
1736                                 }
1737                                 length = ntohl(length);
1738
1739                                 /* read transaction state */
1740                                 status = pool_read(cp->con, &state, sizeof(state));
1741                                 if (status < 0)
1742                                 {
1743                                         pool_error("s_do_auth: error while reading transaction state");
1744                                         return -1;
1745                                 }
1746
1747                                 pool_debug("s_do_auth: transaction state: %c", state);
1748                                 cp->con->tstate = state;
1749                                 return 0;
1750                                 break;
1751
1752                         case 'S':       /* parameter status */
1753                                 pool_debug("s_do_auth: parameter status data received");
1754
1755                                 status = pool_read(cp->con, &length, sizeof(length));
1756                                 if (status < 0)
1757                                 {
1758                                         pool_error("s_do_auth: error while reading message length");
1759                                         return -1;
1760                                 }
1761
1762                                 length = ntohl(length);
1763                                 length -= 4;
1764
1765                                 p = pool_read2(cp->con, length);
1766                                 if (p == NULL)
1767                                         return -1;
1768                                 break;
1769
1770                         default:
1771                                 pool_error("s_do_auth: unknown response \"%c\" before processing BackendKeyData",
1772                                                    kind);
1773                                 break;
1774                 }
1775         }
1776         return -1;
1777 }
1778
1779 /*
1780  * Count up connection counter (from frontend to pgpool)
1781  * in shared memory
1782  */
1783 static void connection_count_up(void)
1784 {
1785         pool_semaphore_lock(CONN_COUNTER_SEM);
1786         Req_info->conn_counter++;
1787         pool_semaphore_unlock(CONN_COUNTER_SEM);
1788 }
1789
1790 /*
1791  * Count down connection counter (from frontend to pgpool)
1792  * in shared memory
1793  */
1794 static void connection_count_down(void)
1795 {
1796         pool_semaphore_lock(CONN_COUNTER_SEM);
1797         /*
1798          * Make sure that we do not decrement too much.  If failed to read
1799          * a start up packet, or receive cancel request etc.,
1800          * connection_count_down() is called and goes back to the
1801          * connection accept loop. Problem is, at the very beginning of
1802          * the connection accept loop, if we have received a signal, we
1803          * call child_exit() which calls connection_count_down() again.
1804          */
1805         if (Req_info->conn_counter > 0)
1806                 Req_info->conn_counter--;
1807         pool_semaphore_unlock(CONN_COUNTER_SEM);
1808 }
1809
1810 /*
1811  * handle SIGUSR2
1812  * Wakeup all process
1813  */
1814 static RETSIGTYPE wakeup_handler(int sig)
1815 {
1816 }
1817
1818
1819 /*
1820  * Select load balancing node
1821  */
1822 int select_load_balancing_node(void)
1823 {
1824         double total_weight,r;
1825         int i;
1826
1827         /* choose a backend in random manner with weight */
1828         selected_slot = MASTER_NODE_ID;
1829         total_weight = 0.0;
1830
1831         for (i=0;i<NUM_BACKENDS;i++)
1832         {
1833                 if (VALID_BACKEND(i))
1834                 {
1835                         total_weight += BACKEND_INFO(i).backend_weight;
1836                 }
1837         }
1838         r = (((double)random())/RAND_MAX) * total_weight;
1839         total_weight = 0.0;
1840         for (i=0;i<NUM_BACKENDS;i++)
1841         {
1842                 if (VALID_BACKEND(i) && BACKEND_INFO(i).backend_weight > 0.0)
1843                 {
1844                         if(r >= total_weight)
1845                                 selected_slot = i;
1846                         else
1847                                 break;
1848                         total_weight += BACKEND_INFO(i).backend_weight;
1849                 }
1850         }
1851
1852         pool_debug("select_load_balancing_node: selected backend id is %d", selected_slot);
1853         return selected_slot;
1854 }
1855
1856 /* SIGHUP handler */
1857 static RETSIGTYPE reload_config_handler(int sig)
1858 {
1859         got_sighup = 1;
1860 }