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