]> git.ipfire.org Git - thirdparty/hostap.git/commitdiff
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 f36fef759ebbf5fd49073a4467624f0be2b29e68..87467b801956da11ed2f06059f0bb5f23491958f 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 725886fc016eeacd3ad14b7d9c2b9d0ddbf84cb4..2d54cd24cb8c2bea5b0dc3e33a93d48a20ca56c5 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 c89479f7d4f71d264c4ee184dfd3b53c82a9128f..509a7c0c8180be670df4bb8be774703212adc330 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 5bc5ffa5d7c76645feb931caedd7f17ff2c4da96..8bb9546e1395551c1b649d135f0812540cfeda99 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,