Linuxのcfg80211_opsを読む


cfg80211_ops のよく使いそうな関数について調べてみました。

cfg80211はLinux KernelのWi-Fi設定（APとの接続、スキャンなど）をするカーネルの機能です。
ドライバまたはmac80211に対してはcfg80211_opsという関数ポインタの構造体を使ってやりとりします。
(FullMACの場合はcfg80211の直下にドライバがある。SoftMACの場合はcfg80211の下にmac80211があり、その下にドライバがある。)
アプリからはioctlを使ってnl80211経由でアクセスします。

LinuxのWi-Fiドライバを上から読む場合は、制御系の操作はcfg80211_opsから読んでいきます。
データ送受信の場合はnetdev関連から読みます。
cfg80211_opsは関数が多すぎなので、まず読むべき関数をピックアップしてみました。
今回はSTAのみとしました。

![Untitled.png](https://qiita-image-store.s3.amazonaws.com/0/42120/ee1fc464-6d5c-0fcb-406c-e5b2385710e2.png)


# ソースコード
* https://github.com/torvalds/linux/blob/master/include/net/cfg80211.h
* ドライバの cfg80211_ops を実装している部分
* mac80211のcfg80211_opsを実装している部分


# cfg80211_ops のSTAでよく使う関数
## connect
* 引数smeで指定したAPに接続する
* 結果は cfg80211_connect_result()でコールバックする。
* 引数
    * wiphy Wireless deviceのインスタンス
    * dev ネットワークインターフェイスに対応するnetdev
    * sme SSID BSSIDなどAPを識別できる情報とscan結果の情報など

```
 * @connect: Connect to the ESS with the specified parameters. When connected,
 *	call cfg80211_connect_result() with status code %WLAN_STATUS_SUCCESS.
 *	If the connection fails for some reason, call cfg80211_connect_result()
 *	with the status from the AP. The driver is allowed to roam to other
 *	BSSes within the ESS when the other BSS matches the connect parameters.
 *	When such roaming is initiated by the driver, the driver is expected to
 *	verify that the target matches the configured security parameters and
 *	to use Reassociation Request frame instead of Association Request frame.
 *	The connect function can also be used to request the driver to perform
 *	a specific roam when connected to an ESS. In that case, the prev_bssid
 *	parameter is set to the BSSID of the currently associated BSS as an
 *	indication of requesting reassociation. In both the driver-initiated and
 *	new connect() call initiated roaming cases, the result of roaming is
 *	indicated with a call to cfg80211_roamed() or cfg80211_roamed_bss().
 *	(invoked with the wireless_dev mutex held)
```
```c
	int	(*connect)(struct wiphy *wiphy, struct net_device *dev,
			   struct cfg80211_connect_params *sme);
```
## disconnect
* AP との接続を切断する。
* 引数
    * wiphy Wireless deviceのインスタンス
    * dev ネットワークインターフェイスに対応するnetdev
    * reason_code 切断要求に含める切断理由

```
 * @disconnect: Disconnect from the BSS/ESS.
 *	(invoked with the wireless_dev mutex held)
```
```c
	int	(*disconnect)(struct wiphy *wiphy, struct net_device *dev,
			      u16 reason_code);
```

## scan
* APなどを探すためにスキャンする。
* スキャン結果は、cfg80211_scan_done()でコールバックする。
* 引数
    * wiphy Wireless deviceのインスタンス
    * request Scanの設定 channel,band,ssidなど

```
 * @scan: Request to do a scan. If returning zero, the scan request is given
 *	the driver, and will be valid until passed to cfg80211_scan_done().
 *	For scan results, call cfg80211_inform_bss(); you can call this outside
 *	the scan/scan_done bracket too.
```
```
	int	(*scan)(struct wiphy *wiphy,
			struct cfg80211_scan_request *request);
```

## add_key
* WEP,WPAなどの暗号キーを追加する。
* 引数
    * wiphy Wireless deviceのインスタンス
    * dev ネットワークインターフェイスに対応するnetdev
    * key_index keyのid
    * pairwise 今は使っていない場合が多いようです。
    * mac_addr 相手のMACアドレス NULLならgroup keyとして扱う
    * params 鍵と暗号の種類などの情報

```
 * @add_key: add a key with the given parameters. @mac_addr will be %NULL
 *	when adding a group key.
```

```
	int	(*add_key)(struct wiphy *wiphy, struct net_device *netdev,
			   u8 key_index, bool pairwise, const u8 *mac_addr,
			   struct key_params *params);
```

## del_key
* WEP,WPAなどの暗号キーを削除する
* 引数
    * wiphy Wireless deviceのインスタンス
    * dev ネットワークインターフェイスに対応するnetdev
    * key_index keyのid
    * pairwise 今は使っていない場合が多いようです。
    * mac_addr MACアドレス NULLならgroup keyとして扱う

```
 * @del_key: remove a key given the @mac_addr (%NULL for a group key)
 *	and @key_index, return -ENOENT if the key doesn't exist.
```
```
	int	(*del_key)(struct wiphy *wiphy, struct net_device *netdev,
			   u8 key_index, bool pairwise, const u8 *mac_addr);
```

## set_default_kery
* add_keyで追加した鍵のうち、どれをデフォルトで使うかを設定する。
* 引数
    * wiphy Wireless deviceのインスタンス
    * dev ネットワークインターフェイスに対応するnetdev
    * key_index keyのid
    * unicast TRUEならユニキャスト鍵
    * multicast　TRUEならマルチキャスト鍵

```
 * @set_default_key: set the default key on an interface
```
```
	int	(*set_default_key)(struct wiphy *wiphy,
				   struct net_device *netdev,
				   u8 key_index, bool unicast, bool multicast);
```