119 #include <sys/socket.h>
120 #include <sys/wait.h>
121 #include <netinet/in.h>
193 static int var_timeout = 300;
195 static int session_count;
196 static int message_count = 1;
197 static struct sockaddr_storage ss;
200 static struct sockaddr_un sun;
201 static struct sockaddr *sa;
202 static int sa_length;
203 static int recipients = 1;
204 static char *defaddr;
205 static char *recipient;
207 static char *message_data;
208 static int message_length;
209 static int disconnect = 1;
210 static int count = 0;
211 static int counter = 0;
212 static int send_helo_first = 1;
213 static int send_headers = 1;
214 static int connect_count = 1;
215 static int random_delay = 0;
216 static int fixed_delay = 0;
217 static int talk_lmtp = 0;
218 static char *subject = 0;
219 static int number_rcpts = 0;
220 static int allow_reject = 0;
222 static void enqueue_connect(
SESSION *);
223 static void start_connect(
SESSION *);
224 static void connect_done(
int,
void *);
225 static void read_banner(
int,
void *);
226 static void send_helo(
SESSION *);
227 static void helo_done(
int,
void *);
228 static void send_mail(
SESSION *);
229 static void mail_done(
int,
void *);
230 static void send_rcpt(
int,
void *);
231 static void rcpt_done(
int,
void *);
232 static void send_data(
int,
void *);
233 static void data_done(
int,
void *);
234 static void dot_done(
int,
void *);
235 static void send_rset(
int,
void *);
236 static void rset_done(
int,
void *);
237 static void send_quit(
SESSION *);
238 static void quit_done(
int,
void *);
239 static void close_session(
SESSION *);
243 static int random_interval(
int interval)
245 return (rand() % (interval + 1));
250 static void command(
VSTREAM *stream,
char *
fmt,...)
274 static int socket_error(
int sock)
284 error_len =
sizeof(error);
285 if (getsockopt(sock, SOL_SOCKET, SO_ERROR, (
void *) &error, &error_len) < 0)
311 if (rdata.
buf == 0) {
321 #define BUF ((char *) vstring_str(buf))
325 for (cp =
BUF; *cp != 0; cp++)
333 rdata.
code = (cp -
BUF == 3 ? atoi(BUF) : 0);
334 if ((more = (*cp ==
'-')) != 0)
350 static char *exception_text(
int except)
354 return (
"lost connection");
358 msg_panic(
"exception_text: unknown exception %d", except);
365 static void startup(
SESSION *session)
367 if (message_count-- <= 0) {
372 if (session->
stream == 0) {
373 enqueue_connect(session);
381 static void start_event(
int unused_event,
void *context)
390 static void start_another(
SESSION *session)
392 if (random_delay > 0) {
394 random_interval(random_delay));
395 }
else if (fixed_delay > 0) {
404 static void enqueue_connect(
SESSION *session)
407 if (last_session == 0) {
408 last_session = session;
409 start_connect(session);
411 last_session->
next = session;
412 last_session = session;
418 static void dequeue_connect(
SESSION *session)
420 if (session == last_session) {
421 if (session->
next != 0)
422 msg_panic(
"dequeue_connect: queue ends after last");
425 if (session->
next == 0)
426 msg_panic(
"dequeue_connect: queue ends before last");
427 start_connect(session->
next);
433 static void fail_connect(
SESSION *session)
441 #ifdef MISSING_USLEEP
446 start_connect(session);
451 static void start_connect(
SESSION *session)
454 struct linger linger;
462 if ((fd = socket(sa->sa_family, SOCK_STREAM, 0)) < 0)
467 if (setsockopt(fd, SOL_SOCKET, SO_LINGER, (
void *) &linger,
469 msg_warn(
"setsockopt SO_LINGER %d: %m", linger.l_linger);
475 if (
sane_connect(fd, sa, sa_length) < 0 && errno != EINPROGRESS)
476 fail_connect(session);
481 static void connect_done(
int unused_event,
void *context)
490 if (socket_error(fd) < 0) {
491 fail_connect(session);
497 dequeue_connect(session);
499 if (sa->sa_family == AF_INET
501 || sa->sa_family == AF_INET6
510 static void read_banner(
int unused_event,
void *context)
520 msg_fatal(
"%s while reading server greeting", exception_text(except));
525 if (((resp = response(session->
stream, buffer))->code / 100) == 2) {
527 }
else if (allow_reject) {
544 static void send_helo(
SESSION *session)
547 const char *
NOCLOBBER protocol = (talk_lmtp ?
"LHLO" :
"HELO");
553 msg_fatal(
"%s while sending %s", exception_text(except), protocol);
555 command(session->
stream,
"%s %s", protocol, var_myhostname);
565 static void helo_done(
int unused_event,
void *context)
570 const char *protocol = (talk_lmtp ?
"LHLO" :
"HELO");
576 msg_fatal(
"%s while sending %s", exception_text(except), protocol);
578 if ((resp = response(session->
stream, buffer))->code / 100 == 2) {
580 }
else if (allow_reject) {
582 if (resp->
code == 421 || resp->
code == 521) {
583 close_session(session);
595 static void send_mail(
SESSION *session)
603 msg_fatal(
"%s while sending sender", exception_text(except));
605 command(session->
stream,
"MAIL FROM:<%s>", sender);
615 static void mail_done(
int unused,
void *context)
625 msg_fatal(
"%s while sending sender", exception_text(except));
627 if ((resp = response(session->
stream, buffer))->code / 100 == 2) {
631 send_rcpt(unused, context);
632 }
else if (allow_reject) {
634 if (resp->
code == 421 || resp->
code == 521) {
635 close_session(session);
638 send_rset(unused, context);
646 static void send_rcpt(
int unused_event,
void *context)
655 msg_fatal(
"%s while sending recipient", exception_text(except));
657 if (session->
rcpt_count > 1 || number_rcpts > 0)
658 command(session->
stream,
"RCPT TO:<%d%s>",
659 number_rcpts ? number_rcpts++ : session->
rcpt_count,
662 command(session->
stream,
"RCPT TO:<%s>", recipient);
674 static void rcpt_done(
int unused,
void *context)
684 msg_fatal(
"%s while sending recipient", exception_text(except));
686 if ((resp = response(session->
stream, buffer))->code / 100 == 2) {
688 }
else if (allow_reject) {
690 if (resp->
code == 421 || resp->
code == 521) {
691 close_session(session);
702 send_rcpt(unused, context);
704 send_data(unused, context);
706 send_rset(unused, context);
711 static void send_data(
int unused_event,
void *context)
720 msg_fatal(
"%s while sending DATA command", exception_text(except));
721 command(session->
stream,
"DATA");
731 static void data_done(
int unused,
void *context)
736 static const char *mydate;
743 msg_fatal(
"%s while sending DATA command", exception_text(except));
744 if ((resp = response(session->
stream, buffer))->code == 354) {
746 }
else if (allow_reject) {
748 if (resp->
code == 421 || resp->
code == 521) {
749 close_session(session);
752 send_rset(unused, context);
780 msg_fatal(
"%s while sending message", exception_text(except));
781 if (message_length == 0) {
798 command(session->
stream,
".");
817 static void dot_done(
int unused_event,
void *context)
827 msg_fatal(
"%s while sending message", exception_text(except));
829 if ((resp = response(session->
stream, buffer))->code / 100 == 2) {
831 }
else if (allow_reject) {
833 if (resp->
code == 421 || resp->
code == 521) {
834 close_session(session);
840 }
while (talk_lmtp && --session->
rcpt_done > 0);
846 if (disconnect || message_count < 1) {
850 start_another(session);
856 static void send_rset(
int unused_event,
void *context)
860 command(session->
stream,
"RSET");
866 static void rset_done(
int unused_event,
void *context)
876 msg_fatal(
"%s while sending message", exception_text(except));
877 if ((resp = response(session->
stream, buffer))->code / 100 == 2) {
879 }
else if (allow_reject) {
881 if (resp->
code == 421 || resp->
code == 521) {
882 close_session(session);
892 if (disconnect || message_count < 1) {
896 start_another(session);
902 static void send_quit(
SESSION *session)
904 command(session->
stream,
"QUIT");
910 static void quit_done(
int unused_event,
void *context)
914 (void) response(session->
stream, buffer);
918 start_another(session);
923 static void close_session(
SESSION *session)
928 start_another(session);
933 static void usage(
char *myname)
935 msg_fatal(
"usage: %s -cdLNov -s sess -l msglen -m msgs -C count -M myhostname -f from -t to -r rcptcount -R delay -w delay host[:port]", myname);
942 int main(
int argc,
char **argv)
953 const char *parse_err;
954 struct addrinfo *res;
957 char *message_file = 0;
964 signal(SIGPIPE, SIG_IGN);
970 while ((ch =
GETOPT(argc, argv,
"46AcC:df:F:l:Lm:M:Nor:R:s:S:t:T:vw:")) > 0) {
985 if ((connect_count = atoi(optarg)) <= 0)
986 msg_fatal(
"bad connection count: %s", optarg);
995 if (message_file == 0 && message_length > 0)
996 msg_fatal(
"-l option cannot be used with -F");
997 message_file = optarg;
1000 if (message_file != 0)
1001 msg_fatal(
"-l option cannot be used with -F");
1002 if ((message_length = atoi(optarg)) <= 0)
1003 msg_fatal(
"bad message length: %s", optarg);
1009 if ((message_count = atoi(optarg)) <= 0)
1010 msg_fatal(
"bad message count: %s", optarg);
1013 if (*optarg ==
'[') {
1015 msg_fatal(
"bad address literal: %s", optarg);
1026 send_helo_first = 0;
1030 if ((recipients = atoi(optarg)) <= 0)
1031 msg_fatal(
"bad recipient count: %s", optarg);
1034 if (fixed_delay > 0)
1035 msg_fatal(
"do not use -w and -R options at the same time");
1036 if ((random_delay = atoi(optarg)) <= 0)
1037 msg_fatal(
"bad random delay: %s", optarg);
1040 if ((sessions = atoi(optarg)) <= 0)
1041 msg_fatal(
"bad session count: %s", optarg);
1051 msg_fatal(
"bad TCP window size: %s", optarg);
1057 if (random_delay > 0)
1058 msg_fatal(
"do not use -w and -R options at the same time");
1059 if ((fixed_delay = atoi(optarg)) <= 0)
1060 msg_fatal(
"bad fixed delay: %s", optarg);
1066 if (argc - optind != 1)
1069 if (random_delay > 0)
1076 if (message_file != 0) {
1096 }
else if (message_length > 0) {
1097 message_data =
mymalloc(message_length);
1098 memset(message_data,
'X', message_length);
1099 for (i = 80; i < message_length; i += 80) {
1100 message_data[i - 80] =
"0123456789"[(i / 80) % 10];
1101 message_data[i - 2] =
'\r';
1102 message_data[i - 1] =
'\n';
1110 if (strncmp(argv[optind],
"unix:", 5) == 0) {
1111 path = argv[optind] + 5;
1112 path_len = strlen(path);
1113 if (path_len >= (
int)
sizeof(sun.sun_path))
1114 msg_fatal(
"unix-domain name too long: %s", path);
1115 memset((
void *) &sun, 0,
sizeof(sun));
1116 sun.sun_family = AF_UNIX;
1118 sun.sun_len = path_len + 1;
1120 memcpy(sun.sun_path, path, path_len);
1121 sa = (
struct sockaddr *) &sun;
1122 sa_length =
sizeof(sun);
1124 if (strncmp(argv[optind],
"inet:", 5) == 0)
1127 if ((parse_err =
host_port(buf, &host, (
char *) 0, &port,
"smtp")) != 0)
1128 msg_fatal(
"%s: %s", argv[optind], parse_err);
1132 sa = (
struct sockaddr *) &ss;
1133 if (res->ai_addrlen >
sizeof(ss))
1134 msg_fatal(
"address length %d > buffer length %d",
1135 (
int) res->ai_addrlen, (
int)
sizeof(ss));
1136 memcpy((
void *) sa, res->ai_addr, res->ai_addrlen);
1137 sa_length = res->ai_addrlen;
1139 sa->sa_len = sa_length;
1158 if (sender == 0 || recipient == 0) {
1164 recipient = defaddr;
1170 while (sessions-- > 0) {
1181 if (session_count <= 0 && message_count <= 0) {
void event_enable_read(int fd, EVENT_NOTIFY_RDWR_FN callback, void *context)
void freeaddrinfo(struct addrinfo *ai)
char * mystrdup(const char *str)
int vstring_get_nonl(VSTRING *vp, VSTREAM *fp)
const char * mail_date(time_t when)
NORETURN msg_panic(const char *fmt,...)
int sane_connect(int sock, struct sockaddr *sa, SOCKADDR_SIZE len)
INET_PROTO_INFO * inet_proto_init(const char *context, const char *protocols)
#define hostname_to_sockaddr(host, serv, sock, res)
#define CA_VSTRING_CTL_MAXLEN(val)
#define INET_PROTO_NAME_ALL
int smtp_get(VSTRING *vp, VSTREAM *stream, ssize_t bound, int flags)
void event_enable_write(int fd, EVENT_NOTIFY_RDWR_FN callback, void *context)
#define vstream_setjmp(stream)
void set_inet_windowsize(int sock, int windowsize)
#define VA_COPY(dest, src)
void vstring_ctl(VSTRING *vp,...)
VSTREAM * vstream_fopen(const char *path, int flags, mode_t mode)
#define VSTRING_TERMINATE(vp)
int main(int argc, char **argv)
void smtp_vprintf(VSTREAM *stream, const char *fmt, va_list ap)
int valid_hostname(const char *name, int gripe)
#define VSTRING_ADDCH(vp, ch)
int valid_mailhost_literal(const char *addr, int gripe)
int vstream_fclose(VSTREAM *stream)
void event_loop(int delay)
VSTREAM * vstream_printf(const char *fmt,...)
#define VSTRING_RESET(vp)
void msg_warn(const char *fmt,...)
VSTRING * vstring_alloc(ssize_t len)
void smtp_fputs(const char *cp, ssize_t todo, VSTREAM *stream)
#define smtp_timeout_setup(stream, timeout)
#define MAIL_VERSION_STAMP_ALLOCATE
VSTRING * vstring_sprintf(VSTRING *vp, const char *format,...)
void smtp_printf(VSTREAM *stream, const char *fmt,...)
void doze(unsigned delay)
#define INET_PROTO_NAME_IPV6
NORETURN msg_fatal(const char *fmt,...)
int vstream_fflush(VSTREAM *stream)
void smtp_flush(VSTREAM *stream)
VSTRING * vstring_memcat(VSTRING *vp, const char *src, ssize_t len)
#define GETOPT(argc, argv, str)
int vstream_tweak_tcp(VSTREAM *)
int non_blocking(int, int)
const char * host_port(char *buf, char **host, char *def_host, char **port, char *def_service)
void vmsg_info(const char *fmt, va_list ap)
VSTRING * vstring_free(VSTRING *vp)
time_t event_request_timer(EVENT_NOTIFY_TIME_FN callback, void *context, int delay)
#define vstream_fileno(vp)
void msg_vstream_init(const char *name, VSTREAM *vp)
#define VSTREAM_PUTC(ch, vp)
#define SMTP_GET_FLAG_SKIP
const char * get_hostname(void)
void event_disable_readwrite(int fd)
#define vstream_ferror(vp)
#define INET_PROTO_NAME_IPV4
VSTRING * vstring_strcat(VSTRING *vp, const char *src)
char * vstring_export(VSTRING *vp)
VSTREAM * vstream_fdopen(int fd, int flags)
void * mymalloc(ssize_t len)
void msg_info(const char *fmt,...)
MAIL_VERSION_STAMP_DECLARE