aboutsummaryrefslogtreecommitdiffstats
path: root/src/wps
diff options
context:
space:
mode:
authorJouni Malinen <jouni.malinen@atheros.com>2010-10-25 19:22:07 (GMT)
committerJouni Malinen <j@w1.fi>2010-10-25 19:22:07 (GMT)
commitbe88391deedbb5b346cd3ae7c095b9b5ea60ce26 (patch)
tree4ff0402f4368d895e859a8e2aa68502122a0f02b /src/wps
parented159ad41bfb132b7da02a389633280f5d029eac (diff)
downloadhostap-be88391deedbb5b346cd3ae7c095b9b5ea60ce26.zip
hostap-be88391deedbb5b346cd3ae7c095b9b5ea60ce26.tar.gz
hostap-be88391deedbb5b346cd3ae7c095b9b5ea60ce26.tar.bz2
WPS ER: Cache AP settings for APs that restart UPnP
This is needed to avoid issues with APs that restart their UPnP, e.g., when ER reconfigures them. The previously known settings are now cached and taken into use if an AP is detected to leave (ssdp:byebye) and then return.
Diffstat (limited to 'src/wps')
-rw-r--r--src/wps/wps_er.c64
-rw-r--r--src/wps/wps_er.h8
-rw-r--r--src/wps/wps_er_ssdp.c1
3 files changed, 73 insertions, 0 deletions
diff --git a/src/wps/wps_er.c b/src/wps/wps_er.c
index 0d0100d..feef04f 100644
--- a/src/wps/wps_er.c
+++ b/src/wps/wps_er.c
@@ -279,6 +279,64 @@ fail:
wps_er_ap_unsubscribed(ap->er, ap);
}
+
+static struct wps_er_ap_settings * wps_er_ap_get_settings(struct wps_er *er,
+ const u8 *uuid)
+{
+ struct wps_er_ap_settings *s;
+ dl_list_for_each(s, &er->ap_settings, struct wps_er_ap_settings, list)
+ if (os_memcmp(uuid, s->uuid, WPS_UUID_LEN) == 0)
+ return s;
+ return NULL;
+}
+
+
+int wps_er_ap_cache_settings(struct wps_er *er, struct in_addr *addr)
+{
+ struct wps_er_ap *ap;
+ struct wps_er_ap_settings *settings;
+
+ ap = wps_er_ap_get(er, addr, NULL);
+ if (ap == NULL || ap->ap_settings == NULL)
+ return -1;
+
+ settings = wps_er_ap_get_settings(er, ap->uuid);
+ if (!settings) {
+ settings = os_zalloc(sizeof(*settings));
+ if (settings == NULL)
+ return -1;
+ os_memcpy(settings->uuid, ap->uuid, WPS_UUID_LEN);
+ dl_list_add(&er->ap_settings, &settings->list);
+ }
+ os_memcpy(&settings->ap_settings, ap->ap_settings,
+ sizeof(struct wps_credential));
+
+ return 0;
+}
+
+
+static int wps_er_ap_use_cached_settings(struct wps_er *er,
+ struct wps_er_ap *ap)
+{
+ struct wps_er_ap_settings *s;
+
+ if (ap->ap_settings)
+ return 0;
+
+ s = wps_er_ap_get_settings(ap->er, ap->uuid);
+ if (!s)
+ return -1;
+
+ ap->ap_settings = os_malloc(sizeof(*ap->ap_settings));
+ if (ap->ap_settings == NULL)
+ return -1;
+
+ os_memcpy(ap->ap_settings, &s->ap_settings, sizeof(*ap->ap_settings));
+ wpa_printf(MSG_DEBUG, "WPS ER: Use cached AP settings");
+ return 0;
+}
+
+
static void wps_er_ap_remove_entry(struct wps_er *er, struct wps_er_ap *ap)
{
wpa_printf(MSG_DEBUG, "WPS ER: Removing AP entry for %s (%s)",
@@ -356,6 +414,7 @@ static void wps_er_http_subscribe_cb(void *ctx, struct http_client *c,
wpa_printf(MSG_DEBUG, "WPS ER: Subscribed to events");
ap->subscribed = 1;
wps_er_get_sid(ap, http_client_get_hdr_line(c, "SID"));
+ wps_er_ap_use_cached_settings(ap->er, ap);
wps_er_ap_event(ap->er->wps, ap, WPS_EV_ER_AP_ADD);
break;
case HTTP_CLIENT_FAILED:
@@ -587,8 +646,12 @@ void wps_er_ap_remove(struct wps_er *er, struct in_addr *addr)
static void wps_er_ap_remove_all(struct wps_er *er)
{
struct wps_er_ap *prev, *ap;
+ struct wps_er_ap_settings *prev_s, *s;
dl_list_for_each_safe(ap, prev, &er->ap, struct wps_er_ap, list)
wps_er_ap_remove_entry(er, ap);
+ dl_list_for_each_safe(s, prev_s, &er->ap_settings,
+ struct wps_er_ap_settings, list)
+ os_free(s);
}
@@ -1166,6 +1229,7 @@ wps_er_init(struct wps_context *wps, const char *ifname, const char *filter)
return NULL;
dl_list_init(&er->ap);
dl_list_init(&er->ap_unsubscribing);
+ dl_list_init(&er->ap_settings);
er->multicast_sd = -1;
er->ssdp_sd = -1;
diff --git a/src/wps/wps_er.h b/src/wps/wps_er.h
index 16dbaa6..5388ed1 100644
--- a/src/wps/wps_er.h
+++ b/src/wps/wps_er.h
@@ -73,6 +73,12 @@ struct wps_er_ap {
void (*m1_handler)(struct wps_er_ap *ap, struct wpabuf *m1);
};
+struct wps_er_ap_settings {
+ struct dl_list list;
+ u8 uuid[WPS_UUID_LEN];
+ struct wps_credential ap_settings;
+};
+
struct wps_er {
struct wps_context *wps;
char ifname[17];
@@ -83,6 +89,7 @@ struct wps_er {
int ssdp_sd;
struct dl_list ap;
struct dl_list ap_unsubscribing;
+ struct dl_list ap_settings;
struct http_server *http_srv;
int http_port;
unsigned int next_ap_id;
@@ -100,6 +107,7 @@ struct wps_er {
void wps_er_ap_add(struct wps_er *er, const u8 *uuid, struct in_addr *addr,
const char *location, int max_age);
void wps_er_ap_remove(struct wps_er *er, struct in_addr *addr);
+int wps_er_ap_cache_settings(struct wps_er *er, struct in_addr *addr);
/* wps_er_ssdp.c */
int wps_er_ssdp_init(struct wps_er *er);
diff --git a/src/wps/wps_er_ssdp.c b/src/wps/wps_er_ssdp.c
index abcb91d..83de9ad 100644
--- a/src/wps/wps_er_ssdp.c
+++ b/src/wps/wps_er_ssdp.c
@@ -113,6 +113,7 @@ static void wps_er_ssdp_rx(int sd, void *eloop_ctx, void *sock_ctx)
return; /* Not WPS advertisement/reply */
if (byebye) {
+ wps_er_ap_cache_settings(er, &addr.sin_addr);
wps_er_ap_remove(er, &addr.sin_addr);
return;
}