P2P: Allow Device ID to be specified for p2p_find command
[mech_eap.git] / src / p2p / p2p.c
index e750547..e61e133 100644 (file)
@@ -114,6 +114,34 @@ static const char * p2p_state_txt(int state)
 }
 
 
+u16 p2p_get_provisioning_info(struct p2p_data *p2p, const u8 *addr)
+{
+       struct p2p_device *dev = NULL;
+
+       if (!addr || !p2p)
+               return 0;
+
+       dev = p2p_get_device(p2p, addr);
+       if (dev)
+               return dev->wps_prov_info;
+       else
+               return 0;
+}
+
+
+void p2p_clear_provisioning_info(struct p2p_data *p2p, const u8 *iface_addr)
+{
+       struct p2p_device *dev = NULL;
+
+       if (!iface_addr || !p2p)
+               return;
+
+       dev = p2p_get_device_interface(p2p, iface_addr);
+       if (dev)
+               dev->wps_prov_info = 0;
+}
+
+
 void p2p_set_state(struct p2p_data *p2p, int new_state)
 {
        wpa_msg(p2p->cfg->msg_ctx, MSG_DEBUG, "P2P: State %s -> %s",
@@ -146,6 +174,8 @@ void p2p_go_neg_failed(struct p2p_data *p2p, struct p2p_device *peer,
        struct p2p_go_neg_results res;
        p2p_clear_timeout(p2p);
        p2p_set_state(p2p, P2P_IDLE);
+       if (p2p->go_neg_peer)
+               p2p->go_neg_peer->wps_method = WPS_NOT_READY;
        p2p->go_neg_peer = NULL;
 
        os_memset(&res, 0, sizeof(res));
@@ -221,6 +251,12 @@ int p2p_listen(struct p2p_data *p2p, unsigned int timeout)
        p2p->pending_listen_usec = (timeout % 1000) * 1000;
 
        if (p2p->p2p_scan_running) {
+               if (p2p->start_after_scan == P2P_AFTER_SCAN_NOTHING) {
+                       wpa_msg(p2p->cfg->msg_ctx, MSG_DEBUG,
+                               "P2P: p2p_scan running - connect is already "
+                               "pending - skip listen");
+                       return 0;
+               }
                wpa_msg(p2p->cfg->msg_ctx, MSG_DEBUG,
                        "P2P: p2p_scan running - delay start of listen state");
                p2p->start_after_scan = P2P_AFTER_SCAN_LISTEN;
@@ -374,6 +410,9 @@ static int p2p_add_group_clients(struct p2p_data *p2p, const u8 *go_dev_addr,
 
        for (c = 0; c < info.num_clients; c++) {
                struct p2p_client_info *cli = &info.client[c];
+               if (os_memcmp(cli->p2p_device_addr, p2p->cfg->dev_addr,
+                             ETH_ALEN) == 0)
+                       continue; /* ignore our own entry */
                dev = p2p_get_device(p2p, cli->p2p_device_addr);
                if (dev) {
                        /*
@@ -627,8 +666,13 @@ static void p2p_device_free(struct p2p_data *p2p, struct p2p_device *dev)
 {
        int i;
 
-       if (p2p->go_neg_peer == dev)
+       if (p2p->go_neg_peer == dev) {
+               /*
+                * If GO Negotiation is in progress, report that it has failed.
+                */
+               p2p_go_neg_failed(p2p, dev, -1);
                p2p->go_neg_peer = NULL;
+       }
        if (p2p->invite_peer == dev)
                p2p->invite_peer = NULL;
        if (p2p->sd_peer == dev)
@@ -751,8 +795,8 @@ static void p2p_search(struct p2p_data *p2p)
        }
 
        if (p2p->cfg->p2p_scan(p2p->cfg->cb_ctx, type, freq,
-                              p2p->num_req_dev_types, p2p->req_dev_types) < 0)
-       {
+                              p2p->num_req_dev_types, p2p->req_dev_types,
+                              p2p->find_dev_id) < 0) {
                wpa_msg(p2p->cfg->msg_ctx, MSG_DEBUG,
                        "P2P: Scan request failed");
                p2p_continue_find(p2p);
@@ -851,7 +895,8 @@ static void p2p_free_req_dev_types(struct p2p_data *p2p)
 
 int p2p_find(struct p2p_data *p2p, unsigned int timeout,
             enum p2p_discovery_type type,
-            unsigned int num_req_dev_types, const u8 *req_dev_types)
+            unsigned int num_req_dev_types, const u8 *req_dev_types,
+            const u8 *dev_id)
 {
        int res;
 
@@ -873,6 +918,12 @@ int p2p_find(struct p2p_data *p2p, unsigned int timeout,
                p2p->num_req_dev_types = num_req_dev_types;
        }
 
+       if (dev_id) {
+               os_memcpy(p2p->find_dev_id_buf, dev_id, ETH_ALEN);
+               p2p->find_dev_id = p2p->find_dev_id_buf;
+       } else
+               p2p->find_dev_id = NULL;
+
        p2p->start_after_scan = P2P_AFTER_SCAN_NOTHING;
        p2p_clear_timeout(p2p);
        p2p->cfg->stop_listen(p2p->cfg->cb_ctx);
@@ -889,12 +940,12 @@ int p2p_find(struct p2p_data *p2p, unsigned int timeout,
        case P2P_FIND_PROGRESSIVE:
                res = p2p->cfg->p2p_scan(p2p->cfg->cb_ctx, P2P_SCAN_FULL, 0,
                                         p2p->num_req_dev_types,
-                                        p2p->req_dev_types);
+                                        p2p->req_dev_types, dev_id);
                break;
        case P2P_FIND_ONLY_SOCIAL:
                res = p2p->cfg->p2p_scan(p2p->cfg->cb_ctx, P2P_SCAN_SOCIAL, 0,
                                         p2p->num_req_dev_types,
-                                        p2p->req_dev_types);
+                                        p2p->req_dev_types, dev_id);
                break;
        default:
                return -1;
@@ -931,7 +982,8 @@ int p2p_other_scan_completed(struct p2p_data *p2p)
        wpa_msg(p2p->cfg->msg_ctx, MSG_DEBUG, "P2P: Starting pending P2P find "
                "now that previous scan was completed");
        if (p2p_find(p2p, p2p->last_p2p_find_timeout, p2p->find_type,
-                    p2p->num_req_dev_types, p2p->req_dev_types) < 0)
+                    p2p->num_req_dev_types, p2p->req_dev_types,
+                    p2p->find_dev_id) < 0)
                return 0;
        return 1;
 }
@@ -2331,11 +2383,11 @@ void p2p_continue_find(struct p2p_data *p2p)
                } else if (dev->req_config_methods &&
                           !(dev->flags & P2P_DEV_PD_FOR_JOIN)) {
                        wpa_msg(p2p->cfg->msg_ctx, MSG_DEBUG, "P2P: Send "
-                               "pending Provisioning Discovery Request to "
+                               "pending Provision Discovery Request to "
                                MACSTR " (config methods 0x%x)",
                                MAC2STR(dev->info.p2p_device_addr),
                                dev->req_config_methods);
-                       if (p2p_send_prov_disc_req(p2p, dev, 0) == 0)
+                       if (p2p_send_prov_disc_req(p2p, dev, 0, 0) == 0)
                                return;
                }
        }
