119dc6445SKristof Provost /*-
219dc6445SKristof Provost * Copyright 2013 Ermal Luci
319dc6445SKristof Provost * All rights reserved.
419dc6445SKristof Provost *
519dc6445SKristof Provost * Redistribution and use in source and binary forms, with or without
619dc6445SKristof Provost * modification, are permitted provided that the following conditions
719dc6445SKristof Provost * are met:
819dc6445SKristof Provost * 1. Redistributions of source code must retain the above copyright
919dc6445SKristof Provost * notice, this list of conditions and the following disclaimer.
1019dc6445SKristof Provost * 2. Redistributions in binary form must reproduce the above copyright
1119dc6445SKristof Provost * notice, this list of conditions and the following disclaimer in the
1219dc6445SKristof Provost * documentation and/or other materials provided with the distribution.
1319dc6445SKristof Provost *
1419dc6445SKristof Provost * THIS SOFTWARE IS PROVIDED BY WASABI SYSTEMS, INC. ``AS IS'' AND
1519dc6445SKristof Provost * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED
1619dc6445SKristof Provost * TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR
1719dc6445SKristof Provost * PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL WASABI SYSTEMS, INC
1819dc6445SKristof Provost * BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
1919dc6445SKristof Provost * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
2019dc6445SKristof Provost * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
2119dc6445SKristof Provost * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
2219dc6445SKristof Provost * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
2319dc6445SKristof Provost * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
2419dc6445SKristof Provost * POSSIBILITY OF SUCH DAMAGE.
2519dc6445SKristof Provost */
2619dc6445SKristof Provost
2719dc6445SKristof Provost #include <sys/param.h>
2819dc6445SKristof Provost #include <sys/ioctl.h>
2919dc6445SKristof Provost #include <sys/socket.h>
3019dc6445SKristof Provost #include <sys/sockio.h>
3119dc6445SKristof Provost
3219dc6445SKristof Provost #include <stdlib.h>
3319dc6445SKristof Provost #include <unistd.h>
3419dc6445SKristof Provost
3519dc6445SKristof Provost #include <net/ethernet.h>
3619dc6445SKristof Provost #include <net/if.h>
3719dc6445SKristof Provost #include <net/route.h>
3819dc6445SKristof Provost
3919dc6445SKristof Provost #include <netinet/in.h>
4019dc6445SKristof Provost #include <sys/mbuf.h>
4119dc6445SKristof Provost #include <net/if_stf.h>
4219dc6445SKristof Provost #include <arpa/inet.h>
4319dc6445SKristof Provost
4419dc6445SKristof Provost #include <ctype.h>
4519dc6445SKristof Provost #include <stdio.h>
4619dc6445SKristof Provost #include <string.h>
4719dc6445SKristof Provost #include <stdlib.h>
4819dc6445SKristof Provost #include <unistd.h>
4919dc6445SKristof Provost #include <err.h>
5019dc6445SKristof Provost #include <errno.h>
5119dc6445SKristof Provost
5219dc6445SKristof Provost #include "ifconfig.h"
5319dc6445SKristof Provost
5419dc6445SKristof Provost static int
do_cmd(if_ctx * ctx,u_long op,void * arg,size_t argsize,int set)556e3a9d7fSAlexander V. Chernikov do_cmd(if_ctx *ctx, u_long op, void *arg, size_t argsize, int set)
5619dc6445SKristof Provost {
57*7fa282e6SAlexander V. Chernikov struct ifdrv ifd = {};
5819dc6445SKristof Provost
59*7fa282e6SAlexander V. Chernikov strlcpy(ifd.ifd_name, ctx->ifname, sizeof(ifd.ifd_name));
6019dc6445SKristof Provost ifd.ifd_cmd = op;
6119dc6445SKristof Provost ifd.ifd_len = argsize;
6219dc6445SKristof Provost ifd.ifd_data = arg;
6319dc6445SKristof Provost
646e3a9d7fSAlexander V. Chernikov return (ioctl_ctx(ctx, set ? SIOCSDRVSPEC : SIOCGDRVSPEC, &ifd));
6519dc6445SKristof Provost }
6619dc6445SKristof Provost
6719dc6445SKristof Provost static void
stf_status(if_ctx * ctx)686e3a9d7fSAlexander V. Chernikov stf_status(if_ctx *ctx)
6919dc6445SKristof Provost {
7019dc6445SKristof Provost struct stfv4args param;
7119dc6445SKristof Provost
726e3a9d7fSAlexander V. Chernikov if (do_cmd(ctx, STF6RD_GV4NET, ¶m, sizeof(param), 0) < 0)
7319dc6445SKristof Provost return;
7419dc6445SKristof Provost
7519dc6445SKristof Provost printf("\tv4net %s/%d -> ", inet_ntoa(param.srcv4_addr),
7619dc6445SKristof Provost param.v4_prefixlen ? param.v4_prefixlen : 32);
7719dc6445SKristof Provost printf("tv4br %s\n", inet_ntoa(param.braddr));
7819dc6445SKristof Provost }
7919dc6445SKristof Provost
8019dc6445SKristof Provost static void
setstf_br(if_ctx * ctx,const char * val,int d __unused)816e3a9d7fSAlexander V. Chernikov setstf_br(if_ctx *ctx, const char *val, int d __unused)
8219dc6445SKristof Provost {
8319dc6445SKristof Provost struct stfv4args req;
8419dc6445SKristof Provost struct sockaddr_in sin;
8519dc6445SKristof Provost
8619dc6445SKristof Provost memset(&req, 0, sizeof(req));
8719dc6445SKristof Provost
8819dc6445SKristof Provost sin.sin_len = sizeof(sin);
8919dc6445SKristof Provost sin.sin_family = AF_INET;
9019dc6445SKristof Provost
9119dc6445SKristof Provost if (!inet_aton(val, &sin.sin_addr))
9219dc6445SKristof Provost errx(1, "%s: bad value", val);
9319dc6445SKristof Provost
9419dc6445SKristof Provost req.braddr = sin.sin_addr;
956e3a9d7fSAlexander V. Chernikov if (do_cmd(ctx, STF6RD_SBR, &req, sizeof(req), 1) < 0)
9619dc6445SKristof Provost err(1, "STF6RD_SBR%s", val);
9719dc6445SKristof Provost }
9819dc6445SKristof Provost
9919dc6445SKristof Provost static void
setstf_set(if_ctx * ctx,const char * val,int d __unused)1006e3a9d7fSAlexander V. Chernikov setstf_set(if_ctx *ctx, const char *val, int d __unused)
10119dc6445SKristof Provost {
10219dc6445SKristof Provost struct stfv4args req;
10319dc6445SKristof Provost struct sockaddr_in sin;
10419dc6445SKristof Provost const char *errstr;
10519dc6445SKristof Provost char *p = NULL;
10619dc6445SKristof Provost
10719dc6445SKristof Provost memset(&req, 0, sizeof(req));
10819dc6445SKristof Provost
10919dc6445SKristof Provost sin.sin_len = sizeof(sin);
11019dc6445SKristof Provost sin.sin_family = AF_INET;
11119dc6445SKristof Provost
11219dc6445SKristof Provost p = strrchr(val, '/');
11319dc6445SKristof Provost if (p == NULL)
11419dc6445SKristof Provost errx(2, "Wrong argument given");
11519dc6445SKristof Provost
11619dc6445SKristof Provost *p = '\0';
11719dc6445SKristof Provost req.v4_prefixlen = (int)strtonum(p + 1, 0, 32, &errstr);
11819dc6445SKristof Provost if (errstr != NULL || req.v4_prefixlen == 0) {
11919dc6445SKristof Provost *p = '/';
12019dc6445SKristof Provost errx(1, "%s: bad value (prefix length %s)", val, errstr);
12119dc6445SKristof Provost }
12219dc6445SKristof Provost
12319dc6445SKristof Provost if (!inet_aton(val, &sin.sin_addr))
12419dc6445SKristof Provost errx(1, "%s: bad value", val);
12519dc6445SKristof Provost
12619dc6445SKristof Provost memcpy(&req.srcv4_addr, &sin.sin_addr, sizeof(req.srcv4_addr));
1276e3a9d7fSAlexander V. Chernikov if (do_cmd(ctx, STF6RD_SV4NET, &req, sizeof(req), 1) < 0)
12819dc6445SKristof Provost err(1, "STF6RD_SV4NET %s", val);
12919dc6445SKristof Provost }
13019dc6445SKristof Provost
13119dc6445SKristof Provost static struct cmd stf_cmds[] = {
13219dc6445SKristof Provost DEF_CMD_ARG("stfv4net", setstf_set),
13319dc6445SKristof Provost DEF_CMD_ARG("stfv4br", setstf_br),
13419dc6445SKristof Provost };
13519dc6445SKristof Provost
13619dc6445SKristof Provost static struct afswtch af_stf = {
13719dc6445SKristof Provost .af_name = "af_stf",
13819dc6445SKristof Provost .af_af = AF_UNSPEC,
13919dc6445SKristof Provost .af_other_status = stf_status,
14019dc6445SKristof Provost };
14119dc6445SKristof Provost
14219dc6445SKristof Provost static __constructor void
stf_ctor(void)14319dc6445SKristof Provost stf_ctor(void)
14419dc6445SKristof Provost {
14544cd85d4SAlexander V. Chernikov for (size_t i = 0; i < nitems(stf_cmds); i++)
14619dc6445SKristof Provost cmd_register(&stf_cmds[i]);
14719dc6445SKristof Provost af_register(&af_stf);
14819dc6445SKristof Provost }
149