From 47b8a9471fe006cef74d1ba8f8a2839fd8164041 Mon Sep 17 00:00:00 2001 From: rodri Date: Sun, 13 Dec 2020 13:49:38 +0000 Subject: initial commit. basic udp echo support. --- Makefile | 28 +++++++++++++ args.h | 22 ++++++++++ dat.h | 26 ++++++++++++ fns.h | 6 +++ main.c | 142 ++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++ readme.md | 6 +++ util.c | 113 +++++++++++++++++++++++++++++++++++++++++++++++++ 7 files changed, 343 insertions(+) create mode 100644 Makefile create mode 100644 args.h create mode 100644 dat.h create mode 100644 fns.h create mode 100644 main.c create mode 100644 readme.md create mode 100644 util.c diff --git a/Makefile b/Makefile new file mode 100644 index 0000000..132c7da --- /dev/null +++ b/Makefile @@ -0,0 +1,28 @@ +CC=cc +CFLAGS=-Wall -Wno-missing-braces -Wno-parentheses -Wno-switch -Wno-pointer-to-int-cast -fno-diagnostics-color -I/usr/local/include -ggdb -c -O2 +LDFLAGS=-L/usr/local/lib -pthread -lfmt -lutf +O=o + +TARG=udp7 +OFILES=\ + main.$O\ + util.$O\ + +HFILES=\ + dat.h\ + fns.h\ + args.h\ + +.PHONY: all clean +all: $(TARG) + +%.$O: %.c + $(CC) $(CFLAGS) $< + +$(OFILES): $(HFILES) + +$(TARG): $(OFILES) + $(CC) -o $@ $(OFILES) $(LDFLAGS) + +clean: + rm $(OFILES) $(TARG) diff --git a/args.h b/args.h new file mode 100644 index 0000000..f7e3d5f --- /dev/null +++ b/args.h @@ -0,0 +1,22 @@ +extern char *argv0; +#define SET(x) ((x)=0) +#define USED(x) if(x);else +#define ARGBEGIN for((argv0? 0: (argv0=*argv)),argv++,argc--;\ + argv[0] && argv[0][0]=='-' && argv[0][1];\ + argc--, argv++) {\ + char *_args, *_argt;\ + Rune _argc;\ + _args = &argv[0][1];\ + if(_args[0]=='-' && _args[1]==0){\ + argc--; argv++; break;\ + }\ + _argc = 0;\ + while(*_args && (_args += chartorune(&_argc, _args)))\ + switch(_argc) +#define ARGEND SET(_argt);USED(_argt); USED(_argc); USED(_args);}USED(argv); USED(argc); +#define ARGF() (_argt=_args, _args="",\ + (*_argt? _argt: argv[1]? (argc--, *++argv): 0)) +#define ARGC() _argc + +#define EARGF(x) (_argt=_args, _args="",\ + (*_argt? _argt: argv[1]? (argc--, *++argv): (x, (char*)0))) diff --git a/dat.h b/dat.h new file mode 100644 index 0000000..f900861 --- /dev/null +++ b/dat.h @@ -0,0 +1,26 @@ +#define nil NULL + +typedef long long vlong; +typedef unsigned int uint; +typedef unsigned long ulong; +typedef unsigned long long uvlong; +typedef uint32_t u32int; +typedef struct sockaddr sockaddr; +typedef struct sockaddr_in sockaddr_in; + +typedef struct UDPEchoPlus UDPEchoPlus; + + +/* + * TR-143 - Enabling Network Throughput Performance Tests and Statistical Monitoring + * Issue 1 Amendment 1 Corrigendum 1, ยง A.1.4 + */ +struct UDPEchoPlus +{ + u32int gensn; /* TestGenSN */ + u32int ressn; /* TestRespSN */ + u32int rxtime; /* TestRespRecvTimeStamp */ + u32int txtime; /* TestRespReplyTimeStamp */ + u32int ntxfails; /* TestRespReplyFailureCount */ + u32int iterno; /* TestIterationNumber */ +}; diff --git a/fns.h b/fns.h new file mode 100644 index 0000000..ae1477c --- /dev/null +++ b/fns.h @@ -0,0 +1,6 @@ +void sysfatal(char*, ...); +void *emalloc(ulong); +sockaddr_in *mkinetsa(char*, int); +int listentcp(int); +int bindudp(int); +int acceptcall(int, char*, int); diff --git a/main.c b/main.c new file mode 100644 index 0000000..8d059e9 --- /dev/null +++ b/main.c @@ -0,0 +1,142 @@ +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include "dat.h" +#include "fns.h" +#include "args.h" + +enum { + LPORT = 7 +}; + +int lfd, ncpu; +pthread_t *threads; +pthread_mutex_t attendlock; + +int debug; +char *argv0; + +/* + * echo service as of rfc862 + */ +//void +//srvecho(int fd) +//{ +// char buf[8192]; +// int n; +// +// while((n = read(fd, buf, sizeof buf)) > 0) +// if(write(fd, buf, n) != n) +// return; +//} +// +//void* +//tmain(void *a) +//{ +// char caddr[128]; +// int cfd; +// +// for(;;){ +// pthread_mutex_lock(&attendlock); +// if((cfd = acceptcall(lfd, caddr, sizeof caddr)) < 0) +// sysfatal("acceptcall: %r"); +// pthread_mutex_unlock(&attendlock); +// +// if(debug) +// fprint(2, "thr#%lu accepted call from %s\n", pthread_self(), caddr); +// +// srvecho(cfd); +// close(cfd); +// +// if(debug) +// fprint(2, "thr#%lu ended call with %s\n", pthread_self(), caddr); +// } +//} + +/* + * (udp)echo service as of rfc862 + */ +void* +udpechosrv(void *a) +{ + sockaddr_in csa; + char buf[4096], caddr[128], *cs; + int n, port; + uint csalen; + + memset(&csa, 0, sizeof(sockaddr_in)); + csalen = sizeof(sockaddr_in); + + for(;;){ + pthread_mutex_lock(&attendlock); + if((n = recvfrom(lfd, buf, sizeof buf, 0, (sockaddr*)&csa, &csalen)) < 0){ + pthread_mutex_unlock(&attendlock); + continue; + } + pthread_mutex_unlock(&attendlock); + + cs = inet_ntoa(csa.sin_addr); + port = ntohs(csa.sin_port); + snprint(caddr, sizeof caddr, "udp!%s!%d", cs, port); + + if(debug) + fprint(2, "thr#%lu received %d byte datagram from %s\n", pthread_self(), n, caddr); + + if(sendto(lfd, buf, n, 0, (sockaddr*)&csa, csalen) < 0) + continue; + + if(debug) + fprint(2, "thr#%lu sent %d byte datagram to %s\n", pthread_self(), n, caddr); + } +} + +static void +usage(void) +{ + fprint(2, "usage: %s [-d]\n", argv0); + exit(1); +} + +int +main(int argc, char *argv[]) +{ + int i; + + ARGBEGIN{ + case 'd': debug++; break; + default: usage(); + }ARGEND; + if(argc != 0) + usage(); + + if((lfd = bindudp(LPORT)) < 0) + sysfatal("bindudp: %r"); + + ncpu = sysconf(_SC_NPROCESSORS_ONLN); + if(ncpu < 1) + ncpu = 1; + + threads = emalloc(sizeof(pthread_t)*ncpu); + pthread_mutex_init(&attendlock, nil); + + for(i = 0; i < ncpu; i++){ + pthread_create(threads+i, nil, udpechosrv, nil); + if(debug) + fprint(2, "created thr#%lu\n", *(threads+i)); + } + + pause(); + + free(threads); + pthread_mutex_destroy(&attendlock); + exit(0); +} diff --git a/readme.md b/readme.md new file mode 100644 index 0000000..5dc9402 --- /dev/null +++ b/readme.md @@ -0,0 +1,6 @@ +# echod + +A UDP Echo daemon as of [RFC862](https://tools.ietf.org/html/rfc862), +with Echo+ support used for CPE testing using the +[TR-143](https://www.broadband-forum.org/technical/download/TR-143_Amendment-1_Corrigendum-1.pdf) +protocol. diff --git a/util.c b/util.c new file mode 100644 index 0000000..26acbc3 --- /dev/null +++ b/util.c @@ -0,0 +1,113 @@ +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include "dat.h" +#include "fns.h" + +extern int debug; + +void +sysfatal(char *fmt, ...) +{ + va_list arg; + char buf[2048]; + + va_start(arg, fmt); + vseprint(buf, buf+sizeof(buf), fmt, arg); + va_end(arg); + fprint(2, "%s\n", buf); + exit(1); +} + +void * +emalloc(ulong n) +{ + void *p; + + p = malloc(n); + if(p == nil) + sysfatal("malloc: %r"); + memset(p, 0, n); + return p; +} + +sockaddr_in* +mkinetsa(char *ipaddr, int port) +{ + sockaddr_in *sa; + + sa = emalloc(sizeof(sockaddr_in)); + sa->sin_family = AF_INET; + if(inet_pton(AF_INET, ipaddr, &sa->sin_addr.s_addr) <= 0) + sysfatal("inet_pton: %r"); + sa->sin_port = htons(port); + return sa; +} + +int +listentcp(int port) +{ + sockaddr_in *addr; + int fd; + + addr = mkinetsa("0.0.0.0", port); + if((fd = socket(PF_INET, SOCK_STREAM, 0)) < 0) + return -1; + if(bind(fd, (sockaddr*)addr, sizeof(sockaddr_in)) < 0){ + close(fd); + return -1; + } + if(listen(fd, 128) < 0){ + close(fd); + return -1; + } + if(debug) + fprint(2, "listening on tcp!%s!%d\n", inet_ntoa(addr->sin_addr), port); + free(addr); + return fd; +} + +int +bindudp(int port) +{ + sockaddr_in *addr; + int fd; + + addr = mkinetsa("0.0.0.0", port); + if((fd = socket(PF_INET, SOCK_DGRAM, 0)) < 0) + return -1; + if(bind(fd, (sockaddr*)addr, sizeof(sockaddr_in)) < 0){ + close(fd); + return -1; + } + if(debug) + fprint(2, "listening on udp!%s!%d\n", inet_ntoa(addr->sin_addr), port); + free(addr); + return fd; +} + +int +acceptcall(int lfd, char *caddr, int caddrlen) +{ + sockaddr_in addr; + uint addrlen; + int fd, port; + char *cs; + + memset(&addr, 0, sizeof(sockaddr_in)); + addrlen = sizeof(sockaddr_in); + if((fd = accept(lfd, (sockaddr*)&addr, &addrlen)) < 0) + return -1; + cs = inet_ntoa(addr.sin_addr); + port = ntohs(addr.sin_port); + snprint(caddr, caddrlen, "tcp!%s!%d", cs, port); + return fd; +} -- cgit v1.2.3