1. 程式人生 > >(一百零二)Android O wpa_supplicant初始化學習

(一百零二)Android O wpa_supplicant初始化學習

前言:之前在 有提及“通過 “setprop ctrl.start wpa_supplicant” 來觸發init程序去fork一個子程序來完成supplicant的啟動”,這裡supplicant是啟動了,但啟動又做了什麼工作呢?

 

1.supplicant初始化配置

初始化配置與.rc檔案有關,具體可參考https://blog.csdn.net/qq_28899635/article/details/56289063

先在程式碼中查詢一下包含wpa_supplicant的rc檔案 

[email protected]:~/expand/aosp/aosp$ grep "wpa_supplicant" ./ -nr --include="*.rc"
./device/google/marlin/init.common.rc:199:    mkdir /data/misc/wifi/wpa_supplicant 0770 wifi wifi
./device/google/marlin/init.common.rc:247:    # Create the symlink to qcn wpa_supplicant folder for ar6000 wpa_supplicant
./device/google/marlin/init.common.rc:686:service wpa_supplicant /vendor/bin/hw/wpa_supplicant \
./device/google/marlin/init.common.rc:689:    -iwlan0 -Dnl80211 -c/data/misc/wifi/wpa_supplicant.conf \
./device/google/marlin/init.common.rc:690:    -I/vendor/etc/wifi/wpa_supplicant_overlay.conf \
./device/google/marlin/init.common.rc:693:#   we will start as root and wpa_supplicant will switch to user wifi
./device/google/cuttlefish/shared/config/init.vsoc.rc:98:service wpa_supplicant /vendor/bin/hw/wpa_supplicant \
./device/google/cuttlefish/shared/config/init.vsoc.rc:99:    -Dnl80211 -iwlan0 -c/data/misc/wifi/wpa_supplicant.conf 
[email protected]
:wpa_wlan0 ./device/google/wahoo/init.hardware.rc:287: mkdir /data/misc/wifi/wpa_supplicant 0770 wifi wifi ./device/google/wahoo/init.hardware.rc:655:service wpa_supplicant /vendor/bin/hw/wpa_supplicant \ ./device/google/wahoo/init.hardware.rc:658: -iwlan0 -Dnl80211 -c/data/misc/wifi/wpa_supplicant.conf \ ./device/google/wahoo/init.hardware.rc:659: -I/vendor/etc/wifi/wpa_supplicant_overlay.conf \ ./device/google/wahoo/init.hardware.rc:662: # we will start as root and wpa_supplicant will switch to user wifi ./device/google/dragon/init.dragon.rc:218:service wpa_supplicant /vendor/bin/hw/wpa_supplicant \ ./device/google/dragon/init.dragon.rc:219: -iwlan0 -Dnl80211 -c/data/misc/wifi/wpa_supplicant.conf \ ./device/huawei/angler/init.angler.rc:412:service wpa_supplicant /vendor/bin/hw/wpa_supplicant \ ./device/huawei/angler/init.angler.rc:413: -iwlan0 -Dnl80211 -c/data/misc/wifi/wpa_supplicant.conf \ ./device/lge/bullhead/init.bullhead.rc:348:service wpa_supplicant /vendor/bin/hw/wpa_supplicant \ ./device/lge/bullhead/init.bullhead.rc:351: -iwlan0 -Dnl80211 -c/data/misc/wifi/wpa_supplicant.conf \ ./device/lge/bullhead/init.bullhead.rc:352: -I/system/etc/wifi/wpa_supplicant_overlay.conf \ ./device/lge/bullhead/init.bullhead.rc:355:# we will start as root and wpa_supplicant will switch to user wifi ./device/linaro/hikey/init.common.rc:104:service wpa_supplicant /system/vendor/bin/hw/wpa_supplicant \ ./device/linaro/hikey/init.common.rc:105: -iwlan0 -Dnl80211 -c/data/misc/wifi/wpa_supplicant.conf \

各配置各不相同,應該和不同的機型有關。簡單看下其中之一

vim +699 ./device/google/marlin/init.common.rc

service wpa_supplicant /vendor/bin/hw/wpa_supplicant \
    -ip2p0 -Dnl80211 -c/data/misc/wifi/p2p_supplicant.conf \
    -I/vendor/etc/wifi/p2p_supplicant_overlay.conf -N \
    -iwlan0 -Dnl80211 -c/data/misc/wifi/wpa_supplicant.conf \
    -I/vendor/etc/wifi/wpa_supplicant_overlay.conf \
    -O/data/misc/wifi/sockets -puse_p2p_group_interface=1 \
    -e/data/misc/wifi/entropy.bin 
[email protected]
:wpa_wlan0 # we will start as root and wpa_supplicant will switch to user wifi # after setting up the capabilities required for WEXT # user wifi # group wifi inet keystore class main socket wpa_wlan0 dgram 660 wifi wifi disabled oneshot

