netlink_deprecated_linux.go 2.7 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126
  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 ioctlSetMacAddress(name, addr string) error {
  65. if len(name) >= ifNameSize {
  66. return fmt.Errorf("Interface name %s too long", name)
  67. }
  68. hw, err := net.ParseMAC(addr)
  69. if err != nil {
  70. return err
  71. }
  72. s, err := getIfSocket()
  73. if err != nil {
  74. return err
  75. }
  76. defer syscall.Close(s)
  77. ifr := ifreqHwaddr{}
  78. ifr.IfruHwaddr.Family = syscall.ARPHRD_ETHER
  79. copy(ifr.IfrnName[:len(ifr.IfrnName)-1], name)
  80. for i := 0; i < 6; i++ {
  81. ifr.IfruHwaddr.Data[i] = ifrDataByte(hw[i])
  82. }
  83. if _, _, err := syscall.Syscall(syscall.SYS_IOCTL, uintptr(s), syscall.SIOCSIFHWADDR, uintptr(unsafe.Pointer(&ifr))); err != 0 {
  84. return err
  85. }
  86. return nil
  87. }
  88. func ioctlCreateBridge(name, macAddr string) error {
  89. if len(name) >= ifNameSize {
  90. return fmt.Errorf("Interface name %s too long", name)
  91. }
  92. s, err := getIfSocket()
  93. if err != nil {
  94. return err
  95. }
  96. defer syscall.Close(s)
  97. nameBytePtr, err := syscall.BytePtrFromString(name)
  98. if err != nil {
  99. return err
  100. }
  101. if _, _, err := syscall.Syscall(syscall.SYS_IOCTL, uintptr(s), ioctlBrAdd, uintptr(unsafe.Pointer(nameBytePtr))); err != 0 {
  102. return err
  103. }
  104. return ioctlSetMacAddress(name, macAddr)
  105. }