uapi_unix.go raw

   1  //go:build linux || darwin || freebsd || openbsd
   2  
   3  /* SPDX-License-Identifier: MIT
   4   *
   5   * Copyright (C) 2017-2025 WireGuard LLC. All Rights Reserved.
   6   */
   7  
   8  package ipc
   9  
  10  import (
  11  	"errors"
  12  	"fmt"
  13  	"net"
  14  	"os"
  15  
  16  	"golang.org/x/sys/unix"
  17  )
  18  
  19  const (
  20  	IpcErrorIO        = -int64(unix.EIO)
  21  	IpcErrorProtocol  = -int64(unix.EPROTO)
  22  	IpcErrorInvalid   = -int64(unix.EINVAL)
  23  	IpcErrorPortInUse = -int64(unix.EADDRINUSE)
  24  	IpcErrorUnknown   = -55 // ENOANO
  25  )
  26  
  27  // socketDirectory is variable because it is modified by a linker
  28  // flag in wireguard-android.
  29  var socketDirectory = "/var/run/wireguard"
  30  
  31  func sockPath(iface string) string {
  32  	return fmt.Sprintf("%s/%s.sock", socketDirectory, iface)
  33  }
  34  
  35  func UAPIOpen(name string) (*os.File, error) {
  36  	if err := os.MkdirAll(socketDirectory, 0o755); err != nil {
  37  		return nil, err
  38  	}
  39  
  40  	socketPath := sockPath(name)
  41  	addr, err := net.ResolveUnixAddr("unix", socketPath)
  42  	if err != nil {
  43  		return nil, err
  44  	}
  45  
  46  	oldUmask := unix.Umask(0o077)
  47  	defer unix.Umask(oldUmask)
  48  
  49  	listener, err := net.ListenUnix("unix", addr)
  50  	if err == nil {
  51  		return listener.File()
  52  	}
  53  
  54  	// Test socket, if not in use cleanup and try again.
  55  	if _, err := net.Dial("unix", socketPath); err == nil {
  56  		return nil, errors.New("unix socket in use")
  57  	}
  58  	if err := os.Remove(socketPath); err != nil {
  59  		return nil, err
  60  	}
  61  	listener, err = net.ListenUnix("unix", addr)
  62  	if err != nil {
  63  		return nil, err
  64  	}
  65  	return listener.File()
  66  }
  67