blob: 214a4196c8e3cfca5376ab380ef7912c07e7de97 [file] [log] [blame]
Albert Strasheime480b812011-03-25 14:42:25 -04001// 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
Mikio Hara484cc672014-09-18 19:17:55 +09005// +build darwin dragonfly freebsd linux netbsd openbsd solaris
Russ Cox27159562011-09-15 16:48:57 -04006
Albert Strasheime480b812011-03-25 14:42:25 -04007package net
8
9import (
10 "os"
11 "syscall"
12)
13
Mikio Hara28397be2012-02-01 00:36:45 +090014func newFileFD(f *os.File) (*netFD, error) {
Brad Fitzpatrick37feacf2013-08-05 15:43:45 -070015 fd, err := dupCloseOnExec(int(f.Fd()))
Mikio Hara28397be2012-02-01 00:36:45 +090016 if err != nil {
17 return nil, os.NewSyscallError("dup", err)
Albert Strasheime480b812011-03-25 14:42:25 -040018 }
Brad Fitzpatrick37feacf2013-08-05 15:43:45 -070019
Ian Lance Taylor31f58dc2013-01-28 08:54:15 -080020 if err = syscall.SetNonblock(fd, true); err != nil {
21 closesocket(fd)
22 return nil, err
23 }
Albert Strasheime480b812011-03-25 14:42:25 -040024
Mikio Harad380a972012-07-22 01:48:15 +090025 sotype, err := syscall.GetsockoptInt(fd, syscall.SOL_SOCKET, syscall.SO_TYPE)
Mikio Hara28397be2012-02-01 00:36:45 +090026 if err != nil {
Mikio Harad380a972012-07-22 01:48:15 +090027 closesocket(fd)
Mikio Hara28397be2012-02-01 00:36:45 +090028 return nil, os.NewSyscallError("getsockopt", err)
Albert Strasheime480b812011-03-25 14:42:25 -040029 }
30
Albert Strasheim51057bda32011-10-12 13:36:45 -040031 family := syscall.AF_UNSPEC
Albert Strasheime480b812011-03-25 14:42:25 -040032 toAddr := sockaddrToTCP
Mikio Hara6cf77f22012-08-23 20:54:00 +090033 lsa, _ := syscall.Getsockname(fd)
34 switch lsa.(type) {
Albert Strasheime480b812011-03-25 14:42:25 -040035 default:
36 closesocket(fd)
Rob Pike56069f02012-02-17 10:04:29 +110037 return nil, syscall.EINVAL
Albert Strasheime480b812011-03-25 14:42:25 -040038 case *syscall.SockaddrInet4:
Albert Strasheim51057bda32011-10-12 13:36:45 -040039 family = syscall.AF_INET
Mikio Harad380a972012-07-22 01:48:15 +090040 if sotype == syscall.SOCK_DGRAM {
Albert Strasheime480b812011-03-25 14:42:25 -040041 toAddr = sockaddrToUDP
Mikio Harad380a972012-07-22 01:48:15 +090042 } else if sotype == syscall.SOCK_RAW {
Albert Strasheime480b812011-03-25 14:42:25 -040043 toAddr = sockaddrToIP
44 }
45 case *syscall.SockaddrInet6:
Albert Strasheim51057bda32011-10-12 13:36:45 -040046 family = syscall.AF_INET6
Mikio Harad380a972012-07-22 01:48:15 +090047 if sotype == syscall.SOCK_DGRAM {
Albert Strasheime480b812011-03-25 14:42:25 -040048 toAddr = sockaddrToUDP
Mikio Harad380a972012-07-22 01:48:15 +090049 } else if sotype == syscall.SOCK_RAW {
Albert Strasheime480b812011-03-25 14:42:25 -040050 toAddr = sockaddrToIP
51 }
52 case *syscall.SockaddrUnix:
Albert Strasheim51057bda32011-10-12 13:36:45 -040053 family = syscall.AF_UNIX
Albert Strasheime480b812011-03-25 14:42:25 -040054 toAddr = sockaddrToUnix
Mikio Harad380a972012-07-22 01:48:15 +090055 if sotype == syscall.SOCK_DGRAM {
Albert Strasheime480b812011-03-25 14:42:25 -040056 toAddr = sockaddrToUnixgram
Mikio Harad380a972012-07-22 01:48:15 +090057 } else if sotype == syscall.SOCK_SEQPACKET {
Albert Strasheime480b812011-03-25 14:42:25 -040058 toAddr = sockaddrToUnixpacket
59 }
60 }
Mikio Hara6cf77f22012-08-23 20:54:00 +090061 laddr := toAddr(lsa)
Mikio Harae4389c02012-09-19 01:33:03 +090062 rsa, _ := syscall.Getpeername(fd)
63 raddr := toAddr(rsa)
Albert Strasheime480b812011-03-25 14:42:25 -040064
Mikio Harad380a972012-07-22 01:48:15 +090065 netfd, err := newFD(fd, family, sotype, laddr.Network())
Mikio Hara28397be2012-02-01 00:36:45 +090066 if err != nil {
Mikio Harad380a972012-07-22 01:48:15 +090067 closesocket(fd)
Alexey Borzenkov2f45f722011-03-28 23:40:01 -040068 return nil, err
69 }
Mikio Hara6a76bca362013-08-06 23:42:33 +090070 if err := netfd.init(); err != nil {
71 netfd.Close()
72 return nil, err
73 }
Mikio Harae4389c02012-09-19 01:33:03 +090074 netfd.setAddr(laddr, raddr)
Mikio Hara28397be2012-02-01 00:36:45 +090075 return netfd, nil
Albert Strasheime480b812011-03-25 14:42:25 -040076}
77
78// FileConn returns a copy of the network connection corresponding to
79// the open file f. It is the caller's responsibility to close f when
80// finished. Closing c does not affect f, and closing f does not
81// affect c.
Russ Coxeb692922011-11-01 22:05:34 -040082func FileConn(f *os.File) (c Conn, err error) {
Albert Strasheime480b812011-03-25 14:42:25 -040083 fd, err := newFileFD(f)
84 if err != nil {
85 return nil, err
86 }
87 switch fd.laddr.(type) {
88 case *TCPAddr:
89 return newTCPConn(fd), nil
90 case *UDPAddr:
91 return newUDPConn(fd), nil
Albert Strasheime480b812011-03-25 14:42:25 -040092 case *IPAddr:
93 return newIPConn(fd), nil
Mikio Hara6cf77f22012-08-23 20:54:00 +090094 case *UnixAddr:
95 return newUnixConn(fd), nil
Albert Strasheime480b812011-03-25 14:42:25 -040096 }
97 fd.Close()
Rob Pike56069f02012-02-17 10:04:29 +110098 return nil, syscall.EINVAL
Albert Strasheime480b812011-03-25 14:42:25 -040099}
100
101// FileListener returns a copy of the network listener corresponding
Mikio Hara14ad4112012-05-30 01:42:36 +0900102// to the open file f. It is the caller's responsibility to close l
Mikio Hara8c8ab052012-05-30 01:52:50 +0900103// when finished. Closing l does not affect f, and closing f does not
104// affect l.
Mikio Hara14ad4112012-05-30 01:42:36 +0900105func FileListener(f *os.File) (l Listener, err error) {
Albert Strasheime480b812011-03-25 14:42:25 -0400106 fd, err := newFileFD(f)
107 if err != nil {
108 return nil, err
109 }
110 switch laddr := fd.laddr.(type) {
111 case *TCPAddr:
112 return &TCPListener{fd}, nil
113 case *UnixAddr:
114 return &UnixListener{fd, laddr.Name}, nil
115 }
116 fd.Close()
Rob Pike56069f02012-02-17 10:04:29 +1100117 return nil, syscall.EINVAL
Albert Strasheime480b812011-03-25 14:42:25 -0400118}
119
120// FilePacketConn returns a copy of the packet network connection
121// corresponding to the open file f. It is the caller's
122// responsibility to close f when finished. Closing c does not affect
123// f, and closing f does not affect c.
Russ Coxeb692922011-11-01 22:05:34 -0400124func FilePacketConn(f *os.File) (c PacketConn, err error) {
Albert Strasheime480b812011-03-25 14:42:25 -0400125 fd, err := newFileFD(f)
126 if err != nil {
127 return nil, err
128 }
129 switch fd.laddr.(type) {
130 case *UDPAddr:
131 return newUDPConn(fd), nil
Mikio Harac88a6712014-01-28 03:18:27 -0800132 case *IPAddr:
133 return newIPConn(fd), nil
Albert Strasheime480b812011-03-25 14:42:25 -0400134 case *UnixAddr:
135 return newUnixConn(fd), nil
136 }
137 fd.Close()
Rob Pike56069f02012-02-17 10:04:29 +1100138 return nil, syscall.EINVAL
Albert Strasheime480b812011-03-25 14:42:25 -0400139}