/** * gas_query_req - Request a GAS query * @gas: GAS query data from gas_query_init() * @dst: Destination MAC address for the query * @freq: Frequency (in MHz) for the channel on which to send the query * @req: GAS query payload (to be freed by gas_query module in case of success * return) * @cb: Callback function for reporting GAS query result and response * @ctx: Context pointer to use with the @cb call * Returns: dialog token (>= 0) on success or -1 on failure */ int gas_query_req(struct gas_query *gas, const u8 *dst, int freq, struct wpabuf *req, void (*cb)(void *ctx, const u8 *dst, u8 dialog_token, enum gas_query_result result, const struct wpabuf *adv_proto, const struct wpabuf *resp, u16 status_code), void *ctx) { struct gas_query_pending *query; int dialog_token; static int next_start = 0; if (wpabuf_len(req) < 3) return -1; for (dialog_token = 0; dialog_token < 256; dialog_token++) { if (gas_query_dialog_token_available( gas, dst, (next_start + dialog_token) % 256)) break; } if (dialog_token == 256) return -1; /* Too many pending queries */ dialog_token = (next_start + dialog_token) % 256; next_start = (dialog_token + 1) % 256; query = os_zalloc(sizeof(*query)); if (query == NULL) return -1; query->gas = gas; os_memcpy(query->addr, dst, ETH_ALEN); query->dialog_token = dialog_token; query->freq = freq; query->cb = cb; query->ctx = ctx; query->req = req; dl_list_add(&gas->pending, &query->list); *(wpabuf_mhead_u8(req) + 2) = dialog_token; wpa_msg(gas->wpa_s, MSG_INFO, GAS_QUERY_START "addr=" MACSTR " dialog_token=%u freq=%d", MAC2STR(query->addr), query->dialog_token, query->freq); if (radio_add_work(gas->wpa_s, freq, "gas-query", 0, gas_query_start_cb, query) < 0) { gas_query_free(query, 1); return -1; } return dialog_token; }
int gas_query_req(struct gas_query *gas, const u8 *dst, int freq, struct wpabuf *req, void (*cb)(void *ctx, const u8 *dst, u8 dialog_token, enum gas_query_result result, const struct wpabuf *adv_proto, const struct wpabuf *resp, u16 status_code), void *ctx) { struct gas_query_pending *query; int dialog_token; if (wpabuf_len(req) < 3) return -1; for (dialog_token = 0; dialog_token < 256; dialog_token++) { if (gas_query_dialog_token_available(gas, dst, dialog_token)) break; } if (dialog_token == 256) return -1; /* Too many pending queries */ query = os_zalloc(sizeof(*query)); if (query == NULL) return -1; os_memcpy(query->addr, dst, ETH_ALEN); query->dialog_token = dialog_token; query->freq = freq; query->cb = cb; query->ctx = ctx; dl_list_add(&gas->pending, &query->list); *(wpabuf_mhead_u8(req) + 2) = dialog_token; wpa_printf(MSG_DEBUG, "GAS: Starting request for " MACSTR " dialog_token %u", MAC2STR(dst), dialog_token); if (gas_query_tx(gas, query, req) < 0) { wpa_printf(MSG_DEBUG, "GAS: Failed to send Action frame to " MACSTR, MAC2STR(query->addr)); os_free(query); return -1; } eloop_register_timeout(GAS_QUERY_TIMEOUT, 0, gas_query_timeout, gas, query); return dialog_token; }
static int gas_query_new_dialog_token(struct gas_query *gas, const u8 *dst) { static int next_start = 0; int dialog_token; for (dialog_token = 0; dialog_token < 256; dialog_token++) { if (gas_query_dialog_token_available( gas, dst, (next_start + dialog_token) % 256)) break; } if (dialog_token == 256) return -1; /* Too many pending queries */ dialog_token = (next_start + dialog_token) % 256; next_start = (dialog_token + 1) % 256; return dialog_token; }