xref: /minix3/sbin/ifconfig/tunnel.c (revision 90b801219a391518dca4b04b17c88ad3b82b6ad9)
1*90b80121SDavid van Moolenbroek /*	$NetBSD: tunnel.c,v 1.20 2013/10/19 15:59:15 christos Exp $	*/
2*90b80121SDavid van Moolenbroek 
3*90b80121SDavid van Moolenbroek /*
4*90b80121SDavid van Moolenbroek  * Copyright (c) 1983, 1993
5*90b80121SDavid van Moolenbroek  *      The Regents of the University of California.  All rights reserved.
6*90b80121SDavid van Moolenbroek  *
7*90b80121SDavid van Moolenbroek  * Redistribution and use in source and binary forms, with or without
8*90b80121SDavid van Moolenbroek  * modification, are permitted provided that the following conditions
9*90b80121SDavid van Moolenbroek  * are met:
10*90b80121SDavid van Moolenbroek  * 1. Redistributions of source code must retain the above copyright
11*90b80121SDavid van Moolenbroek  *    notice, this list of conditions and the following disclaimer.
12*90b80121SDavid van Moolenbroek  * 2. Redistributions in binary form must reproduce the above copyright
13*90b80121SDavid van Moolenbroek  *    notice, this list of conditions and the following disclaimer in the
14*90b80121SDavid van Moolenbroek  *    documentation and/or other materials provided with the distribution.
15*90b80121SDavid van Moolenbroek  * 3. Neither the name of the University nor the names of its contributors
16*90b80121SDavid van Moolenbroek  *    may be used to endorse or promote products derived from this software
17*90b80121SDavid van Moolenbroek  *    without specific prior written permission.
18*90b80121SDavid van Moolenbroek  *
19*90b80121SDavid van Moolenbroek  * THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND
20*90b80121SDavid van Moolenbroek  * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
21*90b80121SDavid van Moolenbroek  * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
22*90b80121SDavid van Moolenbroek  * ARE DISCLAIMED.  IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE
23*90b80121SDavid van Moolenbroek  * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
24*90b80121SDavid van Moolenbroek  * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
25*90b80121SDavid van Moolenbroek  * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
26*90b80121SDavid van Moolenbroek  * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
27*90b80121SDavid van Moolenbroek  * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
28*90b80121SDavid van Moolenbroek  * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
29*90b80121SDavid van Moolenbroek  * SUCH DAMAGE.
30*90b80121SDavid van Moolenbroek  */
31*90b80121SDavid van Moolenbroek 
32*90b80121SDavid van Moolenbroek #include <sys/cdefs.h>
33*90b80121SDavid van Moolenbroek #ifndef lint
34*90b80121SDavid van Moolenbroek __RCSID("$NetBSD: tunnel.c,v 1.20 2013/10/19 15:59:15 christos Exp $");
35*90b80121SDavid van Moolenbroek #endif /* not lint */
36*90b80121SDavid van Moolenbroek 
37*90b80121SDavid van Moolenbroek #include <sys/param.h>
38*90b80121SDavid van Moolenbroek #include <sys/ioctl.h>
39*90b80121SDavid van Moolenbroek #include <sys/socket.h>
40*90b80121SDavid van Moolenbroek 
41*90b80121SDavid van Moolenbroek #include <net/if.h>
42*90b80121SDavid van Moolenbroek 
43*90b80121SDavid van Moolenbroek #ifdef INET6
44*90b80121SDavid van Moolenbroek #include <netinet/in.h>
45*90b80121SDavid van Moolenbroek #endif
46*90b80121SDavid van Moolenbroek 
47*90b80121SDavid van Moolenbroek #include <ctype.h>
48*90b80121SDavid van Moolenbroek #include <err.h>
49*90b80121SDavid van Moolenbroek #include <errno.h>
50*90b80121SDavid van Moolenbroek #include <netdb.h>
51*90b80121SDavid van Moolenbroek #include <string.h>
52*90b80121SDavid van Moolenbroek #include <stdlib.h>
53*90b80121SDavid van Moolenbroek #include <stdio.h>
54*90b80121SDavid van Moolenbroek #include <util.h>
55*90b80121SDavid van Moolenbroek 
56*90b80121SDavid van Moolenbroek #include "env.h"
57*90b80121SDavid van Moolenbroek #include "extern.h"
58*90b80121SDavid van Moolenbroek #include "parse.h"
59*90b80121SDavid van Moolenbroek #include "util.h"
60*90b80121SDavid van Moolenbroek 
61*90b80121SDavid van Moolenbroek static status_func_t status;
62*90b80121SDavid van Moolenbroek static usage_func_t usage;
63*90b80121SDavid van Moolenbroek static cmdloop_branch_t branch;
64*90b80121SDavid van Moolenbroek 
65*90b80121SDavid van Moolenbroek static void tunnel_constructor(void) __attribute__((constructor));
66*90b80121SDavid van Moolenbroek static int settunnel(prop_dictionary_t, prop_dictionary_t);
67*90b80121SDavid van Moolenbroek static int deletetunnel(prop_dictionary_t, prop_dictionary_t);
68*90b80121SDavid van Moolenbroek static void tunnel_status(prop_dictionary_t, prop_dictionary_t);
69*90b80121SDavid van Moolenbroek 
70*90b80121SDavid van Moolenbroek struct paddr tundst = PADDR_INITIALIZER(&tundst, "tundst", settunnel,
71*90b80121SDavid van Moolenbroek     "tundst", NULL, NULL, NULL, &command_root.pb_parser);
72*90b80121SDavid van Moolenbroek 
73*90b80121SDavid van Moolenbroek struct paddr tunsrc = PADDR_INITIALIZER(&tunsrc, "tunsrc", NULL,
74*90b80121SDavid van Moolenbroek     "tunsrc", NULL, NULL, NULL, &tundst.pa_parser);
75*90b80121SDavid van Moolenbroek 
76*90b80121SDavid van Moolenbroek static const struct kwinst tunnelkw[] = {
77*90b80121SDavid van Moolenbroek 	  {.k_word = "deletetunnel", .k_exec = deletetunnel,
78*90b80121SDavid van Moolenbroek 	   .k_nextparser = &command_root.pb_parser}
79*90b80121SDavid van Moolenbroek 	, {.k_word = "tunnel", .k_nextparser = &tunsrc.pa_parser}
80*90b80121SDavid van Moolenbroek };
81*90b80121SDavid van Moolenbroek 
82*90b80121SDavid van Moolenbroek struct pkw tunnel = PKW_INITIALIZER(&tunnel, "tunnel", NULL, NULL,
83*90b80121SDavid van Moolenbroek     tunnelkw, __arraycount(tunnelkw), NULL);
84*90b80121SDavid van Moolenbroek 
85*90b80121SDavid van Moolenbroek static int
settunnel(prop_dictionary_t env,prop_dictionary_t oenv)86*90b80121SDavid van Moolenbroek settunnel(prop_dictionary_t env, prop_dictionary_t oenv)
87*90b80121SDavid van Moolenbroek {
88*90b80121SDavid van Moolenbroek 	const struct paddr_prefix *srcpfx, *dstpfx;
89*90b80121SDavid van Moolenbroek 	struct if_laddrreq req;
90*90b80121SDavid van Moolenbroek 	prop_data_t srcdata, dstdata;
91*90b80121SDavid van Moolenbroek 
92*90b80121SDavid van Moolenbroek 	srcdata = (prop_data_t)prop_dictionary_get(env, "tunsrc");
93*90b80121SDavid van Moolenbroek 	dstdata = (prop_data_t)prop_dictionary_get(env, "tundst");
94*90b80121SDavid van Moolenbroek 
95*90b80121SDavid van Moolenbroek 	if (srcdata == NULL || dstdata == NULL) {
96*90b80121SDavid van Moolenbroek 		warnx("%s.%d", __func__, __LINE__);
97*90b80121SDavid van Moolenbroek 		errno = ENOENT;
98*90b80121SDavid van Moolenbroek 		return -1;
99*90b80121SDavid van Moolenbroek 	}
100*90b80121SDavid van Moolenbroek 
101*90b80121SDavid van Moolenbroek 	srcpfx = prop_data_data_nocopy(srcdata);
102*90b80121SDavid van Moolenbroek 	dstpfx = prop_data_data_nocopy(dstdata);
103*90b80121SDavid van Moolenbroek 
104*90b80121SDavid van Moolenbroek 	if (srcpfx->pfx_addr.sa_family != dstpfx->pfx_addr.sa_family)
105*90b80121SDavid van Moolenbroek 		errx(EXIT_FAILURE,
106*90b80121SDavid van Moolenbroek 		    "source and destination address families do not match");
107*90b80121SDavid van Moolenbroek 
108*90b80121SDavid van Moolenbroek 	memset(&req, 0, sizeof(req));
109*90b80121SDavid van Moolenbroek 	memcpy(&req.addr, &srcpfx->pfx_addr,
110*90b80121SDavid van Moolenbroek 	    MIN(sizeof(req.addr), srcpfx->pfx_addr.sa_len));
111*90b80121SDavid van Moolenbroek 	memcpy(&req.dstaddr, &dstpfx->pfx_addr,
112*90b80121SDavid van Moolenbroek 	    MIN(sizeof(req.dstaddr), dstpfx->pfx_addr.sa_len));
113*90b80121SDavid van Moolenbroek 
114*90b80121SDavid van Moolenbroek #ifdef INET6
115*90b80121SDavid van Moolenbroek 	if (req.addr.ss_family == AF_INET6) {
116*90b80121SDavid van Moolenbroek 		struct sockaddr_in6 *s6, *d;
117*90b80121SDavid van Moolenbroek 
118*90b80121SDavid van Moolenbroek 		s6 = (struct sockaddr_in6 *)&req.addr;
119*90b80121SDavid van Moolenbroek 		d = (struct sockaddr_in6 *)&req.dstaddr;
120*90b80121SDavid van Moolenbroek 		if (s6->sin6_scope_id != d->sin6_scope_id) {
121*90b80121SDavid van Moolenbroek 			errx(EXIT_FAILURE, "scope mismatch");
122*90b80121SDavid van Moolenbroek 			/* NOTREACHED */
123*90b80121SDavid van Moolenbroek 		}
124*90b80121SDavid van Moolenbroek 		if (IN6_IS_ADDR_MULTICAST(&d->sin6_addr) ||
125*90b80121SDavid van Moolenbroek 		    IN6_IS_ADDR_MULTICAST(&s6->sin6_addr))
126*90b80121SDavid van Moolenbroek 			errx(EXIT_FAILURE, "tunnel src/dst is multicast");
127*90b80121SDavid van Moolenbroek 		/* embed scopeid */
128*90b80121SDavid van Moolenbroek 		inet6_putscopeid(s6, INET6_IS_ADDR_LINKLOCAL);
129*90b80121SDavid van Moolenbroek 		inet6_putscopeid(d, INET6_IS_ADDR_LINKLOCAL);
130*90b80121SDavid van Moolenbroek 	}
131*90b80121SDavid van Moolenbroek #endif /* INET6 */
132*90b80121SDavid van Moolenbroek 
133*90b80121SDavid van Moolenbroek 	if (direct_ioctl(env, SIOCSLIFPHYADDR, &req) == -1)
134*90b80121SDavid van Moolenbroek 		warn("SIOCSLIFPHYADDR");
135*90b80121SDavid van Moolenbroek 	return 0;
136*90b80121SDavid van Moolenbroek }
137*90b80121SDavid van Moolenbroek 
138*90b80121SDavid van Moolenbroek static int
deletetunnel(prop_dictionary_t env,prop_dictionary_t oenv)139*90b80121SDavid van Moolenbroek deletetunnel(prop_dictionary_t env, prop_dictionary_t oenv)
140*90b80121SDavid van Moolenbroek {
141*90b80121SDavid van Moolenbroek 	if (indirect_ioctl(env, SIOCDIFPHYADDR, NULL) == -1)
142*90b80121SDavid van Moolenbroek 		err(EXIT_FAILURE, "SIOCDIFPHYADDR");
143*90b80121SDavid van Moolenbroek 	return 0;
144*90b80121SDavid van Moolenbroek }
145*90b80121SDavid van Moolenbroek 
146*90b80121SDavid van Moolenbroek static void
tunnel_status(prop_dictionary_t env,prop_dictionary_t oenv)147*90b80121SDavid van Moolenbroek tunnel_status(prop_dictionary_t env, prop_dictionary_t oenv)
148*90b80121SDavid van Moolenbroek {
149*90b80121SDavid van Moolenbroek 	char dstserv[sizeof(",65535")];
150*90b80121SDavid van Moolenbroek 	char srcserv[sizeof(",65535")];
151*90b80121SDavid van Moolenbroek 	char psrcaddr[NI_MAXHOST];
152*90b80121SDavid van Moolenbroek 	char pdstaddr[NI_MAXHOST];
153*90b80121SDavid van Moolenbroek 	const int niflag = Nflag ? 0 : (NI_NUMERICHOST|NI_NUMERICSERV);
154*90b80121SDavid van Moolenbroek 	struct if_laddrreq req;
155*90b80121SDavid van Moolenbroek 	const struct afswtch *afp;
156*90b80121SDavid van Moolenbroek 
157*90b80121SDavid van Moolenbroek 	psrcaddr[0] = pdstaddr[0] = '\0';
158*90b80121SDavid van Moolenbroek 
159*90b80121SDavid van Moolenbroek 	memset(&req, 0, sizeof(req));
160*90b80121SDavid van Moolenbroek 	if (direct_ioctl(env, SIOCGLIFPHYADDR, &req) == -1)
161*90b80121SDavid van Moolenbroek 		return;
162*90b80121SDavid van Moolenbroek 	afp = lookup_af_bynum(req.addr.ss_family);
163*90b80121SDavid van Moolenbroek #ifdef INET6
164*90b80121SDavid van Moolenbroek 	if (req.addr.ss_family == AF_INET6)
165*90b80121SDavid van Moolenbroek 		inet6_getscopeid((struct sockaddr_in6 *)&req.addr,
166*90b80121SDavid van Moolenbroek 		    INET6_IS_ADDR_LINKLOCAL);
167*90b80121SDavid van Moolenbroek #endif /* INET6 */
168*90b80121SDavid van Moolenbroek 	getnameinfo((struct sockaddr *)&req.addr, req.addr.ss_len,
169*90b80121SDavid van Moolenbroek 	    psrcaddr, sizeof(psrcaddr), &srcserv[1], sizeof(srcserv) - 1,
170*90b80121SDavid van Moolenbroek 	    niflag);
171*90b80121SDavid van Moolenbroek 
172*90b80121SDavid van Moolenbroek #ifdef INET6
173*90b80121SDavid van Moolenbroek 	if (req.dstaddr.ss_family == AF_INET6)
174*90b80121SDavid van Moolenbroek 		inet6_getscopeid((struct sockaddr_in6 *)&req.dstaddr,
175*90b80121SDavid van Moolenbroek 		    INET6_IS_ADDR_LINKLOCAL);
176*90b80121SDavid van Moolenbroek #endif
177*90b80121SDavid van Moolenbroek 	getnameinfo((struct sockaddr *)&req.dstaddr, req.dstaddr.ss_len,
178*90b80121SDavid van Moolenbroek 	    pdstaddr, sizeof(pdstaddr), &dstserv[1], sizeof(dstserv) - 1,
179*90b80121SDavid van Moolenbroek 	    niflag);
180*90b80121SDavid van Moolenbroek 
181*90b80121SDavid van Moolenbroek 	srcserv[0] = (strcmp(&srcserv[1], "0") == 0) ? '\0' : ',';
182*90b80121SDavid van Moolenbroek 	dstserv[0] = (strcmp(&dstserv[1], "0") == 0) ? '\0' : ',';
183*90b80121SDavid van Moolenbroek 
184*90b80121SDavid van Moolenbroek 	printf("\ttunnel %s %s%s --> %s%s\n", afp ? afp->af_name : "???",
185*90b80121SDavid van Moolenbroek 	    psrcaddr, srcserv, pdstaddr, dstserv);
186*90b80121SDavid van Moolenbroek }
187*90b80121SDavid van Moolenbroek 
188*90b80121SDavid van Moolenbroek static void
tunnel_usage(prop_dictionary_t env)189*90b80121SDavid van Moolenbroek tunnel_usage(prop_dictionary_t env)
190*90b80121SDavid van Moolenbroek {
191*90b80121SDavid van Moolenbroek 	fprintf(stderr,
192*90b80121SDavid van Moolenbroek 	    "\t[ [ af ] tunnel src_addr dest_addr ] [ deletetunnel ]\n");
193*90b80121SDavid van Moolenbroek }
194*90b80121SDavid van Moolenbroek 
195*90b80121SDavid van Moolenbroek static void
tunnel_constructor(void)196*90b80121SDavid van Moolenbroek tunnel_constructor(void)
197*90b80121SDavid van Moolenbroek {
198*90b80121SDavid van Moolenbroek 	cmdloop_branch_init(&branch, &tunnel.pk_parser);
199*90b80121SDavid van Moolenbroek 	register_cmdloop_branch(&branch);
200*90b80121SDavid van Moolenbroek 	status_func_init(&status, tunnel_status);
201*90b80121SDavid van Moolenbroek 	usage_func_init(&usage, tunnel_usage);
202*90b80121SDavid van Moolenbroek 	register_status(&status);
203*90b80121SDavid van Moolenbroek 	register_usage(&usage);
204*90b80121SDavid van Moolenbroek }
205