commit cd801d3eefc9654dd2f56d4944eaa245eb581c9f
parent 965324af5e5e7826cf87d5c760e8298f5e47161e
Author: sin <sin@2f30.org>
Date: Tue, 12 Apr 2016 16:52:04 +0100
split out client/server code
Diffstat:
M | Makefile | | | 6 | +++--- |
A | client.c | | | 53 | +++++++++++++++++++++++++++++++++++++++++++++++++++++ |
A | server.c | | | 75 | +++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++ |
M | stun.c | | | 186 | ++++++++++++++++++------------------------------------------------------------- |
M | stun.h | | | 10 | ++++++++++ |
5 files changed, 182 insertions(+), 148 deletions(-)
diff --git a/Makefile b/Makefile
@@ -1,9 +1,9 @@
include config.mk
DISTFILES = Makefile README WHATSNEW UNLICENSE arg.h auth.c \
- config.mk crypto.c dev_bsd.c dev_linux.c log.c \
- netpkt.c stun.8 stun.c stun.h util.c
-OBJ = $(EXTRAOBJ) auth.o crypto.o log.o netpkt.o stun.o util.o
+ client.c config.mk crypto.c dev_bsd.c dev_linux.c log.c \
+ netpkt.c server.c stun.8 stun.c stun.h util.c
+OBJ = $(EXTRAOBJ) auth.o client.o crypto.o log.o netpkt.o server.o stun.o util.o
BIN = stun
all: $(BIN)
diff --git a/client.c b/client.c
@@ -0,0 +1,53 @@
+#include <sys/types.h>
+#include <sys/socket.h>
+
+#include <netinet/in.h>
+#include <netinet/tcp.h>
+#include <arpa/inet.h>
+#include <netdb.h>
+
+#include <stdint.h>
+#include <string.h>
+#include <unistd.h>
+
+#include "stun.h"
+
+int
+clientconnect(char *host, char *port)
+{
+ struct addrinfo hints, *ai, *p;
+ int ret, netfd;
+
+ memset(&hints, 0, sizeof(hints));
+ hints.ai_family = AF_INET;
+ hints.ai_socktype = SOCK_STREAM;
+ if ((ret = getaddrinfo(host, port, &hints, &ai)))
+ logerr("getaddrinfo: %s", gai_strerror(ret));
+
+ for (p = ai; p; p = p->ai_next) {
+ if ((netfd = socket(AF_INET, SOCK_STREAM, 0)) < 0)
+ continue;
+ if (connect(netfd, p->ai_addr, p->ai_addrlen) < 0) {
+ close(netfd);
+ continue;
+ }
+ break;
+ }
+ freeaddrinfo(ai);
+ if (!p) {
+ close(netfd);
+ logwarn("failed to connect to %s:%s", host, port);
+ return -1;
+ }
+
+ setnonblock(netfd, 1);
+ setsockopt(netfd, SOL_SOCKET, SO_KEEPALIVE, (int []){1}, sizeof(int));
+ setsockopt(netfd, IPPROTO_TCP, TCP_NODELAY, (int []){1}, sizeof(int));
+
+ if (response(netfd) < 0 || challenge(netfd) < 0) {
+ close(netfd);
+ logwarn("challenge-response failed");
+ return -1;
+ }
+ return netfd;
+}
diff --git a/server.c b/server.c
@@ -0,0 +1,75 @@
+#include <sys/types.h>
+#include <sys/socket.h>
+
+#include <netinet/in.h>
+#include <netinet/tcp.h>
+#include <arpa/inet.h>
+#include <netdb.h>
+
+#include <errno.h>
+#include <stdint.h>
+#include <string.h>
+#include <unistd.h>
+
+#include "stun.h"
+
+int
+serverinit(char *host, char *port)
+{
+ struct addrinfo hints, *ai, *p;
+ int ret, listenfd;
+
+ memset(&hints, 0, sizeof(hints));
+ hints.ai_family = AF_INET;
+ hints.ai_socktype = SOCK_STREAM;
+ hints.ai_flags = AI_PASSIVE;
+
+ if ((ret = getaddrinfo(host, port, &hints, &ai)))
+ logerr("getaddrinfo: %s", gai_strerror(ret));
+
+ for (p = ai; p; p = p->ai_next) {
+ if ((listenfd = socket(AF_INET, SOCK_STREAM, 0)) < 0)
+ continue;
+ setsockopt(listenfd, SOL_SOCKET, SO_REUSEADDR, (int []){1},
+ sizeof(int));
+ if (bind(listenfd, p->ai_addr, p->ai_addrlen) < 0) {
+ close(listenfd);
+ continue;
+ }
+ if (listen(listenfd, 5) < 0) {
+ close(listenfd);
+ continue;
+ }
+ break;
+ }
+ if (!p)
+ logerr("failed to bind socket");
+ freeaddrinfo(ai);
+ return listenfd;
+}
+
+int
+serveraccept(int listenfd)
+{
+ struct sockaddr_in remote;
+ int netfd;
+
+ netfd = accept(listenfd, (struct sockaddr *)&remote,
+ (socklen_t []){sizeof(remote)});
+ if (netfd < 0) {
+ if (errno != ECONNABORTED)
+ logwarn("accept failed");
+ return -1;
+ }
+
+ setnonblock(netfd, 1);
+ setsockopt(netfd, SOL_SOCKET, SO_KEEPALIVE, (int []){1}, sizeof(int));
+ setsockopt(netfd, IPPROTO_TCP, TCP_NODELAY, (int []){1}, sizeof(int));
+
+ if (challenge(netfd) < 0 || response(netfd) < 0) {
+ close(netfd);
+ logwarn("challenge-response failed");
+ return -1;
+ }
+ return netfd;
+}
diff --git a/stun.c b/stun.c
@@ -41,17 +41,8 @@
*
*/
-#include <sys/types.h>
#include <sys/resource.h>
-#include <sys/socket.h>
-#include <netinet/in.h>
-#include <netinet/tcp.h>
-#include <arpa/inet.h>
-#include <netdb.h>
-
-#include <errno.h>
-#include <fcntl.h>
#include <poll.h>
#include <signal.h>
#include <stdio.h>
@@ -106,124 +97,6 @@ tunnel(int netfd, int devfd)
return 0;
}
-int
-serversetup(int devfd)
-{
- struct addrinfo hints, *ai, *p;
- struct sockaddr_in remote;
- int ret, netfd, listenfd;
-
- memset(&hints, 0, sizeof(hints));
- hints.ai_family = AF_INET;
- hints.ai_socktype = SOCK_STREAM;
- hints.ai_flags = AI_PASSIVE;
-
- if ((ret = getaddrinfo(bindaddr, port, &hints, &ai)))
- logerr("getaddrinfo: %s", gai_strerror(ret));
-
- for (p = ai; p; p = p->ai_next) {
- if ((listenfd = socket(AF_INET, SOCK_STREAM, 0)) < 0)
- continue;
- setsockopt(listenfd, SOL_SOCKET, SO_REUSEADDR, (int []){1},
- sizeof(int));
- if (bind(listenfd, p->ai_addr, p->ai_addrlen) < 0) {
- close(listenfd);
- continue;
- }
- if (listen(listenfd, 5) < 0) {
- close(listenfd);
- continue;
- }
- break;
- }
- if (!p)
- logerr("failed to bind socket");
- freeaddrinfo(ai);
-
- revokeprivs();
-#if defined(__OpenBSD__)
- if (pledge("stdio inet", NULL) < 0)
- logerr("pledge failed");
-#endif
-
- for (;;) {
- netfd = accept(listenfd, (struct sockaddr *)&remote,
- (socklen_t []){sizeof(remote)});
- if (netfd < 0) {
- if (errno != ECONNABORTED)
- logwarn("accept failed");
- continue;
- }
- if (debug)
- logdbg("remote peer connected: %s",
- inet_ntoa(remote.sin_addr));
-
- setnonblock(netfd, 1);
- setsockopt(netfd, SOL_SOCKET, SO_KEEPALIVE, (int []){1}, sizeof(int));
- setsockopt(netfd, IPPROTO_TCP, TCP_NODELAY, (int []){1}, sizeof(int));
-
- if (challenge(netfd) < 0 || response(netfd) < 0) {
- logwarn("challenge-response failed");
- goto err;
- }
-
- tunnel(netfd, devfd);
-err:
- netreset();
- close(netfd);
- if (debug)
- logdbg("remote peer disconnected: %s",
- inet_ntoa(remote.sin_addr));
- }
-}
-
-int
-clientsetup(int devfd)
-{
- struct addrinfo hints, *ai, *p;
- int ret, netfd;
-
- memset(&hints, 0, sizeof(hints));
- hints.ai_family = AF_INET;
- hints.ai_socktype = SOCK_STREAM;
- if ((ret = getaddrinfo(host, port, &hints, &ai)))
- logerr("getaddrinfo: %s", gai_strerror(ret));
-
- for (p = ai; p; p = p->ai_next) {
- if ((netfd = socket(AF_INET, SOCK_STREAM, 0)) < 0)
- continue;
- if (connect(netfd, p->ai_addr, p->ai_addrlen) < 0) {
- close(netfd);
- continue;
- }
- break;
- }
- freeaddrinfo(ai);
- if (!p) {
- close(netfd);
- logwarn("failed to connect to %s:%s", host, port);
- return -1;
- }
- if (debug)
- logdbg("connected to %s:%s", host, port);
-
- setnonblock(netfd, 1);
- setsockopt(netfd, SOL_SOCKET, SO_KEEPALIVE, (int []){1}, sizeof(int));
- setsockopt(netfd, IPPROTO_TCP, TCP_NODELAY, (int []){1}, sizeof(int));
-
- if (response(netfd) < 0 || challenge(netfd) < 0) {
- logwarn("challenge-response failed");
- goto err;
- }
-
- tunnel(netfd, devfd);
-err:
- netreset();
- close(netfd);
- logwarn("connection to %s:%s dropped", host, port);
- return -1;
-}
-
void
usage(void)
{
@@ -237,7 +110,7 @@ main(int argc, char *argv[])
{
struct rlimit rlim;
char *arg, *pw;
- int devfd;
+ int devfd, listenfd, netfd;
ARGBEGIN {
case 'd':
@@ -274,37 +147,60 @@ main(int argc, char *argv[])
if (argc != 1 || !(sflag ^ (host != NULL)))
usage();
+ /* disable core dumps as memory contains the pre-shared key */
+ rlim.rlim_cur = rlim.rlim_max = 0;
+ if (setrlimit(RLIMIT_CORE, &rlim) < 0)
+ logerr("failed to disable core dumps");
+
signal(SIGPIPE, SIG_IGN);
if (!debug)
daemon(0, 0);
loginit("stun");
- devfd = devopen(argv[0]);
- /* disable core dumps as memory contains the pre-shared key */
- rlim.rlim_cur = rlim.rlim_max = 0;
- if (setrlimit(RLIMIT_CORE, &rlim) < 0)
- logerr("failed to disable core dumps");
+ /* initialize tun/tap device */
+ devfd = devopen(argv[0]);
+ /* initialize crypto engine */
if (!(pw = getenv("STUNPW")))
logerr("STUNPW is not set");
cryptoinit(pw);
memset(pw, 0, strlen(pw));
+ /* initialize networking engine */
netinit();
-
- if (sflag)
- return serversetup(devfd);
-
- revokeprivs();
+ if (sflag) {
+ listenfd = serverinit(bindaddr, port);
+ revokeprivs();
#if defined(__OpenBSD__)
- if (pledge("stdio dns inet", NULL) < 0)
- logerr("pledge failed");
+ if (pledge("stdio inet", NULL) < 0)
+ logerr("pledge failed");
#endif
-
- /* auto-reconnect client */
- for (;;) {
- clientsetup(devfd);
- sleep(RECONNECTTIMEO);
+ for (;;) {
+ if ((netfd = serveraccept(listenfd)) < 0) {
+ netreset();
+ continue;
+ }
+ tunnel(netfd, devfd);
+ close(netfd);
+ netreset();
+ }
+ } else {
+ revokeprivs();
+#if defined(__OpenBSD__)
+ if (pledge("stdio dns inet", NULL) < 0)
+ logerr("pledge failed");
+#endif
+ for (;;) {
+ if ((netfd = clientconnect(host, port)) < 0) {
+ netreset();
+ sleep(RECONNECTTIMEO);
+ continue;
+ }
+ tunnel(netfd, devfd);
+ close(netfd);
+ netreset();
+ sleep(RECONNECTTIMEO);
+ }
}
return 0;
}
diff --git a/stun.h b/stun.h
@@ -26,6 +26,9 @@ extern char *cipher;
int challenge(int);
int response(int);
+/* client.c */
+int clientconnect(char *, char *);
+
/* crypto.c */
void cryptoinit(char *);
size_t cryptononcelen(void);
@@ -54,6 +57,13 @@ int netread(int, unsigned char *, size_t, size_t *);
void netreset(void);
void netinit(void);
+/* server.c */
+int serverinit(char *, char *);
+int serveraccept(int);
+
+/* stun.c */
+int tunnel(int, int);
+
/* util.c */
void pack16(unsigned char *, uint16_t);
uint16_t unpack16(unsigned char *);