From 588c46d0589ae9b64974c826ca6be2bc05e04033 Mon Sep 17 00:00:00 2001 From: David Johnson Date: Mon, 9 Oct 2006 09:29:18 +0000 Subject: [PATCH] supafly is a synthetic application for "proving" the point that evaluating apps/protocols that use X cpu on PlanetLab can also add network artifacts. sfmiddleman sits in the middle as a compute-intensive proxy. sfsender sends the middleman n "messages" each composed of m "blocks", and can pause for t1 and t2 times at microsecond granularity after each block send and msg send. sfmiddleman reads blocks and does operations on them (default is decrypt/encrypt, can also do only encrypt), then forwards them to all connected receivers. You guessed it, sfreceiver connects to sfmiddleman and reads blocks and prints timestamps. For each op on a block, sfmiddleman notes the number of microseconds taken by the crypto ops, and the timestamp when it/they finished, and prints those. There is one known bug. I'll fix it in the morning. If there are others, I'll get them then too. --- pelab/supafly/GNUmakefile | 16 ++ pelab/supafly/crypto.c | 100 ++++++++ pelab/supafly/crypto.h | 18 ++ pelab/supafly/defs.h | 31 +++ pelab/supafly/sfmiddleman.c | 459 ++++++++++++++++++++++++++++++++++++ pelab/supafly/sfreceiver.c | 156 ++++++++++++ pelab/supafly/sfsender.c | 224 ++++++++++++++++++ pelab/supafly/util.c | 48 ++++ pelab/supafly/util.h | 18 ++ 9 files changed, 1070 insertions(+) create mode 100644 pelab/supafly/GNUmakefile create mode 100644 pelab/supafly/crypto.c create mode 100644 pelab/supafly/crypto.h create mode 100644 pelab/supafly/defs.h create mode 100644 pelab/supafly/sfmiddleman.c create mode 100644 pelab/supafly/sfreceiver.c create mode 100644 pelab/supafly/sfsender.c create mode 100644 pelab/supafly/util.c create mode 100644 pelab/supafly/util.h diff --git a/pelab/supafly/GNUmakefile b/pelab/supafly/GNUmakefile new file mode 100644 index 000000000..1126baf6b --- /dev/null +++ b/pelab/supafly/GNUmakefile @@ -0,0 +1,16 @@ +CC = gcc +CFLAGS += -g -lssl + +all: sfmiddleman sfsender sfreceiver + +sfmiddleman: sfmiddleman.c util.c crypto.c + $(CC) -o sfmiddleman $(CFLAGS) sfmiddleman.c util.c crypto.c + +sfsender: sfsender.c util.c crypto.c + $(CC) -o sfsender $(CFLAGS) sfsender.c util.c crypto.c + +sfreceiver: sfreceiver.c util.c + $(CC) -o sfreceiver $(CFLAGS) sfreceiver.c util.c + +clean: + rm -f sfmiddleman sfsender sfreceiver diff --git a/pelab/supafly/crypto.c b/pelab/supafly/crypto.c new file mode 100644 index 000000000..a6a6da016 --- /dev/null +++ b/pelab/supafly/crypto.c @@ -0,0 +1,100 @@ +#include +#include +#include +#include +#include +#include +#include + +#include "crypto.h" + +DES_cblock *sgenkey() { + DES_cblock *retval; + + retval = (DES_cblock *)malloc(sizeof(DES_cblock)); + if (retval != NULL) { + DES_random_key(retval); + } + + return retval; +} + +DES_cblock *sgeniv() { + DES_cblock *retval; + + retval = (DES_cblock *)malloc(sizeof(DES_cblock)); + if (retval != NULL) { + DES_random_key(retval); + } + + return retval; +} + +/* note: if IV is null, don't do cbc; otherwise, do it. */ +int sencrypt(unsigned char *input,unsigned char *output, + unsigned int len,DES_cblock *k1,DES_cblock *k2, + DES_cblock *iv + ) { + DES_key_schedule s1,s2; + int i; + + if (len%8 != 0) { + return -1; + } + + /* the idea is to process the keys each time to keep them out of memory + * if possible (besides, it's easier) + */ + + DES_set_key_checked(k1,&s1); + DES_set_key_checked(k2,&s2); + + if (iv == NULL) { + /* actually encrypt, now */ + //printf("%d\n",len/8); + for (i = 0; i < len; i+=8) { + //printf("encrypt block %d\n",i); + DES_ecb2_encrypt(input+i,output+i,&s1,&s2,DES_ENCRYPT); + } + } + else { + DES_ede2_cbc_encrypt(input,output,len,&s1,&s2,iv,DES_ENCRYPT); + } + + return 0; + +} + +int sdecrypt(unsigned char *input,unsigned char *output, + unsigned int len,DES_cblock *k1,DES_cblock *k2, + DES_cblock *iv + ) { + DES_key_schedule s1,s2; + int i; + + if (len%8 != 0) { + return -1; + } + + /* the idea is to process the keys each time to keep them out of memory + * if possible (besides, it's easier) + */ + + DES_set_key_checked(k1,&s1); + DES_set_key_checked(k2,&s2); + //printf("blah2\n"); + if (iv == NULL) { + //printf("blah3\n"); + /* actually encrypt, now */ + for (i = 0; i < len; i+=8) { + //printf("decrypt block %d\n",i); + DES_ecb2_encrypt(input+i,output+i,&s1,&s2,DES_DECRYPT); + } + } + else { + //printf("blah4\n"); + DES_ede2_cbc_encrypt(input,output,len,&s1,&s2,iv,DES_DECRYPT); + } + + return 0; +} diff --git a/pelab/supafly/crypto.h b/pelab/supafly/crypto.h new file mode 100644 index 000000000..873645972 --- /dev/null +++ b/pelab/supafly/crypto.h @@ -0,0 +1,18 @@ +#ifndef __CRYPTO_H__ +#define __CRYPTO_H__ + +#include +#include + +DES_cblock *sgenkey(); +DES_cblock *sgeniv(); +/* note: if IV is null, don't do cbc; otherwise, do it. */ +int sencrypt(unsigned char *input,unsigned char *output, + unsigned int len,DES_cblock *k1,DES_cblock *k2, + DES_cblock *iv); +int sdecrypt(unsigned char *input,unsigned char *output, + unsigned int len,DES_cblock *k1,DES_cblock *k2, + DES_cblock *iv); + + +#endif /* __CRYPTO_H__ */ diff --git a/pelab/supafly/defs.h b/pelab/supafly/defs.h new file mode 100644 index 000000000..3553b5917 --- /dev/null +++ b/pelab/supafly/defs.h @@ -0,0 +1,31 @@ +#ifndef __DEFS_H__ +#define __DEFS_H__ + +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include + +/** sane systems honor this as 32 bits regardless */ +/** + * each sent packet group (allowing for app/ip frag) must prefix a new + * unit with the length of crap being sent. This might be useful... + */ +typedef uint32_t slen_t; + +#define MIDDLEMAN_SEND_CLIENT_PORT 6878 +#define MIDDLEMAN_RECV_CLIENT_PORT 6888 + +#define MIDDLEMAN_MAX_CLIENTS 32 + +#define MAX_NAME_LEN 255 + +#endif /* __DEFS_H__ */ diff --git a/pelab/supafly/sfmiddleman.c b/pelab/supafly/sfmiddleman.c new file mode 100644 index 000000000..8a8146304 --- /dev/null +++ b/pelab/supafly/sfmiddleman.c @@ -0,0 +1,459 @@ +#include +#include + +#include "defs.h" +#include "crypto.h" + +/** + * globals + */ +char *optarg; +int optind,opterr,optopt; + +int block_size = 4096; +int block_count = 1024; +int only_encrypt = 0; +int debug = 0; +char *srv_host = "localhost"; +short srv_send_port = MIDDLEMAN_SEND_CLIENT_PORT; +short srv_recv_port = MIDDLEMAN_RECV_CLIENT_PORT; + +char *deadbeef = "deadbeef"; + +/** + * defs + */ +void usage(char *bin) { + fprintf(stdout, + "USAGE: %s -scohSRud (option defaults in parens)\n", + bin + ); +} + +void parse_args(int argc,char **argv) { + int c; + char *ep = NULL; + + while ((c = getopt(argc,argv,"s:c:oud")) != -1) { + switch(c) { + case 's': + block_size = (int)strtol(optarg,&ep,10); + if (ep == optarg) { + usage(argv[0]); + exit(-1); + } + break; + case 'c': + block_count = (int)strtol(optarg,&ep,10); + if (ep == optarg) { + usage(argv[0]); + exit(-1); + } + break; + case 'h': + srv_host = optarg; + break; + case 'S': + srv_send_port = (short)strtol(optarg,&ep,10); + if (ep == optarg) { + usage(argv[0]); + exit(-1); + } + break; + case 'R': + srv_recv_port = (short)strtol(optarg,&ep,10); + if (ep == optarg) { + usage(argv[0]); + exit(-1); + } + break; + case 'o': + only_encrypt = 1; + break; + case 'u': + usage(argv[0]); + exit(0); + case 'd': + ++debug; + break; + default: + break; + } + } + + /** arg check */ + if (block_size % 8 != 0) { + fprintf(stderr,"block_size must be divisible by 8!\n"); + exit(-1); + } + + return; + +} + +int main(int argc,char **argv) { + int srv_send_sock,srv_recv_sock; + int retval,ptype; + int i,j; + struct sockaddr_in srv_send_sa,srv_recv_sa; + int recv_clientfds[MIDDLEMAN_MAX_CLIENTS]; + char *recv_clientsas[MIDDLEMAN_MAX_CLIENTS]; + int recv_client_cnt = 0; + int max_fd = 0; + int send_client_fd = -1; + int c; + char *buf = NULL; + char *outbuf = NULL; + fd_set rfds; + fd_set static_rfds; + int current_send_rc; + + /* grab some quick args */ + parse_args(argc,argv); + + /* initialize ourself... */ + srand(time(NULL)); + + /* grab the bufs... */ + if ((buf = (char *)malloc(sizeof(char)*block_size)) == NULL) { + efatal("no memory for data buf"); + } + if ((outbuf = (char *)malloc(sizeof(char)*block_size)) == NULL) { + efatal("no memory for output data buf"); + } + + /* fill with deadbeef */ + for (i = 0; i < block_size; i += 8) { + memcpy(&buf[i],deadbeef,8); + } + + /* setup the sockaddrs */ + if ((retval = fill_sockaddr(srv_host,srv_send_port,&srv_send_sa)) != 0) { + if (retval == -1) { + fatal("bad port"); + } + else { + efatal("host lookup failed"); + } + } + if ((retval = fill_sockaddr(srv_host,srv_recv_port,&srv_recv_sa)) != 0) { + if (retval == -1) { + fatal("bad port"); + } + else { + efatal("host lookup failed"); + } + } + + /* startup server... */ + if ((srv_send_sock = socket(PF_INET,SOCK_STREAM,0)) == -1) { + efatal("could not get send listen socket"); + } + if ((srv_recv_sock = socket(PF_INET,SOCK_STREAM,0)) == -1) { + efatal("could not get send listen socket"); + } + + if (bind(srv_send_sock, + (struct sockaddr *)&srv_send_sa, + sizeof(struct sockaddr_in) + ) < 0) { + efatal("could not bind"); + } + if (bind(srv_recv_sock, + (struct sockaddr *)&srv_recv_sa, + sizeof(struct sockaddr_in) + ) < 0) { + efatal("could not bind"); + } + + /* only listen for len 1 cause we won't accept on this guy if we + * already have a sender + */ + if (listen(srv_send_sock,1) < 0) { + efatal("could not listen"); + } + /* more sane listen queue for this one */ + if (listen(srv_recv_sock,8) < 0) { + efatal("could not listen"); + } + + /* daemonize... */ + if (!debug) { + daemon(0,0); + } + + for (i = 0; i < MIDDLEMAN_MAX_CLIENTS; ++i) { + recv_clientfds[i] = -1; + recv_clientsas[i] = (char *)malloc(MAX_NAME_LEN + 1); + } + + FD_ZERO(&static_rfds); + FD_SET(srv_send_sock,&static_rfds); + FD_SET(srv_recv_sock,&static_rfds); + max_fd = (srv_send_sock > srv_recv_sock) ? srv_send_sock : srv_recv_sock; + + /* listen and read forever */ + while (1) { + /* reset fdsets */ + memcpy(&rfds,&static_rfds,sizeof(static_rfds)); + + retval = select(max_fd+1,&rfds,NULL,NULL,NULL); + + if (retval > 0) { + if (FD_ISSET(srv_send_sock,&rfds) + && send_client_fd < 0) { + struct sockaddr_in client_sin; + socklen_t slen; + + slen = sizeof(client_sin); + + if ((send_client_fd = accept(srv_send_sock, + (struct sockaddr *)&client_sin, + &slen)) < 0) { + warn("accept failed"); + } + + if (send_client_fd > max_fd) { + max_fd = send_client_fd; + } + + char *addr = inet_ntoa(client_sin.sin_addr); + int addrlen = strlen(addr); + + if (debug > 1) { + fprintf(stdout, + "DEBUG: (send client!) connect from %s:%d\n", + addr, + ntohs(client_sin.sin_port)); + } + + /* add the new send client for consideration */ + FD_SET(send_client_fd,&static_rfds); + + /* zero the counter */ + current_send_rc = 0; + } + else if (FD_ISSET(srv_recv_sock,&rfds)) { + struct sockaddr_in client_sin; + socklen_t slen; + int client_fd; + + slen = sizeof(client_sin); + + if ((client_fd = accept(srv_recv_sock, + (struct sockaddr *)&client_sin, + &slen)) < 0) { + warn("accept failed"); + } + else if (recv_client_cnt >= MIDDLEMAN_MAX_CLIENTS) { + warn("already at max clients"); + close(client_fd); + } + else { + /* add new recv client... */ + for (i = 0; i < MIDDLEMAN_MAX_CLIENTS; ++i) { + if (recv_clientfds[i] == -1) { + break; + } + } + + recv_clientfds[i] = client_fd; + if (client_fd > max_fd) { + max_fd = client_fd; + } + + FD_SET(client_fd,&static_rfds); + + char *addr = inet_ntoa(client_sin.sin_addr); + int addrlen = strlen(addr); + + if (debug > 1) { + fprintf(stdout, + "DEBUG: connect from %s:%d\n", + addr, + ntohs(client_sin.sin_port)); + } + + strncpy(recv_clientsas[i], + addr, + (addrlen > MAX_NAME_LEN)?MAX_NAME_LEN:addrlen); + /* null term if strncpy couldn't */ + if (addrlen > MAX_NAME_LEN) { + recv_clientsas[i][MAX_NAME_LEN] = '\0'; + } + + ++recv_client_cnt; + } + } + else if (send_client_fd > 0 + && FD_ISSET(send_client_fd,&rfds)) { + /** + * ok, here we need to read a block from this guy for awhile, + * then [decrypt/munge]/encrypt (according to command line + * arg), then forward the block to all the recv clients. + */ + + /** + * we don't fork or spin a thread for this, since none of + * the clients will be writing and I don't have time to + * write any app-level buffering to process the sender's + * packets. The sender should just have a fixed rate. :-) + * We'll see how that works out. + */ + + /** + * Of course, we put send_client_fd in nonblocking mode, so + * we read what we can when we can... + */ + + retval = read(send_client_fd, + &buf[current_send_rc], + block_size - current_send_rc); + + if (retval < 0) { + if (errno == ECONNRESET) { + /* dead sender */ + close(send_client_fd); + FD_CLR(send_client_fd,&static_rfds); + send_client_fd = -1; + + current_send_rc = 0; + + if (debug > 1) { + fprintf(stderr, + "DEBUG: (send client!) disconnect from %s\n", + recv_clientsas[i]); + } + } + else if (errno == EAGAIN) { + // ignore, doh + } + } + else { + current_send_rc += retval; + } + + + if (current_send_rc == block_size) { + current_send_rc = 0; + + /* end of block, do the encryption op and note times... */ + if (debug > 1) { + fprintf(stderr, + "DEBUG: read %d bytes (a block)\n", + block_size); + } + + DES_cblock *iv = sgeniv(); + DES_cblock *k1 = sgenkey(); + DES_cblock *k2 = sgenkey(); + struct timeval t1,t2,t3; + + if (only_encrypt) { + gettimeofday(&t1,NULL); + sencrypt(buf,outbuf,block_size, + k1,k2,iv); + gettimeofday(&t2,NULL); + } + else { + /* do a decrypt, then choose new iv, then encrypt. */ + gettimeofday(&t1,NULL); + sdecrypt(buf,outbuf,block_size, + k1,k2,iv); + iv = sgeniv(); + sencrypt(buf,outbuf,block_size, + k1,k2,iv); + gettimeofday(&t2,NULL); + } + + t3.tv_sec = t2.tv_sec - t1.tv_sec; + t3.tv_usec = t2.tv_usec - t1.tv_usec; + if (t3.tv_usec < 0) { + t3.tv_sec--; + t3.tv_usec += 1000000; + } + fprintf(stdout, + "BLOCKTIME(%s): %d at %.6f\n", + (only_encrypt)?"e":"de", + t3.tv_sec * 1000 + t3.tv_usec, + t2.tv_sec + t2.tv_usec / 1000000.0f); + fflush(stdout); + + if (debug > 1) { + fprintf(stderr, + "DEBUG: sending to clients\n"); + } + + /* send to clients */ + for (i = 0; i < MIDDLEMAN_MAX_CLIENTS; ++i) { + if (recv_clientfds[i] > -1) { + retval = write(recv_clientfds[i], + outbuf, + block_size); + if (retval < 0) { + ewarn("client write failed"); + } + else if (retval != block_size) { + fprintf(stderr, + "ERROR: wrote only %d bytes to client %d!\n", + retval,i); + } + else { + if (debug > 1) { + fprintf(stderr, + "DEBUG: wrote all block_size %d bytes to client %d!\n", + block_size,i); + } + } + } + } + + } + + } + else { + /** + * If we get here, assume that one of the recv clients + * has died (cause they are not supposed to write anything + * to us)... so nuke the doofus! + */ + for (i = 0; i < MIDDLEMAN_MAX_CLIENTS; ++i) { + if (recv_clientfds[i] > -1) { + if (FD_ISSET(recv_clientfds[i],&rfds)) { + /* read a block, or as much as possible */ + //retval = read(recv_clientfds[i],buf,block_size); + + /* dead client, pretty much */ + //if (retval <= 0) { + if (debug > 1) { + fprintf(stderr, + "DEBUG: disconnect from %s\n", + recv_clientsas[i]); + } + + close(recv_clientfds[i]); + FD_CLR(recv_clientfds[i],&static_rfds); + recv_clientfds[i] = -1; + + --recv_client_cnt; + //} + //else if (debug > 2 ) { + //fprintf(stdout, + //"DEBUG: read %d bytes from %s\n", + //retval, + //recv_clientsas[i]); + //} + } + } + } + } + } + else if (retval < 0) { + /* error... */ + ewarn("error in select"); + } + } + + return -1; + +} diff --git a/pelab/supafly/sfreceiver.c b/pelab/supafly/sfreceiver.c new file mode 100644 index 000000000..cf6f19ca4 --- /dev/null +++ b/pelab/supafly/sfreceiver.c @@ -0,0 +1,156 @@ +#include + +#include "defs.h" +#include "crypto.h" + +/** + * globals + */ +char *optarg; +int optind,opterr,optopt; + +/** -s */ +int block_size = 4096; +/** -m */ +char *middleman_host = "localhost"; +/** -M */ +short middleman_port = MIDDLEMAN_RECV_CLIENT_PORT; +int debug = 0; + +char *deadbeef = "deadbeef"; + +/** + * functions + */ +void usage(char *bin) { + fprintf(stdout, + "USAGE: %s -scCmMud (option defaults in parens)\n", + bin + ); +} + +void parse_args(int argc,char **argv) { + int c; + char *ep = NULL; + + while ((c = getopt(argc,argv,"s:m:M:ud")) != -1) { + switch(c) { + case 's': + block_size = (int)strtol(optarg,&ep,10); + if (ep == optarg) { + usage(argv[0]); + exit(-1); + } + break; + case 'u': + usage(argv[0]); + exit(0); + case 'd': + ++debug; + break; + default: + break; + } + } + + /** arg check */ + if (block_size % 8 != 0) { + fprintf(stderr,"block_size must be divisible by 8!\n"); + exit(-1); + } + + return; + +} + + +int main(int argc,char **argv) { + char *buf,*outbuf; + struct sockaddr_in recv_sa; + int recv_sock; + int i; + int retval; + int bytesRead; + int blocksRead = 0; + struct timeval t1; + + parse_args(argc,argv); + + /* initialize ourself... */ + //srand(time(NULL)); + + /* grab some buf! */ + if ((buf = (char *)malloc(sizeof(char)*block_size)) == NULL) { + efatal("no memory for data buf"); + } + if ((outbuf = (char *)malloc(sizeof(char)*block_size)) == NULL) { + efatal("no memory for output data buf"); + } + + /* fill with deadbeef */ + //for (i = 0; i < block_size; i += 8) { + //memcpy(&buf[i],deadbeef,8); + //} + + /* setup the sockaddrs */ + if ((retval = fill_sockaddr(middleman_host, + middleman_port, + &recv_sa)) != 0) { + if (retval == -1) { + fatal("bad port"); + } + else { + efatal("host lookup failed"); + } + } + + /* startup recv client... */ + if ((recv_sock = socket(PF_INET,SOCK_STREAM,0)) == -1) { + efatal("could not get recv socket"); + } + + /* connect to the middleman if we can... */ + if (connect(recv_sock, + (struct sockaddr *)&recv_sa, + sizeof(struct sockaddr_in)) < 0) { + efatal("could not connect to middleman"); + } + + /** + * read blocks forever, noting times at which a block was completely read. + */ + + while (1) { + bytesRead = 0; + while (bytesRead < block_size) { + retval = read(recv_sock,buf,block_size); + + if (retval < 0) { + if (errno == ECONNRESET) { + /* middleman must've dumped out. */ + efatal("middleman appears to have disappeared"); + } + else if (errno == EAGAIN) { + ; + } + else { + ewarn("weird"); + } + } + else { + bytesRead += retval; + } + } + + gettimeofday(&t1,NULL); + + fprintf(stdout, + "INFO: read %d bytes (a block) at %.6f\n", + block_size, + t1.tv_sec + t1.tv_usec / 1000000.0f); + } + + /* never get here... */ + exit(0); + +} diff --git a/pelab/supafly/sfsender.c b/pelab/supafly/sfsender.c new file mode 100644 index 000000000..d732e07c0 --- /dev/null +++ b/pelab/supafly/sfsender.c @@ -0,0 +1,224 @@ +#include + +#include "defs.h" +#include "crypto.h" + +/** + * globals + */ +char *optarg; +int optind,opterr,optopt; + +/** -s */ +int block_size = 4096; +/** -c */ +int block_count = 1024; +/** -C */ +int msg_count = 1; +/** -p */ +long block_pause_us = 1000; +/** -P */ +long msg_pause_us = 5000000; +/** -m */ +char *middleman_host = "localhost"; +/** -M */ +short middleman_port = MIDDLEMAN_SEND_CLIENT_PORT; +int debug = 0; + +char *deadbeef = "deadbeef"; + +/** + * functions + */ +void usage(char *bin) { + fprintf(stdout, + "USAGE: %s -scCpPmMud (option defaults in parens)\n", + bin + ); +} + +void parse_args(int argc,char **argv) { + int c; + char *ep = NULL; + + while ((c = getopt(argc,argv,"s:c:C:p:P:m:M:ud")) != -1) { + switch(c) { + case 's': + block_size = (int)strtol(optarg,&ep,10); + if (ep == optarg) { + usage(argv[0]); + exit(-1); + } + break; + case 'c': + block_count = (int)strtol(optarg,&ep,10); + if (ep == optarg) { + usage(argv[0]); + exit(-1); + } + break; + case 'C': + msg_count = (int)strtol(optarg,&ep,10); + if (ep == optarg) { + usage(argv[0]); + exit(-1); + } + break; + case 'p': + block_pause_us = strtol(optarg,&ep,10); + if (ep == optarg) { + usage(argv[0]); + exit(-1); + } + break; + case 'P': + msg_pause_us = strtol(optarg,&ep,10); + if (ep == optarg) { + usage(argv[0]); + exit(-1); + } + break; + case 'u': + usage(argv[0]); + exit(0); + case 'd': + ++debug; + break; + default: + break; + } + } + + /** arg check */ + if (block_size % 8 != 0) { + fprintf(stderr,"block_size must be divisible by 8!\n"); + exit(-1); + } + + return; + +} + + +int main(int argc,char **argv) { + char *buf,*outbuf; + struct sockaddr_in send_sa; + int send_sock; + int remaining_block_count; + int remaining_msg_count; + int i; + int retval; + int bytesWritten; + + parse_args(argc,argv); + + remaining_block_count = block_count; + remaining_msg_count = msg_count; + + /* initialize ourself... */ + srand(time(NULL)); + + /* grab some buf! */ + if ((buf = (char *)malloc(sizeof(char)*block_size)) == NULL) { + efatal("no memory for data buf"); + } + if ((outbuf = (char *)malloc(sizeof(char)*block_size)) == NULL) { + efatal("no memory for output data buf"); + } + + /* fill with deadbeef */ + for (i = 0; i < block_size; i += 8) { + memcpy(&buf[i],deadbeef,8); + } + + /* setup the sockaddrs */ + if ((retval = fill_sockaddr(middleman_host, + middleman_port, + &send_sa)) != 0) { + if (retval == -1) { + fatal("bad port"); + } + else { + efatal("host lookup failed"); + } + } + + /* startup send client... */ + if ((send_sock = socket(PF_INET,SOCK_STREAM,0)) == -1) { + efatal("could not get send socket"); + } + + /* connect to the middleman if we can... */ + if (connect(send_sock, + (struct sockaddr *)&send_sa, + sizeof(struct sockaddr_in)) < 0) { + efatal("could not connect to middleman"); + } + + /* heh, we don't do encryption! that way, if the middleman + * does a decrypt/encrypt with the same keys/iv, they should forward + * deadbeef to the sfreceiver. nasty, but whatever. provides a little + * testing. + */ + + while (remaining_msg_count > 0) { + /* prepare to send a msg... */ + + while (remaining_block_count > 0) { + /* send a block */ + bytesWritten = 0; + + while (bytesWritten < block_size) { + retval = write(send_sock,buf,block_size - bytesWritten); + + if (retval < 0) { + if (errno == EPIPE) { + efatal("while writing to middleman"); + } + else { + ewarn("while writing to middleman"); + } + } + else { + bytesWritten += retval; + } + } + + --remaining_block_count; + + if (remaining_block_count % 8 == 0) { + fprintf(stdout, + "INFO: %d blocks remaining in msg %d\n", + remaining_block_count, + msg_count - remaining_msg_count); + } + + /* interblock sleep time */ + if (block_pause_us > 0) { + if (usleep(block_pause_us) < 0) { + ewarn("usleep after block failed"); + } + } + + } + + --remaining_msg_count; + + fprintf(stdout, + "INFO: only %d msgs remaining\n", + remaining_msg_count); + + /* intermsg sleep time */ + if (msg_pause_us > 0 && remaining_msg_count > 0) { + if (usleep(msg_pause_us) < 0) { + ewarn("usleep after msg failed"); + } + } + + } + + fprintf(stdout,"Done, exiting.\n"); + + exit(0); + +} diff --git a/pelab/supafly/util.c b/pelab/supafly/util.c new file mode 100644 index 000000000..4dad3f667 --- /dev/null +++ b/pelab/supafly/util.c @@ -0,0 +1,48 @@ +#include "util.h" +#include "defs.h" + +void efatal(char *msg) { + fprintf(stdout,"%s: %s\n",msg,strerror(errno)); + exit(-1); +} + +void fatal(char *msg) { + fprintf(stdout,"%s\n",msg); + exit(-2); +} + +void ewarn(char *msg) { + fprintf(stdout,"WARNING: %s: %s\n",msg,strerror(errno)); +} + +void warn(char *msg) { + fprintf(stdout,"WARNING: %s\n",msg); +} + +int fill_sockaddr(char *hostname,int port,struct sockaddr_in *new_sa) { + struct hostent *host_ptr; + + if (port < 1) { + return -2; + } + + new_sa->sin_family = AF_INET; + new_sa->sin_port = htons((short) port); + + if (hostname != NULL && strlen(hostname) > 0) { + host_ptr = gethostbyname(hostname); + + if (!host_ptr) { + return -3; + } + + memcpy((char *) &new_sa->sin_addr.s_addr, + (char *) host_ptr->h_addr_list[0], + host_ptr->h_length); + } + else { + new_sa->sin_addr.s_addr = INADDR_ANY; + } + + return 0; +} diff --git a/pelab/supafly/util.h b/pelab/supafly/util.h new file mode 100644 index 000000000..df1b6e2ef --- /dev/null +++ b/pelab/supafly/util.h @@ -0,0 +1,18 @@ +#ifndef __UTIL_H__ +#define __UTIL_H__ + +#include + +/** + * ugh, this is all very catch-all. + * + * ANYTHING that I might in more than one entity goes here. + */ + +void efatal(char *msg); +void fatal(char *msg); +void ewarn(char *msg); +void warn(char *msg); +int fill_sockaddr(char *hostname,int port,struct sockaddr_in *new_sa); + +#endif -- GitLab