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