diff --git a/network.go b/network.go index fc76bc3421..a230356a7d 100644 --- a/network.go +++ b/network.go @@ -12,6 +12,8 @@ import ( "net" "strconv" "sync" + "syscall" + "unsafe" ) const ( @@ -19,6 +21,7 @@ const ( DisableNetworkBridge = "none" portRangeStart = 49153 portRangeEnd = 65535 + siocBRADDBR = 0x89a0 ) // Calculates the first and last IP addresses in an IPNet @@ -149,8 +152,8 @@ func CreateBridgeIface(config *DaemonConfig) error { } utils.Debugf("Creating bridge %s with network %s", config.BridgeIface, ifaceAddr) - if err := netlink.NetworkLinkAdd(config.BridgeIface, "bridge"); err != nil { - return fmt.Errorf("Error creating bridge: %s", err) + if err := createBridgeIface(config.BridgeIface); err != nil { + return err } iface, err := net.InterfaceByName(config.BridgeIface) if err != nil { @@ -170,6 +173,26 @@ func CreateBridgeIface(config *DaemonConfig) error { return nil } +// Create the actual bridge device. This is more backward-compatible than +// netlink.NetworkLinkAdd and works on RHEL 6. +func createBridgeIface(name string) error { + s, err := syscall.Socket(syscall.AF_INET6, syscall.SOCK_STREAM, syscall.IPPROTO_IP) + if err != nil { + return fmt.Errorf("Error creating bridge creation socket: %s", err) + } + defer syscall.Close(s) + + nameBytePtr, err := syscall.BytePtrFromString(name) + if err != nil { + return fmt.Errorf("Error converting bridge name %s to byte array: %s", name, err) + } + + if _, _, err := syscall.Syscall(syscall.SYS_IOCTL, uintptr(s), siocBRADDBR, uintptr(unsafe.Pointer(nameBytePtr))); err != 0 { + return fmt.Errorf("Error creating bridge: %s", err) + } + return nil +} + // Return the IPv4 address of a network interface func getIfaceAddr(name string) (net.Addr, error) { iface, err := net.InterfaceByName(name)