Code Monkey home page Code Monkey logo

gonetworkmanager's Introduction

GoDoc Go build

gonetworkmanager

Go D-Bus bindings for NetworkManager.

Usage

You can find some examples in the examples directory.

External documentations

Backward compatibility

The library is most likely compatible with NetworkManager 0.9 to 1.40.

Tests

Tested with NetworkManager 1.40.0.

There are no automated tests for this library. Tests are made manually on a best-effort basis. Unit tests PRs are welcome.

Development and contributions

There is no active development workforce from the maintainer. PRs are welcome.

Issues

Before reporting an issue, please test the scenario with nmcli (if possible) to ensure the problem comes from the library.

gonetworkmanager's People

Contributors

appnostic-io avatar bminer avatar everactivemilligan avatar felixmr1 avatar guelfey avatar honeytrap15 avatar jkirkwood avatar joseffilzmaier avatar kamil-krawczyk avatar mullerch avatar mwohlert avatar paulburlumi avatar phommel avatar prairir avatar raqbit avatar tom5760 avatar vaxvhbe avatar

Stargazers

 avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar

Watchers

 avatar  avatar  avatar  avatar  avatar  avatar

gonetworkmanager's Issues

Define some contants necessary to access types/settings maps etc

The C library has a bunch of #defines for keys used in various maps. e.g. from nm-setting-wireless.h:

#define NM_SETTING_WIRELESS_SETTING_NAME "802-11-wireless"

...

#define NM_SETTING_WIRELESS_SSID                      "ssid"
#define NM_SETTING_WIRELESS_MODE                      "mode"
#define NM_SETTING_WIRELESS_BAND                      "band"
#define NM_SETTING_WIRELESS_CHANNEL                   "channel"
#define NM_SETTING_WIRELESS_BSSID                     "bssid"

Could these bindings define a similar set of Go consts to reduce the possibility of typos? Or would specific getter methods be more appropriate?

There are also various defines and enums etc for values, such as:

#define NM_SETTING_WIRELESS_MODE_ADHOC "adhoc"

....

typedef enum {                                                            /*< flags >*/
    NM_SETTING_WIRELESS_WAKE_ON_WLAN_NONE                 = 0, /*< skip >*/
    NM_SETTING_WIRELESS_WAKE_ON_WLAN_ANY                  = 0x2,
    NM_SETTING_WIRELESS_WAKE_ON_WLAN_DISCONNECT           = 0x4,
    NM_SETTING_WIRELESS_WAKE_ON_WLAN_MAGIC                = 0x8,
...
} NMSettingWirelessWakeOnWLan;

There are lots of nm-setting-*.h though and it would be a lot to maintain all of them, but perhaps ad-hoc/as needed coverage could be acceptable?

Setting IPv6 Address

I want to know how to configure IPv6 addresses, but the example provided only has methods for configuring IPv4 addresses. Could you please show how to configure IPv6 addresses?

CheckpointCreate ignores the Devices parameter

Checkpoints are created for all devices:

	nm, _ := gnm.NewNetworkManager()
	device, _ := nm.GetDeviceByIpIface("wlp0s20f3")
	newCheckpoint, _ := nm.CheckpointCreate([]gnm.Device{device}, 3, 0)
	devices, _ := newCheckpoint.GetPropertyDevices()

	ifaces := make([]string, len(devices))
	for _, device := range devices {
		iface, _ := device.GetPropertyInterface()
		ifaces = append(ifaces, iface)
	}

	fmt.Println(newCheckpoint.GetPath(), ifaces)

Expected output:
/org/freedesktop/NetworkManager/Checkpoint/1 [wlp0s20f3]

Actual output:
/org/freedesktop/NetworkManager/Checkpoint/20 [ lo docker0 enp0s31f6 vethdba3724 wlp0s20f3 p2p-dev-wlp0s20f3 tun0]

Incorrect return type for NetworkManager.GetPropertyPrimaryConnection

The NetworkManager.PrimaryConnect property contains:

The object path of the "primary" active connection being used to access the network.

However the NetworkManager.GetPropertyPrimaryConnection binding is:

	GetPropertyPrimaryConnection() (Connection, error)

Which is incorrect, it should be ActiveConnection I believe.

Example code

package main

import (
	"fmt"

	nm "github.com/Wifx/gonetworkmanager"
)

