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
7 // Raw IP sockets for POSIX
16 func sockaddrToIP(sa syscall
.Sockaddr
) Addr
{
17 switch sa
:= sa
.(type) {
18 case *syscall
.SockaddrInet4
:
19 return &IPAddr
{IP
: sa
.Addr
[0:]}
20 case *syscall
.SockaddrInet6
:
21 return &IPAddr
{IP
: sa
.Addr
[0:], Zone
: zoneToString(int(sa
.ZoneId
))}
26 func (a
*IPAddr
) family() int {
27 if a
== nil ||
len(a
.IP
) <= IPv4len
{
28 return syscall
.AF_INET
30 if a
.IP
.To4() != nil {
31 return syscall
.AF_INET
33 return syscall
.AF_INET6
36 func (a
*IPAddr
) isWildcard() bool {
37 if a
== nil || a
.IP
== nil {
40 return a
.IP
.IsUnspecified()
43 func (a
*IPAddr
) sockaddr(family
int) (syscall
.Sockaddr
, error
) {
44 return ipToSockaddr(family
, a
.IP
, 0, a
.Zone
)
47 func (a
*IPAddr
) toAddr() sockaddr
{
48 if a
== nil { // nil *IPAddr
49 return nil // nil interface
54 // IPConn is the implementation of the Conn and PacketConn
55 // interfaces for IP network connections.
60 func newIPConn(fd
*netFD
) *IPConn
{ return &IPConn
{conn
{fd
}} }
62 // ReadFromIP reads an IP packet from c, copying the payload into b.
63 // It returns the number of bytes copied into b and the return address
64 // that was on the packet.
66 // ReadFromIP can be made to time out and return an error with
67 // Timeout() == true after a fixed time limit; see SetDeadline and
69 func (c
*IPConn
) ReadFromIP(b
[]byte) (int, *IPAddr
, error
) {
71 return 0, nil, syscall
.EINVAL
73 // TODO(cw,rsc): consider using readv if we know the family
74 // type to avoid the header trim/copy
76 n
, sa
, err
:= c
.fd
.ReadFrom(b
)
77 switch sa
:= sa
.(type) {
78 case *syscall
.SockaddrInet4
:
79 addr
= &IPAddr
{IP
: sa
.Addr
[0:]}
80 if len(b
) >= IPv4len
{ // discard ipv4 header
81 hsize
:= (int(b
[0]) & 0xf) * 4
85 case *syscall
.SockaddrInet6
:
86 addr
= &IPAddr
{IP
: sa
.Addr
[0:], Zone
: zoneToString(int(sa
.ZoneId
))}
91 // ReadFrom implements the PacketConn ReadFrom method.
92 func (c
*IPConn
) ReadFrom(b
[]byte) (int, Addr
, error
) {
94 return 0, nil, syscall
.EINVAL
96 n
, addr
, err
:= c
.ReadFromIP(b
)
97 return n
, addr
.toAddr(), err
100 // ReadMsgIP reads a packet from c, copying the payload into b and the
101 // associdated out-of-band data into oob. It returns the number of
102 // bytes copied into b, the number of bytes copied into oob, the flags
103 // that were set on the packet and the source address of the packet.
104 func (c
*IPConn
) ReadMsgIP(b
, oob
[]byte) (n
, oobn
, flags
int, addr
*IPAddr
, err error
) {
106 return 0, 0, 0, nil, syscall
.EINVAL
108 var sa syscall
.Sockaddr
109 n
, oobn
, flags
, sa
, err
= c
.fd
.ReadMsg(b
, oob
)
110 switch sa
:= sa
.(type) {
111 case *syscall
.SockaddrInet4
:
112 addr
= &IPAddr
{IP
: sa
.Addr
[0:]}
113 case *syscall
.SockaddrInet6
:
114 addr
= &IPAddr
{IP
: sa
.Addr
[0:], Zone
: zoneToString(int(sa
.ZoneId
))}
119 // WriteToIP writes an IP packet to addr via c, copying the payload from b.
121 // WriteToIP can be made to time out and return
122 // an error with Timeout() == true after a fixed time limit;
123 // see SetDeadline and SetWriteDeadline.
124 // On packet-oriented connections, write timeouts are rare.
125 func (c
*IPConn
) WriteToIP(b
[]byte, addr
*IPAddr
) (int, error
) {
127 return 0, syscall
.EINVAL
129 sa
, err
:= addr
.sockaddr(c
.fd
.family
)
131 return 0, &OpError
{"write", c
.fd
.net
, addr
, err
}
133 return c
.fd
.WriteTo(b
, sa
)
136 // WriteTo implements the PacketConn WriteTo method.
137 func (c
*IPConn
) WriteTo(b
[]byte, addr Addr
) (int, error
) {
139 return 0, syscall
.EINVAL
141 a
, ok
:= addr
.(*IPAddr
)
143 return 0, &OpError
{"write", c
.fd
.net
, addr
, syscall
.EINVAL
}
145 return c
.WriteToIP(b
, a
)
148 // WriteMsgIP writes a packet to addr via c, copying the payload from
149 // b and the associated out-of-band data from oob. It returns the
150 // number of payload and out-of-band bytes written.
151 func (c
*IPConn
) WriteMsgIP(b
, oob
[]byte, addr
*IPAddr
) (n
, oobn
int, err error
) {
153 return 0, 0, syscall
.EINVAL
155 sa
, err
:= addr
.sockaddr(c
.fd
.family
)
157 return 0, 0, &OpError
{"write", c
.fd
.net
, addr
, err
}
159 return c
.fd
.WriteMsg(b
, oob
, sa
)
162 // DialIP connects to the remote address raddr on the network protocol netProto,
163 // which must be "ip", "ip4", or "ip6" followed by a colon 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
:= parseDialNetwork(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
189 // local address laddr. The returned connection c's ReadFrom
190 // and WriteTo methods can be used to receive and send IP
191 // packets with per-packet addressing.
192 func ListenIP(netProto
string, laddr
*IPAddr
) (*IPConn
, error
) {
193 net
, proto
, err
:= parseDialNetwork(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