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      ");
        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      ");
        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;
}

 

你可能感兴趣的:(Android)