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