github.com/juju/juju@v0.0.0-20240430160146-1752b71fcf00/core/network/linklayer.go (about)

     1  // Copyright 2019 Canonical Ltd.
     2  // Licensed under the AGPLv3, see LICENCE file for details.
     3  
     4  package network
     5  
     6  import (
     7  	"runtime"
     8  	"strings"
     9  )
    10  
    11  // LinkLayerDeviceType defines the type of a link-layer network device.
    12  type LinkLayerDeviceType string
    13  
    14  const (
    15  	// UnknownDevice indicates that the type of this device is not known.
    16  	UnknownDevice LinkLayerDeviceType = ""
    17  
    18  	// LoopbackDevice is used for loopback devices.
    19  	LoopbackDevice LinkLayerDeviceType = "loopback"
    20  
    21  	// EthernetDevice is used for Ethernet (IEEE 802.3) devices.
    22  	EthernetDevice LinkLayerDeviceType = "ethernet"
    23  
    24  	// VLAN8021QDevice is used for IEEE 802.1Q VLAN devices.
    25  	VLAN8021QDevice LinkLayerDeviceType = "802.1q"
    26  
    27  	// BondDevice is used for bonding devices.
    28  	BondDevice LinkLayerDeviceType = "bond"
    29  
    30  	// BridgeDevice is used for OSI layer-2 bridge devices.
    31  	BridgeDevice LinkLayerDeviceType = "bridge"
    32  
    33  	// VXLANDevice is used for Virtual Extensible LAN devices.
    34  	VXLANDevice LinkLayerDeviceType = "vxlan"
    35  )
    36  
    37  // IsValidLinkLayerDeviceType returns whether the given value is a valid
    38  // link-layer network device type.
    39  func IsValidLinkLayerDeviceType(value string) bool {
    40  	switch LinkLayerDeviceType(value) {
    41  	case LoopbackDevice, EthernetDevice, VLAN8021QDevice, BondDevice, BridgeDevice, VXLANDevice:
    42  		return true
    43  	}
    44  	return false
    45  }
    46  
    47  // IsValidLinkLayerDeviceName returns whether the given name is a valid network
    48  // link-layer device name, depending on the runtime.GOOS value.
    49  func IsValidLinkLayerDeviceName(name string) bool {
    50  	return isValidLinkLayerDeviceName(name, runtime.GOOS)
    51  }
    52  
    53  func isValidLinkLayerDeviceName(name string, runtimeOS string) bool {
    54  	if runtimeOS == "linux" {
    55  		return isValidLinuxDeviceName(name)
    56  	}
    57  	hasHash := strings.Contains(name, "#")
    58  	return !hasHash && stringLengthBetween(name, 1, 255)
    59  }
    60  
    61  // isValidLinuxDeviceName returns whether the given deviceName is valid,
    62  // using the same criteria as dev_valid_name(9) in the Linux kernel:
    63  // - no whitespace allowed
    64  // - length from 1 to 15 ASCII characters
    65  // - literal "." and ".." as names are not allowed.
    66  // Additionally, we don't allow "#" in the name.
    67  func isValidLinuxDeviceName(name string) bool {
    68  	hasWhitespace := whitespaceReplacer.Replace(name) != name
    69  	isDot, isDoubleDot := name == ".", name == ".."
    70  	hasValidLength := stringLengthBetween(name, 1, 15)
    71  	hasHash := strings.Contains(name, "#")
    72  
    73  	return hasValidLength && !(hasHash || hasWhitespace || isDot || isDoubleDot)
    74  }
    75  
    76  // whitespaceReplacer strips whitespace characters from the input string.
    77  var whitespaceReplacer = strings.NewReplacer(
    78  	" ", "",
    79  	"\t", "",
    80  	"\v", "",
    81  	"\n", "",
    82  	"\r", "",
    83  )
    84  
    85  func stringLengthBetween(value string, minLength, maxLength uint) bool {
    86  	length := uint(len(value))
    87  	return length >= minLength && length <= maxLength
    88  }