Created
March 18, 2013 18:58
-
-
Save songgao/5189799 to your computer and use it in GitHub Desktop.
Revisions
-
songgao created this gist
Mar 18, 2013 .There are no files selected for viewing
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters. Learn more about bidirectional Unicode charactersOriginal file line number Diff line number Diff line change @@ -0,0 +1,96 @@ package main import ( "io" "net" "os" "fmt" "strings" "syscall" "unsafe" ) const ( cIFF_TUN = 0x0001 cIFF_NO_PI = 0x1000 ) const ( cMAX_PACKET_SIZE = 1500 //MTU ) type ifReq struct { Name [0x10]byte Flags uint16 pad [0x28 - 0x10 - 2]byte } type tunIF struct { name string file *os.File } func (tun *tunIF) Name() string { return tun.name } func (tun *tunIF) createInterface(ifPattern string) (err error) { var req ifReq req.Flags = cIFF_TUN | cIFF_NO_PI copy(req.Name[:], ifPattern) _, _, errno := syscall.Syscall(syscall.SYS_IOCTL, tun.file.Fd(), uintptr(syscall.TUNSETIFF), uintptr(unsafe.Pointer(&req))) if errno != 0 { return errno } tun.name = strings.Trim(string(req.Name[:]), "\x00") return } func newTun(ifPattern string) (tun *tunIF, err error) { file, err := os.OpenFile("/dev/net/tun", os.O_RDWR, 0) if err != nil { return nil, err } tun = &tunIF{name: "", file: file} err = tun.createInterface(ifPattern) if err != nil { file.Close() return nil, err } return } // Read a packet from TUN device. func (tun *tunIF) Read() (packet []byte, err error) { buf := make([]byte, cMAX_PACKET_SIZE) n, err := tun.file.Read(buf) if err != nil && err != io.EOF { return } packet = buf[:n] return packet, nil } // Write a packet into TUN device (blocking) func (tun *tunIF) Write(packet []byte) (err error) { _, err = tun.file.Write(packet) return } func IPFrom(bytes []byte) net.IP { return net.IPv4(bytes[0], bytes[1], bytes[2], bytes[3]).To4() } func main() { tun, err := newTun("tun0") if err != nil{ fmt.Println(err) } for { packet, err := tun.Read() if err != nil { break } fmt.Printf("From: %v; To: %v\n", IPFrom(packet[12:16]), IPFrom(packet[16:20])) } }