summaryrefslogtreecommitdiff
path: root/gssm/src/mktun
diff options
context:
space:
mode:
Diffstat (limited to 'gssm/src/mktun')
-rw-r--r--gssm/src/mktun/Makefile.am7
-rw-r--r--gssm/src/mktun/mktun.c125
2 files changed, 132 insertions, 0 deletions
diff --git a/gssm/src/mktun/Makefile.am b/gssm/src/mktun/Makefile.am
new file mode 100644
index 0000000..95dc50a
--- /dev/null
+++ b/gssm/src/mktun/Makefile.am
@@ -0,0 +1,7 @@
+# $Id: Makefile.am,v 1.3 2007-06-01 05:35:59 jl Exp $
+
+#include $(top_srcdir)/Makefile.common
+
+bin_PROGRAMS = mktun
+mktun_SOURCES = mktun.c
+
diff --git a/gssm/src/mktun/mktun.c b/gssm/src/mktun/mktun.c
new file mode 100644
index 0000000..e22d496
--- /dev/null
+++ b/gssm/src/mktun/mktun.c
@@ -0,0 +1,125 @@
+#include <stdio.h>
+#include <stdlib.h>
+#include <unistd.h>
+#include <string.h>
+#include <libgen.h>
+#include <getopt.h>
+#include <fcntl.h>
+#include <sys/ioctl.h>
+#include <sys/socket.h>
+#include <linux/if_tun.h>
+#include <linux/if.h>
+#include <linux/if_ether.h>
+#include <arpa/inet.h>
+
+
+static struct option long_options[] = {
+ { "delete", no_argument, 0, 'd'},
+ { "help", no_argument, 0, 'h'},
+ { 0, 0, 0, 0}
+};
+
+
+void usage(char *prog) {
+
+ fprintf(stderr, "note: you must be root (except perhaps to delete "
+ "the interface)\n");
+ fprintf(stderr, "usage: %s [--help | -h] | [--delete | -d] "
+ "<interface_name>\n", basename(prog));
+ exit(-1);
+}
+
+
+int main(int argc, char **argv) {
+
+ struct ifreq ifr, ifw;
+ char if_name[IFNAMSIZ], *chan_name = "gsm";
+ int option_index = 0, c, delete_if = 0, persist = 1, fd, sd;
+
+ while((c = getopt_long(argc, argv, "dh?", long_options, &option_index))
+ != -1) {
+ switch(c) {
+ case 'd':
+ delete_if = 1;
+ break;
+ case 'h':
+ case '?':
+ default:
+ usage(argv[0]);
+ break;
+ }
+ }
+
+ if(optind >= argc)
+ usage(argv[0]);
+
+ chan_name = argv[optind];
+
+ if(!delete_if && getuid() && geteuid())
+ usage(argv[0]);
+
+ // construct TUN interface
+ if((fd = open("/dev/net/tun", O_RDWR)) == -1) {
+ perror("open");
+ return -1;
+ }
+
+ memset(&ifr, 0, sizeof(ifr));
+ ifr.ifr_flags = IFF_TAP | IFF_NO_PI;
+ snprintf(ifr.ifr_name, IFNAMSIZ, "%s", chan_name);
+ if(ioctl(fd, TUNSETIFF, (void *)&ifr) == -1) {
+ perror("TUNSETIFF");
+ close(fd);
+ return -1;
+ }
+
+ // save actual name
+ memcpy(if_name, ifr.ifr_name, IFNAMSIZ);
+
+ if(delete_if)
+ persist = 0;
+
+ if(ioctl(fd, TUNSETPERSIST, (void *)persist) == -1) {
+ perror("TUNSETPERSIST");
+ close(fd);
+ return -1;
+ }
+
+ if(delete_if) {
+ close(fd);
+ return 0;
+ }
+
+ // set interface up
+ if((sd = socket(AF_INET, SOCK_DGRAM, 0)) == -1) {
+ perror("socket");
+ close(fd);
+ return -1;
+ }
+
+ // get current flags
+ memset(&ifr, 0, sizeof(ifr));
+ strncpy(ifr.ifr_name, if_name, IFNAMSIZ - 1);
+ if(ioctl(sd, SIOCGIFFLAGS, &ifr) == -1) {
+ perror("SIOCGIFFLAGS");
+ close(sd);
+ close(fd);
+ return -1;
+ }
+
+ // set up
+ memset(&ifw, 0, sizeof(ifw));
+ strncpy(ifw.ifr_name, if_name, IFNAMSIZ - 1);
+ ifw.ifr_flags = ifr.ifr_flags | IFF_UP | IFF_RUNNING;
+ if(ioctl(sd, SIOCSIFFLAGS, &ifw) == -1) {
+ perror("SIOCSIFFLAGS");
+ close(sd);
+ close(fd);
+ return -1;
+ }
+
+ close(sd);
+ close(fd);
+
+ return 0;
+}
personal git repositories of Harald Welte. Your mileage may vary