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