ieee802_11_shared.c revision 1f69aa52ea2e0a73ac502565df8c666ee49cab6a
11f69aa52ea2e0a73ac502565df8c666ee49cab6aDmitry Shmidt/* 21f69aa52ea2e0a73ac502565df8c666ee49cab6aDmitry Shmidt * hostapd / IEEE 802.11 Management 31f69aa52ea2e0a73ac502565df8c666ee49cab6aDmitry Shmidt * Copyright (c) 2002-2010, Jouni Malinen <j@w1.fi> 41f69aa52ea2e0a73ac502565df8c666ee49cab6aDmitry Shmidt * 51f69aa52ea2e0a73ac502565df8c666ee49cab6aDmitry Shmidt * This program is free software; you can redistribute it and/or modify 61f69aa52ea2e0a73ac502565df8c666ee49cab6aDmitry Shmidt * it under the terms of the GNU General Public License version 2 as 71f69aa52ea2e0a73ac502565df8c666ee49cab6aDmitry Shmidt * published by the Free Software Foundation. 81f69aa52ea2e0a73ac502565df8c666ee49cab6aDmitry Shmidt * 91f69aa52ea2e0a73ac502565df8c666ee49cab6aDmitry Shmidt * Alternatively, this software may be distributed under the terms of BSD 101f69aa52ea2e0a73ac502565df8c666ee49cab6aDmitry Shmidt * license. 111f69aa52ea2e0a73ac502565df8c666ee49cab6aDmitry Shmidt * 121f69aa52ea2e0a73ac502565df8c666ee49cab6aDmitry Shmidt * See README and COPYING for more details. 131f69aa52ea2e0a73ac502565df8c666ee49cab6aDmitry Shmidt */ 141f69aa52ea2e0a73ac502565df8c666ee49cab6aDmitry Shmidt 151f69aa52ea2e0a73ac502565df8c666ee49cab6aDmitry Shmidt#include "utils/includes.h" 161f69aa52ea2e0a73ac502565df8c666ee49cab6aDmitry Shmidt 171f69aa52ea2e0a73ac502565df8c666ee49cab6aDmitry Shmidt#include "utils/common.h" 181f69aa52ea2e0a73ac502565df8c666ee49cab6aDmitry Shmidt#include "common/ieee802_11_defs.h" 191f69aa52ea2e0a73ac502565df8c666ee49cab6aDmitry Shmidt#include "hostapd.h" 201f69aa52ea2e0a73ac502565df8c666ee49cab6aDmitry Shmidt#include "sta_info.h" 211f69aa52ea2e0a73ac502565df8c666ee49cab6aDmitry Shmidt#include "ap_config.h" 221f69aa52ea2e0a73ac502565df8c666ee49cab6aDmitry Shmidt#include "ap_drv_ops.h" 231f69aa52ea2e0a73ac502565df8c666ee49cab6aDmitry Shmidt#include "ieee802_11.h" 241f69aa52ea2e0a73ac502565df8c666ee49cab6aDmitry Shmidt 251f69aa52ea2e0a73ac502565df8c666ee49cab6aDmitry Shmidt 261f69aa52ea2e0a73ac502565df8c666ee49cab6aDmitry Shmidt#ifdef CONFIG_IEEE80211W 271f69aa52ea2e0a73ac502565df8c666ee49cab6aDmitry Shmidt 281f69aa52ea2e0a73ac502565df8c666ee49cab6aDmitry Shmidtu8 * hostapd_eid_assoc_comeback_time(struct hostapd_data *hapd, 291f69aa52ea2e0a73ac502565df8c666ee49cab6aDmitry Shmidt struct sta_info *sta, u8 *eid) 301f69aa52ea2e0a73ac502565df8c666ee49cab6aDmitry Shmidt{ 311f69aa52ea2e0a73ac502565df8c666ee49cab6aDmitry Shmidt u8 *pos = eid; 321f69aa52ea2e0a73ac502565df8c666ee49cab6aDmitry Shmidt u32 timeout, tu; 331f69aa52ea2e0a73ac502565df8c666ee49cab6aDmitry Shmidt struct os_time now, passed; 341f69aa52ea2e0a73ac502565df8c666ee49cab6aDmitry Shmidt 351f69aa52ea2e0a73ac502565df8c666ee49cab6aDmitry Shmidt *pos++ = WLAN_EID_TIMEOUT_INTERVAL; 361f69aa52ea2e0a73ac502565df8c666ee49cab6aDmitry Shmidt *pos++ = 5; 371f69aa52ea2e0a73ac502565df8c666ee49cab6aDmitry Shmidt *pos++ = WLAN_TIMEOUT_ASSOC_COMEBACK; 381f69aa52ea2e0a73ac502565df8c666ee49cab6aDmitry Shmidt os_get_time(&now); 391f69aa52ea2e0a73ac502565df8c666ee49cab6aDmitry Shmidt os_time_sub(&now, &sta->sa_query_start, &passed); 401f69aa52ea2e0a73ac502565df8c666ee49cab6aDmitry Shmidt tu = (passed.sec * 1000000 + passed.usec) / 1024; 411f69aa52ea2e0a73ac502565df8c666ee49cab6aDmitry Shmidt if (hapd->conf->assoc_sa_query_max_timeout > tu) 421f69aa52ea2e0a73ac502565df8c666ee49cab6aDmitry Shmidt timeout = hapd->conf->assoc_sa_query_max_timeout - tu; 431f69aa52ea2e0a73ac502565df8c666ee49cab6aDmitry Shmidt else 441f69aa52ea2e0a73ac502565df8c666ee49cab6aDmitry Shmidt timeout = 0; 451f69aa52ea2e0a73ac502565df8c666ee49cab6aDmitry Shmidt if (timeout < hapd->conf->assoc_sa_query_max_timeout) 461f69aa52ea2e0a73ac502565df8c666ee49cab6aDmitry Shmidt timeout++; /* add some extra time for local timers */ 471f69aa52ea2e0a73ac502565df8c666ee49cab6aDmitry Shmidt WPA_PUT_LE32(pos, timeout); 481f69aa52ea2e0a73ac502565df8c666ee49cab6aDmitry Shmidt pos += 4; 491f69aa52ea2e0a73ac502565df8c666ee49cab6aDmitry Shmidt 501f69aa52ea2e0a73ac502565df8c666ee49cab6aDmitry Shmidt return pos; 511f69aa52ea2e0a73ac502565df8c666ee49cab6aDmitry Shmidt} 521f69aa52ea2e0a73ac502565df8c666ee49cab6aDmitry Shmidt 531f69aa52ea2e0a73ac502565df8c666ee49cab6aDmitry Shmidt 541f69aa52ea2e0a73ac502565df8c666ee49cab6aDmitry Shmidt/* MLME-SAQuery.request */ 551f69aa52ea2e0a73ac502565df8c666ee49cab6aDmitry Shmidtvoid ieee802_11_send_sa_query_req(struct hostapd_data *hapd, 561f69aa52ea2e0a73ac502565df8c666ee49cab6aDmitry Shmidt const u8 *addr, const u8 *trans_id) 571f69aa52ea2e0a73ac502565df8c666ee49cab6aDmitry Shmidt{ 581f69aa52ea2e0a73ac502565df8c666ee49cab6aDmitry Shmidt struct ieee80211_mgmt mgmt; 591f69aa52ea2e0a73ac502565df8c666ee49cab6aDmitry Shmidt u8 *end; 601f69aa52ea2e0a73ac502565df8c666ee49cab6aDmitry Shmidt 611f69aa52ea2e0a73ac502565df8c666ee49cab6aDmitry Shmidt wpa_printf(MSG_DEBUG, "IEEE 802.11: Sending SA Query Request to " 621f69aa52ea2e0a73ac502565df8c666ee49cab6aDmitry Shmidt MACSTR, MAC2STR(addr)); 631f69aa52ea2e0a73ac502565df8c666ee49cab6aDmitry Shmidt wpa_hexdump(MSG_DEBUG, "IEEE 802.11: SA Query Transaction ID", 641f69aa52ea2e0a73ac502565df8c666ee49cab6aDmitry Shmidt trans_id, WLAN_SA_QUERY_TR_ID_LEN); 651f69aa52ea2e0a73ac502565df8c666ee49cab6aDmitry Shmidt 661f69aa52ea2e0a73ac502565df8c666ee49cab6aDmitry Shmidt os_memset(&mgmt, 0, sizeof(mgmt)); 671f69aa52ea2e0a73ac502565df8c666ee49cab6aDmitry Shmidt mgmt.frame_control = IEEE80211_FC(WLAN_FC_TYPE_MGMT, 681f69aa52ea2e0a73ac502565df8c666ee49cab6aDmitry Shmidt WLAN_FC_STYPE_ACTION); 691f69aa52ea2e0a73ac502565df8c666ee49cab6aDmitry Shmidt os_memcpy(mgmt.da, addr, ETH_ALEN); 701f69aa52ea2e0a73ac502565df8c666ee49cab6aDmitry Shmidt os_memcpy(mgmt.sa, hapd->own_addr, ETH_ALEN); 711f69aa52ea2e0a73ac502565df8c666ee49cab6aDmitry Shmidt os_memcpy(mgmt.bssid, hapd->own_addr, ETH_ALEN); 721f69aa52ea2e0a73ac502565df8c666ee49cab6aDmitry Shmidt mgmt.u.action.category = WLAN_ACTION_SA_QUERY; 731f69aa52ea2e0a73ac502565df8c666ee49cab6aDmitry Shmidt mgmt.u.action.u.sa_query_req.action = WLAN_SA_QUERY_REQUEST; 741f69aa52ea2e0a73ac502565df8c666ee49cab6aDmitry Shmidt os_memcpy(mgmt.u.action.u.sa_query_req.trans_id, trans_id, 751f69aa52ea2e0a73ac502565df8c666ee49cab6aDmitry Shmidt WLAN_SA_QUERY_TR_ID_LEN); 761f69aa52ea2e0a73ac502565df8c666ee49cab6aDmitry Shmidt end = mgmt.u.action.u.sa_query_req.trans_id + WLAN_SA_QUERY_TR_ID_LEN; 771f69aa52ea2e0a73ac502565df8c666ee49cab6aDmitry Shmidt if (hostapd_drv_send_mlme(hapd, &mgmt, end - (u8 *) &mgmt, 0) < 0) 781f69aa52ea2e0a73ac502565df8c666ee49cab6aDmitry Shmidt perror("ieee802_11_send_sa_query_req: send"); 791f69aa52ea2e0a73ac502565df8c666ee49cab6aDmitry Shmidt} 801f69aa52ea2e0a73ac502565df8c666ee49cab6aDmitry Shmidt 811f69aa52ea2e0a73ac502565df8c666ee49cab6aDmitry Shmidt 821f69aa52ea2e0a73ac502565df8c666ee49cab6aDmitry Shmidtstatic void ieee802_11_send_sa_query_resp(struct hostapd_data *hapd, 831f69aa52ea2e0a73ac502565df8c666ee49cab6aDmitry Shmidt const u8 *sa, const u8 *trans_id) 841f69aa52ea2e0a73ac502565df8c666ee49cab6aDmitry Shmidt{ 851f69aa52ea2e0a73ac502565df8c666ee49cab6aDmitry Shmidt struct sta_info *sta; 861f69aa52ea2e0a73ac502565df8c666ee49cab6aDmitry Shmidt struct ieee80211_mgmt resp; 871f69aa52ea2e0a73ac502565df8c666ee49cab6aDmitry Shmidt u8 *end; 881f69aa52ea2e0a73ac502565df8c666ee49cab6aDmitry Shmidt 891f69aa52ea2e0a73ac502565df8c666ee49cab6aDmitry Shmidt wpa_printf(MSG_DEBUG, "IEEE 802.11: Received SA Query Request from " 901f69aa52ea2e0a73ac502565df8c666ee49cab6aDmitry Shmidt MACSTR, MAC2STR(sa)); 911f69aa52ea2e0a73ac502565df8c666ee49cab6aDmitry Shmidt wpa_hexdump(MSG_DEBUG, "IEEE 802.11: SA Query Transaction ID", 921f69aa52ea2e0a73ac502565df8c666ee49cab6aDmitry Shmidt trans_id, WLAN_SA_QUERY_TR_ID_LEN); 931f69aa52ea2e0a73ac502565df8c666ee49cab6aDmitry Shmidt 941f69aa52ea2e0a73ac502565df8c666ee49cab6aDmitry Shmidt sta = ap_get_sta(hapd, sa); 951f69aa52ea2e0a73ac502565df8c666ee49cab6aDmitry Shmidt if (sta == NULL || !(sta->flags & WLAN_STA_ASSOC)) { 961f69aa52ea2e0a73ac502565df8c666ee49cab6aDmitry Shmidt wpa_printf(MSG_DEBUG, "IEEE 802.11: Ignore SA Query Request " 971f69aa52ea2e0a73ac502565df8c666ee49cab6aDmitry Shmidt "from unassociated STA " MACSTR, MAC2STR(sa)); 981f69aa52ea2e0a73ac502565df8c666ee49cab6aDmitry Shmidt return; 991f69aa52ea2e0a73ac502565df8c666ee49cab6aDmitry Shmidt } 1001f69aa52ea2e0a73ac502565df8c666ee49cab6aDmitry Shmidt 1011f69aa52ea2e0a73ac502565df8c666ee49cab6aDmitry Shmidt wpa_printf(MSG_DEBUG, "IEEE 802.11: Sending SA Query Response to " 1021f69aa52ea2e0a73ac502565df8c666ee49cab6aDmitry Shmidt MACSTR, MAC2STR(sa)); 1031f69aa52ea2e0a73ac502565df8c666ee49cab6aDmitry Shmidt 1041f69aa52ea2e0a73ac502565df8c666ee49cab6aDmitry Shmidt os_memset(&resp, 0, sizeof(resp)); 1051f69aa52ea2e0a73ac502565df8c666ee49cab6aDmitry Shmidt resp.frame_control = IEEE80211_FC(WLAN_FC_TYPE_MGMT, 1061f69aa52ea2e0a73ac502565df8c666ee49cab6aDmitry Shmidt WLAN_FC_STYPE_ACTION); 1071f69aa52ea2e0a73ac502565df8c666ee49cab6aDmitry Shmidt os_memcpy(resp.da, sa, ETH_ALEN); 1081f69aa52ea2e0a73ac502565df8c666ee49cab6aDmitry Shmidt os_memcpy(resp.sa, hapd->own_addr, ETH_ALEN); 1091f69aa52ea2e0a73ac502565df8c666ee49cab6aDmitry Shmidt os_memcpy(resp.bssid, hapd->own_addr, ETH_ALEN); 1101f69aa52ea2e0a73ac502565df8c666ee49cab6aDmitry Shmidt resp.u.action.category = WLAN_ACTION_SA_QUERY; 1111f69aa52ea2e0a73ac502565df8c666ee49cab6aDmitry Shmidt resp.u.action.u.sa_query_req.action = WLAN_SA_QUERY_RESPONSE; 1121f69aa52ea2e0a73ac502565df8c666ee49cab6aDmitry Shmidt os_memcpy(resp.u.action.u.sa_query_req.trans_id, trans_id, 1131f69aa52ea2e0a73ac502565df8c666ee49cab6aDmitry Shmidt WLAN_SA_QUERY_TR_ID_LEN); 1141f69aa52ea2e0a73ac502565df8c666ee49cab6aDmitry Shmidt end = resp.u.action.u.sa_query_req.trans_id + WLAN_SA_QUERY_TR_ID_LEN; 1151f69aa52ea2e0a73ac502565df8c666ee49cab6aDmitry Shmidt if (hostapd_drv_send_mlme(hapd, &resp, end - (u8 *) &resp, 0) < 0) 1161f69aa52ea2e0a73ac502565df8c666ee49cab6aDmitry Shmidt perror("ieee80211_mgmt_sa_query_request: send"); 1171f69aa52ea2e0a73ac502565df8c666ee49cab6aDmitry Shmidt} 1181f69aa52ea2e0a73ac502565df8c666ee49cab6aDmitry Shmidt 1191f69aa52ea2e0a73ac502565df8c666ee49cab6aDmitry Shmidt 1201f69aa52ea2e0a73ac502565df8c666ee49cab6aDmitry Shmidtvoid ieee802_11_sa_query_action(struct hostapd_data *hapd, const u8 *sa, 1211f69aa52ea2e0a73ac502565df8c666ee49cab6aDmitry Shmidt const u8 action_type, const u8 *trans_id) 1221f69aa52ea2e0a73ac502565df8c666ee49cab6aDmitry Shmidt{ 1231f69aa52ea2e0a73ac502565df8c666ee49cab6aDmitry Shmidt struct sta_info *sta; 1241f69aa52ea2e0a73ac502565df8c666ee49cab6aDmitry Shmidt int i; 1251f69aa52ea2e0a73ac502565df8c666ee49cab6aDmitry Shmidt 1261f69aa52ea2e0a73ac502565df8c666ee49cab6aDmitry Shmidt if (action_type == WLAN_SA_QUERY_REQUEST) { 1271f69aa52ea2e0a73ac502565df8c666ee49cab6aDmitry Shmidt ieee802_11_send_sa_query_resp(hapd, sa, trans_id); 1281f69aa52ea2e0a73ac502565df8c666ee49cab6aDmitry Shmidt return; 1291f69aa52ea2e0a73ac502565df8c666ee49cab6aDmitry Shmidt } 1301f69aa52ea2e0a73ac502565df8c666ee49cab6aDmitry Shmidt 1311f69aa52ea2e0a73ac502565df8c666ee49cab6aDmitry Shmidt if (action_type != WLAN_SA_QUERY_RESPONSE) { 1321f69aa52ea2e0a73ac502565df8c666ee49cab6aDmitry Shmidt wpa_printf(MSG_DEBUG, "IEEE 802.11: Unexpected SA Query " 1331f69aa52ea2e0a73ac502565df8c666ee49cab6aDmitry Shmidt "Action %d", action_type); 1341f69aa52ea2e0a73ac502565df8c666ee49cab6aDmitry Shmidt return; 1351f69aa52ea2e0a73ac502565df8c666ee49cab6aDmitry Shmidt } 1361f69aa52ea2e0a73ac502565df8c666ee49cab6aDmitry Shmidt 1371f69aa52ea2e0a73ac502565df8c666ee49cab6aDmitry Shmidt wpa_printf(MSG_DEBUG, "IEEE 802.11: Received SA Query Response from " 1381f69aa52ea2e0a73ac502565df8c666ee49cab6aDmitry Shmidt MACSTR, MAC2STR(sa)); 1391f69aa52ea2e0a73ac502565df8c666ee49cab6aDmitry Shmidt wpa_hexdump(MSG_DEBUG, "IEEE 802.11: SA Query Transaction ID", 1401f69aa52ea2e0a73ac502565df8c666ee49cab6aDmitry Shmidt trans_id, WLAN_SA_QUERY_TR_ID_LEN); 1411f69aa52ea2e0a73ac502565df8c666ee49cab6aDmitry Shmidt 1421f69aa52ea2e0a73ac502565df8c666ee49cab6aDmitry Shmidt /* MLME-SAQuery.confirm */ 1431f69aa52ea2e0a73ac502565df8c666ee49cab6aDmitry Shmidt 1441f69aa52ea2e0a73ac502565df8c666ee49cab6aDmitry Shmidt sta = ap_get_sta(hapd, sa); 1451f69aa52ea2e0a73ac502565df8c666ee49cab6aDmitry Shmidt if (sta == NULL || sta->sa_query_trans_id == NULL) { 1461f69aa52ea2e0a73ac502565df8c666ee49cab6aDmitry Shmidt wpa_printf(MSG_DEBUG, "IEEE 802.11: No matching STA with " 1471f69aa52ea2e0a73ac502565df8c666ee49cab6aDmitry Shmidt "pending SA Query request found"); 1481f69aa52ea2e0a73ac502565df8c666ee49cab6aDmitry Shmidt return; 1491f69aa52ea2e0a73ac502565df8c666ee49cab6aDmitry Shmidt } 1501f69aa52ea2e0a73ac502565df8c666ee49cab6aDmitry Shmidt 1511f69aa52ea2e0a73ac502565df8c666ee49cab6aDmitry Shmidt for (i = 0; i < sta->sa_query_count; i++) { 1521f69aa52ea2e0a73ac502565df8c666ee49cab6aDmitry Shmidt if (os_memcmp(sta->sa_query_trans_id + 1531f69aa52ea2e0a73ac502565df8c666ee49cab6aDmitry Shmidt i * WLAN_SA_QUERY_TR_ID_LEN, 1541f69aa52ea2e0a73ac502565df8c666ee49cab6aDmitry Shmidt trans_id, WLAN_SA_QUERY_TR_ID_LEN) == 0) 1551f69aa52ea2e0a73ac502565df8c666ee49cab6aDmitry Shmidt break; 1561f69aa52ea2e0a73ac502565df8c666ee49cab6aDmitry Shmidt } 1571f69aa52ea2e0a73ac502565df8c666ee49cab6aDmitry Shmidt 1581f69aa52ea2e0a73ac502565df8c666ee49cab6aDmitry Shmidt if (i >= sta->sa_query_count) { 1591f69aa52ea2e0a73ac502565df8c666ee49cab6aDmitry Shmidt wpa_printf(MSG_DEBUG, "IEEE 802.11: No matching SA Query " 1601f69aa52ea2e0a73ac502565df8c666ee49cab6aDmitry Shmidt "transaction identifier found"); 1611f69aa52ea2e0a73ac502565df8c666ee49cab6aDmitry Shmidt return; 1621f69aa52ea2e0a73ac502565df8c666ee49cab6aDmitry Shmidt } 1631f69aa52ea2e0a73ac502565df8c666ee49cab6aDmitry Shmidt 1641f69aa52ea2e0a73ac502565df8c666ee49cab6aDmitry Shmidt hostapd_logger(hapd, sta->addr, HOSTAPD_MODULE_IEEE80211, 1651f69aa52ea2e0a73ac502565df8c666ee49cab6aDmitry Shmidt HOSTAPD_LEVEL_DEBUG, 1661f69aa52ea2e0a73ac502565df8c666ee49cab6aDmitry Shmidt "Reply to pending SA Query received"); 1671f69aa52ea2e0a73ac502565df8c666ee49cab6aDmitry Shmidt ap_sta_stop_sa_query(hapd, sta); 1681f69aa52ea2e0a73ac502565df8c666ee49cab6aDmitry Shmidt} 1691f69aa52ea2e0a73ac502565df8c666ee49cab6aDmitry Shmidt 1701f69aa52ea2e0a73ac502565df8c666ee49cab6aDmitry Shmidt#endif /* CONFIG_IEEE80211W */ 1711f69aa52ea2e0a73ac502565df8c666ee49cab6aDmitry Shmidt 1721f69aa52ea2e0a73ac502565df8c666ee49cab6aDmitry Shmidt 1731f69aa52ea2e0a73ac502565df8c666ee49cab6aDmitry Shmidtu8 * hostapd_eid_ext_capab(struct hostapd_data *hapd, u8 *eid) 1741f69aa52ea2e0a73ac502565df8c666ee49cab6aDmitry Shmidt{ 1751f69aa52ea2e0a73ac502565df8c666ee49cab6aDmitry Shmidt u8 *pos = eid; 1761f69aa52ea2e0a73ac502565df8c666ee49cab6aDmitry Shmidt u8 len = 0; 1771f69aa52ea2e0a73ac502565df8c666ee49cab6aDmitry Shmidt 1781f69aa52ea2e0a73ac502565df8c666ee49cab6aDmitry Shmidt if (hapd->conf->tdls & (TDLS_PROHIBIT | TDLS_PROHIBIT_CHAN_SWITCH)) 1791f69aa52ea2e0a73ac502565df8c666ee49cab6aDmitry Shmidt len = 5; 1801f69aa52ea2e0a73ac502565df8c666ee49cab6aDmitry Shmidt if (len < 4 && hapd->conf->interworking) 1811f69aa52ea2e0a73ac502565df8c666ee49cab6aDmitry Shmidt len = 4; 1821f69aa52ea2e0a73ac502565df8c666ee49cab6aDmitry Shmidt if (len == 0) 1831f69aa52ea2e0a73ac502565df8c666ee49cab6aDmitry Shmidt return eid; 1841f69aa52ea2e0a73ac502565df8c666ee49cab6aDmitry Shmidt 1851f69aa52ea2e0a73ac502565df8c666ee49cab6aDmitry Shmidt *pos++ = WLAN_EID_EXT_CAPAB; 1861f69aa52ea2e0a73ac502565df8c666ee49cab6aDmitry Shmidt *pos++ = len; 1871f69aa52ea2e0a73ac502565df8c666ee49cab6aDmitry Shmidt *pos++ = 0x00; 1881f69aa52ea2e0a73ac502565df8c666ee49cab6aDmitry Shmidt *pos++ = 0x00; 1891f69aa52ea2e0a73ac502565df8c666ee49cab6aDmitry Shmidt *pos++ = 0x00; 1901f69aa52ea2e0a73ac502565df8c666ee49cab6aDmitry Shmidt 1911f69aa52ea2e0a73ac502565df8c666ee49cab6aDmitry Shmidt *pos = 0x00; 1921f69aa52ea2e0a73ac502565df8c666ee49cab6aDmitry Shmidt if (hapd->conf->time_advertisement == 2) 1931f69aa52ea2e0a73ac502565df8c666ee49cab6aDmitry Shmidt *pos |= 0x08; /* Bit 27 - UTC TSF Offset */ 1941f69aa52ea2e0a73ac502565df8c666ee49cab6aDmitry Shmidt if (hapd->conf->interworking) 1951f69aa52ea2e0a73ac502565df8c666ee49cab6aDmitry Shmidt *pos |= 0x80; /* Bit 31 - Interworking */ 1961f69aa52ea2e0a73ac502565df8c666ee49cab6aDmitry Shmidt pos++; 1971f69aa52ea2e0a73ac502565df8c666ee49cab6aDmitry Shmidt 1981f69aa52ea2e0a73ac502565df8c666ee49cab6aDmitry Shmidt if (len < 5) 1991f69aa52ea2e0a73ac502565df8c666ee49cab6aDmitry Shmidt return pos; 2001f69aa52ea2e0a73ac502565df8c666ee49cab6aDmitry Shmidt *pos = 0x00; 2011f69aa52ea2e0a73ac502565df8c666ee49cab6aDmitry Shmidt if (hapd->conf->tdls & TDLS_PROHIBIT) 2021f69aa52ea2e0a73ac502565df8c666ee49cab6aDmitry Shmidt *pos |= 0x40; /* Bit 38 - TDLS Prohibited */ 2031f69aa52ea2e0a73ac502565df8c666ee49cab6aDmitry Shmidt if (hapd->conf->tdls & TDLS_PROHIBIT_CHAN_SWITCH) 2041f69aa52ea2e0a73ac502565df8c666ee49cab6aDmitry Shmidt *pos |= 0x80; /* Bit 39 - TDLS Channel Switching Prohibited */ 2051f69aa52ea2e0a73ac502565df8c666ee49cab6aDmitry Shmidt pos++; 2061f69aa52ea2e0a73ac502565df8c666ee49cab6aDmitry Shmidt 2071f69aa52ea2e0a73ac502565df8c666ee49cab6aDmitry Shmidt return pos; 2081f69aa52ea2e0a73ac502565df8c666ee49cab6aDmitry Shmidt} 2091f69aa52ea2e0a73ac502565df8c666ee49cab6aDmitry Shmidt 2101f69aa52ea2e0a73ac502565df8c666ee49cab6aDmitry Shmidt 2111f69aa52ea2e0a73ac502565df8c666ee49cab6aDmitry Shmidtu8 * hostapd_eid_interworking(struct hostapd_data *hapd, u8 *eid) 2121f69aa52ea2e0a73ac502565df8c666ee49cab6aDmitry Shmidt{ 2131f69aa52ea2e0a73ac502565df8c666ee49cab6aDmitry Shmidt u8 *pos = eid; 2141f69aa52ea2e0a73ac502565df8c666ee49cab6aDmitry Shmidt#ifdef CONFIG_INTERWORKING 2151f69aa52ea2e0a73ac502565df8c666ee49cab6aDmitry Shmidt u8 *len; 2161f69aa52ea2e0a73ac502565df8c666ee49cab6aDmitry Shmidt 2171f69aa52ea2e0a73ac502565df8c666ee49cab6aDmitry Shmidt if (!hapd->conf->interworking) 2181f69aa52ea2e0a73ac502565df8c666ee49cab6aDmitry Shmidt return eid; 2191f69aa52ea2e0a73ac502565df8c666ee49cab6aDmitry Shmidt 2201f69aa52ea2e0a73ac502565df8c666ee49cab6aDmitry Shmidt *pos++ = WLAN_EID_INTERWORKING; 2211f69aa52ea2e0a73ac502565df8c666ee49cab6aDmitry Shmidt len = pos++; 2221f69aa52ea2e0a73ac502565df8c666ee49cab6aDmitry Shmidt 2231f69aa52ea2e0a73ac502565df8c666ee49cab6aDmitry Shmidt *pos = hapd->conf->access_network_type; 2241f69aa52ea2e0a73ac502565df8c666ee49cab6aDmitry Shmidt if (hapd->conf->internet) 2251f69aa52ea2e0a73ac502565df8c666ee49cab6aDmitry Shmidt *pos |= INTERWORKING_ANO_INTERNET; 2261f69aa52ea2e0a73ac502565df8c666ee49cab6aDmitry Shmidt if (hapd->conf->asra) 2271f69aa52ea2e0a73ac502565df8c666ee49cab6aDmitry Shmidt *pos |= INTERWORKING_ANO_ASRA; 2281f69aa52ea2e0a73ac502565df8c666ee49cab6aDmitry Shmidt if (hapd->conf->esr) 2291f69aa52ea2e0a73ac502565df8c666ee49cab6aDmitry Shmidt *pos |= INTERWORKING_ANO_ESR; 2301f69aa52ea2e0a73ac502565df8c666ee49cab6aDmitry Shmidt if (hapd->conf->uesa) 2311f69aa52ea2e0a73ac502565df8c666ee49cab6aDmitry Shmidt *pos |= INTERWORKING_ANO_UESA; 2321f69aa52ea2e0a73ac502565df8c666ee49cab6aDmitry Shmidt pos++; 2331f69aa52ea2e0a73ac502565df8c666ee49cab6aDmitry Shmidt 2341f69aa52ea2e0a73ac502565df8c666ee49cab6aDmitry Shmidt if (hapd->conf->venue_info_set) { 2351f69aa52ea2e0a73ac502565df8c666ee49cab6aDmitry Shmidt *pos++ = hapd->conf->venue_group; 2361f69aa52ea2e0a73ac502565df8c666ee49cab6aDmitry Shmidt *pos++ = hapd->conf->venue_type; 2371f69aa52ea2e0a73ac502565df8c666ee49cab6aDmitry Shmidt } 2381f69aa52ea2e0a73ac502565df8c666ee49cab6aDmitry Shmidt 2391f69aa52ea2e0a73ac502565df8c666ee49cab6aDmitry Shmidt if (!is_zero_ether_addr(hapd->conf->hessid)) { 2401f69aa52ea2e0a73ac502565df8c666ee49cab6aDmitry Shmidt os_memcpy(pos, hapd->conf->hessid, ETH_ALEN); 2411f69aa52ea2e0a73ac502565df8c666ee49cab6aDmitry Shmidt pos += ETH_ALEN; 2421f69aa52ea2e0a73ac502565df8c666ee49cab6aDmitry Shmidt } 2431f69aa52ea2e0a73ac502565df8c666ee49cab6aDmitry Shmidt 2441f69aa52ea2e0a73ac502565df8c666ee49cab6aDmitry Shmidt *len = pos - len - 1; 2451f69aa52ea2e0a73ac502565df8c666ee49cab6aDmitry Shmidt#endif /* CONFIG_INTERWORKING */ 2461f69aa52ea2e0a73ac502565df8c666ee49cab6aDmitry Shmidt 2471f69aa52ea2e0a73ac502565df8c666ee49cab6aDmitry Shmidt return pos; 2481f69aa52ea2e0a73ac502565df8c666ee49cab6aDmitry Shmidt} 2491f69aa52ea2e0a73ac502565df8c666ee49cab6aDmitry Shmidt 2501f69aa52ea2e0a73ac502565df8c666ee49cab6aDmitry Shmidt 2511f69aa52ea2e0a73ac502565df8c666ee49cab6aDmitry Shmidtu8 * hostapd_eid_adv_proto(struct hostapd_data *hapd, u8 *eid) 2521f69aa52ea2e0a73ac502565df8c666ee49cab6aDmitry Shmidt{ 2531f69aa52ea2e0a73ac502565df8c666ee49cab6aDmitry Shmidt u8 *pos = eid; 2541f69aa52ea2e0a73ac502565df8c666ee49cab6aDmitry Shmidt#ifdef CONFIG_INTERWORKING 2551f69aa52ea2e0a73ac502565df8c666ee49cab6aDmitry Shmidt 2561f69aa52ea2e0a73ac502565df8c666ee49cab6aDmitry Shmidt /* TODO: Separate configuration for ANQP? */ 2571f69aa52ea2e0a73ac502565df8c666ee49cab6aDmitry Shmidt if (!hapd->conf->interworking) 2581f69aa52ea2e0a73ac502565df8c666ee49cab6aDmitry Shmidt return eid; 2591f69aa52ea2e0a73ac502565df8c666ee49cab6aDmitry Shmidt 2601f69aa52ea2e0a73ac502565df8c666ee49cab6aDmitry Shmidt *pos++ = WLAN_EID_ADV_PROTO; 2611f69aa52ea2e0a73ac502565df8c666ee49cab6aDmitry Shmidt *pos++ = 2; 2621f69aa52ea2e0a73ac502565df8c666ee49cab6aDmitry Shmidt *pos++ = 0x7F; /* Query Response Length Limit | PAME-BI */ 2631f69aa52ea2e0a73ac502565df8c666ee49cab6aDmitry Shmidt *pos++ = ACCESS_NETWORK_QUERY_PROTOCOL; 2641f69aa52ea2e0a73ac502565df8c666ee49cab6aDmitry Shmidt#endif /* CONFIG_INTERWORKING */ 2651f69aa52ea2e0a73ac502565df8c666ee49cab6aDmitry Shmidt 2661f69aa52ea2e0a73ac502565df8c666ee49cab6aDmitry Shmidt return pos; 2671f69aa52ea2e0a73ac502565df8c666ee49cab6aDmitry Shmidt} 2681f69aa52ea2e0a73ac502565df8c666ee49cab6aDmitry Shmidt 2691f69aa52ea2e0a73ac502565df8c666ee49cab6aDmitry Shmidt 2701f69aa52ea2e0a73ac502565df8c666ee49cab6aDmitry Shmidtu8 * hostapd_eid_roaming_consortium(struct hostapd_data *hapd, u8 *eid) 2711f69aa52ea2e0a73ac502565df8c666ee49cab6aDmitry Shmidt{ 2721f69aa52ea2e0a73ac502565df8c666ee49cab6aDmitry Shmidt u8 *pos = eid; 2731f69aa52ea2e0a73ac502565df8c666ee49cab6aDmitry Shmidt#ifdef CONFIG_INTERWORKING 2741f69aa52ea2e0a73ac502565df8c666ee49cab6aDmitry Shmidt u8 *len; 2751f69aa52ea2e0a73ac502565df8c666ee49cab6aDmitry Shmidt unsigned int i, count; 2761f69aa52ea2e0a73ac502565df8c666ee49cab6aDmitry Shmidt 2771f69aa52ea2e0a73ac502565df8c666ee49cab6aDmitry Shmidt if (!hapd->conf->interworking || 2781f69aa52ea2e0a73ac502565df8c666ee49cab6aDmitry Shmidt hapd->conf->roaming_consortium == NULL || 2791f69aa52ea2e0a73ac502565df8c666ee49cab6aDmitry Shmidt hapd->conf->roaming_consortium_count == 0) 2801f69aa52ea2e0a73ac502565df8c666ee49cab6aDmitry Shmidt return eid; 2811f69aa52ea2e0a73ac502565df8c666ee49cab6aDmitry Shmidt 2821f69aa52ea2e0a73ac502565df8c666ee49cab6aDmitry Shmidt *pos++ = WLAN_EID_ROAMING_CONSORTIUM; 2831f69aa52ea2e0a73ac502565df8c666ee49cab6aDmitry Shmidt len = pos++; 2841f69aa52ea2e0a73ac502565df8c666ee49cab6aDmitry Shmidt 2851f69aa52ea2e0a73ac502565df8c666ee49cab6aDmitry Shmidt /* Number of ANQP OIs (in addition to the max 3 listed here) */ 2861f69aa52ea2e0a73ac502565df8c666ee49cab6aDmitry Shmidt if (hapd->conf->roaming_consortium_count > 3 + 255) 2871f69aa52ea2e0a73ac502565df8c666ee49cab6aDmitry Shmidt *pos++ = 255; 2881f69aa52ea2e0a73ac502565df8c666ee49cab6aDmitry Shmidt else if (hapd->conf->roaming_consortium_count > 3) 2891f69aa52ea2e0a73ac502565df8c666ee49cab6aDmitry Shmidt *pos++ = hapd->conf->roaming_consortium_count - 3; 2901f69aa52ea2e0a73ac502565df8c666ee49cab6aDmitry Shmidt else 2911f69aa52ea2e0a73ac502565df8c666ee49cab6aDmitry Shmidt *pos++ = 0; 2921f69aa52ea2e0a73ac502565df8c666ee49cab6aDmitry Shmidt 2931f69aa52ea2e0a73ac502565df8c666ee49cab6aDmitry Shmidt /* OU #1 and #2 Lengths */ 2941f69aa52ea2e0a73ac502565df8c666ee49cab6aDmitry Shmidt *pos = hapd->conf->roaming_consortium[0].len; 2951f69aa52ea2e0a73ac502565df8c666ee49cab6aDmitry Shmidt if (hapd->conf->roaming_consortium_count > 1) 2961f69aa52ea2e0a73ac502565df8c666ee49cab6aDmitry Shmidt *pos |= hapd->conf->roaming_consortium[1].len << 4; 2971f69aa52ea2e0a73ac502565df8c666ee49cab6aDmitry Shmidt pos++; 2981f69aa52ea2e0a73ac502565df8c666ee49cab6aDmitry Shmidt 2991f69aa52ea2e0a73ac502565df8c666ee49cab6aDmitry Shmidt if (hapd->conf->roaming_consortium_count > 3) 3001f69aa52ea2e0a73ac502565df8c666ee49cab6aDmitry Shmidt count = 3; 3011f69aa52ea2e0a73ac502565df8c666ee49cab6aDmitry Shmidt else 3021f69aa52ea2e0a73ac502565df8c666ee49cab6aDmitry Shmidt count = hapd->conf->roaming_consortium_count; 3031f69aa52ea2e0a73ac502565df8c666ee49cab6aDmitry Shmidt 3041f69aa52ea2e0a73ac502565df8c666ee49cab6aDmitry Shmidt for (i = 0; i < count; i++) { 3051f69aa52ea2e0a73ac502565df8c666ee49cab6aDmitry Shmidt os_memcpy(pos, hapd->conf->roaming_consortium[i].oi, 3061f69aa52ea2e0a73ac502565df8c666ee49cab6aDmitry Shmidt hapd->conf->roaming_consortium[i].len); 3071f69aa52ea2e0a73ac502565df8c666ee49cab6aDmitry Shmidt pos += hapd->conf->roaming_consortium[i].len; 3081f69aa52ea2e0a73ac502565df8c666ee49cab6aDmitry Shmidt } 3091f69aa52ea2e0a73ac502565df8c666ee49cab6aDmitry Shmidt 3101f69aa52ea2e0a73ac502565df8c666ee49cab6aDmitry Shmidt *len = pos - len - 1; 3111f69aa52ea2e0a73ac502565df8c666ee49cab6aDmitry Shmidt#endif /* CONFIG_INTERWORKING */ 3121f69aa52ea2e0a73ac502565df8c666ee49cab6aDmitry Shmidt 3131f69aa52ea2e0a73ac502565df8c666ee49cab6aDmitry Shmidt return pos; 3141f69aa52ea2e0a73ac502565df8c666ee49cab6aDmitry Shmidt} 3151f69aa52ea2e0a73ac502565df8c666ee49cab6aDmitry Shmidt 3161f69aa52ea2e0a73ac502565df8c666ee49cab6aDmitry Shmidt 3171f69aa52ea2e0a73ac502565df8c666ee49cab6aDmitry Shmidtu8 * hostapd_eid_time_adv(struct hostapd_data *hapd, u8 *eid) 3181f69aa52ea2e0a73ac502565df8c666ee49cab6aDmitry Shmidt{ 3191f69aa52ea2e0a73ac502565df8c666ee49cab6aDmitry Shmidt if (hapd->conf->time_advertisement != 2) 3201f69aa52ea2e0a73ac502565df8c666ee49cab6aDmitry Shmidt return eid; 3211f69aa52ea2e0a73ac502565df8c666ee49cab6aDmitry Shmidt 3221f69aa52ea2e0a73ac502565df8c666ee49cab6aDmitry Shmidt if (hapd->time_adv == NULL && 3231f69aa52ea2e0a73ac502565df8c666ee49cab6aDmitry Shmidt hostapd_update_time_adv(hapd) < 0) 3241f69aa52ea2e0a73ac502565df8c666ee49cab6aDmitry Shmidt return eid; 3251f69aa52ea2e0a73ac502565df8c666ee49cab6aDmitry Shmidt 3261f69aa52ea2e0a73ac502565df8c666ee49cab6aDmitry Shmidt if (hapd->time_adv == NULL) 3271f69aa52ea2e0a73ac502565df8c666ee49cab6aDmitry Shmidt return eid; 3281f69aa52ea2e0a73ac502565df8c666ee49cab6aDmitry Shmidt 3291f69aa52ea2e0a73ac502565df8c666ee49cab6aDmitry Shmidt os_memcpy(eid, wpabuf_head(hapd->time_adv), 3301f69aa52ea2e0a73ac502565df8c666ee49cab6aDmitry Shmidt wpabuf_len(hapd->time_adv)); 3311f69aa52ea2e0a73ac502565df8c666ee49cab6aDmitry Shmidt eid += wpabuf_len(hapd->time_adv); 3321f69aa52ea2e0a73ac502565df8c666ee49cab6aDmitry Shmidt 3331f69aa52ea2e0a73ac502565df8c666ee49cab6aDmitry Shmidt return eid; 3341f69aa52ea2e0a73ac502565df8c666ee49cab6aDmitry Shmidt} 3351f69aa52ea2e0a73ac502565df8c666ee49cab6aDmitry Shmidt 3361f69aa52ea2e0a73ac502565df8c666ee49cab6aDmitry Shmidt 3371f69aa52ea2e0a73ac502565df8c666ee49cab6aDmitry Shmidtu8 * hostapd_eid_time_zone(struct hostapd_data *hapd, u8 *eid) 3381f69aa52ea2e0a73ac502565df8c666ee49cab6aDmitry Shmidt{ 3391f69aa52ea2e0a73ac502565df8c666ee49cab6aDmitry Shmidt size_t len; 3401f69aa52ea2e0a73ac502565df8c666ee49cab6aDmitry Shmidt 3411f69aa52ea2e0a73ac502565df8c666ee49cab6aDmitry Shmidt if (hapd->conf->time_advertisement != 2) 3421f69aa52ea2e0a73ac502565df8c666ee49cab6aDmitry Shmidt return eid; 3431f69aa52ea2e0a73ac502565df8c666ee49cab6aDmitry Shmidt 3441f69aa52ea2e0a73ac502565df8c666ee49cab6aDmitry Shmidt len = os_strlen(hapd->conf->time_zone); 3451f69aa52ea2e0a73ac502565df8c666ee49cab6aDmitry Shmidt 3461f69aa52ea2e0a73ac502565df8c666ee49cab6aDmitry Shmidt *eid++ = WLAN_EID_TIME_ZONE; 3471f69aa52ea2e0a73ac502565df8c666ee49cab6aDmitry Shmidt *eid++ = len; 3481f69aa52ea2e0a73ac502565df8c666ee49cab6aDmitry Shmidt os_memcpy(eid, hapd->conf->time_zone, len); 3491f69aa52ea2e0a73ac502565df8c666ee49cab6aDmitry Shmidt eid += len; 3501f69aa52ea2e0a73ac502565df8c666ee49cab6aDmitry Shmidt 3511f69aa52ea2e0a73ac502565df8c666ee49cab6aDmitry Shmidt return eid; 3521f69aa52ea2e0a73ac502565df8c666ee49cab6aDmitry Shmidt} 3531f69aa52ea2e0a73ac502565df8c666ee49cab6aDmitry Shmidt 3541f69aa52ea2e0a73ac502565df8c666ee49cab6aDmitry Shmidt 3551f69aa52ea2e0a73ac502565df8c666ee49cab6aDmitry Shmidtint hostapd_update_time_adv(struct hostapd_data *hapd) 3561f69aa52ea2e0a73ac502565df8c666ee49cab6aDmitry Shmidt{ 3571f69aa52ea2e0a73ac502565df8c666ee49cab6aDmitry Shmidt const int elen = 2 + 1 + 10 + 5 + 1; 3581f69aa52ea2e0a73ac502565df8c666ee49cab6aDmitry Shmidt struct os_time t; 3591f69aa52ea2e0a73ac502565df8c666ee49cab6aDmitry Shmidt struct os_tm tm; 3601f69aa52ea2e0a73ac502565df8c666ee49cab6aDmitry Shmidt u8 *pos; 3611f69aa52ea2e0a73ac502565df8c666ee49cab6aDmitry Shmidt 3621f69aa52ea2e0a73ac502565df8c666ee49cab6aDmitry Shmidt if (hapd->conf->time_advertisement != 2) 3631f69aa52ea2e0a73ac502565df8c666ee49cab6aDmitry Shmidt return 0; 3641f69aa52ea2e0a73ac502565df8c666ee49cab6aDmitry Shmidt 3651f69aa52ea2e0a73ac502565df8c666ee49cab6aDmitry Shmidt if (os_get_time(&t) < 0 || os_gmtime(t.sec, &tm) < 0) 3661f69aa52ea2e0a73ac502565df8c666ee49cab6aDmitry Shmidt return -1; 3671f69aa52ea2e0a73ac502565df8c666ee49cab6aDmitry Shmidt 3681f69aa52ea2e0a73ac502565df8c666ee49cab6aDmitry Shmidt if (!hapd->time_adv) { 3691f69aa52ea2e0a73ac502565df8c666ee49cab6aDmitry Shmidt hapd->time_adv = wpabuf_alloc(elen); 3701f69aa52ea2e0a73ac502565df8c666ee49cab6aDmitry Shmidt if (hapd->time_adv == NULL) 3711f69aa52ea2e0a73ac502565df8c666ee49cab6aDmitry Shmidt return -1; 3721f69aa52ea2e0a73ac502565df8c666ee49cab6aDmitry Shmidt pos = wpabuf_put(hapd->time_adv, elen); 3731f69aa52ea2e0a73ac502565df8c666ee49cab6aDmitry Shmidt } else 3741f69aa52ea2e0a73ac502565df8c666ee49cab6aDmitry Shmidt pos = wpabuf_mhead_u8(hapd->time_adv); 3751f69aa52ea2e0a73ac502565df8c666ee49cab6aDmitry Shmidt 3761f69aa52ea2e0a73ac502565df8c666ee49cab6aDmitry Shmidt *pos++ = WLAN_EID_TIME_ADVERTISEMENT; 3771f69aa52ea2e0a73ac502565df8c666ee49cab6aDmitry Shmidt *pos++ = 1 + 10 + 5 + 1; 3781f69aa52ea2e0a73ac502565df8c666ee49cab6aDmitry Shmidt 3791f69aa52ea2e0a73ac502565df8c666ee49cab6aDmitry Shmidt *pos++ = 2; /* UTC time at which the TSF timer is 0 */ 3801f69aa52ea2e0a73ac502565df8c666ee49cab6aDmitry Shmidt 3811f69aa52ea2e0a73ac502565df8c666ee49cab6aDmitry Shmidt /* Time Value at TSF 0 */ 3821f69aa52ea2e0a73ac502565df8c666ee49cab6aDmitry Shmidt /* FIX: need to calculate this based on the current TSF value */ 3831f69aa52ea2e0a73ac502565df8c666ee49cab6aDmitry Shmidt WPA_PUT_LE16(pos, tm.year); /* Year */ 3841f69aa52ea2e0a73ac502565df8c666ee49cab6aDmitry Shmidt pos += 2; 3851f69aa52ea2e0a73ac502565df8c666ee49cab6aDmitry Shmidt *pos++ = tm.month; /* Month */ 3861f69aa52ea2e0a73ac502565df8c666ee49cab6aDmitry Shmidt *pos++ = tm.day; /* Day of month */ 3871f69aa52ea2e0a73ac502565df8c666ee49cab6aDmitry Shmidt *pos++ = tm.hour; /* Hours */ 3881f69aa52ea2e0a73ac502565df8c666ee49cab6aDmitry Shmidt *pos++ = tm.min; /* Minutes */ 3891f69aa52ea2e0a73ac502565df8c666ee49cab6aDmitry Shmidt *pos++ = tm.sec; /* Seconds */ 3901f69aa52ea2e0a73ac502565df8c666ee49cab6aDmitry Shmidt WPA_PUT_LE16(pos, 0); /* Milliseconds (not used) */ 3911f69aa52ea2e0a73ac502565df8c666ee49cab6aDmitry Shmidt pos += 2; 3921f69aa52ea2e0a73ac502565df8c666ee49cab6aDmitry Shmidt *pos++ = 0; /* Reserved */ 3931f69aa52ea2e0a73ac502565df8c666ee49cab6aDmitry Shmidt 3941f69aa52ea2e0a73ac502565df8c666ee49cab6aDmitry Shmidt /* Time Error */ 3951f69aa52ea2e0a73ac502565df8c666ee49cab6aDmitry Shmidt /* TODO: fill in an estimate on the error */ 3961f69aa52ea2e0a73ac502565df8c666ee49cab6aDmitry Shmidt *pos++ = 0; 3971f69aa52ea2e0a73ac502565df8c666ee49cab6aDmitry Shmidt *pos++ = 0; 3981f69aa52ea2e0a73ac502565df8c666ee49cab6aDmitry Shmidt *pos++ = 0; 3991f69aa52ea2e0a73ac502565df8c666ee49cab6aDmitry Shmidt *pos++ = 0; 4001f69aa52ea2e0a73ac502565df8c666ee49cab6aDmitry Shmidt *pos++ = 0; 4011f69aa52ea2e0a73ac502565df8c666ee49cab6aDmitry Shmidt 4021f69aa52ea2e0a73ac502565df8c666ee49cab6aDmitry Shmidt *pos++ = hapd->time_update_counter++; 4031f69aa52ea2e0a73ac502565df8c666ee49cab6aDmitry Shmidt 4041f69aa52ea2e0a73ac502565df8c666ee49cab6aDmitry Shmidt return 0; 4051f69aa52ea2e0a73ac502565df8c666ee49cab6aDmitry Shmidt} 406