blob: a68bfb010f5608126d37206b610f97d8d67da027 [file] [log] [blame]
David K. Bainbridge215e0242017-09-05 23:18:24 -07001// Copyright 2014 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
5package icmp
6
7import (
8 "net"
9 "runtime"
10 "syscall"
11 "time"
12
13 "golang.org/x/net/ipv4"
14 "golang.org/x/net/ipv6"
15)
16
17var _ net.PacketConn = &PacketConn{}
18
19// A PacketConn represents a packet network endpoint that uses either
20// ICMPv4 or ICMPv6.
21type PacketConn struct {
22 c net.PacketConn
23 p4 *ipv4.PacketConn
24 p6 *ipv6.PacketConn
25}
26
27func (c *PacketConn) ok() bool { return c != nil && c.c != nil }
28
29// IPv4PacketConn returns the ipv4.PacketConn of c.
30// It returns nil when c is not created as the endpoint for ICMPv4.
31func (c *PacketConn) IPv4PacketConn() *ipv4.PacketConn {
32 if !c.ok() {
33 return nil
34 }
35 return c.p4
36}
37
38// IPv6PacketConn returns the ipv6.PacketConn of c.
39// It returns nil when c is not created as the endpoint for ICMPv6.
40func (c *PacketConn) IPv6PacketConn() *ipv6.PacketConn {
41 if !c.ok() {
42 return nil
43 }
44 return c.p6
45}
46
47// ReadFrom reads an ICMP message from the connection.
48func (c *PacketConn) ReadFrom(b []byte) (int, net.Addr, error) {
49 if !c.ok() {
50 return 0, nil, syscall.EINVAL
51 }
52 // Please be informed that ipv4.NewPacketConn enables
53 // IP_STRIPHDR option by default on Darwin.
54 // See golang.org/issue/9395 for further information.
55 if runtime.GOOS == "darwin" && c.p4 != nil {
56 n, _, peer, err := c.p4.ReadFrom(b)
57 return n, peer, err
58 }
59 return c.c.ReadFrom(b)
60}
61
62// WriteTo writes the ICMP message b to dst.
63// Dst must be net.UDPAddr when c is a non-privileged
64// datagram-oriented ICMP endpoint. Otherwise it must be net.IPAddr.
65func (c *PacketConn) WriteTo(b []byte, dst net.Addr) (int, error) {
66 if !c.ok() {
67 return 0, syscall.EINVAL
68 }
69 return c.c.WriteTo(b, dst)
70}
71
72// Close closes the endpoint.
73func (c *PacketConn) Close() error {
74 if !c.ok() {
75 return syscall.EINVAL
76 }
77 return c.c.Close()
78}
79
80// LocalAddr returns the local network address.
81func (c *PacketConn) LocalAddr() net.Addr {
82 if !c.ok() {
83 return nil
84 }
85 return c.c.LocalAddr()
86}
87
88// SetDeadline sets the read and write deadlines associated with the
89// endpoint.
90func (c *PacketConn) SetDeadline(t time.Time) error {
91 if !c.ok() {
92 return syscall.EINVAL
93 }
94 return c.c.SetDeadline(t)
95}
96
97// SetReadDeadline sets the read deadline associated with the
98// endpoint.
99func (c *PacketConn) SetReadDeadline(t time.Time) error {
100 if !c.ok() {
101 return syscall.EINVAL
102 }
103 return c.c.SetReadDeadline(t)
104}
105
106// SetWriteDeadline sets the write deadline associated with the
107// endpoint.
108func (c *PacketConn) SetWriteDeadline(t time.Time) error {
109 if !c.ok() {
110 return syscall.EINVAL
111 }
112 return c.c.SetWriteDeadline(t)
113}