码迷,mamicode.com
首页 > 其他好文 > 详细

golang 创建 tun 设备

时间:2019-10-29 19:58:45      阅读:289      评论:0      收藏:0      [点我收藏+]

标签:link   return   creat   string   message   dev   div   int   ace   

源码:

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
}

运行结果:

[root@wangjq 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
[root@wangjq 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

 

golang 创建 tun 设备

标签:link   return   creat   string   message   dev   div   int   ace   

原文地址:https://www.cnblogs.com/wangjq19920210/p/11760820.html

(0)
(0)
   
举报
评论 一句话评论(0
登录后才能评论!
© 2014 mamicode.com 版权所有  联系我们:gaon5@hotmail.com
迷上了代码!