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