(九十五)Android O wpa_supplicant.conf配置文件探究
发布日期:2021-06-30 15:25:22 浏览次数:2 分类:技术文章

本文共 10437 字,大约阅读时间需要 34 分钟。

参考:

 

1.wpa_supplicant.conf简介

首先说下源码位置,与wpa_supplicant.conf相关的配置文件、脚本如下红框标注处。

其中wpa_supplicant.conf 不是手机中的wpa_supplicant.conf,打开看一下是wpa_supplicant.conf的配置说明。

##### Example wpa_supplicant configuration file ################################# This file describes configuration file format and lists all available option.# Please also take a look at simpler configuration examples in 'examples'# subdirectory.## Empty lines and lines starting with # are ignored# NOTE! This file may contain password information and should probably be made# readable only by root user on multiuser systems.# Note: All file paths in this configuration file should use full (absolute,# not relative to working directory) path in order to allow working directory# to be changed. This can happen if wpa_supplicant is run in the background.# Whether to allow wpa_supplicant to update (overwrite) configuration## This option can be used to allow wpa_supplicant to overwrite configuration# file whenever configuration is changed (e.g., new network block is added with# wpa_cli or wpa_gui, or a password is changed). This is required for# wpa_cli/wpa_gui to be able to store the configuration changes permanently.# Please note that overwriting configuration file will remove the comments from# it.#update_config=1

简单翻译一下,wpa_supplicant.conf是wpa_supplicant.conf配置文件的一个例子,这个文件描述了配置文件格式以及列举了所有的可选选项。请看一下在examples文件夹下的例子。

请注意文件有可能包含密码信息,所以尽可能地在多用户系统中将这个文件设为root用户只读。

注意,所有这个文件中的路径请用绝对路径,不用用相对路径,只是为了允许工作目录可以改变。在supplicant运行在后台时有可能会发生这个事情。

 

那顺势看下wpa_supplicant.conf在example的例子吧:

是指这个么

 

2. 探讨wpa_supplicant.conf由来

2.1 wpa_supplicant_conf.mk

# Include this makefile to generate your hardware specific wpa_supplicant.conf# Requires: WIFI_DRIVER_SOCKET_IFACELOCAL_PATH := $(call my-dir)########################include $(CLEAR_VARS)LOCAL_MODULE := wpa_supplicant.confLOCAL_MODULE_CLASS := ETC LOCAL_MODULE_TAGS := optionalLOCAL_MODULE_PATH := $(TARGET_OUT_VENDOR)/etc/wifiinclude $(BUILD_SYSTEM)/base_rules.mkWPA_SUPPLICANT_CONF_TEMPLATE := $(LOCAL_PATH)/wpa_supplicant_template.confWPA_SUPPLICANT_CONF_SCRIPT := $(LOCAL_PATH)/wpa_supplicant_conf.sh$(LOCAL_BUILT_MODULE): PRIVATE_WIFI_DRIVER_SOCKET_IFACE := $(WIFI_DRIVER_SOCKET_IFACE)$(LOCAL_BUILT_MODULE): PRIVATE_WPA_SUPPLICANT_CONF_TEMPLATE := $(WPA_SUPPLICANT_CONF_TEMPLATE)$(LOCAL_BUILT_MODULE): PRIVATE_WPA_SUPPLICANT_CONF_SCRIPT := $(WPA_SUPPLICANT_CONF_SCRIPT)$(LOCAL_BUILT_MODULE) : $(WPA_SUPPLICANT_CONF_TEMPLATE) $(WPA_SUPPLICANT_CONF_SCRIPT)    @echo Target wpa_supplicant.conf: $@    @mkdir -p $(dir $@)    $(hide) WIFI_DRIVER_SOCKET_IFACE="$(PRIVATE_WIFI_DRIVER_SOCKET_IFACE)" \        bash $(PRIVATE_WPA_SUPPLICANT_CONF_SCRIPT) $(PRIVATE_WPA_SUPPLICANT_CONF_TEMPLATE) > $@########################

先看一下mk文件,模块名直接就是wpa_supplicant.conf,试着make一下

ninja: no work to do.ninja: no work to do.wildcard(out/target/product/generic_x86_64/clean_steps.mk) was changed, regenerating...$(shell uname -rsm) was changed, regenerating...[526/824] including system/sepolicy/Android.mk ...system/sepolicy/Android.mk:79: warning: BOARD_SEPOLICY_VERS not specified, assuming current platform version[824/824] including tools/tradefederation/core/Android.mk ...[ 93% 14/15] glob tools/metalava/src/main/java/**/*.ktninja: error: unknown target 'wpa_supplicant.conf'10:28:42 ninja failed with: exit status 1#### failed to build some targets (02:08 (mm:ss)) ####

