源码:

package main

import (
"flag"
"fmt"
"github.com/pkg/errors"
"net"
"os"
"syscall"
"unsafe"
)
var (
HostName, _ = os.Hostname()
ETH_P_ARP = 0x0806
AF_INET = int32()
AF_INET6 = int32()
AF_BRIDGE = int32()
) func Htons(i uint16) uint16 {
return (i<<)&0xff00 | i>>
} type intfReq struct {
name []byte
flags uint16
} // sendIOCtlMessage ioctl system call
func sendIOCtlMessage(fd uintptr, request uintptr, ifReq uintptr) error {
fmt.Printf("syscall fd %+v, request %+v, ifReq %+v", fd, request, ifReq)
_, _, errno := syscall.Syscall(syscall.SYS_IOCTL, fd, request, ifReq)
if errno != {
fmt.Printf("Fail to execute ioctl, the errno is %+v", errno)
return errors.New("failed execute ioctl")
}
return nil
} // sendFCtlMessage fcntl system call
func sendFCtlMessage(fd int, cmd int, arg int) error {
_, _, err := syscall.Syscall(syscall.SYS_FCNTL, uintptr(fd), uintptr(cmd), uintptr(arg))
if err != {
fmt.Printf("Fail to execute fctl, the error is %+v", err)
return errors.New("failed execute fctl")
}
return nil
}

var tunDevicePath = "/dev/net/tun"
func main() {
var DeviceName string
flag.StringVar(&DeviceName, "name", "", "pkt0")
flag.Parse()
flag.Usage() fd, err := syscall.Open(tunDevicePath, os.O_RDWR, )
if err != nil {
fmt.Printf("failed to open tun device: %+v", err)
return
} var req intfReq
req.flags = syscall.IFF_TAP | syscall.IFF_NO_PI
copy(req.name[:], DeviceName) if err := sendIOCtlMessage(uintptr(fd),
uintptr(syscall.TUNSETIFF),
uintptr(unsafe.Pointer(&req))); err != nil {
return
}
if err := sendFCtlMessage(fd, syscall.F_SETFD, syscall.FD_CLOEXEC); err != nil {
return
}
if err := sendIOCtlMessage(uintptr(fd), syscall.TUNSETPERSIST, ); err != nil {
return
} raw, err := syscall.Socket(syscall.AF_PACKET, syscall.SOCK_RAW, int(Htons(syscall.ETH_P_ALL)))
if err != nil {
fmt.Printf("failed to create RAW socket: %+v", err)
return
} var reqRaw intfReq
copy(reqRaw.name[:], DeviceName)
if err := sendIOCtlMessage(uintptr(raw),
syscall.SIOCGIFINDEX,
uintptr(unsafe.Pointer(&reqRaw))); err != nil {
return
} ifi, err := net.InterfaceByName(DeviceName)
if err != nil {
fmt.Printf("failed to get device: %+v", err)
return
} if err := syscall.Bind(raw, &syscall.SockaddrLinklayer{
Protocol: uint16(Htons(syscall.ETH_P_ALL)),
Ifindex: ifi.Index,
}); err != nil {
fmt.Printf("failed to bind: %+v", err)
return
}
if err := sendIOCtlMessage(uintptr(raw),
syscall.SIOCSIFTXQLEN, uintptr(unsafe.Pointer(&reqRaw))); err != nil {
return
}
if err := sendIOCtlMessage(uintptr(raw),
syscall.SIOCGIFFLAGS, uintptr(unsafe.Pointer(&reqRaw))); err != nil {
return
}
reqRaw.flags = syscall.IFF_UP if err := sendIOCtlMessage(uintptr(raw),
syscall.SIOCSIFFLAGS, uintptr(unsafe.Pointer(&reqRaw))); err != nil {
return
} var r intfReq
copy(r.name[:], DeviceName)
if err := sendIOCtlMessage(uintptr(raw),
syscall.SIOCGIFFLAGS, uintptr(unsafe.Pointer(&r))); err != nil {
return
} if err := syscall.Close(raw); err != nil {
fmt.Printf("failed to close RAW socket: %+v", err)
return
} return
}

运行结果:

[root@wangjq tun]# ./main -name demo
Usage of ./main:
-name string
pkt0
syscall fd , request , ifReq
syscall fd , request , ifReq
syscall fd , request , ifReq
syscall fd , request , ifReq
syscall fd , request , ifReq
syscall fd , request , ifReq
syscall fd , request , ifReq
[root@wangjq tun]# ip link show demo
: demo: <NO-CARRIER,BROADCAST,UP> mtu qdisc pfifo_fast state DOWN mode DEFAULT group default qlen
link/ether 7e:e7::ad:f7:9e brd ff:ff:ff:ff:ff:ff

