...
1
2
3
4
5
6
7 package icmp
8
9 import (
10 "net"
11 "strconv"
12 "syscall"
13 )
14
15 func 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
53 func 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
67 func 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 }
76
View as plain text