11.2Sknakahar/*	$NetBSD: natt_terminator.c,v 1.2 2018/11/22 04:51:41 knakahara Exp $	*/
21.1Sozaki
31.1Sozaki/*-
41.1Sozaki * Copyright (c) 2017 Internet Initiative Japan Inc.
51.1Sozaki * All rights reserved.
61.1Sozaki *
71.1Sozaki * Redistribution and use in source and binary forms, with or without
81.1Sozaki * modification, are permitted provided that the following conditions
91.1Sozaki * are met:
101.1Sozaki * 1. Redistributions of source code must retain the above copyright
111.1Sozaki *    notice, this list of conditions and the following disclaimer.
121.1Sozaki * 2. Redistributions in binary form must reproduce the above copyright
131.1Sozaki *    notice, this list of conditions and the following disclaimer in the
141.1Sozaki *    documentation and/or other materials provided with the distribution.
151.1Sozaki *
161.1Sozaki * THIS SOFTWARE IS PROVIDED BY THE NETBSD FOUNDATION, INC. AND CONTRIBUTORS
171.1Sozaki * ``AS IS'' AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED
181.1Sozaki * TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR
191.1Sozaki * PURPOSE ARE DISCLAIMED.  IN NO EVENT SHALL THE FOUNDATION OR CONTRIBUTORS
201.1Sozaki * BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
211.1Sozaki * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
221.1Sozaki * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
231.1Sozaki * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
241.1Sozaki * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
251.1Sozaki * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
261.1Sozaki * POSSIBILITY OF SUCH DAMAGE.
271.1Sozaki */
281.1Sozaki
291.1Sozaki#include <sys/types.h>
301.1Sozaki#include <sys/socket.h>
311.1Sozaki#include <sys/wait.h>
321.1Sozaki#include <sys/time.h>
331.1Sozaki
341.1Sozaki#include <netinet/in.h>
351.1Sozaki#include <netinet/udp.h>
361.1Sozaki
371.1Sozaki#include <stdio.h>
381.1Sozaki#include <err.h>
391.1Sozaki#include <netdb.h>
401.1Sozaki#include <string.h>
411.1Sozaki#include <stdlib.h>
421.1Sozaki#include <unistd.h>
431.1Sozaki
441.2Sknakaharstatic void
451.2Sknakaharusage(void)
461.2Sknakahar{
471.2Sknakahar	const char *prog = "natt_terminator";
481.2Sknakahar
491.2Sknakahar	fprintf(stderr, "Usage: %s [-46] <addr> <port>\n", prog);
501.2Sknakahar}
511.2Sknakahar
521.1Sozakiint
531.1Sozakimain(int argc, char **argv)
541.1Sozaki{
551.1Sozaki	struct addrinfo hints;
561.1Sozaki	struct addrinfo *res;
571.1Sozaki	int s, e;
581.1Sozaki	const char *addr, *port;
591.1Sozaki	int option;
601.2Sknakahar	int c, family = AF_INET;
611.2Sknakahar
621.2Sknakahar	while ((c = getopt(argc, argv, "46")) != -1) {
631.2Sknakahar		switch (c) {
641.2Sknakahar		case '4':
651.2Sknakahar			family = AF_INET;
661.2Sknakahar			break;
671.2Sknakahar		case '6':
681.2Sknakahar			family = AF_INET6;
691.2Sknakahar			break;
701.2Sknakahar		default:
711.2Sknakahar			usage();
721.2Sknakahar			return 1;
731.2Sknakahar		}
741.2Sknakahar	}
751.2Sknakahar	argc -= optind;
761.2Sknakahar	argv += optind;
771.1Sozaki
781.2Sknakahar	if (argc != 2) {
791.2Sknakahar		usage();
801.1Sozaki		return 1;
811.1Sozaki	}
821.1Sozaki
831.2Sknakahar	addr = argv[0];
841.2Sknakahar	port = argv[1];
851.1Sozaki
861.1Sozaki	memset(&hints, 0, sizeof(hints));
871.2Sknakahar	hints.ai_family = family;
881.1Sozaki	hints.ai_socktype = SOCK_DGRAM;
891.1Sozaki	hints.ai_protocol = IPPROTO_UDP;
901.1Sozaki	hints.ai_flags = 0;
911.1Sozaki
921.1Sozaki	e = getaddrinfo(addr, port, &hints, &res);
931.1Sozaki	if (e != 0)
941.1Sozaki		errx(EXIT_FAILURE, "getaddrinfo failed: %s", gai_strerror(e));
951.1Sozaki
961.1Sozaki	s = socket(res->ai_family, res->ai_socktype, res->ai_protocol);
971.1Sozaki	if (s == -1)
981.1Sozaki		err(EXIT_FAILURE, "socket");
991.1Sozaki
1001.1Sozaki	/*
1011.1Sozaki	 * Set the option to tell the kernel that the socket can handle
1021.1Sozaki	 * UDP-encapsulated ESP packets for NAT-T.
1031.1Sozaki	 */
1041.1Sozaki	option = UDP_ENCAP_ESPINUDP;
1051.1Sozaki	e = setsockopt(s, IPPROTO_UDP, UDP_ENCAP, &option, sizeof(option));
1061.1Sozaki	if (e == -1)
1071.1Sozaki		err(EXIT_FAILURE, "setsockopt(UDP_ENCAP)");
1081.1Sozaki
1091.1Sozaki	e = bind(s, res->ai_addr, res->ai_addrlen);
1101.1Sozaki	if (e == -1)
1111.1Sozaki		err(EXIT_FAILURE, "bind");
1121.1Sozaki
1131.1Sozaki	/* Receiving a packet make the NAPT create a mapping. */
1141.1Sozaki	{
1151.1Sozaki		char buf[64];
1161.1Sozaki		struct sockaddr_storage z;
1171.1Sozaki		socklen_t len = sizeof(z);
1181.1Sozaki
1191.1Sozaki		e = recvfrom(s, buf, 64, MSG_PEEK,
1201.1Sozaki		    (struct sockaddr *)&z, &len);
1211.1Sozaki		if (e == -1)
1221.1Sozaki			err(EXIT_FAILURE, "recvfrom");
1231.1Sozaki	}
1241.1Sozaki
1251.1Sozaki	/*
1261.1Sozaki	 * Keep the socket in the kernel to handle UDP-encapsulated ESP packets.
1271.1Sozaki	 */
1281.1Sozaki	pause();
1291.1Sozaki
1301.1Sozaki	close(s);
1311.1Sozaki
1321.1Sozaki	return 0;
1331.1Sozaki}
134