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 1401264779 Lines: 398 439 90.7 %
Date: 2014-05-28 Functions: 13 13 100.0 %

          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       10440 : 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       10440 :         switch (id) {
      26             :         case P2P_ATTR_CAPABILITY:
      27        4185 :                 if (len < 2) {
      28           1 :                         wpa_printf(MSG_DEBUG, "P2P: Too short Capability "
      29             :                                    "attribute (length %d)", len);
      30           1 :                         return -1;
      31             :                 }
      32        4184 :                 msg->capability = data;
      33        8368 :                 wpa_printf(MSG_DEBUG, "P2P: * Device Capability %02x "
      34             :                            "Group Capability %02x",
      35        8368 :                            data[0], data[1]);
      36        4184 :                 break;
      37             :         case P2P_ATTR_DEVICE_ID:
      38          67 :                 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          66 :                 msg->device_id = data;
      44         396 :                 wpa_printf(MSG_DEBUG, "P2P: * Device ID " MACSTR,
      45         396 :                            MAC2STR(msg->device_id));
      46          66 :                 break;
      47             :         case P2P_ATTR_GROUP_OWNER_INTENT:
      48         205 :                 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         204 :                 msg->go_intent = data;
      54         408 :                 wpa_printf(MSG_DEBUG, "P2P: * GO Intent: Intent %u "
      55         408 :                            "Tie breaker %u", data[0] >> 1, data[0] & 0x01);
      56         204 :                 break;
      57             :         case P2P_ATTR_STATUS:
      58         198 :                 if (len < 1) {
      59           1 :                         wpa_printf(MSG_DEBUG, "P2P: Too short Status "
      60             :                                    "attribute (length %d)", len);
      61           1 :                         return -1;
      62             :                 }
      63         197 :                 msg->status = data;
      64         197 :                 wpa_printf(MSG_DEBUG, "P2P: * Status: %d", data[0]);
      65         197 :                 break;
      66             :         case P2P_ATTR_LISTEN_CHANNEL:
      67        1501 :                 if (len == 0) {
      68           1 :                         wpa_printf(MSG_DEBUG, "P2P: * Listen Channel: Ignore "
      69             :                                    "null channel");
      70           1 :                         break;
      71             :                 }
      72        1500 :                 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        1499 :                 msg->listen_channel = data;
      78        7495 :                 wpa_printf(MSG_DEBUG, "P2P: * Listen Channel: "
      79             :                            "Country %c%c(0x%02x) Regulatory "
      80        2998 :                            "Class %d Channel Number %d", data[0], data[1],
      81        4497 :                            data[2], data[3], data[4]);
      82        1499 :                 break;
      83             :         case P2P_ATTR_OPERATING_CHANNEL:
      84         285 :                 if (len == 0) {
      85           1 :                         wpa_printf(MSG_DEBUG, "P2P: * Operating Channel: "
      86             :                                    "Ignore null channel");
      87           1 :                         break;
      88             :                 }
      89         284 :                 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         283 :                 msg->operating_channel = data;
      95        1415 :                 wpa_printf(MSG_DEBUG, "P2P: * Operating Channel: "
      96             :                            "Country %c%c(0x%02x) Regulatory "
      97         566 :                            "Class %d Channel Number %d", data[0], data[1],
      98         849 :                            data[2], data[3], data[4]);
      99         283 :                 break;
     100             :         case P2P_ATTR_CHANNEL_LIST:
     101         333 :                 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         332 :                 msg->channel_list = data;
     107         332 :                 msg->channel_list_len = len;
     108         996 :                 wpa_printf(MSG_DEBUG, "P2P: * Channel List: Country String "
     109         996 :                            "'%c%c(0x%02x)'", data[0], data[1], data[2]);
     110         664 :                 wpa_hexdump(MSG_MSGDUMP, "P2P: Channel List",
     111         664 :                             msg->channel_list, msg->channel_list_len);
     112         332 :                 break;
     113             :         case P2P_ATTR_GROUP_INFO:
     114         133 :                 msg->group_info = data;
     115         133 :                 msg->group_info_len = len;
     116         133 :                 wpa_printf(MSG_DEBUG, "P2P: * Group Info");
     117         133 :                 break;
     118             :         case P2P_ATTR_DEVICE_INFO:
     119        2713 :                 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        2712 :                 msg->p2p_device_info = data;
     125        2712 :                 msg->p2p_device_info_len = len;
     126        2712 :                 pos = data;
     127        2712 :                 msg->p2p_device_addr = pos;
     128        2712 :                 pos += ETH_ALEN;
     129        2712 :                 msg->config_methods = WPA_GET_BE16(pos);
     130        2712 :                 pos += 2;
     131        2712 :                 msg->pri_dev_type = pos;
     132        2712 :                 pos += 8;
     133        2712 :                 msg->num_sec_dev_types = *pos++;
     134        2712 :                 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        2711 :                 pos += msg->num_sec_dev_types * 8;
     139        2711 :                 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        2710 :                 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        2709 :                 pos += 2;
     150        2709 :                 nlen = WPA_GET_BE16(pos);
     151        2709 :                 pos += 2;
     152        2709 :                 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        2706 :                 os_memcpy(msg->device_name, pos, nlen);
     159        2706 :                 msg->device_name[nlen] = '\0';
     160       23732 :                 for (i = 0; i < nlen; i++) {
     161       21027 :                         if (msg->device_name[i] == '\0')
     162           1 :                                 break;
     163       42052 :                         if (msg->device_name[i] > 0 &&
     164       21026 :                             msg->device_name[i] < 32)
     165           1 :                                 msg->device_name[i] = '_';
     166             :                 }
     167       21648 :                 wpa_printf(MSG_DEBUG, "P2P: * Device Info: addr " MACSTR
     168             :                            " primary device type %s device name '%s' "
     169             :                            "config methods 0x%x",
     170       16236 :                            MAC2STR(msg->p2p_device_addr),
     171             :                            wps_dev_type_bin2str(msg->pri_dev_type, devtype,
     172             :                                                 sizeof(devtype)),
     173        5412 :                            msg->device_name, msg->config_methods);
     174        2706 :                 break;
     175             :         case P2P_ATTR_CONFIGURATION_TIMEOUT:
     176         266 :                 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         265 :                 msg->config_timeout = data;
     182         265 :                 wpa_printf(MSG_DEBUG, "P2P: * Configuration Timeout");
     183         265 :                 break;
     184             :         case P2P_ATTR_INTENDED_INTERFACE_ADDR:
     185         206 :                 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         205 :                 msg->intended_addr = data;
     192        1230 :                 wpa_printf(MSG_DEBUG, "P2P: * Intended P2P Interface Address: "
     193        1230 :                            MACSTR, MAC2STR(msg->intended_addr));
     194         205 :                 break;
     195             :         case P2P_ATTR_GROUP_BSSID:
     196          42 :                 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          41 :                 msg->group_bssid = data;
     202         246 :                 wpa_printf(MSG_DEBUG, "P2P: * P2P Group BSSID: " MACSTR,
     203         246 :                            MAC2STR(msg->group_bssid));
     204          41 :                 break;
     205             :         case P2P_ATTR_GROUP_ID:
     206         185 :                 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         183 :                 msg->group_id = data;
     212         183 :                 msg->group_id_len = len;
     213        1098 :                 wpa_printf(MSG_DEBUG, "P2P: * P2P Group ID: Device Address "
     214        1098 :                            MACSTR, MAC2STR(msg->group_id));
     215         366 :                 wpa_hexdump_ascii(MSG_DEBUG, "P2P: * P2P Group ID: SSID",
     216         183 :                                   msg->group_id + ETH_ALEN,
     217         183 :                                   msg->group_id_len - ETH_ALEN);
     218         183 :                 break;
     219             :         case P2P_ATTR_INVITATION_FLAGS:
     220          43 :                 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          42 :                 msg->invitation_flags = data;
     226          42 :                 wpa_printf(MSG_DEBUG, "P2P: * Invitation Flags: bitmap 0x%x",
     227          42 :                            data[0]);
     228          42 :                 break;
     229             :         case P2P_ATTR_MANAGEABILITY:
     230          10 :                 if (len < 1) {
     231           1 :                         wpa_printf(MSG_DEBUG, "P2P: Too short Manageability "
     232             :                                    "attribute (length %d)", len);
     233           1 :                         return -1;
     234             :                 }
     235           9 :                 msg->manageability = data;
     236           9 :                 wpa_printf(MSG_DEBUG, "P2P: * Manageability: bitmap 0x%x",
     237           9 :                            data[0]);
     238           9 :                 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          35 :                 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          34 :                 msg->ext_listen_timing = data;
     256          68 :                 wpa_printf(MSG_DEBUG, "P2P: * Extended Listen Timing "
     257             :                            "(period %u msec  interval %u msec)",
     258          34 :                            WPA_GET_LE16(msg->ext_listen_timing),
     259          34 :                            WPA_GET_LE16(msg->ext_listen_timing + 2));
     260          34 :                 break;
     261             :         case P2P_ATTR_MINOR_REASON_CODE:
     262           4 :                 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           3 :                 msg->minor_reason_code = data;
     268           3 :                 wpa_printf(MSG_DEBUG, "P2P: * Minor Reason Code: %u",
     269           3 :                            *msg->minor_reason_code);
     270           3 :                 break;
     271             :         case P2P_ATTR_OOB_GO_NEG_CHANNEL:
     272          25 :                 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          24 :                 msg->oob_go_neg_channel = data;
     278         144 :                 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         120 :                            data[0], data[1], data[2], data[3], data[4],
     282          24 :                            data[5]);
     283          24 :                 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       10415 :         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        4309 : int p2p_parse_p2p_ie(const struct wpabuf *buf, struct p2p_message *msg)
     304             : {
     305        4309 :         const u8 *pos = wpabuf_head_u8(buf);
     306        4309 :         const u8 *end = pos + wpabuf_len(buf);
     307             : 
     308        4309 :         wpa_printf(MSG_DEBUG, "P2P: Parsing P2P IE");
     309             : 
     310       19033 :         while (pos < end) {
     311             :                 u16 attr_len;
     312       10446 :                 if (pos + 2 >= end) {
     313           4 :                         wpa_printf(MSG_DEBUG, "P2P: Invalid P2P attribute");
     314           4 :                         return -1;
     315             :                 }
     316       10442 :                 attr_len = WPA_GET_LE16(pos + 1);
     317       20884 :                 wpa_printf(MSG_DEBUG, "P2P: Attribute %d length %u",
     318       10442 :                            pos[0], attr_len);
     319       10442 :                 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       10440 :                 if (p2p_parse_attribute(pos[0], pos + 3, attr_len, msg))
     327          25 :                         return -1;
     328       10415 :                 pos += 3 + attr_len;
     329             :         }
     330             : 
     331        4278 :         return 0;
     332             : }
     333             : 
     334             : 
     335        2222 : 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        2222 :         wpa_printf(MSG_DEBUG, "P2P: Parsing WPS IE");
     341        2222 :         if (wps_parse_msg(buf, &attr))
     342           0 :                 return -1;
     343        3992 :         if (attr.dev_name && attr.dev_name_len < sizeof(msg->device_name) &&
     344        1770 :             !msg->device_name[0])
     345        1770 :                 os_memcpy(msg->device_name, attr.dev_name, attr.dev_name_len);
     346        2222 :         if (attr.config_methods) {
     347        1882 :                 msg->wps_config_methods =
     348        1882 :                         WPA_GET_BE16(attr.config_methods);
     349        1882 :                 wpa_printf(MSG_DEBUG, "P2P: Config Methods (WPS): 0x%x",
     350        1882 :                            msg->wps_config_methods);
     351             :         }
     352        2222 :         if (attr.dev_password_id) {
     353        1427 :                 msg->dev_password_id = WPA_GET_BE16(attr.dev_password_id);
     354        1427 :                 wpa_printf(MSG_DEBUG, "P2P: Device Password ID: %d",
     355        1427 :                            msg->dev_password_id);
     356        1427 :                 msg->dev_password_id_present = 1;
     357             :         }
     358        2222 :         if (attr.primary_dev_type) {
     359             :                 char devtype[WPS_DEV_TYPE_BUFSIZE];
     360        1770 :                 msg->wps_pri_dev_type = attr.primary_dev_type;
     361        1770 :                 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        2222 :         if (attr.sec_dev_type_list) {
     366          93 :                 msg->wps_sec_dev_type_list = attr.sec_dev_type_list;
     367          93 :                 msg->wps_sec_dev_type_list_len = attr.sec_dev_type_list_len;
     368             :         }
     369             : 
     370       24442 :         for (i = 0; i < P2P_MAX_WPS_VENDOR_EXT; i++) {
     371       22220 :                 msg->wps_vendor_ext[i] = attr.vendor_ext[i];
     372       22220 :                 msg->wps_vendor_ext_len[i] = attr.vendor_ext_len[i];
     373             :         }
     374             : 
     375        2222 :         msg->manufacturer = attr.manufacturer;
     376        2222 :         msg->manufacturer_len = attr.manufacturer_len;
     377        2222 :         msg->model_name = attr.model_name;
     378        2222 :         msg->model_name_len = attr.model_name_len;
     379        2222 :         msg->model_number = attr.model_number;
     380        2222 :         msg->model_number_len = attr.model_number_len;
     381        2222 :         msg->serial_number = attr.serial_number;
     382        2222 :         msg->serial_number_len = attr.serial_number_len;
     383             : 
     384        2222 :         msg->oob_dev_password = attr.oob_dev_password;
     385        2222 :         msg->oob_dev_password_len = attr.oob_dev_password_len;
     386             : 
     387        2222 :         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        2593 : int p2p_parse_ies(const u8 *data, size_t len, struct p2p_message *msg)
     405             : {
     406             :         struct ieee802_11_elems elems;
     407             : 
     408        2593 :         ieee802_11_parse_elems(data, len, &elems, 0);
     409        2593 :         if (elems.ds_params && elems.ds_params_len >= 1)
     410        1823 :                 msg->ds_params = elems.ds_params;
     411        2593 :         if (elems.ssid)
     412        2090 :                 msg->ssid = elems.ssid - 2;
     413             : 
     414        2593 :         msg->wps_attributes = ieee802_11_vendor_ie_concat(data, len,
     415             :                                                           WPS_DEV_OUI_WFA);
     416        4791 :         if (msg->wps_attributes &&
     417        2198 :             p2p_parse_wps_ie(msg->wps_attributes, msg)) {
     418           0 :                 p2p_parse_free(msg);
     419           0 :                 return -1;
     420             :         }
     421             : 
     422        2593 :         msg->p2p_attributes = ieee802_11_vendor_ie_concat(data, len,
     423             :                                                           P2P_IE_VENDOR_TYPE);
     424        5062 :         if (msg->p2p_attributes &&
     425        2469 :             p2p_parse_p2p_ie(msg->p2p_attributes, msg)) {
     426          31 :                 wpa_printf(MSG_DEBUG, "P2P: Failed to parse P2P IE data");
     427          31 :                 if (msg->p2p_attributes)
     428          31 :                         wpa_hexdump_buf(MSG_MSGDUMP, "P2P: P2P IE data",
     429          31 :                                         msg->p2p_attributes);
     430          31 :                 p2p_parse_free(msg);
     431          31 :                 return -1;
     432             :         }
     433             : 
     434             : #ifdef CONFIG_WIFI_DISPLAY
     435        2562 :         if (elems.wfd) {
     436          21 :                 msg->wfd_subelems = ieee802_11_vendor_ie_concat(
     437             :                         data, len, WFD_IE_VENDOR_TYPE);
     438             :         }
     439             : #endif /* CONFIG_WIFI_DISPLAY */
     440             : 
     441        2562 :         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         460 : int p2p_parse(const u8 *data, size_t len, struct p2p_message *msg)
     456             : {
     457         460 :         os_memset(msg, 0, sizeof(*msg));
     458         460 :         wpa_printf(MSG_DEBUG, "P2P: Parsing the received message");
     459         460 :         if (len < 1) {
     460           1 :                 wpa_printf(MSG_DEBUG, "P2P: No Dialog Token in the message");
     461           1 :                 return -1;
     462             :         }
     463         459 :         msg->dialog_token = data[0];
     464         459 :         wpa_printf(MSG_DEBUG, "P2P: * Dialog Token: %d", msg->dialog_token);
     465             : 
     466         459 :         return p2p_parse_ies(data + 1, len - 1, msg);
     467             : }
     468             : 
     469             : 
     470          24 : 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          24 :         os_memset(msg, 0, sizeof(*msg));
     474             : 
     475          24 :         msg->wps_attributes = wpabuf_alloc_copy(wsc, wsc_len);
     476          48 :         if (msg->wps_attributes &&
     477          24 :             p2p_parse_wps_ie(msg->wps_attributes, msg)) {
     478           0 :                 p2p_parse_free(msg);
     479           0 :                 return -1;
     480             :         }
     481             : 
     482          24 :         msg->p2p_attributes = wpabuf_alloc_copy(p2p, p2p_len);
     483          48 :         if (msg->p2p_attributes &&
     484          24 :             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          24 :         return 0;
     494             : }
     495             : 
     496             : 
     497             : /**
     498             :  * p2p_parse_free - Free temporary data from P2P parsing
     499             :  * @msg: Parsed attributes
     500             :  */
     501        2617 : void p2p_parse_free(struct p2p_message *msg)
     502             : {
     503        2617 :         wpabuf_free(msg->p2p_attributes);
     504        2617 :         msg->p2p_attributes = NULL;
     505        2617 :         wpabuf_free(msg->wps_attributes);
     506        2617 :         msg->wps_attributes = NULL;
     507             : #ifdef CONFIG_WIFI_DISPLAY
     508        2617 :         wpabuf_free(msg->wfd_subelems);
     509        2617 :         msg->wfd_subelems = NULL;
     510             : #endif /* CONFIG_WIFI_DISPLAY */
     511        2617 : }
     512             : 
     513             : 
     514          26 : 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          26 :         os_memset(info, 0, sizeof(*info));
     520          26 :         if (gi == NULL)
     521           3 :                 return 0;
     522             : 
     523          23 :         g = gi;
     524          23 :         gend = gi + gi_len;
     525          69 :         while (g < gend) {
     526             :                 struct p2p_client_info *cli;
     527             :                 const u8 *t, *cend;
     528             :                 int count;
     529             : 
     530          23 :                 cli = &info->client[info->num_clients];
     531          23 :                 cend = g + 1 + g[0];
     532          23 :                 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          23 :                 t = g + 1 + 2 * ETH_ALEN;
     537          23 :                 if (t > cend)
     538           0 :                         return -1; /* invalid data */
     539          23 :                 cli->p2p_device_addr = g + 1;
     540          23 :                 cli->p2p_interface_addr = g + 1 + ETH_ALEN;
     541          23 :                 cli->dev_capab = t[0];
     542             : 
     543          23 :                 if (t + 1 + 2 + 8 + 1 > cend)
     544           0 :                         return -1; /* invalid data */
     545             : 
     546          23 :                 cli->config_methods = WPA_GET_BE16(&t[1]);
     547          23 :                 cli->pri_dev_type = &t[3];
     548             : 
     549          23 :                 t += 1 + 2 + 8;
     550             :                 /* t at Number of Secondary Device Types */
     551          23 :                 cli->num_sec_dev_types = *t++;
     552          23 :                 if (t + 8 * cli->num_sec_dev_types > cend)
     553           0 :                         return -1; /* invalid data */
     554          23 :                 cli->sec_dev_types = t;
     555          23 :                 t += 8 * cli->num_sec_dev_types;
     556             : 
     557             :                 /* t at Device Name in WPS TLV format */
     558          23 :                 if (t + 2 + 2 > cend)
     559           0 :                         return -1; /* invalid data */
     560          23 :                 if (WPA_GET_BE16(t) != ATTR_DEV_NAME)
     561           0 :                         return -1; /* invalid Device Name TLV */
     562          23 :                 t += 2;
     563          23 :                 count = WPA_GET_BE16(t);
     564          23 :                 t += 2;
     565          23 :                 if (count > cend - t)
     566           0 :                         return -1; /* invalid Device Name TLV */
     567          23 :                 if (count >= 32)
     568           0 :                         count = 32;
     569          23 :                 cli->dev_name = (const char *) t;
     570          23 :                 cli->dev_name_len = count;
     571             : 
     572          23 :                 g = cend;
     573             : 
     574          23 :                 info->num_clients++;
     575          23 :                 if (info->num_clients == P2P_MAX_GROUP_ENTRIES)
     576           0 :                         return -1;
     577             :         }
     578             : 
     579          23 :         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          10 :         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           3 :                 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          10 :                 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           4 : int p2p_get_cross_connect_disallowed(const struct wpabuf *p2p_ie)
     724             : {
     725             :         struct p2p_message msg;
     726             : 
     727           4 :         os_memset(&msg, 0, sizeof(msg));
     728           4 :         if (p2p_parse_p2p_ie(p2p_ie, &msg))
     729           0 :                 return 0;
     730             : 
     731           4 :         if (!msg.manageability)
     732           2 :                 return 0;
     733             : 
     734           2 :         return !(msg.manageability[0] & P2P_MAN_CROSS_CONNECTION_PERMITTED);
     735             : }
     736             : 
     737             : 
     738         541 : u8 p2p_get_group_capab(const struct wpabuf *p2p_ie)
     739             : {
     740             :         struct p2p_message msg;
     741             : 
     742         541 :         os_memset(&msg, 0, sizeof(msg));
     743         541 :         if (p2p_parse_p2p_ie(p2p_ie, &msg))
     744           0 :                 return 0;
     745             : 
     746         541 :         if (!msg.capability)
     747           0 :                 return 0;
     748             : 
     749         541 :         return msg.capability[1];
     750             : }
     751             : 
     752             : 
     753         659 : const u8 * p2p_get_go_dev_addr(const struct wpabuf *p2p_ie)
     754             : {
     755             :         struct p2p_message msg;
     756             : 
     757         659 :         os_memset(&msg, 0, sizeof(msg));
     758         659 :         if (p2p_parse_p2p_ie(p2p_ie, &msg))
     759           0 :                 return NULL;
     760             : 
     761         659 :         if (msg.p2p_device_addr)
     762         638 :                 return msg.p2p_device_addr;
     763          21 :         if (msg.device_id)
     764          14 :                 return msg.device_id;
     765             : 
     766           7 :         return NULL;
     767             : }

Generated by: LCOV version 1.10