blob: c4bd0bc06a218cc9277cac5c12d961184b4d863a [file] [log] [blame]
Fazlul Shahriar0f7bc922011-08-17 13:28:29 -04001// Copyright 2009 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
Dave Cheney7c8280c2014-02-25 09:47:42 -05005// +build darwin dragonfly freebsd linux nacl netbsd openbsd solaris windows
Russ Cox27159562011-09-15 16:48:57 -04006
Fazlul Shahriar0f7bc922011-08-17 13:28:29 -04007package net
8
Brad Fitzpatrickef6806f2012-11-08 10:35:16 -06009import (
10 "syscall"
11 "time"
12)
Mikio Hara974fa752012-01-27 01:31:42 +090013
Fazlul Shahriar0f7bc922011-08-17 13:28:29 -040014func sockaddrToUDP(sa syscall.Sockaddr) Addr {
15 switch sa := sa.(type) {
16 case *syscall.SockaddrInet4:
Mikio Harae8cf49f2012-11-27 00:45:42 +090017 return &UDPAddr{IP: sa.Addr[0:], Port: sa.Port}
Fazlul Shahriar0f7bc922011-08-17 13:28:29 -040018 case *syscall.SockaddrInet6:
Mikio Harae8cf49f2012-11-27 00:45:42 +090019 return &UDPAddr{IP: sa.Addr[0:], Port: sa.Port, Zone: zoneToString(int(sa.ZoneId))}
Fazlul Shahriar0f7bc922011-08-17 13:28:29 -040020 }
21 return nil
22}
23
24func (a *UDPAddr) family() int {
Mikio Hara80f79ad2011-08-24 13:59:33 -040025 if a == nil || len(a.IP) <= IPv4len {
Fazlul Shahriar0f7bc922011-08-17 13:28:29 -040026 return syscall.AF_INET
27 }
28 if a.IP.To4() != nil {
29 return syscall.AF_INET
30 }
31 return syscall.AF_INET6
32}
33
Russ Coxeb692922011-11-01 22:05:34 -040034func (a *UDPAddr) sockaddr(family int) (syscall.Sockaddr, error) {
Mikio Hara8a7def22013-08-03 13:32:22 +090035 if a == nil {
36 return nil, nil
37 }
Mikio Harae8cf49f2012-11-27 00:45:42 +090038 return ipToSockaddr(family, a.IP, a.Port, a.Zone)
Fazlul Shahriar0f7bc922011-08-17 13:28:29 -040039}
40
Mikio Harae2c453e2013-03-31 16:47:54 +090041// UDPConn is the implementation of the Conn and PacketConn interfaces
42// for UDP network connections.
Fazlul Shahriar0f7bc922011-08-17 13:28:29 -040043type UDPConn struct {
Dave Cheneyf72c8282012-04-27 22:17:08 +100044 conn
Fazlul Shahriar0f7bc922011-08-17 13:28:29 -040045}
46
Dave Cheneyf72c8282012-04-27 22:17:08 +100047func newUDPConn(fd *netFD) *UDPConn { return &UDPConn{conn{fd}} }
Fazlul Shahriar0f7bc922011-08-17 13:28:29 -040048
Fazlul Shahriar0f7bc922011-08-17 13:28:29 -040049// ReadFromUDP reads a UDP packet from c, copying the payload into b.
50// It returns the number of bytes copied into b and the return address
51// that was on the packet.
52//
Mikio Harae2c453e2013-03-31 16:47:54 +090053// ReadFromUDP can be made to time out and return an error with
54// Timeout() == true after a fixed time limit; see SetDeadline and
55// SetReadDeadline.
Mikio Haraec114442015-04-16 23:10:56 +090056func (c *UDPConn) ReadFromUDP(b []byte) (int, *UDPAddr, error) {
Fazlul Shahriar0f7bc922011-08-17 13:28:29 -040057 if !c.ok() {
Rob Pike56069f02012-02-17 10:04:29 +110058 return 0, nil, syscall.EINVAL
Fazlul Shahriar0f7bc922011-08-17 13:28:29 -040059 }
Mikio Haraec114442015-04-16 23:10:56 +090060 var addr *UDPAddr
Ian Lance Taylor7d299d02014-04-02 17:06:51 -070061 n, sa, err := c.fd.readFrom(b)
Fazlul Shahriar0f7bc922011-08-17 13:28:29 -040062 switch sa := sa.(type) {
63 case *syscall.SockaddrInet4:
Mikio Harae8cf49f2012-11-27 00:45:42 +090064 addr = &UDPAddr{IP: sa.Addr[0:], Port: sa.Port}
Fazlul Shahriar0f7bc922011-08-17 13:28:29 -040065 case *syscall.SockaddrInet6:
Mikio Harae8cf49f2012-11-27 00:45:42 +090066 addr = &UDPAddr{IP: sa.Addr[0:], Port: sa.Port, Zone: zoneToString(int(sa.ZoneId))}
Fazlul Shahriar0f7bc922011-08-17 13:28:29 -040067 }
Mikio Haraec114442015-04-16 23:10:56 +090068 if err != nil {
69 err = &OpError{Op: "read", Net: c.fd.net, Addr: c.fd.laddr, Err: err}
70 }
71 return n, addr, err
Fazlul Shahriar0f7bc922011-08-17 13:28:29 -040072}
73
Mikio Hara3d400db2012-01-29 19:11:05 +090074// ReadFrom implements the PacketConn ReadFrom method.
Mikio Hara2f63afd2012-02-01 01:53:26 +090075func (c *UDPConn) ReadFrom(b []byte) (int, Addr, error) {
Fazlul Shahriar0f7bc922011-08-17 13:28:29 -040076 if !c.ok() {
Rob Pike56069f02012-02-17 10:04:29 +110077 return 0, nil, syscall.EINVAL
Fazlul Shahriar0f7bc922011-08-17 13:28:29 -040078 }
Mikio Harae8cf49f2012-11-27 00:45:42 +090079 n, addr, err := c.ReadFromUDP(b)
Paul Marksa5dec382015-04-01 15:17:09 -070080 if addr == nil {
81 return n, nil, err
82 }
83 return n, addr, err
Fazlul Shahriar0f7bc922011-08-17 13:28:29 -040084}
85
Mikio Hara4b9e8412012-09-25 06:57:32 +090086// ReadMsgUDP reads a packet from c, copying the payload into b and
Robert Griesemer0ad265d2013-03-20 16:32:37 -070087// the associated out-of-band data into oob. It returns the number
Mikio Hara4b9e8412012-09-25 06:57:32 +090088// of bytes copied into b, the number of bytes copied into oob, the
89// flags that were set on the packet and the source address of the
90// packet.
91func (c *UDPConn) ReadMsgUDP(b, oob []byte) (n, oobn, flags int, addr *UDPAddr, err error) {
92 if !c.ok() {
93 return 0, 0, 0, nil, syscall.EINVAL
94 }
95 var sa syscall.Sockaddr
Ian Lance Taylor7d299d02014-04-02 17:06:51 -070096 n, oobn, flags, sa, err = c.fd.readMsg(b, oob)
Mikio Hara4b9e8412012-09-25 06:57:32 +090097 switch sa := sa.(type) {
98 case *syscall.SockaddrInet4:
Mikio Harae8cf49f2012-11-27 00:45:42 +090099 addr = &UDPAddr{IP: sa.Addr[0:], Port: sa.Port}
Mikio Hara4b9e8412012-09-25 06:57:32 +0900100 case *syscall.SockaddrInet6:
Mikio Harae8cf49f2012-11-27 00:45:42 +0900101 addr = &UDPAddr{IP: sa.Addr[0:], Port: sa.Port, Zone: zoneToString(int(sa.ZoneId))}
Mikio Hara4b9e8412012-09-25 06:57:32 +0900102 }
Mikio Haraec114442015-04-16 23:10:56 +0900103 if err != nil {
104 err = &OpError{Op: "read", Net: c.fd.net, Addr: c.fd.laddr, Err: err}
105 }
Mikio Hara4b9e8412012-09-25 06:57:32 +0900106 return
107}
108
Mikio Harae2c453e2013-03-31 16:47:54 +0900109// WriteToUDP writes a UDP packet to addr via c, copying the payload
110// from b.
Fazlul Shahriar0f7bc922011-08-17 13:28:29 -0400111//
Mikio Harae2c453e2013-03-31 16:47:54 +0900112// WriteToUDP can be made to time out and return an error with
113// Timeout() == true after a fixed time limit; see SetDeadline and
114// SetWriteDeadline. On packet-oriented connections, write timeouts
115// are rare.
Mikio Hara77cb8952012-01-24 02:59:43 +0900116func (c *UDPConn) WriteToUDP(b []byte, addr *UDPAddr) (int, error) {
Fazlul Shahriar0f7bc922011-08-17 13:28:29 -0400117 if !c.ok() {
Rob Pike56069f02012-02-17 10:04:29 +1100118 return 0, syscall.EINVAL
Fazlul Shahriar0f7bc922011-08-17 13:28:29 -0400119 }
Mikio Hara974fa752012-01-27 01:31:42 +0900120 if c.fd.isConnected {
Mikio Hara11b5f982015-04-16 11:26:44 +0900121 return 0, &OpError{Op: "write", Net: c.fd.net, Addr: addr, Err: ErrWriteToConnected}
Mikio Hara974fa752012-01-27 01:31:42 +0900122 }
Mikio Hara7917b882013-08-18 19:19:36 +0900123 if addr == nil {
124 return 0, &OpError{Op: "write", Net: c.fd.net, Addr: nil, Err: errMissingAddress}
125 }
Mikio Hara77cb8952012-01-24 02:59:43 +0900126 sa, err := addr.sockaddr(c.fd.family)
127 if err != nil {
Mikio Hara11b5f982015-04-16 11:26:44 +0900128 return 0, &OpError{Op: "write", Net: c.fd.net, Addr: addr, Err: err}
Fazlul Shahriar0f7bc922011-08-17 13:28:29 -0400129 }
Mikio Hara11b5f982015-04-16 11:26:44 +0900130 n, err := c.fd.writeTo(b, sa)
131 if err != nil {
132 err = &OpError{Op: "write", Net: c.fd.net, Addr: addr, Err: err}
133 }
134 return n, err
Fazlul Shahriar0f7bc922011-08-17 13:28:29 -0400135}
136
Mikio Hara3d400db2012-01-29 19:11:05 +0900137// WriteTo implements the PacketConn WriteTo method.
Mikio Hara77cb8952012-01-24 02:59:43 +0900138func (c *UDPConn) WriteTo(b []byte, addr Addr) (int, error) {
Fazlul Shahriar0f7bc922011-08-17 13:28:29 -0400139 if !c.ok() {
Rob Pike56069f02012-02-17 10:04:29 +1100140 return 0, syscall.EINVAL
Fazlul Shahriar0f7bc922011-08-17 13:28:29 -0400141 }
142 a, ok := addr.(*UDPAddr)
143 if !ok {
Mikio Hara11b5f982015-04-16 11:26:44 +0900144 return 0, &OpError{Op: "write", Net: c.fd.net, Addr: addr, Err: syscall.EINVAL}
Fazlul Shahriar0f7bc922011-08-17 13:28:29 -0400145 }
146 return c.WriteToUDP(b, a)
147}
148
Nicolas S. Dade263405e2015-02-04 18:05:53 -0800149// WriteMsgUDP writes a packet to addr via c if c isn't connected, or
150// to c's remote destination address if c is connected (in which case
151// addr must be nil). The payload is copied from b and the associated
152// out-of-band data is copied from oob. It returns the number of
153// payload and out-of-band bytes written.
Mikio Hara4b9e8412012-09-25 06:57:32 +0900154func (c *UDPConn) WriteMsgUDP(b, oob []byte, addr *UDPAddr) (n, oobn int, err error) {
155 if !c.ok() {
156 return 0, 0, syscall.EINVAL
157 }
Nicolas S. Dade263405e2015-02-04 18:05:53 -0800158 if c.fd.isConnected && addr != nil {
Mikio Hara11b5f982015-04-16 11:26:44 +0900159 return 0, 0, &OpError{Op: "write", Net: c.fd.net, Addr: addr, Err: ErrWriteToConnected}
Mikio Hara4b9e8412012-09-25 06:57:32 +0900160 }
Nicolas S. Dade263405e2015-02-04 18:05:53 -0800161 if !c.fd.isConnected && addr == nil {
Mikio Hara7917b882013-08-18 19:19:36 +0900162 return 0, 0, &OpError{Op: "write", Net: c.fd.net, Addr: nil, Err: errMissingAddress}
163 }
Mikio Hara11b5f982015-04-16 11:26:44 +0900164 var sa syscall.Sockaddr
165 sa, err = addr.sockaddr(c.fd.family)
Mikio Hara4b9e8412012-09-25 06:57:32 +0900166 if err != nil {
Mikio Hara11b5f982015-04-16 11:26:44 +0900167 return 0, 0, &OpError{Op: "write", Net: c.fd.net, Addr: addr, Err: err}
Mikio Hara4b9e8412012-09-25 06:57:32 +0900168 }
Mikio Hara11b5f982015-04-16 11:26:44 +0900169 n, oobn, err = c.fd.writeMsg(b, oob, sa)
170 if err != nil {
171 err = &OpError{Op: "write", Net: c.fd.net, Addr: addr, Err: err}
172 }
173 return
Mikio Hara4b9e8412012-09-25 06:57:32 +0900174}
175
Fazlul Shahriar0f7bc922011-08-17 13:28:29 -0400176// DialUDP connects to the remote address raddr on the network net,
Mikio Harae2c453e2013-03-31 16:47:54 +0900177// which must be "udp", "udp4", or "udp6". If laddr is not nil, it is
178// used as the local address for the connection.
Mikio Hara28397be2012-02-01 00:36:45 +0900179func DialUDP(net string, laddr, raddr *UDPAddr) (*UDPConn, error) {
Fazlul Shahriar0f7bc922011-08-17 13:28:29 -0400180 switch net {
181 case "udp", "udp4", "udp6":
182 default:
Mikio Harae4bb1392013-08-28 19:51:02 +0900183 return nil, &OpError{Op: "dial", Net: net, Addr: raddr, Err: UnknownNetworkError(net)}
Fazlul Shahriar0f7bc922011-08-17 13:28:29 -0400184 }
185 if raddr == nil {
Mikio Harae4bb1392013-08-28 19:51:02 +0900186 return nil, &OpError{Op: "dial", Net: net, Addr: nil, Err: errMissingAddress}
Fazlul Shahriar0f7bc922011-08-17 13:28:29 -0400187 }
Mikio Hara3b961bf2013-08-22 10:33:06 +0900188 return dialUDP(net, laddr, raddr, noDeadline)
189}
190
191func dialUDP(net string, laddr, raddr *UDPAddr, deadline time.Time) (*UDPConn, error) {
Mikio Hara5c055e72014-08-05 06:10:46 +0900192 fd, err := internetSocket(net, laddr, raddr, deadline, syscall.SOCK_DGRAM, 0, "dial")
Mikio Hara28397be2012-02-01 00:36:45 +0900193 if err != nil {
Mikio Harae4bb1392013-08-28 19:51:02 +0900194 return nil, &OpError{Op: "dial", Net: net, Addr: raddr, Err: err}
Fazlul Shahriar0f7bc922011-08-17 13:28:29 -0400195 }
196 return newUDPConn(fd), nil
197}
198
Mikio Hara245dc622013-03-29 15:06:43 +0900199// ListenUDP listens for incoming UDP packets addressed to the local
200// address laddr. Net must be "udp", "udp4", or "udp6". If laddr has
201// a port of 0, ListenUDP will choose an available port.
202// The LocalAddr method of the returned UDPConn can be used to
203// discover the port. The returned connection's ReadFrom and WriteTo
204// methods can be used to receive and send UDP packets with per-packet
205// addressing.
Mikio Hara77cb8952012-01-24 02:59:43 +0900206func ListenUDP(net string, laddr *UDPAddr) (*UDPConn, error) {
Fazlul Shahriar0f7bc922011-08-17 13:28:29 -0400207 switch net {
208 case "udp", "udp4", "udp6":
209 default:
Mikio Harae4bb1392013-08-28 19:51:02 +0900210 return nil, &OpError{Op: "listen", Net: net, Addr: laddr, Err: UnknownNetworkError(net)}
Fazlul Shahriar0f7bc922011-08-17 13:28:29 -0400211 }
212 if laddr == nil {
Mikio Hara677c6e62012-11-13 12:56:28 +0900213 laddr = &UDPAddr{}
Fazlul Shahriar0f7bc922011-08-17 13:28:29 -0400214 }
Mikio Hara5c055e72014-08-05 06:10:46 +0900215 fd, err := internetSocket(net, laddr, nil, noDeadline, syscall.SOCK_DGRAM, 0, "listen")
Mikio Hara77cb8952012-01-24 02:59:43 +0900216 if err != nil {
Mikio Harae4bb1392013-08-28 19:51:02 +0900217 return nil, &OpError{Op: "listen", Net: net, Addr: laddr, Err: err}
Fazlul Shahriar0f7bc922011-08-17 13:28:29 -0400218 }
219 return newUDPConn(fd), nil
220}
221
Mikio Hara2f63afd2012-02-01 01:53:26 +0900222// ListenMulticastUDP listens for incoming multicast UDP packets
Mikio Harae2c453e2013-03-31 16:47:54 +0900223// addressed to the group address gaddr on ifi, which specifies the
224// interface to join. ListenMulticastUDP uses default multicast
225// interface if ifi is nil.
Mikio Hara2f63afd2012-02-01 01:53:26 +0900226func ListenMulticastUDP(net string, ifi *Interface, gaddr *UDPAddr) (*UDPConn, error) {
227 switch net {
228 case "udp", "udp4", "udp6":
229 default:
Mikio Harae4bb1392013-08-28 19:51:02 +0900230 return nil, &OpError{Op: "listen", Net: net, Addr: gaddr, Err: UnknownNetworkError(net)}
Fazlul Shahriar0f7bc922011-08-17 13:28:29 -0400231 }
Mikio Hara2f63afd2012-02-01 01:53:26 +0900232 if gaddr == nil || gaddr.IP == nil {
Mikio Harae4bb1392013-08-28 19:51:02 +0900233 return nil, &OpError{Op: "listen", Net: net, Addr: nil, Err: errMissingAddress}
Fazlul Shahriar0f7bc922011-08-17 13:28:29 -0400234 }
Mikio Hara5c055e72014-08-05 06:10:46 +0900235 fd, err := internetSocket(net, gaddr, nil, noDeadline, syscall.SOCK_DGRAM, 0, "listen")
Mikio Hara2f63afd2012-02-01 01:53:26 +0900236 if err != nil {
Mikio Harae4bb1392013-08-28 19:51:02 +0900237 return nil, &OpError{Op: "listen", Net: net, Addr: gaddr, Err: err}
Mikio Hara2f63afd2012-02-01 01:53:26 +0900238 }
239 c := newUDPConn(fd)
Mikio Hara6d725e92013-01-15 08:53:12 +0900240 if ip4 := gaddr.IP.To4(); ip4 != nil {
241 if err := listenIPv4MulticastUDP(c, ifi, ip4); err != nil {
Mikio Hara2f63afd2012-02-01 01:53:26 +0900242 c.Close()
Mikio Harae4bb1392013-08-28 19:51:02 +0900243 return nil, &OpError{Op: "listen", Net: net, Addr: &IPAddr{IP: ip4}, Err: err}
Mikio Hara2f63afd2012-02-01 01:53:26 +0900244 }
245 } else {
Mikio Hara6d725e92013-01-15 08:53:12 +0900246 if err := listenIPv6MulticastUDP(c, ifi, gaddr.IP); err != nil {
Mikio Hara2f63afd2012-02-01 01:53:26 +0900247 c.Close()
Mikio Harae4bb1392013-08-28 19:51:02 +0900248 return nil, &OpError{Op: "listen", Net: net, Addr: &IPAddr{IP: gaddr.IP}, Err: err}
Mikio Hara2f63afd2012-02-01 01:53:26 +0900249 }
250 }
251 return c, nil
Mikio Harafca50822011-08-18 12:22:02 -0400252}
253
Mikio Hara2f63afd2012-02-01 01:53:26 +0900254func listenIPv4MulticastUDP(c *UDPConn, ifi *Interface, ip IP) error {
255 if ifi != nil {
Mikio Hara6d725e92013-01-15 08:53:12 +0900256 if err := setIPv4MulticastInterface(c.fd, ifi); err != nil {
Mikio Hara2f63afd2012-02-01 01:53:26 +0900257 return err
258 }
Fazlul Shahriar0f7bc922011-08-17 13:28:29 -0400259 }
Mikio Hara6d725e92013-01-15 08:53:12 +0900260 if err := setIPv4MulticastLoopback(c.fd, false); err != nil {
Mikio Hara2f63afd2012-02-01 01:53:26 +0900261 return err
Mikio Harafca50822011-08-18 12:22:02 -0400262 }
Mikio Hara6d725e92013-01-15 08:53:12 +0900263 if err := joinIPv4Group(c.fd, ifi, ip); err != nil {
Mikio Hara2f63afd2012-02-01 01:53:26 +0900264 return err
265 }
266 return nil
267}
268
269func listenIPv6MulticastUDP(c *UDPConn, ifi *Interface, ip IP) error {
270 if ifi != nil {
Mikio Hara6d725e92013-01-15 08:53:12 +0900271 if err := setIPv6MulticastInterface(c.fd, ifi); err != nil {
Mikio Hara2f63afd2012-02-01 01:53:26 +0900272 return err
273 }
274 }
Mikio Hara6d725e92013-01-15 08:53:12 +0900275 if err := setIPv6MulticastLoopback(c.fd, false); err != nil {
Mikio Hara2f63afd2012-02-01 01:53:26 +0900276 return err
277 }
Mikio Hara6d725e92013-01-15 08:53:12 +0900278 if err := joinIPv6Group(c.fd, ifi, ip); err != nil {
Mikio Hara2f63afd2012-02-01 01:53:26 +0900279 return err
280 }
281 return nil
Mikio Harafca50822011-08-18 12:22:02 -0400282}