1 // Copyright 2010 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.
5 // +build darwin freebsd linux netbsd openbsd windows
14 func sockaddrToIP(sa syscall
.Sockaddr
) Addr
{
15 switch sa
:= sa
.(type) {
16 case *syscall
.SockaddrInet4
:
17 return &IPAddr
{IP
: sa
.Addr
[0:]}
18 case *syscall
.SockaddrInet6
:
19 return &IPAddr
{IP
: sa
.Addr
[0:], Zone
: zoneToString(int(sa
.ZoneId
))}
24 func (a
*IPAddr
) family() int {
25 if a
== nil ||
len(a
.IP
) <= IPv4len
{
26 return syscall
.AF_INET
28 if a
.IP
.To4() != nil {
29 return syscall
.AF_INET
31 return syscall
.AF_INET6
34 func (a
*IPAddr
) isWildcard() bool {
35 if a
== nil || a
.IP
== nil {
38 return a
.IP
.IsUnspecified()
41 func (a
*IPAddr
) sockaddr(family
int) (syscall
.Sockaddr
, error
) {
42 return ipToSockaddr(family
, a
.IP
, 0, a
.Zone
)
45 func (a
*IPAddr
) toAddr() sockaddr
{
46 if a
== nil { // nil *IPAddr
47 return nil // nil interface
52 // IPConn is the implementation of the Conn and PacketConn interfaces
53 // for IP network connections.
58 func newIPConn(fd
*netFD
) *IPConn
{ return &IPConn
{conn
{fd
}} }
60 // ReadFromIP reads an IP packet from c, copying the payload into b.
61 // It returns the number of bytes copied into b and the return address
62 // that was on the packet.
64 // ReadFromIP can be made to time out and return an error with
65 // Timeout() == true after a fixed time limit; see SetDeadline and
67 func (c
*IPConn
) ReadFromIP(b
[]byte) (int, *IPAddr
, error
) {
69 return 0, nil, syscall
.EINVAL
71 // TODO(cw,rsc): consider using readv if we know the family
72 // type to avoid the header trim/copy
74 n
, sa
, err
:= c
.fd
.ReadFrom(b
)
75 switch sa
:= sa
.(type) {
76 case *syscall
.SockaddrInet4
:
77 addr
= &IPAddr
{IP
: sa
.Addr
[0:]}
78 if len(b
) >= IPv4len
{ // discard ipv4 header
79 hsize
:= (int(b
[0]) & 0xf) * 4
83 case *syscall
.SockaddrInet6
:
84 addr
= &IPAddr
{IP
: sa
.Addr
[0:], Zone
: zoneToString(int(sa
.ZoneId
))}
89 // ReadFrom implements the PacketConn ReadFrom method.
90 func (c
*IPConn
) ReadFrom(b
[]byte) (int, Addr
, error
) {
92 return 0, nil, syscall
.EINVAL
94 n
, addr
, err
:= c
.ReadFromIP(b
)
95 return n
, addr
.toAddr(), err
98 // ReadMsgIP reads a packet from c, copying the payload into b and the
99 // associated out-of-band data into oob. It returns the number of
100 // bytes copied into b, the number of bytes copied into oob, the flags
101 // that were set on the packet and the source address of the packet.
102 func (c
*IPConn
) ReadMsgIP(b
, oob
[]byte) (n
, oobn
, flags
int, addr
*IPAddr
, err error
) {
104 return 0, 0, 0, nil, syscall
.EINVAL
106 var sa syscall
.Sockaddr
107 n
, oobn
, flags
, sa
, err
= c
.fd
.ReadMsg(b
, oob
)
108 switch sa
:= sa
.(type) {
109 case *syscall
.SockaddrInet4
:
110 addr
= &IPAddr
{IP
: sa
.Addr
[0:]}
111 case *syscall
.SockaddrInet6
:
112 addr
= &IPAddr
{IP
: sa
.Addr
[0:], Zone
: zoneToString(int(sa
.ZoneId
))}
117 // WriteToIP writes an IP packet to addr via c, copying the payload
120 // WriteToIP can be made to time out and return an error with
121 // Timeout() == true after a fixed time limit; see SetDeadline and
122 // SetWriteDeadline. On packet-oriented connections, write timeouts
124 func (c
*IPConn
) WriteToIP(b
[]byte, addr
*IPAddr
) (int, error
) {
126 return 0, syscall
.EINVAL
128 sa
, err
:= addr
.sockaddr(c
.fd
.family
)
130 return 0, &OpError
{"write", c
.fd
.net
, addr
, err
}
132 return c
.fd
.WriteTo(b
, sa
)
135 // WriteTo implements the PacketConn WriteTo method.
136 func (c
*IPConn
) WriteTo(b
[]byte, addr Addr
) (int, error
) {
138 return 0, syscall
.EINVAL
140 a
, ok
:= addr
.(*IPAddr
)
142 return 0, &OpError
{"write", c
.fd
.net
, addr
, syscall
.EINVAL
}
144 return c
.WriteToIP(b
, a
)
147 // WriteMsgIP writes a packet to addr via c, copying the payload from
148 // b and the associated out-of-band data from oob. It returns the
149 // number of payload and out-of-band bytes written.
150 func (c
*IPConn
) WriteMsgIP(b
, oob
[]byte, addr
*IPAddr
) (n
, oobn
int, err error
) {
152 return 0, 0, syscall
.EINVAL
154 sa
, err
:= addr
.sockaddr(c
.fd
.family
)
156 return 0, 0, &OpError
{"write", c
.fd
.net
, addr
, err
}
158 return c
.fd
.WriteMsg(b
, oob
, sa
)
161 // DialIP connects to the remote address raddr on the network protocol
162 // netProto, which must be "ip", "ip4", or "ip6" followed by a colon
163 // and a protocol number or name.
164 func DialIP(netProto
string, laddr
, raddr
*IPAddr
) (*IPConn
, error
) {
165 return dialIP(netProto
, laddr
, raddr
, noDeadline
)
168 func dialIP(netProto
string, laddr
, raddr
*IPAddr
, deadline time
.Time
) (*IPConn
, error
) {
169 net
, proto
, err
:= parseNetwork(netProto
)
174 case "ip", "ip4", "ip6":
176 return nil, UnknownNetworkError(netProto
)
179 return nil, &OpError
{"dial", netProto
, nil, errMissingAddress
}
181 fd
, err
:= internetSocket(net
, laddr
.toAddr(), raddr
.toAddr(), deadline
, syscall
.SOCK_RAW
, proto
, "dial", sockaddrToIP
)
185 return newIPConn(fd
), nil
188 // ListenIP listens for incoming IP packets addressed to the local
189 // address laddr. The returned connection's ReadFrom and WriteTo
190 // methods can be used to receive and send IP packets with per-packet
192 func ListenIP(netProto
string, laddr
*IPAddr
) (*IPConn
, error
) {
193 net
, proto
, err
:= parseNetwork(netProto
)
198 case "ip", "ip4", "ip6":
200 return nil, UnknownNetworkError(netProto
)
202 fd
, err
:= internetSocket(net
, laddr
.toAddr(), nil, noDeadline
, syscall
.SOCK_RAW
, proto
, "listen", sockaddrToIP
)
206 return newIPConn(fd
), nil