SSH connection status indicators

- Add Connected bool field to vfs.Entry and RemoteMount
- Track connection status in sshState.connectedHosts
- Show status icon (connected/disconnected) in pane header when browsing remote host
- Async SSH connection test with cancel support for Add Host dialog
- Colored labels and styled help text in SSH dialogs
- Confirmation dialog when deleting manually-added SSH hosts
This commit is contained in:
vrubelroman 2026-04-29 03:11:53 +03:00
parent df4df6b8f6
commit 1ed2d3defb
224 changed files with 33447 additions and 236 deletions

View file

@ -6,9 +6,7 @@
package unix
import (
"unsafe"
)
import "unsafe"
// ioctl itself should not be exposed directly, but additional get/set
// functions for specific types are permissible.
@ -28,6 +26,13 @@ func IoctlSetPointerInt(fd int, req int, value int) error {
return ioctlPtr(fd, req, unsafe.Pointer(&v))
}
// IoctlSetString performs an ioctl operation which sets a string value
// on fd, using the specified request number.
func IoctlSetString(fd int, req int, value string) error {
bs := append([]byte(value), 0)
return ioctlPtr(fd, req, unsafe.Pointer(&bs[0]))
}
// IoctlSetWinsize performs an ioctl on fd with a *Winsize argument.
//
// To change fd's window size, the req argument should be TIOCSWINSZ.

View file

@ -6,9 +6,7 @@
package unix
import (
"unsafe"
)
import "unsafe"
// ioctl itself should not be exposed directly, but additional get/set
// functions for specific types are permissible.
@ -28,6 +26,13 @@ func IoctlSetPointerInt(fd int, req uint, value int) error {
return ioctlPtr(fd, req, unsafe.Pointer(&v))
}
// IoctlSetString performs an ioctl operation which sets a string value
// on fd, using the specified request number.
func IoctlSetString(fd int, req uint, value string) error {
bs := append([]byte(value), 0)
return ioctlPtr(fd, req, unsafe.Pointer(&bs[0]))
}
// IoctlSetWinsize performs an ioctl on fd with a *Winsize argument.
//
// To change fd's window size, the req argument should be TIOCSWINSZ.

View file

