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