netlink_deprecated_linux.go 2.8 KB

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