aboutsummaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorrodri <rgl@antares-labs.eu>2020-12-13 13:49:38 +0000
committerrodri <rgl@antares-labs.eu>2020-12-13 13:49:38 +0000
commit47b8a9471fe006cef74d1ba8f8a2839fd8164041 (patch)
tree9c06df600c7b690d0ede965f7d589ef8c4aab629
downloadechod-47b8a9471fe006cef74d1ba8f8a2839fd8164041.tar.gz
echod-47b8a9471fe006cef74d1ba8f8a2839fd8164041.tar.bz2
echod-47b8a9471fe006cef74d1ba8f8a2839fd8164041.zip
initial commit. basic udp echo support.
-rw-r--r--Makefile28
-rw-r--r--args.h22
-rw-r--r--dat.h26
-rw-r--r--fns.h6
-rw-r--r--main.c142
-rw-r--r--readme.md6
-rw-r--r--util.c113
7 files changed, 343 insertions, 0 deletions
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 <unistd.h>
+#include <stdlib.h>
+#include <stdio.h>
+#include <stdarg.h>
+#include <string.h>
+#include <sys/types.h>
+#include <sys/socket.h>
+#include <netinet/in.h>
+#include <arpa/inet.h>
+#include <pthread.h>
+#include <utf.h>
+#include <fmt.h>
+#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 <unistd.h>
+#include <stdlib.h>
+#include <stdio.h>
+#include <stdarg.h>
+#include <string.h>
+#include <sys/types.h>
+#include <sys/socket.h>
+#include <netinet/in.h>
+#include <arpa/inet.h>
+#include <utf.h>
+#include <fmt.h>
+#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;
+}