1*36ecdf3eSbluhm /*	$OpenBSD: nonxt-reflect.c,v 1.2 2018/05/21 01:19:21 bluhm Exp $	*/
2ecef6068Sbluhm /*
3ecef6068Sbluhm  * Copyright (c) Alexander Bluhm <bluhm@genua.de>
4ecef6068Sbluhm  *
5ecef6068Sbluhm  * Permission to use, copy, modify, and distribute this software for any
6ecef6068Sbluhm  * purpose with or without fee is hereby granted, provided that the above
7ecef6068Sbluhm  * copyright notice and this permission notice appear in all copies.
8ecef6068Sbluhm  *
9ecef6068Sbluhm  * THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES
10ecef6068Sbluhm  * WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF
11ecef6068Sbluhm  * MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR
12ecef6068Sbluhm  * ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES
13ecef6068Sbluhm  * WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN
14ecef6068Sbluhm  * ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF
15ecef6068Sbluhm  * OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.
16ecef6068Sbluhm  */
17ecef6068Sbluhm 
18ecef6068Sbluhm #include <sys/types.h>
19ecef6068Sbluhm #include <sys/socket.h>
20ecef6068Sbluhm 
21ecef6068Sbluhm #include <netdb.h>
22ecef6068Sbluhm 
23ecef6068Sbluhm #include <err.h>
24ecef6068Sbluhm #include <errno.h>
25ecef6068Sbluhm #include <stdio.h>
26ecef6068Sbluhm #include <stdlib.h>
27ecef6068Sbluhm #include <string.h>
28ecef6068Sbluhm #include <unistd.h>
29ecef6068Sbluhm 
30ecef6068Sbluhm void __dead usage(void);
31ecef6068Sbluhm 
32ecef6068Sbluhm void
usage(void)33ecef6068Sbluhm usage(void)
34ecef6068Sbluhm {
35*36ecdf3eSbluhm 	fprintf(stderr, "usage: nonxt-reflect localaddr\n"
36*36ecdf3eSbluhm 	    "Daemonize, wait for protocol 59 packets, and answer them.\n");
37ecef6068Sbluhm 	exit(1);
38ecef6068Sbluhm }
39ecef6068Sbluhm 
40ecef6068Sbluhm int
main(int argc,char * argv[])41ecef6068Sbluhm main(int argc, char *argv[])
42ecef6068Sbluhm {
43ecef6068Sbluhm 	struct addrinfo hints, *res, *res0;
44ecef6068Sbluhm 	const char *cause = NULL, *local;
45ecef6068Sbluhm 	int error;
46ecef6068Sbluhm 	int save_errno;
47ecef6068Sbluhm 	int s;
48ecef6068Sbluhm 	char buf[1024];
49ecef6068Sbluhm 
50ecef6068Sbluhm 	switch (argc) {
51ecef6068Sbluhm 	case 2:
52ecef6068Sbluhm 		local = argv[1];
53ecef6068Sbluhm 		break;
54ecef6068Sbluhm 	default:
55ecef6068Sbluhm 		usage();
56ecef6068Sbluhm 	}
57ecef6068Sbluhm 
58*36ecdf3eSbluhm 	if (pledge("stdio inet dns proc", NULL) == -1)
59*36ecdf3eSbluhm 		err(1, "pledge");
60*36ecdf3eSbluhm 
61ecef6068Sbluhm 	/* Create socket and bind it to local address. */
62ecef6068Sbluhm 	memset(&hints, 0, sizeof(hints));
63ecef6068Sbluhm 	hints.ai_family = AF_UNSPEC;
64ecef6068Sbluhm 	hints.ai_socktype = SOCK_RAW;
65ecef6068Sbluhm 	hints.ai_protocol = IPPROTO_NONE;
66ecef6068Sbluhm 	hints.ai_flags = AI_PASSIVE;
67ecef6068Sbluhm 	error = getaddrinfo(local, NULL, &hints, &res0);
68ecef6068Sbluhm 	if (error)
69ecef6068Sbluhm 		errx(1, "getaddrinfo local: %s", gai_strerror(error));
70ecef6068Sbluhm 	for (res = res0; res; res = res->ai_next) {
71ecef6068Sbluhm 		s = socket(res->ai_family, res->ai_socktype, res->ai_protocol);
72ecef6068Sbluhm 		if (s == -1) {
73ecef6068Sbluhm 			cause = "socket";
74ecef6068Sbluhm 			continue;
75ecef6068Sbluhm 		}
76ecef6068Sbluhm 		if (bind(s, res->ai_addr, res->ai_addrlen) == -1) {
77ecef6068Sbluhm 			cause = "bind";
78ecef6068Sbluhm 			save_errno = errno;
79ecef6068Sbluhm 			close(s);
80ecef6068Sbluhm 			errno = save_errno;
81ecef6068Sbluhm 			continue;
82ecef6068Sbluhm 		}
83ecef6068Sbluhm 		break;
84ecef6068Sbluhm 	}
85ecef6068Sbluhm 	if (res == NULL)
86ecef6068Sbluhm 		err(1, "%s", cause);
87ecef6068Sbluhm 	freeaddrinfo(res0);
88ecef6068Sbluhm 
89*36ecdf3eSbluhm 	/* Socket is ready to receive, parent process may proceed. */
90*36ecdf3eSbluhm 	daemon(1, 1);
91*36ecdf3eSbluhm 	if (pledge("stdio inet", NULL) == -1)
92*36ecdf3eSbluhm 		err(1, "pledge");
93*36ecdf3eSbluhm 
94*36ecdf3eSbluhm 	for (;;) {
95*36ecdf3eSbluhm 		struct sockaddr_storage ss;
96*36ecdf3eSbluhm 		socklen_t slen;
97ecef6068Sbluhm 
98ecef6068Sbluhm 		/* Receive a protocol 59 packet. */
99ecef6068Sbluhm 		slen = sizeof(ss);
100*36ecdf3eSbluhm 		if (recvfrom(s, buf, sizeof(buf), 0, (struct sockaddr *)&ss,
101*36ecdf3eSbluhm 		    &slen) == -1)
102ecef6068Sbluhm 			err(1, "recv");
103ecef6068Sbluhm 		/* Send back a reply packet. */
104ecef6068Sbluhm 		if (sendto(s, buf, 0, 0, (struct sockaddr *)&ss, slen) == -1)
105ecef6068Sbluhm 			err(1, "send");
106*36ecdf3eSbluhm 	}
107ecef6068Sbluhm 
108*36ecdf3eSbluhm 	/* NOTREACHED */
109ecef6068Sbluhm 	return 0;
110ecef6068Sbluhm }
111