Skip to content

Commit d6f89c3

Browse files
committed
Add generation of MAC addresses when not specified in the configuration file for a TAP net type. Move pidFile() and uuidFile() to a new file internal/config/file.go along with a new hwaddrFile() function
1 parent c19ca61 commit d6f89c3

File tree

4 files changed

+118
-38
lines changed

4 files changed

+118
-38
lines changed

TODO.md

Lines changed: 2 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -8,7 +8,6 @@
88

99
- Reorganize internal/config to move VM action logic outside of config, eg. vm/vm.go
1010
- Generate HDD if it doesn't already exist
11-
- Generate MAC for tap interfaces if not specified, store in .run/vm/\<name\>/\<net\>_mac
1211
- Check write privs on run_dir, pid, and tty in Validate()
1312
- Check write privs on hdd, read privs on cdrom
1413
- Add template support for kexec cmdline for IP, ssh public
@@ -62,7 +61,6 @@ Configuring Network: "net0"
6261
cmd: ifconfig bridge1 192.168.99.1 netmask 0xffffff00
6362
cmd: ifconfig bridge1 192.168.99.1 netmask 0xffffff00
6463

65-
6664
## Completed
6765

6866
- Add arg to each relevant command to work on specific VM
@@ -77,4 +75,5 @@ cmd: ifconfig bridge1 192.168.99.1 netmask 0xffffff00
7775
- Make relative paths in a VM config relative to the run_dir
7876
- Add pid in status output
7977
- Add CI, CircleCI, clean code, etc.
80-
- Generate UUID if not specified, store in .run/vm/\<name\>/uuid
78+
- Generate UUID if not specified, store in .run/vm/\<name\>/uuid
79+
- Generate MAC for tap interfaces if not specified, store in .run/vm/\<name\>/\<net\>_mac

internal/config/file.go

Lines changed: 62 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,62 @@
1+
package config
2+
3+
import (
4+
"fmt"
5+
"io/ioutil"
6+
"net"
7+
"os"
8+
"strconv"
9+
10+
"github.com/google/uuid"
11+
)
12+
13+
func pidFile(path string) (int, error) {
14+
if _, err := os.Stat(path); os.IsNotExist(err) {
15+
return 0, fmt.Errorf("pid file not found")
16+
}
17+
pidTxt, err := ioutil.ReadFile(path)
18+
if err != nil {
19+
return 0, fmt.Errorf("pid file cannot be read")
20+
}
21+
22+
pid, err := strconv.Atoi(string(pidTxt))
23+
if err != nil {
24+
return 0, fmt.Errorf("pid file does not contain an integer")
25+
}
26+
27+
return pid, nil
28+
}
29+
30+
func uuidFile(path string) (uuid.UUID, error) {
31+
if _, err := os.Stat(path); os.IsNotExist(err) {
32+
return [16]byte{}, fmt.Errorf("uuid file not found")
33+
}
34+
uuidTxt, err := ioutil.ReadFile(path)
35+
if err != nil {
36+
return [16]byte{}, fmt.Errorf("uuid file cannot be read")
37+
}
38+
39+
uuid, err := uuid.Parse(string(uuidTxt))
40+
if err != nil {
41+
return [16]byte{}, fmt.Errorf("uuid file does not contain an UUID")
42+
}
43+
44+
return uuid, nil
45+
}
46+
47+
func hwaddrFile(path string) (net.HardwareAddr, error) {
48+
if _, err := os.Stat(path); os.IsNotExist(err) {
49+
return nil, fmt.Errorf("mac addr file not found")
50+
}
51+
hwaddrTxt, err := ioutil.ReadFile(path)
52+
if err != nil {
53+
return nil, fmt.Errorf("mac addr file cannot be read")
54+
}
55+
56+
hwaddr, err := net.ParseMAC(string(hwaddrTxt))
57+
if err != nil {
58+
return nil, fmt.Errorf("mac addr file does not contain a hardware address")
59+
}
60+
61+
return hwaddr, nil
62+
}

internal/config/network.go

