func (fd *netFD) dial(ctx context.Context, laddr, raddr sockaddr) error { var err error var lsa syscall.Sockaddr if laddr != nil { if lsa, err = laddr.sockaddr(fd.family); err != nil { return err } else if lsa != nil { if err := syscall.Bind(fd.sysfd, lsa); err != nil { return os.NewSyscallError("bind", err) } } } var rsa syscall.Sockaddr if raddr != nil { if rsa, err = raddr.sockaddr(fd.family); err != nil { return err } if err := fd.connect(ctx, lsa, rsa); err != nil { return err } fd.isConnected = true } else { if err := fd.init(); err != nil { return err } } lsa, _ = syscall.Getsockname(fd.sysfd) if rsa, _ = syscall.Getpeername(fd.sysfd); rsa != nil { fd.setAddr(fd.addrFunc()(lsa), fd.addrFunc()(rsa)) } else { fd.setAddr(fd.addrFunc()(lsa), raddr) } return nil }
func remoteSockname(fd *netFD, toAddr func(syscall.Sockaddr) Addr) Addr { sa, _ := syscall.Getpeername(fd.sysfd) if sa == nil { return nullProtocolAddr(fd.family, fd.sotype) } return toAddr(sa) }
func (fd *netFD) dial(laddr, raddr sockaddr, deadline time.Time, toAddr func(syscall.Sockaddr) Addr) error { var err error var lsa syscall.Sockaddr if laddr != nil { if lsa, err = laddr.sockaddr(fd.family); err != nil { return err } else if lsa != nil { if err := syscall.Bind(fd.sysfd, lsa); err != nil { return os.NewSyscallError("bind", err) } } } var rsa syscall.Sockaddr if raddr != nil { if rsa, err = raddr.sockaddr(fd.family); err != nil { return err } if err := fd.connect(lsa, rsa, deadline); err != nil { return err } fd.isConnected = true } else { if err := fd.init(); err != nil { return err } } lsa, _ = syscall.Getsockname(fd.sysfd) if rsa, _ = syscall.Getpeername(fd.sysfd); rsa != nil { fd.setAddr(toAddr(lsa), toAddr(rsa)) } else { fd.setAddr(toAddr(lsa), raddr) } return nil }
// Generic socket creation. func socket(net string, f, t, p int, ipv6only bool, ulsa, ursa syscall.Sockaddr, deadline time.Time, toAddr func(syscall.Sockaddr) Addr) (fd *netFD, err error) { // See ../syscall/exec_unix.go for description of ForkLock. syscall.ForkLock.RLock() s, err := syscall.Socket(f, t, p) if err != nil { syscall.ForkLock.RUnlock() return nil, err } syscall.CloseOnExec(s) syscall.ForkLock.RUnlock() if err = setDefaultSockopts(s, f, t, ipv6only); err != nil { closesocket(s) return nil, err } if ulsa != nil { // We provide a socket that listens to a wildcard // address with reusable UDP port when the given ulsa // is an appropriate UDP multicast address prefix. // This makes it possible for a single UDP listener // to join multiple different group addresses, for // multiple UDP listeners that listen on the same UDP // port to join the same group address. if ulsa, err = listenerSockaddr(s, f, ulsa, toAddr); err != nil { closesocket(s) return nil, err } if err = syscall.Bind(s, ulsa); err != nil { closesocket(s) return nil, err } } if fd, err = newFD(s, f, t, net); err != nil { closesocket(s) return nil, err } if ursa != nil { if !deadline.IsZero() { fd.wdeadline = deadline.UnixNano() } if err = fd.connect(ursa); err != nil { closesocket(s) fd.Close() return nil, err } fd.isConnected = true fd.wdeadline = 0 } lsa, _ := syscall.Getsockname(s) laddr := toAddr(lsa) rsa, _ := syscall.Getpeername(s) raddr := toAddr(rsa) fd.setAddr(laddr, raddr) return fd, nil }
// Generic socket creation. func socket(net string, f, t, p int, ipv6only bool, la, ra syscall.Sockaddr, toAddr func(syscall.Sockaddr) Addr) (fd *netFD, err error) { // See ../syscall/exec.go for description of ForkLock. syscall.ForkLock.RLock() s, err := syscall.Socket(f, t, p) if err != nil { syscall.ForkLock.RUnlock() return nil, err } syscall.CloseOnExec(s) syscall.ForkLock.RUnlock() err = setDefaultSockopts(s, f, t, ipv6only) if err != nil { closesocket(s) return nil, err } var bla syscall.Sockaddr if la != nil { bla, err = listenerSockaddr(s, f, la, toAddr) if err != nil { closesocket(s) return nil, err } err = syscall.Bind(s, bla) if err != nil { closesocket(s) return nil, err } } if fd, err = newFD(s, f, t, net); err != nil { closesocket(s) return nil, err } if ra != nil { if err = fd.connect(ra); err != nil { closesocket(s) fd.Close() return nil, err } fd.isConnected = true } sa, _ := syscall.Getsockname(s) var laddr Addr if la != nil && bla != la { laddr = toAddr(la) } else { laddr = toAddr(sa) } sa, _ = syscall.Getpeername(s) raddr := toAddr(sa) fd.setAddr(laddr, raddr) return fd, nil }
// Generic POSIX socket creation. func socket(net string, f, t, p int, ipv6only bool, ulsa, ursa syscall.Sockaddr, deadline time.Time, toAddr func(syscall.Sockaddr) Addr) (fd *netFD, err error) { s, err := sysSocket(f, t, p) if err != nil { return nil, err } if err = setDefaultSockopts(s, f, t, ipv6only); err != nil { closesocket(s) return nil, err } if ulsa != nil { // We provide a socket that listens to a wildcard // address with reusable UDP port when the given ulsa // is an appropriate UDP multicast address prefix. // This makes it possible for a single UDP listener // to join multiple different group addresses, for // multiple UDP listeners that listen on the same UDP // port to join the same group address. if ulsa, err = listenerSockaddr(s, f, ulsa, toAddr); err != nil { closesocket(s) return nil, err } if err = syscall.Bind(s, ulsa); err != nil { closesocket(s) return nil, err } } if fd, err = newFD(s, f, t, net); err != nil { closesocket(s) return nil, err } if ursa != nil { if !deadline.IsZero() { setWriteDeadline(fd, deadline) } if err = fd.connect(ursa); err != nil { closesocket(s) return nil, err } fd.isConnected = true if !deadline.IsZero() { setWriteDeadline(fd, time.Time{}) } } lsa, _ := syscall.Getsockname(s) laddr := toAddr(lsa) rsa, _ := syscall.Getpeername(s) raddr := toAddr(rsa) fd.setAddr(laddr, raddr) if fd.raddr == nil { fd.raddr = toAddr(ursa) } return fd, nil }
func newFileFD(f *os.File) (*netFD, error) { syscall.ForkLock.RLock() fd, err := syscall.Dup(int(f.Fd())) if err != nil { syscall.ForkLock.RUnlock() return nil, os.NewSyscallError("dup", err) } syscall.CloseOnExec(fd) syscall.ForkLock.RUnlock() sotype, err := syscall.GetsockoptInt(fd, syscall.SOL_SOCKET, syscall.SO_TYPE) if err != nil { closesocket(fd) return nil, os.NewSyscallError("getsockopt", err) } family := syscall.AF_UNSPEC toAddr := sockaddrToTCP sa, _ := syscall.Getsockname(fd) switch sa.(type) { default: closesocket(fd) return nil, syscall.EINVAL case *syscall.SockaddrInet4: family = syscall.AF_INET if sotype == syscall.SOCK_DGRAM { toAddr = sockaddrToUDP } else if sotype == syscall.SOCK_RAW { toAddr = sockaddrToIP } case *syscall.SockaddrInet6: family = syscall.AF_INET6 if sotype == syscall.SOCK_DGRAM { toAddr = sockaddrToUDP } else if sotype == syscall.SOCK_RAW { toAddr = sockaddrToIP } case *syscall.SockaddrUnix: family = syscall.AF_UNIX toAddr = sockaddrToUnix if sotype == syscall.SOCK_DGRAM { toAddr = sockaddrToUnixgram } else if sotype == syscall.SOCK_SEQPACKET { toAddr = sockaddrToUnixpacket } } laddr := toAddr(sa) sa, _ = syscall.Getpeername(fd) raddr := toAddr(sa) netfd, err := newFD(fd, family, sotype, laddr.Network()) if err != nil { closesocket(fd) return nil, err } netfd.setAddr(laddr, raddr) return netfd, nil }
func newFileFD(f *os.File, sa SocketAddr) (*netFD, error) { s, err := dupSocket(f) if err != nil { return nil, err } var laddr, raddr Addr var fd *netFD if sa != nil { lsa := make([]byte, syscall.SizeofSockaddrAny) if err := unix.Getsockname(s, lsa); err != nil { lsa = nil } rsa := make([]byte, syscall.SizeofSockaddrAny) if err := unix.Getpeername(s, rsa); err != nil { rsa = nil } laddr = sa.Addr(lsa) raddr = sa.Addr(rsa) fd, err = newFD(s, -1, -1, laddr.Network()) } else { family := syscall.AF_UNSPEC var sotype int sotype, err = syscall.GetsockoptInt(s, syscall.SOL_SOCKET, syscall.SO_TYPE) if err != nil { closeFunc(s) return nil, os.NewSyscallError("getsockopt", err) } lsa, _ := syscall.Getsockname(s) rsa, _ := syscall.Getpeername(s) switch lsa.(type) { case *syscall.SockaddrInet4: family = syscall.AF_INET case *syscall.SockaddrInet6: family = syscall.AF_INET6 case *syscall.SockaddrUnix: family = syscall.AF_UNIX default: closeFunc(s) return nil, syscall.EPROTONOSUPPORT } fd, err = newFD(s, family, sotype, "") laddr = fd.addrFunc()(lsa) raddr = fd.addrFunc()(rsa) fd.net = laddr.Network() } if err != nil { closeFunc(s) return nil, err } if err := fd.init(); err != nil { fd.Close() return nil, err } fd.setAddr(laddr, raddr) return fd, nil }
func (sl *stdioConn) RemoteAddr() net.Addr { sa, _ := syscall.Getpeername(int(os.Stdin.Fd())) switch sa := sa.(type) { case *syscall.SockaddrInet4: return &net.IPAddr{sa.Addr[0:]} case *syscall.SockaddrInet6: return &net.IPAddr{sa.Addr[0:]} } return sl.LocalAddr() }
// 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 newFileFD(f *os.File) (nfd *netFD, err error) { fd, errno := syscall.Dup(f.Fd()) if errno != 0 { return nil, os.NewSyscallError("dup", errno) } proto, errno := syscall.GetsockoptInt(fd, syscall.SOL_SOCKET, syscall.SO_TYPE) if errno != 0 { return nil, os.NewSyscallError("getsockopt", errno) } family := syscall.AF_UNSPEC toAddr := sockaddrToTCP sa, _ := syscall.Getsockname(fd) switch sa.(type) { default: closesocket(fd) return nil, os.EINVAL case *syscall.SockaddrInet4: family = syscall.AF_INET if proto == syscall.SOCK_DGRAM { toAddr = sockaddrToUDP } else if proto == syscall.SOCK_RAW { toAddr = sockaddrToIP } case *syscall.SockaddrInet6: family = syscall.AF_INET6 if proto == syscall.SOCK_DGRAM { toAddr = sockaddrToUDP } else if proto == syscall.SOCK_RAW { toAddr = sockaddrToIP } case *syscall.SockaddrUnix: family = syscall.AF_UNIX toAddr = sockaddrToUnix if proto == syscall.SOCK_DGRAM { toAddr = sockaddrToUnixgram } else if proto == syscall.SOCK_SEQPACKET { toAddr = sockaddrToUnixpacket } } laddr := toAddr(sa) sa, _ = syscall.Getpeername(fd) raddr := toAddr(sa) if nfd, err = newFD(fd, family, proto, laddr.Network()); err != nil { return nil, err } nfd.setAddr(laddr, raddr) return nfd, 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 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 getip(fd int, remote bool) (ip []byte, port int, ok bool) { // No attempt at error reporting because // there are no possible errors, and the // caller won't report them anyway. var sa syscall.Sockaddr if remote { sa, _ = syscall.Getpeername(fd) } else { sa, _ = syscall.Getsockname(fd) } switch sa := sa.(type) { case *syscall.SockaddrInet4: return &sa.Addr, sa.Port, true case *syscall.SockaddrInet6: return &sa.Addr, sa.Port, true } return }
// 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() setKernelSpecificSockopt(s, f) if la != nil { e = syscall.Bind(s, la) if e != 0 { closesocket(s) return nil, os.Errno(e) } } if fd, err = newFD(s, f, p, net); err != nil { closesocket(s) return nil, err } if ra != nil { if err = fd.connect(ra); err != nil { fd.sysfd = -1 closesocket(s) return nil, err } } sa, _ := syscall.Getsockname(s) laddr := toAddr(sa) sa, _ = syscall.Getpeername(s) raddr := toAddr(sa) fd.setAddr(laddr, raddr) return fd, nil }
func newFileFD(f *os.File) (*netFD, error) { s, err := dupSocket(f) if err != nil { return nil, err } family := syscall.AF_UNSPEC sotype, err := syscall.GetsockoptInt(s, syscall.SOL_SOCKET, syscall.SO_TYPE) if err != nil { closeFunc(s) return nil, os.NewSyscallError("getsockopt", err) } lsa, _ := syscall.Getsockname(s) rsa, _ := syscall.Getpeername(s) switch lsa.(type) { case *syscall.SockaddrInet4: family = syscall.AF_INET case *syscall.SockaddrInet6: family = syscall.AF_INET6 case *syscall.SockaddrUnix: family = syscall.AF_UNIX default: closeFunc(s) return nil, syscall.EPROTONOSUPPORT } fd, err := newFD(s, family, sotype, "") if err != nil { closeFunc(s) return nil, err } laddr := fd.addrFunc()(lsa) raddr := fd.addrFunc()(rsa) fd.net = laddr.Network() if err := fd.init(); err != nil { fd.Close() return nil, err } fd.setAddr(laddr, raddr) return fd, nil }
// dialTCP dials a TCP connection to the specified host and sets marking on the // socket. The host must be given as an IP address. A mark of zero results in a // normal (non-marked) connection. func dialTCP(network, addr string, timeout time.Duration, mark int) (nc net.Conn, err error) { host, port, err := net.SplitHostPort(addr) if err != nil { return nil, err } ip := net.ParseIP(host) if ip == nil { return nil, fmt.Errorf("invalid IP address %q", host) } p, err := strconv.ParseUint(port, 10, 16) if err != nil { return nil, fmt.Errorf("invalid port number %q", port) } var domain int var rsa syscall.Sockaddr switch network { case "tcp4": domain = syscall.AF_INET if ip.To4() == nil { return nil, fmt.Errorf("invalid IPv4 address %q", host) } sa := &syscall.SockaddrInet4{Port: int(p)} copy(sa.Addr[:], ip.To4()) rsa = sa case "tcp6": domain = syscall.AF_INET6 if ip.To4() != nil { return nil, fmt.Errorf("invalid IPv6 address %q", host) } sa := &syscall.SockaddrInet6{Port: int(p)} copy(sa.Addr[:], ip.To16()) rsa = sa default: return nil, fmt.Errorf("unsupported network %q", network) } c := &conn{} defer func() { if err != nil { c.Close() } }() c.fd, err = syscall.Socket(domain, syscall.SOCK_STREAM|syscall.SOCK_CLOEXEC, 0) if err != nil { return nil, os.NewSyscallError("socket", err) } if mark != 0 { if err := setSocketMark(c.fd, mark); err != nil { return nil, err } } if err := setSocketTimeout(c.fd, timeout); err != nil { return nil, err } if err := syscall.Connect(c.fd, rsa); err != nil { return nil, os.NewSyscallError("connect", err) } if err := setSocketTimeout(c.fd, 0); err != nil { return nil, err } lsa, _ := syscall.Getsockname(c.fd) rsa, _ = syscall.Getpeername(c.fd) name := fmt.Sprintf("%s %s -> %s", network, sockaddrToString(lsa), sockaddrToString(rsa)) c.f = os.NewFile(uintptr(c.fd), name) // When we call net.FileConn the socket will be made non-blocking and // we will get a *net.TCPConn in return. The *os.File needs to be // closed in addition to the *net.TCPConn when we're done (conn.Close // takes care of that for us). if c.Conn, err = net.FileConn(c.f); err != nil { return nil, err } if _, ok := c.Conn.(*net.TCPConn); !ok { return nil, fmt.Errorf("%T is not a *net.TCPConn", c.Conn) } return c, nil }