golang 创建 tun 设备的更多相关文章

  1. Linux 网络工具详解之 ip tuntap 和 tunctl 创建 tap/tun 设备

    本文首发于我的公众号 Linux云计算网络(id: cloud_dev),专注于干货分享,号内有 10T 书籍和视频资源,后台回复「1024」即可领取,欢迎大家关注,二维码文末可以扫. 在前面一篇文章 ...

  2. 【转】Linux 网络工具详解之 ip tuntap 和 tunctl 创建 tap/tun 设备

    原文:https://www.cnblogs.com/bakari/p/10449664.html -------------------------------------------------- ...

  3. 使用 TUN 设备实现一个简单的 UDP 代理隧道

    若要实现在 Linux 下的代理程序,方法有很多,比如看着 RFC 1928 来实现一个 socks5 代理并自行设置程序经过 socks5 代理等方式,下文是使用 Linux 提供的 tun/tap ...

  4. 代码片段 - Golang 创建 .tar.gz 压缩包

    Golang创建 .tar.gz 压缩包 tar 包实现了文件的打包功能,可以将多个文件或目录存储到单一的 .tar 文件中,tar 本身不具有压缩功能,只能打包文件或目录: import " ...

  5. Sybase ASE安装过程报错,无法创建数据库设备[AM fork() failed]

    今天同事要搭建一套测试环境,安装开发版的SYBASE ASE 15.03 Windows平台下的,发现安装过程中到了创建数据库设备的环节就开始报错了,报错信息如下: 03/24/14 09:31:44 ...

  6. D3D游戏降帧的动态创建D3D设备以及ShellCode HOOK玩法

    欢迎转载,转载请注明出处:http://blog.csdn.net/gnorth/article/details/9327971 说白了,也就是HOOK掉Present,这种代码,其实百度上某些地方有 ...

  7. 自动创建字符设备,不需mknod

    自动创建设备文件 1.自动创建设备文件的流程 字符设备驱动模块 -->创建一个设备驱动class--->创建属于class的device--->调用mdev工具(自动完成)--> ...

  8. linux之misc及使用misc创建字符设备

    1:linux字符设备及udev 1.1字符设备 字符设备就是:一个一个字节来进行访问的,不能对字符设备进行随机读写.简单字符设备创建实例如下: #include <linux/module.h ...

  9. -bash: 无法为立即文档创建临时文件: 设备上没有空间---记一次报错

    故障发生原因 测试环境,之前用该机器做过docker-compose,后来有需要用到该机器上的docker环境,需要将旧的docker容器全部删除,由于之前启动是使用docker-compose启动的 ...

随机推荐

  1. PHP设计模式之----观察者模式

    一.概述 1.观察者模式(Observer),当一个对象的状态发生改变时,依赖他的对象会全部收到通知,并自动更新. 2.场景:一个事件发生后,要执行一连串更新操作.传统的编程方式,就是在事件的代码之后 ...

  2. 给自己挖坑——DateWay

    参考文章 官方手册 官方博客 填坑 目录 简介 使用 1. 引入相关依赖 2. 配置 Dataway,并初始化数据表 3. 配置数据源 4. 把数据源设置到 Hasor 容器中 5. 在SprintB ...

  3. Android给ListView添加侧滑菜单功能

    贼简单,但是上次集成完之后忘记整理,所以写的有点简单 SwipeMenu类 继承自ViewGroup package com.onepilltest.others; import android.co ...

  4. 对‘sqrt’未定义的引用

    首先, 引用数学库 #include<math.h> 引用数学库时,要在编译后加上-lm 是每一个都要加!! 如下: gcc su.c -o su.o -lm gcc -g  su.c - ...

  5. TCP-三次握手和四次挥手简单理解

    TCP-三次握手和四次挥手简单理解 背景:TCP,即传输控制协议,是一种面向连接的可靠的,基于字节流的传输层协议.作用是在不可靠的互联网络上提供一个可靠的端到端的字节流服务,为了准确无误的将数据送达目 ...

  6. Upload 上传 el-upload 上传配置请求头为Content-Type: "multipart/form-data"

    api接口处添加属性 (标红处) // 校验台账 export const checkEquiment = (data) => { return axios({ url: '/job/equip ...

  7. PHP date_default_timezone_set() 函数

    ------------恢复内容开始------------ 实例 设置默认时区: <?php date_default_timezone_set("Asia/Shanghai&quo ...

  8. PHP fmod() 函数

    实例 返回 x/y 的浮点数余数: <?php$x = 7;$y = 2;$result = fmod($x,$y);echo $result;// $result equals 1, beca ...

  9. PHP zip_entry_filesize() 函数

    定义和用法 The zip_entry_filesize() 函数返回 zip 档案项目的原始文件尺寸(在压缩之前).高佣联盟 www.cgewang.com 语法 zip_entry_filesiz ...

  10. C/C++编程笔记:C语言预处理命令是什么?不要以为你直接写#就行!

    很多小伙伴在自己写代码的时候,已经多次使用过#include命令.使用库函数之前,应该用#include引入对应的头文件.其实这种以#号开头的命令称为预处理命令. C语言源文件要经过编译.链接才能生成 ...