0
0
mirror of https://github.com/vx3r/wg-gen-web.git synced 2025-01-05 03:13:24 +00:00

go fmt / badges

This commit is contained in:
vx3r 2020-01-30 16:12:26 +09:00
parent 024d2b4ebb
commit 9b6d610a9c
9 changed files with 85 additions and 53 deletions

View File

@ -2,6 +2,13 @@


Simple Web based configuration generator for [WireGuard](https://wireguard.com). Simple Web based configuration generator for [WireGuard](https://wireguard.com).


---

<p align="left">
<a href="https://goreportcard.com/report/github.com/vx3r/wg-gen-web"><img src="https://goreportcard.com/badge/github.com/vx3r/wg-gen-web" alt="Go Report Card"></a>
<a href="https://gitlab.127-0-0-1.fr/vx3r/wg-gen-web/commits/master"><img src="https://gitlab.127-0-0-1.fr/vx3r/wg-gen-web/badges/master/pipeline.svg" alt="Gitlab CI / CD"></a>
</p>

## Whay another one ? ## Whay another one ?


All WireGuard UI implementation are trying to manage the WireGuard by applying configurations or creation network rules. All WireGuard UI implementation are trying to manage the WireGuard by applying configurations or creation network rules.

View File

@ -29,7 +29,6 @@ func ApplyRoutes(r *gin.Engine) {
} }
} }



func createClient(c *gin.Context) { func createClient(c *gin.Context) {
var data model.Client var data model.Client


@ -136,19 +135,18 @@ func configClient(c *gin.Context) {
c.Header("Content-Disposition", "attachment; filename=wg0.conf") c.Header("Content-Disposition", "attachment; filename=wg0.conf")
c.Data(http.StatusOK, "application/config", configData) c.Data(http.StatusOK, "application/config", configData)
return return
} else { }
// return config as png qrcode // return config as png qrcode
png, err := qrcode.Encode(string(configData), qrcode.Medium, 220) png, err := qrcode.Encode(string(configData), qrcode.Medium, 220)
if err != nil { if err != nil {
log.WithFields(log.Fields{ log.WithFields(log.Fields{
"err": err, "err": err,
}).Error("failed to create qrcode") }).Error("failed to create qrcode")
c.AbortWithStatus(http.StatusInternalServerError) c.AbortWithStatus(http.StatusInternalServerError)
return
}
c.Data(http.StatusOK, "image/png", png)
return return
} }
c.Data(http.StatusOK, "image/png", png)
return
} }


