diff --git a/src/wps/wps_upnp.c b/src/wps/wps_upnp.c index 4c0a5c1c8..410df463a 100644 --- a/src/wps/wps_upnp.c +++ b/src/wps/wps_upnp.c @@ -499,7 +499,8 @@ static void upnp_wps_device_send_event(struct upnp_wps_device_sm *sm) dl_list_for_each_safe(s, tmp, &sm->subscriptions, struct subscription, list) { - if (event_add(s, buf) == 1) { + if (event_add(s, buf, sm->wlanevent_type == + UPNP_WPS_WLANEVENT_TYPE_PROBE) == 1) { wpa_printf(MSG_INFO, "WPS UPnP: Dropping " "subscriber %p due to event backlog", s); dl_list_del(&s->list); @@ -650,7 +651,7 @@ static int subscription_first_event(struct subscription *s) wpabuf_put_property(buf, "WLANEvent", wlan_event); wpabuf_put_str(buf, tail); - ret = event_add(s, buf); + ret = event_add(s, buf, 0); if (ret) { wpabuf_free(buf); return ret; @@ -798,6 +799,7 @@ int upnp_wps_device_send_wlan_event(struct upnp_wps_device_sm *sm, os_free(sm->wlanevent); sm->wlanevent = val; + sm->wlanevent_type = ev_type; upnp_wps_device_send_event(sm); ret = 0; diff --git a/src/wps/wps_upnp_event.c b/src/wps/wps_upnp_event.c index 6555f9e9d..8c3ded8d7 100644 --- a/src/wps/wps_upnp_event.c +++ b/src/wps/wps_upnp_event.c @@ -132,6 +132,7 @@ static void event_retry(struct wps_event_ *e, int do_next_address) wpa_printf(MSG_DEBUG, "WPS UPnP: Giving up on sending event " "for %s", e->addr->domain_and_port); event_delete(e); + s->last_event_failed = 1; if (!dl_list_empty(&s->event_queue)) event_send_all_later(s->sm); return; @@ -222,6 +223,7 @@ static void event_http_cb(void *ctx, struct http_client *c, "WPS UPnP: Got event %p reply OK from %s", e, e->addr->domain_and_port); e->addr->num_failures = 0; + s->last_event_failed = 0; event_delete(e); /* Schedule sending more if there is more to send */ @@ -367,9 +369,10 @@ void event_send_stop_all(struct upnp_wps_device_sm *sm) * event_add - Add a new event to a queue * @s: Subscription * @data: Event data (is copied; caller retains ownership) + * @probereq: Whether this is a Probe Request event * Returns: 0 on success, -1 on error, 1 on max event queue limit reached */ -int event_add(struct subscription *s, const struct wpabuf *data) +int event_add(struct subscription *s, const struct wpabuf *data, int probereq) { struct wps_event_ *e; unsigned int len; @@ -381,6 +384,17 @@ int event_add(struct subscription *s, const struct wpabuf *data) return 1; } + if (s->last_event_failed && probereq && len > 0) { + /* + * Avoid queuing frames for subscribers that may have left + * without unsubscribing. + */ + wpa_printf(MSG_DEBUG, "WPS UPnP: Do not queue more Probe " + "Request frames for subscription %p since last " + "delivery failed", s); + return -1; + } + e = os_zalloc(sizeof(*e)); if (e == NULL) return -1; diff --git a/src/wps/wps_upnp_i.h b/src/wps/wps_upnp_i.h index 68782c054..4143ecad5 100644 --- a/src/wps/wps_upnp_i.h +++ b/src/wps/wps_upnp_i.h @@ -92,6 +92,7 @@ struct subscription { struct dl_list event_queue; /* Queued event messages. */ struct wps_event_ *current_event; /* non-NULL if being sent (not in q) */ + int last_event_failed; /* Whether delivery of last event failed */ /* Information from SetSelectedRegistrar action */ u8 selected_registrar; @@ -132,6 +133,7 @@ struct upnp_wps_device_sm { */ char *wlanevent; /* the last WLANEvent data */ + enum upnp_wps_wlanevent_type wlanevent_type; /* FIX: maintain separate structures for each UPnP peer */ struct upnp_wps_peer peer; @@ -168,7 +170,7 @@ int web_listener_start(struct upnp_wps_device_sm *sm); void web_listener_stop(struct upnp_wps_device_sm *sm); /* wps_upnp_event.c */ -int event_add(struct subscription *s, const struct wpabuf *data); +int event_add(struct subscription *s, const struct wpabuf *data, int probereq); void event_delete_all(struct subscription *s); void event_send_all_later(struct upnp_wps_device_sm *sm); void event_send_stop_all(struct upnp_wps_device_sm *sm);