@ -256,6 +256,7 @@ struct ltchars {
#include <linux/loop.h>
#include <linux/lwtunnel.h>
#include <linux/magic.h>
#include <linux/mei.h>
#include <linux/memfd.h>
#include <linux/module.h>
#include <linux/mount.h>
@ -613,7 +614,7 @@ ccflags="$@"
$2 !~ /IOC_MAGIC/ &&
$2 ~ /^[A-Z][A-Z0-9_]+_MAGIC2?$/ ||
$2 ~ /^(VM|VMADDR)_/ ||
$2 ~ /^IOCTL_VM_SOCKETS_/ ||
$2 ~ /^(IOCTL_VM_SOCKETS_|IOCTL_MEI_)/ ||
$2 ~ /^(TASKSTATS|TS)_/ ||
$2 ~ /^CGROUPSTATS_/ ||
$2 ~ /^GENL_/ ||

View file

@ -1052,14 +1052,6 @@ func IoctlSetIntRetInt(fd int, req int, arg int) (int, error) {
return ioctlRet(fd, req, uintptr(arg))
}
func IoctlSetString(fd int, req int, val string) error {
bs := make([]byte, len(val)+1)
copy(bs[:len(bs)-1], val)
err := ioctlPtr(fd, req, unsafe.Pointer(&bs[0]))
runtime.KeepAlive(&bs[0])
return err
}
// Lifreq Helpers
func (l *Lifreq) SetName(name string) error {

View file

@ -367,7 +367,9 @@ func Recvmsg(fd int, p, oob []byte, flags int) (n, oobn int, recvflags int, from
iov[0].SetLen(len(p))
}
var rsa RawSockaddrAny
n, oobn, recvflags, err = recvmsgRaw(fd, iov[:], oob, flags, &rsa)
if n, oobn, recvflags, err = recvmsgRaw(fd, iov[:], oob, flags, &rsa); err != nil {
return
}
// source address is only specified if the socket is unconnected
if rsa.Addr.Family != AF_UNSPEC {
from, err = anyToSockaddr(fd, &rsa)
@ -389,8 +391,10 @@ func RecvmsgBuffers(fd int, buffers [][]byte, oob []byte, flags int) (n, oobn in
}
}
var rsa RawSockaddrAny
n, oobn, recvflags, err = recvmsgRaw(fd, iov, oob, flags, &rsa)
if err == nil && rsa.Addr.Family != AF_UNSPEC {
if n, oobn, recvflags, err = recvmsgRaw(fd, iov, oob, flags, &rsa); err != nil {
return
}
if rsa.Addr.Family != AF_UNSPEC {
from, err = anyToSockaddr(fd, &rsa)
}
return

View file

@ -1615,6 +1615,8 @@ const (
IN_OPEN = 0x20
IN_Q_OVERFLOW = 0x4000
IN_UNMOUNT = 0x2000
IOCTL_MEI_CONNECT_CLIENT = 0xc0104801
IOCTL_MEI_CONNECT_CLIENT_VTAG = 0xc0144804
IPPROTO_AH = 0x33
IPPROTO_BEETPH = 0x5e
IPPROTO_COMP = 0x6c

View file

@ -116,6 +116,8 @@ const (
IEXTEN = 0x8000
IN_CLOEXEC = 0x80000
IN_NONBLOCK = 0x800
IOCTL_MEI_NOTIFY_GET = 0x80044803
IOCTL_MEI_NOTIFY_SET = 0x40044802
IOCTL_VM_SOCKETS_GET_LOCAL_CID = 0x7b9
IPV6_FLOWINFO_MASK = 0xffffff0f
IPV6_FLOWLABEL_MASK = 0xffff0f00

View file

@ -116,6 +116,8 @@ const (
IEXTEN = 0x8000
IN_CLOEXEC = 0x80000
IN_NONBLOCK = 0x800
IOCTL_MEI_NOTIFY_GET = 0x80044803
IOCTL_MEI_NOTIFY_SET = 0x40044802
IOCTL_VM_SOCKETS_GET_LOCAL_CID = 0x7b9
IPV6_FLOWINFO_MASK = 0xffffff0f
IPV6_FLOWLABEL_MASK = 0xffff0f00

View file

@ -115,6 +115,8 @@ const (
IEXTEN = 0x8000
IN_CLOEXEC = 0x80000
IN_NONBLOCK = 0x800
IOCTL_MEI_NOTIFY_GET = 0x80044803
IOCTL_MEI_NOTIFY_SET = 0x40044802
IOCTL_VM_SOCKETS_GET_LOCAL_CID = 0x7b9
IPV6_FLOWINFO_MASK = 0xffffff0f
IPV6_FLOWLABEL_MASK = 0xffff0f00

View file

@ -120,6 +120,8 @@ const (
IEXTEN = 0x8000
IN_CLOEXEC = 0x80000
IN_NONBLOCK = 0x800
IOCTL_MEI_NOTIFY_GET = 0x80044803
IOCTL_MEI_NOTIFY_SET = 0x40044802
IOCTL_VM_SOCKETS_GET_LOCAL_CID = 0x7b9
IPV6_FLOWINFO_MASK = 0xffffff0f
IPV6_FLOWLABEL_MASK = 0xffff0f00

View file

@ -116,6 +116,8 @@ const (
IEXTEN = 0x8000
IN_CLOEXEC = 0x80000
IN_NONBLOCK = 0x800
IOCTL_MEI_NOTIFY_GET = 0x80044803
IOCTL_MEI_NOTIFY_SET = 0x40044802
IOCTL_VM_SOCKETS_GET_LOCAL_CID = 0x7b9
IPV6_FLOWINFO_MASK = 0xffffff0f
IPV6_FLOWLABEL_MASK = 0xffff0f00

View file

@ -115,6 +115,8 @@ const (
IEXTEN = 0x100
IN_CLOEXEC = 0x80000
IN_NONBLOCK = 0x80
IOCTL_MEI_NOTIFY_GET = 0x40044803
IOCTL_MEI_NOTIFY_SET = 0x80044802
IOCTL_VM_SOCKETS_GET_LOCAL_CID = 0x200007b9
IPV6_FLOWINFO_MASK = 0xfffffff
IPV6_FLOWLABEL_MASK = 0xfffff

View file

@ -115,6 +115,8 @@ const (
IEXTEN = 0x100
IN_CLOEXEC = 0x80000
IN_NONBLOCK = 0x80
IOCTL_MEI_NOTIFY_GET = 0x40044803
IOCTL_MEI_NOTIFY_SET = 0x80044802
IOCTL_VM_SOCKETS_GET_LOCAL_CID = 0x200007b9
IPV6_FLOWINFO_MASK = 0xfffffff
IPV6_FLOWLABEL_MASK = 0xfffff

View file

@ -115,6 +115,8 @@ const (
IEXTEN = 0x100
IN_CLOEXEC = 0x80000
IN_NONBLOCK = 0x80
IOCTL_MEI_NOTIFY_GET = 0x40044803
IOCTL_MEI_NOTIFY_SET = 0x80044802
IOCTL_VM_SOCKETS_GET_LOCAL_CID = 0x200007b9
IPV6_FLOWINFO_MASK = 0xffffff0f
IPV6_FLOWLABEL_MASK = 0xffff0f00

View file

@ -115,6 +115,8 @@ const (
IEXTEN = 0x100
IN_CLOEXEC = 0x80000
IN_NONBLOCK = 0x80
IOCTL_MEI_NOTIFY_GET = 0x40044803
IOCTL_MEI_NOTIFY_SET = 0x80044802
IOCTL_VM_SOCKETS_GET_LOCAL_CID = 0x200007b9
IPV6_FLOWINFO_MASK = 0xffffff0f
IPV6_FLOWLABEL_MASK = 0xffff0f00

View file

@ -115,6 +115,8 @@ const (
IEXTEN = 0x400
IN_CLOEXEC = 0x80000
IN_NONBLOCK = 0x800
IOCTL_MEI_NOTIFY_GET = 0x40044803
IOCTL_MEI_NOTIFY_SET = 0x80044802
IOCTL_VM_SOCKETS_GET_LOCAL_CID = 0x200007b9
IPV6_FLOWINFO_MASK = 0xfffffff
IPV6_FLOWLABEL_MASK = 0xfffff

View file

@ -115,6 +115,8 @@ const (
IEXTEN = 0x400
IN_CLOEXEC = 0x80000
IN_NONBLOCK = 0x800
IOCTL_MEI_NOTIFY_GET = 0x40044803
IOCTL_MEI_NOTIFY_SET = 0x80044802
IOCTL_VM_SOCKETS_GET_LOCAL_CID = 0x200007b9
IPV6_FLOWINFO_MASK = 0xfffffff
IPV6_FLOWLABEL_MASK = 0xfffff

View file

@ -115,6 +115,8 @@ const (
IEXTEN = 0x400
IN_CLOEXEC = 0x80000
IN_NONBLOCK = 0x800
IOCTL_MEI_NOTIFY_GET = 0x40044803
IOCTL_MEI_NOTIFY_SET = 0x80044802
IOCTL_VM_SOCKETS_GET_LOCAL_CID = 0x200007b9
IPV6_FLOWINFO_MASK = 0xffffff0f
IPV6_FLOWLABEL_MASK = 0xffff0f00

View file

@ -115,6 +115,8 @@ const (
IEXTEN = 0x8000
IN_CLOEXEC = 0x80000
IN_NONBLOCK = 0x800
IOCTL_MEI_NOTIFY_GET = 0x80044803
IOCTL_MEI_NOTIFY_SET = 0x40044802
IOCTL_VM_SOCKETS_GET_LOCAL_CID = 0x7b9
IPV6_FLOWINFO_MASK = 0xffffff0f
IPV6_FLOWLABEL_MASK = 0xffff0f00

View file

@ -115,6 +115,8 @@ const (
IEXTEN = 0x8000
IN_CLOEXEC = 0x80000
IN_NONBLOCK = 0x800
IOCTL_MEI_NOTIFY_GET = 0x80044803
IOCTL_MEI_NOTIFY_SET = 0x40044802
IOCTL_VM_SOCKETS_GET_LOCAL_CID = 0x7b9
IPV6_FLOWINFO_MASK = 0xfffffff
IPV6_FLOWLABEL_MASK = 0xfffff

View file

@ -119,6 +119,8 @@ const (
IEXTEN = 0x8000
IN_CLOEXEC = 0x400000
IN_NONBLOCK = 0x4000
IOCTL_MEI_NOTIFY_GET = 0x40044803
IOCTL_MEI_NOTIFY_SET = 0x80044802
IOCTL_VM_SOCKETS_GET_LOCAL_CID = 0x200007b9
IPV6_FLOWINFO_MASK = 0xfffffff
IPV6_FLOWLABEL_MASK = 0xfffff

View file

@ -593,110 +593,115 @@ const (
)
const (
NDA_UNSPEC = 0x0
NDA_DST = 0x1
NDA_LLADDR = 0x2
NDA_CACHEINFO = 0x3
NDA_PROBES = 0x4
NDA_VLAN = 0x5
NDA_PORT = 0x6
NDA_VNI = 0x7
NDA_IFINDEX = 0x8
NDA_MASTER = 0x9
NDA_LINK_NETNSID = 0xa
NDA_SRC_VNI = 0xb
NTF_USE = 0x1
NTF_SELF = 0x2
NTF_MASTER = 0x4
NTF_PROXY = 0x8
NTF_EXT_LEARNED = 0x10
NTF_OFFLOADED = 0x20
NTF_ROUTER = 0x80
NUD_INCOMPLETE = 0x1
NUD_REACHABLE = 0x2
NUD_STALE = 0x4
NUD_DELAY = 0x8
NUD_PROBE = 0x10
NUD_FAILED = 0x20
NUD_NOARP = 0x40
NUD_PERMANENT = 0x80
NUD_NONE = 0x0
IFA_UNSPEC = 0x0
IFA_ADDRESS = 0x1
IFA_LOCAL = 0x2
IFA_LABEL = 0x3
IFA_BROADCAST = 0x4
IFA_ANYCAST = 0x5
IFA_CACHEINFO = 0x6
IFA_MULTICAST = 0x7
IFA_FLAGS = 0x8
IFA_RT_PRIORITY = 0x9
IFA_TARGET_NETNSID = 0xa
IFAL_LABEL = 0x2
IFAL_ADDRESS = 0x1
RT_SCOPE_UNIVERSE = 0x0
RT_SCOPE_SITE = 0xc8
RT_SCOPE_LINK = 0xfd
RT_SCOPE_HOST = 0xfe
RT_SCOPE_NOWHERE = 0xff
RT_TABLE_UNSPEC = 0x0
RT_TABLE_COMPAT = 0xfc
RT_TABLE_DEFAULT = 0xfd
RT_TABLE_MAIN = 0xfe
RT_TABLE_LOCAL = 0xff
RT_TABLE_MAX = 0xffffffff
RTA_UNSPEC = 0x0
RTA_DST = 0x1
RTA_SRC = 0x2
RTA_IIF = 0x3
RTA_OIF = 0x4
RTA_GATEWAY = 0x5
RTA_PRIORITY = 0x6
RTA_PREFSRC = 0x7
RTA_METRICS = 0x8
RTA_MULTIPATH = 0x9
RTA_FLOW = 0xb
RTA_CACHEINFO = 0xc
RTA_TABLE = 0xf
RTA_MARK = 0x10
RTA_MFC_STATS = 0x11
RTA_VIA = 0x12
RTA_NEWDST = 0x13
RTA_PREF = 0x14
RTA_ENCAP_TYPE = 0x15
RTA_ENCAP = 0x16
RTA_EXPIRES = 0x17
RTA_PAD = 0x18
RTA_UID = 0x19
RTA_TTL_PROPAGATE = 0x1a
RTA_IP_PROTO = 0x1b
RTA_SPORT = 0x1c
RTA_DPORT = 0x1d
RTN_UNSPEC = 0x0
RTN_UNICAST = 0x1
RTN_LOCAL = 0x2
RTN_BROADCAST = 0x3
RTN_ANYCAST = 0x4
RTN_MULTICAST = 0x5
RTN_BLACKHOLE = 0x6
RTN_UNREACHABLE = 0x7
RTN_PROHIBIT = 0x8
RTN_THROW = 0x9
RTN_NAT = 0xa
RTN_XRESOLVE = 0xb
SizeofNlMsghdr = 0x10
SizeofNlMsgerr = 0x14
SizeofRtGenmsg = 0x1
SizeofNlAttr = 0x4
SizeofRtAttr = 0x4
SizeofIfInfomsg = 0x10
SizeofIfAddrmsg = 0x8
SizeofIfAddrlblmsg = 0xc
SizeofIfaCacheinfo = 0x10
SizeofRtMsg = 0xc
SizeofRtNexthop = 0x8
SizeofNdUseroptmsg = 0x10
SizeofNdMsg = 0xc
NDA_UNSPEC = 0x0
NDA_DST = 0x1
NDA_LLADDR = 0x2
NDA_CACHEINFO = 0x3
NDA_PROBES = 0x4
NDA_VLAN = 0x5
NDA_PORT = 0x6
NDA_VNI = 0x7
NDA_IFINDEX = 0x8
NDA_MASTER = 0x9
NDA_LINK_NETNSID = 0xa
NDA_SRC_VNI = 0xb
NTF_USE = 0x1
NTF_SELF = 0x2
NTF_MASTER = 0x4
NTF_PROXY = 0x8
NTF_EXT_LEARNED = 0x10
NTF_OFFLOADED = 0x20
NTF_ROUTER = 0x80
NUD_INCOMPLETE = 0x1
NUD_REACHABLE = 0x2
NUD_STALE = 0x4
NUD_DELAY = 0x8
NUD_PROBE = 0x10
NUD_FAILED = 0x20
NUD_NOARP = 0x40
NUD_PERMANENT = 0x80
NUD_NONE = 0x0
IFA_UNSPEC = 0x0
IFA_ADDRESS = 0x1
IFA_LOCAL = 0x2
IFA_LABEL = 0x3
IFA_BROADCAST = 0x4
IFA_ANYCAST = 0x5
IFA_CACHEINFO = 0x6
IFA_MULTICAST = 0x7
IFA_FLAGS = 0x8
IFA_RT_PRIORITY = 0x9
IFA_TARGET_NETNSID = 0xa
IFAL_LABEL = 0x2
IFAL_ADDRESS = 0x1
RT_SCOPE_UNIVERSE = 0x0
RT_SCOPE_SITE = 0xc8
RT_SCOPE_LINK = 0xfd
RT_SCOPE_HOST = 0xfe
RT_SCOPE_NOWHERE = 0xff
RT_TABLE_UNSPEC = 0x0
RT_TABLE_COMPAT = 0xfc
RT_TABLE_DEFAULT = 0xfd
RT_TABLE_MAIN = 0xfe
RT_TABLE_LOCAL = 0xff
RT_TABLE_MAX = 0xffffffff
RTA_UNSPEC = 0x0
RTA_DST = 0x1
RTA_SRC = 0x2
RTA_IIF = 0x3
RTA_OIF = 0x4
RTA_GATEWAY = 0x5
RTA_PRIORITY = 0x6
RTA_PREFSRC = 0x7
RTA_METRICS = 0x8
RTA_MULTIPATH = 0x9
RTA_FLOW = 0xb
RTA_CACHEINFO = 0xc
RTA_TABLE = 0xf
RTA_MARK = 0x10
RTA_MFC_STATS = 0x11
RTA_VIA = 0x12
RTA_NEWDST = 0x13
RTA_PREF = 0x14
RTA_ENCAP_TYPE = 0x15
RTA_ENCAP = 0x16
RTA_EXPIRES = 0x17
RTA_PAD = 0x18
RTA_UID = 0x19
RTA_TTL_PROPAGATE = 0x1a
RTA_IP_PROTO = 0x1b
RTA_SPORT = 0x1c
RTA_DPORT = 0x1d
RTN_UNSPEC = 0x0
RTN_UNICAST = 0x1
RTN_LOCAL = 0x2
RTN_BROADCAST = 0x3
RTN_ANYCAST = 0x4
RTN_MULTICAST = 0x5
RTN_BLACKHOLE = 0x6
RTN_UNREACHABLE = 0x7
RTN_PROHIBIT = 0x8
RTN_THROW = 0x9
RTN_NAT = 0xa
RTN_XRESOLVE = 0xb
PREFIX_UNSPEC = 0x0
PREFIX_ADDRESS = 0x1
PREFIX_CACHEINFO = 0x2
SizeofNlMsghdr = 0x10
SizeofNlMsgerr = 0x14
SizeofRtGenmsg = 0x1
SizeofNlAttr = 0x4
SizeofRtAttr = 0x4
SizeofIfInfomsg = 0x10
SizeofPrefixmsg = 0xc
SizeofPrefixCacheinfo = 0x8
SizeofIfAddrmsg = 0x8
SizeofIfAddrlblmsg = 0xc
SizeofIfaCacheinfo = 0x10
SizeofRtMsg = 0xc
SizeofRtNexthop = 0x8
SizeofNdUseroptmsg = 0x10
SizeofNdMsg = 0xc
)
type NlMsghdr struct {
@ -735,6 +740,22 @@ type IfInfomsg struct {
Change uint32
}
type Prefixmsg struct {
Family uint8
Pad1 uint8
Pad2 uint16
Ifindex int32
Type uint8
Len uint8
Flags uint8
Pad3 uint8
}
type PrefixCacheinfo struct {
Preferred_time uint32
Valid_time uint32
}
type IfAddrmsg struct {
Family uint8
Prefixlen uint8

View file

@ -104,7 +104,7 @@ type Statvfs_t struct {
Fsid uint32
Namemax uint32
Owner uint32
Spare [4]uint32
Spare [4]uint64
Fstypename [32]byte
Mntonname [1024]byte
Mntfromname [1024]byte