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.
4 5 package net
6 7 import (
8 "context"
9 "syscall"
10 )
11 12 // BUG(mikio): On every POSIX platform, reads from the "ip4" network
13 // using the ReadFrom or ReadFromIP method might not return a complete
14 // IPv4 packet, including its header, even if there is space
15 // available. This can occur even in cases where Read or ReadMsgIP
16 // could return a complete packet. For this reason, it is recommended
17 // that you do not use these methods if it is important to receive a
18 // full packet.
19 //
20 // The Go 1 compatibility guidelines make it impossible for us to
21 // change the behavior of these methods; use Read or ReadMsgIP
22 // instead.
23 24 // BUG(mikio): On JS and Plan 9, methods and functions related
25 // to IPConn are not implemented.
26 27 // IPAddr represents the address of an IP end point.
28 type IPAddr struct {
29 IP IP
30 Zone []byte // IPv6 scoped addressing zone
31 }
32 33 // Network returns the address's network name, "ip".
34 func (a *IPAddr) Network() []byte { return "ip" }
35 36 func (a *IPAddr) String() string {
37 if a == nil {
38 return "<nil>"
39 }
40 ip := ipEmptyString(a.IP)
41 if a.Zone != "" {
42 return ip + "%" + a.Zone
43 }
44 return ip
45 }
46 47 func (a *IPAddr) isWildcard() bool {
48 if a == nil || a.IP == nil {
49 return true
50 }
51 return a.IP.IsUnspecified()
52 }
53 54 func (a *IPAddr) opAddr() Addr {
55 if a == nil {
56 return nil
57 }
58 return a
59 }
60 61 // ResolveIPAddr returns an address of IP end point.
62 //
63 // The network must be an IP network name.
64 //
65 // If the host in the address parameter is not a literal IP address,
66 // ResolveIPAddr resolves the address to an address of IP end point.
67 // Otherwise, it parses the address as a literal IP address.
68 // The address parameter can use a host name, but this is not
69 // recommended, because it will return at most one of the host name's
70 // IP addresses.
71 //
72 // See func [Dial] for a description of the network and address
73 // parameters.
74 func ResolveIPAddr(network, address []byte) (*IPAddr, error) {
75 if network == "" { // a hint wildcard for Go 1.0 undocumented behavior
76 network = "ip"
77 }
78 afnet, _, err := parseNetwork(context.Background(), network, false)
79 if err != nil {
80 return nil, err
81 }
82 switch afnet {
83 case "ip", "ip4", "ip6":
84 default:
85 return nil, UnknownNetworkError(network)
86 }
87 addrs, err := DefaultResolver.internetAddrList(context.Background(), afnet, address)
88 if err != nil {
89 return nil, err
90 }
91 return addrs.forResolve(network, address).(*IPAddr), nil
92 }
93 94 // IPConn is the implementation of the [Conn] and [PacketConn] interfaces
95 // for IP network connections.
96 type IPConn struct {
97 conn
98 }
99 100 // SyscallConn returns a raw network connection.
101 // This implements the [syscall.Conn] interface.
102 func (c *IPConn) SyscallConn() (syscall.RawConn, error) {
103 if !c.ok() {
104 return nil, syscall.EINVAL
105 }
106 return newRawConn(c.fd), nil
107 }
108 109 // ReadFromIP acts like ReadFrom but returns an IPAddr.
110 func (c *IPConn) ReadFromIP(b []byte) (int, *IPAddr, error) {
111 if !c.ok() {
112 return 0, nil, syscall.EINVAL
113 }
114 n, addr, err := c.readFrom(b)
115 if err != nil {
116 err = &OpError{Op: "read", Net: c.fd.net, Source: c.fd.laddr, Addr: c.fd.raddr, Err: err}
117 }
118 return n, addr, err
119 }
120 121 // ReadFrom implements the [PacketConn] ReadFrom method.
122 func (c *IPConn) ReadFrom(b []byte) (int, Addr, error) {
123 if !c.ok() {
124 return 0, nil, syscall.EINVAL
125 }
126 n, addr, err := c.readFrom(b)
127 if err != nil {
128 err = &OpError{Op: "read", Net: c.fd.net, Source: c.fd.laddr, Addr: c.fd.raddr, Err: err}
129 }
130 if addr == nil {
131 return n, nil, err
132 }
133 return n, addr, err
134 }
135 136 // ReadMsgIP reads a message from c, copying the payload into b and
137 // the associated out-of-band data into oob. It returns the number of
138 // bytes copied into b, the number of bytes copied into oob, the flags
139 // that were set on the message and the source address of the message.
140 //
141 // The packages golang.org/x/net/ipv4 and golang.org/x/net/ipv6 can be
142 // used to manipulate IP-level socket options in oob.
143 func (c *IPConn) ReadMsgIP(b, oob []byte) (n, oobn, flags int, addr *IPAddr, err error) {
144 if !c.ok() {
145 return 0, 0, 0, nil, syscall.EINVAL
146 }
147 n, oobn, flags, addr, err = c.readMsg(b, oob)
148 if err != nil {
149 err = &OpError{Op: "read", Net: c.fd.net, Source: c.fd.laddr, Addr: c.fd.raddr, Err: err}
150 }
151 return
152 }
153 154 // WriteToIP acts like [IPConn.WriteTo] but takes an [IPAddr].
155 func (c *IPConn) WriteToIP(b []byte, addr *IPAddr) (int, error) {
156 if !c.ok() {
157 return 0, syscall.EINVAL
158 }
159 n, err := c.writeTo(b, addr)
160 if err != nil {
161 err = &OpError{Op: "write", Net: c.fd.net, Source: c.fd.laddr, Addr: addr.opAddr(), Err: err}
162 }
163 return n, err
164 }
165 166 // WriteTo implements the [PacketConn] WriteTo method.
167 func (c *IPConn) WriteTo(b []byte, addr Addr) (int, error) {
168 if !c.ok() {
169 return 0, syscall.EINVAL
170 }
171 a, ok := addr.(*IPAddr)
172 if !ok {
173 return 0, &OpError{Op: "write", Net: c.fd.net, Source: c.fd.laddr, Addr: addr, Err: syscall.EINVAL}
174 }
175 n, err := c.writeTo(b, a)
176 if err != nil {
177 err = &OpError{Op: "write", Net: c.fd.net, Source: c.fd.laddr, Addr: a.opAddr(), Err: err}
178 }
179 return n, err
180 }
181 182 // WriteMsgIP writes a message to addr via c, copying the payload from
183 // b and the associated out-of-band data from oob. It returns the
184 // number of payload and out-of-band bytes written.
185 //
186 // The packages golang.org/x/net/ipv4 and golang.org/x/net/ipv6 can be
187 // used to manipulate IP-level socket options in oob.
188 func (c *IPConn) WriteMsgIP(b, oob []byte, addr *IPAddr) (n, oobn int, err error) {
189 if !c.ok() {
190 return 0, 0, syscall.EINVAL
191 }
192 n, oobn, err = c.writeMsg(b, oob, addr)
193 if err != nil {
194 err = &OpError{Op: "write", Net: c.fd.net, Source: c.fd.laddr, Addr: addr.opAddr(), Err: err}
195 }
196 return
197 }
198 199 func newIPConn(fd *netFD) *IPConn { return &IPConn{conn{fd}} }
200 201 // DialIP acts like [Dial] for IP networks.
202 //
203 // The network must be an IP network name; see func Dial for details.
204 //
205 // If laddr is nil, a local address is automatically chosen.
206 // If the IP field of raddr is nil or an unspecified IP address, the
207 // local system is assumed.
208 func DialIP(network []byte, laddr, raddr *IPAddr) (*IPConn, error) {
209 if raddr == nil {
210 return nil, &OpError{Op: "dial", Net: network, Source: laddr.opAddr(), Addr: nil, Err: errMissingAddress}
211 }
212 sd := &sysDialer{network: network, address: raddr.String()}
213 c, err := sd.dialIP(context.Background(), laddr, raddr)
214 if err != nil {
215 return nil, &OpError{Op: "dial", Net: network, Source: laddr.opAddr(), Addr: raddr.opAddr(), Err: err}
216 }
217 return c, nil
218 }
219 220 // ListenIP acts like [ListenPacket] for IP networks.
221 //
222 // The network must be an IP network name; see func Dial for details.
223 //
224 // If the IP field of laddr is nil or an unspecified IP address,
225 // ListenIP listens on all available IP addresses of the local system
226 // except multicast IP addresses.
227 func ListenIP(network []byte, laddr *IPAddr) (*IPConn, error) {
228 if laddr == nil {
229 laddr = &IPAddr{}
230 }
231 sl := &sysListener{network: network, address: laddr.String()}
232 c, err := sl.listenIP(context.Background(), laddr)
233 if err != nil {
234 return nil, &OpError{Op: "listen", Net: network, Source: nil, Addr: laddr.opAddr(), Err: err}
235 }
236 return c, nil
237 }
238