LCOV - code coverage report
Current view: top level - src/wps - wps_er_ssdp.c (source / functions) Hit Total Coverage
Test: wpa_supplicant/hostapd combined for hwsim test run 1443382998 Lines: 100 108 92.6 %
Date: 2015-09-27 Functions: 4 4 100.0 %

          Line data    Source code
       1             : /*
       2             :  * Wi-Fi Protected Setup - External Registrar (SSDP)
       3             :  * Copyright (c) 2009, Jouni Malinen <j@w1.fi>
       4             :  *
       5             :  * This software may be distributed under the terms of the BSD license.
       6             :  * See README for more details.
       7             :  */
       8             : 
       9             : #include "includes.h"
      10             : 
      11             : #include "common.h"
      12             : #include "uuid.h"
      13             : #include "eloop.h"
      14             : #include "wps_i.h"
      15             : #include "wps_upnp.h"
      16             : #include "wps_upnp_i.h"
      17             : #include "wps_er.h"
      18             : 
      19             : 
      20         364 : static void wps_er_ssdp_rx(int sd, void *eloop_ctx, void *sock_ctx)
      21             : {
      22         364 :         struct wps_er *er = eloop_ctx;
      23             :         struct sockaddr_in addr; /* client address */
      24             :         socklen_t addr_len;
      25             :         int nread;
      26             :         char buf[MULTICAST_MAX_READ], *pos, *pos2, *start;
      27         364 :         int wfa = 0, byebye = 0;
      28         364 :         int max_age = -1;
      29         364 :         char *location = NULL;
      30             :         u8 uuid[WPS_UUID_LEN];
      31             : 
      32         364 :         addr_len = sizeof(addr);
      33         364 :         nread = recvfrom(sd, buf, sizeof(buf) - 1, 0,
      34             :                          (struct sockaddr *) &addr, &addr_len);
      35         364 :         if (nread <= 0)
      36         227 :                 return;
      37         364 :         buf[nread] = '\0';
      38         366 :         if (er->filter_addr.s_addr &&
      39           2 :             er->filter_addr.s_addr != addr.sin_addr.s_addr)
      40           2 :                 return;
      41             : 
      42         362 :         wpa_printf(MSG_DEBUG, "WPS ER: Received SSDP from %s",
      43             :                    inet_ntoa(addr.sin_addr));
      44         362 :         wpa_hexdump_ascii(MSG_MSGDUMP, "WPS ER: Received SSDP contents",
      45             :                           (u8 *) buf, nread);
      46             : 
      47         362 :         if (sd == er->multicast_sd) {
      48             :                 /* Reply to M-SEARCH */
      49         223 :                 if (os_strncmp(buf, "HTTP/1.1 200 OK", 15) != 0)
      50           1 :                         return; /* unexpected response header */
      51             :         } else {
      52             :                 /* Unsolicited message (likely NOTIFY or M-SEARCH) */
      53         139 :                 if (os_strncmp(buf, "NOTIFY ", 7) != 0)
      54          50 :                         return; /* only process notifications */
      55             :         }
      56             : 
      57         311 :         os_memset(uuid, 0, sizeof(uuid));
      58             : 
      59        2839 :         for (start = buf; start && *start; start = pos) {
      60        2531 :                 pos = os_strchr(start, '\n');
      61        2531 :                 if (pos) {
      62        2531 :                         if (pos[-1] == '\r')
      63        2531 :                                 pos[-1] = '\0';
      64        2531 :                         *pos++ = '\0';
      65             :                 }
      66        2531 :                 if (os_strstr(start, "schemas-wifialliance-org:device:"
      67             :                               "WFADevice:1"))
      68         168 :                         wfa = 1;
      69        2531 :                 if (os_strstr(start, "schemas-wifialliance-org:service:"
      70             :                               "WFAWLANConfig:1"))
      71         134 :                         wfa = 1;
      72        2531 :                 if (os_strncasecmp(start, "LOCATION:", 9) == 0) {
      73         242 :                         start += 9;
      74         692 :                         while (*start == ' ')
      75         208 :                                 start++;
      76         242 :                         location = start;
      77        2289 :                 } else if (os_strncasecmp(start, "NTS:", 4) == 0) {
      78          92 :                         if (os_strstr(start, "ssdp:byebye"))
      79          59 :                                 byebye = 1;
      80        2197 :                 } else if (os_strncasecmp(start, "CACHE-CONTROL:", 14) == 0) {
      81         300 :                         start += 14;
      82         300 :                         pos2 = os_strstr(start, "max-age=");
      83         300 :                         if (pos2 == NULL)
      84           1 :                                 continue;
      85         299 :                         pos2 += 8;
      86         299 :                         max_age = atoi(pos2);
      87        1897 :                 } else if (os_strncasecmp(start, "USN:", 4) == 0) {
      88         270 :                         start += 4;
      89         270 :                         pos2 = os_strstr(start, "uuid:");
      90         270 :                         if (pos2) {
      91         268 :                                 pos2 += 5;
      92         546 :                                 while (*pos2 == ' ')
      93          10 :                                         pos2++;
      94         268 :                                 if (uuid_str2bin(pos2, uuid) < 0) {
      95           3 :                                         wpa_printf(MSG_DEBUG, "WPS ER: "
      96             :                                                    "Invalid UUID in USN: %s",
      97             :                                                    pos2);
      98           3 :                                         return;
      99             :                                 }
     100             :                         }
     101             :                 }
     102             :         }
     103             : 
     104         308 :         if (!wfa)
     105         139 :                 return; /* Not WPS advertisement/reply */
     106             : 
     107         169 :         if (byebye) {
     108          30 :                 wps_er_ap_cache_settings(er, &addr.sin_addr);
     109          30 :                 wps_er_ap_remove(er, &addr.sin_addr);
     110          30 :                 return;
     111             :         }
     112             : 
     113         139 :         if (!location)
     114           1 :                 return; /* Unknown location */
     115             : 
     116         138 :         if (max_age < 1)
     117           1 :                 return; /* No max-age reported */
     118             : 
     119         137 :         wpa_printf(MSG_DEBUG, "WPS ER: AP discovered: %s "
     120             :                    "(packet source: %s  max-age: %d)",
     121             :                    location, inet_ntoa(addr.sin_addr), max_age);
     122             : 
     123         137 :         wps_er_ap_add(er, uuid, &addr.sin_addr, location, max_age);
     124             : }
     125             : 
     126             : 
     127          52 : void wps_er_send_ssdp_msearch(struct wps_er *er)
     128             : {
     129             :         struct wpabuf *msg;
     130             :         struct sockaddr_in dest;
     131             : 
     132          52 :         msg = wpabuf_alloc(500);
     133          52 :         if (msg == NULL)
     134          52 :                 return;
     135             : 
     136          52 :         wpabuf_put_str(msg,
     137             :                        "M-SEARCH * HTTP/1.1\r\n"
     138             :                        "HOST: 239.255.255.250:1900\r\n"
     139             :                        "MAN: \"ssdp:discover\"\r\n"
     140             :                        "MX: 3\r\n"
     141             :                        "ST: urn:schemas-wifialliance-org:device:WFADevice:1"
     142             :                        "\r\n"
     143             :                        "\r\n");
     144             : 
     145          52 :         os_memset(&dest, 0, sizeof(dest));
     146          52 :         dest.sin_family = AF_INET;
     147          52 :         dest.sin_addr.s_addr = inet_addr(UPNP_MULTICAST_ADDRESS);
     148          52 :         dest.sin_port = htons(UPNP_MULTICAST_PORT);
     149             : 
     150          52 :         if (sendto(er->multicast_sd, wpabuf_head(msg), wpabuf_len(msg), 0,
     151             :                    (struct sockaddr *) &dest, sizeof(dest)) < 0)
     152           0 :                 wpa_printf(MSG_DEBUG, "WPS ER: M-SEARCH sendto failed: "
     153           0 :                            "%d (%s)", errno, strerror(errno));
     154             : 
     155          52 :         wpabuf_free(msg);
     156             : }
     157             : 
     158             : 
     159          52 : int wps_er_ssdp_init(struct wps_er *er)
     160             : {
     161          52 :         if (add_ssdp_network(er->ifname)) {
     162           0 :                 wpa_printf(MSG_INFO, "WPS ER: Failed to add routing entry for "
     163             :                            "SSDP");
     164           0 :                 return -1;
     165             :         }
     166             : 
     167          52 :         er->multicast_sd = ssdp_open_multicast_sock(er->ip_addr,
     168          52 :                                                     er->forced_ifname ?
     169             :                                                     er->ifname : NULL);
     170          52 :         if (er->multicast_sd < 0) {
     171           0 :                 wpa_printf(MSG_INFO, "WPS ER: Failed to open multicast socket "
     172             :                            "for SSDP");
     173           0 :                 return -1;
     174             :         }
     175             : 
     176          52 :         er->ssdp_sd = ssdp_listener_open();
     177          52 :         if (er->ssdp_sd < 0) {
     178           0 :                 wpa_printf(MSG_INFO, "WPS ER: Failed to open SSDP listener "
     179             :                            "socket");
     180           0 :                 return -1;
     181             :         }
     182             : 
     183          52 :         if (eloop_register_sock(er->multicast_sd, EVENT_TYPE_READ,
     184          51 :                                 wps_er_ssdp_rx, er, NULL) ||
     185          51 :             eloop_register_sock(er->ssdp_sd, EVENT_TYPE_READ,
     186             :                                 wps_er_ssdp_rx, er, NULL))
     187           1 :                 return -1;
     188             : 
     189          51 :         wps_er_send_ssdp_msearch(er);
     190             : 
     191          51 :         return 0;
     192             : }
     193             : 
     194             : 
     195          55 : void wps_er_ssdp_deinit(struct wps_er *er)
     196             : {
     197          55 :         if (er->multicast_sd >= 0) {
     198          52 :                 eloop_unregister_sock(er->multicast_sd, EVENT_TYPE_READ);
     199          52 :                 close(er->multicast_sd);
     200             :         }
     201          55 :         if (er->ssdp_sd >= 0) {
     202          52 :                 eloop_unregister_sock(er->ssdp_sd, EVENT_TYPE_READ);
     203          52 :                 close(er->ssdp_sd);
     204             :         }
     205          55 : }

Generated by: LCOV version 1.10