func readServer(c *gin.Context) { func readServer(c *gin.Context) {

1
go.mod
View File

@ -11,6 +11,5 @@ require (
github.com/satori/go.uuid v1.2.0 github.com/satori/go.uuid v1.2.0
github.com/sirupsen/logrus v1.4.2 github.com/sirupsen/logrus v1.4.2
github.com/skip2/go-qrcode v0.0.0-20191027152451-9434209cb086 github.com/skip2/go-qrcode v0.0.0-20191027152451-9434209cb086
golang.org/x/crypto v0.0.0-20200117160349-530e935923ad
golang.zx2c4.com/wireguard/wgctrl v0.0.0-20200114203027-fcfc50b29cbb golang.zx2c4.com/wireguard/wgctrl v0.0.0-20200114203027-fcfc50b29cbb
) )

7
go.sum
View File

@ -39,10 +39,8 @@ github.com/leodido/go-urn v1.1.0/go.mod h1:+cyI34gQWZcE1eQU7NVgKkkzdXDQHr1dBMtdA
github.com/mattn/go-isatty v0.0.7/go.mod h1:Iq45c/XA43vh69/j3iqttzPXn0bhXyGjM0Hdxcsrc5s= github.com/mattn/go-isatty v0.0.7/go.mod h1:Iq45c/XA43vh69/j3iqttzPXn0bhXyGjM0Hdxcsrc5s=
github.com/mattn/go-isatty v0.0.9 h1:d5US/mDsogSGW37IV293h//ZFaeajb69h+EHFsv2xGg= github.com/mattn/go-isatty v0.0.9 h1:d5US/mDsogSGW37IV293h//ZFaeajb69h+EHFsv2xGg=
github.com/mattn/go-isatty v0.0.9/go.mod h1:YNRxwqDuOph6SZLI9vUUz6OYw3QyUt7WiY2yME+cCiQ= github.com/mattn/go-isatty v0.0.9/go.mod h1:YNRxwqDuOph6SZLI9vUUz6OYw3QyUt7WiY2yME+cCiQ=
github.com/mdlayher/genetlink v1.0.0 h1:OoHN1OdyEIkScEmRgxLEe2M9U8ClMytqA5niynLtfj0=
github.com/mdlayher/genetlink v1.0.0/go.mod h1:0rJ0h4itni50A86M2kHcgS85ttZazNt7a8H2a2cw0Gc= github.com/mdlayher/genetlink v1.0.0/go.mod h1:0rJ0h4itni50A86M2kHcgS85ttZazNt7a8H2a2cw0Gc=
github.com/mdlayher/netlink v0.0.0-20190409211403-11939a169225/go.mod h1:eQB3mZE4aiYnlUsyGGCOpPETfdQq4Jhsgf1fk3cwQaA= github.com/mdlayher/netlink v0.0.0-20190409211403-11939a169225/go.mod h1:eQB3mZE4aiYnlUsyGGCOpPETfdQq4Jhsgf1fk3cwQaA=
github.com/mdlayher/netlink v1.0.0 h1:vySPY5Oxnn/8lxAPn2cK6kAzcZzYJl3KriSLO46OT18=
github.com/mdlayher/netlink v1.0.0/go.mod h1:KxeJAFOFLG6AjpyDkQ/iIhxygIUKD+vcwqcnu43w/+M= github.com/mdlayher/netlink v1.0.0/go.mod h1:KxeJAFOFLG6AjpyDkQ/iIhxygIUKD+vcwqcnu43w/+M=
github.com/mikioh/ipaddr v0.0.0-20190404000644-d465c8ab6721/go.mod h1:Ickgr2WtCLZ2MDGd4Gr0geeCH5HybhRJbonOgQpvSxc= github.com/mikioh/ipaddr v0.0.0-20190404000644-d465c8ab6721/go.mod h1:Ickgr2WtCLZ2MDGd4Gr0geeCH5HybhRJbonOgQpvSxc=
github.com/modern-go/concurrent v0.0.0-20180228061459-e0a39a4cb421/go.mod h1:6dJC0mAP4ikYIbvyc7fijjWJddQyLn8Ig3JB5CqoB9Q= github.com/modern-go/concurrent v0.0.0-20180228061459-e0a39a4cb421/go.mod h1:6dJC0mAP4ikYIbvyc7fijjWJddQyLn8Ig3JB5CqoB9Q=
@ -70,16 +68,14 @@ github.com/ugorji/go/codec v1.1.7 h1:2SvQaVZ1ouYrrKKwoSk2pzd4A9evlKJb9oTL+OaLUSs
github.com/ugorji/go/codec v1.1.7/go.mod h1:Ax+UKWsSmolVDwsd+7N3ZtXu+yMGCf907BLYF3GoBXY= github.com/ugorji/go/codec v1.1.7/go.mod h1:Ax+UKWsSmolVDwsd+7N3ZtXu+yMGCf907BLYF3GoBXY=
golang.org/x/crypto v0.0.0-20190308221718-c2843e01d9a2/go.mod h1:djNgcEr1/C05ACkg1iLfiJU5Ep61QUkGW8qpdssI0+w= golang.org/x/crypto v0.0.0-20190308221718-c2843e01d9a2/go.mod h1:djNgcEr1/C05ACkg1iLfiJU5Ep61QUkGW8qpdssI0+w=
golang.org/x/crypto v0.0.0-20191002192127-34f69633bfdc/go.mod h1:yigFU9vqHzYiE8UmvKecakEJjdnWj3jj499lnFckfCI= golang.org/x/crypto v0.0.0-20191002192127-34f69633bfdc/go.mod h1:yigFU9vqHzYiE8UmvKecakEJjdnWj3jj499lnFckfCI=
golang.org/x/crypto v0.0.0-20191206172530-e9b2fee46413 h1:ULYEB3JvPRE/IfO+9uO7vKV/xzVTO7XPAwm8xbf4w2g=
golang.org/x/crypto v0.0.0-20191206172530-e9b2fee46413/go.mod h1:LzIPMQfyMNhhGPhUkYOs5KpL4U8rLKemX1yGLhDgUto= golang.org/x/crypto v0.0.0-20191206172530-e9b2fee46413/go.mod h1:LzIPMQfyMNhhGPhUkYOs5KpL4U8rLKemX1yGLhDgUto=
golang.org/x/crypto v0.0.0-20200117160349-530e935923ad h1:Jh8cai0fqIK+f6nG0UgPW5wFk8wmiMhM3AyciDBdtQg=
golang.org/x/crypto v0.0.0-20200117160349-530e935923ad/go.mod h1:LzIPMQfyMNhhGPhUkYOs5KpL4U8rLKemX1yGLhDgUto=
golang.org/x/net v0.0.0-20190311183353-d8887717615a/go.mod h1:t9HGtf8HONx5eT2rtn7q6eTqICYqUVnKs3thJo3Qplg= golang.org/x/net v0.0.0-20190311183353-d8887717615a/go.mod h1:t9HGtf8HONx5eT2rtn7q6eTqICYqUVnKs3thJo3Qplg=
golang.org/x/net v0.0.0-20190404232315-eb5bcb51f2a3/go.mod h1:t9HGtf8HONx5eT2rtn7q6eTqICYqUVnKs3thJo3Qplg= golang.org/x/net v0.0.0-20190404232315-eb5bcb51f2a3/go.mod h1:t9HGtf8HONx5eT2rtn7q6eTqICYqUVnKs3thJo3Qplg=
golang.org/x/net v0.0.0-20190503192946-f4e77d36d62c/go.mod h1:t9HGtf8HONx5eT2rtn7q6eTqICYqUVnKs3thJo3Qplg= golang.org/x/net v0.0.0-20190503192946-f4e77d36d62c/go.mod h1:t9HGtf8HONx5eT2rtn7q6eTqICYqUVnKs3thJo3Qplg=
golang.org/x/net v0.0.0-20190827160401-ba9fcec4b297/go.mod h1:z5CRVTTTmAJ677TzLLGU+0bjPO0LkuOLi4/5GtJWs/s= golang.org/x/net v0.0.0-20190827160401-ba9fcec4b297/go.mod h1:z5CRVTTTmAJ677TzLLGU+0bjPO0LkuOLi4/5GtJWs/s=
golang.org/x/net v0.0.0-20191003171128-d98b1b443823/go.mod h1:z5CRVTTTmAJ677TzLLGU+0bjPO0LkuOLi4/5GtJWs/s= golang.org/x/net v0.0.0-20191003171128-d98b1b443823/go.mod h1:z5CRVTTTmAJ677TzLLGU+0bjPO0LkuOLi4/5GtJWs/s=
golang.org/x/net v0.0.0-20191007182048-72f939374954/go.mod h1:z5CRVTTTmAJ677TzLLGU+0bjPO0LkuOLi4/5GtJWs/s= golang.org/x/net v0.0.0-20191007182048-72f939374954/go.mod h1:z5CRVTTTmAJ677TzLLGU+0bjPO0LkuOLi4/5GtJWs/s=
golang.org/x/net v0.0.0-20191209160850-c0dbc17a3553 h1:efeOvDhwQ29Dj3SdAV/MJf8oukgn+8D8WgaCaRMchF8=
golang.org/x/net v0.0.0-20191209160850-c0dbc17a3553/go.mod h1:z5CRVTTTmAJ677TzLLGU+0bjPO0LkuOLi4/5GtJWs/s= golang.org/x/net v0.0.0-20191209160850-c0dbc17a3553/go.mod h1:z5CRVTTTmAJ677TzLLGU+0bjPO0LkuOLi4/5GtJWs/s=
golang.org/x/sys v0.0.0-20190215142949-d0b11bdaac8a/go.mod h1:STP8DvDyc/dI5b8T5hshtkjS+E42TnysNCUPdjciGhY= golang.org/x/sys v0.0.0-20190215142949-d0b11bdaac8a/go.mod h1:STP8DvDyc/dI5b8T5hshtkjS+E42TnysNCUPdjciGhY=
golang.org/x/sys v0.0.0-20190222072716-a9d3bda3a223/go.mod h1:STP8DvDyc/dI5b8T5hshtkjS+E42TnysNCUPdjciGhY= golang.org/x/sys v0.0.0-20190222072716-a9d3bda3a223/go.mod h1:STP8DvDyc/dI5b8T5hshtkjS+E42TnysNCUPdjciGhY=
@ -88,7 +84,6 @@ golang.org/x/sys v0.0.0-20190411185658-b44545bcd369/go.mod h1:h1NjWce9XRLGQEsW7w
golang.org/x/sys v0.0.0-20190412213103-97732733099d/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= golang.org/x/sys v0.0.0-20190412213103-97732733099d/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs=
golang.org/x/sys v0.0.0-20190422165155-953cdadca894/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= golang.org/x/sys v0.0.0-20190422165155-953cdadca894/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs=
golang.org/x/sys v0.0.0-20190507160741-ecd444e8653b/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= golang.org/x/sys v0.0.0-20190507160741-ecd444e8653b/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs=
golang.org/x/sys v0.0.0-20190813064441-fde4db37ae7a h1:aYOabOQFp6Vj6W1F80affTUvO9UxmJRx8K0gsfABByQ=
golang.org/x/sys v0.0.0-20190813064441-fde4db37ae7a/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= golang.org/x/sys v0.0.0-20190813064441-fde4db37ae7a/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs=
golang.org/x/sys v0.0.0-20190826190057-c7b8b68b1456/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= golang.org/x/sys v0.0.0-20190826190057-c7b8b68b1456/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs=
golang.org/x/sys v0.0.0-20191003212358-c178f38b412c/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= golang.org/x/sys v0.0.0-20191003212358-c178f38b412c/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs=

View File

@ -2,15 +2,16 @@ package model


import "time" import "time"


// client structure
type Client struct { type Client struct {
Id string `json:"id"` Id string `json:"id"`
Name string `json:"name"` Name string `json:"name"`
Email string `json:"email"` Email string `json:"email"`
Enable bool `json:"enable"` Enable bool `json:"enable"`
Created time.Time `json:"created"` Created time.Time `json:"created"`
Updated time.Time `json:"updated"` Updated time.Time `json:"updated"`
AllowedIPs string `json:"allowedIPs"` AllowedIPs string `json:"allowedIPs"`
Address string `json:"address"` Address string `json:"address"`
PrivateKey string `json:"privateKey"` PrivateKey string `json:"privateKey"`
PublicKey string `json:"publicKey"` PublicKey string `json:"publicKey"`
} }

View File

@ -2,16 +2,17 @@ package model


import "time" import "time"


// server structure
type Server struct { type Server struct {
Name string `json:"name"` Name string `json:"name"`
Created time.Time `json:"created"` Created time.Time `json:"created"`
Updated time.Time `json:"updated"` Updated time.Time `json:"updated"`
Address string `json:"address"` Address string `json:"address"`
ListenPort int `json:"listenPort"` ListenPort int `json:"listenPort"`
PrivateKey string `json:"privateKey"` PrivateKey string `json:"privateKey"`
PublicKey string `json:"publicKey"` PublicKey string `json:"publicKey"`
PresharedKey string `json:"presharedKey"` PresharedKey string `json:"presharedKey"`
Endpoint string `json:"endpoint"` Endpoint string `json:"endpoint"`
PersistentKeepalive int `json:"persistentKeepalive"` PersistentKeepalive int `json:"persistentKeepalive"`
Dns string `json:"dns"` Dns string `json:"dns"`
} }

View File

@ -16,6 +16,9 @@ import (
"time" "time"
) )


