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