LCOV - code coverage report
Current view: top level - src/p2p - p2p_parse.c (source / functions) Hit Total Coverage
Test: wpa_supplicant/hostapd combined for hwsim test run 1393793999 Lines: 396 439 90.2 %
Date: 2014-03-02 Functions: 13 13 100.0 %
Branches: 173 230 75.2 %

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

Generated by: LCOV version 1.9