Lines changed: 17 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1,6 +1,7 @@
11
package config
22

33
import (
4+
"crypto/rand"
45
"fmt"
56
"net"
67
"strings"
@@ -129,3 +130,19 @@ func (v *VPNKit) Up() error {
129130
func (v *VPNKit) Destroy() error {
130131
return nil
131132
}
133+
134+
// genMAC creates a random 6 byte hardware address, eg. MAC address.
135+
// The address generated has the locally administered bit set and
136+
// is a unicast address.
137+
func genMAC() (net.HardwareAddr, error) {
138+
buf := make([]byte, 6)
139+
_, err := rand.Read(buf)
140+
if err != nil {
141+
return nil, err
142+
}
143+
144+
// Set local bit, ensure unicast address
145+
buf[0] = (buf[0] | 2) & 0xfe
146+
147+
return buf, nil
148+
}

internal/config/vm.go

Lines changed: 37 additions & 35 deletions
Original file line numberDiff line numberDiff line change
@@ -3,7 +3,6 @@ package config
33
import (
44
"errors"
55
"fmt"
6-
"io/ioutil"
76
"os"
87
"os/exec"
98
"path/filepath"
@@ -172,40 +171,6 @@ func sigLookup(s string) (syscall.Signal, error) {
172171
return sig, nil
173172
}
174173

175-
func pidFile(path string) (int, error) {
176-
if _, err := os.Stat(path); os.IsNotExist(err) {
177-
return 0, fmt.Errorf("pid file not found")
178-
}
179-
pidTxt, err := ioutil.ReadFile(path)
180-
if err != nil {
181-
return 0, fmt.Errorf("pid file cannot be read")
182-
}
183-
184-
pid, err := strconv.Atoi(string(pidTxt))
185-
if err != nil {
186-
return 0, fmt.Errorf("pid file does not contain an integer")
187-
}
188-
189-
return pid, nil
190-
}
191-
192-
func uuidFile(path string) (uuid.UUID, error) {
193-
if _, err := os.Stat(path); os.IsNotExist(err) {
194-
return [16]byte{}, fmt.Errorf("uuid file not found")
195-
}
196-
uuidTxt, err := ioutil.ReadFile(path)
197-
if err != nil {
198-
return [16]byte{}, fmt.Errorf("uuid file cannot be read")
199-
}
200-
201-
uuid, err := uuid.Parse(string(uuidTxt))
202-
if err != nil {
203-
return [16]byte{}, fmt.Errorf("uuid file does not contain an UUID")
204-
}
205-
206-
return uuid, nil
207-
}
208-
209174
func (v *VMConfig) Cli() []string {
210175

211176
var args []string
@@ -307,6 +272,13 @@ func (v *VMConfig) defaults(configDir string, name string) error {
307272
}
308273
v.UUID = UUID.String()
309274
}
275+
276+
for _, net := range v.Network {
277+
if err := net.defaults(v.RunDir); err != nil {
278+
return err
279+
}
280+
}
281+
310282
return nil
311283
}
312284

@@ -494,6 +466,36 @@ func (n *NetConf) validate() error {
494466
return nil
495467
}
496468

469+
func (n *NetConf) defaults(runDir string) error {
470+
switch n.Driver {
471+
472+
case "virtio-tap":
473+
if n.MAC == "" {
474+
MAC, err := hwaddrFile(runDir + "/" + n.MemberOf + "_mac")
475+
476+
if err != nil {
477+
MAC, err = genMAC()
478+
if err != nil {
479+
return err
480+
}
481+
482+
w, err := os.Create(runDir + "/" + n.MemberOf + "_mac")
483+
if err != nil {
484+
return err
485+
}
486+
487+
defer w.Close()
488+
489+
if _, err := w.WriteString(MAC.String()); err != nil {
490+
return err
491+
}
492+
}
493+
n.MAC = MAC.String()
494+
}
495+
}
496+
return nil
497+
}
498+
497499
func (n *NetConf) devicePath() string {
498500
if n.Device[:1] == "/" {
499501
return n.Device

0 commit comments

Comments
 (0)