ze-filter  (ze-filter-0.8.0-develop-180218)
ze-inet.c
Go to the documentation of this file.
1 /*
2  *
3  * ze-filter - Mail Server Filter for sendmail
4  *
5  * Copyright (c) 2001-2018 - Jose-Marcio Martins da Cruz
6  *
7  * Auteur : Jose Marcio Martins da Cruz
8  * jose.marcio.mc@gmail.org
9  *
10  * Historique :
11  * Creation : janvier 2002
12  *
13  * This program is free software, but with restricted license :
14  *
15  *
16  * This program is distributed in the hope that it will be useful,
17  * but WITHOUT ANY WARRANTY; without even the implied warranty of
18  * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.
19  *
20  * More details about ze-filter license can be found at ze-filter
21  * web site : http://foss.jose-marcio.org
22  */
23 
24 #include <ze-sys.h>
25 
26 #include "libze.h"
27 #include "ze-inet.h"
28 
29 /* ****************************************************************************
30  * *
31  * *
32  **************************************************************************** */
33 char *
34 jinet_ntop(family, addr, cp, size)
35  int family;
36  void *addr;
37  char *cp;
38  size_t size;
39 {
40 #if HAVE_INET_NTOP
41  char *p = NULL;
42 
43  if (family == AF_UNSPEC)
44  family = AF_INET;
45 
46  if ((p = (char *) inet_ntop(family, addr, cp, size)) == NULL)
47  ZE_LogSysError("inet_ntop error");
48  return p;
49 #else
50 #if HAVE_INET_NTOA
51  char *p, *s;
52  static pthread_mutex_t mutex = PTHREAD_MUTEX_INITIALIZER;
53 
54  s = NULL;
55  MUTEX_LOCK(&mutex);
56  if ((p = inet_ntoa(addr)) != NULL)
57  {
58  strlcpy(cp, p, size);
59  s = cp;
60  }
61  MUTEX_UNLOCK(&mutex);
62 
63  return s;
64 #else
65  return NULL;
66 #endif
67 #endif
68 }
69 
70 /* ****************************************************************************
71  * *
72  * *
73  **************************************************************************** */
74 int
75 jinet_pton(family, cp, addr)
76  sa_family_t family;
77  char *cp;
78  void *addr;
79 {
80  int res = 0;
81 
82 #if HAVE_INET_PTON
83  res = inet_pton(family, cp, addr);
84  if (res < 0)
85  ZE_LogSysError("inet_pton");
86  if (res == 0)
87  ZE_LogMsgError(0, "inet_pton : /%s/ isn't a valid address string",
88  cp != NULL ? cp : "(NULL)");
89 #else
90 #ifdef HAVE_INET_ATON
91  res = inet_aton(cp, addr) == 0 ? 0 : 1;
92  if (res == 0)
93  ZE_LogMsgError(0, "inet_aton : %s isn't a valid address string",
94  cp != NULL ? cp : "(NULL)");
95 #endif
96 #endif
97  return res;
98 }
99 
100 
101 /* ****************************************************************************
102  * *
103  * *
104  **************************************************************************** */
105 bool
106 jsock_ntop(sa, salen, buf, size)
107  struct sockaddr *sa;
108  socklen_t salen;
109  char *buf;
110  size_t size;
111 {
112  switch (sa->sa_family)
113  {
114  case AF_INET:
115  {
116  struct sockaddr_in *sin = (struct sockaddr_in *) sa;
117 
118  if (jinet_ntop(sa->sa_family, &sin->sin_addr.s_addr, buf, size) == NULL)
119  return FALSE;
120  return TRUE;
121  }
122  break;
123  case AF_INET6:
124  {
125  struct sockaddr_in6 *sin6 = (struct sockaddr_in6 *) sa;
126 
127  if (jinet_ntop(sa->sa_family, &sin6->sin6_addr, buf, size) == NULL)
128  return FALSE;
129  return TRUE;
130  }
131  break;
132  }
133  return FALSE;
134 }
135 
136 /* ****************************************************************************
137  * *
138  * *
139  **************************************************************************** */
140 int
142  char *a;
143  char *b;
144 {
145  bool aipv6, bipv6 = FALSE;
146 
147  aipv6 = (strchr(a, ':') != NULL);
148  bipv6 = (strchr(b, ':') != NULL);
149 
150  if (aipv6 && bipv6)
151  {
152  return strcasecmp(a, b);
153  }
154 
155  if (!aipv6 && !bipv6)
156  {
157  struct in_addr aa, ab;
158 
159  /* XXX a voir */
160  if (jinet_pton(AF_INET, b, &ab.s_addr)
161  && jinet_pton(AF_INET, a, &aa.s_addr))
162  {
163  if (htonl(aa.s_addr) > htonl(ab.s_addr))
164  return 1;
165  if (htonl(aa.s_addr) < htonl(ab.s_addr))
166  return -1;
167  return 0;
168  }
169  }
170 
171  if (aipv6)
172  return 1;
173  return -1;
174 }
175 
176 /* ****************************************************************************
177  * *
178  * *
179  **************************************************************************** */
180 bool
181 get_hostname(host, size)
182  char *host;
183  size_t size;
184 {
185  ASSERT(host != NULL);
186  ASSERT(size > 0);
187 
188  memset(host, 0, size);
189 
190 #if HAVE_GETHOSTNAME
191  ZE_LogMsgDebug(15, "Using gethostname to get host name");
192 
193  if (gethostname(host, size) < 0)
194  {
195  ZE_LogSysError("sysinfo(SI_HOSTNAME) error");
196  return FALSE;
197  }
198  return TRUE;
199 #else
200 
201 # if HAVE_UNAME
202  {
203  struct utsname udata;
204 
205  ZE_LogMsgDebug(15, "Using uname to get host name");
206  if (uname(&udata) < 0)
207  {
208  ZE_LogSysError("uname error");
209  return FALSE;
210  }
211  strlcpy(host, udata.nodename, size);
212  return TRUE;
213  }
214 # else
215 
216 # if SYSINFO_NODENAME
217  SYSINFO ZE_LogMsgDebug(15, "Using sysinfo to get host name");
218 
219  if (sysinfo(SI_HOSTNAME, host, sizeof (host)) < 0)
220  {
221  ZE_LogSysError("sysinfo(SI_HOSTNAME) error");
222  return FALSE;
223  }
224  return TRUE;
225 # endif
226 
227 # endif
228 
229 #endif
230  return FALSE;
231 }
232 
233 
234 /* ****************************************************************************
235  * *
236  * *
237  **************************************************************************** */
238 #ifndef NI_MAXHOST
239 #define NI_MAXHOST 1025
240 #endif
241 #ifndef NI_MAXSERV
242 #define NI_MAXSERV 32
243 #endif
244 
245 static bool
246 convNameAddr(bout, bin, size, conv2addr)
247  char *bout;
248  char *bin;
249  size_t size;
250  bool conv2addr;
251 {
252  struct addrinfo hints, *res, *rp;
253  bool ok = TRUE;
254  int r;
255 
256  ASSERT(bout != NULL);
257  ASSERT(size > 0);
258  memset(bout, 0, size);
259 
260  memset(&hints, 0, sizeof (hints));
261  hints.ai_family = AF_UNSPEC; /* Allow IPv4 or IPv6 */
262  hints.ai_socktype = SOCK_DGRAM; /* Datagram socket */
263  hints.ai_flags = AI_PASSIVE; /* For wildcard IP address */
264  hints.ai_protocol = 0; /* Any protocol */
265  hints.ai_canonname = NULL;
266  hints.ai_addr = NULL;
267  hints.ai_next = NULL;
268 
269  r = getaddrinfo(bin, NULL, &hints, &res);
270  if (r != 0)
271  {
272  if (conv2addr && r == EAI_NONAME)
273  {
274  ok = FALSE;
275  goto fin;
276  }
277 
278  ZE_LogSysError("getaddrinfo(%s,%s) : %d %s",
279  bin,
280  STRBOOL(conv2addr, "name -> addr", "addr -> name"),
281  r, gai_strerror(r));
282  ok = FALSE;
283  goto fin;
284  }
285 
286  for (rp = res; rp != NULL; rp = rp->ai_next)
287  {
288  int r;
289  char buf[NI_MAXHOST];
290 
291  r = getnameinfo(rp->ai_addr, rp->ai_addrlen,
292  buf, sizeof (buf), NULL, 0, conv2addr ? NI_NUMERICHOST : 0);
293 
294  if (r != 0)
295  {
296  ZE_LogSysError("getnameinfo(%s,%s) : %d %s",
297  bin,
298  STRBOOL(conv2addr, "name -> addr", "addr -> name"),
299  r, gai_strerror(r));
300  ok = FALSE;
301  goto fin;
302  }
303 
304  ZE_MessageInfo(12, "IN : %s - OUT : %s", bin, buf);
305 
306  if (!conv2addr && STRCASEEQUAL(buf, bin))
307  snprintf(bout, size, "[%s]", buf);
308  else
309  strlcpy(bout, buf, size);
310 
311  break;
312  }
313 fin:
314  return ok;
315 }
316 
317 
318 /* ****************************************************************************
319  * *
320  * *
321  **************************************************************************** */
322 bool
323 get_hostbyaddr(ip, name, len)
324  char *ip;
325  char *name;
326  int len;
327 {
328  return convNameAddr(name, ip, len, FALSE);
329 }
330 
331 /* ****************************************************************************
332  * *
333  * *
334  **************************************************************************** */
335 bool
336 get_hostbyname(name, ip, len)
337  char *name;
338  char *ip;
339  int len;
340 {
341  return convNameAddr(ip, name, len, TRUE);
342 }
343 
344 /* ****************************************************************************
345  * *
346  * *
347  **************************************************************************** */
348 char *
349 inet_n2p(family, addr, cp, size)
350  int family;
351  void *addr;
352  char *cp;
353  size_t size;
354 {
355 #if HAVE_INET_NTOP
356  char *p = NULL;
357 
358  if (family == AF_UNSPEC)
359  family = AF_INET;
360 
361  if ((p = (char *) inet_ntop(family, addr, cp, size)) == NULL)
362  ZE_LogSysError("inet_ntop error");
363  return p;
364 #else
365 #if HAVE_INET_NTOA
366  char *p, *s;
367  static pthread_mutex_t mutex = PTHREAD_MUTEX_INITIALIZER;
368 
369  s = NULL;
370  MUTEX_LOCK(&mutex);
371  if ((p = inet_ntoa(addr)) != NULL)
372  {
373  strlcpy(cp, p, size);
374  s = cp;
375  }
376  MUTEX_UNLOCK(&mutex);
377 
378  return s;
379 #else
380  return NULL;
381 #endif
382 #endif
383 }
384 
385 /* ****************************************************************************
386  * *
387  * *
388  **************************************************************************** */
389 int
390 inet_p2n(family, cp, addr)
391  sa_family_t family;
392  char *cp;
393  void *addr;
394 {
395  int res = 0;
396 
397 #if HAVE_INET_PTON
398  res = inet_pton(family, cp, addr);
399  if (res < 0)
400  ZE_LogSysError("inet_pton");
401  if (res == 0)
402  ZE_LogMsgError(0, "inet_pton : /%s/ isn't a valid address string",
403  cp != NULL ? cp : "(NULL)");
404 #else
405 #ifdef HAVE_INET_ATON
406  res = inet_aton(cp, addr) == 0 ? 0 : 1;
407  if (res == 0)
408  ZE_LogMsgError(0, "inet_aton : %s isn't a valid address string",
409  cp != NULL ? cp : "(NULL)");
410 #endif
411 #endif
412  return res;
413 }
414 
415 
416 /* ****************************************************************************
417  * *
418  * *
419  **************************************************************************** */
420 bool
421 get_hostbysock(sock, slen, addr, alen, name, nlen)
422  struct sockaddr *sock;
423  socklen_t slen;
424  char *addr;
425  size_t alen;
426  char *name;
427  size_t nlen;
428 {
429  char buf[NI_MAXHOST];
430  int r;
431  bool ok = TRUE;
432 
433  if (addr != NULL && alen > 0)
434  {
435  memset(buf, 0, sizeof (buf));
436  memset(addr, 0, alen);
437  r = getnameinfo(sock, slen, buf, sizeof (buf), NULL, 0, NI_NUMERICHOST);
438  if (r != 0)
439  {
440  ZE_LogSysError("getnameinfo(%s) : %d %s", "name -> addr", r,
441  gai_strerror(r));
442  ok = FALSE;
443  goto fin;
444  }
445  strlcpy(addr, buf, alen);
446  }
447 
448  if (name != NULL && nlen > 0)
449  {
450  memset(buf, 0, sizeof (buf));
451  memset(name, 0, nlen);
452  r = getnameinfo(sock, slen, buf, sizeof (buf), NULL, 0, 0);
453  if (r != 0)
454  {
455  ZE_LogSysError("getnameinfo(%s) : %d %s", "addr -> name", r,
456  gai_strerror(r));
457  ok = FALSE;
458  goto fin;
459  }
460 #if 0
461  if (STRCASEEQUAL(buf, bin))
462  snprintf(bout, size, "[%s]", buf);
463  else
464  strlcpy(bout, buf, size);
465 #else
466  strlcpy(name, buf, nlen);
467 #endif
468  }
469 
470 fin:
471  return ok;
472 }
473 
474 
475 /* ****************************************************************************
476  * *
477  * *
478  **************************************************************************** */
479 int
481  char *a;
482  char *b;
483 {
484  bool aip, bip = FALSE;
485 
486  aip = (strchr(a, ':') != NULL);
487  bip = (strchr(b, ':') != NULL);
488 
489  if (aip && bip)
490  {
491  return strcasecmp(a, b);
492  }
493 
494  if (!aip && !bip)
495  {
496  struct in_addr aa, ab;
497 
498  /* XXX a voir */
499  if (inet_p2n(AF_INET, b, &ab.s_addr) && inet_p2n(AF_INET, a, &aa.s_addr))
500  {
501  if (htonl(aa.s_addr) > htonl(ab.s_addr))
502  return 1;
503  if (htonl(aa.s_addr) < htonl(ab.s_addr))
504  return -1;
505  return 0;
506  }
507  }
508 
509  if (aip)
510  return 1;
511  return -1;
512 }
513 
514 
515 /* ****************************************************************************
516  * *
517  * *
518  **************************************************************************** */
519 #if HAVE_POLL
520 # define J_POLL_RD_FLAGS (POLLIN | POLLPRI | POLLHUP)
521 # define J_POLL_WR_FLAGS (POLLOUT | POLLHUP)
522 #endif /* HAVE_POLL */
523 
524 #ifndef FDREADY_LOG_LEVEL
525 #define FDREADY_LOG_LEVEL 0
526 #endif
527 
528 int
529 jfd_ready(sd, fdmode, to)
530  int sd;
531  bool fdmode;
532  long to;
533 {
534 #if HAVE_POLL
535  struct pollfd pfd;
536  int r;
537  time_t now = time(NULL);
538  int nerr = 0;
539 
540  int flags;
541 
542  flags = (fdmode == ZE_SOCK_READ ? J_POLL_RD_FLAGS : J_POLL_WR_FLAGS);
543 
544  for (;;)
545  {
546  pfd.fd = sd;
547  pfd.events = flags;
548  pfd.revents = 0;
549  r = poll(&pfd, 1, to);
550  if (r == 0)
551  return ZE_SOCK_TIMEOUT;
552 
553 #if 0
554  if ((pfd.revents & (POLLERR | POLLHUP | POLLNVAL)) != 0)
555  {
556  ZE_MessageInfo(FDREADY_LOG_LEVEL, " POLL ERR/HUP/NVAL = %s/%s/%s",
557  STRBOOL((pfd.revents & POLLERR) == TRUE, "T", "F"),
558  STRBOOL((pfd.revents & POLLHUP) == TRUE, "T", "F"),
559  STRBOOL((pfd.revents & POLLNVAL) == TRUE, "T", "F"));
560  }
561 #endif
562  if (r < 0)
563  {
564  if (errno == EINTR)
565  {
566  if (++nerr > 100)
567  return ZE_SOCK_ERROR;
568  continue;
569  }
570  ZE_LogSysError("poll(%ld)", (long) pfd.fd);
571  return ZE_SOCK_ERROR;
572  }
573  nerr = 0;
574  if ((pfd.revents & flags) != 0)
575  return ZE_SOCK_READY;
576 
577  if ((pfd.revents & (POLLERR | POLLHUP | POLLNVAL)) != 0)
578  return ZE_SOCK_ERROR;
579 
580  if (time(NULL) > (now + to / 1000))
581  return ZE_SOCK_TIMEOUT;
582  }
583 #if 0
584  ZE_LogMsgError(0, "ERROR=poll:mi_rd_socket_ready, socket=%d, r=%d, errno=%d revents=%d", sd,
585  r, errno, pfd.revents);
586  return ZE_SOCK_ERROR;
587 #endif
588 #else /* HAVE_POLL */
589  fd_set rdfs, excfs;
590  int r;
591  struct timeval timeout;
592 
593  for (;;)
594  {
595  timeout.tv_usec = 1000 * (to % 1000);
596  timeout.tv_sec = to / 1000;
597  FD_ZERO(&rdfs);
598  FD_SET((unsigned int) sd, &rdfs);
599  FD_ZERO(&excfs);
600  FD_SET((unsigned int) sd, &excfs);
601  if (fdmode == ZE_SOCK_READ)
602  r = select(sd + 1, &rdfs, NULL, &excfs, timeout);
603  else
604  r = select(sd + 1, NULL, &rdfs, &excfs, timeout);
605  if (r == 0)
606  return ZE_SOCK_TIMEOUT;
607  if (r < 0)
608  {
609  if (errno == EINTR)
610  continue;
611  return ZE_SOCK_ERROR;
612  }
613  if (FD_ISSET(sd, &excfs))
614  return ZE_SOCK_ERROR;
615  if (FD_ISSET(sd, &rdfs))
616  return ZE_SOCK_READY;
617  }
618 #endif /* HAVE_POLL */
619  return ZE_SOCK_ERROR;
620 }
621 
622 /* ****************************************************************************
623  * *
624  * *
625  **************************************************************************** */
626 #define MAX_EINTR_ERRORS 24
627 
628 bool
629 sd_printf(int sd, char *format, ...)
630 {
631  va_list arg;
632  char str[1024];
633  int result = FALSE;
634  int nerr = 0;
635 
636  memset(str, 0, sizeof(str));
637  va_start(arg, format);
638  (void) vsnprintf(str, sizeof (str), format, arg);
639  va_end(arg);
640 
641  while (TRUE)
642  {
643  int r;
644 
645  r = sendto(sd, str, strlen(str), 0, NULL, 0);
646  if (r == -1)
647  {
648  if (nerr++ > MAX_EINTR_ERRORS)
649  break;
650 
651  if (errno == EINTR)
652  continue;
653 
654  ZE_LogSysError("sendto error (r = %d)", r);
655  break;
656  }
657  if (r == 0)
658  {
659  ZE_LogMsgError(0, "sendto error (r = %d)", r);
660  break;
661  }
662 
663  return TRUE;
664  }
665 
666  return result;
667 }
668 
669 /* ****************************************************************************
670  * *
671  * *
672  **************************************************************************** */
673 int
674 sd_readln(fd, buf, size)
675  int fd;
676  char *buf;
677  size_t size;
678 {
679  char *p = buf;
680 
681  if (fd < 0)
682  return -1;
683 
684  *p = '\0';
685  while (size > 0)
686  {
687  int n;
688 
689  n = recvfrom(fd, p, 1, MSG_DONTWAIT, NULL, NULL);
690  if (n == 0)
691  break;
692  if (n < 0)
693  {
694  if (errno == EINTR || errno == EAGAIN)
695  continue;
696  ZE_LogSysError("read error");
697  break;
698  }
699 
700  if (*p == '\r')
701  continue;
702  if (*p == '\n')
703  break;
704  p++;
705  size--;
706  }
707  *p = '\0';
708  return strlen(buf);
709 }
bool sd_printf(int sd, char *format,...)
Definition: ze-inet.c:629
#define STRBOOL(x, t, f)
Definition: macros.h:87
int socklen_t
Definition: ze-sys.h:534
#define ASSERT(a)
Definition: macros.h:27
int inet_p2n(sa_family_t family, char *cp, void *addr)
Definition: ze-inet.c:390
#define MUTEX_UNLOCK(mutex)
Definition: macros.h:101
bool ok
Definition: ze-connopen.c:59
#define MUTEX_LOCK(mutex)
Definition: macros.h:93
#define FDREADY_LOG_LEVEL
Definition: ze-inet.c:525
pthread_mutex_t mutex
Definition: ze-connopen.c:63
int jfd_ready(int sd, bool fdmode, long to)
Definition: ze-inet.c:529
int Ip_strcmp(char *a, char *b)
Definition: ze-inet.c:480
#define FALSE
Definition: macros.h:160
#define strlcpy
Definition: zeString.h:32
#define ZE_LogMsgError(level,...)
Definition: zeSyslog.h:113
#define NI_MAXHOST
Definition: ze-inet.c:239
int jinet_pton(sa_family_t family, char *cp, void *addr)
Definition: ze-inet.c:75
int ip_strcmp(char *a, char *b)
Definition: ze-inet.c:141
#define ZE_SOCK_TIMEOUT
Definition: ze-inet.h:62
bool jsock_ntop(struct sockaddr *sa, socklen_t salen, char *buf, size_t size)
Definition: ze-inet.c:106
bool get_hostbyaddr(char *ip, char *name, int len)
Definition: ze-inet.c:323
#define strchr
Definition: ze-sys.h:218
#define ZE_LogMsgDebug(level,...)
Definition: zeSyslog.h:109
bool get_hostbysock(struct sockaddr *sock, socklen_t slen, char *addr, size_t alen, char *name, size_t nlen)
Definition: ze-inet.c:421
#define ZE_MessageInfo(level,...)
Definition: zeSyslog.h:90
#define TRUE
Definition: macros.h:157
bool get_hostname(char *host, size_t size)
Definition: ze-inet.c:181
#define ZE_LogSysError(...)
Definition: zeSyslog.h:129
#define ZE_SOCK_ERROR
Definition: ze-inet.h:60
int sd_readln(int fd, char *buf, size_t size)
Definition: ze-inet.c:674
#define STRCASEEQUAL(a, b)
Definition: macros.h:72
#define ZE_SOCK_READ
Definition: ze-inet.h:57
char * inet_n2p(int family, void *addr, char *cp, size_t size)
Definition: ze-inet.c:349
#define ZE_SOCK_READY
Definition: ze-inet.h:61
#define MAX_EINTR_ERRORS
Definition: ze-inet.c:626
bool get_hostbyname(char *name, char *ip, int len)
Definition: ze-inet.c:336
char * jinet_ntop(int family, void *addr, char *cp, size_t size)
Definition: ze-inet.c:34