func main() {
	// https://pkg.go.dev/github.com/Wifx/gonetworkmanager#NetworkManager
	nmManager, err := nm.NewNetworkManager()
	if err != nil {
		panic(err)
	}

	// Returns https://pkg.go.dev/github.com/Wifx/gonetworkmanager#Connection
	p, err := nmManager.GetPropertyPrimaryConnection()
	if err != nil {
		panic(err)
	}

	// This fails with "No such interface" because the underlying object is an "ActiveConnection" but we try to treat it as a "Connection"
	if s, err := p.GetSettings(); err != nil {
		// No such interface “org.freedesktop.NetworkManager.Settings.Connection” on object at path /org/freedesktop/NetworkManager/ActiveConnection/330
		fmt.Printf("GetSettings: %v\n", err)
	} else {
		fmt.Printf("GetSettings: settings has %d keys\n", len(s))
	}

	// Convert to a https://pkg.go.dev/github.com/Wifx/gonetworkmanager#ActiveConnection
	ac, err := nm.NewActiveConnection(p.GetPath())
	if err != nil {
		panic(err)
	}

	if t, err := ac.GetPropertyType(); err != nil {
		panic(err)
	} else {
		fmt.Printf("GetPropertyType: %v\n", t)
	}

	p, err = ac.GetPropertyConnection()
	if err != nil {
		panic(err)
	}

	if s, err := p.GetSettings(); err != nil {
		// No such interface “org.freedesktop.NetworkManager.Settings.Connection” on object at path /org/freedesktop/NetworkManager/ActiveConnection/330
		fmt.Printf("GetSettings: %v\n", err)
	} else {
		fmt.Printf("GetSettings: settings has %d keys\n", len(s))
	}
}

The output is:

$ go run ./
GetSettings: No such interface “org.freedesktop.NetworkManager.Settings.Connection” on object at path /org/freedesktop/NetworkManager/ActiveConnection/330
GetPropertyType: 802-3-ethernet
GetSettings: settings has 5 keys

The first p.GetSettings() (line 23) fails with "No such interface" but after conversion to a ActiveConnection methods work and we can then obtain an actual connection from it and the second p.GetSettings() (line 47) on the right object type works.

[Question] Setters on properties

Hello!

There are a lot of getters for almost all properties of NetworkManager. But there are almost no setters.
In my case i would need the property to set a device managed or unmanaged.
Is this a design decision to not include setters or simply a lack of time?

Would you take pull requests if i provide the patches in the latter case?

Greetings

Settings.GetConnectionByUuid() method not yet implemented

The GetConnectionByUuid method appears not be implemented yet.

As a workaround I wrote:

func getConnection(wantedUUID string) (gonetworkmanager.Connection, error) {
	settings, err := gonetworkmanager.NewSettings()
	if err != nil {
		return nil, fmt.Errorf("NewSettings failed: %v", err)
	}

	connections, err := settings.ListConnections()
	for _, c := range connections {
		settings, err := c.GetSettings()
		if err != nil {
			return nil, fmt.Errorf("GetSettings failed: %v", err)
		}

		uuid, ok := settings["connection"]["uuid"].(string)
		if !ok {
			return nil, fmt.Errorf("got data of type %T, but wanted string", uuid)
		}

		if uuid == wantedUUID {
			return c, nil
		}
	}

	return nil, fmt.Errorf("connection with uuid: %s not found, exiting", wantedUUID)
}

dbus wire format error: variant signature is empty

Hello!

I have been playing around with your library and think it's quite nice, as i need similar functionality.

I did, however run into a problem: When calling GetSettings() on the Connection object:
I do get the error
wire format error: variant signature is empty
After i get the error the dbus connection also seems to be flawed.

disclaimer: I'm using NetworkManager 1.20.0
All other functions are working fine.

I don't think the dbus interface changed from nm 1.16 to 1.20, so it should be able to parse the dbus response

Any idea on this?

Cannot set ipv4 routes property

I'm currently working with this library to manage the connections on my Raspberry.
I'm able to add and activate a connection with no problem.
image

However, eventhough I'm able to update some fields of the connection previously created like id, route-metric, etc. I can't seem to set new "ipv4.routes".

I have tried updating "routes" and "route-data" but none of them had any effect on my connection.

image

Am I missing something? Is there any other property I need to change in order to be able to set the routes?

Thank you in advance

Get Accesspoint properties from activeConnection

Hi there!

So far the the gonetworkmanager works fine from my side!

I encounter 1 problem.

I want to have the SSID from my activeConnection

I tried the following:


nm, err :=gonetworkmanager.NewNetworkManager()

if err != nil {
fmt.Println("Could not create networkManager instance:")
fmt.Println(err.Error())
}
	
activeConnections, err := nm.GetPropertyActiveConnections()
if err != nil {
fmt.Println("Could not create activeConnections instance:")
fmt.Println(err.Error())
}

