diff options
Diffstat (limited to 'src/smtpstone/smtp-source.c')
-rw-r--r-- | src/smtpstone/smtp-source.c | 94 |
1 files changed, 70 insertions, 24 deletions
diff --git a/src/smtpstone/smtp-source.c b/src/smtpstone/smtp-source.c index be388d6..f9fa64f 100644 --- a/src/smtpstone/smtp-source.c +++ b/src/smtpstone/smtp-source.c @@ -42,7 +42,7 @@ /* Don't disconnect after sending a message; send the next /* message over the same connection. /* .IP "\fB-f \fIfrom\fR" -/* Use the specified sender address (default: <foo@myhostname>). +/* Use the specified sender address (default: <foo@my-hostname>). /* .IP "\fB-F \fIfile\fR" /* Send the pre-formatted message header and body in the /* specified \fIfile\fR, while prepending '.' before lines that @@ -54,31 +54,49 @@ /* Speak LMTP rather than SMTP. /* .IP "\fB-m \fImessage_count\fR" /* Send the specified number of messages (default: 1). -/* .IP "\fB-M \fImyhostname\fR" +/* .IP "\fB-M \fImy-hostname\fR" /* Use the specified hostname or [address] in the HELO command /* and in the default sender and recipient addresses, instead /* of the machine hostname. /* .IP "\fB-N\fR" -/* Prepend a non-repeating sequence number to each recipient -/* address. This avoids the artificial 100% hit rate in the -/* resolve and rewrite client caches and exercises the -/* trivial-rewrite daemon, better approximating Postfix -/* performance under real-life work-loads. +/* Generate each recipient address by appending a number (a +/* per-process recipient counter) to the recipient address +/* localpart specified with the \fB-t\fR option. +/* +/* Note: to use the number as an address extension, specify +/* an explicit address delimiter at the end of the recipient +/* localpart, as in "\fB-t localpart+@domain\fR" or "\fB-t +/* localpart+\fR", where "\fB+\fR" is a Postfix recipient +/* address delimiter. +/* +/* Benefits: +/* .RS +/* .IP \(bu +/* A non-constant recipient address avoids an unrealistic 100% +/* cache hit rate in clients of the Postfix trivial-rewrite +/* service, better approximating performance under real-life +/* work-loads. +/* .IP \(bu +/* A fixed recipient address local-part with a non-constant +/* address extension avoids the need to configure a large +/* number of valid recipient addresses in the receiving Postfix +/* server. +/* .RE /* .IP \fB-o\fR /* Old mode: don't send HELO, and don't send message headers. /* .IP "\fB-r \fIrecipient_count\fR" -/* Send the specified number of recipients per transaction (default: 1). -/* Recipient names are generated by prepending a number to the -/* recipient address. +/* Send the specified number of recipients per transaction +/* (default: 1), and generate recipient addresses as described +/* under the \fB-N\fR option. /* .IP "\fB-R \fIinterval\fR" -/* Wait for a random period of time 0 <= n <= interval between messages. +/* Wait a random time (0 <= n <= \fIinterval\fR) between messages. /* Suspending one thread does not affect other delivery threads. /* .IP "\fB-s \fIsession_count\fR" /* Run the specified number of SMTP sessions in parallel (default: 1). /* .IP "\fB-S \fIsubject\fR" /* Send mail with the named subject line (default: none). /* .IP "\fB-t \fIto\fR" -/* Use the specified recipient address (default: <foo@myhostname>). +/* Use the specified recipient address (default: <foo@my-hostname>). /* .IP "\fB-T \fIwindowsize\fR" /* Override the default TCP window size. To work around /* broken TCP window scaling implementations, specify a @@ -172,6 +190,7 @@ typedef struct SESSION { int rcpt_done; /* # of recipients done */ int rcpt_count; /* # of recipients to go */ int rcpt_accepted; /* # of recipients accepted */ + int rcpt_sample; /* Sample recipient # for To: header */ VSTREAM *stream; /* open connection */ int connect_count; /* # of connect()s to retry */ struct SESSION *next; /* connect() queue linkage */ @@ -202,7 +221,11 @@ static struct sockaddr *sa; static int sa_length; static int recipients = 1; static char *defaddr; -static char *recipient; +typedef struct { + char *local; + char *at_domain; +} RECIPIENT; +static RECIPIENT *recipient; static char *sender; static char *message_data; static int message_length; @@ -216,7 +239,8 @@ static int random_delay = 0; static int fixed_delay = 0; static int talk_lmtp = 0; static char *subject = 0; -static int number_rcpts = 0; +static int global_rcpt_suffix = 0; +static int global_rcpt_done = 0; static int allow_reject = 0; static void enqueue_connect(SESSION *); @@ -238,6 +262,20 @@ static void send_quit(SESSION *); static void quit_done(int, void *); static void close_session(SESSION *); +/* make_recipient - parse recipient into localpart and at_domain */ + +static RECIPIENT *make_recipient(const char *address) +{ + RECIPIENT *rp = (RECIPIENT *) mymalloc(sizeof(*rp)); + const char *at; + + if ((at = strrchr(address, '@')) == 0) + at = address + strlen(address); + rp->local = mystrndup(address, at - address); + rp->at_domain = mystrdup(at); + return (rp); +} + /* random_interval - generate a random value in 0 .. (small) interval */ static int random_interval(int interval) @@ -655,12 +693,13 @@ static void send_rcpt(int unused_event, void *context) if ((except = vstream_setjmp(session->stream)) != 0) msg_fatal("%s while sending recipient", exception_text(except)); - if (session->rcpt_count > 1 || number_rcpts > 0) - command(session->stream, "RCPT TO:<%d%s>", - number_rcpts ? number_rcpts++ : session->rcpt_count, - recipient); + if (global_rcpt_suffix) + command(session->stream, "RCPT TO:<%s%d%s>", + recipient->local, session->rcpt_sample = global_rcpt_done++, + recipient->at_domain); else - command(session->stream, "RCPT TO:<%s>", recipient); + command(session->stream, "RCPT TO:<%s%s>", + recipient->local, recipient->at_domain); session->rcpt_count--; session->rcpt_done++; @@ -765,10 +804,16 @@ static void data_done(int unused, void *context) mypid = getpid(); } smtp_printf(session->stream, "From: <%s>", sender); - smtp_printf(session->stream, "To: <%s>", recipient); + if (global_rcpt_suffix) + smtp_printf(session->stream, "To: <%s%d%s>", recipient->local, + session->rcpt_sample, recipient->at_domain); + else + smtp_printf(session->stream, "To: <%s%s>", + recipient->local, recipient->at_domain); smtp_printf(session->stream, "Date: %s", mydate); smtp_printf(session->stream, "Message-Id: <%04x.%04x.%04x@%s>", - mypid, vstream_fileno(session->stream), message_count, var_myhostname); + mypid, vstream_fileno(session->stream), message_count, + var_myhostname); if (subject) smtp_printf(session->stream, "Subject: %s", subject); smtp_fputs("", 0, session->stream); @@ -1021,7 +1066,7 @@ int main(int argc, char **argv) var_myhostname = optarg; break; case 'N': - number_rcpts = 1; + global_rcpt_suffix = 1; break; case 'o': send_helo_first = 0; @@ -1030,6 +1075,7 @@ int main(int argc, char **argv) case 'r': if ((recipients = atoi(optarg)) <= 0) msg_fatal("bad recipient count: %s", optarg); + global_rcpt_suffix = 1; break; case 'R': if (fixed_delay > 0) @@ -1045,7 +1091,7 @@ int main(int argc, char **argv) subject = optarg; break; case 't': - recipient = optarg; + recipient = make_recipient(optarg); break; case 'T': if ((inet_windowsize = atoi(optarg)) <= 0) @@ -1160,7 +1206,7 @@ int main(int argc, char **argv) if (sender == 0) sender = defaddr; if (recipient == 0) - recipient = defaddr; + recipient = make_recipient(defaddr); } /* |