diff --git a/src/wps/wps_upnp.c b/src/wps/wps_upnp.c index 07b5bce68..eaadd2725 100644 --- a/src/wps/wps_upnp.c +++ b/src/wps/wps_upnp.c @@ -964,8 +964,7 @@ void upnp_wps_device_stop(struct upnp_wps_device_sm *sm) subscription_destroy(s); } - advertisement_state_machine_stop(sm); - /* TODO: send byebye notifications */ + advertisement_state_machine_stop(sm, 1); event_send_stop_all(sm); os_free(sm->wlanevent); diff --git a/src/wps/wps_upnp_i.h b/src/wps/wps_upnp_i.h index ac8a7103f..63e6506d1 100644 --- a/src/wps/wps_upnp_i.h +++ b/src/wps/wps_upnp_i.h @@ -159,7 +159,8 @@ int get_netif_info(const char *net_if, unsigned *ip_addr, char **ip_addr_text, /* wps_upnp_ssdp.c */ void msearchreply_state_machine_stop(struct advertisement_state_machine *a); int advertisement_state_machine_start(struct upnp_wps_device_sm *sm); -void advertisement_state_machine_stop(struct upnp_wps_device_sm *sm); +void advertisement_state_machine_stop(struct upnp_wps_device_sm *sm, + int send_byebye); void ssdp_listener_stop(struct upnp_wps_device_sm *sm); int ssdp_listener_start(struct upnp_wps_device_sm *sm); int ssdp_listener_open(void); diff --git a/src/wps/wps_upnp_ssdp.c b/src/wps/wps_upnp_ssdp.c index 3ffff092d..93706ea47 100644 --- a/src/wps/wps_upnp_ssdp.c +++ b/src/wps/wps_upnp_ssdp.c @@ -228,10 +228,41 @@ static void advertisement_state_machine_handler(void *eloop_data, /** * advertisement_state_machine_stop - Stop SSDP advertisements * @sm: WPS UPnP state machine from upnp_wps_device_init() + * @send_byebye: Send byebye advertisement messages immediately */ -void advertisement_state_machine_stop(struct upnp_wps_device_sm *sm) +void advertisement_state_machine_stop(struct upnp_wps_device_sm *sm, + int send_byebye) { + struct advertisement_state_machine *a = &sm->advertisement; + int islast = 0; + struct wpabuf *msg; + struct sockaddr_in dest; + eloop_cancel_timeout(advertisement_state_machine_handler, NULL, sm); + if (!send_byebye) + return; + + a->type = ADVERTISE_DOWN; + a->state = 0; + a->sm = sm; + + os_memset(&dest, 0, sizeof(dest)); + dest.sin_family = AF_INET; + dest.sin_addr.s_addr = inet_addr(UPNP_MULTICAST_ADDRESS); + dest.sin_port = htons(UPNP_MULTICAST_PORT); + + while (!islast) { + msg = next_advertisement(a, &islast); + if (msg == NULL) + break; + if (sendto(sm->multicast_sd, wpabuf_head(msg), wpabuf_len(msg), + 0, (struct sockaddr *) &dest, sizeof(dest)) < 0) { + wpa_printf(MSG_INFO, "WPS UPnP: Advertisement sendto " + "failed: %d (%s)", errno, strerror(errno)); + } + wpabuf_free(msg); + a->state++; + } } @@ -317,7 +348,7 @@ int advertisement_state_machine_start(struct upnp_wps_device_sm *sm) struct advertisement_state_machine *a = &sm->advertisement; int next_timeout_msec; - advertisement_state_machine_stop(sm); + advertisement_state_machine_stop(sm, 0); /* * Start out advertising down, this automatically switches