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 1422976643 Lines: 86 110 78.2 %
Date: 2015-02-03 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          91 : static void wps_er_ssdp_rx(int sd, void *eloop_ctx, void *sock_ctx)
      21             : {
      22          91 :         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          91 :         int wfa = 0, byebye = 0;
      28          91 :         int max_age = -1;
      29          91 :         char *location = NULL;
      30             :         u8 uuid[WPS_UUID_LEN];
      31             : 
      32          91 :         addr_len = sizeof(addr);
      33          91 :         nread = recvfrom(sd, buf, sizeof(buf) - 1, 0,
      34             :                          (struct sockaddr *) &addr, &addr_len);
      35          91 :         if (nread <= 0)
      36          51 :                 return;
      37          91 :         buf[nread] = '\0';
      38          91 :         if (er->filter_addr.s_addr &&
      39           0 :             er->filter_addr.s_addr != addr.sin_addr.s_addr)
      40           0 :                 return;
      41             : 
      42          91 :         wpa_printf(MSG_DEBUG, "WPS ER: Received SSDP from %s",
      43             :                    inet_ntoa(addr.sin_addr));
      44          91 :         wpa_hexdump_ascii(MSG_MSGDUMP, "WPS ER: Received SSDP contents",
      45             :                           (u8 *) buf, nread);
      46             : 
      47          91 :         if (sd == er->multicast_sd) {
      48             :                 /* Reply to M-SEARCH */
      49          80 :                 if (os_strncmp(buf, "HTTP/1.1 200 OK", 15) != 0)
      50           0 :                         return; /* unexpected response header */
      51             :         } else {
      52             :                 /* Unsolicited message (likely NOTIFY or M-SEARCH) */
      53          11 :                 if (os_strncmp(buf, "NOTIFY ", 7) != 0)
      54          11 :                         return; /* only process notifications */
      55             :         }
      56             : 
      57          80 :         os_memset(uuid, 0, sizeof(uuid));
      58             : 
      59         800 :         for (start = buf; start && *start; start = pos) {
      60         720 :                 pos = os_strchr(start, '\n');
      61         720 :                 if (pos) {
      62         720 :                         if (pos[-1] == '\r')
      63         720 :                                 pos[-1] = '\0';
      64         720 :                         *pos++ = '\0';
      65             :                 }
      66         720 :                 if (os_strstr(start, "schemas-wifialliance-org:device:"
      67             :                               "WFADevice:1"))
      68          40 :                         wfa = 1;
      69         720 :                 if (os_strstr(start, "schemas-wifialliance-org:service:"
      70             :                               "WFAWLANConfig:1"))
      71          40 :                         wfa = 1;
      72         720 :                 if (os_strncasecmp(start, "LOCATION:", 9) == 0) {
      73          80 :                         start += 9;
      74         240 :                         while (*start == ' ')
      75          80 :                                 start++;
      76          80 :                         location = start;
      77         640 :                 } else if (os_strncasecmp(start, "NTS:", 4) == 0) {
      78           0 :                         if (os_strstr(start, "ssdp:byebye"))
      79           0 :                                 byebye = 1;
      80         640 :                 } else if (os_strncasecmp(start, "CACHE-CONTROL:", 14) == 0) {
      81          80 :                         start += 9;
      82         160 :                         while (*start == ' ')
      83           0 :                                 start++;
      84          80 :                         pos2 = os_strstr(start, "max-age=");
      85          80 :                         if (pos2 == NULL)
      86           0 :                                 continue;
      87          80 :                         pos2 += 8;
      88          80 :                         max_age = atoi(pos2);
      89         560 :                 } else if (os_strncasecmp(start, "USN:", 4) == 0) {
      90          80 :                         start += 4;
      91          80 :                         pos2 = os_strstr(start, "uuid:");
      92          80 :                         if (pos2) {
      93          80 :                                 pos2 += 5;
      94         160 :                                 while (*pos2 == ' ')
      95           0 :                                         pos2++;
      96          80 :                                 if (uuid_str2bin(pos2, uuid) < 0) {
      97           0 :                                         wpa_printf(MSG_DEBUG, "WPS ER: "
      98             :                                                    "Invalid UUID in USN: %s",
      99             :                                                    pos2);
     100           0 :                                         return;
     101             :                                 }
     102             :                         }
     103             :                 }
     104             :         }
     105             : 
     106          80 :         if (!wfa)
     107          40 :                 return; /* Not WPS advertisement/reply */
     108             : 
     109          40 :         if (byebye) {
     110           0 :                 wps_er_ap_cache_settings(er, &addr.sin_addr);
     111           0 :                 wps_er_ap_remove(er, &addr.sin_addr);
     112           0 :                 return;
     113             :         }
     114             : 
     115          40 :         if (!location)
     116           0 :                 return; /* Unknown location */
     117             : 
     118          40 :         if (max_age < 1)
     119           0 :                 return; /* No max-age reported */
     120             : 
     121          40 :         wpa_printf(MSG_DEBUG, "WPS ER: AP discovered: %s "
     122             :                    "(packet source: %s  max-age: %d)",
     123             :                    location, inet_ntoa(addr.sin_addr), max_age);
     124             : 
     125          40 :         wps_er_ap_add(er, uuid, &addr.sin_addr, location, max_age);
     126             : }
     127             : 
     128             : 
     129          11 : void wps_er_send_ssdp_msearch(struct wps_er *er)
     130             : {
     131             :         struct wpabuf *msg;
     132             :         struct sockaddr_in dest;
     133             : 
     134          11 :         msg = wpabuf_alloc(500);
     135          11 :         if (msg == NULL)
     136          11 :                 return;
     137             : 
     138          11 :         wpabuf_put_str(msg,
     139             :                        "M-SEARCH * HTTP/1.1\r\n"
     140             :                        "HOST: 239.255.255.250:1900\r\n"
     141             :                        "MAN: \"ssdp:discover\"\r\n"
     142             :                        "MX: 3\r\n"
     143             :                        "ST: urn:schemas-wifialliance-org:device:WFADevice:1"
     144             :                        "\r\n"
     145             :                        "\r\n");
     146             : 
     147          11 :         os_memset(&dest, 0, sizeof(dest));
     148          11 :         dest.sin_family = AF_INET;
     149          11 :         dest.sin_addr.s_addr = inet_addr(UPNP_MULTICAST_ADDRESS);
     150          11 :         dest.sin_port = htons(UPNP_MULTICAST_PORT);
     151             : 
     152          11 :         if (sendto(er->multicast_sd, wpabuf_head(msg), wpabuf_len(msg), 0,
     153             :                    (struct sockaddr *) &dest, sizeof(dest)) < 0)
     154           0 :                 wpa_printf(MSG_DEBUG, "WPS ER: M-SEARCH sendto failed: "
     155           0 :                            "%d (%s)", errno, strerror(errno));
     156             : 
     157          11 :         wpabuf_free(msg);
     158             : }
     159             : 
     160             : 
     161          10 : int wps_er_ssdp_init(struct wps_er *er)
     162             : {
     163          10 :         if (add_ssdp_network(er->ifname)) {
     164           0 :                 wpa_printf(MSG_INFO, "WPS ER: Failed to add routing entry for "
     165             :                            "SSDP");
     166           0 :                 return -1;
     167             :         }
     168             : 
     169          10 :         er->multicast_sd = ssdp_open_multicast_sock(er->ip_addr,
     170          10 :                                                     er->forced_ifname ?
     171             :                                                     er->ifname : NULL);
     172          10 :         if (er->multicast_sd < 0) {
     173           0 :                 wpa_printf(MSG_INFO, "WPS ER: Failed to open multicast socket "
     174             :                            "for SSDP");
     175           0 :                 return -1;
     176             :         }
     177             : 
     178          10 :         er->ssdp_sd = ssdp_listener_open();
     179          10 :         if (er->ssdp_sd < 0) {
     180           0 :                 wpa_printf(MSG_INFO, "WPS ER: Failed to open SSDP listener "
     181             :                            "socket");
     182           0 :                 return -1;
     183             :         }
     184             : 
     185          10 :         if (eloop_register_sock(er->multicast_sd, EVENT_TYPE_READ,
     186          10 :                                 wps_er_ssdp_rx, er, NULL) ||
     187          10 :             eloop_register_sock(er->ssdp_sd, EVENT_TYPE_READ,
     188             :                                 wps_er_ssdp_rx, er, NULL))
     189           0 :                 return -1;
     190             : 
     191          10 :         wps_er_send_ssdp_msearch(er);
     192             : 
     193          10 :         return 0;
     194             : }
     195             : 
     196             : 
     197          10 : void wps_er_ssdp_deinit(struct wps_er *er)
     198             : {
     199          10 :         if (er->multicast_sd >= 0) {
     200          10 :                 eloop_unregister_sock(er->multicast_sd, EVENT_TYPE_READ);
     201          10 :                 close(er->multicast_sd);
     202             :         }
     203          10 :         if (er->ssdp_sd >= 0) {
     204          10 :                 eloop_unregister_sock(er->ssdp_sd, EVENT_TYPE_READ);
     205          10 :                 close(er->ssdp_sd);
     206             :         }
     207          10 : }

Generated by: LCOV version 1.10