~nskaggs/+junk/xenial-test

« back to all changes in this revision

Viewing changes to src/golang.org/x/net/icmp/listen_posix.go

  • Committer: Nicholas Skaggs
  • Date: 2016-10-24 20:56:05 UTC
  • Revision ID: nicholas.skaggs@canonical.com-20161024205605-z8lta0uvuhtxwzwl
Initi with beta15

Show diffs side-by-side

added added

removed removed

Lines of Context:
 
1
// 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
 
 
5
// +build darwin dragonfly freebsd linux netbsd openbsd solaris windows
 
6
 
 
7
package icmp
 
8
 
 
9
import (
 
10
        "net"
 
11
        "os"
 
12
        "runtime"
 
13
        "syscall"
 
14
 
 
15
        "golang.org/x/net/internal/iana"
 
16
        "golang.org/x/net/ipv4"
 
17
        "golang.org/x/net/ipv6"
 
18
)
 
19
 
 
20
const sysIP_STRIPHDR = 0x17 // for now only darwin supports this option
 
21
 
 
22
// ListenPacket listens for incoming ICMP packets addressed to
 
23
// address. See net.Dial for the syntax of address.
 
24
//
 
25
// For non-privileged datagram-oriented ICMP endpoints, network must
 
26
// be "udp4" or "udp6". The endpoint allows to read, write a few
 
27
// limited ICMP messages such as echo request and echo reply.
 
28
// Currently only Darwin and Linux support this.
 
29
//
 
30
// Examples:
 
31
//      ListenPacket("udp4", "192.168.0.1")
 
32
//      ListenPacket("udp4", "0.0.0.0")
 
33
//      ListenPacket("udp6", "fe80::1%en0")
 
34
//      ListenPacket("udp6", "::")
 
35
//
 
36
// For privileged raw ICMP endpoints, network must be "ip4" or "ip6"
 
37
// followed by a colon and an ICMP protocol number or name.
 
38
//
 
39
// Examples:
 
40
//      ListenPacket("ip4:icmp", "192.168.0.1")
 
41
//      ListenPacket("ip4:1", "0.0.0.0")
 
42
//      ListenPacket("ip6:ipv6-icmp", "fe80::1%en0")
 
43
//      ListenPacket("ip6:58", "::")
 
44
func ListenPacket(network, address string) (*PacketConn, error) {
 
45
        var family, proto int
 
46
        switch network {
 
47
        case "udp4":
 
48
                family, proto = syscall.AF_INET, iana.ProtocolICMP
 
49
        case "udp6":
 
50
                family, proto = syscall.AF_INET6, iana.ProtocolIPv6ICMP
 
51
        default:
 
52
                i := last(network, ':')
 
53
                switch network[:i] {
 
54
                case "ip4":
 
55
                        proto = iana.ProtocolICMP
 
56
                case "ip6":
 
57
                        proto = iana.ProtocolIPv6ICMP
 
58
                }
 
59
        }
 
60
        var cerr error
 
61
        var c net.PacketConn
 
62
        switch family {
 
63
        case syscall.AF_INET, syscall.AF_INET6:
 
64
                s, err := syscall.Socket(family, syscall.SOCK_DGRAM, proto)
 
65
                if err != nil {
 
66
                        return nil, os.NewSyscallError("socket", err)
 
67
                }
 
68
                defer syscall.Close(s)
 
69
                if runtime.GOOS == "darwin" && family == syscall.AF_INET {
 
70
                        if err := syscall.SetsockoptInt(s, iana.ProtocolIP, sysIP_STRIPHDR, 1); err != nil {
 
71
                                return nil, os.NewSyscallError("setsockopt", err)
 
72
                        }
 
73
                }
 
74
                sa, err := sockaddr(family, address)
 
75
                if err != nil {
 
76
                        return nil, err
 
77
                }
 
78
                if err := syscall.Bind(s, sa); err != nil {
 
79
                        return nil, os.NewSyscallError("bind", err)
 
80
                }
 
81
                f := os.NewFile(uintptr(s), "datagram-oriented icmp")
 
82
                defer f.Close()
 
83
                c, cerr = net.FilePacketConn(f)
 
84
        default:
 
85
                c, cerr = net.ListenPacket(network, address)
 
86
        }
 
87
        if cerr != nil {
 
88
                return nil, cerr
 
89
        }
 
90
        switch proto {
 
91
        case iana.ProtocolICMP:
 
92
                return &PacketConn{c: c, ipc: ipv4.NewPacketConn(c)}, nil
 
93
        case iana.ProtocolIPv6ICMP:
 
94
                return &PacketConn{c: c, ipc: ipv6.NewPacketConn(c)}, nil
 
95
        default:
 
96
                return &PacketConn{c: c}, nil
 
97
        }
 
98
}