mirror of
https://github.com/anotherhadi/settuings.git
synced 2026-10-05 16:18:24 +02:00
@@ -0,0 +1,122 @@
|
||||
package network
|
||||
|
||||
import "strings"
|
||||
|
||||
// Device is one row of `nmcli device status`.
|
||||
type Device struct {
|
||||
Name string
|
||||
Type string // e.g. "wifi", "ethernet", "wireguard", "loopback"
|
||||
State string // e.g. "connected", "disconnected", "unavailable"
|
||||
Connection string // active connection profile name, empty if none
|
||||
}
|
||||
|
||||
func (d Device) Connected() bool {
|
||||
return strings.HasPrefix(d.State, "connected")
|
||||
}
|
||||
|
||||
// ListDevices returns every network device known to NetworkManager.
|
||||
func ListDevices() ([]Device, error) {
|
||||
rows, err := runTerse("DEVICE,TYPE,STATE,CONNECTION", "device", "status")
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
devices := make([]Device, 0, len(rows))
|
||||
for _, row := range rows {
|
||||
devices = append(devices, Device{
|
||||
Name: field(row, 0),
|
||||
Type: field(row, 1),
|
||||
State: field(row, 2),
|
||||
Connection: field(row, 3),
|
||||
})
|
||||
}
|
||||
return devices, nil
|
||||
}
|
||||
|
||||
// DeviceConnect asks NetworkManager to bring a device up using whichever
|
||||
// saved connection profile fits it best. Unlike VPNUp (which reactivates a
|
||||
// specific, already-known connection by name), this works even right after
|
||||
// a disconnect, when `device status` no longer reports which connection
|
||||
// profile was last active on that device.
|
||||
func DeviceConnect(device string) error {
|
||||
_, err := run("device", "connect", device)
|
||||
return err
|
||||
}
|
||||
|
||||
// DeviceIP4 returns the device's primary private IPv4 address without its
|
||||
// CIDR suffix (e.g. "192.168.1.54"), or "" if the device has none.
|
||||
func DeviceIP4(device string) (string, error) {
|
||||
out, err := getField("IP4.ADDRESS", "device", "show", device)
|
||||
if err != nil {
|
||||
return "", err
|
||||
}
|
||||
if out == "" {
|
||||
return "", nil
|
||||
}
|
||||
// nmcli -g can return multiple addresses newline-separated; keep the first.
|
||||
if i := strings.IndexByte(out, '\n'); i >= 0 {
|
||||
out = out[:i]
|
||||
}
|
||||
if i := strings.IndexByte(out, '/'); i >= 0 {
|
||||
out = out[:i]
|
||||
}
|
||||
return out, nil
|
||||
}
|
||||
|
||||
// DeviceDetail holds everything settuings shows on the "network info" screen
|
||||
// for a connected device: addressing, gateway, DNS and hardware details.
|
||||
type DeviceDetail struct {
|
||||
HWAddr string
|
||||
MTU string
|
||||
IPv4 string // address + CIDR, e.g. "192.168.1.54/24"
|
||||
Gateway4 string
|
||||
DNS4 []string
|
||||
IPv6 []string
|
||||
Gateway6 string
|
||||
DNS6 []string
|
||||
}
|
||||
|
||||
// DeviceDetails fetches full addressing/hardware info for device via
|
||||
// `nmcli device show`. Unlike the tabular nmcli commands elsewhere in this
|
||||
// package, `device show` prints one "KEY:VALUE" line per property (with
|
||||
// "KEY[n]" for multi-valued ones) and does not escape colons inside values,
|
||||
// so it's parsed differently from runTerse.
|
||||
func DeviceDetails(device string) (DeviceDetail, error) {
|
||||
out, err := run("-t", "-f",
|
||||
"GENERAL.HWADDR,GENERAL.MTU,IP4.ADDRESS,IP4.GATEWAY,IP4.DNS,IP6.ADDRESS,IP6.GATEWAY,IP6.DNS",
|
||||
"device", "show", device)
|
||||
if err != nil {
|
||||
return DeviceDetail{}, err
|
||||
}
|
||||
|
||||
var d DeviceDetail
|
||||
for _, line := range strings.Split(strings.TrimRight(out, "\n"), "\n") {
|
||||
key, value, ok := strings.Cut(line, ":")
|
||||
if !ok {
|
||||
continue
|
||||
}
|
||||
if i := strings.IndexByte(key, '['); i >= 0 {
|
||||
key = key[:i] // strip the "[n]" multi-value index
|
||||
}
|
||||
switch key {
|
||||
case "GENERAL.HWADDR":
|
||||
d.HWAddr = value
|
||||
case "GENERAL.MTU":
|
||||
d.MTU = value
|
||||
case "IP4.ADDRESS":
|
||||
if d.IPv4 == "" {
|
||||
d.IPv4 = value
|
||||
}
|
||||
case "IP4.GATEWAY":
|
||||
d.Gateway4 = value
|
||||
case "IP4.DNS":
|
||||
d.DNS4 = append(d.DNS4, value)
|
||||
case "IP6.ADDRESS":
|
||||
d.IPv6 = append(d.IPv6, value)
|
||||
case "IP6.GATEWAY":
|
||||
d.Gateway6 = value
|
||||
case "IP6.DNS":
|
||||
d.DNS6 = append(d.DNS6, value)
|
||||
}
|
||||
}
|
||||
return d, nil
|
||||
}
|
||||
Reference in New Issue
Block a user