network 1.0.0

Network Basic Library: Network Basic Operations, WiFi Definition, Linux WPA Implementation
Documentation
# network

一个面向 Rust 的网络工具库,主要提供以下能力:

- 枚举本机物理网卡与基础网络状态
- 获取本机 IP、MAC、默认联网网卡等信息
- 监听网卡上下线变化
- 在 Linux 下启用/禁用网卡
- 通过可选 `feature` 提供 Wi-Fi 管理能力
- 在 Linux 下基于 `wpa_supplicant` 管理无线网络

这个项目目前更偏向库(library)而不是独立命令行程序。

## 特性概览

### 通用网络能力

默认特性下即可使用:

- 获取网卡列表:`utils::ifaces`
- 获取原始网卡信息:`utils::get_source_ifaces`
- 获取本机 IP:`utils::get_local_ip` / `utils::get_local_ips`
- 获取 MAC 地址:`utils::get_mac_addr` / `utils::get_physical_mac`
- 判断当前是否联网:`utils::check_online` / `utils::is_online`
- 获取局域网连接与在线状态:`utils::lan_is_ok`
- 监听网卡事件:`utils::listen_change`
- Linux 下启用/禁用网卡:`utils::enable`

### Wi-Fi 能力

启用 `wifi` feature 后可使用统一的 Wi-Fi trait 和数据结构:

- `wifi::IWifi`
- `wifi::ScanResult`
- `wifi::NetworkListResult`
- `wifi::Status`

### WPA / wpa_supplicant 能力

启用 `wpa` feature 且运行在 Linux 时,可通过 Unix Domain Socket 与 `wpa_supplicant` 通信:

- 自动发现无线网卡并初始化:`wifi::linux::WpaSupplicant::auto_setup`
- 指定网卡初始化:`wifi::linux::WpaSupplicant::new`
- 扫描附近 Wi-Fi
- 查看已保存网络
- 连接 / 断开 / 重连 Wi-Fi
- 选择指定 network id
- 保存或移除 `wpa_supplicant` 配置

## 平台说明

- 通用网卡信息读取依赖 `netdev``if-watch`,核心逻辑以跨平台接口为主
- `linux` 模块仅在 `target_os = "linux"` 下编译
- `wpa` 模块仅在 `Linux + feature = "wpa"` 下可用
- 当前 Wi-Fi 管理实现实际依赖 Linux 的 `wpa_supplicant` socket,Windows 下未实现对应控制逻辑

## Feature 说明

`Cargo.toml` 中当前提供两个可选 feature:

```toml
[features]
default = []
wifi = ["async-trait"]
wpa = ["libc", "config", "tempfile"]
```

建议按场景启用:

- 只使用基础网络能力:不需要额外 feature
- 只依赖 Wi-Fi trait / DTO:`wifi`
- 使用 Linux `wpa_supplicant` 控制能力:`wifi,wpa`

示例:

```bash
cargo add network
```

如果以本地路径依赖:

```toml
[dependencies]
network = { path = ".", features = ["wifi", "wpa"] }
```

## 依赖环境

当你使用 `wpa` 能力时,需要保证:

- 系统为 Linux
- 已安装并启动 `wpa_supplicant`
- 存在对应网卡的控制 socket,例如 `/var/run/wpa_supplicant/wlan0`
- 当前进程对该 socket 具有访问权限

项目内部默认会尝试连接类似下面的路径:

```text
/var/run/wpa_supplicant/<iface>
```

## 快速开始

### 1. 获取网卡列表

```rust
use network::utils;

fn main() {
    let ifaces = utils::ifaces();
    for iface in ifaces {
        println!(
            "{} {} wifi={} up={} ipv4={}",
            iface.name, iface.friendly_name, iface.is_wifi, iface.is_up, iface.ipv4_addr
        );
    }
}
```

### 2. 获取本机 IP 与 MAC

```rust
use network::utils;

fn main() -> anyhow::Result<()> {
    let ip = utils::get_local_ip()?;
    let mac = utils::get_mac_addr()?;

    println!("local ip: {ip}");
    println!("mac: {mac}");
    Ok(())
}
```

### 3. 监听网络变化

```rust
use network::utils;

fn on_change(is_up: bool) {
    println!("network changed, is_up={is_up}");
}

#[tokio::main]
async fn main() -> anyhow::Result<()> {
    let _handle = utils::listen_change(on_change)?;

    loop {
        tokio::time::sleep(std::time::Duration::from_secs(60)).await;
    }
}
```

### 4. Linux 下启用或禁用网卡

```rust
#[cfg(target_os = "linux")]
#[tokio::main]
async fn main() -> anyhow::Result<()> {
    network::utils::enable("eth0", true).await?;
    Ok(())
}
```

