1 package utils
2
3 import (
4 "fmt"
5 "net"
6 "strconv"
7 "strings"
8 )
9
10
15 func ParseIP(ip_s string) (string, uint32, int, error) {
16 if len(ip_s) < 4 {
17 return "", 0, 0, fmt.Errorf("\"%s\" is not a valid ip", ip_s)
18 }
19 ct := strings.Count(ip_s, ":")
20 if ct == 1 {
21 idx := strings.Index(ip_s, ":")
22 ip := ip_s[:idx]
23 port, err := strconv.Atoi(ip_s[idx+1:])
24 if err != nil {
25 return "", 0, 0, err
26 }
27 return ip, uint32(port), 4, nil
28 }
29
30 if ct == 0 {
31 return ip_s, 0, 4, nil
32 }
33
34
35 if ip_s[0] != '[' {
36
37 return ip_s, 0, 6, nil
38 }
39
40 ep := ip_s[1:]
41 idx := strings.Index(ep, "]")
42 if idx == -1 {
43 return "", 0, 0, fmt.Errorf("not a valid ipv6 with port: \"%s\"", ip_s)
44 }
45 ip := ep[:idx]
46 port, err := strconv.Atoi(ep[idx+2:])
47 if err != nil {
48 return "", 0, 0, err
49 }
50 return ip, uint32(port), 6, nil
51 }
52
53
54
55 func IsPrivateIP(ip_s string) (bool, error) {
56 ip, masksize, err := GetIPAndNet(ip_s)
57 if err != nil {
58 return false, err
59 }
60 ipa, _, err := net.ParseCIDR(fmt.Sprintf("%s/%d", ip, masksize))
61 if err != nil {
62 return false, err
63 }
64
65 if ipa.IsPrivate() {
66 return true, nil
67 }
68 if ipa.IsLoopback() {
69 return true, nil
70 }
71 if ipa.IsLinkLocalUnicast() {
72 return true, nil
73 }
74 if ipa.IsLinkLocalMulticast() {
75 return true, nil
76 }
77 if ipa.IsInterfaceLocalMulticast() {
78 return true, nil
79 }
80 return false, nil
81
82 }
83
84
91 func GetIPAndNet(ip_s string) (string, int, error) {
92 if strings.Contains(ip_s, "/") {
93
94 ip, ipnet, err := net.ParseCIDR(ip_s)
95 if err != nil {
96 return "", 0, err
97 }
98 ones, _ := ipnet.Mask.Size()
99 return ip.String(), ones, nil
100 }
101
102 ip_ns := ""
103 host, _, err := net.SplitHostPort(ip_s)
104 if err == nil {
105 ip_ns = host
106 } else {
107 ip_ns = ip_s
108 }
109 ip, _, t, err := ParseIP(ip_ns)
110 if err != nil {
111 return "", 0, err
112 }
113 if t == 4 {
114 return ip, 32, nil
115 } else if t == 6 {
116 return ip, 128, nil
117 }
118 return "", 0, fmt.Errorf("invalid ip type %d for \"%s\"", t, ip_s)
119 }
120
121
122 func IsLinkLocal(s string) bool {
123 ips, _, version, err := ParseIP(s)
124 if err != nil {
125 panic(fmt.Sprintf("invalid ip %s", s))
126 }
127 if version != 6 {
128 return false
129 }
130 if strings.HasPrefix(ips, "fe80:") {
131 return true
132 }
133 return false
134 }
135
136
137 func IsLoopback(s string) bool {
138 s = strings.ToLower(s)
139 if strings.HasPrefix(s, "127.") {
140 return true
141 }
142 if s == "::1" {
143 return true
144 }
145 return false
146 }
147
View as plain text