golang 创建 tun 设备
源码:
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 设备的更多相关文章
- Linux 网络工具详解之 ip tuntap 和 tunctl 创建 tap/tun 设备
本文首发于我的公众号 Linux云计算网络(id: cloud_dev),专注于干货分享,号内有 10T 书籍和视频资源,后台回复「1024」即可领取,欢迎大家关注,二维码文末可以扫. 在前面一篇文章 ...
- 【转】Linux 网络工具详解之 ip tuntap 和 tunctl 创建 tap/tun 设备
原文:https://www.cnblogs.com/bakari/p/10449664.html -------------------------------------------------- ...
- 使用 TUN 设备实现一个简单的 UDP 代理隧道
若要实现在 Linux 下的代理程序,方法有很多,比如看着 RFC 1928 来实现一个 socks5 代理并自行设置程序经过 socks5 代理等方式,下文是使用 Linux 提供的 tun/tap ...
- 代码片段 - Golang 创建 .tar.gz 压缩包
Golang创建 .tar.gz 压缩包 tar 包实现了文件的打包功能,可以将多个文件或目录存储到单一的 .tar 文件中,tar 本身不具有压缩功能,只能打包文件或目录: import " ...
- Sybase ASE安装过程报错,无法创建数据库设备[AM fork() failed]
今天同事要搭建一套测试环境,安装开发版的SYBASE ASE 15.03 Windows平台下的,发现安装过程中到了创建数据库设备的环节就开始报错了,报错信息如下: 03/24/14 09:31:44 ...
- D3D游戏降帧的动态创建D3D设备以及ShellCode HOOK玩法
欢迎转载,转载请注明出处:http://blog.csdn.net/gnorth/article/details/9327971 说白了,也就是HOOK掉Present,这种代码,其实百度上某些地方有 ...
- 自动创建字符设备,不需mknod
自动创建设备文件 1.自动创建设备文件的流程 字符设备驱动模块 -->创建一个设备驱动class--->创建属于class的device--->调用mdev工具(自动完成)--> ...
- linux之misc及使用misc创建字符设备
1:linux字符设备及udev 1.1字符设备 字符设备就是:一个一个字节来进行访问的,不能对字符设备进行随机读写.简单字符设备创建实例如下: #include <linux/module.h ...
- -bash: 无法为立即文档创建临时文件: 设备上没有空间---记一次报错
故障发生原因 测试环境,之前用该机器做过docker-compose,后来有需要用到该机器上的docker环境,需要将旧的docker容器全部删除,由于之前启动是使用docker-compose启动的 ...
随机推荐
- PHP设计模式之----观察者模式
一.概述 1.观察者模式(Observer),当一个对象的状态发生改变时,依赖他的对象会全部收到通知,并自动更新. 2.场景:一个事件发生后,要执行一连串更新操作.传统的编程方式,就是在事件的代码之后 ...
- 给自己挖坑——DateWay
参考文章 官方手册 官方博客 填坑 目录 简介 使用 1. 引入相关依赖 2. 配置 Dataway,并初始化数据表 3. 配置数据源 4. 把数据源设置到 Hasor 容器中 5. 在SprintB ...
- Android给ListView添加侧滑菜单功能
贼简单,但是上次集成完之后忘记整理,所以写的有点简单 SwipeMenu类 继承自ViewGroup package com.onepilltest.others; import android.co ...
- 对‘sqrt’未定义的引用
首先, 引用数学库 #include<math.h> 引用数学库时,要在编译后加上-lm 是每一个都要加!! 如下: gcc su.c -o su.o -lm gcc -g su.c - ...
- TCP-三次握手和四次挥手简单理解
TCP-三次握手和四次挥手简单理解 背景:TCP,即传输控制协议,是一种面向连接的可靠的,基于字节流的传输层协议.作用是在不可靠的互联网络上提供一个可靠的端到端的字节流服务,为了准确无误的将数据送达目 ...
- Upload 上传 el-upload 上传配置请求头为Content-Type: "multipart/form-data"
api接口处添加属性 (标红处) // 校验台账 export const checkEquiment = (data) => { return axios({ url: '/job/equip ...
- PHP date_default_timezone_set() 函数
------------恢复内容开始------------ 实例 设置默认时区: <?php date_default_timezone_set("Asia/Shanghai&quo ...
- PHP fmod() 函数
实例 返回 x/y 的浮点数余数: <?php$x = 7;$y = 2;$result = fmod($x,$y);echo $result;// $result equals 1, beca ...
- PHP zip_entry_filesize() 函数
定义和用法 The zip_entry_filesize() 函数返回 zip 档案项目的原始文件尺寸(在压缩之前).高佣联盟 www.cgewang.com 语法 zip_entry_filesiz ...
- C/C++编程笔记:C语言预处理命令是什么?不要以为你直接写#就行!
很多小伙伴在自己写代码的时候,已经多次使用过#include命令.使用库函数之前,应该用#include引入对应的头文件.其实这种以#号开头的命令称为预处理命令. C语言源文件要经过编译.链接才能生成 ...