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