netlink_deprecated_linux.go 3.0 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139
  1. package bridge
  2. import (
  3. "fmt"
  4. "math/rand"
  5. "net"
  6. "syscall"
  7. "time"
  8. "unsafe"
  9. )
  10. const (
  11. ifNameSize = 16
  12. ioctlBrAdd = 0x89a0
  13. ioctlBrAddIf = 0x89a2
  14. )
  15. type ifreqIndex struct {
  16. IfrnName [ifNameSize]byte
  17. IfruIndex int32
  18. }
  19. type ifreqHwaddr struct {
  20. IfrnName [ifNameSize]byte
  21. IfruHwaddr syscall.RawSockaddr
  22. }
  23. var rnd = rand.New(rand.NewSource(time.Now().UnixNano()))
  24. // THIS CODE DOES NOT COMMUNICATE WITH KERNEL VIA RTNETLINK INTERFACE
  25. // IT IS HERE FOR BACKWARDS COMPATIBILITY WITH OLDER LINUX KERNELS
  26. // WHICH SHIP WITH OLDER NOT ENTIRELY FUNCTIONAL VERSION OF NETLINK
  27. func getIfSocket() (fd int, err error) {
  28. for _, socket := range []int{
  29. syscall.AF_INET,
  30. syscall.AF_PACKET,
  31. syscall.AF_INET6,
  32. } {
  33. if fd, err = syscall.Socket(socket, syscall.SOCK_DGRAM, 0); err == nil {
  34. break
  35. }
  36. }
  37. if err == nil {
  38. return fd, nil
  39. }
  40. return -1, err
  41. }
  42. func ifIoctBridge(iface, master *net.Interface, op uintptr) error {
  43. if len(master.Name) >= ifNameSize {
  44. return fmt.Errorf("Interface name %s too long", master.Name)
  45. }
  46. s, err := getIfSocket()
  47. if err != nil {
  48. return err
  49. }
  50. defer syscall.Close(s)
  51. ifr := ifreqIndex{}
  52. copy(ifr.IfrnName[:len(ifr.IfrnName)-1], master.Name)
  53. ifr.IfruIndex = int32(iface.Index)
  54. if _, _, err := syscall.Syscall(syscall.SYS_IOCTL, uintptr(s), op, uintptr(unsafe.Pointer(&ifr))); err != 0 {
  55. return err
  56. }
  57. return nil
  58. }
  59. // Add a slave to a bridge device. This is more backward-compatible than
  60. // netlink.NetworkSetMaster and works on RHEL 6.
  61. func ioctlAddToBridge(iface, master *net.Interface) error {
  62. return ifIoctBridge(iface, master, ioctlBrAddIf)
  63. }
  64. func randMacAddr() string {
  65. hw := make(net.HardwareAddr, 6)
  66. for i := 0; i < 6; i++ {
  67. hw[i] = byte(rnd.Intn(255))
  68. }
  69. hw[0] &^= 0x1 // clear multicast bit
  70. hw[0] |= 0x2 // set local assignment bit (IEEE802)
  71. return hw.String()
  72. }
  73. func ioctlSetMacAddress(name, addr string) error {
  74. if len(name) >= ifNameSize {
  75. return fmt.Errorf("Interface name %s too long", name)
  76. }
  77. hw, err := net.ParseMAC(addr)
  78. if err != nil {
  79. return err
  80. }
  81. s, err := getIfSocket()
  82. if err != nil {
  83. return err
  84. }
  85. defer syscall.Close(s)
  86. ifr := ifreqHwaddr{}
  87. ifr.IfruHwaddr.Family = syscall.ARPHRD_ETHER
  88. copy(ifr.IfrnName[:len(ifr.IfrnName)-1], name)
  89. for i := 0; i < 6; i++ {
  90. ifr.IfruHwaddr.Data[i] = ifrDataByte(hw[i])
  91. }
  92. if _, _, err := syscall.Syscall(syscall.SYS_IOCTL, uintptr(s), syscall.SIOCSIFHWADDR, uintptr(unsafe.Pointer(&ifr))); err != 0 {
  93. return err
  94. }
  95. return nil
  96. }
  97. func ioctlCreateBridge(name string, setMacAddr bool) error {
  98. if len(name) >= ifNameSize {
  99. return fmt.Errorf("Interface name %s too long", name)
  100. }
  101. s, err := getIfSocket()
  102. if err != nil {
  103. return err
  104. }
  105. defer syscall.Close(s)
  106. nameBytePtr, err := syscall.BytePtrFromString(name)
  107. if err != nil {
  108. return err
  109. }
  110. if _, _, err := syscall.Syscall(syscall.SYS_IOCTL, uintptr(s), ioctlBrAdd, uintptr(unsafe.Pointer(nameBytePtr))); err != 0 {
  111. return err
  112. }
  113. if setMacAddr {
  114. return ioctlSetMacAddress(name, randMacAddr())
  115. }
  116. return nil
  117. }