android添加wifi热点管理黑白名单

        本文旨在为android wifi热点添加黑白名单管理机制,提供针对应用程序的相关接口,可以通过用户界面拉黑连到AP的终端或洗白设备终端。

        软件环境:Android4.4.3

        硬件平台:Marvell


        我们的设备端是效仿google原生的便携式热点添加了第二套热点,即我们的设备是双SSID。这样的话我们的设备是用来支持两种AP的连接模式,google原生的作为AP1,当启动此热点的时候,外围终端设备不需要输入密码即可连接;当开启我们添加的AP2的时候,是走热点名和密码的验证形式。然而添加AP2不在本文所要添加功能之列,遂针对本文提到的黑白名单,我们只做在原生AP上的分析说明。


        不在赘述,上代码:

第一部分,是framework部分的修改:

1,提供应用程序获取连接到当前热点的设备终端列表接口

 --- a/services/java/com/android/server/wifi/WifiApService.java
+++ b/services/java/com/android/server/wifi/WifiApService.java
@@ -78,6 +78,10 @@ import com.android.internal.app.IBatteryStats;
 import com.android.internal.telephony.TelephonyIntents;
 import com.android.internal.util.AsyncChannel;
 import com.android.server.am.BatteryStatsService;
+
+import android.net.wifi.p2p.WifiP2pDevice;
+import android.net.wifi.p2p.WifiP2pDeviceList;
+

 import static com.android.server.wifi.WifiApController.CMD_AIRPLANE_TOGGLED;
 import static com.android.server.wifi.WifiApController.CMD_BATTERY_CHANGED;
 import static com.android.server.wifi.WifiApController.CMD_EMERGENCY_MODE_CHANGED;
@@ -1044,13 +1048,21 @@ public final class WifiApService extends IWifiApManager.Stub {
     }
 
     /**
-     * see {@link android.net.wifi.WifiApManager#addToBlacklist}
+     * see {@link android.net.wifi.WifiApManager#modifyBlacklist}
      *
      */
