【转】Android软件限制AP的最大连接数

最近有个需要是要做成AP的最大连接数用户可配置,此处不讨论硬件限制,仅仅从软件方面去对Android源码做修改。

让/data/misc/wifi/hostapd.conf里面带上max_num_sta参数即可达到目的,例如要限制成10个,则max_num_sta=10。

Android原生代码不包含此参数,/data/misc/wifi/hostapd.conf会在AP开启的时候由/system/bin/netd通过softap set参数设置下去,查看netd相关源码,可以看到最后的配置文件是由system/netd/SoftapController.cpp中的SoftapController::setSoftap()函数根据java层传过来的参数设置的。

最简单的方式是使用原有的argv[5],也就是Channel值,修改成包含Channel和max_num_sta两个值的参数,上层传参数时把这两个值合成,SoftapController::setSoftap()函数再把值解析出来即可,修改如下:

/*

  • Arguments:

  • argv[2] - wlan interface

  • argv[3] - SSID

  • argv[4] - Broadcast/Hidden

  • argv[5] - Channel

  • argv[6] - Security

  • argv[7] - Key
    */
    int SoftapController::setSoftap(int argc, char *argv[]) {
    int hidden = 0;
    int channel = AP_CHANNEL_DEFAULT;
    int max_num_sta = 0;//add for sta limit 20180921

    if (argc < 5) {
    ALOGE("Softap set is missing arguments. Please use:");
    ALOGE("softap <wlan iface> <SSID> <hidden/broadcast> <channel> <wpa2?-psk|open> <passphrase>");
    return ResponseCode::CommandSyntaxError;
    }

    if (!strcasecmp(argv[4], "hidden"))
    hidden = 1;

    if (argc >= 5) {
    channel = atoi(argv[5]);
    //start add for sta limit 20180921
    char buf[PROPERTY_VALUE_MAX] = {'\0',};
    if (property_get("persist.sys.softap.limit", buf, "0")) {
    max_num_sta = (channel >> 16) & 0xFFFF;
    channel &= 0xFFFF;
    }
    //end add for sta limit 20180921
    if (channel <= 0)
    channel = AP_CHANNEL_DEFAULT;
    }

    std::string wbuf;
    if(max_num_sta) {
    std::string wbuf_tmp(StringPrintf("interface=%s\n"
    "driver=nl80211\n"
    "ctrl_interface=/data/misc/wifi/hostapd\n"
    "ssid=%s\n"
    "channel=%d\n"
    "ieee80211n=1\n"
    "hw_mode=%c\n"
    "ignore_broadcast_ssid=%d\n"
    "wowlan_triggers=any\n"
    "max_num_sta=%d\n",
    argv[2], argv[3], channel, (channel <= 14) ? 'g' : 'a', hidden, max_num_sta));
    wbuf = wbuf_tmp;
    }
    else {
    std::string wbuf_tmp(StringPrintf("interface=%s\n"
    "driver=nl80211\n"
    "ctrl_interface=/data/misc/wifi/hostapd\n"
    "ssid=%s\n"
    "channel=%d\n"
    "ieee80211n=1\n"
    "hw_mode=%c\n"
    "ignore_broadcast_ssid=%d\n"
    "wowlan_triggers=any\n",
    argv[2], argv[3], channel, (channel <= 14) ? 'g' : 'a', hidden));
    wbuf = wbuf_tmp;
    }

    std::string fbuf;
    if (argc > 7) {
    char psk_str[2*SHA256_DIGEST_LENGTH+1];
    if (!strcmp(argv[6], "wpa-psk")) {
    generatePsk(argv[3], argv[7], psk_str);
    fbuf = StringPrintf("%swpa=3\nwpa_pairwise=TKIP CCMP\nwpa_psk=%s\n", wbuf.c_str(), psk_str);
    } else if (!strcmp(argv[6], "wpa2-psk")) {
    generatePsk(argv[3], argv[7], psk_str);
    fbuf = StringPrintf("%swpa=2\nrsn_pairwise=CCMP\nwpa_psk=%s\n", wbuf.c_str(), psk_str);
    } else if (!strcmp(argv[6], "open")) {
    fbuf = wbuf;
    }
    } else if (argc > 6) {
    if (!strcmp(argv[6], "open")) {
    fbuf = wbuf;
    }
    } else {
    fbuf = wbuf;
    }

    if (!WriteStringToFile(fbuf, HOSTAPD_CONF_FILE, 0660, AID_SYSTEM, AID_WIFI)) {
    ALOGE("Cannot write to "%s": %s", HOSTAPD_CONF_FILE, strerror(errno));
    return ResponseCode::OperationFailed;
    }
    return ResponseCode::SoftapStatusResult;
    }
    至于java层的修改则是修改WifiConfiguration类,添加一个apMaxNumSta字段,并修改WifiConfiguration相关操作函数增加对此值的处理,最后通过NetworkManagementService.startAccessPoint把值传下去,修改如下:

    @Override
    public void startAccessPoint(
    WifiConfiguration wifiConfig, String wlanIface) {
    mContext.enforceCallingOrSelfPermission(CONNECTIVITY_INTERNAL, TAG);
    try {
    if (wifiConfig == null) {
    mConnector.execute("softap", "set", wlanIface);
    } else {
    if (SystemProperties.getInt("persist.sys.softap.limit", 0) != 0 && wifiConfig.apMaxNumSta != 0) {
    int mix = (wifiConfig.apMaxNumSta << 16) | wifiConfig.apChannel ;
    //start add by gerhard.lao for sta limit 20180921
    Slog.d(TAG, "startAccessPoint apMaxNumSta " + wifiConfig.apMaxNumSta +
    "apChannel " + wifiConfig.apChannel + "mix " + mix);
    mConnector.execute("softap", "set", wlanIface, wifiConfig.SSID,
    "broadcast", Integer.toString(mix),
    getSecurityType(wifiConfig),
    new SensitiveArg(wifiConfig.preSharedKey));
    //end add by gerhard.lao for sta limit 20180921
    } else {
    mConnector.execute("softap", "set", wlanIface, wifiConfig.SSID,
    "broadcast", Integer.toString(wifiConfig.apChannel),
    getSecurityType(wifiConfig),
    new SensitiveArg(wifiConfig.preSharedKey));
    }
    }
    mConnector.execute("softap", "startap");
    } catch (NativeDaemonConnectorException e) {
    throw e.rethrowAsParcelableException();
    }
    }
    这样,上层使用的时候设置apMaxNumSta即可带到native层然后写/data/misc/wifi/hostapd.conf,最终开启AP的时候会根据此参数限制最大连接数。