emmm,本地编译有点问题,编译其他的是可以的,待续

还是回头来看下mk文件,其中用到了两个其他的文件,分别是wpa_supplicant_template.conf 和 wpa_supplicant_conf.sh

脚本+文件最后生成在$(TARGET_OUT_VENDOR)/etc/wifi目录下的wpa_supplicant.conf

LOCAL_MODULE := wpa_supplicant.confLOCAL_MODULE_CLASS := ETC LOCAL_MODULE_TAGS := optionalLOCAL_MODULE_PATH := $(TARGET_OUT_VENDOR)/etc/wifi

可以看手机的vendor/etc/wifi下看到该文件

另外在/data/misc/wifi下也有该文件

 

2.2 wpa_supplicant_template.conf

jiatai@jiatai:~/expand/aosp/aosp/external/wpa_supplicant_8/wpa_supplicant$ cat wpa_supplicant_template.conf##### wpa_supplicant configuration file template #####update_config=1eapol_version=1ap_scan=1fast_reauth=1pmf=1p2p_add_cli_chan=1

 

2.3 wpa_supplicant_conf.sh

jiatai@jiatai:~/expand/aosp/aosp/external/wpa_supplicant_8/wpa_supplicant$ cat wpa_supplicant_conf.sh#!/bin/bash## Copyright (C) 2010 The Android Open Source Project## This software may be distributed under the terms of the BSD license.# See README for more details.## Generate a wpa_supplicant.conf from the template.# $1: the template file nameif [ -n "$WIFI_DRIVER_SOCKET_IFACE" ]then  sed -e 's/#.*$//' -e 's/[ \t]*$//' -e '/^$/d' < $1 | sed -e "s/wlan0/$WIFI_DRIVER_SOCKET_IFACE/"else  sed -e 's/#.*$//' -e 's/[ \t]*$//' -e '/^$/d' < $1fi

学习一下sed命令的功能。

sed作用:主要用于替换指定的字符;查找或替换指定字符串时,必须把字符串用//来注释下,比如root 必须是/root/;sed 只要不适用-i参数,一般都是在输出终端上显示而已,无法更改源文件;参数-e: --expression,多重编辑;参数-n:不带-n则列出文件所有内容,加上-n只列出结果sed特殊处理的那一行;参数-i:直接修改读取的内容文件,而不是输出到终端;功能s:替换、取代;功能d:删除;功能a:新增;

如上命令应该是去除注释、去除空格、去除空行,替换wlan0为WIFI_DRIVER_SOCKET_IFACE

执行下看下效果

自己写个例子试下

空格、tab键、空格+tab键的单独行,末尾不要加字符也试了下,会被删除。

 

2.4 supplicant启动流程

回头在看下 启动流程中与wpa_supplicant_conf的关系。

bool SupplicantManager::StartSupplicant() {  char supp_status[PROPERTY_VALUE_MAX] = {'\0'};  int count = 200; /* wait at most 20 seconds for completion */  const prop_info* pi;  unsigned serial = 0;  /* Check whether already running */  if (property_get(kSupplicantInitProperty, supp_status, NULL) &&      strcmp(supp_status, "running") == 0) {    return true;  }  /* Before starting the daemon, make sure its config file exists */  if (ensure_config_file_exists(kSupplicantConfigFile) < 0) {    LOG(ERROR) << "Wi-Fi will not be enabled";    return false;  }  /*   * Some devices have another configuration file for the p2p interface.   * However, not all devices have this, and we'll let it slide if it   * is missing.  For devices that do expect this file to exist,   * supplicant will refuse to start and emit a good error message.   * No need to check for it here.   */  (void)ensure_config_file_exists(kP2pConfigFile);  /*   * Get a reference to the status property, so we can distinguish   * the case where it goes stopped => running => stopped (i.e.,   * it start up, but fails right away) from the case in which   * it starts in the stopped state and never manages to start   * running at all.   */  pi = __system_property_find(kSupplicantInitProperty);  if (pi != NULL) {    serial = __system_property_serial(pi);  }  property_set("ctl.start", kSupplicantServiceName);  sched_yield();  while (count-- > 0) {    if (pi == NULL) {      pi = __system_property_find(kSupplicantInitProperty);    }    if (pi != NULL) {      /*       * property serial updated means that init process is scheduled       * after we sched_yield, further property status checking is based on this       */      if (__system_property_serial(pi) != serial) {        __system_property_read(pi, NULL, supp_status);        if (strcmp(supp_status, "running") == 0) {          return true;        } else if (strcmp(supp_status, "stopped") == 0) {          return false;        }      }    }    usleep(100000);  }  return false;}

关注下如下代码

