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