WPS NFC: Add connection handover support for ER
authorJouni Malinen <jouni@qca.qualcomm.com>
Sun, 24 Feb 2013 08:56:29 +0000 (10:56 +0200)
committerJouni Malinen <j@w1.fi>
Sun, 24 Feb 2013 08:56:29 +0000 (10:56 +0200)
wpa_supplicant can now generate the WPS carrier record for connection
handover response when acting as an ER. The AP whose configuration is
provided in this way is identified with an UUID as an argument to
wps-nfc.py.

Signed-hostap: Jouni Malinen <jouni@qca.qualcomm.com>

wpa_supplicant/ctrl_iface.c
wpa_supplicant/examples/wps-nfc.py
wpa_supplicant/wps_supplicant.c
wpa_supplicant/wps_supplicant.h

index f36fef7..87467b8 100644 (file)
@@ -910,12 +910,12 @@ static int wpas_ctrl_nfc_get_handover_req(struct wpa_supplicant *wpa_s,
 
 static int wpas_ctrl_nfc_get_handover_sel_wps(struct wpa_supplicant *wpa_s,
                                              char *reply, size_t max_len,
-                                             int ndef, int cr)
+                                             int ndef, int cr, char *uuid)
 {
        struct wpabuf *buf;
        int res;
 
-       buf = wpas_wps_nfc_handover_sel(wpa_s, ndef, cr);
+       buf = wpas_wps_nfc_handover_sel(wpa_s, ndef, cr, uuid);
        if (buf == NULL)
                return -1;
 
@@ -934,7 +934,7 @@ static int wpas_ctrl_nfc_get_handover_sel(struct wpa_supplicant *wpa_s,
                                          char *cmd, char *reply,
                                          size_t max_len)
 {
-       char *pos;
+       char *pos, *pos2;
        int ndef;
 
        pos = os_strchr(cmd, ' ');
@@ -949,10 +949,13 @@ static int wpas_ctrl_nfc_get_handover_sel(struct wpa_supplicant *wpa_s,
        else
                return -1;
 
+       pos2 = os_strchr(pos, ' ');
+       if (pos2)
+               *pos2++ = '\0';
        if (os_strcmp(pos, "WPS") == 0 || os_strcmp(pos, "WPS-CR") == 0) {
                return wpas_ctrl_nfc_get_handover_sel_wps(
                        wpa_s, reply, max_len, ndef,
-                       os_strcmp(pos, "WPS-CR") == 0);
+                       os_strcmp(pos, "WPS-CR") == 0, pos2);
        }
 
        return -1;
index 725886f..2d54cd2 100755 (executable)
@@ -82,15 +82,86 @@ def wpas_get_handover_req():
     return wpas.request("NFC_GET_HANDOVER_REQ NDEF WPS-CR").rstrip().decode("hex")
 
 
-def wpas_report_handover(req, sel):
+def wpas_get_handover_sel(uuid):
     wpas = wpas_connect()
     if (wpas == None):
         return None
-    return wpas.request("NFC_REPORT_HANDOVER INIT WPS " +
+    return wpas.request("NFC_GET_HANDOVER_SEL NDEF WPS-CR " + uuid).rstrip().decode("hex")
+
+
+def wpas_report_handover(req, sel, type):
+    wpas = wpas_connect()
+    if (wpas == None):
+        return None
+    return wpas.request("NFC_REPORT_HANDOVER " + type + " WPS " +
                         str(req).encode("hex") + " " +
                         str(sel).encode("hex"))
 
 
+class HandoverServer(nfc.handover.HandoverServer):
+    def __init__(self):
+        super(HandoverServer, self).__init__()
+
+    def process_request(self, request):
+        print "HandoverServer - request received"
+        print "Parsed handover request: " + request.pretty()
+
+        sel = nfc.ndef.HandoverSelectMessage(version="1.2")
+
+        for carrier in request.carriers:
+            print "Remote carrier type: " + carrier.type
+            if carrier.type == "application/vnd.wfa.wsc":
+                print "WPS carrier type match - add WPS carrier record"
+                self.received_carrier = carrier.record
+                data = wpas_get_handover_sel(self.uuid)
+                if data is None:
+                    print "Could not get handover select carrier record from wpa_supplicant"
+                    continue
+                print "Handover select carrier record from wpa_supplicant:"
+                print data.encode("hex")
+                self.sent_carrier = data
+
+                message = nfc.ndef.Message(data);
+                sel.add_carrier(message[0], "active", message[1:])
+
+        print "Handover select:"
+        print sel.pretty()
+        print str(sel).encode("hex")
+
+        print "Sending handover select"
+        return sel
+
+
+def wps_handover_resp(peer, uuid):
+    print "Trying to handle WPS handover with AP " + uuid
+
+    srv = HandoverServer()
+    srv.sent_carrier = None
+    srv.uuid = uuid
+
+    nfc.llcp.activate(peer);
+
+    try:
+        print "Trying handover";
+        srv.start()
+        print "Wait for disconnect"
+        while nfc.llcp.connected():
+            time.sleep(0.1)
+        print "Disconnected after handover"
+    except nfc.llcp.ConnectRefused:
+        print "Handover connection refused"
+        nfc.llcp.shutdown()
+        return
+
+    if srv.sent_carrier:
+        wpas_report_handover(srv.received_carrier, srv.sent_carrier, "RESP")
+
+    print "Remove peer"
+    nfc.llcp.shutdown()
+    print "Done with handover"
+    time.sleep(1)
+
+
 def wps_handover_init(peer):
     print "Trying to initiate WPS handover"
 
@@ -154,7 +225,7 @@ def wps_handover_init(peer):
         print "Remote carrier type: " + carrier.type
         if carrier.type == "application/vnd.wfa.wsc":
             print "WPS carrier type match - send to wpa_supplicant"
-            wpas_report_handover(data, carrier.record)
+            wpas_report_handover(data, carrier.record, "INIT")
             wifi = nfc.ndef.WifiConfigRecord(carrier.record)
             print wifi.pretty()
 
@@ -281,6 +352,10 @@ def main():
     clf = nfc.ContactlessFrontend()
 
     try:
+        arg_uuid = None
+        if len(sys.argv) > 1:
+            arg_uuid = sys.argv[1]
+
         if len(sys.argv) > 1 and sys.argv[1] == "write-config":
             wps_write_config_tag(clf)
             raise SystemExit
@@ -298,7 +373,10 @@ def main():
 
             tag = find_peer(clf)
             if isinstance(tag, nfc.DEP):
-                wps_handover_init(tag)
+                if arg_uuid is None:
+                    wps_handover_init(tag)
+                else:
+                    wps_handover_resp(tag, arg_uuid)
                 continue
 
             if tag.ndef:
index c89479f..509a7c0 100644 (file)
@@ -2003,12 +2003,48 @@ struct wpabuf * wpas_wps_nfc_handover_req(struct wpa_supplicant *wpa_s, int cr)
 }
 
 
+#ifdef CONFIG_WPS_NFC
+struct wpabuf * wpas_wps_er_nfc_handover_sel(struct wpa_supplicant *wpa_s,
+                                            int ndef, const char *uuid)
+{
+       struct wpabuf *ret;
+       u8 u[UUID_LEN];
+
+       if (!wpa_s->wps_er)
+               return NULL;
+
+       if (uuid == NULL || uuid_str2bin(uuid, u))
+               return NULL;
+
+       /*
+        * Handover Select carrier record for WPS uses the same format as
+        * configuration token.
+        */
+       ret = wps_er_nfc_config_token(wpa_s->wps_er, u);
+       if (ndef && ret) {
+               struct wpabuf *tmp;
+               tmp = ndef_build_wifi(ret);
+               wpabuf_free(ret);
+               if (tmp == NULL)
+                       return NULL;
+               ret = tmp;
+       }
+
+       return ret;
+}
+#endif /* CONFIG_WPS_NFC */
+
+
 struct wpabuf * wpas_wps_nfc_handover_sel(struct wpa_supplicant *wpa_s,
-                                         int ndef, int cr)
+                                         int ndef, int cr, const char *uuid)
 {
+       struct wpabuf *ret;
        if (!cr)
                return NULL;
-       return wpas_ap_wps_nfc_handover_sel(wpa_s, ndef);
+       ret = wpas_ap_wps_nfc_handover_sel(wpa_s, ndef);
+       if (ret)
+               return ret;
+       return wpas_wps_er_nfc_handover_sel(wpa_s, ndef, uuid);
 }
 
 
index 5bc5ffa..8bb9546 100644 (file)
@@ -70,7 +70,7 @@ int wpas_wps_nfc_tag_read(struct wpa_supplicant *wpa_s,
                          const struct wpabuf *data);
 struct wpabuf * wpas_wps_nfc_handover_req(struct wpa_supplicant *wpa_s, int cr);
 struct wpabuf * wpas_wps_nfc_handover_sel(struct wpa_supplicant *wpa_s,
-                                         int ndef, int cr);
+                                         int ndef, int cr, const char *uuid);
 int wpas_wps_nfc_rx_handover_req(struct wpa_supplicant *wpa_s,
                                 const struct wpabuf *data);
 int wpas_wps_nfc_rx_handover_sel(struct wpa_supplicant *wpa_s,