Merge pull request #194 from lmars/netlink-set-mac-addr

netlink: Add NetworkSetMacAddress
This commit is contained in:
Michael Crosby 2014-09-19 11:18:51 -07:00
commit 185328a426
4 changed files with 56 additions and 18 deletions

View File

@ -4,6 +4,7 @@ import (
"encoding/binary"
"fmt"
"io"
"math/rand"
"net"
"sync/atomic"
"syscall"
@ -932,7 +933,7 @@ func CreateBridge(name string, setMacAddr bool) error {
return err
}
if setMacAddr {
return setBridgeMacAddress(s, name)
return NetworkSetMacAddress(name, randMacAddr())
}
return nil
}
@ -988,22 +989,40 @@ func AddToBridge(iface, master *net.Interface) error {
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 {
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.IfruHwaddr.Family = syscall.ARPHRD_ETHER
copy(ifr.IfrnName[:len(ifr.IfrnName)-1], name)
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 {
return err
}

View File

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

View File

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

View File

@ -125,3 +125,30 @@ func TestCreateVethPair(t *testing.T) {
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)
}
}