wg-gen-web/util/util.go

163 lines
3.7 KiB
Go

package util
import (
"crypto/rand"
"encoding/base64"
"errors"
"io/ioutil"
"net"
"os"
"regexp"
)
var (
AuthTokenHeaderName = "x-wg-gen-web-auth"
// RegexpEmail check valid email
RegexpEmail = regexp.MustCompile("^[a-zA-Z0-9.!#$%&'*+/=?^_`{|}~-]+@[a-zA-Z0-9](?:[a-zA-Z0-9-]{0,61}[a-zA-Z0-9])?(?:\\.[a-zA-Z0-9](?:[a-zA-Z0-9-]{0,61}[a-zA-Z0-9])?)*$")
)
// ReadFile file content
func ReadFile(path string) (bytes []byte, err error) {
bytes, err = ioutil.ReadFile(path)
if err != nil {
return nil, err
}
return bytes, nil
}
// WriteFile content to file
func WriteFile(path string, bytes []byte) (err error) {
err = ioutil.WriteFile(path, bytes, 0644)
if err != nil {
return err
}
return nil
}
// FileExists check if file exists
func FileExists(name string) bool {
info, err := os.Stat(name)
if os.IsNotExist(err) {
return false
}
return !info.IsDir()
}
// DirectoryExists check if directory exists
func DirectoryExists(name string) bool {
info, err := os.Stat(name)
if os.IsNotExist(err) {
return false
}
return info.IsDir()
}
// GetAvailableIp search for an available ip in cidr against a list of reserved ips
func GetAvailableIp(cidr string, reserved []string) (string, error) {
ip, ipnet, err := net.ParseCIDR(cidr)
if err != nil {
return "", err
}
// this two addresses are not usable
broadcastAddr := BroadcastAddr(ipnet).String()
networkAddr := ipnet.IP.String()
for ip := ip.Mask(ipnet.Mask); ipnet.Contains(ip); inc(ip) {
ok := true
address := ip.String()
for _, r := range reserved {
if address == r {
ok = false
break
}
}
if ok && address != networkAddr && address != broadcastAddr {
return address, nil
}
}
return "", errors.New("no more available address from cidr")
}
// IsIPv6 check if given ip is IPv6
func IsIPv6(address string) bool {
ip := net.ParseIP(address)
if ip == nil {
return false
}
return ip.To4() == nil
}
// IsValidIp check if ip is valid
func IsValidIp(ip string) bool {
return net.ParseIP(ip) != nil
}
// IsValidCidr check if CIDR is valid
func IsValidCidr(cidr string) bool {
_, _, err := net.ParseCIDR(cidr)
return err == nil
}
// GetIpFromCidr get ip from cidr
func GetIpFromCidr(cidr string) (string, error) {
ip, _, err := net.ParseCIDR(cidr)
if err != nil {
return "", err
}
return ip.String(), nil
}
// http://play.golang.org/p/m8TNTtygK0
func inc(ip net.IP) {
for j := len(ip) - 1; j >= 0; j-- {
ip[j]++
if ip[j] > 0 {
break
}
}
}
// BroadcastAddr returns the last address in the given network, or the broadcast address.
func BroadcastAddr(n *net.IPNet) net.IP {
// The golang net package doesn't make it easy to calculate the broadcast address. :(
var broadcast net.IP
if len(n.IP) == 4 {
broadcast = net.ParseIP("0.0.0.0").To4()
} else {
broadcast = net.ParseIP("::")
}
for i := 0; i < len(n.IP); i++ {
broadcast[i] = n.IP[i] | ^n.Mask[i]
}
return broadcast
}
// GenerateRandomBytes returns securely generated random bytes.
// It will return an error if the system's secure random
// number generator fails to function correctly, in which
// case the caller should not continue.
func GenerateRandomBytes(n int) ([]byte, error) {
b := make([]byte, n)
_, err := rand.Read(b)
// Note that err == nil only if we read len(b) bytes.
if err != nil {
return nil, err
}
return b, nil
}
// GenerateRandomString returns a URL-safe, base64 encoded
// securely generated random string.
// It will return an error if the system's secure random
// number generator fails to function correctly, in which
// case the caller should not continue.
func GenerateRandomString(s int) (string, error) {
b, err := GenerateRandomBytes(s)
return base64.URLEncoding.EncodeToString(b), err
}