scripts

misc scripts and tools
git clone git://git.2f30.org/scripts.git
Log | Files | Refs

commit a50a7b1218b318ddb98a0c053b4f18226f22a577
parent a9c8fbff5f115e108edf8b45c50e9b8833448f78
Author: sin <sin@2f30.org>
Date:   Sun Apr  3 11:51:45 +0100

program to introduce delay/packet loss in the networking stack

Diffstat:
divert/arg.h | 65+++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++
divert/divert.c | 119+++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++
2 files changed, 184 insertions(+), 0 deletions(-)
diff --git a/divert/arg.h b/divert/arg.h @@ -0,0 +1,65 @@ +/* + * Copy me if you can. + * by 20h + */ + +#ifndef ARG_H__ +#define ARG_H__ + +extern char *argv0; + +/* use main(int argc, char *argv[]) */ +#define ARGBEGIN for (argv0 = *argv, argv++, argc--;\ + argv[0] && argv[0][0] == '-'\ + && argv[0][1];\ + argc--, argv++) {\ + char argc_;\ + char **argv_;\ + int brk_;\ + if (argv[0][1] == '-' && argv[0][2] == '\0') {\ + argv++;\ + argc--;\ + break;\ + }\ + for (brk_ = 0, argv[0]++, argv_ = argv;\ + argv[0][0] && !brk_;\ + argv[0]++) {\ + if (argv_ != argv)\ + break;\ + argc_ = argv[0][0];\ + switch (argc_) + +/* Handles obsolete -NUM syntax */ +#define ARGNUM case '0':\ + case '1':\ + case '2':\ + case '3':\ + case '4':\ + case '5':\ + case '6':\ + case '7':\ + case '8':\ + case '9' + +#define ARGEND }\ + } + +#define ARGC() argc_ + +#define ARGNUMF() (brk_ = 1, estrtonum(argv[0], 0, INT_MAX)) + +#define EARGF(x) ((argv[0][1] == '\0' && argv[1] == NULL)?\ + ((x), abort(), (char *)0) :\ + (brk_ = 1, (argv[0][1] != '\0')?\ + (&argv[0][1]) :\ + (argc--, argv++, argv[0]))) + +#define ARGF() ((argv[0][1] == '\0' && argv[1] == NULL)?\ + (char *)0 :\ + (brk_ = 1, (argv[0][1] != '\0')?\ + (&argv[0][1]) :\ + (argc--, argv++, argv[0]))) + +#define LNGARG() &argv[0][0] + +#endif diff --git a/divert/divert.c b/divert/divert.c @@ -0,0 +1,119 @@ +/* + * introduce artificial delay/packet drop in the networking stack + * using divert sockets. + * + * pass out quick inet divert-packet port 666 + */ + +#include <sys/types.h> +#include <sys/socket.h> + +#include <netinet/in.h> +#include <netinet/ip.h> +#include <netinet/tcp.h> +#include <arpa/inet.h> + +#include <err.h> +#include <stdio.h> +#include <stdlib.h> +#include <string.h> +#include <time.h> + +#include "arg.h" + +char *argv0; +int port = 666; +int drop; +int wait; + +void +ms2tv(struct timeval *tv, int ms) +{ + tv->tv_sec = ms / 1000; + tv->tv_usec = (ms % 1000) * 1000; +} + +int +tvsleep(struct timeval *tv) +{ + struct timespec ts; + + ts.tv_sec = tv->tv_sec; + ts.tv_nsec = tv->tv_usec * 1000; + return nanosleep(&ts, NULL); +} + +void +loop(void) +{ + char pkt[65535]; + struct sockaddr_in sa; + socklen_t salen; + struct timeval tv; + int fd, n; + + fd = socket(AF_INET, SOCK_RAW, IPPROTO_DIVERT); + if (fd < 0) + err(1, "socket"); + + memset(&sa, 0, sizeof(sa)); + sa.sin_family = AF_INET; + sa.sin_port = htons(port); + sa.sin_addr.s_addr = 0; + + salen = sizeof(sa); + if (bind(fd, (struct sockaddr *)&sa, salen) < 0) + err(1, "bind"); + + ms2tv(&tv, wait); + for (;;) { + tvsleep(&tv); + n = recvfrom(fd, pkt, sizeof(pkt), 0, + (struct sockaddr *)&sa, &salen); + if (n < 0) { + warn("recvfrom"); + continue; + } + if (drop > arc4random_uniform(100)) + continue; + n = sendto(fd, pkt, n, 0, (struct sockaddr *)&sa, salen); + if (n < 0) + warn("sendto"); + } +} + +void +usage(void) +{ + fprintf(stderr, "usage: a.out [-d drop-percentage] [-i wait-interval] [-p port]\n"); + exit(1); +} + +int +main(int argc, char *argv[]) +{ + const char *errstr; + + ARGBEGIN { + case 'd': + drop = strtonum(EARGF(usage()), 0, 100, &errstr); + if (errstr) + errx(1, "invalid packet drop percentage"); + break; + case 'i': + wait = strtonum(EARGF(usage()), 1, 1000, &errstr); + if (errstr) + errx(1, "invalid timing interval"); + break; + case 'p': + port = strtonum(EARGF(usage()), 1, 65535, &errstr); + if (errstr) + errx(1, "invalid port"); + break; + default: + usage(); + } ARGEND + if (argc) + usage(); + loop(); +}