1 // Copyright 2011 The Go Authors. All rights reserved. 2 // Use of this source code is governed by a BSD-style 3 // license that can be found in the LICENSE file. 4 5 // +build darwin dragonfly freebsd linux netbsd openbsd solaris 6 7 package net 8 9 import ( 10 "internal/poll" 11 "os" 12 "syscall" 13 ) 14 15 func dupSocket(f *os.File) (int, error) { 16 s, err := dupCloseOnExec(int(f.Fd())) 17 if err != nil { 18 return -1, err 19 } 20 if err := syscall.SetNonblock(s, true); err != nil { 21 poll.CloseFunc(s) 22 return -1, os.NewSyscallError("setnonblock", err) 23 } 24 return s, nil 25 } 26 27 func newFileFD(f *os.File) (*netFD, error) { 28 s, err := dupSocket(f) 29 if err != nil { 30 return nil, err 31 } 32 family := syscall.AF_UNSPEC 33 sotype, err := syscall.GetsockoptInt(s, syscall.SOL_SOCKET, syscall.SO_TYPE) 34 if err != nil { 35 poll.CloseFunc(s) 36 return nil, os.NewSyscallError("getsockopt", err) 37 } 38 lsa, _ := syscall.Getsockname(s) 39 rsa, _ := syscall.Getpeername(s) 40 switch lsa.(type) { 41 case *syscall.SockaddrInet4: 42 family = syscall.AF_INET 43 case *syscall.SockaddrInet6: 44 family = syscall.AF_INET6 45 case *syscall.SockaddrUnix: 46 family = syscall.AF_UNIX 47 default: 48 poll.CloseFunc(s) 49 return nil, syscall.EPROTONOSUPPORT 50 } 51 fd, err := newFD(s, family, sotype, "") 52 if err != nil { 53 poll.CloseFunc(s) 54 return nil, err 55 } 56 laddr := fd.addrFunc()(lsa) 57 raddr := fd.addrFunc()(rsa) 58 fd.net = laddr.Network() 59 if err := fd.init(); err != nil { 60 fd.Close() 61 return nil, err 62 } 63 fd.setAddr(laddr, raddr) 64 return fd, nil 65 } 66 67 func fileConn(f *os.File) (Conn, error) { 68 fd, err := newFileFD(f) 69 if err != nil { 70 return nil, err 71 } 72 switch fd.laddr.(type) { 73 case *TCPAddr: 74 return newTCPConn(fd), nil 75 case *UDPAddr: 76 return newUDPConn(fd), nil 77 case *IPAddr: 78 return newIPConn(fd), nil 79 case *UnixAddr: 80 return newUnixConn(fd), nil 81 } 82 fd.Close() 83 return nil, syscall.EINVAL 84 } 85 86 func fileListener(f *os.File) (Listener, error) { 87 fd, err := newFileFD(f) 88 if err != nil { 89 return nil, err 90 } 91 switch laddr := fd.laddr.(type) { 92 case *TCPAddr: 93 return &TCPListener{fd}, nil 94 case *UnixAddr: 95 return &UnixListener{fd: fd, path: laddr.Name, unlink: false}, nil 96 } 97 fd.Close() 98 return nil, syscall.EINVAL 99 } 100 101 func filePacketConn(f *os.File) (PacketConn, error) { 102 fd, err := newFileFD(f) 103 if err != nil { 104 return nil, err 105 } 106 switch fd.laddr.(type) { 107 case *UDPAddr: 108 return newUDPConn(fd), nil 109 case *IPAddr: 110 return newIPConn(fd), nil 111 case *UnixAddr: 112 return newUnixConn(fd), nil 113 } 114 fd.Close() 115 return nil, syscall.EINVAL 116 } 117