1/* 2 * hostapd / Station table 3 * Copyright (c) 2002-2013, Jouni Malinen <j@w1.fi> 4 * 5 * This software may be distributed under the terms of the BSD license. 6 * See README for more details. 7 */ 8 9#include "utils/includes.h" 10 11#include "utils/common.h" 12#include "utils/eloop.h" 13#include "common/ieee802_11_defs.h" 14#include "common/wpa_ctrl.h" 15#include "common/sae.h" 16#include "radius/radius.h" 17#include "radius/radius_client.h" 18#include "p2p/p2p.h" 19#include "hostapd.h" 20#include "accounting.h" 21#include "ieee802_1x.h" 22#include "ieee802_11.h" 23#include "ieee802_11_auth.h" 24#include "wpa_auth.h" 25#include "preauth_auth.h" 26#include "ap_config.h" 27#include "beacon.h" 28#include "ap_mlme.h" 29#include "vlan_init.h" 30#include "p2p_hostapd.h" 31#include "ap_drv_ops.h" 32#include "gas_serv.h" 33#include "wnm_ap.h" 34#include "ndisc_snoop.h" 35#include "sta_info.h" 36 37static void ap_sta_remove_in_other_bss(struct hostapd_data *hapd, 38 struct sta_info *sta); 39static void ap_handle_session_timer(void *eloop_ctx, void *timeout_ctx); 40static void ap_handle_session_warning_timer(void *eloop_ctx, void *timeout_ctx); 41static void ap_sta_deauth_cb_timeout(void *eloop_ctx, void *timeout_ctx); 42static void ap_sta_disassoc_cb_timeout(void *eloop_ctx, void *timeout_ctx); 43#ifdef CONFIG_IEEE80211W 44static void ap_sa_query_timer(void *eloop_ctx, void *timeout_ctx); 45#endif /* CONFIG_IEEE80211W */ 46static int ap_sta_remove(struct hostapd_data *hapd, struct sta_info *sta); 47 48int ap_for_each_sta(struct hostapd_data *hapd, 49 int (*cb)(struct hostapd_data *hapd, struct sta_info *sta, 50 void *ctx), 51 void *ctx) 52{ 53 struct sta_info *sta; 54 55 for (sta = hapd->sta_list; sta; sta = sta->next) { 56 if (cb(hapd, sta, ctx)) 57 return 1; 58 } 59 60 return 0; 61} 62 63 64struct sta_info * ap_get_sta(struct hostapd_data *hapd, const u8 *sta) 65{ 66 struct sta_info *s; 67 68 s = hapd->sta_hash[STA_HASH(sta)]; 69 while (s != NULL && os_memcmp(s->addr, sta, 6) != 0) 70 s = s->hnext; 71 return s; 72} 73 74 75#ifdef CONFIG_P2P 76struct sta_info * ap_get_sta_p2p(struct hostapd_data *hapd, const u8 *addr) 77{ 78 struct sta_info *sta; 79 80 for (sta = hapd->sta_list; sta; sta = sta->next) { 81 const u8 *p2p_dev_addr; 82 83 if (sta->p2p_ie == NULL) 84 continue; 85 86 p2p_dev_addr = p2p_get_go_dev_addr(sta->p2p_ie); 87 if (p2p_dev_addr == NULL) 88 continue; 89 90 if (os_memcmp(p2p_dev_addr, addr, ETH_ALEN) == 0) 91 return sta; 92 } 93 94 return NULL; 95} 96#endif /* CONFIG_P2P */ 97 98 99static void ap_sta_list_del(struct hostapd_data *hapd, struct sta_info *sta) 100{ 101 struct sta_info *tmp; 102 103 if (hapd->sta_list == sta) { 104 hapd->sta_list = sta->next; 105 return; 106 } 107 108 tmp = hapd->sta_list; 109 while (tmp != NULL && tmp->next != sta) 110 tmp = tmp->next; 111 if (tmp == NULL) { 112 wpa_printf(MSG_DEBUG, "Could not remove STA " MACSTR " from " 113 "list.", MAC2STR(sta->addr)); 114 } else 115 tmp->next = sta->next; 116} 117 118 119void ap_sta_hash_add(struct hostapd_data *hapd, struct sta_info *sta) 120{ 121 sta->hnext = hapd->sta_hash[STA_HASH(sta->addr)]; 122 hapd->sta_hash[STA_HASH(sta->addr)] = sta; 123} 124 125 126static void ap_sta_hash_del(struct hostapd_data *hapd, struct sta_info *sta) 127{ 128 struct sta_info *s; 129 130 s = hapd->sta_hash[STA_HASH(sta->addr)]; 131 if (s == NULL) return; 132 if (os_memcmp(s->addr, sta->addr, 6) == 0) { 133 hapd->sta_hash[STA_HASH(sta->addr)] = s->hnext; 134 return; 135 } 136 137 while (s->hnext != NULL && 138 os_memcmp(s->hnext->addr, sta->addr, ETH_ALEN) != 0) 139 s = s->hnext; 140 if (s->hnext != NULL) 141 s->hnext = s->hnext->hnext; 142 else 143 wpa_printf(MSG_DEBUG, "AP: could not remove STA " MACSTR 144 " from hash table", MAC2STR(sta->addr)); 145} 146 147 148void ap_sta_ip6addr_del(struct hostapd_data *hapd, struct sta_info *sta) 149{ 150 sta_ip6addr_del(hapd, sta); 151} 152 153 154void ap_free_sta(struct hostapd_data *hapd, struct sta_info *sta) 155{ 156 int set_beacon = 0; 157 158 accounting_sta_stop(hapd, sta); 159 160 /* just in case */ 161 ap_sta_set_authorized(hapd, sta, 0); 162 163 if (sta->flags & WLAN_STA_WDS) 164 hostapd_set_wds_sta(hapd, NULL, sta->addr, sta->aid, 0); 165 166 if (sta->ipaddr) 167 hostapd_drv_br_delete_ip_neigh(hapd, 4, (u8 *) &sta->ipaddr); 168 ap_sta_ip6addr_del(hapd, sta); 169 170 if (!hapd->iface->driver_ap_teardown && 171 !(sta->flags & WLAN_STA_PREAUTH)) 172 hostapd_drv_sta_remove(hapd, sta->addr); 173 174#ifndef CONFIG_NO_VLAN 175 if (sta->vlan_id_bound) { 176 /* 177 * Need to remove the STA entry before potentially removing the 178 * VLAN. 179 */ 180 if (hapd->iface->driver_ap_teardown && 181 !(sta->flags & WLAN_STA_PREAUTH)) 182 hostapd_drv_sta_remove(hapd, sta->addr); 183 vlan_remove_dynamic(hapd, sta->vlan_id_bound); 184 } 185#endif /* CONFIG_NO_VLAN */ 186 187 ap_sta_hash_del(hapd, sta); 188 ap_sta_list_del(hapd, sta); 189 190 if (sta->aid > 0) 191 hapd->sta_aid[(sta->aid - 1) / 32] &= 192 ~BIT((sta->aid - 1) % 32); 193 194 hapd->num_sta--; 195 if (sta->nonerp_set) { 196 sta->nonerp_set = 0; 197 hapd->iface->num_sta_non_erp--; 198 if (hapd->iface->num_sta_non_erp == 0) 199 set_beacon++; 200 } 201 202 if (sta->no_short_slot_time_set) { 203 sta->no_short_slot_time_set = 0; 204 hapd->iface->num_sta_no_short_slot_time--; 205 if (hapd->iface->current_mode->mode == HOSTAPD_MODE_IEEE80211G 206 && hapd->iface->num_sta_no_short_slot_time == 0) 207 set_beacon++; 208 } 209 210 if (sta->no_short_preamble_set) { 211 sta->no_short_preamble_set = 0; 212 hapd->iface->num_sta_no_short_preamble--; 213 if (hapd->iface->current_mode->mode == HOSTAPD_MODE_IEEE80211G 214 && hapd->iface->num_sta_no_short_preamble == 0) 215 set_beacon++; 216 } 217 218 if (sta->no_ht_gf_set) { 219 sta->no_ht_gf_set = 0; 220 hapd->iface->num_sta_ht_no_gf--; 221 } 222 223 if (sta->no_ht_set) { 224 sta->no_ht_set = 0; 225 hapd->iface->num_sta_no_ht--; 226 } 227 228 if (sta->ht_20mhz_set) { 229 sta->ht_20mhz_set = 0; 230 hapd->iface->num_sta_ht_20mhz--; 231 } 232 233#ifdef CONFIG_IEEE80211N 234 ht40_intolerant_remove(hapd->iface, sta); 235#endif /* CONFIG_IEEE80211N */ 236 237#ifdef CONFIG_P2P 238 if (sta->no_p2p_set) { 239 sta->no_p2p_set = 0; 240 hapd->num_sta_no_p2p--; 241 if (hapd->num_sta_no_p2p == 0) 242 hostapd_p2p_non_p2p_sta_disconnected(hapd); 243 } 244#endif /* CONFIG_P2P */ 245 246#if defined(NEED_AP_MLME) && defined(CONFIG_IEEE80211N) 247 if (hostapd_ht_operation_update(hapd->iface) > 0) 248 set_beacon++; 249#endif /* NEED_AP_MLME && CONFIG_IEEE80211N */ 250 251#ifdef CONFIG_MESH 252 if (hapd->mesh_sta_free_cb) 253 hapd->mesh_sta_free_cb(sta); 254#endif /* CONFIG_MESH */ 255 256 if (set_beacon) 257 ieee802_11_set_beacons(hapd->iface); 258 259 wpa_printf(MSG_DEBUG, "%s: cancel ap_handle_timer for " MACSTR, 260 __func__, MAC2STR(sta->addr)); 261 eloop_cancel_timeout(ap_handle_timer, hapd, sta); 262 eloop_cancel_timeout(ap_handle_session_timer, hapd, sta); 263 eloop_cancel_timeout(ap_handle_session_warning_timer, hapd, sta); 264 eloop_cancel_timeout(ap_sta_deauth_cb_timeout, hapd, sta); 265 eloop_cancel_timeout(ap_sta_disassoc_cb_timeout, hapd, sta); 266 sae_clear_retransmit_timer(hapd, sta); 267 268 ieee802_1x_free_station(sta); 269 wpa_auth_sta_deinit(sta->wpa_sm); 270 rsn_preauth_free_station(hapd, sta); 271#ifndef CONFIG_NO_RADIUS 272 if (hapd->radius) 273 radius_client_flush_auth(hapd->radius, sta->addr); 274#endif /* CONFIG_NO_RADIUS */ 275 276 os_free(sta->challenge); 277 278#ifdef CONFIG_IEEE80211W 279 os_free(sta->sa_query_trans_id); 280 eloop_cancel_timeout(ap_sa_query_timer, hapd, sta); 281#endif /* CONFIG_IEEE80211W */ 282 283#ifdef CONFIG_P2P 284 p2p_group_notif_disassoc(hapd->p2p_group, sta->addr); 285#endif /* CONFIG_P2P */ 286 287#ifdef CONFIG_INTERWORKING 288 if (sta->gas_dialog) { 289 int i; 290 for (i = 0; i < GAS_DIALOG_MAX; i++) 291 gas_serv_dialog_clear(&sta->gas_dialog[i]); 292 os_free(sta->gas_dialog); 293 } 294#endif /* CONFIG_INTERWORKING */ 295 296 wpabuf_free(sta->wps_ie); 297 wpabuf_free(sta->p2p_ie); 298 wpabuf_free(sta->hs20_ie); 299 300 os_free(sta->ht_capabilities); 301 os_free(sta->vht_capabilities); 302 hostapd_free_psk_list(sta->psk); 303 os_free(sta->identity); 304 os_free(sta->radius_cui); 305 os_free(sta->remediation_url); 306 wpabuf_free(sta->hs20_deauth_req); 307 os_free(sta->hs20_session_info_url); 308 309#ifdef CONFIG_SAE 310 sae_clear_data(sta->sae); 311 os_free(sta->sae); 312#endif /* CONFIG_SAE */ 313 314 os_free(sta); 315} 316 317 318void hostapd_free_stas(struct hostapd_data *hapd) 319{ 320 struct sta_info *sta, *prev; 321 322 sta = hapd->sta_list; 323 324 while (sta) { 325 prev = sta; 326 if (sta->flags & WLAN_STA_AUTH) { 327 mlme_deauthenticate_indication( 328 hapd, sta, WLAN_REASON_UNSPECIFIED); 329 } 330 sta = sta->next; 331 wpa_printf(MSG_DEBUG, "Removing station " MACSTR, 332 MAC2STR(prev->addr)); 333 ap_free_sta(hapd, prev); 334 } 335} 336 337 338/** 339 * ap_handle_timer - Per STA timer handler 340 * @eloop_ctx: struct hostapd_data * 341 * @timeout_ctx: struct sta_info * 342 * 343 * This function is called to check station activity and to remove inactive 344 * stations. 345 */ 346void ap_handle_timer(void *eloop_ctx, void *timeout_ctx) 347{ 348 struct hostapd_data *hapd = eloop_ctx; 349 struct sta_info *sta = timeout_ctx; 350 unsigned long next_time = 0; 351 int reason; 352 353 wpa_printf(MSG_DEBUG, "%s: " MACSTR " flags=0x%x timeout_next=%d", 354 __func__, MAC2STR(sta->addr), sta->flags, 355 sta->timeout_next); 356 if (sta->timeout_next == STA_REMOVE) { 357 hostapd_logger(hapd, sta->addr, HOSTAPD_MODULE_IEEE80211, 358 HOSTAPD_LEVEL_INFO, "deauthenticated due to " 359 "local deauth request"); 360 ap_free_sta(hapd, sta); 361 return; 362 } 363 364 if ((sta->flags & WLAN_STA_ASSOC) && 365 (sta->timeout_next == STA_NULLFUNC || 366 sta->timeout_next == STA_DISASSOC)) { 367 int inactive_sec; 368 /* 369 * Add random value to timeout so that we don't end up bouncing 370 * all stations at the same time if we have lots of associated 371 * stations that are idle (but keep re-associating). 372 */ 373 int fuzz = os_random() % 20; 374 inactive_sec = hostapd_drv_get_inact_sec(hapd, sta->addr); 375 if (inactive_sec == -1) { 376 wpa_msg(hapd->msg_ctx, MSG_DEBUG, 377 "Check inactivity: Could not " 378 "get station info from kernel driver for " 379 MACSTR, MAC2STR(sta->addr)); 380 /* 381 * The driver may not support this functionality. 382 * Anyway, try again after the next inactivity timeout, 383 * but do not disconnect the station now. 384 */ 385 next_time = hapd->conf->ap_max_inactivity + fuzz; 386 } else if (inactive_sec == -ENOENT) { 387 wpa_msg(hapd->msg_ctx, MSG_DEBUG, 388 "Station " MACSTR " has lost its driver entry", 389 MAC2STR(sta->addr)); 390 391 /* Avoid sending client probe on removed client */ 392 sta->timeout_next = STA_DISASSOC; 393 goto skip_poll; 394 } else if (inactive_sec < hapd->conf->ap_max_inactivity) { 395 /* station activity detected; reset timeout state */ 396 wpa_msg(hapd->msg_ctx, MSG_DEBUG, 397 "Station " MACSTR " has been active %is ago", 398 MAC2STR(sta->addr), inactive_sec); 399 sta->timeout_next = STA_NULLFUNC; 400 next_time = hapd->conf->ap_max_inactivity + fuzz - 401 inactive_sec; 402 } else { 403 wpa_msg(hapd->msg_ctx, MSG_DEBUG, 404 "Station " MACSTR " has been " 405 "inactive too long: %d sec, max allowed: %d", 406 MAC2STR(sta->addr), inactive_sec, 407 hapd->conf->ap_max_inactivity); 408 409 if (hapd->conf->skip_inactivity_poll) 410 sta->timeout_next = STA_DISASSOC; 411 } 412 } 413 414 if ((sta->flags & WLAN_STA_ASSOC) && 415 sta->timeout_next == STA_DISASSOC && 416 !(sta->flags & WLAN_STA_PENDING_POLL) && 417 !hapd->conf->skip_inactivity_poll) { 418 wpa_msg(hapd->msg_ctx, MSG_DEBUG, "Station " MACSTR 419 " has ACKed data poll", MAC2STR(sta->addr)); 420 /* data nullfunc frame poll did not produce TX errors; assume 421 * station ACKed it */ 422 sta->timeout_next = STA_NULLFUNC; 423 next_time = hapd->conf->ap_max_inactivity; 424 } 425 426skip_poll: 427 if (next_time) { 428 wpa_printf(MSG_DEBUG, "%s: register ap_handle_timer timeout " 429 "for " MACSTR " (%lu seconds)", 430 __func__, MAC2STR(sta->addr), next_time); 431 eloop_register_timeout(next_time, 0, ap_handle_timer, hapd, 432 sta); 433 return; 434 } 435 436 if (sta->timeout_next == STA_NULLFUNC && 437 (sta->flags & WLAN_STA_ASSOC)) { 438 wpa_printf(MSG_DEBUG, " Polling STA"); 439 sta->flags |= WLAN_STA_PENDING_POLL; 440 hostapd_drv_poll_client(hapd, hapd->own_addr, sta->addr, 441 sta->flags & WLAN_STA_WMM); 442 } else if (sta->timeout_next != STA_REMOVE) { 443 int deauth = sta->timeout_next == STA_DEAUTH; 444 445 wpa_dbg(hapd->msg_ctx, MSG_DEBUG, 446 "Timeout, sending %s info to STA " MACSTR, 447 deauth ? "deauthentication" : "disassociation", 448 MAC2STR(sta->addr)); 449 450 if (deauth) { 451 hostapd_drv_sta_deauth( 452 hapd, sta->addr, 453 WLAN_REASON_PREV_AUTH_NOT_VALID); 454 } else { 455 reason = (sta->timeout_next == STA_DISASSOC) ? 456 WLAN_REASON_DISASSOC_DUE_TO_INACTIVITY : 457 WLAN_REASON_PREV_AUTH_NOT_VALID; 458 459 hostapd_drv_sta_disassoc(hapd, sta->addr, reason); 460 } 461 } 462 463 switch (sta->timeout_next) { 464 case STA_NULLFUNC: 465 sta->timeout_next = STA_DISASSOC; 466 wpa_printf(MSG_DEBUG, "%s: register ap_handle_timer timeout " 467 "for " MACSTR " (%d seconds - AP_DISASSOC_DELAY)", 468 __func__, MAC2STR(sta->addr), AP_DISASSOC_DELAY); 469 eloop_register_timeout(AP_DISASSOC_DELAY, 0, ap_handle_timer, 470 hapd, sta); 471 break; 472 case STA_DISASSOC: 473 case STA_DISASSOC_FROM_CLI: 474 ap_sta_set_authorized(hapd, sta, 0); 475 sta->flags &= ~WLAN_STA_ASSOC; 476 ieee802_1x_notify_port_enabled(sta->eapol_sm, 0); 477 if (!sta->acct_terminate_cause) 478 sta->acct_terminate_cause = 479 RADIUS_ACCT_TERMINATE_CAUSE_IDLE_TIMEOUT; 480 accounting_sta_stop(hapd, sta); 481 ieee802_1x_free_station(sta); 482 hostapd_logger(hapd, sta->addr, HOSTAPD_MODULE_IEEE80211, 483 HOSTAPD_LEVEL_INFO, "disassociated due to " 484 "inactivity"); 485 reason = (sta->timeout_next == STA_DISASSOC) ? 486 WLAN_REASON_DISASSOC_DUE_TO_INACTIVITY : 487 WLAN_REASON_PREV_AUTH_NOT_VALID; 488 sta->timeout_next = STA_DEAUTH; 489 wpa_printf(MSG_DEBUG, "%s: register ap_handle_timer timeout " 490 "for " MACSTR " (%d seconds - AP_DEAUTH_DELAY)", 491 __func__, MAC2STR(sta->addr), AP_DEAUTH_DELAY); 492 eloop_register_timeout(AP_DEAUTH_DELAY, 0, ap_handle_timer, 493 hapd, sta); 494 mlme_disassociate_indication(hapd, sta, reason); 495 break; 496 case STA_DEAUTH: 497 case STA_REMOVE: 498 hostapd_logger(hapd, sta->addr, HOSTAPD_MODULE_IEEE80211, 499 HOSTAPD_LEVEL_INFO, "deauthenticated due to " 500 "inactivity (timer DEAUTH/REMOVE)"); 501 if (!sta->acct_terminate_cause) 502 sta->acct_terminate_cause = 503 RADIUS_ACCT_TERMINATE_CAUSE_IDLE_TIMEOUT; 504 mlme_deauthenticate_indication( 505 hapd, sta, 506 WLAN_REASON_PREV_AUTH_NOT_VALID); 507 ap_free_sta(hapd, sta); 508 break; 509 } 510} 511 512 513static void ap_handle_session_timer(void *eloop_ctx, void *timeout_ctx) 514{ 515 struct hostapd_data *hapd = eloop_ctx; 516 struct sta_info *sta = timeout_ctx; 517 518 if (!(sta->flags & WLAN_STA_AUTH)) { 519 if (sta->flags & WLAN_STA_GAS) { 520 wpa_printf(MSG_DEBUG, "GAS: Remove temporary STA " 521 "entry " MACSTR, MAC2STR(sta->addr)); 522 ap_free_sta(hapd, sta); 523 } 524 return; 525 } 526 527 hostapd_drv_sta_deauth(hapd, sta->addr, 528 WLAN_REASON_PREV_AUTH_NOT_VALID); 529 mlme_deauthenticate_indication(hapd, sta, 530 WLAN_REASON_PREV_AUTH_NOT_VALID); 531 hostapd_logger(hapd, sta->addr, HOSTAPD_MODULE_IEEE80211, 532 HOSTAPD_LEVEL_INFO, "deauthenticated due to " 533 "session timeout"); 534 sta->acct_terminate_cause = 535 RADIUS_ACCT_TERMINATE_CAUSE_SESSION_TIMEOUT; 536 ap_free_sta(hapd, sta); 537} 538 539 540void ap_sta_replenish_timeout(struct hostapd_data *hapd, struct sta_info *sta, 541 u32 session_timeout) 542{ 543 if (eloop_replenish_timeout(session_timeout, 0, 544 ap_handle_session_timer, hapd, sta) == 1) { 545 hostapd_logger(hapd, sta->addr, HOSTAPD_MODULE_IEEE80211, 546 HOSTAPD_LEVEL_DEBUG, "setting session timeout " 547 "to %d seconds", session_timeout); 548 } 549} 550 551 552void ap_sta_session_timeout(struct hostapd_data *hapd, struct sta_info *sta, 553 u32 session_timeout) 554{ 555 hostapd_logger(hapd, sta->addr, HOSTAPD_MODULE_IEEE80211, 556 HOSTAPD_LEVEL_DEBUG, "setting session timeout to %d " 557 "seconds", session_timeout); 558 eloop_cancel_timeout(ap_handle_session_timer, hapd, sta); 559 eloop_register_timeout(session_timeout, 0, ap_handle_session_timer, 560 hapd, sta); 561} 562 563 564void ap_sta_no_session_timeout(struct hostapd_data *hapd, struct sta_info *sta) 565{ 566 eloop_cancel_timeout(ap_handle_session_timer, hapd, sta); 567} 568 569 570static void ap_handle_session_warning_timer(void *eloop_ctx, void *timeout_ctx) 571{ 572#ifdef CONFIG_WNM 573 struct hostapd_data *hapd = eloop_ctx; 574 struct sta_info *sta = timeout_ctx; 575 576 wpa_printf(MSG_DEBUG, "WNM: Session warning time reached for " MACSTR, 577 MAC2STR(sta->addr)); 578 if (sta->hs20_session_info_url == NULL) 579 return; 580 581 wnm_send_ess_disassoc_imminent(hapd, sta, sta->hs20_session_info_url, 582 sta->hs20_disassoc_timer); 583#endif /* CONFIG_WNM */ 584} 585 586 587void ap_sta_session_warning_timeout(struct hostapd_data *hapd, 588 struct sta_info *sta, int warning_time) 589{ 590 eloop_cancel_timeout(ap_handle_session_warning_timer, hapd, sta); 591 eloop_register_timeout(warning_time, 0, ap_handle_session_warning_timer, 592 hapd, sta); 593} 594 595 596struct sta_info * ap_sta_add(struct hostapd_data *hapd, const u8 *addr) 597{ 598 struct sta_info *sta; 599 600 sta = ap_get_sta(hapd, addr); 601 if (sta) 602 return sta; 603 604 wpa_printf(MSG_DEBUG, " New STA"); 605 if (hapd->num_sta >= hapd->conf->max_num_sta) { 606 /* FIX: might try to remove some old STAs first? */ 607 wpa_printf(MSG_DEBUG, "no more room for new STAs (%d/%d)", 608 hapd->num_sta, hapd->conf->max_num_sta); 609 return NULL; 610 } 611 612 sta = os_zalloc(sizeof(struct sta_info)); 613 if (sta == NULL) { 614 wpa_printf(MSG_ERROR, "malloc failed"); 615 return NULL; 616 } 617 sta->acct_interim_interval = hapd->conf->acct_interim_interval; 618 accounting_sta_get_id(hapd, sta); 619 620 if (!(hapd->iface->drv_flags & WPA_DRIVER_FLAGS_INACTIVITY_TIMER)) { 621 wpa_printf(MSG_DEBUG, "%s: register ap_handle_timer timeout " 622 "for " MACSTR " (%d seconds - ap_max_inactivity)", 623 __func__, MAC2STR(addr), 624 hapd->conf->ap_max_inactivity); 625 eloop_register_timeout(hapd->conf->ap_max_inactivity, 0, 626 ap_handle_timer, hapd, sta); 627 } 628 629 /* initialize STA info data */ 630 os_memcpy(sta->addr, addr, ETH_ALEN); 631 sta->next = hapd->sta_list; 632 hapd->sta_list = sta; 633 hapd->num_sta++; 634 ap_sta_hash_add(hapd, sta); 635 ap_sta_remove_in_other_bss(hapd, sta); 636 sta->last_seq_ctrl = WLAN_INVALID_MGMT_SEQ; 637 dl_list_init(&sta->ip6addr); 638 639 return sta; 640} 641 642 643static int ap_sta_remove(struct hostapd_data *hapd, struct sta_info *sta) 644{ 645 ieee802_1x_notify_port_enabled(sta->eapol_sm, 0); 646 647 if (sta->ipaddr) 648 hostapd_drv_br_delete_ip_neigh(hapd, 4, (u8 *) &sta->ipaddr); 649 ap_sta_ip6addr_del(hapd, sta); 650 651 wpa_printf(MSG_DEBUG, "Removing STA " MACSTR " from kernel driver", 652 MAC2STR(sta->addr)); 653 if (hostapd_drv_sta_remove(hapd, sta->addr) && 654 sta->flags & WLAN_STA_ASSOC) { 655 wpa_printf(MSG_DEBUG, "Could not remove station " MACSTR 656 " from kernel driver.", MAC2STR(sta->addr)); 657 return -1; 658 } 659 return 0; 660} 661 662 663static void ap_sta_remove_in_other_bss(struct hostapd_data *hapd, 664 struct sta_info *sta) 665{ 666 struct hostapd_iface *iface = hapd->iface; 667 size_t i; 668 669 for (i = 0; i < iface->num_bss; i++) { 670 struct hostapd_data *bss = iface->bss[i]; 671 struct sta_info *sta2; 672 /* bss should always be set during operation, but it may be 673 * NULL during reconfiguration. Assume the STA is not 674 * associated to another BSS in that case to avoid NULL pointer 675 * dereferences. */ 676 if (bss == hapd || bss == NULL) 677 continue; 678 sta2 = ap_get_sta(bss, sta->addr); 679 if (!sta2) 680 continue; 681 682 ap_sta_disconnect(bss, sta2, sta2->addr, 683 WLAN_REASON_PREV_AUTH_NOT_VALID); 684 } 685} 686 687 688static void ap_sta_disassoc_cb_timeout(void *eloop_ctx, void *timeout_ctx) 689{ 690 struct hostapd_data *hapd = eloop_ctx; 691 struct sta_info *sta = timeout_ctx; 692 693 ap_sta_remove(hapd, sta); 694 mlme_disassociate_indication(hapd, sta, sta->disassoc_reason); 695} 696 697 698void ap_sta_disassociate(struct hostapd_data *hapd, struct sta_info *sta, 699 u16 reason) 700{ 701 wpa_printf(MSG_DEBUG, "%s: disassociate STA " MACSTR, 702 hapd->conf->iface, MAC2STR(sta->addr)); 703 sta->last_seq_ctrl = WLAN_INVALID_MGMT_SEQ; 704 sta->flags &= ~(WLAN_STA_ASSOC | WLAN_STA_ASSOC_REQ_OK); 705 ap_sta_set_authorized(hapd, sta, 0); 706 sta->timeout_next = STA_DEAUTH; 707 wpa_printf(MSG_DEBUG, "%s: reschedule ap_handle_timer timeout " 708 "for " MACSTR " (%d seconds - " 709 "AP_MAX_INACTIVITY_AFTER_DISASSOC)", 710 __func__, MAC2STR(sta->addr), 711 AP_MAX_INACTIVITY_AFTER_DISASSOC); 712 eloop_cancel_timeout(ap_handle_timer, hapd, sta); 713 eloop_register_timeout(AP_MAX_INACTIVITY_AFTER_DISASSOC, 0, 714 ap_handle_timer, hapd, sta); 715 accounting_sta_stop(hapd, sta); 716 ieee802_1x_free_station(sta); 717 718 sta->disassoc_reason = reason; 719 sta->flags |= WLAN_STA_PENDING_DISASSOC_CB; 720 eloop_cancel_timeout(ap_sta_disassoc_cb_timeout, hapd, sta); 721 eloop_register_timeout(hapd->iface->drv_flags & 722 WPA_DRIVER_FLAGS_DEAUTH_TX_STATUS ? 2 : 0, 0, 723 ap_sta_disassoc_cb_timeout, hapd, sta); 724} 725 726 727static void ap_sta_deauth_cb_timeout(void *eloop_ctx, void *timeout_ctx) 728{ 729 struct hostapd_data *hapd = eloop_ctx; 730 struct sta_info *sta = timeout_ctx; 731 732 ap_sta_remove(hapd, sta); 733 mlme_deauthenticate_indication(hapd, sta, sta->deauth_reason); 734} 735 736 737void ap_sta_deauthenticate(struct hostapd_data *hapd, struct sta_info *sta, 738 u16 reason) 739{ 740 wpa_printf(MSG_DEBUG, "%s: deauthenticate STA " MACSTR, 741 hapd->conf->iface, MAC2STR(sta->addr)); 742 sta->last_seq_ctrl = WLAN_INVALID_MGMT_SEQ; 743 sta->flags &= ~(WLAN_STA_AUTH | WLAN_STA_ASSOC | WLAN_STA_ASSOC_REQ_OK); 744 ap_sta_set_authorized(hapd, sta, 0); 745 sta->timeout_next = STA_REMOVE; 746 wpa_printf(MSG_DEBUG, "%s: reschedule ap_handle_timer timeout " 747 "for " MACSTR " (%d seconds - " 748 "AP_MAX_INACTIVITY_AFTER_DEAUTH)", 749 __func__, MAC2STR(sta->addr), 750 AP_MAX_INACTIVITY_AFTER_DEAUTH); 751 eloop_cancel_timeout(ap_handle_timer, hapd, sta); 752 eloop_register_timeout(AP_MAX_INACTIVITY_AFTER_DEAUTH, 0, 753 ap_handle_timer, hapd, sta); 754 accounting_sta_stop(hapd, sta); 755 ieee802_1x_free_station(sta); 756 757 sta->deauth_reason = reason; 758 sta->flags |= WLAN_STA_PENDING_DEAUTH_CB; 759 eloop_cancel_timeout(ap_sta_deauth_cb_timeout, hapd, sta); 760 eloop_register_timeout(hapd->iface->drv_flags & 761 WPA_DRIVER_FLAGS_DEAUTH_TX_STATUS ? 2 : 0, 0, 762 ap_sta_deauth_cb_timeout, hapd, sta); 763} 764 765 766#ifdef CONFIG_WPS 767int ap_sta_wps_cancel(struct hostapd_data *hapd, 768 struct sta_info *sta, void *ctx) 769{ 770 if (sta && (sta->flags & WLAN_STA_WPS)) { 771 ap_sta_deauthenticate(hapd, sta, 772 WLAN_REASON_PREV_AUTH_NOT_VALID); 773 wpa_printf(MSG_DEBUG, "WPS: %s: Deauth sta=" MACSTR, 774 __func__, MAC2STR(sta->addr)); 775 return 1; 776 } 777 778 return 0; 779} 780#endif /* CONFIG_WPS */ 781 782 783int ap_sta_bind_vlan(struct hostapd_data *hapd, struct sta_info *sta) 784{ 785#ifndef CONFIG_NO_VLAN 786 const char *iface; 787 struct hostapd_vlan *vlan = NULL; 788 int ret; 789 int old_vlanid = sta->vlan_id_bound; 790 791 iface = hapd->conf->iface; 792 if (hapd->conf->ssid.vlan[0]) 793 iface = hapd->conf->ssid.vlan; 794 795 if (hapd->conf->ssid.dynamic_vlan == DYNAMIC_VLAN_DISABLED) 796 sta->vlan_id = 0; 797 else if (sta->vlan_id > 0) { 798 struct hostapd_vlan *wildcard_vlan = NULL; 799 vlan = hapd->conf->vlan; 800 while (vlan) { 801 if (vlan->vlan_id == sta->vlan_id) 802 break; 803 if (vlan->vlan_id == VLAN_ID_WILDCARD) 804 wildcard_vlan = vlan; 805 vlan = vlan->next; 806 } 807 if (!vlan) 808 vlan = wildcard_vlan; 809 if (vlan) 810 iface = vlan->ifname; 811 } 812 813 /* 814 * Do not increment ref counters if the VLAN ID remains same, but do 815 * not skip hostapd_drv_set_sta_vlan() as hostapd_drv_sta_remove() might 816 * have been called before. 817 */ 818 if (sta->vlan_id == old_vlanid) 819 goto skip_counting; 820 821 if (sta->vlan_id > 0 && vlan == NULL) { 822 hostapd_logger(hapd, sta->addr, HOSTAPD_MODULE_IEEE80211, 823 HOSTAPD_LEVEL_DEBUG, "could not find VLAN for " 824 "binding station to (vlan_id=%d)", 825 sta->vlan_id); 826 ret = -1; 827 goto done; 828 } else if (sta->vlan_id > 0 && vlan->vlan_id == VLAN_ID_WILDCARD) { 829 vlan = vlan_add_dynamic(hapd, vlan, sta->vlan_id); 830 if (vlan == NULL) { 831 hostapd_logger(hapd, sta->addr, 832 HOSTAPD_MODULE_IEEE80211, 833 HOSTAPD_LEVEL_DEBUG, "could not add " 834 "dynamic VLAN interface for vlan_id=%d", 835 sta->vlan_id); 836 ret = -1; 837 goto done; 838 } 839 840 iface = vlan->ifname; 841 if (vlan_setup_encryption_dyn(hapd, iface) != 0) { 842 hostapd_logger(hapd, sta->addr, 843 HOSTAPD_MODULE_IEEE80211, 844 HOSTAPD_LEVEL_DEBUG, "could not " 845 "configure encryption for dynamic VLAN " 846 "interface for vlan_id=%d", 847 sta->vlan_id); 848 } 849 850 hostapd_logger(hapd, sta->addr, HOSTAPD_MODULE_IEEE80211, 851 HOSTAPD_LEVEL_DEBUG, "added new dynamic VLAN " 852 "interface '%s'", iface); 853 } else if (vlan && vlan->vlan_id == sta->vlan_id) { 854 if (vlan->dynamic_vlan > 0) { 855 vlan->dynamic_vlan++; 856 hostapd_logger(hapd, sta->addr, 857 HOSTAPD_MODULE_IEEE80211, 858 HOSTAPD_LEVEL_DEBUG, "updated existing " 859 "dynamic VLAN interface '%s'", iface); 860 } 861 862 /* 863 * Update encryption configuration for statically generated 864 * VLAN interface. This is only used for static WEP 865 * configuration for the case where hostapd did not yet know 866 * which keys are to be used when the interface was added. 867 */ 868 if (vlan_setup_encryption_dyn(hapd, iface) != 0) { 869 hostapd_logger(hapd, sta->addr, 870 HOSTAPD_MODULE_IEEE80211, 871 HOSTAPD_LEVEL_DEBUG, "could not " 872 "configure encryption for VLAN " 873 "interface for vlan_id=%d", 874 sta->vlan_id); 875 } 876 } 877 878 /* ref counters have been increased, so mark the station */ 879 sta->vlan_id_bound = sta->vlan_id; 880 881skip_counting: 882 hostapd_logger(hapd, sta->addr, HOSTAPD_MODULE_IEEE80211, 883 HOSTAPD_LEVEL_DEBUG, "binding station to interface " 884 "'%s'", iface); 885 886 if (wpa_auth_sta_set_vlan(sta->wpa_sm, sta->vlan_id) < 0) 887 wpa_printf(MSG_INFO, "Failed to update VLAN-ID for WPA"); 888 889 ret = hostapd_drv_set_sta_vlan(iface, hapd, sta->addr, sta->vlan_id); 890 if (ret < 0) { 891 hostapd_logger(hapd, sta->addr, HOSTAPD_MODULE_IEEE80211, 892 HOSTAPD_LEVEL_DEBUG, "could not bind the STA " 893 "entry to vlan_id=%d", sta->vlan_id); 894 } 895 896 /* During 1x reauth, if the vlan id changes, then remove the old id. */ 897 if (old_vlanid > 0 && old_vlanid != sta->vlan_id) 898 vlan_remove_dynamic(hapd, old_vlanid); 899done: 900 901 return ret; 902#else /* CONFIG_NO_VLAN */ 903 return 0; 904#endif /* CONFIG_NO_VLAN */ 905} 906 907 908#ifdef CONFIG_IEEE80211W 909 910int ap_check_sa_query_timeout(struct hostapd_data *hapd, struct sta_info *sta) 911{ 912 u32 tu; 913 struct os_reltime now, passed; 914 os_get_reltime(&now); 915 os_reltime_sub(&now, &sta->sa_query_start, &passed); 916 tu = (passed.sec * 1000000 + passed.usec) / 1024; 917 if (hapd->conf->assoc_sa_query_max_timeout < tu) { 918 hostapd_logger(hapd, sta->addr, 919 HOSTAPD_MODULE_IEEE80211, 920 HOSTAPD_LEVEL_DEBUG, 921 "association SA Query timed out"); 922 sta->sa_query_timed_out = 1; 923 os_free(sta->sa_query_trans_id); 924 sta->sa_query_trans_id = NULL; 925 sta->sa_query_count = 0; 926 eloop_cancel_timeout(ap_sa_query_timer, hapd, sta); 927 return 1; 928 } 929 930 return 0; 931} 932 933 934static void ap_sa_query_timer(void *eloop_ctx, void *timeout_ctx) 935{ 936 struct hostapd_data *hapd = eloop_ctx; 937 struct sta_info *sta = timeout_ctx; 938 unsigned int timeout, sec, usec; 939 u8 *trans_id, *nbuf; 940 941 if (sta->sa_query_count > 0 && 942 ap_check_sa_query_timeout(hapd, sta)) 943 return; 944 945 nbuf = os_realloc_array(sta->sa_query_trans_id, 946 sta->sa_query_count + 1, 947 WLAN_SA_QUERY_TR_ID_LEN); 948 if (nbuf == NULL) 949 return; 950 if (sta->sa_query_count == 0) { 951 /* Starting a new SA Query procedure */ 952 os_get_reltime(&sta->sa_query_start); 953 } 954 trans_id = nbuf + sta->sa_query_count * WLAN_SA_QUERY_TR_ID_LEN; 955 sta->sa_query_trans_id = nbuf; 956 sta->sa_query_count++; 957 958 if (os_get_random(trans_id, WLAN_SA_QUERY_TR_ID_LEN) < 0) { 959 /* 960 * We don't really care which ID is used here, so simply 961 * hardcode this if the mostly theoretical os_get_random() 962 * failure happens. 963 */ 964 trans_id[0] = 0x12; 965 trans_id[1] = 0x34; 966 } 967 968 timeout = hapd->conf->assoc_sa_query_retry_timeout; 969 sec = ((timeout / 1000) * 1024) / 1000; 970 usec = (timeout % 1000) * 1024; 971 eloop_register_timeout(sec, usec, ap_sa_query_timer, hapd, sta); 972 973 hostapd_logger(hapd, sta->addr, HOSTAPD_MODULE_IEEE80211, 974 HOSTAPD_LEVEL_DEBUG, 975 "association SA Query attempt %d", sta->sa_query_count); 976 977 ieee802_11_send_sa_query_req(hapd, sta->addr, trans_id); 978} 979 980 981void ap_sta_start_sa_query(struct hostapd_data *hapd, struct sta_info *sta) 982{ 983 ap_sa_query_timer(hapd, sta); 984} 985 986 987void ap_sta_stop_sa_query(struct hostapd_data *hapd, struct sta_info *sta) 988{ 989 eloop_cancel_timeout(ap_sa_query_timer, hapd, sta); 990 os_free(sta->sa_query_trans_id); 991 sta->sa_query_trans_id = NULL; 992 sta->sa_query_count = 0; 993} 994 995#endif /* CONFIG_IEEE80211W */ 996 997 998void ap_sta_set_authorized(struct hostapd_data *hapd, struct sta_info *sta, 999 int authorized) 1000{ 1001 const u8 *dev_addr = NULL; 1002 char buf[100]; 1003#ifdef CONFIG_P2P 1004 u8 addr[ETH_ALEN]; 1005 u8 ip_addr_buf[4]; 1006#endif /* CONFIG_P2P */ 1007 1008 if (!!authorized == !!(sta->flags & WLAN_STA_AUTHORIZED)) 1009 return; 1010 1011 if (authorized) 1012 sta->flags |= WLAN_STA_AUTHORIZED; 1013 else 1014 sta->flags &= ~WLAN_STA_AUTHORIZED; 1015 1016#ifdef CONFIG_P2P 1017 if (hapd->p2p_group == NULL) { 1018 if (sta->p2p_ie != NULL && 1019 p2p_parse_dev_addr_in_p2p_ie(sta->p2p_ie, addr) == 0) 1020 dev_addr = addr; 1021 } else 1022 dev_addr = p2p_group_get_dev_addr(hapd->p2p_group, sta->addr); 1023 1024 if (dev_addr) 1025 os_snprintf(buf, sizeof(buf), MACSTR " p2p_dev_addr=" MACSTR, 1026 MAC2STR(sta->addr), MAC2STR(dev_addr)); 1027 else 1028#endif /* CONFIG_P2P */ 1029 os_snprintf(buf, sizeof(buf), MACSTR, MAC2STR(sta->addr)); 1030 1031 if (hapd->sta_authorized_cb) 1032 hapd->sta_authorized_cb(hapd->sta_authorized_cb_ctx, 1033 sta->addr, authorized, dev_addr); 1034 1035 if (authorized) { 1036 char ip_addr[100]; 1037 ip_addr[0] = '\0'; 1038#ifdef CONFIG_P2P 1039 if (wpa_auth_get_ip_addr(sta->wpa_sm, ip_addr_buf) == 0) { 1040 os_snprintf(ip_addr, sizeof(ip_addr), 1041 " ip_addr=%u.%u.%u.%u", 1042 ip_addr_buf[0], ip_addr_buf[1], 1043 ip_addr_buf[2], ip_addr_buf[3]); 1044 } 1045#endif /* CONFIG_P2P */ 1046 1047 wpa_msg(hapd->msg_ctx, MSG_INFO, AP_STA_CONNECTED "%s%s", 1048 buf, ip_addr); 1049 1050 if (hapd->msg_ctx_parent && 1051 hapd->msg_ctx_parent != hapd->msg_ctx) 1052 wpa_msg_no_global(hapd->msg_ctx_parent, MSG_INFO, 1053 AP_STA_CONNECTED "%s%s", 1054 buf, ip_addr); 1055 } else { 1056 wpa_msg(hapd->msg_ctx, MSG_INFO, AP_STA_DISCONNECTED "%s", buf); 1057 1058 if (hapd->msg_ctx_parent && 1059 hapd->msg_ctx_parent != hapd->msg_ctx) 1060 wpa_msg_no_global(hapd->msg_ctx_parent, MSG_INFO, 1061 AP_STA_DISCONNECTED "%s", buf); 1062 } 1063} 1064 1065 1066void ap_sta_disconnect(struct hostapd_data *hapd, struct sta_info *sta, 1067 const u8 *addr, u16 reason) 1068{ 1069 1070 if (sta == NULL && addr) 1071 sta = ap_get_sta(hapd, addr); 1072 1073 if (addr) 1074 hostapd_drv_sta_deauth(hapd, addr, reason); 1075 1076 if (sta == NULL) 1077 return; 1078 ap_sta_set_authorized(hapd, sta, 0); 1079 wpa_auth_sm_event(sta->wpa_sm, WPA_DEAUTH); 1080 ieee802_1x_notify_port_enabled(sta->eapol_sm, 0); 1081 sta->flags &= ~(WLAN_STA_AUTH | WLAN_STA_ASSOC); 1082 wpa_printf(MSG_DEBUG, "%s: reschedule ap_handle_timer timeout " 1083 "for " MACSTR " (%d seconds - " 1084 "AP_MAX_INACTIVITY_AFTER_DEAUTH)", 1085 __func__, MAC2STR(sta->addr), 1086 AP_MAX_INACTIVITY_AFTER_DEAUTH); 1087 eloop_cancel_timeout(ap_handle_timer, hapd, sta); 1088 eloop_register_timeout(AP_MAX_INACTIVITY_AFTER_DEAUTH, 0, 1089 ap_handle_timer, hapd, sta); 1090 sta->timeout_next = STA_REMOVE; 1091 1092 sta->deauth_reason = reason; 1093 sta->flags |= WLAN_STA_PENDING_DEAUTH_CB; 1094 eloop_cancel_timeout(ap_sta_deauth_cb_timeout, hapd, sta); 1095 eloop_register_timeout(hapd->iface->drv_flags & 1096 WPA_DRIVER_FLAGS_DEAUTH_TX_STATUS ? 2 : 0, 0, 1097 ap_sta_deauth_cb_timeout, hapd, sta); 1098} 1099 1100 1101void ap_sta_deauth_cb(struct hostapd_data *hapd, struct sta_info *sta) 1102{ 1103 if (!(sta->flags & WLAN_STA_PENDING_DEAUTH_CB)) { 1104 wpa_printf(MSG_DEBUG, "Ignore deauth cb for test frame"); 1105 return; 1106 } 1107 sta->flags &= ~WLAN_STA_PENDING_DEAUTH_CB; 1108 eloop_cancel_timeout(ap_sta_deauth_cb_timeout, hapd, sta); 1109 ap_sta_deauth_cb_timeout(hapd, sta); 1110} 1111 1112 1113void ap_sta_disassoc_cb(struct hostapd_data *hapd, struct sta_info *sta) 1114{ 1115 if (!(sta->flags & WLAN_STA_PENDING_DISASSOC_CB)) { 1116 wpa_printf(MSG_DEBUG, "Ignore disassoc cb for test frame"); 1117 return; 1118 } 1119 sta->flags &= ~WLAN_STA_PENDING_DISASSOC_CB; 1120 eloop_cancel_timeout(ap_sta_disassoc_cb_timeout, hapd, sta); 1121 ap_sta_disassoc_cb_timeout(hapd, sta); 1122} 1123 1124 1125int ap_sta_flags_txt(u32 flags, char *buf, size_t buflen) 1126{ 1127 int res; 1128 1129 buf[0] = '\0'; 1130 res = os_snprintf(buf, buflen, "%s%s%s%s%s%s%s%s%s%s%s%s%s%s%s%s%s", 1131 (flags & WLAN_STA_AUTH ? "[AUTH]" : ""), 1132 (flags & WLAN_STA_ASSOC ? "[ASSOC]" : ""), 1133 (flags & WLAN_STA_AUTHORIZED ? "[AUTHORIZED]" : ""), 1134 (flags & WLAN_STA_PENDING_POLL ? "[PENDING_POLL" : 1135 ""), 1136 (flags & WLAN_STA_SHORT_PREAMBLE ? 1137 "[SHORT_PREAMBLE]" : ""), 1138 (flags & WLAN_STA_PREAUTH ? "[PREAUTH]" : ""), 1139 (flags & WLAN_STA_WMM ? "[WMM]" : ""), 1140 (flags & WLAN_STA_MFP ? "[MFP]" : ""), 1141 (flags & WLAN_STA_WPS ? "[WPS]" : ""), 1142 (flags & WLAN_STA_MAYBE_WPS ? "[MAYBE_WPS]" : ""), 1143 (flags & WLAN_STA_WDS ? "[WDS]" : ""), 1144 (flags & WLAN_STA_NONERP ? "[NonERP]" : ""), 1145 (flags & WLAN_STA_WPS2 ? "[WPS2]" : ""), 1146 (flags & WLAN_STA_GAS ? "[GAS]" : ""), 1147 (flags & WLAN_STA_VHT ? "[VHT]" : ""), 1148 (flags & WLAN_STA_VENDOR_VHT ? "[VENDOR_VHT]" : ""), 1149 (flags & WLAN_STA_WNM_SLEEP_MODE ? 1150 "[WNM_SLEEP_MODE]" : "")); 1151 if (os_snprintf_error(buflen, res)) 1152 res = -1; 1153 1154 return res; 1155} 1156