CUBRID Engine  latest
tcp.c
Go to the documentation of this file.
1 /*
2  * Copyright 2008 Search Solution Corporation
3  * Copyright 2016 CUBRID Corporation
4  *
5  * Licensed under the Apache License, Version 2.0 (the "License");
6  * you may not use this file except in compliance with the License.
7  * You may obtain a copy of the License at
8  *
9  * http://www.apache.org/licenses/LICENSE-2.0
10  *
11  * Unless required by applicable law or agreed to in writing, software
12  * distributed under the License is distributed on an "AS IS" BASIS,
13  * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
14  * See the License for the specific language governing permissions and
15  * limitations under the License.
16  *
17  */
18 
19 
20 /*
21  * tcp.c - Open a TCP connection
22  */
23 
24 #ident "$Id$"
25 
26 #include "config.h"
27 
28 #include <netdb.h>
29 #include <stdio.h>
30 #include <stdlib.h>
31 #include <string.h>
32 #include <errno.h>
33 #include <time.h>
34 #include <signal.h>
35 #include <unistd.h>
36 #include <fcntl.h>
37 #include <sys/types.h>
38 #include <sys/time.h>
39 #include <sys/param.h>
40 #include <sys/socket.h>
41 #include <netdb.h>
42 #include <netinet/in.h>
43 #if !defined(WINDOWS)
44 #include <netinet/ip.h>
45 #include <netinet/ip_icmp.h>
46 #endif
47 #if defined(AIX)
48 #include <netinet/if_ether.h>
49 #include <net/if_dl.h>
50 #endif /* AIX */
51 #include <arpa/inet.h>
52 #include <sys/uio.h>
53 #include <sys/un.h>
54 #include <sys/ioctl.h>
55 #if defined(SOLARIS)
56 #include <sys/filio.h>
57 #endif /* SOLARIS */
58 #if defined(sun)
59 #include <sys/sockio.h>
60 #endif /* sun */
61 #if defined(LINUX)
62 #include <sys/stat.h>
63 #endif /* LINUX */
64 #include <netinet/tcp.h>
65 #include <assert.h>
66 
67 #include "porting.h"
68 #if defined(SERVER_MODE)
69 #include "connection_error.h"
70 #include "connection_sr.h"
71 #else /* SERVER_MODE */
72 #include "connection_cl.h"
73 #endif /* SERVER_MODE */
74 #include "error_manager.h"
75 #include "connection_globals.h"
76 #include "system_parameter.h"
77 #include "environment_variable.h"
78 #include "tcp.h"
79 
80 #ifndef HAVE_GETHOSTBYNAME_R
81 #include <pthread.h>
82 static pthread_mutex_t gethostbyname_lock = PTHREAD_MUTEX_INITIALIZER;
83 #endif /* HAVE_GETHOSTBYNAME_R */
84 
85 #define HOST_ID_ARRAY_SIZE 8 /* size of the host_id string */
86 #define TCP_MIN_NUM_RETRIES 3
87 #define CONTROLLEN (sizeof(struct cmsghdr) + sizeof(int))
88 #if !defined(INADDR_NONE)
89 #define INADDR_NONE 0xffffffff
90 #endif /* !INADDR_NONE */
91 
92 static const int css_Maximum_server_count = 1000;
93 
94 #if !defined (WINDOWS)
95 #define SET_NONBLOCKING(fd) { \
96  int flags = fcntl (fd, F_GETFL); \
97  flags |= O_NONBLOCK; \
98  fcntl (fd, F_SETFL, flags); \
99 }
100 #endif /* !WINDOWS */
101 
102 static void css_sockopt (SOCKET sd);
103 static int css_sockaddr (const char *host, int port, struct sockaddr *saddr, socklen_t * slen);
104 static int css_fd_error (SOCKET fd);
105 
106 /*
107  * Put the canonical name of the current host in name out variable.
108  * The result is null-terminated if namelen is large enough for the full name and the terminator.
109  * return: 0 if success, or error
110  * name(out): buffer for name
111  * namelen(in): max buffer size
112  */
113 int
114 css_gethostname (char *name, size_t namelen)
115 {
116  if (namelen <= 0)
117  {
118  return ER_FAILED;
119  }
120 
121  size_t namelen_ = (size_t) namelen;
122  addrinfo hints, *result = NULL;
123 
124  memset (&hints, 0, sizeof (hints));
125  hints.ai_family = AF_UNSPEC; // either IPV4 or IPV6
126  hints.ai_socktype = SOCK_STREAM;
127  hints.ai_flags = AI_CANONNAME;
128 
129  char hostname[namelen_];
130  hostname[namelen_ - 1] = '\0';
131  gethostname (hostname, namelen_);
132 
133  int gai_error = getaddrinfo (hostname, NULL, &hints, &result);
134  if (gai_error != 0)
135  {
137  return ER_GAI_ERROR;
138  }
139 
140  size_t canonname_size = strlen (result->ai_canonname) + 1; // +1 for NULL terminator
141  if (canonname_size > namelen_)
142  {
143  freeaddrinfo (result);
144  return ER_FAILED;
145  }
146 
147  memcpy (name, result->ai_canonname, canonname_size);
148  name[canonname_size] = '\0';
149 
150  freeaddrinfo (result);
151  return NO_ERROR;
152 }
153 
154 char *
156 {
157  static char path[PATH_MAX];
158  static bool need_init = true;
159 
160  if (need_init)
161  {
162  const char *cubrid_tmp = envvar_get ("TMP");
163 
164  if (cubrid_tmp == NULL || cubrid_tmp[0] == '\0')
165  {
166  cubrid_tmp = "/tmp";
167  }
168  snprintf (path, PATH_MAX, "%s/%s%d", cubrid_tmp, envvar_prefix (), prm_get_master_port_id ());
169  need_init = false;
170  }
171 
172  return path;
173 }
174 
175 /*
176  * css_tcp_client_open () -
177  * return:
178  * host(in):
179  * port(in):
180  */
181 SOCKET
182 css_tcp_client_open (const char *host, int port)
183 {
184  SOCKET fd;
185 
186  fd = css_tcp_client_open_with_retry (host, port, true);
187  if (IS_INVALID_SOCKET (fd))
188  {
190  }
191  return fd;
192 }
193 
194 static void
196 {
197  int bool_value = 1;
198 
200  {
201  setsockopt (sd, SOL_SOCKET, SO_RCVBUF, (int *) prm_get_value (PRM_ID_TCP_RCVBUF_SIZE), sizeof (int));
202  }
203 
205  {
206  setsockopt (sd, SOL_SOCKET, SO_SNDBUF, (int *) prm_get_value (PRM_ID_TCP_SNDBUF_SIZE), sizeof (int));
207  }
208 
210  {
211  setsockopt (sd, IPPROTO_TCP, TCP_NODELAY, (const char *) &bool_value, sizeof (bool_value));
212  }
213 
215  {
216  setsockopt (sd, SOL_SOCKET, SO_KEEPALIVE, (const char *) &bool_value, sizeof (bool_value));
217  }
218 }
219 
220 /*
221  * css_hostname_to_ip()
222  * return:
223  * host(in):
224  * ip_addr(out):
225  */
226 int
227 css_hostname_to_ip (const char *host, unsigned char *ip_addr)
228 {
229  in_addr_t in_addr;
230 
231  /*
232  * First try to convert to the host name as a dotted-decimal number.
233  * Only if that fails do we call gethostbyname.
234  */
235  in_addr = inet_addr (host);
236  if (in_addr != INADDR_NONE)
237  {
238  memcpy ((void *) ip_addr, (void *) &in_addr, sizeof (in_addr));
239  return NO_ERROR;
240  }
241  else
242  {
243 #ifdef HAVE_GETHOSTBYNAME_R
244 #if defined (HAVE_GETHOSTBYNAME_R_GLIBC)
245  struct hostent *hp, hent;
246  int herr;
247  char buf[1024];
248 
249  if (gethostbyname_r (host, &hent, buf, sizeof (buf), &hp, &herr) != 0 || hp == NULL)
250  {
253  }
254  memcpy ((void *) ip_addr, (void *) hent.h_addr, hent.h_length);
255 #elif defined (HAVE_GETHOSTBYNAME_R_SOLARIS)
256  struct hostent hent;
257  int herr;
258  char buf[1024];
259 
260  if (gethostbyname_r (host, &hent, buf, sizeof (buf), &herr) == NULL)
261  {
264  }
265  memcpy ((void *) ip_addr, (void *) hent.h_addr, hent.h_length);
266 #elif defined (HAVE_GETHOSTBYNAME_R_HOSTENT_DATA)
267  struct hostent hent;
268  struct hostent_data ht_data;
269 
270  if (gethostbyname_r (host, &hent, &ht_data) == -1)
271  {
274  }
275  memcpy ((void *) ip_addr, (void *) hent.h_addr, hent.h_length);
276 #else
277 #error "HAVE_GETHOSTBYNAME_R"
278 #endif
279 #else /* HAVE_GETHOSTBYNAME_R */
280  struct hostent *hp;
281 
283  hp = gethostbyname (host);
284  if (hp == NULL)
285  {
289  }
290  memcpy ((void *) ip_addr, (void *) hp->h_addr, hp->h_length);
292 #endif /* !HAVE_GETHOSTBYNAME_R */
293  }
294 
295  return NO_ERROR;
296 }
297 
298 /*
299  * css_sockaddr()
300  * return:
301  * host(in):
302  * port(in):
303  * saddr(out):
304  * slen(out):
305  */
306 static int
307 css_sockaddr (const char *host, int port, struct sockaddr *saddr, socklen_t * slen)
308 {
309  struct sockaddr_in tcp_saddr;
310  struct sockaddr_un unix_saddr;
311  in_addr_t in_addr;
312 
313  /*
314  * Construct address for TCP socket
315  */
316  memset ((void *) &tcp_saddr, 0, sizeof (tcp_saddr));
317  tcp_saddr.sin_family = AF_INET;
318  tcp_saddr.sin_port = htons (port);
319 
320  /*
321  * First try to convert to the host name as a dotten-decimal number.
322  * Only if that fails do we call gethostbyname.
323  */
324  in_addr = inet_addr (host);
325  if (in_addr != INADDR_NONE)
326  {
327  memcpy ((void *) &tcp_saddr.sin_addr, (void *) &in_addr, sizeof (in_addr));
328  }
329  else
330  {
331 #ifdef HAVE_GETHOSTBYNAME_R
332 #if defined (HAVE_GETHOSTBYNAME_R_GLIBC)
333  struct hostent *hp, hent;
334  int herr;
335  char buf[1024];
336 
337  if (gethostbyname_r (host, &hent, buf, sizeof (buf), &hp, &herr) != 0 || hp == NULL)
338  {
340  return INVALID_SOCKET;
341  }
342  memcpy ((void *) &tcp_saddr.sin_addr, (void *) hent.h_addr, hent.h_length);
343 #elif defined (HAVE_GETHOSTBYNAME_R_SOLARIS)
344  struct hostent hent;
345  int herr;
346  char buf[1024];
347 
348  if (gethostbyname_r (host, &hent, buf, sizeof (buf), &herr) == NULL)
349  {
351  return INVALID_SOCKET;
352  }
353  memcpy ((void *) &tcp_saddr.sin_addr, (void *) hent.h_addr, hent.h_length);
354 #elif defined (HAVE_GETHOSTBYNAME_R_HOSTENT_DATA)
355  struct hostent hent;
356  struct hostent_data ht_data;
357 
358  if (gethostbyname_r (host, &hent, &ht_data) == -1)
359  {
361  return INVALID_SOCKET;
362  }
363  memcpy ((void *) &tcp_saddr.sin_addr, (void *) hent.h_addr, hent.h_length);
364 #else
365 #error "HAVE_GETHOSTBYNAME_R"
366 #endif
367 #else /* HAVE_GETHOSTBYNAME_R */
368  struct hostent *hp;
369  int r;
370 
372  hp = gethostbyname (host);
373  if (hp == NULL)
374  {
377  return INVALID_SOCKET;
378  }
379  memcpy ((void *) &tcp_saddr.sin_addr, (void *) hp->h_addr, hp->h_length);
381 #endif /* !HAVE_GETHOSTBYNAME_R */
382  }
383 
384  /*
385  * Compare with the TCP address with localhost.
386  * If it is, use Unix domain socket rather than TCP for the performance
387  */
388  memcpy ((void *) &in_addr, (void *) &tcp_saddr.sin_addr, sizeof (in_addr));
389  if (in_addr == inet_addr ("127.0.0.1"))
390  {
391  memset ((void *) &unix_saddr, 0, sizeof (unix_saddr));
392  unix_saddr.sun_family = AF_UNIX;
393  strncpy (unix_saddr.sun_path, css_get_master_domain_path (), sizeof (unix_saddr.sun_path) - 1);
394  *slen = sizeof (unix_saddr);
395  memcpy ((void *) saddr, (void *) &unix_saddr, *slen);
396  }
397  else
398  {
399  *slen = sizeof (tcp_saddr);
400  memcpy ((void *) saddr, (void *) &tcp_saddr, *slen);
401  }
402 
403  return NO_ERROR;
404 }
405 
406 /*
407  * css_tcp_client_open_with_retry () -
408  * return:
409  * host(in):
410  * port(in):
411  * willretry(in):
412  */
413 SOCKET
414 css_tcp_client_open_with_retry (const char *host, int port, bool will_retry)
415 {
416  SOCKET sd = INVALID_SOCKET;
417  struct sockaddr *saddr;
418  socklen_t slen;
419  time_t start_contime;
420  int nsecs, sleep_nsecs = 1;
421  int success, num_retries = 0;
422  union
423  {
424  struct sockaddr_in in;
425  struct sockaddr_un un;
426  } saddr_buf;
427 
428  assert (host != NULL);
429  assert (port > 0);
430 
431  saddr = (struct sockaddr *) &saddr_buf;
432  if (css_sockaddr (host, port, saddr, &slen) != NO_ERROR)
433  return INVALID_SOCKET;
434 
435  start_contime = time (NULL);
436  do
437  {
438  sd = socket (saddr->sa_family, SOCK_STREAM, 0);
439  if (IS_INVALID_SOCKET (sd))
440  {
442  return INVALID_SOCKET;
443  }
444  else
445  {
446  css_sockopt (sd);
447  }
448 
449  /*
450  * If we get an ECONNREFUSED from the connect, we close the socket, and
451  * retry again. This is needed since the backlog parameter of the SUN
452  * machine is too small (See man page of listen...see BUG section).
453  * To avoid a possible infinite loop, we only retry five times
454  */
455  again_eintr:
456  if ((success = connect (sd, saddr, slen)) == 0)
457  {
458  /* connection is established successfully */
459  break;
460  }
461  if (errno == EINTR)
462  {
463  goto again_eintr;
464  }
465 
466  if ((errno == ECONNREFUSED || errno == ETIMEDOUT) && will_retry == true)
467  {
468  nsecs = (int) difftime (time (NULL), start_contime);
470  if (nsecs >= 0 && num_retries > TCP_MIN_NUM_RETRIES)
471  {
472  will_retry = false;
473  }
474  else
475  {
476  /*
477  * Wait a little bit to change the load of the server.
478  * Don't wait for more than 1/2 min or the timeout period
479  */
480  if (sleep_nsecs > 30)
481  {
482  sleep_nsecs = 30;
483  }
484 
485  /*
486  * Sleep only when we have not timed out. That is, when nsecs is
487  * negative.
488  */
489  if (nsecs < 0 && sleep_nsecs > (-nsecs))
490  {
491  sleep_nsecs = -nsecs;
492  }
493  if (nsecs < 0)
494  {
495  (void) sleep (sleep_nsecs);
496  sleep_nsecs *= 2; /* Go 1, 2, 4, 8, etc */
497  }
498  num_retries++;
499  }
500  }
501  else
502  {
503  will_retry = false; /* Don't retry */
504  }
505 
506  /*
507  * According to the Sun man page of connect & listen. When a connect
508  * was forcefully rejected. The calling program must close the
509  * socket descriptor, before another connect is retried.
510  *
511  * The server's host is probably overloaded. Sleep for a while, then
512  * try again. We sleep a different number of seconds between 1 and 30
513  * to avoid having the same situation with other processes that could
514  * have reached the timeout/refuse connection.
515  *
516  * The sleep time is guessing that the server is not going to be
517  * overloaded by connections in that amount of time.
518  *
519  * Similar things are suggested by R. Stevens Unix Network programming
520  * book. See Remote Command execution example in Chapter 14
521  *
522  * See connect and listen MAN pages.
523  */
524  close (sd);
525  sd = INVALID_SOCKET;
526  }
527  while (success < 0 && will_retry == true);
528 
529  if (success < 0)
530  {
531 #if defined(CUBRID_DEBUG)
532  er_log_debug (ARG_FILE_LINE, "css_tcp_client_open_with_retry:" "connection failed with retries %d errno %d\n",
533  num_retries, errno);
534 #endif /* CUBRID_DEBUG */
535  return INVALID_SOCKET;
536  }
537 
538  return sd;
539 }
540 
541 #if !defined (WINDOWS)
542 /*
543  * css_tcp_client_open_with_timeout() -
544  * return: socket descriptor
545  * host(in): host name
546  * port(in): port no
547  * timeout(in): timeout in milli-seconds
548  */
549 SOCKET
550 css_tcp_client_open_with_timeout (const char *host, int port, int timeout)
551 {
552  SOCKET sd = -1;
553  struct sockaddr *saddr;
554  socklen_t slen;
555  int n;
556  struct pollfd po[1] = { {0, 0, 0} };
557  union
558  {
559  struct sockaddr_in in;
560  struct sockaddr_un un;
561  } saddr_buf;
562 
563  assert (host != NULL);
564  assert (port > 0);
565  assert (timeout >= 0);
566 
567  saddr = (struct sockaddr *) &saddr_buf;
568  if (css_sockaddr (host, port, saddr, &slen) != NO_ERROR)
569  return INVALID_SOCKET;
570 
571  sd = socket (saddr->sa_family, SOCK_STREAM, 0);
572  if (sd < 0)
573  {
575  return INVALID_SOCKET;
576  }
577  else
578  {
579  css_sockopt (sd);
580  SET_NONBLOCKING (sd);
581  }
582 
583 again_eintr:
584  n = connect (sd, saddr, slen);
585  if (n == 0)
586  {
587  /* connection is established immediately */
588  return sd;
589  }
590  if (errno == EINTR)
591  {
592  goto again_eintr;
593  }
594 
595  if (errno != EINPROGRESS)
596  {
597  close (sd);
598 #if defined(CUBRID_DEBUG)
599  er_log_debug (ARG_FILE_LINE, "css_tcp_client_open_with_timeout:" "connect failed with errno %d", errno);
600 #endif /* CUBRID_DEBUG */
601  return INVALID_SOCKET;
602  }
603 
604 retry_poll:
605  po[0].fd = sd;
606  po[0].events = POLLOUT;
607  po[0].revents = 0;
608  n = poll (po, 1, timeout);
609  if (n < 0)
610  {
611  if (errno == EINTR)
612  {
613  goto retry_poll;
614  }
615 
616 #if defined(CUBRID_DEBUG)
617  er_log_debug (ARG_FILE_LINE, "css_tcp_client_open_with_timeout:" "poll failed errno %d", errno);
618 #endif /* CUBRID_DEBUG */
619  close (sd);
620  return INVALID_SOCKET;
621  }
622  else if (n == 0)
623  {
624  /* 0 means it timed out and no fd is changed */
625  errno = ETIMEDOUT;
626  close (sd);
627 #if defined(CUBRID_DEBUG)
628  er_log_debug (ARG_FILE_LINE, "css_tcp_client_open_with_timeout:" "poll failed with timeout %d", timeout);
629 #endif /* CUBRID_DEBUG */
630  return INVALID_SOCKET;
631  }
632 
633  /* has connection been established? */
634  slen = sizeof (n);
635  if (getsockopt (sd, SOL_SOCKET, SO_ERROR, (void *) &n, &slen) < 0)
636  {
637 #if defined(CUBRID_DEBUG)
638  er_log_debug (ARG_FILE_LINE, "css_tcp_client_open_with_timeout:" "getsockopt failed errno %d", errno);
639 #endif /* CUBRID_DEBUG */
640  close (sd);
641  return INVALID_SOCKET;
642  }
643  if (n != 0)
644  {
645 #if defined(CUBRID_DEBUG)
646  er_log_debug (ARG_FILE_LINE, "css_tcp_client_open_with_timeout:" "connection failed errno %d", n);
647 #endif /* CUBRID_DEBUG */
648  close (sd);
649  return INVALID_SOCKET;
650  }
651 
652  return sd;
653 }
654 #endif /* !WINDOWS */
655 
656 /*
657  * css_tcp_master_open () -
658  * return:
659  * port(in):
660  * sockfd(in):
661  */
662 int
663 css_tcp_master_open (int port, SOCKET * sockfd)
664 {
665  struct sockaddr_in tcp_srv_addr; /* server's internet socket addr */
666  struct sockaddr_un unix_srv_addr;
667  int retry_count = 0;
668  int reuseaddr_flag = 1;
669  struct stat unix_socket_stat;
670 
671  /*
672  * We have to create a socket ourselves and bind our well-known address to it.
673  */
674 
675  memset ((void *) &tcp_srv_addr, 0, sizeof (tcp_srv_addr));
676  tcp_srv_addr.sin_family = AF_INET;
677  tcp_srv_addr.sin_addr.s_addr = htonl (INADDR_ANY);
678 
679  if (port > 0)
680  {
681  tcp_srv_addr.sin_port = htons (port);
682  }
683  else
684  {
686  return ERR_CSS_TCP_PORT_ERROR;
687  }
688 
689  unix_srv_addr.sun_family = AF_UNIX;
690  strncpy (unix_srv_addr.sun_path, css_get_master_domain_path (), sizeof (unix_srv_addr.sun_path) - 1);
691 
692  /*
693  * Create the socket and Bind our local address so that any
694  * client may send to us.
695  */
696 
697 retry:
698  /*
699  * Allow the new master to rebind the CUBRID port even if there are
700  * clients with open connections from previous masters.
701  */
702 
703  sockfd[0] = socket (AF_INET, SOCK_STREAM, 0);
704  if (IS_INVALID_SOCKET (sockfd[0]))
705  {
708  }
709 
710  if (setsockopt (sockfd[0], SOL_SOCKET, SO_REUSEADDR, (char *) &reuseaddr_flag, sizeof (reuseaddr_flag)) < 0)
711  {
713  css_shutdown_socket (sockfd[0]);
714  return ERR_CSS_TCP_BIND_ABORT;
715  }
716 
717  if (bind (sockfd[0], (struct sockaddr *) &tcp_srv_addr, sizeof (tcp_srv_addr)) < 0)
718  {
719  if (errno == EADDRINUSE && retry_count <= 5)
720  {
721  retry_count++;
722  css_shutdown_socket (sockfd[0]);
723  (void) sleep (1);
724  goto retry;
725  }
727  css_shutdown_socket (sockfd[0]);
728  return ERR_CSS_TCP_BIND_ABORT;
729  }
730 
731  /*
732  * And set the listen parameter, telling the system that we're
733  * ready to accept incoming connection requests.
734  */
735  if (listen (sockfd[0], css_Maximum_server_count) != 0)
736  {
738  css_shutdown_socket (sockfd[0]);
740  }
741 
742  /*
743  * Since the master now forks /M drivers, make sure we do a close
744  * on exec on the socket.
745  */
746 #if defined(HPUX)
747  fcntl (sockfd[0], F_SETFD, 1);
748 #else /* HPUX */
749  ioctl (sockfd[0], FIOCLEX, 0);
750 #endif /* HPUX */
751 
752  if (access (css_get_master_domain_path (), F_OK) == 0)
753  {
754  if (stat (css_get_master_domain_path (), &unix_socket_stat) == -1)
755  {
756  /* stat() failed */
759  css_shutdown_socket (sockfd[0]);
761  }
762  if (!S_ISSOCK (unix_socket_stat.st_mode))
763  {
764  /* not socket file */
767  css_shutdown_socket (sockfd[0]);
769  }
770  if (unlink (css_get_master_domain_path ()) == -1)
771  {
772  /* unlink() failed */
775  css_shutdown_socket (sockfd[0]);
777  }
778  }
779 
780 retry2:
781 
782  sockfd[1] = socket (AF_UNIX, SOCK_STREAM, 0);
783  if (IS_INVALID_SOCKET (sockfd[1]))
784  {
786  css_shutdown_socket (sockfd[0]);
788  }
789 
790  if (setsockopt (sockfd[1], SOL_SOCKET, SO_REUSEADDR, (char *) &reuseaddr_flag, sizeof (reuseaddr_flag)) < 0)
791  {
793  css_shutdown_socket (sockfd[0]);
794  css_shutdown_socket (sockfd[1]);
795  return ERR_CSS_TCP_BIND_ABORT;
796  }
797 
798  if (bind (sockfd[1], (struct sockaddr *) &unix_srv_addr, sizeof (unix_srv_addr)) < 0)
799  {
800  if (errno == EADDRINUSE && retry_count <= 5)
801  {
802  retry_count++;
803  css_shutdown_socket (sockfd[1]);
804  (void) sleep (1);
805  goto retry2;
806  }
808  css_shutdown_socket (sockfd[0]);
809  css_shutdown_socket (sockfd[1]);
810  return ERR_CSS_TCP_BIND_ABORT;
811  }
812 
813  if (listen (sockfd[1], css_Maximum_server_count) != 0)
814  {
816  css_shutdown_socket (sockfd[0]);
817  css_shutdown_socket (sockfd[1]);
819  }
820 
821 #if defined(HPUX)
822  fcntl (sockfd[1], F_SETFD, 1);
823 #else /* HPUX */
824  ioctl (sockfd[1], FIOCLEX, 0);
825 #endif /* HPUX */
826 
827  return NO_ERROR;
828 }
829 
830 /*
831  * css_master_accept() - master accept of a request from a client
832  * return:
833  * sockfd(in):
834  */
835 SOCKET
837 {
838  struct sockaddr sa;
839  static SOCKET new_sockfd;
840  socklen_t clilen;
841  int boolean = 1;
842 
843  while (true)
844  {
845  clilen = sizeof (sa);
846  new_sockfd = accept (sockfd, &sa, &clilen);
847 
848  if (IS_INVALID_SOCKET (new_sockfd))
849  {
850  if (errno == EINTR)
851  {
852  errno = 0;
853  continue;
854  }
855 
857  return INVALID_SOCKET;
858  }
859 
860  break;
861  }
862 
863  if (sa.sa_family == AF_INET)
864  {
865  setsockopt (sockfd, IPPROTO_TCP, TCP_NODELAY, (char *) &boolean, sizeof (boolean));
866  }
867 
868  return new_sockfd;
869 }
870 
871 /*
872  * css_tcp_setup_server_datagram() - server datagram open support
873  * return:
874  * pathname(in):
875  * sockfd(in):
876  *
877  * Note: This will let the master server open a unix domain socket to the
878  * server to pass internet domain socket fds to the server. It returns
879  * the new socket fd
880  */
881 bool
882 css_tcp_setup_server_datagram (const char *pathname, SOCKET * sockfd)
883 {
884  int servlen;
885  struct sockaddr_un serv_addr;
886 
887  *sockfd = socket (AF_UNIX, SOCK_STREAM, 0);
888  if (IS_INVALID_SOCKET (*sockfd))
889  {
891  return false;
892  }
893 
894  memset ((void *) &serv_addr, 0, sizeof (serv_addr));
895  serv_addr.sun_family = AF_UNIX;
896  strncpy (serv_addr.sun_path, pathname, sizeof (serv_addr.sun_path) - 1);
897  servlen = strlen (pathname) + 1 + sizeof (serv_addr.sun_family);
898 
899  if (bind (*sockfd, (struct sockaddr *) &serv_addr, servlen) < 0)
900  {
902  return false;
903  }
904 
905  /*
906  * some operating system does not set the permission for unix domain socket.
907  * so a server can't connect to master which is initiated by other user.
908  */
909 #if defined(LINUX)
910  chmod (pathname, S_IRWXU | S_IRWXG | S_IRWXO);
911 #endif /* LINUX */
912 
913  if (listen (*sockfd, 5) != 0)
914  {
916  return false;
917  }
918 
919  return true;
920 }
921 
922 /*
923  * css_tcp_listen_server_datagram() - verifies that the pipe to the master has
924  * been setup properly
925  * return:
926  * sockfd(in):
927  * newfd(in):
928  */
929 bool
931 {
932  socklen_t clilen;
933  struct sockaddr_un cli_addr;
934  int boolean = 1;
935 
936  clilen = sizeof (cli_addr);
937 
938  while (true)
939  {
940  *newfd = accept (sockfd, (struct sockaddr *) &cli_addr, &clilen);
941  if (IS_INVALID_SOCKET (*newfd))
942  {
943  if (errno == EINTR)
944  {
945  continue;
946  }
947 
949  return false;
950  }
951 
952  break;
953  }
954 
955  setsockopt (sockfd, IPPROTO_TCP, TCP_NODELAY, (char *) &boolean, sizeof (boolean));
956 
957  return true;
958 }
959 
960 /*
961  * css_tcp_master_datagram() - master side of the datagram interface
962  * return:
963  * path_name(in):
964  * sockfd(in):
965  */
966 bool
967 css_tcp_master_datagram (char *path_name, SOCKET * sockfd)
968 {
969  int servlen;
970  struct sockaddr_un serv_addr;
971  bool will_retry = true;
972  int success = -1;
973  int num_retries = 0;
974 
975  memset ((void *) &serv_addr, 0, sizeof (serv_addr));
976  serv_addr.sun_family = AF_UNIX;
977  strncpy (serv_addr.sun_path, path_name, sizeof (serv_addr.sun_path) - 1);
978  servlen = strlen (serv_addr.sun_path) + 1 + sizeof (serv_addr.sun_family);
979 
980  do
981  {
982  /*
983  * If we get an ECONNREFUSED from the connect, we close the socket, and
984  * retry again. This is needed since the backlog parameter of the SUN
985  * machine is too small (See man page of listen...see BUG section).
986  * To avoid a possible infinite loop, we only retry few times
987  */
988  *sockfd = socket (AF_UNIX, SOCK_STREAM, 0);
989  if (IS_INVALID_SOCKET (*sockfd))
990  {
992  return false;
993  }
994 
995  again_eintr:
996  success = connect (*sockfd, (struct sockaddr *) &serv_addr, servlen);
997  if (success < 0)
998  {
999  if (errno == EINTR)
1000  {
1001  goto again_eintr;
1002  }
1003 
1004  if (errno == ECONNREFUSED || errno == ETIMEDOUT)
1005  {
1006 
1007  if (num_retries > TCP_MIN_NUM_RETRIES)
1008  {
1009  will_retry = false;
1010  }
1011  else
1012  {
1013  will_retry = true;
1014  num_retries++;
1015  }
1016  }
1017  else
1018  {
1019  will_retry = false; /* Don't retry */
1020  }
1021 
1022  close (*sockfd);
1023  *sockfd = INVALID_SOCKET;
1024  (void) sleep (1);
1025  continue;
1026  }
1027  break;
1028  }
1029  while (success < 0 && will_retry == true);
1030 
1031 
1032  if (success < 0)
1033  {
1035 #if defined(CUBRID_DEBUG)
1036  er_log_debug (ARG_FILE_LINE, "Failed with number of retries = %d during connection\n", num_retries);
1037 #endif /* CUBRID_DEBUG */
1038  return false;
1039  }
1040 
1041  if (num_retries > 0)
1042  {
1043 #if defined(CUBRID_DEBUG)
1044  er_log_debug (ARG_FILE_LINE, "Connected after number of retries = %d\n", num_retries);
1045 #endif /* CUBRID_DEBUG */
1046  }
1047 
1048  return true;
1049 }
1050 
1051 /*
1052  * css_open_new_socket_from_master() - the message interface to the master
1053  * server
1054  * return:
1055  * fd(in):
1056  * rid(in):
1057  */
1058 SOCKET
1059 css_open_new_socket_from_master (SOCKET fd, unsigned short *rid)
1060 {
1061  unsigned short req_id;
1062  SOCKET new_fd = INVALID_SOCKET;
1063  int rc;
1064  struct iovec iov[1];
1065  struct msghdr msg;
1066  int pid;
1067 #if defined(LINUX) || defined(AIX)
1068  static struct cmsghdr *cmptr = NULL;
1069 #endif /* LINUX || AIX */
1070 
1071  iov[0].iov_base = (char *) &req_id;
1072  iov[0].iov_len = sizeof (unsigned short);
1073  msg.msg_iov = iov;
1074  msg.msg_iovlen = 1;
1075  msg.msg_name = (caddr_t) NULL;
1076  msg.msg_namelen = 0;
1077 #if !defined(LINUX) && !defined(AIX)
1078  msg.msg_accrights = (caddr_t) & new_fd; /* address of descriptor */
1079  msg.msg_accrightslen = sizeof (new_fd); /* receive 1 descriptor */
1080 #else /* not LINUX and not AIX */
1081  if (cmptr == NULL && (cmptr = (struct cmsghdr *) malloc (CONTROLLEN)) == NULL)
1082  {
1083  return INVALID_SOCKET;
1084  }
1085  msg.msg_control = (void *) cmptr;
1086  msg.msg_controllen = CONTROLLEN;
1087 #endif /* not LINUX */
1088 
1089  rc = recvmsg (fd, &msg, 0);
1090  if (rc < 0)
1091  {
1092  TPRINTF ("recvmsg failed for fd = %d\n", rc);
1094  return INVALID_SOCKET;
1095  }
1096 
1097  *rid = ntohs (req_id);
1098 
1099  pid = getpid ();
1100 #if defined(LINUX) || defined(AIX)
1101  new_fd = *(SOCKET *) CMSG_DATA (cmptr);
1102 #endif /* LINUX || AIX */
1103 
1104 #ifdef SYSV
1105  ioctl (new_fd, SIOCSPGRP, (caddr_t) & pid);
1106 #else /* not SYSV */
1107  fcntl (new_fd, F_SETOWN, pid);
1108 #endif /* not SYSV */
1109 
1110  css_sockopt (new_fd);
1111  return new_fd;
1112 }
1113 
1114 /*
1115  * css_transfer_fd() - send the fd of a new client request to a server
1116  * return:
1117  * server_fd(in):
1118  * client_fd(in):
1119  * rid(in):
1120  */
1121 bool
1122 css_transfer_fd (SOCKET server_fd, SOCKET client_fd, unsigned short rid, CSS_SERVER_REQUEST request_for_server)
1123 {
1124  int request;
1125  unsigned short req_id;
1126  struct iovec iov[1];
1127  struct msghdr msg;
1128 #if defined(LINUX) || defined(AIX)
1129  static struct cmsghdr *cmptr = NULL;
1130 #endif /* LINUX || AIX */
1131 
1132  request = htonl (request_for_server);
1133  if (send (server_fd, (char *) &request, sizeof (int), 0) < 0)
1134  {
1135  /* Master->Server link down. remove old link, and try again. */
1137  return false;
1138  }
1139  req_id = htons (rid);
1140 
1141  /* Pass the fd to the server */
1142  iov[0].iov_base = (char *) &req_id;
1143  iov[0].iov_len = sizeof (unsigned short);
1144  msg.msg_iov = iov;
1145  msg.msg_iovlen = 1;
1146  msg.msg_namelen = 0;
1147  msg.msg_name = (caddr_t) 0;
1148 #if !defined(LINUX) && !defined(AIX)
1149  msg.msg_accrights = (caddr_t) & client_fd;
1150  msg.msg_accrightslen = sizeof (client_fd);
1151 #else /* LINUX || AIX */
1152  if (cmptr == NULL && (cmptr = (struct cmsghdr *) malloc (CONTROLLEN)) == NULL)
1153  {
1154  return false;
1155  }
1156  cmptr->cmsg_level = SOL_SOCKET;
1157  cmptr->cmsg_type = SCM_RIGHTS;
1158  cmptr->cmsg_len = CONTROLLEN;
1159  msg.msg_control = (void *) cmptr;
1160  msg.msg_controllen = CONTROLLEN;
1161  *(SOCKET *) CMSG_DATA (cmptr) = client_fd;
1162 #endif /* LINUX || AIX */
1163 
1164  if (sendmsg (server_fd, &msg, 0) < 0)
1165  {
1167  return false;
1168  }
1169 
1170  return true;
1171 }
1172 
1173 /*
1174  * css_shutdown_socket() -
1175  * return:
1176  * fd(in):
1177  */
1178 void
1180 {
1181  int rc;
1182 
1183  if (!IS_INVALID_SOCKET (fd))
1184  {
1185  again_eintr:
1186  rc = close (fd);
1187  if (rc != 0)
1188  {
1189  if (errno == EINTR)
1190  {
1191  goto again_eintr;
1192  }
1193 #if defined(CUBRID_DEBUG)
1195 #endif /* CUBRID_DEBUG */
1196  }
1197  }
1198 }
1199 
1200 /*
1201  * css_gethostid() - returns the 32 bit host identifier for this machine
1202  * return: 32 bit host identifier
1203  *
1204  * Note: Used for host key validation and some other purposes. Uses gethostid()
1205  * on the Sun machines, for the rest, it tries to determine the IP
1206  * address and encodes that as a 32 bit value.
1207  */
1208 unsigned int
1210 {
1211  unsigned int id = 0;
1212 
1213 #ifdef HAVE_GETHOSTID
1214  id = (unsigned int) gethostid ();
1215 #endif /* !HAVE_GETHOSTID */
1216  return id;
1217 }
1218 
1219 /*
1220  * css_open_server_connection_socket() -
1221  * return:
1222  *
1223  * Note: Stub functions for the new-style connection protocol.
1224  * Eventually should try to support these on non-NT platforms.
1225  * See also wintcp.c
1226  */
1227 int
1229 {
1230  return -1;
1231 }
1232 
1233 /*
1234  * css_close_server_connection_socket() -
1235  * return; void
1236  *
1237  * Note: Stub functions for the new-style connection protocol.
1238  * Eventually should try to support these on non-NT platforms.
1239  * See also wintcp.c
1240  */
1241 void
1243 {
1244 }
1245 
1246 /*
1247  * css_server_accept() -
1248  * return:
1249  * sockfd(in):
1250  *
1251  * Note: Stub functions for the new-style connection protocol.
1252  * Eventually should try to support these on non-NT platforms.
1253  * See also wintcp.c
1254  */
1255 SOCKET
1257 {
1258  return INVALID_SOCKET;
1259 }
1260 
1261 /*
1262  * css_fd_error() -
1263  * return:
1264  * fd(in):
1265  */
1266 static int
1268 {
1269  int rc = 0, count = 0;
1270 
1271 again_:
1272  errno = 0;
1273  rc = ioctl (fd, FIONREAD, (caddr_t) & count);
1274  if (rc < 0)
1275  {
1276  if (errno == EINTR)
1277  {
1278  goto again_;
1279  }
1280  else
1281  {
1282  return rc;
1283  }
1284  }
1285 
1286  return count;
1287 }
1288 
1289 #if defined (ENABLE_UNUSED_FUNCTION)
1290 /*
1291  * css_fd_down() -
1292  * return:
1293  * fd(in):
1294  */
1295 int
1296 css_fd_down (SOCKET fd)
1297 {
1298  int error_code;
1299  socklen_t error_size = sizeof (socklen_t);
1300  int rc = 0;
1301 
1302  if (getsockopt (fd, SOL_SOCKET, SO_ERROR, (char *) &error_code, &error_size) >= 0)
1303  {
1304  if (error_code > 0 || css_fd_error (fd) <= 0)
1305  {
1306  rc = 1;
1307  }
1308  }
1309 
1310  return rc;
1311 }
1312 #endif
1313 
1314 int
1316 {
1317  return (int) sysconf (_SC_OPEN_MAX);
1318 }
1319 
1320 #define SET_NONBLOCKING(fd) { \
1321  int flags = fcntl (fd, F_GETFL); \
1322  flags |= O_NONBLOCK; \
1323  fcntl (fd, F_SETFL, flags); \
1324 }
1325 
1326 /*
1327  * in_cksum - Checksum routine for Internet Protocol family headers
1328  */
1329 static int
1330 in_cksum (u_short * addr, int len)
1331 {
1332  int nleft = len;
1333  u_short *w = addr;
1334  int sum = 0;
1335  u_short answer = 0;
1336 
1337  /*
1338  * Our algorithm is simple, using a 32 bit accumulator (sum), we add
1339  * sequential 16 bit words to it, and at the end, fold back all the
1340  * carry bits from the top 16 bits into the lower 16 bits.
1341  */
1342  while (nleft > 1)
1343  {
1344  sum += *w++;
1345  nleft -= 2;
1346  }
1347 
1348  /* mop up an odd byte, if necessary */
1349  if (nleft == 1)
1350  {
1351  *(u_char *) (&answer) = *(u_char *) w;
1352  sum += answer;
1353  }
1354 
1355  /* add back carry outs from top 16 bits to low 16 bits */
1356  sum = (sum >> 16) + (sum & 0xffff); /* add hi 16 to low 16 */
1357  sum += (sum >> 16); /* add carry */
1358  answer = ~sum; /* truncate to 16 bits */
1359  return (answer);
1360 }
1361 
1362 #if defined(ENABLE_UNUSED_FUNCTION)
1363 /*
1364  * css_ping() - ping implementation
1365  * Send a ICMP_ECHO_REQUEST packet every second until either the
1366  * timeout expires or a answer is received.
1367  * return: 0 if an ICMP_ECHO_REPLY is received, otherwise errno
1368  * ETIME if timed out
1369  * sd(in): raw socket
1370  * sa_send(in): peer address
1371  * timeout(in): timeout in mili seconds
1372  */
1373 int
1374 css_ping (SOCKET sd, struct sockaddr_in *sa_send, int timeout)
1375 {
1376  char sendbuf[1500], recvbuf[1500];
1377  struct icmp *icmp;
1378  struct ip *ip;
1379  struct sockaddr_in sa_recv;
1380  struct timeval tv;
1381  fd_set fds;
1382  uint16_t pid;
1383  int size, seq, n, hlen;
1384  size_t plen;
1385  socklen_t slen;
1386 
1387  /* icmp_id is a 16 bit data type, therefore down cast the pid */
1388  pid = (uint16_t) getpid ();
1389  size = 60 * 1024;
1390  setsockopt (sd, SOL_SOCKET, SO_RCVBUF, &size, sizeof (size));
1391 
1392  /* make the socket non blocking so we can use select */
1393  SET_NONBLOCKING (sd);
1394 
1395  seq = 0;
1396  do
1397  {
1398  /* create the ICMP request */
1399  icmp = (struct icmp *) sendbuf;
1400  icmp->icmp_type = ICMP_ECHO;
1401  icmp->icmp_code = 0;
1402  icmp->icmp_id = htons (pid);
1403  icmp->icmp_seq = htons (seq);
1404  seq++;
1405  gettimeofday (&tv, NULL);
1406  memcpy (icmp->icmp_data, &tv, sizeof (tv));
1407  plen = ICMP_ADVLENMIN + sizeof (tv);
1408  icmp->icmp_cksum = 0;
1409  icmp->icmp_cksum = in_cksum ((u_short *) icmp, plen);
1410  /* send it */
1411  n = sendto (sd, sendbuf, plen, 0, (struct sockaddr *) sa_send, sizeof (struct sockaddr));
1412  if (n < 0 && errno != EINPROGRESS)
1413  {
1414  er_log_debug (ARG_FILE_LINE, "css_ping: can't send ICMP packet to %s errno %d\n",
1415  inet_ntoa (sa_send->sin_addr), errno);
1416  close (sd);
1417  return errno;
1418  }
1419 
1420  FD_ZERO (&fds);
1421  FD_SET (sd, &fds);
1422  /* wait one second */
1423  tv.tv_sec = timeout >= 1000 ? 1 : 0;
1424  tv.tv_usec = timeout >= 1000 ? 0 : timeout * 1000;
1425  n = select (sd + 1, &fds, NULL, NULL, &tv);
1426  if (n < 0 && errno != EINTR)
1427  {
1428  er_log_debug (ARG_FILE_LINE, "css_ping: select() errno %d\n", errno);
1429  close (sd);
1430  return errno;
1431  }
1432  if (n > 0)
1433  {
1434  /* something is available to read */
1435  slen = sizeof (sa_recv);
1436  n = recvfrom (sd, recvbuf, sizeof (recvbuf), 0, (struct sockaddr *) &sa_recv, &slen);
1437  ip = (struct ip *) recvbuf;
1438  hlen = (ip->ip_hl) << 2;
1439  icmp = (struct icmp *) (recvbuf + hlen);
1440  /*
1441  * We did received somthing, but is it what we were expecting?
1442  * Is is ICMP_ECHO_REPLY packet with the proper PID value?
1443  */
1444  if ((n - hlen >= 8) && icmp->icmp_type == ICMP_ECHOREPLY && (ntohs (icmp->icmp_id) == pid)
1445  && (sa_send->sin_addr.s_addr == sa_recv.sin_addr.s_addr))
1446  {
1447  /* er_log_debug (ARG_FILE_LINE, "css_ping: success\n"); */
1448  close (sd);
1449  return 0;
1450  }
1451  }
1452  timeout -= 1000;
1453  }
1454  while (timeout > 0);
1455  /* timed out */
1456  er_log_debug (ARG_FILE_LINE, "css_ping: timed out\n");
1457  close (sd);
1458  return ETIME;
1459 }
1460 #endif
1461 
1462 /*
1463  * css_peer_alive() - check if the peer is alive or not
1464  * Try to ping the peer or connect to the port 7 (ECHO)
1465  * return: true or false
1466  * sd(in): socket descriptor connected to the peer
1467  * timeout(in): timeout in mili seconds
1468  */
1469 bool
1470 css_peer_alive (SOCKET sd, int timeout)
1471 {
1472  SOCKET nsd;
1473  int n;
1474  socklen_t size;
1475  struct sockaddr_in saddr;
1476  socklen_t slen;
1477  struct pollfd po[1];
1478 
1479 #if defined (CS_MODE)
1480  er_log_debug (ARG_FILE_LINE, "The css_peer_alive() is calling.");
1481 #endif
1482 
1483  slen = sizeof (saddr);
1484  if (getpeername (sd, (struct sockaddr *) &saddr, &slen) < 0)
1485  {
1486  er_log_debug (ARG_FILE_LINE, "css_peer_alive: returning errno %d from getpeername()\n", errno);
1487  return false;
1488  }
1489 
1490  /* if Unix domain socket, the peer(=local) is alive always */
1491  if (saddr.sin_family != AF_INET)
1492  {
1493  return true;
1494  }
1495 
1496 #if 0 /* temporarily disabled */
1497  /* try to make raw socket to ping the peer */
1498  if ((nsd = socket (AF_INET, SOCK_RAW, IPPROTO_ICMP)) >= 0)
1499  {
1500  return (css_ping (nsd, &saddr, timeout) == 0);
1501  }
1502 #endif
1503  /* failed to make a ICMP socket; try to connect to the port ECHO */
1504  if ((nsd = socket (AF_INET, SOCK_STREAM, 0)) < 0)
1505  {
1506  er_log_debug (ARG_FILE_LINE, "css_peer_alive: errno %d from socket(SOCK_STREAM)\n", errno);
1507  return false;
1508  }
1509 
1510  /* make the socket non blocking so we can use select */
1511  SET_NONBLOCKING (nsd);
1512 
1513  saddr.sin_port = htons (7); /* port ECHO */
1514  n = connect (nsd, (struct sockaddr *) &saddr, slen);
1515 
1516  /*
1517  * Connection will be established or refused immediately.
1518  * Either way it means that the peer host is alive.
1519  */
1520  if (n == 0 || (n < 0 && errno == ECONNREFUSED))
1521  {
1522  close (nsd);
1523  return true;
1524  }
1525 
1526  switch (errno)
1527  {
1528  case EINPROGRESS: /* non-blocking, asynchronously */
1529  break;
1530  case ENETUNREACH: /* network unreachable */
1531  case EAFNOSUPPORT: /* address family not supported */
1532  case EADDRNOTAVAIL: /* address is not available on the remote machine */
1533  case EINVAL: /* on some linux, connecting to the loopback */
1534  er_log_debug (ARG_FILE_LINE, "css_peer_alive: errno %d from connect()\n", errno);
1535  close (nsd);
1536  return false;
1537  default: /* otherwise, connection failed */
1538  er_log_debug (ARG_FILE_LINE, "css_peer_alive: errno %d from connect()\n", errno);
1539  close (nsd);
1540  return false;
1541  }
1542 
1543 retry_poll:
1544  po[0].fd = nsd;
1545  po[0].events = POLLOUT;
1546  po[0].revents = 0;
1547  n = poll (po, 1, timeout);
1548  if (n < 0)
1549  {
1550  if (errno == EINTR)
1551  {
1552  goto retry_poll;
1553  }
1554  er_log_debug (ARG_FILE_LINE, "css_peer_alive: errno %d from poll()\n", errno);
1555  close (nsd);
1556  return false;
1557  }
1558  else if (n == 0)
1559  {
1560  er_log_debug (ARG_FILE_LINE, "css_peer_alive: timed out %d\n", timeout);
1561  close (nsd);
1562  return false;
1563  }
1564 
1565  /* has connection been established? */
1566  size = sizeof (n);
1567  if (getsockopt (nsd, SOL_SOCKET, SO_ERROR, (void *) &n, &size) < 0)
1568  {
1569  er_log_debug (ARG_FILE_LINE, "css_peer_alive: getsockopt() return error %d\n", errno);
1570  close (nsd);
1571  return false;
1572  }
1573 
1574  if (n == 0 || n == ECONNREFUSED)
1575  {
1576  close (nsd);
1577  return true;
1578  }
1579 
1580  er_log_debug (ARG_FILE_LINE, "css_peer_alive: errno %d from connect()\n", n);
1581  close (nsd);
1582  return false;
1583 }
1584 
1585 /*
1586  * css_get_peer_name() - get the hostname of the peer socket
1587  * return: 0 if success; otherwise errno
1588  * hostname(in): buffer for hostname
1589  * len(in): size of the hostname buffer
1590  */
1591 int
1592 css_get_peer_name (SOCKET sockfd, char *hostname, size_t len)
1593 {
1594  union
1595  {
1596  struct sockaddr_in in;
1597  struct sockaddr_un un;
1598  } saddr_buf;
1599  struct sockaddr *saddr;
1600  socklen_t saddr_len;
1601 
1602  saddr = (struct sockaddr *) &saddr_buf;
1603  saddr_len = sizeof (saddr_buf);
1604  if (getpeername (sockfd, saddr, &saddr_len) != 0)
1605  {
1606  return errno;
1607  }
1608  return getnameinfo (saddr, saddr_len, hostname, len, NULL, 0, NI_NOFQDN);
1609 }
1610 
1611 /*
1612  * css_get_sock_name() - get the hostname of the socket
1613  * return: 0 if success; otherwise errno
1614  * hostname(in): buffer for hostname
1615  * len(in): size of the hostname buffer
1616  */
1617 int
1618 css_get_sock_name (SOCKET sockfd, char *hostname, size_t len)
1619 {
1620  union
1621  {
1622  struct sockaddr_in in;
1623  struct sockaddr_un un;
1624  } saddr_buf;
1625  struct sockaddr *saddr;
1626  socklen_t saddr_len;
1627 
1628  saddr = (struct sockaddr *) &saddr_buf;
1629  saddr_len = sizeof (saddr_buf);
1630  if (getsockname (sockfd, saddr, &saddr_len) != 0)
1631  {
1632  return errno;
1633  }
1634  return getnameinfo (saddr, saddr_len, hostname, len, NULL, 0, NI_NOFQDN);
1635 }
#define NO_ERROR
Definition: error_code.h:46
void css_close_server_connection_socket(void)
Definition: tcp.c:1242
bool css_tcp_listen_server_datagram(SOCKET sockfd, SOCKET *newfd)
Definition: tcp.c:930
#define ERR_CSS_TCP_CANNOT_CREATE_SOCKET
Definition: error_code.h:427
int SOCKET
Definition: porting.h:482
#define ERR_CSS_TCP_CANNOT_CREATE_STREAM
Definition: error_code.h:431
#define ERR_CSS_TCP_DATAGRAM_ACCEPT
Definition: error_code.h:436
int css_hostname_to_ip(const char *host, unsigned char *ip_addr)
Definition: tcp.c:227
unsigned int htonl(unsigned int from)
#define ER_FAILED
Definition: error_code.h:47
#define pthread_mutex_unlock(a)
Definition: area_alloc.c:51
SOCKET css_tcp_client_open_with_retry(const char *host, int port, bool will_retry)
Definition: tcp.c:414
#define ERR_CSS_TCP_BIND_ABORT
Definition: error_code.h:433
SOCKET fd
int css_gethostname(char *name, size_t namelen)
Definition: tcp.c:114
#define ERR_CSS_TCP_PASSING_FD
Definition: error_code.h:440
#define SET_NONBLOCKING(fd)
Definition: tcp.c:1320
int css_get_max_socket_fds(void)
Definition: tcp.c:1315
static int in_cksum(u_short *addr, int len)
Definition: tcp.c:1330
#define er_log_debug(...)
bool css_tcp_setup_server_datagram(const char *pathname, SOCKET *sockfd)
Definition: tcp.c:882
#define INVALID_SOCKET
Definition: porting.h:483
#define ERR_CSS_TCP_HOST_NAME_ERROR
Definition: error_code.h:426
bool css_transfer_fd(SOCKET server_fd, SOCKET client_fd, unsigned short rid, CSS_SERVER_REQUEST request_for_server)
Definition: tcp.c:1122
static pthread_mutex_t gethostbyname_lock
Definition: tcp.c:82
void * prm_get_value(PARAM_ID prm_id)
#define INADDR_NONE
Definition: tcp.c:89
#define ERR_CSS_TCP_PORT_ERROR
Definition: error_code.h:425
#define ERR_CSS_TCP_DATAGRAM_CONNECT
Definition: error_code.h:437
void er_set(int severity, const char *file_name, const int line_no, int err_id, int num_args,...)
#define assert(x)
int prm_get_integer_value(PARAM_ID prm_id)
#define ER_GENERIC_ERROR
Definition: error_code.h:49
SOCKET css_tcp_client_open(const char *host, int port)
Definition: tcp.c:182
#define TCP_MIN_NUM_RETRIES
Definition: tcp.c:86
const char * envvar_prefix(void)
int prm_get_master_port_id(void)
#define IS_INVALID_SOCKET(socket)
Definition: porting.h:484
SOCKET css_server_accept(SOCKET sockfd)
Definition: tcp.c:1256
#define ERR_CSS_TCP_DATAGRAM_BIND
Definition: error_code.h:435
static const int css_Maximum_server_count
Definition: tcp.c:92
void css_shutdown_socket(SOCKET fd)
Definition: tcp.c:1179
#define NULL
Definition: freelistheap.h:34
pid_t pid
Definition: dynamic_load.c:955
unsigned short htons(unsigned short from)
static int success()
bool css_peer_alive(SOCKET sd, int timeout)
Definition: tcp.c:1470
#define CONTROLLEN
Definition: tcp.c:87
#define TPRINTF(error_string, arg)
SOCKET css_open_new_socket_from_master(SOCKET fd, unsigned short *rid)
Definition: tcp.c:1059
static int css_sockaddr(const char *host, int port, struct sockaddr *saddr, socklen_t *slen)
Definition: tcp.c:307
static int css_fd_error(SOCKET fd)
Definition: tcp.c:1267
void er_set_with_oserror(int severity, const char *file_name, const int line_no, int err_id, int num_args,...)
int count(int &result, const cub_regex_object &reg, const std::string &src, const int position, const INTL_CODESET codeset)
#define ER_BO_UNABLE_TO_FIND_HOSTNAME
Definition: error_code.h:180
bool css_tcp_master_datagram(char *path_name, SOCKET *sockfd)
Definition: tcp.c:967
const char * envvar_get(const char *name)
unsigned int css_gethostid(void)
Definition: tcp.c:1209
static int rc
Definition: serial.c:50
#define ERR_CSS_TCP_RECVMSG
Definition: error_code.h:439
int css_ping(SOCKET sd, struct sockaddr_in *sa_send, int timeout)
#define ARG_FILE_LINE
Definition: error_manager.h:44
char * css_get_master_domain_path(void)
Definition: tcp.c:155
unsigned short ntohs(unsigned short from)
SOCKET css_tcp_client_open_with_timeout(const char *host, int port, int timeout)
Definition: tcp.c:550
#define strlen(s1)
Definition: intl_support.c:43
#define ERR_CSS_TCP_ACCEPT_ERROR
Definition: error_code.h:434
int css_tcp_master_open(int port, SOCKET *sockfd)
Definition: tcp.c:663
bool prm_get_bool_value(PARAM_ID prm_id)
#define ER_GAI_ERROR
Definition: error_code.h:1604
#define ERR_CSS_TCP_CANNOT_CONNECT_TO_MASTER
Definition: error_code.h:429
int css_get_peer_name(SOCKET sockfd, char *hostname, size_t len)
Definition: tcp.c:1592
int css_get_sock_name(SOCKET sockfd, char *hostname, size_t len)
Definition: tcp.c:1618
enum css_server_request CSS_SERVER_REQUEST
#define pthread_mutex_lock(a)
Definition: area_alloc.c:50
static void css_sockopt(SOCKET sd)
Definition: tcp.c:195
static char * host
int css_open_server_connection_socket(void)
Definition: tcp.c:1228
#define ERR_CSS_UNIX_DOMAIN_SOCKET_FILE_EXIST
Definition: error_code.h:432
SOCKET css_master_accept(SOCKET sockfd)
Definition: tcp.c:836
#define ERR_CSS_TCP_DATAGRAM_SOCKET
Definition: error_code.h:438