Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
Show all changes
139 commits
Select commit Hold shift + click to select a range
8238bf4
refactor(#289): `connect_vpn` sig and new `VpnConfig` trait
cachebag Mar 19, 2026
5e125df
refactor(nmrs): remove `gateway` from `VpnConfig` trait
cachebag Mar 27, 2026
81aaadf
feat(models): add OpenVpn variant to VpnType enum
stoutes Mar 26, 2026
b966295
refactor(vpn): dispatch on vpn_type in connect_vpn, disconnect_vpn, f…
stoutes Mar 26, 2026
f9df4ca
refactor(api): simplify connect_vpn to delegate fully to core::vpn
stoutes Mar 26, 2026
80c8215
refactor(vpn): expand list_vpn_connections and get_vpn_info to detect…
stoutes Mar 26, 2026
311cf2b
style(vpn): apply cargo fmt
stoutes Mar 26, 2026
a9f9bd2
chore(api): remove unused ConnectionOptions import
stoutes Mar 26, 2026
0e24a42
refactor(vpn): regular comment on detect_vpn_type, explicit match in …
stoutes Mar 28, 2026
1ab2de3
refactor(models): removed gateway method from the VpnConfig trait, Vp…
stoutes Mar 28, 2026
8ce7044
feat(#290): add OpenVpnAuthType enum and OpenVpnConfig struct
Dandiggas Mar 23, 2026
4885a2e
feat(#290): add derive macros and Clone impl
Dandiggas Mar 23, 2026
463e449
feat(#290): implement VpnConfig trait for OpenVpnConfig
Dandiggas Mar 24, 2026
7994573
feat(#290): rework struct fields per review feedback
Dandiggas Mar 26, 2026
906243d
feat(#290): remove gateway fn from OpenVpnConfig impl
Dandiggas Mar 27, 2026
51d0a64
fix: removed fn gateway from impl openvpnconfig
Dandiggas Mar 27, 2026
2565524
feat(vpn): complete OpenVPN config implementation
cachebag Mar 31, 2026
012b6c2
feat(nmrs): `.ovpn` parser models and error addition
cachebag Mar 27, 2026
a7705b1
refactor(nmrs): refactor parser into sub-module + error shape
cachebag Mar 27, 2026
04def6e
feat(nmrs): `.ovpn` lexer
cachebag Mar 28, 2026
fdc47eb
feat(nmrs): `.ovpn` parser
cachebag Mar 31, 2026
de6ae16
refactor(nmrs): helper struct for `OvpnFile` building and `Compress` …
cachebag Mar 31, 2026
5730d62
tests(nmrs): `.ovpn` parser tests and refactored logic in arms
cachebag Apr 1, 2026
d92109a
fix(nmrs): line tracking for directives and blocks
cachebag Apr 3, 2026
65f65ba
fix(nmrs): handle `key_direction` both within `tls_auth` block and as…
cachebag Apr 3, 2026
d771da1
chore: cleanup FIXMEs, commment magic number
cachebag Apr 3, 2026
8f613f7
feat(#292): add OpenVPN compression and proxy support with build_open…
stoutes Apr 1, 2026
0c4cd3f
feat(#292): add doc comment for build_openvpn_connection
stoutes Apr 1, 2026
ded74c5
chore(#292): run cargo fmt
stoutes Apr 1, 2026
e164ff3
feat(#292): update openvpn_connection note section
stoutes Apr 1, 2026
38c1eca
feat(#292): extend OpenVpnConfig with compression/proxy and add TryFr…
stoutes Apr 2, 2026
0b76296
chore(#292): run cargo fmt
stoutes Apr 2, 2026
658a48f
fix(#292): wrap up review feedback
cachebag Apr 4, 2026
e77a3d0
feat(#288): add VpnConfiguration enum and wire up OpenVPN connect
cachebag Apr 4, 2026
a056478
chore(build): allow unsafe code
cachebag Apr 4, 2026
30ec857
feat(#296): cert store for inline `.ovpn` certs
cachebag Apr 4, 2026
2bc1415
feat(#216): multiple bt adapter support
cachebag Mar 3, 2026
cdb7b40
refactor(#289): `connect_vpn` sig and new `VpnConfig` trait
cachebag Mar 19, 2026
25e0c46
chore: update CHANGELOG
cachebag Apr 4, 2026
81ed3a8
feature(#291): adding openvpn_builder.rs with all requirements.
stoutes Apr 4, 2026
f9e5d4a
feature(#291): adding re-export for openvpn_builder in mod.rs
stoutes Apr 4, 2026
7daa623
revert: remove openvpn_builder commits that bypassed PR process
stoutes Apr 4, 2026
58becd1
feature(#291): adding re-export for openvpn_builder in mod.rs
stoutes Apr 4, 2026
5000773
feature(#291): adding openvpn_builder.rs struct and implementation wi…
stoutes Apr 4, 2026
d87e362
feature(#291): running cargo fmt
stoutes Apr 4, 2026
2350f90
feat(#326): add name validation, StaticKey guard, and remove unused f…
cachebag Apr 10, 2026
c9d60e8
fix: restore OpenVPN types and VpnConfiguration enum dropped during r…
cachebag Apr 10, 2026
a4800c6
fix: add BluetoothIdentity.adapter field and remove extra BluetoothDe…
cachebag Apr 10, 2026
08e8bc3
fix(#334): use zvariant::Dict for vpn.data and vpn.secrets dbus types
cachebag Apr 10, 2026
b467018
fix: propogate errors on `string_to_pairs` callsite
cachebag Apr 10, 2026
6d87f4c
refactor: split `vpn.rs` into seperate modules
cachebag Apr 11, 2026
8a45e05
feat(#336): parse auth-user-pass and infer OpenVPN auth_type
cachebag Apr 12, 2026
5d0b2b1
refactor: require both `cert` and `key` before inferring TLS-based au…
cachebag Apr 12, 2026
550511b
fix(#333): deserialize vpn.data as Dict to extract OpenVPN gateway
cachebag Apr 14, 2026
8695e1e
feat(#294): add openvpn input validation
cachebag Apr 14, 2026
2e91003
feat(#298): add openvpn tls hardening options
cachebag Apr 14, 2026
4778bd8
feat(#297): add `NetworkManager::import_ovpn()` and `OpenVpnBuilder::…
cachebag Apr 14, 2026
87fb993
feat(#301): add VpnDetails enum to VpnConnectionInfo
cachebag Apr 14, 2026
66a1cf3
fix: handle ca/cert/key/tls-crypt file-path directives in ovpn parser
cachebag Apr 14, 2026
64787d1
feat(#300): openvpn routing, resilience, and NCP options
cachebag Apr 14, 2026
7edac81
feat: seal VpnConfig trait and reject inline certs in TryFrom<OvpnFile>
cachebag Apr 14, 2026
efbc6f3
docs(#335): update stale WireGuard-only doc comments to include OpenVPN
cachebag Apr 14, 2026
51aee6a
feat: add WWAN properties to NMProxy and BlueZ adapter proxy
cachebag Apr 24, 2026
efb5879
docs: record airplane-mode surface in changelog and readme
cachebag Apr 24, 2026
d8674c7
docs: add airplane_mode example
cachebag Apr 24, 2026
5260253
feat: add HardwareRadioKilled and BluezUnavailable error variants
cachebag Apr 24, 2026
94023cd
feat: add RadioState and AirplaneModeState types
cachebag Apr 24, 2026
c2b352e
feat: add kernel rfkill hardware-block reader via sysfs
cachebag Apr 24, 2026
346c4c4
feat: add airplane-mode aggregation and radio toggle logic
cachebag Apr 24, 2026
7affe34
feat: add airplane-mode API and deprecate old wifi accessors
cachebag Apr 24, 2026
5318f46
chore: bump nmrs version to 2.5.0
cachebag Apr 24, 2026
d2c2016
refactor: migrate GUI from deprecated wifi accessors
cachebag Apr 24, 2026
3844269
refactor: migrate integration tests from deprecated wifi accessors
cachebag Apr 24, 2026
198fd9e
fix: resolve broken intra-doc link for BluezUnavailable
cachebag Apr 24, 2026
ec93fa3
chore(deps): update Cargo.lock
cachebag Apr 24, 2026
7c1f909
fix(nix): update cargoHash
github-actions[bot] Apr 24, 2026
7e9d32d
chore: fix clippy lint error
cachebag Apr 24, 2026
421d4fb
feat: add LastSeen property to AccessPoint D-Bus proxy
cachebag Apr 25, 2026
f57b287
feat: add ApBssidNotFound and InvalidBssid error variants
cachebag Apr 25, 2026
c4e1de9
feat: add validate_bssid helper with unit tests
cachebag Apr 25, 2026
89e5adf
feat: add AccessPoint model with SecurityFeatures and decode_security
cachebag Apr 25, 2026
9af2d02
feat: add best_bssid, bssids, is_active, known, security_features to …
cachebag Apr 25, 2026
a94fa30
feat: implement list_access_points and refactor list_networks to use it
cachebag Apr 25, 2026
c8a046a
feat: add connect_to_bssid for BSSID-targeted connections
cachebag Apr 25, 2026
f6739f9
feat: expose list_access_points and connect_to_bssid on NetworkManager
cachebag Apr 25, 2026
37190ba
docs: add ap_list example, update CHANGELOG and README
cachebag Apr 25, 2026
92cc4fe
feat: add WifiInterfaceNotFound and NotAWifiDevice errors
cachebag Apr 25, 2026
e4bc68d
feat: expose Device.Autoconnect setter and Disconnect method
cachebag Apr 25, 2026
c08f648
feat: add WifiDevice model
cachebag Apr 25, 2026
2b46259
feat: add list_wifi_devices and per-interface set_wifi_enabled
cachebag Apr 25, 2026
6351c86
feat!: thread interface through connect, connect_to_bssid, disconnect
cachebag Apr 25, 2026
19832df
feat!: thread interface through scan_networks and list_networks
cachebag Apr 25, 2026
52fb844
feat: add WifiScope for per-interface ergonomic API
cachebag Apr 25, 2026
54722cd
feat!: per-device Wi-Fi surface on NetworkManager and drop deprecated…
cachebag Apr 25, 2026
1c0ac08
feat: re-export WifiDevice and WifiScope at crate root
cachebag Apr 25, 2026
3d72d37
docs: update Network doctests for new list_networks/scan_networks sig…
cachebag Apr 25, 2026
0c1be47
chore!: update existing examples for 3.0 connect/scan signatures
cachebag Apr 25, 2026
9294a4b
feat: add multi_wifi example
cachebag Apr 25, 2026
2d9701b
test!: update integration tests for 3.0 per-interface signatures
cachebag Apr 25, 2026
c430f47
chore(nmrs-gui)!: migrate to 3.0 connect/scan/list_networks signatures
cachebag Apr 25, 2026
1a3e507
chore!: bump nmrs to 3.0.0
cachebag Apr 25, 2026
0e6c238
docs: document per-device scoping and 3.0 break
cachebag Apr 25, 2026
112611e
feat: add NM Settings and Settings.Connection D-Bus proxies
cachebag Apr 25, 2026
8ac1509
feat: add SavedConnectionNotFound and MalformedSavedConnection
cachebag Apr 25, 2026
8ee3de6
feat: add SavedConnection and SettingsSummary types
cachebag Apr 25, 2026
4cb33c8
feat: decode saved profiles and enumerate with bounded concurrency
cachebag Apr 25, 2026
f785dc8
refactor: remove list_saved_connections from connection_settings
cachebag Apr 25, 2026
97cb25f
feat!: expose saved profile enumeration on NetworkManager
cachebag Apr 25, 2026
3a5ff8e
docs: add saved_list example
cachebag Apr 25, 2026
69790aa
docs: changelog and readme for saved connection API
cachebag Apr 25, 2026
d1744b8
feat: add connectivity and captive-portal properties to NM proxy
cachebag Apr 25, 2026
ea44655
feat: add ConnectivityState enum and ConnectivityReport struct
cachebag Apr 25, 2026
a4ba8e9
feat: add ConnectivityCheckDisabled error variant
cachebag Apr 25, 2026
e12573e
feat: implement connectivity reads and captive-portal URL detection
cachebag Apr 25, 2026
98f38c1
feat: wire connectivity/check_connectivity/connectivity_report on Net…
cachebag Apr 25, 2026
891049d
feat: re-export ConnectivityState and ConnectivityReport at crate root
cachebag Apr 25, 2026
9772d92
docs: add connectivity example
cachebag Apr 25, 2026
6ed3323
docs: update changelog and readme for connectivity surface
cachebag Apr 25, 2026
f068c60
feat: add ConnectivityCheckDisabled error variant
cachebag Apr 25, 2026
d7c317a
feat: wire connectivity methods on NetworkManager
cachebag Apr 25, 2026
b901361
feat: re-export ConnectivityState and ConnectivityReport
cachebag Apr 25, 2026
f22bd32
docs: add connectivity example
cachebag Apr 25, 2026
4f69846
docs: update changelog and readme for connectivity
cachebag Apr 25, 2026
912e330
feat: data-carrying VpnType, VpnKind, OpenVpnConnectionType, enriched…
cachebag Apr 25, 2026
f420149
refactor: rename VpnType to VpnKind in wireguard models
cachebag Apr 25, 2026
db6374d
refactor: rename VpnType to VpnKind in openvpn models
cachebag Apr 25, 2026
45fcc0d
test: update model tests for VpnKind rename
cachebag Apr 25, 2026
b9d3593
refactor: update builders for VpnKind rename
cachebag Apr 25, 2026
ce6bef9
feat: vpn_type_from_settings decoder, connect_vpn_by_uuid/id, disconn…
cachebag Apr 25, 2026
9939f49
test: update integration tests for VpnKind rename
cachebag Apr 25, 2026
f09f3c3
docs: add vpn_list example
cachebag Apr 25, 2026
92601e4
fix(#356): add missing public API annotations
cachebag Apr 25, 2026
a94d142
fix(#350): return Result from VpnCredentials and EapOptions builders
cachebag Apr 25, 2026
073800a
fix(#351): propagate disconnect errors; narrow Wi-Fi pre-connect tear…
cachebag Apr 25, 2026
7bcfd2f
docs(#374, #302): update mdbook for 3.0 per-interface Wi-Fi API and a…
cachebag Apr 25, 2026
8817fd9
docs: prepare docs for 3.0 release
cachebag Apr 25, 2026
9d5b001
fix(nix): update cargoHash
github-actions[bot] Apr 25, 2026
77dd975
chore(nmrs): prepare 3.0.0 release
cachebag Apr 25, 2026
20e9a6b
docs: automate README contributors table
cachebag Apr 25, 2026
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
25 changes: 25 additions & 0 deletions .github/workflows/contributors.yml
Original file line number Diff line number Diff line change
@@ -0,0 +1,25 @@
name: Contributors

on:
workflow_dispatch:
push:
branches:
- master

permissions:
contents: write
pull-requests: write

jobs:
contributors:
runs-on: ubuntu-latest
steps:
- name: Update contributors in README
uses: akhilmhdh/contributors-readme-action@v2.3.11
env:
GITHUB_TOKEN: ${{ secrets.GITHUB_TOKEN }}
with:
readme_path: README.md
image_size: 100
columns_per_row: 6
commit_message: "docs: update contributors in README"
2 changes: 1 addition & 1 deletion Cargo.lock

Some generated files are not rendered by default. Learn more about how customized files appear on GitHub.

3 changes: 1 addition & 2 deletions Cargo.toml
Original file line number Diff line number Diff line change
Expand Up @@ -12,7 +12,6 @@ license = "MIT"
repository = "https://github.com/cachebag/nmrs"

[workspace.lints.rust]
unsafe_code = "forbid"
# This shouldn't apply to nmrs-gui
# missing_docs = "warn"
unused = { level = "warn", priority = -1 }
Expand All @@ -33,7 +32,7 @@ uuid = { version = "1.23.1", features = ["v4", "v5"] }
futures = "0.3.32"
futures-timer = "3.0.3"
base64 = "0.22.1"
nmrs = { path = "nmrs", version = "2.2" }
nmrs = { path = "nmrs", version = "3.0" }
gtk = { version = "0.11.2", package = "gtk4" }
glib = "0.22.5"
dirs = "6.0.0"
Expand Down
43 changes: 37 additions & 6 deletions README.md
Original file line number Diff line number Diff line change
Expand Up @@ -43,7 +43,7 @@ async fn main() -> nmrs::Result<()> {
let nm = NetworkManager::new().await?;

// Scan for networks
let networks = nm.list_networks().await?;
let networks = nm.list_networks(None).await?;

for net in networks {
println!(
Expand All @@ -70,7 +70,7 @@ async fn main() -> nmrs::Result<()> {
let nm = NetworkManager::new().await?;

// Connect to a network
nm.connect("MyNetwork", WifiSecurity::WpaPsk {
nm.connect("MyNetwork", None, WifiSecurity::WpaPsk {
psk: "password123".into()
}).await?;

Expand All @@ -94,7 +94,7 @@ use nmrs::{NetworkManager, WifiSecurity, ConnectionError};
async fn main() -> nmrs::Result<()> {
let nm = NetworkManager::new().await?;

match nm.connect("MyNetwork", WifiSecurity::WpaPsk {
match nm.connect("MyNetwork", None, WifiSecurity::WpaPsk {
psk: "wrong_password".into()
}).await {
Ok(_) => println!("Connected successfully"),
Expand Down Expand Up @@ -212,12 +212,12 @@ Edit `~/.config/nmrs/style.css` to customize the interface. There are also pre-d
- [x] Active Connection
- [x] Settings
- [x] Settings Connection
- [ ] Agent Manager
- [x] Agent Manager
- [ ] Checkpoint
- [ ] DNS Manager
- [ ] PPP
- [ ] Secret Agent
- [X] VPN Connection (WireGuard)
- [x] Secret Agent
- [x] VPN Connection (WireGuard + plugin VPNs)
- [ ] VPN Plugin
- [ ] Wi-Fi P2P
- [ ] WiMAX NSP
Expand Down Expand Up @@ -246,3 +246,34 @@ You may use, copy, modify, and distribute this software under the terms of eithe
See the following files for full license texts:
- [MIT License](./LICENSE-MIT)
- [Apache License 2.0](./LICENSE-APACHE)

## Contributors

Thank you to everyone who has helped build, test, document, and review `nmrs`.

<!-- readme: contributors -start -->
<table>
<tr>
<td align="center"><a href="https://github.com/cachebag"><img src="https://avatars.githubusercontent.com/u/111914307?v=4" width="100px;" alt="cachebag"/><br /><sub><b>cachebag</b></sub></a></td>
<td align="center"><a href="https://github.com/stoutes"><img src="https://avatars.githubusercontent.com/u/31317041?v=4" width="100px;" alt="stoutes"/><br /><sub><b>stoutes</b></sub></a></td>
<td align="center"><a href="https://github.com/pluiee"><img src="https://avatars.githubusercontent.com/u/93393389?v=4" width="100px;" alt="pluiee"/><br /><sub><b>pluiee</b></sub></a></td>
<td align="center"><a href="https://github.com/JonnieCache"><img src="https://avatars.githubusercontent.com/u/211093?v=4" width="100px;" alt="JonnieCache"/><br /><sub><b>JonnieCache</b></sub></a></td>
<td align="center"><a href="https://github.com/tristanmsct"><img src="https://avatars.githubusercontent.com/u/69300092?v=4" width="100px;" alt="tristanmsct"/><br /><sub><b>tristanmsct</b></sub></a></td>
<td align="center"><a href="https://github.com/Rifat-R"><img src="https://avatars.githubusercontent.com/u/81259132?v=4" width="100px;" alt="Rifat-R"/><br /><sub><b>Rifat-R</b></sub></a></td>
</tr>
<tr>
<td align="center"><a href="https://github.com/of-the-stars"><img src="https://avatars.githubusercontent.com/u/47869156?v=4" width="100px;" alt="of-the-stars"/><br /><sub><b>of-the-stars</b></sub></a></td>
<td align="center"><a href="https://github.com/okhsunrog"><img src="https://avatars.githubusercontent.com/u/42293787?v=4" width="100px;" alt="okhsunrog"/><br /><sub><b>okhsunrog</b></sub></a></td>
<td align="center"><a href="https://github.com/ruthwik-01"><img src="https://avatars.githubusercontent.com/u/235033610?v=4" width="100px;" alt="ruthwik-01"/><br /><sub><b>ruthwik-01</b></sub></a></td>
<td align="center"><a href="https://github.com/joncorv"><img src="https://avatars.githubusercontent.com/u/151096562?v=4" width="100px;" alt="joncorv"/><br /><sub><b>joncorv</b></sub></a></td>
<td align="center"><a href="https://github.com/AK78gz"><img src="https://avatars.githubusercontent.com/u/89071188?v=4" width="100px;" alt="AK78gz"/><br /><sub><b>AK78gz</b></sub></a></td>
<td align="center"><a href="https://github.com/pwsandoval"><img src="https://avatars.githubusercontent.com/u/15174704?v=4" width="100px;" alt="pwsandoval"/><br /><sub><b>pwsandoval</b></sub></a></td>
</tr>
<tr>
<td align="center"><a href="https://github.com/ritiek"><img src="https://avatars.githubusercontent.com/u/20314742?v=4" width="100px;" alt="ritiek"/><br /><sub><b>ritiek</b></sub></a></td>
<td align="center"><a href="https://github.com/shubhsingh5901"><img src="https://avatars.githubusercontent.com/u/110416544?v=4" width="100px;" alt="shubhsingh5901"/><br /><sub><b>shubhsingh5901</b></sub></a></td>
<td align="center"><a href="https://github.com/cinnamonstic"><img src="https://avatars.githubusercontent.com/u/182801542?v=4" width="100px;" alt="cinnamonstic"/><br /><sub><b>cinnamonstic</b></sub></a></td>
<td align="center"><a href="https://github.com/tuned-willow"><img src="https://avatars.githubusercontent.com/u/250158319?v=4" width="100px;" alt="tuned-willow"/><br /><sub><b>tuned-willow</b></sub></a></td>
</tr>
</table>
<!-- readme: contributors -end -->
4 changes: 4 additions & 0 deletions docs/src/SUMMARY.md
Original file line number Diff line number Diff line change
Expand Up @@ -16,8 +16,10 @@
- [WPA-PSK Networks](./guide/wifi-wpa-psk.md)
- [WPA-EAP (Enterprise)](./guide/wifi-enterprise.md)
- [Hidden Networks](./guide/wifi-hidden.md)
- [Per-Device Wi-Fi Scoping](./guide/wifi-per-device.md)
- [VPN Connections](./guide/vpn.md)
- [WireGuard Setup](./guide/vpn-wireguard.md)
- [OpenVPN Setup](./guide/vpn-openvpn.md)
- [VPN Management](./guide/vpn-management.md)
- [Ethernet Management](./guide/ethernet.md)
- [Bluetooth](./guide/bluetooth.md)
Expand All @@ -40,6 +42,8 @@
- [WiFi Auto-Connect](./examples/wifi-auto-connect.md)
- [Enterprise WiFi](./examples/enterprise-wifi.md)
- [WireGuard VPN Client](./examples/wireguard-client.md)
- [OpenVPN Client](./examples/openvpn-client.md)
- [.ovpn File Import](./examples/ovpn-import.md)
- [Network Monitor Dashboard](./examples/network-monitor.md)
- [Connection Manager](./examples/connection-manager.md)

Expand Down
8 changes: 4 additions & 4 deletions docs/src/advanced/async-runtimes.md
Original file line number Diff line number Diff line change
Expand Up @@ -12,7 +12,7 @@ use nmrs::NetworkManager;
#[tokio::main]
async fn main() -> nmrs::Result<()> {
let nm = NetworkManager::new().await?;
let networks = nm.list_networks().await?;
let networks = nm.list_networks(None).await?;
println!("{} networks found", networks.len());
Ok(())
}
Expand Down Expand Up @@ -49,7 +49,7 @@ use nmrs::NetworkManager;
#[async_std::main]
async fn main() -> nmrs::Result<()> {
let nm = NetworkManager::new().await?;
let networks = nm.list_networks().await?;
let networks = nm.list_networks(None).await?;
println!("{} networks found", networks.len());
Ok(())
}
Expand All @@ -69,7 +69,7 @@ use nmrs::NetworkManager;
fn main() -> nmrs::Result<()> {
smol::block_on(async {
let nm = NetworkManager::new().await?;
let networks = nm.list_networks().await?;
let networks = nm.list_networks(None).await?;
println!("{} networks found", networks.len());
Ok(())
})
Expand All @@ -93,7 +93,7 @@ use nmrs::NetworkManager;
glib::MainContext::default().spawn_local(async {
let nm = NetworkManager::new().await.unwrap();

let networks = nm.list_networks().await.unwrap();
let networks = nm.list_networks(None).await.unwrap();
for net in &networks {
println!("{}: {}%", net.ssid, net.strength.unwrap_or(0));
}
Expand Down
2 changes: 1 addition & 1 deletion docs/src/advanced/dbus.md
Original file line number Diff line number Diff line change
Expand Up @@ -65,7 +65,7 @@ nmrs: nm.monitor_network_changes(callback)
When connecting to a network, nmrs builds a settings dictionary and sends it via D-Bus:

```
nmrs: nm.connect("MyWiFi", WifiSecurity::WpaPsk { psk: "..." })
nmrs: nm.connect("MyWiFi", None, WifiSecurity::WpaPsk { psk: "..." })
→ Build settings HashMap
→ D-Bus: AddAndActivateConnection(settings, device_path, specific_object)
← D-Bus: Active connection path
Expand Down
2 changes: 1 addition & 1 deletion docs/src/advanced/logging.md
Original file line number Diff line number Diff line change
Expand Up @@ -21,7 +21,7 @@ async fn main() -> nmrs::Result<()> {
env_logger::init();

let nm = NetworkManager::new().await?;
nm.scan_networks().await?;
nm.scan_networks(None).await?;

Ok(())
}
Expand Down
2 changes: 1 addition & 1 deletion docs/src/advanced/timeouts.md
Original file line number Diff line number Diff line change
Expand Up @@ -98,7 +98,7 @@ let config = TimeoutConfig::new()

let nm = NetworkManager::with_config(config).await?;

match nm.connect("SlowNetwork", WifiSecurity::Open).await {
match nm.connect("SlowNetwork", None, WifiSecurity::Open).await {
Ok(_) => println!("Connected!"),
Err(ConnectionError::Timeout) => {
eprintln!("Connection timed out — try a longer timeout");
Expand Down
43 changes: 38 additions & 5 deletions docs/src/api/builders.md
Original file line number Diff line number Diff line change
Expand Up @@ -128,17 +128,14 @@ The `build()` method validates all fields and returns `Result<Settings, Connecti
Convenience functions that wrap the builders:

```rust
use nmrs::builders::{build_wifi_connection, build_ethernet_connection, build_wireguard_connection};
use nmrs::{WifiSecurity, ConnectionOptions, VpnCredentials};
use nmrs::builders::{build_wifi_connection, build_ethernet_connection};
use nmrs::{WifiSecurity, ConnectionOptions};

// Wi-Fi
let wifi = build_wifi_connection("MyNetwork", &WifiSecurity::Open, &ConnectionOptions::default());

// Ethernet
let eth = build_ethernet_connection("eth0", &ConnectionOptions::default());

// WireGuard (returns Result)
let wg = build_wireguard_connection(&creds, &ConnectionOptions::default())?;
```

## When to Use Builders
Expand All @@ -151,6 +148,42 @@ Use the builders when you need:

For standard connections, the `NetworkManager` API handles everything automatically.

## OpenVpnBuilder

Builds OpenVPN connection settings from an `OpenVpnConfig` or by importing a `.ovpn` file.

### From Configuration

```rust
use nmrs::{OpenVpnConfig, OpenVpnAuthType};

let config = OpenVpnConfig::new("CorpVPN", "vpn.example.com", 1194, false)
.with_auth_type(OpenVpnAuthType::PasswordTls)
.with_username("user")
.with_password("secret")
.with_ca_cert("/etc/openvpn/ca.crt")
.with_client_cert("/etc/openvpn/client.crt")
.with_client_key("/etc/openvpn/client.key");
```

### From .ovpn File

```rust
use nmrs::builders::OpenVpnBuilder;

let config = OpenVpnBuilder::from_ovpn_file("client.ovpn")?
.username("user")
.password("secret")
.build()?;
```

Or use the high-level API directly:

```rust
let nm = NetworkManager::new().await?;
nm.import_ovpn("client.ovpn", Some("user"), Some("secret")).await?;
```

## Full API Reference

See [docs.rs/nmrs](https://docs.rs/nmrs) for complete builder documentation.
23 changes: 20 additions & 3 deletions docs/src/api/errors.md
Original file line number Diff line number Diff line change
Expand Up @@ -36,15 +36,32 @@ pub enum ConnectionError {
DeviceFailed(StateReason),
ActivationFailed(ConnectionStateReason),

// Per-device errors
WifiInterfaceNotFound { interface: String },
NotAWifiDevice { interface: String },

// Radio errors
HardwareRadioKilled,
BluezUnavailable,

// VPN errors
NoVpnConnection,
VpnFailed(String),
VpnIdAmbiguous { id: String },
IncompleteBuilder(String),
InvalidPrivateKey(String),
InvalidPublicKey(String),
InvalidAddress(String),
InvalidGateway(String),
InvalidPeers(String),

// Connectivity
ConnectivityCheckDisabled,

// BSSID
ApBssidNotFound { ssid: String, bssid: String },
InvalidBssid(String),

// Other
InvalidUtf8(Utf8Error),
}
Expand Down Expand Up @@ -127,15 +144,15 @@ pub enum ActiveConnectionState {
```rust
async fn connect() -> nmrs::Result<()> {
let nm = NetworkManager::new().await?;
nm.connect("MyWiFi", WifiSecurity::Open).await?;
nm.connect("MyWiFi", None, WifiSecurity::Open).await?;
Ok(())
}
```

### Specific Error Handling

```rust
match nm.connect("MyWiFi", security).await {
match nm.connect("MyWiFi", None, security).await {
Ok(_) => println!("Connected"),
Err(ConnectionError::AuthFailed) => eprintln!("Wrong password"),
Err(ConnectionError::NotFound) => eprintln!("Network not found"),
Expand All @@ -151,7 +168,7 @@ use anyhow::{Context, Result};
async fn connect() -> Result<()> {
let nm = NetworkManager::new().await
.context("Failed to connect to NetworkManager")?;
nm.connect("MyWiFi", WifiSecurity::Open).await
nm.connect("MyWiFi", None, WifiSecurity::Open).await
.context("Failed to connect to MyWiFi")?;
Ok(())
}
Expand Down
Loading