/* Before starting the daemon, make sure its config file exists */  if (ensure_config_file_exists(kSupplicantConfigFile) < 0) {    LOG(ERROR) << "Wi-Fi will not be enabled";    return false;  }

看下对应常量声明

const char kSupplicantInitProperty[] = "init.svc.wpa_supplicant";const char kSupplicantConfigTemplatePath[] =    "/etc/wifi/wpa_supplicant.conf";const char kSupplicantConfigFile[] = "/data/misc/wifi/wpa_supplicant.conf";const char kP2pConfigFile[] = "/data/misc/wifi/p2p_supplicant.conf";const char kSupplicantServiceName[] = "wpa_supplicant";constexpr mode_t kConfigFileMode = S_IRUSR | S_IWUSR | S_IRGRP | S_IWGRP;

如下是确保配置文件存在的逻辑代码

  1. 尝试对/data/misc/wifi/wpa_supplicant.conf其进行读写,如果已经有该文件则返回,不能读写的话尝试改写读写权限。
  2. 先看下/system/etc/wifi有没有配置文件,没有的话再看下vendor/etc/wifi
  3. 打开/data/misc/wifi/wpa_supplicant.conf
  4. 将etc/wifi下的配置文件拷贝到/data/misc/wifi/wpa_supplicant.conf
  5. 修改权限用户组
int ensure_config_file_exists(const char* config_file) {  char buf[2048];  int srcfd, destfd;  int nread;  int ret;  std::string templatePath;  ret = access(config_file, R_OK | W_OK);  if ((ret == 0) || (errno == EACCES)) {    if ((ret != 0) && (chmod(config_file, kConfigFileMode) != 0)) {      LOG(ERROR) << "Cannot set RW to \"" << config_file << "\": "                 << strerror(errno);      return false;    }    return true;  } else if (errno != ENOENT) {    LOG(ERROR) << "Cannot access \"" << config_file << "\": "               << strerror(errno);    return false;  }  std::string configPathSystem =      std::string("/system") + std::string(kSupplicantConfigTemplatePath);  std::string configPathVendor =      std::string("/vendor") + std::string(kSupplicantConfigTemplatePath);  srcfd = TEMP_FAILURE_RETRY(open(configPathSystem.c_str(), O_RDONLY));  templatePath = configPathSystem;  if (srcfd < 0) {    int errnoSystem = errno;    srcfd = TEMP_FAILURE_RETRY(open(configPathVendor.c_str(), O_RDONLY));    templatePath = configPathVendor;    if (srcfd < 0) {      int errnoVendor = errno;      LOG(ERROR) << "Cannot open \"" << configPathSystem << "\": "                 << strerror(errnoSystem);      LOG(ERROR) << "Cannot open \"" << configPathVendor << "\": "                 << strerror(errnoVendor);      return false;    }  }  destfd = TEMP_FAILURE_RETRY(open(config_file,                                   O_CREAT | O_RDWR,                                   kConfigFileMode));  if (destfd < 0) {    close(srcfd);    LOG(ERROR) << "Cannot create \"" << config_file << "\": "               << strerror(errno);    return false;  }  while ((nread = TEMP_FAILURE_RETRY(read(srcfd, buf, sizeof(buf)))) != 0) {    if (nread < 0) {      LOG(ERROR) << "Error reading \"" << templatePath                 << "\": " << strerror(errno);      close(srcfd);      close(destfd);      unlink(config_file);      return false;    }    TEMP_FAILURE_RETRY(write(destfd, buf, nread));  }  close(destfd);  close(srcfd);  /* chmod is needed because open() didn't set permisions properly */  if (chmod(config_file, kConfigFileMode) < 0) {    LOG(ERROR) << "Error changing permissions of " << config_file               << " to 0660: " << strerror(errno);    unlink(config_file);    return false;  }  return true;}

到这里也梳理完了如下两个配置文件的由来。

  1. /data/misc/wifi/wpa_supplicant.conf
  2. /vendor/etc/wifi/wpa_supplicant.conf

 

3. 总结

/vendor/etc/wifi/wpa_supplicant.conf 这个配置文件是由wpa_supplicant下的wpa_supplicant_template.conf作简单处理生成的。

/data/misc/wifi/wpa_supplicant.conf是在supplicant第一次启动的时候由/vendor/etc/wifi/wpa_supplicant.conf 拷贝过来的。

转载地址:https://jiatai.blog.csdn.net/article/details/82820314 如侵犯您的版权,请留言回复原文章的地址,我们会给您删除此文章,给您带来不便请您谅解!

上一篇:(九十六)Android O activity standard mode 探究
下一篇:(九十四) Android O 连接WiFi AP流程梳理续——连接网络

发表评论

最新留言

关注你微信了!
[***.104.42.241]2024年04月24日 21时05分08秒