Merge pull request #194 from lmars/netlink-set-mac-addr
netlink: Add NetworkSetMacAddress
This commit is contained in:
commit
185328a426
|
@ -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
|
||||
}
|
||||
|
|
|
@ -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)
|
||||
}
|
||||
|
|
|
@ -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)
|
||||
}
|
||||
|
|
|
@ -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)
|
||||
}
|
||||
}
|
||||
|
|
Loading…
Reference in New Issue