Browse Source

WPS: Add Enrollee-seen event message and wpa_gui-qt4 Peers entry

This can be used to show active Enrollees in AP mode to make it
easier to provision a new device.
Jouni Malinen 15 years ago
parent
commit
c2f5126941
5 changed files with 144 additions and 5 deletions
  1. 24 0
      src/ap/wps_hostapd.c
  2. 2 0
      src/common/wpa_ctrl.h
  3. 16 0
      src/wps/wps.h
  4. 23 0
      src/wps/wps_registrar.c
  5. 79 5
      wpa_supplicant/wpa_gui-qt4/peers.cpp

+ 24 - 0
src/ap/wps_hostapd.c

@@ -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;

+ 2 - 0
src/common/wpa_ctrl.h

@@ -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 "

+ 16 - 0
src/wps/wps.h

@@ -277,6 +277,22 @@ struct wps_registrar_config {
 	void (*set_sel_reg_cb)(void *ctx, int sel_reg, u16 dev_passwd_id,
 			       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
 	 */

+ 23 - 0
src/wps/wps_registrar.c

@@ -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 */

+ 79 - 5
wpa_supplicant/wpa_gui-qt4/peers.cpp

@@ -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());
 	}
 }