yggdrasilctl

A library for accessing [Admin API] of [Yggdrasil network router].

It supports both sync and async environment. All you need is to provide socket that implements either Read and Write from std for synchronous operation, or AsyncRead and AsyncWrite from any async runtime. Currently supported runtimes: tokio and futures. If your favourite runtime is not in the list, consider filing an issue or pull request.

Compatibility

In version 0.4.5 of yggdrasil-go (October 2022), a new API call scheme was intoduced for commands: getpeers, getsessions, getself, getpaths, getdht, list. New commands: addpeer, removepeer and gettun. And API extentions, for example uptime attribute in SessionEntry. Old_router API is supported and automatically detected in the Endpoint::attach function with further translation engaged. Note that missing fields are silently populated with 0. Tested versions include 0.4.4, 0.4.7. You can test your setup yourself by running cargo test -p yggdrasilctl in the crate directory.

Basic usage

Add either line to your dependencies in Cargo.toml

```toml

Use std (synchronous)

yggdrasilctl = "1"

Use async runtime

Availible features: "usetokio" or "usefutures"

yggdrasilctl = { version = "1", default-features = false, features = [ "use_tokio" ] } ```

Next:

```rust,ignore use yggdrasilctl::Endpoint; use std::os::unix::net::UnixStream;

// Connect socket using your favourite runtime let socket = UnixStream::connect("/var/run/yggdrasil/yggdrasil.sock")/.await/.unwrap();

// Attach endpoint to a socket let mut endpoint = Endpoint::attach(socket);

// First you can get I/O or protocol parsing error let maybeerror = endpoint.getself()/.await/.unwrap();

// Then Admin API can return error (string) to your request match maybe_error { Ok(response) => println!("Yggdrasil address: {}", response.address), Err(error) => println!("Admin API returned error: {error}"), } ```

Advanced usage

You may also want to perform debug_* requests, which are deliberately unimplemented in this library. For this case yggdrasilctl allows you to provide response structure you want to receive.

First, add crates serde and serde_json to your dependecies

```toml

Import derive macros for Deserialize trait

serde = { version = "1", features = [ "derive" ] }

Import enum Value that represents any possible json value

serde_json = "1" ```

Next:

```rust,ignore use yggdrasilctl::Endpoint; use serde::Deserialize; use serde_json::Value; use std::collections::HashMap; use std::net::Ipv6Addr;

// Connect endpoint use std::os::unix::net::UnixStream; let socket = UnixStream::connect("/var/run/yggdrasil/yggdrasil.sock")/.await/.unwrap(); let mut endpoint = Endpoint::attach(socket); let getself = endpoint.getself()/.await/.unwrap().unwrap();

// Declare a struct you want to receive

[derive(Deserialize)]

struct DebugRemoteGetSelfEntry { coords: String, key: String, } type DebugRemoteGetSelf = HashMap;

// Pass arguments to your request let mut args = HashMap::::new(); args.insert("key".tostring(), Value::from(getself.key.as_str()));

// Perform request let maybeerror = endpoint.requestargs::("debug_remotegetself", args)/.await/.unwrap();

// Parse request match maybeerror { Ok(response) => println!( "Yggdrasil node coordinates: {:?}", response[&getself.address].coords ), Err(error) => println!("Admin API returned error: {error}"), } ```