1*d1268e2eSknakahara /* $NetBSD: natt_terminator.c,v 1.2 2018/11/22 04:51:41 knakahara Exp $ */
20de7b049Sozaki-r
30de7b049Sozaki-r /*-
40de7b049Sozaki-r * Copyright (c) 2017 Internet Initiative Japan Inc.
50de7b049Sozaki-r * All rights reserved.
60de7b049Sozaki-r *
70de7b049Sozaki-r * Redistribution and use in source and binary forms, with or without
80de7b049Sozaki-r * modification, are permitted provided that the following conditions
90de7b049Sozaki-r * are met:
100de7b049Sozaki-r * 1. Redistributions of source code must retain the above copyright
110de7b049Sozaki-r * notice, this list of conditions and the following disclaimer.
120de7b049Sozaki-r * 2. Redistributions in binary form must reproduce the above copyright
130de7b049Sozaki-r * notice, this list of conditions and the following disclaimer in the
140de7b049Sozaki-r * documentation and/or other materials provided with the distribution.
150de7b049Sozaki-r *
160de7b049Sozaki-r * THIS SOFTWARE IS PROVIDED BY THE NETBSD FOUNDATION, INC. AND CONTRIBUTORS
170de7b049Sozaki-r * ``AS IS'' AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED
180de7b049Sozaki-r * TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR
190de7b049Sozaki-r * PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE FOUNDATION OR CONTRIBUTORS
200de7b049Sozaki-r * BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
210de7b049Sozaki-r * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
220de7b049Sozaki-r * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
230de7b049Sozaki-r * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
240de7b049Sozaki-r * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
250de7b049Sozaki-r * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
260de7b049Sozaki-r * POSSIBILITY OF SUCH DAMAGE.
270de7b049Sozaki-r */
280de7b049Sozaki-r
290de7b049Sozaki-r #include <sys/types.h>
300de7b049Sozaki-r #include <sys/socket.h>
310de7b049Sozaki-r #include <sys/wait.h>
320de7b049Sozaki-r #include <sys/time.h>
330de7b049Sozaki-r
340de7b049Sozaki-r #include <netinet/in.h>
350de7b049Sozaki-r #include <netinet/udp.h>
360de7b049Sozaki-r
370de7b049Sozaki-r #include <stdio.h>
380de7b049Sozaki-r #include <err.h>
390de7b049Sozaki-r #include <netdb.h>
400de7b049Sozaki-r #include <string.h>
410de7b049Sozaki-r #include <stdlib.h>
420de7b049Sozaki-r #include <unistd.h>
430de7b049Sozaki-r
44*d1268e2eSknakahara static void
usage(void)45*d1268e2eSknakahara usage(void)
46*d1268e2eSknakahara {
47*d1268e2eSknakahara const char *prog = "natt_terminator";
48*d1268e2eSknakahara
49*d1268e2eSknakahara fprintf(stderr, "Usage: %s [-46] <addr> <port>\n", prog);
50*d1268e2eSknakahara }
51*d1268e2eSknakahara
520de7b049Sozaki-r int
main(int argc,char ** argv)530de7b049Sozaki-r main(int argc, char **argv)
540de7b049Sozaki-r {
550de7b049Sozaki-r struct addrinfo hints;
560de7b049Sozaki-r struct addrinfo *res;
570de7b049Sozaki-r int s, e;
580de7b049Sozaki-r const char *addr, *port;
590de7b049Sozaki-r int option;
60*d1268e2eSknakahara int c, family = AF_INET;
610de7b049Sozaki-r
62*d1268e2eSknakahara while ((c = getopt(argc, argv, "46")) != -1) {
63*d1268e2eSknakahara switch (c) {
64*d1268e2eSknakahara case '4':
65*d1268e2eSknakahara family = AF_INET;
66*d1268e2eSknakahara break;
67*d1268e2eSknakahara case '6':
68*d1268e2eSknakahara family = AF_INET6;
69*d1268e2eSknakahara break;
70*d1268e2eSknakahara default:
71*d1268e2eSknakahara usage();
72*d1268e2eSknakahara return 1;
73*d1268e2eSknakahara }
74*d1268e2eSknakahara }
75*d1268e2eSknakahara argc -= optind;
76*d1268e2eSknakahara argv += optind;
77*d1268e2eSknakahara
78*d1268e2eSknakahara if (argc != 2) {
79*d1268e2eSknakahara usage();
800de7b049Sozaki-r return 1;
810de7b049Sozaki-r }
820de7b049Sozaki-r
83*d1268e2eSknakahara addr = argv[0];
84*d1268e2eSknakahara port = argv[1];
850de7b049Sozaki-r
860de7b049Sozaki-r memset(&hints, 0, sizeof(hints));
87*d1268e2eSknakahara hints.ai_family = family;
880de7b049Sozaki-r hints.ai_socktype = SOCK_DGRAM;
890de7b049Sozaki-r hints.ai_protocol = IPPROTO_UDP;
900de7b049Sozaki-r hints.ai_flags = 0;
910de7b049Sozaki-r
920de7b049Sozaki-r e = getaddrinfo(addr, port, &hints, &res);
930de7b049Sozaki-r if (e != 0)
940de7b049Sozaki-r errx(EXIT_FAILURE, "getaddrinfo failed: %s", gai_strerror(e));
950de7b049Sozaki-r
960de7b049Sozaki-r s = socket(res->ai_family, res->ai_socktype, res->ai_protocol);
970de7b049Sozaki-r if (s == -1)
980de7b049Sozaki-r err(EXIT_FAILURE, "socket");
990de7b049Sozaki-r
1000de7b049Sozaki-r /*
1010de7b049Sozaki-r * Set the option to tell the kernel that the socket can handle
1020de7b049Sozaki-r * UDP-encapsulated ESP packets for NAT-T.
1030de7b049Sozaki-r */
1040de7b049Sozaki-r option = UDP_ENCAP_ESPINUDP;
1050de7b049Sozaki-r e = setsockopt(s, IPPROTO_UDP, UDP_ENCAP, &option, sizeof(option));
1060de7b049Sozaki-r if (e == -1)
1070de7b049Sozaki-r err(EXIT_FAILURE, "setsockopt(UDP_ENCAP)");
1080de7b049Sozaki-r
1090de7b049Sozaki-r e = bind(s, res->ai_addr, res->ai_addrlen);
1100de7b049Sozaki-r if (e == -1)
1110de7b049Sozaki-r err(EXIT_FAILURE, "bind");
1120de7b049Sozaki-r
1130de7b049Sozaki-r /* Receiving a packet make the NAPT create a mapping. */
1140de7b049Sozaki-r {
1150de7b049Sozaki-r char buf[64];
1160de7b049Sozaki-r struct sockaddr_storage z;
1170de7b049Sozaki-r socklen_t len = sizeof(z);
1180de7b049Sozaki-r
1190de7b049Sozaki-r e = recvfrom(s, buf, 64, MSG_PEEK,
1200de7b049Sozaki-r (struct sockaddr *)&z, &len);
1210de7b049Sozaki-r if (e == -1)
1220de7b049Sozaki-r err(EXIT_FAILURE, "recvfrom");
1230de7b049Sozaki-r }
1240de7b049Sozaki-r
1250de7b049Sozaki-r /*
1260de7b049Sozaki-r * Keep the socket in the kernel to handle UDP-encapsulated ESP packets.
1270de7b049Sozaki-r */
1280de7b049Sozaki-r pause();
1290de7b049Sozaki-r
1300de7b049Sozaki-r close(s);
1310de7b049Sozaki-r
1320de7b049Sozaki-r return 0;
1330de7b049Sozaki-r }
134