84 #include <sys/socket.h>
86 #include <netinet/in.h>
144 static int var_timeout = 300;
146 static int session_count;
147 static int message_count = 1;
148 static struct sockaddr_storage ss;
151 static struct sockaddr_un sun;
152 static struct sockaddr *sa;
153 static int sa_length;
154 static int recipients = 1;
155 static char *defaddr;
156 static char *recipient;
158 static int message_length = 1024;
159 static int count = 0;
160 static int counter = 0;
161 static int connect_count = 1;
162 static int random_delay = 0;
163 static int fixed_delay = 0;
164 static const char *mydate;
167 static void enqueue_connect(
SESSION *);
168 static void start_connect(
SESSION *);
169 static void connect_done(
int,
void *);
171 static void send_data(
SESSION *);
172 static void receive_reply(
int,
void *);
174 static VSTRING *message_buffer;
176 static VSTRING *recipient_buffer;
180 #define STR(x) vstring_str(x)
181 #define LEN(x) VSTRING_LEN(x)
185 static int random_interval(
int interval)
187 return (rand() % (interval + 1));
192 static int socket_error(
int sock)
202 error_len =
sizeof(error);
203 if (getsockopt(sock, SOL_SOCKET, SO_ERROR, (
void *) &error, &error_len) < 0)
218 static char *exception_text(
int except)
224 return (
"lost connection");
228 return (
"netstring format error");
230 return (
"netstring size exceeds limit");
232 msg_panic(
"exception_text: unknown exception %d", except);
239 static void startup(
SESSION *session)
241 if (message_count-- <= 0) {
246 enqueue_connect(session);
251 static void start_event(
int unused_event,
void *context)
260 static void start_another(
SESSION *session)
262 if (random_delay > 0) {
264 random_interval(random_delay));
265 }
else if (fixed_delay > 0) {
274 static void enqueue_connect(
SESSION *session)
277 if (last_session == 0) {
278 last_session = session;
279 start_connect(session);
281 last_session->
next = session;
282 last_session = session;
288 static void dequeue_connect(
SESSION *session)
290 if (session == last_session) {
291 if (session->
next != 0)
292 msg_panic(
"dequeue_connect: queue ends after last");
295 if (session->
next == 0)
296 msg_panic(
"dequeue_connect: queue ends before last");
297 start_connect(session->
next);
303 static void fail_connect(
SESSION *session)
311 #ifdef MISSING_USLEEP
316 start_connect(session);
321 static void start_connect(
SESSION *session)
324 struct linger linger;
332 if ((fd = socket(sa->sa_family, SOCK_STREAM, 0)) < 0)
337 if (setsockopt(fd, SOL_SOCKET, SO_LINGER, (
void *) &linger,
339 msg_warn(
"setsockopt SO_LINGER %d: %m", linger.l_linger);
343 if (
sane_connect(fd, sa, sa_length) < 0 && errno != EINPROGRESS)
344 fail_connect(session);
349 static void connect_done(
int unused_event,
void *context)
358 if (socket_error(fd) < 0) {
359 fail_connect(session);
361 dequeue_connect(session);
365 if (sa->sa_family == AF_INET
367 || sa->sa_family == AF_INET6
377 static void send_data(
SESSION *session)
386 msg_fatal(
"%s while sending message", exception_text(except));
396 STR(message_buffer),
LEN(message_buffer),
397 STR(sender_buffer),
LEN(sender_buffer),
398 STR(recipient_buffer),
LEN(recipient_buffer),
410 static void receive_reply(
int unused_event,
void *context)
419 msg_fatal(
"%s while receiving server reply", exception_text(except));
431 "unknown", (
int)
LEN(buffer) - 1,
STR(buffer) + 1);
448 start_another(session);
453 static void usage(
char *myname)
455 msg_fatal(
"usage: %s -cv -s sess -l msglen -m msgs -C count -M myhostname -f from -t to -R delay -w delay host[:port]", myname);
462 int main(
int argc,
char **argv)
475 const char *parse_err;
476 struct addrinfo *res;
485 signal(SIGPIPE, SIG_IGN);
491 while ((ch =
GETOPT(argc, argv,
"46cC:f:l:m:M:r:R:s:t:vw:")) > 0) {
503 if ((connect_count = atoi(optarg)) <= 0)
510 if ((message_length = atoi(optarg)) <= 0)
514 if ((message_count = atoi(optarg)) <= 0)
518 if (*optarg ==
'[') {
520 msg_fatal(
"bad address literal: %s", optarg);
528 if ((recipients = atoi(optarg)) <= 0)
532 if (fixed_delay > 0 || (random_delay = atoi(optarg)) <= 0)
536 if ((sessions = atoi(optarg)) <= 0)
546 if (random_delay > 0 || (fixed_delay = atoi(optarg)) <= 0)
553 if (argc - optind != 1)
556 if (random_delay > 0)
563 if (strncmp(argv[optind],
"unix:", 5) == 0) {
564 path = argv[optind] + 5;
565 path_len = strlen(path);
566 if (path_len >= (
int)
sizeof(sun.sun_path))
567 msg_fatal(
"unix-domain name too long: %s", path);
568 memset((
void *) &sun, 0,
sizeof(sun));
569 sun.sun_family = AF_UNIX;
571 sun.sun_len = path_len + 1;
573 memcpy(sun.sun_path, path, path_len);
574 sa = (
struct sockaddr *) &sun;
575 sa_length =
sizeof(sun);
577 if (strncmp(argv[optind],
"inet:", 5) == 0)
580 if ((parse_err =
host_port(buf, &host, (
char *) 0, &port,
"628")) != 0)
581 msg_fatal(
"%s: %s", argv[optind], parse_err);
585 sa = (
struct sockaddr *) &ss;
586 if (res->ai_addrlen >
sizeof(ss))
587 msg_fatal(
"address length %d > buffer length %d",
588 (
int) res->ai_addrlen, (
int)
sizeof(ss));
589 memcpy((
void *) sa, res->ai_addr, res->ai_addrlen);
590 sa_length = res->ai_addrlen;
592 sa->sa_len = sa_length;
607 if (sender == 0 || recipient == 0) {
625 "From: <%s>\nTo: <%s>\nDate: %s\nMessage-Id: <%d@%s>\n\n",
627 for (n = 1;
LEN(buffer) < message_length; n++) {
628 for (i = 0; i < n && i < 79; i++)
632 STR(buffer)[message_length - 1] =
'\n';
635 len = strlen(sender);
639 if (recipients == 1) {
640 len = strlen(recipient);
645 for (n = 0; n < recipients; n++) {
654 while (sessions-- > 0) {
665 if (session_count <= 0 && message_count <= 0) {
void event_enable_read(int fd, EVENT_NOTIFY_RDWR_FN callback, void *context)
void netstring_fflush(VSTREAM *stream)
void freeaddrinfo(struct addrinfo *ai)
char * mystrdup(const char *str)
const char * mail_date(time_t when)
#define NETSTRING_ERR_FORMAT
NORETURN msg_panic(const char *fmt,...)
VSTRING * netstring_get(VSTREAM *stream, VSTRING *buf, ssize_t limit)
int sane_connect(int sock, struct sockaddr *sa, SOCKADDR_SIZE len)
INET_PROTO_INFO * inet_proto_init(const char *context, const char *protocols)
VSTRING * netstring_memcpy(VSTRING *buf, const char *src, ssize_t len)
#define hostname_to_sockaddr(host, serv, sock, res)
void netstring_setup(VSTREAM *stream, int timeout)
#define INET_PROTO_NAME_ALL
void event_enable_write(int fd, EVENT_NOTIFY_RDWR_FN callback, void *context)
#define vstream_setjmp(stream)
int main(int argc, char **argv)
int valid_hostname(const char *name, int gripe)
#define NETSTRING_ERR_SIZE
#define VSTRING_ADDCH(vp, ch)
int valid_mailhost_literal(const char *addr, int gripe)
VSTRING * netstring_memcat(VSTRING *buf, const char *src, ssize_t len)
int vstream_fclose(VSTREAM *stream)
void event_loop(int delay)
VSTREAM * vstream_printf(const char *fmt,...)
void msg_warn(const char *fmt,...)
VSTRING * vstring_alloc(ssize_t len)
#define MAIL_VERSION_STAMP_ALLOCATE
VSTRING * vstring_sprintf(VSTRING *vp, const char *format,...)
void netstring_put_multi(VSTREAM *stream,...)
void doze(unsigned delay)
#define INET_PROTO_NAME_IPV6
NORETURN msg_fatal(const char *fmt,...)
MAIL_VERSION_STAMP_DECLARE
int vstream_fflush(VSTREAM *stream)
#define GETOPT(argc, argv, str)
int vstream_tweak_tcp(VSTREAM *)
#define NETSTRING_ERR_EOF
#define NETSTRING_ERR_TIME
int non_blocking(int, int)
const char * host_port(char *buf, char **host, char *def_host, char **port, char *def_service)
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)
const char * get_hostname(void)
void event_disable_readwrite(int fd)
#define INET_PROTO_NAME_IPV4
VSTREAM * vstream_fdopen(int fd, int flags)
void * mymalloc(ssize_t len)