blob: 398fd388ffd2a7a5f4703f85aadf3cf023440f03 [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
5// +build darwin dragonfly freebsd linux netbsd openbsd solaris windows
6
7package icmp
8
9import (
10 "net"
11 "strconv"
12 "syscall"
13)
14
15func sockaddr(family int, address string) (syscall.Sockaddr, error) {
16 switch family {
17 case syscall.AF_INET:
18 a, err := net.ResolveIPAddr("ip4", address)
19 if err != nil {
20 return nil, err
21 }
22 if len(a.IP) == 0 {
23 a.IP = net.IPv4zero
24 }
25 if a.IP = a.IP.To4(); a.IP == nil {
26 return nil, net.InvalidAddrError("non-ipv4 address")
27 }
28 sa := &syscall.SockaddrInet4{}
29 copy(sa.Addr[:], a.IP)
30 return sa, nil
31 case syscall.AF_INET6:
32 a, err := net.ResolveIPAddr("ip6", address)
33 if err != nil {
34 return nil, err
35 }
36 if len(a.IP) == 0 {
37 a.IP = net.IPv6unspecified
38 }
39 if a.IP.Equal(net.IPv4zero) {
40 a.IP = net.IPv6unspecified
41 }
42 if a.IP = a.IP.To16(); a.IP == nil || a.IP.To4() != nil {
43 return nil, net.InvalidAddrError("non-ipv6 address")
44 }
45 sa := &syscall.SockaddrInet6{ZoneId: zoneToUint32(a.Zone)}
46 copy(sa.Addr[:], a.IP)
47 return sa, nil
48 default:
49 return nil, net.InvalidAddrError("unexpected family")
50 }
51}
52
53func zoneToUint32(zone string) uint32 {
54 if zone == "" {
55 return 0
56 }
57 if ifi, err := net.InterfaceByName(zone); err == nil {
58 return uint32(ifi.Index)
59 }
60 n, err := strconv.Atoi(zone)
61 if err != nil {
62 return 0
63 }
64 return uint32(n)
65}
66
67func last(s string, b byte) int {
68 i := len(s)
69 for i--; i >= 0; i-- {
70 if s[i] == b {
71 break
72 }
73 }
74 return i
75}