2019-02-02 16:18:25 +08:00
|
|
|
// Copyright 2017 gf Author(https://github.com/gogf/gf). All Rights Reserved.
|
2017-12-29 16:03:30 +08:00
|
|
|
//
|
|
|
|
// This Source Code Form is subject to the terms of the MIT License.
|
|
|
|
// If a copy of the MIT was not distributed with this file,
|
2019-02-02 16:18:25 +08:00
|
|
|
// You can obtain one at https://github.com/gogf/gf.
|
2017-12-29 16:03:30 +08:00
|
|
|
//
|
2017-12-31 18:19:58 +08:00
|
|
|
|
2019-01-15 23:27:47 +08:00
|
|
|
// Package gipv4 provides useful API for IPv4 address handling.
|
2017-12-14 17:32:51 +08:00
|
|
|
package gipv4
|
2017-11-23 10:21:28 +08:00
|
|
|
|
|
|
|
import (
|
2019-06-19 09:06:52 +08:00
|
|
|
"encoding/binary"
|
|
|
|
"fmt"
|
|
|
|
"net"
|
|
|
|
"strconv"
|
|
|
|
"strings"
|
2019-07-29 21:01:19 +08:00
|
|
|
|
|
|
|
"github.com/gogf/gf/text/gregex"
|
2017-11-23 10:21:28 +08:00
|
|
|
)
|
|
|
|
|
2019-10-30 19:55:50 +08:00
|
|
|
// Validate checks whether given <ip> a valid IPv4 address.
|
2017-12-29 15:42:42 +08:00
|
|
|
func Validate(ip string) bool {
|
2019-06-19 09:06:52 +08:00
|
|
|
return gregex.IsMatchString(`^((25[0-5]|2[0-4]\d|[01]?\d\d?)\.){3}(25[0-5]|2[0-4]\d|[01]?\d\d?)$`, ip)
|
2017-12-29 15:42:42 +08:00
|
|
|
}
|
|
|
|
|
2019-10-30 19:55:50 +08:00
|
|
|
// GetHostByName returns the IPv4 address corresponding to a given Internet host name.
|
2019-01-30 21:27:03 +08:00
|
|
|
func GetHostByName(hostname string) (string, error) {
|
2019-06-19 09:06:52 +08:00
|
|
|
ips, err := net.LookupIP(hostname)
|
|
|
|
if ips != nil {
|
|
|
|
for _, v := range ips {
|
|
|
|
if v.To4() != nil {
|
|
|
|
return v.String(), nil
|
|
|
|
}
|
|
|
|
}
|
|
|
|
return "", nil
|
|
|
|
}
|
|
|
|
return "", err
|
2019-01-30 21:27:03 +08:00
|
|
|
}
|
2017-11-23 10:21:28 +08:00
|
|
|
|
2019-10-30 19:55:50 +08:00
|
|
|
// GetHostsByName returns a list of IPv4 addresses corresponding to a given Internet host name.
|
2019-01-30 21:27:03 +08:00
|
|
|
func GetHostsByName(hostname string) ([]string, error) {
|
2019-06-19 09:06:52 +08:00
|
|
|
ips, err := net.LookupIP(hostname)
|
|
|
|
if ips != nil {
|
2019-10-30 19:55:50 +08:00
|
|
|
var ipStrings []string
|
2019-06-19 09:06:52 +08:00
|
|
|
for _, v := range ips {
|
|
|
|
if v.To4() != nil {
|
2019-10-30 19:55:50 +08:00
|
|
|
ipStrings = append(ipStrings, v.String())
|
2019-06-19 09:06:52 +08:00
|
|
|
}
|
|
|
|
}
|
2019-10-30 19:55:50 +08:00
|
|
|
return ipStrings, nil
|
2019-06-19 09:06:52 +08:00
|
|
|
}
|
|
|
|
return nil, err
|
2019-01-30 21:27:03 +08:00
|
|
|
}
|
2017-11-23 10:21:28 +08:00
|
|
|
|
2019-10-30 19:55:50 +08:00
|
|
|
// GetNameByAddr returns the Internet host name corresponding to a given IP address.
|
2019-01-30 21:27:03 +08:00
|
|
|
func GetNameByAddr(ipAddress string) (string, error) {
|
2019-06-19 09:06:52 +08:00
|
|
|
names, err := net.LookupAddr(ipAddress)
|
|
|
|
if names != nil {
|
|
|
|
return strings.TrimRight(names[0], "."), nil
|
|
|
|
}
|
|
|
|
return "", err
|
2019-01-30 21:27:03 +08:00
|
|
|
}
|
2017-11-23 10:21:28 +08:00
|
|
|
|
2019-10-30 19:55:50 +08:00
|
|
|
// Ip2long converts ip address to an uint32 integer.
|
2019-01-30 21:27:03 +08:00
|
|
|
func Ip2long(ipAddress string) uint32 {
|
2019-06-19 09:06:52 +08:00
|
|
|
ip := net.ParseIP(ipAddress)
|
|
|
|
if ip == nil {
|
|
|
|
return 0
|
|
|
|
}
|
|
|
|
return binary.BigEndian.Uint32(ip.To4())
|
2017-11-23 10:21:28 +08:00
|
|
|
}
|
|
|
|
|
2019-10-30 19:55:50 +08:00
|
|
|
// Long2ip converts an uint32 integer ip address to its string type address.
|
2019-01-30 21:27:03 +08:00
|
|
|
func Long2ip(properAddress uint32) string {
|
2019-06-19 09:06:52 +08:00
|
|
|
ipByte := make([]byte, 4)
|
|
|
|
binary.BigEndian.PutUint32(ipByte, properAddress)
|
|
|
|
return net.IP(ipByte).String()
|
2017-11-23 10:21:28 +08:00
|
|
|
}
|
|
|
|
|
2019-10-30 19:55:50 +08:00
|
|
|
// GetSegment returns the segment of given ip address.
|
|
|
|
// Eg: 192.168.2.102 -> 192.168.2
|
2017-11-23 10:21:28 +08:00
|
|
|
func GetSegment(ip string) string {
|
2019-10-30 19:55:50 +08:00
|
|
|
match, err := gregex.MatchString(`^(\d{1,3})\.(\d{1,3})\.(\d{1,3})\.(\d{1,3})$`, ip)
|
|
|
|
if err != nil || len(match) < 4 {
|
2019-06-19 09:06:52 +08:00
|
|
|
return ""
|
|
|
|
}
|
2019-10-30 19:55:50 +08:00
|
|
|
return fmt.Sprintf("%s.%s.%s", match[1], match[2], match[3])
|
2017-11-23 10:21:28 +08:00
|
|
|
}
|
|
|
|
|
2019-10-30 19:55:50 +08:00
|
|
|
// ParseAddress parses <address> to its ip and port.
|
|
|
|
// Eg: 192.168.1.1:80 -> 192.168.1.1, 80
|
|
|
|
func ParseAddress(address string) (string, int) {
|
|
|
|
match, err := gregex.MatchString(`^(.+):(\d+)$`, address)
|
|
|
|
if err == nil {
|
|
|
|
i, _ := strconv.Atoi(match[2])
|
|
|
|
return match[1], i
|
2019-06-19 09:06:52 +08:00
|
|
|
}
|
|
|
|
return "", 0
|
2017-11-23 10:21:28 +08:00
|
|
|
}
|
|
|
|
|
2019-10-30 19:55:50 +08:00
|
|
|
// IntranetIP returns the intranet ip list of current machine.
|
2017-11-23 10:21:28 +08:00
|
|
|
func IntranetIP() (ips []string, err error) {
|
2019-06-19 09:06:52 +08:00
|
|
|
ips = make([]string, 0)
|
|
|
|
ifaces, e := net.Interfaces()
|
|
|
|
if e != nil {
|
|
|
|
return ips, e
|
|
|
|
}
|
|
|
|
for _, iface := range ifaces {
|
|
|
|
if iface.Flags&net.FlagUp == 0 {
|
2019-10-30 19:55:50 +08:00
|
|
|
// interface down
|
|
|
|
continue
|
2019-06-19 09:06:52 +08:00
|
|
|
}
|
|
|
|
if iface.Flags&net.FlagLoopback != 0 {
|
2019-10-30 19:55:50 +08:00
|
|
|
// loopback interface
|
|
|
|
continue
|
2019-06-19 09:06:52 +08:00
|
|
|
}
|
|
|
|
// ignore warden bridge
|
|
|
|
if strings.HasPrefix(iface.Name, "w-") {
|
|
|
|
continue
|
|
|
|
}
|
2019-10-30 19:55:50 +08:00
|
|
|
addresses, e := iface.Addrs()
|
2019-06-19 09:06:52 +08:00
|
|
|
if e != nil {
|
|
|
|
return ips, e
|
|
|
|
}
|
2019-10-30 19:55:50 +08:00
|
|
|
for _, addr := range addresses {
|
2019-06-19 09:06:52 +08:00
|
|
|
var ip net.IP
|
|
|
|
switch v := addr.(type) {
|
|
|
|
case *net.IPNet:
|
|
|
|
ip = v.IP
|
|
|
|
case *net.IPAddr:
|
|
|
|
ip = v.IP
|
|
|
|
}
|
|
|
|
|
|
|
|
if ip == nil || ip.IsLoopback() {
|
|
|
|
continue
|
|
|
|
}
|
|
|
|
ip = ip.To4()
|
|
|
|
if ip == nil {
|
2019-10-30 19:55:50 +08:00
|
|
|
// not an ipv4 address
|
|
|
|
continue
|
2019-06-19 09:06:52 +08:00
|
|
|
}
|
|
|
|
ipStr := ip.String()
|
|
|
|
if IsIntranet(ipStr) {
|
|
|
|
ips = append(ips, ipStr)
|
|
|
|
}
|
|
|
|
}
|
|
|
|
}
|
|
|
|
return ips, nil
|
2017-11-23 10:21:28 +08:00
|
|
|
}
|
|
|
|
|
2019-10-30 19:55:50 +08:00
|
|
|
// IsIntranet checks and returns whether given ip an intranet ip.
|
2019-10-31 15:13:34 +08:00
|
|
|
//
|
|
|
|
// Local: 127.0.0.1
|
2019-10-30 19:55:50 +08:00
|
|
|
// A: 10.0.0.0--10.255.255.255
|
|
|
|
// B: 172.16.0.0--172.31.255.255
|
|
|
|
// C: 192.168.0.0--192.168.255.255
|
|
|
|
func IsIntranet(ip string) bool {
|
2019-10-31 15:13:34 +08:00
|
|
|
if ip == "127.0.0.1" {
|
|
|
|
return true
|
|
|
|
}
|
2019-10-30 19:55:50 +08:00
|
|
|
array := strings.Split(ip, ".")
|
|
|
|
if len(array) != 4 {
|
|
|
|
return false
|
|
|
|
}
|
|
|
|
// A
|
|
|
|
if array[0] == "10" || (array[0] == "192" && array[1] == "168") {
|
2019-06-19 09:06:52 +08:00
|
|
|
return true
|
|
|
|
}
|
2019-10-30 19:55:50 +08:00
|
|
|
// C
|
|
|
|
if array[0] == "192" && array[1] == "168" {
|
|
|
|
return true
|
|
|
|
}
|
|
|
|
// B
|
|
|
|
if array[0] == "172" {
|
|
|
|
second, err := strconv.ParseInt(array[1], 10, 64)
|
2019-06-19 09:06:52 +08:00
|
|
|
if err != nil {
|
|
|
|
return false
|
|
|
|
}
|
|
|
|
if second >= 16 && second <= 31 {
|
|
|
|
return true
|
|
|
|
}
|
|
|
|
}
|
|
|
|
return false
|
2017-11-23 10:21:28 +08:00
|
|
|
}
|