或者使用更简单直接的方式:

SoftapController::setSoftap()读取persist.sys.softap.limit值然后如果是非0值就应用到配置里面:

/*

  • Arguments:

  • argv[2] - wlan interface

  • argv[3] - SSID

  • argv[4] - Broadcast/Hidden

  • argv[5] - Channel

  • argv[6] - Security

  • argv[7] - Key
    */
    int SoftapController::setSoftap(int argc, char *argv[]) {
    int hidden = 0;
    int channel = AP_CHANNEL_DEFAULT;

    if (argc < 5) {
    ALOGE("Softap set is missing arguments. Please use:");
    ALOGE("softap <wlan iface> <SSID> <hidden/broadcast> <channel> <wpa2?-psk|open> <passphrase>");
    return ResponseCode::CommandSyntaxError;
    }

    if (!strcasecmp(argv[4], "hidden"))
    hidden = 1;

    if (argc >= 5) {
    channel = atoi(argv[5]);
    if (channel <= 0)
    channel = AP_CHANNEL_DEFAULT;
    }

    //start add for sta limit 20180921
    int max_num_sta = 0;
    char buf[PROPERTY_VALUE_MAX] = {'\0',};
    if (property_get("persist.sys.softap.limit", buf, "0")) {
    max_num_sta = atoi(buf);
    if(max_num_sta != 0) {
    if(max_num_sta < 0 || max_num_sta > 255)
    max_num_sta = 0;
    }
    }
    //end add for sta limit 20180921

    std::string wbuf;
    if(max_num_sta) {
    std::string wbuf_tmp(StringPrintf("interface=%s\n"
    "driver=nl80211\n"
    "ctrl_interface=/data/misc/wifi/hostapd\n"
    "ssid=%s\n"
    "channel=%d\n"
    "ieee80211n=1\n"
    "hw_mode=%c\n"
    "ignore_broadcast_ssid=%d\n"
    "wowlan_triggers=any\n"
    "max_num_sta=%d\n",
    argv[2], argv[3], channel, (channel <= 14) ? 'g' : 'a', hidden, max_num_sta));
    wbuf = wbuf_tmp;
    }
    else {
    std::string wbuf_tmp(StringPrintf("interface=%s\n"
    "driver=nl80211\n"
    "ctrl_interface=/data/misc/wifi/hostapd\n"
    "ssid=%s\n"
    "channel=%d\n"
    "ieee80211n=1\n"
    "hw_mode=%c\n"
    "ignore_broadcast_ssid=%d\n"
    "wowlan_triggers=any\n",
    argv[2], argv[3], channel, (channel <= 14) ? 'g' : 'a', hidden));
    wbuf = wbuf_tmp;
    }

    std::string fbuf;
    if (argc > 7) {
    char psk_str[2*SHA256_DIGEST_LENGTH+1];
    if (!strcmp(argv[6], "wpa-psk")) {
    generatePsk(argv[3], argv[7], psk_str);
    fbuf = StringPrintf("%swpa=3\nwpa_pairwise=TKIP CCMP\nwpa_psk=%s\n", wbuf.c_str(), psk_str);
    } else if (!strcmp(argv[6], "wpa2-psk")) {
    generatePsk(argv[3], argv[7], psk_str);
    fbuf = StringPrintf("%swpa=2\nrsn_pairwise=CCMP\nwpa_psk=%s\n", wbuf.c_str(), psk_str);
    } else if (!strcmp(argv[6], "open")) {
    fbuf = wbuf;
    }
    } else if (argc > 6) {
    if (!strcmp(argv[6], "open")) {
    fbuf = wbuf;
    }
    } else {
    fbuf = wbuf;
    }

    if (!WriteStringToFile(fbuf, HOSTAPD_CONF_FILE, 0660, AID_SYSTEM, AID_WIFI)) {
    ALOGE("Cannot write to "%s": %s", HOSTAPD_CONF_FILE, strerror(errno));
    return ResponseCode::OperationFailed;
    }
    return ResponseCode::SoftapStatusResult;
    }
    ————————————————
    版权声明:本文为CSDN博主「觅风者」的原创文章,遵循 CC 4.0 BY-SA 版权协议,转载请附上原文出处链接及本声明。
    原文链接:https://blog.csdn.net/laoguanhua/article/details/82810386

©著作权归作者所有,转载或内容合作请联系作者
【社区内容提示】社区部分内容疑似由AI辅助生成,浏览时请结合常识与多方信息审慎甄别。
平台声明:文章内容(如有图片或视频亦包括在内)由作者上传并发布,文章内容仅代表作者本人观点,简书系信息发布平台,仅提供信息存储服务。

相关阅读更多精彩内容

友情链接更多精彩内容