Home | History | Annotate | Download | only in wpa_supplicant
      1 /*
      2  * wpa_supplicant - MBO
      3  *
      4  * Copyright(c) 2015 Intel Deutschland GmbH
      5  * Contact Information:
      6  * Intel Linux Wireless <ilw (at) linux.intel.com>
      7  * Intel Corporation, 5200 N.E. Elam Young Parkway, Hillsboro, OR 97124-6497
      8  *
      9  * This software may be distributed under the terms of the BSD license.
     10  * See README for more details.
     11  */
     12 
     13 #include "utils/includes.h"
     14 
     15 #include "utils/common.h"
     16 #include "common/ieee802_11_defs.h"
     17 #include "common/gas.h"
     18 #include "config.h"
     19 #include "wpa_supplicant_i.h"
     20 #include "driver_i.h"
     21 #include "bss.h"
     22 #include "scan.h"
     23 
     24 /* type + length + oui + oui type */
     25 #define MBO_IE_HEADER 6
     26 
     27 
     28 static int wpas_mbo_validate_non_pref_chan(u8 oper_class, u8 chan, u8 reason)
     29 {
     30 	if (reason > MBO_NON_PREF_CHAN_REASON_INT_INTERFERENCE)
     31 		return -1;
     32 
     33 	/* Only checking the validity of the channel and oper_class */
     34 	if (ieee80211_chan_to_freq(NULL, oper_class, chan) == -1)
     35 		return -1;
     36 
     37 	return 0;
     38 }
     39 
     40 
     41 const u8 * wpas_mbo_get_bss_attr(struct wpa_bss *bss, enum mbo_attr_id attr)
     42 {
     43 	const u8 *mbo, *end;
     44 
     45 	if (!bss)
     46 		return NULL;
     47 
     48 	mbo = wpa_bss_get_vendor_ie(bss, MBO_IE_VENDOR_TYPE);
     49 	if (!mbo)
     50 		return NULL;
     51 
     52 	end = mbo + 2 + mbo[1];
     53 	mbo += MBO_IE_HEADER;
     54 
     55 	return get_ie(mbo, end - mbo, attr);
     56 }
     57 
     58 
     59 static void wpas_mbo_non_pref_chan_attr_body(struct wpa_supplicant *wpa_s,
     60 					     struct wpabuf *mbo,
     61 					     u8 start, u8 end)
     62 {
     63 	u8 i;
     64 
     65 	wpabuf_put_u8(mbo, wpa_s->non_pref_chan[start].oper_class);
     66 
     67 	for (i = start; i < end; i++)
     68 		wpabuf_put_u8(mbo, wpa_s->non_pref_chan[i].chan);
     69 
     70 	wpabuf_put_u8(mbo, wpa_s->non_pref_chan[start].preference);
     71 	wpabuf_put_u8(mbo, wpa_s->non_pref_chan[start].reason);
     72 }
     73 
     74 
     75 static void wpas_mbo_non_pref_chan_attr(struct wpa_supplicant *wpa_s,
     76 					struct wpabuf *mbo, u8 start, u8 end)
     77 {
     78 	size_t size = end - start + 3;
     79 
     80 	if (size + 2 > wpabuf_tailroom(mbo))
     81 		return;
     82 
     83 	wpabuf_put_u8(mbo, MBO_ATTR_ID_NON_PREF_CHAN_REPORT);
     84 	wpabuf_put_u8(mbo, size); /* Length */
     85 
     86 	wpas_mbo_non_pref_chan_attr_body(wpa_s, mbo, start, end);
     87 }
     88 
     89 
     90 static void wpas_mbo_non_pref_chan_subelem_hdr(struct wpabuf *mbo, u8 len)
     91 {
     92 	wpabuf_put_u8(mbo, WLAN_EID_VENDOR_SPECIFIC);
     93 	wpabuf_put_u8(mbo, len); /* Length */
     94 	wpabuf_put_be24(mbo, OUI_WFA);
     95 	wpabuf_put_u8(mbo, MBO_ATTR_ID_NON_PREF_CHAN_REPORT);
     96 }
     97 
     98 
     99 static void wpas_mbo_non_pref_chan_subelement(struct wpa_supplicant *wpa_s,
    100 					      struct wpabuf *mbo, u8 start,
    101 					      u8 end)
    102 {
    103 	size_t size = end - start + 7;
    104 
    105 	if (size + 2 > wpabuf_tailroom(mbo))
    106 		return;
    107 
    108 	wpas_mbo_non_pref_chan_subelem_hdr(mbo, size);
    109 	wpas_mbo_non_pref_chan_attr_body(wpa_s, mbo, start, end);
    110 }
    111 
    112 
    113 static void wpas_mbo_non_pref_chan_attrs(struct wpa_supplicant *wpa_s,
    114 					 struct wpabuf *mbo, int subelement)
    115 {
    116 	u8 i, start = 0;
    117 	struct wpa_mbo_non_pref_channel *start_pref;
    118 
    119 	if (!wpa_s->non_pref_chan || !wpa_s->non_pref_chan_num) {
    120 		if (subelement)
    121 			wpas_mbo_non_pref_chan_subelem_hdr(mbo, 4);
    122 		return;
    123 	}
    124 	start_pref = &wpa_s->non_pref_chan[0];
    125 
    126 	for (i = 1; i <= wpa_s->non_pref_chan_num; i++) {
    127 		struct wpa_mbo_non_pref_channel *non_pref = NULL;
    128 
    129 		if (i < wpa_s->non_pref_chan_num)
    130 			non_pref = &wpa_s->non_pref_chan[i];
    131 		if (!non_pref ||
    132 		    non_pref->oper_class != start_pref->oper_class ||
    133 		    non_pref->reason != start_pref->reason ||
    134 		    non_pref->preference != start_pref->preference) {
    135 			if (subelement)
    136 				wpas_mbo_non_pref_chan_subelement(wpa_s, mbo,
    137 								  start, i);
    138 			else
    139 				wpas_mbo_non_pref_chan_attr(wpa_s, mbo, start,
    140 							    i);
    141 
    142 			if (!non_pref)
    143 				return;
    144 
    145 			start = i;
    146 			start_pref = non_pref;
    147 		}
    148 	}
    149 }
    150 
    151 
    152 int wpas_mbo_ie(struct wpa_supplicant *wpa_s, u8 *buf, size_t len)
    153 {
    154 	struct wpabuf *mbo;
    155 	int res;
    156 
    157 	if (len < MBO_IE_HEADER + 3 + 7 +
    158 	    ((wpa_s->enable_oce & OCE_STA) ? 3 : 0))
    159 		return 0;
    160 
    161 	/* Leave room for the MBO IE header */
    162 	mbo = wpabuf_alloc(len - MBO_IE_HEADER);
    163 	if (!mbo)
    164 		return 0;
    165 
    166 	/* Add non-preferred channels attribute */
    167 	wpas_mbo_non_pref_chan_attrs(wpa_s, mbo, 0);
    168 
    169 	/*
    170 	 * Send cellular capabilities attribute even if AP does not advertise
    171 	 * cellular capabilities.
    172 	 */
    173 	wpabuf_put_u8(mbo, MBO_ATTR_ID_CELL_DATA_CAPA);
    174 	wpabuf_put_u8(mbo, 1);
    175 	wpabuf_put_u8(mbo, wpa_s->conf->mbo_cell_capa);
    176 
    177 	/* Add OCE capability indication attribute if OCE is enabled */
    178 	if (wpa_s->enable_oce & OCE_STA) {
    179 		wpabuf_put_u8(mbo, OCE_ATTR_ID_CAPA_IND);
    180 		wpabuf_put_u8(mbo, 1);
    181 		wpabuf_put_u8(mbo, OCE_RELEASE);
    182 	}
    183 
    184 	res = mbo_add_ie(buf, len, wpabuf_head_u8(mbo), wpabuf_len(mbo));
    185 	if (!res)
    186 		wpa_printf(MSG_ERROR, "Failed to add MBO/OCE IE");
    187 
    188 	wpabuf_free(mbo);
    189 	return res;
    190 }
    191 
    192 
    193 static void wpas_mbo_send_wnm_notification(struct wpa_supplicant *wpa_s,
    194 					   const u8 *data, size_t len)
    195 {
    196 	struct wpabuf *buf;
    197 	int res;
    198 
    199 	/*
    200 	 * Send WNM-Notification Request frame only in case of a change in
    201 	 * non-preferred channels list during association, if the AP supports
    202 	 * MBO.
    203 	 */
    204 	if (wpa_s->wpa_state != WPA_COMPLETED || !wpa_s->current_bss ||
    205 	    !wpa_bss_get_vendor_ie(wpa_s->current_bss, MBO_IE_VENDOR_TYPE))
    206 		return;
    207 
    208 	buf = wpabuf_alloc(4 + len);
    209 	if (!buf)
    210 		return;
    211 
    212 	wpabuf_put_u8(buf, WLAN_ACTION_WNM);
    213 	wpabuf_put_u8(buf, WNM_NOTIFICATION_REQ);
    214 	wpa_s->mbo_wnm_token++;
    215 	if (wpa_s->mbo_wnm_token == 0)
    216 		wpa_s->mbo_wnm_token++;
    217 	wpabuf_put_u8(buf, wpa_s->mbo_wnm_token);
    218 	wpabuf_put_u8(buf, WLAN_EID_VENDOR_SPECIFIC); /* Type */
    219 
    220 	wpabuf_put_data(buf, data, len);
    221 
    222 	res = wpa_drv_send_action(wpa_s, wpa_s->assoc_freq, 0, wpa_s->bssid,
    223 				  wpa_s->own_addr, wpa_s->bssid,
    224 				  wpabuf_head(buf), wpabuf_len(buf), 0);
    225 	if (res < 0)
    226 		wpa_printf(MSG_DEBUG,
    227 			   "Failed to send WNM-Notification Request frame with non-preferred channel list");
    228 
    229 	wpabuf_free(buf);
    230 }
    231 
    232 
    233 static void wpas_mbo_non_pref_chan_changed(struct wpa_supplicant *wpa_s)
    234 {
    235 	struct wpabuf *buf;
    236 
    237 	buf = wpabuf_alloc(512);
    238 	if (!buf)
    239 		return;
    240 
    241 	wpas_mbo_non_pref_chan_attrs(wpa_s, buf, 1);
    242 	wpas_mbo_send_wnm_notification(wpa_s, wpabuf_head_u8(buf),
    243 				       wpabuf_len(buf));
    244 	wpabuf_free(buf);
    245 }
    246 
    247 
    248 static int wpa_non_pref_chan_is_eq(struct wpa_mbo_non_pref_channel *a,
    249 				   struct wpa_mbo_non_pref_channel *b)
    250 {
    251 	return a->oper_class == b->oper_class && a->chan == b->chan;
    252 }
    253 
    254 
    255 /*
    256  * wpa_non_pref_chan_cmp - Compare two channels for sorting
    257  *
    258  * In MBO IE non-preferred channel subelement we can put many channels in an
    259  * attribute if they are in the same operating class and have the same
    260  * preference and reason. To make it easy for the functions that build
    261  * the IE attributes and WNM Request subelements, save the channels sorted
    262  * by their oper_class and reason.
    263  */
    264 static int wpa_non_pref_chan_cmp(const void *_a, const void *_b)
    265 {
    266 	const struct wpa_mbo_non_pref_channel *a = _a, *b = _b;
    267 
    268 	if (a->oper_class != b->oper_class)
    269 		return a->oper_class - b->oper_class;
    270 	if (a->reason != b->reason)
    271 		return a->reason - b->reason;
    272 	return a->preference - b->preference;
    273 }
    274 
    275 
    276 int wpas_mbo_update_non_pref_chan(struct wpa_supplicant *wpa_s,
    277 				  const char *non_pref_chan)
    278 {
    279 	char *cmd, *token, *context = NULL;
    280 	struct wpa_mbo_non_pref_channel *chans = NULL, *tmp_chans;
    281 	size_t num = 0, size = 0;
    282 	unsigned i;
    283 
    284 	wpa_printf(MSG_DEBUG, "MBO: Update non-preferred channels, non_pref_chan=%s",
    285 		   non_pref_chan ? non_pref_chan : "N/A");
    286 
    287 	/*
    288 	 * The shortest channel configuration is 7 characters - 3 colons and
    289 	 * 4 values.
    290 	 */
    291 	if (!non_pref_chan || os_strlen(non_pref_chan) < 7)
    292 		goto update;
    293 
    294 	cmd = os_strdup(non_pref_chan);
    295 	if (!cmd)
    296 		return -1;
    297 
    298 	while ((token = str_token(cmd, " ", &context))) {
    299 		struct wpa_mbo_non_pref_channel *chan;
    300 		int ret;
    301 		unsigned int _oper_class;
    302 		unsigned int _chan;
    303 		unsigned int _preference;
    304 		unsigned int _reason;
    305 
    306 		if (num == size) {
    307 			size = size ? size * 2 : 1;
    308 			tmp_chans = os_realloc_array(chans, size,
    309 						     sizeof(*chans));
    310 			if (!tmp_chans) {
    311 				wpa_printf(MSG_ERROR,
    312 					   "Couldn't reallocate non_pref_chan");
    313 				goto fail;
    314 			}
    315 			chans = tmp_chans;
    316 		}
    317 
    318 		chan = &chans[num];
    319 
    320 		ret = sscanf(token, "%u:%u:%u:%u", &_oper_class,
    321 			     &_chan, &_preference, &_reason);
    322 		if (ret != 4 ||
    323 		    _oper_class > 255 || _chan > 255 ||
    324 		    _preference > 255 || _reason > 65535 ) {
    325 			wpa_printf(MSG_ERROR, "Invalid non-pref chan input %s",
    326 				   token);
    327 			goto fail;
    328 		}
    329 		chan->oper_class = _oper_class;
    330 		chan->chan = _chan;
    331 		chan->preference = _preference;
    332 		chan->reason = _reason;
    333 
    334 		if (wpas_mbo_validate_non_pref_chan(chan->oper_class,
    335 						    chan->chan, chan->reason)) {
    336 			wpa_printf(MSG_ERROR,
    337 				   "Invalid non_pref_chan: oper class %d chan %d reason %d",
    338 				   chan->oper_class, chan->chan, chan->reason);
    339 			goto fail;
    340 		}
    341 
    342 		for (i = 0; i < num; i++)
    343 			if (wpa_non_pref_chan_is_eq(chan, &chans[i]))
    344 				break;
    345 		if (i != num) {
    346 			wpa_printf(MSG_ERROR,
    347 				   "oper class %d chan %d is duplicated",
    348 				   chan->oper_class, chan->chan);
    349 			goto fail;
    350 		}
    351 
    352 		num++;
    353 	}
    354 
    355 	os_free(cmd);
    356 
    357 	if (chans) {
    358 		qsort(chans, num, sizeof(struct wpa_mbo_non_pref_channel),
    359 		      wpa_non_pref_chan_cmp);
    360 	}
    361 
    362 update:
    363 	os_free(wpa_s->non_pref_chan);
    364 	wpa_s->non_pref_chan = chans;
    365 	wpa_s->non_pref_chan_num = num;
    366 	wpas_mbo_non_pref_chan_changed(wpa_s);
    367 
    368 	return 0;
    369 
    370 fail:
    371 	os_free(chans);
    372 	os_free(cmd);
    373 	return -1;
    374 }
    375 
    376 
    377 void wpas_mbo_scan_ie(struct wpa_supplicant *wpa_s, struct wpabuf *ie)
    378 {
    379 	u8 *len;
    380 
    381 	wpabuf_put_u8(ie, WLAN_EID_VENDOR_SPECIFIC);
    382 	len = wpabuf_put(ie, 1);
    383 
    384 	wpabuf_put_be24(ie, OUI_WFA);
    385 	wpabuf_put_u8(ie, MBO_OUI_TYPE);
    386 
    387 	wpabuf_put_u8(ie, MBO_ATTR_ID_CELL_DATA_CAPA);
    388 	wpabuf_put_u8(ie, 1);
    389 	wpabuf_put_u8(ie, wpa_s->conf->mbo_cell_capa);
    390 	if (wpa_s->enable_oce & OCE_STA) {
    391 		wpabuf_put_u8(ie, OCE_ATTR_ID_CAPA_IND);
    392 		wpabuf_put_u8(ie, 1);
    393 		wpabuf_put_u8(ie, OCE_RELEASE);
    394 	}
    395 	*len = (u8 *) wpabuf_put(ie, 0) - len - 1;
    396 }
    397 
    398 
    399 void wpas_mbo_ie_trans_req(struct wpa_supplicant *wpa_s, const u8 *mbo_ie,
    400 			   size_t len)
    401 {
    402 	const u8 *pos, *cell_pref = NULL;
    403 	u8 id, elen;
    404 	u16 disallowed_sec = 0;
    405 
    406 	if (len <= 4 || WPA_GET_BE24(mbo_ie) != OUI_WFA ||
    407 	    mbo_ie[3] != MBO_OUI_TYPE)
    408 		return;
    409 
    410 	pos = mbo_ie + 4;
    411 	len -= 4;
    412 
    413 	while (len >= 2) {
    414 		id = *pos++;
    415 		elen = *pos++;
    416 		len -= 2;
    417 
    418 		if (elen > len)
    419 			goto fail;
    420 
    421 		switch (id) {
    422 		case MBO_ATTR_ID_CELL_DATA_PREF:
    423 			if (elen != 1)
    424 				goto fail;
    425 
    426 			if (wpa_s->conf->mbo_cell_capa ==
    427 			    MBO_CELL_CAPA_AVAILABLE)
    428 				cell_pref = pos;
    429 			else
    430 				wpa_printf(MSG_DEBUG,
    431 					   "MBO: Station does not support Cellular data connection");
    432 			break;
    433 		case MBO_ATTR_ID_TRANSITION_REASON:
    434 			if (elen != 1)
    435 				goto fail;
    436 
    437 			wpa_s->wnm_mbo_trans_reason_present = 1;
    438 			wpa_s->wnm_mbo_transition_reason = *pos;
    439 			break;
    440 		case MBO_ATTR_ID_ASSOC_RETRY_DELAY:
    441 			if (elen != 2)
    442 				goto fail;
    443 
    444 			if (wpa_s->wnm_mode &
    445 			    WNM_BSS_TM_REQ_BSS_TERMINATION_INCLUDED) {
    446 				wpa_printf(MSG_DEBUG,
    447 					   "MBO: Unexpected association retry delay, BSS is terminating");
    448 				goto fail;
    449 			} else if (wpa_s->wnm_mode &
    450 				   WNM_BSS_TM_REQ_DISASSOC_IMMINENT) {
    451 				disallowed_sec = WPA_GET_LE16(pos);
    452 				wpa_printf(MSG_DEBUG,
    453 					   "MBO: Association retry delay: %u",
    454 					   disallowed_sec);
    455 			} else {
    456 				wpa_printf(MSG_DEBUG,
    457 					   "MBO: Association retry delay attribute not in disassoc imminent mode");
    458 			}
    459 
    460 			break;
    461 		case MBO_ATTR_ID_AP_CAPA_IND:
    462 		case MBO_ATTR_ID_NON_PREF_CHAN_REPORT:
    463 		case MBO_ATTR_ID_CELL_DATA_CAPA:
    464 		case MBO_ATTR_ID_ASSOC_DISALLOW:
    465 		case MBO_ATTR_ID_TRANSITION_REJECT_REASON:
    466 			wpa_printf(MSG_DEBUG,
    467 				   "MBO: Attribute %d should not be included in BTM Request frame",
    468 				   id);
    469 			break;
    470 		default:
    471 			wpa_printf(MSG_DEBUG, "MBO: Unknown attribute id %u",
    472 				   id);
    473 			return;
    474 		}
    475 
    476 		pos += elen;
    477 		len -= elen;
    478 	}
    479 
    480 	if (cell_pref)
    481 		wpa_msg(wpa_s, MSG_INFO, MBO_CELL_PREFERENCE "preference=%u",
    482 			*cell_pref);
    483 
    484 	if (wpa_s->wnm_mbo_trans_reason_present)
    485 		wpa_msg(wpa_s, MSG_INFO, MBO_TRANSITION_REASON "reason=%u",
    486 			wpa_s->wnm_mbo_transition_reason);
    487 
    488 	if (disallowed_sec && wpa_s->current_bss)
    489 		wpa_bss_tmp_disallow(wpa_s, wpa_s->current_bss->bssid,
    490 				     disallowed_sec);
    491 
    492 	return;
    493 fail:
    494 	wpa_printf(MSG_DEBUG, "MBO IE parsing failed (id=%u len=%u left=%zu)",
    495 		   id, elen, len);
    496 }
    497 
    498 
    499 size_t wpas_mbo_ie_bss_trans_reject(struct wpa_supplicant *wpa_s, u8 *pos,
    500 				    size_t len,
    501 				    enum mbo_transition_reject_reason reason)
    502 {
    503 	u8 reject_attr[3];
    504 
    505 	reject_attr[0] = MBO_ATTR_ID_TRANSITION_REJECT_REASON;
    506 	reject_attr[1] = 1;
    507 	reject_attr[2] = reason;
    508 
    509 	return mbo_add_ie(pos, len, reject_attr, sizeof(reject_attr));
    510 }
    511 
    512 
    513 void wpas_mbo_update_cell_capa(struct wpa_supplicant *wpa_s, u8 mbo_cell_capa)
    514 {
    515 	u8 cell_capa[7];
    516 
    517 	if (wpa_s->conf->mbo_cell_capa == mbo_cell_capa) {
    518 		wpa_printf(MSG_DEBUG,
    519 			   "MBO: Cellular capability already set to %u",
    520 			   mbo_cell_capa);
    521 		return;
    522 	}
    523 
    524 	wpa_s->conf->mbo_cell_capa = mbo_cell_capa;
    525 
    526 	cell_capa[0] = WLAN_EID_VENDOR_SPECIFIC;
    527 	cell_capa[1] = 5; /* Length */
    528 	WPA_PUT_BE24(cell_capa + 2, OUI_WFA);
    529 	cell_capa[5] = MBO_ATTR_ID_CELL_DATA_CAPA;
    530 	cell_capa[6] = mbo_cell_capa;
    531 
    532 	wpas_mbo_send_wnm_notification(wpa_s, cell_capa, 7);
    533 	wpa_supplicant_set_default_scan_ies(wpa_s);
    534 }
    535 
    536 
    537 struct wpabuf * mbo_build_anqp_buf(struct wpa_supplicant *wpa_s,
    538 				   struct wpa_bss *bss, u32 mbo_subtypes)
    539 {
    540 	struct wpabuf *anqp_buf;
    541 	u8 *len_pos;
    542 	u8 i;
    543 
    544 	if (!wpa_bss_get_vendor_ie(bss, MBO_IE_VENDOR_TYPE)) {
    545 		wpa_printf(MSG_INFO, "MBO: " MACSTR
    546 			   " does not support MBO - cannot request MBO ANQP elements from it",
    547 			   MAC2STR(bss->bssid));
    548 		return NULL;
    549 	}
    550 
    551 	/* Allocate size for the maximum case - all MBO subtypes are set */
    552 	anqp_buf = wpabuf_alloc(9 + MAX_MBO_ANQP_SUBTYPE);
    553 	if (!anqp_buf)
    554 		return NULL;
    555 
    556 	len_pos = gas_anqp_add_element(anqp_buf, ANQP_VENDOR_SPECIFIC);
    557 	wpabuf_put_be24(anqp_buf, OUI_WFA);
    558 	wpabuf_put_u8(anqp_buf, MBO_ANQP_OUI_TYPE);
    559 
    560 	wpabuf_put_u8(anqp_buf, MBO_ANQP_SUBTYPE_QUERY_LIST);
    561 
    562 	/* The first valid MBO subtype is 1 */
    563 	for (i = 1; i <= MAX_MBO_ANQP_SUBTYPE; i++) {
    564 		if (mbo_subtypes & BIT(i))
    565 			wpabuf_put_u8(anqp_buf, i);
    566 	}
    567 
    568 	gas_anqp_set_element_len(anqp_buf, len_pos);
    569 
    570 	return anqp_buf;
    571 }
    572 
    573 
    574 void mbo_parse_rx_anqp_resp(struct wpa_supplicant *wpa_s,
    575 			    struct wpa_bss *bss, const u8 *sa,
    576 			    const u8 *data, size_t slen)
    577 {
    578 	const u8 *pos = data;
    579 	u8 subtype;
    580 
    581 	if (slen < 1)
    582 		return;
    583 
    584 	subtype = *pos++;
    585 	slen--;
    586 
    587 	switch (subtype) {
    588 	case MBO_ANQP_SUBTYPE_CELL_CONN_PREF:
    589 		if (slen < 1)
    590 			break;
    591 		wpa_msg(wpa_s, MSG_INFO, RX_MBO_ANQP MACSTR
    592 			" cell_conn_pref=%u", MAC2STR(sa), *pos);
    593 		break;
    594 	default:
    595 		wpa_printf(MSG_DEBUG, "MBO: Unsupported ANQP subtype %u",
    596 			   subtype);
    597 		break;
    598 	}
    599 }
    600