xref: /netbsd-src/external/bsd/blocklist/test/srvtest.c (revision df83713dd85c543f79ef38c5e4862663436a08ae)
1*df83713dSchristos /*	$NetBSD: srvtest.c,v 1.1.1.1 2020/06/15 01:52:54 christos Exp $	*/
2*df83713dSchristos 
3*df83713dSchristos /*-
4*df83713dSchristos  * Copyright (c) 2015 The NetBSD Foundation, Inc.
5*df83713dSchristos  * All rights reserved.
6*df83713dSchristos  *
7*df83713dSchristos  * This code is derived from software contributed to The NetBSD Foundation
8*df83713dSchristos  * by Christos Zoulas.
9*df83713dSchristos  *
10*df83713dSchristos  * Redistribution and use in source and binary forms, with or without
11*df83713dSchristos  * modification, are permitted provided that the following conditions
12*df83713dSchristos  * are met:
13*df83713dSchristos  * 1. Redistributions of source code must retain the above copyright
14*df83713dSchristos  *    notice, this list of conditions and the following disclaimer.
15*df83713dSchristos  * 2. Redistributions in binary form must reproduce the above copyright
16*df83713dSchristos  *    notice, this list of conditions and the following disclaimer in the
17*df83713dSchristos  *    documentation and/or other materials provided with the distribution.
18*df83713dSchristos  *
19*df83713dSchristos  * THIS SOFTWARE IS PROVIDED BY THE NETBSD FOUNDATION, INC. AND CONTRIBUTORS
20*df83713dSchristos  * ``AS IS'' AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED
21*df83713dSchristos  * TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR
22*df83713dSchristos  * PURPOSE ARE DISCLAIMED.  IN NO EVENT SHALL THE FOUNDATION OR CONTRIBUTORS
23*df83713dSchristos  * BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
24*df83713dSchristos  * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
25*df83713dSchristos  * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
26*df83713dSchristos  * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
27*df83713dSchristos  * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
28*df83713dSchristos  * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
29*df83713dSchristos  * POSSIBILITY OF SUCH DAMAGE.
30*df83713dSchristos  */
31*df83713dSchristos #ifdef HAVE_CONFIG_H
32*df83713dSchristos #include "config.h"
33*df83713dSchristos #endif
34*df83713dSchristos 
35*df83713dSchristos #include <sys/cdefs.h>
36*df83713dSchristos __RCSID("$NetBSD: srvtest.c,v 1.1.1.1 2020/06/15 01:52:54 christos Exp $");
37*df83713dSchristos 
38*df83713dSchristos #include <sys/types.h>
39*df83713dSchristos #include <sys/socket.h>
40*df83713dSchristos #include <netinet/in.h>
41*df83713dSchristos 
42*df83713dSchristos #include <stdio.h>
43*df83713dSchristos #include <signal.h>
44*df83713dSchristos #include <string.h>
45*df83713dSchristos #include <syslog.h>
46*df83713dSchristos #include <unistd.h>
47*df83713dSchristos #include <stdlib.h>
48*df83713dSchristos #include <poll.h>
49*df83713dSchristos #include <err.h>
50*df83713dSchristos 
51*df83713dSchristos #include "blocklist.h"
52*df83713dSchristos #ifdef BLDEBUG
53*df83713dSchristos #include "bl.h"
54*df83713dSchristos static void *b;
55*df83713dSchristos #endif
56*df83713dSchristos 
57*df83713dSchristos #ifndef INFTIM
58*df83713dSchristos #define INFTIM -1
59*df83713dSchristos #endif
60*df83713dSchristos 
61*df83713dSchristos static void
process_tcp(int afd)62*df83713dSchristos process_tcp(int afd)
63*df83713dSchristos {
64*df83713dSchristos 	ssize_t n;
65*df83713dSchristos 	char buffer[256];
66*df83713dSchristos 
67*df83713dSchristos 	memset(buffer, 0, sizeof(buffer));
68*df83713dSchristos 
69*df83713dSchristos 	if ((n = read(afd, buffer, sizeof(buffer))) == -1)
70*df83713dSchristos 		err(1, "read");
71*df83713dSchristos 	buffer[sizeof(buffer) - 1] = '\0';
72*df83713dSchristos 	printf("%s: sending %d %s\n", getprogname(), afd, buffer);
73*df83713dSchristos #ifdef BLDEBUG
74*df83713dSchristos 	blocklist_r(b, 1, afd, buffer);
75*df83713dSchristos #else
76*df83713dSchristos 	blocklist(1, afd, buffer);
77*df83713dSchristos #endif
78*df83713dSchristos 	exit(0);
79*df83713dSchristos }
80*df83713dSchristos 
81*df83713dSchristos static void
process_udp(int afd)82*df83713dSchristos process_udp(int afd)
83*df83713dSchristos {
84*df83713dSchristos 	ssize_t n;
85*df83713dSchristos 	char buffer[256];
86*df83713dSchristos 	struct sockaddr_storage ss;
87*df83713dSchristos 	socklen_t slen;
88*df83713dSchristos 
89*df83713dSchristos 	memset(buffer, 0, sizeof(buffer));
90*df83713dSchristos 
91*df83713dSchristos 	slen = (socklen_t)sizeof(ss);
92*df83713dSchristos 	memset(&ss, 0, sizeof(ss));
93*df83713dSchristos 	if ((n = recvfrom(afd, buffer, sizeof(buffer), 0, (void *)&ss,
94*df83713dSchristos 		&slen)) == -1)
95*df83713dSchristos 		err(1, "recvfrom");
96*df83713dSchristos 	buffer[sizeof(buffer) - 1] = '\0';
97*df83713dSchristos 	printf("%s: sending %d %s\n", getprogname(), afd, buffer);
98*df83713dSchristos 	blocklist_sa(1, afd, (void *)&ss, slen, buffer);
99*df83713dSchristos 	exit(0);
100*df83713dSchristos }
101*df83713dSchristos static int
cr(int af,int type,in_port_t p)102*df83713dSchristos cr(int af, int type, in_port_t p)
103*df83713dSchristos {
104*df83713dSchristos 	int sfd;
105*df83713dSchristos 	struct sockaddr_storage ss;
106*df83713dSchristos 	socklen_t slen;
107*df83713dSchristos 	sfd = socket(af == AF_INET ? PF_INET : PF_INET6, type, 0);
108*df83713dSchristos 	if (sfd == -1)
109*df83713dSchristos 		err(1, "socket");
110*df83713dSchristos 
111*df83713dSchristos 	p = htons(p);
112*df83713dSchristos 	memset(&ss, 0, sizeof(ss));
113*df83713dSchristos 	if (af == AF_INET) {
114*df83713dSchristos 		struct sockaddr_in *s = (void *)&ss;
115*df83713dSchristos 		s->sin_family = AF_INET;
116*df83713dSchristos 		slen = sizeof(*s);
117*df83713dSchristos 		s->sin_port = p;
118*df83713dSchristos 	} else {
119*df83713dSchristos 		struct sockaddr_in6 *s6 = (void *)&ss;
120*df83713dSchristos 		s6->sin6_family = AF_INET6;
121*df83713dSchristos 		slen = sizeof(*s6);
122*df83713dSchristos 		s6->sin6_port = p;
123*df83713dSchristos 	}
124*df83713dSchristos #ifdef HAVE_STRUCT_SOCKADDR_SA_LEN
125*df83713dSchristos 	ss.ss_len = (uint8_t)slen;
126*df83713dSchristos #endif
127*df83713dSchristos 
128*df83713dSchristos 	if (bind(sfd, (const void *)&ss, slen) == -1)
129*df83713dSchristos 		err(1, "bind");
130*df83713dSchristos 
131*df83713dSchristos 	if (type != SOCK_DGRAM)
132*df83713dSchristos 		if (listen(sfd, 5) == -1)
133*df83713dSchristos 			err(1, "listen");
134*df83713dSchristos 	return sfd;
135*df83713dSchristos }
136*df83713dSchristos 
137*df83713dSchristos static void
handle(int type,int sfd)138*df83713dSchristos handle(int type, int sfd)
139*df83713dSchristos {
140*df83713dSchristos 	struct sockaddr_storage ss;
141*df83713dSchristos 	socklen_t alen = sizeof(ss);
142*df83713dSchristos 	int afd;
143*df83713dSchristos 
144*df83713dSchristos 	if (type != SOCK_DGRAM) {
145*df83713dSchristos 		if ((afd = accept(sfd, (void *)&ss, &alen)) == -1)
146*df83713dSchristos 			err(1, "accept");
147*df83713dSchristos 	} else
148*df83713dSchristos 		afd = sfd;
149*df83713dSchristos 
150*df83713dSchristos 	/* Create child process */
151*df83713dSchristos 	switch (fork()) {
152*df83713dSchristos 	case -1:
153*df83713dSchristos 		err(1, "fork");
154*df83713dSchristos 	case 0:
155*df83713dSchristos 		if (type == SOCK_DGRAM)
156*df83713dSchristos 			process_udp(afd);
157*df83713dSchristos 		else
158*df83713dSchristos 			process_tcp(afd);
159*df83713dSchristos 		break;
160*df83713dSchristos 	default:
161*df83713dSchristos 		close(afd);
162*df83713dSchristos 		break;
163*df83713dSchristos 	}
164*df83713dSchristos }
165*df83713dSchristos 
166*df83713dSchristos static __dead void
usage(int c)167*df83713dSchristos usage(int c)
168*df83713dSchristos {
169*df83713dSchristos 	warnx("Unknown option `%c'", (char)c);
170*df83713dSchristos 	fprintf(stderr, "Usage: %s [-u] [-p <num>]\n", getprogname());
171*df83713dSchristos 	exit(EXIT_FAILURE);
172*df83713dSchristos }
173*df83713dSchristos 
174*df83713dSchristos int
main(int argc,char * argv[])175*df83713dSchristos main(int argc, char *argv[])
176*df83713dSchristos {
177*df83713dSchristos #ifdef __linux__
178*df83713dSchristos #define NUMFD 1
179*df83713dSchristos #else
180*df83713dSchristos #define NUMFD 2
181*df83713dSchristos #endif
182*df83713dSchristos 	struct pollfd pfd[NUMFD];
183*df83713dSchristos 	int type = SOCK_STREAM, c;
184*df83713dSchristos 	in_port_t port = 6161;
185*df83713dSchristos 
186*df83713dSchristos 	signal(SIGCHLD, SIG_IGN);
187*df83713dSchristos 
188*df83713dSchristos #ifdef BLDEBUG
189*df83713dSchristos 	b = bl_create(false, "blsock", vsyslog);
190*df83713dSchristos #endif
191*df83713dSchristos 
192*df83713dSchristos 	while ((c = getopt(argc, argv, "up:")) != -1)
193*df83713dSchristos 		switch (c) {
194*df83713dSchristos 		case 'u':
195*df83713dSchristos 			type = SOCK_DGRAM;
196*df83713dSchristos 			break;
197*df83713dSchristos 		case 'p':
198*df83713dSchristos 			port = (in_port_t)atoi(optarg);
199*df83713dSchristos 			break;
200*df83713dSchristos 		default:
201*df83713dSchristos 			usage(c);
202*df83713dSchristos 		}
203*df83713dSchristos 
204*df83713dSchristos 	pfd[0].fd = cr(AF_INET, type, port);
205*df83713dSchristos 	pfd[0].events = POLLIN;
206*df83713dSchristos #if NUMFD > 1
207*df83713dSchristos 	pfd[1].fd = cr(AF_INET6, type, port);
208*df83713dSchristos 	pfd[1].events = POLLIN;
209*df83713dSchristos #endif
210*df83713dSchristos 
211*df83713dSchristos 	for (;;) {
212*df83713dSchristos 		if (poll(pfd, __arraycount(pfd), INFTIM) == -1)
213*df83713dSchristos 			err(1, "poll");
214*df83713dSchristos 		for (size_t i = 0; i < __arraycount(pfd); i++) {
215*df83713dSchristos 			if ((pfd[i].revents & POLLIN) == 0)
216*df83713dSchristos 				continue;
217*df83713dSchristos 			handle(type, pfd[i].fd);
218*df83713dSchristos 		}
219*df83713dSchristos 	}
220*df83713dSchristos }
221