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 hurd js,wasm 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: zoneCache.name(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: zoneCache.name(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: zoneCache.name(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 (sd *sysDialer) dialIP(ctx context.Context, laddr, raddr *IPAddr) (*IPConn, error) {
116 network, proto, err := parseNetwork(ctx, sd.network, true)
121 case "ip", "ip4", "ip6":
123 return nil, UnknownNetworkError(sd.network)
125 fd, err := internetSocket(ctx, network, laddr, raddr, syscall.SOCK_RAW, proto, "dial", sd.Dialer.Control)
129 return newIPConn(fd), nil
132 func (sl *sysListener) listenIP(ctx context.Context, laddr *IPAddr) (*IPConn, error) {
133 network, proto, err := parseNetwork(ctx, sl.network, true)
138 case "ip", "ip4", "ip6":
140 return nil, UnknownNetworkError(sl.network)
142 fd, err := internetSocket(ctx, network, laddr, nil, syscall.SOCK_RAW, proto, "listen", sl.ListenConfig.Control)
146 return newIPConn(fd), nil