Index: ChangeLog =================================================================== RCS file: /home/mea/src/CVSROOT/zmailer/ChangeLog,v retrieving revision 1.187 retrieving revision 1.189 diff -u -r1.187 -r1.189 --- ChangeLog 1999/07/05 11:08:00 1.187 +++ ChangeLog 1999/07/05 14:26:05 1.189 @@ -1,5 +1,16 @@ 1999-07-05 Matti Aarnio + * transports/smtp/smtp.c: + Reworked the EHLO/HELO reconnect mechanisms. Now it + reconnects to the *same* address where EHLO failed + just previously. Otherwise it could connect to some + other address in case the target has several addresses.. + + * lib/rfc822scan.c: + MKERROR() did crash for some reason in previous form. + Modified call a bit and changed it into a static function + of its own. Now it seems to work. + * Makefile.in: Version 2.99.51-pre1 Index: lib/rfc822scan.c =================================================================== RCS file: /home/mea/src/CVSROOT/zmailer/lib/rfc822scan.c,v retrieving revision 1.9 retrieving revision 1.10 diff -u -r1.9 -r1.10 --- lib/rfc822scan.c 1999/07/04 00:57:21 1.9 +++ lib/rfc822scan.c 1999/07/05 13:42:09 1.10 @@ -126,10 +126,23 @@ } } -#define MKERROR(msg,prev) tn = makeToken((msg), strlen(msg)); \ +#if 0 +#define MKERROR(msg,prevp) tn = makeToken((msg), strlen(msg)); \ tn->t_type = Error; \ - tn->t_next = (prev); \ - (prev) = tn; + tn->t_next = *(prevp); \ + *(prevp) = tn; +#else +static void +MKERROR(msg, prevp) + const char *msg; + token822 **prevp; +{ + token822 *tn = makeToken((msg), strlen(msg)); + tn->t_type = Error; + tn->t_next = *(prevp); + *(prevp) = tn; +} +#endif /* * Recognize a compound token, or rather, a token which is defined by @@ -167,12 +180,13 @@ } else if (*cp == cstart) { if (type == Comment) ++nest; - else - MKERROR("illegal char in compound", *tlist); + else { + MKERROR("illegal char in compound", tlist); + } } else if (*cp == '\\') { if (n == 1) { MKERROR("missing character after backslash", - *tlist); + tlist); /* Continue with next line, if existing! */ n = 0; break; @@ -182,7 +196,7 @@ ++len; } else if (*cp == '\r') { /* type = Error; */ - MKERROR("illegal CR in token",*tlist); + MKERROR("illegal CR in token", tlist); } } /* we either found cend, or ran off the end, either may be within @@ -201,7 +215,7 @@ } /* type = Error; */ /* hey, no reason to refuse a message */ sprintf(msgbuf, "missing closing '%c' in token", cend); - MKERROR(msgbuf,*tlist); + MKERROR(msgbuf, tlist); tp->t_pname = 0; /* ugly way of signalling scanner */ } else if (*cp == cend) { /* we found matching terminator */ ++len; /* move past terminator */ @@ -308,19 +322,19 @@ continue; if (n == 0 || !(rfc_ctype[(*cp) & 0xFF] & _l)) { strcpy(msgbuf, "CR without LF (newline)"); - MKERROR(msgbuf,tlist); + MKERROR(msgbuf, &tlist); } else if (n > 1 && (rfc_ctype[(*cp) & 0xFF] & _l)) { while (--n > 0 && (rfc_ctype[(*++cp) & 0xFF] & _l)) continue; strcpy(msgbuf,"too many newlines (LFs) in field[1]"); - MKERROR(msgbuf,tlist); + MKERROR(msgbuf, &tlist); } t.t_type = Fold; } else if (ct & _l) { /* >= 1 LFs without CR is a fold too */ while (--n > 0 && (rfc_ctype[(*++cp) & 0xFF] & _l)) continue; strcpy(msgbuf,"too many newlines (LFs) in field[2]"); - MKERROR(msgbuf,tlist); + MKERROR(msgbuf, &tlist); t.t_type = Fold; } else if ((ct & _s) && (*cp=='(' || *cp=='"' || *cp=='[')) { TokenType type; @@ -387,7 +401,7 @@ strcpy(msgbuf, "illegal control character"); if (t.t_len > n+1) strcat(msgbuf, "s"); - MKERROR(msgbuf,tlist); + MKERROR(msgbuf, &tlist); t.t_type = Atom; } t.t_len -= n; @@ -407,6 +421,7 @@ } } while (n > 0); + /* Reverse the token822 chain */ tp = tn = NULL; for (tp = NULL; tlist != NULL; tlist = tn) { tn = tlist->t_next; Index: transports/smtp/smtp.c =================================================================== RCS file: /home/mea/src/CVSROOT/zmailer/transports/smtp/smtp.c,v retrieving revision 1.83 retrieving revision 1.87 diff -u -r1.83 -r1.87 --- transports/smtp/smtp.c 1999/07/04 14:13:13 1.83 +++ transports/smtp/smtp.c 1999/07/05 15:45:53 1.87 @@ -322,6 +322,10 @@ char *mailfrommsg; char ipaddress[200]; + struct addrinfo *ai; /* Lattest active connection */ + int ismx; + struct addrinfo *ai_root; /* All lattest addresses */ + char stdinbuf[8192]; int stdinsize; /* Available */ int stdincurs; /* Consumed */ @@ -365,7 +369,8 @@ extern int check_7bit_cleanness __((struct ctldesc *dp)); extern void notarystatsave __((SmtpState *SS, char *smtpstatline, char *status)); -extern int makeconn __((SmtpState *SS, struct addrinfo *, int)); +extern int makeconn __((SmtpState *SS, struct addrinfo *, int)); +extern int makereconn __((SmtpState *SS)); extern int vcsetup __((SmtpState *SS, struct sockaddr *, int*, char*)); #ifdef BIND extern int rightmx __((const char*, const char*, void*)); @@ -2348,7 +2353,7 @@ if (i == EX_TEMPFAIL) { /* There are systems, which hang up on us, when we greet them with an "EHLO".. Do here a normal "HELO".. */ - i = smtpconn(SS, host, noMX); + i = makereconn(SS); if (i != EX_OK) continue; i = EX_TEMPFAIL; @@ -2374,7 +2379,7 @@ } if (i == EX_TEMPFAIL) { /* Ok, sometimes EHLO+HELO cause crash, open and do HELO only */ - i = smtpconn(SS, host, noMX); + i = makereconn(SS); if (i != EX_OK) continue;; i = smtpwrite(SS, 1, SMTPbuf, 0, NULL); @@ -2514,6 +2519,7 @@ SS->mxcount = 0; retval = makeconn(SS, ai, -2); + ai = NULL; /* Don't free -- now */ } else { @@ -2655,13 +2661,16 @@ "smtp; 500 (nameserver data inconsistency. All MXes rejected [we are the best?], no address: '%.200s')", host); #if 1 zsyslog((LOG_ERR, "%s", SS->remotemsg)); - r = EX_NOHOST; + if (r != EX_TEMPFAIL) + r = EX_NOHOST; #endif } else if (gai_err == EAI_NONAME || gai_err == EAI_NODATA) { sprintf(SS->remotemsg, "smtp; 500 (nameserver data inconsistency. No MX, no address: '%.200s')", host); - r = EX_NOHOST; /* Can do instant reject */ + zsyslog((LOG_ERR, "%s r=%d", SS->remotemsg, r)); + if (r != EX_TEMPFAIL) + r = EX_NOHOST; /* Can do instant reject */ } else { sprintf(SS->remotemsg, "smtp; 500 (nameserver data inconsistency. No MX, no address: '%.200s', errno=%s, gai_errno='%s')", @@ -2690,8 +2699,8 @@ notary_setwtt(buf); } retval = makeconn(SS, ai, -1); - freeaddrinfo(ai); - ai = NULL; + /* freeaddrinfo(ai); -- stored into the SS */ + ai = NULL; /* Make sure we don't free the 'ai' chain below */ } else { /* Has valid MX records, they have been suitably randomized @@ -2708,6 +2717,8 @@ r = makeconn(SS, SS->mxh[i].ai, i); SS->firstmx = i+1; + SS->mxh[i].ai = NULL; /* Save this chain into + internal SS context! */ if (r == EX_OK) { retval = EX_OK; break; @@ -2721,8 +2732,11 @@ fprintf(logfp, "%s#\tsmtpconn: retval = %d\n", logtag(), retval); } - if (ai != NULL) - freeaddrinfo(ai); + + if (retval != EX_OK) + if (ai != NULL) + freeaddrinfo(ai); + return retval; } @@ -2802,8 +2816,9 @@ } #endif /* RFC974 */ #endif /* BIND */ + - retval = EX_UNAVAILABLE; + retval = EX_TEMPFAIL; #if 0 if (SS->verboselog) { fprintf(SS->verboselog,"makeconn('%.200s') to IP addresses:", hostbuf); @@ -2815,6 +2830,16 @@ fprintf(SS->verboselog,"\n"); } #endif + + /* discard old reconnect state */ + + if (SS->ai_root) + freeaddrinfo(SS->ai_root); + + /* Save new reconnect state */ + + SS->ai_root = ai; + for ( ; ai && !getout ; ai = ai->ai_next ) { int i = 0; @@ -2823,6 +2848,10 @@ struct sockaddr_in6 *si6; #endif + /* For possible reconnect */ + SS->ai = ai; + SS->ismx = ismx; + if (ai->ai_family == AF_INET) { si = (struct sockaddr_in *)ai->ai_addr; i = matchmyaddress((struct sockaddr*)ai->ai_addr); @@ -2869,6 +2898,7 @@ break; } sprintf(SS->remotemsg,"Trying to talk with myself!"); + retval = EX_UNAVAILABLE; break; /* TEMPFAIL or UNAVAILABLE.. */ } @@ -2880,7 +2910,8 @@ } - i = vcsetup(SS, /* (struct sockaddr *) */ ai->ai_addr, &mfd, hostbuf); + i = vcsetup(SS, /* (struct sockaddr*) */ ai->ai_addr, &mfd, hostbuf); + retval = i; switch (i) { case EX_OK: @@ -2915,13 +2946,22 @@ retval = EX_TEMPFAIL; break; } - } + } /* end of for-loop */ + if (getout) retval = EX_TEMPFAIL; return retval; } int +makereconn(SS) + SmtpState *SS; +{ + smtpclose(SS); + return makeconn(SS, SS->ai, SS->ismx); +} + +int vcsetup(SS, sa, fdp, hostname) SmtpState *SS; struct sockaddr *sa; @@ -3822,8 +3862,7 @@ if (strncmp(SS->pipecmds[idx], "RSET",4) != 0) /* If RSET, append to previous! */ SS->remotemsg[0] = 0; - rmsgappend(SS,"\r<<- "); - rmsgappend(SS,"%s", SS->pipecmds[idx]); + rmsgappend(SS,"\r<<- %s", SS->pipecmds[idx]); } else { strcpy(SS->remotemsg,"\r<<- (null)"); } @@ -4165,8 +4204,7 @@ if (strbuf) { if (strncmp(strbuf,"RSET",4) != 0) /* If RSET, append to previous! */ *SS->remotemsg = 0; - rmsgappend(SS,"\r<<- "); - rmsgappend(SS,"%s", strbuf); + rmsgappend(SS,"\r<<- %s", strbuf); } else { strcpy(SS->remotemsg,"\r<<- (null)"); } @@ -4224,6 +4262,9 @@ if (*s != '\n') break; *s = '\0'; + + rmsgappend(SS,"\r->> %s",buf); + if (SS->within_ehlo) ehlo_check(SS,&buf[4]); if (!strbuf && !SS->esmtp_on_banner) @@ -4324,7 +4365,7 @@ return EX_TEMPFAIL; } *--cp = '\0'; /* kill the LF */ - if ((cp - buf) < 4) { + if ((cp - buf) < 3) { /* A '354' could be treated as ok... */ sprintf(SS->remotemsg, "smtp; 500 (SMTP response '%s' unexpected!)", buf); time(&endtime); @@ -4360,9 +4401,6 @@ if (!strbuf && !SS->esmtp_on_banner) esmtp_banner_check(SS,&buf[4]); - rmsgappend(SS,"\r->> %s",buf); - - dflag = 0; if (response >= 400)