连接管理器(ConnMan)是一个连接管理守护进程 , 用于管理运行 Linux 操作系统中设备的互联网连接。 它以快速、连贯、同步的方式对不断变化的网络条件提供了低内存消耗。ConnMan拥有各种插件, 是一个完全模块化的系统, 可以扩展支持各种有线或无线技术,允许对各种用例进行简单的适配和修改。 例如DHCP 和DNS 这样的配置方法就是使用插件实现的。所有的应用程序都使用 D-Bus 来与 ConnMan 通信,与嵌入式 Yocto 构建系统一起使用, 是 GENIVI 规范的一部分。ConnMan遵循 GPL v2.0许可, 英特尔是该项目的主要贡献者。其内部架构如下:
图1
功能特性
以下特性嵌入到ConnMan中:
- 通用插件基础结构
- 设备和网络抽象(带有基本存储支持)
- IPv4, IPv4-LL (link-local) 和DHCP以及IPv6, DHCPv6,V6到V4的 隧道等
- 高级路由和 DNS 配置
- 内置 DNS 代理和智能缓存
- 内置的 WISPr 热点登录和门户检测
- 时区配置(手动和自动的 NTP)
- 代理处理(手动和自动的WPAD)
- 网络支持(USB, 蓝牙和 WiFi AP 模式)
- 详细统计处理(家居及漫游)
可以启用各种插件来支持网络:
- 以太网插件
- Wifi 插件 WEP40 / WEP128及 WPA/WPA2(个人及企业)
- 蓝牙插件(使用 BlueZ)
- 2g / 3g / 4g 插件(使用 oFono)
还提供了附加功能的插件:
- 回路接口设置
- PACrunner 代理
- PolicyKit 授权工具
D-Bus接口
应用程序都使用 D-Bus 来与 ConnMan 通信,通过管理器对象来实现应用入口。管理器对象包含服务对象的引用(接口),其他接口包括 VPN、时钟、任务、技术、会话、通知、对等、代理和计数器等。
图2
D-Bus Manager 接口
D-Bus Manager 解释了所有的方法和属性。
图3
检索所有全局属性的简单方法如下:
bus = dbus.SystemBus()
manager = dbus.Interface(bus.get_object("net.connman", "/"), "net.connman.Manager")
properties = manager.GetProperties()
改变一个全局属性也非常简单。 例如, 启用所谓的飞行模式(AKA flight mode)可以以设置该属性: manager.SetProperty ("OfflineMode", dbus.Boolean (1))。
图4
服务接口
高级用户接口易于访问网络细节和用户选择的偏好。 这是服务列表和接口(图5), 以一个单一的平面和排序列表来维护所有可用的服务。
图5
图6
服务状态
图7
- 每个服务的基本状态都是"空闲",这意味着这项服务目前根本没有使用。 它也不是试图连接或做任何其他事情。
- "关联"状态表明该服务试图建立与网络的低级连接 -- 例如, 与 WiFi 接入点相关联/连接。
- 在"配置"状态下, 表示服务正在尝试检索/配置 IP 设置。
- "准备好"状态标志着一个成功连接的设备,并不意味着它有默认的路由, 但是基本的 IP操作将会成功。
- "断开"状态,表明服务将终止当前连接并返回到"空闲"状态。
- "失败"状态表明一种错误的行为,类似于"空闲"状态, 服务没有连接。
服务的使用
下面是如何获得一个服务对象:
service = dbus.Interface(bus.get_object("net.connman", path), "net.connman.Service")
它还包含连接或断开特定服务的方法,ConnMan可以根据策略或通过外部事件(如在以太网电缆中插入)自动连接服务。
图8
图9
技能接口
基本的设备配置任务是通过技能接口完成的,例如, 通过技术接口来切换设备(例如通过 RFKILL)。
图10用户可以通过 OfflineMode 属性激活离线(飞行)模式。 在离线模式下, 包括以太网在内的所有技能都被关闭。 在离线模式下, 用户可以通过使用 rfkill 命令来临时激活单个技能。
ConnMan 的一些细节
可以通过命令行参数来启动ConnMan:
-c, --config=FILE Load the specified configuration file instead of /usr/local/etc/connman/main.conf
-d, --debug=DEBUG Specify debug options to enable
-i, --device=DEV Specify networking device or interface
-I, --nodevice=DEV Specify networking interface to ignore
-p, --plugin=NAME,... Specify plugins to load
-P, --noplugin=NAME,... Specify plugins not to load
-W, --wifi=NAME Specify driver for WiFi/Supplicant
-n, --nodaemon Don't fork daemon to background
-r, --nodnsproxy Don't enable DNS Proxy
--nobacktrace Don't print out backtrace information
使用示例如下:
connmand -i wlan0 -I eth0 --nodnsproxy --nodaemon >& connman.log
主配置文件(main.conf)如下:
InputRequestTimeout = 120 (default)---------> input request ( ex. passphrase) timeout
BrowserLaunchTimeout = 300 ( default) -----> The request for launching a browser for portal pages
BackgroundScanning = true --------------------> option for background scanning
FallbackTimeservers = --------------------------> List of fallback timeservers ( used by NTP sync) separated by ","
FallbackNameservers = -------------------------> List of fallback nameservers
DefaultAutoConnectTechnologies = -----------> List of technologies that are marked autoconnectable by default.
PreferredTechnologies = ------------------------> List of preferred technologies from - most preferred one to least preferred
NetworkInterfaceBlacklist = vmnet,vboxnet,virbr,ifb,ve-,vb- ---> List of blacklisted network interfaces
AllowHostnameUpdates = true -----------------> Allow connman to change the system hostname ( ex. dhcp hostname option)
SingleConnectedTechnology = false -----------> Keep only a single connected technology at any time
TetheringTechnologies = wifi,bluetooth,gadget
PersistentTetheringMode = false --------------> Restore earlier tethering status when returning from offline mode
Enable6to4 = false ------------------------------> Automatically enable Anycast 6to4 if possible (not recommended. see RFC6343 )
EnableOnlineCheck = false --------------------> Enable use of http get as on online status check
AlwaysConnectedTechnologies = -------------> List of technologies with AutoConnect = true which are always connected regardless of PreferredTechnologies setting
ConnMan 使用配置文件来提供现有的服务,在 /var/lib/Connman/目录下 。 配置文件名不能包含字母或数字以外的其他字符, 并且必须有一个 Config后缀. 例如:
Ex. #cat /var/lib/connman/example.config
[global]
Name = Example
Description = Example network configuration
[service_home_ethernet]
Type = ethernet
IPv4 = 192.168.1.42/255.255.255.0/192.168.1.1
IPv6 = 2001:db8::42/64/2001:db8::1
MAC = 01:02:03:04:05:06
Nameservers = 10.2.3.4,192.168.1.99
SearchDomains = my.home,isp.net
Timeservers = 10.172.2.1,ntp.my.isp.net
Domain = my.home
[service_home_wifi]
Type = wifi
Name = my_home_wifi
Passphrase = secret
IPv4 = 192.168.2.2/255.255.255.0/192.168.2.1
MAC = 06:05:04:03:02:01
设置和配置文件是为用户经常连接的网络而自动创建的,例如:
# cat /var/lib/connman/settings
[global]
OfflineMode=false
[WiFi]
Enable=true
Tethering=false
[Bluetooth]
Enable=false
Tethering=false
Vpn 设置可以在 /var/lib/connman-VPN/ 。
写一个插件
基本插件包含通过 CONNMAN 定义的插件描述, 以及通过该描述定义的 init / exit 回调。例如:
#include
static int example_init(void)
{
return 0;
}
static void example_exit(void)
{
}
CONNMAN_PLUGIN_DEFINE(example, "Example plugin", CONNMAN_VERSION,
example_init, example_exit)
插件通过技术、网络和设备以及其他基础结构与ConnMan的核心功能相互作用。 以下是技术基础设施:
ex. bluetooth plugin
static struct connman_technology_driver tech_driver = {
.name = "bluetooth",
.type = CONNMAN_SERVICE_TYPE_BLUETOOTH,
.probe = bluetooth_tech_probe,
.remove = bluetooth_tech_remove,
.set_tethering = bluetooth_tech_set_tethering,
};
为了让连接管理器了解新的插件, 需要通过调用ConnMan驱动注册器来注册它的驱动程序。
connman_technology_driver_register(&tech_driver);
设备
设备代表给定技术的真实设备,每种技术都可能有很多设备。
static struct connman_device_driver device_driver = {
.name = "bluetooth",
.type = CONNMAN_DEVICE_TYPE_BLUETOOTH,
.probe = bluetooth_device_probe,
.remove = bluetooth_device_remove,
.enable = bluetooth_device_enable,
.disable = bluetooth_device_disable,
};
注册驱动程序:
connman_device_driver_register(&device_driver);
此外, 需要为每个插件编写处理新设备的检测代码; 蓝牙插件通过为 BlueZ-d-bus 接口来注册观察者来实现。 一旦新的蓝牙设备出现, 插件需要通过调用 ConnMan 设备创建来通知 ConnMan 内涵。 对于蓝牙插件, 这个调用将是:
struct connman_device *device;
device = connman_device_create("bluetooth", CONNMAN_DEVICE_TYPE_BLUETOOTH)
网络
连接管理器为插件提供了一种手段, 用于处理为每种技术建立 / 处理连接的细节。 对于蓝牙插件, 需要注册一个connman
networkdriver:
static struct connman_network_driver network_driver = {
.name = "bluetooth",
.type = CONNMAN_NETWORK_TYPE_BLUETOOTH_PAN,
.probe = bluetooth_pan_probe,
.remove = bluetooth_pan_remove,
.connect = bluetooth_pan_connect,
.disconnect = bluetooth_pan_disconnect,
};
然后, 调用注册函数:
connman_network_driver_register(&network_driver);
源文件的结构解读
初始化函数将在 src/main.c 中在运行主循环之前调用。
src/util.c - /dev/urandom support
src/inotify.c - used by the core (config.c) and the session policy plugin
src/technology.c – used for technology interface
src/notifier.c – basic notifier infrastructure
src/agent.c – agent interface
src/service.c – used for service interface
src/peer_service.c – p2p peer service API
src/peer.c – p2p peer object’s core logic
src/provider.c – provider infrastructure
src/network.c – network infrastructure used by plug-ins
src/config.c – framework for configuration files
src/device.c – device infrastructure used by plug-ins
src/iptables.c – iptables support (netfilter chains and rules)
src/firewall-iptables.c, nftables.c (older firewall.c) – firewall infrastructure.
src/nat.c – used for NAT
src/tethering.c – tethering infrastructure
src/manager.c – Manager interface
src/stats.c – used for storing service stats ( mmaped into memory)
src/ipconfig.c – IP configuration framework
src/rtnl.c – netlink support
src/session.c – Allows 3rd party applications to request a network session
src/resolver.c – resolver framework
src/dhcp.c, dhcpv6.c – dhcp framework
src/rfkill.c – rfkill interface support
src/machine.c - basic systemd-hostnamed ( machine-type- “chassis”) support
命令行客户端
ConnMan有一个标准的命令行客户端 connmanctl。 它可以有两种运行模式:
- 在命令行模式中, 命令输入作为对 connmanctl 命令的参数, 就像 systemctl 一样
- 交互式模式是在没有参数的情况下键入 connmanctl 来开始的。 将改变为 connmanctl 表示它正在等待用户命令, 就像 python 交互模式一样
connmanctl示例:1.启用和禁用 WiFi
$ connmanctl technologies - check for the line that says Powered: True/False.
$ connmanctl enable wifi - To power the wifi on.
$ connmanctl disable wifi – To power off the wifi.
2.连接到一个开放的访问点本示例的命令显示如何在命令行模式下运行控制器。 为了扫描网络, connmanctl 接受简单的技术名参数。 扫描附近的 WiFi 网络:
$ connmanctl scan wifi To list the available networks found after a scan run (example output):
$ connmanctl services
*AO MyNetwork wifi_dc85de828967_68756773616d_managed_psk OtherNET wifi_dc85de828967_38303944616e69656c73_managed_psk AnotherOne wifi_dc85de828967_3257495245363836_managed_wep FourthNetwork wifi_dc85de828967_4d7572706879_managed_wep AnO6penNetwork wifi_dc85de828967_4d6568657272696e_managed_none
$ connmanctl connect wifi_dc85de828967_4d6568657272696e_managed_none
3.连接到受保护的AP对于受保护的AP, 提供一些信息给 ConnMan 守护进程, 例如一个密码。
$ connmanctl
connmanctl> scan wifi ----- To list services:
connmanctl> services
connmanctl> agent on --- register the agent to handle user requests.
connmanctl> connect wifi_dc85de828967_38303944616e69656c73_managed_psk
代理需要根据所连接的网络类型提供更多信息,代理还将打印关于它所需要信息的额外数据, 如下面的示例所示。
Agent RequestInput wifi_dc85de828967_38303944616e69656c73_managed_psk Passphrase = [ Type=psk, Requirement=mandatory ] Passphrase?
提供完请求的信息后, 然后键入 quit 退出。如果提供的信息是正确的, 那现在应该就连接到受保护的AP了。各种硬件接口被在ConnMan中称为技术,要列出可用的技术, 可以运行:
$ connmanctl technologies
那些技术可以通过以下方式进行:
$ connmanctl enable technology_type
$ connmanctl disable technology_type
例如, 切换 WiFi:
$ connmanctl disable wifi
测试与调试
ConnMan同时也提供了基于 python 的测试脚本(ex. test-connman, list-services 等)。 通过这些脚本支持连接、断开、自动连接、服务、扫描、启用、禁用、非线性、状态等基本操作。可以使用-d 命令行选项在 ConnMan 中激活调试打印。
-d Activate all normal debug prints
-d src/service.c This prints debugging info from src/service.c file only
-d src/network.c:src/ipconfig.c This activates debug prints in src/network.c and src/ipconfig.c files.
-d 'src/n*.c' This would activate debug print from all the C source files starting with letter 'n' in src directory. Note the quotation marks around option, that is to prevent shell expansion.
-d '*/n*.c:*/i*.c' Activate debug prints for all C source files starting with letters 'n' or 'i' in any sub-directory.
Connman 的一些组件有基于环境变量启动的调试版本。 如果环境变量已设置, 则相应组件将打印一些额外的调试信息。可以使用下列环境变量:
* CONNMAN_DHCP_DEBUG: Dhcpv4相关调试信息
* CONNMAN_DHCPV6_DEBUG: DHCPv6相关调试信息
* CONNMAN_IPTABLES_DEBUG: 使用 iptables 时的额外信息
* CONNMAN_RESOLV_DEBUG: 名称解析器调试打印。 这些调试信息用于当 ConnMan 解析主机名称以供自己使用。 请注意, DNS 代理调试版本不使用此环境变量。 为此, 我们可以使用"-d src / dnsproxy。 "c"命令行选项
* CONNMAN_SUPPLICANT_DEBUG :调试打印, 用于控制和 wpa 拼接过程之间的通信
* CONNMAN_WEB_DEBUG: 当 ConnMan 在 Wispr 进行互联网连接检查时的调试信息
例如:
CONNMAN_SUPPLICANT_DEBUG=1 src/connmand -n
译自 http://www.embedded-computing.com/dev-tools-and-os/the-connman