Home | History | Annotate | Download | only in p2p
      1 /*
      2  * P2P - IE builder
      3  * Copyright (c) 2009-2010, Atheros Communications
      4  *
      5  * This program is free software; you can redistribute it and/or modify
      6  * it under the terms of the GNU General Public License version 2 as
      7  * published by the Free Software Foundation.
      8  *
      9  * Alternatively, this software may be distributed under the terms of BSD
     10  * license.
     11  *
     12  * See README and COPYING for more details.
     13  */
     14 
     15 #include "includes.h"
     16 
     17 #include "common.h"
     18 #include "common/ieee802_11_defs.h"
     19 #include "wps/wps_i.h"
     20 #include "p2p_i.h"
     21 
     22 
     23 void p2p_buf_add_action_hdr(struct wpabuf *buf, u8 subtype, u8 dialog_token)
     24 {
     25 	wpabuf_put_u8(buf, WLAN_ACTION_VENDOR_SPECIFIC);
     26 	wpabuf_put_be24(buf, OUI_WFA);
     27 	wpabuf_put_u8(buf, P2P_OUI_TYPE);
     28 
     29 	wpabuf_put_u8(buf, subtype); /* OUI Subtype */
     30 	wpabuf_put_u8(buf, dialog_token);
     31 	wpa_printf(MSG_DEBUG, "P2P: * Dialog Token: %d", dialog_token);
     32 }
     33 
     34 
     35 void p2p_buf_add_public_action_hdr(struct wpabuf *buf, u8 subtype,
     36 				   u8 dialog_token)
     37 {
     38 	wpabuf_put_u8(buf, WLAN_ACTION_PUBLIC);
     39 	wpabuf_put_u8(buf, WLAN_PA_VENDOR_SPECIFIC);
     40 	wpabuf_put_be24(buf, OUI_WFA);
     41 	wpabuf_put_u8(buf, P2P_OUI_TYPE);
     42 
     43 	wpabuf_put_u8(buf, subtype); /* OUI Subtype */
     44 	wpabuf_put_u8(buf, dialog_token);
     45 	wpa_printf(MSG_DEBUG, "P2P: * Dialog Token: %d", dialog_token);
     46 }
     47 
     48 
     49 u8 * p2p_buf_add_ie_hdr(struct wpabuf *buf)
     50 {
     51 	u8 *len;
     52 
     53 	/* P2P IE header */
     54 	wpabuf_put_u8(buf, WLAN_EID_VENDOR_SPECIFIC);
     55 	len = wpabuf_put(buf, 1); /* IE length to be filled */
     56 	wpabuf_put_be24(buf, OUI_WFA);
     57 	wpabuf_put_u8(buf, P2P_OUI_TYPE);
     58 	wpa_printf(MSG_DEBUG, "P2P: * P2P IE header");
     59 	return len;
     60 }
     61 
     62 
     63 void p2p_buf_update_ie_hdr(struct wpabuf *buf, u8 *len)
     64 {
     65 	/* Update P2P IE Length */
     66 	*len = (u8 *) wpabuf_put(buf, 0) - len - 1;
     67 }
     68 
     69 
     70 void p2p_buf_add_capability(struct wpabuf *buf, u8 dev_capab, u8 group_capab)
     71 {
     72 	/* P2P Capability */
     73 	wpabuf_put_u8(buf, P2P_ATTR_CAPABILITY);
     74 	wpabuf_put_le16(buf, 2);
     75 	wpabuf_put_u8(buf, dev_capab); /* Device Capabilities */
     76 	wpabuf_put_u8(buf, group_capab); /* Group Capabilities */
     77 	wpa_printf(MSG_DEBUG, "P2P: * Capability dev=%02x group=%02x",
     78 		   dev_capab, group_capab);
     79 }
     80 
     81 
     82 void p2p_buf_add_go_intent(struct wpabuf *buf, u8 go_intent)
     83 {
     84 	/* Group Owner Intent */
     85 	wpabuf_put_u8(buf, P2P_ATTR_GROUP_OWNER_INTENT);
     86 	wpabuf_put_le16(buf, 1);
     87 	wpabuf_put_u8(buf, go_intent);
     88 	wpa_printf(MSG_DEBUG, "P2P: * GO Intent: Intent %u Tie breaker %u",
     89 		   go_intent >> 1, go_intent & 0x01);
     90 }
     91 
     92 
     93 void p2p_buf_add_listen_channel(struct wpabuf *buf, const char *country,
     94 				u8 reg_class, u8 channel)
     95 {
     96 	/* Listen Channel */
     97 	wpabuf_put_u8(buf, P2P_ATTR_LISTEN_CHANNEL);
     98 	wpabuf_put_le16(buf, 5);
     99 	wpabuf_put_data(buf, country, 3);
    100 	wpabuf_put_u8(buf, reg_class); /* Regulatory Class */
    101 	wpabuf_put_u8(buf, channel); /* Channel Number */
    102 	wpa_printf(MSG_DEBUG, "P2P: * Listen Channel: Regulatory Class %u "
    103 		   "Channel %u", reg_class, channel);
    104 }
    105 
    106 
    107 void p2p_buf_add_operating_channel(struct wpabuf *buf, const char *country,
    108 				   u8 reg_class, u8 channel)
    109 {
    110 	/* Operating Channel */
    111 	wpabuf_put_u8(buf, P2P_ATTR_OPERATING_CHANNEL);
    112 	wpabuf_put_le16(buf, 5);
    113 	wpabuf_put_data(buf, country, 3);
    114 	wpabuf_put_u8(buf, reg_class); /* Regulatory Class */
    115 	wpabuf_put_u8(buf, channel); /* Channel Number */
    116 	wpa_printf(MSG_DEBUG, "P2P: * Operating Channel: Regulatory Class %u "
    117 		   "Channel %u", reg_class, channel);
    118 }
    119 
    120 
    121 void p2p_buf_add_channel_list(struct wpabuf *buf, const char *country,
    122 			      struct p2p_channels *chan)
    123 {
    124 	u8 *len;
    125 	size_t i;
    126 
    127 	/* Channel List */
    128 	wpabuf_put_u8(buf, P2P_ATTR_CHANNEL_LIST);
    129 	len = wpabuf_put(buf, 2); /* IE length to be filled */
    130 	wpabuf_put_data(buf, country, 3); /* Country String */
    131 
    132 	for (i = 0; i < chan->reg_classes; i++) {
    133 		struct p2p_reg_class *c = &chan->reg_class[i];
    134 		wpabuf_put_u8(buf, c->reg_class);
    135 		wpabuf_put_u8(buf, c->channels);
    136 		wpabuf_put_data(buf, c->channel, c->channels);
    137 	}
    138 
    139 	/* Update attribute length */
    140 	WPA_PUT_LE16(len, (u8 *) wpabuf_put(buf, 0) - len - 2);
    141 	wpa_printf(MSG_DEBUG, "P2P: * Channel List");
    142 }
    143 
    144 
    145 void p2p_buf_add_status(struct wpabuf *buf, u8 status)
    146 {
    147 	/* Status */
    148 	wpabuf_put_u8(buf, P2P_ATTR_STATUS);
    149 	wpabuf_put_le16(buf, 1);
    150 	wpabuf_put_u8(buf, status);
    151 	wpa_printf(MSG_DEBUG, "P2P: * Status: %d", status);
    152 }
    153 
    154 
    155 void p2p_buf_add_device_info(struct wpabuf *buf, struct p2p_data *p2p,
    156 			     struct p2p_device *peer)
    157 {
    158 	u8 *len;
    159 	u16 methods;
    160 	size_t nlen, i;
    161 
    162 	/* P2P Device Info */
    163 	wpabuf_put_u8(buf, P2P_ATTR_DEVICE_INFO);
    164 	len = wpabuf_put(buf, 2); /* IE length to be filled */
    165 
    166 	/* P2P Device address */
    167 #ifdef ANDROID_BRCM_P2P_PATCH
    168 	/*
    169 	* P2P_ADDR: Supplicant uses primary mac addr for p2p and hence advertises that. To
    170 	* to make it compatible with solution using virtual interface for P2P, a new variable
    171 	* is added to hold the actual p2p device address.
    172 	*/
    173 	wpabuf_put_data(buf, p2p->cfg->p2p_dev_addr, ETH_ALEN);
    174 #else
    175 	wpabuf_put_data(buf, p2p->cfg->dev_addr, ETH_ALEN);
    176 #endif
    177 
    178 	/* Config Methods */
    179 	methods = 0;
    180 	if (peer && peer->wps_method != WPS_NOT_READY) {
    181 		if (peer->wps_method == WPS_PBC)
    182 			methods |= WPS_CONFIG_PUSHBUTTON;
    183 		else if (peer->wps_method == WPS_PIN_LABEL)
    184 			methods |= WPS_CONFIG_LABEL;
    185 		else if (peer->wps_method == WPS_PIN_DISPLAY ||
    186 			 peer->wps_method == WPS_PIN_KEYPAD)
    187 			methods |= WPS_CONFIG_DISPLAY | WPS_CONFIG_KEYPAD;
    188 	} else {
    189 		methods |= WPS_CONFIG_PUSHBUTTON;
    190 		methods |= WPS_CONFIG_DISPLAY | WPS_CONFIG_KEYPAD;
    191 	}
    192 	wpabuf_put_be16(buf, methods);
    193 
    194 	/* Primary Device Type */
    195 	wpabuf_put_data(buf, p2p->cfg->pri_dev_type,
    196 			sizeof(p2p->cfg->pri_dev_type));
    197 
    198 	/* Number of Secondary Device Types */
    199 	wpabuf_put_u8(buf, p2p->cfg->num_sec_dev_types);
    200 
    201 	/* Secondary Device Type List */
    202 	for (i = 0; i < p2p->cfg->num_sec_dev_types; i++)
    203 		wpabuf_put_data(buf, p2p->cfg->sec_dev_type[i],
    204 				WPS_DEV_TYPE_LEN);
    205 
    206 	/* Device Name */
    207 	nlen = p2p->cfg->dev_name ? os_strlen(p2p->cfg->dev_name) : 0;
    208 	wpabuf_put_be16(buf, ATTR_DEV_NAME);
    209 	wpabuf_put_be16(buf, nlen);
    210 	wpabuf_put_data(buf, p2p->cfg->dev_name, nlen);
    211 
    212 	/* Update attribute length */
    213 	WPA_PUT_LE16(len, (u8 *) wpabuf_put(buf, 0) - len - 2);
    214 	wpa_printf(MSG_DEBUG, "P2P: * Device Info");
    215 }
    216 
    217 
    218 void p2p_buf_add_device_id(struct wpabuf *buf, const u8 *dev_addr)
    219 {
    220 	/* P2P Device ID */
    221 	wpabuf_put_u8(buf, P2P_ATTR_DEVICE_ID);
    222 	wpabuf_put_le16(buf, ETH_ALEN);
    223 	wpabuf_put_data(buf, dev_addr, ETH_ALEN);
    224 	wpa_printf(MSG_DEBUG, "P2P: * Device ID: " MACSTR, MAC2STR(dev_addr));
    225 }
    226 
    227 
    228 void p2p_buf_add_config_timeout(struct wpabuf *buf, u8 go_timeout,
    229 				u8 client_timeout)
    230 {
    231 	/* Configuration Timeout */
    232 	wpabuf_put_u8(buf, P2P_ATTR_CONFIGURATION_TIMEOUT);
    233 	wpabuf_put_le16(buf, 2);
    234 	wpabuf_put_u8(buf, go_timeout);
    235 	wpabuf_put_u8(buf, client_timeout);
    236 	wpa_printf(MSG_DEBUG, "P2P: * Configuration Timeout: GO %d (*10ms)  "
    237 		   "client %d (*10ms)", go_timeout, client_timeout);
    238 }
    239 
    240 
    241 void p2p_buf_add_intended_addr(struct wpabuf *buf, const u8 *interface_addr)
    242 {
    243 	/* Intended P2P Interface Address */
    244 	wpabuf_put_u8(buf, P2P_ATTR_INTENDED_INTERFACE_ADDR);
    245 	wpabuf_put_le16(buf, ETH_ALEN);
    246 	wpabuf_put_data(buf, interface_addr, ETH_ALEN);
    247 	wpa_printf(MSG_DEBUG, "P2P: * Intended P2P Interface Address " MACSTR,
    248 		   MAC2STR(interface_addr));
    249 }
    250 
    251 
    252 void p2p_buf_add_group_bssid(struct wpabuf *buf, const u8 *bssid)
    253 {
    254 	/* P2P Group BSSID */
    255 	wpabuf_put_u8(buf, P2P_ATTR_GROUP_BSSID);
    256 	wpabuf_put_le16(buf, ETH_ALEN);
    257 	wpabuf_put_data(buf, bssid, ETH_ALEN);
    258 	wpa_printf(MSG_DEBUG, "P2P: * P2P Group BSSID " MACSTR,
    259 		   MAC2STR(bssid));
    260 }
    261 
    262 
    263 void p2p_buf_add_group_id(struct wpabuf *buf, const u8 *dev_addr,
    264 			  const u8 *ssid, size_t ssid_len)
    265 {
    266 	/* P2P Group ID */
    267 	wpabuf_put_u8(buf, P2P_ATTR_GROUP_ID);
    268 	wpabuf_put_le16(buf, ETH_ALEN + ssid_len);
    269 	wpabuf_put_data(buf, dev_addr, ETH_ALEN);
    270 	wpabuf_put_data(buf, ssid, ssid_len);
    271 	wpa_printf(MSG_DEBUG, "P2P: * P2P Group ID " MACSTR,
    272 		   MAC2STR(dev_addr));
    273 }
    274 
    275 
    276 void p2p_buf_add_invitation_flags(struct wpabuf *buf, u8 flags)
    277 {
    278 	/* Invitation Flags */
    279 	wpabuf_put_u8(buf, P2P_ATTR_INVITATION_FLAGS);
    280 	wpabuf_put_le16(buf, 1);
    281 	wpabuf_put_u8(buf, flags);
    282 	wpa_printf(MSG_DEBUG, "P2P: * Invitation Flags: bitmap 0x%x", flags);
    283 }
    284 
    285 
    286 static void p2p_buf_add_noa_desc(struct wpabuf *buf, struct p2p_noa_desc *desc)
    287 {
    288 	if (desc == NULL)
    289 		return;
    290 
    291 	wpabuf_put_u8(buf, desc->count_type);
    292 	wpabuf_put_le32(buf, desc->duration);
    293 	wpabuf_put_le32(buf, desc->interval);
    294 	wpabuf_put_le32(buf, desc->start_time);
    295 }
    296 
    297 
    298 void p2p_buf_add_noa(struct wpabuf *buf, u8 noa_index, u8 opp_ps, u8 ctwindow,
    299 		     struct p2p_noa_desc *desc1, struct p2p_noa_desc *desc2)
    300 {
    301 	/* Notice of Absence */
    302 	wpabuf_put_u8(buf, P2P_ATTR_NOTICE_OF_ABSENCE);
    303 	wpabuf_put_le16(buf, 2 + (desc1 ? 13 : 0) + (desc2 ? 13 : 0));
    304 	wpabuf_put_u8(buf, noa_index);
    305 	wpabuf_put_u8(buf, (opp_ps ? 0x80 : 0) | (ctwindow & 0x7f));
    306 	p2p_buf_add_noa_desc(buf, desc1);
    307 	p2p_buf_add_noa_desc(buf, desc2);
    308 	wpa_printf(MSG_DEBUG, "P2P: * Notice of Absence");
    309 }
    310 
    311 
    312 void p2p_buf_add_ext_listen_timing(struct wpabuf *buf, u16 period,
    313 				   u16 interval)
    314 {
    315 	/* Extended Listen Timing */
    316 	wpabuf_put_u8(buf, P2P_ATTR_EXT_LISTEN_TIMING);
    317 	wpabuf_put_le16(buf, 4);
    318 	wpabuf_put_le16(buf, period);
    319 	wpabuf_put_le16(buf, interval);
    320 	wpa_printf(MSG_DEBUG, "P2P: * Extended Listen Timing (period %u msec  "
    321 		   "interval %u msec)", period, interval);
    322 }
    323 
    324 
    325 void p2p_buf_add_p2p_interface(struct wpabuf *buf, struct p2p_data *p2p)
    326 {
    327 	/* P2P Interface */
    328 	wpabuf_put_u8(buf, P2P_ATTR_INTERFACE);
    329 	wpabuf_put_le16(buf, ETH_ALEN + 1 + ETH_ALEN);
    330 	/* P2P Device address */
    331 	wpabuf_put_data(buf, p2p->cfg->dev_addr, ETH_ALEN);
    332 	/*
    333 	 * FIX: Fetch interface address list from driver. Do not include
    334 	 * the P2P Device address if it is never used as interface address.
    335 	 */
    336 	/* P2P Interface Address Count */
    337 	wpabuf_put_u8(buf, 1);
    338 	wpabuf_put_data(buf, p2p->cfg->dev_addr, ETH_ALEN);
    339 }
    340 
    341 
    342 static void p2p_add_wps_string(struct wpabuf *buf, enum wps_attribute attr,
    343 			       const char *val)
    344 {
    345 	size_t len;
    346 
    347 	wpabuf_put_be16(buf, attr);
    348 	len = val ? os_strlen(val) : 0;
    349 #ifndef CONFIG_WPS_STRICT
    350 	if (len == 0) {
    351 		/*
    352 		 * Some deployed WPS implementations fail to parse zeor-length
    353 		 * attributes. As a workaround, send a space character if the
    354 		 * device attribute string is empty.
    355 		 */
    356 		wpabuf_put_be16(buf, 1);
    357 		wpabuf_put_u8(buf, ' ');
    358 		return;
    359 	}
    360 #endif /* CONFIG_WPS_STRICT */
    361 	wpabuf_put_be16(buf, len);
    362 	if (val)
    363 		wpabuf_put_data(buf, val, len);
    364 }
    365 
    366 
    367 void p2p_build_wps_ie(struct p2p_data *p2p, struct wpabuf *buf, u16 pw_id,
    368 		      int all_attr)
    369 {
    370 	u8 *len;
    371 	int i;
    372 
    373 	wpabuf_put_u8(buf, WLAN_EID_VENDOR_SPECIFIC);
    374 	len = wpabuf_put(buf, 1);
    375 	wpabuf_put_be32(buf, WPS_DEV_OUI_WFA);
    376 
    377 	wps_build_version(buf);
    378 
    379 	if (all_attr) {
    380 		wpabuf_put_be16(buf, ATTR_WPS_STATE);
    381 		wpabuf_put_be16(buf, 1);
    382 		wpabuf_put_u8(buf, WPS_STATE_NOT_CONFIGURED);
    383 	}
    384 
    385 	/* Device Password ID */
    386 	wpabuf_put_be16(buf, ATTR_DEV_PASSWORD_ID);
    387 	wpabuf_put_be16(buf, 2);
    388 	wpa_printf(MSG_DEBUG, "P2P: WPS IE Device Password ID: %d", pw_id);
    389 	wpabuf_put_be16(buf, pw_id);
    390 
    391 	if (all_attr) {
    392 		wpabuf_put_be16(buf, ATTR_RESPONSE_TYPE);
    393 		wpabuf_put_be16(buf, 1);
    394 		wpabuf_put_u8(buf, WPS_RESP_ENROLLEE_INFO);
    395 
    396 		wps_build_uuid_e(buf, p2p->cfg->uuid);
    397 		p2p_add_wps_string(buf, ATTR_MANUFACTURER,
    398 				   p2p->cfg->manufacturer);
    399 		p2p_add_wps_string(buf, ATTR_MODEL_NAME, p2p->cfg->model_name);
    400 		p2p_add_wps_string(buf, ATTR_MODEL_NUMBER,
    401 				   p2p->cfg->model_number);
    402 		p2p_add_wps_string(buf, ATTR_SERIAL_NUMBER,
    403 				   p2p->cfg->serial_number);
    404 
    405 		wpabuf_put_be16(buf, ATTR_PRIMARY_DEV_TYPE);
    406 		wpabuf_put_be16(buf, WPS_DEV_TYPE_LEN);
    407 		wpabuf_put_data(buf, p2p->cfg->pri_dev_type, WPS_DEV_TYPE_LEN);
    408 
    409 		p2p_add_wps_string(buf, ATTR_DEV_NAME, p2p->cfg->dev_name);
    410 
    411 		wpabuf_put_be16(buf, ATTR_CONFIG_METHODS);
    412 		wpabuf_put_be16(buf, 2);
    413 		wpabuf_put_be16(buf, p2p->cfg->config_methods);
    414 	}
    415 
    416 	wps_build_wfa_ext(buf, 0, NULL, 0);
    417 
    418 	if (all_attr && p2p->cfg->num_sec_dev_types) {
    419 		wpabuf_put_be16(buf, ATTR_SECONDARY_DEV_TYPE_LIST);
    420 		wpabuf_put_be16(buf, WPS_DEV_TYPE_LEN *
    421 				p2p->cfg->num_sec_dev_types);
    422 		wpabuf_put_data(buf, p2p->cfg->sec_dev_type,
    423 				WPS_DEV_TYPE_LEN *
    424 				p2p->cfg->num_sec_dev_types);
    425 	}
    426 
    427 	/* Add the WPS vendor extensions */
    428 	for (i = 0; i < P2P_MAX_WPS_VENDOR_EXT; i++) {
    429 		if (p2p->wps_vendor_ext[i] == NULL)
    430 			break;
    431 		if (wpabuf_tailroom(buf) <
    432 		    4 + wpabuf_len(p2p->wps_vendor_ext[i]))
    433 			continue;
    434 		wpabuf_put_be16(buf, ATTR_VENDOR_EXT);
    435 		wpabuf_put_be16(buf, wpabuf_len(p2p->wps_vendor_ext[i]));
    436 		wpabuf_put_buf(buf, p2p->wps_vendor_ext[i]);
    437 	}
    438 
    439 	p2p_buf_update_ie_hdr(buf, len);
    440 }
    441