netlink: Add NetworkSetMacAddress

Signed-off-by: Lewis Marshall <lewis@lmars.net>
This commit is contained in:
Lewis Marshall 2014-09-18 01:16:37 +01:00
parent e1d882b523
commit 80a574ab49
4 changed files with 56 additions and 18 deletions

View File

@ -4,6 +4,7 @@ import (
"encoding/binary" "encoding/binary"
"fmt" "fmt"
"io" "io"
"math/rand"
"net" "net"
"sync/atomic" "sync/atomic"
"syscall" "syscall"
@ -932,7 +933,7 @@ func CreateBridge(name string, setMacAddr bool) error {
return err return err
} }
if setMacAddr { if setMacAddr {
return setBridgeMacAddress(s, name) return NetworkSetMacAddress(name, randMacAddr())
} }
return nil return nil
} }
@ -988,22 +989,40 @@ func AddToBridge(iface, master *net.Interface) error {
return nil return nil
} }
func setBridgeMacAddress(s int, name string) error { func randMacAddr() string {
hw := make(net.HardwareAddr, 6)
for i := 0; i < 6; i++ {
hw[i] = byte(rand.Intn(255))
}
hw[0] &^= 0x1 // clear multicast bit
hw[0] |= 0x2 // set local assignment bit (IEEE802)
return hw.String()
}
func NetworkSetMacAddress(name, addr string) error {
if len(name) >= IFNAMSIZ { if len(name) >= IFNAMSIZ {
return fmt.Errorf("Interface name %s too long", name) return fmt.Errorf("Interface name %s too long", name)
} }
hw, err := net.ParseMAC(addr)
if err != nil {
return err
}
s, err := getIfSocket()
if err != nil {
return err
}
defer syscall.Close(s)
ifr := ifreqHwaddr{} ifr := ifreqHwaddr{}
ifr.IfruHwaddr.Family = syscall.ARPHRD_ETHER ifr.IfruHwaddr.Family = syscall.ARPHRD_ETHER
copy(ifr.IfrnName[:len(ifr.IfrnName)-1], name) copy(ifr.IfrnName[:len(ifr.IfrnName)-1], name)
for i := 0; i < 6; i++ { for i := 0; i < 6; i++ {
ifr.IfruHwaddr.Data[i] = randIfrDataByte() ifr.IfruHwaddr.Data[i] = ifrDataByte(hw[i])
} }
ifr.IfruHwaddr.Data[0] &^= 0x1 // clear multicast bit
ifr.IfruHwaddr.Data[0] |= 0x2 // set local assignment bit (IEEE802)
if _, _, err := syscall.Syscall(syscall.SYS_IOCTL, uintptr(s), syscall.SIOCSIFHWADDR, uintptr(unsafe.Pointer(&ifr))); err != 0 { if _, _, err := syscall.Syscall(syscall.SYS_IOCTL, uintptr(s), syscall.SIOCSIFHWADDR, uintptr(unsafe.Pointer(&ifr))); err != 0 {
return err return err
} }

View File

@ -1,9 +1,5 @@
package netlink package netlink
import ( func ifrDataByte(b byte) uint8 {
"math/rand" return uint8(b)
)
func randIfrDataByte() uint8 {
return uint8(rand.Intn(255))
} }

View File

@ -2,10 +2,6 @@
package netlink package netlink
import ( func ifrDataByte(b byte) int8 {
"math/rand" return int8(b)
)
func randIfrDataByte() int8 {
return int8(rand.Intn(255))
} }

View File

@ -125,3 +125,30 @@ func TestCreateVethPair(t *testing.T) {
t.Fatal(err) t.Fatal(err)
} }
} }
func TestSetMACAddress(t *testing.T) {
if testing.Short() {
return
}
name := "testmac"
mac := randMacAddr()
if err := NetworkLinkAdd(name, "bridge"); err != nil {
t.Fatal(err)
}
defer NetworkLinkDel(name)
if err := NetworkSetMacAddress(name, mac); err != nil {
t.Fatal(err)
}
iface, err := net.InterfaceByName(name)
if err != nil {
t.Fatal(err)
}
if iface.HardwareAddr.String() != mac {
t.Fatalf("mac address %q does not match %q", iface.HardwareAddr, mac)
}
}