/*
* Create client with all necessary data
*/
func CreateClient(client *model.Client) (*model.Client, error) { func CreateClient(client *model.Client) (*model.Client, error) {
u := uuid.NewV4() u := uuid.NewV4()
client.Id = u.String() client.Id = u.String()
@ -37,10 +40,10 @@ func CreateClient(client *model.Client) (*model.Client, error) {
for _, client := range clients { for _, client := range clients {
ips := strings.Split(client.Address, ",") ips := strings.Split(client.Address, ",")
for i := range ips { for i := range ips {
if util.IsIPv6(ips[i]){ if util.IsIPv6(ips[i]) {
ips[i] = strings.ReplaceAll(strings.TrimSpace(ips[i]), "/128","") ips[i] = strings.ReplaceAll(strings.TrimSpace(ips[i]), "/128", "")
} else { } else {
ips[i] = strings.ReplaceAll(strings.TrimSpace(ips[i]), "/32","") ips[i] = strings.ReplaceAll(strings.TrimSpace(ips[i]), "/32", "")
} }
} }
reserverIps = append(reserverIps, ips...) reserverIps = append(reserverIps, ips...)
@ -56,7 +59,7 @@ func CreateClient(client *model.Client) (*model.Client, error) {
if err != nil { if err != nil {
return nil, err return nil, err
} }
if util.IsIPv6(ip){ if util.IsIPv6(ip) {
ip = ip + "/128" ip = ip + "/128"
} else { } else {
ip = ip + "/32" ip = ip + "/32"
@ -82,6 +85,9 @@ func CreateClient(client *model.Client) (*model.Client, error) {
return client, nil return client, nil
} }


/*
* Read client by id
*/
func ReadClient(id string) (*model.Client, error) { func ReadClient(id string) (*model.Client, error) {
v, err := deserialize(id) v, err := deserialize(id)
if err != nil { if err != nil {
@ -92,6 +98,9 @@ func ReadClient(id string) (*model.Client, error) {
return client, nil return client, nil
} }


/*
* Get client config ion wg format
*/
func ReadClientConfig(id string) ([]byte, error) { func ReadClientConfig(id string) ([]byte, error) {
client, err := ReadClient(id) client, err := ReadClient(id)
if err != nil { if err != nil {
@ -111,6 +120,9 @@ func ReadClientConfig(id string) ([]byte, error) {
return configDataWg.Bytes(), nil return configDataWg.Bytes(), nil
} }


/*
* Update client preserve keys
*/
func UpdateClient(Id string, client *model.Client) (*model.Client, error) { func UpdateClient(Id string, client *model.Client) (*model.Client, error) {
v, err := deserialize(Id) v, err := deserialize(Id)
if err != nil { if err != nil {
@ -141,6 +153,9 @@ func UpdateClient(Id string, client *model.Client) (*model.Client, error) {
return client, nil return client, nil
} }


/*
* Delete client from disk
*/
func DeleteClient(id string) error { func DeleteClient(id string) error {
path := filepath.Join(os.Getenv("WG_CONF_DIR"), id) path := filepath.Join(os.Getenv("WG_CONF_DIR"), id)
err := os.Remove(path) err := os.Remove(path)
@ -152,6 +167,9 @@ func DeleteClient(id string) error {
return generateWgConfig() return generateWgConfig()
} }


/*
* Read all clients
*/
func ReadClients() ([]*model.Client, error) { func ReadClients() ([]*model.Client, error) {
clients := make([]*model.Client, 0) clients := make([]*model.Client, 0)


@ -253,6 +271,7 @@ func UpdateServer(server *model.Server) (*model.Server, error) {


return server, nil return server, nil
} }

/* /*
* Write object to disk * Write object to disk
*/ */
@ -270,6 +289,7 @@ func serialize(id string, c interface{}) error {
// data modified, dump new config // data modified, dump new config
return generateWgConfig() return generateWgConfig()
} }

/* /*
* Read client from disc * Read client from disc
*/ */
@ -282,6 +302,7 @@ func deserializeClient(data []byte) (*model.Client, error) {


return c, nil return c, nil
} }

/* /*
* Read server from disc * Read server from disc
*/ */
@ -307,6 +328,7 @@ func deserialize(id string) (interface{}, error) {


return deserializeClient(b) return deserializeClient(b)
} }

/* /*
* Generate Wireguard interface configuration * Generate Wireguard interface configuration
*/ */

View File

@ -40,6 +40,7 @@ AllowedIPs = {{.Address}}
{{end}}` {{end}}`
) )


// dump client wg config with go template
func DumpClient(client *model.Client, server *model.Server) (bytes.Buffer, error) { func DumpClient(client *model.Client, server *model.Server) (bytes.Buffer, error) {
var tplBuff bytes.Buffer var tplBuff bytes.Buffer


@ -57,6 +58,7 @@ func DumpClient(client *model.Client, server *model.Server) (bytes.Buffer, error
}) })
} }


// dump server wg config with go template
func DumpServerWg(clients []*model.Client, server *model.Server) (bytes.Buffer, error) { func DumpServerWg(clients []*model.Client, server *model.Server) (bytes.Buffer, error) {
var tplBuff bytes.Buffer var tplBuff bytes.Buffer


@ -66,17 +68,17 @@ func DumpServerWg(clients []*model.Client, server *model.Server) (bytes.Buffer,
} }


return dump(t, struct { return dump(t, struct {
Clients []*model.Client Clients []*model.Client
Server *model.Server Server *model.Server
ServerAdresses []string ServerAdresses []string
}{ }{
ServerAdresses: strings.Split(server.Address, ","), ServerAdresses: strings.Split(server.Address, ","),
Clients: clients, Clients: clients,
Server: server, Server: server,
}) })
} }


func dump(tpl *template.Template , data interface{}) (bytes.Buffer, error) { func dump(tpl *template.Template, data interface{}) (bytes.Buffer, error) {
var tplBuff bytes.Buffer var tplBuff bytes.Buffer


err := tpl.Execute(&tplBuff, data) err := tpl.Execute(&tplBuff, data)

View File

@ -8,6 +8,7 @@ import (
"strings" "strings"
) )


// read file content
func ReadFile(path string) (bytes []byte, err error) { func ReadFile(path string) (bytes []byte, err error) {
bytes, err = ioutil.ReadFile(path) bytes, err = ioutil.ReadFile(path)
if err != nil { if err != nil {
@ -17,6 +18,7 @@ func ReadFile(path string) (bytes []byte, err error) {
return bytes, nil return bytes, nil
} }


// write content to file
func WriteFile(path string, bytes []byte) (err error) { func WriteFile(path string, bytes []byte) (err error) {
err = ioutil.WriteFile(path, bytes, 0644) err = ioutil.WriteFile(path, bytes, 0644)
if err != nil { if err != nil {
@ -26,6 +28,7 @@ func WriteFile(path string, bytes []byte) (err error) {
return nil return nil
} }


// check if file exists
func FileExists(name string) bool { func FileExists(name string) bool {
info, err := os.Stat(name) info, err := os.Stat(name)
if os.IsNotExist(err) { if os.IsNotExist(err) {
@ -34,6 +37,7 @@ func FileExists(name string) bool {
return !info.IsDir() return !info.IsDir()
} }


// check if directory exists
func DirectoryExists(name string) bool { func DirectoryExists(name string) bool {
info, err := os.Stat(name) info, err := os.Stat(name)
if os.IsNotExist(err) { if os.IsNotExist(err) {
@ -42,6 +46,7 @@ func DirectoryExists(name string) bool {
return info.IsDir() return info.IsDir()
} }


// search for an available in cidr against a list of reserved ips
func GetAvailableIp(cidr string, reserved []string) (string, error) { func GetAvailableIp(cidr string, reserved []string) (string, error) {
addresses, err := GetAllAddressesFromCidr(cidr) addresses, err := GetAllAddressesFromCidr(cidr)
if err != nil { if err != nil {
@ -64,6 +69,7 @@ func GetAvailableIp(cidr string, reserved []string) (string, error) {
return "", errors.New("no more available address from cidr") return "", errors.New("no more available address from cidr")
} }


// get all ip addresses from cidr
func GetAllAddressesFromCidr(cidr string) ([]string, error) { func GetAllAddressesFromCidr(cidr string) ([]string, error) {
ip, ipnet, err := net.ParseCIDR(cidr) ip, ipnet, err := net.ParseCIDR(cidr)
if err != nil { if err != nil {
@ -88,6 +94,7 @@ func inc(ip net.IP) {
} }
} }


// check if given ip is IPv6
func IsIPv6(address string) bool { func IsIPv6(address string) bool {
return strings.Count(address, ":") >= 2 return strings.Count(address, ":") >= 2
} }