Skip to content

Instantly share code, notes, and snippets.

@ttys3
Forked from glacjay/tun-ping-linux.go
Last active November 14, 2024 08:52
Show Gist options
  • Save ttys3/045ee3f074646c423833a31f024ea0a1 to your computer and use it in GitHub Desktop.
Save ttys3/045ee3f074646c423833a31f024ea0a1 to your computer and use it in GitHub Desktop.
Reading/Writing Linux's TUN/TAP device in Go.
package main
import (
"log"
"os"
"os/exec"
"syscall"
"unsafe"
)
func main() {
file, err := os.OpenFile("/dev/net/tun", os.O_RDWR, 0)
if err != nil {
log.Fatalf("error os.Open(): %v\n", err)
}
ifr := make([]byte, 18)
copy(ifr, []byte("tun0"))
ifr[16] = 0x01
ifr[17] = 0x10
_, _, errno := syscall.Syscall(syscall.SYS_IOCTL, uintptr(file.Fd()),
uintptr(0x400454ca), uintptr(unsafe.Pointer(&ifr[0])))
if errno != 0 {
log.Fatalf("error syscall.Ioctl(): %v\n", syscall.Errno(errno).Error())
}
// use ip instead of ifconfig to config the interface
cmd := exec.Command("/sbin/ip")
cmd.Args = []string{
"addr", "add", "192.168.7.1/24", "peer", "192.168.7.2", "dev", "tun0",
}
if err := cmd.Run(); err != nil {
log.Fatalf("error exec.Run(): %v\n", err)
}
// Set interface up explicitly if needed
cmdUp := exec.Command("/sbin/ip")
cmdUp.Args = []string{"link", "set", "dev", "tun0", "up"}
if err := cmdUp.Run(); err != nil {
log.Fatalf("error setting interface up: %v\n", err)
}
for {
buf := make([]byte, 2048)
read, err := file.Read(buf)
if err != nil {
log.Fatalf("error os.Read(): %v\n", err)
}
for i := 0; i < 4; i++ {
buf[i+12], buf[i+16] = buf[i+16], buf[i+12]
}
buf[20] = 0
buf[22] = 0
buf[23] = 0
var checksum uint16
for i := 20; i < read; i += 2 {
checksum += uint16(buf[i])<<8 + uint16(buf[i+1])
}
checksum = ^(checksum + 4)
buf[22] = byte(checksum >> 8)
buf[23] = byte(checksum & ((1 << 8) - 1))
_, err = file.Write(buf)
if err != nil {
log.Fatalf("error os.Write(): %v\n", err)
}
}
}
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment