]> git.ipfire.org Git - thirdparty/hostap.git/commitdiff
P2P: Maintain a list of P2P Clients for persistent group on GO
authorJouni Malinen <j@w1.fi>
Thu, 22 Dec 2011 20:47:41 +0000 (22:47 +0200)
committerJouni Malinen <j@w1.fi>
Thu, 22 Dec 2011 20:47:41 +0000 (22:47 +0200)
Add a new persistent group network block field, p2p_client_list, to
maintain a list of P2P Clients that have connected to a persistent
group. This allows GO of a persistent group to figure out more easily
whether re-invocation of a persistent group can be used with a specific
peer device.

Signed-hostap: Jouni Malinen <j@w1.fi>

src/ap/hostapd.h
src/ap/sta_info.c
wpa_supplicant/ap.c
wpa_supplicant/config.c
wpa_supplicant/config_file.c
wpa_supplicant/config_ssid.h
wpa_supplicant/notify.c
wpa_supplicant/notify.h
wpa_supplicant/p2p_supplicant.c
wpa_supplicant/p2p_supplicant.h

index 5b727685bfe9aa8d03ff165471d8895140595f28..c6f6205733a539afa162f579ebedcc6d126453c5 100644 (file)
@@ -149,7 +149,7 @@ struct hostapd_data {
        void *wps_event_cb_ctx;
 
        void (*sta_authorized_cb)(void *ctx, const u8 *mac_addr,
-                                 int authorized);
+                                 int authorized, const u8 *p2p_dev_addr);
        void *sta_authorized_cb_ctx;
 
        void (*setup_complete_cb)(void *ctx);
index d9c348e0d202648890d8b6d5f061e5e69fd305a3..27ab25856b9157c4b6f22e5f968c9783142fe356 100644 (file)
@@ -824,7 +824,7 @@ void ap_sta_set_authorized(struct hostapd_data *hapd, struct sta_info *sta,
 
        if (hapd->sta_authorized_cb)
                hapd->sta_authorized_cb(hapd->sta_authorized_cb_ctx,
-                                       sta->addr, authorized);
+                                       sta->addr, authorized, dev_addr);
 }
 
 
index 2d147d1a4013b0350640d38e6af9be61022d183f..1386d0c0289aed698298e43a90450ef5d680266f 100644 (file)
@@ -328,9 +328,9 @@ static void ap_wps_event_cb(void *ctx, enum wps_event event,
 
 
 static void ap_sta_authorized_cb(void *ctx, const u8 *mac_addr,
-                                int authorized)
+                                int authorized, const u8 *p2p_dev_addr)
 {
-       wpas_notify_sta_authorized(ctx, mac_addr, authorized);
+       wpas_notify_sta_authorized(ctx, mac_addr, authorized, p2p_dev_addr);
 }
 
 
index b446a3f44413837e756c2991f0448d8730e7dfb5..0fd1f3e0d6f0dcb4e5267e44a7bf18f94a93a219 100644 (file)
@@ -1351,6 +1351,90 @@ static char * wpa_config_write_wep_key3(const struct parse_data *data,
 #endif /* NO_CONFIG_WRITE */
 
 
+#ifdef CONFIG_P2P
+
+static int wpa_config_parse_p2p_client_list(const struct parse_data *data,
+                                           struct wpa_ssid *ssid, int line,
+                                           const char *value)
+{
+       const char *pos;
+       u8 *buf, *n, addr[ETH_ALEN];
+       size_t count;
+
+       buf = NULL;
+       count = 0;
+
+       pos = value;
+       while (pos && *pos) {
+               while (*pos == ' ')
+                       pos++;
+
+               if (hwaddr_aton(pos, addr)) {
+                       wpa_printf(MSG_ERROR, "Line %d: Invalid "
+                                  "p2p_client_list address '%s'.",
+                                  line, value);
+                       /* continue anyway */
+               } else {
+                       n = os_realloc(buf, (count + 1) * ETH_ALEN);
+                       if (n == NULL) {
+                               os_free(buf);
+                               return -1;
+                       }
+                       buf = n;
+                       os_memcpy(buf + count * ETH_ALEN, addr, ETH_ALEN);
+                       count++;
+                       wpa_hexdump(MSG_MSGDUMP, "p2p_client_list",
+                                   addr, ETH_ALEN);
+               }
+
+               pos = os_strchr(pos, ' ');
+       }
+
+       os_free(ssid->p2p_client_list);
+       ssid->p2p_client_list = buf;
+       ssid->num_p2p_clients = count;
+
+       return 0;
+}
+
+
+#ifndef NO_CONFIG_WRITE
+static char * wpa_config_write_p2p_client_list(const struct parse_data *data,
+                                              struct wpa_ssid *ssid)
+{
+       char *value, *end, *pos;
+       int res;
+       size_t i;
+
+       if (ssid->p2p_client_list == NULL || ssid->num_p2p_clients == 0)
+               return NULL;
+
+       value = os_malloc(20 * ssid->num_p2p_clients);
+       if (value == NULL)
+               return NULL;
+       pos = value;
+       end = value + 20 * ssid->num_p2p_clients;
+
+       for (i = 0; i < ssid->num_p2p_clients; i++) {
+               res = os_snprintf(pos, end - pos, MACSTR " ",
+                                 MAC2STR(ssid->p2p_client_list +
+                                         i * ETH_ALEN));
+               if (res < 0 || res >= end - pos) {
+                       os_free(value);
+                       return NULL;
+               }
+               pos += res;
+       }
+
+       if (pos > value)
+               pos[-1] = '\0';
+
+       return value;
+}
+#endif /* NO_CONFIG_WRITE */
+
+#endif /* CONFIG_P2P */
+
 /* Helper macros for network block parser */
 
 #ifdef OFFSET
@@ -1511,6 +1595,9 @@ static const struct parse_data ssid_fields[] = {
        { INT_RANGE(frequency, 0, 10000) },
        { INT(wpa_ptk_rekey) },
        { STR(bgscan) },
+#ifdef CONFIG_P2P
+       { FUNC(p2p_client_list) },
+#endif /* CONFIG_P2P */
 };
 
 #undef OFFSET
@@ -1677,6 +1764,7 @@ void wpa_config_free_ssid(struct wpa_ssid *ssid)
        os_free(ssid->scan_freq);
        os_free(ssid->freq_list);
        os_free(ssid->bgscan);
+       os_free(ssid->p2p_client_list);
        os_free(ssid);
 }
 
