LCOV - code coverage report
Current view: top level - src/p2p - p2p_build.c (source / functions) Hit Total Coverage
Test: wpa_supplicant/hostapd combined for hwsim test run 1422976643 Lines: 352 409 86.1 %
Date: 2015-02-03 Functions: 31 32 96.9 %

          Line data    Source code
       1             : /*
       2             :  * P2P - IE builder
       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 "wps/wps_i.h"
      14             : #include "p2p_i.h"
      15             : 
      16             : 
      17          10 : void p2p_buf_add_action_hdr(struct wpabuf *buf, u8 subtype, u8 dialog_token)
      18             : {
      19          10 :         wpabuf_put_u8(buf, WLAN_ACTION_VENDOR_SPECIFIC);
      20          10 :         wpabuf_put_be32(buf, P2P_IE_VENDOR_TYPE);
      21             : 
      22          10 :         wpabuf_put_u8(buf, subtype); /* OUI Subtype */
      23          10 :         wpabuf_put_u8(buf, dialog_token);
      24          10 :         wpa_printf(MSG_DEBUG, "P2P: * Dialog Token: %d", dialog_token);
      25          10 : }
      26             : 
      27             : 
      28         865 : void p2p_buf_add_public_action_hdr(struct wpabuf *buf, u8 subtype,
      29             :                                    u8 dialog_token)
      30             : {
      31         865 :         wpabuf_put_u8(buf, WLAN_ACTION_PUBLIC);
      32         865 :         wpabuf_put_u8(buf, WLAN_PA_VENDOR_SPECIFIC);
      33         865 :         wpabuf_put_be32(buf, P2P_IE_VENDOR_TYPE);
      34             : 
      35         865 :         wpabuf_put_u8(buf, subtype); /* OUI Subtype */
      36         865 :         wpabuf_put_u8(buf, dialog_token);
      37         865 :         wpa_printf(MSG_DEBUG, "P2P: * Dialog Token: %d", dialog_token);
      38         865 : }
      39             : 
      40             : 
      41        8572 : u8 * p2p_buf_add_ie_hdr(struct wpabuf *buf)
      42             : {
      43             :         u8 *len;
      44             : 
      45             :         /* P2P IE header */
      46        8572 :         wpabuf_put_u8(buf, WLAN_EID_VENDOR_SPECIFIC);
      47        8572 :         len = wpabuf_put(buf, 1); /* IE length to be filled */
      48        8572 :         wpabuf_put_be32(buf, P2P_IE_VENDOR_TYPE);
      49        8572 :         wpa_printf(MSG_DEBUG, "P2P: * P2P IE header");
      50        8572 :         return len;
      51             : }
      52             : 
      53             : 
      54       11619 : void p2p_buf_update_ie_hdr(struct wpabuf *buf, u8 *len)
      55             : {
      56             :         /* Update P2P IE Length */
      57       11619 :         *len = (u8 *) wpabuf_put(buf, 0) - len - 1;
      58       11619 : }
      59             : 
      60             : 
      61        7798 : void p2p_buf_add_capability(struct wpabuf *buf, u8 dev_capab, u8 group_capab)
      62             : {
      63             :         /* P2P Capability */
      64        7798 :         wpabuf_put_u8(buf, P2P_ATTR_CAPABILITY);
      65        7798 :         wpabuf_put_le16(buf, 2);
      66        7798 :         wpabuf_put_u8(buf, dev_capab); /* Device Capabilities */
      67        7798 :         wpabuf_put_u8(buf, group_capab); /* Group Capabilities */
      68        7798 :         wpa_printf(MSG_DEBUG, "P2P: * Capability dev=%02x group=%02x",
      69             :                    dev_capab, group_capab);
      70        7798 : }
      71             : 
      72             : 
      73         359 : void p2p_buf_add_go_intent(struct wpabuf *buf, u8 go_intent)
      74             : {
      75             :         /* Group Owner Intent */
      76         359 :         wpabuf_put_u8(buf, P2P_ATTR_GROUP_OWNER_INTENT);
      77         359 :         wpabuf_put_le16(buf, 1);
      78         359 :         wpabuf_put_u8(buf, go_intent);
      79         359 :         wpa_printf(MSG_DEBUG, "P2P: * GO Intent: Intent %u Tie breaker %u",
      80             :                    go_intent >> 1, go_intent & 0x01);
      81         359 : }
      82             : 
      83             : 
      84        2945 : void p2p_buf_add_listen_channel(struct wpabuf *buf, const char *country,
      85             :                                 u8 reg_class, u8 channel)
      86             : {
      87             :         /* Listen Channel */
      88        2945 :         wpabuf_put_u8(buf, P2P_ATTR_LISTEN_CHANNEL);
      89        2945 :         wpabuf_put_le16(buf, 5);
      90        2945 :         wpabuf_put_data(buf, country, 3);
      91        2945 :         wpabuf_put_u8(buf, reg_class); /* Regulatory Class */
      92        2945 :         wpabuf_put_u8(buf, channel); /* Channel Number */
      93        2945 :         wpa_printf(MSG_DEBUG, "P2P: * Listen Channel: Regulatory Class %u "
      94             :                    "Channel %u", reg_class, channel);
      95        2945 : }
      96             : 
      97             : 
      98         489 : void p2p_buf_add_operating_channel(struct wpabuf *buf, const char *country,
      99             :                                    u8 reg_class, u8 channel)
     100             : {
     101             :         /* Operating Channel */
     102         489 :         wpabuf_put_u8(buf, P2P_ATTR_OPERATING_CHANNEL);
     103         489 :         wpabuf_put_le16(buf, 5);
     104         489 :         wpabuf_put_data(buf, country, 3);
     105         489 :         wpabuf_put_u8(buf, reg_class); /* Regulatory Class */
     106         489 :         wpabuf_put_u8(buf, channel); /* Channel Number */
     107         489 :         wpa_printf(MSG_DEBUG, "P2P: * Operating Channel: Regulatory Class %u "
     108             :                    "Channel %u", reg_class, channel);
     109         489 : }
     110             : 
     111             : 
     112         581 : void p2p_buf_add_channel_list(struct wpabuf *buf, const char *country,
     113             :                               struct p2p_channels *chan)
     114             : {
     115             :         u8 *len;
     116             :         size_t i;
     117             : 
     118             :         /* Channel List */
     119         581 :         wpabuf_put_u8(buf, P2P_ATTR_CHANNEL_LIST);
     120         581 :         len = wpabuf_put(buf, 2); /* IE length to be filled */
     121         581 :         wpabuf_put_data(buf, country, 3); /* Country String */
     122             : 
     123        1271 :         for (i = 0; i < chan->reg_classes; i++) {
     124         690 :                 struct p2p_reg_class *c = &chan->reg_class[i];
     125         690 :                 wpabuf_put_u8(buf, c->reg_class);
     126         690 :                 wpabuf_put_u8(buf, c->channels);
     127         690 :                 wpabuf_put_data(buf, c->channel, c->channels);
     128             :         }
     129             : 
     130             :         /* Update attribute length */
     131         581 :         WPA_PUT_LE16(len, (u8 *) wpabuf_put(buf, 0) - len - 2);
     132         581 :         wpa_hexdump(MSG_DEBUG, "P2P: * Channel List",
     133         581 :                     len + 2, (u8 *) wpabuf_put(buf, 0) - len - 2);
     134         581 : }
     135             : 
     136             : 
     137         353 : void p2p_buf_add_status(struct wpabuf *buf, u8 status)
     138             : {
     139             :         /* Status */
     140         353 :         wpabuf_put_u8(buf, P2P_ATTR_STATUS);
     141         353 :         wpabuf_put_le16(buf, 1);
     142         353 :         wpabuf_put_u8(buf, status);
     143         353 :         wpa_printf(MSG_DEBUG, "P2P: * Status: %d", status);
     144         353 : }
     145             : 
     146             : 
     147        4530 : void p2p_buf_add_device_info(struct wpabuf *buf, struct p2p_data *p2p,
     148             :                              struct p2p_device *peer)
     149             : {
     150             :         u8 *len;
     151             :         u16 methods;
     152             :         size_t nlen, i;
     153             : 
     154             :         /* P2P Device Info */
     155        4530 :         wpabuf_put_u8(buf, P2P_ATTR_DEVICE_INFO);
     156        4530 :         len = wpabuf_put(buf, 2); /* IE length to be filled */
     157             : 
     158             :         /* P2P Device address */
     159        4530 :         wpabuf_put_data(buf, p2p->cfg->dev_addr, ETH_ALEN);
     160             : 
     161             :         /* Config Methods */
     162        4530 :         methods = 0;
     163        4530 :         if (peer && peer->wps_method != WPS_NOT_READY) {
     164         634 :                 if (peer->wps_method == WPS_PBC)
     165         107 :                         methods |= WPS_CONFIG_PUSHBUTTON;
     166         319 :                 else if (peer->wps_method == WPS_PIN_DISPLAY ||
     167         109 :                          peer->wps_method == WPS_PIN_KEYPAD) {
     168         190 :                         methods |= WPS_CONFIG_DISPLAY | WPS_CONFIG_KEYPAD;
     169         190 :                         methods |= WPS_CONFIG_P2PS;
     170             :                 }
     171        4213 :         } else if (p2p->cfg->config_methods) {
     172        4213 :                 methods |= p2p->cfg->config_methods &
     173             :                         (WPS_CONFIG_PUSHBUTTON | WPS_CONFIG_DISPLAY |
     174             :                          WPS_CONFIG_KEYPAD | WPS_CONFIG_P2PS);
     175             :         } else {
     176           0 :                 methods |= WPS_CONFIG_PUSHBUTTON;
     177           0 :                 methods |= WPS_CONFIG_DISPLAY | WPS_CONFIG_KEYPAD;
     178           0 :                 methods |= WPS_CONFIG_P2PS;
     179             :         }
     180        4530 :         wpabuf_put_be16(buf, methods);
     181             : 
     182             :         /* Primary Device Type */
     183        4530 :         wpabuf_put_data(buf, p2p->cfg->pri_dev_type,
     184             :                         sizeof(p2p->cfg->pri_dev_type));
     185             : 
     186             :         /* Number of Secondary Device Types */
     187        4530 :         wpabuf_put_u8(buf, p2p->cfg->num_sec_dev_types);
     188             : 
     189             :         /* Secondary Device Type List */
     190        4655 :         for (i = 0; i < p2p->cfg->num_sec_dev_types; i++)
     191         125 :                 wpabuf_put_data(buf, p2p->cfg->sec_dev_type[i],
     192             :                                 WPS_DEV_TYPE_LEN);
     193             : 
     194             :         /* Device Name */
     195        4530 :         nlen = p2p->cfg->dev_name ? os_strlen(p2p->cfg->dev_name) : 0;
     196        4530 :         wpabuf_put_be16(buf, ATTR_DEV_NAME);
     197        4530 :         wpabuf_put_be16(buf, nlen);
     198        4530 :         wpabuf_put_data(buf, p2p->cfg->dev_name, nlen);
     199             : 
     200             :         /* Update attribute length */
     201        4530 :         WPA_PUT_LE16(len, (u8 *) wpabuf_put(buf, 0) - len - 2);
     202        4530 :         wpa_printf(MSG_DEBUG, "P2P: * Device Info");
     203        4530 : }
     204             : 
     205             : 
     206         488 : void p2p_buf_add_device_id(struct wpabuf *buf, const u8 *dev_addr)
     207             : {
     208             :         /* P2P Device ID */
     209         488 :         wpabuf_put_u8(buf, P2P_ATTR_DEVICE_ID);
     210         488 :         wpabuf_put_le16(buf, ETH_ALEN);
     211         488 :         wpabuf_put_data(buf, dev_addr, ETH_ALEN);
     212         488 :         wpa_printf(MSG_DEBUG, "P2P: * Device ID: " MACSTR, MAC2STR(dev_addr));
     213         488 : }
     214             : 
     215             : 
     216         496 : void p2p_buf_add_config_timeout(struct wpabuf *buf, u8 go_timeout,
     217             :                                 u8 client_timeout)
     218             : {
     219             :         /* Configuration Timeout */
     220         496 :         wpabuf_put_u8(buf, P2P_ATTR_CONFIGURATION_TIMEOUT);
     221         496 :         wpabuf_put_le16(buf, 2);
     222         496 :         wpabuf_put_u8(buf, go_timeout);
     223         496 :         wpabuf_put_u8(buf, client_timeout);
     224         496 :         wpa_printf(MSG_DEBUG, "P2P: * Configuration Timeout: GO %d (*10ms)  "
     225             :                    "client %d (*10ms)", go_timeout, client_timeout);
     226         496 : }
     227             : 
     228             : 
     229         379 : void p2p_buf_add_intended_addr(struct wpabuf *buf, const u8 *interface_addr)
     230             : {
     231             :         /* Intended P2P Interface Address */
     232         379 :         wpabuf_put_u8(buf, P2P_ATTR_INTENDED_INTERFACE_ADDR);
     233         379 :         wpabuf_put_le16(buf, ETH_ALEN);
     234         379 :         wpabuf_put_data(buf, interface_addr, ETH_ALEN);
     235        2274 :         wpa_printf(MSG_DEBUG, "P2P: * Intended P2P Interface Address " MACSTR,
     236        2274 :                    MAC2STR(interface_addr));
     237         379 : }
     238             : 
     239             : 
     240          47 : void p2p_buf_add_group_bssid(struct wpabuf *buf, const u8 *bssid)
     241             : {
     242             :         /* P2P Group BSSID */
     243          47 :         wpabuf_put_u8(buf, P2P_ATTR_GROUP_BSSID);
     244          47 :         wpabuf_put_le16(buf, ETH_ALEN);
     245          47 :         wpabuf_put_data(buf, bssid, ETH_ALEN);
     246         282 :         wpa_printf(MSG_DEBUG, "P2P: * P2P Group BSSID " MACSTR,
     247         282 :                    MAC2STR(bssid));
     248          47 : }
     249             : 
     250             : 
     251         239 : void p2p_buf_add_group_id(struct wpabuf *buf, const u8 *dev_addr,
     252             :                           const u8 *ssid, size_t ssid_len)
     253             : {
     254             :         /* P2P Group ID */
     255         239 :         wpabuf_put_u8(buf, P2P_ATTR_GROUP_ID);
     256         239 :         wpabuf_put_le16(buf, ETH_ALEN + ssid_len);
     257         239 :         wpabuf_put_data(buf, dev_addr, ETH_ALEN);
     258         239 :         wpabuf_put_data(buf, ssid, ssid_len);
     259        1434 :         wpa_printf(MSG_DEBUG, "P2P: * P2P Group ID " MACSTR,
     260        1434 :                    MAC2STR(dev_addr));
     261         239 :         wpa_hexdump_ascii(MSG_DEBUG, "P2P: P2P Group ID SSID", ssid, ssid_len);
     262         239 : }
     263             : 
     264             : 
     265          48 : void p2p_buf_add_invitation_flags(struct wpabuf *buf, u8 flags)
     266             : {
     267             :         /* Invitation Flags */
     268          48 :         wpabuf_put_u8(buf, P2P_ATTR_INVITATION_FLAGS);
     269          48 :         wpabuf_put_le16(buf, 1);
     270          48 :         wpabuf_put_u8(buf, flags);
     271          48 :         wpa_printf(MSG_DEBUG, "P2P: * Invitation Flags: bitmap 0x%x", flags);
     272          48 : }
     273             : 
     274             : 
     275          20 : static void p2p_buf_add_noa_desc(struct wpabuf *buf, struct p2p_noa_desc *desc)
     276             : {
     277          20 :         if (desc == NULL)
     278          34 :                 return;
     279             : 
     280           6 :         wpabuf_put_u8(buf, desc->count_type);
     281           6 :         wpabuf_put_le32(buf, desc->duration);
     282           6 :         wpabuf_put_le32(buf, desc->interval);
     283           6 :         wpabuf_put_le32(buf, desc->start_time);
     284             : }
     285             : 
     286             : 
     287          10 : void p2p_buf_add_noa(struct wpabuf *buf, u8 noa_index, u8 opp_ps, u8 ctwindow,
     288             :                      struct p2p_noa_desc *desc1, struct p2p_noa_desc *desc2)
     289             : {
     290             :         /* Notice of Absence */
     291          10 :         wpabuf_put_u8(buf, P2P_ATTR_NOTICE_OF_ABSENCE);
     292          10 :         wpabuf_put_le16(buf, 2 + (desc1 ? 13 : 0) + (desc2 ? 13 : 0));
     293          10 :         wpabuf_put_u8(buf, noa_index);
     294          10 :         wpabuf_put_u8(buf, (opp_ps ? 0x80 : 0) | (ctwindow & 0x7f));
     295          10 :         p2p_buf_add_noa_desc(buf, desc1);
     296          10 :         p2p_buf_add_noa_desc(buf, desc2);
     297          10 :         wpa_printf(MSG_DEBUG, "P2P: * Notice of Absence");
     298          10 : }
     299             : 
     300             : 
     301          18 : void p2p_buf_add_ext_listen_timing(struct wpabuf *buf, u16 period,
     302             :                                    u16 interval)
     303             : {
     304             :         /* Extended Listen Timing */
     305          18 :         wpabuf_put_u8(buf, P2P_ATTR_EXT_LISTEN_TIMING);
     306          18 :         wpabuf_put_le16(buf, 4);
     307          18 :         wpabuf_put_le16(buf, period);
     308          18 :         wpabuf_put_le16(buf, interval);
     309          18 :         wpa_printf(MSG_DEBUG, "P2P: * Extended Listen Timing (period %u msec  "
     310             :                    "interval %u msec)", period, interval);
     311          18 : }
     312             : 
     313             : 
     314           0 : void p2p_buf_add_p2p_interface(struct wpabuf *buf, struct p2p_data *p2p)
     315             : {
     316             :         /* P2P Interface */
     317           0 :         wpabuf_put_u8(buf, P2P_ATTR_INTERFACE);
     318           0 :         wpabuf_put_le16(buf, ETH_ALEN + 1 + ETH_ALEN);
     319             :         /* P2P Device address */
     320           0 :         wpabuf_put_data(buf, p2p->cfg->dev_addr, ETH_ALEN);
     321             :         /*
     322             :          * FIX: Fetch interface address list from driver. Do not include
     323             :          * the P2P Device address if it is never used as interface address.
     324             :          */
     325             :         /* P2P Interface Address Count */
     326           0 :         wpabuf_put_u8(buf, 1);
     327           0 :         wpabuf_put_data(buf, p2p->cfg->dev_addr, ETH_ALEN);
     328           0 : }
     329             : 
     330             : 
     331          30 : void p2p_buf_add_oob_go_neg_channel(struct wpabuf *buf, const char *country,
     332             :                                     u8 oper_class, u8 channel,
     333             :                                     enum p2p_role_indication role)
     334             : {
     335             :         /* OOB Group Owner Negotiation Channel */
     336          30 :         wpabuf_put_u8(buf, P2P_ATTR_OOB_GO_NEG_CHANNEL);
     337          30 :         wpabuf_put_le16(buf, 6);
     338          30 :         wpabuf_put_data(buf, country, 3);
     339          30 :         wpabuf_put_u8(buf, oper_class); /* Operating Class */
     340          30 :         wpabuf_put_u8(buf, channel); /* Channel Number */
     341          30 :         wpabuf_put_u8(buf, (u8) role); /* Role indication */
     342          30 :         wpa_printf(MSG_DEBUG, "P2P: * OOB GO Negotiation Channel: Operating "
     343             :                    "Class %u Channel %u Role %d",
     344             :                    oper_class, channel, role);
     345          30 : }
     346             : 
     347             : 
     348          28 : void p2p_buf_add_service_hash(struct wpabuf *buf, struct p2p_data *p2p)
     349             : {
     350          28 :         if (!p2p)
     351          28 :                 return;
     352             : 
     353             :         /* Service Hash */
     354          28 :         wpabuf_put_u8(buf, P2P_ATTR_SERVICE_HASH);
     355          28 :         wpabuf_put_le16(buf, p2p->p2ps_seek_count * P2PS_HASH_LEN);
     356          28 :         wpabuf_put_data(buf, p2p->query_hash,
     357          28 :                         p2p->p2ps_seek_count * P2PS_HASH_LEN);
     358          56 :         wpa_hexdump(MSG_DEBUG, "P2P: * Service Hash",
     359          56 :                     p2p->query_hash, p2p->p2ps_seek_count * P2PS_HASH_LEN);
     360             : }
     361             : 
     362             : 
     363           4 : void p2p_buf_add_session_info(struct wpabuf *buf, const char *info)
     364             : {
     365           4 :         size_t info_len = 0;
     366             : 
     367           4 :         if (info && info[0])
     368           4 :                 info_len = os_strlen(info);
     369             : 
     370             :         /* Session Information Data Info */
     371           4 :         wpabuf_put_u8(buf, P2P_ATTR_SESSION_INFORMATION_DATA);
     372           4 :         wpabuf_put_le16(buf, (u16) info_len);
     373             : 
     374           4 :         if (info) {
     375           4 :                 wpabuf_put_data(buf, info, info_len);
     376           4 :                 wpa_printf(MSG_DEBUG, "P2P: * Session Info Data (%s)", info);
     377             :         }
     378           4 : }
     379             : 
     380             : 
     381          31 : void p2p_buf_add_connection_capability(struct wpabuf *buf, u8 connection_cap)
     382             : {
     383             :         /* Connection Capability Info */
     384          31 :         wpabuf_put_u8(buf, P2P_ATTR_CONNECTION_CAPABILITY);
     385          31 :         wpabuf_put_le16(buf, 1);
     386          31 :         wpabuf_put_u8(buf, connection_cap);
     387          31 :         wpa_printf(MSG_DEBUG, "P2P: * Connection Capability: 0x%x",
     388             :                    connection_cap);
     389          31 : }
     390             : 
     391             : 
     392          36 : void p2p_buf_add_advertisement_id(struct wpabuf *buf, u32 id, const u8 *mac)
     393             : {
     394          36 :         if (!buf || !mac)
     395          36 :                 return;
     396             : 
     397             :         /* Advertisement ID Info */
     398          36 :         wpabuf_put_u8(buf, P2P_ATTR_ADVERTISEMENT_ID);
     399          36 :         wpabuf_put_le16(buf, (u16) (sizeof(u32) + ETH_ALEN));
     400          36 :         wpabuf_put_le32(buf, id);
     401          36 :         wpabuf_put_data(buf, mac, ETH_ALEN);
     402         216 :         wpa_printf(MSG_DEBUG, "P2P: * Advertisement ID (%x) " MACSTR,
     403         216 :                    id, MAC2STR(mac));
     404             : }
     405             : 
     406             : 
     407          25 : void p2p_buf_add_service_instance(struct wpabuf *buf, struct p2p_data *p2p,
     408             :                                   u8 hash_count, const u8 *hash,
     409             :                                   struct p2ps_advertisement *adv_list)
     410             : {
     411             :         struct p2ps_advertisement *adv;
     412             :         struct wpabuf *tmp_buf;
     413          25 :         u8 *tag_len = NULL, *ie_len = NULL;
     414          25 :         size_t svc_len = 0, remaining = 0, total_len = 0;
     415             : 
     416          25 :         if (!adv_list || !hash)
     417           0 :                 return;
     418             : 
     419             :         /* Allocate temp buffer, allowing for overflow of 1 instance */
     420          25 :         tmp_buf = wpabuf_alloc(MAX_SVC_ADV_IE_LEN + 256 + P2PS_HASH_LEN);
     421          25 :         if (!tmp_buf)
     422           0 :                 return;
     423             : 
     424          76 :         for (adv = adv_list; adv && total_len <= MAX_SVC_ADV_LEN;
     425          26 :              adv = adv->next) {
     426          34 :                 u8 count = hash_count;
     427          34 :                 const u8 *test = hash;
     428             : 
     429          77 :                 while (count--) {
     430             :                         /* Check for wildcard */
     431          34 :                         if (os_memcmp(test, p2p->wild_card_hash,
     432             :                                       P2PS_HASH_LEN) == 0) {
     433           8 :                                 total_len = MAX_SVC_ADV_LEN + 1;
     434           8 :                                 goto wild_hash;
     435             :                         }
     436             : 
     437          26 :                         if (os_memcmp(test, adv->hash, P2PS_HASH_LEN) == 0)
     438          17 :                                 goto hash_match;
     439             : 
     440           9 :                         test += P2PS_HASH_LEN;
     441             :                 }
     442             : 
     443             :                 /* No matches found - Skip this Adv Instance */
     444           9 :                 continue;
     445             : 
     446             : hash_match:
     447          17 :                 if (!tag_len) {
     448          17 :                         tag_len = p2p_buf_add_ie_hdr(tmp_buf);
     449          17 :                         remaining = 255 - 4;
     450          17 :                         if (!ie_len) {
     451          17 :                                 wpabuf_put_u8(tmp_buf,
     452             :                                               P2P_ATTR_ADVERTISED_SERVICE);
     453          17 :                                 ie_len = wpabuf_put(tmp_buf, sizeof(u16));
     454          17 :                                 remaining -= (sizeof(u8) + sizeof(u16));
     455             :                         }
     456             :                 }
     457             : 
     458          17 :                 svc_len = os_strlen(adv->svc_name);
     459             : 
     460          17 :                 if (7 + svc_len + total_len > MAX_SVC_ADV_LEN) {
     461             :                         /* Can't fit... return wildcard */
     462           0 :                         total_len = MAX_SVC_ADV_LEN + 1;
     463           0 :                         break;
     464             :                 }
     465             : 
     466          17 :                 if (remaining <= (sizeof(adv->id) +
     467             :                                   sizeof(adv->config_methods))) {
     468           0 :                         size_t front = remaining;
     469           0 :                         size_t back = (sizeof(adv->id) +
     470             :                                        sizeof(adv->config_methods)) - front;
     471             :                         u8 holder[sizeof(adv->id) +
     472             :                                   sizeof(adv->config_methods)];
     473             : 
     474             :                         /* This works even if front or back == 0 */
     475           0 :                         WPA_PUT_LE32(holder, adv->id);
     476           0 :                         WPA_PUT_BE16(&holder[sizeof(adv->id)],
     477           0 :                                      adv->config_methods);
     478           0 :                         wpabuf_put_data(tmp_buf, holder, front);
     479           0 :                         p2p_buf_update_ie_hdr(tmp_buf, tag_len);
     480           0 :                         tag_len = p2p_buf_add_ie_hdr(tmp_buf);
     481           0 :                         wpabuf_put_data(tmp_buf, &holder[front], back);
     482           0 :                         remaining = 255 - (sizeof(adv->id) +
     483             :                                            sizeof(adv->config_methods)) - back;
     484             :                 } else {
     485          17 :                         wpabuf_put_le32(tmp_buf, adv->id);
     486          17 :                         wpabuf_put_be16(tmp_buf, adv->config_methods);
     487          17 :                         remaining -= (sizeof(adv->id) +
     488             :                                       sizeof(adv->config_methods));
     489             :                 }
     490             : 
     491             :                 /* We are guaranteed at least one byte for svc_len */
     492          17 :                 wpabuf_put_u8(tmp_buf, svc_len);
     493          17 :                 remaining -= sizeof(u8);
     494             : 
     495          17 :                 if (remaining < svc_len) {
     496           0 :                         size_t front = remaining;
     497           0 :                         size_t back = svc_len - front;
     498             : 
     499           0 :                         wpabuf_put_data(tmp_buf, adv->svc_name, front);
     500           0 :                         p2p_buf_update_ie_hdr(tmp_buf, tag_len);
     501           0 :                         tag_len = p2p_buf_add_ie_hdr(tmp_buf);
     502             : 
     503             :                         /* In rare cases, we must split across 3 attributes */
     504           0 :                         if (back > 255 - 4) {
     505           0 :                                 wpabuf_put_data(tmp_buf,
     506           0 :                                                 &adv->svc_name[front], 255 - 4);
     507           0 :                                 back -= 255 - 4;
     508           0 :                                 front += 255 - 4;
     509           0 :                                 p2p_buf_update_ie_hdr(tmp_buf, tag_len);
     510           0 :                                 tag_len = p2p_buf_add_ie_hdr(tmp_buf);
     511             :                         }
     512             : 
     513           0 :                         wpabuf_put_data(tmp_buf, &adv->svc_name[front], back);
     514           0 :                         remaining = 255 - 4 - back;
     515             :                 } else {
     516          17 :                         wpabuf_put_data(tmp_buf, adv->svc_name, svc_len);
     517          17 :                         remaining -= svc_len;
     518             :                 }
     519             : 
     520             :                 /*           adv_id      config_methods     svc_string */
     521          17 :                 total_len += sizeof(u32) + sizeof(u16) + sizeof(u8) + svc_len;
     522             :         }
     523             : 
     524          17 :         if (tag_len)
     525          17 :                 p2p_buf_update_ie_hdr(tmp_buf, tag_len);
     526             : 
     527          17 :         if (ie_len)
     528          17 :                 WPA_PUT_LE16(ie_len, (u16) total_len);
     529             : 
     530             : wild_hash:
     531             :         /* If all fit, return matching instances, otherwise the wildcard */
     532          25 :         if (total_len <= MAX_SVC_ADV_LEN) {
     533          17 :                 wpabuf_put_buf(buf, tmp_buf);
     534             :         } else {
     535           8 :                 char *wild_card = P2PS_WILD_HASH_STR;
     536             :                 u8 wild_len;
     537             : 
     538             :                 /* Insert wildcard instance */
     539           8 :                 tag_len = p2p_buf_add_ie_hdr(buf);
     540           8 :                 wpabuf_put_u8(buf, P2P_ATTR_ADVERTISED_SERVICE);
     541           8 :                 ie_len = wpabuf_put(buf, sizeof(u16));
     542             : 
     543           8 :                 wild_len = (u8) os_strlen(wild_card);
     544           8 :                 wpabuf_put_le32(buf, 0);
     545           8 :                 wpabuf_put_be16(buf, 0);
     546           8 :                 wpabuf_put_u8(buf, wild_len);
     547           8 :                 wpabuf_put_data(buf, wild_card, wild_len);
     548             : 
     549           8 :                 WPA_PUT_LE16(ie_len, 4 + 2 + 1 + wild_len);
     550           8 :                 p2p_buf_update_ie_hdr(buf, tag_len);
     551             :         }
     552             : 
     553          25 :         wpabuf_free(tmp_buf);
     554             : }
     555             : 
     556             : 
     557          36 : void p2p_buf_add_session_id(struct wpabuf *buf, u32 id, const u8 *mac)
     558             : {
     559          36 :         if (!buf || !mac)
     560          36 :                 return;
     561             : 
     562             :         /* Session ID Info */
     563          36 :         wpabuf_put_u8(buf, P2P_ATTR_SESSION_ID);
     564          36 :         wpabuf_put_le16(buf, (u16) (sizeof(u32) + ETH_ALEN));
     565          36 :         wpabuf_put_le32(buf, id);
     566          36 :         wpabuf_put_data(buf, mac, ETH_ALEN);
     567         216 :         wpa_printf(MSG_DEBUG, "P2P: * Session ID Info (%x) " MACSTR,
     568         216 :                    id, MAC2STR(mac));
     569             : }
     570             : 
     571             : 
     572          36 : void p2p_buf_add_feature_capability(struct wpabuf *buf, u16 len, const u8 *mask)
     573             : {
     574          36 :         if (!buf || !len || !mask)
     575          36 :                 return;
     576             : 
     577             :         /* Feature Capability */
     578          36 :         wpabuf_put_u8(buf, P2P_ATTR_FEATURE_CAPABILITY);
     579          36 :         wpabuf_put_le16(buf, len);
     580          36 :         wpabuf_put_data(buf, mask, len);
     581          36 :         wpa_printf(MSG_DEBUG, "P2P: * Feature Capability (%d)", len);
     582             : }
     583             : 
     584             : 
     585           2 : void p2p_buf_add_persistent_group_info(struct wpabuf *buf, const u8 *dev_addr,
     586             :                                        const u8 *ssid, size_t ssid_len)
     587             : {
     588             :         /* P2P Group ID */
     589           2 :         wpabuf_put_u8(buf, P2P_ATTR_PERSISTENT_GROUP);
     590           2 :         wpabuf_put_le16(buf, ETH_ALEN + ssid_len);
     591           2 :         wpabuf_put_data(buf, dev_addr, ETH_ALEN);
     592           2 :         wpabuf_put_data(buf, ssid, ssid_len);
     593          12 :         wpa_printf(MSG_DEBUG, "P2P: * P2P Group ID " MACSTR,
     594          12 :                    MAC2STR(dev_addr));
     595           2 : }
     596             : 
     597             : 
     598       12025 : static int p2p_add_wps_string(struct wpabuf *buf, enum wps_attribute attr,
     599             :                               const char *val)
     600             : {
     601             :         size_t len;
     602             : 
     603       12025 :         len = val ? os_strlen(val) : 0;
     604       12025 :         if (wpabuf_tailroom(buf) < 4 + len)
     605           0 :                 return -1;
     606       12025 :         wpabuf_put_be16(buf, attr);
     607             : #ifndef CONFIG_WPS_STRICT
     608       12025 :         if (len == 0) {
     609             :                 /*
     610             :                  * Some deployed WPS implementations fail to parse zeor-length
     611             :                  * attributes. As a workaround, send a space character if the
     612             :                  * device attribute string is empty.
     613             :                  */
     614        9677 :                 if (wpabuf_tailroom(buf) < 3)
     615           0 :                         return -1;
     616        9677 :                 wpabuf_put_be16(buf, 1);
     617        9677 :                 wpabuf_put_u8(buf, ' ');
     618        9677 :                 return 0;
     619             :         }
     620             : #endif /* CONFIG_WPS_STRICT */
     621        2348 :         wpabuf_put_be16(buf, len);
     622        2348 :         if (val)
     623        2348 :                 wpabuf_put_data(buf, val, len);
     624        2348 :         return 0;
     625             : }
     626             : 
     627             : 
     628        2767 : int p2p_build_wps_ie(struct p2p_data *p2p, struct wpabuf *buf, int pw_id,
     629             :                      int all_attr)
     630             : {
     631             :         u8 *len;
     632             :         int i;
     633             : 
     634        2767 :         if (wpabuf_tailroom(buf) < 6)
     635           0 :                 return -1;
     636        2767 :         wpabuf_put_u8(buf, WLAN_EID_VENDOR_SPECIFIC);
     637        2767 :         len = wpabuf_put(buf, 1);
     638        2767 :         wpabuf_put_be32(buf, WPS_DEV_OUI_WFA);
     639             : 
     640        2767 :         if (wps_build_version(buf) < 0)
     641           0 :                 return -1;
     642             : 
     643        2767 :         if (all_attr) {
     644        2405 :                 if (wpabuf_tailroom(buf) < 5)
     645           0 :                         return -1;
     646        2405 :                 wpabuf_put_be16(buf, ATTR_WPS_STATE);
     647        2405 :                 wpabuf_put_be16(buf, 1);
     648        2405 :                 wpabuf_put_u8(buf, WPS_STATE_NOT_CONFIGURED);
     649             :         }
     650             : 
     651        2767 :         if (pw_id >= 0) {
     652        1155 :                 if (wpabuf_tailroom(buf) < 6)
     653           0 :                         return -1;
     654             :                 /* Device Password ID */
     655        1155 :                 wpabuf_put_be16(buf, ATTR_DEV_PASSWORD_ID);
     656        1155 :                 wpabuf_put_be16(buf, 2);
     657        1155 :                 wpa_printf(MSG_DEBUG, "P2P: WPS IE Device Password ID: %d",
     658             :                            pw_id);
     659        1155 :                 wpabuf_put_be16(buf, pw_id);
     660             :         }
     661             : 
     662        2767 :         if (all_attr) {
     663        2405 :                 if (wpabuf_tailroom(buf) < 5)
     664           0 :                         return -1;
     665        2405 :                 wpabuf_put_be16(buf, ATTR_RESPONSE_TYPE);
     666        2405 :                 wpabuf_put_be16(buf, 1);
     667        2405 :                 wpabuf_put_u8(buf, WPS_RESP_ENROLLEE_INFO);
     668             : 
     669        4810 :                 if (wps_build_uuid_e(buf, p2p->cfg->uuid) < 0 ||
     670        2405 :                     p2p_add_wps_string(buf, ATTR_MANUFACTURER,
     671        4810 :                                        p2p->cfg->manufacturer) < 0 ||
     672        2405 :                     p2p_add_wps_string(buf, ATTR_MODEL_NAME,
     673        4810 :                                        p2p->cfg->model_name) < 0 ||
     674        2405 :                     p2p_add_wps_string(buf, ATTR_MODEL_NUMBER,
     675        4810 :                                        p2p->cfg->model_number) < 0 ||
     676        2405 :                     p2p_add_wps_string(buf, ATTR_SERIAL_NUMBER,
     677        2405 :                                        p2p->cfg->serial_number) < 0)
     678           0 :                         return -1;
     679             : 
     680        2405 :                 if (wpabuf_tailroom(buf) < 4 + WPS_DEV_TYPE_LEN)
     681           0 :                         return -1;
     682        2405 :                 wpabuf_put_be16(buf, ATTR_PRIMARY_DEV_TYPE);
     683        2405 :                 wpabuf_put_be16(buf, WPS_DEV_TYPE_LEN);
     684        2405 :                 wpabuf_put_data(buf, p2p->cfg->pri_dev_type, WPS_DEV_TYPE_LEN);
     685             : 
     686        2405 :                 if (p2p_add_wps_string(buf, ATTR_DEV_NAME, p2p->cfg->dev_name)
     687             :                     < 0)
     688           0 :                         return -1;
     689             : 
     690        2405 :                 if (wpabuf_tailroom(buf) < 6)
     691           0 :                         return -1;
     692        2405 :                 wpabuf_put_be16(buf, ATTR_CONFIG_METHODS);
     693        2405 :                 wpabuf_put_be16(buf, 2);
     694        2405 :                 wpabuf_put_be16(buf, p2p->cfg->config_methods);
     695             :         }
     696             : 
     697        2767 :         if (wps_build_wfa_ext(buf, 0, NULL, 0) < 0)
     698           0 :                 return -1;
     699             : 
     700        2767 :         if (all_attr && p2p->cfg->num_sec_dev_types) {
     701         108 :                 if (wpabuf_tailroom(buf) <
     702          54 :                     4 + WPS_DEV_TYPE_LEN * p2p->cfg->num_sec_dev_types)
     703           0 :                         return -1;
     704          54 :                 wpabuf_put_be16(buf, ATTR_SECONDARY_DEV_TYPE_LIST);
     705          54 :                 wpabuf_put_be16(buf, WPS_DEV_TYPE_LEN *
     706          54 :                                 p2p->cfg->num_sec_dev_types);
     707          54 :                 wpabuf_put_data(buf, p2p->cfg->sec_dev_type,
     708             :                                 WPS_DEV_TYPE_LEN *
     709          54 :                                 p2p->cfg->num_sec_dev_types);
     710             :         }
     711             : 
     712             :         /* Add the WPS vendor extensions */
     713        2767 :         for (i = 0; i < P2P_MAX_WPS_VENDOR_EXT; i++) {
     714        2767 :                 if (p2p->wps_vendor_ext[i] == NULL)
     715        2767 :                         break;
     716           0 :                 if (wpabuf_tailroom(buf) <
     717           0 :                     4 + wpabuf_len(p2p->wps_vendor_ext[i]))
     718           0 :                         continue;
     719           0 :                 wpabuf_put_be16(buf, ATTR_VENDOR_EXT);
     720           0 :                 wpabuf_put_be16(buf, wpabuf_len(p2p->wps_vendor_ext[i]));
     721           0 :                 wpabuf_put_buf(buf, p2p->wps_vendor_ext[i]);
     722             :         }
     723             : 
     724        2767 :         p2p_buf_update_ie_hdr(buf, len);
     725             : 
     726        2767 :         return 0;
     727             : }

Generated by: LCOV version 1.10