| 123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494495496497498499500501502503504505506507508509510511512513514515516517518519520521522523524525526527528529530531532533534535536537538539540541542543544545546547548549550551552553554555556557558559560561562563564565566567568569570571572573574575576577578579580581582583584585586587588589590591592593594595596597598599600601602603604605606607608609610611612613614615616617618619620621622623624625626627628629630631632633634635636637638639640641642643644645646647648649650651652653654655656657658659660661662663664665666667668669670671672673674675676677678679680681682683684685686687688689690691692693694695696697698699700701702703704705706707708709710711712713714715716717718719720721722723724725726727728729730731732733734735736737738739740741742743744745746747748749750751752753754755756757758759760761762763764765766767768769770771772773774775776777778779780781782783784785786787788789790791792793794795796 |
- // Copyright 2019 Yunion
- //
- // Licensed under the Apache License, Version 2.0 (the "License");
- // you may not use this file except in compliance with the License.
- // You may obtain a copy of the License at
- //
- // http://www.apache.org/licenses/LICENSE-2.0
- //
- // Unless required by applicable law or agreed to in writing, software
- // distributed under the License is distributed on an "AS IS" BASIS,
- // WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
- // See the License for the specific language governing permissions and
- // limitations under the License.
- package netutils2
- import (
- "bytes"
- "fmt"
- "net"
- "strconv"
- "strings"
- "time"
- "unicode"
- "yunion.io/x/log"
- "yunion.io/x/pkg/errors"
- "yunion.io/x/pkg/util/netutils"
- "yunion.io/x/pkg/util/regutils"
- "yunion.io/x/pkg/utils"
- "yunion.io/x/onecloud/pkg/cloudcommon/types"
- "yunion.io/x/onecloud/pkg/util/procutils"
- "yunion.io/x/onecloud/pkg/util/stringutils2"
- )
- var PSEUDO_VIP = "169.254.169.231"
- // var MASKS = []string{"0", "128", "192", "224", "240", "248", "252", "254", "255"}
- var PRIVATE_PREFIXES = []string{
- "10.0.0.0/8",
- "172.16.0.0/12",
- "192.168.0.0/16",
- }
- func GetFreePort() (int, error) {
- return netutils.GetFreePort()
- }
- func IsTcpPortUsed(addr string, port int) bool {
- server, err := net.Listen("tcp", fmt.Sprintf("%s:%d", addr, port))
- if err != nil {
- return true
- }
- server.Close()
- return false
- }
- // MyIP returns source ip used to communicate with udp:114.114.114.114
- func MyIP() (ip string, err error) {
- return MyIPTo("114.114.114.114")
- }
- // MyIPTo returns source ip used to communicate with udp:dstIP
- func MyIPTo(dstIP string) (ip string, err error) {
- conn, err := net.Dial("udp4", dstIP+":53")
- if err != nil {
- return
- }
- defer conn.Close()
- addr, ok := conn.LocalAddr().(*net.UDPAddr)
- if !ok {
- err = fmt.Errorf("not a net.UDPAddr: %#v", conn.LocalAddr())
- return
- }
- ip = addr.IP.String()
- return
- }
- func MyIPSmart() (ip string, err error) {
- return MyIPSmartTo("114.114.114.114", "2001:4860:4860::8888")
- }
- func MyIPSmartTo(ipv4Target, ipv6Target string) (ip string, err error) {
- // try IPv4 connect
- if ipv4Target != "" {
- conn, err4 := net.Dial("udp4", ipv4Target+":53")
- if err4 == nil {
- defer conn.Close()
- if addr, ok := conn.LocalAddr().(*net.UDPAddr); ok {
- return addr.IP.String(), nil
- }
- }
- }
- // try IPv6 connect
- if ipv6Target != "" {
- conn, err6 := net.Dial("udp6", "["+ipv6Target+"]:53")
- if err6 == nil {
- defer conn.Close()
- if addr, ok := conn.LocalAddr().(*net.UDPAddr); ok {
- return addr.IP.String(), nil
- }
- }
- }
- // try locallink
- return getLocalIP()
- }
- func getLocalIP() (string, error) {
- // get default route
- if ip := getIPFromDefaultRoute(); ip != "" {
- return ip, nil
- }
- interfaces, err := net.Interfaces()
- if err != nil {
- return "", errors.Wrap(err, "get network interfaces")
- }
- var candidateIPs []string
- for _, iface := range interfaces {
- if iface.Flags&net.FlagUp == 0 || iface.Flags&net.FlagLoopback != 0 {
- continue
- }
- addrs, err := iface.Addrs()
- if err != nil {
- continue
- }
- for _, addr := range addrs {
- if ipnet, ok := addr.(*net.IPNet); ok && !ipnet.IP.IsLoopback() {
- if ipnet.IP.To4() != nil {
- return ipnet.IP.String(), nil
- } else if ipnet.IP.To16() != nil && !ipnet.IP.IsLinkLocalUnicast() {
- candidateIPs = append(candidateIPs, ipnet.IP.String())
- }
- }
- }
- }
- if len(candidateIPs) > 0 {
- return candidateIPs[0], nil
- }
- return "", fmt.Errorf("no suitable IP address found")
- }
- func getIPFromDefaultRoute() string {
- if ip := getIPFromDefaultRouteV4(); ip != "" {
- return ip
- }
- if ip := getIPFromDefaultRouteV6(); ip != "" {
- return ip
- }
- return ""
- }
- func getIPFromDefaultRouteV4() string {
- output, err := procutils.NewCommand("ip", "route", "show", "default").Output()
- if err != nil {
- return ""
- }
- lines := strings.Split(string(output), "\n")
- for _, line := range lines {
- if strings.Contains(line, "default") && strings.Contains(line, "src") {
- fields := strings.Fields(line)
- for i, field := range fields {
- if field == "src" && i+1 < len(fields) {
- return fields[i+1]
- }
- }
- }
- if strings.Contains(line, "default") && strings.Contains(line, "dev") {
- fields := strings.Fields(line)
- for i, field := range fields {
- if field == "dev" && i+1 < len(fields) {
- if ip := getIPFromInterface(fields[i+1]); ip != "" {
- return ip
- }
- }
- }
- }
- }
- return ""
- }
- func getIPFromDefaultRouteV6() string {
- output, err := procutils.NewCommand("ip", "-6", "route", "show", "default").Output()
- if err != nil {
- return ""
- }
- lines := strings.Split(string(output), "\n")
- for _, line := range lines {
- if strings.Contains(line, "default") && strings.Contains(line, "src") {
- fields := strings.Fields(line)
- for i, field := range fields {
- if field == "src" && i+1 < len(fields) {
- return fields[i+1]
- }
- }
- }
- if strings.Contains(line, "default") && strings.Contains(line, "dev") {
- fields := strings.Fields(line)
- for i, field := range fields {
- if field == "dev" && i+1 < len(fields) {
- if ip := getIPFromInterfaceV6(fields[i+1]); ip != "" {
- return ip
- }
- }
- }
- }
- }
- return ""
- }
- func getIPFromInterface(ifaceName string) string {
- iface, err := net.InterfaceByName(ifaceName)
- if err != nil {
- return ""
- }
- addrs, err := iface.Addrs()
- if err != nil {
- return ""
- }
- for _, addr := range addrs {
- if ipnet, ok := addr.(*net.IPNet); ok && !ipnet.IP.IsLoopback() {
- if ipv4 := ipnet.IP.To4(); ipv4 != nil {
- return ipv4.String()
- }
- }
- }
- return ""
- }
- func getIPFromInterfaceV6(ifaceName string) string {
- iface, err := net.InterfaceByName(ifaceName)
- if err != nil {
- return ""
- }
- addrs, err := iface.Addrs()
- if err != nil {
- return ""
- }
- for _, addr := range addrs {
- if ipnet, ok := addr.(*net.IPNet); ok && !ipnet.IP.IsLoopback() {
- if ipv6 := ipnet.IP.To16(); ipv6 != nil && ipnet.IP.To4() == nil && !ipnet.IP.IsLinkLocalUnicast() {
- return ipv6.String()
- }
- }
- }
- return ""
- }
- func GetPrivatePrefixes(privatePrefixes []string) []string {
- if privatePrefixes != nil {
- return privatePrefixes
- } else {
- return PRIVATE_PREFIXES
- }
- }
- func GetMainNicFromDeployApi(nics []*types.SServerNic) (*types.SServerNic, error) {
- var mainIp netutils.IPV4Addr
- var mainNic *types.SServerNic
- for _, n := range nics {
- if len(n.Gateway) > 0 {
- ip := n.Ip
- ipInt, err := netutils.NewIPV4Addr(ip)
- if err != nil {
- return nil, errors.Wrapf(err, "netutils.NewIPV4Addr %s", ip)
- }
- if mainIp == 0 {
- mainIp = ipInt
- mainNic = n
- } else if !netutils.IsPrivate(ipInt) && netutils.IsPrivate(mainIp) {
- mainIp = ipInt
- mainNic = n
- }
- }
- }
- if mainNic != nil {
- return mainNic, nil
- }
- for _, n := range nics {
- ip := n.Ip
- ipInt, err := netutils.NewIPV4Addr(ip)
- if err != nil {
- return nil, errors.Wrap(err, "netutils.NewIPV4Addr")
- }
- if mainIp == 0 {
- mainIp = ipInt
- mainNic = n
- } else if !netutils.IsPrivate(ipInt) && netutils.IsPrivate(mainIp) {
- mainIp = ipInt
- mainNic = n
- }
- }
- if mainNic != nil {
- return mainNic, nil
- }
- return nil, errors.Wrap(errors.ErrInvalidStatus, "no valid nic")
- }
- func Netlen2Mask(netmasklen int) string {
- return netutils.Netlen2Mask(netmasklen)
- }
- func addRoute(routes []SRouteInfo, net, gw string) []SRouteInfo {
- route, _ := ParseRouteInfo([]string{net, gw})
- if route != nil {
- for _, rt := range routes {
- if rt.Prefix.String() == route.Prefix.String() && rt.PrefixLen == route.PrefixLen {
- return routes
- }
- }
- // not found
- routes = append(routes, *route)
- }
- return routes
- }
- func extendRoutes(routes4, routes6 []SRouteInfo, nicRoutes []types.SRoute) ([]SRouteInfo, []SRouteInfo) {
- for i := 0; i < len(nicRoutes); i++ {
- if regutils.MatchCIDR6(nicRoutes[i][0]) {
- routes6 = addRoute(routes6, nicRoutes[i][0], nicRoutes[i][1])
- } else {
- routes4 = addRoute(routes4, nicRoutes[i][0], nicRoutes[i][1])
- }
- }
- return routes4, routes6
- }
- func isExitAddress(ip string) bool {
- ipv4, err := netutils.NewIPV4Addr(ip)
- if err != nil {
- log.Errorf("NewIPV4Addr %s fail %s", ip, err)
- return false
- }
- return netutils.IsExitAddress(ipv4)
- }
- var (
- Ip4MetadataServers = []string{
- "169.254.169.254",
- }
- Ip6MetadataServers = []string{
- "fd00:ec2::254",
- }
- )
- func SetIp4MetadataServers(ip4s []string) {
- if len(ip4s) == 0 {
- ip4s = []string{
- "169.254.169.254",
- }
- }
- Ip4MetadataServers = ip4s
- }
- func SetIp6MetadataServers(ip6s []string) {
- if len(ip6s) == 0 {
- ip6s = []string{
- "fd00:ec2::254",
- }
- }
- Ip6MetadataServers = ip6s
- }
- func AddNicRoutes(routes4 []SRouteInfo, routes6 []SRouteInfo, nicDesc *types.SServerNic, mainIp string, mainIp6 string, nicCnt int) ([]SRouteInfo, []SRouteInfo) {
- // always add static routes, even if this is the default NIC
- // if mainIp == nicDesc.Ip {
- // return routes
- // }
- if len(nicDesc.Routes) > 0 {
- routes4, routes6 = extendRoutes(routes4, routes6, nicDesc.Routes)
- } else if len(nicDesc.Gateway) > 0 && !isExitAddress(nicDesc.Ip) &&
- nicCnt == 2 && nicDesc.Ip != mainIp && isExitAddress(mainIp) {
- for _, pref := range netutils.GetPrivateIPRanges() {
- prefs := pref.ToPrefixes()
- for _, p := range prefs {
- routes4 = addRoute(routes4, p.String(), nicDesc.Gateway)
- }
- }
- }
- if len(mainIp) > 0 && nicDesc.Ip == mainIp {
- // always add 169.254.169.254 for default NIC
- for _, ip := range Ip4MetadataServers {
- pref := ip + "/32"
- routes4 = addRoute(routes4, pref, "0.0.0.0")
- }
- }
- if len(mainIp6) > 0 && nicDesc.Ip6 == mainIp6 {
- for _, ip6 := range Ip6MetadataServers {
- pref := ip6 + "/128"
- routes6 = addRoute(routes6, pref, "::")
- }
- }
- return routes4, routes6
- }
- func GetNicDns(nicdesc *types.SServerNic) ([]string, []string) {
- dns4list := []string{}
- dns6list := []string{}
- if len(nicdesc.Dns) > 0 {
- for _, dns := range strings.Split(nicdesc.Dns, ",") {
- if regutils.MatchIP6Addr(dns) {
- dns6list = append(dns6list, dns)
- } else {
- dns4list = append(dns4list, dns)
- }
- }
- }
- return dns4list, dns6list
- }
- func NetBytes2Mask(mask []byte) string {
- if len(mask) != 4 {
- return ""
- }
- var res string
- for i := range mask {
- res += strconv.Itoa(int(mask[i])) + "."
- }
- return res[:len(res)-1]
- }
- type SNetInterface struct {
- name string
- Addr string
- Mask net.IPMask
- mac string
- Addr6 string
- Mask6 net.IPMask
- Addr4LinkLocal string
- Addr6LinkLocal string
- Mtu int
- VlanId int
- VlanParent *SNetInterface
- BondingMode int
- BondingSlaves []*SNetInterface
- }
- var (
- SECRET_PREFIX = "169.254"
- SECRET_MASK = []byte{255, 255, 255, 255}
- SECRET_MASK_LEN = 32
- secretInterfaceIndex = 254
- )
- func NewNetInterface(name string) *SNetInterface {
- n := new(SNetInterface)
- n.name = name
- n.FetchConfig()
- return n
- }
- func NewNetInterfaceWithExpectIp(name string, expectIp string, expectIp6 string, excludeIps []string) *SNetInterface {
- n := new(SNetInterface)
- n.name = name
- n.FetchConfig2(expectIp, expectIp6, excludeIps)
- return n
- }
- func (n *SNetInterface) String() string {
- return n.name
- }
- func (n *SNetInterface) Exist() bool {
- _, err := net.InterfaceByName(n.name)
- return err == nil
- }
- func (n *SNetInterface) FetchInter() *net.Interface {
- inter, err := net.InterfaceByName(n.name)
- if err != nil {
- log.Errorf("fetch interface %s error %s", n.name, err)
- return nil
- }
- return inter
- }
- func (n *SNetInterface) FetchConfig() {
- n.FetchConfig2("", "", nil)
- }
- // FetchConfig2 is used to fetch config with expectIp and expectIp6
- func (n *SNetInterface) FetchConfig2(expectIp string, expectIp6 string, excludeIps []string) {
- n.Addr = ""
- n.Mask = nil
- n.mac = ""
- // n.Mtu = 0
- inter := n.FetchInter()
- if inter == nil {
- return
- }
- n.Mtu = inter.MTU
- n.mac = inter.HardwareAddr.String()
- addrs, err := inter.Addrs()
- if err == nil {
- for _, addr := range addrs {
- if ipnet, ok := addr.(*net.IPNet); ok && !ipnet.IP.IsLoopback() {
- if ipnet.IP.To4() != nil {
- if strings.HasPrefix(ipnet.IP.To4().String(), SECRET_PREFIX) {
- n.Addr4LinkLocal = ipnet.IP.String()
- } else if (len(expectIp) > 0 && ipnet.IP.String() == expectIp) || (len(expectIp) == 0 && n.Addr == "") {
- if len(excludeIps) > 0 && utils.IsInStringArray(ipnet.IP.String(), excludeIps) {
- continue
- }
- n.Addr = ipnet.IP.String()
- n.Mask = ipnet.Mask
- }
- } else if ipnet.IP.To16() != nil {
- if ipnet.IP.IsLinkLocalUnicast() {
- n.Addr6LinkLocal = ipnet.IP.String()
- } else if (len(expectIp6) > 0 && ipnet.IP.String() == expectIp6) || (len(expectIp6) == 0 && n.Addr6 == "") {
- if len(excludeIps) > 0 && utils.IsInStringArray(ipnet.IP.String(), excludeIps) {
- continue
- }
- n.Addr6 = ipnet.IP.String()
- n.Mask6 = ipnet.Mask
- }
- }
- }
- }
- }
- // check vlanId
- vlanConf := getVlanConfig(n.name)
- if vlanConf != nil {
- n.VlanId = vlanConf.VlanId
- n.VlanParent = NewNetInterface(vlanConf.Parent)
- } else {
- n.VlanId = 1
- n.VlanParent = nil
- }
- // check bonding
- bondingConf := getBondingConfig(n.name)
- if bondingConf != nil {
- n.BondingMode = bondingConf.Mode
- for _, slave := range bondingConf.Slaves {
- n.BondingSlaves = append(n.BondingSlaves, NewNetInterface(slave))
- }
- }
- }
- func (n *SNetInterface) GetMac() string {
- return n.mac
- }
- func (n *SNetInterface) GetHardwareAddr() net.HardwareAddr {
- mac, err := net.ParseMAC(n.mac)
- if err != nil {
- return nil
- }
- return mac
- }
- func (n *SNetInterface) GetAllMacs() []string {
- macs := make([]string, 0, len(n.BondingSlaves)+1)
- find := false
- for _, inf := range n.BondingSlaves {
- macs = append(macs, inf.GetMac())
- if n.mac == inf.GetMac() {
- find = true
- }
- }
- if !find {
- macs = append(macs, n.mac)
- }
- return macs
- }
- // https://kris.io/2015/10/01/kvm-network-performance-tso-and-gso-turn-it-off/
- // General speaking, it is recommended to turn of GSO
- // however, this will degrade host network performance
- func (n *SNetInterface) SetupGso(on bool) {
- onoff := "off"
- if on {
- onoff = "on"
- }
- procutils.NewCommand(
- "ethtool", "-K", n.name,
- "tso", onoff, "gso", onoff,
- "ufo", onoff, "lro", onoff,
- "gro", onoff, "tx", onoff,
- "rx", onoff, "sg", onoff).Run()
- }
- func (n *SNetInterface) IsSecretInterface() bool {
- return n.Addr4LinkLocal != "" && n.Addr == ""
- }
- func (n *SNetInterface) IsSecretInterface6() bool {
- return n.Addr6LinkLocal != "" && n.Addr6 == ""
- }
- /*func (n *SNetInterface) IsSecretAddress(addr string, mask []byte) bool {
- log.Infof("MASK --- %s", mask)
- if reflect.DeepEqual(mask, SECRET_MASK) && strings.HasPrefix(addr, SECRET_PREFIX) {
- return true
- } else {
- return false
- }
- }*/
- func GetSecretInterfaceAddress() (string, int) {
- addr := fmt.Sprintf("%s.%d.1", SECRET_PREFIX, secretInterfaceIndex)
- secretInterfaceIndex -= 1
- return addr, SECRET_MASK_LEN
- }
- func (n *SNetInterface) GetSlaveAddresses() []SNicAddress {
- addrs := n.GetAddresses()
- var slaves = make([]SNicAddress, 0)
- for _, addr := range addrs {
- if addr.Addr != n.Addr && addr.Addr != n.Addr6 {
- slaves = append(slaves, addr)
- }
- }
- return slaves
- }
- func FormatMac(macStr string) string {
- var ret = []byte{}
- for i := 0; i < len(macStr); i++ {
- if bytes.IndexByte([]byte("0123456789abcdef"), macStr[i]) >= 0 {
- ret = append(ret, macStr[i])
- } else if bytes.IndexByte([]byte("ABCDEF"), macStr[i]) >= 0 {
- ret = append(ret, byte(unicode.ToLower(rune(macStr[i]))))
- }
- }
- if len(ret) == 12 {
- var res string
- for i := 0; i < 12; i += 2 {
- res += string(ret[i:i+2]) + ":"
- }
- return res[:len(res)-1]
- }
- return ""
- }
- func MacEqual(mac1, mac2 string) bool {
- mac1 = FormatMac(mac1)
- mac2 = FormatMac(mac2)
- if len(mac1) > 0 && len(mac2) > 0 && mac1 == mac2 {
- return true
- }
- return false
- }
- func netmask2len(mask string) int {
- masks := []string{"0", "128", "192", "224", "240", "248", "252", "254", "255"}
- for i := 0; i < len(masks); i++ {
- if masks[i] == mask {
- return i
- }
- }
- return -1
- }
- func Netmask2Len(mask string) int {
- data := strings.Split(mask, ".")
- mlen := 0
- for _, d := range data {
- if d != "0" {
- nle := netmask2len(d)
- log.Errorln(d)
- if nle < 0 {
- return -1
- }
- mlen += nle
- }
- }
- return mlen
- }
- func PrefixSplit(pref string) (string, int, error) {
- slash := strings.Index(pref, "/")
- var intMask int
- var err error
- if slash > 0 {
- ip := pref[:slash]
- mask := pref[slash+1:]
- if regutils.MatchIPAddr(mask) {
- intMask = Netmask2Len(mask)
- } else {
- intMask, err = strconv.Atoi(mask)
- if err != nil {
- return "", 0, err
- }
- }
- return ip, intMask, nil
- } else {
- return pref, 32, nil
- }
- }
- func TestTcpPort(ip string, port int, timeoutSecs int, tries int) error {
- if timeoutSecs <= 0 {
- timeoutSecs = 3
- }
- if tries <= 0 {
- tries = 3
- }
- address := net.JoinHostPort(ip, fmt.Sprintf("%d", port))
- // 3 second timeout
- errs := make([]error, 0)
- for i := 0; i < tries; i++ {
- conn, err := net.DialTimeout("tcp", address, time.Duration(timeoutSecs)*time.Second)
- if err != nil {
- errs = append(errs, err)
- } else {
- if conn != nil {
- _ = conn.Close()
- return nil
- } else {
- errs = append(errs, errors.Wrap(errors.ErrEmpty, "nil conn"))
- }
- }
- time.Sleep(10 * time.Millisecond)
- }
- return errors.NewAggregate(errs)
- }
- func IP2SolicitMcastIP(ip6 net.IP) net.IP {
- // Solicited-Node Multicast Address, FF02::1:FF00:0/104
- return net.IP{0xff, 0x02, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x01, 0xff, ip6[13], ip6[14], ip6[15]}
- }
- func IP2SolicitMcastMac(ip6 net.IP) net.HardwareAddr {
- // Solicited-Node Multicast Address, 33:33:ff:00:00:00
- return net.HardwareAddr{0x33, 0x33, 0xff, ip6[13], ip6[14], ip6[15]}
- }
- func SplitV46Addr(addrsStr string) ([]string, []string) {
- servers4 := stringutils2.NewSortedStrings(nil)
- servers6 := stringutils2.NewSortedStrings(nil)
- for _, ntp := range strings.Split(addrsStr, ",") {
- if regutils.MatchIP4Addr(ntp) {
- servers4 = servers4.Append(ntp)
- } else if regutils.MatchIP6Addr(ntp) {
- servers6 = servers6.Append(ntp)
- } else if regutils.MatchDomainName(ntp) {
- ntpAddrs, _ := net.LookupHost(ntp)
- for _, ntpAddr := range ntpAddrs {
- if regutils.MatchIP4Addr(ntpAddr) {
- servers4 = servers4.Append(ntpAddr)
- } else if regutils.MatchIP6Addr(ntpAddr) {
- servers6 = servers6.Append(ntpAddr)
- }
- }
- }
- }
- return servers4, servers6
- }
- func SplitV46Addr2IP(addrsStr string) ([]net.IP, []net.IP) {
- addrs4, addrs6 := SplitV46Addr(addrsStr)
- ip4s := make([]net.IP, len(addrs4))
- ip6s := make([]net.IP, len(addrs6))
- for i := range addrs4 {
- ip4s[i] = net.ParseIP(addrs4[i])
- }
- for i := range addrs6 {
- ip6s[i] = net.ParseIP(addrs6[i])
- }
- return ip4s, ip6s
- }
|