@@ -2400,11 +2452,11 @@ static void p2p_retry_pd(struct p2p_data *p2p)
                        continue;
 
                wpa_msg(p2p->cfg->msg_ctx, MSG_DEBUG, "P2P: Send "
-                       "pending Provisioning Discovery Request to "
+                       "pending Provision Discovery Request to "
                        MACSTR " (config methods 0x%x)",
                        MAC2STR(dev->info.p2p_device_addr),
                        dev->req_config_methods);
-               p2p_send_prov_disc_req(p2p, dev, 0);
+               p2p_send_prov_disc_req(p2p, dev, 0, 0);
                return;
        }
 }
@@ -2489,10 +2541,12 @@ void p2p_scan_res_handled(struct p2p_data *p2p)
 }
 
 
-void p2p_scan_ie(struct p2p_data *p2p, struct wpabuf *ies)
+void p2p_scan_ie(struct p2p_data *p2p, struct wpabuf *ies, const u8 *dev_id)
 {
        u8 *len = p2p_buf_add_ie_hdr(ies);
        p2p_buf_add_capability(ies, p2p->dev_capab, 0);
+       if (dev_id)
+               p2p_buf_add_device_id(ies, dev_id);
        if (p2p->cfg->reg_class && p2p->cfg->channel)
                p2p_buf_add_listen_channel(ies, p2p->cfg->country,
                                           p2p->cfg->reg_class,
@@ -2790,7 +2844,7 @@ static void p2p_timeout_wait_peer_connect(struct p2p_data *p2p)
         * state once per second to give other uses a chance to use the radio.
         */
        p2p_set_state(p2p, P2P_WAIT_PEER_IDLE);
-       p2p_set_timeout(p2p, 1, 0);
+       p2p_set_timeout(p2p, 0, 500000);
 }
 
 
@@ -2994,7 +3048,7 @@ int p2p_reject(struct p2p_data *p2p, const u8 *peer_addr)
 }
 
 
