diff options
| author | James Henstridge <james@jamesh.id.au> | 2019-06-06 10:34:23 +0800 |
|---|---|---|
| committer | James Henstridge <james@jamesh.id.au> | 2019-06-25 09:56:48 +0800 |
| commit | c1fdc932f4006b63a766e86077a2c637ad689662 (patch) | |
| tree | ad568bb421c81627e87fd6064e1190b3b2897bed /netutil | |
| parent | 57f9ad71fb299c809adb0fc06601fa07219baae3 (diff) | |
netutil: extract socket activation helpers from daemon package.
Diffstat (limited to 'netutil')
| -rw-r--r-- | netutil/activation.go | 85 |
1 files changed, 85 insertions, 0 deletions
diff --git a/netutil/activation.go b/netutil/activation.go new file mode 100644 index 0000000000..48f1205b70 --- /dev/null +++ b/netutil/activation.go @@ -0,0 +1,85 @@ +// -*- Mode: Go; indent-tabs-mode: t -*- + +/* + * Copyright (C) 2015-2019 Canonical Ltd + * + * This program is free software: you can redistribute it and/or modify + * it under the terms of the GNU General Public License version 3 as + * published by the Free Software Foundation. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program. If not, see <http://www.gnu.org/licenses/>. + * + */ + +package netutil + +import ( + "fmt" + "net" + "os" + "runtime" + unix "syscall" + + "github.com/coreos/go-systemd/activation" + + "github.com/snapcore/snapd/logger" +) + +// GetListener tries to get a listener for the given socket path from +// the listener map, and if it fails it tries to set it up directly. +func GetListener(socketPath string, listenerMap map[string]net.Listener) (net.Listener, error) { + if listener, ok := listenerMap[socketPath]; ok { + return listener, nil + } + + if c, err := net.Dial("unix", socketPath); err == nil { + c.Close() + return nil, fmt.Errorf("socket %q already in use", socketPath) + } + + if err := os.Remove(socketPath); err != nil && !os.IsNotExist(err) { + return nil, err + } + + address, err := net.ResolveUnixAddr("unix", socketPath) + if err != nil { + return nil, err + } + + runtime.LockOSThread() + oldmask := unix.Umask(0111) + listener, err := net.ListenUnix("unix", address) + unix.Umask(oldmask) + runtime.UnlockOSThread() + if err != nil { + return nil, err + } + + logger.Debugf("socket %q was not activated; listening", socketPath) + + return listener, nil +} + +// ActivationListeners builds a map of addresses to listeners that were passed +// during systemd activation +func ActivationListeners() (lns map[string]net.Listener, err error) { + // pass false to keep LISTEN_* environment variables passed by systemd + files := activation.Files(false) + lns = make(map[string]net.Listener, len(files)) + + for _, f := range files { + ln, err := net.FileListener(f) + if err != nil { + return nil, err + } + addr := ln.Addr().String() + lns[addr] = ln + } + return lns, nil +} |
