// Copyright 2014 The Go Authors. All rights reserved. // Use of this source code is governed by a BSD-style // license that can be found in the LICENSE file. // +build darwin dragonfly freebsd linux netbsd openbsd solaris package icmp import ( "net" "syscall" ) func sockaddr(family int, address string) (syscall.Sockaddr, error) { switch family { case syscall.AF_INET: a, err := net.ResolveIPAddr("ip4", address) if err != nil { return nil, err } if len(a.IP) == 0 { a.IP = net.IPv4zero } if a.IP = a.IP.To4(); a.IP == nil { return nil, net.InvalidAddrError("non-ipv4 address") } sa := &syscall.SockaddrInet4{} copy(sa.Addr[:], a.IP) return sa, nil case syscall.AF_INET6: a, err := net.ResolveIPAddr("ip6", address) if err != nil { return nil, err } if len(a.IP) == 0 { a.IP = net.IPv6unspecified } if a.IP.Equal(net.IPv4zero) { a.IP = net.IPv6unspecified } if a.IP = a.IP.To16(); a.IP == nil || a.IP.To4() != nil { return nil, net.InvalidAddrError("non-ipv6 address") } sa := &syscall.SockaddrInet6{ZoneId: zoneToUint32(a.Zone)} copy(sa.Addr[:], a.IP) return sa, nil default: return nil, net.InvalidAddrError("unexpected family") } } func zoneToUint32(zone string) uint32 { if zone == "" { return 0 } if ifi, err := net.InterfaceByName(zone); err == nil { return uint32(ifi.Index) } n, _, _ := dtoi(zone, 0) return uint32(n) } func last(s string, b byte) int { i := len(s) for i--; i >= 0; i-- { if s[i] == b { break } } return i } const big = 0xFFFFFF func dtoi(s string, i0 int) (n int, i int, ok bool) { n = 0 for i = i0; i < len(s) && '0' <= s[i] && s[i] <= '9'; i++ { n = n*10 + int(s[i]-'0') if n >= big { return 0, i, false } } if i == i0 { return 0, i, false } return n, i, true }