diff --git a/daemon/daemon.go b/daemon/daemon.go index c622a4ae93a..7e6fba320ac 100644 --- a/daemon/daemon.go +++ b/daemon/daemon.go @@ -26,14 +26,11 @@ import ( "os" "os/exec" "os/signal" - "runtime" "strconv" "strings" "sync" - unix "syscall" "time" - "github.com/coreos/go-systemd/activation" "github.com/gorilla/mux" "gopkg.in/tomb.v2" @@ -42,6 +39,7 @@ import ( "github.com/snapcore/snapd/httputil" "github.com/snapcore/snapd/i18n" "github.com/snapcore/snapd/logger" + "github.com/snapcore/snapd/netutil" "github.com/snapcore/snapd/osutil" "github.com/snapcore/snapd/overlord" "github.com/snapcore/snapd/overlord/auth" @@ -312,75 +310,22 @@ func logit(handler http.Handler) http.Handler { }) } -// 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 -} - // Init sets up the Daemon's internal workings. // Don't call more than once. func (d *Daemon) Init() error { - listenerMap, err := activationListeners() + listenerMap, err := netutil.ActivationListeners() if err != nil { return err } // The SnapdSocket is required-- without it, die. - if listener, err := getListener(dirs.SnapdSocket, listenerMap); err == nil { + if listener, err := netutil.GetListener(dirs.SnapdSocket, listenerMap); err == nil { d.snapdListener = &ucrednetListener{listener} } else { return fmt.Errorf("when trying to listen on %s: %v", dirs.SnapdSocket, err) } - if listener, err := getListener(dirs.SnapSocket, listenerMap); err == nil { + if listener, err := netutil.GetListener(dirs.SnapSocket, listenerMap); err == nil { // This listener may also be nil if that socket wasn't among // the listeners, so check it before using it. d.snapListener = &ucrednetListener{listener} diff --git a/netutil/activation.go b/netutil/activation.go new file mode 100644 index 00000000000..48f1205b705 --- /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 . + * + */ + +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 +}