static int add_pmk_file(struct wlantest *wt, const char *pmk_file) { FILE *f; u8 pmk[32]; char buf[300], *pos; struct wlantest_pmk *p; f = fopen(pmk_file, "r"); if (f == NULL) { wpa_printf(MSG_ERROR, "Could not open '%s'", pmk_file); return -1; } while (fgets(buf, sizeof(buf), f)) { pos = buf; while (*pos && *pos != '\r' && *pos != '\n') pos++; *pos = '\0'; if (pos - buf < 2 * 32) continue; if (hexstr2bin(buf, pmk, 32) < 0) continue; p = os_zalloc(sizeof(*p)); if (p == NULL) break; os_memcpy(p->pmk, pmk, 32); dl_list_add(&wt->pmk, &p->list); wpa_hexdump(MSG_DEBUG, "Added PMK from file", pmk, 32); } fclose(f); return 0; }
int gas_server_register(struct gas_server *gas, const u8 *adv_proto_id, u8 adv_proto_id_len, struct wpabuf * (*req_cb)(void *ctx, const u8 *sa, const u8 *query, size_t query_len), void (*status_cb)(void *ctx, struct wpabuf *resp, int ok), void *ctx) { struct gas_server_handler *handler; if (!gas || adv_proto_id_len > MAX_ADV_PROTO_ID_LEN) return -1; handler = os_zalloc(sizeof(*handler)); if (!handler) return -1; os_memcpy(handler->adv_proto_id, adv_proto_id, adv_proto_id_len); handler->adv_proto_id_len = adv_proto_id_len; handler->req_cb = req_cb; handler->status_cb = status_cb; handler->ctx = ctx; handler->gas = gas; dl_list_add(&gas->handlers, &handler->list); return 0; }
/** * event_retry - Called when we had a failure delivering event msg * @e: Event * @do_next_address: skip address e.g. on connect fail */ static void event_retry(struct wps_event_ *e, int do_next_address) { struct subscription *s = e->s; struct upnp_wps_device_sm *sm = s->sm; wpa_printf(MSG_DEBUG, "WPS UPnP: Retry event %p for subscription %p", e, s); event_clean(e); /* will set: s->current_event = NULL; */ if (do_next_address) { e->retry++; wpa_printf(MSG_DEBUG, "WPS UPnP: Try address %d", e->retry); } if (e->retry >= dl_list_len(&s->addr_list)) { wpa_printf(MSG_DEBUG, "WPS UPnP: Giving up on sending event " "for %s", e->addr->domain_and_port); event_delete(e); s->last_event_failed = 1; if (!dl_list_empty(&s->event_queue)) event_send_all_later(s->sm); return; } dl_list_add(&s->event_queue, &e->list); event_send_all_later(sm); }
static int bgscan_learn_load(struct bgscan_learn_data *data) { FILE *f; char buf[128]; struct bgscan_learn_bss *bss; if (data->fname == NULL) { return 0; } f = fopen(data->fname, "r"); if (f == NULL) { return 0; } wpa_printf(MSG_DEBUG, "bgscan learn: Loading data from %s", data->fname); if (fgets(buf, sizeof(buf), f) == NULL || os_strncmp(buf, "wpa_supplicant-bgscan-learn\n", 28) != 0) { wpa_printf(MSG_INFO, "bgscan learn: Invalid data file %s", data->fname); fclose(f); return -1; } while (fgets(buf, sizeof(buf), f)) { if (os_strncmp(buf, "BSS ", 4) == 0) { bss = os_zalloc(sizeof(*bss)); if (!bss) { continue; } if (hwaddr_aton(buf + 4, bss->bssid) < 0) { bss_free(bss); continue; } bss->freq = atoi(buf + 4 + 18); dl_list_add(&data->bss, &bss->list); wpa_printf(MSG_DEBUG, "bgscan learn: Loaded BSS " "entry: " MACSTR " freq=%d", MAC2STR(bss->bssid), bss->freq); } if (os_strncmp(buf, "NEIGHBOR ", 9) == 0) { u8 addr[ETH_ALEN]; if (hwaddr_aton(buf + 9, addr) < 0) { continue; } bss = bgscan_learn_get_bss(data, addr); if (bss == NULL) { continue; } if (hwaddr_aton(buf + 9 + 18, addr) < 0) { continue; } bgscan_learn_add_neighbor(bss, addr); } } fclose(f); return 0; }
void wpa_trace_add_ref_func(struct wpa_trace_ref *ref, const void *addr) { if (addr == NULL) return; ref->addr = addr; wpa_trace_record(ref); dl_list_add(&active_references, &ref->list); }
int hs20_anqp_send_req(struct wpa_supplicant *wpa_s, const u8 *dst, u32 stypes, const u8 *payload, size_t payload_len, int inmem) { struct wpabuf *buf; int ret = 0; int freq; struct wpa_bss *bss; int res; struct icon_entry *icon_entry; bss = wpa_bss_get_bssid(wpa_s, dst); if (!bss) { wpa_printf(MSG_WARNING, "ANQP: Cannot send query to unknown BSS " MACSTR, MAC2STR(dst)); return -1; } wpa_bss_anqp_unshare_alloc(bss); freq = bss->freq; wpa_printf(MSG_DEBUG, "HS20: ANQP Query Request to " MACSTR " for " "subtypes 0x%x", MAC2STR(dst), stypes); buf = hs20_build_anqp_req(stypes, payload, payload_len); if (buf == NULL) return -1; res = gas_query_req(wpa_s->gas, dst, freq, buf, anqp_resp_cb, wpa_s); if (res < 0) { wpa_printf(MSG_DEBUG, "ANQP: Failed to send Query Request"); wpabuf_free(buf); return -1; } else wpa_printf(MSG_DEBUG, "ANQP: Query started with dialog token " "%u", res); if (inmem) { icon_entry = os_zalloc(sizeof(struct icon_entry)); if (!icon_entry) return -1; os_memcpy(icon_entry->bssid, dst, ETH_ALEN); icon_entry->file_name = os_malloc(payload_len + 1); if (!icon_entry->file_name) { os_free(icon_entry); return -1; } os_memcpy(icon_entry->file_name, payload, payload_len); icon_entry->file_name[payload_len] = '\0'; icon_entry->dialog_token = res; dl_list_add(&wpa_s->icon_head, &icon_entry->list); } return ret; }
void * os_malloc(size_t size) { struct os_alloc_trace *a; a = malloc(sizeof(*a) + size); if (a == NULL) return NULL; a->magic = ALLOC_MAGIC; dl_list_add(&alloc_list, &a->list); a->len = size; wpa_trace_record(a); return a + 1; }
/** * 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; }
static void add_secret(struct wlantest *wt, const char *secret) { struct wlantest_radius_secret *s; size_t len = os_strlen(secret); if (len >= MAX_RADIUS_SECRET_LEN) return; s = os_zalloc(sizeof(*s)); if (s == NULL) return; os_memcpy(s->secret, secret, len); dl_list_add(&wt->secret, &s->list); }
static void add_passphrase(struct wlantest *wt, const char *passphrase) { struct wlantest_passphrase *p; size_t len = os_strlen(passphrase); if (len < 8 || len > 63) return; p = os_zalloc(sizeof(*p)); if (p == NULL) return; os_memcpy(p->passphrase, passphrase, len); dl_list_add(&wt->passphrase, &p->list); }
static struct hostapd_neighbor_entry * hostapd_neighbor_add(struct hostapd_data *hapd) { struct hostapd_neighbor_entry *nr; nr = os_zalloc(sizeof(struct hostapd_neighbor_entry)); if (!nr) return NULL; dl_list_add(&hapd->nr_db, &nr->list); return nr; }
static int add_ptk_file(struct wlantest *wt, const char *ptk_file) { FILE *f; u8 ptk[64]; size_t ptk_len; char buf[300], *pos; struct wlantest_ptk *p; f = fopen(ptk_file, "r"); if (f == NULL) { wpa_printf(MSG_ERROR, "Could not open '%s'", ptk_file); return -1; } while (fgets(buf, sizeof(buf), f)) { pos = buf; while (*pos && *pos != '\r' && *pos != '\n') pos++; *pos = '\0'; ptk_len = pos - buf; if (ptk_len & 1) continue; ptk_len /= 2; if (ptk_len != 16 && ptk_len != 32 && ptk_len != 48 && ptk_len != 64) continue; if (hexstr2bin(buf, ptk, ptk_len) < 0) continue; p = os_zalloc(sizeof(*p)); if (p == NULL) break; if (ptk_len < 48) { os_memcpy(p->ptk.tk, ptk, ptk_len); p->ptk.tk_len = ptk_len; p->ptk_len = 32 + ptk_len; } else { os_memcpy(p->ptk.kck, ptk, 16); p->ptk.kck_len = 16; os_memcpy(p->ptk.kek, ptk + 16, 16); p->ptk.kek_len = 16; os_memcpy(p->ptk.tk, ptk + 32, ptk_len - 32); p->ptk.tk_len = ptk_len - 32; p->ptk_len = ptk_len; } dl_list_add(&wt->ptk, &p->list); wpa_hexdump(MSG_DEBUG, "Added PTK from file", ptk, ptk_len); } fclose(f); return 0; }
static struct wlantest_tdls * get_tdls(struct wlantest *wt, const u8 *linkid, int create_new, const u8 *bssid) { struct wlantest_bss *bss; struct wlantest_sta *init, *resp; struct wlantest_tdls *tdls; bss = bss_find(wt, linkid); if (bss == NULL && bssid) { bss = bss_find(wt, bssid); if (bss) add_note(wt, MSG_INFO, "TDLS: Incorrect BSSID " MACSTR " in LinkId?! (init=" MACSTR " resp=" MACSTR ")", MAC2STR(linkid), MAC2STR(linkid + ETH_ALEN), MAC2STR(linkid + 2 * ETH_ALEN)); } if (bss == NULL) return NULL; init = sta_find(bss, linkid + ETH_ALEN); if (init == NULL) return NULL; resp = sta_find(bss, linkid + 2 * ETH_ALEN); if (resp == NULL) return NULL; dl_list_for_each(tdls, &bss->tdls, struct wlantest_tdls, list) { if (tdls->init == init && tdls->resp == resp) return tdls; } if (!create_new) return NULL; add_note(wt, MSG_DEBUG, "Add new TDLS link context: initiator " MACSTR " responder " MACSTR " BSSID " MACSTR, MAC2STR(linkid + ETH_ALEN), MAC2STR(linkid + 2 * ETH_ALEN), MAC2STR(bssid)); tdls = os_zalloc(sizeof(*tdls)); if (tdls == NULL) return NULL; tdls->init = init; tdls->resp = resp; dl_list_add(&bss->tdls, &tdls->list); return tdls; }
int eloop_register_timeout(unsigned int secs, unsigned int usecs, eloop_timeout_handler handler, void *eloop_data, void *user_data) { struct eloop_timeout *timeout, *tmp; os_time_t now_sec; timeout = os_zalloc(sizeof(*timeout)); if (timeout == NULL) return -1; if (os_get_reltime(&timeout->time) < 0) { os_free(timeout); return -1; } now_sec = timeout->time.sec; timeout->time.sec += secs; if (timeout->time.sec < now_sec) { /* * Integer overflow - assume long enough timeout to be assumed * to be infinite, i.e., the timeout would never happen. */ wpa_printf(MSG_DEBUG, "ELOOP: Too long timeout (secs=%u) to " "ever happen - ignore it", secs); os_free(timeout); return 0; } timeout->time.usec += usecs; while (timeout->time.usec >= 1000000) { timeout->time.sec++; timeout->time.usec -= 1000000; } timeout->eloop_data = eloop_data; timeout->user_data = user_data; timeout->handler = handler; wpa_trace_add_ref(timeout, eloop, eloop_data); wpa_trace_add_ref(timeout, user, user_data); wpa_trace_record(timeout); /* Maintain timeouts in order of increasing time */ dl_list_for_each(tmp, &eloop.timeout, struct eloop_timeout, list) { if (os_reltime_before(&timeout->time, &tmp->time)) { dl_list_add(tmp->list.prev, &timeout->list); return 0; } } dl_list_add_tail(&eloop.timeout, &timeout->list); return 0; }
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; }
/** * 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; if (wpabuf_len(req) < 3) return -1; dialog_token = gas_query_new_dialog_token(gas, dst); if (dialog_token < 0) return -1; 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) { query->req = NULL; /* caller will free this in error case */ gas_query_free(query, 1); return -1; } return dialog_token; }
int cli_txt_list_add(struct dl_list *txt_list, const char *txt) { struct cli_txt_entry *e; e = cli_txt_list_get(txt_list, txt); if (e) return 0; e = os_zalloc(sizeof(*e)); if (e == NULL) return -1; e->txt = os_strdup(txt); if (e->txt == NULL) { os_free(e); return -1; } dl_list_add(txt_list, &e->list); return 0; }
static void wps_er_ap_remove_entry(struct wps_er *er, struct wps_er_ap *ap) { wpa_printf(MSG_DEBUG, "WPS ER: Removing AP entry for %s (%s)", inet_ntoa(ap->addr), ap->location); eloop_cancel_timeout(wps_er_ap_timeout, er, ap); wps_er_sta_remove_all(ap); wps_er_ap_event(er->wps, ap, WPS_EV_ER_AP_REMOVE); http_client_free(ap->http); ap->http = NULL; if (ap->wps) { wps_deinit(ap->wps); ap->wps = NULL; } dl_list_del(&ap->list); if (ap->subscribed) { dl_list_add(&er->ap_unsubscribing, &ap->list); wps_er_ap_unsubscribe(er, ap); } else wps_er_ap_free(ap); }
int add_wep(struct wlantest *wt, const char *key) { struct wlantest_wep *w; size_t len = os_strlen(key); if (len != 2 * 5 && len != 2 * 13) { wpa_printf(MSG_INFO, "Invalid WEP key '%s'", key); return -1; } w = os_zalloc(sizeof(*w)); if (w == NULL) return -1; if (hexstr2bin(key, w->key, len / 2) < 0) { os_free(w); wpa_printf(MSG_INFO, "Invalid WEP key '%s'", key); return -1; } w->key_len = len / 2; dl_list_add(&wt->wep, &w->list); return 0; }
int bss_add_pmk_from_passphrase(struct wlantest_bss *bss, const char *passphrase) { struct wlantest_pmk *pmk; pmk = os_zalloc(sizeof(*pmk)); if (pmk == NULL) return -1; if (pbkdf2_sha1(passphrase, bss->ssid, bss->ssid_len, 4096, pmk->pmk, sizeof(pmk->pmk)) < 0) { os_free(pmk); return -1; } wpa_printf(MSG_INFO, "Add possible PMK for BSSID " MACSTR " based on passphrase '%s'", MAC2STR(bss->bssid), passphrase); wpa_hexdump(MSG_DEBUG, "Possible PMK", pmk->pmk, sizeof(pmk->pmk)); dl_list_add(&bss->pmk, &pmk->list); return 0; }
int wps_er_ap_cache_settings(struct wps_er *er, struct in_addr *addr) { struct wps_er_ap *ap; struct wps_er_ap_settings *settings; ap = wps_er_ap_get(er, addr, NULL); if (ap == NULL || ap->ap_settings == NULL) return -1; settings = wps_er_ap_get_settings(er, ap->uuid); if (!settings) { settings = os_zalloc(sizeof(*settings)); if (settings == NULL) return -1; os_memcpy(settings->uuid, ap->uuid, WPS_UUID_LEN); dl_list_add(&er->ap_settings, &settings->list); } os_memcpy(&settings->ap_settings, ap->ap_settings, sizeof(struct wps_credential)); return 0; }
int eloop_register_timeout(unsigned int secs, unsigned int usecs, eloop_timeout_handler handler, void *eloop_data, void *user_data) { struct eloop_timeout *timeout, *tmp; os_time_t now_sec; timeout = os_zalloc(sizeof(*timeout)); if (timeout == NULL) return -1; if (os_get_reltime(&timeout->time) < 0) { os_free(timeout); return -1; } now_sec = timeout->time.sec; timeout->time.sec += secs; if (timeout->time.sec < now_sec) { fprintf(stderr, "ELOOP: Too long timeout (secs=%u) to " "ever happen - ignore it", secs); os_free(timeout); return 0; } timeout->time.usec += usecs; while (timeout->time.usec >= 1000000) { timeout->time.sec++; timeout->time.usec -= 1000000; } timeout->eloop_data = eloop_data; timeout->user_data = user_data; timeout->handler = handler; dl_list_for_each(tmp, &eloop.timeout, struct eloop_timeout, list) { if (os_reltime_before(&timeout->time, &tmp->time)) { dl_list_add(tmp->list.prev, &timeout->list); return 0; } } dl_list_add_tail(&eloop.timeout, &timeout->list); return 0; }
struct wlantest_sta * sta_get(struct wlantest_bss *bss, const u8 *addr) { struct wlantest_sta *sta; if (addr[0] & 0x01) return NULL; /* Skip group addressed frames */ sta = sta_find(bss, addr); if (sta) return sta; sta = os_zalloc(sizeof(*sta)); if (sta == NULL) return NULL; os_memset(sta->seq_ctrl_to_sta, 0xff, sizeof(sta->seq_ctrl_to_sta)); os_memset(sta->seq_ctrl_to_ap, 0xff, sizeof(sta->seq_ctrl_to_ap)); sta->bss = bss; os_memcpy(sta->addr, addr, ETH_ALEN); dl_list_add(&bss->sta, &sta->list); wpa_printf(MSG_DEBUG, "Discovered new STA " MACSTR " in BSS " MACSTR, MAC2STR(sta->addr), MAC2STR(bss->bssid)); return sta; }
struct wlantest_bss * bss_get(struct wlantest *wt, const u8 *bssid) { struct wlantest_bss *bss; if (bssid[0] & 0x01) return NULL; /* Skip group addressed frames */ bss = bss_find(wt, bssid); if (bss) return bss; bss = os_zalloc(sizeof(*bss)); if (bss == NULL) return NULL; dl_list_init(&bss->sta); dl_list_init(&bss->pmk); dl_list_init(&bss->tdls); os_memcpy(bss->bssid, bssid, ETH_ALEN); dl_list_add(&wt->bss, &bss->list); wpa_printf(MSG_DEBUG, "Discovered new BSS - " MACSTR, MAC2STR(bss->bssid)); return bss; }
vl_list *vl_list_add(vl_list *list, char *str, int attributes, void *user_ptr) { vl_entry *ent; if( list == NULL ){ list = malloc(sizeof(vl_list)); list->entries = NULL; list->selected_entry = NULL; list->first_visible_entry = NULL; list->last_visible_entry = NULL; list->n_entries = 0; } ent = malloc(sizeof(vl_entry)); ent->str = str; ent->attributes = attributes; ent->user_ptr = user_ptr; list->n_entries ++; list->entries = dl_list_add(list->entries, ent); return list; }
void wps_er_ap_add(struct wps_er *er, const u8 *uuid, struct in_addr *addr, const char *location, int max_age) { struct wps_er_ap *ap; ap = wps_er_ap_get(er, addr, uuid); if (ap) { /* Update advertisement timeout */ eloop_cancel_timeout(wps_er_ap_timeout, er, ap); eloop_register_timeout(max_age, 0, wps_er_ap_timeout, er, ap); return; } ap = os_zalloc(sizeof(*ap)); if (ap == NULL) return; dl_list_init(&ap->sta); ap->er = er; ap->id = ++er->next_ap_id; ap->location = os_strdup(location); if (ap->location == NULL) { os_free(ap); return; } dl_list_add(&er->ap, &ap->list); ap->addr.s_addr = addr->s_addr; os_memcpy(ap->uuid, uuid, WPS_UUID_LEN); eloop_register_timeout(max_age, 0, wps_er_ap_timeout, er, ap); wpa_printf(MSG_DEBUG, "WPS ER: Added AP entry for %s (%s)", inet_ntoa(ap->addr), ap->location); /* Fetch device description */ ap->http = http_client_url(ap->location, NULL, 10000, wps_er_http_dev_desc_cb, ap); }
int eloop_register_timeout(unsigned int secs, unsigned int usecs, eloop_timeout_handler handler, void *eloop_data, void *user_data) { struct eloop_timeout *timeout, *tmp; timeout = os_zalloc(sizeof(*timeout)); if (timeout == NULL) return -1; if (os_get_time(&timeout->time) < 0) { os_free(timeout); return -1; } timeout->time.sec += secs; timeout->time.usec += usecs; while (timeout->time.usec >= 1000000) { timeout->time.sec++; timeout->time.usec -= 1000000; } timeout->eloop_data = eloop_data; timeout->user_data = user_data; timeout->handler = handler; wpa_trace_add_ref(timeout, eloop, eloop_data); wpa_trace_add_ref(timeout, user, user_data); wpa_trace_record(timeout); /* Maintain timeouts in order of increasing time */ dl_list_for_each(tmp, &eloop.timeout, struct eloop_timeout, list) { if (os_time_before(&timeout->time, &tmp->time)) { dl_list_add(tmp->list.prev, &timeout->list); return 0; } } dl_list_add_tail(&eloop.timeout, &timeout->list); return 0; }
static void gas_server_send_resp(struct gas_server *gas, struct gas_server_handler *handler, const u8 *da, int freq, u8 dialog_token, struct wpabuf *query_resp) { size_t max_len = (freq > 56160) ? 928 : 1400; size_t hdr_len = 24 + 2 + 5 + 3 + handler->adv_proto_id_len + 2; size_t resp_frag_len; struct wpabuf *resp; u16 comeback_delay; struct gas_server_response *response; if (!query_resp) return; response = os_zalloc(sizeof(*response)); if (!response) return; wpa_printf(MSG_DEBUG, "DPP: Allocated GAS response @%p", response); response->freq = freq; response->handler = handler; os_memcpy(response->dst, da, ETH_ALEN); response->dialog_token = dialog_token; if (hdr_len + wpabuf_len(query_resp) > max_len) { /* Need to use comeback to initiate fragmentation */ comeback_delay = 1; resp_frag_len = 0; } else { /* Full response fits into the initial response */ comeback_delay = 0; resp_frag_len = wpabuf_len(query_resp); } resp = gas_build_initial_resp(dialog_token, WLAN_STATUS_SUCCESS, comeback_delay, handler->adv_proto_id_len + resp_frag_len); if (!resp) { gas_server_free_response(response); return; } /* Advertisement Protocol element */ wpabuf_put_u8(resp, WLAN_EID_ADV_PROTO); wpabuf_put_u8(resp, 1 + handler->adv_proto_id_len); /* Length */ wpabuf_put_u8(resp, 0x7f); /* Advertisement Protocol ID */ wpabuf_put_data(resp, handler->adv_proto_id, handler->adv_proto_id_len); /* Query Response Length */ wpabuf_put_le16(resp, resp_frag_len); if (!comeback_delay) wpabuf_put_buf(resp, query_resp); if (comeback_delay) { wpa_printf(MSG_DEBUG, "GAS: Need to fragment query response"); } else { wpa_printf(MSG_DEBUG, "GAS: Full query response fits in the GAS Initial Response frame"); } response->offset = resp_frag_len; response->resp = query_resp; dl_list_add(&gas->responses, &response->list); gas->tx(gas->ctx, freq, da, resp, comeback_delay ? 2000 : 0); wpabuf_free(resp); eloop_register_timeout(GAS_QUERY_TIMEOUT, 0, gas_server_response_timeout, response, NULL); }
static struct wps_er_sta * wps_er_add_sta_data(struct wps_er_ap *ap, const u8 *addr, struct wps_parse_attr *attr, int probe_req) { struct wps_er_sta *sta = wps_er_sta_get(ap, addr, NULL); int new_sta = 0; int m1; m1 = !probe_req && attr->msg_type && *attr->msg_type == WPS_M1; if (sta == NULL) { /* * Only allow new STA entry to be added based on Probe Request * or M1. This will filter out bogus events and anything that * may have been ongoing at the time ER subscribed for events. */ if (!probe_req && !m1) return NULL; sta = os_zalloc(sizeof(*sta)); if (sta == NULL) return NULL; os_memcpy(sta->addr, addr, ETH_ALEN); sta->ap = ap; dl_list_add(&ap->sta, &sta->list); new_sta = 1; } if (m1) sta->m1_received = 1; if (attr->config_methods && (!probe_req || !sta->m1_received)) sta->config_methods = WPA_GET_BE16(attr->config_methods); if (attr->uuid_e && (!probe_req || !sta->m1_received)) os_memcpy(sta->uuid, attr->uuid_e, WPS_UUID_LEN); if (attr->primary_dev_type && (!probe_req || !sta->m1_received)) os_memcpy(sta->pri_dev_type, attr->primary_dev_type, 8); if (attr->dev_password_id && (!probe_req || !sta->m1_received)) sta->dev_passwd_id = WPA_GET_BE16(attr->dev_password_id); if (attr->manufacturer) { os_free(sta->manufacturer); sta->manufacturer = os_malloc(attr->manufacturer_len + 1); if (sta->manufacturer) { os_memcpy(sta->manufacturer, attr->manufacturer, attr->manufacturer_len); sta->manufacturer[attr->manufacturer_len] = '\0'; } } if (attr->model_name) { os_free(sta->model_name); sta->model_name = os_malloc(attr->model_name_len + 1); if (sta->model_name) { os_memcpy(sta->model_name, attr->model_name, attr->model_name_len); sta->model_name[attr->model_name_len] = '\0'; } } if (attr->model_number) { os_free(sta->model_number); sta->model_number = os_malloc(attr->model_number_len + 1); if (sta->model_number) { os_memcpy(sta->model_number, attr->model_number, attr->model_number_len); sta->model_number[attr->model_number_len] = '\0'; } } if (attr->serial_number) { os_free(sta->serial_number); sta->serial_number = os_malloc(attr->serial_number_len + 1); if (sta->serial_number) { os_memcpy(sta->serial_number, attr->serial_number, attr->serial_number_len); sta->serial_number[attr->serial_number_len] = '\0'; } } if (attr->dev_name) { os_free(sta->dev_name); sta->dev_name = os_malloc(attr->dev_name_len + 1); if (sta->dev_name) { os_memcpy(sta->dev_name, attr->dev_name, attr->dev_name_len); sta->dev_name[attr->dev_name_len] = '\0'; } } eloop_cancel_timeout(wps_er_sta_timeout, sta, NULL); eloop_register_timeout(300, 0, wps_er_sta_timeout, sta, NULL); if (m1 || new_sta) wps_er_sta_event(ap->er->wps, sta, WPS_EV_ER_ENROLLEE_ADD); return sta; }
/* subscr_addr_add_url -- add address(es) for one url to subscription */ static void subscr_addr_add_url(struct subscription *s, const char *url, size_t url_len) { int alloc_len; char *scratch_mem = NULL; char *mem; char *domain_and_port; char *delim; char *path; char *domain; int port = 80; /* port to send to (default is port 80) */ struct addrinfo hints; struct addrinfo *result = NULL; struct addrinfo *rp; int rerr; /* url MUST begin with http: */ if (url_len < 7 || os_strncasecmp(url, "http://", 7)) goto fail; url += 7; url_len -= 7; /* allocate memory for the extra stuff we need */ alloc_len = 2 * (url_len + 1); scratch_mem = os_zalloc(alloc_len); if (scratch_mem == NULL) goto fail; mem = scratch_mem; os_strncpy(mem, url, url_len); wpa_printf(MSG_DEBUG, "WPS UPnP: Adding URL '%s'", mem); domain_and_port = mem; mem += 1 + os_strlen(mem); delim = os_strchr(domain_and_port, '/'); if (delim) { *delim++ = 0; /* null terminate domain and port */ path = delim; } else { path = domain_and_port + os_strlen(domain_and_port); } domain = mem; strcpy(domain, domain_and_port); delim = os_strchr(domain, ':'); if (delim) { *delim++ = 0; /* null terminate domain */ if (isdigit(*delim)) port = atol(delim); } /* * getaddrinfo does the right thing with dotted decimal notations, or * will resolve domain names. Resolving domain names will unfortunately * hang the entire program until it is resolved or it times out * internal to getaddrinfo; fortunately we think that the use of actual * domain names (vs. dotted decimal notations) should be uncommon. */ os_memset(&hints, 0, sizeof(struct addrinfo)); hints.ai_family = AF_INET; /* IPv4 */ hints.ai_socktype = SOCK_STREAM; #if NO_DOMAIN_NAME_RESOLUTION /* Suppress domain name resolutions that would halt * the program for periods of time */ hints.ai_flags = AI_NUMERICHOST; #else /* Allow domain name resolution. */ hints.ai_flags = 0; #endif hints.ai_protocol = 0; /* Any protocol? */ rerr = getaddrinfo(domain, NULL /* fill in port ourselves */, &hints, &result); if (rerr) { wpa_printf(MSG_INFO, "WPS UPnP: Resolve error %d (%s) on: %s", rerr, gai_strerror(rerr), domain); goto fail; } for (rp = result; rp; rp = rp->ai_next) { struct subscr_addr *a; /* Limit no. of address to avoid denial of service attack */ if (dl_list_len(&s->addr_list) >= MAX_ADDR_PER_SUBSCRIPTION) { wpa_printf(MSG_INFO, "WPS UPnP: subscr_addr_add_url: " "Ignoring excessive addresses"); break; } a = os_zalloc(sizeof(*a) + alloc_len); if (a == NULL) continue; mem = (void *) (a + 1); a->domain_and_port = mem; strcpy(mem, domain_and_port); mem += 1 + strlen(mem); a->path = mem; if (path[0] != '/') *mem++ = '/'; strcpy(mem, path); mem += 1 + os_strlen(mem); os_memcpy(&a->saddr, rp->ai_addr, sizeof(a->saddr)); a->saddr.sin_port = htons(port); dl_list_add(&s->addr_list, &a->list); } fail: if (result) freeaddrinfo(result); os_free(scratch_mem); }