這一大長串也不知道啥意思,這時切換到supplicant的main.c中看下。

 

2.supplicant的main.c

有如上介面列表,其中比較在意兩個介面,一個main,一個usage.

2.1 usage

先看一下usage介面

static void usage(void)
{
	int i;
	printf("%s\n\n%s\n"
	       "usage:\n"
	       "  wpa_supplicant [-BddhKLqq"
#ifdef CONFIG_DEBUG_SYSLOG
	       "s"
#endif /* CONFIG_DEBUG_SYSLOG */
	       "t"
#ifdef CONFIG_DBUS
	       "u"
#endif /* CONFIG_DBUS */
	       "vW] [-P<pid file>] "
	       "[-g<global ctrl>] \\\n"
	       "        [-G<group>] \\\n"
	       "        -i<ifname> -c<config file> [-C<ctrl>] [-D<driver>] "
	       "[-p<driver_param>] \\\n"
	       "        [-b<br_ifname>] [-e<entropy file>]"
#ifdef CONFIG_DEBUG_FILE
	       " [-f<debug file>]"
#endif /* CONFIG_DEBUG_FILE */
	       " \\\n"
	       "        [-o<override driver>] [-O<override ctrl>] \\\n"
	       "        [-N -i<ifname> -c<conf> [-C<ctrl>] "
	       "[-D<driver>] \\\n"
#ifdef CONFIG_P2P
	       "        [-m<P2P Device config file>] \\\n"
#endif /* CONFIG_P2P */
	       "        [-p<driver_param>] [-b<br_ifname>] [-I<config file>] "
	       "...]\n"
	       "\n"
	       "drivers:\n",
	       wpa_supplicant_version, wpa_supplicant_license);

	for (i = 0; wpa_drivers[i]; i++) {
		printf("  %s = %s\n",
		       wpa_drivers[i]->name,
		       wpa_drivers[i]->desc);
	}

#ifndef CONFIG_NO_STDOUT_DEBUG
	printf("options:\n"
	       "  -b = optional bridge interface name\n"
	       "  -B = run daemon in the background\n"
	       "  -c = Configuration file\n"
	       "  -C = ctrl_interface parameter (only used if -c is not)\n"
	       "  -d = increase debugging verbosity (-dd even more)\n"
	       "  -D = driver name (can be multiple drivers: nl80211,wext)\n"
	       "  -e = entropy file\n"
#ifdef CONFIG_DEBUG_FILE
	       "  -f = log output to debug file instead of stdout\n"
#endif /* CONFIG_DEBUG_FILE */
	       "  -g = global ctrl_interface\n"
	       "  -G = global ctrl_interface group\n"
	       "  -h = show this help text\n"
	       "  -i = interface name\n"
	       "  -I = additional configuration file\n"
	       "  -K = include keys (passwords, etc.) in debug output\n"
	       "  -L = show license (BSD)\n"
#ifdef CONFIG_P2P
	       "  -m = Configuration file for the P2P Device interface\n"
#endif /* CONFIG_P2P */
#ifdef CONFIG_MATCH_IFACE
	       "  -M = start describing new matching interface\n"
#endif /* CONFIG_MATCH_IFACE */
	       "  -N = start describing new interface\n"
	       "  -o = override driver parameter for new interfaces\n"
	       "  -O = override ctrl_interface parameter for new interfaces\n"
	       "  -p = driver parameters\n"
	       "  -P = PID file\n"
	       "  -q = decrease debugging verbosity (-qq even less)\n"
#ifdef CONFIG_DEBUG_SYSLOG
	       "  -s = log output to syslog instead of stdout\n"
#endif /* CONFIG_DEBUG_SYSLOG */
	       "  -t = include timestamp in debug messages\n"
#ifdef CONFIG_DEBUG_LINUX_TRACING
	       "  -T = record to Linux tracing in addition to logging\n"
	       "       (records all messages regardless of debug verbosity)\n"
#endif /* CONFIG_DEBUG_LINUX_TRACING */
#ifdef CONFIG_DBUS
	       "  -u = enable DBus control interface\n"
#endif /* CONFIG_DBUS */
	       "  -v = show version\n"
	       "  -W = wait for a control interface monitor before starting\n");

	printf("example:\n"
	       "  wpa_supplicant -D%s -iwlan0 -c/etc/wpa_supplicant.conf\n",
	       wpa_drivers[0] ? wpa_drivers[0]->name : "nl80211");
#endif /* CONFIG_NO_STDOUT_DEBUG */
}

對應在adb命令列執行一下supplicant

/vendor/bin/hw # ./wpa_supplicant                                   
wpa_supplicant v2.7-devel-8.1.0
Copyright (c) 2003-2017, Jouni Malinen <[email protected]> and contributors

