forked from terra-farm/go-virtualbox
-
Notifications
You must be signed in to change notification settings - Fork 0
/
hostonlynet.go
156 lines (143 loc) · 4 KB
/
hostonlynet.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
148
149
150
151
152
153
154
155
156
package virtualbox
import (
"bufio"
"errors"
"fmt"
"net"
"os/exec"
"regexp"
"runtime"
"strconv"
"strings"
)
var (
reHostonlyInterfaceCreated = regexp.MustCompile(`Interface '(.+)' was successfully created`)
)
var (
// ErrHostonlyInterfaceCreation is the error message created when VBoxManaged failed to create a new hostonly interface.
ErrHostonlyInterfaceCreation = errors.New("failed to create hostonly interface")
)
// HostonlyNet defines each host-only network.
type HostonlyNet struct {
Name string
GUID string
DHCP bool
IPv4 net.IPNet
IPv6 net.IPNet
HwAddr net.HardwareAddr
Medium string
Status string
NetworkName string // referenced in DHCP.NetworkName
}
// CreateHostonlyNet creates a new host-only network.
func CreateHostonlyNet() (*HostonlyNet, error) {
out, _, err := Manage().run("hostonlyif", "create")
if err != nil {
return nil, err
}
res := reHostonlyInterfaceCreated.FindStringSubmatch(out)
if res == nil {
return nil, ErrHostonlyInterfaceCreation
}
return &HostonlyNet{Name: res[1]}, nil
}
// Config changes the configuration of the host-only network.
func (n *HostonlyNet) Config() error {
//We need a windowsfix because of https://www.virtualbox.org/ticket/8796
if runtime.GOOS == osWindows {
if n.IPv4.IP != nil && n.IPv4.Mask != nil {
cmd := exec.Command("netsh", "interface", "ip", "set", "address", fmt.Sprintf("name=\"%s\"", n.Name), "static", n.IPv4.IP.String(), net.IP(n.IPv4.Mask).String()) // #nosec
if err := cmd.Run(); err != nil {
return err
}
}
if n.IPv6.IP != nil && n.IPv6.Mask != nil {
prefixLen, _ := n.IPv6.Mask.Size()
cmd := exec.Command("netsh", "interface", "ipv6", "add", "address", n.Name, fmt.Sprintf("%s/%d", n.IPv6.IP.String(), prefixLen)) // #nosec
if err := cmd.Run(); err != nil {
return err
}
}
if n.DHCP {
if _, _, err := Manage().run("hostonlyif", "ipconfig", fmt.Sprintf("\"%s\"", n.Name), "--dhcp"); err != nil { // not implemented as of VirtualBox 4.3
return err
}
}
} else {
if n.IPv4.IP != nil && n.IPv4.Mask != nil {
if _, _, err := Manage().run("hostonlyif", "ipconfig", n.Name, "--ip", n.IPv4.IP.String(), "--netmask", net.IP(n.IPv4.Mask).String()); err != nil {
return err
}
}
if n.IPv6.IP != nil && n.IPv6.Mask != nil {
prefixLen, _ := n.IPv6.Mask.Size()
if _, _, err := Manage().run("hostonlyif", "ipconfig", n.Name, "--ipv6", n.IPv6.IP.String(), "--netmasklengthv6", fmt.Sprintf("%d", prefixLen)); err != nil {
return err
}
}
if n.DHCP {
if _, _, err := Manage().run("hostonlyif", "ipconfig", n.Name, "--dhcp"); err != nil { // not implemented as of VirtualBox 4.3
return err
}
}
}
return nil
}
// HostonlyNets gets all host-only networks in a map keyed by HostonlyNet.NetworkName.
func HostonlyNets() (map[string]*HostonlyNet, error) {
out, _, err := Manage().run("list", "hostonlyifs")
if err != nil {
return nil, err
}
s := bufio.NewScanner(strings.NewReader(out))
m := map[string]*HostonlyNet{}
n := &HostonlyNet{}
for s.Scan() {
line := s.Text()
if line == "" {
m[n.NetworkName] = n
n = &HostonlyNet{}
continue
}
res := reColonLine.FindStringSubmatch(line)
if res == nil {
continue
}
switch key, val := res[1], res[2]; key {
case "Name":
n.Name = val
case "GUID":
n.GUID = val
case "DHCP":
n.DHCP = (val != "Disabled")
case "IPAddress":
n.IPv4.IP = net.ParseIP(val)
case "NetworkMask":
n.IPv4.Mask = ParseIPv4Mask(val)
case "IPV6Address":
n.IPv6.IP = net.ParseIP(val)
case "IPV6NetworkMaskPrefixLength":
l, err := strconv.ParseUint(val, 10, 7)
if err != nil {
return nil, err
}
n.IPv6.Mask = net.CIDRMask(int(l), net.IPv6len*8)
case "HardwareAddress":
mac, err := net.ParseMAC(val)
if err != nil {
return nil, err
}
n.HwAddr = mac
case "MediumType":
n.Medium = val
case "Status":
n.Status = val
case "VBoxNetworkName":
n.NetworkName = val
}
}
if err := s.Err(); err != nil {
return nil, err
}
return m, nil
}