## Wi-Fi 使用示例

下面示例需要启用 `features = ["wifi", "wpa"]`,并运行在 Linux。

### 初始化 `wpa_supplicant` 客户端

```rust
use network::wifi::{IWifi, linux::WpaSupplicant};

fn on_wifi_event(evt: String) {
    println!("wifi event: {evt}");
}

#[tokio::main]
async fn main() -> anyhow::Result<()> {
    let wifi = WpaSupplicant::auto_setup(Some(on_wifi_event)).await?;

    let status = wifi.status().await?;
    println!("{status:?}");
    Ok(())
}
```

### 扫描附近 Wi-Fi

```rust
use network::wifi::{IWifi, linux::WpaSupplicant};

#[tokio::main]
async fn main() -> anyhow::Result<()> {
    let wifi = WpaSupplicant::auto_setup(None).await?;
    let results = wifi.scan().await?;

    for item in results {
        println!(
            "ssid={} signal={} level={} encrypted={}",
            item.ssid_name,
            item.signal,
            item.to_level(),
            item.is_encrypted
        );
    }

    Ok(())
}
```

### 连接 Wi-Fi

```rust
use network::wifi::{IWifi, linux::WpaSupplicant};

#[tokio::main]
async fn main() -> anyhow::Result<()> {
    let wifi = WpaSupplicant::auto_setup(None).await?;

    wifi.connect("MyWiFi".to_string(), "12345678".to_string()).await?;

    Ok(())
}
```

开放网络可传空密码:

```rust
wifi.connect("OpenWiFi".to_string(), "".to_string()).await?;
```

### 查看已保存网络

```rust
use network::wifi::{IWifi, linux::WpaSupplicant};

#[tokio::main]
async fn main() -> anyhow::Result<()> {
    let wifi = WpaSupplicant::auto_setup(None).await?;
    let networks = wifi.get_networks().await?;

    for item in networks {
        println!(
            "id={} ssid={} connected={} disabled={}",
            item.network_id,
            item.ssid,
            item.is_connected(),
            item.is_disable()
        );
    }

    Ok(())
}
```

### 切换、断开与移除网络

```rust
use network::wifi::{IWifi, linux::WpaSupplicant};

#[tokio::main]
async fn main() -> anyhow::Result<()> {
    let wifi = WpaSupplicant::auto_setup(None).await?;

    let _ = wifi.select_id(0).await?;
    wifi.disconnect().await?;
    wifi.reconnect().await?;
    wifi.remove(0).await?;

    Ok(())
}
```

## 主要数据结构

### `IfaceDto`

表示网卡的基础信息:

- `index`: 网卡索引
- `name`: 系统网卡名,如 `eth0``wlan0`
- `friendly_name`: 友好名称
- `is_wifi`: 是否为无线网卡
- `mac_addr`: MAC 地址
- `ipv4_addr`: IPv4 地址
- `ipv6_addr`: IPv6 地址
- `has_dns`: 是否存在 DNS 配置
- `cur_used`: 是否为当前默认使用网卡
- `is_up`: 是否启用

### `NetInfoDto`

- `ifaces`: 网卡列表
- `connected`: 是否已连接网络

### `ScanResult`

- `bissid_mac`: AP 的 BSSID / MAC
- `frequency`: 频段频率
- `signal`: 信号强度(dBm)
- `flags`: 扫描标志
- `is_encrypted`: 是否加密
- `ssid_name`: Wi-Fi 名称

### `NetworkListResult`

- `network_id`: `wpa_supplicant` 中的网络 ID
- `ssid`: Wi-Fi 名称
- `flags`: 状态标记
- `bssid`: 关联 BSSID

## 设计说明

- 底层网卡枚举基于 `netdev`
- 网络变化监听基于 `if-watch`
- 异步运行时基于 `tokio`
- Wi-Fi 控制通过异步 channel + `wpa_supplicant` socket 完成
- 扫描结果和事件结果会经过简单封装,便于上层业务直接使用

## 注意事项

- `utils::check_online()` 当前通过 UDP 连接 `114.114.114.114:53` 判断外网连通性,这更像“是否可以访问外部网络”的近似判断
- `utils::ifaces()` 会过滤回环网卡、Docker 网卡、`p2p0` 以及非物理网卡
- `WpaSupplicant::auto_setup()` 会选择扫描到的第一个无线网卡
- 使用 `wpa` 能力时,运行权限、socket 权限和系统网络配置都会影响结果
- README 中的示例基于当前代码接口编写,如后续 API 调整请同步更新

## 开发与检查

```bash
cargo check
cargo check --features wifi
cargo check --features "wifi wpa"
```

## 许可证

本项目基于 [MIT License](./LICENSE) 发布。