diff options
Diffstat (limited to 'sd_login/machined_machine.go')
-rw-r--r-- | sd_login/machined_machine.go | 122 |
1 files changed, 122 insertions, 0 deletions
diff --git a/sd_login/machined_machine.go b/sd_login/machined_machine.go new file mode 100644 index 0000000..d89eaad --- /dev/null +++ b/sd_login/machined_machine.go @@ -0,0 +1,122 @@ +// Copyright (C) 2016-2017 Luke Shumaker <lukeshu@sbcglobal.net> +// +// Licensed under the Apache License, Version 2.0 (the "License"); +// you may not use this file except in compliance with the License. +// You may obtain a copy of the License at +// +// http://www.apache.org/licenses/LICENSE-2.0 +// +// Unless required by applicable law or agreed to in writing, software +// distributed under the License is distributed on an "AS IS" BASIS, +// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +// See the License for the specific language governing permissions and +// limitations under the License. + +package sd_login + +import ( + "strconv" + "strings" + + "golang.org/x/sys/unix" +) + +// A Machine is a name representing a locally running container or +// virtual machine that is registerd with (systemd-)machined. +type Machine string + +// isValid returns whether the Machine name is valid. +func (m Machine) isValid() bool { + if len(m) > host_name_max { + // Note that Linux HOST_NAME_MAX is 64, but DNS allows + // 255, so names from DNS might be invalid. + return false + } + + n_dots := 0 + dot := true + for _, c := range m { + if c == '.' { + if dot { + return false + } + dot = true + n_dots++ + } else { + if !strings.ContainsRune(letters+digits+"-_.", c) { + return false + } + dot = false + } + } + + if dot { // trailing dot or empty + return false + } + + return true +} + +// GetMachines returns a list of currently running containers/virtual +// machines. +func GetMachines() ([]Machine, error) { + strs, err := get_files_in_directory("/run/systemd/machines/") + if err != nil { + return nil, err + } + var machines []Machine + for _, str := range strs { + machine := Machine(str) + if strings.HasPrefix(str, "unit:") || machine.isValid() { + continue + } + machines = append(machines, Machine(str)) + } + return machines, nil +} + +// GetClass returns the class of a locally running machine. The class +// is either "vm" or "container", depending on if the machine is an +// virtual machine or a container. +func (m Machine) GetClass() (string, error) { + if !m.isValid() { + return "", unix.EINVAL + } + + env, err := parse_env_file("/run/systemd/machines/" + string(m)) + if err != nil { + return "", err + } + class, ok := env["CLASS"] + if !ok { + return "", unix.ENXIO // or EIO? + } + return class, nil +} + +// GetIfIndices returns the numeric indices of the network interfaces +// on the host that are pointing toward this machine. +func (m Machine) GetIfIndices() ([]int, error) { + if !m.isValid() { + return nil, unix.EINVAL + } + + env, err := parse_env_file("/run/systemd/machines/" + string(m)) + if err != nil { + return nil, err + } + netif, ok := env["NETIF"] + if !ok { + return nil, unix.ENXIO // or EIO? + } + + var ifindices []int + for _, word := range strings.FieldsFunc(netif, func(c rune) bool { return strings.ContainsRune(whitespace, c) }) { + ifindex, err := strconv.Atoi(word) + if err != nil { + return nil, err + } + ifindices = append(ifindices, ifindex) + } + return ifindices, nil +} |