/** * 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 void acs_survey_chan_interference_factor(struct hostapd_iface *iface, struct hostapd_channel_data *chan) { struct freq_survey *survey; unsigned int i = 0; long double int_factor = 0; if (dl_list_empty(&chan->survey_list)) return; if (chan->flag & HOSTAPD_CHAN_DISABLED) return; chan->interference_factor = 0; dl_list_for_each(survey, &chan->survey_list, struct freq_survey, list) { int_factor = acs_survey_interference_factor(survey, iface->lowest_nf); chan->interference_factor += int_factor; wpa_printf(MSG_DEBUG, "ACS: %d: min_nf=%d interference_factor=%Lg nf=%d time=%lu busy=%lu rx=%lu", ++i, chan->min_nf, int_factor, survey->nf, (unsigned long) survey->channel_time, (unsigned long) survey->channel_time_busy, (unsigned long) survey->channel_time_rx); } chan->interference_factor = chan->interference_factor / dl_list_len(&chan->survey_list); }
/** * event_add - Add a new event to a queue * @s: Subscription * @data: Event data (is copied; caller retains ownership) * @probereq: Whether this is a Probe Request event * Returns: 0 on success, -1 on error, 1 on max event queue limit reached */ int event_add(struct subscription *s, const struct wpabuf *data, int probereq) { struct wps_event_ *e; unsigned int len; len = dl_list_len(&s->event_queue); if (len >= MAX_EVENTS_QUEUED) { wpa_printf(MSG_DEBUG, "WPS UPnP: Too many events queued for " "subscriber %p", s); if (probereq) return 1; /* Drop oldest entry to allow EAP event to be stored. */ e = event_dequeue(s); if (!e) return 1; event_delete(e); } if (s->last_event_failed && probereq && len > 0) { /* * Avoid queuing frames for subscribers that may have left * without unsubscribing. */ wpa_printf(MSG_DEBUG, "WPS UPnP: Do not queue more Probe " "Request frames for subscription %p since last " "delivery failed", s); return -1; } e = os_zalloc(sizeof(*e)); if (e == NULL) return -1; dl_list_init(&e->list); e->s = s; e->data = wpabuf_dup(data); if (e->data == NULL) { os_free(e); return -1; } e->subscriber_sequence = s->next_subscriber_sequence++; if (s->next_subscriber_sequence == 0) s->next_subscriber_sequence++; wpa_printf(MSG_DEBUG, "WPS UPnP: Queue event %p for subscriber %p " "(queue len %u)", e, s, len + 1); dl_list_add_tail(&s->event_queue, &e->list); event_send_all_later(s->sm); return 0; }
static struct tls_netconn *net_alloc_socket(struct tls_netconn *conn) { int sock=-1, i=0, j=0; u32 cpu_sr; struct tls_netconn * conn_t = NULL; for (i = 0; i < TLS_MAX_NETCONN_NUM; i++) { if(p_net_conn[i] == NULL) { sock = i; break; } } if (i == TLS_MAX_NETCONN_NUM){ return NULL; } if(conn != NULL) { j = dl_list_len(&conn->list); if(j>=4) { sock = -1; } } if(sock < 0) return NULL; cpu_sr = tls_os_set_critical(); conn_t = tls_mem_alloc(sizeof(struct tls_netconn)); tls_os_release_critical(cpu_sr); if (NULL != conn_t) { p_net_conn[sock] = conn_t; memset(conn_t, 0, sizeof(struct tls_netconn)); conn_t->used = true; conn_t->state = NETCONN_STATE_NONE; conn_t->skt_num = sock + 1;//TLS_MAX_NETCONN_NUM + dl_list_init(&conn_t->list); if (sys_sem_new(&conn_t->op_completed, 0) != ERR_OK) { net_free_socket(conn_t); } } TLS_DBGPRT_INFO("net_alloc_socket conn ptr = 0x%x\n", conn_t); return conn_t; // return NULL; }
/** * subscription_start - Remember a UPnP control point to send events to. * @sm: WPS UPnP state machine from upnp_wps_device_init() * @callback_urls: Callback URLs * Returns: %NULL on error, or pointer to new subscription structure. */ struct subscription * subscription_start(struct upnp_wps_device_sm *sm, const char *callback_urls) { struct subscription *s; time_t now = time(NULL); time_t expire = now + UPNP_SUBSCRIBE_SEC; /* Get rid of expired subscriptions so we have room */ subscription_list_age(sm, now); /* If too many subscriptions, remove oldest */ if (dl_list_len(&sm->subscriptions) >= MAX_SUBSCRIPTIONS) { s = dl_list_first(&sm->subscriptions, struct subscription, list); wpa_printf(MSG_INFO, "WPS UPnP: Too many subscriptions, " "trashing oldest"); dl_list_del(&s->list); subscription_destroy(s); }
static enum http_reply_code web_process_get_device_info(struct upnp_wps_device_sm *sm, struct wpabuf **reply, const char **replyname) { static const char *name = "NewDeviceInfo"; struct wps_config cfg; struct upnp_wps_device_interface *iface; struct upnp_wps_peer *peer; iface = dl_list_first(&sm->interfaces, struct upnp_wps_device_interface, list); wpa_printf(MSG_DEBUG, "WPS UPnP: GetDeviceInfo"); if (!iface || iface->ctx->ap_pin == NULL) return HTTP_INTERNAL_SERVER_ERROR; peer = os_zalloc(sizeof(*peer)); if (!peer) return HTTP_INTERNAL_SERVER_ERROR; /* * Request for DeviceInfo, i.e., M1 TLVs. This is a start of WPS * registration over UPnP with the AP acting as an Enrollee. It should * be noted that this is frequently used just to get the device data, * i.e., there may not be any intent to actually complete the * registration. */ os_memset(&cfg, 0, sizeof(cfg)); cfg.wps = iface->wps; cfg.pin = (u8 *) iface->ctx->ap_pin; cfg.pin_len = os_strlen(iface->ctx->ap_pin); peer->wps = wps_init(&cfg); if (peer->wps) { enum wsc_op_code op_code; *reply = wps_get_msg(peer->wps, &op_code); if (*reply == NULL) { wps_deinit(peer->wps); peer->wps = NULL; } } else *reply = NULL; if (*reply == NULL) { wpa_printf(MSG_INFO, "WPS UPnP: Failed to get DeviceInfo"); os_free(peer); return HTTP_INTERNAL_SERVER_ERROR; } if (dl_list_len(&iface->peers) > 3) { struct upnp_wps_peer *old; old = dl_list_first(&iface->peers, struct upnp_wps_peer, list); if (old) { wpa_printf(MSG_DEBUG, "WPS UPnP: Drop oldest active session"); wps_upnp_peer_del(old); } } dl_list_add_tail(&iface->peers, &peer->list); /* TODO: Could schedule a timeout to free the entry */ *replyname = name; return HTTP_OK; }
/** * @brief WPS worker thread * * @param arg * * @return */ void *wps_pbc_work(void *arg) { struct wbr_context *wctx ; struct wbr_wpa_pbc *pvap ; int pid ; char *cmdargs[] = { "/sbin/wpatalk" , NULL , "configthem" , NULL } ; wbr_printf(MSG_DEBUG,"%s: Starting WPS worker ...\n",__func__); wctx = (struct wbr_context *) arg; /* Wait on condition */ pthread_mutex_lock(&wctx->wps_pbc_mutex) ; pthread_cond_wait(&wctx->wps_pbc_cond ,&wctx->wps_pbc_mutex); pthread_mutex_unlock(&wctx->wps_pbc_mutex) ; while(1) { pvap = NULL ; pthread_mutex_lock(&wctx->wps_pbc_mutex) ; if(dl_list_len( &wctx->wps_pbc_head )) { pvap = dl_list_entry(wctx->wps_pbc_head.next, struct wbr_wpa_pbc, list) ; dl_list_del(&pvap->list) ; pthread_mutex_unlock(&wctx->wps_pbc_mutex) ; cmdargs[1] = pvap->name ; pid = 0 ; pid = fork(); if(pid == 0) { /* Child process. * Execute '/sbin/wpatalk <vap> configthem'. */ wbr_printf(MSG_DEBUG,"%s: Execute wpatalk for %s\n", __func__,pvap->name); execve("/sbin/wpatalk" , cmdargs , NULL) ; } else { int stat ; int sleepcount ; int sleepdur ; /* sleep duration in sec */ /* wait on child process */ sleepdur = 5 ; sleepcount = (130) / sleepdur; while(sleepcount) { sleep(sleepdur); stat = waitpid(pid, &stat, WNOHANG); if ( stat == pid ) break ; sleepcount--; } if(sleepcount == 0) { /* Child did not terminate during wait period. * Send signal to terminate child. */ kill(pid , SIGTERM) ; waitpid(pid, &stat, WUNTRACED); } free(pvap) ; } } // end if(dl_list_len( &wctx->wps_pbc_head )) else {
/* 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); }
u8 * hostapd_eid_fils_indic(struct hostapd_data *hapd, u8 *eid, int hessid) { u8 *pos = eid; #ifdef CONFIG_FILS u8 *len; u16 fils_info = 0; size_t realms; struct fils_realm *realm; if (!(hapd->conf->wpa & WPA_PROTO_RSN) || !wpa_key_mgmt_fils(hapd->conf->wpa_key_mgmt)) return pos; realms = dl_list_len(&hapd->conf->fils_realms); if (realms > 7) realms = 7; /* 3 bit count field limits this to max 7 */ *pos++ = WLAN_EID_FILS_INDICATION; len = pos++; /* TODO: B0..B2: Number of Public Key Identifiers */ if (hapd->conf->erp_domain) { /* B3..B5: Number of Realm Identifiers */ fils_info |= realms << 3; } /* TODO: B6: FILS IP Address Configuration */ if (hapd->conf->fils_cache_id_set) fils_info |= BIT(7); if (hessid && !is_zero_ether_addr(hapd->conf->hessid)) fils_info |= BIT(8); /* HESSID Included */ /* FILS Shared Key Authentication without PFS Supported */ fils_info |= BIT(9); if (hapd->conf->fils_dh_group) { /* FILS Shared Key Authentication with PFS Supported */ fils_info |= BIT(10); } /* TODO: B11: FILS Public Key Authentication Supported */ /* B12..B15: Reserved */ WPA_PUT_LE16(pos, fils_info); pos += 2; if (hapd->conf->fils_cache_id_set) { os_memcpy(pos, hapd->conf->fils_cache_id, FILS_CACHE_ID_LEN); pos += FILS_CACHE_ID_LEN; } if (hessid && !is_zero_ether_addr(hapd->conf->hessid)) { os_memcpy(pos, hapd->conf->hessid, ETH_ALEN); pos += ETH_ALEN; } dl_list_for_each(realm, &hapd->conf->fils_realms, struct fils_realm, list) { if (realms == 0) break; realms--; os_memcpy(pos, realm->hash, 2); pos += 2; } *len = pos - len - 1; #endif /* CONFIG_FILS */ return pos; }
/* 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 *host; char *delim; char *path; int port = 80; /* port to send to (default is port 80) */ struct addrinfo hints; struct addrinfo *result = NULL; struct addrinfo *rp; int rerr; size_t host_len, path_len; /* url MUST begin with http: */ if (url_len < 7 || os_strncasecmp(url, "http://", 7)) goto fail; url += 7; url_len -= 7; /* Make a copy of the string to allow modification during parsing */ scratch_mem = dup_binstr(url, url_len); if (scratch_mem == NULL) goto fail; wpa_printf(MSG_DEBUG, "WPS UPnP: Adding URL '%s'", scratch_mem); host = scratch_mem; path = os_strchr(host, '/'); if (path) *path++ = '\0'; /* null terminate host */ /* Process and remove optional port component */ delim = os_strchr(host, ':'); if (delim) { *delim = '\0'; /* null terminate host name for now */ if (isdigit(delim[1])) port = atol(delim + 1); } /* * 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(host, 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), host); goto fail; } if (delim) *delim = ':'; /* Restore port */ host_len = os_strlen(host); path_len = path ? os_strlen(path) : 0; alloc_len = host_len + 1 + 1 + path_len + 1; 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) break; mem = (char *) (a + 1); a->domain_and_port = mem; os_memcpy(mem, host, host_len); mem += host_len + 1; a->path = mem; if (path == NULL || path[0] != '/') *mem++ = '/'; if (path) os_memcpy(mem, path, path_len); 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); }