index 8ea03abe3d244ebfd30f37254c57cf050947f3aa..f3a729137614271ae43686bdccd53b10a36edc48 100644 (file)
@@ -493,6 +493,18 @@ static void write_wep_key(FILE *f, int idx, struct wpa_ssid *ssid)
 }
 
 
+#ifdef CONFIG_P2P
+static void write_p2p_client_list(FILE *f, struct wpa_ssid *ssid)
+{
+       char *value = wpa_config_get(ssid, "p2p_client_list");
+       if (value == NULL)
+               return;
+       fprintf(f, "\tp2p_client_list=%s\n", value);
+       os_free(value);
+}
+#endif /* CONFIG_P2P */
+
+
 static void wpa_config_write_network(FILE *f, struct wpa_ssid *ssid)
 {
        int i;
@@ -567,6 +579,9 @@ static void wpa_config_write_network(FILE *f, struct wpa_ssid *ssid)
        INT(ieee80211w);
 #endif /* CONFIG_IEEE80211W */
        STR(id_str);
+#ifdef CONFIG_P2P
+       write_p2p_client_list(f, ssid);
+#endif /* CONFIG_P2P */
 
 #undef STR
 #undef INT
index 8419f43d9438f162a4208aa627d645f336df12e9..8a47c0b9d75a702403a8f9c6c9cbc6d59e315418 100644 (file)
@@ -386,6 +386,20 @@ struct wpa_ssid {
         */
        int *freq_list;
 
+       /**
+        * p2p_client_list - List of P2P Clients in a persistent group (GO)
+        *
+        * This is a list of P2P Clients (P2P Device Address) that have joined
+        * the persistent group. This is maintained on the GO for persistent
+        * group entries (disabled == 2).
+        */
+       u8 *p2p_client_list;
+
+       /**
+        * num_p2p_clients - Number of entries in p2p_client_list
+        */
+       size_t num_p2p_clients;
+
        /**
         * p2p_group - Network generated as a P2P group (used internally)
         */
index 71778ae44073f78a18fd590829440bc11f3d24e6..6e9b5a9f4ec8157bf07e62e54c40051ca0ecf40d 100644 (file)
@@ -525,9 +525,12 @@ void wpas_notify_p2p_wps_failed(struct wpa_supplicant *wpa_s,
 
 
 static void wpas_notify_ap_sta_authorized(struct wpa_supplicant *wpa_s,
-                                         const u8 *sta)
+                                         const u8 *sta,
+                                         const u8 *p2p_dev_addr)
 {
 #ifdef CONFIG_P2P
+       wpas_p2p_notify_ap_sta_authorized(wpa_s, p2p_dev_addr);
+
        /*
         * Register a group member object corresponding to this peer and
         * emit a PeerJoined signal. This will check if it really is a
@@ -564,10 +567,11 @@ static void wpas_notify_ap_sta_deauthorized(struct wpa_supplicant *wpa_s,
 
 
 void wpas_notify_sta_authorized(struct wpa_supplicant *wpa_s,
-                               const u8 *mac_addr, int authorized)
+                               const u8 *mac_addr, int authorized,
+                               const u8 *p2p_dev_addr)
 {
        if (authorized)
-               wpas_notify_ap_sta_authorized(wpa_s, mac_addr);
+               wpas_notify_ap_sta_authorized(wpa_s, mac_addr, p2p_dev_addr);
        else
                wpas_notify_ap_sta_deauthorized(wpa_s, mac_addr);
 }
index 7d4a11e71d4cce5d08af6312dda47259392acc06..236a31ee8cbc3b871eaa8590d0c9783ddc2e8184 100644 (file)
@@ -86,7 +86,8 @@ void wpas_notify_suspend(struct wpa_global *global);
 void wpas_notify_resume(struct wpa_global *global);
 
 void wpas_notify_sta_authorized(struct wpa_supplicant *wpa_s,
-                               const u8 *mac_addr, int authorized);
+                               const u8 *mac_addr, int authorized,
+                               const u8 *p2p_dev_addr);
 void wpas_notify_p2p_device_found(struct wpa_supplicant *wpa_s,
                                  const u8 *dev_addr, int new_device);
 void wpas_notify_p2p_device_lost(struct wpa_supplicant *wpa_s,
index 367fce144809f851c3bc5fe6c000a1ca4ccb1468..5cb9db613f0ac11f636a54af47045d892564b91b 100644 (file)
@@ -465,6 +465,52 @@ static int wpas_p2p_store_persistent_group(struct wpa_supplicant *wpa_s,
 }
 
 
+static void wpas_p2p_add_persistent_group_client(struct wpa_supplicant *wpa_s,
+                                                const u8 *addr)
+{
+       struct wpa_ssid *ssid, *s;
+       u8 *n;
+       size_t i;
+
+       ssid = wpa_s->current_ssid;
+       if (ssid == NULL || ssid->mode != WPAS_MODE_P2P_GO ||
+           !ssid->p2p_persistent_group)
+               return;
+
+       for (s = wpa_s->parent->conf->ssid; s; s = s->next) {
+               if (s->disabled != 2 || s->mode != WPAS_MODE_P2P_GO)
+                       continue;
+
+               if (s->ssid_len == ssid->ssid_len &&
+                   os_memcmp(s->ssid, ssid->ssid, s->ssid_len) == 0)
+                       break;
+       }
+
+       if (s == NULL)
+               return;
+
+       for (i = 0; s->p2p_client_list && i < s->num_p2p_clients; i++) {
+               if (os_memcmp(s->p2p_client_list + i * ETH_ALEN, addr,
+                             ETH_ALEN) == 0)
+                       return; /* already in list */
+       }
+
+       n = os_realloc(s->p2p_client_list,
+                      (s->num_p2p_clients + 1) * ETH_ALEN);
+       if (n == NULL)
+               return;
+       os_memcpy(n + s->num_p2p_clients * ETH_ALEN, addr, ETH_ALEN);
+       s->p2p_client_list = n;
+       s->num_p2p_clients++;
+
+#ifndef CONFIG_NO_CONFIG_WRITE
+       if (wpa_s->parent->conf->update_config &&
+           wpa_config_write(wpa_s->parent->confname, wpa_s->parent->conf))
+               wpa_printf(MSG_DEBUG, "P2P: Failed to update configuration");
+#endif /* CONFIG_NO_CONFIG_WRITE */
+}
+
+
 static void wpas_group_formation_completed(struct wpa_supplicant *wpa_s,
                                           int success)
 {
@@ -4266,12 +4312,31 @@ struct wpa_ssid * wpas_p2p_get_persistent(struct wpa_supplicant *wpa_s,
                                          const u8 *addr)
 {
        struct wpa_ssid *s;
+       size_t i;
 
        for (s = wpa_s->conf->ssid; s; s = s->next) {
-               if (s->disabled == 2 &&
-                   os_memcmp(s->bssid, addr, ETH_ALEN) == 0)
-                       return s;
+               if (s->disabled != 2)
+                       continue;
+               if (os_memcmp(s->bssid, addr, ETH_ALEN) == 0)
+                       return s; /* peer is GO in the persistent group */
+               if (s->mode != WPAS_MODE_P2P_GO || s->p2p_client_list == NULL)
+                       continue;
+               for (i = 0; i < s->num_p2p_clients; i++) {
+                       if (os_memcmp(s->p2p_client_list + i * ETH_ALEN,
+                                     addr, ETH_ALEN) == 0)
+                               return s; /* peer is P2P client in persistent
+                                          * group */
+               }
        }
 
        return NULL;
 }
+
+
+void wpas_p2p_notify_ap_sta_authorized(struct wpa_supplicant *wpa_s,
+                                      const u8 *addr)
+{
+       if (addr == NULL)
+               return;
+       wpas_p2p_add_persistent_group_client(wpa_s, addr);
+}
index 0a450b6c7390021f392a6dec9dca67cbab8efa4d..3150f04993857e695f0482a34a48d6e98d9adef4 100644 (file)
@@ -133,5 +133,7 @@ void wpas_p2p_network_removed(struct wpa_supplicant *wpa_s,
                              struct wpa_ssid *ssid);
 struct wpa_ssid * wpas_p2p_get_persistent(struct wpa_supplicant *wpa_s,
                                          const u8 *addr);
+void wpas_p2p_notify_ap_sta_authorized(struct wpa_supplicant *wpa_s,
+                                      const u8 *addr);
 
 #endif /* P2P_SUPPLICANT_H */