wps_er_ssdp.c revision c5ec7f57ead87efa365800228aa0b09a12d9e6c4
18ad0dd2a5c5f23cd210aedba72a43e48026e7436The Android Open Source Project/* 28ad0dd2a5c5f23cd210aedba72a43e48026e7436The Android Open Source Project * Wi-Fi Protected Setup - External Registrar (SSDP) 38ad0dd2a5c5f23cd210aedba72a43e48026e7436The Android Open Source Project * Copyright (c) 2009, Jouni Malinen <j@w1.fi> 48ad0dd2a5c5f23cd210aedba72a43e48026e7436The Android Open Source Project * 58ad0dd2a5c5f23cd210aedba72a43e48026e7436The Android Open Source Project * This software may be distributed under the terms of the BSD license. 68ad0dd2a5c5f23cd210aedba72a43e48026e7436The Android Open Source Project * See README for more details. 78ad0dd2a5c5f23cd210aedba72a43e48026e7436The Android Open Source Project */ 88ad0dd2a5c5f23cd210aedba72a43e48026e7436The Android Open Source Project 98ad0dd2a5c5f23cd210aedba72a43e48026e7436The Android Open Source Project#include "includes.h" 108ad0dd2a5c5f23cd210aedba72a43e48026e7436The Android Open Source Project 118ad0dd2a5c5f23cd210aedba72a43e48026e7436The Android Open Source Project#include "common.h" 128ad0dd2a5c5f23cd210aedba72a43e48026e7436The Android Open Source Project#include "uuid.h" 138ad0dd2a5c5f23cd210aedba72a43e48026e7436The Android Open Source Project#include "eloop.h" 148ad0dd2a5c5f23cd210aedba72a43e48026e7436The Android Open Source Project#include "wps_i.h" 158ad0dd2a5c5f23cd210aedba72a43e48026e7436The Android Open Source Project#include "wps_upnp.h" 168ad0dd2a5c5f23cd210aedba72a43e48026e7436The Android Open Source Project#include "wps_upnp_i.h" 178ad0dd2a5c5f23cd210aedba72a43e48026e7436The Android Open Source Project#include "wps_er.h" 188ad0dd2a5c5f23cd210aedba72a43e48026e7436The Android Open Source Project 198ad0dd2a5c5f23cd210aedba72a43e48026e7436The Android Open Source Project 208ad0dd2a5c5f23cd210aedba72a43e48026e7436The Android Open Source Projectstatic void wps_er_ssdp_rx(int sd, void *eloop_ctx, void *sock_ctx) 218ad0dd2a5c5f23cd210aedba72a43e48026e7436The Android Open Source Project{ 228ad0dd2a5c5f23cd210aedba72a43e48026e7436The Android Open Source Project struct wps_er *er = eloop_ctx; 238ad0dd2a5c5f23cd210aedba72a43e48026e7436The Android Open Source Project struct sockaddr_in addr; /* client address */ 248ad0dd2a5c5f23cd210aedba72a43e48026e7436The Android Open Source Project socklen_t addr_len; 258ad0dd2a5c5f23cd210aedba72a43e48026e7436The Android Open Source Project int nread; 268ad0dd2a5c5f23cd210aedba72a43e48026e7436The Android Open Source Project char buf[MULTICAST_MAX_READ], *pos, *pos2, *start; 278ad0dd2a5c5f23cd210aedba72a43e48026e7436The Android Open Source Project int wfa = 0, byebye = 0; 288ad0dd2a5c5f23cd210aedba72a43e48026e7436The Android Open Source Project int max_age = -1; 298ad0dd2a5c5f23cd210aedba72a43e48026e7436The Android Open Source Project char *location = NULL; 308ad0dd2a5c5f23cd210aedba72a43e48026e7436The Android Open Source Project u8 uuid[WPS_UUID_LEN]; 318ad0dd2a5c5f23cd210aedba72a43e48026e7436The Android Open Source Project 328ad0dd2a5c5f23cd210aedba72a43e48026e7436The Android Open Source Project addr_len = sizeof(addr); 338ad0dd2a5c5f23cd210aedba72a43e48026e7436The Android Open Source Project nread = recvfrom(sd, buf, sizeof(buf) - 1, 0, 348ad0dd2a5c5f23cd210aedba72a43e48026e7436The Android Open Source Project (struct sockaddr *) &addr, &addr_len); 358ad0dd2a5c5f23cd210aedba72a43e48026e7436The Android Open Source Project if (nread <= 0) 368ad0dd2a5c5f23cd210aedba72a43e48026e7436The Android Open Source Project return; 378ad0dd2a5c5f23cd210aedba72a43e48026e7436The Android Open Source Project buf[nread] = '\0'; 388ad0dd2a5c5f23cd210aedba72a43e48026e7436The Android Open Source Project if (er->filter_addr.s_addr && 398ad0dd2a5c5f23cd210aedba72a43e48026e7436The Android Open Source Project er->filter_addr.s_addr != addr.sin_addr.s_addr) 408ad0dd2a5c5f23cd210aedba72a43e48026e7436The Android Open Source Project return; 418ad0dd2a5c5f23cd210aedba72a43e48026e7436The Android Open Source Project 428ad0dd2a5c5f23cd210aedba72a43e48026e7436The Android Open Source Project wpa_printf(MSG_DEBUG, "WPS ER: Received SSDP from %s", 438ad0dd2a5c5f23cd210aedba72a43e48026e7436The Android Open Source Project inet_ntoa(addr.sin_addr)); 448ad0dd2a5c5f23cd210aedba72a43e48026e7436The Android Open Source Project wpa_hexdump_ascii(MSG_MSGDUMP, "WPS ER: Received SSDP contents", 458ad0dd2a5c5f23cd210aedba72a43e48026e7436The Android Open Source Project (u8 *) buf, nread); 468ad0dd2a5c5f23cd210aedba72a43e48026e7436The Android Open Source Project 478ad0dd2a5c5f23cd210aedba72a43e48026e7436The Android Open Source Project if (sd == er->multicast_sd) { 488ad0dd2a5c5f23cd210aedba72a43e48026e7436The Android Open Source Project /* Reply to M-SEARCH */ 498ad0dd2a5c5f23cd210aedba72a43e48026e7436The Android Open Source Project if (os_strncmp(buf, "HTTP/1.1 200 OK", 15) != 0) 508ad0dd2a5c5f23cd210aedba72a43e48026e7436The Android Open Source Project return; /* unexpected response header */ 518ad0dd2a5c5f23cd210aedba72a43e48026e7436The Android Open Source Project } else { 528ad0dd2a5c5f23cd210aedba72a43e48026e7436The Android Open Source Project /* Unsolicited message (likely NOTIFY or M-SEARCH) */ 538ad0dd2a5c5f23cd210aedba72a43e48026e7436The Android Open Source Project if (os_strncmp(buf, "NOTIFY ", 7) != 0) 548ad0dd2a5c5f23cd210aedba72a43e48026e7436The Android Open Source Project return; /* only process notifications */ 558ad0dd2a5c5f23cd210aedba72a43e48026e7436The Android Open Source Project } 568ad0dd2a5c5f23cd210aedba72a43e48026e7436The Android Open Source Project 578ad0dd2a5c5f23cd210aedba72a43e48026e7436The Android Open Source Project os_memset(uuid, 0, sizeof(uuid)); 588ad0dd2a5c5f23cd210aedba72a43e48026e7436The Android Open Source Project 598ad0dd2a5c5f23cd210aedba72a43e48026e7436The Android Open Source Project for (start = buf; start && *start; start = pos) { 608ad0dd2a5c5f23cd210aedba72a43e48026e7436The Android Open Source Project pos = os_strchr(start, '\n'); 618ad0dd2a5c5f23cd210aedba72a43e48026e7436The Android Open Source Project if (pos) { 628ad0dd2a5c5f23cd210aedba72a43e48026e7436The Android Open Source Project if (pos[-1] == '\r') 638ad0dd2a5c5f23cd210aedba72a43e48026e7436The Android Open Source Project pos[-1] = '\0'; 646c569d212164aa9334e27abac8884a3d13999420Colin Cross *pos++ = '\0'; 658ad0dd2a5c5f23cd210aedba72a43e48026e7436The Android Open Source Project } 668ad0dd2a5c5f23cd210aedba72a43e48026e7436The Android Open Source Project if (os_strstr(start, "schemas-wifialliance-org:device:" 678ad0dd2a5c5f23cd210aedba72a43e48026e7436The Android Open Source Project "WFADevice:1")) 688ad0dd2a5c5f23cd210aedba72a43e48026e7436The Android Open Source Project wfa = 1; 698ad0dd2a5c5f23cd210aedba72a43e48026e7436The Android Open Source Project if (os_strstr(start, "schemas-wifialliance-org:service:" 708ad0dd2a5c5f23cd210aedba72a43e48026e7436The Android Open Source Project "WFAWLANConfig:1")) 718ad0dd2a5c5f23cd210aedba72a43e48026e7436The Android Open Source Project wfa = 1; 728ad0dd2a5c5f23cd210aedba72a43e48026e7436The Android Open Source Project if (os_strncasecmp(start, "LOCATION:", 9) == 0) { 738ad0dd2a5c5f23cd210aedba72a43e48026e7436The Android Open Source Project start += 9; 748ad0dd2a5c5f23cd210aedba72a43e48026e7436The Android Open Source Project while (*start == ' ') 758ad0dd2a5c5f23cd210aedba72a43e48026e7436The Android Open Source Project start++; 768ad0dd2a5c5f23cd210aedba72a43e48026e7436The Android Open Source Project location = start; 778ad0dd2a5c5f23cd210aedba72a43e48026e7436The Android Open Source Project } else if (os_strncasecmp(start, "NTS:", 4) == 0) { 788ad0dd2a5c5f23cd210aedba72a43e48026e7436The Android Open Source Project if (os_strstr(start, "ssdp:byebye")) 798ad0dd2a5c5f23cd210aedba72a43e48026e7436The Android Open Source Project byebye = 1; 808ad0dd2a5c5f23cd210aedba72a43e48026e7436The Android Open Source Project } else if (os_strncasecmp(start, "CACHE-CONTROL:", 14) == 0) { 818ad0dd2a5c5f23cd210aedba72a43e48026e7436The Android Open Source Project start += 9; 828ad0dd2a5c5f23cd210aedba72a43e48026e7436The Android Open Source Project while (*start == ' ') 838ad0dd2a5c5f23cd210aedba72a43e48026e7436The Android Open Source Project start++; 848527dca81baa73fba64d6724bd498195ed1abbf2Nick Kralevich pos2 = os_strstr(start, "max-age="); 858527dca81baa73fba64d6724bd498195ed1abbf2Nick Kralevich if (pos2 == NULL) 868ad0dd2a5c5f23cd210aedba72a43e48026e7436The Android Open Source Project continue; 878ad0dd2a5c5f23cd210aedba72a43e48026e7436The Android Open Source Project pos2 += 8; 888ad0dd2a5c5f23cd210aedba72a43e48026e7436The Android Open Source Project max_age = atoi(pos2); 898ad0dd2a5c5f23cd210aedba72a43e48026e7436The Android Open Source Project } else if (os_strncasecmp(start, "USN:", 4) == 0) { 908ad0dd2a5c5f23cd210aedba72a43e48026e7436The Android Open Source Project start += 4; 918ad0dd2a5c5f23cd210aedba72a43e48026e7436The Android Open Source Project pos2 = os_strstr(start, "uuid:"); 928ad0dd2a5c5f23cd210aedba72a43e48026e7436The Android Open Source Project if (pos2) { 938ad0dd2a5c5f23cd210aedba72a43e48026e7436The Android Open Source Project pos2 += 5; 948ad0dd2a5c5f23cd210aedba72a43e48026e7436The Android Open Source Project while (*pos2 == ' ') 958ad0dd2a5c5f23cd210aedba72a43e48026e7436The Android Open Source Project pos2++; 968ad0dd2a5c5f23cd210aedba72a43e48026e7436The Android Open Source Project if (uuid_str2bin(pos2, uuid) < 0) { 978ad0dd2a5c5f23cd210aedba72a43e48026e7436The Android Open Source Project wpa_printf(MSG_DEBUG, "WPS ER: " 988ad0dd2a5c5f23cd210aedba72a43e48026e7436The Android Open Source Project "Invalid UUID in USN: %s", 998ad0dd2a5c5f23cd210aedba72a43e48026e7436The Android Open Source Project pos2); 1008ad0dd2a5c5f23cd210aedba72a43e48026e7436The Android Open Source Project return; 1018ad0dd2a5c5f23cd210aedba72a43e48026e7436The Android Open Source Project } 1028ad0dd2a5c5f23cd210aedba72a43e48026e7436The Android Open Source Project } 1038ad0dd2a5c5f23cd210aedba72a43e48026e7436The Android Open Source Project } 1048ad0dd2a5c5f23cd210aedba72a43e48026e7436The Android Open Source Project } 1058ad0dd2a5c5f23cd210aedba72a43e48026e7436The Android Open Source Project 1068ad0dd2a5c5f23cd210aedba72a43e48026e7436The Android Open Source Project if (!wfa) 1078ad0dd2a5c5f23cd210aedba72a43e48026e7436The Android Open Source Project return; /* Not WPS advertisement/reply */ 1088ad0dd2a5c5f23cd210aedba72a43e48026e7436The Android Open Source Project 1098ad0dd2a5c5f23cd210aedba72a43e48026e7436The Android Open Source Project if (byebye) { 1108ad0dd2a5c5f23cd210aedba72a43e48026e7436The Android Open Source Project wps_er_ap_cache_settings(er, &addr.sin_addr); 1118ad0dd2a5c5f23cd210aedba72a43e48026e7436The Android Open Source Project wps_er_ap_remove(er, &addr.sin_addr); 1128ad0dd2a5c5f23cd210aedba72a43e48026e7436The Android Open Source Project return; 1138ad0dd2a5c5f23cd210aedba72a43e48026e7436The Android Open Source Project } 1148ad0dd2a5c5f23cd210aedba72a43e48026e7436The Android Open Source Project 1158ad0dd2a5c5f23cd210aedba72a43e48026e7436The Android Open Source Project if (!location) 1168ad0dd2a5c5f23cd210aedba72a43e48026e7436The Android Open Source Project return; /* Unknown location */ 1178ad0dd2a5c5f23cd210aedba72a43e48026e7436The Android Open Source Project 1188ad0dd2a5c5f23cd210aedba72a43e48026e7436The Android Open Source Project if (max_age < 1) 1198ad0dd2a5c5f23cd210aedba72a43e48026e7436The Android Open Source Project return; /* No max-age reported */ 1208ad0dd2a5c5f23cd210aedba72a43e48026e7436The Android Open Source Project 1218ad0dd2a5c5f23cd210aedba72a43e48026e7436The Android Open Source Project wpa_printf(MSG_DEBUG, "WPS ER: AP discovered: %s " 1228ad0dd2a5c5f23cd210aedba72a43e48026e7436The Android Open Source Project "(packet source: %s max-age: %d)", 1238527dca81baa73fba64d6724bd498195ed1abbf2Nick Kralevich location, inet_ntoa(addr.sin_addr), max_age); 1248ad0dd2a5c5f23cd210aedba72a43e48026e7436The Android Open Source Project 1258ad0dd2a5c5f23cd210aedba72a43e48026e7436The Android Open Source Project wps_er_ap_add(er, uuid, &addr.sin_addr, location, max_age); 1268ad0dd2a5c5f23cd210aedba72a43e48026e7436The Android Open Source Project} 1278ad0dd2a5c5f23cd210aedba72a43e48026e7436The Android Open Source Project 1288ad0dd2a5c5f23cd210aedba72a43e48026e7436The Android Open Source Project 1298ad0dd2a5c5f23cd210aedba72a43e48026e7436The Android Open Source Projectvoid wps_er_send_ssdp_msearch(struct wps_er *er) 1308ad0dd2a5c5f23cd210aedba72a43e48026e7436The Android Open Source Project{ 1318ad0dd2a5c5f23cd210aedba72a43e48026e7436The Android Open Source Project struct wpabuf *msg; 1328ad0dd2a5c5f23cd210aedba72a43e48026e7436The Android Open Source Project struct sockaddr_in dest; 1338ad0dd2a5c5f23cd210aedba72a43e48026e7436The Android Open Source Project 1348ad0dd2a5c5f23cd210aedba72a43e48026e7436The Android Open Source Project msg = wpabuf_alloc(500); 1358ad0dd2a5c5f23cd210aedba72a43e48026e7436The Android Open Source Project if (msg == NULL) 1368ad0dd2a5c5f23cd210aedba72a43e48026e7436The Android Open Source Project return; 1378ad0dd2a5c5f23cd210aedba72a43e48026e7436The Android Open Source Project 1388ad0dd2a5c5f23cd210aedba72a43e48026e7436The Android Open Source Project wpabuf_put_str(msg, 1398ad0dd2a5c5f23cd210aedba72a43e48026e7436The Android Open Source Project "M-SEARCH * HTTP/1.1\r\n" 1408ad0dd2a5c5f23cd210aedba72a43e48026e7436The Android Open Source Project "HOST: 239.255.255.250:1900\r\n" 1418ad0dd2a5c5f23cd210aedba72a43e48026e7436The Android Open Source Project "MAN: \"ssdp:discover\"\r\n" 1428ad0dd2a5c5f23cd210aedba72a43e48026e7436The Android Open Source Project "MX: 3\r\n" 1438ad0dd2a5c5f23cd210aedba72a43e48026e7436The Android Open Source Project "ST: urn:schemas-wifialliance-org:device:WFADevice:1" 1448ad0dd2a5c5f23cd210aedba72a43e48026e7436The Android Open Source Project "\r\n" 1458ad0dd2a5c5f23cd210aedba72a43e48026e7436The Android Open Source Project "\r\n"); 1468ad0dd2a5c5f23cd210aedba72a43e48026e7436The Android Open Source Project 1478ad0dd2a5c5f23cd210aedba72a43e48026e7436The Android Open Source Project os_memset(&dest, 0, sizeof(dest)); 1488ad0dd2a5c5f23cd210aedba72a43e48026e7436The Android Open Source Project dest.sin_family = AF_INET; 1498ad0dd2a5c5f23cd210aedba72a43e48026e7436The Android Open Source Project dest.sin_addr.s_addr = inet_addr(UPNP_MULTICAST_ADDRESS); 1508ad0dd2a5c5f23cd210aedba72a43e48026e7436The Android Open Source Project dest.sin_port = htons(UPNP_MULTICAST_PORT); 1518ad0dd2a5c5f23cd210aedba72a43e48026e7436The Android Open Source Project 1528ad0dd2a5c5f23cd210aedba72a43e48026e7436The Android Open Source Project if (sendto(er->multicast_sd, wpabuf_head(msg), wpabuf_len(msg), 0, 1538ad0dd2a5c5f23cd210aedba72a43e48026e7436The Android Open Source Project (struct sockaddr *) &dest, sizeof(dest)) < 0) 1548ad0dd2a5c5f23cd210aedba72a43e48026e7436The Android Open Source Project wpa_printf(MSG_DEBUG, "WPS ER: M-SEARCH sendto failed: " 1558ad0dd2a5c5f23cd210aedba72a43e48026e7436The Android Open Source Project "%d (%s)", errno, strerror(errno)); 1568ad0dd2a5c5f23cd210aedba72a43e48026e7436The Android Open Source Project 1578ad0dd2a5c5f23cd210aedba72a43e48026e7436The Android Open Source Project wpabuf_free(msg); 1588ad0dd2a5c5f23cd210aedba72a43e48026e7436The Android Open Source Project} 1598ad0dd2a5c5f23cd210aedba72a43e48026e7436The Android Open Source Project 1608ad0dd2a5c5f23cd210aedba72a43e48026e7436The Android Open Source Project 1618ad0dd2a5c5f23cd210aedba72a43e48026e7436The Android Open Source Projectint wps_er_ssdp_init(struct wps_er *er) 1628ad0dd2a5c5f23cd210aedba72a43e48026e7436The Android Open Source Project{ 1638ad0dd2a5c5f23cd210aedba72a43e48026e7436The Android Open Source Project if (add_ssdp_network(er->ifname)) { 1648ad0dd2a5c5f23cd210aedba72a43e48026e7436The Android Open Source Project wpa_printf(MSG_INFO, "WPS ER: Failed to add routing entry for " 1658ad0dd2a5c5f23cd210aedba72a43e48026e7436The Android Open Source Project "SSDP"); 1668ad0dd2a5c5f23cd210aedba72a43e48026e7436The Android Open Source Project return -1; 1678ad0dd2a5c5f23cd210aedba72a43e48026e7436The Android Open Source Project } 1688ad0dd2a5c5f23cd210aedba72a43e48026e7436The Android Open Source Project 1698ad0dd2a5c5f23cd210aedba72a43e48026e7436The Android Open Source Project er->multicast_sd = ssdp_open_multicast_sock(er->ip_addr); 1708ad0dd2a5c5f23cd210aedba72a43e48026e7436The Android Open Source Project if (er->multicast_sd < 0) { 1718ad0dd2a5c5f23cd210aedba72a43e48026e7436The Android Open Source Project wpa_printf(MSG_INFO, "WPS ER: Failed to open multicast socket " 1728ad0dd2a5c5f23cd210aedba72a43e48026e7436The Android Open Source Project "for SSDP"); 1738ad0dd2a5c5f23cd210aedba72a43e48026e7436The Android Open Source Project return -1; 1748ad0dd2a5c5f23cd210aedba72a43e48026e7436The Android Open Source Project } 1758ad0dd2a5c5f23cd210aedba72a43e48026e7436The Android Open Source Project 1768ad0dd2a5c5f23cd210aedba72a43e48026e7436The Android Open Source Project er->ssdp_sd = ssdp_listener_open(); 1778ad0dd2a5c5f23cd210aedba72a43e48026e7436The Android Open Source Project if (er->ssdp_sd < 0) { 1788ad0dd2a5c5f23cd210aedba72a43e48026e7436The Android Open Source Project wpa_printf(MSG_INFO, "WPS ER: Failed to open SSDP listener " 1798ad0dd2a5c5f23cd210aedba72a43e48026e7436The Android Open Source Project "socket"); 1808ad0dd2a5c5f23cd210aedba72a43e48026e7436The Android Open Source Project return -1; 1818ad0dd2a5c5f23cd210aedba72a43e48026e7436The Android Open Source Project } 1828ad0dd2a5c5f23cd210aedba72a43e48026e7436The Android Open Source Project 1838ad0dd2a5c5f23cd210aedba72a43e48026e7436The Android Open Source Project if (eloop_register_sock(er->multicast_sd, EVENT_TYPE_READ, 1848ad0dd2a5c5f23cd210aedba72a43e48026e7436The Android Open Source Project wps_er_ssdp_rx, er, NULL) || 1858ad0dd2a5c5f23cd210aedba72a43e48026e7436The Android Open Source Project eloop_register_sock(er->ssdp_sd, EVENT_TYPE_READ, 1868ad0dd2a5c5f23cd210aedba72a43e48026e7436The Android Open Source Project wps_er_ssdp_rx, er, NULL)) 1878ad0dd2a5c5f23cd210aedba72a43e48026e7436The Android Open Source Project return -1; 1888ad0dd2a5c5f23cd210aedba72a43e48026e7436The Android Open Source Project 1898ad0dd2a5c5f23cd210aedba72a43e48026e7436The Android Open Source Project wps_er_send_ssdp_msearch(er); 1908ad0dd2a5c5f23cd210aedba72a43e48026e7436The Android Open Source Project 1918ad0dd2a5c5f23cd210aedba72a43e48026e7436The Android Open Source Project return 0; 1928ad0dd2a5c5f23cd210aedba72a43e48026e7436The Android Open Source Project} 1938ad0dd2a5c5f23cd210aedba72a43e48026e7436The Android Open Source Project 1948ad0dd2a5c5f23cd210aedba72a43e48026e7436The Android Open Source Project 1958ad0dd2a5c5f23cd210aedba72a43e48026e7436The Android Open Source Projectvoid wps_er_ssdp_deinit(struct wps_er *er) 1968ad0dd2a5c5f23cd210aedba72a43e48026e7436The Android Open Source Project{ 1978ad0dd2a5c5f23cd210aedba72a43e48026e7436The Android Open Source Project if (er->multicast_sd >= 0) { 1988ad0dd2a5c5f23cd210aedba72a43e48026e7436The Android Open Source Project eloop_unregister_sock(er->multicast_sd, EVENT_TYPE_READ); 1998ad0dd2a5c5f23cd210aedba72a43e48026e7436The Android Open Source Project close(er->multicast_sd); 2008ad0dd2a5c5f23cd210aedba72a43e48026e7436The Android Open Source Project } 2018ad0dd2a5c5f23cd210aedba72a43e48026e7436The Android Open Source Project if (er->ssdp_sd >= 0) { 2028ad0dd2a5c5f23cd210aedba72a43e48026e7436The Android Open Source Project eloop_unregister_sock(er->ssdp_sd, EVENT_TYPE_READ); 2038ad0dd2a5c5f23cd210aedba72a43e48026e7436The Android Open Source Project close(er->ssdp_sd); 2048ad0dd2a5c5f23cd210aedba72a43e48026e7436The Android Open Source Project } 2058ad0dd2a5c5f23cd210aedba72a43e48026e7436The Android Open Source Project} 2068ad0dd2a5c5f23cd210aedba72a43e48026e7436The Android Open Source Project