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.
15 var onceReadProtocols sync
.Once
17 func sockaddrToIP(sa syscall
.Sockaddr
) Addr
{
18 switch sa
:= sa
.(type) {
19 case *syscall
.SockaddrInet4
:
20 return &IPAddr
{sa
.Addr
[0:]}
21 case *syscall
.SockaddrInet6
:
22 return &IPAddr
{sa
.Addr
[0:]}
27 // IPAddr represents the address of a IP end point.
32 // Network returns the address's network name, "ip".
33 func (a
*IPAddr
) Network() string { return "ip" }
35 func (a
*IPAddr
) String() string {
42 func (a
*IPAddr
) family() int {
43 if a
== nil ||
len(a
.IP
) <= 4 {
44 return syscall
.AF_INET
46 if ip
:= a
.IP
.To4(); ip
!= nil {
47 return syscall
.AF_INET
49 return syscall
.AF_INET6
52 func (a
*IPAddr
) sockaddr(family
int) (syscall
.Sockaddr
, os
.Error
) {
53 return ipToSockaddr(family
, a
.IP
, 0)
56 func (a
*IPAddr
) toAddr() sockaddr
{
57 if a
== nil { // nil *IPAddr
58 return nil // nil interface
63 // ResolveIPAddr parses addr as a IP address and resolves domain
64 // names to numeric addresses. A literal IPv6 host address must be
65 // enclosed in square brackets, as in "[::]".
66 func ResolveIPAddr(addr
string) (*IPAddr
, os
.Error
) {
67 ip
, err
:= hostToIP(addr
)
71 return &IPAddr
{ip
}, nil
74 // IPConn is the implementation of the Conn and PacketConn
75 // interfaces for IP network connections.
80 func newIPConn(fd
*netFD
) *IPConn
{ return &IPConn
{fd
} }
82 func (c
*IPConn
) ok() bool { return c
!= nil && c
.fd
!= nil }
84 // Implementation of the Conn interface - see Conn for documentation.
86 // Read implements the net.Conn Read method.
87 func (c
*IPConn
) Read(b
[]byte) (n
int, err os
.Error
) {
88 n
, _
, err
= c
.ReadFrom(b
)
92 // Write implements the net.Conn Write method.
93 func (c
*IPConn
) Write(b
[]byte) (n
int, err os
.Error
) {
100 // Close closes the IP connection.
101 func (c
*IPConn
) Close() os
.Error
{
110 // LocalAddr returns the local network address.
111 func (c
*IPConn
) LocalAddr() Addr
{
118 // RemoteAddr returns the remote network address, a *IPAddr.
119 func (c
*IPConn
) RemoteAddr() Addr
{
126 // SetTimeout implements the net.Conn SetTimeout method.
127 func (c
*IPConn
) SetTimeout(nsec
int64) os
.Error
{
131 return setTimeout(c
.fd
, nsec
)
134 // SetReadTimeout implements the net.Conn SetReadTimeout method.
135 func (c
*IPConn
) SetReadTimeout(nsec
int64) os
.Error
{
139 return setReadTimeout(c
.fd
, nsec
)
142 // SetWriteTimeout implements the net.Conn SetWriteTimeout method.
143 func (c
*IPConn
) SetWriteTimeout(nsec
int64) os
.Error
{
147 return setWriteTimeout(c
.fd
, nsec
)
150 // SetReadBuffer sets the size of the operating system's
151 // receive buffer associated with the connection.
152 func (c
*IPConn
) SetReadBuffer(bytes
int) os
.Error
{
156 return setReadBuffer(c
.fd
, bytes
)
159 // SetWriteBuffer sets the size of the operating system's
160 // transmit buffer associated with the connection.
161 func (c
*IPConn
) SetWriteBuffer(bytes
int) os
.Error
{
165 return setWriteBuffer(c
.fd
, bytes
)
168 // IP-specific methods.
170 // ReadFromIP reads a IP packet from c, copying the payload into b.
171 // It returns the number of bytes copied into b and the return address
172 // that was on the packet.
174 // ReadFromIP can be made to time out and return an error with
175 // Timeout() == true after a fixed time limit; see SetTimeout and
177 func (c
*IPConn
) ReadFromIP(b
[]byte) (n
int, addr
*IPAddr
, err os
.Error
) {
179 return 0, nil, os
.EINVAL
181 // TODO(cw,rsc): consider using readv if we know the family
182 // type to avoid the header trim/copy
183 n
, sa
, err
:= c
.fd
.ReadFrom(b
)
184 switch sa
:= sa
.(type) {
185 case *syscall
.SockaddrInet4
:
186 addr
= &IPAddr
{sa
.Addr
[0:]}
187 if len(b
) >= 4 { // discard ipv4 header
188 hsize
:= (int(b
[0]) & 0xf) * 4
192 case *syscall
.SockaddrInet6
:
193 addr
= &IPAddr
{sa
.Addr
[0:]}
198 // ReadFrom implements the net.PacketConn ReadFrom method.
199 func (c
*IPConn
) ReadFrom(b
[]byte) (n
int, addr Addr
, err os
.Error
) {
201 return 0, nil, os
.EINVAL
203 n
, uaddr
, err
:= c
.ReadFromIP(b
)
204 return n
, uaddr
.toAddr(), err
207 // WriteToIP writes a IP packet to addr via c, copying the payload from b.
209 // WriteToIP can be made to time out and return
210 // an error with Timeout() == true after a fixed time limit;
211 // see SetTimeout and SetWriteTimeout.
212 // On packet-oriented connections, write timeouts are rare.
213 func (c
*IPConn
) WriteToIP(b
[]byte, addr
*IPAddr
) (n
int, err os
.Error
) {
217 sa
, err1
:= addr
.sockaddr(c
.fd
.family
)
219 return 0, &OpError
{Op
: "write", Net
: "ip", Addr
: addr
, Error
: err1
}
221 return c
.fd
.WriteTo(b
, sa
)
224 // WriteTo implements the net.PacketConn WriteTo method.
225 func (c
*IPConn
) WriteTo(b
[]byte, addr Addr
) (n
int, err os
.Error
) {
229 a
, ok
:= addr
.(*IPAddr
)
231 return 0, &OpError
{"writeto", "ip", addr
, os
.EINVAL
}
233 return c
.WriteToIP(b
, a
)
236 // Convert "host" into IP address.
237 func hostToIP(host
string) (ip IP
, err os
.Error
) {
239 // Try as an IP address.
242 // Not an IP address. Try as a DNS name.
243 _
, addrs
, err1
:= LookupHost(host
)
248 addr
= ParseIP(addrs
[0])
251 err
= &AddrError
{"LookupHost returned invalid address", addrs
[0]}
263 var protocols
map[string]int
265 func readProtocols() {
266 protocols
= make(map[string]int)
267 if file
, err
:= open("/etc/protocols"); err
== nil {
268 for line
, ok
:= file
.readLine(); ok
; line
, ok
= file
.readLine() {
269 // tcp 6 TCP # transmission control protocol
270 if i
:= byteIndex(line
, '#'); i
>= 0 {
277 if proto
, _
, ok
:= dtoi(f
[1], 0); ok
{
278 protocols
[f
[0]] = proto
279 for _
, alias
:= range f
[2:] {
280 protocols
[alias
] = proto
288 func netProtoSplit(netProto
string) (net
string, proto
int, err os
.Error
) {
289 onceReadProtocols
.Do(readProtocols
)
290 i
:= last(netProto
, ':')
291 if i
< 0 { // no colon
292 return "", 0, os
.ErrorString("no IP protocol specified")
295 protostr
:= netProto
[i
+1:]
296 proto
, i
, ok
:= dtoi(protostr
, 0)
297 if !ok || i
!= len(protostr
) {
299 proto
, ok
= protocols
[protostr
]
307 // DialIP connects to the remote address raddr on the network net,
308 // which must be "ip", "ip4", or "ip6".
309 func DialIP(netProto
string, laddr
, raddr
*IPAddr
) (c
*IPConn
, err os
.Error
) {
310 net
, proto
, err
:= netProtoSplit(netProto
)
314 switch prefixBefore(net
, ':') {
315 case "ip", "ip4", "ip6":
317 return nil, UnknownNetworkError(net
)
320 return nil, &OpError
{"dial", "ip", nil, errMissingAddress
}
322 fd
, e
:= internetSocket(net
, laddr
.toAddr(), raddr
.toAddr(), syscall
.SOCK_RAW
, proto
, "dial", sockaddrToIP
)
326 return newIPConn(fd
), nil
329 // ListenIP listens for incoming IP packets addressed to the
330 // local address laddr. The returned connection c's ReadFrom
331 // and WriteTo methods can be used to receive and send IP
332 // packets with per-packet addressing.
333 func ListenIP(netProto
string, laddr
*IPAddr
) (c
*IPConn
, err os
.Error
) {
334 net
, proto
, err
:= netProtoSplit(netProto
)
338 switch prefixBefore(net
, ':') {
339 case "ip", "ip4", "ip6":
341 return nil, UnknownNetworkError(net
)
343 fd
, e
:= internetSocket(net
, laddr
.toAddr(), nil, syscall
.SOCK_RAW
, proto
, "dial", sockaddrToIP
)
347 return newIPConn(fd
), nil
350 // BindToDevice binds an IPConn to a network interface.
351 func (c
*IPConn
) BindToDevice(device
string) os
.Error
{
357 return os
.NewSyscallError("setsockopt", syscall
.BindToDevice(c
.fd
.sysfd
, device
))