diff --git a/example/tcp_server.go b/example/tcp_server.go new file mode 100644 index 0000000..c871726 --- /dev/null +++ b/example/tcp_server.go @@ -0,0 +1,38 @@ +package main + +import ( + "fmt" + "log" + "net" + "runtime" + "strings" +) + +type TCPHandler interface { + Handle(net.Conn) +} + +func TCPServer(listener net.Listener, handler TCPHandler, logf lg.AppLogFunc) error { + log.Printf("TCP: listening on %s", listener.Addr()) + + for { + clientConn, err := listener.Accept() + if err != nil { + if nerr, ok := err.(net.Error); ok && nerr.Temporary() { + log.Printf("temporary Accept() failure - %s", err) + runtime.Gosched() + continue + } + // theres no direct way to detect this error because it is not exposed + if !strings.Contains(err.Error(), "use of closed network connection") { + return fmt.Errorf("listener.Accept() error - %s", err) + } + break + } + go handler.Handle(clientConn) + } + + log.Printf("TCP: closing %s", listener.Addr()) + + return nil +} diff --git a/img/document-uid949121labid10418timestamp1555399038307.png b/img/document-uid949121labid10418timestamp1555399038307.png new file mode 100644 index 0000000..8ce6110 Binary files /dev/null and b/img/document-uid949121labid10418timestamp1555399038307.png differ diff --git a/tcpip/link/tuntap/tuntap.go b/tcpip/link/tuntap/tuntap.go index 5533354..91c78f5 100644 --- a/tcpip/link/tuntap/tuntap.go +++ b/tcpip/link/tuntap/tuntap.go @@ -2,7 +2,10 @@ package tuntap import ( "errors" + "fmt" + "os/exec" "syscall" + "unsafe" ) const ( @@ -44,6 +47,38 @@ func NewNetDev(c *Config) (fd int, err error) { } +// SetLinkUp 让系统启动该网卡 +func SetLinkUp(name string) (err error) { + out, cmdErr := exec.Command("ip", "link", "set", name, "up").CombinedOutput() + if cmdErr != nil { + err = fmt.Errorf("%v:%v", cmdErr, string(out)) + return + } + return +} + +// SetRoute 通过ip命令添加路由 +func SetRoute(name, cidr string) (err error) { + out, cmdErr := exec.Command("ip", "link", "set", name, "up").CombinedOutput() + if cmdErr != nil { + err = fmt.Errorf("%v:%v", cmdErr, string(out)) + return + } + return + +} + +// SetRoute 通过ip命令添加IP地址 +func AddIP(name, ip string) (err error) { + out, cmdErr := exec.Command("ip", "link", "set", name, "up").CombinedOutput() + if cmdErr != nil { + err = fmt.Errorf("%v:%v", cmdErr, string(out)) + return + } + return + +} + func newTun(name string) (int, error) { return open(name, syscall.IFF_TUN|syscall.IFF_NO_PI) @@ -56,9 +91,27 @@ func newTAP(name string) (int, error) { // 先打开一个字符串设备,通过系统调用将虚拟网卡和字符串设备fd bind在一起 func open(name string, flags uint16) (int, error) { + // 打开一个字符串设备 得到自负设备的文件描述符 fd, err := syscall.Open("/dev/net/tun", syscall.O_RDWR, 0) if err != nil { return -1, err } + var ifr struct { + name []byte + flags uint16 + _ [22]byte + } + + copy(ifr.name[:], name) + ifr.flags = flags + // 通过ioctl系统调用 将fd和虚拟网卡驱动绑定在一起 + _, _, errno := syscall.Syscall(syscall.SYS_IOCTL, uintptr(fd), + syscall.TUNSETIFF, uintptr(unsafe.Pointer(&ifr))) + if errno != 0 { + syscall.Close(fd) + return -1, errno + } + return fd, nil + }