#include "config.h"#include "libspamc.h"#include "utils.h"#include <stdlib.h>#include <assert.h>#include <stdio.h>#include <string.h>#include <syslog.h>#include <unistd.h>#include <sys/types.h>#include <sys/socket.h>#include <netinet/in.h>#include <sys/un.h>#include <netinet/tcp.h>#include <arpa/inet.h>Go to the source code of this file.
Classes | |
| struct | libspamc_private_message |
Defines | |
| #define | closesocket(x) close(x) |
| #define | SHUT_RD 0 |
| #define | SHUT_WR 1 |
| #define | SHUT_RDWR 2 |
| #define | h_errno errno |
| #define | spamc_get_errno() errno |
| #define | INADDR_NONE ((in_addr_t) 0xffffffff) |
| #define | EX__MAX 200 |
| #define | SPAMC_MAXHOST 256 |
| #define | SPAMC_MAXSERV 256 |
| #define | CRNLCRNL "\r\n\r\n" |
| #define | CRNLCRNL_LEN 4 |
| #define | NLNL "\n\n" |
| #define | NLNL_LEN 2 |
| #define | LOG_BUFSIZ 1023 |
Functions | |
| static int | _translate_connect_errno (int err) |
| static int | _opensocket (int flags, int type, int *psock) |
| static int | _try_to_connect_unix (struct transport *tp, int *sockptr) |
| static int | _try_to_connect_tcp (const struct transport *tp, int *sockptr) |
| static void | _clear_message (struct message *m) |
| static void | _use_msg_for_out (struct message *m) |
| static int | _message_read_raw (int fd, struct message *m) |
| static int | _message_read_bsmtp (int fd, struct message *m) |
| int | message_read (int fd, int flags, struct message *m) |
| long | message_write (int fd, struct message *m) |
| void | message_dump (int in_fd, int out_fd, struct message *m) |
| static int | _spamc_read_full_line (struct message *m, int flags, SSL *ssl, int sock, char *buf, size_t *lenp, size_t bufsiz) |
| static float | _locale_safe_string_to_float (char *buf, int siz) |
| static int | _handle_spamd_header (struct message *m, int flags, char *buf, int len, unsigned int *didtellflags) |
| static int | _zlib_compress (char *m_msg, int m_msg_len, unsigned char **zlib_buf, int *zlib_bufsiz, int flags) |
| int | _append_original_body (struct message *m, int flags) |
| int | message_filter (struct transport *tp, const char *username, int flags, struct message *m) |
| int | message_process (struct transport *trans, char *username, int max_size, int in_fd, int out_fd, const int flags) |
| int | message_tell (struct transport *tp, const char *username, int flags, struct message *m, int msg_class, unsigned int tellflags, unsigned int *didtellflags) |
| void | message_cleanup (struct message *m) |
| int | process_message (struct transport *tp, char *username, int max_size, int in_fd, int out_fd, const int my_check_only, const int my_safe_fallback) |
| void | transport_init (struct transport *tp) |
| static void | _randomize_hosts (struct transport *tp) |
| int | transport_setup (struct transport *tp, int flags) |
| void | libspamc_log (int flags, int level, char *msg,...) |
Variables | |
| char * | optarg |
| static const int | EXPANSION_ALLOWANCE = 16384 |
| static const char * | PROTOCOL_VERSION = "SPAMC/1.4" |
| int | libspamc_timeout = 0 |
|
|
Definition at line 49 of file libspamc.c. Referenced by _opensocket(), _try_to_connect_tcp(), _try_to_connect_unix(), message_filter(), and message_tell(). |
|
|
Referenced by _append_original_body(). |
|
|
Referenced by _append_original_body(). |
|
|
Definition at line 107 of file libspamc.c. |
|
|
Definition at line 85 of file libspamc.c. Referenced by transport_setup(). |
|
|
Definition at line 99 of file libspamc.c. |
|
|
Definition at line 2028 of file libspamc.c. Referenced by libspamc_log(). |
|
|
Referenced by _append_original_body(). |
|
|
Referenced by _append_original_body(). |
|
|
Definition at line 75 of file libspamc.c. Referenced by message_filter(), and message_tell(). |
|
|
Definition at line 81 of file libspamc.c. |
|
|
Definition at line 78 of file libspamc.c. Referenced by message_filter(), and message_tell(). |
|
|
Definition at line 91 of file libspamc.c. Referenced by _opensocket(), and _try_to_connect_tcp(). |
|
|
Definition at line 120 of file libspamc.c. Referenced by _try_to_connect_tcp(). |
|
|
Definition at line 126 of file libspamc.c. Referenced by _try_to_connect_tcp(). |
|
||||||||||||
|
Definition at line 1096 of file libspamc.c. References libspamc_private_message::alloced_size, CRNLCRNL, CRNLCRNL_LEN, EX_OK, EX_SOFTWARE, libspamc_log(), LOG_ERR, NLNL, NLNL_LEN, message::out, message::out_len, message::priv, message::raw, and message::raw_len. Referenced by message_filter(). 01097 { 01098 char *cp, *cpend, *bodystart; 01099 int bodylen, outspaceleft, towrite; 01100 01101 /* at this stage, m->out now contains the rewritten headers. 01102 * find and append the raw message's body, up to m->priv->alloced_size 01103 * bytes. 01104 */ 01105 01106 #define CRNLCRNL "\r\n\r\n" 01107 #define CRNLCRNL_LEN 4 01108 #define NLNL "\n\n" 01109 #define NLNL_LEN 2 01110 01111 cpend = m->raw + m->raw_len; 01112 bodystart = NULL; 01113 01114 for (cp = m->raw; cp < cpend; cp++) { 01115 if (*cp == '\r' && cpend - cp >= CRNLCRNL_LEN && 01116 !strncmp(cp, CRNLCRNL, CRNLCRNL_LEN)) 01117 { 01118 bodystart = cp + CRNLCRNL_LEN; 01119 break; 01120 } 01121 else if (*cp == '\n' && cpend - cp >= NLNL_LEN && 01122 !strncmp(cp, NLNL, NLNL_LEN)) 01123 { 01124 bodystart = cp + NLNL_LEN; 01125 break; 01126 } 01127 } 01128 01129 if (bodystart == NULL) { 01130 libspamc_log(flags, LOG_ERR, "failed to find end-of-headers"); 01131 return EX_SOFTWARE; 01132 } 01133 01134 bodylen = cpend - bodystart; 01135 outspaceleft = (m->priv->alloced_size-1) - m->out_len; 01136 towrite = (bodylen < outspaceleft ? bodylen : outspaceleft); 01137 01138 /* copy in the body; careful not to overflow */ 01139 strncpy (m->out + m->out_len, bodystart, towrite); 01140 m->out_len += towrite; 01141 return EX_OK; 01142 }
|
|
|
Definition at line 606 of file libspamc.c. References message::content_length, EX_TOOBIG, message::is_spam, MESSAGE_NONE, message::msg, message::msg_len, message::out, message::out_len, message::outbuf, message::post, message::post_len, message::pre, message::pre_len, message::raw, message::raw_len, message::score, message::threshold, and message::type. Referenced by _message_read_bsmtp(), _message_read_raw(), message_cleanup(), and message_read(). 00607 { 00608 m->type = MESSAGE_NONE; 00609 m->raw = NULL; 00610 m->raw_len = 0; 00611 m->pre = NULL; 00612 m->pre_len = 0; 00613 m->msg = NULL; 00614 m->msg_len = 0; 00615 m->post = NULL; 00616 m->post_len = 0; 00617 m->is_spam = EX_TOOBIG; 00618 m->score = 0.0; 00619 m->threshold = 0.0; 00620 m->outbuf = NULL; 00621 m->out = NULL; 00622 m->out_len = 0; 00623 m->content_length = -1; 00624 }
|
|
||||||||||||||||||||||||
|
Definition at line 965 of file libspamc.c. References _locale_safe_string_to_float(), message::content_length, EX_ISSPAM, EX_NOTSPAM, EX_OK, EX_PROTOCOL, message::is_spam, libspamc_log(), LOG_ERR, message::out, message::out_len, message::score, SPAMC_CHECK_ONLY, SPAMC_REMOVE_LOCAL, SPAMC_REMOVE_REMOTE, SPAMC_REPORT, SPAMC_REPORT_IFSPAM, SPAMC_SET_LOCAL, SPAMC_SET_REMOTE, message::threshold, and UNUSED_VARIABLE. Referenced by message_filter(), and message_tell(). 00967 { 00968 char is_spam[6]; 00969 char s_str[21], t_str[21]; 00970 char didset_ret[15]; 00971 char didremove_ret[15]; 00972 00973 UNUSED_VARIABLE(len); 00974 00975 /* Feb 12 2003 jm: actually, I think sccanf is working fine here ;) 00976 * let's stick with it for this parser. 00977 * May 7 2003 jm: using %f is bad where LC_NUMERIC is "," in the locale. 00978 * work around using our own locale-independent float-parser code. 00979 */ 00980 if (sscanf(buf, "Spam: %5s ; %20s / %20s", is_spam, s_str, t_str) == 3) { 00981 m->score = _locale_safe_string_to_float(s_str, 20); 00982 m->threshold = _locale_safe_string_to_float(t_str, 20); 00983 00984 /* set bounds on these to ensure no buffer overflow in the sprintf */ 00985 if (m->score > 1e10) 00986 m->score = 1e10; 00987 else if (m->score < -1e10) 00988 m->score = -1e10; 00989 if (m->threshold > 1e10) 00990 m->threshold = 1e10; 00991 else if (m->threshold < -1e10) 00992 m->threshold = -1e10; 00993 00994 /* Format is "Spam: x; y / x" */ 00995 m->is_spam = 00996 strcasecmp("true", is_spam) == 0 ? EX_ISSPAM : EX_NOTSPAM; 00997 00998 if (flags & SPAMC_CHECK_ONLY) { 00999 m->out_len = sprintf(m->out, 01000 "%.1f/%.1f\n", m->score, m->threshold); 01001 } 01002 else if ((flags & SPAMC_REPORT_IFSPAM && m->is_spam == EX_ISSPAM) 01003 || (flags & SPAMC_REPORT)) { 01004 m->out_len = sprintf(m->out, 01005 "%.1f/%.1f\n", m->score, m->threshold); 01006 } 01007 return EX_OK; 01008 01009 } 01010 else if (sscanf(buf, "Content-length: %d", &m->content_length) == 1) { 01011 if (m->content_length < 0) { 01012 libspamc_log(flags, LOG_ERR, "spamd responded with bad Content-length '%s'", 01013 buf); 01014 return EX_PROTOCOL; 01015 } 01016 return EX_OK; 01017 } 01018 else if (sscanf(buf, "DidSet: %14s", didset_ret) == 1) { 01019 if (strstr(didset_ret, "local")) { 01020 *didtellflags |= SPAMC_SET_LOCAL; 01021 } 01022 if (strstr(didset_ret, "remote")) { 01023 *didtellflags |= SPAMC_SET_REMOTE; 01024 } 01025 } 01026 else if (sscanf(buf, "DidRemove: %14s", didremove_ret) == 1) { 01027 if (strstr(didremove_ret, "local")) { 01028 *didtellflags |= SPAMC_REMOVE_LOCAL; 01029 } 01030 if (strstr(didremove_ret, "remote")) { 01031 *didtellflags |= SPAMC_REMOVE_REMOTE; 01032 } 01033 } 01034 01035 return EX_OK; 01036 }
|
|
||||||||||||
|
Definition at line 904 of file libspamc.c. Referenced by _handle_spamd_header(), message_filter(), and message_tell(). 00905 { 00906 int is_neg; 00907 char *cp, *dot; 00908 int divider; 00909 float ret, postdot; 00910 00911 buf[siz - 1] = '\0'; /* ensure termination */ 00912 00913 /* ok, let's illustrate using "100.033" as an example... */ 00914 00915 is_neg = 0; 00916 if (*buf == '-') { 00917 is_neg = 1; 00918 } 00919 00920 ret = (float) (strtol(buf, &dot, 10)); 00921 if (dot == NULL) { 00922 return 0.0; 00923 } 00924 if (dot != NULL && *dot != '.') { 00925 return ret; 00926 } 00927 00928 /* ex: ret == 100.0 */ 00929 00930 cp = (dot + 1); 00931 postdot = (float) (strtol(cp, NULL, 10)); 00932 /* note: don't compare floats == 0.0, it's unsafe. use a range */ 00933 if (postdot >= -0.00001 && postdot <= 0.00001) { 00934 return ret; 00935 } 00936 00937 /* ex: postdot == 33.0, cp="033" */ 00938 00939 /* now count the number of decimal places and figure out what power of 10 to use */ 00940 divider = 1; 00941 while (*cp != '\0') { 00942 divider *= 10; 00943 cp++; 00944 } 00945 00946 /* ex: 00947 * cp="033", divider=1 00948 * cp="33", divider=10 00949 * cp="3", divider=100 00950 * cp="", divider=1000 00951 */ 00952 00953 if (is_neg) { 00954 ret -= (postdot / ((float) divider)); 00955 } 00956 else { 00957 ret += (postdot / ((float) divider)); 00958 } 00959 /* ex: ret == 100.033, tada! ... hopefully */ 00960 00961 return ret; 00962 }
|
|
||||||||||||
|
Definition at line 663 of file libspamc.c. References _clear_message(), EX_DATAERR, EX_IOERR, EX_OK, EX_OSERR, EX_SOFTWARE, EX_TOOBIG, full_read(), message::max_len, MESSAGE_BSMTP, MESSAGE_ERROR, message::msg, message::msg_len, message::out, message::out_len, message::post, message::post_len, message::pre, message::pre_len, message::raw, message::raw_len, and message::type. Referenced by message_read(). 00664 { 00665 unsigned int i, j, p_len; 00666 char prev; 00667 char* p; 00668 00669 _clear_message(m); 00670 if ((m->raw = malloc(m->max_len + 1)) == NULL) 00671 return EX_OSERR; 00672 00673 /* Find the DATA line */ 00674 m->raw_len = full_read(fd, 1, m->raw, m->max_len + 1, m->max_len + 1); 00675 if (m->raw_len <= 0) { 00676 free(m->raw); 00677 m->raw = NULL; 00678 m->raw_len = 0; 00679 return EX_IOERR; 00680 } 00681 m->type = MESSAGE_ERROR; 00682 if (m->raw_len > (int) m->max_len) 00683 return EX_TOOBIG; 00684 p = m->pre = m->raw; 00685 /* Search for \nDATA\n which marks start of actual message */ 00686 while ((p_len = (m->raw_len - (p - m->raw))) > 8) { /* leave room for at least \nDATA\n.\n */ 00687 char* q = memchr(p, '\n', p_len - 8); /* find next \n then see if start of \nDATA\n */ 00688 if (q == NULL) break; 00689 q++; 00690 if (((q[0]|0x20) == 'd') && /* case-insensitive ASCII comparison */ 00691 ((q[1]|0x20) == 'a') && 00692 ((q[2]|0x20) == 't') && 00693 ((q[3]|0x20) == 'a')) { 00694 q+=4; 00695 if (q[0] == '\r') ++q; 00696 if (*(q++) == '\n') { /* leave q at start of message if we found it */ 00697 m->msg = q; 00698 m->pre_len = q - m->raw; 00699 m->msg_len = m->raw_len - m->pre_len; 00700 break; 00701 } 00702 } 00703 p = q; /* the above code ensures no other '\n' comes before q */ 00704 } 00705 if (m->msg == NULL) 00706 return EX_DATAERR; 00707 00708 /* ensure this is >= 0 */ 00709 if (m->msg_len < 0) { 00710 return EX_SOFTWARE; 00711 } 00712 00713 /* Find the end-of-DATA line */ 00714 prev = '\n'; 00715 for (i = j = 0; i < (unsigned int) m->msg_len; i++) { 00716 if (prev == '\n' && m->msg[i] == '.') { 00717 /* Dot at the beginning of a line */ 00718 if (((int) (i+1) == m->msg_len) 00719 || ((int) (i+1) < m->msg_len && m->msg[i + 1] == '\n') 00720 || ((int) (i+2) < m->msg_len && m->msg[i + 1] == '\r' && m->msg[i + 2] == '\n')) { 00721 /* Lone dot! That's all, folks */ 00722 m->post = m->msg + i; 00723 m->post_len = m->msg_len - i; 00724 m->msg_len = j; 00725 break; 00726 } 00727 else if ((int) (i+1) < m->msg_len && m->msg[i + 1] == '.') { 00728 /* Escaping dot, eliminate. */ 00729 prev = '.'; 00730 continue; 00731 } /* Else an ordinary dot, drop down to ordinary char handler */ 00732 } 00733 prev = m->msg[i]; 00734 m->msg[j++] = m->msg[i]; 00735 } 00736 00737 /* if bad format with no end "\n.\n", error out */ 00738 if (m->post == NULL) 00739 return EX_DATAERR; 00740 m->type = MESSAGE_BSMTP; 00741 m->out = m->msg; 00742 m->out_len = m->msg_len; 00743 return EX_OK; 00744 }
|
|
||||||||||||
|
Definition at line 635 of file libspamc.c. References _clear_message(), EX_IOERR, EX_OK, EX_OSERR, EX_TOOBIG, libspamc_private_message::flags, full_read(), libspamc_log(), LOG_ERR, message::max_len, MESSAGE_ERROR, MESSAGE_RAW, message::msg, message::msg_len, message::out, message::out_len, message::priv, message::raw, message::raw_len, and message::type. Referenced by message_read(). 00636 { 00637 _clear_message(m); 00638 if ((m->raw = malloc(m->max_len + 1)) == NULL) 00639 return EX_OSERR; 00640 m->raw_len = full_read(fd, 1, m->raw, m->max_len + 1, m->max_len + 1); 00641 if (m->raw_len <= 0) { 00642 free(m->raw); 00643 m->raw = NULL; 00644 m->raw_len = 0; 00645 return EX_IOERR; 00646 } 00647 m->type = MESSAGE_ERROR; 00648 if (m->raw_len > (int) m->max_len) 00649 { 00650 libspamc_log(m->priv->flags, LOG_ERR, 00651 "skipped message, greater than max message size (%d bytes)", 00652 m->max_len); 00653 return EX_TOOBIG; 00654 } 00655 m->type = MESSAGE_RAW; 00656 m->msg = m->raw; 00657 m->msg_len = m->raw_len; 00658 m->out = m->msg; 00659 m->out_len = m->msg_len; 00660 return EX_OK; 00661 }
|
|
||||||||||||||||
|
Definition at line 205 of file libspamc.c. References closesocket, EX_NOPERM, EX_OSERR, EX_SOFTWARE, libspamc_log(), libspamc_timeout, LOG_ERR, and spamc_get_errno. Referenced by _try_to_connect_tcp(), and _try_to_connect_unix(). 00206 { 00207 int proto = 0; 00208 #endif 00209 const char *typename; 00210 int origerr; 00211 #ifdef _WIN32 00212 int socktout; 00213 #endif 00214 00215 assert(psock != 0); 00216 00217 /*---------------------------------------------------------------- 00218 * Create a few induction variables that are implied by the socket 00219 * type given by the user. The typename is strictly used for debug 00220 * reporting. 00221 */ 00222 #ifdef SPAMC_HAS_ADDRINFO 00223 switch(res->ai_family) { 00224 case PF_UNIX: 00225 typename = "PF_UNIX"; 00226 break; 00227 case PF_INET: 00228 typename = "PF_INET"; 00229 break; 00230 case PF_INET6: 00231 typename = "PF_INET6"; 00232 break; 00233 default: 00234 typename = "Unknown"; 00235 break; 00236 } 00237 #else 00238 if (type == PF_UNIX) { 00239 typename = "PF_UNIX"; 00240 } 00241 else { 00242 typename = "PF_INET"; 00243 proto = IPPROTO_TCP; 00244 } 00245 #endif 00246 00247 #ifdef DO_CONNECT_DEBUG_SYSLOGS 00248 libspamc_log(flags, CONNECT_DEBUG_LEVEL, "dbg: create socket(%s)", typename); 00249 #endif 00250 00251 #ifdef SPAMC_HAS_ADDRINFO 00252 if ((*psock = socket(res->ai_family, res->ai_socktype, res->ai_protocol)) 00253 #else 00254 if ((*psock = socket(type, SOCK_STREAM, proto)) 00255 #endif 00256 #ifndef _WIN32 00257 < 0 00258 #else 00259 == INVALID_SOCKET 00260 #endif 00261 ) { 00262 00263 /*-------------------------------------------------------- 00264 * At this point we had a failure creating the socket, and 00265 * this is pretty much fatal. Translate the error reason 00266 * into something the user can understand. 00267 */ 00268 origerr = spamc_get_errno(); 00269 #ifndef _WIN32 00270 libspamc_log(flags, LOG_ERR, "socket(%s) to spamd failed: %s", typename, strerror(origerr)); 00271 #else 00272 libspamc_log(flags, LOG_ERR, "socket(%s) to spamd failed: %d", typename, origerr); 00273 #endif 00274 00275 switch (origerr) { 00276 case EPROTONOSUPPORT: 00277 case EINVAL: 00278 return EX_SOFTWARE; 00279 00280 case EACCES: 00281 return EX_NOPERM; 00282 00283 case ENFILE: 00284 case EMFILE: 00285 case ENOBUFS: 00286 case ENOMEM: 00287 return EX_OSERR; 00288 00289 default: 00290 return EX_SOFTWARE; 00291 } 00292 } 00293 00294 #ifdef _WIN32 00295 /* bug 4344: makes timeout functional on Win32 */ 00296 socktout = libspamc_timeout * 1000; 00297 if (type == PF_INET 00298 && setsockopt(*psock, SOL_SOCKET, SO_RCVTIMEO, (char *)&socktout, sizeof(socktout)) != 0) 00299 { 00300 00301 origerr = spamc_get_errno(); 00302 switch (origerr) 00303 { 00304 case EBADF: 00305 case ENOTSOCK: 00306 case ENOPROTOOPT: 00307 case EFAULT: 00308 libspamc_log(flags, LOG_ERR, "setsockopt(SO_RCVTIMEO) failed: %d", origerr); 00309 closesocket(*psock); 00310 return EX_SOFTWARE; 00311 00312 default: 00313 break; /* ignored */ 00314 } 00315 } 00316 #endif 00317 00318 /*---------------------------------------------------------------- 00319 * Do a bit of setup on the TCP socket if required. Notes above 00320 * suggest this is probably not set 00321 */ 00322 #ifdef USE_TCP_NODELAY 00323 { 00324 int one = 1; 00325 00326 if (type == PF_INET 00327 && setsockopt(*psock, 0, TCP_NODELAY, &one, sizeof one) != 0) { 00328 origerr = spamc_get_errno(); 00329 switch (origerr) { 00330 case EBADF: 00331 case ENOTSOCK: 00332 case ENOPROTOOPT: 00333 case EFAULT: 00334 libspamc_log(flags, LOG_ERR, 00335 #ifndef _WIN32 00336 "setsockopt(TCP_NODELAY) failed: %s", strerror(origerr)); 00337 #else 00338 "setsockopt(TCP_NODELAY) failed: %d", origerr); 00339 #endif 00340 closesocket(*psock); 00341 return EX_SOFTWARE; 00342 00343 default: 00344 break; /* ignored */ 00345 } 00346 } 00347 } 00348 #endif /* USE_TCP_NODELAY */ 00349 00350 return EX_OK; /* all is well */ 00351 }
|
|
|
Definition at line 1749 of file libspamc.c. References transport::hosts, and transport::nhosts. Referenced by transport_setup(). 01750 { 01751 #ifdef SPAMC_HAS_ADDRINFO 01752 struct addrinfo *tmp; 01753 #else 01754 struct in_addr tmp; 01755 #endif 01756 int i; 01757 int rnum; 01758 01759 assert(tp != 0); 01760 01761 if (tp->nhosts <= 1) 01762 return; 01763 01764 rnum = rand() % tp->nhosts; 01765 01766 while (rnum-- > 0) { 01767 tmp = tp->hosts[0]; 01768 01769 /* TODO: free using freeaddrinfo() */ 01770 for (i = 1; i < tp->nhosts; i++) 01771 tp->hosts[i - 1] = tp->hosts[i]; 01772 01773 tp->hosts[i - 1] = tmp; 01774 } 01775 }
|
|
||||||||||||||||||||||||||||||||
|
Definition at line 858 of file libspamc.c. References EX_IOERR, EX_OK, EX_TOOBIG, fd_timeout_read(), libspamc_log(), LOG_ERR, SPAMC_USE_SSL, ssl_timeout_read(), and UNUSED_VARIABLE. Referenced by message_filter(), and message_tell(). 00860 { 00861 int failureval; 00862 int bytesread = 0; 00863 size_t len; 00864 00865 UNUSED_VARIABLE(m); 00866 00867 *lenp = 0; 00868 /* Now, read from spamd */ 00869 for (len = 0; len < bufsiz - 1; len++) { 00870 if (flags & SPAMC_USE_SSL) { 00871 bytesread = ssl_timeout_read(ssl, buf + len, 1); 00872 } 00873 else { 00874 bytesread = fd_timeout_read(sock, 0, buf + len, 1); 00875 } 00876 00877 if (bytesread <= 0) { 00878 failureval = EX_IOERR; 00879 goto failure; 00880 } 00881 00882 if (buf[len] == '\n') { 00883 buf[len] = '\0'; 00884 if (len > 0 && buf[len - 1] == '\r') { 00885 len--; 00886 buf[len] = '\0'; 00887 } 00888 *lenp = len; 00889 return EX_OK; 00890 } 00891 } 00892 00893 libspamc_log(flags, LOG_ERR, "spamd responded with line of %d bytes, dying", len); 00894 failureval = EX_TOOBIG; 00895 00896 failure: 00897 return failureval; 00898 }
|
|
|
Definition at line 165 of file libspamc.c. References EX_NOPERM, EX_SOFTWARE, and EX_UNAVAILABLE. Referenced by _try_to_connect_tcp(), and _try_to_connect_unix(). 00166 { 00167 switch (err) { 00168 case EBADF: 00169 case EFAULT: 00170 case ENOTSOCK: 00171 case EISCONN: 00172 case EADDRINUSE: 00173 case EINPROGRESS: 00174 case EALREADY: 00175 case EAFNOSUPPORT: 00176 return EX_SOFTWARE; 00177 00178 case ECONNREFUSED: 00179 case ETIMEDOUT: 00180 case ENETUNREACH: 00181 return EX_UNAVAILABLE; 00182 00183 case EACCES: 00184 return EX_NOPERM; 00185 00186 default: 00187 return EX_SOFTWARE; 00188 } 00189 }
|
|
||||||||||||
|
Definition at line 435 of file libspamc.c. References _opensocket(), _translate_connect_errno(), closesocket, transport::connect_retries, EX_OK, transport::flags, transport::hosts, libspamc_log(), LOG_DEBUG, LOG_ERR, transport::nhosts, transport::port, transport::retry_sleep, spamc_get_errno, SPAMC_MAXHOST, SPAMC_MAXSERV, and timeout_connect(). Referenced by message_filter(), and message_tell(). 00436 { 00437 int numloops; 00438 int origerr = 0; 00439 int ret; 00440 #ifdef SPAMC_HAS_ADDRINFO 00441 struct addrinfo *res = NULL; 00442 #else 00443 int res = PF_INET; 00444 #endif 00445 00446 char host[SPAMC_MAXHOST-1]; /* hostname, for logging */ 00447 char port[SPAMC_MAXSERV-1]; /* port, for logging */ 00448 00449 int connect_retries, retry_sleep; 00450 00451 assert(tp != 0); 00452 assert(sockptr != 0); 00453 assert(tp->nhosts > 0); 00454 00455 /* default values */ 00456 retry_sleep = tp->retry_sleep; 00457 connect_retries = tp->connect_retries; 00458 if (connect_retries == 0) { 00459 connect_retries = 3; 00460 } 00461 if (retry_sleep < 0) { 00462 retry_sleep = 1; 00463 } 00464 00465 for (numloops = 0; numloops < connect_retries; numloops++) { 00466 const int hostix = numloops % tp->nhosts; 00467 int status, mysock; 00468 00469 /*-------------------------------------------------------- 00470 * We always start by creating the socket, as we get only 00471 * one attempt to connect() on each one. If this fails, 00472 * we're done. 00473 */ 00474 00475 #ifdef SPAMC_HAS_ADDRINFO 00476 res = tp->hosts[hostix]; 00477 while(res) { 00478 char *family = NULL; 00479 switch(res->ai_family) { 00480 case AF_INET: 00481 family = "AF_INET"; 00482 break; 00483 case AF_INET6: 00484 family = "AF_INET6"; 00485 break; 00486 default: 00487 family = "Unknown"; 00488 break; 00489 } 00490 00491 if ((ret = _opensocket(tp->flags, res, &mysock)) != EX_OK) { 00492 res = res->ai_next; 00493 continue; 00494 } 00495 00496 getnameinfo(res->ai_addr, res->ai_addrlen, 00497 host, sizeof(host), 00498 port, sizeof(port), 00499 NI_NUMERICHOST|NI_NUMERICSERV); 00500 00501 #ifdef DO_CONNECT_DEBUG_SYSLOGS 00502 libspamc_log(tp->flags, CONNECT_DEBUG_LEVEL, 00503 "dbg: connect(%s) to spamd (host %s, port %s) (try #%d of %d)", 00504 family, host, port, numloops + 1, connect_retries); 00505 #endif 00506 00507 /* this is special-cased so that we have an address we can 00508 * safely use as an "always fail" test case */ 00509 if (!strcmp(host, "255.255.255.255")) { 00510 libspamc_log(tp->flags, LOG_ERR, 00511 "connect to spamd on %s failed, broadcast addr", 00512 host); 00513 status = -1; 00514 } 00515 else { 00516 status = timeout_connect(mysock, res->ai_addr, res->ai_addrlen); 00517 } 00518 00519 #else 00520 struct sockaddr_in addrbuf; 00521 const char *ipaddr; 00522 const char* family="AF_INET"; 00523 if ((ret = _opensocket(tp->flags, PF_INET, &mysock)) != EX_OK) 00524 return ret; 00525 00526 memset(&addrbuf, 0, sizeof(addrbuf)); 00527 00528 addrbuf.sin_family = AF_INET; 00529 addrbuf.sin_port = htons(tp->port); 00530 addrbuf.sin_addr = tp->hosts[hostix]; 00531 00532 ipaddr = inet_ntoa(addrbuf.sin_addr); 00533 00534 /* make a copy in host, for logging (bug 5577) */ 00535 strncpy (host, ipaddr, sizeof(host) - 1); 00536 00537 #ifdef DO_CONNECT_DEBUG_SYSLOGS 00538 libspamc_log(tp->flags, LOG_DEBUG, 00539 "dbg: connect(AF_INET) to spamd at %s (try #%d of %d)", 00540 ipaddr, numloops + 1, connect_retries); 00541 #endif 00542 00543 /* this is special-cased so that we have an address we can 00544 * safely use as an "always fail" test case */ 00545 if (!strcmp(ipaddr, "255.255.255.255")) { 00546 libspamc_log(tp->flags, LOG_ERR, 00547 "connect to spamd on %s failed, broadcast addr", 00548 ipaddr); 00549 status = -1; 00550 } 00551 else { 00552 status = timeout_connect(mysock, (struct sockaddr *) &addrbuf, 00553 sizeof(addrbuf)); 00554 } 00555 00556 #endif 00557 00558 if (status != 0) { 00559 origerr = spamc_get_errno(); 00560 closesocket(mysock); 00561 00562 #ifndef _WIN32 00563 libspamc_log(tp->flags, LOG_ERR, 00564 "connect to spamd on %s failed, retrying (#%d of %d): %s", 00565 host, numloops+1, connect_retries, strerror(origerr)); 00566 #else 00567 libspamc_log(tp->flags, LOG_ERR, 00568 "connect to spamd on %s failed, retrying (#%d of %d): %d", 00569 host, numloops+1, connect_retries, origerr); 00570 #endif 00571 00572 } else { 00573 #ifdef DO_CONNECT_DEBUG_SYSLOGS 00574 libspamc_log(tp->flags, CONNECT_DEBUG_LEVEL, 00575 "dbg: connect(%s) to spamd done",family); 00576 #endif 00577 *sockptr = mysock; 00578 00579 return EX_OK; 00580 } 00581 #ifdef SPAMC_HAS_ADDRINFO 00582 res = res->ai_next; 00583 } 00584 #endif 00585 sleep(retry_sleep); 00586 } /* for(numloops...) */ 00587 00588 #ifdef SPAMC_HAS_ADDRINFO 00589 for(numloops=0;numloops<tp->nhosts;numloops++) { 00590 freeaddrinfo(tp->hosts[numloops]); 00591 } 00592 #endif 00593 00594 libspamc_log(tp->flags, LOG_ERR, 00595 "connection attempt to spamd aborted after %d retries", 00596 connect_retries); 00597 00598 return _translate_connect_errno(origerr); 00599 }
|
|
||||||||||||
|
Definition at line 361 of file libspamc.c. References _opensocket(), _translate_connect_errno(), closesocket, EX_OK, EX_OSERR, transport::flags, libspamc_log(), LOG_ERR, transport::socketpath, and timeout_connect(). Referenced by message_filter(), and message_tell(). 00362 { 00363 #ifndef _WIN32 00364 int mysock, status, origerr; 00365 struct sockaddr_un addrbuf; 00366 #ifdef SPAMC_HAS_ADDRINFO 00367 struct addrinfo hints, *res; 00368 #else 00369 int res = PF_UNIX; 00370 #endif 00371 int ret; 00372 00373 assert(tp != 0); 00374 assert(sockptr != 0); 00375 assert(tp->socketpath != 0); 00376 00377 #ifdef SPAMC_HAS_ADDRINFO 00378 memset(&hints, 0, sizeof(hints)); 00379 hints.ai_family = PF_UNIX; 00380 hints.ai_socktype = SOCK_STREAM; 00381 hints.ai_protocol = 0; 00382 res = &hints; 00383 #endif 00384 /*---------------------------------------------------------------- 00385 * If the socket itself can't be created, this is a fatal error. 00386 */ 00387 if ((ret = _opensocket(tp->flags, res, &mysock)) != EX_OK) 00388 return ret; 00389 00390 /* set up the UNIX domain socket */ 00391 memset(&addrbuf, 0, sizeof addrbuf); 00392 addrbuf.sun_family = AF_UNIX; 00393 strncpy(addrbuf.sun_path, tp->socketpath, sizeof addrbuf.sun_path - 1); 00394 addrbuf.sun_path[sizeof addrbuf.sun_path - 1] = '\0'; 00395 00396 #ifdef DO_CONNECT_DEBUG_SYSLOGS 00397 libspamc_log(tp->flags, CONNECT_DEBUG_LEVEL, "dbg: connect(AF_UNIX) to spamd at %s", 00398 addrbuf.sun_path); 00399 #endif 00400 00401 status = timeout_connect(mysock, (struct sockaddr *) &addrbuf, sizeof(addrbuf)); 00402 00403 origerr = errno; 00404 00405 if (status >= 0) { 00406 #ifdef DO_CONNECT_DEBUG_SYSLOGS 00407 libspamc_log(tp->flags, CONNECT_DEBUG_LEVEL, "dbg: connect(AF_UNIX) ok"); 00408 #endif 00409 00410 *sockptr = mysock; 00411 00412 return EX_OK; 00413 } 00414 00415 libspamc_log(tp->flags, LOG_ERR, "connect(AF_UNIX) to spamd %s failed: %s", 00416 addrbuf.sun_path, strerror(origerr)); 00417 closesocket(mysock); 00418 00419 return _translate_connect_errno(origerr); 00420 #else 00421 (void) tp; /* not used. suppress compiler warning */ 00422 (void) sockptr; /* not used. suppress compiler warning */ 00423 return EX_OSERR; 00424 #endif 00425 }
|