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