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