ze-filter  (ze-filter-0.8.0-develop-180218)
ze-grey-client.c
Go to the documentation of this file.
1 
2 /*
3  *
4  * ze-filter - Mail Server Filter for sendmail
5  *
6  * Copyright (c) 2001-2018 - Jose-Marcio Martins da Cruz
7  *
8  * Auteur : Jose Marcio Martins da Cruz
9  * jose.marcio.mc@gmail.org
10  *
11  * Historique :
12  * Creation : Thu Feb 10 21:19:57 CET 2005
13  *
14  * This program is free software, but with restricted license :
15  *
16  *
17  * This program is distributed in the hope that it will be useful,
18  * but WITHOUT ANY WARRANTY; without even the implied warranty of
19  * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.
20  *
21  * More details about ze-filter license can be found at ze-filter
22  * web site : http://foss.jose-marcio.org
23  */
24 
25 
26 #include <ze-sys.h>
27 #include <libze.h>
28 #include <ze-filter.h>
29 #include <ze-grey-client.h>
30 
31 
32 /* ****************************************************************************
33  * *
34  * *
35  **************************************************************************** */
36 
37 #define DEBUG_LEVEL 12
38 
39 static char *greysock = "inet:2012@localhost";
40 
41 typedef struct greychan_T greychan_T;
42 
43 struct greychan_T {
44  bool ok;
45  int socktype;
46 
47  int inetport;
48  char *inethost;
49 
50  char *sockname;
51 
52  int sd;
53 
54  time_t recv_timeout;
55  time_t send_timeout;
56 };
57 
58 static greychan_T gChan = { FALSE, AF_UNSPEC, 0, NULL, NULL, -1, 10, 10 };
59 
60 static pthread_mutex_t grcl_mutex = PTHREAD_MUTEX_INITIALIZER;
61 
62 static int grey_server_disconnect();
63 static int grey_server_connect();
64 
65 static void grey_errors_clear();
66 
67 static bool grey_socket_flush_read();
68 
69 
70 /* ****************************************************************************
71  * *
72  * *
73  **************************************************************************** */
74 #define GREY_CONN_INC() grey_queue_check_size(1)
75 #define GREY_CONN_DEC() grey_queue_check_size(-1)
76 #define GREY_CONN_CHECK() grey_queue_check_size(0)
77 
78 
79 #define MAX_OPEN_CONN 50
80 static int grey_connections = 0;
81 
82 static bool
83 grey_queue_check_size(n)
84  int n;
85 {
86  static pthread_mutex_t wmutex = PTHREAD_MUTEX_INITIALIZER;
87  bool result = TRUE;
88 
89  MUTEX_LOCK(&wmutex);
90  grey_connections += n;
91  if (grey_connections >= MAX_OPEN_CONN)
92  result = FALSE;
93  MUTEX_UNLOCK(&wmutex);
94  return result;
95 }
96 
97 /* ****************************************************************************
98  * *
99  * *
100  **************************************************************************** */
101 #define SRV_ERR_MAX 4
102 
103 #define SRV_MIN_ERR_DELAY (1 MINUTES)
104 #define SRV_MAX_ERR_DELAY (8 MINUTES)
105 
106 static time_t error_last = (time_t) 0;
107 static int error_count = 0;
108 static time_t dt_error = SRV_MIN_ERR_DELAY;
109 
110 static pthread_mutex_t err_mutex = PTHREAD_MUTEX_INITIALIZER;
111 
112 static bool
113 grey_server_error_inc_and_check(inc)
114  bool inc;
115 {
116  time_t now = time(NULL);
117  bool res = FALSE;
118 
119  if (inc) {
120  error_count++;
121  if (error_count < SRV_ERR_MAX)
122  error_last = now;
123 
124  if (error_count == SRV_ERR_MAX) {
125  dt_error *= 2;
126  dt_error = MIN(dt_error, SRV_MAX_ERR_DELAY);
127  ZE_MessageWarning(9, "Too many errors (%d) - "
128  "disabling remote check for %d seconds", SRV_ERR_MAX,
129  dt_error);
130 
131  grey_server_disconnect();
132  }
133  }
134 
135  res = (error_count < SRV_ERR_MAX) || (error_last + dt_error < now);
136 
137  return res;
138 }
139 
140 static void
141 grey_errors_clear()
142 {
143  error_count = 0;
144  dt_error = SRV_MIN_ERR_DELAY;
145 }
146 
147 void
149 {
150  MUTEX_LOCK(&err_mutex);
151 
152  if (error_count >= SRV_ERR_MAX && gChan.sd >= 0)
153  grey_server_disconnect();
154 
155  grey_errors_clear();
156 
157  MUTEX_UNLOCK(&err_mutex);
158 }
159 
160 /* ****************************************************************************
161  * *
162  * *
163  **************************************************************************** */
164 static bool
165 grey_socket_check(sd)
166  int sd;
167 {
168  struct pollfd pfd;
169  int res = 0;
170 
171  if (sd < 0)
172  return FALSE;
173 
174  memset(&pfd, 0, sizeof (pfd));
175 
176  pfd.fd = sd;
177  pfd.events = POLLIN | POLLOUT;
178 
179  if ((res = poll(&pfd, 1, 0)) < 0)
180  ZE_LogSysError("poll error");
181 
182  return (res >= 0);
183 }
184 
185 /* ****************************************************************************
186  * *
187  * *
188  **************************************************************************** */
189 static bool
190 grey_socket_decode(arg)
191  char *arg;
192 {
193  char *p = arg;
194  char *s = "unix:";
195 
196  FREE(gChan.sockname);
197  FREE(gChan.inethost);
198  gChan.socktype = -1;
199  gChan.inetport = -1;
200 
201  if (strncasecmp(p, s, strlen(s)) == 0) {
202  p += strlen(s);
203  if (strlen(p) > 0) {
204  if ((gChan.sockname = strdup(p)) == NULL) {
205  ZE_LogSysError("strdup(sockname) error");
206  return FALSE;
207  }
208  }
209  gChan.socktype = AF_UNIX;
210  return TRUE;
211  }
212 
213  s = "local:";
214  if (strncasecmp(p, s, strlen(s)) == 0) {
215  p += strlen(s);
216  if (strlen(p) > 0) {
217  if ((gChan.sockname = strdup(p)) == NULL) {
218  ZE_LogSysError("strdup(sockname) error");
219  return FALSE;
220  }
221  }
222  gChan.socktype = AF_UNIX;
223  return TRUE;
224  }
225 
226  s = "inet:";
227  if (strncasecmp(p, s, strlen(s)) == 0) {
228  char tmp[16];
229  int n;
230 
231  p += strlen(s);
232  n = strspn(p, "0123456789");
233  if ((n > 0) && (n < sizeof (tmp))) {
234  strncpy(tmp, p, n);
235  tmp[n] = '\0';
236 
237  gChan.inetport = atoi(tmp);
238 
239  p += n;
240  if (*p == '@')
241  p++;
242  if (strlen(p) > 0)
243  gChan.inethost = strdup(p);
244  else
245  gChan.inethost = strdup("localhost");
246  if (gChan.inethost == NULL)
247  ZE_LogSysError("strdup(inethost) error");
248  }
249 
250  if ((gChan.inethost == NULL) || (gChan.inetport < 0)) {
251  FREE(gChan.inethost);
252  gChan.inetport = -1;
253  return FALSE;
254  }
255  gChan.socktype = AF_INET;
256  return TRUE;
257  }
258 
259  return FALSE;
260 }
261 
262 
263 
264 /* ****************************************************************************
265  * *
266  * *
267  **************************************************************************** */
268 static int
269 grey_server_disconnect()
270 {
271  if (gChan.sd >= 0) {
272  if (jfd_ready(gChan.sd, ZE_SOCK_WRITE, 0))
273  (void) sd_printf(gChan.sd, "QUIT\r\n");
274 #if 0
275  sleep(1);
276 #endif
277  shutdown(gChan.sd, SHUT_RDWR);
278  close(gChan.sd);
279  }
280  gChan.sd = -1;
281  gChan.ok = FALSE;
282 
283  return 0;
284 }
285 
286 /* ****************************************************************************
287  * *
288  * *
289  **************************************************************************** */
290 static int
291 grey_server_connect()
292 {
293  int sd = -1;
294  char *env = NULL;
295 
296  gChan.recv_timeout = 10;
297  if ((env = getenv("GREYD_RECV_TIMEOUT")) != NULL) {
298  long to = zeStr2long(env, NULL, gChan.recv_timeout);
299 
300  if (to > 100)
301  gChan.recv_timeout = to;
302  }
303  gChan.send_timeout = 10;
304  if ((env = getenv("GREYD_SEND_TIMEOUT")) != NULL) {
305  long to = zeStr2long(env, NULL, gChan.send_timeout);
306 
307  if (to > 100)
308  gChan.send_timeout = to;
309  }
310 
311  if (gChan.socktype == AF_INET) {
312  struct sockaddr_in his_sock;
313  struct hostent *hp;
314  int to;
315 
317  if (to < 1)
318  to = 1;
319 
320  if ((sd = socket(AF_INET, SOCK_STREAM, 0)) < 0) {
321  ZE_LogSysError("AF_INET : socket");
322  return -1;
323  }
324 
325  /*
326  * adresse destinataire XXX
327  */
328  if ((hp = gethostbyname(gChan.inethost)) == NULL) {
329  ZE_LogSysError("gethostbyname(%s)", STRNULL(gChan.inethost, "NULL"));
330  return -1;
331  }
332 
333  memcpy((char *) &his_sock.sin_addr, hp->h_addr, hp->h_length);
334  his_sock.sin_family = AF_INET;
335  his_sock.sin_port = htons(gChan.inetport);
336 
337 #if 0
338  if (ze_logLevel >= DEBUG_LEVEL)
339  log_sock_addr(&his_sock);
340 #endif
341 
342  /*
343  * emission sur sd vers his_sock d'un message de taille size
344  */
345  if (connect_timed(sd, (struct sockaddr *) &his_sock, sizeof (his_sock), to)
346  != 0) {
347  ZE_LogSysError("connect error (%s:%d)", STRNULL(gChan.inethost, "NULL"),
348  gChan.inetport);
349  shutdown(sd, SHUT_RDWR);
350  close(sd);
351  sd = -1;
352  }
353 
354  grey_errors_clear();
355 
356  gChan.sd = sd;
357  return sd;
358  }
359 
360  if (gChan.socktype == AF_UNIX) {
361  struct sockaddr_un his_sock;
362 
363  if ((gChan.sockname != NULL) && (strlen(gChan.sockname) == 0)) {
364  ZE_LogSysError("AF_UNIX : No sockname given...");
365  return -1;
366  }
367 
368  if ((sd = socket(AF_UNIX, SOCK_STREAM, 0)) < 0) {
369  ZE_LogSysError("AF_UNIX : socket");
370  return -1;
371  }
372 
373  /*
374  * unlink(sockname);
375  */
376  memset(&his_sock, 0, sizeof (his_sock));
377  his_sock.sun_family = AF_UNIX;
378 
379  strncpy(his_sock.sun_path, gChan.sockname, strlen(gChan.sockname) + 1);
380 
381  /*
382  * emission sur sd vers his_sock d'un message de taille size
383  */
384  if (connect(sd, (struct sockaddr *) &his_sock, sizeof (his_sock)) != 0) {
385  ZE_LogSysError("connect error (%s)", STRNULL(gChan.sockname, "NULL"));
386  shutdown(sd, SHUT_RDWR);
387  close(sd);
388  sd = -1;
389  }
390 
391  grey_errors_clear();
392 
393  gChan.sd = sd;
394  return sd;
395  }
396 
397  ZE_MessageError(8, "Family socket unknown... %d", gChan.socktype);
398 
399  return -1;
400 }
401 
402 /* ****************************************************************************
403  * *
404  * *
405  **************************************************************************** */
406 static bool
407 grey_channel_check()
408 {
409  char *scan_arg = NULL;
410  static bool ok = FALSE;
411 
412  if (!ok) {
413  atexit(remote_grey_quit);
414  ok = TRUE;
415  }
416 
417  /*
418  ** Check errors
419  ** if :
420  ** ok - continue
421  ** ko - return false
422  */
423  if (!grey_server_error_inc_and_check(FALSE))
424  return FALSE;
425 
426  if (!gChan.ok) {
427 
428  if ((scan_arg = cf_get_str(CF_GREY_SOCKET)) != NULL)
429  greysock = scan_arg;
430 
431  gChan.ok = grey_socket_decode(greysock);
432 
433  ZE_MessageInfo(DEBUG_LEVEL, "SOCK : %s",
434  STRNULL(greysock, "NULL"));
435  ZE_MessageInfo(DEBUG_LEVEL, "SOCKTYPE : %d", gChan.socktype);
436  ZE_MessageInfo(DEBUG_LEVEL, "SOCKNAME : %s",
437  STRNULL(gChan.sockname, "NULL"));
438  ZE_MessageInfo(DEBUG_LEVEL, "INETHOST : %s",
439  STRNULL(gChan.inethost, "NULL"));
440  ZE_MessageInfo(DEBUG_LEVEL, "INETPORT : %d", gChan.inetport);
441  ZE_MessageInfo(DEBUG_LEVEL, "INIT OK : %d %s", gChan.ok,
442  STRBOOL(gChan.ok, "TRUE", "FALSE"));
443  }
444 
445  if (!gChan.ok) {
446  (void) grey_server_error_inc_and_check(TRUE);
447 
448  return FALSE;
449  }
450 
451  if (gChan.sd >= 0 && !grey_socket_check(gChan.sd))
452  grey_server_disconnect();
453 
454  if (gChan.sd < 0) {
455  time_t to = 10;
456 
457  gChan.sd = grey_server_connect();
458 
459  if (gChan.sd >= 0) {
460  while (jfd_ready(gChan.sd, ZE_SOCK_READ, to) == ZE_SOCK_READY) {
461  size_t sz;
462  char buf[256];
463 
464  to = 10;
465  sz = recvfrom(gChan.sd, buf, sizeof (buf), 0, NULL, NULL);
466  buf[sz] = '\0';
467  if (sz > 0)
468  ZE_MessageInfo(DEBUG_LEVEL, "Connected to ze-greyd : %5d %s", sz,
469  buf);
470  else
471  break;
472  }
473  gChan.ok = TRUE;
474  }
475  }
476 
477  /*
478  * XXX if gChan.sd < 0 -> increment error count
479  */
480  if (gChan.sd >= 0)
481  grey_errors_clear();
482  else
483  (void) grey_server_error_inc_and_check(TRUE);
484 
485  return gChan.sd >= 0;
486 }
487 
488 
489 
490 /* ****************************************************************************
491  * *
492  * *
493  **************************************************************************** */
494 int
495 remote_grey_check(ip, from, to, hostname)
496  char *ip;
497  char *from;
498  char *to;
499  char *hostname;
500 {
501  int result = GREY_ERROR;
502  time_t tout = 10;
503 
504  time_t tiw, tfw, tfs;
505 
506  /*
507  * CHECK XXX : OK or return
508  */
509 
510  /*
511  * INC XXX
512  */
513  if (ISSTREMPTY(ip) || ISSTREMPTY(from) || ISSTREMPTY(to)
514  || ISSTREMPTY(hostname)) {
515  ZE_MessageWarning(9, "Calling %s with invalid parameters : %s %s %s %s",
516  __FILE__, STREMPTY(ip, "--"), STREMPTY(from, "--"),
517  STREMPTY(to, "--"), STREMPTY(hostname, "--"));
518  return GREY_DUNNO;
519  }
520 
521  if (!GREY_CONN_CHECK()) {
523  "Not checking ze-greyd server - too many open connections (%d/%d)",
524  grey_connections, MAX_OPEN_CONN);
525  return GREY_DUNNO;
526  }
527 
528  tiw = tfw = tfs = time(NULL);
529  (void) GREY_CONN_INC();
530  MUTEX_LOCK(&grcl_mutex);
531  tfw = tfs = time(NULL);
532 
533  if (!grey_channel_check())
534  goto fin;
535 
536  ZE_MessageInfo(DEBUG_LEVEL, "Checking %s %s %s %s", ip, from, to, hostname);
537 
538 #if _FFR_FLUSH_GREYD
539  /*
540  * empty input buffer before asking something
541  */
542  if (!flush_read_socket(gChan.sd)) {
543  /*
544  * log errors and ...
545  */
546  }
547 #endif
548 
549  if (!sd_printf(gChan.sd, "GREYCHECK %s %s %s %s\r\n", ip, STRNULL(from, "-"),
550  STRNULL(to, "-"), STRNULL(hostname, "-"))) {
551  grey_server_disconnect();
552  goto fin;
553  }
554 
555  tout = gChan.recv_timeout;
556 
557  {
558  char buf[4096];
559 
560  time_t ti, tf;
561  time_t dt = 100;
562  bool gotit = FALSE;
563 
564  ti = tf = time(NULL);
565 
566  memset(buf, 0, sizeof (buf));
567  while (!gotit) {
568  int rfd;
569 
570  tf = time(NULL);
571  if (tf >= ti + tout)
572  break;
573 
574  /*
575  * check if socket is ready
576  */
577  rfd = jfd_ready(gChan.sd, ZE_SOCK_READ, dt);
578  if (rfd == ZE_SOCK_TIMEOUT)
579  continue;
580 
581  if (rfd == ZE_SOCK_ERROR) {
582  /*
583  * an error occured
584  */
585  ZE_LogMsgError(0, "greyd server sent no data or time out exceeded");
586  grey_server_error_inc_and_check(TRUE);
587  goto fin;
588  }
589 
590  /*
591  * read buf
592  */
593  if (rfd == ZE_SOCK_READY) {
594  size_t n;
595  size_t szok;
596  char *p;
597 
598  szok = sizeof (buf) - strlen(buf) - 1;
599  p = buf + strlen(buf);
600 
601  n = recvfrom(gChan.sd, p, szok, 0, NULL, NULL);
602 
603  if (n > 0) {
604  p[n] = '\0';
605  dt = 10;
606  }
607 
608  if (n < 0) {
609  if (errno == EINTR)
610  continue;
611 
612  /*
613  * an error occured
614  */
615  ZE_LogSysError("recvfrom error");
616  grey_server_error_inc_and_check(TRUE);
617  goto fin;
618  }
619 
620  if (n == 0) {
621  /*
622  * an error occured
623  */
624  ZE_LogMsgWarning(0, "greyd server performed an orderly shutdown");
625  grey_server_disconnect();
626  goto fin;
627  }
628  }
629 
630  grey_errors_clear();
631 
632  if (strlen(buf) > 0) {
633  char *p;
634  size_t sz;
635  char line[1024];
636 
637  p = buf;
638 
639  while ((sz = buf_get_line(line, sizeof (line), p, strlen(p))) > 0) {
640  int argc, code = GREY_ERROR;
641  char *argv[16];
642 
643  ZE_MessageInfo(DEBUG_LEVEL, "LINE IN : %s", line);
644 
645  p += sz;
646  if (!zeStrRegex
647  (line, "([0-9]+) .*GREYCHECK ANSWER", NULL, NULL, TRUE))
648  continue;
649 
650  argc = zeStr2Tokens(line, 16, argv, " ");
651  if (argc > 0)
652  code = zeStr2ulong(argv[0], NULL, GREY_OK);
653  switch (code) {
654  case GREY_OK:
655  case GREY_WAIT:
656  case GREY_ERROR:
657  case GREY_REJECT:
658  case GREY_DUNNO:
659  result = code;
660  break;
661  default:
662  result = GREY_ERROR;
663  }
664  gotit = TRUE;
665  break;
666  }
667  }
668  } /* while (!gotit) */
669  grey_socket_flush_read();
670  }
671 
672 fin:
673 
674  tfs = time(NULL);
675  {
676  time_t dtw, dts;
677 
678  dtw = tfw - tiw;
679  dts = tfs - tfw;
680 
681  if (dts >= 15 || dtw >= 15 || dts + dtw >= 15) {
682  ZE_MessageWarning(9, "grey_client : too long wait time : dtw/dts = %d/%d",
683  dtw, dts);
684  grey_server_disconnect();
685  }
686  }
687 
688  MUTEX_UNLOCK(&grcl_mutex);
689  (void) GREY_CONN_DEC();
690 
691  if (result == GREY_ERROR)
693 
694  /*
695  * DEC XXX
696  */
697 
698  return result;
699 }
700 
701 /* ****************************************************************************
702  * *
703  * *
704  **************************************************************************** */
705 int
706 remote_grey_validate(ip, from, to, hostname)
707  char *ip;
708  char *from;
709  char *to;
710  char *hostname;
711 {
712  int result = GREY_WAIT;
713  time_t tout = 10;
714 
715  time_t tiw, tfw, tfs;
716 
717  /*
718  * CHECK XXX : OK or return
719  */
720  if (ISSTREMPTY(ip) || ISSTREMPTY(from) || ISSTREMPTY(to)
721  || ISSTREMPTY(hostname)) {
722  ZE_MessageWarning(9, "Calling %s with invalid parameters : %s %s %s %s",
723  __FILE__, STREMPTY(ip, "--"), STREMPTY(from, "--"),
724  STREMPTY(to, "--"), STREMPTY(hostname, "--"));
725  return GREY_DUNNO;
726  }
727 
728  /*
729  * INC XXX
730  */
731  if (!GREY_CONN_CHECK()) {
733  "Not checking ze-greyd server - too many open connections (%d/%d)",
734  grey_connections, MAX_OPEN_CONN);
735  return GREY_DUNNO;
736  }
737 
738  tiw = tfw = tfs = time(NULL);
739  (void) GREY_CONN_INC();
740  MUTEX_LOCK(&grcl_mutex);
741  tfw = tfs = time(NULL);
742 
743  if (!grey_channel_check())
744  goto fin;
745 
746 #if _FFR_FLUSH_GREYD
747  /*
748  * empty input buffer before asking something
749  */
750  if (!flush_read_socket(gChan.sd)) {
751  /*
752  * log errors and ...
753  */
754  }
755 #endif
756 
757  if (!sd_printf(gChan.sd, "GREYVALID %s %s %s %s\r\n", ip, STRNULL(from, "-"),
758  STRNULL(to, "-"), STRNULL(hostname, "-"))) {
759  grey_server_disconnect();
760  goto fin;
761  }
762 
763  tout = gChan.recv_timeout;
764 
765  {
766  char buf[4096];
767 
768  time_t ti, tf;
769  time_t dt = 100;
770  bool gotit = FALSE;
771 
772  ti = tf = time(NULL);
773 
774  memset(buf, 0, sizeof (buf));
775  while (!gotit) {
776  int rfd;
777 
778  tf = time(NULL);
779  if (tf >= ti + tout)
780  break;
781 
782  /*
783  * check if socket is ready
784  */
785  rfd = jfd_ready(gChan.sd, ZE_SOCK_READ, dt);
786  if (rfd == ZE_SOCK_TIMEOUT)
787  continue;
788 
789  if (rfd == ZE_SOCK_ERROR) {
790  /*
791  * an error occured
792  */
793  ZE_LogMsgError(0, "greyd server sent no data or time out exceeded");
794  grey_server_error_inc_and_check(TRUE);
795  goto fin;
796  }
797 
798  /*
799  * read buf
800  */
801  if (rfd == ZE_SOCK_READY) {
802  size_t n;
803  size_t szok;
804  char *p;
805 
806  szok = sizeof (buf) - strlen(buf) - 1;
807  p = buf + strlen(buf);
808 
809  n = recvfrom(gChan.sd, p, szok, 0, NULL, NULL);
810 
811  if (n > 0) {
812  p[n] = '\0';
813  dt = 10;
814  }
815 
816  if (n < 0) {
817  if (errno == EINTR)
818  continue;
819 
820  /*
821  * an error occured
822  */
823  ZE_LogSysError("recvfrom error");
824  grey_server_error_inc_and_check(TRUE);
825  goto fin;
826  }
827 
828  if (n == 0) {
829  /*
830  * an error occured
831  */
832  ZE_LogMsgWarning(0, "greyd server performed an orderly shutdown");
833  grey_server_disconnect();
834  goto fin;
835  }
836  }
837 
838  if (strlen(buf) <= 0) {
839  /*
840  * an error occured
841  */
842  ZE_LogMsgError(0, "greyd server sent no data or time out exceeded");
843  grey_server_error_inc_and_check(TRUE);
844  goto fin;
845  }
846 
847  grey_errors_clear();
848 
849  if (strlen(buf) > 0) {
850  char *p;
851  size_t sz;
852  char line[1024];
853 
854  p = buf;
855 
856  while ((sz = buf_get_line(line, sizeof (line), p, strlen(p))) > 0) {
857  int argc, code = GREY_ERROR;
858  char *argv[16];
859 
860  ZE_MessageInfo(DEBUG_LEVEL, "LINE IN : %s", line);
861 
862  p += sz;
863  if (!zeStrRegex
864  (line, "([0-9]+) .*GREYVALID ANSWER", NULL, NULL, TRUE))
865  continue;
866 
867  argc = zeStr2Tokens(line, 16, argv, " ");
868  if (argc > 0)
869  code = zeStr2ulong(argv[0], NULL, GREY_OK);
870  switch (code) {
871  case GREY_OK:
872  case GREY_WAIT:
873  case GREY_ERROR:
874  case GREY_REJECT:
875  case GREY_DUNNO:
876  result = code;
877  break;
878  default:
879  result = GREY_ERROR;
880  }
881  gotit = TRUE;
882  break;
883  }
884  }
885  } /* while (!gotit) */
886  grey_socket_flush_read();
887  }
888 
889 fin:
890  tfs = time(NULL);
891  {
892  time_t dtw, dts;
893 
894  dtw = tfw - tiw;
895  dts = tfs - tfw;
896 
897  if (dts >= 15 || dtw >= 15 || dts + dtw >= 15) {
898  ZE_MessageWarning(9, "grey_client : too long wait time : dtw/dts = %d/%d",
899  dtw, dts);
900  grey_server_disconnect();
901  }
902  }
903 
904  MUTEX_UNLOCK(&grcl_mutex);
905  (void) GREY_CONN_DEC();
906 
907  if (result == GREY_ERROR)
909 
910  /*
911  * XXX DEC
912  */
913 
914  return result;
915 }
916 
917 /* ****************************************************************************
918  * *
919  * *
920  **************************************************************************** */
921 void
923 {
924  MUTEX_LOCK(&grcl_mutex);
925 
926  grey_server_disconnect(gChan.sd);
927 
928  grey_errors_clear();
929 
930  MUTEX_UNLOCK(&grcl_mutex);
931 
932  /*
933  * XXX ZERO
934  */
935 }
936 
937 
938 /* ****************************************************************************
939  * *
940  * *
941  **************************************************************************** */
942 static bool
943 grey_socket_flush_read()
944 {
945  bool result = TRUE;
946  char buf[1024];
947 
948  /*
949  * empty input buffer before asking something
950  */
951  while (jfd_ready(gChan.sd, ZE_SOCK_READ, 1) == ZE_SOCK_READY) {
952  size_t n;
953 
954  n = recvfrom(gChan.sd, buf, sizeof (buf), 0, NULL, NULL);
955 
956  if (n > 0)
957  continue;
958  if (n < 0) {
959  if (errno == EINTR)
960  continue;
961 
962  /*
963  * an error occured
964  */
965  ZE_LogSysError("recvfrom error");
966  grey_server_error_inc_and_check(TRUE);
967  goto fin;
968  }
969 
970  if (n == 0) {
971  /*
972  * an error occured
973  */
974  ZE_LogMsgError(0, "greyd server performed an orderly shutdown");
975  grey_server_disconnect(gChan.sd);
976  goto fin;
977  }
978  }
979 
980 fin:
981  return result;
982 }
#define GREY_CONN_INC()
bool sd_printf(int sd, char *format,...)
Definition: ze-inet.c:629
#define STRBOOL(x, t, f)
Definition: macros.h:87
char * inethost
char * sockname
#define MAX_OPEN_CONN
#define ISSTREMPTY(x)
Definition: macros.h:85
#define CF_GREY_SOCKET
Definition: cfh-defs.h:192
#define ZE_SOCK_WRITE
Definition: ze-inet.h:58
#define FREE(x)
Definition: macros.h:37
int remote_grey_check(char *ip, char *from, char *to, char *hostname)
#define MUTEX_UNLOCK(mutex)
Definition: macros.h:101
int ze_logLevel
Definition: zeSyslog.c:34
#define STRNULL(x, r)
Definition: macros.h:81
#define DEBUG_LEVEL
#define MUTEX_LOCK(mutex)
Definition: macros.h:93
int buf_get_line(char *, long, char *, long)
Definition: ze-buffer.c:98
int jfd_ready(int, bool, long)
Definition: ze-inet.c:529
#define FALSE
Definition: macros.h:160
#define ZE_LogMsgError(level,...)
Definition: zeSyslog.h:113
bool zeStrRegex(char *, char *, long *, long *, bool)
Definition: zeStrings.c:544
#define GREY_ERROR
Definition: ze-grey.h:38
#define GREY_REJECT
Definition: ze-grey.h:37
#define ZE_SOCK_TIMEOUT
Definition: ze-inet.h:62
int remote_grey_validate(char *ip, char *from, char *to, char *hostname)
int cf_get_int(int id)
Definition: ze-cf.c:803
int zeStr2Tokens(char *, int, char **, char *)
Definition: zeStrings.c:610
#define SRV_ERR_MAX
#define MIN(a, b)
Definition: macros.h:140
time_t recv_timeout
#define GREY_CONN_CHECK()
#define CF_GREY_CONNECT_TIMEOUT
Definition: cfh-defs.h:193
long zeStr2long(char *s, int *error, long dval)
Definition: zeStrConvert.c:35
void grey_channel_error_clear()
#define GREY_DUNNO
Definition: ze-grey.h:39
int connect_timed(int, struct sockaddr *, socklen_t, int)
Definition: ze-client.c:639
#define GREY_OK
Definition: ze-grey.h:35
#define GREY_CONN_DEC()
#define ZE_MessageInfo(level,...)
Definition: zeSyslog.h:90
#define TRUE
Definition: macros.h:157
#define ZE_MessageWarning(level,...)
Definition: zeSyslog.h:92
#define memcpy(d, s, n)
Definition: ze-sys.h:224
#define ZE_LogSysError(...)
Definition: zeSyslog.h:129
#define ZE_MessageError(level,...)
Definition: zeSyslog.h:93
#define ZE_SOCK_ERROR
Definition: ze-inet.h:60
char * cf_get_str(int id)
Definition: ze-cf.c:854
#define STREMPTY(x, r)
Definition: macros.h:82
#define ZE_LogMsgWarning(level,...)
Definition: zeSyslog.h:112
#define GREY_WAIT
Definition: ze-grey.h:36
unsigned long zeStr2ulong(char *s, int *error, unsigned long dval)
Definition: zeStrConvert.c:100
#define ZE_SOCK_READ
Definition: ze-inet.h:57
void remote_grey_quit()
#define SRV_MAX_ERR_DELAY
#define ZE_SOCK_READY
Definition: ze-inet.h:61
#define SRV_MIN_ERR_DELAY
time_t send_timeout