for _, activeConnection := range activeConnections {
   accessPoint, err := activeConnection.GetPropertySpecificObject()
   if err != nil {
       fmt.Println("Could not create access point instance:")
       fmt.Println(err.Error())
   }

   ssid, err := accessPoint.GetPropertySSID()
   
    if err != nil {
      fmt.Println("typeOf---")
      fmt.Println(reflect.TypeOf(accessPoint))
      fmt.Println("---")
       fmt.Println("Could not access the ssid:")
       fmt.Println(err.Error())
   }
}

This outputs:


typeOf---
*gonetworkmanager.accessPoint
---
Could not access the ssid:
No such interface “org.freedesktop.DBus.Properties” on object at path /org/freedesktop/NetworkManager/AccessPoint/3

What Do I miss?

Thanks alot!

Cannot Create AccessPoint

	{
		conn := map[string]map[string]interface{}{
			"802-11-wireless": map[string]interface{}{
				"ssid":     "HELLO",
				"mode":     []string{"s", "ap"},
				"security": "802-11-wireless-security",
			},
			"802-11-wireless-security": map[string]interface{}{
				"psk":      "HELLO",
				"key-mgmt": []string{"s", "wpa-psk"},
			},
		}
		var ap gnm.AccessPoint
		if ap, err = gnm.NewAccessPoint(gnm.NetworkManagerObjectPath + "/AccessPoint/0"); err != nil {
			return fmt.Errorf(LP+"Could not make access point: %v", err)
		}
		var activeConn gnm.ActiveConnection
		if activeConn, err = nm.AddAndActivateWirelessConnection(conn, device, ap); err != nil {
			return fmt.Errorf(LP+"Could not make access point: %v", err)
		}
		log.Infof(LP+"New Access Point: %s", activeConn.GetPath())
	}

yields...

{"level":"info","msg":"WIFI Manager: Found the following network devices...","time":"2022-05-02T15:05:13-07:00"}
{"level":"info","msg":"WIFI Manager: lo - /org/freedesktop/NetworkManager/Devices/1","time":"2022-05-02T15:05:13-07:00"}
{"level":"info","msg":"WIFI Manager: eth0 - /org/freedesktop/NetworkManager/Devices/2","time":"2022-05-02T15:05:13-07:00"}
{"level":"info","msg":"WIFI Manager: wlan0 - /org/freedesktop/NetworkManager/Devices/3","time":"2022-05-02T15:05:13-07:00"}
{"level":"info","msg":"WIFI Manager: p2p-dev-wlan0 - /org/freedesktop/NetworkManager/Devices/4","time":"2022-05-02T15:05:13-07:00"}
2022-05-02T15:05:14-07:00 error layer=debugger error loading binary "/lib/aarch64-linux-gnu/libc.so.6": could not parse .eh_frame section: pointer encoding not supported 0x9b at 0x5a24
{"level":"fatal","msg":"WIFI Manager: Could not make access point: The access point /org/freedesktop/NetworkManager/AccessPoint/0 was not in the scan list.","time":"2022-05-02T15:05:20-07:00"}
Process 23015 has exited with status 1

Settings.Connection.Update() round-trip failure

I'm trying to change the SSID for a connection and have written the following code:

func setSSID(conn gonetworkmanager.Connection, ssid string) error {
	settings, err := conn.GetSettings()
	if err != nil {
		return fmt.Errorf("GetSettings failed: %v", err)
	}

	for k1, v1 := range settings {
		for k2, v2 := range v1 {
			log.Printf("[\"%s\"][\"%s\"] = \"%T\", \"%v\"", k1, k2, v2, v2)
		}
	}

	settings["802-11-wireless"]["ssid"] = []byte(ssid)

	// TODO: determine why these keys don't round trip correctly.
	delete(settings["ipv6"], "addresses")
	delete(settings["ipv6"], "routes")

	err = conn.Update(settings)
	if err != nil {
		return fmt.Errorf("Update failed: %v", err)
	}

	return nil
}

If I remove the two lines marked TODO I get this failure:

2020/06/28 15:07:16 Update failed: ipv6.addresses: can't set property of type 'a(ayuay)' from value of type 'aav'

or this failure:

2020/06/28 15:19:39 Update failed: ipv6.routes: can't set property of type 'a(ayuayu)' from value of type 'aav'

The output from the program is:

2020/06/28 16:36:16 ["802-11-wireless-security"]["proto"] = "[]string", "[rsn]"
2020/06/28 16:36:16 ["802-11-wireless-security"]["group"] = "[]string", "[ccmp]"
2020/06/28 16:36:16 ["802-11-wireless-security"]["key-mgmt"] = "string", "wpa-psk"
2020/06/28 16:36:16 ["802-11-wireless-security"]["pairwise"] = "[]string", "[ccmp]"
2020/06/28 16:36:16 ["ipv4"]["address-data"] = "[]map[string]dbus.Variant", "[]"
2020/06/28 16:36:16 ["ipv4"]["addresses"] = "[][]uint32", "[]"
2020/06/28 16:36:16 ["ipv4"]["dns"] = "[]uint32", "[]"
2020/06/28 16:36:16 ["ipv4"]["dns-search"] = "[]string", "[]"
2020/06/28 16:36:16 ["ipv4"]["method"] = "string", "shared"
2020/06/28 16:36:16 ["ipv4"]["route-data"] = "[]map[string]dbus.Variant", "[]"
2020/06/28 16:36:16 ["ipv4"]["routes"] = "[][]uint32", "[]"
2020/06/28 16:36:16 ["ipv6"]["address-data"] = "[]map[string]dbus.Variant", "[]"
2020/06/28 16:36:16 ["ipv6"]["addresses"] = "[][]interface {}", "[]"
2020/06/28 16:36:16 ["ipv6"]["dns"] = "[][]uint8", "[]"
2020/06/28 16:36:16 ["ipv6"]["dns-search"] = "[]string", "[]"
2020/06/28 16:36:16 ["ipv6"]["method"] = "string", "ignore"
2020/06/28 16:36:16 ["ipv6"]["route-data"] = "[]map[string]dbus.Variant", "[]"
2020/06/28 16:36:16 ["ipv6"]["routes"] = "[][]interface {}", "[]"
2020/06/28 16:36:16 ["connection"]["timestamp"] = "uint64", "1593362134"
2020/06/28 16:36:16 ["connection"]["uuid"] = "string", "833d47c1-fb7f-4dc8-9a73-51fc4337deb3"
2020/06/28 16:36:16 ["connection"]["type"] = "string", "802-11-wireless"
2020/06/28 16:36:16 ["connection"]["id"] = "string", "Hotspot"
2020/06/28 16:36:16 ["connection"]["permissions"] = "[]string", "[]"
2020/06/28 16:36:16 ["802-11-wireless"]["seen-bssids"] = "[]string", "[DC:A6:32:81:8C:72]"
2020/06/28 16:36:16 ["802-11-wireless"]["ssid"] = "[]uint8", "[84 69 77 83 45 67 84 82 76 45 72 85 66 45 66 65 76 69 78 65]"
2020/06/28 16:36:16 ["802-11-wireless"]["mac-address-blacklist"] = "[]string", "[]"
2020/06/28 16:36:16 ["802-11-wireless"]["mode"] = "string", "ap"
2020/06/28 16:36:16 ["802-11-wireless"]["security"] = "string", "802-11-wireless-security"

Looking at the documentation it appears ["ipv6"]["addresses"] and ["ipv6"]["routes"] are both marked Deprecated.

I'm not familiar with the code, but I suspect a bug somewhere.

Updating ConnectionSettings

How do you update ConnectionSettings? I want to be able to update the IPV4 address-data, but I do not see any way of doing it other than recreating the ConnectingSettings Map.

activeDevConn, _ := device.GetPropertyActiveConnection()
conn, _ := activeDevConn.GetPropertyConnection()
settings, _ := conn.GetSettings()
// If I simply write back the config obtained by the GetSettings method, the following error is called when calling conn.Update()
err := conn.Update(settings)
fmt.Println(err.Error())
//ipv6.addresses: can't set property of type 'a(ayuay)' from value of type 'aav'

My guess is we need to call the DbusVariant method? Any ideas?

Recommend Projects

  • React photo React

    A declarative, efficient, and flexible JavaScript library for building user interfaces.

  • Vue.js photo Vue.js

    🖖 Vue.js is a progressive, incrementally-adoptable JavaScript framework for building UI on the web.

  • Typescript photo Typescript

    TypeScript is a superset of JavaScript that compiles to clean JavaScript output.

  • TensorFlow photo TensorFlow

    An Open Source Machine Learning Framework for Everyone

  • Django photo Django

    The Web framework for perfectionists with deadlines.

  • D3 photo D3

    Bring data to life with SVG, Canvas and HTML. 📊📈🎉

Recommend Topics

  • javascript

    JavaScript (JS) is a lightweight interpreted programming language with first-class functions.

  • web

    Some thing interesting about web. New door for the world.

  • server

    A server is a program made to process requests and deliver data to clients.

  • Machine learning

    Machine learning is a way of modeling and interpreting data that allows a piece of software to respond intelligently.

  • Game

    Some thing interesting about game, make everyone happy.

Recommend Org

  • Facebook photo Facebook

    We are working to build community through open source technology. NB: members must have two-factor auth.

  • Microsoft photo Microsoft

    Open source projects and samples from Microsoft.

  • Google photo Google

    Google ❤️ Open Source for everyone.

  • D3 photo D3

    Data-Driven Documents codes.