-
-
Notifications
You must be signed in to change notification settings - Fork 1.5k
/
gipv4_ip.go
147 lines (138 loc) · 3.23 KB
/
gipv4_ip.go
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
// Copyright GoFrame Author(https://goframe.org). All Rights Reserved.
//
// 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,
// You can obtain one at https://github.com/gogf/gf.
//
package gipv4
import (
"net"
"strconv"
"strings"
"github.com/gogf/gf/v2/errors/gcode"
"github.com/gogf/gf/v2/errors/gerror"
)
// GetIpArray retrieves and returns all the ip of current host.
func GetIpArray() (ips []string, err error) {
interfaceAddr, err := net.InterfaceAddrs()
if err != nil {
err = gerror.Wrap(err, `net.InterfaceAddrs failed`)
return nil, err
}
for _, address := range interfaceAddr {
ipNet, isValidIpNet := address.(*net.IPNet)
if isValidIpNet && !ipNet.IP.IsLoopback() {
if ipNet.IP.To4() != nil {
ips = append(ips, ipNet.IP.String())
}
}
}
return ips, nil
}
// MustGetIntranetIp performs as GetIntranetIp, but it panics if any error occurs.
func MustGetIntranetIp() string {
ip, err := GetIntranetIp()
if err != nil {
panic(err)
}
return ip
}
// GetIntranetIp retrieves and returns the first intranet ip of current machine.
func GetIntranetIp() (ip string, err error) {
ips, err := GetIntranetIpArray()
if err != nil {
return "", err
}
if len(ips) == 0 {
return "", gerror.New("no intranet ip found")
}
return ips[0], nil
}
// GetIntranetIpArray retrieves and returns the intranet ip list of current machine.
func GetIntranetIpArray() (ips []string, err error) {
var (
addresses []net.Addr
interFaces []net.Interface
)
interFaces, err = net.Interfaces()
if err != nil {
err = gerror.Wrap(err, `net.Interfaces failed`)
return ips, err
}
for _, interFace := range interFaces {
if interFace.Flags&net.FlagUp == 0 {
// interface down
continue
}
if interFace.Flags&net.FlagLoopback != 0 {
// loop back interface
continue
}
// ignore warden bridge
if strings.HasPrefix(interFace.Name, "w-") {
continue
}
addresses, err = interFace.Addrs()
if err != nil {
err = gerror.Wrap(err, `interFace.Addrs failed`)
return ips, err
}
for _, addr := range addresses {
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 {
// not an ipv4 address
continue
}
ipStr := ip.String()
if IsIntranet(ipStr) {
ips = append(ips, ipStr)
}
}
}
return ips, nil
}
// IsIntranet checks and returns whether given ip an intranet ip.
//
// Local: 127.0.0.1
// 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 {
if ip == "127.0.0.1" {
return true
}
array := strings.Split(ip, ".")
if len(array) != 4 {
return false
}
// A
if array[0] == "10" || (array[0] == "192" && array[1] == "168") {
return true
}
// C
if array[0] == "192" && array[1] == "168" {
return true
}
// B
if array[0] == "172" {
second, err := strconv.ParseInt(array[1], 10, 64)
if err != nil {
err = gerror.WrapCodef(gcode.CodeInvalidParameter, err, `strconv.ParseInt failed for string "%s"`, array[1])
return false
}
if second >= 16 && second <= 31 {
return true
}
}
return false
}