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  <[email protected]>

+       * 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<CRLR>' 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)