-    public void addToBlacklist(String bssid) {
+    public void modifyBlacklist(String bssid, int option) {
         enforceChangePermission();
+        mWifiStateMachine.modifyBlacklist(bssid, option);
+    }

 
-        mWifiStateMachine.addToBlacklist(bssid);
+    /**
+     * see {@link android.net.wifi.WifiApManager#getApDeviceList}
+     *
+     */
+    public WifiP2pDeviceList getApDeviceList() {
+        enforceChangePermission();
+        return mWifiStateMachine.getApDeviceList();


2,修改wifiapmanager接口语言部分,

--- a/wifi/java/android/net/wifi/IWifiApManager.aidl
+++ b/wifi/java/android/net/wifi/IWifiApManager.aidl
@@ -27,6 +27,10 @@ import android.net.DhcpInfo;
 import android.os.Messenger;
 import android.os.WorkSource;
 
+
+import android.net.wifi.p2p.WifiP2pDevice;
+import android.net.wifi.p2p.WifiP2pDeviceList;
+

 /**
  * Interface that allows controlling and querying Wi-Fi connectivity.
  *
@@ -44,6 +48,8 @@ interface IWifiApManager
 
     boolean disableNetwork(int netId);
 
+    WifiP2pDeviceList getApDeviceList();
+
     boolean pingSupplicant();
 
     void startScan(in WorkSource ws);
@@ -104,7 +110,7 @@ interface IWifiApManager
 
     void stopWifi();
 
-    void addToBlacklist(String bssid);
+    void modifyBlacklist(String bssid, int option);


3,修改WifiApManager,添加相关接口,

--- a/wifi/java/android/net/wifi/WifiApManager.java
+++ b/wifi/java/android/net/wifi/WifiApManager.java
@@ -41,6 +41,9 @@ import com.android.internal.util.AsyncChannel;
 import com.android.internal.util.Protocol;
 
 import java.util.List;
+import android.net.wifi.p2p.WifiP2pDevice;
+import android.net.wifi.p2p.WifiP2pDeviceList;
+

 
 /**
  * This class provides the primary API for managing all aspects of Wi-Fi
@@ -1235,16 +1238,22 @@ public class WifiApManager {
     }
 
     /**
-     * Add a bssid to the supplicant blacklist
+     * Add , deltet a bssid to the supplicant blacklist
      *
      * This API is used by WifiWatchdogService
+        *
+        * bssid: a mac address
+        *
+        * option: 0 : add a bssid to the blacklist
+        *         1 : delete a bssid from balcklist
+        *         2 : clear blacklist

      *
      * @return {@code true} if the operation succeeds else {@code false}
-     * @hide
+     *
      */
-    public boolean addToBlacklist(String bssid) {
+    public boolean modifyBlacklist(String bssid, int option) {
         try {
-            mService.addToBlacklist(bssid);
+            mService.modifyBlacklist(bssid, option);
             return true;
         } catch (RemoteException e) {
             return false;
@@ -1252,6 +1261,21 @@ public class WifiApManager {
     }
 
     /**
+     * get device list to connected the ap
+     *
+     * @return {@code result} if the operation succeeds else {@code null}
+     *
+     **/
+    public WifiP2pDeviceList getApDeviceList() {
+        try {
+            return mService.getApDeviceList();
+        } catch (RemoteException e) {
+            return null;
+        }
+
+    }
+
+    /**

      * Clear the supplicant blacklist
      *
      * This API is used by WifiWatchdogService


4,修改WifiApStateMachine,是上层应用通过wifiapservice实现相应功能接口的实体函数实现:

--- a/wifi/java/android/net/wifi/WifiApStateMachine.java
+++ b/wifi/java/android/net/wifi/WifiApStateMachine.java
@@ -452,6 +452,11 @@ public class WifiApStateMachine extends StateMachine {
     private static final int SUCCESS = 1;
     private static final int FAILURE = -1;
 
+    public static final int ADD_BLACKLIST                  = 0;
+    public static final int DELETE_BLACKLIST               = 1;
+    public static final int CLEAR_BLACKLIST                = 2;
+
+

     /**
      * The maximum number of times we will retry a connection to an access point
      * for which we have failed in acquiring an IP address from DHCP. A value of
@@ -1562,10 +1567,16 @@ public class WifiApStateMachine extends StateMachine {
      *
      * @param bssid BSSID of the network
      */
-    public void addToBlacklist(String bssid) {
-        sendMessage(CMD_BLACKLIST_NETWORK, bssid);

+    public void modifyBlacklist(String bssid, int option ) {
+           if(option == ADD_BLACKLIST )
+            sendMessage(CMD_BLACKLIST_NETWORK, "add" + bssid);
+           if(option == DELETE_BLACKLIST )
+            sendMessage(CMD_BLACKLIST_NETWORK, "delete" + bssid);
+           if(option == CLEAR_BLACKLIST )
+            sendMessage(CMD_BLACKLIST_NETWORK, "clear" + bssid);
     }
 
     /**
      * Clear the blacklist list
      *
@@ -1574,6 +1585,10 @@ public class WifiApStateMachine extends StateMachine {
         sendMessage(CMD_CLEAR_BLACKLIST);
     }
 
+    public WifiP2pDeviceList getApDeviceList() {
+        return mPeers;
+    }
+

     public void enableRssiPolling(boolean enabled) {
        sendMessage(CMD_ENABLE_RSSI_POLL, enabled ? 1 : 0, 0);
     }
@@ -4567,6 +4582,9 @@ public class WifiApStateMachine extends StateMachine {
                         sendWifiApClientChangedBroadcast();
                     }
                     break;
+                case CMD_BLACKLIST_NETWORK:
+                    mWifiNative.modifyApBlacklist((String)message.obj);
+                    break;

                 default:
                     return NOT_HANDLED;
             }

通过代码我们发现,这里调用了WifiNative类的相关方法,接下看看此类当中的实现。


5,WifiNative的实现:

--- a/wifi/java/android/net/wifi/WifiNative.java
+++ b/wifi/java/android/net/wifi/WifiNative.java
@@ -666,6 +666,15 @@ public class WifiNative {
         return doBooleanCommand("BLACKLIST " + bssid);
     }
 
+    public boolean modifyApBlacklist(String mac) {
+        if (TextUtils.isEmpty(mac)) return false;
+            return doApBooleanCommand("APBLACKLIST " + mac);
+    }

     public boolean clearBlacklist() {
         return doBooleanCommand("BLACKLIST clear");
     }


6,获取设备连接的列表方法:

--- a/wifi/java/android/net/wifi/p2p/WifiP2pDeviceList.java
+++ b/wifi/java/android/net/wifi/p2p/WifiP2pDeviceList.java
@@ -40,6 +40,10 @@ public class WifiP2pDeviceList implements Parcelable {
     public WifiP2pDeviceList() {
     }
 
+    public HashMap getDevices (){
+        return mDevices;
+    }
+

     /** copy constructor */
     public WifiP2pDeviceList(WifiP2pDeviceList source) {
         if (source != null) {


        应用程序可以通过getDevices()获取设备连接的列表,通过modifyBlacklist来添加或移除设备黑名单。至此framework部分改动大功告成。那么framework下发操作MSG是在哪一层实现的呢?毫无疑问,wpa_supplicant层,后边开始这部分修改分析。


第二部分,wap_supplicant层的修改。

--- a/hostapd/Android.mk
+++ b/hostapd/Android.mk
@@ -82,6 +82,8 @@ endif
 OBJS = main.c
 OBJS += config_file.c
 
+OBJS += src/ap/hostap_blacklist.c
+

 OBJS += src/ap/hostapd.c
 OBJS += src/ap/wpa_auth_glue.c
 OBJS += src/ap/drv_callbacks.c
diff --git a/hostapd/ctrl_iface.c b/hostapd/ctrl_iface.c
index eabfda3..d670794 100644
--- a/hostapd/ctrl_iface.c
+++ b/hostapd/ctrl_iface.c
@@ -34,6 +34,8 @@
 #include "wps/wps.h"
 #include "config_file.h"
 #include "ctrl_iface.h"
+#include "src/ap/hostap_blacklist.h"
+#include "src/utils/common.h"

 
 
 struct wpa_ctrl_dst {
@@ -505,6 +507,74 @@ static const char * pbc_status_str(enum pbc_status status)
        }
 }
 

//以下为wpa层从名单列表中删除相关SSID的接口函数。
+static int hostapd_ctrl_iface_blacklist(struct hostapd_data *hapd_s,
+                                              char *cmd, char *buf,
+                                              size_t buflen)
+{
+       u8 bssid[ETH_ALEN];
+       struct hostap_blacklist *e;
+       char *pos, *end, *mac;
+       int ret;
+
+       /* cmd: "BLACKLIST []" */
+       if (*cmd == '\0') {
+               pos = buf;
+               end = buf + buflen;
+               e = hapd_s->blacklist;
+               while (e) {
+                       ret = os_snprintf(pos, end - pos, MACSTR "\n",
+                                         MAC2STR(e->bssid));
+                       if (ret < 0 || ret >= end - pos)
+                               return pos - buf;
+                       pos += ret;
+                       e = e->next;
+               }
+               return pos - buf;
+       }
+
+       cmd++;
+       if (os_strncmp(cmd, "clear", 5) == 0) {
+               wpa_printf(MSG_DEBUG, "clear blacklist\n");
+               hostap_blacklist_clear(hapd_s);
+               os_memcpy(buf, "OK\n", 3);
+               return 3;
+       } else if (os_strncmp(cmd, "delete", 6) == 0) {
+               mac = cmd + 6;
+               wpa_printf(MSG_DEBUG, "delete mac: %s\n", mac);
+           if (hwaddr_aton(mac, bssid)) {
+                       wpa_printf(MSG_DEBUG, "CTRL_IFACE: delete invalid BSSID '%s'", mac);
+                       return -1;
+               }
+               hostap_blacklist_del(hapd_s, bssid);
+               os_memcpy(buf, "OK\n", 3);
+               return 3;
+       } else if (os_strncmp(cmd, "add", 3) == 0) {
+
+               mac = cmd + 3;
+               wpa_printf(MSG_DEBUG, "add mac: %s\n", mac);
+               if (hostapd_ctrl_iface_disassociate(hapd_s, mac)){
+                       wpa_printf(MSG_ERROR, "hostapd_ctrl_iface_disassociate\n");
+                       return -1;
+               }
+
+               if (hwaddr_aton(mac, bssid)) {
+                       wpa_printf(MSG_DEBUG, "CTRL_IFACE: invalid BSSID '%s'", mac);
+                       return -1;
+               }
+
+               /*
+               * Add the BSSID twice, so its count will be 2, causing it to be
+               * skipped when processing scan results.
+               */
+               ret = hostap_blacklist_add(hapd_s, bssid);
+               if (ret < 0)
+                       return -1;
+               os_memcpy(buf, "OK\n", 3);
+               return 3;
+       } else {
+               return -1;
+       }
+}

 
 static int hostapd_ctrl_iface_wps_get_status(struct hostapd_data *hapd,
                                             char *buf, size_t buflen)
@@ -1212,6 +1282,12 @@ static void hostapd_ctrl_iface_receive(int sock, void *eloop_ctx,
        } else if (os_strncmp(buf, "LOG_LEVEL", 9) == 0) {
                reply_len = hostapd_ctrl_iface_log_level(
                        hapd, buf + 9, reply, reply_size);
+       } else if (os_strncmp(buf, "IFNAME=uap1 AP2BLACKLIST", 24) == 0) {
+        reply_len = hostapd_ctrl_iface_blacklist(hapd, buf + 24, reply, reply_size);
+
+       } else if (os_strncmp(buf, "IFNAME=uap0 APBLACKLIST", 23) == 0) {
+        reply_len = hostapd_ctrl_iface_blacklist(hapd, buf + 23, reply, reply_size);
+

        } else {
                os_memcpy(reply, "UNKNOWN COMMAND\n", 16);
                reply_len = 16;
diff --git a/src/ap/drv_callbacks.c b/src/ap/drv_callbacks.c
index d6bc98d..0209569 100644
--- a/src/ap/drv_callbacks.c
+++ b/src/ap/drv_callbacks.c
@@ -29,6 +29,7 @@
 #include "ap_drv_ops.h"
 #include "ap_config.h"
 #include "hw_features.h"
+#include "hostap_blacklist.h"
 
 
 int hostapd_notif_assoc(struct hostapd_data *hapd, const u8 *addr,
@@ -96,12 +97,20 @@ int hostapd_notif_assoc(struct hostapd_data *hapd, const u8 *addr,
                sta->timeout_next = STA_NULLFUNC;
        } else {
                sta = ap_sta_add(hapd, addr);

                if (sta == NULL) {
                        hostapd_drv_sta_disassoc(hapd, addr,
                                                 WLAN_REASON_DISASSOC_AP_BUSY);
                        return -1;
                }
+
+               if ( NULL != hostap_blacklist_get(hapd, addr)) {
+                       hostapd_drv_sta_disassoc(hapd, addr,
+                                                WLAN_REASON_PREV_AUTH_NOT_VALID);
+                       return -1;
+               }
        }
+

        sta->flags &= ~(WLAN_STA_WPS | WLAN_STA_MAYBE_WPS | WLAN_STA_WPS2);
 
 #ifdef CONFIG_P2P
diff --git a/src/ap/hostap_blacklist.c b/src/ap/hostap_blacklist.c
new file mode 100644
index 0000000..3716542
--- /dev/null
+++ b/src/ap/hostap_blacklist.c
@@ -0,0 +1,141 @@
+/*
+ * hostap_supplicant - Temporary BSSID blacklist
+ * Copyright (c) 2003-2007, Jouni Malinen
+ *
+ * This software may be distributed under the terms of the BSD license.
+ * See README for more details.
+ */
+
+#include "includes.h"
+
+#include "common.h"
+#include "src/ap/hostapd.h"
+#include "hostap_blacklist.h"
+
+/**
+ * hostap_blacklist_get - Get the blacklist entry for a BSSID
+ * @hostap_s: Pointer to hostap_supplicant data
+ * @bssid: BSSID
+ * Returns: Matching blacklist entry for the BSSID or %NULL if not found
+ */

//匹配要操作的SSID是否已经在黑名单中,已经有返回入口,没有则返回空。
+struct hostap_blacklist * hostap_blacklist_get(struct hostapd_data *hostap_s,
+                                        const u8 *bssid)
+{
+       struct hostap_blacklist *e;
+
+       if (hostap_s == NULL || bssid == NULL)
+               return NULL;
+
+       e = hostap_s->blacklist;
+       while (e) {
+               if (os_memcmp(e->bssid, bssid, ETH_ALEN) == 0)
+                       return e;
+               e = e->next;
+       }
+
+       return NULL;
+}
+
+
+/**
+ * hostap_blacklist_add - Add an BSSID to the blacklist
+ * @hostap_s: Pointer to hostap_supplicant data
+ * @bssid: BSSID to be added to the blacklist
+ * Returns: Current blacklist count on success, -1 on failure
+ *
+ * This function adds the specified BSSID to the blacklist or increases the
+ * blacklist count if the BSSID was already listed. It should be called when
+ * an association attempt fails either due to the selected BSS rejecting
+ * association or due to timeout.
+ *
+ * This blacklist is used to force %hostap_supplicant to go through all available
+ * BSSes before retrying to associate with an BSS that rejected or timed out
+ * association. It does not prevent the listed BSS from being used; it only
+ * changes the order in which they are tried.
+ */

//添加要拉黑的SSID至黑名单链表。
+int hostap_blacklist_add(struct hostapd_data *hostap_s, const u8 *bssid)
+{
+       struct hostap_blacklist *e;
+
+       if (hostap_s == NULL || bssid == NULL)
+               return -1;
+
+       e = hostap_blacklist_get(hostap_s, bssid);
+       if (e) {
+               e->count++;
+               wpa_printf(MSG_DEBUG, "BSSID " MACSTR " blacklist count "
+                          "incremented to %d",
+                          MAC2STR(bssid), e->count);
+               return e->count;
+       }
+
+       e = os_zalloc(sizeof(*e));
+       if (e == NULL)
+               return -1;
+       os_memcpy(e->bssid, bssid, ETH_ALEN);
+       e->count = 1;
+       e->next = hostap_s->blacklist;
+       hostap_s->blacklist = e;
+       wpa_printf(MSG_DEBUG, "Added BSSID " MACSTR " into apblacklist",
+                  MAC2STR(e->bssid));
+
+       return e->count;
+}
+
+
+/**
+ * hostap_blacklist_del - Remove an BSSID from the blacklist
+ * @hostap_s: Pointer to hostap_supplicant data
+ * @bssid: BSSID to be removed from the blacklist
+ * Returns: 0 on success, -1 on failure
+ */

//移除黑名单
+int hostap_blacklist_del(struct hostapd_data *hostap_s, const u8 *bssid)
+{
+       struct hostap_blacklist *e, *prev = NULL;
+
+       if (hostap_s == NULL || bssid == NULL)
+               return -1;
+
+       e = hostap_s->blacklist;
+       while (e) {
+               if (os_memcmp(e->bssid, bssid, ETH_ALEN) == 0) {
+                       if (prev == NULL) {
+                               hostap_s->blacklist = e->next;
+                       } else {
+                               prev->next = e->next;
+                       }
+                       wpa_printf(MSG_DEBUG, "Removed BSSID " MACSTR " from "
+                                  "apblacklist", MAC2STR(bssid));
+                       os_free(e);
+                       return 0;
+               }
+               prev = e;
+               e = e->next;
+       }
+       return -1;
+}
+
+
+/**
+ * hostap_blacklist_clear - Clear the blacklist of all entries
+ * @hostap_s: Pointer to hostap_supplicant data
+ */

//一次性清除黑名单所有设备。
+void hostap_blacklist_clear(struct hostapd_data *hostap_s)
+{
+       struct hostap_blacklist *e, *prev;
+       int max_count = 0;
+
+       e = hostap_s->blacklist;
+       hostap_s->blacklist = NULL;
+       while (e) {
+               if (e->count > max_count)
+                       max_count = e->count;
+               prev = e;
+               e = e->next;
+               wpa_printf(MSG_DEBUG, "Removed BSSID " MACSTR " from "
+                          "apblacklist (clear)", MAC2STR(prev->bssid));
+               os_free(prev);
+       }
+
+       //hostap_s->extra_blacklist_count += max_count;
+}

//最后是一些相关的数据结构的定义以及相关makefile的修改。
diff --git a/src/ap/hostap_blacklist.h b/src/ap/hostap_blacklist.h
new file mode 100644
index 0000000..aac26bd
--- /dev/null
+++ b/src/ap/hostap_blacklist.h
@@ -0,0 +1,24 @@
+/*
+ * hostap_supplicant - Temporary BSSID blacklist
+ * Copyright (c) 2003-2007, Jouni Malinen
+ *
+ * This software may be distributed under the terms of the BSD license.
+ * See README for more details.
+ */
+
+#ifndef AP_BLACKLIST_H
+#define AP_BLACKLIST_H
+
+struct hostap_blacklist {
+       struct hostap_blacklist *next;
+       u8 bssid[ETH_ALEN];
+       int count;
+};
+
+struct hostap_blacklist * hostap_blacklist_get(struct hostapd_data *hostap_s,
+                                        const u8 *bssid);
+int hostap_blacklist_add(struct hostapd_data *hostap_s, const u8 *bssid);
+int hostap_blacklist_del(struct hostapd_data *hostap_s, const u8 *bssid);
+void hostap_blacklist_clear(struct hostapd_data *hostap_s);
+
+#endif /* BLACKLIST_H */

index 0000000..aac26bd
--- /dev/null
+++ b/src/ap/hostap_blacklist.h
@@ -0,0 +1,24 @@
+/*
+ * hostap_supplicant - Temporary BSSID blacklist
+ * Copyright (c) 2003-2007, Jouni Malinen
+ *
+ * This software may be distributed under the terms of the BSD license.
+ * See README for more details.
+ */
+
+#ifndef AP_BLACKLIST_H
+#define AP_BLACKLIST_H
+
+struct hostap_blacklist {
+       struct hostap_blacklist *next;
+       u8 bssid[ETH_ALEN];
+       int count;
+};
+
+struct hostap_blacklist * hostap_blacklist_get(struct hostapd_data *hostap_s,
+                                        const u8 *bssid);
+int hostap_blacklist_add(struct hostapd_data *hostap_s, const u8 *bssid);
+int hostap_blacklist_del(struct hostapd_data *hostap_s, const u8 *bssid);
+void hostap_blacklist_clear(struct hostapd_data *hostap_s);
+
+#endif /* BLACKLIST_H */

diff --git a/src/ap/hostapd.h b/src/ap/hostapd.h
index dbf1b52..59ad0ae 100644
--- a/src/ap/hostapd.h
+++ b/src/ap/hostapd.h
@@ -156,6 +156,11 @@ struct hostapd_data {
        u8 time_update_counter;
        struct wpabuf *time_adv;
 
+
+       struct hostap_blacklist *blacklist;
+
+       int extra_blacklist_count;
+

 #ifdef CONFIG_FULL_DYNAMIC_VLAN
        struct full_dynamic_vlan *full_dynamic_vlan;
 #endif /* CONFIG_FULL_DYNAMIC_VLAN */
diff --git a/wpa_supplicant/Android.mk b/wpa_supplicant/Android.mk
index 96f4b80..262fb4e 100644
--- a/wpa_supplicant/Android.mk
+++ b/wpa_supplicant/Android.mk
@@ -782,6 +782,7 @@ OBJS += src/eapol_auth/eapol_auth_sm.c
 OBJS += src/ap/ieee802_11_auth.c
 OBJS += src/ap/ieee802_11_shared.c
 OBJS += src/ap/drv_callbacks.c
+OBJS += src/ap/hostap_blacklist.c
 OBJS += src/ap/ap_drv_ops.c
 OBJS += src/ap/beacon.c
 OBJS += src/ap/eap_user_db.c


        综上两部分,我们得知,此功能的修改权杖两个层面,一个是framework层面,该层面在相应的service和manager中添加开放给应用程序的接口,这个接口在往下操作是通过给wpa层发送命令字,通过socket实现;其二是wpa层,这里的改动才是最实质的通过解析framework层接口下发的命令字串添加或删除链表的设备数据。


     后续根据需求,可能会写一篇关于双SSID的文章,感兴趣的同仁敬请期待!O(∩_∩)O哈哈哈~   













你可能感兴趣的:(Android)