This software may be distributed under the terms of the BSD license.
See README for more details.

This product includes software developed by the OpenSSL Project
for use in the OpenSSL Toolkit (http://www.openssl.org/)

usage:
  wpa_supplicant [-BddhKLqqtvW] [-P<pid file>] [-g<global ctrl>] \
        [-G<group>] \
        -i<ifname> -c<config file> [-C<ctrl>] [-D<driver>] [-p<driver_param>] \
        [-b<br_ifname>] [-e<entropy file>] \
        [-o<override driver>] [-O<override ctrl>] \
        [-N -i<ifname> -c<conf> [-C<ctrl>] [-D<driver>] \
        [-m<P2P Device config file>] \
        [-p<driver_param>] [-b<br_ifname>] [-I<config file>] ...]

drivers:
  nl80211 = Linux nl80211/cfg80211
options:
  -b = optional bridge interface name
  -B = run daemon in the background
  -c = Configuration file
  -C = ctrl_interface parameter (only used if -c is not)
  -d = increase debugging verbosity (-dd even more)
  -D = driver name (can be multiple drivers: nl80211,wext)
  -e = entropy file
  -g = global ctrl_interface
  -G = global ctrl_interface group
  -h = show this help text
  -i = interface name
  -I = additional configuration file
  -K = include keys (passwords, etc.) in debug output
  -L = show license (BSD)
  -m = Configuration file for the P2P Device interface
  -N = start describing new interface
  -o = override driver parameter for new interfaces
  -O = override ctrl_interface parameter for new interfaces
  -p = driver parameters
  -P = PID file
  -q = decrease debugging verbosity (-qq even less)
  -t = include timestamp in debug messages
  -v = show version
  -W = wait for a control interface monitor before starting
example:
  wpa_supplicant -Dnl80211 -iwlan0 -c/etc/wpa_supplicant.conf

然後再對照下supplicant在.rc檔案中的配置

service wpa_supplicant /vendor/bin/hw/wpa_supplicant \
    -ip2p0 -Dnl80211 -c/data/misc/wifi/p2p_supplicant.conf \
    -I/vendor/etc/wifi/p2p_supplicant_overlay.conf -N \
    -iwlan0 -Dnl80211 -c/data/misc/wifi/wpa_supplicant.conf \
    -I/vendor/etc/wifi/wpa_supplicant_overlay.conf \
    -O/data/misc/wifi/sockets -puse_p2p_group_interface=1 \
    -e/data/misc/wifi/entropy.bin [email protected]:wpa_wlan0
#   we will start as root and wpa_supplicant will switch to user wifi
#   after setting up the capabilities required for WEXT
#   user wifi
#   group wifi inet keystore
    class main
    socket wpa_wlan0 dgram 660 wifi wifi
    disabled
    oneshot

可以得出如下詳細註釋:

service wpa_supplicant /vendor/bin/hw/wpa_supplicant \
//Service名稱為wpa_supplicant,可執行檔案位置為/vendor/bin/hw/wpa_supplicant

    -ip2p0 -Dnl80211 -c/data/misc/wifi/p2p_supplicant.conf \
    -I/vendor/etc/wifi/p2p_supplicant_overlay.conf -N \
以p2p0為介面,nl80211為驅動,/data/misc/wifi/p2p_supplicant.conf和/vendor/etc/wifi/p2p_supplicant_overlay.conf為配置檔案,之後描述新的介面

    -iwlan0 -Dnl80211 -c/data/misc/wifi/wpa_supplicant.conf \
    -I/vendor/etc/wifi/wpa_supplicant_overlay.conf \
以wlan0為介面,nl80211為驅動,/data/misc/wifi/wpa_supplicant.conf和/vendor/etc/wifi/wpa_supplicant_overlay.conf為配置檔案

    -O/data/misc/wifi/sockets -puse_p2p_group_interface=1 \
	       "  -O = override ctrl_interface parameter for new interfaces\n"
	       "  -p = driver parameters\n"


    -e/data/misc/wifi/entropy.bin [email protected]:wpa_wlan0
	       "  -e = entropy file\n"
	       "  -g = global ctrl_interface\n"
#   we will start as root and wpa_supplicant will switch to user wifi
#   after setting up the capabilities required for WEXT
#   user wifi
#   group wifi inet keystore
    class main
    socket wpa_wlan0 dgram 660 wifi wifi
    disabled
    oneshot
//這邊應該是.rc的語法
//百度上搜了下是這樣描述的“其中 socket wpa_wlan0 dgram 660 wifi wifi建立了一個socket,wpa_s使用該socket接收framework的命令和向上傳遞event。framework同樣會呼叫連線該socket”

 

2.2 main.c

上面對wpa_s後面帶的引數有了基本的瞭解,那看下main.c中是如何解析儲存的吧。

	for (;;) {
		c = getopt(argc, argv,
			   "b:Bc:C:D:de:f:g:G:hi:I:KLMm:No:O:p:P:qsTtuvW");
		if (c < 0)
			break;
		switch (c) {
		case 'b':
			iface->bridge_ifname = optarg;
			break;
		case 'B':
			params.daemonize++;
			break;
		case 'c':
			iface->confname = optarg;
			break;
		case 'C':
			iface->ctrl_interface = optarg;
			break;
		case 'D':
			iface->driver = optarg;
			break;
		case 'd':
#ifdef CONFIG_NO_STDOUT_DEBUG
			printf("Debugging disabled with "
			       "CONFIG_NO_STDOUT_DEBUG=y build time "
			       "option.\n");
			goto out;
#else /* CONFIG_NO_STDOUT_DEBUG */
			params.wpa_debug_level--;
			break;
#endif /* CONFIG_NO_STDOUT_DEBUG */
		case 'e':
			params.entropy_file = optarg;
			break;
#ifdef CONFIG_DEBUG_FILE
		case 'f':
			params.wpa_debug_file_path = optarg;
			break;
#endif /* CONFIG_DEBUG_FILE */
		case 'g':
			params.ctrl_interface = optarg;
			break;

main.c中有如上的for迴圈,我截取了部分程式碼,會對傳入的argv進行解析,解析完了之後會逐一賦值到wpa_params這個結構體中進行儲存。

/**
 * struct wpa_params - Parameters for wpa_supplicant_init()
 */
struct wpa_params {
	/**
	 * daemonize - Run %wpa_supplicant in the background
	 */
	int daemonize;

	/**
	 * wait_for_monitor - Wait for a monitor program before starting
	 */
	int wait_for_monitor;

	/**
	 * pid_file - Path to a PID (process ID) file
	 *
	 * If this and daemonize are set, process ID of the background process
	 * will be written to the specified file.
	 */
	char *pid_file;

	/**
	 * wpa_debug_level - Debugging verbosity level (e.g., MSG_INFO)
	 */
	int wpa_debug_level;

	/**
	 * wpa_debug_show_keys - Whether keying material is included in debug
	 *
	 * This parameter can be used to allow keying material to be included
	 * in debug messages. This is a security risk and this option should
	 * not be enabled in normal configuration. If needed during
	 * development or while troubleshooting, this option can provide more
	 * details for figuring out what is happening.
	 */

這裡再看下解析的函式

int getopt(int argc, char *const argv[], const char *optstring)
{
	static int optchr = 1;
	char *cp;

	if (optchr == 1) {
		if (optind >= argc) {
			/* all arguments processed */
			return EOF;
		}
//校驗引數是否處理完成,optind應該對應於傳入引數的index,是option index簡寫,同樣optchr是opt char index的縮寫。
		if (argv[optind][0] != '-' || argv[optind][1] == '\0') {
			/* no option characters */
			return EOF;
		}
//校驗傳入引數是否帶‘-’並且內容不為空
	}

	if (os_strcmp(argv[optind], "--") == 0) {
		/* no more options */
		optind++;
		return EOF;
	}
//optind預設為1,傳入引數index=0的應該是/vendor/bin/hw/wpa_supplicant,沒有解析的必要
	optopt = argv[optind][optchr];
	cp = os_(optstring, optopt);
//optstring是由main.c傳入的"b:Bc:C:D:de:f:g:G:hi:I:KLMm:No:O:p:P:qsTtuvW",這裡進行校驗,指令不能超出這個範圍。
	if (cp == NULL || optopt == ':') {
		if (argv[optind][++optchr] == '\0') {
			optchr = 1;
			optind++;
		}
		return '?';
	}

	if (cp[1] == ':') {
		/* Argument required */
		optchr = 1;
		if (argv[optind][optchr + 1]) {
			/* No space between option and argument */
			optarg = &argv[optind++][optchr + 1];
		} else if (++optind >= argc) {
			/* option requires an argument */
			return '?';
		} else {
			/* Argument in the next argv */
			optarg = argv[optind++];
		}
//若指令後面是:代表支援引數,則獲取對應引數指令攜帶的引數optarg,若引數是直接跟著指令的就直接返回,否則遞進下一個引數返回,同時提前檢查是否陣列越界。
	} else {
		/* No argument */
		if (argv[optind][++optchr] == '\0') {
			optchr = 1;
			optind++;
		}
		optarg = NULL;
	}
//若後面不是:的,說明是不帶引數的,引數置為NULL。比如
//		case 'B':
//			params.daemonize++;
//			break;

	return *cp;
}
#endif /* CONFIG_ANSI_C_EXTRA */

 

3.總結

主要學習了下wpa_s的初始化引數的配置以及解析,具體功能還未深入瞭解,待續。