LCOV - code coverage report
Current view: top level - src/wps - wps_er_ssdp.c (source / functions) Hit Total Coverage
Test: wpa_supplicant hwsim test run 1388240082 Lines: 90 110 81.8 %
Date: 2013-12-28 Functions: 4 4 100.0 %
Branches: 49 74 66.2 %

           Branch data     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                 :         50 : static void wps_er_ssdp_rx(int sd, void *eloop_ctx, void *sock_ctx)
      21                 :            : {
      22                 :         50 :         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                 :         50 :         int wfa = 0, byebye = 0;
      28                 :         50 :         int max_age = -1;
      29                 :         50 :         char *location = NULL;
      30                 :            :         u8 uuid[WPS_UUID_LEN];
      31                 :            : 
      32                 :         50 :         addr_len = sizeof(addr);
      33                 :         50 :         nread = recvfrom(sd, buf, sizeof(buf) - 1, 0,
      34                 :            :                          (struct sockaddr *) &addr, &addr_len);
      35         [ -  + ]:         50 :         if (nread <= 0)
      36                 :          0 :                 return;
      37                 :         50 :         buf[nread] = '\0';
      38 [ -  + ][ #  # ]:         50 :         if (er->filter_addr.s_addr &&
      39                 :          0 :             er->filter_addr.s_addr != addr.sin_addr.s_addr)
      40                 :          0 :                 return;
      41                 :            : 
      42                 :         50 :         wpa_printf(MSG_DEBUG, "WPS ER: Received SSDP from %s",
      43                 :            :                    inet_ntoa(addr.sin_addr));
      44                 :         50 :         wpa_hexdump_ascii(MSG_MSGDUMP, "WPS ER: Received SSDP contents",
      45                 :            :                           (u8 *) buf, nread);
      46                 :            : 
      47         [ +  + ]:         50 :         if (sd == er->multicast_sd) {
      48                 :            :                 /* Reply to M-SEARCH */
      49         [ -  + ]:         16 :                 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         [ +  + ]:         34 :                 if (os_strncmp(buf, "NOTIFY ", 7) != 0)
      54                 :          2 :                         return; /* only process notifications */
      55                 :            :         }
      56                 :            : 
      57                 :         48 :         os_memset(uuid, 0, sizeof(uuid));
      58                 :            : 
      59 [ +  - ][ +  + ]:        456 :         for (start = buf; start && *start; start = pos) {
      60                 :        408 :                 pos = os_strchr(start, '\n');
      61         [ +  - ]:        408 :                 if (pos) {
      62         [ +  - ]:        408 :                         if (pos[-1] == '\r')
      63                 :        408 :                                 pos[-1] = '\0';
      64                 :        408 :                         *pos++ = '\0';
      65                 :            :                 }
      66         [ +  + ]:        408 :                 if (os_strstr(start, "schemas-wifialliance-org:device:"
      67                 :            :                               "WFADevice:1"))
      68                 :         24 :                         wfa = 1;
      69         [ +  + ]:        408 :                 if (os_strstr(start, "schemas-wifialliance-org:service:"
      70                 :            :                               "WFAWLANConfig:1"))
      71                 :         24 :                         wfa = 1;
      72         [ +  + ]:        408 :                 if (os_strncasecmp(start, "LOCATION:", 9) == 0) {
      73                 :         24 :                         start += 9;
      74         [ +  + ]:         48 :                         while (*start == ' ')
      75                 :         24 :                                 start++;
      76                 :         24 :                         location = start;
      77         [ +  + ]:        384 :                 } else if (os_strncasecmp(start, "NTS:", 4) == 0) {
      78         [ +  + ]:         32 :                         if (os_strstr(start, "ssdp:byebye"))
      79                 :         24 :                                 byebye = 1;
      80         [ +  + ]:        352 :                 } else if (os_strncasecmp(start, "CACHE-CONTROL:", 14) == 0) {
      81                 :         48 :                         start += 9;
      82         [ -  + ]:         48 :                         while (*start == ' ')
      83                 :          0 :                                 start++;
      84                 :         48 :                         pos2 = os_strstr(start, "max-age=");
      85         [ -  + ]:         48 :                         if (pos2 == NULL)
      86                 :          0 :                                 continue;
      87                 :         48 :                         pos2 += 8;
      88                 :         48 :                         max_age = atoi(pos2);
      89         [ +  + ]:        304 :                 } else if (os_strncasecmp(start, "USN:", 4) == 0) {
      90                 :         48 :                         start += 4;
      91                 :         48 :                         pos2 = os_strstr(start, "uuid:");
      92         [ +  - ]:         48 :                         if (pos2) {
      93                 :         48 :                                 pos2 += 5;
      94         [ -  + ]:         48 :                                 while (*pos2 == ' ')
      95                 :          0 :                                         pos2++;
      96         [ -  + ]:         48 :                                 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         [ +  + ]:         48 :         if (!wfa)
     107                 :         24 :                 return; /* Not WPS advertisement/reply */
     108                 :            : 
     109         [ +  + ]:         24 :         if (byebye) {
     110                 :         12 :                 wps_er_ap_cache_settings(er, &addr.sin_addr);
     111                 :         12 :                 wps_er_ap_remove(er, &addr.sin_addr);
     112                 :         12 :                 return;
     113                 :            :         }
     114                 :            : 
     115         [ -  + ]:         12 :         if (!location)
     116                 :          0 :                 return; /* Unknown location */
     117                 :            : 
     118         [ -  + ]:         12 :         if (max_age < 1)
     119                 :          0 :                 return; /* No max-age reported */
     120                 :            : 
     121                 :         12 :         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                 :         50 :         wps_er_ap_add(er, uuid, &addr.sin_addr, location, max_age);
     126                 :            : }
     127                 :            : 
     128                 :            : 
     129                 :          2 : void wps_er_send_ssdp_msearch(struct wps_er *er)
     130                 :            : {
     131                 :            :         struct wpabuf *msg;
     132                 :            :         struct sockaddr_in dest;
     133                 :            : 
     134                 :          2 :         msg = wpabuf_alloc(500);
     135         [ -  + ]:          2 :         if (msg == NULL)
     136                 :          2 :                 return;
     137                 :            : 
     138                 :          2 :         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                 :          2 :         os_memset(&dest, 0, sizeof(dest));
     148                 :          2 :         dest.sin_family = AF_INET;
     149                 :          2 :         dest.sin_addr.s_addr = inet_addr(UPNP_MULTICAST_ADDRESS);
     150                 :          2 :         dest.sin_port = htons(UPNP_MULTICAST_PORT);
     151                 :            : 
     152         [ -  + ]:          2 :         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                 :          2 :         wpabuf_free(msg);
     158                 :            : }
     159                 :            : 
     160                 :            : 
     161                 :          1 : int wps_er_ssdp_init(struct wps_er *er)
     162                 :            : {
     163         [ -  + ]:          1 :         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         [ +  - ]:          1 :         er->multicast_sd = ssdp_open_multicast_sock(er->ip_addr,
     170                 :          1 :                                                     er->forced_ifname ?
     171                 :            :                                                     er->ifname : NULL);
     172         [ -  + ]:          1 :         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                 :          1 :         er->ssdp_sd = ssdp_listener_open();
     179         [ -  + ]:          1 :         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         [ +  - ]:          1 :         if (eloop_register_sock(er->multicast_sd, EVENT_TYPE_READ,
     186         [ -  + ]:          1 :                                 wps_er_ssdp_rx, er, NULL) ||
     187                 :          1 :             eloop_register_sock(er->ssdp_sd, EVENT_TYPE_READ,
     188                 :            :                                 wps_er_ssdp_rx, er, NULL))
     189                 :          0 :                 return -1;
     190                 :            : 
     191                 :          1 :         wps_er_send_ssdp_msearch(er);
     192                 :            : 
     193                 :          1 :         return 0;
     194                 :            : }
     195                 :            : 
     196                 :            : 
     197                 :          1 : void wps_er_ssdp_deinit(struct wps_er *er)
     198                 :            : {
     199         [ +  - ]:          1 :         if (er->multicast_sd >= 0) {
     200                 :          1 :                 eloop_unregister_sock(er->multicast_sd, EVENT_TYPE_READ);
     201                 :          1 :                 close(er->multicast_sd);
     202                 :            :         }
     203         [ +  - ]:          1 :         if (er->ssdp_sd >= 0) {
     204                 :          1 :                 eloop_unregister_sock(er->ssdp_sd, EVENT_TYPE_READ);
     205                 :          1 :                 close(er->ssdp_sd);
     206                 :            :         }
     207                 :          1 : }

Generated by: LCOV version 1.9