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  }