-static const char * p2p_wps_method_text(enum p2p_wps_method method)
+const char * p2p_wps_method_text(enum p2p_wps_method method)
 {
        switch (method) {
        case WPS_NOT_READY:
@@ -3026,14 +3080,10 @@ static const char * p2p_go_state_text(enum p2p_go_state go_state)
 }
 
 
-int p2p_get_peer_info(struct p2p_data *p2p, const u8 *addr, int next,
-                     char *buf, size_t buflen)
+const struct p2p_peer_info * p2p_get_peer_info(struct p2p_data *p2p,
+                                              const u8 *addr, int next)
 {
        struct p2p_device *dev;
-       int res;
-       char *pos, *end;
-       struct os_time now;
-       char devtype[WPS_DEV_TYPE_BUFSIZE];
 
        if (addr)
                dev = p2p_get_device(p2p, addr);
@@ -3047,35 +3097,37 @@ int p2p_get_peer_info(struct p2p_data *p2p, const u8 *addr, int next,
        }
 
        if (dev == NULL)
+               return NULL;
+
+       return &dev->info;
+}
+
+
+int p2p_get_peer_info_txt(const struct p2p_peer_info *info,
+                         char *buf, size_t buflen)
+{
+       struct p2p_device *dev;
+       int res;
+       char *pos, *end;
+       struct os_time now;
+
+       if (info == NULL)
                return -1;
 
+       dev = (struct p2p_device *) (((u8 *) info) -
+                                    offsetof(struct p2p_device, info));
+
        pos = buf;
        end = buf + buflen;
 
-       res = os_snprintf(pos, end - pos, MACSTR "\n",
-                         MAC2STR(dev->info.p2p_device_addr));
-       if (res < 0 || res >= end - pos)
-               return pos - buf;
-       pos += res;
-
        os_get_time(&now);
        res = os_snprintf(pos, end - pos,
                          "age=%d\n"
                          "listen_freq=%d\n"
-                         "level=%d\n"
                          "wps_method=%s\n"
                          "interface_addr=" MACSTR "\n"
                          "member_in_go_dev=" MACSTR "\n"
                          "member_in_go_iface=" MACSTR "\n"
-                         "pri_dev_type=%s\n"
-                         "device_name=%s\n"
-                         "manufacturer=%s\n"
-                         "model_name=%s\n"
-                         "model_number=%s\n"
-                         "serial_number=%s\n"
-                         "config_methods=0x%x\n"
-                         "dev_capab=0x%x\n"
-                         "group_capab=0x%x\n"
                          "go_neg_req_sent=%d\n"
                          "go_state=%s\n"
                          "dialog_token=%u\n"
@@ -3089,21 +3141,10 @@ int p2p_get_peer_info(struct p2p_data *p2p, const u8 *addr, int next,
                          "invitation_reqs=%u\n",
                          (int) (now.sec - dev->last_seen.sec),
                          dev->listen_freq,
-                         dev->info.level,
                          p2p_wps_method_text(dev->wps_method),
                          MAC2STR(dev->interface_addr),
                          MAC2STR(dev->member_in_go_dev),
                          MAC2STR(dev->member_in_go_iface),
-                         wps_dev_type_bin2str(dev->info.pri_dev_type,
-                                              devtype, sizeof(devtype)),
-                         dev->info.device_name,
-                         dev->info.manufacturer,
-                         dev->info.model_name,
-                         dev->info.model_number,
-                         dev->info.serial_number,
-                         dev->info.config_methods,
-                         dev->info.dev_capab,
-                         dev->info.group_capab,
                          dev->go_neg_req_sent,
                          p2p_go_state_text(dev->go_state),
                          dev->dialog_token,
@@ -3172,6 +3213,12 @@ int p2p_get_peer_info(struct p2p_data *p2p, const u8 *addr, int next,
 }
 
 
+int p2p_peer_known(struct p2p_data *p2p, const u8 *addr)
+{
+       return p2p_get_device(p2p, addr) != NULL;
+}
+
+
 void p2p_set_client_discoverability(struct p2p_data *p2p, int enabled)
 {
        if (enabled) {