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(2)
AF_INET6 = int32(10)
AF_BRIDGE = int32(7)
)
func Htons(i uint16) uint16 {
return (i<<8)&0xff00 | i>>8
}
type intfReq struct {
name [16]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 != 0 {
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 != 0 {
fmt.Printf("Fail to execute fctl, the error is %+v", err)
return errors.New("failed execute fctl")
}
return nil
}
func main() {
var DeviceName string
flag.StringVar(&DeviceName, "name", "", "pkt0")
flag.Parse()
flag.Usage()
fd, err := syscall.Open(tunDevicePath, os.O_RDWR, 0)
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, 1); 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
}运行结果:
[ tun]# ./main -name demo
Usage of ./main:
-name string
pkt0
syscall fd 3, request 1074025674, ifReq 824634130180
syscall fd 3, request 1074025675, ifReq 1
syscall fd 5, request 35123, ifReq 824634130162
syscall fd 5, request 35139, ifReq 824634130162
syscall fd 5, request 35091, ifReq 824634130162
syscall fd 5, request 35092, ifReq 824634130162
syscall fd 5, request 35091, ifReq 824634130198
[ tun]# ip link show demo
10: demo: <NO-CARRIER,BROADCAST,UP> mtu 1500 qdisc pfifo_fast state DOWN mode DEFAULT group default qlen 10
link/ether 7e:e7:77:ad:f7:9e brd ff:ff:ff:ff:ff:ff 相关推荐
OwenJi 2020-06-01
qscool 2020-05-10
jackalwb 2020-02-11
KilluaZoldyck 2020-01-06
alwayshelloworld 2013-06-30
cmsmdn 2019-12-17
小仙儿 2019-12-01
PHP恶魔笔记 2019-11-21
xuyunti 2019-11-05
mingmingini 2011-03-06
Scorpionbao 2011-03-06
hickwu 2011-02-18
过儿古墓 2011-01-14
linuxisperfect 2010-12-12
xz0mzq 2011-09-02
柯利南 2011-04-16
lianweikj0 2019-11-04
whx00 2011-07-08