From 484920dab2064a18ca00f7b3335ae0417c8b4034 Mon Sep 17 00:00:00 2001 From: Daniel Hokka Zakrisson Date: Thu, 28 Feb 2008 23:28:31 +0000 Subject: [PATCH] Add tunctl. git-svn-id: http://svn.linux-vserver.org/svn/util-vserver/trunk@2687 94cd875c-1c1d-0410-91d2-eb244daf1a30 --- contrib/manifest.dat.pathsubst | 1 + ensc_wrappers/wrappers-ioctl.hc | 5 + src/Makefile-files | 8 +- src/tunctl.c | 226 ++++++++++++++++++++++++++++++++++++++++ 4 files changed, 239 insertions(+), 1 deletion(-) create mode 100644 src/tunctl.c diff --git a/contrib/manifest.dat.pathsubst b/contrib/manifest.dat.pathsubst index 22c9093..cf49623 100644 --- a/contrib/manifest.dat.pathsubst +++ b/contrib/manifest.dat.pathsubst @@ -69,6 +69,7 @@ base @PKGLIBDIR@/save_ctxinfo base @PKGLIBDIR@/secure-mount base @PKGLIBDIR@/sigexec base @PKGLIBDIR@/start-vservers +base @PKGLIBDIR@/tunctl build @PKGLIBDIR@/vapt-get-worker build @PKGLIBDIR@/vyum-worker build @PKGLIBDIR@/vpkg diff --git a/ensc_wrappers/wrappers-ioctl.hc b/ensc_wrappers/wrappers-ioctl.hc index 7656bf1..710d956 100644 --- a/ensc_wrappers/wrappers-ioctl.hc +++ b/ensc_wrappers/wrappers-ioctl.hc @@ -27,3 +27,8 @@ Eioctl(int fd, int request, void *p) FatalErrnoError(res<0, "ioctl()"); } +#define EioctlD(fd, request, p) \ + do { \ + int res = ioctl(fd, request, p); \ + FatalErrnoError(res<0, "ioctl(" #request ")"); \ + } while (0) diff --git a/src/Makefile-files b/src/Makefile-files index 33e17cb..c24d11a 100644 --- a/src/Makefile-files +++ b/src/Makefile-files @@ -84,7 +84,8 @@ DIETPROGS += src/chcontext-compat \ src/h2ext \ src/vtag \ src/vspace \ - src/vmemctrl + src/vmemctrl \ + src/tunctl if ENSC_CAN_CRYPTO_WITH_DIETLIBC DIETPROGS += src/vhashify @@ -123,6 +124,7 @@ pkglib_PROGRAMS += src/capchroot \ src/chbind-compat \ src/vsysctl \ src/h2ext \ + src/tunctl \ $(src_pkglib_C99_X_PROGS) \ $(src_pkglib_CXX_X_PROGS) @@ -361,6 +363,10 @@ src_vmemctrl_SOURCES = src/vmemctrl.c src_vmemctrl_LDADD = $(VSERVER_LDADDS) $(LIBINTERNAL) src_vmemctrl_LDFLAGS = $(VSERVER_LDFLGS) +src_tunctl_SOURCES = src/tunctl.c +src_tunctl_LDADD = $(VSERVER_LDADDS) $(LIBINTERNAL) +src_tunctl_LDFLAGS = $(VSERVER_LDFLGS) + EXTRA_PROGRAMS += $(src_sbin_CXX_PROGS) $(src_pkglib_CXX_PROGS) TESTS_ENVIRONMENT += srctestsuitedir=$(top_builddir)/src/testsuite diff --git a/src/tunctl.c b/src/tunctl.c new file mode 100644 index 0000000..ba695b5 --- /dev/null +++ b/src/tunctl.c @@ -0,0 +1,226 @@ +// $Id$ --*- c -*-- + +// Copyright (C) 2008 Daniel Hokka Zakrisson +// +// This program is free software; you can redistribute it and/or modify +// it under the terms of the GNU General Public License as published by +// the Free Software Foundation; version 2 of the License. +// +// This program is distributed in the hope that it will be useful, +// but WITHOUT ANY WARRANTY; without even the implied warranty of +// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +// GNU General Public License for more details. +// +// You should have received a copy of the GNU General Public License +// along with this program; if not, write to the Free Software +// Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. + + +#ifdef HAVE_CONFIG_H +# include +#endif + +#include "util.h" + +#include + +#include +#include +#include +#include +#include +#include +#include + +/* Make sure we have the necessary ioctls */ +#ifndef TUNSETGROUP +# define TUNSETGROUP _IOW('T', 206, int) +#endif +#ifndef TUNSETNID +# define TUNSETNID _IOW('T', 215, int) +#endif + +#define ENSC_WRAPPERS_PREFIX "tunctl: " +#define ENSC_WRAPPERS_UNISTD 1 +#define ENSC_WRAPPERS_VSERVER 1 +#define ENSC_WRAPPERS_FCNTL 1 +#define ENSC_WRAPPERS_IOCTL 1 +#include + + +#define CMD_HELP 0x1000 +#define CMD_VERSION 0x1001 +#define CMD_NID 0x0001 +#define CMD_DEVICE 0x0002 +#define CMD_PERSIST 0x0004 +#define CMD_NOPERSIST 0x0008 +#define CMD_CSUM 0x0010 +#define CMD_NOCSUM 0x0020 +#define CMD_UID 0x0040 +#define CMD_GID 0x0080 +#define CMD_LINKTYPE 0x0100 +#define CMD_TUN 0x0200 +#define CMD_TAP 0x0400 + +int wrapper_exit_code = 255; + +struct option const +CMDLINE_OPTIONS[] = { + { "help", no_argument, 0, CMD_HELP }, + { "version", no_argument, 0, CMD_VERSION }, + { "nid", required_argument, 0, CMD_NID }, + { "device", required_argument, 0, CMD_DEVICE }, + { "persist", no_argument, 0, CMD_PERSIST }, + { "~persist", no_argument, 0, CMD_NOPERSIST }, + { "checksum", no_argument, 0, CMD_CSUM }, + { "~checksum", no_argument, 0, CMD_NOCSUM }, + { "uid", required_argument, 0, CMD_UID }, + { "gid", required_argument, 0, CMD_GID }, + { "linktype", required_argument, 0, CMD_LINKTYPE }, + { "tun", no_argument, 0, CMD_TUN }, + { "tap", no_argument, 0, CMD_TAP }, + {0,0,0,0} +}; + +struct Arguments { + unsigned int set; + nid_t nid; + char *device; + unsigned persist : 1; + unsigned checksum : 1; + uid_t uid; + gid_t gid; + int linktype; + int type; +}; + +static void +showHelp(int fd, char const *cmd, int res) +{ + WRITE_MSG(fd, "Usage: "); + WRITE_STR(fd, cmd); + WRITE_MSG(fd, + " {--tun|--tap}\n" + " [--persist|--~persist] [--checksum|--~checksum]\n" + " [--nid ] [--uid ] [--gid ] [--linktype ]\n" + " ...\n" + "\n" + "Please report bugs to " PACKAGE_BUGREPORT "\n"); + + exit(res); +} + +static void +showVersion() +{ + WRITE_MSG(1, + "tunctl " VERSION " -- controls TUN/TAP devices\n" + "This program is part of " PACKAGE_STRING "\n\n" + "Copyright (C) 2008 Daniel Hokka Zakrisson\n" + VERSION_COPYRIGHT_DISCLAIMER); + exit(0); +} + +static void +doTunctl(struct Arguments *args, char *interface) +{ + int fd; + struct ifreq ifr; + + fd = EopenD(args->device, O_RDWR, 0); + + strncpy(ifr.ifr_name, interface, IFNAMSIZ); + ifr.ifr_name[IFNAMSIZ-1] = '\0'; + ifr.ifr_flags = args->type; + EioctlD(fd, TUNSETIFF, &ifr); + + if (args->set & (CMD_PERSIST|CMD_NOPERSIST)) + EioctlD(fd, TUNSETPERSIST, (void *) (long) args->persist); + if (args->set & (CMD_CSUM|CMD_NOCSUM)) + EioctlD(fd, TUNSETNOCSUM, (void *) (long) !args->checksum); + if (args->set & CMD_UID) + EioctlD(fd, TUNSETOWNER, (void *) (long) args->uid); + if (args->set & CMD_GID) + EioctlD(fd, TUNSETGROUP, (void *) (long) args->gid); + if (args->set & CMD_NID) + EioctlD(fd, TUNSETNID, (void *) (long) args->nid); + if (args->set & CMD_LINKTYPE) + EioctlD(fd, TUNSETLINK, (void *) (long) args->linktype); + + close(fd); +} + +int main(int argc, char *argv[]) +{ + struct Arguments args = { + .set = 0, + .nid = VC_NOCTX, + .device = "/dev/net/tun", + .persist = 0, + .checksum = 0, + .uid = -1, + .gid = -1, + .linktype = -1, + .type = IFF_TUN, + }; + char **interface; + + while (1) { + int c = getopt_long(argc, argv, "+", CMDLINE_OPTIONS, 0); + signed long tmp = 0; + if (c==-1) break; + + switch (c) { + case CMD_HELP : showHelp(1, argv[0], 0); + case CMD_VERSION : showVersion(); + + case CMD_NID : args.nid = Evc_nidopt2nid(optarg, true); break; + case CMD_DEVICE : args.device = optarg; break; + case CMD_PERSIST : args.persist = 1; break; + case CMD_NOPERSIST: args.persist = 0; break; + case CMD_CSUM : args.checksum = 1; break; + case CMD_NOCSUM : args.checksum = 0; break; + case CMD_TUN : args.type = IFF_TUN; break; + case CMD_TAP : args.type = IFF_TAP; break; + case CMD_UID : + if (!isNumber(optarg, &tmp, true)) { + WRITE_MSG(2, "Uid '"); + WRITE_STR(2, optarg); + WRITE_MSG(2, "' is not an integer.\n"); + } + args.uid = (uid_t) tmp; + break; + case CMD_GID : + if (!isNumber(optarg, &tmp, true)) { + WRITE_MSG(2, "Gid '"); + WRITE_STR(2, optarg); + WRITE_MSG(2, "' is not an integer.\n"); + } + args.gid = (gid_t) tmp; + break; + case CMD_LINKTYPE : + if (!isNumber(optarg, &tmp, true)) { + WRITE_MSG(2, "Link-type '"); + WRITE_STR(2, optarg); + WRITE_STR(2, "' is not an integer.\n"); + } + args.linktype = (int) tmp; + break; + + default : + WRITE_MSG(2, "Try '"); + WRITE_STR(2, argv[0]); + WRITE_MSG(2, " --help' for more information.\n"); + return 255; + break; + } + + args.set |= c; + } + + for (interface = argv + optind; *interface; interface++) { + doTunctl(&args, *interface); + } + + return EXIT_SUCCESS; +} -- 1.8.1.5