LCOV - code coverage report
Current view: top level - src/p2p - p2p_parse.c (source / functions) Hit Total Coverage
Test: wpa_supplicant hwsim test run 1388943092 Lines: 292 411 71.0 %
Date: 2014-01-05 Functions: 12 12 100.0 %
Branches: 125 217 57.6 %

           Branch data     Line data    Source code
       1                 :            : /*
       2                 :            :  * P2P - IE parser
       3                 :            :  * Copyright (c) 2009-2010, Atheros Communications
       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 "common/ieee802_11_defs.h"
      13                 :            : #include "common/ieee802_11_common.h"
      14                 :            : #include "wps/wps_i.h"
      15                 :            : #include "p2p_i.h"
      16                 :            : 
      17                 :            : 
      18                 :       5028 : static int p2p_parse_attribute(u8 id, const u8 *data, u16 len,
      19                 :            :                                struct p2p_message *msg)
      20                 :            : {
      21                 :            :         const u8 *pos;
      22                 :            :         size_t i, nlen;
      23                 :            :         char devtype[WPS_DEV_TYPE_BUFSIZE];
      24                 :            : 
      25   [ +  +  +  +  :       5028 :         switch (id) {
          +  +  +  +  +  
          +  +  +  +  +  
             -  +  -  -  
                      - ]
      26                 :            :         case P2P_ATTR_CAPABILITY:
      27         [ -  + ]:       2090 :                 if (len < 2) {
      28                 :          0 :                         wpa_printf(MSG_DEBUG, "P2P: Too short Capability "
      29                 :            :                                    "attribute (length %d)", len);
      30                 :          0 :                         return -1;
      31                 :            :                 }
      32                 :       2090 :                 msg->capability = data;
      33                 :       2090 :                 wpa_printf(MSG_DEBUG, "P2P: * Device Capability %02x "
      34                 :            :                            "Group Capability %02x",
      35                 :       4180 :                            data[0], data[1]);
      36                 :       2090 :                 break;
      37                 :            :         case P2P_ATTR_DEVICE_ID:
      38         [ -  + ]:          3 :                 if (len < ETH_ALEN) {
      39                 :          0 :                         wpa_printf(MSG_DEBUG, "P2P: Too short Device ID "
      40                 :            :                                    "attribute (length %d)", len);
      41                 :          0 :                         return -1;
      42                 :            :                 }
      43                 :          3 :                 msg->device_id = data;
      44                 :          3 :                 wpa_printf(MSG_DEBUG, "P2P: * Device ID " MACSTR,
      45                 :         18 :                            MAC2STR(msg->device_id));
      46                 :          3 :                 break;
      47                 :            :         case P2P_ATTR_GROUP_OWNER_INTENT:
      48         [ -  + ]:         93 :                 if (len < 1) {
      49                 :          0 :                         wpa_printf(MSG_DEBUG, "P2P: Too short GO Intent "
      50                 :            :                                    "attribute (length %d)", len);
      51                 :          0 :                         return -1;
      52                 :            :                 }
      53                 :         93 :                 msg->go_intent = data;
      54                 :         93 :                 wpa_printf(MSG_DEBUG, "P2P: * GO Intent: Intent %u "
      55                 :        186 :                            "Tie breaker %u", data[0] >> 1, data[0] & 0x01);
      56                 :         93 :                 break;
      57                 :            :         case P2P_ATTR_STATUS:
      58         [ -  + ]:         95 :                 if (len < 1) {
      59                 :          0 :                         wpa_printf(MSG_DEBUG, "P2P: Too short Status "
      60                 :            :                                    "attribute (length %d)", len);
      61                 :          0 :                         return -1;
      62                 :            :                 }
      63                 :         95 :                 msg->status = data;
      64                 :         95 :                 wpa_printf(MSG_DEBUG, "P2P: * Status: %d", data[0]);
      65                 :         95 :                 break;
      66                 :            :         case P2P_ATTR_LISTEN_CHANNEL:
      67         [ -  + ]:        770 :                 if (len == 0) {
      68                 :          0 :                         wpa_printf(MSG_DEBUG, "P2P: * Listen Channel: Ignore "
      69                 :            :                                    "null channel");
      70                 :          0 :                         break;
      71                 :            :                 }
      72         [ -  + ]:        770 :                 if (len < 5) {
      73                 :          0 :                         wpa_printf(MSG_DEBUG, "P2P: Too short Listen Channel "
      74                 :            :                                    "attribute (length %d)", len);
      75                 :          0 :                         return -1;
      76                 :            :                 }
      77                 :        770 :                 msg->listen_channel = data;
      78                 :        770 :                 wpa_printf(MSG_DEBUG, "P2P: * Listen Channel: "
      79                 :            :                            "Country %c%c(0x%02x) Regulatory "
      80                 :       1540 :                            "Class %d Channel Number %d", data[0], data[1],
      81                 :       2310 :                            data[2], data[3], data[4]);
      82                 :        770 :                 break;
      83                 :            :         case P2P_ATTR_OPERATING_CHANNEL:
      84         [ -  + ]:        125 :                 if (len == 0) {
      85                 :          0 :                         wpa_printf(MSG_DEBUG, "P2P: * Operating Channel: "
      86                 :            :                                    "Ignore null channel");
      87                 :          0 :                         break;
      88                 :            :                 }
      89         [ -  + ]:        125 :                 if (len < 5) {
      90                 :          0 :                         wpa_printf(MSG_DEBUG, "P2P: Too short Operating "
      91                 :            :                                    "Channel attribute (length %d)", len);
      92                 :          0 :                         return -1;
      93                 :            :                 }
      94                 :        125 :                 msg->operating_channel = data;
      95                 :        125 :                 wpa_printf(MSG_DEBUG, "P2P: * Operating Channel: "
      96                 :            :                            "Country %c%c(0x%02x) Regulatory "
      97                 :        250 :                            "Class %d Channel Number %d", data[0], data[1],
      98                 :        375 :                            data[2], data[3], data[4]);
      99                 :        125 :                 break;
     100                 :            :         case P2P_ATTR_CHANNEL_LIST:
     101         [ -  + ]:        148 :                 if (len < 3) {
     102                 :          0 :                         wpa_printf(MSG_DEBUG, "P2P: Too short Channel List "
     103                 :            :                                    "attribute (length %d)", len);
     104                 :          0 :                         return -1;
     105                 :            :                 }
     106                 :        148 :                 msg->channel_list = data;
     107                 :        148 :                 msg->channel_list_len = len;
     108                 :        148 :                 wpa_printf(MSG_DEBUG, "P2P: * Channel List: Country String "
     109                 :        444 :                            "'%c%c(0x%02x)'", data[0], data[1], data[2]);
     110                 :        148 :                 wpa_hexdump(MSG_MSGDUMP, "P2P: Channel List",
     111                 :        296 :                             msg->channel_list, msg->channel_list_len);
     112                 :        148 :                 break;
     113                 :            :         case P2P_ATTR_GROUP_INFO:
     114                 :         49 :                 msg->group_info = data;
     115                 :         49 :                 msg->group_info_len = len;
     116                 :         49 :                 wpa_printf(MSG_DEBUG, "P2P: * Group Info");
     117                 :         49 :                 break;
     118                 :            :         case P2P_ATTR_DEVICE_INFO:
     119         [ -  + ]:       1337 :                 if (len < ETH_ALEN + 2 + 8 + 1) {
     120                 :          0 :                         wpa_printf(MSG_DEBUG, "P2P: Too short Device Info "
     121                 :            :                                    "attribute (length %d)", len);
     122                 :          0 :                         return -1;
     123                 :            :                 }
     124                 :       1337 :                 msg->p2p_device_info = data;
     125                 :       1337 :                 msg->p2p_device_info_len = len;
     126                 :       1337 :                 pos = data;
     127                 :       1337 :                 msg->p2p_device_addr = pos;
     128                 :       1337 :                 pos += ETH_ALEN;
     129                 :       1337 :                 msg->config_methods = WPA_GET_BE16(pos);
     130                 :       1337 :                 pos += 2;
     131                 :       1337 :                 msg->pri_dev_type = pos;
     132                 :       1337 :                 pos += 8;
     133                 :       1337 :                 msg->num_sec_dev_types = *pos++;
     134         [ -  + ]:       1337 :                 if (msg->num_sec_dev_types * 8 > data + len - pos) {
     135                 :          0 :                         wpa_printf(MSG_DEBUG, "P2P: Device Info underflow");
     136                 :          0 :                         return -1;
     137                 :            :                 }
     138                 :       1337 :                 pos += msg->num_sec_dev_types * 8;
     139         [ -  + ]:       1337 :                 if (data + len - pos < 4) {
     140                 :          0 :                         wpa_printf(MSG_DEBUG, "P2P: Invalid Device Name "
     141                 :          0 :                                    "length %d", (int) (data + len - pos));
     142                 :          0 :                         return -1;
     143                 :            :                 }
     144         [ -  + ]:       1337 :                 if (WPA_GET_BE16(pos) != ATTR_DEV_NAME) {
     145                 :          0 :                         wpa_hexdump(MSG_DEBUG, "P2P: Unexpected Device Name "
     146                 :            :                                     "header", pos, 4);
     147                 :          0 :                         return -1;
     148                 :            :                 }
     149                 :       1337 :                 pos += 2;
     150                 :       1337 :                 nlen = WPA_GET_BE16(pos);
     151                 :       1337 :                 pos += 2;
     152 [ +  - ][ -  + ]:       1337 :                 if (data + len - pos < (int) nlen || nlen > 32) {
     153                 :          0 :                         wpa_printf(MSG_DEBUG, "P2P: Invalid Device Name "
     154                 :            :                                    "length %d (buf len %d)", (int) nlen,
     155                 :          0 :                                    (int) (data + len - pos));
     156                 :          0 :                         return -1;
     157                 :            :                 }
     158                 :       1337 :                 os_memcpy(msg->device_name, pos, nlen);
     159                 :       1337 :                 msg->device_name[nlen] = '\0';
     160         [ +  + ]:      11729 :                 for (i = 0; i < nlen; i++) {
     161         [ -  + ]:      10392 :                         if (msg->device_name[i] == '\0')
     162                 :          0 :                                 break;
     163 [ +  - ][ -  + ]:      10392 :                         if (msg->device_name[i] > 0 &&
     164                 :      10392 :                             msg->device_name[i] < 32)
     165                 :          0 :                                 msg->device_name[i] = '_';
     166                 :            :                 }
     167                 :       1337 :                 wpa_printf(MSG_DEBUG, "P2P: * Device Info: addr " MACSTR
     168                 :            :                            " primary device type %s device name '%s' "
     169                 :            :                            "config methods 0x%x",
     170                 :       8022 :                            MAC2STR(msg->p2p_device_addr),
     171                 :            :                            wps_dev_type_bin2str(msg->pri_dev_type, devtype,
     172                 :            :                                                 sizeof(devtype)),
     173                 :       2674 :                            msg->device_name, msg->config_methods);
     174                 :       1337 :                 break;
     175                 :            :         case P2P_ATTR_CONFIGURATION_TIMEOUT:
     176         [ -  + ]:        116 :                 if (len < 2) {
     177                 :          0 :                         wpa_printf(MSG_DEBUG, "P2P: Too short Configuration "
     178                 :            :                                    "Timeout attribute (length %d)", len);
     179                 :          0 :                         return -1;
     180                 :            :                 }
     181                 :        116 :                 msg->config_timeout = data;
     182                 :        116 :                 wpa_printf(MSG_DEBUG, "P2P: * Configuration Timeout");
     183                 :        116 :                 break;
     184                 :            :         case P2P_ATTR_INTENDED_INTERFACE_ADDR:
     185         [ -  + ]:         93 :                 if (len < ETH_ALEN) {
     186                 :          0 :                         wpa_printf(MSG_DEBUG, "P2P: Too short Intended P2P "
     187                 :            :                                    "Interface Address attribute (length %d)",
     188                 :            :                                    len);
     189                 :          0 :                         return -1;
     190                 :            :                 }
     191                 :         93 :                 msg->intended_addr = data;
     192                 :         93 :                 wpa_printf(MSG_DEBUG, "P2P: * Intended P2P Interface Address: "
     193                 :        558 :                            MACSTR, MAC2STR(msg->intended_addr));
     194                 :         93 :                 break;
     195                 :            :         case P2P_ATTR_GROUP_BSSID:
     196         [ -  + ]:         12 :                 if (len < ETH_ALEN) {
     197                 :          0 :                         wpa_printf(MSG_DEBUG, "P2P: Too short P2P Group BSSID "
     198                 :            :                                    "attribute (length %d)", len);
     199                 :          0 :                         return -1;
     200                 :            :                 }
     201                 :         12 :                 msg->group_bssid = data;
     202                 :         12 :                 wpa_printf(MSG_DEBUG, "P2P: * P2P Group BSSID: " MACSTR,
     203                 :         72 :                            MAC2STR(msg->group_bssid));
     204                 :         12 :                 break;
     205                 :            :         case P2P_ATTR_GROUP_ID:
     206 [ +  - ][ -  + ]:         83 :                 if (len < ETH_ALEN || len > ETH_ALEN + 32) {
     207                 :          0 :                         wpa_printf(MSG_DEBUG, "P2P: Invalid P2P Group ID "
     208                 :            :                                    "attribute length %d", len);
     209                 :          0 :                         return -1;
     210                 :            :                 }
     211                 :         83 :                 msg->group_id = data;
     212                 :         83 :                 msg->group_id_len = len;
     213                 :         83 :                 wpa_printf(MSG_DEBUG, "P2P: * P2P Group ID: Device Address "
     214                 :        498 :                            MACSTR, MAC2STR(msg->group_id));
     215                 :         83 :                 wpa_hexdump_ascii(MSG_DEBUG, "P2P: * P2P Group ID: SSID",
     216                 :         83 :                                   msg->group_id + ETH_ALEN,
     217                 :         83 :                                   msg->group_id_len - ETH_ALEN);
     218                 :         83 :                 break;
     219                 :            :         case P2P_ATTR_INVITATION_FLAGS:
     220         [ -  + ]:         12 :                 if (len < 1) {
     221                 :          0 :                         wpa_printf(MSG_DEBUG, "P2P: Too short Invitation "
     222                 :            :                                    "Flag attribute (length %d)", len);
     223                 :          0 :                         return -1;
     224                 :            :                 }
     225                 :         12 :                 msg->invitation_flags = data;
     226                 :         12 :                 wpa_printf(MSG_DEBUG, "P2P: * Invitation Flags: bitmap 0x%x",
     227                 :         12 :                            data[0]);
     228                 :         12 :                 break;
     229                 :            :         case P2P_ATTR_MANAGEABILITY:
     230         [ #  # ]:          0 :                 if (len < 1) {
     231                 :          0 :                         wpa_printf(MSG_DEBUG, "P2P: Too short Manageability "
     232                 :            :                                    "attribute (length %d)", len);
     233                 :          0 :                         return -1;
     234                 :            :                 }
     235                 :          0 :                 msg->manageability = data;
     236                 :          0 :                 wpa_printf(MSG_DEBUG, "P2P: * Manageability: bitmap 0x%x",
     237                 :          0 :                            data[0]);
     238                 :          0 :                 break;
     239                 :            :         case P2P_ATTR_NOTICE_OF_ABSENCE:
     240         [ -  + ]:          2 :                 if (len < 2) {
     241                 :          0 :                         wpa_printf(MSG_DEBUG, "P2P: Too short Notice of "
     242                 :            :                                    "Absence attribute (length %d)", len);
     243                 :          0 :                         return -1;
     244                 :            :                 }
     245                 :          2 :                 msg->noa = data;
     246                 :          2 :                 msg->noa_len = len;
     247                 :          2 :                 wpa_printf(MSG_DEBUG, "P2P: * Notice of Absence");
     248                 :          2 :                 break;
     249                 :            :         case P2P_ATTR_EXT_LISTEN_TIMING:
     250         [ #  # ]:          0 :                 if (len < 4) {
     251                 :          0 :                         wpa_printf(MSG_DEBUG, "P2P: Too short Extended Listen "
     252                 :            :                                    "Timing attribute (length %d)", len);
     253                 :          0 :                         return -1;
     254                 :            :                 }
     255                 :          0 :                 msg->ext_listen_timing = data;
     256                 :          0 :                 wpa_printf(MSG_DEBUG, "P2P: * Extended Listen Timing "
     257                 :            :                            "(period %u msec  interval %u msec)",
     258                 :          0 :                            WPA_GET_LE16(msg->ext_listen_timing),
     259                 :          0 :                            WPA_GET_LE16(msg->ext_listen_timing + 2));
     260                 :          0 :                 break;
     261                 :            :         case P2P_ATTR_MINOR_REASON_CODE:
     262         [ #  # ]:          0 :                 if (len < 1) {
     263                 :          0 :                         wpa_printf(MSG_DEBUG, "P2P: Too short Minor Reason "
     264                 :            :                                    "Code attribute (length %d)", len);
     265                 :          0 :                         return -1;
     266                 :            :                 }
     267                 :          0 :                 msg->minor_reason_code = data;
     268                 :          0 :                 wpa_printf(MSG_DEBUG, "P2P: * Minor Reason Code: %u",
     269                 :          0 :                            *msg->minor_reason_code);
     270                 :          0 :                 break;
     271                 :            :         default:
     272                 :          0 :                 wpa_printf(MSG_DEBUG, "P2P: Skipped unknown attribute %d "
     273                 :            :                            "(length %d)", id, len);
     274                 :          0 :                 break;
     275                 :            :         }
     276                 :            : 
     277                 :       5028 :         return 0;
     278                 :            : }
     279                 :            : 
     280                 :            : 
     281                 :            : /**
     282                 :            :  * p2p_parse_p2p_ie - Parse P2P IE
     283                 :            :  * @buf: Concatenated P2P IE(s) payload
     284                 :            :  * @msg: Buffer for returning parsed attributes
     285                 :            :  * Returns: 0 on success, -1 on failure
     286                 :            :  *
     287                 :            :  * Note: Caller is responsible for clearing the msg data structure before
     288                 :            :  * calling this function.
     289                 :            :  */
     290                 :       2121 : int p2p_parse_p2p_ie(const struct wpabuf *buf, struct p2p_message *msg)
     291                 :            : {
     292                 :       2121 :         const u8 *pos = wpabuf_head_u8(buf);
     293                 :       2121 :         const u8 *end = pos + wpabuf_len(buf);
     294                 :            : 
     295                 :       2121 :         wpa_printf(MSG_DEBUG, "P2P: Parsing P2P IE");
     296                 :            : 
     297         [ +  + ]:       7149 :         while (pos < end) {
     298                 :            :                 u16 attr_len;
     299         [ -  + ]:       5028 :                 if (pos + 2 >= end) {
     300                 :          0 :                         wpa_printf(MSG_DEBUG, "P2P: Invalid P2P attribute");
     301                 :          0 :                         return -1;
     302                 :            :                 }
     303                 :       5028 :                 attr_len = WPA_GET_LE16(pos + 1);
     304                 :       5028 :                 wpa_printf(MSG_DEBUG, "P2P: Attribute %d length %u",
     305                 :       5028 :                            pos[0], attr_len);
     306         [ -  + ]:       5028 :                 if (pos + 3 + attr_len > end) {
     307                 :          0 :                         wpa_printf(MSG_DEBUG, "P2P: Attribute underflow "
     308                 :            :                                    "(len=%u left=%d)",
     309                 :          0 :                                    attr_len, (int) (end - pos - 3));
     310                 :          0 :                         wpa_hexdump(MSG_MSGDUMP, "P2P: Data", pos, end - pos);
     311                 :          0 :                         return -1;
     312                 :            :                 }
     313         [ -  + ]:       5028 :                 if (p2p_parse_attribute(pos[0], pos + 3, attr_len, msg))
     314                 :          0 :                         return -1;
     315                 :       5028 :                 pos += 3 + attr_len;
     316                 :            :         }
     317                 :            : 
     318                 :       2121 :         return 0;
     319                 :            : }
     320                 :            : 
     321                 :            : 
     322                 :       1222 : static int p2p_parse_wps_ie(const struct wpabuf *buf, struct p2p_message *msg)
     323                 :            : {
     324                 :            :         struct wps_parse_attr attr;
     325                 :            :         int i;
     326                 :            : 
     327                 :       1222 :         wpa_printf(MSG_DEBUG, "P2P: Parsing WPS IE");
     328         [ -  + ]:       1222 :         if (wps_parse_msg(buf, &attr))
     329                 :          0 :                 return -1;
     330 [ +  + ][ +  - ]:       1222 :         if (attr.dev_name && attr.dev_name_len < sizeof(msg->device_name) &&
                 [ +  - ]
     331                 :       1015 :             !msg->device_name[0])
     332                 :       1015 :                 os_memcpy(msg->device_name, attr.dev_name, attr.dev_name_len);
     333         [ +  + ]:       1222 :         if (attr.config_methods) {
     334                 :       1074 :                 msg->wps_config_methods =
     335                 :       1074 :                         WPA_GET_BE16(attr.config_methods);
     336                 :       1074 :                 wpa_printf(MSG_DEBUG, "P2P: Config Methods (WPS): 0x%x",
     337                 :       1074 :                            msg->wps_config_methods);
     338                 :            :         }
     339         [ +  + ]:       1222 :         if (attr.dev_password_id) {
     340                 :        751 :                 msg->dev_password_id = WPA_GET_BE16(attr.dev_password_id);
     341                 :        751 :                 wpa_printf(MSG_DEBUG, "P2P: Device Password ID: %d",
     342                 :        751 :                            msg->dev_password_id);
     343                 :            :         }
     344         [ +  + ]:       1222 :         if (attr.primary_dev_type) {
     345                 :            :                 char devtype[WPS_DEV_TYPE_BUFSIZE];
     346                 :       1015 :                 msg->wps_pri_dev_type = attr.primary_dev_type;
     347                 :       1015 :                 wpa_printf(MSG_DEBUG, "P2P: Primary Device Type (WPS): %s",
     348                 :            :                            wps_dev_type_bin2str(msg->wps_pri_dev_type, devtype,
     349                 :            :                                                 sizeof(devtype)));
     350                 :            :         }
     351         [ -  + ]:       1222 :         if (attr.sec_dev_type_list) {
     352                 :          0 :                 msg->wps_sec_dev_type_list = attr.sec_dev_type_list;
     353                 :          0 :                 msg->wps_sec_dev_type_list_len = attr.sec_dev_type_list_len;
     354                 :            :         }
     355                 :            : 
     356         [ +  + ]:      13442 :         for (i = 0; i < P2P_MAX_WPS_VENDOR_EXT; i++) {
     357                 :      12220 :                 msg->wps_vendor_ext[i] = attr.vendor_ext[i];
     358                 :      12220 :                 msg->wps_vendor_ext_len[i] = attr.vendor_ext_len[i];
     359                 :            :         }
     360                 :            : 
     361                 :       1222 :         msg->manufacturer = attr.manufacturer;
     362                 :       1222 :         msg->manufacturer_len = attr.manufacturer_len;
     363                 :       1222 :         msg->model_name = attr.model_name;
     364                 :       1222 :         msg->model_name_len = attr.model_name_len;
     365                 :       1222 :         msg->model_number = attr.model_number;
     366                 :       1222 :         msg->model_number_len = attr.model_number_len;
     367                 :       1222 :         msg->serial_number = attr.serial_number;
     368                 :       1222 :         msg->serial_number_len = attr.serial_number_len;
     369                 :            : 
     370                 :       1222 :         return 0;
     371                 :            : }
     372                 :            : 
     373                 :            : 
     374                 :            : /**
     375                 :            :  * p2p_parse_ies - Parse P2P message IEs (both WPS and P2P IE)
     376                 :            :  * @data: IEs from the message
     377                 :            :  * @len: Length of data buffer in octets
     378                 :            :  * @msg: Buffer for returning parsed attributes
     379                 :            :  * Returns: 0 on success, -1 on failure
     380                 :            :  *
     381                 :            :  * Note: Caller is responsible for clearing the msg data structure before
     382                 :            :  * calling this function.
     383                 :            :  *
     384                 :            :  * Note: Caller must free temporary memory allocations by calling
     385                 :            :  * p2p_parse_free() when the parsed data is not needed anymore.
     386                 :            :  */
     387                 :       1414 : int p2p_parse_ies(const u8 *data, size_t len, struct p2p_message *msg)
     388                 :            : {
     389                 :            :         struct ieee802_11_elems elems;
     390                 :            : 
     391                 :       1414 :         ieee802_11_parse_elems(data, len, &elems, 0);
     392 [ +  + ][ +  - ]:       1414 :         if (elems.ds_params && elems.ds_params_len >= 1)
     393                 :       1070 :                 msg->ds_params = elems.ds_params;
     394         [ +  + ]:       1414 :         if (elems.ssid)
     395                 :       1196 :                 msg->ssid = elems.ssid - 2;
     396                 :            : 
     397                 :       1414 :         msg->wps_attributes = ieee802_11_vendor_ie_concat(data, len,
     398                 :            :                                                           WPS_DEV_OUI_WFA);
     399   [ +  +  -  + ]:       2636 :         if (msg->wps_attributes &&
     400                 :       1222 :             p2p_parse_wps_ie(msg->wps_attributes, msg)) {
     401                 :          0 :                 p2p_parse_free(msg);
     402                 :          0 :                 return -1;
     403                 :            :         }
     404                 :            : 
     405                 :       1414 :         msg->p2p_attributes = ieee802_11_vendor_ie_concat(data, len,
     406                 :            :                                                           P2P_IE_VENDOR_TYPE);
     407   [ +  +  -  + ]:       2745 :         if (msg->p2p_attributes &&
     408                 :       1331 :             p2p_parse_p2p_ie(msg->p2p_attributes, msg)) {
     409                 :          0 :                 wpa_printf(MSG_DEBUG, "P2P: Failed to parse P2P IE data");
     410         [ #  # ]:          0 :                 if (msg->p2p_attributes)
     411                 :          0 :                         wpa_hexdump_buf(MSG_MSGDUMP, "P2P: P2P IE data",
     412                 :          0 :                                         msg->p2p_attributes);
     413                 :          0 :                 p2p_parse_free(msg);
     414                 :          0 :                 return -1;
     415                 :            :         }
     416                 :            : 
     417                 :            : #ifdef CONFIG_WIFI_DISPLAY
     418         [ +  + ]:       1414 :         if (elems.wfd) {
     419                 :       1163 :                 msg->wfd_subelems = ieee802_11_vendor_ie_concat(
     420                 :            :                         data, len, WFD_IE_VENDOR_TYPE);
     421                 :            :         }
     422                 :            : #endif /* CONFIG_WIFI_DISPLAY */
     423                 :            : 
     424                 :       1414 :         return 0;
     425                 :            : }
     426                 :            : 
     427                 :            : 
     428                 :            : /**
     429                 :            :  * p2p_parse - Parse a P2P Action frame contents
     430                 :            :  * @data: Action frame payload after Category and Code fields
     431                 :            :  * @len: Length of data buffer in octets
     432                 :            :  * @msg: Buffer for returning parsed attributes
     433                 :            :  * Returns: 0 on success, -1 on failure
     434                 :            :  *
     435                 :            :  * Note: Caller must free temporary memory allocations by calling
     436                 :            :  * p2p_parse_free() when the parsed data is not needed anymore.
     437                 :            :  */
     438                 :        202 : int p2p_parse(const u8 *data, size_t len, struct p2p_message *msg)
     439                 :            : {
     440                 :        202 :         os_memset(msg, 0, sizeof(*msg));
     441                 :        202 :         wpa_printf(MSG_DEBUG, "P2P: Parsing the received message");
     442         [ -  + ]:        202 :         if (len < 1) {
     443                 :          0 :                 wpa_printf(MSG_DEBUG, "P2P: No Dialog Token in the message");
     444                 :          0 :                 return -1;
     445                 :            :         }
     446                 :        202 :         msg->dialog_token = data[0];
     447                 :        202 :         wpa_printf(MSG_DEBUG, "P2P: * Dialog Token: %d", msg->dialog_token);
     448                 :            : 
     449                 :        202 :         return p2p_parse_ies(data + 1, len - 1, msg);
     450                 :            : }
     451                 :            : 
     452                 :            : 
     453                 :            : /**
     454                 :            :  * p2p_parse_free - Free temporary data from P2P parsing
     455                 :            :  * @msg: Parsed attributes
     456                 :            :  */
     457                 :       1414 : void p2p_parse_free(struct p2p_message *msg)
     458                 :            : {
     459                 :       1414 :         wpabuf_free(msg->p2p_attributes);
     460                 :       1414 :         msg->p2p_attributes = NULL;
     461                 :       1414 :         wpabuf_free(msg->wps_attributes);
     462                 :       1414 :         msg->wps_attributes = NULL;
     463                 :            : #ifdef CONFIG_WIFI_DISPLAY
     464                 :       1414 :         wpabuf_free(msg->wfd_subelems);
     465                 :       1414 :         msg->wfd_subelems = NULL;
     466                 :            : #endif /* CONFIG_WIFI_DISPLAY */
     467                 :       1414 : }
     468                 :            : 
     469                 :            : 
     470                 :         15 : int p2p_group_info_parse(const u8 *gi, size_t gi_len,
     471                 :            :                          struct p2p_group_info *info)
     472                 :            : {
     473                 :            :         const u8 *g, *gend;
     474                 :            : 
     475                 :         15 :         os_memset(info, 0, sizeof(*info));
     476         [ +  + ]:         15 :         if (gi == NULL)
     477                 :          3 :                 return 0;
     478                 :            : 
     479                 :         12 :         g = gi;
     480                 :         12 :         gend = gi + gi_len;
     481         [ +  + ]:         24 :         while (g < gend) {
     482                 :            :                 struct p2p_client_info *cli;
     483                 :            :                 const u8 *t, *cend;
     484                 :            :                 int count;
     485                 :            : 
     486                 :         12 :                 cli = &info->client[info->num_clients];
     487                 :         12 :                 cend = g + 1 + g[0];
     488         [ -  + ]:         12 :                 if (cend > gend)
     489                 :          0 :                         return -1; /* invalid data */
     490                 :            :                 /* g at start of P2P Client Info Descriptor */
     491                 :            :                 /* t at Device Capability Bitmap */
     492                 :         12 :                 t = g + 1 + 2 * ETH_ALEN;
     493         [ -  + ]:         12 :                 if (t > cend)
     494                 :          0 :                         return -1; /* invalid data */
     495                 :         12 :                 cli->p2p_device_addr = g + 1;
     496                 :         12 :                 cli->p2p_interface_addr = g + 1 + ETH_ALEN;
     497                 :         12 :                 cli->dev_capab = t[0];
     498                 :            : 
     499         [ -  + ]:         12 :                 if (t + 1 + 2 + 8 + 1 > cend)
     500                 :          0 :                         return -1; /* invalid data */
     501                 :            : 
     502                 :         12 :                 cli->config_methods = WPA_GET_BE16(&t[1]);
     503                 :         12 :                 cli->pri_dev_type = &t[3];
     504                 :            : 
     505                 :         12 :                 t += 1 + 2 + 8;
     506                 :            :                 /* t at Number of Secondary Device Types */
     507                 :         12 :                 cli->num_sec_dev_types = *t++;
     508         [ -  + ]:         12 :                 if (t + 8 * cli->num_sec_dev_types > cend)
     509                 :          0 :                         return -1; /* invalid data */
     510                 :         12 :                 cli->sec_dev_types = t;
     511                 :         12 :                 t += 8 * cli->num_sec_dev_types;
     512                 :            : 
     513                 :            :                 /* t at Device Name in WPS TLV format */
     514         [ -  + ]:         12 :                 if (t + 2 + 2 > cend)
     515                 :          0 :                         return -1; /* invalid data */
     516         [ -  + ]:         12 :                 if (WPA_GET_BE16(t) != ATTR_DEV_NAME)
     517                 :          0 :                         return -1; /* invalid Device Name TLV */
     518                 :         12 :                 t += 2;
     519                 :         12 :                 count = WPA_GET_BE16(t);
     520                 :         12 :                 t += 2;
     521         [ -  + ]:         12 :                 if (count > cend - t)
     522                 :          0 :                         return -1; /* invalid Device Name TLV */
     523         [ -  + ]:         12 :                 if (count >= 32)
     524                 :          0 :                         count = 32;
     525                 :         12 :                 cli->dev_name = (const char *) t;
     526                 :         12 :                 cli->dev_name_len = count;
     527                 :            : 
     528                 :         12 :                 g = cend;
     529                 :            : 
     530                 :         12 :                 info->num_clients++;
     531         [ -  + ]:         12 :                 if (info->num_clients == P2P_MAX_GROUP_ENTRIES)
     532                 :          0 :                         return -1;
     533                 :            :         }
     534                 :            : 
     535                 :         15 :         return 0;
     536                 :            : }
     537                 :            : 
     538                 :            : 
     539                 :          4 : static int p2p_group_info_text(const u8 *gi, size_t gi_len, char *buf,
     540                 :            :                                char *end)
     541                 :            : {
     542                 :          4 :         char *pos = buf;
     543                 :            :         int ret;
     544                 :            :         struct p2p_group_info info;
     545                 :            :         unsigned int i;
     546                 :            : 
     547         [ -  + ]:          4 :         if (p2p_group_info_parse(gi, gi_len, &info) < 0)
     548                 :          0 :                 return 0;
     549                 :            : 
     550         [ +  + ]:          5 :         for (i = 0; i < info.num_clients; i++) {
     551                 :            :                 struct p2p_client_info *cli;
     552                 :            :                 char name[33];
     553                 :            :                 char devtype[WPS_DEV_TYPE_BUFSIZE];
     554                 :            :                 u8 s;
     555                 :            :                 int count;
     556                 :            : 
     557                 :          1 :                 cli = &info.client[i];
     558                 :         12 :                 ret = os_snprintf(pos, end - pos, "p2p_group_client: "
     559                 :            :                                   "dev=" MACSTR " iface=" MACSTR,
     560                 :          6 :                                   MAC2STR(cli->p2p_device_addr),
     561                 :          6 :                                   MAC2STR(cli->p2p_interface_addr));
     562 [ +  - ][ -  + ]:          1 :                 if (ret < 0 || ret >= end - pos)
     563                 :          0 :                         return pos - buf;
     564                 :          1 :                 pos += ret;
     565                 :            : 
     566                 :          1 :                 ret = os_snprintf(pos, end - pos,
     567                 :            :                                   " dev_capab=0x%x config_methods=0x%x "
     568                 :            :                                   "dev_type=%s",
     569                 :          2 :                                   cli->dev_capab, cli->config_methods,
     570                 :            :                                   wps_dev_type_bin2str(cli->pri_dev_type,
     571                 :            :                                                        devtype,
     572                 :            :                                                        sizeof(devtype)));
     573 [ +  - ][ -  + ]:          1 :                 if (ret < 0 || ret >= end - pos)
     574                 :          0 :                         return pos - buf;
     575                 :          1 :                 pos += ret;
     576                 :            : 
     577         [ -  + ]:          1 :                 for (s = 0; s < cli->num_sec_dev_types; s++) {
     578                 :          0 :                         ret = os_snprintf(pos, end - pos, " dev_type=%s",
     579                 :            :                                           wps_dev_type_bin2str(
     580                 :          0 :                                                   &cli->sec_dev_types[s * 8],
     581                 :            :                                                   devtype, sizeof(devtype)));
     582 [ #  # ][ #  # ]:          0 :                         if (ret < 0 || ret >= end - pos)
     583                 :          0 :                                 return pos - buf;
     584                 :          0 :                         pos += ret;
     585                 :            :                 }
     586                 :            : 
     587                 :          1 :                 os_memcpy(name, cli->dev_name, cli->dev_name_len);
     588                 :          1 :                 name[cli->dev_name_len] = '\0';
     589                 :          1 :                 count = (int) cli->dev_name_len - 1;
     590         [ +  + ]:          9 :                 while (count >= 0) {
     591 [ +  - ][ -  + ]:          8 :                         if (name[count] > 0 && name[count] < 32)
     592                 :          0 :                                 name[count] = '_';
     593                 :          8 :                         count--;
     594                 :            :                 }
     595                 :            : 
     596                 :          1 :                 ret = os_snprintf(pos, end - pos, " dev_name='%s'\n", name);
     597 [ +  - ][ -  + ]:          1 :                 if (ret < 0 || ret >= end - pos)
     598                 :          0 :                         return pos - buf;
     599                 :          1 :                 pos += ret;
     600                 :            :         }
     601                 :            : 
     602                 :          4 :         return pos - buf;
     603                 :            : }
     604                 :            : 
     605                 :            : 
     606                 :            : /**
     607                 :            :  * p2p_attr_text - Build text format description of P2P IE attributes
     608                 :            :  * @data: P2P IE contents
     609                 :            :  * @buf: Buffer for returning text
     610                 :            :  * @end: Pointer to the end of the buf area
     611                 :            :  * Returns: Number of octets written to the buffer or -1 on faikure
     612                 :            :  *
     613                 :            :  * This function can be used to parse P2P IE contents into text format
     614                 :            :  * field=value lines.
     615                 :            :  */
     616                 :          4 : int p2p_attr_text(struct wpabuf *data, char *buf, char *end)
     617                 :            : {
     618                 :            :         struct p2p_message msg;
     619                 :          4 :         char *pos = buf;
     620                 :            :         int ret;
     621                 :            : 
     622                 :          4 :         os_memset(&msg, 0, sizeof(msg));
     623         [ -  + ]:          4 :         if (p2p_parse_p2p_ie(data, &msg))
     624                 :          0 :                 return -1;
     625                 :            : 
     626         [ +  - ]:          4 :         if (msg.capability) {
     627                 :          8 :                 ret = os_snprintf(pos, end - pos,
     628                 :            :                                   "p2p_dev_capab=0x%x\n"
     629                 :            :                                   "p2p_group_capab=0x%x\n",
     630                 :          8 :                                   msg.capability[0], msg.capability[1]);
     631 [ +  - ][ -  + ]:          4 :                 if (ret < 0 || ret >= end - pos)
     632                 :          0 :                         return pos - buf;
     633                 :          4 :                 pos += ret;
     634                 :            :         }
     635                 :            : 
     636         [ +  - ]:          4 :         if (msg.pri_dev_type) {
     637                 :            :                 char devtype[WPS_DEV_TYPE_BUFSIZE];
     638                 :          4 :                 ret = os_snprintf(pos, end - pos,
     639                 :            :                                   "p2p_primary_device_type=%s\n",
     640                 :            :                                   wps_dev_type_bin2str(msg.pri_dev_type,
     641                 :            :                                                        devtype,
     642                 :            :                                                        sizeof(devtype)));
     643 [ +  - ][ -  + ]:          4 :                 if (ret < 0 || ret >= end - pos)
     644                 :          0 :                         return pos - buf;
     645                 :          4 :                 pos += ret;
     646                 :            :         }
     647                 :            : 
     648                 :          4 :         ret = os_snprintf(pos, end - pos, "p2p_device_name=%s\n",
     649                 :            :                           msg.device_name);
     650 [ +  - ][ -  + ]:          4 :         if (ret < 0 || ret >= end - pos)
     651                 :          0 :                 return pos - buf;
     652                 :          4 :         pos += ret;
     653                 :            : 
     654         [ +  - ]:          4 :         if (msg.p2p_device_addr) {
     655                 :         24 :                 ret = os_snprintf(pos, end - pos, "p2p_device_addr=" MACSTR
     656                 :            :                                   "\n",
     657                 :         24 :                                   MAC2STR(msg.p2p_device_addr));
     658 [ +  - ][ -  + ]:          4 :                 if (ret < 0 || ret >= end - pos)
     659                 :          0 :                         return pos - buf;
     660                 :          4 :                 pos += ret;
     661                 :            :         }
     662                 :            : 
     663                 :          4 :         ret = os_snprintf(pos, end - pos, "p2p_config_methods=0x%x\n",
     664                 :          4 :                           msg.config_methods);
     665 [ +  - ][ -  + ]:          4 :         if (ret < 0 || ret >= end - pos)
     666                 :          0 :                 return pos - buf;
     667                 :          4 :         pos += ret;
     668                 :            : 
     669                 :          4 :         ret = p2p_group_info_text(msg.group_info, msg.group_info_len,
     670                 :            :                                   pos, end);
     671         [ -  + ]:          4 :         if (ret < 0)
     672                 :          0 :                 return pos - buf;
     673                 :          4 :         pos += ret;
     674                 :            : 
     675                 :          4 :         return pos - buf;
     676                 :            : }
     677                 :            : 
     678                 :            : 
     679                 :          2 : int p2p_get_cross_connect_disallowed(const struct wpabuf *p2p_ie)
     680                 :            : {
     681                 :            :         struct p2p_message msg;
     682                 :            : 
     683                 :          2 :         os_memset(&msg, 0, sizeof(msg));
     684         [ -  + ]:          2 :         if (p2p_parse_p2p_ie(p2p_ie, &msg))
     685                 :          0 :                 return 0;
     686                 :            : 
     687         [ +  - ]:          2 :         if (!msg.manageability)
     688                 :          2 :                 return 0;
     689                 :            : 
     690                 :          2 :         return !(msg.manageability[0] & P2P_MAN_CROSS_CONNECTION_PERMITTED);
     691                 :            : }
     692                 :            : 
     693                 :            : 
     694                 :        168 : u8 p2p_get_group_capab(const struct wpabuf *p2p_ie)
     695                 :            : {
     696                 :            :         struct p2p_message msg;
     697                 :            : 
     698                 :        168 :         os_memset(&msg, 0, sizeof(msg));
     699         [ -  + ]:        168 :         if (p2p_parse_p2p_ie(p2p_ie, &msg))
     700                 :          0 :                 return 0;
     701                 :            : 
     702         [ -  + ]:        168 :         if (!msg.capability)
     703                 :          0 :                 return 0;
     704                 :            : 
     705                 :        168 :         return msg.capability[1];
     706                 :            : }
     707                 :            : 
     708                 :            : 
     709                 :        349 : const u8 * p2p_get_go_dev_addr(const struct wpabuf *p2p_ie)
     710                 :            : {
     711                 :            :         struct p2p_message msg;
     712                 :            : 
     713                 :        349 :         os_memset(&msg, 0, sizeof(msg));
     714         [ -  + ]:        349 :         if (p2p_parse_p2p_ie(p2p_ie, &msg))
     715                 :          0 :                 return NULL;
     716                 :            : 
     717         [ +  + ]:        349 :         if (msg.p2p_device_addr)
     718                 :        346 :                 return msg.p2p_device_addr;
     719         [ -  + ]:          3 :         if (msg.device_id)
     720                 :          0 :                 return msg.device_id;
     721                 :            : 
     722                 :        349 :         return NULL;
     723                 :            : }

Generated by: LCOV version 1.9