mirror of https://github.com/vishvananda/netlink
Add basic support for TUN/TAP link type and creation.
This commit is contained in:
parent
ecf47fd573
commit
de4cc349a5
26
link.go
26
link.go
|
@ -1,6 +1,9 @@
|
|||
package netlink
|
||||
|
||||
import "net"
|
||||
import (
|
||||
"net"
|
||||
"syscall"
|
||||
)
|
||||
|
||||
// Link represents a link device from netlink. Shared link attributes
|
||||
// like name may be retrieved using the Attrs() method. Unique data
|
||||
|
@ -136,6 +139,27 @@ func (macvtap Macvtap) Type() string {
|
|||
return "macvtap"
|
||||
}
|
||||
|
||||
type TuntapMode uint16
|
||||
|
||||
const (
|
||||
TUNTAP_MODE_TUN TuntapMode = syscall.IFF_TUN
|
||||
TUNTAP_MODE_TAP TuntapMode = syscall.IFF_TAP
|
||||
)
|
||||
|
||||
// Tuntap links created via /dev/tun/tap, but can be destroyed via netlink
|
||||
type Tuntap struct {
|
||||
LinkAttrs
|
||||
Mode TuntapMode
|
||||
}
|
||||
|
||||
func (tuntap *Tuntap) Attrs() *LinkAttrs {
|
||||
return &tuntap.LinkAttrs
|
||||
}
|
||||
|
||||
func (tuntap *Tuntap) Type() string {
|
||||
return "tuntap"
|
||||
}
|
||||
|
||||
// Veth devices must specify PeerName on create
|
||||
type Veth struct {
|
||||
LinkAttrs
|
||||
|
|
|
@ -5,6 +5,8 @@ import (
|
|||
"encoding/binary"
|
||||
"fmt"
|
||||
"net"
|
||||
"os"
|
||||
"unsafe"
|
||||
"syscall"
|
||||
|
||||
"github.com/vishvananda/netlink/nl"
|
||||
|
@ -285,6 +287,44 @@ func LinkAdd(link Link) error {
|
|||
return fmt.Errorf("LinkAttrs.Name cannot be empty!")
|
||||
}
|
||||
|
||||
if tuntap, ok := link.(*Tuntap); ok {
|
||||
// TODO: support user
|
||||
// TODO: support group
|
||||
// TODO: support non- one_queue
|
||||
// TODO: support pi | vnet_hdr | multi_queue
|
||||
// TODO: support non- exclusive
|
||||
// TODO: support non- persistent
|
||||
if (tuntap.Mode < syscall.IFF_TUN || tuntap.Mode > syscall.IFF_TAP) {
|
||||
return fmt.Errorf("Tuntap.Mode %v unknown!", tuntap.Mode)
|
||||
}
|
||||
file, err := os.OpenFile("/dev/net/tun", os.O_RDWR, 0)
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
defer file.Close()
|
||||
var req ifReq
|
||||
req.Flags |= syscall.IFF_ONE_QUEUE
|
||||
req.Flags |= syscall.IFF_TUN_EXCL
|
||||
copy(req.Name[:15], base.Name)
|
||||
req.Flags |= uint16(tuntap.Mode)
|
||||
_, _, errno := syscall.Syscall(syscall.SYS_IOCTL, file.Fd(), uintptr(syscall.TUNSETIFF), uintptr(unsafe.Pointer(&req)))
|
||||
if errno != 0 {
|
||||
return fmt.Errorf("Tuntap IOCTL TUNSETIFF failed, errno %v", errno)
|
||||
}
|
||||
_, _, errno = syscall.Syscall(syscall.SYS_IOCTL, file.Fd(), uintptr(syscall.TUNSETPERSIST), 1)
|
||||
if errno != 0 {
|
||||
return fmt.Errorf("Tuntap IOCTL TUNSETPERSIST failed, errno %v", errno)
|
||||
}
|
||||
ensureIndex(base)
|
||||
|
||||
// can't set master during create, so set it afterwards
|
||||
if base.MasterIndex != 0 {
|
||||
// TODO: verify MasterIndex is actually a bridge?
|
||||
return LinkSetMasterByIndex(link, base.MasterIndex)
|
||||
}
|
||||
return nil
|
||||
}
|
||||
|
||||
req := nl.NewNetlinkRequest(syscall.RTM_NEWLINK, syscall.NLM_F_CREATE|syscall.NLM_F_EXCL|syscall.NLM_F_ACK)
|
||||
|
||||
msg := nl.NewIfInfomsg(syscall.AF_UNSPEC)
|
||||
|
|
|
@ -0,0 +1,17 @@
|
|||
package netlink
|
||||
|
||||
/*
|
||||
#include <sys/ioctl.h>
|
||||
#include <sys/socket.h>
|
||||
#include <linux/if.h>
|
||||
#include <linux/if_tun.h>
|
||||
|
||||
#define IFREQ_SIZE sizeof(struct ifreq)
|
||||
*/
|
||||
import "C"
|
||||
|
||||
type ifReq struct {
|
||||
Name [C.IFNAMSIZ]byte
|
||||
Flags uint16
|
||||
pad [C.IFREQ_SIZE-C.IFNAMSIZ-2]byte
|
||||
}
|
Loading…
Reference in New Issue