summaryrefslogtreecommitdiff
path: root/test/srvtest.c
diff options
context:
space:
mode:
Diffstat (limited to 'test/srvtest.c')
-rw-r--r--test/srvtest.c220
1 files changed, 220 insertions, 0 deletions
diff --git a/test/srvtest.c b/test/srvtest.c
new file mode 100644
index 000000000000..03a762ab81f2
--- /dev/null
+++ b/test/srvtest.c
@@ -0,0 +1,220 @@
+/* $NetBSD: srvtest.c,v 1.10 2015/05/30 22:40:38 christos Exp $ */
+
+/*-
+ * Copyright (c) 2015 The NetBSD Foundation, Inc.
+ * All rights reserved.
+ *
+ * This code is derived from software contributed to The NetBSD Foundation
+ * by Christos Zoulas.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions
+ * are met:
+ * 1. Redistributions of source code must retain the above copyright
+ * notice, this list of conditions and the following disclaimer.
+ * 2. Redistributions in binary form must reproduce the above copyright
+ * notice, this list of conditions and the following disclaimer in the
+ * documentation and/or other materials provided with the distribution.
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE NETBSD FOUNDATION, INC. AND CONTRIBUTORS
+ * ``AS IS'' AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED
+ * TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR
+ * PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE FOUNDATION OR CONTRIBUTORS
+ * BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
+ * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
+ * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
+ * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
+ * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
+ * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
+ * POSSIBILITY OF SUCH DAMAGE.
+ */
+#ifdef HAVE_CONFIG_H
+#include "config.h"
+#endif
+
+#include <sys/cdefs.h>
+__RCSID("$NetBSD: srvtest.c,v 1.10 2015/05/30 22:40:38 christos Exp $");
+
+#include <sys/types.h>
+#include <sys/socket.h>
+#include <netinet/in.h>
+
+#include <stdio.h>
+#include <signal.h>
+#include <string.h>
+#include <syslog.h>
+#include <unistd.h>
+#include <stdlib.h>
+#include <poll.h>
+#include <err.h>
+
+#include "blacklist.h"
+#ifdef BLDEBUG
+#include "bl.h"
+static void *b;
+#endif
+
+#ifndef INFTIM
+#define INFTIM -1
+#endif
+
+static void
+process_tcp(int afd)
+{
+ ssize_t n;
+ char buffer[256];
+
+ memset(buffer, 0, sizeof(buffer));
+
+ if ((n = read(afd, buffer, sizeof(buffer))) == -1)
+ err(1, "read");
+ buffer[sizeof(buffer) - 1] = '\0';
+ printf("%s: sending %d %s\n", getprogname(), afd, buffer);
+#ifdef BLDEBUG
+ blacklist_r(b, 1, afd, buffer);
+#else
+ blacklist(1, afd, buffer);
+#endif
+ exit(0);
+}
+
+static void
+process_udp(int afd)
+{
+ ssize_t n;
+ char buffer[256];
+ struct sockaddr_storage ss;
+ socklen_t slen;
+
+ memset(buffer, 0, sizeof(buffer));
+
+ slen = (socklen_t)sizeof(ss);
+ memset(&ss, 0, sizeof(ss));
+ if ((n = recvfrom(afd, buffer, sizeof(buffer), 0, (void *)&ss,
+ &slen)) == -1)
+ err(1, "recvfrom");
+ buffer[sizeof(buffer) - 1] = '\0';
+ printf("%s: sending %d %s\n", getprogname(), afd, buffer);
+ blacklist_sa(1, afd, (void *)&ss, slen, buffer);
+ exit(0);
+}
+static int
+cr(int af, int type, in_port_t p)
+{
+ int sfd;
+ struct sockaddr_storage ss;
+ socklen_t slen;
+ sfd = socket(af == AF_INET ? PF_INET : PF_INET6, type, 0);
+ if (sfd == -1)
+ err(1, "socket");
+
+ p = htons(p);
+ memset(&ss, 0, sizeof(ss));
+ if (af == AF_INET) {
+ struct sockaddr_in *s = (void *)&ss;
+ s->sin_family = AF_INET;
+ slen = sizeof(*s);
+ s->sin_port = p;
+ } else {
+ struct sockaddr_in6 *s6 = (void *)&ss;
+ s6->sin6_family = AF_INET6;
+ slen = sizeof(*s6);
+ s6->sin6_port = p;
+ }
+#ifdef HAVE_STRUCT_SOCKADDR_SA_LEN
+ ss.ss_len = (uint8_t)slen;
+#endif
+
+ if (bind(sfd, (const void *)&ss, slen) == -1)
+ err(1, "bind");
+
+ if (type != SOCK_DGRAM)
+ if (listen(sfd, 5) == -1)
+ err(1, "listen");
+ return sfd;
+}
+
+static void
+handle(int type, int sfd)
+{
+ struct sockaddr_storage ss;
+ socklen_t alen = sizeof(ss);
+ int afd;
+
+ if (type != SOCK_DGRAM) {
+ if ((afd = accept(sfd, (void *)&ss, &alen)) == -1)
+ err(1, "accept");
+ } else
+ afd = sfd;
+
+ /* Create child process */
+ switch (fork()) {
+ case -1:
+ err(1, "fork");
+ case 0:
+ if (type == SOCK_DGRAM)
+ process_udp(afd);
+ else
+ process_tcp(afd);
+ break;
+ default:
+ close(afd);
+ break;
+ }
+}
+
+static __dead void
+usage(int c)
+{
+ warnx("Unknown option `%c'", (char)c);
+ fprintf(stderr, "Usage: %s [-u] [-p <num>]\n", getprogname());
+ exit(EXIT_FAILURE);
+}
+
+int
+main(int argc, char *argv[])
+{
+#ifdef __linux__
+#define NUMFD 1
+#else
+#define NUMFD 2
+#endif
+ struct pollfd pfd[NUMFD];
+ int type = SOCK_STREAM, c;
+ in_port_t port = 6161;
+
+ signal(SIGCHLD, SIG_IGN);
+
+#ifdef BLDEBUG
+ b = bl_create(false, "blsock", vsyslog);
+#endif
+
+ while ((c = getopt(argc, argv, "up:")) != -1)
+ switch (c) {
+ case 'u':
+ type = SOCK_DGRAM;
+ break;
+ case 'p':
+ port = (in_port_t)atoi(optarg);
+ break;
+ default:
+ usage(c);
+ }
+
+ pfd[0].fd = cr(AF_INET, type, port);
+ pfd[0].events = POLLIN;
+#if NUMFD > 1
+ pfd[1].fd = cr(AF_INET6, type, port);
+ pfd[1].events = POLLIN;
+#endif
+
+ for (;;) {
+ if (poll(pfd, __arraycount(pfd), INFTIM) == -1)
+ err(1, "poll");
+ for (size_t i = 0; i < __arraycount(pfd); i++) {
+ if ((pfd[i].revents & POLLIN) == 0)
+ continue;
+ handle(type, pfd[i].fd);
+ }
+ }
+}