WPS: Add Enrollee-seen event message and wpa_gui-qt4 Peers entry
authorJouni Malinen <jouni.malinen@atheros.com>
Mon, 28 Dec 2009 14:24:04 +0000 (16:24 +0200)
committerJouni Malinen <j@w1.fi>
Mon, 28 Dec 2009 14:24:04 +0000 (16:24 +0200)
This can be used to show active Enrollees in AP mode to make it
easier to provision a new device.

src/ap/wps_hostapd.c
src/common/wpa_ctrl.h
src/wps/wps.h
src/wps/wps_registrar.c
wpa_supplicant/wpa_gui-qt4/peers.cpp

index 235071b..d5145f0 100644 (file)
@@ -154,6 +154,29 @@ static void hostapd_wps_reg_success_cb(void *ctx, const u8 *mac_addr,
 }
 
 
+static void hostapd_wps_enrollee_seen_cb(void *ctx, const u8 *addr,
+                                        const u8 *uuid_e,
+                                        const u8 *pri_dev_type,
+                                        u16 config_methods,
+                                        u16 dev_password_id, u8 request_type,
+                                        const char *dev_name)
+{
+       struct hostapd_data *hapd = ctx;
+       char uuid[40];
+       char devtype[WPS_DEV_TYPE_BUFSIZE];
+       if (uuid_bin2str(uuid_e, uuid, sizeof(uuid)))
+               return;
+       if (dev_name == NULL)
+               dev_name = "";
+       wpa_msg_ctrl(hapd->msg_ctx, MSG_INFO, WPS_EVENT_ENROLLEE_SEEN MACSTR
+                    " %s %s 0x%x %u %u [%s]",
+                    MAC2STR(addr), uuid,
+                    wps_dev_type_bin2str(pri_dev_type, devtype,
+                                         sizeof(devtype)),
+                    config_methods, dev_password_id, request_type, dev_name);
+}
+
+
 static int str_starts(const char *str, const char *start)
 {
        return os_strncmp(str, start, os_strlen(start)) == 0;
@@ -596,6 +619,7 @@ int hostapd_init_wps(struct hostapd_data *hapd,
        cfg.set_ie_cb = hostapd_wps_set_ie_cb;
        cfg.pin_needed_cb = hostapd_wps_pin_needed_cb;
        cfg.reg_success_cb = hostapd_wps_reg_success_cb;
+       cfg.enrollee_seen_cb = hostapd_wps_enrollee_seen_cb;
        cfg.cb_ctx = hapd;
        cfg.skip_cred_build = conf->skip_cred_build;
        cfg.extra_cred = conf->extra_cred;
index d2cf920..25032d9 100644 (file)
@@ -73,6 +73,8 @@ extern "C" {
 /** WPS enrollment attempt timed out and was terminated */
 #define WPS_EVENT_TIMEOUT "WPS-TIMEOUT "
 
+#define WPS_EVENT_ENROLLEE_SEEN "WPS-ENROLLEE-SEEN "
+
 /* WPS ER events */
 #define WPS_EVENT_ER_AP_ADD "WPS-ER-AP-ADD "
 #define WPS_EVENT_ER_AP_REMOVE "WPS-ER-AP-REMOVE "
index 449d1cb..350a640 100644 (file)
@@ -278,6 +278,22 @@ struct wps_registrar_config {
                               u16 sel_reg_config_methods);
 
        /**
+        * enrollee_seen_cb - Callback for reporting Enrollee based on ProbeReq
+        * @ctx: Higher layer context data (cb_ctx)
+        * @addr: MAC address of the Enrollee
+        * @uuid_e: UUID of the Enrollee
+        * @pri_dev_type: Primary device type
+        * @config_methods: Config Methods
+        * @dev_password_id: Device Password ID
+        * @request_type: Request Type
+        * @dev_name: Device Name (if available)
+        */
+       void (*enrollee_seen_cb)(void *ctx, const u8 *addr, const u8 *uuid_e,
+                                const u8 *pri_dev_type, u16 config_methods,
+                                u16 dev_password_id, u8 request_type,
+                                const char *dev_name);
+
+       /**
         * cb_ctx: Higher layer context data for Registrar callbacks
         */
        void *cb_ctx;
index 07e6546..3f51190 100644 (file)
@@ -107,6 +107,10 @@ struct wps_registrar {
                               const u8 *uuid_e);
        void (*set_sel_reg_cb)(void *ctx, int sel_reg, u16 dev_passwd_id,
                               u16 sel_reg_config_methods);
+       void (*enrollee_seen_cb)(void *ctx, const u8 *addr, const u8 *uuid_e,
+                                const u8 *pri_dev_type, u16 config_methods,
+                                u16 dev_password_id, u8 request_type,
+                                const char *dev_name);
        void *cb_ctx;
 
        struct dl_list pins;
@@ -456,6 +460,7 @@ wps_registrar_init(struct wps_context *wps,
        reg->pin_needed_cb = cfg->pin_needed_cb;
        reg->reg_success_cb = cfg->reg_success_cb;
        reg->set_sel_reg_cb = cfg->set_sel_reg_cb;
+       reg->enrollee_seen_cb = cfg->enrollee_seen_cb;
        reg->cb_ctx = cfg->cb_ctx;
        reg->skip_cred_build = cfg->skip_cred_build;
        if (cfg->extra_cred) {
@@ -770,6 +775,24 @@ void wps_registrar_probe_req_rx(struct wps_registrar *reg, const u8 *addr,
                return;
        }
 
+       if (reg->enrollee_seen_cb && attr.dev_password_id && attr.uuid_e &&
+           attr.primary_dev_type && attr.request_type) {
+               char *dev_name = NULL;
+               if (attr.dev_name) {
+                       dev_name = os_zalloc(attr.dev_name_len + 1);
+                       if (dev_name) {
+                               os_memcpy(dev_name, attr.dev_name,
+                                         attr.dev_name_len);
+                       }
+               }
+               reg->enrollee_seen_cb(reg->cb_ctx, addr, attr.uuid_e,
+                                     attr.primary_dev_type,
+                                     WPA_GET_BE16(attr.config_methods),
+                                     WPA_GET_BE16(attr.dev_password_id),
+                                     *attr.request_type, dev_name);
+               os_free(dev_name);
+       }
+
        methods = WPA_GET_BE16(attr.config_methods);
        if (!(methods & WPS_CONFIG_PUSHBUTTON))
                return; /* Not PBC */
index d1439e2..195fb8d 100644 (file)
@@ -45,7 +45,8 @@ enum peer_type {
        PEER_TYPE_WPS_PIN_NEEDED,
        PEER_TYPE_WPS_ER_AP,
        PEER_TYPE_WPS_ER_AP_UNCONFIGURED,
-       PEER_TYPE_WPS_ER_ENROLLEE
+       PEER_TYPE_WPS_ER_ENROLLEE,
+       PEER_TYPE_WPS_ENROLLEE
 };
 
 
@@ -122,6 +123,9 @@ QString Peers::ItemType(int type)
        case PEER_TYPE_WPS_ER_ENROLLEE:
                title = tr("ER: WPS Enrollee");
                break;
+       case PEER_TYPE_WPS_ENROLLEE:
+               title = tr("WPS Enrollee");
+               break;
        }
        return title;
 }
@@ -148,7 +152,8 @@ void Peers::context_menu(const QPoint &pos)
                if ((type == PEER_TYPE_ASSOCIATED_STATION ||
                     type == PEER_TYPE_AP_WPS ||
                     type == PEER_TYPE_WPS_PIN_NEEDED ||
-                    type == PEER_TYPE_WPS_ER_ENROLLEE) &&
+                    type == PEER_TYPE_WPS_ER_ENROLLEE ||
+                    type == PEER_TYPE_WPS_ENROLLEE) &&
                    (config_methods == -1 || (config_methods & 0x010c))) {
                        menu->addAction(tr("Enter WPS PIN"), this,
                                        SLOT(enter_pin()));
@@ -160,7 +165,8 @@ void Peers::context_menu(const QPoint &pos)
                }
 
                if ((type == PEER_TYPE_ASSOCIATED_STATION ||
-                    type == PEER_TYPE_WPS_ER_ENROLLEE) &&
+                    type == PEER_TYPE_WPS_ER_ENROLLEE ||
+                    type == PEER_TYPE_WPS_ENROLLEE) &&
                    config_methods >= 0 && (config_methods & 0x0080)) {
                        menu->addAction(tr("Enroll (PBC)"), this,
                                        SLOT(connect_pbc()));
@@ -644,6 +650,71 @@ void Peers::event_notify(WpaMsg msg)
                remove_enrollee_uuid(items[1]);
                return;
        }
+
+       if (text.startsWith(WPS_EVENT_ENROLLEE_SEEN)) {
+               /* TODO: need to time out this somehow or remove on successful
+                * WPS run, etc. */
+               /*
+                * WPS-ENROLLEE-SEEN 02:00:00:00:01:00
+                * 572cf82f-c957-5653-9b16-b5cfb298abf1 1-0050F204-1 0x80 4 1
+                * [Wireless Client]
+                * (MAC addr, UUID-E, pri dev type, config methods,
+                * dev passwd id, request type, [dev name])
+                */
+               QStringList items = text.split(' ');
+               if (items.size() < 7)
+                       return;
+               QString addr = items[1];
+               QString uuid = items[2];
+               QString pri_dev_type = items[3];
+               int config_methods = items[4].toInt(0, 0);
+               int dev_passwd_id = items[5].toInt();
+               QString name;
+
+               int pos = text.indexOf('[');
+               if (pos >= 0) {
+                       int pos2 = text.lastIndexOf(']');
+                       if (pos2 >= pos) {
+                               QStringList items2 =
+                                       text.mid(pos + 1, pos2 - pos - 1).
+                                       split('|');
+                               name = items2[0];
+                       }
+               }
+               if (name.isEmpty())
+                       name = addr;
+
+               QStandardItem *item;
+
+               item = find_uuid(uuid);
+               if (item) {
+                       QVariant var = item->data(peer_role_config_methods);
+                       QVariant var2 = item->data(peer_role_dev_passwd_id);
+                       if ((var.isValid() && config_methods != var.toInt()) ||
+                           (var2.isValid() && dev_passwd_id != var2.toInt()))
+                               remove_enrollee_uuid(uuid);
+                       else
+                               return;
+               }
+
+               item = new QStandardItem(*laptop_icon, name);
+               if (item) {
+                       item->setData(uuid, peer_role_uuid);
+                       item->setData(addr, peer_role_address);
+                       item->setData(PEER_TYPE_WPS_ENROLLEE,
+                                     peer_role_type);
+                       item->setToolTip(ItemType(PEER_TYPE_WPS_ENROLLEE));
+                       item->setData(items.join(QString("\n")),
+                                     peer_role_details);
+                       item->setData(pri_dev_type, peer_role_pri_dev_type);
+                       item->setData(config_methods,
+                                     peer_role_config_methods);
+                       item->setData(dev_passwd_id, peer_role_dev_passwd_id);
+                       model.appendRow(item);
+               }
+
+               return;
+       }
 }
 
 
@@ -673,8 +744,11 @@ void Peers::remove_enrollee_uuid(QString uuid)
                                          peer_role_uuid, uuid);
        for (int i = 0; i < lst.size(); i++) {
                QStandardItem *item = model.itemFromIndex(lst[i]);
-               if (item && item->data(peer_role_type).toInt() ==
-                   PEER_TYPE_WPS_ER_ENROLLEE)
+               if (item == NULL)
+                       continue;
+               int type = item->data(peer_role_type).toInt();
+               if (type == PEER_TYPE_WPS_ER_ENROLLEE ||
+                   type == PEER_TYPE_WPS_ENROLLEE)
                        model.removeRow(lst[i].row());
        }
 }