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 aix darwin dragonfly freebsd linux nacl netbsd openbsd solaris 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
) sockaddr(family
int) (syscall
.Sockaddr
, error
) {
38 return ipToSockaddr(family
, a
.IP
, 0, a
.Zone
)
41 func (a
*IPAddr
) toLocal(net
string) sockaddr
{
42 return &IPAddr
{loopbackIP(net
), a
.Zone
}
45 func (c
*IPConn
) readFrom(b
[]byte) (int, *IPAddr
, error
) {
46 // TODO(cw,rsc): consider using readv if we know the family
47 // type to avoid the header trim/copy
49 n
, sa
, err
:= c
.fd
.readFrom(b
)
50 switch sa
:= sa
.(type) {
51 case *syscall
.SockaddrInet4
:
52 addr
= &IPAddr
{IP
: sa
.Addr
[0:]}
53 n
= stripIPv4Header(n
, b
)
54 case *syscall
.SockaddrInet6
:
55 addr
= &IPAddr
{IP
: sa
.Addr
[0:], Zone
: zoneToString(int(sa
.ZoneId
))}
60 func stripIPv4Header(n
int, b
[]byte) int {
64 l
:= int(b
[0]&0x0f) << 2
65 if 20 > l || l
> len(b
) {
75 func (c
*IPConn
) readMsg(b
, oob
[]byte) (n
, oobn
, flags
int, addr
*IPAddr
, err error
) {
76 var sa syscall
.Sockaddr
77 n
, oobn
, flags
, sa
, err
= c
.fd
.readMsg(b
, oob
)
78 switch sa
:= sa
.(type) {
79 case *syscall
.SockaddrInet4
:
80 addr
= &IPAddr
{IP
: sa
.Addr
[0:]}
81 case *syscall
.SockaddrInet6
:
82 addr
= &IPAddr
{IP
: sa
.Addr
[0:], Zone
: zoneToString(int(sa
.ZoneId
))}
87 func (c
*IPConn
) writeTo(b
[]byte, addr
*IPAddr
) (int, error
) {
89 return 0, ErrWriteToConnected
92 return 0, errMissingAddress
94 sa
, err
:= addr
.sockaddr(c
.fd
.family
)
98 return c
.fd
.writeTo(b
, sa
)
101 func (c
*IPConn
) writeMsg(b
, oob
[]byte, addr
*IPAddr
) (n
, oobn
int, err error
) {
102 if c
.fd
.isConnected
{
103 return 0, 0, ErrWriteToConnected
106 return 0, 0, errMissingAddress
108 sa
, err
:= addr
.sockaddr(c
.fd
.family
)
112 return c
.fd
.writeMsg(b
, oob
, sa
)
115 func dialIP(ctx context
.Context
, netProto
string, laddr
, raddr
*IPAddr
) (*IPConn
, error
) {
116 network
, proto
, err
:= parseNetwork(ctx
, netProto
)
121 case "ip", "ip4", "ip6":
123 return nil, UnknownNetworkError(netProto
)
126 return nil, errMissingAddress
128 fd
, err
:= internetSocket(ctx
, network
, laddr
, raddr
, syscall
.SOCK_RAW
, proto
, "dial")
132 return newIPConn(fd
), nil
135 func listenIP(ctx context
.Context
, netProto
string, laddr
*IPAddr
) (*IPConn
, error
) {
136 network
, proto
, err
:= parseNetwork(ctx
, netProto
)
141 case "ip", "ip4", "ip6":
143 return nil, UnknownNetworkError(netProto
)
145 fd
, err
:= internetSocket(ctx
, network
, laddr
, nil, syscall
.SOCK_RAW
, proto
, "listen")
149 return newIPConn(fd
), nil