Import wpa_supplicant / hostapd 2.0.
2013-01-12 - v2.0 * added AP-STA-DISCONNECTED ctrl_iface event * improved debug logging (human readable event names, interface name included in more entries) * added number of small changes to make it easier for static analyzers to understand the implementation * added a workaround for Windows 7 Michael MIC failure reporting and use of the Secure bit in EAPOL-Key msg 3/4 * fixed number of small bugs (see git logs for more details) * changed OpenSSL to read full certificate chain from server_cert file * nl80211: number of updates to use new cfg80211/nl80211 functionality - replace monitor interface with nl80211 commands - additional information for driver-based AP SME * EAP-pwd: - fix KDF for group 21 and zero-padding - added support for fragmentation - increased maximum number of hunting-and-pecking iterations * avoid excessive Probe Response retries for broadcast Probe Request frames (only with drivers using hostapd SME/MLME) * added preliminary support for using TLS v1.2 (CONFIG_TLSV12=y) * fixed WPS operation stopping on dual concurrent AP * added wps_rf_bands configuration parameter for overriding RF Bands value for WPS * added support for getting per-device PSK from RADIUS Tunnel-Password * added support for libnl 3.2 and newer * increased initial group key handshake retransmit timeout to 500 ms * added a workaround for 4-way handshake to update SNonce even after having sent EAPOL-Key 3/4 to avoid issues with some supplicant implementations that can change SNonce for each EAP-Key 2/4 * added a workaround for EAPOL-Key 4/4 using incorrect type value in WPA2 mode (some deployed stations use WPA type in that message) * added a WPS workaround for mixed mode AP Settings with Windows 7 * changed WPS AP PIN disabling mechanism to disable the PIN after 10 consecutive failures in addition to using the exponential lockout period * added support for WFA Hotspot 2.0 - GAS/ANQP advertisement of network information - disable_dgaf parameter to disable downstream group-addressed forwarding * simplified licensing terms by selecting the BSD license as the only alternative * EAP-SIM: fixed re-authentication not to update pseudonym * EAP-SIM: use Notification round before EAP-Failure * EAP-AKA: added support for AT_COUNTER_TOO_SMALL * EAP-AKA: skip AKA/Identity exchange if EAP identity is recognized * EAP-AKA': fixed identity for MK derivation * EAP-AKA': updated to RFC 5448 (username prefixes changed); note: this breaks interoperability with older versions * EAP-SIM/AKA: allow pseudonym to be used after unknown reauth id * changed ANonce to be a random number instead of Counter-based * added support for canceling WPS operations with hostapd_cli wps_cancel * fixed EAP/WPS to PSK transition on reassociation in cases where deauthentication is missed * hlr_auc_gw enhancements: - a new command line parameter -u can be used to enable updating of SQN in Milenage file - use 5 bit IND for SQN updates - SQLite database can now be used to store Milenage information * EAP-SIM/AKA DB: added optional use of SQLite database for pseudonyms and reauth data * added support for Chargeable-User-Identity (RFC 4372) * added radius_auth_req_attr and radius_acct_req_attr configuration parameters to allow adding/overriding of RADIUS attributes in Access-Request and Accounting-Request packets * added support for RADIUS dynamic authorization server (RFC 5176) * added initial support for WNM operations - BSS max idle period - WNM-Sleep Mode * added new WPS NFC ctrl_iface mechanism - removed obsoleted WPS_OOB command (including support for deprecated UFD config_method) * added FT support for drivers that implement MLME internally * added SA Query support for drivers that implement MLME internally * removed default ACM=1 from AC_VO and AC_VI * changed VENDOR-TEST EAP method to use proper private enterprise number (this will not interoperate with older versions) * added hostapd.conf parameter vendor_elements to allow arbitrary vendor specific elements to be added to the Beacon and Probe Response frames * added support for configuring GCMP cipher for IEEE 802.11ad * added support for 256-bit AES with internal TLS implementation * changed EAPOL transmission to use AC_VO if WMM is active * fixed EAP-TLS/PEAP/TTLS/FAST server to validate TLS Message Length correctly; invalid messages could have caused the hostapd process to terminate before this fix [CVE-2012-4445] * limit number of active wildcard PINs for WPS Registrar to one to avoid confusing behavior with multiple wildcard PINs * added a workaround for WPS PBC session overlap detection to avoid interop issues with deployed station implementations that do not remove active PBC indication from Probe Request frames properly * added support for using SQLite for the eap_user database * added Acct-Session-Id attribute into Access-Request messages * fixed EAPOL frame transmission to non-QoS STAs with nl80211 (do not send QoS frames if the STA did not negotiate use of QoS for this association) 2012-05-10 - v1.0 * Add channel selection support in hostapd. See hostapd.conf. * Add support for IEEE 802.11v Time Advertisement mechanism with UTC TSF offset. See hostapd.conf for config info. * Delay STA entry removal until Deauth/Disassoc TX status in AP mode. This allows the driver to use PS buffering of Deauthentication and Disassociation frames when the STA is in power save sleep. Only available with drivers that provide TX status events for Deauth/ Disassoc frames (nl80211). * Allow PMKSA caching to be disabled on the Authenticator. See hostap.conf config parameter disable_pmksa_caching. * atheros: Add support for IEEE 802.11w configuration. * bsd: Add support for setting HT values in IFM_MMASK. * Allow client isolation to be configured with ap_isolate. Client isolation can be used to prevent low-level bridging of frames between associated stations in the BSS. By default, this bridging is allowed. * Allow coexistance of HT BSSes with WEP/TKIP BSSes. * Add require_ht config parameter, which can be used to configure hostapd to reject association with any station that does not support HT PHY. * Add support for writing debug log to a file using "-f" option. Also add relog CLI command to re-open the log file. * Add bridge handling for WDS STA interfaces. By default they are added to the configured bridge of the AP interface (if present), but the user can also specify a separate bridge using cli command wds_bridge. * hostapd_cli: - Add wds_bridge command for specifying bridge for WDS STA interfaces. - Add relog command for reopening log file. - Send AP-STA-DISCONNECTED event when an AP disconnects a station due to inactivity. - Add wps_config ctrl_interface command for configuring AP. This command can be used to configure the AP using the internal WPS registrar. It works in the same way as new AP settings received from an ER. - Many WPS/WPS ER commands - see WPS/WPS ER sections for details. - Add command get version, that returns hostapd version string. * WNM: Add BSS Transition Management Request for ESS Disassoc Imminent. Use hostapd_cli ess_disassoc (STA addr) (URL) to send the notification to the STA. * Allow AP mode to disconnect STAs based on low ACK condition (when the data connection is not working properly, e.g., due to the STA going outside the range of the AP). Disabled by default, enable by config option disassoc_low_ack. * Add WPA_IGNORE_CONFIG_ERRORS build option to continue in case of bad config file. * WPS: - Send AP Settings as a wrapped Credential attribute to ctrl_iface in WPS-NEW-AP-SETTINGS. - Dispatch more WPS events through hostapd ctrl_iface. - Add mechanism for indicating non-standard WPS errors. - Change concurrent radio AP to use only one WPS UPnP instance. - Add wps_check_pin command for processing PIN from user input. UIs can use this command to process a PIN entered by a user and to validate the checksum digit (if present). - Add hostap_cli get_config command to display current AP config. - Add new hostapd_cli command, wps_ap_pin, to manage AP PIN at runtime and support dynamic AP PIN management. - Disable AP PIN after 10 consecutive failures. Slow down attacks on failures up to 10. - Allow AP to start in Enrollee mode without AP PIN for probing, to be compatible with Windows 7. - Add Config Error into WPS-FAIL events to provide more info to the user on how to resolve the issue. - When controlling multiple interfaces: - apply WPS commands to all interfaces configured to use WPS - apply WPS config changes to all interfaces that use WPS - when an attack is detected on any interface, disable AP PIN on all interfaces * WPS ER: - Show SetSelectedRegistrar events as ctrl_iface events. - Add special AP Setup Locked mode to allow read only ER. ap_setup_locked=2 can now be used to enable a special mode where WPS ER can learn the current AP settings, but cannot change them. * WPS 2.0: Add support for WPS 2.0 (CONFIG_WPS2) - Add build option CONFIG_WPS_EXTENSIBILITY_TESTING to enable tool for testing protocol extensibility. - Add build option CONFIG_WPS_STRICT to allow disabling of WPS workarounds. - Add support for AuthorizedMACs attribute. * TDLS: - Allow TDLS use or TDLS channel switching in the BSS to be prohibited in the BSS, using config params tdls_prohibit and tdls_prohibit_chan_switch. * EAP server: Add support for configuring fragment size (see fragment_size in hostapd.conf). * wlantest: Add a tool wlantest for IEEE802.11 protocol testing. wlantest can be used to capture frames from a monitor interface for realtime capturing or from pcap files for offline analysis. * Interworking: Support added for 802.11u. Enable in .config with CONFIG_INTERWORKING. See hostapd.conf for config parameters for interworking. * Android: Add build and runtime support for Android hostapd. * Add a new debug message level for excessive information. Use -ddd to enable. * TLS: Add support for tls_disable_time_checks=1 in client mode. * Internal TLS: - Add support for TLS v1.1 (RFC 4346). Enable with build parameter CONFIG_TLSV11. - Add domainComponent parser for X.509 names * Reorder some IEs to get closer to IEEE 802.11 standard. Move WMM into end of Beacon, Probe Resp and (Re)Assoc Resp frames. Move HT IEs to be later in (Re)Assoc Resp. * Many bugfixes.
This commit is contained in:
parent
be536156b1
commit
5e9e13ee49
352
COPYING
352
COPYING
@ -1,340 +1,22 @@
|
||||
GNU GENERAL PUBLIC LICENSE
|
||||
Version 2, June 1991
|
||||
wpa_supplicant and hostapd
|
||||
--------------------------
|
||||
|
||||
Copyright (C) 1989, 1991 Free Software Foundation, Inc.
|
||||
51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA
|
||||
Everyone is permitted to copy and distribute verbatim copies
|
||||
of this license document, but changing it is not allowed.
|
||||
|
||||
Preamble
|
||||
|
||||
The licenses for most software are designed to take away your
|
||||
freedom to share and change it. By contrast, the GNU General Public
|
||||
License is intended to guarantee your freedom to share and change free
|
||||
software--to make sure the software is free for all its users. This
|
||||
General Public License applies to most of the Free Software
|
||||
Foundation's software and to any other program whose authors commit to
|
||||
using it. (Some other Free Software Foundation software is covered by
|
||||
the GNU Library General Public License instead.) You can apply it to
|
||||
your programs, too.
|
||||
|
||||
When we speak of free software, we are referring to freedom, not
|
||||
price. Our General Public Licenses are designed to make sure that you
|
||||
have the freedom to distribute copies of free software (and charge for
|
||||
this service if you wish), that you receive source code or can get it
|
||||
if you want it, that you can change the software or use pieces of it
|
||||
in new free programs; and that you know you can do these things.
|
||||
|
||||
To protect your rights, we need to make restrictions that forbid
|
||||
anyone to deny you these rights or to ask you to surrender the rights.
|
||||
These restrictions translate to certain responsibilities for you if you
|
||||
distribute copies of the software, or if you modify it.
|
||||
|
||||
For example, if you distribute copies of such a program, whether
|
||||
gratis or for a fee, you must give the recipients all the rights that
|
||||
you have. You must make sure that they, too, receive or can get the
|
||||
source code. And you must show them these terms so they know their
|
||||
rights.
|
||||
|
||||
We protect your rights with two steps: (1) copyright the software, and
|
||||
(2) offer you this license which gives you legal permission to copy,
|
||||
distribute and/or modify the software.
|
||||
|
||||
Also, for each author's protection and ours, we want to make certain
|
||||
that everyone understands that there is no warranty for this free
|
||||
software. If the software is modified by someone else and passed on, we
|
||||
want its recipients to know that what they have is not the original, so
|
||||
that any problems introduced by others will not reflect on the original
|
||||
authors' reputations.
|
||||
|
||||
Finally, any free program is threatened constantly by software
|
||||
patents. We wish to avoid the danger that redistributors of a free
|
||||
program will individually obtain patent licenses, in effect making the
|
||||
program proprietary. To prevent this, we have made it clear that any
|
||||
patent must be licensed for everyone's free use or not licensed at all.
|
||||
|
||||
The precise terms and conditions for copying, distribution and
|
||||
modification follow.
|
||||
|
||||
GNU GENERAL PUBLIC LICENSE
|
||||
TERMS AND CONDITIONS FOR COPYING, DISTRIBUTION AND MODIFICATION
|
||||
|
||||
0. This License applies to any program or other work which contains
|
||||
a notice placed by the copyright holder saying it may be distributed
|
||||
under the terms of this General Public License. The "Program", below,
|
||||
refers to any such program or work, and a "work based on the Program"
|
||||
means either the Program or any derivative work under copyright law:
|
||||
that is to say, a work containing the Program or a portion of it,
|
||||
either verbatim or with modifications and/or translated into another
|
||||
language. (Hereinafter, translation is included without limitation in
|
||||
the term "modification".) Each licensee is addressed as "you".
|
||||
|
||||
Activities other than copying, distribution and modification are not
|
||||
covered by this License; they are outside its scope. The act of
|
||||
running the Program is not restricted, and the output from the Program
|
||||
is covered only if its contents constitute a work based on the
|
||||
Program (independent of having been made by running the Program).
|
||||
Whether that is true depends on what the Program does.
|
||||
|
||||
1. You may copy and distribute verbatim copies of the Program's
|
||||
source code as you receive it, in any medium, provided that you
|
||||
conspicuously and appropriately publish on each copy an appropriate
|
||||
copyright notice and disclaimer of warranty; keep intact all the
|
||||
notices that refer to this License and to the absence of any warranty;
|
||||
and give any other recipients of the Program a copy of this License
|
||||
along with the Program.
|
||||
|
||||
You may charge a fee for the physical act of transferring a copy, and
|
||||
you may at your option offer warranty protection in exchange for a fee.
|
||||
|
||||
2. You may modify your copy or copies of the Program or any portion
|
||||
of it, thus forming a work based on the Program, and copy and
|
||||
distribute such modifications or work under the terms of Section 1
|
||||
above, provided that you also meet all of these conditions:
|
||||
|
||||
a) You must cause the modified files to carry prominent notices
|
||||
stating that you changed the files and the date of any change.
|
||||
|
||||
b) You must cause any work that you distribute or publish, that in
|
||||
whole or in part contains or is derived from the Program or any
|
||||
part thereof, to be licensed as a whole at no charge to all third
|
||||
parties under the terms of this License.
|
||||
|
||||
c) If the modified program normally reads commands interactively
|
||||
when run, you must cause it, when started running for such
|
||||
interactive use in the most ordinary way, to print or display an
|
||||
announcement including an appropriate copyright notice and a
|
||||
notice that there is no warranty (or else, saying that you provide
|
||||
a warranty) and that users may redistribute the program under
|
||||
these conditions, and telling the user how to view a copy of this
|
||||
License. (Exception: if the Program itself is interactive but
|
||||
does not normally print such an announcement, your work based on
|
||||
the Program is not required to print an announcement.)
|
||||
|
||||
These requirements apply to the modified work as a whole. If
|
||||
identifiable sections of that work are not derived from the Program,
|
||||
and can be reasonably considered independent and separate works in
|
||||
themselves, then this License, and its terms, do not apply to those
|
||||
sections when you distribute them as separate works. But when you
|
||||
distribute the same sections as part of a whole which is a work based
|
||||
on the Program, the distribution of the whole must be on the terms of
|
||||
this License, whose permissions for other licensees extend to the
|
||||
entire whole, and thus to each and every part regardless of who wrote it.
|
||||
|
||||
Thus, it is not the intent of this section to claim rights or contest
|
||||
your rights to work written entirely by you; rather, the intent is to
|
||||
exercise the right to control the distribution of derivative or
|
||||
collective works based on the Program.
|
||||
|
||||
In addition, mere aggregation of another work not based on the Program
|
||||
with the Program (or with a work based on the Program) on a volume of
|
||||
a storage or distribution medium does not bring the other work under
|
||||
the scope of this License.
|
||||
|
||||
3. You may copy and distribute the Program (or a work based on it,
|
||||
under Section 2) in object code or executable form under the terms of
|
||||
Sections 1 and 2 above provided that you also do one of the following:
|
||||
|
||||
a) Accompany it with the complete corresponding machine-readable
|
||||
source code, which must be distributed under the terms of Sections
|
||||
1 and 2 above on a medium customarily used for software interchange; or,
|
||||
|
||||
b) Accompany it with a written offer, valid for at least three
|
||||
years, to give any third party, for a charge no more than your
|
||||
cost of physically performing source distribution, a complete
|
||||
machine-readable copy of the corresponding source code, to be
|
||||
distributed under the terms of Sections 1 and 2 above on a medium
|
||||
customarily used for software interchange; or,
|
||||
|
||||
c) Accompany it with the information you received as to the offer
|
||||
to distribute corresponding source code. (This alternative is
|
||||
allowed only for noncommercial distribution and only if you
|
||||
received the program in object code or executable form with such
|
||||
an offer, in accord with Subsection b above.)
|
||||
|
||||
The source code for a work means the preferred form of the work for
|
||||
making modifications to it. For an executable work, complete source
|
||||
code means all the source code for all modules it contains, plus any
|
||||
associated interface definition files, plus the scripts used to
|
||||
control compilation and installation of the executable. However, as a
|
||||
special exception, the source code distributed need not include
|
||||
anything that is normally distributed (in either source or binary
|
||||
form) with the major components (compiler, kernel, and so on) of the
|
||||
operating system on which the executable runs, unless that component
|
||||
itself accompanies the executable.
|
||||
|
||||
If distribution of executable or object code is made by offering
|
||||
access to copy from a designated place, then offering equivalent
|
||||
access to copy the source code from the same place counts as
|
||||
distribution of the source code, even though third parties are not
|
||||
compelled to copy the source along with the object code.
|
||||
|
||||
4. You may not copy, modify, sublicense, or distribute the Program
|
||||
except as expressly provided under this License. Any attempt
|
||||
otherwise to copy, modify, sublicense or distribute the Program is
|
||||
void, and will automatically terminate your rights under this License.
|
||||
However, parties who have received copies, or rights, from you under
|
||||
this License will not have their licenses terminated so long as such
|
||||
parties remain in full compliance.
|
||||
|
||||
5. You are not required to accept this License, since you have not
|
||||
signed it. However, nothing else grants you permission to modify or
|
||||
distribute the Program or its derivative works. These actions are
|
||||
prohibited by law if you do not accept this License. Therefore, by
|
||||
modifying or distributing the Program (or any work based on the
|
||||
Program), you indicate your acceptance of this License to do so, and
|
||||
all its terms and conditions for copying, distributing or modifying
|
||||
the Program or works based on it.
|
||||
|
||||
6. Each time you redistribute the Program (or any work based on the
|
||||
Program), the recipient automatically receives a license from the
|
||||
original licensor to copy, distribute or modify the Program subject to
|
||||
these terms and conditions. You may not impose any further
|
||||
restrictions on the recipients' exercise of the rights granted herein.
|
||||
You are not responsible for enforcing compliance by third parties to
|
||||
this License.
|
||||
|
||||
7. If, as a consequence of a court judgment or allegation of patent
|
||||
infringement or for any other reason (not limited to patent issues),
|
||||
conditions are imposed on you (whether by court order, agreement or
|
||||
otherwise) that contradict the conditions of this License, they do not
|
||||
excuse you from the conditions of this License. If you cannot
|
||||
distribute so as to satisfy simultaneously your obligations under this
|
||||
License and any other pertinent obligations, then as a consequence you
|
||||
may not distribute the Program at all. For example, if a patent
|
||||
license would not permit royalty-free redistribution of the Program by
|
||||
all those who receive copies directly or indirectly through you, then
|
||||
the only way you could satisfy both it and this License would be to
|
||||
refrain entirely from distribution of the Program.
|
||||
|
||||
If any portion of this section is held invalid or unenforceable under
|
||||
any particular circumstance, the balance of the section is intended to
|
||||
apply and the section as a whole is intended to apply in other
|
||||
circumstances.
|
||||
|
||||
It is not the purpose of this section to induce you to infringe any
|
||||
patents or other property right claims or to contest validity of any
|
||||
such claims; this section has the sole purpose of protecting the
|
||||
integrity of the free software distribution system, which is
|
||||
implemented by public license practices. Many people have made
|
||||
generous contributions to the wide range of software distributed
|
||||
through that system in reliance on consistent application of that
|
||||
system; it is up to the author/donor to decide if he or she is willing
|
||||
to distribute software through any other system and a licensee cannot
|
||||
impose that choice.
|
||||
|
||||
This section is intended to make thoroughly clear what is believed to
|
||||
be a consequence of the rest of this License.
|
||||
|
||||
8. If the distribution and/or use of the Program is restricted in
|
||||
certain countries either by patents or by copyrighted interfaces, the
|
||||
original copyright holder who places the Program under this License
|
||||
may add an explicit geographical distribution limitation excluding
|
||||
those countries, so that distribution is permitted only in or among
|
||||
countries not thus excluded. In such case, this License incorporates
|
||||
the limitation as if written in the body of this License.
|
||||
|
||||
9. The Free Software Foundation may publish revised and/or new versions
|
||||
of the General Public License from time to time. Such new versions will
|
||||
be similar in spirit to the present version, but may differ in detail to
|
||||
address new problems or concerns.
|
||||
|
||||
Each version is given a distinguishing version number. If the Program
|
||||
specifies a version number of this License which applies to it and "any
|
||||
later version", you have the option of following the terms and conditions
|
||||
either of that version or of any later version published by the Free
|
||||
Software Foundation. If the Program does not specify a version number of
|
||||
this License, you may choose any version ever published by the Free Software
|
||||
Foundation.
|
||||
|
||||
10. If you wish to incorporate parts of the Program into other free
|
||||
programs whose distribution conditions are different, write to the author
|
||||
to ask for permission. For software which is copyrighted by the Free
|
||||
Software Foundation, write to the Free Software Foundation; we sometimes
|
||||
make exceptions for this. Our decision will be guided by the two goals
|
||||
of preserving the free status of all derivatives of our free software and
|
||||
of promoting the sharing and reuse of software generally.
|
||||
|
||||
NO WARRANTY
|
||||
|
||||
11. BECAUSE THE PROGRAM IS LICENSED FREE OF CHARGE, THERE IS NO WARRANTY
|
||||
FOR THE PROGRAM, TO THE EXTENT PERMITTED BY APPLICABLE LAW. EXCEPT WHEN
|
||||
OTHERWISE STATED IN WRITING THE COPYRIGHT HOLDERS AND/OR OTHER PARTIES
|
||||
PROVIDE THE PROGRAM "AS IS" WITHOUT WARRANTY OF ANY KIND, EITHER EXPRESSED
|
||||
OR IMPLIED, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF
|
||||
MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE. THE ENTIRE RISK AS
|
||||
TO THE QUALITY AND PERFORMANCE OF THE PROGRAM IS WITH YOU. SHOULD THE
|
||||
PROGRAM PROVE DEFECTIVE, YOU ASSUME THE COST OF ALL NECESSARY SERVICING,
|
||||
REPAIR OR CORRECTION.
|
||||
|
||||
12. IN NO EVENT UNLESS REQUIRED BY APPLICABLE LAW OR AGREED TO IN WRITING
|
||||
WILL ANY COPYRIGHT HOLDER, OR ANY OTHER PARTY WHO MAY MODIFY AND/OR
|
||||
REDISTRIBUTE THE PROGRAM AS PERMITTED ABOVE, BE LIABLE TO YOU FOR DAMAGES,
|
||||
INCLUDING ANY GENERAL, SPECIAL, INCIDENTAL OR CONSEQUENTIAL DAMAGES ARISING
|
||||
OUT OF THE USE OR INABILITY TO USE THE PROGRAM (INCLUDING BUT NOT LIMITED
|
||||
TO LOSS OF DATA OR DATA BEING RENDERED INACCURATE OR LOSSES SUSTAINED BY
|
||||
YOU OR THIRD PARTIES OR A FAILURE OF THE PROGRAM TO OPERATE WITH ANY OTHER
|
||||
PROGRAMS), EVEN IF SUCH HOLDER OR OTHER PARTY HAS BEEN ADVISED OF THE
|
||||
POSSIBILITY OF SUCH DAMAGES.
|
||||
|
||||
END OF TERMS AND CONDITIONS
|
||||
|
||||
How to Apply These Terms to Your New Programs
|
||||
|
||||
If you develop a new program, and you want it to be of the greatest
|
||||
possible use to the public, the best way to achieve this is to make it
|
||||
free software which everyone can redistribute and change under these terms.
|
||||
|
||||
To do so, attach the following notices to the program. It is safest
|
||||
to attach them to the start of each source file to most effectively
|
||||
convey the exclusion of warranty; and each file should have at least
|
||||
the "copyright" line and a pointer to where the full notice is found.
|
||||
|
||||
<one line to give the program's name and a brief idea of what it does.>
|
||||
Copyright (C) 19yy <name of author>
|
||||
|
||||
This program is free software; you can redistribute it and/or modify
|
||||
it under the terms of the GNU General Public License as published by
|
||||
the Free Software Foundation; either version 2 of the License, or
|
||||
(at your option) any later version.
|
||||
|
||||
This program is distributed in the hope that it will be useful,
|
||||
but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||
GNU General Public License for more details.
|
||||
|
||||
You should have received a copy of the GNU General Public License
|
||||
along with this program; if not, write to the Free Software
|
||||
Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA
|
||||
Copyright (c) 2002-2012, Jouni Malinen <j@w1.fi> and contributors
|
||||
All Rights Reserved.
|
||||
|
||||
|
||||
Also add information on how to contact you by electronic and paper mail.
|
||||
See the README file for the current license terms.
|
||||
|
||||
If the program is interactive, make it output a short notice like this
|
||||
when it starts in an interactive mode:
|
||||
This software was previously distributed under BSD/GPL v2 dual license
|
||||
terms that allowed either of those license alternatives to be
|
||||
selected. As of February 11, 2012, the project has chosen to use only
|
||||
the BSD license option for future distribution. As such, the GPL v2
|
||||
license option is no longer used. It should be noted that the BSD
|
||||
license option (the one with advertisement clause removed) is compatible
|
||||
with GPL and as such, does not prevent use of this software in projects
|
||||
that use GPL.
|
||||
|
||||
Gnomovision version 69, Copyright (C) 19yy name of author
|
||||
Gnomovision comes with ABSOLUTELY NO WARRANTY; for details type `show w'.
|
||||
This is free software, and you are welcome to redistribute it
|
||||
under certain conditions; type `show c' for details.
|
||||
|
||||
The hypothetical commands `show w' and `show c' should show the appropriate
|
||||
parts of the General Public License. Of course, the commands you use may
|
||||
be called something other than `show w' and `show c'; they could even be
|
||||
mouse-clicks or menu items--whatever suits your program.
|
||||
|
||||
You should also get your employer (if you work as a programmer) or your
|
||||
school, if any, to sign a "copyright disclaimer" for the program, if
|
||||
necessary. Here is a sample; alter the names:
|
||||
|
||||
Yoyodyne, Inc., hereby disclaims all copyright interest in the program
|
||||
`Gnomovision' (which makes passes at compilers) written by James Hacker.
|
||||
|
||||
<signature of Ty Coon>, 1 April 1989
|
||||
Ty Coon, President of Vice
|
||||
|
||||
This General Public License does not permit incorporating your program into
|
||||
proprietary programs. If your program is a subroutine library, you may
|
||||
consider it more useful to permit linking proprietary applications with the
|
||||
library. If this is what you want to do, use the GNU Library General
|
||||
Public License instead of this License.
|
||||
Some of the files may still include pointers to GPL version 2 license
|
||||
terms. However, such copyright and license notifications are maintained
|
||||
only for attribution purposes and any distribution of this software
|
||||
after February 11, 2012 is no longer under the GPL v2 option.
|
||||
|
57
README
57
README
@ -1,19 +1,56 @@
|
||||
wpa_supplicant and hostapd v0.6.x
|
||||
---------------------------------
|
||||
wpa_supplicant and hostapd
|
||||
--------------------------
|
||||
|
||||
Copyright (c) 2002-2007, Jouni Malinen <j@w1.fi> and contributors
|
||||
Copyright (c) 2002-2012, Jouni Malinen <j@w1.fi> and contributors
|
||||
All Rights Reserved.
|
||||
|
||||
These program is dual-licensed under both the GPL version 2 and BSD
|
||||
license. Either license may be used at your option.
|
||||
These programs are licensed under the BSD license (the one with
|
||||
advertisement clause removed).
|
||||
|
||||
If you are submitting changes to the project, please see CONTRIBUTIONS
|
||||
file for more instructions.
|
||||
|
||||
|
||||
This package may include either wpa_supplicant, hostapd, or both. See
|
||||
README file respective subdirectories (wpa_supplicant/README or
|
||||
hostapd/README) for more details.
|
||||
|
||||
Source code files have been moved around in v0.6.x releases and
|
||||
compared to earlier releases, the programs are now build by first
|
||||
going to a subdirectory (wpa_supplicant or hostapd) and creating
|
||||
build configuration (.config) and running 'make' there (for
|
||||
Linux/BSD/cygwin builds).
|
||||
Source code files were moved around in v0.6.x releases and compared to
|
||||
earlier releases, the programs are now built by first going to a
|
||||
subdirectory (wpa_supplicant or hostapd) and creating build
|
||||
configuration (.config) and running 'make' there (for Linux/BSD/cygwin
|
||||
builds).
|
||||
|
||||
|
||||
License
|
||||
-------
|
||||
|
||||
This software may be distributed, used, and modified under the terms of
|
||||
BSD license:
|
||||
|
||||
Redistribution and use in source and binary forms, with or without
|
||||
modification, are permitted provided that the following conditions are
|
||||
met:
|
||||
|
||||
1. Redistributions of source code must retain the above copyright
|
||||
notice, this list of conditions and the following disclaimer.
|
||||
|
||||
2. Redistributions in binary form must reproduce the above copyright
|
||||
notice, this list of conditions and the following disclaimer in the
|
||||
documentation and/or other materials provided with the distribution.
|
||||
|
||||
3. Neither the name(s) of the above-listed copyright holder(s) nor the
|
||||
names of its contributors may be used to endorse or promote products
|
||||
derived from this software without specific prior written permission.
|
||||
|
||||
THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
|
||||
"AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
|
||||
LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
|
||||
A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
|
||||
OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
|
||||
SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
|
||||
LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
|
||||
DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
|
||||
THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
|
||||
(INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
|
||||
OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
|
||||
|
7
hostapd/.gitignore
vendored
7
hostapd/.gitignore
vendored
@ -1,7 +0,0 @@
|
||||
*.d
|
||||
.config
|
||||
driver_conf.c
|
||||
hostapd
|
||||
hostapd_cli
|
||||
hlr_auc_gw
|
||||
nt_password_hash
|
@ -1,20 +1,206 @@
|
||||
ChangeLog for hostapd
|
||||
|
||||
2010-09-07 - v0.7.3
|
||||
* fixed re-association after WPS not initializing WPA state machine in
|
||||
some cases
|
||||
* fixed WPS IE update on reconfiguration
|
||||
* fixed WPS code not to proxy Probe Request frames for foreign SSIDs
|
||||
* added WPS workaround for open networks and some known interop issues
|
||||
* fixed WPS Diffie-Hellman derivation to use correct public key length
|
||||
* fixed FT RRB messages on big endian CPUs
|
||||
* changed WPS protection for brute force AP PIN attacks to disable AP
|
||||
PIN only temporarily (but with increasing time) to avoid usability
|
||||
issues on Label-only devices
|
||||
* added wps_ap_pin command for more secure handling of AP PIN
|
||||
operations (e.g., to generate a random AP PIN and only use it for
|
||||
short amount of time)
|
||||
* fixed HT STBC negotiation
|
||||
2013-01-12 - v2.0
|
||||
* added AP-STA-DISCONNECTED ctrl_iface event
|
||||
* improved debug logging (human readable event names, interface name
|
||||
included in more entries)
|
||||
* added number of small changes to make it easier for static analyzers
|
||||
to understand the implementation
|
||||
* added a workaround for Windows 7 Michael MIC failure reporting and
|
||||
use of the Secure bit in EAPOL-Key msg 3/4
|
||||
* fixed number of small bugs (see git logs for more details)
|
||||
* changed OpenSSL to read full certificate chain from server_cert file
|
||||
* nl80211: number of updates to use new cfg80211/nl80211 functionality
|
||||
- replace monitor interface with nl80211 commands
|
||||
- additional information for driver-based AP SME
|
||||
* EAP-pwd:
|
||||
- fix KDF for group 21 and zero-padding
|
||||
- added support for fragmentation
|
||||
- increased maximum number of hunting-and-pecking iterations
|
||||
* avoid excessive Probe Response retries for broadcast Probe Request
|
||||
frames (only with drivers using hostapd SME/MLME)
|
||||
* added preliminary support for using TLS v1.2 (CONFIG_TLSV12=y)
|
||||
* fixed WPS operation stopping on dual concurrent AP
|
||||
* added wps_rf_bands configuration parameter for overriding RF Bands
|
||||
value for WPS
|
||||
* added support for getting per-device PSK from RADIUS Tunnel-Password
|
||||
* added support for libnl 3.2 and newer
|
||||
* increased initial group key handshake retransmit timeout to 500 ms
|
||||
* added a workaround for 4-way handshake to update SNonce even after
|
||||
having sent EAPOL-Key 3/4 to avoid issues with some supplicant
|
||||
implementations that can change SNonce for each EAP-Key 2/4
|
||||
* added a workaround for EAPOL-Key 4/4 using incorrect type value in
|
||||
WPA2 mode (some deployed stations use WPA type in that message)
|
||||
* added a WPS workaround for mixed mode AP Settings with Windows 7
|
||||
* changed WPS AP PIN disabling mechanism to disable the PIN after 10
|
||||
consecutive failures in addition to using the exponential lockout
|
||||
period
|
||||
* added support for WFA Hotspot 2.0
|
||||
- GAS/ANQP advertisement of network information
|
||||
- disable_dgaf parameter to disable downstream group-addressed
|
||||
forwarding
|
||||
* simplified licensing terms by selecting the BSD license as the only
|
||||
alternative
|
||||
* EAP-SIM: fixed re-authentication not to update pseudonym
|
||||
* EAP-SIM: use Notification round before EAP-Failure
|
||||
* EAP-AKA: added support for AT_COUNTER_TOO_SMALL
|
||||
* EAP-AKA: skip AKA/Identity exchange if EAP identity is recognized
|
||||
* EAP-AKA': fixed identity for MK derivation
|
||||
* EAP-AKA': updated to RFC 5448 (username prefixes changed); note: this
|
||||
breaks interoperability with older versions
|
||||
* EAP-SIM/AKA: allow pseudonym to be used after unknown reauth id
|
||||
* changed ANonce to be a random number instead of Counter-based
|
||||
* added support for canceling WPS operations with hostapd_cli wps_cancel
|
||||
* fixed EAP/WPS to PSK transition on reassociation in cases where
|
||||
deauthentication is missed
|
||||
* hlr_auc_gw enhancements:
|
||||
- a new command line parameter -u can be used to enable updating of
|
||||
SQN in Milenage file
|
||||
- use 5 bit IND for SQN updates
|
||||
- SQLite database can now be used to store Milenage information
|
||||
* EAP-SIM/AKA DB: added optional use of SQLite database for pseudonyms
|
||||
and reauth data
|
||||
* added support for Chargeable-User-Identity (RFC 4372)
|
||||
* added radius_auth_req_attr and radius_acct_req_attr configuration
|
||||
parameters to allow adding/overriding of RADIUS attributes in
|
||||
Access-Request and Accounting-Request packets
|
||||
* added support for RADIUS dynamic authorization server (RFC 5176)
|
||||
* added initial support for WNM operations
|
||||
- BSS max idle period
|
||||
- WNM-Sleep Mode
|
||||
* added new WPS NFC ctrl_iface mechanism
|
||||
- removed obsoleted WPS_OOB command (including support for deprecated
|
||||
UFD config_method)
|
||||
* added FT support for drivers that implement MLME internally
|
||||
* added SA Query support for drivers that implement MLME internally
|
||||
* removed default ACM=1 from AC_VO and AC_VI
|
||||
* changed VENDOR-TEST EAP method to use proper private enterprise number
|
||||
(this will not interoperate with older versions)
|
||||
* added hostapd.conf parameter vendor_elements to allow arbitrary vendor
|
||||
specific elements to be added to the Beacon and Probe Response frames
|
||||
* added support for configuring GCMP cipher for IEEE 802.11ad
|
||||
* added support for 256-bit AES with internal TLS implementation
|
||||
* changed EAPOL transmission to use AC_VO if WMM is active
|
||||
* fixed EAP-TLS/PEAP/TTLS/FAST server to validate TLS Message Length
|
||||
correctly; invalid messages could have caused the hostapd process to
|
||||
terminate before this fix [CVE-2012-4445]
|
||||
* limit number of active wildcard PINs for WPS Registrar to one to avoid
|
||||
confusing behavior with multiple wildcard PINs
|
||||
* added a workaround for WPS PBC session overlap detection to avoid
|
||||
interop issues with deployed station implementations that do not
|
||||
remove active PBC indication from Probe Request frames properly
|
||||
* added support for using SQLite for the eap_user database
|
||||
* added Acct-Session-Id attribute into Access-Request messages
|
||||
* fixed EAPOL frame transmission to non-QoS STAs with nl80211
|
||||
(do not send QoS frames if the STA did not negotiate use of QoS for
|
||||
this association)
|
||||
|
||||
2012-05-10 - v1.0
|
||||
* Add channel selection support in hostapd. See hostapd.conf.
|
||||
* Add support for IEEE 802.11v Time Advertisement mechanism with UTC
|
||||
TSF offset. See hostapd.conf for config info.
|
||||
* Delay STA entry removal until Deauth/Disassoc TX status in AP mode.
|
||||
This allows the driver to use PS buffering of Deauthentication and
|
||||
Disassociation frames when the STA is in power save sleep. Only
|
||||
available with drivers that provide TX status events for Deauth/
|
||||
Disassoc frames (nl80211).
|
||||
* Allow PMKSA caching to be disabled on the Authenticator. See
|
||||
hostap.conf config parameter disable_pmksa_caching.
|
||||
* atheros: Add support for IEEE 802.11w configuration.
|
||||
* bsd: Add support for setting HT values in IFM_MMASK.
|
||||
* Allow client isolation to be configured with ap_isolate. Client
|
||||
isolation can be used to prevent low-level bridging of frames
|
||||
between associated stations in the BSS. By default, this bridging
|
||||
is allowed.
|
||||
* Allow coexistance of HT BSSes with WEP/TKIP BSSes.
|
||||
* Add require_ht config parameter, which can be used to configure
|
||||
hostapd to reject association with any station that does not support
|
||||
HT PHY.
|
||||
* Add support for writing debug log to a file using "-f" option. Also
|
||||
add relog CLI command to re-open the log file.
|
||||
* Add bridge handling for WDS STA interfaces. By default they are
|
||||
added to the configured bridge of the AP interface (if present),
|
||||
but the user can also specify a separate bridge using cli command
|
||||
wds_bridge.
|
||||
* hostapd_cli:
|
||||
- Add wds_bridge command for specifying bridge for WDS STA
|
||||
interfaces.
|
||||
- Add relog command for reopening log file.
|
||||
- Send AP-STA-DISCONNECTED event when an AP disconnects a station
|
||||
due to inactivity.
|
||||
- Add wps_config ctrl_interface command for configuring AP. This
|
||||
command can be used to configure the AP using the internal WPS
|
||||
registrar. It works in the same way as new AP settings received
|
||||
from an ER.
|
||||
- Many WPS/WPS ER commands - see WPS/WPS ER sections for details.
|
||||
- Add command get version, that returns hostapd version string.
|
||||
* WNM: Add BSS Transition Management Request for ESS Disassoc Imminent.
|
||||
Use hostapd_cli ess_disassoc (STA addr) (URL) to send the
|
||||
notification to the STA.
|
||||
* Allow AP mode to disconnect STAs based on low ACK condition (when
|
||||
the data connection is not working properly, e.g., due to the STA
|
||||
going outside the range of the AP). Disabled by default, enable by
|
||||
config option disassoc_low_ack.
|
||||
* Add WPA_IGNORE_CONFIG_ERRORS build option to continue in case of bad
|
||||
config file.
|
||||
* WPS:
|
||||
- Send AP Settings as a wrapped Credential attribute to ctrl_iface
|
||||
in WPS-NEW-AP-SETTINGS.
|
||||
- Dispatch more WPS events through hostapd ctrl_iface.
|
||||
- Add mechanism for indicating non-standard WPS errors.
|
||||
- Change concurrent radio AP to use only one WPS UPnP instance.
|
||||
- Add wps_check_pin command for processing PIN from user input.
|
||||
UIs can use this command to process a PIN entered by a user and to
|
||||
validate the checksum digit (if present).
|
||||
- Add hostap_cli get_config command to display current AP config.
|
||||
- Add new hostapd_cli command, wps_ap_pin, to manage AP PIN at
|
||||
runtime and support dynamic AP PIN management.
|
||||
- Disable AP PIN after 10 consecutive failures. Slow down attacks
|
||||
on failures up to 10.
|
||||
- Allow AP to start in Enrollee mode without AP PIN for probing,
|
||||
to be compatible with Windows 7.
|
||||
- Add Config Error into WPS-FAIL events to provide more info
|
||||
to the user on how to resolve the issue.
|
||||
- When controlling multiple interfaces:
|
||||
- apply WPS commands to all interfaces configured to use WPS
|
||||
- apply WPS config changes to all interfaces that use WPS
|
||||
- when an attack is detected on any interface, disable AP PIN on
|
||||
all interfaces
|
||||
* WPS ER:
|
||||
- Show SetSelectedRegistrar events as ctrl_iface events.
|
||||
- Add special AP Setup Locked mode to allow read only ER.
|
||||
ap_setup_locked=2 can now be used to enable a special mode where
|
||||
WPS ER can learn the current AP settings, but cannot change them.
|
||||
* WPS 2.0: Add support for WPS 2.0 (CONFIG_WPS2)
|
||||
- Add build option CONFIG_WPS_EXTENSIBILITY_TESTING to enable tool
|
||||
for testing protocol extensibility.
|
||||
- Add build option CONFIG_WPS_STRICT to allow disabling of WPS
|
||||
workarounds.
|
||||
- Add support for AuthorizedMACs attribute.
|
||||
* TDLS:
|
||||
- Allow TDLS use or TDLS channel switching in the BSS to be
|
||||
prohibited in the BSS, using config params tdls_prohibit and
|
||||
tdls_prohibit_chan_switch.
|
||||
* EAP server: Add support for configuring fragment size (see
|
||||
fragment_size in hostapd.conf).
|
||||
* wlantest: Add a tool wlantest for IEEE802.11 protocol testing.
|
||||
wlantest can be used to capture frames from a monitor interface
|
||||
for realtime capturing or from pcap files for offline analysis.
|
||||
* Interworking: Support added for 802.11u. Enable in .config with
|
||||
CONFIG_INTERWORKING. See hostapd.conf for config parameters for
|
||||
interworking.
|
||||
* Android: Add build and runtime support for Android hostapd.
|
||||
* Add a new debug message level for excessive information. Use
|
||||
-ddd to enable.
|
||||
* TLS: Add support for tls_disable_time_checks=1 in client mode.
|
||||
* Internal TLS:
|
||||
- Add support for TLS v1.1 (RFC 4346). Enable with build parameter
|
||||
CONFIG_TLSV11.
|
||||
- Add domainComponent parser for X.509 names
|
||||
* Reorder some IEs to get closer to IEEE 802.11 standard. Move
|
||||
WMM into end of Beacon, Probe Resp and (Re)Assoc Resp frames.
|
||||
Move HT IEs to be later in (Re)Assoc Resp.
|
||||
* Many bugfixes.
|
||||
|
||||
2010-04-18 - v0.7.2
|
||||
* fix WPS internal Registrar use when an external Registrar is also
|
||||
@ -98,7 +284,7 @@ ChangeLog for hostapd
|
||||
* updated management frame protection to use IEEE Std 802.11w-2009
|
||||
* fixed number of small WPS issues and added workarounds to
|
||||
interoperate with common deployed broken implementations
|
||||
* added some IEEE 802.11n co-existance rules to disable 40 MHz channels
|
||||
* added some IEEE 802.11n co-existence rules to disable 40 MHz channels
|
||||
or modify primary/secondary channels if needed based on neighboring
|
||||
networks
|
||||
* added support for NFC out-of-band mechanism with WPS
|
||||
|
172
hostapd/Makefile
172
hostapd/Makefile
@ -43,6 +43,7 @@ OBJS += ../src/ap/utils.o
|
||||
OBJS += ../src/ap/authsrv.o
|
||||
OBJS += ../src/ap/ieee802_1x.o
|
||||
OBJS += ../src/ap/ap_config.o
|
||||
OBJS += ../src/ap/eap_user_db.o
|
||||
OBJS += ../src/ap/ieee802_11_auth.o
|
||||
OBJS += ../src/ap/sta_info.o
|
||||
OBJS += ../src/ap/wpa_auth.o
|
||||
@ -51,6 +52,10 @@ OBJS += ../src/ap/ap_mlme.o
|
||||
OBJS += ../src/ap/wpa_auth_ie.o
|
||||
OBJS += ../src/ap/preauth_auth.o
|
||||
OBJS += ../src/ap/pmksa_cache_auth.o
|
||||
OBJS += ../src/ap/ieee802_11_shared.o
|
||||
OBJS += ../src/ap/beacon.o
|
||||
|
||||
OBJS_c = hostapd_cli.o ../src/common/wpa_ctrl.o ../src/utils/os_$(CONFIG_OS).o
|
||||
|
||||
NEED_RC4=y
|
||||
NEED_AES=y
|
||||
@ -63,18 +68,25 @@ CFLAGS += -DHOSTAPD
|
||||
ifdef CONFIG_WPA_TRACE
|
||||
CFLAGS += -DWPA_TRACE
|
||||
OBJS += ../src/utils/trace.o
|
||||
HOBJS += ../src/utils/trace.o
|
||||
LDFLAGS += -rdynamic
|
||||
CFLAGS += -funwind-tables
|
||||
ifdef CONFIG_WPA_TRACE_BFD
|
||||
CFLAGS += -DWPA_TRACE_BFD
|
||||
LIBS += -lbfd
|
||||
LIBS_c += -lbfd
|
||||
LIBS_h += -lbfd
|
||||
endif
|
||||
endif
|
||||
|
||||
OBJS += ../src/utils/eloop.o
|
||||
ifndef CONFIG_ELOOP
|
||||
CONFIG_ELOOP=eloop
|
||||
endif
|
||||
OBJS += ../src/utils/$(CONFIG_ELOOP).o
|
||||
OBJS_c += ../src/utils/$(CONFIG_ELOOP).o
|
||||
OBJS += ../src/utils/common.o
|
||||
OBJS += ../src/utils/wpa_debug.o
|
||||
OBJS_c += ../src/utils/wpa_debug.o
|
||||
OBJS += ../src/utils/wpabuf.o
|
||||
OBJS += ../src/utils/os_$(CONFIG_OS).o
|
||||
OBJS += ../src/utils/ip_addr.o
|
||||
@ -99,6 +111,7 @@ CONFIG_NO_ACCOUNTING=y
|
||||
else
|
||||
OBJS += ../src/radius/radius.o
|
||||
OBJS += ../src/radius/radius_client.o
|
||||
OBJS += ../src/radius/radius_das.o
|
||||
endif
|
||||
|
||||
ifdef CONFIG_NO_ACCOUNTING
|
||||
@ -111,6 +124,12 @@ ifdef CONFIG_NO_VLAN
|
||||
CFLAGS += -DCONFIG_NO_VLAN
|
||||
else
|
||||
OBJS += ../src/ap/vlan_init.o
|
||||
ifdef CONFIG_VLAN_NETLINK
|
||||
ifdef CONFIG_FULL_DYNAMIC_VLAN
|
||||
OBJS += ../src/ap/vlan_util.o
|
||||
endif
|
||||
CFLAGS += -DCONFIG_VLAN_NETLINK
|
||||
endif
|
||||
endif
|
||||
|
||||
ifdef CONFIG_NO_CTRL_IFACE
|
||||
@ -153,10 +172,23 @@ NEED_AES_OMAC1=y
|
||||
NEED_AES_UNWRAP=y
|
||||
endif
|
||||
|
||||
ifdef CONFIG_SAE
|
||||
CFLAGS += -DCONFIG_SAE
|
||||
endif
|
||||
|
||||
ifdef CONFIG_WNM
|
||||
CFLAGS += -DCONFIG_WNM
|
||||
OBJS += ../src/ap/wnm_ap.o
|
||||
endif
|
||||
|
||||
ifdef CONFIG_IEEE80211N
|
||||
CFLAGS += -DCONFIG_IEEE80211N
|
||||
endif
|
||||
|
||||
ifdef CONFIG_IEEE80211AC
|
||||
CFLAGS += -DCONFIG_IEEE80211AC
|
||||
endif
|
||||
|
||||
include ../src/drivers/drivers.mak
|
||||
OBJS += $(DRV_AP_OBJS)
|
||||
CFLAGS += $(DRV_AP_CFLAGS)
|
||||
@ -192,6 +224,14 @@ OBJS += ../src/eap_server/eap_server_tls.o
|
||||
TLS_FUNCS=y
|
||||
endif
|
||||
|
||||
ifdef CONFIG_EAP_UNAUTH_TLS
|
||||
CFLAGS += -DEAP_SERVER_UNAUTH_TLS
|
||||
ifndef CONFIG_EAP_TLS
|
||||
OBJS += ../src/eap_server/eap_server_tls.o
|
||||
TLS_FUNCS=y
|
||||
endif
|
||||
endif
|
||||
|
||||
ifdef CONFIG_EAP_PEAP
|
||||
CFLAGS += -DEAP_SERVER_PEAP
|
||||
OBJS += ../src/eap_server/eap_server_peap.o
|
||||
@ -274,6 +314,12 @@ NEED_SHA256=y
|
||||
NEED_AES_OMAC1=y
|
||||
endif
|
||||
|
||||
ifdef CONFIG_EAP_PWD
|
||||
CFLAGS += -DEAP_SERVER_PWD
|
||||
OBJS += ../src/eap_server/eap_server_pwd.o ../src/eap_common/eap_pwd_common.o
|
||||
NEED_SHA256=y
|
||||
endif
|
||||
|
||||
ifdef CONFIG_EAP_VENDOR_TEST
|
||||
CFLAGS += -DEAP_SERVER_VENDOR_TEST
|
||||
OBJS += ../src/eap_server/eap_server_vendor_test.o
|
||||
@ -289,6 +335,10 @@ NEED_AES_UNWRAP=y
|
||||
endif
|
||||
|
||||
ifdef CONFIG_WPS
|
||||
ifdef CONFIG_WPS2
|
||||
CFLAGS += -DCONFIG_WPS2
|
||||
endif
|
||||
|
||||
CFLAGS += -DCONFIG_WPS -DEAP_SERVER_WSC
|
||||
OBJS += ../src/utils/uuid.o
|
||||
OBJS += ../src/ap/wps_hostapd.o
|
||||
@ -308,25 +358,10 @@ NEED_AES_CBC=y
|
||||
NEED_MODEXP=y
|
||||
CONFIG_EAP=y
|
||||
|
||||
ifdef CONFIG_WPS_UFD
|
||||
CFLAGS += -DCONFIG_WPS_UFD
|
||||
OBJS += ../src/wps/wps_ufd.o
|
||||
NEED_WPS_OOB=y
|
||||
endif
|
||||
|
||||
ifdef CONFIG_WPS_NFC
|
||||
CFLAGS += -DCONFIG_WPS_NFC
|
||||
OBJS += ../src/wps/ndef.o
|
||||
OBJS += ../src/wps/wps_nfc.o
|
||||
NEED_WPS_OOB=y
|
||||
ifdef CONFIG_WPS_NFC_PN531
|
||||
PN531_PATH ?= /usr/local/src/nfc
|
||||
CFLAGS += -DCONFIG_WPS_NFC_PN531
|
||||
CFLAGS += -I${PN531_PATH}/inc
|
||||
OBJS += ../src/wps/wps_nfc_pn531.o
|
||||
LIBS += ${PN531_PATH}/lib/wpsnfc.dll
|
||||
LIBS += ${PN531_PATH}/lib/libnfc_mapping_pn53x.dll
|
||||
endif
|
||||
endif
|
||||
|
||||
ifdef NEED_WPS_OOB
|
||||
@ -346,6 +381,15 @@ OBJS += ../src/wps/http_client.o
|
||||
OBJS += ../src/wps/http_server.o
|
||||
endif
|
||||
|
||||
ifdef CONFIG_WPS_STRICT
|
||||
CFLAGS += -DCONFIG_WPS_STRICT
|
||||
OBJS += ../src/wps/wps_validate.o
|
||||
endif
|
||||
|
||||
ifdef CONFIG_WPS_TESTING
|
||||
CFLAGS += -DCONFIG_WPS_TESTING
|
||||
endif
|
||||
|
||||
endif
|
||||
|
||||
ifdef CONFIG_EAP_IKEV2
|
||||
@ -406,6 +450,15 @@ ifndef CONFIG_TLS
|
||||
CONFIG_TLS=openssl
|
||||
endif
|
||||
|
||||
ifdef CONFIG_TLSV11
|
||||
CFLAGS += -DCONFIG_TLSV11
|
||||
endif
|
||||
|
||||
ifdef CONFIG_TLSV12
|
||||
CFLAGS += -DCONFIG_TLSV12
|
||||
NEED_SHA256=y
|
||||
endif
|
||||
|
||||
ifeq ($(CONFIG_TLS), openssl)
|
||||
ifdef TLS_FUNCS
|
||||
OBJS += ../src/crypto/tls_openssl.o
|
||||
@ -424,10 +477,6 @@ ifeq ($(CONFIG_TLS), gnutls)
|
||||
ifdef TLS_FUNCS
|
||||
OBJS += ../src/crypto/tls_gnutls.o
|
||||
LIBS += -lgnutls -lgpg-error
|
||||
ifdef CONFIG_GNUTLS_EXTRA
|
||||
CFLAGS += -DCONFIG_GNUTLS_EXTRA
|
||||
LIBS += -lgnutls-extra
|
||||
endif
|
||||
endif
|
||||
OBJS += ../src/crypto/crypto_gnutls.o
|
||||
HOBJS += ../src/crypto/crypto_gnutls.o
|
||||
@ -489,6 +538,9 @@ OBJS += ../src/tls/pkcs8.o
|
||||
NEED_SHA256=y
|
||||
NEED_BASE64=y
|
||||
NEED_TLS_PRF=y
|
||||
ifdef CONFIG_TLSV12
|
||||
NEED_TLS_PRF_SHA256=y
|
||||
endif
|
||||
NEED_MODEXP=y
|
||||
NEED_CIPHER=y
|
||||
CFLAGS += -DCONFIG_TLS_INTERNAL
|
||||
@ -602,14 +654,19 @@ OBJS += $(AESOBJS)
|
||||
endif
|
||||
|
||||
ifdef NEED_SHA1
|
||||
ifneq ($(CONFIG_TLS), openssl)
|
||||
SHA1OBJS += ../src/crypto/sha1.o
|
||||
endif
|
||||
SHA1OBJS += ../src/crypto/sha1-prf.o
|
||||
ifdef CONFIG_INTERNAL_SHA1
|
||||
SHA1OBJS += ../src/crypto/sha1-internal.o
|
||||
ifdef NEED_FIPS186_2_PRF
|
||||
SHA1OBJS += ../src/crypto/fips_prf_internal.o
|
||||
endif
|
||||
endif
|
||||
ifneq ($(CONFIG_TLS), openssl)
|
||||
SHA1OBJS += ../src/crypto/sha1-pbkdf2.o
|
||||
endif
|
||||
ifdef NEED_T_PRF
|
||||
SHA1OBJS += ../src/crypto/sha1-tprf.o
|
||||
endif
|
||||
@ -625,6 +682,7 @@ endif
|
||||
ifdef NEED_MD5
|
||||
ifdef CONFIG_INTERNAL_MD5
|
||||
OBJS += ../src/crypto/md5-internal.o
|
||||
HOBJS += ../src/crypto/md5-internal.o
|
||||
endif
|
||||
endif
|
||||
|
||||
@ -647,10 +705,17 @@ endif
|
||||
endif
|
||||
|
||||
ifdef NEED_SHA256
|
||||
CFLAGS += -DCONFIG_SHA256
|
||||
ifneq ($(CONFIG_TLS), openssl)
|
||||
OBJS += ../src/crypto/sha256.o
|
||||
endif
|
||||
OBJS += ../src/crypto/sha256-prf.o
|
||||
ifdef CONFIG_INTERNAL_SHA256
|
||||
OBJS += ../src/crypto/sha256-internal.o
|
||||
endif
|
||||
ifdef NEED_TLS_PRF_SHA256
|
||||
OBJS += ../src/crypto/sha256-tlsprf.o
|
||||
endif
|
||||
endif
|
||||
|
||||
ifdef NEED_DH_GROUPS
|
||||
@ -665,6 +730,16 @@ OBJS += ../src/crypto/dh_group5.o
|
||||
endif
|
||||
endif
|
||||
|
||||
ifdef CONFIG_NO_RANDOM_POOL
|
||||
CFLAGS += -DCONFIG_NO_RANDOM_POOL
|
||||
else
|
||||
OBJS += ../src/crypto/random.o
|
||||
HOBJS += ../src/crypto/random.o
|
||||
HOBJS += ../src/utils/eloop.o
|
||||
HOBJS += $(SHA1OBJS)
|
||||
HOBJS += ../src/crypto/md5.o
|
||||
endif
|
||||
|
||||
ifdef CONFIG_RADIUS_SERVER
|
||||
CFLAGS += -DRADIUS_SERVER
|
||||
OBJS += ../src/radius/radius_server.o
|
||||
@ -689,7 +764,6 @@ OBJS += ../src/utils/base64.o
|
||||
endif
|
||||
|
||||
ifdef NEED_AP_MLME
|
||||
OBJS += ../src/ap/beacon.o
|
||||
OBJS += ../src/ap/wmm.o
|
||||
OBJS += ../src/ap/ap_list.o
|
||||
OBJS += ../src/ap/ieee802_11.o
|
||||
@ -700,10 +774,49 @@ ifdef CONFIG_IEEE80211N
|
||||
OBJS += ../src/ap/ieee802_11_ht.o
|
||||
endif
|
||||
|
||||
ifdef CONFIG_IEEE80211AC
|
||||
OBJS += ../src/ap/ieee802_11_vht.o
|
||||
endif
|
||||
|
||||
ifdef CONFIG_P2P_MANAGER
|
||||
CFLAGS += -DCONFIG_P2P_MANAGER
|
||||
OBJS += ../src/ap/p2p_hostapd.o
|
||||
endif
|
||||
|
||||
ifdef CONFIG_HS20
|
||||
CFLAGS += -DCONFIG_HS20
|
||||
OBJS += ../src/ap/hs20.o
|
||||
CONFIG_INTERWORKING=y
|
||||
endif
|
||||
|
||||
ifdef CONFIG_INTERWORKING
|
||||
CFLAGS += -DCONFIG_INTERWORKING
|
||||
OBJS += ../src/common/gas.o
|
||||
OBJS += ../src/ap/gas_serv.o
|
||||
endif
|
||||
|
||||
OBJS += ../src/drivers/driver_common.o
|
||||
|
||||
ifdef CONFIG_WPA_CLI_EDIT
|
||||
OBJS_c += ../src/utils/edit.o
|
||||
else
|
||||
OBJS_c += ../src/utils/edit_simple.o
|
||||
endif
|
||||
|
||||
ifdef CONFIG_NO_STDOUT_DEBUG
|
||||
CFLAGS += -DCONFIG_NO_STDOUT_DEBUG
|
||||
endif
|
||||
|
||||
ifdef CONFIG_DEBUG_FILE
|
||||
CFLAGS += -DCONFIG_DEBUG_FILE
|
||||
endif
|
||||
|
||||
ifdef CONFIG_SQLITE
|
||||
CFLAGS += -DCONFIG_SQLITE
|
||||
LIBS += -lsqlite3
|
||||
LIBS_h += -lsqlite3
|
||||
endif
|
||||
|
||||
ALL=hostapd hostapd_cli
|
||||
|
||||
all: verify_config $(ALL)
|
||||
@ -729,7 +842,8 @@ verify_config:
|
||||
fi
|
||||
|
||||
install: all
|
||||
for i in $(ALL); do cp -f $$i /usr/local/bin/$$i; done
|
||||
mkdir -p $(DESTDIR)/usr/local/bin
|
||||
for i in $(ALL); do cp -f $$i $(DESTDIR)/usr/local/bin/$$i; done
|
||||
|
||||
../src/drivers/build.hostapd:
|
||||
@if [ -f ../src/drivers/build.wpa_supplicant ]; then \
|
||||
@ -740,15 +854,15 @@ install: all
|
||||
BCHECK=../src/drivers/build.hostapd
|
||||
|
||||
hostapd: $(BCHECK) $(OBJS)
|
||||
$(CC) $(LDFLAGS) -o hostapd $(OBJS) $(LIBS)
|
||||
$(Q)$(CC) $(LDFLAGS) -o hostapd $(OBJS) $(LIBS)
|
||||
@$(E) " LD " $@
|
||||
|
||||
OBJS_c = hostapd_cli.o ../src/common/wpa_ctrl.o ../src/utils/os_$(CONFIG_OS).o
|
||||
ifdef CONFIG_WPA_TRACE
|
||||
OBJS_c += ../src/utils/trace.o
|
||||
OBJS_c += ../src/utils/wpa_debug.o
|
||||
endif
|
||||
hostapd_cli: $(OBJS_c)
|
||||
$(CC) $(LDFLAGS) -o hostapd_cli $(OBJS_c) $(LIBS_c)
|
||||
$(Q)$(CC) $(LDFLAGS) -o hostapd_cli $(OBJS_c) $(LIBS_c)
|
||||
@$(E) " LD " $@
|
||||
|
||||
NOBJS = nt_password_hash.o ../src/crypto/ms_funcs.o $(SHA1OBJS) ../src/crypto/md5.o
|
||||
ifdef NEED_RC4
|
||||
@ -778,10 +892,12 @@ HOBJS += ../src/crypto/aes-internal-enc.o
|
||||
endif
|
||||
|
||||
nt_password_hash: $(NOBJS)
|
||||
$(CC) $(LDFLAGS) -o nt_password_hash $(NOBJS) $(LIBS_n)
|
||||
$(Q)$(CC) $(LDFLAGS) -o nt_password_hash $(NOBJS) $(LIBS_n)
|
||||
@$(E) " LD " $@
|
||||
|
||||
hlr_auc_gw: $(HOBJS)
|
||||
$(CC) $(LDFLAGS) -o hlr_auc_gw $(HOBJS) $(LIBS_h)
|
||||
$(Q)$(CC) $(LDFLAGS) -o hlr_auc_gw $(HOBJS) $(LIBS_h)
|
||||
@$(E) " LD " $@
|
||||
|
||||
clean:
|
||||
$(MAKE) -C ../src clean
|
||||
|
@ -2,37 +2,22 @@ hostapd - user space IEEE 802.11 AP and IEEE 802.1X/WPA/WPA2/EAP
|
||||
Authenticator and RADIUS authentication server
|
||||
================================================================
|
||||
|
||||
Copyright (c) 2002-2010, Jouni Malinen <j@w1.fi> and contributors
|
||||
Copyright (c) 2002-2012, Jouni Malinen <j@w1.fi> and contributors
|
||||
All Rights Reserved.
|
||||
|
||||
This program is dual-licensed under both the GPL version 2 and BSD
|
||||
license. Either license may be used at your option.
|
||||
This program is licensed under the BSD license (the one with
|
||||
advertisement clause removed).
|
||||
|
||||
If you are submitting changes to the project, please see CONTRIBUTIONS
|
||||
file for more instructions.
|
||||
|
||||
|
||||
|
||||
License
|
||||
-------
|
||||
|
||||
GPL v2:
|
||||
|
||||
This program is free software; you can redistribute it and/or modify
|
||||
it under the terms of the GNU General Public License version 2 as
|
||||
published by the Free Software Foundation.
|
||||
|
||||
This program is distributed in the hope that it will be useful,
|
||||
but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||
GNU General Public License for more details.
|
||||
|
||||
You should have received a copy of the GNU General Public License
|
||||
along with this program; if not, write to the Free Software
|
||||
Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA
|
||||
|
||||
(this copy of the license is in COPYING file)
|
||||
|
||||
|
||||
Alternatively, this software may be distributed, used, and modified
|
||||
under the terms of BSD license:
|
||||
This software may be distributed, used, and modified under the terms of
|
||||
BSD license:
|
||||
|
||||
Redistribution and use in source and binary forms, with or without
|
||||
modification, are permitted provided that the following conditions are
|
||||
|
@ -63,8 +63,13 @@ includes WPS support and uses madwifi driver interface:
|
||||
CONFIG_DRIVER_MADWIFI=y
|
||||
CFLAGS += -I/usr/src/madwifi-0.9.3
|
||||
CONFIG_WPS=y
|
||||
CONFIG_WPS2=y
|
||||
CONFIG_WPS_UPNP=y
|
||||
|
||||
Following parameter can be used to enable support for NFC config method:
|
||||
|
||||
CONFIG_WPS_NFC=y
|
||||
|
||||
|
||||
Following section shows an example runtime configuration
|
||||
(hostapd.conf) that enables WPS:
|
||||
@ -119,6 +124,13 @@ pushbutton event (for PBC) to allow a new WPS Enrollee to join the
|
||||
network. hostapd uses the control interface as an input channel for
|
||||
these events.
|
||||
|
||||
The PIN value used in the commands must be processed by an UI to
|
||||
remove non-digit characters and potentially, to verify the checksum
|
||||
digit. "hostapd_cli wps_check_pin <PIN>" can be used to do such
|
||||
processing. It returns FAIL if the PIN is invalid, or FAIL-CHECKSUM if
|
||||
the checksum digit is incorrect, or the processed PIN (non-digit
|
||||
characters removed) if the PIN is valid.
|
||||
|
||||
When a client device (WPS Enrollee) connects to hostapd (WPS
|
||||
Registrar) in order to start PIN mode negotiation for WPS, an
|
||||
identifier (Enrollee UUID) is sent. hostapd will need to be configured
|
||||
@ -171,10 +183,17 @@ hostapd_cli wps_pin any 12345670
|
||||
|
||||
To reduce likelihood of PIN being used with other devices or of
|
||||
forgetting an active PIN available for potential attackers, expiration
|
||||
time can be set for the new PIN:
|
||||
time in seconds can be set for the new PIN (value 0 indicates no
|
||||
expiration):
|
||||
|
||||
hostapd_cli wps_pin any 12345670 300
|
||||
|
||||
If the MAC address of the enrollee is known, it should be configured
|
||||
to allow the AP to advertise list of authorized enrollees:
|
||||
|
||||
hostapd_cli wps_pin 53b63a98-d29e-4457-a2ed-094d7e6a669c \
|
||||
12345670 300 00:11:22:33:44:55
|
||||
|
||||
|
||||
After this, the Enrollee can connect to the AP again and complete WPS
|
||||
negotiation. At that point, a new, random WPA PSK is generated for the
|
||||
@ -221,6 +240,17 @@ hostapd_cli wps_ap_pin set <PIN> [timeout]
|
||||
- if the optional timeout parameter is given, the AP PIN will be enabled
|
||||
for the specified number of seconds
|
||||
|
||||
hostapd_cli get_config
|
||||
- display the current configuration
|
||||
|
||||
hostapd_cli wps_config <new SSID> <auth> <encr> <new key>
|
||||
examples:
|
||||
hostapd_cli wps_config testing WPA2PSK CCMP 12345678
|
||||
hostapd_cli wps_config "no security" OPEN NONE ""
|
||||
|
||||
<auth> must be one of the following: OPEN WPAPSK WPA2PSK
|
||||
<encr> must be one of the following: NONE WEP TKIP CCMP
|
||||
|
||||
|
||||
Credential generation and configuration changes
|
||||
-----------------------------------------------
|
||||
@ -251,7 +281,7 @@ WPS-REG-SUCCESS <Enrollee MAC address <UUID-E>
|
||||
For example:
|
||||
<2>WPS-REG-SUCCESS 02:66:a0:ee:17:27 2b7093f1-d6fb-5108-adbb-bea66bb87333
|
||||
|
||||
This can be used to tricker change from unconfigured to configured
|
||||
This can be used to trigger change from unconfigured to configured
|
||||
state (random configuration based on the first successful WPS
|
||||
registration). In addition, this can be used to update AP UI about the
|
||||
status of WPS registration progress.
|
||||
@ -263,3 +293,48 @@ For example:
|
||||
|
||||
This can be used to update the externally stored AP configuration and
|
||||
then update hostapd configuration (followed by restarting of hostapd).
|
||||
|
||||
|
||||
WPS with NFC
|
||||
------------
|
||||
|
||||
WPS can be used with NFC-based configuration method. An NFC tag
|
||||
containing a password token from the Enrollee can be used to
|
||||
authenticate the connection instead of the PIN. In addition, an NFC tag
|
||||
with a configuration token can be used to transfer AP settings without
|
||||
going through the WPS protocol.
|
||||
|
||||
When the AP acts as an Enrollee, a local NFC tag with a password token
|
||||
can be used by touching the NFC interface of an external Registrar. The
|
||||
wps_nfc_token command is used to manage use of the NFC password token
|
||||
from the AP. "wps_nfc_token enable" enables the use of the AP's NFC
|
||||
password token (in place of AP PIN) and "wps_nfc_token disable" disables
|
||||
the NFC password token.
|
||||
|
||||
The NFC password token that is either pre-configured in the
|
||||
configuration file (wps_nfc_dev_pw_id, wps_nfc_dh_pubkey,
|
||||
wps_nfc_dh_privkey, wps_nfc_dev_pw) or generated dynamically with
|
||||
"wps_nfc_token <WPS|NDEF>" command. The nfc_pw_token tool from
|
||||
wpa_supplicant can be used to generate NFC password tokens during
|
||||
manufacturing (each AP needs to have its own random keys).
|
||||
|
||||
The "wps_nfc_config_token <WPS/NDEF>" command can be used to build an
|
||||
NFC configuration token. The output value from this command is a hexdump
|
||||
of the current AP configuration (WPS parameter requests this to include
|
||||
only the WPS attributes; NDEF parameter requests additional NDEF
|
||||
encapsulation to be included). This data needs to be written to an NFC
|
||||
tag with an external program. Once written, the NFC configuration token
|
||||
can be used to touch an NFC interface on a station to provision the
|
||||
credentials needed to access the network.
|
||||
|
||||
When the NFC device on the AP reads an NFC tag with a MIME media type
|
||||
"application/vnd.wfa.wsc", the NDEF message payload (with or without
|
||||
NDEF encapsulation) can be delivered to hostapd using the
|
||||
following hostapd_cli command:
|
||||
|
||||
wps_nfc_tag_read <hexdump of payload>
|
||||
|
||||
If the NFC tag contains a password token, the token is added to the
|
||||
internal Registrar. This allows station Enrollee from which the password
|
||||
token was received to run through WPS protocol to provision the
|
||||
credential.
|
||||
|
File diff suppressed because it is too large
Load Diff
@ -2,19 +2,16 @@
|
||||
* hostapd / Configuration file parser
|
||||
* Copyright (c) 2003-2009, Jouni Malinen <j@w1.fi>
|
||||
*
|
||||
* This program is free software; you can redistribute it and/or modify
|
||||
* it under the terms of the GNU General Public License version 2 as
|
||||
* published by the Free Software Foundation.
|
||||
*
|
||||
* Alternatively, this software may be distributed under the terms of BSD
|
||||
* license.
|
||||
*
|
||||
* See README and COPYING for more details.
|
||||
* This software may be distributed under the terms of the BSD license.
|
||||
* See README for more details.
|
||||
*/
|
||||
|
||||
#ifndef CONFIG_FILE_H
|
||||
#define CONFIG_FILE_H
|
||||
|
||||
struct hostapd_config * hostapd_config_read(const char *fname);
|
||||
int hostapd_set_iface(struct hostapd_config *conf,
|
||||
struct hostapd_bss_config *bss, char *field,
|
||||
char *value);
|
||||
|
||||
#endif /* CONFIG_FILE_H */
|
||||
|
File diff suppressed because it is too large
Load Diff
@ -2,14 +2,8 @@
|
||||
* hostapd / UNIX domain socket -based control interface
|
||||
* Copyright (c) 2004, Jouni Malinen <j@w1.fi>
|
||||
*
|
||||
* This program is free software; you can redistribute it and/or modify
|
||||
* it under the terms of the GNU General Public License version 2 as
|
||||
* published by the Free Software Foundation.
|
||||
*
|
||||
* Alternatively, this software may be distributed under the terms of BSD
|
||||
* license.
|
||||
*
|
||||
* See README and COPYING for more details.
|
||||
* This software may be distributed under the terms of the BSD license.
|
||||
* See README for more details.
|
||||
*/
|
||||
|
||||
#ifndef CTRL_IFACE_H
|
||||
@ -18,6 +12,8 @@
|
||||
#ifndef CONFIG_NO_CTRL_IFACE
|
||||
int hostapd_ctrl_iface_init(struct hostapd_data *hapd);
|
||||
void hostapd_ctrl_iface_deinit(struct hostapd_data *hapd);
|
||||
int hostapd_global_ctrl_iface_init(struct hapd_interfaces *interface);
|
||||
void hostapd_global_ctrl_iface_deinit(struct hapd_interfaces *interface);
|
||||
#else /* CONFIG_NO_CTRL_IFACE */
|
||||
static inline int hostapd_ctrl_iface_init(struct hostapd_data *hapd)
|
||||
{
|
||||
@ -27,6 +23,17 @@ static inline int hostapd_ctrl_iface_init(struct hostapd_data *hapd)
|
||||
static inline void hostapd_ctrl_iface_deinit(struct hostapd_data *hapd)
|
||||
{
|
||||
}
|
||||
|
||||
static inline int
|
||||
hostapd_global_ctrl_iface_init(struct hapd_interfaces *interface)
|
||||
{
|
||||
return 0;
|
||||
}
|
||||
|
||||
static inline void
|
||||
hostapd_global_ctrl_iface_deinit(struct hapd_interfaces *interface)
|
||||
{
|
||||
}
|
||||
#endif /* CONFIG_NO_CTRL_IFACE */
|
||||
|
||||
#endif /* CTRL_IFACE_H */
|
||||
|
@ -20,13 +20,7 @@ CONFIG_DRIVER_HOSTAP=y
|
||||
#CFLAGS += -I../../madwifi # change to the madwifi source directory
|
||||
|
||||
# Driver interface for drivers using the nl80211 kernel interface
|
||||
#CONFIG_DRIVER_NL80211=y
|
||||
# driver_nl80211.c requires a rather new libnl (version 1.1) which may not be
|
||||
# shipped with your distribution yet. If that is the case, you need to build
|
||||
# newer libnl version and point the hostapd build to use it.
|
||||
#LIBNL=/usr/src/libnl
|
||||
#CFLAGS += -I$(LIBNL)/include
|
||||
#LIBS += -L$(LIBNL)/lib
|
||||
CONFIG_DRIVER_NL80211=y
|
||||
|
||||
# Driver interface for FreeBSD net80211 layer (e.g., Atheros driver)
|
||||
#CONFIG_DRIVER_BSD=y
|
||||
@ -90,6 +84,9 @@ CONFIG_EAP_TTLS=y
|
||||
# EAP-PSK for the integrated EAP server (this is _not_ needed for WPA-PSK)
|
||||
#CONFIG_EAP_PSK=y
|
||||
|
||||
# EAP-pwd for the integrated EAP server (secure authentication with a password)
|
||||
#CONFIG_EAP_PWD=y
|
||||
|
||||
# EAP-SAKE for the integrated EAP server
|
||||
#CONFIG_EAP_SAKE=y
|
||||
|
||||
@ -107,8 +104,12 @@ CONFIG_EAP_TTLS=y
|
||||
|
||||
# Wi-Fi Protected Setup (WPS)
|
||||
#CONFIG_WPS=y
|
||||
# Enable WSC 2.0 support
|
||||
#CONFIG_WPS2=y
|
||||
# Enable UPnP support for external WPS Registrars
|
||||
#CONFIG_WPS_UPNP=y
|
||||
# Enable WPS support with NFC config method
|
||||
#CONFIG_WPS_NFC=y
|
||||
|
||||
# EAP-IKEv2
|
||||
#CONFIG_EAP_IKEV2=y
|
||||
@ -137,11 +138,22 @@ CONFIG_IPV6=y
|
||||
# IEEE 802.11n (High Throughput) support
|
||||
#CONFIG_IEEE80211N=y
|
||||
|
||||
# Wireless Network Management (IEEE Std 802.11v-2011)
|
||||
# Note: This is experimental and not complete implementation.
|
||||
#CONFIG_WNM=y
|
||||
|
||||
# IEEE 802.11ac (Very High Throughput) support
|
||||
#CONFIG_IEEE80211AC=y
|
||||
|
||||
# Remove debugging code that is printing out debug messages to stdout.
|
||||
# This can be used to reduce the size of the hostapd considerably if debugging
|
||||
# code is not needed.
|
||||
#CONFIG_NO_STDOUT_DEBUG=y
|
||||
|
||||
# Add support for writing debug log to a file: -f /tmp/hostapd.log
|
||||
# Disabled by default.
|
||||
#CONFIG_DEBUG_FILE=y
|
||||
|
||||
# Remove support for RADIUS accounting
|
||||
#CONFIG_NO_ACCOUNTING=y
|
||||
|
||||
@ -151,6 +163,14 @@ CONFIG_IPV6=y
|
||||
# Remove support for VLANs
|
||||
#CONFIG_NO_VLAN=y
|
||||
|
||||
# Enable support for fully dynamic VLANs. This enables hostapd to
|
||||
# automatically create bridge and VLAN interfaces if necessary.
|
||||
#CONFIG_FULL_DYNAMIC_VLAN=y
|
||||
|
||||
# Use netlink-based kernel API for VLAN operations instead of ioctl()
|
||||
# Note: This requires libnl 3.1 or newer.
|
||||
#CONFIG_VLAN_NETLINK=y
|
||||
|
||||
# Remove support for dumping state into a file on SIGUSR1 signal
|
||||
# This can be used to reduce binary size at the cost of disabling a debugging
|
||||
# option.
|
||||
@ -173,3 +193,77 @@ CONFIG_IPV6=y
|
||||
#LIBS += -lbfd -liberty -lz
|
||||
#LIBS_p += -lbfd -liberty -lz
|
||||
#LIBS_c += -lbfd -liberty -lz
|
||||
|
||||
# hostapd depends on strong random number generation being available from the
|
||||
# operating system. os_get_random() function is used to fetch random data when
|
||||
# needed, e.g., for key generation. On Linux and BSD systems, this works by
|
||||
# reading /dev/urandom. It should be noted that the OS entropy pool needs to be
|
||||
# properly initialized before hostapd is started. This is important especially
|
||||
# on embedded devices that do not have a hardware random number generator and
|
||||
# may by default start up with minimal entropy available for random number
|
||||
# generation.
|
||||
#
|
||||
# As a safety net, hostapd is by default trying to internally collect
|
||||
# additional entropy for generating random data to mix in with the data
|
||||
# fetched from the OS. This by itself is not considered to be very strong, but
|
||||
# it may help in cases where the system pool is not initialized properly.
|
||||
# However, it is very strongly recommended that the system pool is initialized
|
||||
# with enough entropy either by using hardware assisted random number
|
||||
# generator or by storing state over device reboots.
|
||||
#
|
||||
# hostapd can be configured to maintain its own entropy store over restarts to
|
||||
# enhance random number generation. This is not perfect, but it is much more
|
||||
# secure than using the same sequence of random numbers after every reboot.
|
||||
# This can be enabled with -e<entropy file> command line option. The specified
|
||||
# file needs to be readable and writable by hostapd.
|
||||
#
|
||||
# If the os_get_random() is known to provide strong random data (e.g., on
|
||||
# Linux/BSD, the board in question is known to have reliable source of random
|
||||
# data from /dev/urandom), the internal hostapd random pool can be disabled.
|
||||
# This will save some in binary size and CPU use. However, this should only be
|
||||
# considered for builds that are known to be used on devices that meet the
|
||||
# requirements described above.
|
||||
#CONFIG_NO_RANDOM_POOL=y
|
||||
|
||||
# Select TLS implementation
|
||||
# openssl = OpenSSL (default)
|
||||
# gnutls = GnuTLS
|
||||
# internal = Internal TLSv1 implementation (experimental)
|
||||
# none = Empty template
|
||||
#CONFIG_TLS=openssl
|
||||
|
||||
# TLS-based EAP methods require at least TLS v1.0. Newer version of TLS (v1.1)
|
||||
# can be enabled to get a stronger construction of messages when block ciphers
|
||||
# are used.
|
||||
#CONFIG_TLSV11=y
|
||||
|
||||
# TLS-based EAP methods require at least TLS v1.0. Newer version of TLS (v1.2)
|
||||
# can be enabled to enable use of stronger crypto algorithms.
|
||||
#CONFIG_TLSV12=y
|
||||
|
||||
# If CONFIG_TLS=internal is used, additional library and include paths are
|
||||
# needed for LibTomMath. Alternatively, an integrated, minimal version of
|
||||
# LibTomMath can be used. See beginning of libtommath.c for details on benefits
|
||||
# and drawbacks of this option.
|
||||
#CONFIG_INTERNAL_LIBTOMMATH=y
|
||||
#ifndef CONFIG_INTERNAL_LIBTOMMATH
|
||||
#LTM_PATH=/usr/src/libtommath-0.39
|
||||
#CFLAGS += -I$(LTM_PATH)
|
||||
#LIBS += -L$(LTM_PATH)
|
||||
#LIBS_p += -L$(LTM_PATH)
|
||||
#endif
|
||||
# At the cost of about 4 kB of additional binary size, the internal LibTomMath
|
||||
# can be configured to include faster routines for exptmod, sqr, and div to
|
||||
# speed up DH and RSA calculation considerably
|
||||
#CONFIG_INTERNAL_LIBTOMMATH_FAST=y
|
||||
|
||||
# Interworking (IEEE 802.11u)
|
||||
# This can be used to enable functionality to improve interworking with
|
||||
# external networks.
|
||||
#CONFIG_INTERWORKING=y
|
||||
|
||||
# Hotspot 2.0
|
||||
#CONFIG_HS20=y
|
||||
|
||||
# Enable SQLite database support in hlr_auc_gw, EAP-SIM DB, and eap_user_file
|
||||
#CONFIG_SQLITE=y
|
||||
|
@ -2,17 +2,12 @@
|
||||
* hostapd / State dump
|
||||
* Copyright (c) 2002-2009, Jouni Malinen <j@w1.fi>
|
||||
*
|
||||
* This program is free software; you can redistribute it and/or modify
|
||||
* it under the terms of the GNU General Public License version 2 as
|
||||
* published by the Free Software Foundation.
|
||||
*
|
||||
* Alternatively, this software may be distributed under the terms of BSD
|
||||
* license.
|
||||
*
|
||||
* See README and COPYING for more details.
|
||||
* This software may be distributed under the terms of the BSD license.
|
||||
* See README for more details.
|
||||
*/
|
||||
|
||||
#include "utils/includes.h"
|
||||
#include <time.h>
|
||||
|
||||
#include "utils/common.h"
|
||||
#include "radius/radius_client.h"
|
||||
@ -106,7 +101,8 @@ static void hostapd_dump_state(struct hostapd_data *hapd)
|
||||
fprintf(f, "\nSTA=" MACSTR "\n", MAC2STR(sta->addr));
|
||||
|
||||
fprintf(f,
|
||||
" AID=%d flags=0x%x %s%s%s%s%s%s%s%s%s%s%s%s%s%s%s\n"
|
||||
" AID=%d flags=0x%x %s%s%s%s%s%s%s%s%s%s%s%s%s%s%s%s"
|
||||
"\n"
|
||||
" capability=0x%x listen_interval=%d\n",
|
||||
sta->aid,
|
||||
sta->flags,
|
||||
@ -115,8 +111,7 @@ static void hostapd_dump_state(struct hostapd_data *hapd)
|
||||
(sta->flags & WLAN_STA_PS ? "[PS]" : ""),
|
||||
(sta->flags & WLAN_STA_TIM ? "[TIM]" : ""),
|
||||
(sta->flags & WLAN_STA_PERM ? "[PERM]" : ""),
|
||||
(sta->flags & WLAN_STA_AUTHORIZED ? "[AUTHORIZED]" :
|
||||
""),
|
||||
(ap_sta_is_authorized(sta) ? "[AUTHORIZED]" : ""),
|
||||
(sta->flags & WLAN_STA_PENDING_POLL ? "[PENDING_POLL" :
|
||||
""),
|
||||
(sta->flags & WLAN_STA_SHORT_PREAMBLE ?
|
||||
@ -128,6 +123,7 @@ static void hostapd_dump_state(struct hostapd_data *hapd)
|
||||
(sta->flags & WLAN_STA_MAYBE_WPS ? "[MAYBE_WPS]" : ""),
|
||||
(sta->flags & WLAN_STA_WDS ? "[WDS]" : ""),
|
||||
(sta->flags & WLAN_STA_NONERP ? "[NonERP]" : ""),
|
||||
(sta->flags & WLAN_STA_WPS2 ? "[WPS2]" : ""),
|
||||
sta->capability,
|
||||
sta->listen_interval);
|
||||
|
||||
|
@ -2,14 +2,8 @@
|
||||
* hostapd / State dump
|
||||
* Copyright (c) 2002-2009, Jouni Malinen <j@w1.fi>
|
||||
*
|
||||
* This program is free software; you can redistribute it and/or modify
|
||||
* it under the terms of the GNU General Public License version 2 as
|
||||
* published by the Free Software Foundation.
|
||||
*
|
||||
* Alternatively, this software may be distributed under the terms of BSD
|
||||
* license.
|
||||
*
|
||||
* See README and COPYING for more details.
|
||||
* This software may be distributed under the terms of the BSD license.
|
||||
* See README for more details.
|
||||
*/
|
||||
|
||||
#ifndef DUMP_STATE_H
|
||||
|
@ -2,14 +2,8 @@
|
||||
* EAP method registration
|
||||
* Copyright (c) 2004-2009, Jouni Malinen <j@w1.fi>
|
||||
*
|
||||
* This program is free software; you can redistribute it and/or modify
|
||||
* it under the terms of the GNU General Public License version 2 as
|
||||
* published by the Free Software Foundation.
|
||||
*
|
||||
* Alternatively, this software may be distributed under the terms of BSD
|
||||
* license.
|
||||
*
|
||||
* See README and COPYING for more details.
|
||||
* This software may be distributed under the terms of the BSD license.
|
||||
* See README for more details.
|
||||
*/
|
||||
|
||||
#include "includes.h"
|
||||
@ -45,6 +39,11 @@ int eap_server_register_methods(void)
|
||||
ret = eap_server_tls_register();
|
||||
#endif /* EAP_SERVER_TLS */
|
||||
|
||||
#ifdef EAP_SERVER_UNAUTH_TLS
|
||||
if (ret == 0)
|
||||
ret = eap_server_unauth_tls_register();
|
||||
#endif /* EAP_SERVER_TLS */
|
||||
|
||||
#ifdef EAP_SERVER_MSCHAPV2
|
||||
if (ret == 0)
|
||||
ret = eap_server_mschapv2_register();
|
||||
@ -130,5 +129,10 @@ int eap_server_register_methods(void)
|
||||
ret = eap_server_tnc_register();
|
||||
#endif /* EAP_SERVER_TNC */
|
||||
|
||||
#ifdef EAP_SERVER_PWD
|
||||
if (ret == 0)
|
||||
ret = eap_server_pwd_register();
|
||||
#endif /* EAP_SERVER_PWD */
|
||||
|
||||
return ret;
|
||||
}
|
||||
|
@ -2,14 +2,8 @@
|
||||
* EAP method registration
|
||||
* Copyright (c) 2004-2009, Jouni Malinen <j@w1.fi>
|
||||
*
|
||||
* This program is free software; you can redistribute it and/or modify
|
||||
* it under the terms of the GNU General Public License version 2 as
|
||||
* published by the Free Software Foundation.
|
||||
*
|
||||
* Alternatively, this software may be distributed under the terms of BSD
|
||||
* license.
|
||||
*
|
||||
* See README and COPYING for more details.
|
||||
* This software may be distributed under the terms of the BSD license.
|
||||
* See README for more details.
|
||||
*/
|
||||
|
||||
#ifndef EAP_REGISTER_H
|
||||
|
@ -1,15 +1,9 @@
|
||||
/*
|
||||
* HLR/AuC testing gateway for hostapd EAP-SIM/AKA database/authenticator
|
||||
* Copyright (c) 2005-2007, Jouni Malinen <j@w1.fi>
|
||||
* Copyright (c) 2005-2007, 2012, Jouni Malinen <j@w1.fi>
|
||||
*
|
||||
* This program is free software; you can redistribute it and/or modify
|
||||
* it under the terms of the GNU General Public License version 2 as
|
||||
* published by the Free Software Foundation.
|
||||
*
|
||||
* Alternatively, this software may be distributed under the terms of BSD
|
||||
* license.
|
||||
*
|
||||
* See README and COPYING for more details.
|
||||
* This software may be distributed under the terms of the BSD license.
|
||||
* See README for more details.
|
||||
*
|
||||
* This is an example implementation of the EAP-SIM/AKA database/authentication
|
||||
* gateway interface to HLR/AuC. It is expected to be replaced with an
|
||||
@ -40,18 +34,30 @@
|
||||
* text file in IMSI:Kc:SRES:RAND format, IMSI in ASCII, other fields as hex
|
||||
* strings. This is used to simulate an HLR/AuC. As such, it is not very useful
|
||||
* for real life authentication, but it is useful both as an example
|
||||
* implementation and for EAP-SIM testing.
|
||||
* implementation and for EAP-SIM/AKA/AKA' testing.
|
||||
*
|
||||
* SQN generation follows the not time-based Profile 2 described in
|
||||
* 3GPP TS 33.102 Annex C.3.2. The length of IND is 5 bits by default, but this
|
||||
* can be changed with a command line options if needed.
|
||||
*/
|
||||
|
||||
#include "includes.h"
|
||||
#include <sys/un.h>
|
||||
#ifdef CONFIG_SQLITE
|
||||
#include <sqlite3.h>
|
||||
#endif /* CONFIG_SQLITE */
|
||||
|
||||
#include "common.h"
|
||||
#include "crypto/milenage.h"
|
||||
#include "crypto/random.h"
|
||||
|
||||
static const char *default_socket_path = "/tmp/hlr_auc_gw.sock";
|
||||
static const char *socket_path;
|
||||
static int serv_sock = -1;
|
||||
static char *milenage_file = NULL;
|
||||
static int update_milenage = 0;
|
||||
static int sqn_changes = 0;
|
||||
static int ind_len = 5;
|
||||
|
||||
/* GSM triplets */
|
||||
struct gsm_triplet {
|
||||
@ -72,6 +78,7 @@ struct milenage_parameters {
|
||||
u8 opc[16];
|
||||
u8 amf[2];
|
||||
u8 sqn[6];
|
||||
int set;
|
||||
};
|
||||
|
||||
static struct milenage_parameters *milenage_db = NULL;
|
||||
@ -86,6 +93,144 @@ static struct milenage_parameters *milenage_db = NULL;
|
||||
#define EAP_AKA_CK_LEN 16
|
||||
|
||||
|
||||
#ifdef CONFIG_SQLITE
|
||||
|
||||
static sqlite3 *sqlite_db = NULL;
|
||||
static struct milenage_parameters db_tmp_milenage;
|
||||
|
||||
|
||||
static int db_table_exists(sqlite3 *db, const char *name)
|
||||
{
|
||||
char cmd[128];
|
||||
os_snprintf(cmd, sizeof(cmd), "SELECT 1 FROM %s;", name);
|
||||
return sqlite3_exec(db, cmd, NULL, NULL, NULL) == SQLITE_OK;
|
||||
}
|
||||
|
||||
|
||||
static int db_table_create_milenage(sqlite3 *db)
|
||||
{
|
||||
char *err = NULL;
|
||||
const char *sql =
|
||||
"CREATE TABLE milenage("
|
||||
" imsi INTEGER PRIMARY KEY NOT NULL,"
|
||||
" ki CHAR(32) NOT NULL,"
|
||||
" opc CHAR(32) NOT NULL,"
|
||||
" amf CHAR(4) NOT NULL,"
|
||||
" sqn CHAR(12) NOT NULL"
|
||||
");";
|
||||
|
||||
printf("Adding database table for milenage information\n");
|
||||
if (sqlite3_exec(db, sql, NULL, NULL, &err) != SQLITE_OK) {
|
||||
printf("SQLite error: %s\n", err);
|
||||
sqlite3_free(err);
|
||||
return -1;
|
||||
}
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
|
||||
static sqlite3 * db_open(const char *db_file)
|
||||
{
|
||||
sqlite3 *db;
|
||||
|
||||
if (sqlite3_open(db_file, &db)) {
|
||||
printf("Failed to open database %s: %s\n",
|
||||
db_file, sqlite3_errmsg(db));
|
||||
sqlite3_close(db);
|
||||
return NULL;
|
||||
}
|
||||
|
||||
if (!db_table_exists(db, "milenage") &&
|
||||
db_table_create_milenage(db) < 0) {
|
||||
sqlite3_close(db);
|
||||
return NULL;
|
||||
}
|
||||
|
||||
return db;
|
||||
}
|
||||
|
||||
|
||||
static int get_milenage_cb(void *ctx, int argc, char *argv[], char *col[])
|
||||
{
|
||||
struct milenage_parameters *m = ctx;
|
||||
int i;
|
||||
|
||||
m->set = 1;
|
||||
|
||||
for (i = 0; i < argc; i++) {
|
||||
if (os_strcmp(col[i], "ki") == 0 && argv[i] &&
|
||||
hexstr2bin(argv[i], m->ki, sizeof(m->ki))) {
|
||||
printf("Invalid ki value in database\n");
|
||||
return -1;
|
||||
}
|
||||
|
||||
if (os_strcmp(col[i], "opc") == 0 && argv[i] &&
|
||||
hexstr2bin(argv[i], m->opc, sizeof(m->opc))) {
|
||||
printf("Invalid opcvalue in database\n");
|
||||
return -1;
|
||||
}
|
||||
|
||||
if (os_strcmp(col[i], "amf") == 0 && argv[i] &&
|
||||
hexstr2bin(argv[i], m->amf, sizeof(m->amf))) {
|
||||
printf("Invalid amf value in database\n");
|
||||
return -1;
|
||||
}
|
||||
|
||||
if (os_strcmp(col[i], "sqn") == 0 && argv[i] &&
|
||||
hexstr2bin(argv[i], m->sqn, sizeof(m->sqn))) {
|
||||
printf("Invalid sqn value in database\n");
|
||||
return -1;
|
||||
}
|
||||
}
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
|
||||
static struct milenage_parameters * db_get_milenage(const char *imsi_txt)
|
||||
{
|
||||
char cmd[128];
|
||||
unsigned long long imsi;
|
||||
|
||||
os_memset(&db_tmp_milenage, 0, sizeof(db_tmp_milenage));
|
||||
imsi = atoll(imsi_txt);
|
||||
os_snprintf(db_tmp_milenage.imsi, sizeof(db_tmp_milenage.imsi),
|
||||
"%llu", imsi);
|
||||
os_snprintf(cmd, sizeof(cmd),
|
||||
"SELECT ki,opc,amf,sqn FROM milenage WHERE imsi=%llu;",
|
||||
imsi);
|
||||
if (sqlite3_exec(sqlite_db, cmd, get_milenage_cb, &db_tmp_milenage,
|
||||
NULL) != SQLITE_OK)
|
||||
return NULL;
|
||||
|
||||
if (!db_tmp_milenage.set)
|
||||
return NULL;
|
||||
return &db_tmp_milenage;
|
||||
}
|
||||
|
||||
|
||||
static int db_update_milenage_sqn(struct milenage_parameters *m)
|
||||
{
|
||||
char cmd[128], val[13], *pos;
|
||||
|
||||
pos = val;
|
||||
pos += wpa_snprintf_hex(pos, sizeof(val), m->sqn, 6);
|
||||
*pos = '\0';
|
||||
os_snprintf(cmd, sizeof(cmd),
|
||||
"UPDATE milenage SET sqn='%s' WHERE imsi=%s;",
|
||||
val, m->imsi);
|
||||
if (sqlite3_exec(sqlite_db, cmd, NULL, NULL, NULL) != SQLITE_OK) {
|
||||
printf("Failed to update SQN in database for IMSI %s\n",
|
||||
m->imsi);
|
||||
return -1;
|
||||
}
|
||||
return 0;
|
||||
}
|
||||
|
||||
#endif /* CONFIG_SQLITE */
|
||||
|
||||
|
||||
static int open_socket(const char *path)
|
||||
{
|
||||
struct sockaddr_un addr;
|
||||
@ -101,7 +246,7 @@ static int open_socket(const char *path)
|
||||
addr.sun_family = AF_UNIX;
|
||||
os_strlcpy(addr.sun_path, path, sizeof(addr.sun_path));
|
||||
if (bind(s, (struct sockaddr *) &addr, sizeof(addr)) < 0) {
|
||||
perror("bind(PF_UNIX)");
|
||||
perror("hlr-auc-gw: bind(PF_UNIX)");
|
||||
close(s);
|
||||
return -1;
|
||||
}
|
||||
@ -215,7 +360,7 @@ static int read_gsm_triplets(const char *fname)
|
||||
gsm_db = g;
|
||||
g = NULL;
|
||||
}
|
||||
free(g);
|
||||
os_free(g);
|
||||
|
||||
fclose(f);
|
||||
|
||||
@ -365,7 +510,7 @@ static int read_milenage(const char *fname)
|
||||
milenage_db = m;
|
||||
m = NULL;
|
||||
}
|
||||
free(m);
|
||||
os_free(m);
|
||||
|
||||
fclose(f);
|
||||
|
||||
@ -373,6 +518,80 @@ static int read_milenage(const char *fname)
|
||||
}
|
||||
|
||||
|
||||
static void update_milenage_file(const char *fname)
|
||||
{
|
||||
FILE *f, *f2;
|
||||
char buf[500], *pos;
|
||||
char *end = buf + sizeof(buf);
|
||||
struct milenage_parameters *m;
|
||||
size_t imsi_len;
|
||||
|
||||
f = fopen(fname, "r");
|
||||
if (f == NULL) {
|
||||
printf("Could not open Milenage data file '%s'\n", fname);
|
||||
return;
|
||||
}
|
||||
|
||||
snprintf(buf, sizeof(buf), "%s.new", fname);
|
||||
f2 = fopen(buf, "w");
|
||||
if (f2 == NULL) {
|
||||
printf("Could not write Milenage data file '%s'\n", buf);
|
||||
fclose(f);
|
||||
return;
|
||||
}
|
||||
|
||||
while (fgets(buf, sizeof(buf), f)) {
|
||||
/* IMSI Ki OPc AMF SQN */
|
||||
buf[sizeof(buf) - 1] = '\0';
|
||||
|
||||
pos = strchr(buf, ' ');
|
||||
if (buf[0] == '#' || pos == NULL || pos - buf >= 20)
|
||||
goto no_update;
|
||||
|
||||
imsi_len = pos - buf;
|
||||
|
||||
for (m = milenage_db; m; m = m->next) {
|
||||
if (strncmp(buf, m->imsi, imsi_len) == 0 &&
|
||||
m->imsi[imsi_len] == '\0')
|
||||
break;
|
||||
}
|
||||
|
||||
if (!m)
|
||||
goto no_update;
|
||||
|
||||
pos = buf;
|
||||
pos += snprintf(pos, end - pos, "%s ", m->imsi);
|
||||
pos += wpa_snprintf_hex(pos, end - pos, m->ki, 16);
|
||||
*pos++ = ' ';
|
||||
pos += wpa_snprintf_hex(pos, end - pos, m->opc, 16);
|
||||
*pos++ = ' ';
|
||||
pos += wpa_snprintf_hex(pos, end - pos, m->amf, 2);
|
||||
*pos++ = ' ';
|
||||
pos += wpa_snprintf_hex(pos, end - pos, m->sqn, 6);
|
||||
*pos++ = '\n';
|
||||
|
||||
no_update:
|
||||
fprintf(f2, "%s", buf);
|
||||
}
|
||||
|
||||
fclose(f2);
|
||||
fclose(f);
|
||||
|
||||
snprintf(buf, sizeof(buf), "%s.bak", fname);
|
||||
if (rename(fname, buf) < 0) {
|
||||
perror("rename");
|
||||
return;
|
||||
}
|
||||
|
||||
snprintf(buf, sizeof(buf), "%s.new", fname);
|
||||
if (rename(buf, fname) < 0) {
|
||||
perror("rename");
|
||||
return;
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
|
||||
static struct milenage_parameters * get_milenage(const char *imsi)
|
||||
{
|
||||
struct milenage_parameters *m = milenage_db;
|
||||
@ -383,6 +602,11 @@ static struct milenage_parameters * get_milenage(const char *imsi)
|
||||
m = m->next;
|
||||
}
|
||||
|
||||
#ifdef CONFIG_SQLITE
|
||||
if (!m)
|
||||
m = db_get_milenage(imsi);
|
||||
#endif /* CONFIG_SQLITE */
|
||||
|
||||
return m;
|
||||
}
|
||||
|
||||
@ -418,7 +642,7 @@ static void sim_req_auth(int s, struct sockaddr_un *from, socklen_t fromlen,
|
||||
if (m) {
|
||||
u8 _rand[16], sres[4], kc[8];
|
||||
for (count = 0; count < max_chal; count++) {
|
||||
if (os_get_random(_rand, 16) < 0)
|
||||
if (random_get_bytes(_rand, 16) < 0)
|
||||
return;
|
||||
gsm_milenage(m->opc, m->ki, _rand, sres, kc);
|
||||
*rpos++ = ' ';
|
||||
@ -465,6 +689,28 @@ send:
|
||||
}
|
||||
|
||||
|
||||
static void inc_sqn(u8 *sqn)
|
||||
{
|
||||
u64 val, seq, ind;
|
||||
|
||||
/*
|
||||
* SQN = SEQ | IND = SEQ1 | SEQ2 | IND
|
||||
*
|
||||
* The mechanism used here is not time-based, so SEQ2 is void and
|
||||
* SQN = SEQ1 | IND. The length of IND is ind_len bits and the length
|
||||
* of SEQ1 is 48 - ind_len bits.
|
||||
*/
|
||||
|
||||
/* Increment both SEQ and IND by one */
|
||||
val = ((u64) WPA_GET_BE32(sqn) << 16) | ((u64) WPA_GET_BE16(sqn + 4));
|
||||
seq = (val >> ind_len) + 1;
|
||||
ind = (val + 1) & ((1 << ind_len) - 1);
|
||||
val = (seq << ind_len) | ind;
|
||||
WPA_PUT_BE32(sqn, val >> 16);
|
||||
WPA_PUT_BE16(sqn + 4, val & 0xffff);
|
||||
}
|
||||
|
||||
|
||||
static void aka_req_auth(int s, struct sockaddr_un *from, socklen_t fromlen,
|
||||
char *imsi)
|
||||
{
|
||||
@ -478,13 +724,18 @@ static void aka_req_auth(int s, struct sockaddr_un *from, socklen_t fromlen,
|
||||
size_t res_len;
|
||||
int ret;
|
||||
struct milenage_parameters *m;
|
||||
int failed = 0;
|
||||
|
||||
m = get_milenage(imsi);
|
||||
if (m) {
|
||||
if (os_get_random(_rand, EAP_AKA_RAND_LEN) < 0)
|
||||
if (random_get_bytes(_rand, EAP_AKA_RAND_LEN) < 0)
|
||||
return;
|
||||
res_len = EAP_AKA_RES_MAX_LEN;
|
||||
inc_byte_array(m->sqn, 6);
|
||||
inc_sqn(m->sqn);
|
||||
#ifdef CONFIG_SQLITE
|
||||
db_update_milenage_sqn(m);
|
||||
#endif /* CONFIG_SQLITE */
|
||||
sqn_changes = 1;
|
||||
printf("AKA: Milenage with SQN=%02x%02x%02x%02x%02x%02x\n",
|
||||
m->sqn[0], m->sqn[1], m->sqn[2],
|
||||
m->sqn[3], m->sqn[4], m->sqn[5]);
|
||||
@ -501,7 +752,7 @@ static void aka_req_auth(int s, struct sockaddr_un *from, socklen_t fromlen,
|
||||
memset(res, '2', EAP_AKA_RES_MAX_LEN);
|
||||
res_len = EAP_AKA_RES_MAX_LEN;
|
||||
#else /* AKA_USE_FIXED_TEST_VALUES */
|
||||
return;
|
||||
failed = 1;
|
||||
#endif /* AKA_USE_FIXED_TEST_VALUES */
|
||||
}
|
||||
|
||||
@ -511,6 +762,13 @@ static void aka_req_auth(int s, struct sockaddr_un *from, socklen_t fromlen,
|
||||
if (ret < 0 || ret >= end - pos)
|
||||
return;
|
||||
pos += ret;
|
||||
if (failed) {
|
||||
ret = snprintf(pos, end - pos, "FAILURE");
|
||||
if (ret < 0 || ret >= end - pos)
|
||||
return;
|
||||
pos += ret;
|
||||
goto done;
|
||||
}
|
||||
pos += wpa_snprintf_hex(pos, end - pos, _rand, EAP_AKA_RAND_LEN);
|
||||
*pos++ = ' ';
|
||||
pos += wpa_snprintf_hex(pos, end - pos, autn, EAP_AKA_AUTN_LEN);
|
||||
@ -521,6 +779,7 @@ static void aka_req_auth(int s, struct sockaddr_un *from, socklen_t fromlen,
|
||||
*pos++ = ' ';
|
||||
pos += wpa_snprintf_hex(pos, end - pos, res, res_len);
|
||||
|
||||
done:
|
||||
printf("Send: %s\n", reply);
|
||||
|
||||
if (sendto(s, reply, pos - reply, 0, (struct sockaddr *) from,
|
||||
@ -568,6 +827,10 @@ static void aka_auts(int s, struct sockaddr_un *from, socklen_t fromlen,
|
||||
printf("AKA-AUTS: Re-synchronized: "
|
||||
"SQN=%02x%02x%02x%02x%02x%02x\n",
|
||||
sqn[0], sqn[1], sqn[2], sqn[3], sqn[4], sqn[5]);
|
||||
#ifdef CONFIG_SQLITE
|
||||
db_update_milenage_sqn(m);
|
||||
#endif /* CONFIG_SQLITE */
|
||||
sqn_changes = 1;
|
||||
}
|
||||
}
|
||||
|
||||
@ -614,22 +877,32 @@ static void cleanup(void)
|
||||
struct gsm_triplet *g, *gprev;
|
||||
struct milenage_parameters *m, *prev;
|
||||
|
||||
if (update_milenage && milenage_file && sqn_changes)
|
||||
update_milenage_file(milenage_file);
|
||||
|
||||
g = gsm_db;
|
||||
while (g) {
|
||||
gprev = g;
|
||||
g = g->next;
|
||||
free(gprev);
|
||||
os_free(gprev);
|
||||
}
|
||||
|
||||
m = milenage_db;
|
||||
while (m) {
|
||||
prev = m;
|
||||
m = m->next;
|
||||
free(prev);
|
||||
os_free(prev);
|
||||
}
|
||||
|
||||
close(serv_sock);
|
||||
unlink(socket_path);
|
||||
|
||||
#ifdef CONFIG_SQLITE
|
||||
if (sqlite_db) {
|
||||
sqlite3_close(sqlite_db);
|
||||
sqlite_db = NULL;
|
||||
}
|
||||
#endif /* CONFIG_SQLITE */
|
||||
}
|
||||
|
||||
|
||||
@ -644,18 +917,22 @@ static void usage(void)
|
||||
{
|
||||
printf("HLR/AuC testing gateway for hostapd EAP-SIM/AKA "
|
||||
"database/authenticator\n"
|
||||
"Copyright (c) 2005-2007, Jouni Malinen <j@w1.fi>\n"
|
||||
"Copyright (c) 2005-2007, 2012, Jouni Malinen <j@w1.fi>\n"
|
||||
"\n"
|
||||
"usage:\n"
|
||||
"hlr_auc_gw [-h] [-s<socket path>] [-g<triplet file>] "
|
||||
"[-m<milenage file>]\n"
|
||||
"hlr_auc_gw [-hu] [-s<socket path>] [-g<triplet file>] "
|
||||
"[-m<milenage file>] \\\n"
|
||||
" [-D<DB file>] [-i<IND len in bits>]\n"
|
||||
"\n"
|
||||
"options:\n"
|
||||
" -h = show this usage help\n"
|
||||
" -u = update SQN in Milenage file on exit\n"
|
||||
" -s<socket path> = path for UNIX domain socket\n"
|
||||
" (default: %s)\n"
|
||||
" -g<triplet file> = path for GSM authentication triplets\n"
|
||||
" -m<milenage file> = path for Milenage keys\n",
|
||||
" -m<milenage file> = path for Milenage keys\n"
|
||||
" -D<DB file> = path to SQLite database\n"
|
||||
" -i<IND len in bits> = IND length for SQN (default: 5)\n",
|
||||
default_socket_path);
|
||||
}
|
||||
|
||||
@ -663,34 +940,65 @@ static void usage(void)
|
||||
int main(int argc, char *argv[])
|
||||
{
|
||||
int c;
|
||||
char *milenage_file = NULL;
|
||||
char *gsm_triplet_file = NULL;
|
||||
char *sqlite_db_file = NULL;
|
||||
|
||||
if (os_program_init())
|
||||
return -1;
|
||||
|
||||
socket_path = default_socket_path;
|
||||
|
||||
for (;;) {
|
||||
c = getopt(argc, argv, "g:hm:s:");
|
||||
c = getopt(argc, argv, "D:g:hi:m:s:u");
|
||||
if (c < 0)
|
||||
break;
|
||||
switch (c) {
|
||||
case 'D':
|
||||
#ifdef CONFIG_SQLITE
|
||||
sqlite_db_file = optarg;
|
||||
break;
|
||||
#else /* CONFIG_SQLITE */
|
||||
printf("No SQLite support included in the build\n");
|
||||
return -1;
|
||||
#endif /* CONFIG_SQLITE */
|
||||
case 'g':
|
||||
gsm_triplet_file = optarg;
|
||||
break;
|
||||
case 'h':
|
||||
usage();
|
||||
return 0;
|
||||
case 'i':
|
||||
ind_len = atoi(optarg);
|
||||
if (ind_len < 0 || ind_len > 32) {
|
||||
printf("Invalid IND length\n");
|
||||
return -1;
|
||||
}
|
||||
break;
|
||||
case 'm':
|
||||
milenage_file = optarg;
|
||||
break;
|
||||
case 's':
|
||||
socket_path = optarg;
|
||||
break;
|
||||
case 'u':
|
||||
update_milenage = 1;
|
||||
break;
|
||||
default:
|
||||
usage();
|
||||
return -1;
|
||||
}
|
||||
}
|
||||
|
||||
if (!gsm_triplet_file && !milenage_file && !sqlite_db_file) {
|
||||
usage();
|
||||
return -1;
|
||||
}
|
||||
|
||||
#ifdef CONFIG_SQLITE
|
||||
if (sqlite_db_file && (sqlite_db = db_open(sqlite_db_file)) == NULL)
|
||||
return -1;
|
||||
#endif /* CONFIG_SQLITE */
|
||||
|
||||
if (gsm_triplet_file && read_gsm_triplets(gsm_triplet_file) < 0)
|
||||
return -1;
|
||||
|
||||
@ -710,5 +1018,14 @@ int main(int argc, char *argv[])
|
||||
for (;;)
|
||||
process(serv_sock);
|
||||
|
||||
#ifdef CONFIG_SQLITE
|
||||
if (sqlite_db) {
|
||||
sqlite3_close(sqlite_db);
|
||||
sqlite_db = NULL;
|
||||
}
|
||||
#endif /* CONFIG_SQLITE */
|
||||
|
||||
os_program_deinit();
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
104
hostapd/hlr_auc_gw.txt
Normal file
104
hostapd/hlr_auc_gw.txt
Normal file
@ -0,0 +1,104 @@
|
||||
HLR/AuC testing gateway for hostapd EAP-SIM/AKA database/authenticator
|
||||
|
||||
hlr_auc_gw is an example implementation of the EAP-SIM/AKA/AKA'
|
||||
database/authentication gateway interface to HLR/AuC. It could be
|
||||
replaced with an implementation of SS7 gateway to GSM/UMTS
|
||||
authentication center (HLR/AuC). hostapd will send SIM/AKA
|
||||
authentication queries over a UNIX domain socket to and external
|
||||
program, e.g., hlr_auc_gw.
|
||||
|
||||
hlr_auc_gw can be configured with GSM and UMTS authentication data with
|
||||
text files: GSM triplet file (see hostapd.sim_db) and Milenage file (see
|
||||
hlr_auc_gw.milenage_db). Milenage parameters can be used to generate
|
||||
dynamic authentication data for EAP-SIM, EAP-AKA, and EAP-AKA' while the
|
||||
GSM triplet data is used for a more static configuration (e.g., triplets
|
||||
extracted from a SIM card).
|
||||
|
||||
Alternatively, hlr_auc_gw can be built with support for an SQLite
|
||||
database for more dynamic operations. This is enabled by adding
|
||||
"CONFIG_SQLITE=y" into hostapd/.config before building hlr_auc_gw ("make
|
||||
clean; make hlr_auc_gw" in this directory).
|
||||
|
||||
hostapd is configured to use hlr_auc_gw with the eap_sim_db parameter in
|
||||
hostapd.conf (e.g., "eap_sim_db=unix:/tmp/hlr_auc_gw.sock"). hlr_auc_gw
|
||||
is configured with command line parameters:
|
||||
|
||||
hlr_auc_gw [-hu] [-s<socket path>] [-g<triplet file>] [-m<milenage file>] \
|
||||
[-D<DB file>] [-i<IND len in bits>]
|
||||
|
||||
options:
|
||||
-h = show this usage help
|
||||
-u = update SQN in Milenage file on exit
|
||||
-s<socket path> = path for UNIX domain socket
|
||||
(default: /tmp/hlr_auc_gw.sock)
|
||||
-g<triplet file> = path for GSM authentication triplets
|
||||
-m<milenage file> = path for Milenage keys
|
||||
-D<DB file> = path to SQLite database
|
||||
-i<IND len in bits> = IND length for SQN (default: 5)
|
||||
|
||||
|
||||
The SQLite database can be initialized with sqlite, e.g., by running
|
||||
following commands in "sqlite3 /path/to/hlr_auc_gw.db":
|
||||
|
||||
CREATE TABLE milenage(
|
||||
imsi INTEGER PRIMARY KEY NOT NULL,
|
||||
ki CHAR(32) NOT NULL,
|
||||
opc CHAR(32) NOT NULL,
|
||||
amf CHAR(4) NOT NULL,
|
||||
sqn CHAR(12) NOT NULL
|
||||
);
|
||||
INSERT INTO milenage(imsi,ki,opc,amf,sqn) VALUES(
|
||||
232010000000000,
|
||||
'90dca4eda45b53cf0f12d7c9c3bc6a89',
|
||||
'cb9cccc4b9258e6dca4760379fb82581',
|
||||
'61df',
|
||||
'000000000000'
|
||||
);
|
||||
INSERT INTO milenage(imsi,ki,opc,amf,sqn) VALUES(
|
||||
555444333222111,
|
||||
'5122250214c33e723a5dd523fc145fc0',
|
||||
'981d464c7c52eb6e5036234984ad0bcf',
|
||||
'c3ab',
|
||||
'16f3b3f70fc1'
|
||||
);
|
||||
|
||||
|
||||
hostapd (EAP server) can also be configured to store the EAP-SIM/AKA
|
||||
pseudonyms and reauth information into a SQLite database. This is
|
||||
configured with the db parameter within the eap_sim_db configuration
|
||||
option.
|
||||
|
||||
|
||||
"hlr_auc_gw -D /path/to/hlr_auc_gw.db" can then be used to fetch
|
||||
Milenage parameters based on IMSI from the database. The database can be
|
||||
updated dynamically while hlr_auc_gw is running to add/remove/modify
|
||||
entries.
|
||||
|
||||
|
||||
Example configuration files for hostapd to operate as a RADIUS
|
||||
authentication server for EAP-SIM/AKA/AKA':
|
||||
|
||||
hostapd.conf:
|
||||
|
||||
driver=none
|
||||
radius_server_clients=hostapd.radius_clients
|
||||
eap_server=1
|
||||
eap_user_file=hostapd.eap_user
|
||||
eap_sim_db=unix:/tmp/hlr_auc_gw.sock db=/tmp/eap_sim.db
|
||||
eap_sim_aka_result_ind=1
|
||||
|
||||
hostapd.radius_clients:
|
||||
|
||||
0.0.0.0/0 radius
|
||||
|
||||
hostapd.eap_user:
|
||||
|
||||
"0"* AKA
|
||||
"1"* SIM
|
||||
"2"* AKA
|
||||
"3"* SIM
|
||||
"4"* AKA
|
||||
"5"* SIM
|
||||
"6"* AKA'
|
||||
"7"* AKA'
|
||||
"8"* AKA'
|
@ -84,6 +84,14 @@ ctrl_interface_group=0
|
||||
|
||||
# SSID to be used in IEEE 802.11 management frames
|
||||
ssid=test
|
||||
# Alternative formats for configuring SSID
|
||||
# (double quoted string, hexdump, printf-escaped string)
|
||||
#ssid2="test"
|
||||
#ssid2=74657374
|
||||
#ssid2=P"hello\nthere"
|
||||
|
||||
# UTF-8 SSID: Whether the SSID is to be interpreted using UTF-8 encoding
|
||||
#utf8_ssid=1
|
||||
|
||||
# Country code (ISO/IEC 3166-1). Used to set regulatory domain.
|
||||
# Set as needed to indicate country in which device is operating.
|
||||
@ -98,20 +106,21 @@ ssid=test
|
||||
#ieee80211d=1
|
||||
|
||||
# Operation mode (a = IEEE 802.11a, b = IEEE 802.11b, g = IEEE 802.11g,
|
||||
# ad = IEEE 802.11ad (60 GHz); a/g options are used with IEEE 802.11n, too, to
|
||||
# specify band)
|
||||
# Default: IEEE 802.11b
|
||||
hw_mode=a
|
||||
hw_mode=g
|
||||
|
||||
# Channel number (IEEE 802.11)
|
||||
# (default: 0, i.e., not set)
|
||||
# Please note that some drivers (e.g., madwifi) do not use this value from
|
||||
# hostapd and the channel will need to be configuration separately with
|
||||
# iwconfig.
|
||||
channel=60
|
||||
# Please note that some drivers do not use this value from hostapd and the
|
||||
# channel will need to be configured separately with iwconfig.
|
||||
channel=1
|
||||
|
||||
# Beacon interval in kus (1.024 ms) (default: 100; range 15..65535)
|
||||
beacon_int=100
|
||||
|
||||
# DTIM (delivery trafic information message) period (range 1..255):
|
||||
# DTIM (delivery traffic information message) period (range 1..255):
|
||||
# number of beacons between DTIMs (1 = every beacon includes DTIM element)
|
||||
# (default: 2)
|
||||
dtim_period=2
|
||||
@ -197,8 +206,14 @@ auth_algs=3
|
||||
# requests for broadcast SSID
|
||||
ignore_broadcast_ssid=0
|
||||
|
||||
# Additional vendor specfic elements for Beacon and Probe Response frames
|
||||
# This parameter can be used to add additional vendor specific element(s) into
|
||||
# the end of the Beacon and Probe Response frames. The format for these
|
||||
# element(s) is a hexdump of the raw information elements (id+len+payload for
|
||||
# one or more elements)
|
||||
#vendor_elements=dd0411223301
|
||||
|
||||
# TX queue parameters (EDCF / bursting)
|
||||
# default for all these fields: not set, use hardware defaults
|
||||
# tx_queue_<queue name>_<param>
|
||||
# queues: data0, data1, data2, data3, after_beacon, beacon
|
||||
# (data0 is the highest priority queue)
|
||||
@ -240,18 +255,6 @@ ignore_broadcast_ssid=0
|
||||
#tx_queue_data0_cwmax=7
|
||||
#tx_queue_data0_burst=1.5
|
||||
# Note: for IEEE 802.11b mode: cWmin=7 cWmax=15 burst=3.3
|
||||
#
|
||||
# Special queues; normally not user configurable
|
||||
#
|
||||
#tx_queue_after_beacon_aifs=2
|
||||
#tx_queue_after_beacon_cwmin=15
|
||||
#tx_queue_after_beacon_cwmax=1023
|
||||
#tx_queue_after_beacon_burst=0
|
||||
#
|
||||
#tx_queue_beacon_aifs=2
|
||||
#tx_queue_beacon_cwmin=3
|
||||
#tx_queue_beacon_cwmax=7
|
||||
#tx_queue_beacon_burst=1.5
|
||||
|
||||
# 802.1D Tag (= UP) to AC mappings
|
||||
# WMM specifies following mapping of data frames to different ACs. This mapping
|
||||
@ -353,6 +356,17 @@ wmm_ac_vo_acm=0
|
||||
# the STA with a data frame.
|
||||
# default: 300 (i.e., 5 minutes)
|
||||
#ap_max_inactivity=300
|
||||
#
|
||||
# The inactivity polling can be disabled to disconnect stations based on
|
||||
# inactivity timeout so that idle stations are more likely to be disconnected
|
||||
# even if they are still in range of the AP. This can be done by setting
|
||||
# skip_inactivity_poll to 1 (default 0).
|
||||
#skip_inactivity_poll=0
|
||||
|
||||
# Disassociate stations based on excessive transmission failures or other
|
||||
# indications of connection loss. This depends on the driver capabilities and
|
||||
# may not be available with all drivers.
|
||||
#disassoc_low_ack=1
|
||||
|
||||
# Maximum allowed Listen Interval (how many Beacon periods STAs are allowed to
|
||||
# remain asleep). Default: 65535 (no limit apart from field size)
|
||||
@ -364,6 +378,15 @@ wmm_ac_vo_acm=0
|
||||
# bridging to be used.
|
||||
#wds_sta=1
|
||||
|
||||
# If bridge parameter is set, the WDS STA interface will be added to the same
|
||||
# bridge by default. This can be overridden with the wds_bridge parameter to
|
||||
# use a separate bridge.
|
||||
#wds_bridge=wds-br0
|
||||
|
||||
# Client isolation can be used to prevent low-level bridging of frames between
|
||||
# associated stations in the BSS. By default, this bridging is allowed.
|
||||
#ap_isolate=1
|
||||
|
||||
##### IEEE 802.11n related configuration ######################################
|
||||
|
||||
# ieee80211n: Whether IEEE 802.11n (HT) is enabled
|
||||
@ -407,6 +430,160 @@ wmm_ac_vo_acm=0
|
||||
# L-SIG TXOP protection support: [LSIG-TXOP-PROT] (disabled if not set)
|
||||
#ht_capab=[HT40-][SHORT-GI-20][SHORT-GI-40]
|
||||
|
||||
# Require stations to support HT PHY (reject association if they do not)
|
||||
#require_ht=1
|
||||
|
||||
##### IEEE 802.11ac related configuration #####################################
|
||||
|
||||
# ieee80211ac: Whether IEEE 802.11ac (VHT) is enabled
|
||||
# 0 = disabled (default)
|
||||
# 1 = enabled
|
||||
# Note: You will also need to enable WMM for full VHT functionality.
|
||||
#ieee80211ac=1
|
||||
|
||||
# vht_capab: VHT capabilities (list of flags)
|
||||
#
|
||||
# vht_max_mpdu_len: [MAX-MPDU-7991] [MAX-MPDU-11454]
|
||||
# Indicates maximum MPDU length
|
||||
# 0 = 3895 octets (default)
|
||||
# 1 = 7991 octets
|
||||
# 2 = 11454 octets
|
||||
# 3 = reserved
|
||||
#
|
||||
# supported_chan_width: [VHT160] [VHT160-80PLUS80]
|
||||
# Indicates supported Channel widths
|
||||
# 0 = 160 MHz & 80+80 channel widths are not supported (default)
|
||||
# 1 = 160 MHz channel width is supported
|
||||
# 2 = 160 MHz & 80+80 channel widths are supported
|
||||
# 3 = reserved
|
||||
#
|
||||
# Rx LDPC coding capability: [RXLDPC]
|
||||
# Indicates support for receiving LDPC coded pkts
|
||||
# 0 = Not supported (default)
|
||||
# 1 = Supported
|
||||
#
|
||||
# Short GI for 80 MHz: [SHORT-GI-80]
|
||||
# Indicates short GI support for reception of packets transmitted with TXVECTOR
|
||||
# params format equal to VHT and CBW = 80Mhz
|
||||
# 0 = Not supported (default)
|
||||
# 1 = Supported
|
||||
#
|
||||
# Short GI for 160 MHz: [SHORT-GI-160]
|
||||
# Indicates short GI support for reception of packets transmitted with TXVECTOR
|
||||
# params format equal to VHT and CBW = 160Mhz
|
||||
# 0 = Not supported (default)
|
||||
# 1 = Supported
|
||||
#
|
||||
# Tx STBC: [TX-STBC-2BY1]
|
||||
# Indicates support for the transmission of at least 2x1 STBC
|
||||
# 0 = Not supported (default)
|
||||
# 1 = Supported
|
||||
#
|
||||
# Rx STBC: [RX-STBC-1] [RX-STBC-12] [RX-STBC-123] [RX-STBC-1234]
|
||||
# Indicates support for the reception of PPDUs using STBC
|
||||
# 0 = Not supported (default)
|
||||
# 1 = support of one spatial stream
|
||||
# 2 = support of one and two spatial streams
|
||||
# 3 = support of one, two and three spatial streams
|
||||
# 4 = support of one, two, three and four spatial streams
|
||||
# 5,6,7 = reserved
|
||||
#
|
||||
# SU Beamformer Capable: [SU-BEAMFORMER]
|
||||
# Indicates support for operation as a single user beamformer
|
||||
# 0 = Not supported (default)
|
||||
# 1 = Supported
|
||||
#
|
||||
# SU Beamformee Capable: [SU-BEAMFORMEE]
|
||||
# Indicates support for operation as a single user beamformee
|
||||
# 0 = Not supported (default)
|
||||
# 1 = Supported
|
||||
#
|
||||
# Compressed Steering Number of Beamformer Antennas Supported: [BF-ANTENNA-2]
|
||||
# Beamformee's capability indicating the maximum number of beamformer
|
||||
# antennas the beamformee can support when sending compressed beamforming
|
||||
# feedback
|
||||
# If SU beamformer capable, set to maximum value minus 1
|
||||
# else reserved (default)
|
||||
#
|
||||
# Number of Sounding Dimensions: [SOUNDING-DIMENSION-2]
|
||||
# Beamformer's capability indicating the maximum value of the NUM_STS parameter
|
||||
# in the TXVECTOR of a VHT NDP
|
||||
# If SU beamformer capable, set to maximum value minus 1
|
||||
# else reserved (default)
|
||||
#
|
||||
# MU Beamformer Capable: [MU-BEAMFORMER]
|
||||
# Indicates support for operation as an MU beamformer
|
||||
# 0 = Not supported or sent by Non-AP STA (default)
|
||||
# 1 = Supported
|
||||
#
|
||||
# MU Beamformee Capable: [MU-BEAMFORMEE]
|
||||
# Indicates support for operation as an MU beamformee
|
||||
# 0 = Not supported or sent by AP (default)
|
||||
# 1 = Supported
|
||||
#
|
||||
# VHT TXOP PS: [VHT-TXOP-PS]
|
||||
# Indicates whether or not the AP supports VHT TXOP Power Save Mode
|
||||
# or whether or not the STA is in VHT TXOP Power Save mode
|
||||
# 0 = VHT AP doesnt support VHT TXOP PS mode (OR) VHT Sta not in VHT TXOP PS
|
||||
# mode
|
||||
# 1 = VHT AP supports VHT TXOP PS mode (OR) VHT Sta is in VHT TXOP power save
|
||||
# mode
|
||||
#
|
||||
# +HTC-VHT Capable: [HTC-VHT]
|
||||
# Indicates whether or not the STA supports receiving a VHT variant HT Control
|
||||
# field.
|
||||
# 0 = Not supported (default)
|
||||
# 1 = supported
|
||||
#
|
||||
# Maximum A-MPDU Length Exponent: [MAX-A-MPDU-LEN-EXP0]..[MAX-A-MPDU-LEN-EXP7]
|
||||
# Indicates the maximum length of A-MPDU pre-EOF padding that the STA can recv
|
||||
# This field is an integer in the range of 0 to 7.
|
||||
# The length defined by this field is equal to
|
||||
# 2 pow(13 + Maximum A-MPDU Length Exponent) -1 octets
|
||||
#
|
||||
# VHT Link Adaptation Capable: [VHT-LINK-ADAPT2] [VHT-LINK-ADAPT3]
|
||||
# Indicates whether or not the STA supports link adaptation using VHT variant
|
||||
# HT Control field
|
||||
# If +HTC-VHTcapable is 1
|
||||
# 0 = (no feedback) if the STA does not provide VHT MFB (default)
|
||||
# 1 = reserved
|
||||
# 2 = (Unsolicited) if the STA provides only unsolicited VHT MFB
|
||||
# 3 = (Both) if the STA can provide VHT MFB in response to VHT MRQ and if the
|
||||
# STA provides unsolicited VHT MFB
|
||||
# Reserved if +HTC-VHTcapable is 0
|
||||
#
|
||||
# Rx Antenna Pattern Consistency: [RX-ANTENNA-PATTERN]
|
||||
# Indicates the possibility of Rx antenna pattern change
|
||||
# 0 = Rx antenna pattern might change during the lifetime of an association
|
||||
# 1 = Rx antenna pattern does not change during the lifetime of an association
|
||||
#
|
||||
# Tx Antenna Pattern Consistency: [TX-ANTENNA-PATTERN]
|
||||
# Indicates the possibility of Tx antenna pattern change
|
||||
# 0 = Tx antenna pattern might change during the lifetime of an association
|
||||
# 1 = Tx antenna pattern does not change during the lifetime of an association
|
||||
#vht_capab=[SHORT-GI-80][HTC-VHT]
|
||||
#
|
||||
# Require stations to support VHT PHY (reject association if they do not)
|
||||
#require_vht=1
|
||||
|
||||
# 0 = 20 or 40 MHz operating Channel width
|
||||
# 1 = 80 MHz channel width
|
||||
# 2 = 160 MHz channel width
|
||||
# 3 = 80+80 MHz channel width
|
||||
#vht_oper_chwidth=1
|
||||
#
|
||||
# center freq = 5 GHz + (5 * index)
|
||||
# So index 42 gives center freq 5.210 GHz
|
||||
# which is channel 42 in 5G band
|
||||
#
|
||||
#vht_oper_centr_freq_seg0_idx=42
|
||||
#
|
||||
# center freq = 5 GHz + (5 * index)
|
||||
# So index 159 gives center freq 5.795 GHz
|
||||
# which is channel 159 in 5G band
|
||||
#
|
||||
#vht_oper_centr_freq_seg1_idx=159
|
||||
|
||||
##### IEEE 802.1X-2004 related configuration ##################################
|
||||
|
||||
# Require IEEE 802.1X authorization
|
||||
@ -463,6 +640,8 @@ eapol_key_index_workaround=0
|
||||
eap_server=0
|
||||
|
||||
# Path for EAP server user database
|
||||
# If SQLite support is included, this can be set to "sqlite:/path/to/sqlite.db"
|
||||
# to use SQLite database instead of a text file.
|
||||
#eap_user_file=/etc/hostapd.eap_user
|
||||
|
||||
# CA certificate (PEM or DER file) for EAP-TLS/PEAP/TTLS
|
||||
@ -504,12 +683,21 @@ eap_server=0
|
||||
# "openssl dhparam -out /etc/hostapd.dh.pem 1024"
|
||||
#dh_file=/etc/hostapd.dh.pem
|
||||
|
||||
# Fragment size for EAP methods
|
||||
#fragment_size=1400
|
||||
|
||||
# Finite cyclic group for EAP-pwd. Number maps to group of domain parameters
|
||||
# using the IANA repository for IKE (RFC 2409).
|
||||
#pwd_group=19
|
||||
|
||||
# Configuration data for EAP-SIM database/authentication gateway interface.
|
||||
# This is a text string in implementation specific format. The example
|
||||
# implementation in eap_sim_db.c uses this as the UNIX domain socket name for
|
||||
# the HLR/AuC gateway (e.g., hlr_auc_gw). In this case, the path uses "unix:"
|
||||
# prefix.
|
||||
# prefix. If hostapd is built with SQLite support (CONFIG_SQLITE=y in .config),
|
||||
# database file can be described with an optional db=<path> parameter.
|
||||
#eap_sim_db=unix:/tmp/hlr_auc_gw.sock
|
||||
#eap_sim_db=unix:/tmp/hlr_auc_gw.sock db=/tmp/hostapd.db
|
||||
|
||||
# Encryption key for EAP-FAST PAC-Opaque values. This key must be a secret,
|
||||
# random value. It is configured as a 16-octet value in hex format. It can be
|
||||
@ -616,6 +804,12 @@ own_ip_addr=127.0.0.1
|
||||
# 60 (1 minute).
|
||||
#radius_acct_interim_interval=600
|
||||
|
||||
# Request Chargeable-User-Identity (RFC 4372)
|
||||
# This parameter can be used to configure hostapd to request CUI from the
|
||||
# RADIUS server by including Chargeable-User-Identity attribute into
|
||||
# Access-Request packets.
|
||||
#radius_request_cui=1
|
||||
|
||||
# Dynamic VLAN mode; allow RADIUS authentication server to decide which VLAN
|
||||
# is used for the stations. This information is parsed from following RADIUS
|
||||
# attributes based on RFC 3580 and RFC 2868: Tunnel-Type (value 13 = VLAN),
|
||||
@ -643,6 +837,61 @@ own_ip_addr=127.0.0.1
|
||||
# to the bridge.
|
||||
#vlan_tagged_interface=eth0
|
||||
|
||||
# When hostapd creates a VLAN interface on vlan_tagged_interfaces, it needs
|
||||
# to know how to name it.
|
||||
# 0 = vlan<XXX>, e.g., vlan1
|
||||
# 1 = <vlan_tagged_interface>.<XXX>, e.g. eth0.1
|
||||
#vlan_naming=0
|
||||
|
||||
# Arbitrary RADIUS attributes can be added into Access-Request and
|
||||
# Accounting-Request packets by specifying the contents of the attributes with
|
||||
# the following configuration parameters. There can be multiple of these to
|
||||
# add multiple attributes. These parameters can also be used to override some
|
||||
# of the attributes added automatically by hostapd.
|
||||
# Format: <attr_id>[:<syntax:value>]
|
||||
# attr_id: RADIUS attribute type (e.g., 26 = Vendor-Specific)
|
||||
# syntax: s = string (UTF-8), d = integer, x = octet string
|
||||
# value: attribute value in format indicated by the syntax
|
||||
# If syntax and value parts are omitted, a null value (single 0x00 octet) is
|
||||
# used.
|
||||
#
|
||||
# Additional Access-Request attributes
|
||||
# radius_auth_req_attr=<attr_id>[:<syntax:value>]
|
||||
# Examples:
|
||||
# Operator-Name = "Operator"
|
||||
#radius_auth_req_attr=126:s:Operator
|
||||
# Service-Type = Framed (2)
|
||||
#radius_auth_req_attr=6:d:2
|
||||
# Connect-Info = "testing" (this overrides the automatically generated value)
|
||||
#radius_auth_req_attr=77:s:testing
|
||||
# Same Connect-Info value set as a hexdump
|
||||
#radius_auth_req_attr=77:x:74657374696e67
|
||||
|
||||
#
|
||||
# Additional Accounting-Request attributes
|
||||
# radius_acct_req_attr=<attr_id>[:<syntax:value>]
|
||||
# Examples:
|
||||
# Operator-Name = "Operator"
|
||||
#radius_acct_req_attr=126:s:Operator
|
||||
|
||||
# Dynamic Authorization Extensions (RFC 5176)
|
||||
# This mechanism can be used to allow dynamic changes to user session based on
|
||||
# commands from a RADIUS server (or some other disconnect client that has the
|
||||
# needed session information). For example, Disconnect message can be used to
|
||||
# request an associated station to be disconnected.
|
||||
#
|
||||
# This is disabled by default. Set radius_das_port to non-zero UDP port
|
||||
# number to enable.
|
||||
#radius_das_port=3799
|
||||
#
|
||||
# DAS client (the host that can send Disconnect/CoA requests) and shared secret
|
||||
#radius_das_client=192.168.1.123 shared secret here
|
||||
#
|
||||
# DAS Event-Timestamp time window in seconds
|
||||
#radius_das_time_window=300
|
||||
#
|
||||
# DAS require Event-Timestamp
|
||||
#radius_das_require_event_timestamp=1
|
||||
|
||||
##### RADIUS authentication server configuration ##############################
|
||||
|
||||
@ -666,6 +915,7 @@ own_ip_addr=127.0.0.1
|
||||
# Enable WPA. Setting this variable configures the AP to require WPA (either
|
||||
# WPA-PSK or WPA-RADIUS/EAP based on other configuration). For WPA-PSK, either
|
||||
# wpa_psk or wpa_passphrase must be set and wpa_key_mgmt must include WPA-PSK.
|
||||
# Instead of wpa_psk / wpa_passphrase, wpa_psk_radius might suffice.
|
||||
# For WPA-RADIUS/EAP, ieee8021x must be set (but without dynamic WEP keys),
|
||||
# RADIUS authentication server must be configured, and WPA-EAP must be included
|
||||
# in wpa_key_mgmt.
|
||||
@ -690,6 +940,15 @@ own_ip_addr=127.0.0.1
|
||||
# configuration reloads.
|
||||
#wpa_psk_file=/etc/hostapd.wpa_psk
|
||||
|
||||
# Optionally, WPA passphrase can be received from RADIUS authentication server
|
||||
# This requires macaddr_acl to be set to 2 (RADIUS)
|
||||
# 0 = disabled (default)
|
||||
# 1 = optional; use default passphrase/psk if RADIUS server does not include
|
||||
# Tunnel-Password
|
||||
# 2 = required; reject authentication if RADIUS server does not include
|
||||
# Tunnel-Password
|
||||
#wpa_psk_radius=0
|
||||
|
||||
# Set of accepted key management algorithms (WPA-PSK, WPA-EAP, or both). The
|
||||
# entries are separated with a space. WPA-PSK-SHA256 and WPA-EAP-SHA256 can be
|
||||
# added to enable SHA256-based stronger algorithms.
|
||||
@ -763,6 +1022,13 @@ own_ip_addr=127.0.0.1
|
||||
# dot11AssociationSAQueryRetryTimeout, 1...4294967295
|
||||
#assoc_sa_query_retry_timeout=201
|
||||
|
||||
# disable_pmksa_caching: Disable PMKSA caching
|
||||
# This parameter can be used to disable caching of PMKSA created through EAP
|
||||
# authentication. RSN preauthentication may still end up using PMKSA caching if
|
||||
# it is enabled (rsn_preauth=1).
|
||||
# 0 = PMKSA caching enabled (default)
|
||||
# 1 = PMKSA caching disabled
|
||||
#disable_pmksa_caching=0
|
||||
|
||||
# okc: Opportunistic Key Caching (aka Proactive Key Caching)
|
||||
# Allow PMK cache to be shared opportunistically among configured interfaces
|
||||
@ -910,8 +1176,21 @@ own_ip_addr=127.0.0.1
|
||||
# Config Methods
|
||||
# List of the supported configuration methods
|
||||
# Available methods: usba ethernet label display ext_nfc_token int_nfc_token
|
||||
# nfc_interface push_button keypad
|
||||
#config_methods=label display push_button keypad
|
||||
# nfc_interface push_button keypad virtual_display physical_display
|
||||
# virtual_push_button physical_push_button
|
||||
#config_methods=label virtual_display virtual_push_button keypad
|
||||
|
||||
# WPS capability discovery workaround for PBC with Windows 7
|
||||
# Windows 7 uses incorrect way of figuring out AP's WPS capabilities by acting
|
||||
# as a Registrar and using M1 from the AP. The config methods attribute in that
|
||||
# message is supposed to indicate only the configuration method supported by
|
||||
# the AP in Enrollee role, i.e., to add an external Registrar. For that case,
|
||||
# PBC shall not be used and as such, the PushButton config method is removed
|
||||
# from M1 by default. If pbc_in_m1=1 is included in the configuration file,
|
||||
# the PushButton config method is left in M1 (if included in config_methods
|
||||
# parameter) to allow Windows 7 to use PBC instead of PIN (e.g., from a label
|
||||
# in the AP).
|
||||
#pbc_in_m1=1
|
||||
|
||||
# Static access point PIN for initial configuration and adding Registrars
|
||||
# If not set, hostapd will not allow external WPS Registrars to control the
|
||||
@ -981,6 +1260,246 @@ own_ip_addr=127.0.0.1
|
||||
# 12-digit, all-numeric code that identifies the consumer package.
|
||||
#upc=123456789012
|
||||
|
||||
# WPS RF Bands (a = 5G, b = 2.4G, g = 2.4G, ag = dual band)
|
||||
# This value should be set according to RF band(s) supported by the AP if
|
||||
# hw_mode is not set. For dual band dual concurrent devices, this needs to be
|
||||
# set to ag to allow both RF bands to be advertized.
|
||||
#wps_rf_bands=ag
|
||||
|
||||
# NFC password token for WPS
|
||||
# These parameters can be used to configure a fixed NFC password token for the
|
||||
# AP. This can be generated, e.g., with nfc_pw_token from wpa_supplicant. When
|
||||
# these parameters are used, the AP is assumed to be deployed with a NFC tag
|
||||
# that includes the matching NFC password token (e.g., written based on the
|
||||
# NDEF record from nfc_pw_token).
|
||||
#
|
||||
#wps_nfc_dev_pw_id: Device Password ID (16..65535)
|
||||
#wps_nfc_dh_pubkey: Hexdump of DH Public Key
|
||||
#wps_nfc_dh_privkey: Hexdump of DH Private Key
|
||||
#wps_nfc_dev_pw: Hexdump of Device Password
|
||||
|
||||
##### Wi-Fi Direct (P2P) ######################################################
|
||||
|
||||
# Enable P2P Device management
|
||||
#manage_p2p=1
|
||||
|
||||
# Allow cross connection
|
||||
#allow_cross_connection=1
|
||||
|
||||
#### TDLS (IEEE 802.11z-2010) #################################################
|
||||
|
||||
# Prohibit use of TDLS in this BSS
|
||||
#tdls_prohibit=1
|
||||
|
||||
# Prohibit use of TDLS Channel Switching in this BSS
|
||||
#tdls_prohibit_chan_switch=1
|
||||
|
||||
##### IEEE 802.11v-2011 #######################################################
|
||||
|
||||
# Time advertisement
|
||||
# 0 = disabled (default)
|
||||
# 2 = UTC time at which the TSF timer is 0
|
||||
#time_advertisement=2
|
||||
|
||||
# Local time zone as specified in 8.3 of IEEE Std 1003.1-2004:
|
||||
# stdoffset[dst[offset][,start[/time],end[/time]]]
|
||||
#time_zone=EST5
|
||||
|
||||
# WNM-Sleep Mode (extended sleep mode for stations)
|
||||
# 0 = disabled (default)
|
||||
# 1 = enabled (allow stations to use WNM-Sleep Mode)
|
||||
#wnm_sleep_mode=1
|
||||
|
||||
# BSS Transition Management
|
||||
# 0 = disabled (default)
|
||||
# 1 = enabled
|
||||
#bss_transition=1
|
||||
|
||||
##### IEEE 802.11u-2011 #######################################################
|
||||
|
||||
# Enable Interworking service
|
||||
#interworking=1
|
||||
|
||||
# Access Network Type
|
||||
# 0 = Private network
|
||||
# 1 = Private network with guest access
|
||||
# 2 = Chargeable public network
|
||||
# 3 = Free public network
|
||||
# 4 = Personal device network
|
||||
# 5 = Emergency services only network
|
||||
# 14 = Test or experimental
|
||||
# 15 = Wildcard
|
||||
#access_network_type=0
|
||||
|
||||
# Whether the network provides connectivity to the Internet
|
||||
# 0 = Unspecified
|
||||
# 1 = Network provides connectivity to the Internet
|
||||
#internet=1
|
||||
|
||||
# Additional Step Required for Access
|
||||
# Note: This is only used with open network, i.e., ASRA shall ne set to 0 if
|
||||
# RSN is used.
|
||||
#asra=0
|
||||
|
||||
# Emergency services reachable
|
||||
#esr=0
|
||||
|
||||
# Unauthenticated emergency service accessible
|
||||
#uesa=0
|
||||
|
||||
# Venue Info (optional)
|
||||
# The available values are defined in IEEE Std 802.11u-2011, 7.3.1.34.
|
||||
# Example values (group,type):
|
||||
# 0,0 = Unspecified
|
||||
# 1,7 = Convention Center
|
||||
# 1,13 = Coffee Shop
|
||||
# 2,0 = Unspecified Business
|
||||
# 7,1 Private Residence
|
||||
#venue_group=7
|
||||
#venue_type=1
|
||||
|
||||
# Homogeneous ESS identifier (optional; dot11HESSID)
|
||||
# If set, this shall be identifical to one of the BSSIDs in the homogeneous
|
||||
# ESS and this shall be set to the same value across all BSSs in homogeneous
|
||||
# ESS.
|
||||
#hessid=02:03:04:05:06:07
|
||||
|
||||
# Roaming Consortium List
|
||||
# Arbitrary number of Roaming Consortium OIs can be configured with each line
|
||||
# adding a new OI to the list. The first three entries are available through
|
||||
# Beacon and Probe Response frames. Any additional entry will be available only
|
||||
# through ANQP queries. Each OI is between 3 and 15 octets and is configured as
|
||||
# a hexstring.
|
||||
#roaming_consortium=021122
|
||||
#roaming_consortium=2233445566
|
||||
|
||||
# Venue Name information
|
||||
# This parameter can be used to configure one or more Venue Name Duples for
|
||||
# Venue Name ANQP information. Each entry has a two or three character language
|
||||
# code (ISO-639) separated by colon from the venue name string.
|
||||
# Note that venue_group and venue_type have to be set for Venue Name
|
||||
# information to be complete.
|
||||
#venue_name=eng:Example venue
|
||||
#venue_name=fin:Esimerkkipaikka
|
||||
|
||||
# Network Authentication Type
|
||||
# This parameter indicates what type of network authentication is used in the
|
||||
# network.
|
||||
# format: <network auth type indicator (1-octet hex str)> [redirect URL]
|
||||
# Network Authentication Type Indicator values:
|
||||
# 00 = Acceptance of terms and conditions
|
||||
# 01 = On-line enrollment supported
|
||||
# 02 = http/https redirection
|
||||
# 03 = DNS redirection
|
||||
#network_auth_type=00
|
||||
#network_auth_type=02http://www.example.com/redirect/me/here/
|
||||
|
||||
# IP Address Type Availability
|
||||
# format: <1-octet encoded value as hex str>
|
||||
# (ipv4_type & 0x3f) << 2 | (ipv6_type & 0x3)
|
||||
# ipv4_type:
|
||||
# 0 = Address type not available
|
||||
# 1 = Public IPv4 address available
|
||||
# 2 = Port-restricted IPv4 address available
|
||||
# 3 = Single NATed private IPv4 address available
|
||||
# 4 = Double NATed private IPv4 address available
|
||||
# 5 = Port-restricted IPv4 address and single NATed IPv4 address available
|
||||
# 6 = Port-restricted IPv4 address and double NATed IPv4 address available
|
||||
# 7 = Availability of the address type is not known
|
||||
# ipv6_type:
|
||||
# 0 = Address type not available
|
||||
# 1 = Address type available
|
||||
# 2 = Availability of the address type not known
|
||||
#ipaddr_type_availability=14
|
||||
|
||||
# Domain Name
|
||||
# format: <variable-octet str>[,<variable-octet str>]
|
||||
#domain_name=example.com,another.example.com,yet-another.example.com
|
||||
|
||||
# 3GPP Cellular Network information
|
||||
# format: <MCC1,MNC1>[;<MCC2,MNC2>][;...]
|
||||
#anqp_3gpp_cell_net=244,91;310,026;234,56
|
||||
|
||||
# NAI Realm information
|
||||
# One or more realm can be advertised. Each nai_realm line adds a new realm to
|
||||
# the set. These parameters provide information for stations using Interworking
|
||||
# network selection to allow automatic connection to a network based on
|
||||
# credentials.
|
||||
# format: <encoding>,<NAI Realm(s)>[,<EAP Method 1>][,<EAP Method 2>][,...]
|
||||
# encoding:
|
||||
# 0 = Realm formatted in accordance with IETF RFC 4282
|
||||
# 1 = UTF-8 formatted character string that is not formatted in
|
||||
# accordance with IETF RFC 4282
|
||||
# NAI Realm(s): Semi-colon delimited NAI Realm(s)
|
||||
# EAP Method: <EAP Method>[:<[AuthParam1:Val1]>][<[AuthParam2:Val2]>][...]
|
||||
# AuthParam (Table 8-188 in IEEE Std 802.11-2012):
|
||||
# ID 2 = Non-EAP Inner Authentication Type
|
||||
# 1 = PAP, 2 = CHAP, 3 = MSCHAP, 4 = MSCHAPV2
|
||||
# ID 3 = Inner authentication EAP Method Type
|
||||
# ID 5 = Credential Type
|
||||
# 1 = SIM, 2 = USIM, 3 = NFC Secure Element, 4 = Hardware Token,
|
||||
# 5 = Softoken, 6 = Certificate, 7 = username/password, 9 = Anonymous,
|
||||
# 10 = Vendor Specific
|
||||
#nai_realm=0,example.com;example.net
|
||||
# EAP methods EAP-TLS with certificate and EAP-TTLS/MSCHAPv2 with
|
||||
# username/password
|
||||
#nai_realm=0,example.org,13[5:6],21[2:4][5:7]
|
||||
|
||||
##### Hotspot 2.0 #############################################################
|
||||
|
||||
# Enable Hotspot 2.0 support
|
||||
#hs20=1
|
||||
|
||||
# Disable Downstream Group-Addressed Forwarding (DGAF)
|
||||
# This can be used to configure a network where no group-addressed frames are
|
||||
# allowed. The AP will not forward any group-address frames to the stations and
|
||||
# random GTKs are issued for each station to prevent associated stations from
|
||||
# forging such frames to other stations in the BSS.
|
||||
#disable_dgaf=1
|
||||
|
||||
# Operator Friendly Name
|
||||
# This parameter can be used to configure one or more Operator Friendly Name
|
||||
# Duples. Each entry has a two or three character language code (ISO-639)
|
||||
# separated by colon from the operator friendly name string.
|
||||
#hs20_oper_friendly_name=eng:Example operator
|
||||
#hs20_oper_friendly_name=fin:Esimerkkioperaattori
|
||||
|
||||
# Connection Capability
|
||||
# This can be used to advertise what type of IP traffic can be sent through the
|
||||
# hotspot (e.g., due to firewall allowing/blocking protocols/ports).
|
||||
# format: <IP Protocol>:<Port Number>:<Status>
|
||||
# IP Protocol: 1 = ICMP, 6 = TCP, 17 = UDP
|
||||
# Port Number: 0..65535
|
||||
# Status: 0 = Closed, 1 = Open, 2 = Unknown
|
||||
# Each hs20_conn_capab line is added to the list of advertised tuples.
|
||||
#hs20_conn_capab=1:0:2
|
||||
#hs20_conn_capab=6:22:1
|
||||
#hs20_conn_capab=17:5060:0
|
||||
|
||||
# WAN Metrics
|
||||
# format: <WAN Info>:<DL Speed>:<UL Speed>:<DL Load>:<UL Load>:<LMD>
|
||||
# WAN Info: B0-B1: Link Status, B2: Symmetric Link, B3: At Capabity
|
||||
# (encoded as two hex digits)
|
||||
# Link Status: 1 = Link up, 2 = Link down, 3 = Link in test state
|
||||
# Downlink Speed: Estimate of WAN backhaul link current downlink speed in kbps;
|
||||
# 1..4294967295; 0 = unknown
|
||||
# Uplink Speed: Estimate of WAN backhaul link current uplink speed in kbps
|
||||
# 1..4294967295; 0 = unknown
|
||||
# Downlink Load: Current load of downlink WAN connection (scaled to 255 = 100%)
|
||||
# Uplink Load: Current load of uplink WAN connection (scaled to 255 = 100%)
|
||||
# Load Measurement Duration: Duration for measuring downlink/uplink load in
|
||||
# tenths of a second (1..65535); 0 if load cannot be determined
|
||||
#hs20_wan_metrics=01:8000:1000:80:240:3000
|
||||
|
||||
# Operating Class Indication
|
||||
# List of operating classes the BSSes in this ESS use. The Global operating
|
||||
# classes in Table E-4 of IEEE Std 802.11-2012 Annex E define the values that
|
||||
# can be used in this.
|
||||
# format: hexdump of operating class octets
|
||||
# for example, operating classes 81 (2.4 GHz channels 1-13) and 115 (5 GHz
|
||||
# channels 36-48):
|
||||
#hs20_operating_class=5173
|
||||
|
||||
##### Multiple BSSID support ##################################################
|
||||
#
|
||||
# Above configuration is using the default interface (wlan#, or multi-SSID VLAN
|
||||
|
@ -69,6 +69,9 @@
|
||||
"3"* SIM,TTLS,TLS,PEAP,AKA
|
||||
"4"* AKA,TTLS,TLS,PEAP,SIM
|
||||
"5"* SIM,TTLS,TLS,PEAP,AKA
|
||||
"6"* AKA'
|
||||
"7"* AKA'
|
||||
"8"* AKA'
|
||||
|
||||
# Wildcard for all other identities
|
||||
* PEAP,TTLS,TLS,SIM,AKA
|
||||
@ -89,3 +92,6 @@
|
||||
"3"* SIM [2]
|
||||
"4"* AKA [2]
|
||||
"5"* SIM [2]
|
||||
"6"* AKA' [2]
|
||||
"7"* AKA' [2]
|
||||
"8"* AKA' [2]
|
||||
|
17
hostapd/hostapd.eap_user_sqlite
Normal file
17
hostapd/hostapd.eap_user_sqlite
Normal file
@ -0,0 +1,17 @@
|
||||
CREATE TABLE users(
|
||||
identity TEXT PRIMARY KEY,
|
||||
methods TEXT,
|
||||
password TEXT,
|
||||
phase2 INTEGER
|
||||
);
|
||||
|
||||
CREATE TABLE wildcards(
|
||||
identity TEXT PRIMARY KEY,
|
||||
methods TEXT
|
||||
);
|
||||
|
||||
INSERT INTO users(identity,methods,password,phase2) VALUES ('user','TTLS-MSCHAPV2','password',1);
|
||||
INSERT INTO users(identity,methods,password,phase2) VALUES ('DOMAIN\mschapv2 user','TTLS-MSCHAPV2','password',1);
|
||||
|
||||
INSERT INTO wildcards(identity,methods) VALUES ('','TTLS,TLS');
|
||||
INSERT INTO wildcards(identity,methods) VALUES ('0','AKA');
|
@ -1,53 +1,32 @@
|
||||
/*
|
||||
* hostapd - command line interface for hostapd daemon
|
||||
* Copyright (c) 2004-2010, Jouni Malinen <j@w1.fi>
|
||||
* Copyright (c) 2004-2012, Jouni Malinen <j@w1.fi>
|
||||
*
|
||||
* This program is free software; you can redistribute it and/or modify
|
||||
* it under the terms of the GNU General Public License version 2 as
|
||||
* published by the Free Software Foundation.
|
||||
*
|
||||
* Alternatively, this software may be distributed under the terms of BSD
|
||||
* license.
|
||||
*
|
||||
* See README and COPYING for more details.
|
||||
* This software may be distributed under the terms of the BSD license.
|
||||
* See README for more details.
|
||||
*/
|
||||
|
||||
#include "includes.h"
|
||||
#include <dirent.h>
|
||||
|
||||
#include "common/wpa_ctrl.h"
|
||||
#include "common.h"
|
||||
#include "utils/common.h"
|
||||
#include "utils/eloop.h"
|
||||
#include "utils/edit.h"
|
||||
#include "common/version.h"
|
||||
|
||||
|
||||
static const char *hostapd_cli_version =
|
||||
"hostapd_cli v" VERSION_STR "\n"
|
||||
"Copyright (c) 2004-2010, Jouni Malinen <j@w1.fi> and contributors";
|
||||
"Copyright (c) 2004-2012, Jouni Malinen <j@w1.fi> and contributors";
|
||||
|
||||
|
||||
static const char *hostapd_cli_license =
|
||||
"This program is free software. You can distribute it and/or modify it\n"
|
||||
"under the terms of the GNU General Public License version 2.\n"
|
||||
"\n"
|
||||
"Alternatively, this software may be distributed under the terms of the\n"
|
||||
"BSD license. See README and COPYING for more details.\n";
|
||||
"This software may be distributed under the terms of the BSD license.\n"
|
||||
"See README for more details.\n";
|
||||
|
||||
static const char *hostapd_cli_full_license =
|
||||
"This program is free software; you can redistribute it and/or modify\n"
|
||||
"it under the terms of the GNU General Public License version 2 as\n"
|
||||
"published by the Free Software Foundation.\n"
|
||||
"\n"
|
||||
"This program is distributed in the hope that it will be useful,\n"
|
||||
"but WITHOUT ANY WARRANTY; without even the implied warranty of\n"
|
||||
"MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the\n"
|
||||
"GNU General Public License for more details.\n"
|
||||
"\n"
|
||||
"You should have received a copy of the GNU General Public License\n"
|
||||
"along with this program; if not, write to the Free Software\n"
|
||||
"Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA\n"
|
||||
"\n"
|
||||
"Alternatively, this software may be distributed under the terms of the\n"
|
||||
"BSD license.\n"
|
||||
"This software may be distributed under the terms of the BSD license.\n"
|
||||
"\n"
|
||||
"Redistribution and use in source and binary forms, with or without\n"
|
||||
"modification, are permitted provided that the following conditions are\n"
|
||||
@ -89,13 +68,19 @@ static const char *commands_help =
|
||||
" sa_query <addr> send SA Query to a station\n"
|
||||
#endif /* CONFIG_IEEE80211W */
|
||||
#ifdef CONFIG_WPS
|
||||
" wps_pin <uuid> <pin> [timeout] add WPS Enrollee PIN (Device Password)\n"
|
||||
" wps_pin <uuid> <pin> [timeout] [addr] add WPS Enrollee PIN\n"
|
||||
" wps_check_pin <PIN> verify PIN checksum\n"
|
||||
" wps_pbc indicate button pushed to initiate PBC\n"
|
||||
#ifdef CONFIG_WPS_OOB
|
||||
" wps_oob <type> <path> <method> use WPS with out-of-band (UFD)\n"
|
||||
#endif /* CONFIG_WPS_OOB */
|
||||
" wps_cancel cancel the pending WPS operation\n"
|
||||
#ifdef CONFIG_WPS_NFC
|
||||
" wps_nfc_tag_read <hexdump> report read NFC tag with WPS data\n"
|
||||
" wps_nfc_config_token <WPS/NDEF> build NFC configuration token\n"
|
||||
" wps_nfc_token <WPS/NDEF/enable/disable> manager NFC password token\n"
|
||||
#endif /* CONFIG_WPS_NFC */
|
||||
" wps_ap_pin <cmd> [params..] enable/disable AP PIN\n"
|
||||
" wps_config <SSID> <auth> <encr> <key> configure AP\n"
|
||||
#endif /* CONFIG_WPS */
|
||||
" get_config show current configuration\n"
|
||||
" help show this usage help\n"
|
||||
" interface [ifname] show interfaces/select interface\n"
|
||||
" level <debug level> change debug level\n"
|
||||
@ -110,6 +95,7 @@ static char *ctrl_ifname = NULL;
|
||||
static const char *pid_file = NULL;
|
||||
static const char *action_file = NULL;
|
||||
static int ping_interval = 5;
|
||||
static int interactive = 0;
|
||||
|
||||
|
||||
static void usage(void)
|
||||
@ -218,6 +204,12 @@ static int hostapd_cli_cmd_ping(struct wpa_ctrl *ctrl, int argc, char *argv[])
|
||||
}
|
||||
|
||||
|
||||
static int hostapd_cli_cmd_relog(struct wpa_ctrl *ctrl, int argc, char *argv[])
|
||||
{
|
||||
return wpa_ctrl_command(ctrl, "RELOG");
|
||||
}
|
||||
|
||||
|
||||
static int hostapd_cli_cmd_mib(struct wpa_ctrl *ctrl, int argc, char *argv[])
|
||||
{
|
||||
return wpa_ctrl_command(ctrl, "MIB");
|
||||
@ -352,13 +344,16 @@ static int hostapd_cli_cmd_sa_query(struct wpa_ctrl *ctrl, int argc,
|
||||
static int hostapd_cli_cmd_wps_pin(struct wpa_ctrl *ctrl, int argc,
|
||||
char *argv[])
|
||||
{
|
||||
char buf[64];
|
||||
char buf[256];
|
||||
if (argc < 2) {
|
||||
printf("Invalid 'wps_pin' command - at least two arguments, "
|
||||
"UUID and PIN, are required.\n");
|
||||
return -1;
|
||||
}
|
||||
if (argc > 2)
|
||||
if (argc > 3)
|
||||
snprintf(buf, sizeof(buf), "WPS_PIN %s %s %s %s",
|
||||
argv[0], argv[1], argv[2], argv[3]);
|
||||
else if (argc > 2)
|
||||
snprintf(buf, sizeof(buf), "WPS_PIN %s %s %s",
|
||||
argv[0], argv[1], argv[2]);
|
||||
else
|
||||
@ -367,6 +362,32 @@ static int hostapd_cli_cmd_wps_pin(struct wpa_ctrl *ctrl, int argc,
|
||||
}
|
||||
|
||||
|
||||
static int hostapd_cli_cmd_wps_check_pin(struct wpa_ctrl *ctrl, int argc,
|
||||
char *argv[])
|
||||
{
|
||||
char cmd[256];
|
||||
int res;
|
||||
|
||||
if (argc != 1 && argc != 2) {
|
||||
printf("Invalid WPS_CHECK_PIN command: needs one argument:\n"
|
||||
"- PIN to be verified\n");
|
||||
return -1;
|
||||
}
|
||||
|
||||
if (argc == 2)
|
||||
res = os_snprintf(cmd, sizeof(cmd), "WPS_CHECK_PIN %s %s",
|
||||
argv[0], argv[1]);
|
||||
else
|
||||
res = os_snprintf(cmd, sizeof(cmd), "WPS_CHECK_PIN %s",
|
||||
argv[0]);
|
||||
if (res < 0 || (size_t) res >= sizeof(cmd) - 1) {
|
||||
printf("Too long WPS_CHECK_PIN command.\n");
|
||||
return -1;
|
||||
}
|
||||
return wpa_ctrl_command(ctrl, cmd);
|
||||
}
|
||||
|
||||
|
||||
static int hostapd_cli_cmd_wps_pbc(struct wpa_ctrl *ctrl, int argc,
|
||||
char *argv[])
|
||||
{
|
||||
@ -374,38 +395,82 @@ static int hostapd_cli_cmd_wps_pbc(struct wpa_ctrl *ctrl, int argc,
|
||||
}
|
||||
|
||||
|
||||
#ifdef CONFIG_WPS_OOB
|
||||
static int hostapd_cli_cmd_wps_oob(struct wpa_ctrl *ctrl, int argc,
|
||||
char *argv[])
|
||||
static int hostapd_cli_cmd_wps_cancel(struct wpa_ctrl *ctrl, int argc,
|
||||
char *argv[])
|
||||
{
|
||||
char cmd[256];
|
||||
int res;
|
||||
return wpa_ctrl_command(ctrl, "WPS_CANCEL");
|
||||
}
|
||||
|
||||
if (argc != 3 && argc != 4) {
|
||||
printf("Invalid WPS_OOB command: need three or four "
|
||||
"arguments:\n"
|
||||
"- DEV_TYPE: use 'ufd' or 'nfc'\n"
|
||||
"- PATH: path of OOB device like '/mnt'\n"
|
||||
"- METHOD: OOB method 'pin-e' or 'pin-r', "
|
||||
"'cred'\n"
|
||||
"- DEV_NAME: (only for NFC) device name like "
|
||||
"'pn531'\n");
|
||||
|
||||
#ifdef CONFIG_WPS_NFC
|
||||
static int hostapd_cli_cmd_wps_nfc_tag_read(struct wpa_ctrl *ctrl, int argc,
|
||||
char *argv[])
|
||||
{
|
||||
int ret;
|
||||
char *buf;
|
||||
size_t buflen;
|
||||
|
||||
if (argc != 1) {
|
||||
printf("Invalid 'wps_nfc_tag_read' command - one argument "
|
||||
"is required.\n");
|
||||
return -1;
|
||||
}
|
||||
|
||||
if (argc == 3)
|
||||
res = os_snprintf(cmd, sizeof(cmd), "WPS_OOB %s %s %s",
|
||||
argv[0], argv[1], argv[2]);
|
||||
else
|
||||
res = os_snprintf(cmd, sizeof(cmd), "WPS_OOB %s %s %s %s",
|
||||
argv[0], argv[1], argv[2], argv[3]);
|
||||
buflen = 18 + os_strlen(argv[0]);
|
||||
buf = os_malloc(buflen);
|
||||
if (buf == NULL)
|
||||
return -1;
|
||||
os_snprintf(buf, buflen, "WPS_NFC_TAG_READ %s", argv[0]);
|
||||
|
||||
ret = wpa_ctrl_command(ctrl, buf);
|
||||
os_free(buf);
|
||||
|
||||
return ret;
|
||||
}
|
||||
|
||||
|
||||
static int hostapd_cli_cmd_wps_nfc_config_token(struct wpa_ctrl *ctrl,
|
||||
int argc, char *argv[])
|
||||
{
|
||||
char cmd[64];
|
||||
int res;
|
||||
|
||||
if (argc != 1) {
|
||||
printf("Invalid 'wps_nfc_config_token' command - one argument "
|
||||
"is required.\n");
|
||||
return -1;
|
||||
}
|
||||
|
||||
res = os_snprintf(cmd, sizeof(cmd), "WPS_NFC_CONFIG_TOKEN %s",
|
||||
argv[0]);
|
||||
if (res < 0 || (size_t) res >= sizeof(cmd) - 1) {
|
||||
printf("Too long WPS_OOB command.\n");
|
||||
printf("Too long WPS_NFC_CONFIG_TOKEN command.\n");
|
||||
return -1;
|
||||
}
|
||||
return wpa_ctrl_command(ctrl, cmd);
|
||||
}
|
||||
#endif /* CONFIG_WPS_OOB */
|
||||
|
||||
|
||||
static int hostapd_cli_cmd_wps_nfc_token(struct wpa_ctrl *ctrl,
|
||||
int argc, char *argv[])
|
||||
{
|
||||
char cmd[64];
|
||||
int res;
|
||||
|
||||
if (argc != 1) {
|
||||
printf("Invalid 'wps_nfc_token' command - one argument is "
|
||||
"required.\n");
|
||||
return -1;
|
||||
}
|
||||
|
||||
res = os_snprintf(cmd, sizeof(cmd), "WPS_NFC_TOKEN %s", argv[0]);
|
||||
if (res < 0 || (size_t) res >= sizeof(cmd) - 1) {
|
||||
printf("Too long WPS_NFC_TOKEN command.\n");
|
||||
return -1;
|
||||
}
|
||||
return wpa_ctrl_command(ctrl, cmd);
|
||||
}
|
||||
#endif /* CONFIG_WPS_NFC */
|
||||
|
||||
|
||||
static int hostapd_cli_cmd_wps_ap_pin(struct wpa_ctrl *ctrl, int argc,
|
||||
@ -427,9 +492,100 @@ static int hostapd_cli_cmd_wps_ap_pin(struct wpa_ctrl *ctrl, int argc,
|
||||
snprintf(buf, sizeof(buf), "WPS_AP_PIN %s", argv[0]);
|
||||
return wpa_ctrl_command(ctrl, buf);
|
||||
}
|
||||
|
||||
|
||||
static int hostapd_cli_cmd_wps_config(struct wpa_ctrl *ctrl, int argc,
|
||||
char *argv[])
|
||||
{
|
||||
char buf[256];
|
||||
char ssid_hex[2 * 32 + 1];
|
||||
char key_hex[2 * 64 + 1];
|
||||
int i;
|
||||
|
||||
if (argc < 1) {
|
||||
printf("Invalid 'wps_config' command - at least two arguments "
|
||||
"are required.\n");
|
||||
return -1;
|
||||
}
|
||||
|
||||
ssid_hex[0] = '\0';
|
||||
for (i = 0; i < 32; i++) {
|
||||
if (argv[0][i] == '\0')
|
||||
break;
|
||||
os_snprintf(&ssid_hex[i * 2], 3, "%02x", argv[0][i]);
|
||||
}
|
||||
|
||||
key_hex[0] = '\0';
|
||||
if (argc > 3) {
|
||||
for (i = 0; i < 64; i++) {
|
||||
if (argv[3][i] == '\0')
|
||||
break;
|
||||
os_snprintf(&key_hex[i * 2], 3, "%02x",
|
||||
argv[3][i]);
|
||||
}
|
||||
}
|
||||
|
||||
if (argc > 3)
|
||||
snprintf(buf, sizeof(buf), "WPS_CONFIG %s %s %s %s",
|
||||
ssid_hex, argv[1], argv[2], key_hex);
|
||||
else if (argc > 2)
|
||||
snprintf(buf, sizeof(buf), "WPS_CONFIG %s %s %s",
|
||||
ssid_hex, argv[1], argv[2]);
|
||||
else
|
||||
snprintf(buf, sizeof(buf), "WPS_CONFIG %s %s",
|
||||
ssid_hex, argv[1]);
|
||||
return wpa_ctrl_command(ctrl, buf);
|
||||
}
|
||||
#endif /* CONFIG_WPS */
|
||||
|
||||
|
||||
static int hostapd_cli_cmd_disassoc_imminent(struct wpa_ctrl *ctrl, int argc,
|
||||
char *argv[])
|
||||
{
|
||||
char buf[300];
|
||||
int res;
|
||||
|
||||
if (argc < 2) {
|
||||
printf("Invalid 'disassoc_imminent' command - two arguments "
|
||||
"(STA addr and Disassociation Timer) are needed\n");
|
||||
return -1;
|
||||
}
|
||||
|
||||
res = os_snprintf(buf, sizeof(buf), "DISASSOC_IMMINENT %s %s",
|
||||
argv[0], argv[1]);
|
||||
if (res < 0 || res >= (int) sizeof(buf))
|
||||
return -1;
|
||||
return wpa_ctrl_command(ctrl, buf);
|
||||
}
|
||||
|
||||
|
||||
static int hostapd_cli_cmd_ess_disassoc(struct wpa_ctrl *ctrl, int argc,
|
||||
char *argv[])
|
||||
{
|
||||
char buf[300];
|
||||
int res;
|
||||
|
||||
if (argc < 2) {
|
||||
printf("Invalid 'ess_disassoc' command - two arguments (STA "
|
||||
"addr and URL) are needed\n");
|
||||
return -1;
|
||||
}
|
||||
|
||||
res = os_snprintf(buf, sizeof(buf), "ESS_DISASSOC %s %s",
|
||||
argv[0], argv[1]);
|
||||
if (res < 0 || res >= (int) sizeof(buf))
|
||||
return -1;
|
||||
return wpa_ctrl_command(ctrl, buf);
|
||||
}
|
||||
|
||||
|
||||
static int hostapd_cli_cmd_get_config(struct wpa_ctrl *ctrl, int argc,
|
||||
char *argv[])
|
||||
{
|
||||
return wpa_ctrl_command(ctrl, "GET_CONFIG");
|
||||
}
|
||||
|
||||
|
||||
static int wpa_ctrl_command_sta(struct wpa_ctrl *ctrl, char *cmd,
|
||||
char *addr, size_t addr_len)
|
||||
{
|
||||
@ -499,6 +655,8 @@ static int hostapd_cli_cmd_license(struct wpa_ctrl *ctrl, int argc,
|
||||
static int hostapd_cli_cmd_quit(struct wpa_ctrl *ctrl, int argc, char *argv[])
|
||||
{
|
||||
hostapd_cli_quit = 1;
|
||||
if (interactive)
|
||||
eloop_terminate();
|
||||
return 0;
|
||||
}
|
||||
|
||||
@ -567,6 +725,46 @@ static int hostapd_cli_cmd_interface(struct wpa_ctrl *ctrl, int argc,
|
||||
}
|
||||
|
||||
|
||||
static int hostapd_cli_cmd_set(struct wpa_ctrl *ctrl, int argc, char *argv[])
|
||||
{
|
||||
char cmd[256];
|
||||
int res;
|
||||
|
||||
if (argc != 2) {
|
||||
printf("Invalid SET command: needs two arguments (variable "
|
||||
"name and value)\n");
|
||||
return -1;
|
||||
}
|
||||
|
||||
res = os_snprintf(cmd, sizeof(cmd), "SET %s %s", argv[0], argv[1]);
|
||||
if (res < 0 || (size_t) res >= sizeof(cmd) - 1) {
|
||||
printf("Too long SET command.\n");
|
||||
return -1;
|
||||
}
|
||||
return wpa_ctrl_command(ctrl, cmd);
|
||||
}
|
||||
|
||||
|
||||
static int hostapd_cli_cmd_get(struct wpa_ctrl *ctrl, int argc, char *argv[])
|
||||
{
|
||||
char cmd[256];
|
||||
int res;
|
||||
|
||||
if (argc != 1) {
|
||||
printf("Invalid GET command: needs one argument (variable "
|
||||
"name)\n");
|
||||
return -1;
|
||||
}
|
||||
|
||||
res = os_snprintf(cmd, sizeof(cmd), "GET %s", argv[0]);
|
||||
if (res < 0 || (size_t) res >= sizeof(cmd) - 1) {
|
||||
printf("Too long GET command.\n");
|
||||
return -1;
|
||||
}
|
||||
return wpa_ctrl_command(ctrl, cmd);
|
||||
}
|
||||
|
||||
|
||||
struct hostapd_cli_cmd {
|
||||
const char *cmd;
|
||||
int (*handler)(struct wpa_ctrl *ctrl, int argc, char *argv[]);
|
||||
@ -575,6 +773,7 @@ struct hostapd_cli_cmd {
|
||||
static struct hostapd_cli_cmd hostapd_cli_commands[] = {
|
||||
{ "ping", hostapd_cli_cmd_ping },
|
||||
{ "mib", hostapd_cli_cmd_mib },
|
||||
{ "relog", hostapd_cli_cmd_relog },
|
||||
{ "sta", hostapd_cli_cmd_sta },
|
||||
{ "all_sta", hostapd_cli_cmd_all_sta },
|
||||
{ "new_sta", hostapd_cli_cmd_new_sta },
|
||||
@ -585,17 +784,27 @@ static struct hostapd_cli_cmd hostapd_cli_commands[] = {
|
||||
#endif /* CONFIG_IEEE80211W */
|
||||
#ifdef CONFIG_WPS
|
||||
{ "wps_pin", hostapd_cli_cmd_wps_pin },
|
||||
{ "wps_check_pin", hostapd_cli_cmd_wps_check_pin },
|
||||
{ "wps_pbc", hostapd_cli_cmd_wps_pbc },
|
||||
#ifdef CONFIG_WPS_OOB
|
||||
{ "wps_oob", hostapd_cli_cmd_wps_oob },
|
||||
#endif /* CONFIG_WPS_OOB */
|
||||
{ "wps_cancel", hostapd_cli_cmd_wps_cancel },
|
||||
#ifdef CONFIG_WPS_NFC
|
||||
{ "wps_nfc_tag_read", hostapd_cli_cmd_wps_nfc_tag_read },
|
||||
{ "wps_nfc_config_token", hostapd_cli_cmd_wps_nfc_config_token },
|
||||
{ "wps_nfc_token", hostapd_cli_cmd_wps_nfc_token },
|
||||
#endif /* CONFIG_WPS_NFC */
|
||||
{ "wps_ap_pin", hostapd_cli_cmd_wps_ap_pin },
|
||||
{ "wps_config", hostapd_cli_cmd_wps_config },
|
||||
#endif /* CONFIG_WPS */
|
||||
{ "disassoc_imminent", hostapd_cli_cmd_disassoc_imminent },
|
||||
{ "ess_disassoc", hostapd_cli_cmd_ess_disassoc },
|
||||
{ "get_config", hostapd_cli_cmd_get_config },
|
||||
{ "help", hostapd_cli_cmd_help },
|
||||
{ "interface", hostapd_cli_cmd_interface },
|
||||
{ "level", hostapd_cli_cmd_level },
|
||||
{ "license", hostapd_cli_cmd_license },
|
||||
{ "quit", hostapd_cli_cmd_quit },
|
||||
{ "set", hostapd_cli_cmd_set },
|
||||
{ "get", hostapd_cli_cmd_get },
|
||||
{ NULL, NULL }
|
||||
};
|
||||
|
||||
@ -610,6 +819,11 @@ static void wpa_request(struct wpa_ctrl *ctrl, int argc, char *argv[])
|
||||
while (cmd->cmd) {
|
||||
if (strncasecmp(cmd->cmd, argv[0], strlen(argv[0])) == 0) {
|
||||
match = cmd;
|
||||
if (os_strcasecmp(cmd->cmd, argv[0]) == 0) {
|
||||
/* we have an exact match */
|
||||
count = 1;
|
||||
break;
|
||||
}
|
||||
count++;
|
||||
}
|
||||
cmd++;
|
||||
@ -661,70 +875,39 @@ static void hostapd_cli_recv_pending(struct wpa_ctrl *ctrl, int in_read,
|
||||
}
|
||||
|
||||
|
||||
static void hostapd_cli_interactive(void)
|
||||
#define max_args 10
|
||||
|
||||
static int tokenize_cmd(char *cmd, char *argv[])
|
||||
{
|
||||
const int max_args = 10;
|
||||
char cmd[256], *res, *argv[max_args], *pos;
|
||||
int argc;
|
||||
char *pos;
|
||||
int argc = 0;
|
||||
|
||||
printf("\nInteractive mode\n\n");
|
||||
|
||||
do {
|
||||
hostapd_cli_recv_pending(ctrl_conn, 0, 0);
|
||||
printf("> ");
|
||||
alarm(ping_interval);
|
||||
res = fgets(cmd, sizeof(cmd), stdin);
|
||||
alarm(0);
|
||||
if (res == NULL)
|
||||
break;
|
||||
pos = cmd;
|
||||
while (*pos != '\0') {
|
||||
if (*pos == '\n') {
|
||||
*pos = '\0';
|
||||
break;
|
||||
}
|
||||
pos = cmd;
|
||||
for (;;) {
|
||||
while (*pos == ' ')
|
||||
pos++;
|
||||
if (*pos == '\0')
|
||||
break;
|
||||
argv[argc] = pos;
|
||||
argc++;
|
||||
if (argc == max_args)
|
||||
break;
|
||||
if (*pos == '"') {
|
||||
char *pos2 = os_strrchr(pos, '"');
|
||||
if (pos2)
|
||||
pos = pos2 + 1;
|
||||
}
|
||||
argc = 0;
|
||||
pos = cmd;
|
||||
for (;;) {
|
||||
while (*pos == ' ')
|
||||
pos++;
|
||||
if (*pos == '\0')
|
||||
break;
|
||||
argv[argc] = pos;
|
||||
argc++;
|
||||
if (argc == max_args)
|
||||
break;
|
||||
while (*pos != '\0' && *pos != ' ')
|
||||
pos++;
|
||||
if (*pos == ' ')
|
||||
*pos++ = '\0';
|
||||
}
|
||||
if (argc)
|
||||
wpa_request(ctrl_conn, argc, argv);
|
||||
} while (!hostapd_cli_quit);
|
||||
while (*pos != '\0' && *pos != ' ')
|
||||
pos++;
|
||||
if (*pos == ' ')
|
||||
*pos++ = '\0';
|
||||
}
|
||||
|
||||
return argc;
|
||||
}
|
||||
|
||||
|
||||
static void hostapd_cli_cleanup(void)
|
||||
{
|
||||
hostapd_cli_close_connection();
|
||||
if (pid_file)
|
||||
os_daemonize_terminate(pid_file);
|
||||
|
||||
os_program_deinit();
|
||||
}
|
||||
|
||||
|
||||
static void hostapd_cli_terminate(int sig)
|
||||
{
|
||||
hostapd_cli_cleanup();
|
||||
exit(0);
|
||||
}
|
||||
|
||||
|
||||
static void hostapd_cli_alarm(int sig)
|
||||
static void hostapd_cli_ping(void *eloop_ctx, void *timeout_ctx)
|
||||
{
|
||||
if (ctrl_conn && _wpa_ctrl_command(ctrl_conn, "PING", 0)) {
|
||||
printf("Connection to hostapd lost - trying to reconnect\n");
|
||||
@ -744,7 +927,55 @@ static void hostapd_cli_alarm(int sig)
|
||||
}
|
||||
if (ctrl_conn)
|
||||
hostapd_cli_recv_pending(ctrl_conn, 1, 0);
|
||||
alarm(ping_interval);
|
||||
eloop_register_timeout(ping_interval, 0, hostapd_cli_ping, NULL, NULL);
|
||||
}
|
||||
|
||||
|
||||
static void hostapd_cli_eloop_terminate(int sig, void *signal_ctx)
|
||||
{
|
||||
eloop_terminate();
|
||||
}
|
||||
|
||||
|
||||
static void hostapd_cli_edit_cmd_cb(void *ctx, char *cmd)
|
||||
{
|
||||
char *argv[max_args];
|
||||
int argc;
|
||||
argc = tokenize_cmd(cmd, argv);
|
||||
if (argc)
|
||||
wpa_request(ctrl_conn, argc, argv);
|
||||
}
|
||||
|
||||
|
||||
static void hostapd_cli_edit_eof_cb(void *ctx)
|
||||
{
|
||||
eloop_terminate();
|
||||
}
|
||||
|
||||
|
||||
static void hostapd_cli_interactive(void)
|
||||
{
|
||||
printf("\nInteractive mode\n\n");
|
||||
|
||||
eloop_register_signal_terminate(hostapd_cli_eloop_terminate, NULL);
|
||||
edit_init(hostapd_cli_edit_cmd_cb, hostapd_cli_edit_eof_cb,
|
||||
NULL, NULL, NULL, NULL);
|
||||
eloop_register_timeout(ping_interval, 0, hostapd_cli_ping, NULL, NULL);
|
||||
|
||||
eloop_run();
|
||||
|
||||
edit_deinit(NULL, NULL);
|
||||
eloop_cancel_timeout(hostapd_cli_ping, NULL, NULL);
|
||||
}
|
||||
|
||||
|
||||
static void hostapd_cli_cleanup(void)
|
||||
{
|
||||
hostapd_cli_close_connection();
|
||||
if (pid_file)
|
||||
os_daemonize_terminate(pid_file);
|
||||
|
||||
os_program_deinit();
|
||||
}
|
||||
|
||||
|
||||
@ -787,7 +1018,6 @@ static void hostapd_cli_action(struct wpa_ctrl *ctrl)
|
||||
|
||||
int main(int argc, char *argv[])
|
||||
{
|
||||
int interactive;
|
||||
int warning_displayed = 0;
|
||||
int c;
|
||||
int daemonize = 0;
|
||||
@ -835,6 +1065,9 @@ int main(int argc, char *argv[])
|
||||
hostapd_cli_license);
|
||||
}
|
||||
|
||||
if (eloop_init())
|
||||
return -1;
|
||||
|
||||
for (;;) {
|
||||
if (ctrl_ifname == NULL) {
|
||||
struct dirent *dent;
|
||||
@ -874,10 +1107,6 @@ int main(int argc, char *argv[])
|
||||
continue;
|
||||
}
|
||||
|
||||
signal(SIGINT, hostapd_cli_terminate);
|
||||
signal(SIGTERM, hostapd_cli_terminate);
|
||||
signal(SIGALRM, hostapd_cli_alarm);
|
||||
|
||||
if (interactive || action_file) {
|
||||
if (wpa_ctrl_attach(ctrl_conn) == 0) {
|
||||
hostapd_cli_attached = 1;
|
||||
@ -899,6 +1128,7 @@ int main(int argc, char *argv[])
|
||||
wpa_request(ctrl_conn, argc - optind, &argv[optind]);
|
||||
|
||||
os_free(ctrl_ifname);
|
||||
eloop_destroy();
|
||||
hostapd_cli_cleanup();
|
||||
return 0;
|
||||
}
|
||||
|
226
hostapd/main.c
226
hostapd/main.c
@ -1,15 +1,9 @@
|
||||
/*
|
||||
* hostapd / main()
|
||||
* Copyright (c) 2002-2010, Jouni Malinen <j@w1.fi>
|
||||
* Copyright (c) 2002-2011, Jouni Malinen <j@w1.fi>
|
||||
*
|
||||
* This program is free software; you can redistribute it and/or modify
|
||||
* it under the terms of the GNU General Public License version 2 as
|
||||
* published by the Free Software Foundation.
|
||||
*
|
||||
* Alternatively, this software may be distributed under the terms of BSD
|
||||
* license.
|
||||
*
|
||||
* See README and COPYING for more details.
|
||||
* This software may be distributed under the terms of the BSD license.
|
||||
* See README for more details.
|
||||
*/
|
||||
|
||||
#include "utils/includes.h"
|
||||
@ -19,6 +13,7 @@
|
||||
|
||||
#include "utils/common.h"
|
||||
#include "utils/eloop.h"
|
||||
#include "crypto/random.h"
|
||||
#include "crypto/tls.h"
|
||||
#include "common/version.h"
|
||||
#include "drivers/driver.h"
|
||||
@ -26,6 +21,7 @@
|
||||
#include "eap_server/tncs.h"
|
||||
#include "ap/hostapd.h"
|
||||
#include "ap/ap_config.h"
|
||||
#include "ap/ap_drv_ops.h"
|
||||
#include "config_file.h"
|
||||
#include "eap_register.h"
|
||||
#include "dump_state.h"
|
||||
@ -36,28 +32,15 @@ extern int wpa_debug_level;
|
||||
extern int wpa_debug_show_keys;
|
||||
extern int wpa_debug_timestamp;
|
||||
|
||||
extern struct wpa_driver_ops *wpa_drivers[];
|
||||
|
||||
struct hapd_interfaces {
|
||||
size_t count;
|
||||
struct hostapd_iface **iface;
|
||||
|
||||
struct hapd_global {
|
||||
void **drv_priv;
|
||||
size_t drv_count;
|
||||
};
|
||||
|
||||
|
||||
static int hostapd_for_each_interface(struct hapd_interfaces *interfaces,
|
||||
int (*cb)(struct hostapd_iface *iface,
|
||||
void *ctx), void *ctx)
|
||||
{
|
||||
size_t i;
|
||||
int ret;
|
||||
|
||||
for (i = 0; i < interfaces->count; i++) {
|
||||
ret = cb(interfaces->iface[i], ctx);
|
||||
if (ret)
|
||||
return ret;
|
||||
}
|
||||
|
||||
return 0;
|
||||
}
|
||||
static struct hapd_global global;
|
||||
|
||||
|
||||
#ifndef CONFIG_NO_HOSTAPD_LOGGER
|
||||
@ -183,14 +166,9 @@ static struct hostapd_iface * hostapd_init(const char *config_file)
|
||||
if (hapd_iface == NULL)
|
||||
goto fail;
|
||||
|
||||
hapd_iface->reload_config = hostapd_reload_config;
|
||||
hapd_iface->config_read_cb = hostapd_config_read;
|
||||
hapd_iface->config_fname = os_strdup(config_file);
|
||||
if (hapd_iface->config_fname == NULL)
|
||||
goto fail;
|
||||
hapd_iface->ctrl_iface_init = hostapd_ctrl_iface_init;
|
||||
hapd_iface->ctrl_iface_deinit = hostapd_ctrl_iface_deinit;
|
||||
hapd_iface->for_each_interface = hostapd_for_each_interface;
|
||||
|
||||
conf = hostapd_config_read(hapd_iface->config_fname);
|
||||
if (conf == NULL)
|
||||
@ -198,7 +176,7 @@ static struct hostapd_iface * hostapd_init(const char *config_file)
|
||||
hapd_iface->conf = conf;
|
||||
|
||||
hapd_iface->num_bss = conf->num_bss;
|
||||
hapd_iface->bss = os_zalloc(conf->num_bss *
|
||||
hapd_iface->bss = os_calloc(conf->num_bss,
|
||||
sizeof(struct hostapd_data *));
|
||||
if (hapd_iface->bss == NULL)
|
||||
goto fail;
|
||||
@ -233,6 +211,7 @@ static int hostapd_driver_init(struct hostapd_iface *iface)
|
||||
struct hostapd_data *hapd = iface->bss[0];
|
||||
struct hostapd_bss_config *conf = hapd->conf;
|
||||
u8 *b = conf->bssid;
|
||||
struct wpa_driver_capa capa;
|
||||
|
||||
if (hapd->driver == NULL || hapd->driver->hapd_init == NULL) {
|
||||
wpa_printf(MSG_ERROR, "No hostapd driver wrapper available");
|
||||
@ -244,15 +223,33 @@ static int hostapd_driver_init(struct hostapd_iface *iface)
|
||||
b = NULL;
|
||||
|
||||
os_memset(¶ms, 0, sizeof(params));
|
||||
for (i = 0; wpa_drivers[i]; i++) {
|
||||
if (wpa_drivers[i] != hapd->driver)
|
||||
continue;
|
||||
|
||||
if (global.drv_priv[i] == NULL &&
|
||||
wpa_drivers[i]->global_init) {
|
||||
global.drv_priv[i] = wpa_drivers[i]->global_init();
|
||||
if (global.drv_priv[i] == NULL) {
|
||||
wpa_printf(MSG_ERROR, "Failed to initialize "
|
||||
"driver '%s'",
|
||||
wpa_drivers[i]->name);
|
||||
return -1;
|
||||
}
|
||||
}
|
||||
|
||||
params.global_priv = global.drv_priv[i];
|
||||
break;
|
||||
}
|
||||
params.bssid = b;
|
||||
params.ifname = hapd->conf->iface;
|
||||
params.ssid = (const u8 *) hapd->conf->ssid.ssid;
|
||||
params.ssid = hapd->conf->ssid.ssid;
|
||||
params.ssid_len = hapd->conf->ssid.ssid_len;
|
||||
params.test_socket = hapd->conf->test_socket;
|
||||
params.use_pae_group_addr = hapd->conf->use_pae_group_addr;
|
||||
|
||||
params.num_bridge = hapd->iface->num_bss;
|
||||
params.bridge = os_zalloc(hapd->iface->num_bss * sizeof(char *));
|
||||
params.bridge = os_calloc(hapd->iface->num_bss, sizeof(char *));
|
||||
if (params.bridge == NULL)
|
||||
return -1;
|
||||
for (i = 0; i < hapd->iface->num_bss; i++) {
|
||||
@ -272,25 +269,16 @@ static int hostapd_driver_init(struct hostapd_iface *iface)
|
||||
return -1;
|
||||
}
|
||||
|
||||
if (hapd->driver->get_capa &&
|
||||
hapd->driver->get_capa(hapd->drv_priv, &capa) == 0) {
|
||||
iface->drv_flags = capa.flags;
|
||||
iface->probe_resp_offloads = capa.probe_resp_offloads;
|
||||
}
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
|
||||
static void hostapd_interface_deinit_free(struct hostapd_iface *iface)
|
||||
{
|
||||
const struct wpa_driver_ops *driver;
|
||||
void *drv_priv;
|
||||
if (iface == NULL)
|
||||
return;
|
||||
driver = iface->bss[0]->driver;
|
||||
drv_priv = iface->bss[0]->drv_priv;
|
||||
hostapd_interface_deinit(iface);
|
||||
if (driver && driver->hapd_deinit)
|
||||
driver->hapd_deinit(drv_priv);
|
||||
hostapd_interface_free(iface);
|
||||
}
|
||||
|
||||
|
||||
static struct hostapd_iface *
|
||||
hostapd_interface_init(struct hapd_interfaces *interfaces,
|
||||
const char *config_fname, int debug)
|
||||
@ -309,10 +297,13 @@ hostapd_interface_init(struct hapd_interfaces *interfaces,
|
||||
iface->bss[0]->conf->logger_stdout_level--;
|
||||
}
|
||||
|
||||
if (hostapd_driver_init(iface) ||
|
||||
hostapd_setup_interface(iface)) {
|
||||
hostapd_interface_deinit_free(iface);
|
||||
return NULL;
|
||||
if (iface->conf->bss[0].iface[0] != 0 ||
|
||||
hostapd_drv_none(iface->bss[0])) {
|
||||
if (hostapd_driver_init(iface) ||
|
||||
hostapd_setup_interface(iface)) {
|
||||
hostapd_interface_deinit_free(iface);
|
||||
return NULL;
|
||||
}
|
||||
}
|
||||
|
||||
return iface;
|
||||
@ -363,8 +354,13 @@ static void handle_dump_state(int sig, void *signal_ctx)
|
||||
#endif /* CONFIG_NATIVE_WINDOWS */
|
||||
|
||||
|
||||
static int hostapd_global_init(struct hapd_interfaces *interfaces)
|
||||
static int hostapd_global_init(struct hapd_interfaces *interfaces,
|
||||
const char *entropy_file)
|
||||
{
|
||||
int i;
|
||||
|
||||
os_memset(&global, 0, sizeof(global));
|
||||
|
||||
hostapd_logger_register_cb(hostapd_logger_cb);
|
||||
|
||||
if (eap_server_register_methods()) {
|
||||
@ -377,6 +373,8 @@ static int hostapd_global_init(struct hapd_interfaces *interfaces)
|
||||
return -1;
|
||||
}
|
||||
|
||||
random_init(entropy_file);
|
||||
|
||||
#ifndef CONFIG_NATIVE_WINDOWS
|
||||
eloop_register_signal(SIGHUP, handle_reload, interfaces);
|
||||
eloop_register_signal(SIGUSR1, handle_dump_state, interfaces);
|
||||
@ -387,16 +385,38 @@ static int hostapd_global_init(struct hapd_interfaces *interfaces)
|
||||
openlog("hostapd", 0, LOG_DAEMON);
|
||||
#endif /* CONFIG_NATIVE_WINDOWS */
|
||||
|
||||
for (i = 0; wpa_drivers[i]; i++)
|
||||
global.drv_count++;
|
||||
if (global.drv_count == 0) {
|
||||
wpa_printf(MSG_ERROR, "No drivers enabled");
|
||||
return -1;
|
||||
}
|
||||
global.drv_priv = os_calloc(global.drv_count, sizeof(void *));
|
||||
if (global.drv_priv == NULL)
|
||||
return -1;
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
|
||||
static void hostapd_global_deinit(const char *pid_file)
|
||||
{
|
||||
int i;
|
||||
|
||||
for (i = 0; wpa_drivers[i] && global.drv_priv; i++) {
|
||||
if (!global.drv_priv[i])
|
||||
continue;
|
||||
wpa_drivers[i]->global_deinit(global.drv_priv[i]);
|
||||
}
|
||||
os_free(global.drv_priv);
|
||||
global.drv_priv = NULL;
|
||||
|
||||
#ifdef EAP_SERVER_TNC
|
||||
tncs_global_deinit();
|
||||
#endif /* EAP_SERVER_TNC */
|
||||
|
||||
random_deinit();
|
||||
|
||||
eloop_destroy();
|
||||
|
||||
#ifndef CONFIG_NATIVE_WINDOWS
|
||||
@ -448,7 +468,7 @@ static void show_version(void)
|
||||
"hostapd v" VERSION_STR "\n"
|
||||
"User space daemon for IEEE 802.11 AP management,\n"
|
||||
"IEEE 802.1X/WPA/WPA2/EAP/RADIUS Authenticator\n"
|
||||
"Copyright (c) 2002-2010, Jouni Malinen <j@w1.fi> "
|
||||
"Copyright (c) 2002-2012, Jouni Malinen <j@w1.fi> "
|
||||
"and contributors\n");
|
||||
}
|
||||
|
||||
@ -458,15 +478,21 @@ static void usage(void)
|
||||
show_version();
|
||||
fprintf(stderr,
|
||||
"\n"
|
||||
"usage: hostapd [-hdBKtv] [-P <PID file>] "
|
||||
"<configuration file(s)>\n"
|
||||
"usage: hostapd [-hdBKtv] [-P <PID file>] [-e <entropy file>] "
|
||||
"\\\n"
|
||||
" [-g <global ctrl_iface>] <configuration file(s)>\n"
|
||||
"\n"
|
||||
"options:\n"
|
||||
" -h show this usage\n"
|
||||
" -d show more debug messages (-dd for even more)\n"
|
||||
" -B run daemon in the background\n"
|
||||
" -e entropy file\n"
|
||||
" -g global control interface path\n"
|
||||
" -P PID file\n"
|
||||
" -K include key data in debug messages\n"
|
||||
#ifdef CONFIG_DEBUG_FILE
|
||||
" -f log output to debug file instead of stdout\n"
|
||||
#endif /* CONFIG_DEBUG_FILE */
|
||||
" -t include timestamps in some debug messages\n"
|
||||
" -v show hostapd version\n");
|
||||
|
||||
@ -474,6 +500,37 @@ static void usage(void)
|
||||
}
|
||||
|
||||
|
||||
static const char * hostapd_msg_ifname_cb(void *ctx)
|
||||
{
|
||||
struct hostapd_data *hapd = ctx;
|
||||
if (hapd && hapd->iconf && hapd->iconf->bss)
|
||||
return hapd->iconf->bss->iface;
|
||||
return NULL;
|
||||
}
|
||||
|
||||
|
||||
static int hostapd_get_global_ctrl_iface(struct hapd_interfaces *interfaces,
|
||||
const char *path)
|
||||
{
|
||||
char *pos;
|
||||
os_free(interfaces->global_iface_path);
|
||||
interfaces->global_iface_path = os_strdup(path);
|
||||
if (interfaces->global_iface_path == NULL)
|
||||
return -1;
|
||||
pos = os_strrchr(interfaces->global_iface_path, '/');
|
||||
if (pos == NULL) {
|
||||
os_free(interfaces->global_iface_path);
|
||||
interfaces->global_iface_path = NULL;
|
||||
return -1;
|
||||
}
|
||||
|
||||
*pos = '\0';
|
||||
interfaces->global_iface_name = pos + 1;
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
|
||||
int main(int argc, char *argv[])
|
||||
{
|
||||
struct hapd_interfaces interfaces;
|
||||
@ -481,12 +538,25 @@ int main(int argc, char *argv[])
|
||||
size_t i;
|
||||
int c, debug = 0, daemonize = 0;
|
||||
char *pid_file = NULL;
|
||||
const char *log_file = NULL;
|
||||
const char *entropy_file = NULL;
|
||||
|
||||
if (os_program_init())
|
||||
return -1;
|
||||
|
||||
os_memset(&interfaces, 0, sizeof(interfaces));
|
||||
interfaces.reload_config = hostapd_reload_config;
|
||||
interfaces.config_read_cb = hostapd_config_read;
|
||||
interfaces.for_each_interface = hostapd_for_each_interface;
|
||||
interfaces.ctrl_iface_init = hostapd_ctrl_iface_init;
|
||||
interfaces.ctrl_iface_deinit = hostapd_ctrl_iface_deinit;
|
||||
interfaces.driver_init = hostapd_driver_init;
|
||||
interfaces.global_iface_path = NULL;
|
||||
interfaces.global_iface_name = NULL;
|
||||
interfaces.global_ctrl_sock = -1;
|
||||
|
||||
for (;;) {
|
||||
c = getopt(argc, argv, "BdhKP:tv");
|
||||
c = getopt(argc, argv, "Bde:f:hKP:tvg:");
|
||||
if (c < 0)
|
||||
break;
|
||||
switch (c) {
|
||||
@ -501,6 +571,12 @@ int main(int argc, char *argv[])
|
||||
case 'B':
|
||||
daemonize++;
|
||||
break;
|
||||
case 'e':
|
||||
entropy_file = optarg;
|
||||
break;
|
||||
case 'f':
|
||||
log_file = optarg;
|
||||
break;
|
||||
case 'K':
|
||||
wpa_debug_show_keys++;
|
||||
break;
|
||||
@ -515,6 +591,9 @@ int main(int argc, char *argv[])
|
||||
show_version();
|
||||
exit(1);
|
||||
break;
|
||||
case 'g':
|
||||
hostapd_get_global_ctrl_iface(&interfaces, optarg);
|
||||
break;
|
||||
|
||||
default:
|
||||
usage();
|
||||
@ -522,18 +601,25 @@ int main(int argc, char *argv[])
|
||||
}
|
||||
}
|
||||
|
||||
if (optind == argc)
|
||||
if (optind == argc && interfaces.global_iface_path == NULL)
|
||||
usage();
|
||||
|
||||
wpa_msg_register_ifname_cb(hostapd_msg_ifname_cb);
|
||||
|
||||
if (log_file)
|
||||
wpa_debug_open_file(log_file);
|
||||
|
||||
interfaces.count = argc - optind;
|
||||
interfaces.iface = os_malloc(interfaces.count *
|
||||
sizeof(struct hostapd_iface *));
|
||||
if (interfaces.iface == NULL) {
|
||||
wpa_printf(MSG_ERROR, "malloc failed\n");
|
||||
return -1;
|
||||
if (interfaces.count) {
|
||||
interfaces.iface = os_calloc(interfaces.count,
|
||||
sizeof(struct hostapd_iface *));
|
||||
if (interfaces.iface == NULL) {
|
||||
wpa_printf(MSG_ERROR, "malloc failed");
|
||||
return -1;
|
||||
}
|
||||
}
|
||||
|
||||
if (hostapd_global_init(&interfaces))
|
||||
if (hostapd_global_init(&interfaces, entropy_file))
|
||||
return -1;
|
||||
|
||||
/* Initialize interfaces */
|
||||
@ -545,12 +631,15 @@ int main(int argc, char *argv[])
|
||||
goto out;
|
||||
}
|
||||
|
||||
hostapd_global_ctrl_iface_init(&interfaces);
|
||||
|
||||
if (hostapd_global_run(&interfaces, daemonize, pid_file))
|
||||
goto out;
|
||||
|
||||
ret = 0;
|
||||
|
||||
out:
|
||||
hostapd_global_ctrl_iface_deinit(&interfaces);
|
||||
/* Deinitialize all interfaces */
|
||||
for (i = 0; i < interfaces.count; i++)
|
||||
hostapd_interface_deinit_free(interfaces.iface[i]);
|
||||
@ -559,6 +648,9 @@ int main(int argc, char *argv[])
|
||||
hostapd_global_deinit(pid_file);
|
||||
os_free(pid_file);
|
||||
|
||||
if (log_file)
|
||||
wpa_debug_close_file();
|
||||
|
||||
os_program_deinit();
|
||||
|
||||
return ret;
|
||||
|
@ -2,14 +2,8 @@
|
||||
* hostapd - Plaintext password to NtPasswordHash
|
||||
* Copyright (c) 2005, Jouni Malinen <j@w1.fi>
|
||||
*
|
||||
* This program is free software; you can redistribute it and/or modify
|
||||
* it under the terms of the GNU General Public License version 2 as
|
||||
* published by the Free Software Foundation.
|
||||
*
|
||||
* Alternatively, this software may be distributed under the terms of BSD
|
||||
* license.
|
||||
*
|
||||
* See README and COPYING for more details.
|
||||
* This software may be distributed under the terms of the BSD license.
|
||||
* See README for more details.
|
||||
*/
|
||||
|
||||
#include "includes.h"
|
||||
|
396
patches/openssl-0.9.8x-tls-extensions.patch
Normal file
396
patches/openssl-0.9.8x-tls-extensions.patch
Normal file
@ -0,0 +1,396 @@
|
||||
This patch adds support for TLS SessionTicket extension (RFC 5077) for
|
||||
the parts used by EAP-FAST (RFC 4851).
|
||||
|
||||
This is based on the patch from Alexey Kobozev <akobozev@cisco.com>
|
||||
(sent to openssl-dev mailing list on Tue, 07 Jun 2005 15:40:58 +0300).
|
||||
|
||||
OpenSSL 0.9.8x does not enable TLS extension support by default, so it
|
||||
will need to be enabled by adding enable-tlsext to config script
|
||||
command line.
|
||||
|
||||
|
||||
diff -upr openssl-0.9.8x.orig/ssl/s3_clnt.c openssl-0.9.8x/ssl/s3_clnt.c
|
||||
--- openssl-0.9.8x.orig/ssl/s3_clnt.c 2011-12-26 21:38:28.000000000 +0200
|
||||
+++ openssl-0.9.8x/ssl/s3_clnt.c 2012-07-07 10:46:31.501140621 +0300
|
||||
@@ -757,6 +757,21 @@ int ssl3_get_server_hello(SSL *s)
|
||||
goto f_err;
|
||||
}
|
||||
|
||||
+#ifndef OPENSSL_NO_TLSEXT
|
||||
+ /* check if we want to resume the session based on external pre-shared secret */
|
||||
+ if (s->version >= TLS1_VERSION && s->tls_session_secret_cb)
|
||||
+ {
|
||||
+ SSL_CIPHER *pref_cipher=NULL;
|
||||
+ s->session->master_key_length=sizeof(s->session->master_key);
|
||||
+ if (s->tls_session_secret_cb(s, s->session->master_key, &s->session->master_key_length,
|
||||
+ NULL, &pref_cipher, s->tls_session_secret_cb_arg))
|
||||
+ {
|
||||
+ s->session->cipher=pref_cipher ?
|
||||
+ pref_cipher : ssl_get_cipher_by_char(s,p+j);
|
||||
+ }
|
||||
+ }
|
||||
+#endif /* OPENSSL_NO_TLSEXT */
|
||||
+
|
||||
if (j != 0 && j == s->session->session_id_length
|
||||
&& memcmp(p,s->session->session_id,j) == 0)
|
||||
{
|
||||
@@ -2725,11 +2740,8 @@ int ssl3_check_finished(SSL *s)
|
||||
{
|
||||
int ok;
|
||||
long n;
|
||||
- /* If we have no ticket or session ID is non-zero length (a match of
|
||||
- * a non-zero session length would never reach here) it cannot be a
|
||||
- * resumed session.
|
||||
- */
|
||||
- if (!s->session->tlsext_tick || s->session->session_id_length)
|
||||
+ /* If we have no ticket it cannot be a resumed session. */
|
||||
+ if (!s->session->tlsext_tick)
|
||||
return 1;
|
||||
/* this function is called when we really expect a Certificate
|
||||
* message, so permit appropriate message length */
|
||||
diff -upr openssl-0.9.8x.orig/ssl/s3_srvr.c openssl-0.9.8x/ssl/s3_srvr.c
|
||||
--- openssl-0.9.8x.orig/ssl/s3_srvr.c 2012-02-16 17:21:17.000000000 +0200
|
||||
+++ openssl-0.9.8x/ssl/s3_srvr.c 2012-07-07 10:46:31.501140621 +0300
|
||||
@@ -1009,6 +1009,59 @@ int ssl3_get_client_hello(SSL *s)
|
||||
SSLerr(SSL_F_SSL3_GET_CLIENT_HELLO,SSL_R_CLIENTHELLO_TLSEXT);
|
||||
goto err;
|
||||
}
|
||||
+
|
||||
+ /* Check if we want to use external pre-shared secret for this
|
||||
+ * handshake for not reused session only. We need to generate
|
||||
+ * server_random before calling tls_session_secret_cb in order to allow
|
||||
+ * SessionTicket processing to use it in key derivation. */
|
||||
+ {
|
||||
+ unsigned long Time;
|
||||
+ unsigned char *pos;
|
||||
+ Time=(unsigned long)time(NULL); /* Time */
|
||||
+ pos=s->s3->server_random;
|
||||
+ l2n(Time,pos);
|
||||
+ if (RAND_pseudo_bytes(pos,SSL3_RANDOM_SIZE-4) <= 0)
|
||||
+ {
|
||||
+ al=SSL_AD_INTERNAL_ERROR;
|
||||
+ goto f_err;
|
||||
+ }
|
||||
+ }
|
||||
+
|
||||
+ if (!s->hit && s->version >= TLS1_VERSION && s->tls_session_secret_cb)
|
||||
+ {
|
||||
+ SSL_CIPHER *pref_cipher=NULL;
|
||||
+
|
||||
+ s->session->master_key_length=sizeof(s->session->master_key);
|
||||
+ if(s->tls_session_secret_cb(s, s->session->master_key, &s->session->master_key_length,
|
||||
+ ciphers, &pref_cipher, s->tls_session_secret_cb_arg))
|
||||
+ {
|
||||
+ s->hit=1;
|
||||
+ s->session->ciphers=ciphers;
|
||||
+ s->session->verify_result=X509_V_OK;
|
||||
+
|
||||
+ ciphers=NULL;
|
||||
+
|
||||
+ /* check if some cipher was preferred by call back */
|
||||
+ pref_cipher=pref_cipher ? pref_cipher : ssl3_choose_cipher(s, s->session->ciphers, SSL_get_ciphers(s));
|
||||
+ if (pref_cipher == NULL)
|
||||
+ {
|
||||
+ al=SSL_AD_HANDSHAKE_FAILURE;
|
||||
+ SSLerr(SSL_F_SSL3_GET_CLIENT_HELLO,SSL_R_NO_SHARED_CIPHER);
|
||||
+ goto f_err;
|
||||
+ }
|
||||
+
|
||||
+ s->session->cipher=pref_cipher;
|
||||
+
|
||||
+ if (s->cipher_list)
|
||||
+ sk_SSL_CIPHER_free(s->cipher_list);
|
||||
+
|
||||
+ if (s->cipher_list_by_id)
|
||||
+ sk_SSL_CIPHER_free(s->cipher_list_by_id);
|
||||
+
|
||||
+ s->cipher_list = sk_SSL_CIPHER_dup(s->session->ciphers);
|
||||
+ s->cipher_list_by_id = sk_SSL_CIPHER_dup(s->session->ciphers);
|
||||
+ }
|
||||
+ }
|
||||
#endif
|
||||
/* Worst case, we will use the NULL compression, but if we have other
|
||||
* options, we will now look for them. We have i-1 compression
|
||||
@@ -1147,16 +1200,22 @@ int ssl3_send_server_hello(SSL *s)
|
||||
unsigned char *buf;
|
||||
unsigned char *p,*d;
|
||||
int i,sl;
|
||||
- unsigned long l,Time;
|
||||
+ unsigned long l;
|
||||
+#ifdef OPENSSL_NO_TLSEXT
|
||||
+ unsigned long Time;
|
||||
+#endif
|
||||
|
||||
if (s->state == SSL3_ST_SW_SRVR_HELLO_A)
|
||||
{
|
||||
buf=(unsigned char *)s->init_buf->data;
|
||||
+#ifdef OPENSSL_NO_TLSEXT
|
||||
p=s->s3->server_random;
|
||||
+ /* Generate server_random if it was not needed previously */
|
||||
Time=(unsigned long)time(NULL); /* Time */
|
||||
l2n(Time,p);
|
||||
if (RAND_pseudo_bytes(p,SSL3_RANDOM_SIZE-4) <= 0)
|
||||
return -1;
|
||||
+#endif
|
||||
/* Do the message type and length last */
|
||||
d=p= &(buf[4]);
|
||||
|
||||
diff -upr openssl-0.9.8x.orig/ssl/ssl_err.c openssl-0.9.8x/ssl/ssl_err.c
|
||||
--- openssl-0.9.8x.orig/ssl/ssl_err.c 2012-03-12 16:50:55.000000000 +0200
|
||||
+++ openssl-0.9.8x/ssl/ssl_err.c 2012-07-07 10:46:31.501140621 +0300
|
||||
@@ -264,6 +264,7 @@ static ERR_STRING_DATA SSL_str_functs[]=
|
||||
{ERR_FUNC(SSL_F_TLS1_ENC), "TLS1_ENC"},
|
||||
{ERR_FUNC(SSL_F_TLS1_SETUP_KEY_BLOCK), "TLS1_SETUP_KEY_BLOCK"},
|
||||
{ERR_FUNC(SSL_F_WRITE_PENDING), "WRITE_PENDING"},
|
||||
+{ERR_FUNC(SSL_F_SSL_SET_SESSION_TICKET_EXT), "SSL_set_session_ticket_ext"},
|
||||
{0,NULL}
|
||||
};
|
||||
|
||||
diff -upr openssl-0.9.8x.orig/ssl/ssl.h openssl-0.9.8x/ssl/ssl.h
|
||||
--- openssl-0.9.8x.orig/ssl/ssl.h 2012-03-12 16:50:55.000000000 +0200
|
||||
+++ openssl-0.9.8x/ssl/ssl.h 2012-07-07 10:46:31.501140621 +0300
|
||||
@@ -344,6 +344,7 @@ extern "C" {
|
||||
* 'struct ssl_st *' function parameters used to prototype callbacks
|
||||
* in SSL_CTX. */
|
||||
typedef struct ssl_st *ssl_crock_st;
|
||||
+typedef struct tls_session_ticket_ext_st TLS_SESSION_TICKET_EXT;
|
||||
|
||||
/* used to hold info on the particular ciphers used */
|
||||
typedef struct ssl_cipher_st
|
||||
@@ -362,6 +363,9 @@ typedef struct ssl_cipher_st
|
||||
|
||||
DECLARE_STACK_OF(SSL_CIPHER)
|
||||
|
||||
+typedef int (*tls_session_ticket_ext_cb_fn)(SSL *s, const unsigned char *data, int len, void *arg);
|
||||
+typedef int (*tls_session_secret_cb_fn)(SSL *s, void *secret, int *secret_len, STACK_OF(SSL_CIPHER) *peer_ciphers, SSL_CIPHER **cipher, void *arg);
|
||||
+
|
||||
/* Used to hold functions for SSLv2 or SSLv3/TLSv1 functions */
|
||||
typedef struct ssl_method_st
|
||||
{
|
||||
@@ -1050,6 +1054,18 @@ struct ssl_st
|
||||
|
||||
/* RFC4507 session ticket expected to be received or sent */
|
||||
int tlsext_ticket_expected;
|
||||
+
|
||||
+ /* TLS Session Ticket extension override */
|
||||
+ TLS_SESSION_TICKET_EXT *tlsext_session_ticket;
|
||||
+
|
||||
+ /* TLS Session Ticket extension callback */
|
||||
+ tls_session_ticket_ext_cb_fn tls_session_ticket_ext_cb;
|
||||
+ void *tls_session_ticket_ext_cb_arg;
|
||||
+
|
||||
+ /* TLS pre-shared secret session resumption */
|
||||
+ tls_session_secret_cb_fn tls_session_secret_cb;
|
||||
+ void *tls_session_secret_cb_arg;
|
||||
+
|
||||
SSL_CTX * initial_ctx; /* initial ctx, used to store sessions */
|
||||
#define session_ctx initial_ctx
|
||||
#else
|
||||
@@ -1663,6 +1679,15 @@ void *SSL_COMP_get_compression_methods(v
|
||||
int SSL_COMP_add_compression_method(int id,void *cm);
|
||||
#endif
|
||||
|
||||
+/* TLS extensions functions */
|
||||
+int SSL_set_session_ticket_ext(SSL *s, void *ext_data, int ext_len);
|
||||
+
|
||||
+int SSL_set_session_ticket_ext_cb(SSL *s, tls_session_ticket_ext_cb_fn cb,
|
||||
+ void *arg);
|
||||
+
|
||||
+/* Pre-shared secret session resumption functions */
|
||||
+int SSL_set_session_secret_cb(SSL *s, tls_session_secret_cb_fn tls_session_secret_cb, void *arg);
|
||||
+
|
||||
/* BEGIN ERROR CODES */
|
||||
/* The following lines are auto generated by the script mkerr.pl. Any changes
|
||||
* made after this point may be overwritten when the script is next run.
|
||||
@@ -1866,6 +1891,7 @@ void ERR_load_SSL_strings(void);
|
||||
#define SSL_F_TLS1_ENC 210
|
||||
#define SSL_F_TLS1_SETUP_KEY_BLOCK 211
|
||||
#define SSL_F_WRITE_PENDING 212
|
||||
+#define SSL_F_SSL_SET_SESSION_TICKET_EXT 213
|
||||
|
||||
/* Reason codes. */
|
||||
#define SSL_R_APP_DATA_IN_HANDSHAKE 100
|
||||
diff -upr openssl-0.9.8x.orig/ssl/ssl_sess.c openssl-0.9.8x/ssl/ssl_sess.c
|
||||
--- openssl-0.9.8x.orig/ssl/ssl_sess.c 2010-02-01 18:48:40.000000000 +0200
|
||||
+++ openssl-0.9.8x/ssl/ssl_sess.c 2012-07-07 10:46:31.501140621 +0300
|
||||
@@ -712,6 +712,61 @@ long SSL_CTX_get_timeout(const SSL_CTX *
|
||||
return(s->session_timeout);
|
||||
}
|
||||
|
||||
+#ifndef OPENSSL_NO_TLSEXT
|
||||
+int SSL_set_session_secret_cb(SSL *s, int (*tls_session_secret_cb)(SSL *s, void *secret, int *secret_len,
|
||||
+ STACK_OF(SSL_CIPHER) *peer_ciphers, SSL_CIPHER **cipher, void *arg), void *arg)
|
||||
+ {
|
||||
+ if (s == NULL) return(0);
|
||||
+ s->tls_session_secret_cb = tls_session_secret_cb;
|
||||
+ s->tls_session_secret_cb_arg = arg;
|
||||
+ return(1);
|
||||
+ }
|
||||
+
|
||||
+int SSL_set_session_ticket_ext_cb(SSL *s, tls_session_ticket_ext_cb_fn cb,
|
||||
+ void *arg)
|
||||
+ {
|
||||
+ if (s == NULL) return(0);
|
||||
+ s->tls_session_ticket_ext_cb = cb;
|
||||
+ s->tls_session_ticket_ext_cb_arg = arg;
|
||||
+ return(1);
|
||||
+ }
|
||||
+
|
||||
+int SSL_set_session_ticket_ext(SSL *s, void *ext_data, int ext_len)
|
||||
+ {
|
||||
+ if (s->version >= TLS1_VERSION)
|
||||
+ {
|
||||
+ if (s->tlsext_session_ticket)
|
||||
+ {
|
||||
+ OPENSSL_free(s->tlsext_session_ticket);
|
||||
+ s->tlsext_session_ticket = NULL;
|
||||
+ }
|
||||
+
|
||||
+ s->tlsext_session_ticket = OPENSSL_malloc(sizeof(TLS_SESSION_TICKET_EXT) + ext_len);
|
||||
+ if (!s->tlsext_session_ticket)
|
||||
+ {
|
||||
+ SSLerr(SSL_F_SSL_SET_SESSION_TICKET_EXT, ERR_R_MALLOC_FAILURE);
|
||||
+ return 0;
|
||||
+ }
|
||||
+
|
||||
+ if (ext_data)
|
||||
+ {
|
||||
+ s->tlsext_session_ticket->length = ext_len;
|
||||
+ s->tlsext_session_ticket->data = s->tlsext_session_ticket + 1;
|
||||
+ memcpy(s->tlsext_session_ticket->data, ext_data, ext_len);
|
||||
+ }
|
||||
+ else
|
||||
+ {
|
||||
+ s->tlsext_session_ticket->length = 0;
|
||||
+ s->tlsext_session_ticket->data = NULL;
|
||||
+ }
|
||||
+
|
||||
+ return 1;
|
||||
+ }
|
||||
+
|
||||
+ return 0;
|
||||
+ }
|
||||
+#endif /* OPENSSL_NO_TLSEXT */
|
||||
+
|
||||
typedef struct timeout_param_st
|
||||
{
|
||||
SSL_CTX *ctx;
|
||||
diff -upr openssl-0.9.8x.orig/ssl/t1_lib.c openssl-0.9.8x/ssl/t1_lib.c
|
||||
--- openssl-0.9.8x.orig/ssl/t1_lib.c 2012-01-04 16:25:10.000000000 +0200
|
||||
+++ openssl-0.9.8x/ssl/t1_lib.c 2012-07-07 10:47:31.153140501 +0300
|
||||
@@ -106,6 +106,12 @@ int tls1_new(SSL *s)
|
||||
|
||||
void tls1_free(SSL *s)
|
||||
{
|
||||
+#ifndef OPENSSL_NO_TLSEXT
|
||||
+ if (s->tlsext_session_ticket)
|
||||
+ {
|
||||
+ OPENSSL_free(s->tlsext_session_ticket);
|
||||
+ }
|
||||
+#endif
|
||||
ssl3_free(s);
|
||||
}
|
||||
|
||||
@@ -206,8 +212,23 @@ unsigned char *ssl_add_clienthello_tlsex
|
||||
int ticklen;
|
||||
if (!s->new_session && s->session && s->session->tlsext_tick)
|
||||
ticklen = s->session->tlsext_ticklen;
|
||||
+ else if (s->session && s->tlsext_session_ticket &&
|
||||
+ s->tlsext_session_ticket->data)
|
||||
+ {
|
||||
+ ticklen = s->tlsext_session_ticket->length;
|
||||
+ s->session->tlsext_tick = OPENSSL_malloc(ticklen);
|
||||
+ if (!s->session->tlsext_tick)
|
||||
+ return NULL;
|
||||
+ memcpy(s->session->tlsext_tick,
|
||||
+ s->tlsext_session_ticket->data,
|
||||
+ ticklen);
|
||||
+ s->session->tlsext_ticklen = ticklen;
|
||||
+ }
|
||||
else
|
||||
ticklen = 0;
|
||||
+ if (ticklen == 0 && s->tlsext_session_ticket &&
|
||||
+ s->tlsext_session_ticket->data == NULL)
|
||||
+ goto skip_ext;
|
||||
/* Check for enough room 2 for extension type, 2 for len
|
||||
* rest for ticket
|
||||
*/
|
||||
@@ -221,6 +242,7 @@ unsigned char *ssl_add_clienthello_tlsex
|
||||
ret += ticklen;
|
||||
}
|
||||
}
|
||||
+ skip_ext:
|
||||
|
||||
if (s->tlsext_status_type == TLSEXT_STATUSTYPE_ocsp &&
|
||||
s->version != DTLS1_VERSION)
|
||||
@@ -486,6 +508,15 @@ int ssl_parse_clienthello_tlsext(SSL *s,
|
||||
return 0;
|
||||
renegotiate_seen = 1;
|
||||
}
|
||||
+ else if (type == TLSEXT_TYPE_session_ticket)
|
||||
+ {
|
||||
+ if (s->tls_session_ticket_ext_cb &&
|
||||
+ !s->tls_session_ticket_ext_cb(s, data, size, s->tls_session_ticket_ext_cb_arg))
|
||||
+ {
|
||||
+ *al = TLS1_AD_INTERNAL_ERROR;
|
||||
+ return 0;
|
||||
+ }
|
||||
+ }
|
||||
else if (type == TLSEXT_TYPE_status_request &&
|
||||
s->version != DTLS1_VERSION && s->ctx->tlsext_status_cb)
|
||||
{
|
||||
@@ -663,6 +694,12 @@ int ssl_parse_serverhello_tlsext(SSL *s,
|
||||
}
|
||||
else if (type == TLSEXT_TYPE_session_ticket)
|
||||
{
|
||||
+ if (s->tls_session_ticket_ext_cb &&
|
||||
+ !s->tls_session_ticket_ext_cb(s, data, size, s->tls_session_ticket_ext_cb_arg))
|
||||
+ {
|
||||
+ *al = TLS1_AD_INTERNAL_ERROR;
|
||||
+ return 0;
|
||||
+ }
|
||||
if ((SSL_get_options(s) & SSL_OP_NO_TICKET)
|
||||
|| (size > 0))
|
||||
{
|
||||
@@ -920,6 +957,15 @@ int tls1_process_ticket(SSL *s, unsigned
|
||||
s->tlsext_ticket_expected = 1;
|
||||
return 0; /* Cache miss */
|
||||
}
|
||||
+ if (s->tls_session_secret_cb)
|
||||
+ {
|
||||
+ /* Indicate cache miss here and instead of
|
||||
+ * generating the session from ticket now,
|
||||
+ * trigger abbreviated handshake based on
|
||||
+ * external mechanism to calculate the master
|
||||
+ * secret later. */
|
||||
+ return 0;
|
||||
+ }
|
||||
return tls_decrypt_ticket(s, p, size, session_id, len,
|
||||
ret);
|
||||
}
|
||||
diff -upr openssl-0.9.8x.orig/ssl/tls1.h openssl-0.9.8x/ssl/tls1.h
|
||||
--- openssl-0.9.8x.orig/ssl/tls1.h 2009-11-08 16:51:54.000000000 +0200
|
||||
+++ openssl-0.9.8x/ssl/tls1.h 2012-07-07 10:46:31.501140621 +0300
|
||||
@@ -401,6 +401,13 @@ SSL_CTX_callback_ctrl(ssl,SSL_CTRL_SET_T
|
||||
#define TLS_MD_MASTER_SECRET_CONST "\x6d\x61\x73\x74\x65\x72\x20\x73\x65\x63\x72\x65\x74" /*master secret*/
|
||||
#endif
|
||||
|
||||
+/* TLS extension struct */
|
||||
+struct tls_session_ticket_ext_st
|
||||
+ {
|
||||
+ unsigned short length;
|
||||
+ void *data;
|
||||
+ };
|
||||
+
|
||||
#ifdef __cplusplus
|
||||
}
|
||||
#endif
|
||||
diff -upr openssl-0.9.8x.orig/util/ssleay.num openssl-0.9.8x/util/ssleay.num
|
||||
--- openssl-0.9.8x.orig/util/ssleay.num 2008-06-05 13:57:21.000000000 +0300
|
||||
+++ openssl-0.9.8x/util/ssleay.num 2012-07-07 10:46:31.505140623 +0300
|
||||
@@ -242,3 +242,5 @@ SSL_set_SSL_CTX
|
||||
SSL_get_servername 291 EXIST::FUNCTION:TLSEXT
|
||||
SSL_get_servername_type 292 EXIST::FUNCTION:TLSEXT
|
||||
SSL_CTX_set_client_cert_engine 293 EXIST::FUNCTION:ENGINE
|
||||
+SSL_set_session_ticket_ext 306 EXIST::FUNCTION:TLSEXT
|
||||
+SSL_set_session_secret_cb 307 EXIST::FUNCTION:TLSEXT
|
@ -1,4 +1,4 @@
|
||||
SUBDIRS=ap common crypto drivers eapol_auth eapol_supp eap_common eap_peer eap_server l2_packet radius rsn_supp tls utils wps
|
||||
SUBDIRS=ap common crypto drivers eapol_auth eapol_supp eap_common eap_peer eap_server l2_packet p2p radius rsn_supp tls utils wps
|
||||
|
||||
all:
|
||||
for d in $(SUBDIRS); do [ -d $$d ] && $(MAKE) -C $$d; done
|
||||
|
@ -1,15 +1,9 @@
|
||||
/*
|
||||
* hostapd / RADIUS Accounting
|
||||
* Copyright (c) 2002-2009, Jouni Malinen <j@w1.fi>
|
||||
* Copyright (c) 2002-2009, 2012, Jouni Malinen <j@w1.fi>
|
||||
*
|
||||
* This program is free software; you can redistribute it and/or modify
|
||||
* it under the terms of the GNU General Public License version 2 as
|
||||
* published by the Free Software Foundation.
|
||||
*
|
||||
* Alternatively, this software may be distributed under the terms of BSD
|
||||
* license.
|
||||
*
|
||||
* See README and COPYING for more details.
|
||||
* This software may be distributed under the terms of the BSD license.
|
||||
* See README for more details.
|
||||
*/
|
||||
|
||||
#include "utils/includes.h"
|
||||
@ -23,6 +17,7 @@
|
||||
#include "ieee802_1x.h"
|
||||
#include "ap_config.h"
|
||||
#include "sta_info.h"
|
||||
#include "ap_drv_ops.h"
|
||||
#include "accounting.h"
|
||||
|
||||
|
||||
@ -31,8 +26,8 @@
|
||||
* input/output octets and updates Acct-{Input,Output}-Gigawords. */
|
||||
#define ACCT_DEFAULT_UPDATE_INTERVAL 300
|
||||
|
||||
static void accounting_sta_get_id(struct hostapd_data *hapd,
|
||||
struct sta_info *sta);
|
||||
static void accounting_sta_interim(struct hostapd_data *hapd,
|
||||
struct sta_info *sta);
|
||||
|
||||
|
||||
static struct radius_msg * accounting_msg(struct hostapd_data *hapd,
|
||||
@ -44,6 +39,7 @@ static struct radius_msg * accounting_msg(struct hostapd_data *hapd,
|
||||
u8 *val;
|
||||
size_t len;
|
||||
int i;
|
||||
struct wpabuf *b;
|
||||
|
||||
msg = radius_msg_new(RADIUS_CODE_ACCOUNTING_REQUEST,
|
||||
radius_client_get_id(hapd->radius));
|
||||
@ -72,7 +68,9 @@ static struct radius_msg * accounting_msg(struct hostapd_data *hapd,
|
||||
goto fail;
|
||||
}
|
||||
|
||||
if (!radius_msg_add_attr_int32(msg, RADIUS_ATTR_ACCT_AUTHENTIC,
|
||||
if (!hostapd_config_get_radius_attr(hapd->conf->radius_acct_req_attr,
|
||||
RADIUS_ATTR_ACCT_AUTHENTIC) &&
|
||||
!radius_msg_add_attr_int32(msg, RADIUS_ATTR_ACCT_AUTHENTIC,
|
||||
hapd->conf->ieee802_1x ?
|
||||
RADIUS_ACCT_AUTHENTIC_RADIUS :
|
||||
RADIUS_ACCT_AUTHENTIC_LOCAL)) {
|
||||
@ -81,7 +79,17 @@ static struct radius_msg * accounting_msg(struct hostapd_data *hapd,
|
||||
}
|
||||
|
||||
if (sta) {
|
||||
/* Use 802.1X identity if available */
|
||||
val = ieee802_1x_get_identity(sta->eapol_sm, &len);
|
||||
|
||||
/* Use RADIUS ACL identity if 802.1X provides no identity */
|
||||
if (!val && sta->identity) {
|
||||
val = (u8 *) sta->identity;
|
||||
len = os_strlen(sta->identity);
|
||||
}
|
||||
|
||||
/* Use STA MAC if neither 802.1X nor RADIUS ACL provided
|
||||
* identity */
|
||||
if (!val) {
|
||||
os_snprintf(buf, sizeof(buf), RADIUS_ADDR_FORMAT,
|
||||
MAC2STR(sta->addr));
|
||||
@ -96,70 +104,11 @@ static struct radius_msg * accounting_msg(struct hostapd_data *hapd,
|
||||
}
|
||||
}
|
||||
|
||||
if (hapd->conf->own_ip_addr.af == AF_INET &&
|
||||
!radius_msg_add_attr(msg, RADIUS_ATTR_NAS_IP_ADDRESS,
|
||||
(u8 *) &hapd->conf->own_ip_addr.u.v4, 4)) {
|
||||
printf("Could not add NAS-IP-Address\n");
|
||||
if (add_common_radius_attr(hapd, hapd->conf->radius_acct_req_attr, sta,
|
||||
msg) < 0)
|
||||
goto fail;
|
||||
}
|
||||
|
||||
#ifdef CONFIG_IPV6
|
||||
if (hapd->conf->own_ip_addr.af == AF_INET6 &&
|
||||
!radius_msg_add_attr(msg, RADIUS_ATTR_NAS_IPV6_ADDRESS,
|
||||
(u8 *) &hapd->conf->own_ip_addr.u.v6, 16)) {
|
||||
printf("Could not add NAS-IPv6-Address\n");
|
||||
goto fail;
|
||||
}
|
||||
#endif /* CONFIG_IPV6 */
|
||||
|
||||
if (hapd->conf->nas_identifier &&
|
||||
!radius_msg_add_attr(msg, RADIUS_ATTR_NAS_IDENTIFIER,
|
||||
(u8 *) hapd->conf->nas_identifier,
|
||||
os_strlen(hapd->conf->nas_identifier))) {
|
||||
printf("Could not add NAS-Identifier\n");
|
||||
goto fail;
|
||||
}
|
||||
|
||||
if (sta &&
|
||||
!radius_msg_add_attr_int32(msg, RADIUS_ATTR_NAS_PORT, sta->aid)) {
|
||||
printf("Could not add NAS-Port\n");
|
||||
goto fail;
|
||||
}
|
||||
|
||||
os_snprintf(buf, sizeof(buf), RADIUS_802_1X_ADDR_FORMAT ":%s",
|
||||
MAC2STR(hapd->own_addr), hapd->conf->ssid.ssid);
|
||||
if (!radius_msg_add_attr(msg, RADIUS_ATTR_CALLED_STATION_ID,
|
||||
(u8 *) buf, os_strlen(buf))) {
|
||||
printf("Could not add Called-Station-Id\n");
|
||||
goto fail;
|
||||
}
|
||||
|
||||
if (sta) {
|
||||
os_snprintf(buf, sizeof(buf), RADIUS_802_1X_ADDR_FORMAT,
|
||||
MAC2STR(sta->addr));
|
||||
if (!radius_msg_add_attr(msg, RADIUS_ATTR_CALLING_STATION_ID,
|
||||
(u8 *) buf, os_strlen(buf))) {
|
||||
printf("Could not add Calling-Station-Id\n");
|
||||
goto fail;
|
||||
}
|
||||
|
||||
if (!radius_msg_add_attr_int32(
|
||||
msg, RADIUS_ATTR_NAS_PORT_TYPE,
|
||||
RADIUS_NAS_PORT_TYPE_IEEE_802_11)) {
|
||||
printf("Could not add NAS-Port-Type\n");
|
||||
goto fail;
|
||||
}
|
||||
|
||||
os_snprintf(buf, sizeof(buf), "CONNECT %d%sMbps %s",
|
||||
radius_sta_rate(hapd, sta) / 2,
|
||||
(radius_sta_rate(hapd, sta) & 1) ? ".5" : "",
|
||||
radius_mode_txt(hapd));
|
||||
if (!radius_msg_add_attr(msg, RADIUS_ATTR_CONNECT_INFO,
|
||||
(u8 *) buf, os_strlen(buf))) {
|
||||
printf("Could not add Connect-Info\n");
|
||||
goto fail;
|
||||
}
|
||||
|
||||
for (i = 0; ; i++) {
|
||||
val = ieee802_1x_get_radius_class(sta->eapol_sm, &len,
|
||||
i);
|
||||
@ -172,6 +121,24 @@ static struct radius_msg * accounting_msg(struct hostapd_data *hapd,
|
||||
goto fail;
|
||||
}
|
||||
}
|
||||
|
||||
b = ieee802_1x_get_radius_cui(sta->eapol_sm);
|
||||
if (b &&
|
||||
!radius_msg_add_attr(msg,
|
||||
RADIUS_ATTR_CHARGEABLE_USER_IDENTITY,
|
||||
wpabuf_head(b), wpabuf_len(b))) {
|
||||
wpa_printf(MSG_ERROR, "Could not add CUI");
|
||||
goto fail;
|
||||
}
|
||||
|
||||
if (!b && sta->radius_cui &&
|
||||
!radius_msg_add_attr(msg,
|
||||
RADIUS_ATTR_CHARGEABLE_USER_IDENTITY,
|
||||
(u8 *) sta->radius_cui,
|
||||
os_strlen(sta->radius_cui))) {
|
||||
wpa_printf(MSG_ERROR, "Could not add CUI from ACL");
|
||||
goto fail;
|
||||
}
|
||||
}
|
||||
|
||||
return msg;
|
||||
@ -186,7 +153,7 @@ static int accounting_sta_update_stats(struct hostapd_data *hapd,
|
||||
struct sta_info *sta,
|
||||
struct hostap_sta_driver_data *data)
|
||||
{
|
||||
if (hapd->drv.read_sta_data(hapd, data, sta->addr))
|
||||
if (hostapd_drv_read_sta_data(hapd, data, sta->addr))
|
||||
return -1;
|
||||
|
||||
if (sta->last_rx_bytes > data->rx_bytes)
|
||||
@ -235,21 +202,22 @@ static void accounting_interim_update(void *eloop_ctx, void *timeout_ctx)
|
||||
void accounting_sta_start(struct hostapd_data *hapd, struct sta_info *sta)
|
||||
{
|
||||
struct radius_msg *msg;
|
||||
struct os_time t;
|
||||
int interval;
|
||||
|
||||
if (sta->acct_session_started)
|
||||
return;
|
||||
|
||||
accounting_sta_get_id(hapd, sta);
|
||||
hostapd_logger(hapd, sta->addr, HOSTAPD_MODULE_RADIUS,
|
||||
HOSTAPD_LEVEL_INFO,
|
||||
"starting accounting session %08X-%08X",
|
||||
sta->acct_session_id_hi, sta->acct_session_id_lo);
|
||||
|
||||
time(&sta->acct_session_start);
|
||||
os_get_time(&t);
|
||||
sta->acct_session_start = t.sec;
|
||||
sta->last_rx_bytes = sta->last_tx_bytes = 0;
|
||||
sta->acct_input_gigawords = sta->acct_output_gigawords = 0;
|
||||
hapd->drv.sta_clear_stats(hapd, sta->addr);
|
||||
hostapd_drv_sta_clear_stats(hapd, sta->addr);
|
||||
|
||||
if (!hapd->conf->radius->acct_server)
|
||||
return;
|
||||
@ -262,8 +230,9 @@ void accounting_sta_start(struct hostapd_data *hapd, struct sta_info *sta)
|
||||
hapd, sta);
|
||||
|
||||
msg = accounting_msg(hapd, sta, RADIUS_ACCT_STATUS_TYPE_START);
|
||||
if (msg)
|
||||
radius_client_send(hapd->radius, msg, RADIUS_ACCT, sta->addr);
|
||||
if (msg &&
|
||||
radius_client_send(hapd->radius, msg, RADIUS_ACCT, sta->addr) < 0)
|
||||
radius_msg_free(msg);
|
||||
|
||||
sta->acct_session_started = 1;
|
||||
}
|
||||
@ -275,6 +244,7 @@ static void accounting_sta_report(struct hostapd_data *hapd,
|
||||
struct radius_msg *msg;
|
||||
int cause = sta->acct_terminate_cause;
|
||||
struct hostap_sta_driver_data data;
|
||||
struct os_time now;
|
||||
u32 gigawords;
|
||||
|
||||
if (!hapd->conf->radius->acct_server)
|
||||
@ -288,8 +258,9 @@ static void accounting_sta_report(struct hostapd_data *hapd,
|
||||
return;
|
||||
}
|
||||
|
||||
os_get_time(&now);
|
||||
if (!radius_msg_add_attr_int32(msg, RADIUS_ATTR_ACCT_SESSION_TIME,
|
||||
time(NULL) - sta->acct_session_start)) {
|
||||
now.sec - sta->acct_session_start)) {
|
||||
printf("Could not add Acct-Session-Time\n");
|
||||
goto fail;
|
||||
}
|
||||
@ -344,7 +315,7 @@ static void accounting_sta_report(struct hostapd_data *hapd,
|
||||
}
|
||||
|
||||
if (!radius_msg_add_attr_int32(msg, RADIUS_ATTR_EVENT_TIMESTAMP,
|
||||
time(NULL))) {
|
||||
now.sec)) {
|
||||
printf("Could not add Event-Timestamp\n");
|
||||
goto fail;
|
||||
}
|
||||
@ -359,9 +330,10 @@ static void accounting_sta_report(struct hostapd_data *hapd,
|
||||
goto fail;
|
||||
}
|
||||
|
||||
radius_client_send(hapd->radius, msg,
|
||||
stop ? RADIUS_ACCT : RADIUS_ACCT_INTERIM,
|
||||
sta->addr);
|
||||
if (radius_client_send(hapd->radius, msg,
|
||||
stop ? RADIUS_ACCT : RADIUS_ACCT_INTERIM,
|
||||
sta->addr) < 0)
|
||||
goto fail;
|
||||
return;
|
||||
|
||||
fail:
|
||||
@ -374,7 +346,8 @@ static void accounting_sta_report(struct hostapd_data *hapd,
|
||||
* @hapd: hostapd BSS data
|
||||
* @sta: The station
|
||||
*/
|
||||
void accounting_sta_interim(struct hostapd_data *hapd, struct sta_info *sta)
|
||||
static void accounting_sta_interim(struct hostapd_data *hapd,
|
||||
struct sta_info *sta)
|
||||
{
|
||||
if (sta->acct_session_started)
|
||||
accounting_sta_report(hapd, sta, 0);
|
||||
@ -401,7 +374,7 @@ void accounting_sta_stop(struct hostapd_data *hapd, struct sta_info *sta)
|
||||
}
|
||||
|
||||
|
||||
static void accounting_sta_get_id(struct hostapd_data *hapd,
|
||||
void accounting_sta_get_id(struct hostapd_data *hapd,
|
||||
struct sta_info *sta)
|
||||
{
|
||||
sta->acct_session_id_lo = hapd->acct_session_id_lo++;
|
||||
@ -464,7 +437,8 @@ static void accounting_report_state(struct hostapd_data *hapd, int on)
|
||||
return;
|
||||
}
|
||||
|
||||
radius_client_send(hapd->radius, msg, RADIUS_ACCT, NULL);
|
||||
if (radius_client_send(hapd->radius, msg, RADIUS_ACCT, NULL) < 0)
|
||||
radius_msg_free(msg);
|
||||
}
|
||||
|
||||
|
||||
@ -475,9 +449,12 @@ static void accounting_report_state(struct hostapd_data *hapd, int on)
|
||||
*/
|
||||
int accounting_init(struct hostapd_data *hapd)
|
||||
{
|
||||
struct os_time now;
|
||||
|
||||
/* Acct-Session-Id should be unique over reboots. If reliable clock is
|
||||
* not available, this could be replaced with reboot counter, etc. */
|
||||
hapd->acct_session_id_hi = time(NULL);
|
||||
os_get_time(&now);
|
||||
hapd->acct_session_id_hi = now.sec;
|
||||
|
||||
if (radius_client_register(hapd->radius, RADIUS_ACCT,
|
||||
accounting_receive, hapd))
|
||||
|
@ -2,21 +2,19 @@
|
||||
* hostapd / RADIUS Accounting
|
||||
* Copyright (c) 2002-2005, Jouni Malinen <j@w1.fi>
|
||||
*
|
||||
* This program is free software; you can redistribute it and/or modify
|
||||
* it under the terms of the GNU General Public License version 2 as
|
||||
* published by the Free Software Foundation.
|
||||
*
|
||||
* Alternatively, this software may be distributed under the terms of BSD
|
||||
* license.
|
||||
*
|
||||
* See README and COPYING for more details.
|
||||
* This software may be distributed under the terms of the BSD license.
|
||||
* See README for more details.
|
||||
*/
|
||||
|
||||
#ifndef ACCOUNTING_H
|
||||
#define ACCOUNTING_H
|
||||
|
||||
void accounting_sta_interim(struct hostapd_data *hapd, struct sta_info *sta);
|
||||
#ifdef CONFIG_NO_ACCOUNTING
|
||||
static inline void accounting_sta_get_id(struct hostapd_data *hapd,
|
||||
struct sta_info *sta)
|
||||
{
|
||||
}
|
||||
|
||||
static inline void accounting_sta_start(struct hostapd_data *hapd,
|
||||
struct sta_info *sta)
|
||||
{
|
||||
@ -36,6 +34,7 @@ static inline void accounting_deinit(struct hostapd_data *hapd)
|
||||
{
|
||||
}
|
||||
#else /* CONFIG_NO_ACCOUNTING */
|
||||
void accounting_sta_get_id(struct hostapd_data *hapd, struct sta_info *sta);
|
||||
void accounting_sta_start(struct hostapd_data *hapd, struct sta_info *sta);
|
||||
void accounting_sta_stop(struct hostapd_data *hapd, struct sta_info *sta);
|
||||
int accounting_init(struct hostapd_data *hapd);
|
||||
|
@ -1,15 +1,9 @@
|
||||
/*
|
||||
* hostapd / Configuration helper functions
|
||||
* Copyright (c) 2003-2009, Jouni Malinen <j@w1.fi>
|
||||
* Copyright (c) 2003-2012, Jouni Malinen <j@w1.fi>
|
||||
*
|
||||
* This program is free software; you can redistribute it and/or modify
|
||||
* it under the terms of the GNU General Public License version 2 as
|
||||
* published by the Free Software Foundation.
|
||||
*
|
||||
* Alternatively, this software may be distributed under the terms of BSD
|
||||
* license.
|
||||
*
|
||||
* See README and COPYING for more details.
|
||||
* This software may be distributed under the terms of the BSD license.
|
||||
* See README for more details.
|
||||
*/
|
||||
|
||||
#include "utils/includes.h"
|
||||
@ -74,6 +68,8 @@ void hostapd_config_defaults_bss(struct hostapd_bss_config *bss)
|
||||
|
||||
bss->max_listen_interval = 65535;
|
||||
|
||||
bss->pwd_group = 19; /* ECC: GF(p=256) */
|
||||
|
||||
#ifdef CONFIG_IEEE80211W
|
||||
bss->assoc_sa_query_max_timeout = 1000;
|
||||
bss->assoc_sa_query_retry_timeout = 201;
|
||||
@ -84,23 +80,44 @@ void hostapd_config_defaults_bss(struct hostapd_bss_config *bss)
|
||||
bss->pac_key_lifetime = 7 * 24 * 60 * 60;
|
||||
bss->pac_key_refresh_time = 1 * 24 * 60 * 60;
|
||||
#endif /* EAP_SERVER_FAST */
|
||||
|
||||
/* Set to -1 as defaults depends on HT in setup */
|
||||
bss->wmm_enabled = -1;
|
||||
|
||||
#ifdef CONFIG_IEEE80211R
|
||||
bss->ft_over_ds = 1;
|
||||
#endif /* CONFIG_IEEE80211R */
|
||||
|
||||
bss->radius_das_time_window = 300;
|
||||
}
|
||||
|
||||
|
||||
struct hostapd_config * hostapd_config_defaults(void)
|
||||
{
|
||||
#define ecw2cw(ecw) ((1 << (ecw)) - 1)
|
||||
|
||||
struct hostapd_config *conf;
|
||||
struct hostapd_bss_config *bss;
|
||||
int i;
|
||||
const int aCWmin = 4, aCWmax = 10;
|
||||
const struct hostapd_wmm_ac_params ac_bk =
|
||||
{ aCWmin, aCWmax, 7, 0, 0 }; /* background traffic */
|
||||
const struct hostapd_wmm_ac_params ac_be =
|
||||
{ aCWmin, aCWmax, 3, 0, 0 }; /* best effort traffic */
|
||||
const struct hostapd_wmm_ac_params ac_vi = /* video traffic */
|
||||
{ aCWmin - 1, aCWmin, 2, 3000 / 32, 1 };
|
||||
{ aCWmin - 1, aCWmin, 2, 3000 / 32, 0 };
|
||||
const struct hostapd_wmm_ac_params ac_vo = /* voice traffic */
|
||||
{ aCWmin - 2, aCWmin - 1, 2, 1500 / 32, 1 };
|
||||
{ aCWmin - 2, aCWmin - 1, 2, 1500 / 32, 0 };
|
||||
const struct hostapd_tx_queue_params txq_bk =
|
||||
{ 7, ecw2cw(aCWmin), ecw2cw(aCWmax), 0 };
|
||||
const struct hostapd_tx_queue_params txq_be =
|
||||
{ 3, ecw2cw(aCWmin), 4 * (ecw2cw(aCWmin) + 1) - 1, 0};
|
||||
const struct hostapd_tx_queue_params txq_vi =
|
||||
{ 1, (ecw2cw(aCWmin) + 1) / 2 - 1, ecw2cw(aCWmin), 30};
|
||||
const struct hostapd_tx_queue_params txq_vo =
|
||||
{ 1, (ecw2cw(aCWmin) + 1) / 4 - 1,
|
||||
(ecw2cw(aCWmin) + 1) / 2 - 1, 15};
|
||||
|
||||
#undef ecw2cw
|
||||
|
||||
conf = os_zalloc(sizeof(*conf));
|
||||
bss = os_zalloc(sizeof(*bss));
|
||||
@ -129,16 +146,21 @@ struct hostapd_config * hostapd_config_defaults(void)
|
||||
conf->fragm_threshold = -1; /* user driver default: 2346 */
|
||||
conf->send_probe_response = 1;
|
||||
|
||||
for (i = 0; i < NUM_TX_QUEUES; i++)
|
||||
conf->tx_queue[i].aifs = -1; /* use hw default */
|
||||
|
||||
conf->wmm_ac_params[0] = ac_be;
|
||||
conf->wmm_ac_params[1] = ac_bk;
|
||||
conf->wmm_ac_params[2] = ac_vi;
|
||||
conf->wmm_ac_params[3] = ac_vo;
|
||||
|
||||
conf->tx_queue[0] = txq_vo;
|
||||
conf->tx_queue[1] = txq_vi;
|
||||
conf->tx_queue[2] = txq_be;
|
||||
conf->tx_queue[3] = txq_bk;
|
||||
|
||||
conf->ht_capab = HT_CAP_INFO_SMPS_DISABLED;
|
||||
|
||||
conf->ap_table_max_size = 255;
|
||||
conf->ap_table_expiration_time = 60;
|
||||
|
||||
return conf;
|
||||
}
|
||||
|
||||
@ -319,6 +341,30 @@ static void hostapd_config_free_radius(struct hostapd_radius_server *servers,
|
||||
}
|
||||
|
||||
|
||||
struct hostapd_radius_attr *
|
||||
hostapd_config_get_radius_attr(struct hostapd_radius_attr *attr, u8 type)
|
||||
{
|
||||
for (; attr; attr = attr->next) {
|
||||
if (attr->type == type)
|
||||
return attr;
|
||||
}
|
||||
return NULL;
|
||||
}
|
||||
|
||||
|
||||
static void hostapd_config_free_radius_attr(struct hostapd_radius_attr *attr)
|
||||
{
|
||||
struct hostapd_radius_attr *prev;
|
||||
|
||||
while (attr) {
|
||||
prev = attr;
|
||||
attr = attr->next;
|
||||
wpabuf_free(prev->val);
|
||||
os_free(prev);
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
static void hostapd_config_free_eap_user(struct hostapd_eap_user *user)
|
||||
{
|
||||
os_free(user->identity);
|
||||
@ -365,6 +411,7 @@ static void hostapd_config_free_bss(struct hostapd_bss_config *conf)
|
||||
user = user->next;
|
||||
hostapd_config_free_eap_user(prev_user);
|
||||
}
|
||||
os_free(conf->eap_user_sqlite);
|
||||
|
||||
os_free(conf->dump_log_name);
|
||||
os_free(conf->eap_req_id_text);
|
||||
@ -375,6 +422,8 @@ static void hostapd_config_free_bss(struct hostapd_bss_config *conf)
|
||||
conf->radius->num_auth_servers);
|
||||
hostapd_config_free_radius(conf->radius->acct_servers,
|
||||
conf->radius->num_acct_servers);
|
||||
hostapd_config_free_radius_attr(conf->radius_auth_req_attr);
|
||||
hostapd_config_free_radius_attr(conf->radius_acct_req_attr);
|
||||
os_free(conf->rsn_preauth_interfaces);
|
||||
os_free(conf->ctrl_interface);
|
||||
os_free(conf->ca_cert);
|
||||
@ -389,6 +438,7 @@ static void hostapd_config_free_bss(struct hostapd_bss_config *conf)
|
||||
os_free(conf->radius_server_clients);
|
||||
os_free(conf->test_socket);
|
||||
os_free(conf->radius);
|
||||
os_free(conf->radius_das_shared_secret);
|
||||
hostapd_config_free_vlan(conf);
|
||||
if (conf->ssid.dyn_vlan_keys) {
|
||||
struct hostapd_ssid *ssid = &conf->ssid;
|
||||
@ -403,6 +453,8 @@ static void hostapd_config_free_bss(struct hostapd_bss_config *conf)
|
||||
ssid->dyn_vlan_keys = NULL;
|
||||
}
|
||||
|
||||
os_free(conf->time_zone);
|
||||
|
||||
#ifdef CONFIG_IEEE80211R
|
||||
{
|
||||
struct ft_remote_r0kh *r0kh, *r0kh_prev;
|
||||
@ -433,7 +485,6 @@ static void hostapd_config_free_bss(struct hostapd_bss_config *conf)
|
||||
os_free(conf->model_name);
|
||||
os_free(conf->model_number);
|
||||
os_free(conf->serial_number);
|
||||
os_free(conf->device_type);
|
||||
os_free(conf->config_methods);
|
||||
os_free(conf->ap_pin);
|
||||
os_free(conf->extra_cred);
|
||||
@ -444,7 +495,30 @@ static void hostapd_config_free_bss(struct hostapd_bss_config *conf)
|
||||
os_free(conf->model_description);
|
||||
os_free(conf->model_url);
|
||||
os_free(conf->upc);
|
||||
wpabuf_free(conf->wps_nfc_dh_pubkey);
|
||||
wpabuf_free(conf->wps_nfc_dh_privkey);
|
||||
wpabuf_free(conf->wps_nfc_dev_pw);
|
||||
#endif /* CONFIG_WPS */
|
||||
|
||||
os_free(conf->roaming_consortium);
|
||||
os_free(conf->venue_name);
|
||||
os_free(conf->nai_realm_data);
|
||||
os_free(conf->network_auth_type);
|
||||
os_free(conf->anqp_3gpp_cell_net);
|
||||
os_free(conf->domain_name);
|
||||
|
||||
#ifdef CONFIG_RADIUS_TEST
|
||||
os_free(conf->dump_msk_file);
|
||||
#endif /* CONFIG_RADIUS_TEST */
|
||||
|
||||
#ifdef CONFIG_HS20
|
||||
os_free(conf->hs20_oper_friendly_name);
|
||||
os_free(conf->hs20_wan_metrics);
|
||||
os_free(conf->hs20_connection_capability);
|
||||
os_free(conf->hs20_operating_class);
|
||||
#endif /* CONFIG_HS20 */
|
||||
|
||||
wpabuf_free(conf->vendor_elements);
|
||||
}
|
||||
|
||||
|
||||
@ -549,57 +623,3 @@ const u8 * hostapd_get_psk(const struct hostapd_bss_config *conf,
|
||||
|
||||
return NULL;
|
||||
}
|
||||
|
||||
|
||||
const struct hostapd_eap_user *
|
||||
hostapd_get_eap_user(const struct hostapd_bss_config *conf, const u8 *identity,
|
||||
size_t identity_len, int phase2)
|
||||
{
|
||||
struct hostapd_eap_user *user = conf->eap_user;
|
||||
|
||||
#ifdef CONFIG_WPS
|
||||
if (conf->wps_state && identity_len == WSC_ID_ENROLLEE_LEN &&
|
||||
os_memcmp(identity, WSC_ID_ENROLLEE, WSC_ID_ENROLLEE_LEN) == 0) {
|
||||
static struct hostapd_eap_user wsc_enrollee;
|
||||
os_memset(&wsc_enrollee, 0, sizeof(wsc_enrollee));
|
||||
wsc_enrollee.methods[0].method = eap_server_get_type(
|
||||
"WSC", &wsc_enrollee.methods[0].vendor);
|
||||
return &wsc_enrollee;
|
||||
}
|
||||
|
||||
if (conf->wps_state && identity_len == WSC_ID_REGISTRAR_LEN &&
|
||||
os_memcmp(identity, WSC_ID_REGISTRAR, WSC_ID_REGISTRAR_LEN) == 0) {
|
||||
static struct hostapd_eap_user wsc_registrar;
|
||||
os_memset(&wsc_registrar, 0, sizeof(wsc_registrar));
|
||||
wsc_registrar.methods[0].method = eap_server_get_type(
|
||||
"WSC", &wsc_registrar.methods[0].vendor);
|
||||
wsc_registrar.password = (u8 *) conf->ap_pin;
|
||||
wsc_registrar.password_len = conf->ap_pin ?
|
||||
os_strlen(conf->ap_pin) : 0;
|
||||
return &wsc_registrar;
|
||||
}
|
||||
#endif /* CONFIG_WPS */
|
||||
|
||||
while (user) {
|
||||
if (!phase2 && user->identity == NULL) {
|
||||
/* Wildcard match */
|
||||
break;
|
||||
}
|
||||
|
||||
if (user->phase2 == !!phase2 && user->wildcard_prefix &&
|
||||
identity_len >= user->identity_len &&
|
||||
os_memcmp(user->identity, identity, user->identity_len) ==
|
||||
0) {
|
||||
/* Wildcard prefix match */
|
||||
break;
|
||||
}
|
||||
|
||||
if (user->phase2 == !!phase2 &&
|
||||
user->identity_len == identity_len &&
|
||||
os_memcmp(user->identity, identity, identity_len) == 0)
|
||||
break;
|
||||
user = user->next;
|
||||
}
|
||||
|
||||
return user;
|
||||
}
|
||||
|
@ -1,15 +1,9 @@
|
||||
/*
|
||||
* hostapd / Configuration definitions and helpers functions
|
||||
* Copyright (c) 2003-2009, Jouni Malinen <j@w1.fi>
|
||||
* Copyright (c) 2003-2012, Jouni Malinen <j@w1.fi>
|
||||
*
|
||||
* This program is free software; you can redistribute it and/or modify
|
||||
* it under the terms of the GNU General Public License version 2 as
|
||||
* published by the Free Software Foundation.
|
||||
*
|
||||
* Alternatively, this software may be distributed under the terms of BSD
|
||||
* license.
|
||||
*
|
||||
* See README and COPYING for more details.
|
||||
* This software may be distributed under the terms of the BSD license.
|
||||
* See README for more details.
|
||||
*/
|
||||
|
||||
#ifndef HOSTAPD_CONFIG_H
|
||||
@ -18,6 +12,8 @@
|
||||
#include "common/defs.h"
|
||||
#include "ip_addr.h"
|
||||
#include "common/wpa_common.h"
|
||||
#include "common/ieee802_11_common.h"
|
||||
#include "wps/wps.h"
|
||||
|
||||
#define MAX_STA_COUNT 2007
|
||||
#define MAX_VLAN_ID 4094
|
||||
@ -53,9 +49,10 @@ typedef enum hostap_security_policy {
|
||||
} secpolicy;
|
||||
|
||||
struct hostapd_ssid {
|
||||
char ssid[HOSTAPD_MAX_SSID_LEN + 1];
|
||||
u8 ssid[HOSTAPD_MAX_SSID_LEN];
|
||||
size_t ssid_len;
|
||||
int ssid_set;
|
||||
unsigned int ssid_set:1;
|
||||
unsigned int utf8_ssid:1;
|
||||
|
||||
char vlan[IFNAMSIZ + 1];
|
||||
secpolicy security_policy;
|
||||
@ -70,6 +67,10 @@ struct hostapd_ssid {
|
||||
#define DYNAMIC_VLAN_OPTIONAL 1
|
||||
#define DYNAMIC_VLAN_REQUIRED 2
|
||||
int dynamic_vlan;
|
||||
#define DYNAMIC_VLAN_NAMING_WITHOUT_DEVICE 0
|
||||
#define DYNAMIC_VLAN_NAMING_WITH_DEVICE 1
|
||||
#define DYNAMIC_VLAN_NAMING_END 2
|
||||
int vlan_naming;
|
||||
#ifdef CONFIG_FULL_DYNAMIC_VLAN
|
||||
char *vlan_tagged_interface;
|
||||
#endif /* CONFIG_FULL_DYNAMIC_VLAN */
|
||||
@ -96,6 +97,11 @@ struct hostapd_vlan {
|
||||
};
|
||||
|
||||
#define PMK_LEN 32
|
||||
struct hostapd_sta_wpa_psk_short {
|
||||
struct hostapd_sta_wpa_psk_short *next;
|
||||
u8 psk[PMK_LEN];
|
||||
};
|
||||
|
||||
struct hostapd_wpa_psk {
|
||||
struct hostapd_wpa_psk *next;
|
||||
int group;
|
||||
@ -103,7 +109,6 @@ struct hostapd_wpa_psk {
|
||||
u8 addr[ETH_ALEN];
|
||||
};
|
||||
|
||||
#define EAP_USER_MAX_METHODS 8
|
||||
struct hostapd_eap_user {
|
||||
struct hostapd_eap_user *next;
|
||||
u8 *identity;
|
||||
@ -111,7 +116,7 @@ struct hostapd_eap_user {
|
||||
struct {
|
||||
int vendor;
|
||||
u32 method;
|
||||
} methods[EAP_USER_MAX_METHODS];
|
||||
} methods[EAP_MAX_METHODS];
|
||||
u8 *password;
|
||||
size_t password_len;
|
||||
int phase2;
|
||||
@ -122,25 +127,52 @@ struct hostapd_eap_user {
|
||||
int ttls_auth; /* EAP_TTLS_AUTH_* bitfield */
|
||||
};
|
||||
|
||||
struct hostapd_radius_attr {
|
||||
u8 type;
|
||||
struct wpabuf *val;
|
||||
struct hostapd_radius_attr *next;
|
||||
};
|
||||
|
||||
#define NUM_TX_QUEUES 8
|
||||
|
||||
#define NUM_TX_QUEUES 4
|
||||
|
||||
struct hostapd_tx_queue_params {
|
||||
int aifs;
|
||||
int cwmin;
|
||||
int cwmax;
|
||||
int burst; /* maximum burst time in 0.1 ms, i.e., 10 = 1 ms */
|
||||
int configured;
|
||||
};
|
||||
|
||||
struct hostapd_wmm_ac_params {
|
||||
int cwmin;
|
||||
int cwmax;
|
||||
int aifs;
|
||||
int txop_limit; /* in units of 32us */
|
||||
int admission_control_mandatory;
|
||||
|
||||
#define MAX_ROAMING_CONSORTIUM_LEN 15
|
||||
|
||||
struct hostapd_roaming_consortium {
|
||||
u8 len;
|
||||
u8 oi[MAX_ROAMING_CONSORTIUM_LEN];
|
||||
};
|
||||
|
||||
struct hostapd_lang_string {
|
||||
u8 lang[3];
|
||||
u8 name_len;
|
||||
u8 name[252];
|
||||
};
|
||||
|
||||
#define MAX_NAI_REALMS 10
|
||||
#define MAX_NAI_REALMLEN 255
|
||||
#define MAX_NAI_EAP_METHODS 5
|
||||
#define MAX_NAI_AUTH_TYPES 4
|
||||
struct hostapd_nai_realm_data {
|
||||
u8 encoding;
|
||||
char realm_buf[MAX_NAI_REALMLEN + 1];
|
||||
char *realm[MAX_NAI_REALMS];
|
||||
u8 eap_method_count;
|
||||
struct hostapd_nai_realm_eap {
|
||||
u8 eap_method;
|
||||
u8 num_auths;
|
||||
u8 auth_id[MAX_NAI_AUTH_TYPES];
|
||||
u8 auth_val[MAX_NAI_AUTH_TYPES];
|
||||
} eap_method[MAX_NAI_EAP_METHODS];
|
||||
};
|
||||
|
||||
/**
|
||||
* struct hostapd_bss_config - Per-BSS configuration
|
||||
@ -148,6 +180,7 @@ struct hostapd_wmm_ac_params {
|
||||
struct hostapd_bss_config {
|
||||
char iface[IFNAMSIZ + 1];
|
||||
char bridge[IFNAMSIZ + 1];
|
||||
char wds_bridge[IFNAMSIZ + 1];
|
||||
|
||||
enum hostapd_logger_level logger_syslog_level, logger_stdout_level;
|
||||
|
||||
@ -165,11 +198,21 @@ struct hostapd_bss_config {
|
||||
int eap_server; /* Use internal EAP server instead of external
|
||||
* RADIUS server */
|
||||
struct hostapd_eap_user *eap_user;
|
||||
char *eap_user_sqlite;
|
||||
char *eap_sim_db;
|
||||
struct hostapd_ip_addr own_ip_addr;
|
||||
char *nas_identifier;
|
||||
struct hostapd_radius_servers *radius;
|
||||
int acct_interim_interval;
|
||||
int radius_request_cui;
|
||||
struct hostapd_radius_attr *radius_auth_req_attr;
|
||||
struct hostapd_radius_attr *radius_acct_req_attr;
|
||||
int radius_das_port;
|
||||
unsigned int radius_das_time_window;
|
||||
int radius_das_require_event_timestamp;
|
||||
struct hostapd_ip_addr radius_das_client_addr;
|
||||
u8 *radius_das_shared_secret;
|
||||
size_t radius_das_shared_secret_len;
|
||||
|
||||
struct hostapd_ssid ssid;
|
||||
|
||||
@ -198,6 +241,7 @@ struct hostapd_bss_config {
|
||||
struct mac_acl_entry *deny_mac;
|
||||
int num_deny_mac;
|
||||
int wds_sta;
|
||||
int isolate;
|
||||
|
||||
int auth_algs; /* bitfield of allowed IEEE 802.11 authentication
|
||||
* algorithms, WPA_AUTH_ALG_{OPEN,SHARED,LEAP} */
|
||||
@ -211,6 +255,11 @@ struct hostapd_bss_config {
|
||||
/* dot11AssociationSAQueryRetryTimeout (in TUs) */
|
||||
int assoc_sa_query_retry_timeout;
|
||||
#endif /* CONFIG_IEEE80211W */
|
||||
enum {
|
||||
PSK_RADIUS_IGNORED = 0,
|
||||
PSK_RADIUS_ACCEPTED = 1,
|
||||
PSK_RADIUS_REQUIRED = 2
|
||||
} wpa_psk_radius;
|
||||
int wpa_pairwise;
|
||||
int wpa_group;
|
||||
int wpa_group_rekey;
|
||||
@ -231,6 +280,7 @@ struct hostapd_bss_config {
|
||||
struct ft_remote_r0kh *r0kh_list;
|
||||
struct ft_remote_r1kh *r1kh_list;
|
||||
int pmk_r1_push;
|
||||
int ft_over_ds;
|
||||
#endif /* CONFIG_IEEE80211R */
|
||||
|
||||
char *ctrl_interface; /* directory for UNIX domain sockets */
|
||||
@ -254,6 +304,8 @@ struct hostapd_bss_config {
|
||||
int pac_key_refresh_time;
|
||||
int eap_sim_aka_result_ind;
|
||||
int tnc;
|
||||
int fragment_size;
|
||||
u16 pwd_group;
|
||||
|
||||
char *radius_server_clients;
|
||||
int radius_server_auth_port;
|
||||
@ -283,6 +335,7 @@ struct hostapd_bss_config {
|
||||
*/
|
||||
u16 max_listen_interval;
|
||||
|
||||
int disable_pmksa_caching;
|
||||
int okc; /* Opportunistic Key Caching */
|
||||
|
||||
int wps_state;
|
||||
@ -295,7 +348,7 @@ struct hostapd_bss_config {
|
||||
char *model_name;
|
||||
char *model_number;
|
||||
char *serial_number;
|
||||
char *device_type;
|
||||
u8 device_type[WPS_DEV_TYPE_LEN];
|
||||
char *config_methods;
|
||||
u8 os_version[4];
|
||||
char *ap_pin;
|
||||
@ -311,7 +364,97 @@ struct hostapd_bss_config {
|
||||
char *model_description;
|
||||
char *model_url;
|
||||
char *upc;
|
||||
struct wpabuf *wps_vendor_ext[MAX_WPS_VENDOR_EXTENSIONS];
|
||||
int wps_nfc_dev_pw_id;
|
||||
struct wpabuf *wps_nfc_dh_pubkey;
|
||||
struct wpabuf *wps_nfc_dh_privkey;
|
||||
struct wpabuf *wps_nfc_dev_pw;
|
||||
#endif /* CONFIG_WPS */
|
||||
int pbc_in_m1;
|
||||
|
||||
#define P2P_ENABLED BIT(0)
|
||||
#define P2P_GROUP_OWNER BIT(1)
|
||||
#define P2P_GROUP_FORMATION BIT(2)
|
||||
#define P2P_MANAGE BIT(3)
|
||||
#define P2P_ALLOW_CROSS_CONNECTION BIT(4)
|
||||
int p2p;
|
||||
|
||||
int disassoc_low_ack;
|
||||
int skip_inactivity_poll;
|
||||
|
||||
#define TDLS_PROHIBIT BIT(0)
|
||||
#define TDLS_PROHIBIT_CHAN_SWITCH BIT(1)
|
||||
int tdls;
|
||||
int disable_11n;
|
||||
int disable_11ac;
|
||||
|
||||
/* IEEE 802.11v */
|
||||
int time_advertisement;
|
||||
char *time_zone;
|
||||
int wnm_sleep_mode;
|
||||
int bss_transition;
|
||||
|
||||
/* IEEE 802.11u - Interworking */
|
||||
int interworking;
|
||||
int access_network_type;
|
||||
int internet;
|
||||
int asra;
|
||||
int esr;
|
||||
int uesa;
|
||||
int venue_info_set;
|
||||
u8 venue_group;
|
||||
u8 venue_type;
|
||||
u8 hessid[ETH_ALEN];
|
||||
|
||||
/* IEEE 802.11u - Roaming Consortium list */
|
||||
unsigned int roaming_consortium_count;
|
||||
struct hostapd_roaming_consortium *roaming_consortium;
|
||||
|
||||
/* IEEE 802.11u - Venue Name duples */
|
||||
unsigned int venue_name_count;
|
||||
struct hostapd_lang_string *venue_name;
|
||||
|
||||
/* IEEE 802.11u - Network Authentication Type */
|
||||
u8 *network_auth_type;
|
||||
size_t network_auth_type_len;
|
||||
|
||||
/* IEEE 802.11u - IP Address Type Availability */
|
||||
u8 ipaddr_type_availability;
|
||||
u8 ipaddr_type_configured;
|
||||
|
||||
/* IEEE 802.11u - 3GPP Cellular Network */
|
||||
u8 *anqp_3gpp_cell_net;
|
||||
size_t anqp_3gpp_cell_net_len;
|
||||
|
||||
/* IEEE 802.11u - Domain Name */
|
||||
u8 *domain_name;
|
||||
size_t domain_name_len;
|
||||
|
||||
unsigned int nai_realm_count;
|
||||
struct hostapd_nai_realm_data *nai_realm_data;
|
||||
|
||||
u16 gas_comeback_delay;
|
||||
int gas_frag_limit;
|
||||
|
||||
#ifdef CONFIG_HS20
|
||||
int hs20;
|
||||
int disable_dgaf;
|
||||
unsigned int hs20_oper_friendly_name_count;
|
||||
struct hostapd_lang_string *hs20_oper_friendly_name;
|
||||
u8 *hs20_wan_metrics;
|
||||
u8 *hs20_connection_capability;
|
||||
size_t hs20_connection_capability_len;
|
||||
u8 *hs20_operating_class;
|
||||
u8 hs20_operating_class_len;
|
||||
#endif /* CONFIG_HS20 */
|
||||
|
||||
u8 wps_rf_bands; /* RF bands for WPS (WPS_RF_*) */
|
||||
|
||||
#ifdef CONFIG_RADIUS_TEST
|
||||
char *dump_msk_file;
|
||||
#endif /* CONFIG_RADIUS_TEST */
|
||||
|
||||
struct wpabuf *vendor_elements;
|
||||
};
|
||||
|
||||
|
||||
@ -332,12 +475,6 @@ struct hostapd_config {
|
||||
LONG_PREAMBLE = 0,
|
||||
SHORT_PREAMBLE = 1
|
||||
} preamble;
|
||||
enum {
|
||||
CTS_PROTECTION_AUTOMATIC = 0,
|
||||
CTS_PROTECTION_FORCE_ENABLED = 1,
|
||||
CTS_PROTECTION_FORCE_DISABLED = 2,
|
||||
CTS_PROTECTION_AUTOMATIC_NO_OLBC = 3,
|
||||
} cts_protection_type;
|
||||
|
||||
int *supported_rates;
|
||||
int *basic_rates;
|
||||
@ -371,6 +508,13 @@ struct hostapd_config {
|
||||
u16 ht_capab;
|
||||
int ieee80211n;
|
||||
int secondary_channel;
|
||||
int require_ht;
|
||||
u32 vht_capab;
|
||||
int ieee80211ac;
|
||||
int require_vht;
|
||||
u8 vht_oper_chwidth;
|
||||
u8 vht_oper_centr_freq_seg0_idx;
|
||||
u8 vht_oper_centr_freq_seg1_idx;
|
||||
};
|
||||
|
||||
|
||||
@ -389,8 +533,7 @@ const u8 * hostapd_get_psk(const struct hostapd_bss_config *conf,
|
||||
int hostapd_setup_wpa_psk(struct hostapd_bss_config *conf);
|
||||
const char * hostapd_get_vlan_id_ifname(struct hostapd_vlan *vlan,
|
||||
int vlan_id);
|
||||
const struct hostapd_eap_user *
|
||||
hostapd_get_eap_user(const struct hostapd_bss_config *conf, const u8 *identity,
|
||||
size_t identity_len, int phase2);
|
||||
struct hostapd_radius_attr *
|
||||
hostapd_config_get_radius_attr(struct hostapd_radius_attr *attr, u8 type);
|
||||
|
||||
#endif /* HOSTAPD_CONFIG_H */
|
||||
|
@ -2,14 +2,8 @@
|
||||
* hostapd - Driver operations
|
||||
* Copyright (c) 2009-2010, Jouni Malinen <j@w1.fi>
|
||||
*
|
||||
* This program is free software; you can redistribute it and/or modify
|
||||
* it under the terms of the GNU General Public License version 2 as
|
||||
* published by the Free Software Foundation.
|
||||
*
|
||||
* Alternatively, this software may be distributed under the terms of BSD
|
||||
* license.
|
||||
*
|
||||
* See README and COPYING for more details.
|
||||
* This software may be distributed under the terms of the BSD license.
|
||||
* See README for more details.
|
||||
*/
|
||||
|
||||
#include "utils/includes.h"
|
||||
@ -17,14 +11,18 @@
|
||||
#include "utils/common.h"
|
||||
#include "drivers/driver.h"
|
||||
#include "common/ieee802_11_defs.h"
|
||||
#include "wps/wps.h"
|
||||
#include "p2p/p2p.h"
|
||||
#include "hostapd.h"
|
||||
#include "ieee802_11.h"
|
||||
#include "sta_info.h"
|
||||
#include "ap_config.h"
|
||||
#include "p2p_hostapd.h"
|
||||
#include "hs20.h"
|
||||
#include "ap_drv_ops.h"
|
||||
|
||||
|
||||
static int hostapd_sta_flags_to_drv(int flags)
|
||||
u32 hostapd_sta_flags_to_drv(u32 flags)
|
||||
{
|
||||
int res = 0;
|
||||
if (flags & WLAN_STA_AUTHORIZED)
|
||||
@ -39,45 +37,190 @@ static int hostapd_sta_flags_to_drv(int flags)
|
||||
}
|
||||
|
||||
|
||||
static int hostapd_set_ap_wps_ie(struct hostapd_data *hapd)
|
||||
int hostapd_build_ap_extra_ies(struct hostapd_data *hapd,
|
||||
struct wpabuf **beacon_ret,
|
||||
struct wpabuf **proberesp_ret,
|
||||
struct wpabuf **assocresp_ret)
|
||||
{
|
||||
struct wpabuf *beacon, *proberesp;
|
||||
struct wpabuf *beacon = NULL, *proberesp = NULL, *assocresp = NULL;
|
||||
u8 buf[200], *pos;
|
||||
|
||||
*beacon_ret = *proberesp_ret = *assocresp_ret = NULL;
|
||||
|
||||
pos = buf;
|
||||
pos = hostapd_eid_time_adv(hapd, pos);
|
||||
if (pos != buf) {
|
||||
if (wpabuf_resize(&beacon, pos - buf) != 0)
|
||||
goto fail;
|
||||
wpabuf_put_data(beacon, buf, pos - buf);
|
||||
}
|
||||
pos = hostapd_eid_time_zone(hapd, pos);
|
||||
if (pos != buf) {
|
||||
if (wpabuf_resize(&proberesp, pos - buf) != 0)
|
||||
goto fail;
|
||||
wpabuf_put_data(proberesp, buf, pos - buf);
|
||||
}
|
||||
|
||||
pos = buf;
|
||||
pos = hostapd_eid_ext_capab(hapd, pos);
|
||||
if (pos != buf) {
|
||||
if (wpabuf_resize(&assocresp, pos - buf) != 0)
|
||||
goto fail;
|
||||
wpabuf_put_data(assocresp, buf, pos - buf);
|
||||
}
|
||||
pos = hostapd_eid_interworking(hapd, pos);
|
||||
pos = hostapd_eid_adv_proto(hapd, pos);
|
||||
pos = hostapd_eid_roaming_consortium(hapd, pos);
|
||||
if (pos != buf) {
|
||||
if (wpabuf_resize(&beacon, pos - buf) != 0)
|
||||
goto fail;
|
||||
wpabuf_put_data(beacon, buf, pos - buf);
|
||||
|
||||
if (wpabuf_resize(&proberesp, pos - buf) != 0)
|
||||
goto fail;
|
||||
wpabuf_put_data(proberesp, buf, pos - buf);
|
||||
}
|
||||
|
||||
if (hapd->wps_beacon_ie) {
|
||||
if (wpabuf_resize(&beacon, wpabuf_len(hapd->wps_beacon_ie)) <
|
||||
0)
|
||||
goto fail;
|
||||
wpabuf_put_buf(beacon, hapd->wps_beacon_ie);
|
||||
}
|
||||
|
||||
if (hapd->wps_probe_resp_ie) {
|
||||
if (wpabuf_resize(&proberesp,
|
||||
wpabuf_len(hapd->wps_probe_resp_ie)) < 0)
|
||||
goto fail;
|
||||
wpabuf_put_buf(proberesp, hapd->wps_probe_resp_ie);
|
||||
}
|
||||
|
||||
#ifdef CONFIG_P2P
|
||||
if (hapd->p2p_beacon_ie) {
|
||||
if (wpabuf_resize(&beacon, wpabuf_len(hapd->p2p_beacon_ie)) <
|
||||
0)
|
||||
goto fail;
|
||||
wpabuf_put_buf(beacon, hapd->p2p_beacon_ie);
|
||||
}
|
||||
|
||||
if (hapd->p2p_probe_resp_ie) {
|
||||
if (wpabuf_resize(&proberesp,
|
||||
wpabuf_len(hapd->p2p_probe_resp_ie)) < 0)
|
||||
goto fail;
|
||||
wpabuf_put_buf(proberesp, hapd->p2p_probe_resp_ie);
|
||||
}
|
||||
#endif /* CONFIG_P2P */
|
||||
|
||||
#ifdef CONFIG_P2P_MANAGER
|
||||
if (hapd->conf->p2p & P2P_MANAGE) {
|
||||
if (wpabuf_resize(&beacon, 100) == 0) {
|
||||
u8 *start, *p;
|
||||
start = wpabuf_put(beacon, 0);
|
||||
p = hostapd_eid_p2p_manage(hapd, start);
|
||||
wpabuf_put(beacon, p - start);
|
||||
}
|
||||
|
||||
if (wpabuf_resize(&proberesp, 100) == 0) {
|
||||
u8 *start, *p;
|
||||
start = wpabuf_put(proberesp, 0);
|
||||
p = hostapd_eid_p2p_manage(hapd, start);
|
||||
wpabuf_put(proberesp, p - start);
|
||||
}
|
||||
}
|
||||
#endif /* CONFIG_P2P_MANAGER */
|
||||
|
||||
#ifdef CONFIG_WPS2
|
||||
if (hapd->conf->wps_state) {
|
||||
struct wpabuf *a = wps_build_assoc_resp_ie();
|
||||
if (a && wpabuf_resize(&assocresp, wpabuf_len(a)) == 0)
|
||||
wpabuf_put_buf(assocresp, a);
|
||||
wpabuf_free(a);
|
||||
}
|
||||
#endif /* CONFIG_WPS2 */
|
||||
|
||||
#ifdef CONFIG_P2P_MANAGER
|
||||
if (hapd->conf->p2p & P2P_MANAGE) {
|
||||
if (wpabuf_resize(&assocresp, 100) == 0) {
|
||||
u8 *start, *p;
|
||||
start = wpabuf_put(assocresp, 0);
|
||||
p = hostapd_eid_p2p_manage(hapd, start);
|
||||
wpabuf_put(assocresp, p - start);
|
||||
}
|
||||
}
|
||||
#endif /* CONFIG_P2P_MANAGER */
|
||||
|
||||
#ifdef CONFIG_WIFI_DISPLAY
|
||||
if (hapd->p2p_group) {
|
||||
struct wpabuf *a;
|
||||
a = p2p_group_assoc_resp_ie(hapd->p2p_group, P2P_SC_SUCCESS);
|
||||
if (a && wpabuf_resize(&assocresp, wpabuf_len(a)) == 0)
|
||||
wpabuf_put_buf(assocresp, a);
|
||||
wpabuf_free(a);
|
||||
}
|
||||
#endif /* CONFIG_WIFI_DISPLAY */
|
||||
|
||||
#ifdef CONFIG_HS20
|
||||
pos = buf;
|
||||
pos = hostapd_eid_hs20_indication(hapd, pos);
|
||||
if (pos != buf) {
|
||||
if (wpabuf_resize(&beacon, pos - buf) != 0)
|
||||
goto fail;
|
||||
wpabuf_put_data(beacon, buf, pos - buf);
|
||||
|
||||
if (wpabuf_resize(&proberesp, pos - buf) != 0)
|
||||
goto fail;
|
||||
wpabuf_put_data(proberesp, buf, pos - buf);
|
||||
}
|
||||
#endif /* CONFIG_HS20 */
|
||||
|
||||
*beacon_ret = beacon;
|
||||
*proberesp_ret = proberesp;
|
||||
*assocresp_ret = assocresp;
|
||||
|
||||
return 0;
|
||||
|
||||
fail:
|
||||
wpabuf_free(beacon);
|
||||
wpabuf_free(proberesp);
|
||||
wpabuf_free(assocresp);
|
||||
return -1;
|
||||
}
|
||||
|
||||
|
||||
void hostapd_free_ap_extra_ies(struct hostapd_data *hapd,
|
||||
struct wpabuf *beacon,
|
||||
struct wpabuf *proberesp,
|
||||
struct wpabuf *assocresp)
|
||||
{
|
||||
wpabuf_free(beacon);
|
||||
wpabuf_free(proberesp);
|
||||
wpabuf_free(assocresp);
|
||||
}
|
||||
|
||||
|
||||
int hostapd_set_ap_wps_ie(struct hostapd_data *hapd)
|
||||
{
|
||||
struct wpabuf *beacon, *proberesp, *assocresp;
|
||||
int ret;
|
||||
|
||||
if (hapd->driver == NULL || hapd->driver->set_ap_wps_ie == NULL)
|
||||
return 0;
|
||||
|
||||
beacon = hapd->wps_beacon_ie;
|
||||
proberesp = hapd->wps_probe_resp_ie;
|
||||
if (hostapd_build_ap_extra_ies(hapd, &beacon, &proberesp, &assocresp) <
|
||||
0)
|
||||
return -1;
|
||||
|
||||
ret = hapd->driver->set_ap_wps_ie(hapd->drv_priv, beacon, proberesp);
|
||||
ret = hapd->driver->set_ap_wps_ie(hapd->drv_priv, beacon, proberesp,
|
||||
assocresp);
|
||||
|
||||
hostapd_free_ap_extra_ies(hapd, beacon, proberesp, assocresp);
|
||||
|
||||
return ret;
|
||||
}
|
||||
|
||||
|
||||
static int hostapd_send_mgmt_frame(struct hostapd_data *hapd, const void *msg,
|
||||
size_t len)
|
||||
{
|
||||
if (hapd->driver == NULL || hapd->driver->send_mlme == NULL)
|
||||
return 0;
|
||||
return hapd->driver->send_mlme(hapd->drv_priv, msg, len);
|
||||
}
|
||||
|
||||
|
||||
static int hostapd_send_eapol(struct hostapd_data *hapd, const u8 *addr,
|
||||
const u8 *data, size_t data_len, int encrypt)
|
||||
{
|
||||
if (hapd->driver == NULL || hapd->driver->hapd_send_eapol == NULL)
|
||||
return 0;
|
||||
return hapd->driver->hapd_send_eapol(hapd->drv_priv, addr, data,
|
||||
data_len, encrypt,
|
||||
hapd->own_addr);
|
||||
}
|
||||
|
||||
|
||||
static int hostapd_set_authorized(struct hostapd_data *hapd,
|
||||
struct sta_info *sta, int authorized)
|
||||
int hostapd_set_authorized(struct hostapd_data *hapd,
|
||||
struct sta_info *sta, int authorized)
|
||||
{
|
||||
if (authorized) {
|
||||
return hostapd_sta_set_flags(hapd, sta->addr,
|
||||
@ -92,39 +235,7 @@ static int hostapd_set_authorized(struct hostapd_data *hapd,
|
||||
}
|
||||
|
||||
|
||||
static int hostapd_set_key(const char *ifname, struct hostapd_data *hapd,
|
||||
enum wpa_alg alg, const u8 *addr, int key_idx,
|
||||
int set_tx, const u8 *seq, size_t seq_len,
|
||||
const u8 *key, size_t key_len)
|
||||
{
|
||||
if (hapd->driver == NULL || hapd->driver->set_key == NULL)
|
||||
return 0;
|
||||
return hapd->driver->set_key(ifname, hapd->drv_priv, alg, addr,
|
||||
key_idx, set_tx, seq, seq_len, key,
|
||||
key_len);
|
||||
}
|
||||
|
||||
|
||||
static int hostapd_read_sta_data(struct hostapd_data *hapd,
|
||||
struct hostap_sta_driver_data *data,
|
||||
const u8 *addr)
|
||||
{
|
||||
if (hapd->driver == NULL || hapd->driver->read_sta_data == NULL)
|
||||
return -1;
|
||||
return hapd->driver->read_sta_data(hapd->drv_priv, data, addr);
|
||||
}
|
||||
|
||||
|
||||
static int hostapd_sta_clear_stats(struct hostapd_data *hapd, const u8 *addr)
|
||||
{
|
||||
if (hapd->driver == NULL || hapd->driver->sta_clear_stats == NULL)
|
||||
return 0;
|
||||
return hapd->driver->sta_clear_stats(hapd->drv_priv, addr);
|
||||
}
|
||||
|
||||
|
||||
static int hostapd_set_sta_flags(struct hostapd_data *hapd,
|
||||
struct sta_info *sta)
|
||||
int hostapd_set_sta_flags(struct hostapd_data *hapd, struct sta_info *sta)
|
||||
{
|
||||
int set_flags, total_flags, flags_and, flags_or;
|
||||
total_flags = hostapd_sta_flags_to_drv(sta->flags);
|
||||
@ -140,8 +251,8 @@ static int hostapd_set_sta_flags(struct hostapd_data *hapd,
|
||||
}
|
||||
|
||||
|
||||
static int hostapd_set_drv_ieee8021x(struct hostapd_data *hapd,
|
||||
const char *ifname, int enabled)
|
||||
int hostapd_set_drv_ieee8021x(struct hostapd_data *hapd, const char *ifname,
|
||||
int enabled)
|
||||
{
|
||||
struct wpa_bss_params params;
|
||||
os_memset(¶ms, 0, sizeof(params));
|
||||
@ -154,166 +265,80 @@ static int hostapd_set_drv_ieee8021x(struct hostapd_data *hapd,
|
||||
params.wpa_pairwise = hapd->conf->wpa_pairwise;
|
||||
params.wpa_key_mgmt = hapd->conf->wpa_key_mgmt;
|
||||
params.rsn_preauth = hapd->conf->rsn_preauth;
|
||||
#ifdef CONFIG_IEEE80211W
|
||||
params.ieee80211w = hapd->conf->ieee80211w;
|
||||
#endif /* CONFIG_IEEE80211W */
|
||||
}
|
||||
return hostapd_set_ieee8021x(hapd, ¶ms);
|
||||
}
|
||||
|
||||
|
||||
static int hostapd_set_radius_acl_auth(struct hostapd_data *hapd,
|
||||
const u8 *mac, int accepted,
|
||||
u32 session_timeout)
|
||||
{
|
||||
if (hapd->driver == NULL || hapd->driver->set_radius_acl_auth == NULL)
|
||||
return 0;
|
||||
return hapd->driver->set_radius_acl_auth(hapd->drv_priv, mac, accepted,
|
||||
session_timeout);
|
||||
}
|
||||
|
||||
|
||||
static int hostapd_set_radius_acl_expire(struct hostapd_data *hapd,
|
||||
const u8 *mac)
|
||||
{
|
||||
if (hapd->driver == NULL ||
|
||||
hapd->driver->set_radius_acl_expire == NULL)
|
||||
return 0;
|
||||
return hapd->driver->set_radius_acl_expire(hapd->drv_priv, mac);
|
||||
}
|
||||
|
||||
|
||||
static int hostapd_set_bss_params(struct hostapd_data *hapd,
|
||||
int use_protection)
|
||||
{
|
||||
int ret = 0;
|
||||
int preamble;
|
||||
#ifdef CONFIG_IEEE80211N
|
||||
u8 buf[60], *ht_capab, *ht_oper, *pos;
|
||||
|
||||
pos = buf;
|
||||
ht_capab = pos;
|
||||
pos = hostapd_eid_ht_capabilities(hapd, pos);
|
||||
ht_oper = pos;
|
||||
pos = hostapd_eid_ht_operation(hapd, pos);
|
||||
if (pos > ht_oper && ht_oper > ht_capab &&
|
||||
hostapd_set_ht_params(hapd, ht_capab + 2, ht_capab[1],
|
||||
ht_oper + 2, ht_oper[1])) {
|
||||
wpa_printf(MSG_ERROR, "Could not set HT capabilities "
|
||||
"for kernel driver");
|
||||
ret = -1;
|
||||
}
|
||||
|
||||
#endif /* CONFIG_IEEE80211N */
|
||||
|
||||
if (hostapd_set_cts_protect(hapd, use_protection)) {
|
||||
wpa_printf(MSG_ERROR, "Failed to set CTS protect in kernel "
|
||||
"driver");
|
||||
ret = -1;
|
||||
}
|
||||
|
||||
if (hapd->iface->current_mode &&
|
||||
hapd->iface->current_mode->mode == HOSTAPD_MODE_IEEE80211G &&
|
||||
hostapd_set_short_slot_time(hapd,
|
||||
hapd->iface->num_sta_no_short_slot_time
|
||||
> 0 ? 0 : 1)) {
|
||||
wpa_printf(MSG_ERROR, "Failed to set Short Slot Time option "
|
||||
"in kernel driver");
|
||||
ret = -1;
|
||||
}
|
||||
|
||||
if (hapd->iface->num_sta_no_short_preamble == 0 &&
|
||||
hapd->iconf->preamble == SHORT_PREAMBLE)
|
||||
preamble = SHORT_PREAMBLE;
|
||||
else
|
||||
preamble = LONG_PREAMBLE;
|
||||
if (hostapd_set_preamble(hapd, preamble)) {
|
||||
wpa_printf(MSG_ERROR, "Could not set preamble for kernel "
|
||||
"driver");
|
||||
ret = -1;
|
||||
}
|
||||
|
||||
return ret;
|
||||
}
|
||||
|
||||
|
||||
static int hostapd_set_beacon(struct hostapd_data *hapd,
|
||||
const u8 *head, size_t head_len,
|
||||
const u8 *tail, size_t tail_len, int dtim_period,
|
||||
int beacon_int)
|
||||
{
|
||||
if (hapd->driver == NULL || hapd->driver->set_beacon == NULL)
|
||||
return 0;
|
||||
return hapd->driver->set_beacon(hapd->drv_priv,
|
||||
head, head_len, tail, tail_len,
|
||||
dtim_period, beacon_int);
|
||||
}
|
||||
|
||||
|
||||
static int hostapd_vlan_if_add(struct hostapd_data *hapd, const char *ifname)
|
||||
int hostapd_vlan_if_add(struct hostapd_data *hapd, const char *ifname)
|
||||
{
|
||||
char force_ifname[IFNAMSIZ];
|
||||
u8 if_addr[ETH_ALEN];
|
||||
return hostapd_if_add(hapd, WPA_IF_AP_VLAN, ifname, NULL, NULL, NULL,
|
||||
force_ifname, if_addr);
|
||||
return hostapd_if_add(hapd, WPA_IF_AP_VLAN, ifname, hapd->own_addr,
|
||||
NULL, NULL, force_ifname, if_addr, NULL);
|
||||
}
|
||||
|
||||
static int hostapd_vlan_if_remove(struct hostapd_data *hapd,
|
||||
const char *ifname)
|
||||
|
||||
int hostapd_vlan_if_remove(struct hostapd_data *hapd, const char *ifname)
|
||||
{
|
||||
return hostapd_if_remove(hapd, WPA_IF_AP_VLAN, ifname);
|
||||
}
|
||||
|
||||
|
||||
static int hostapd_set_wds_sta(struct hostapd_data *hapd, const u8 *addr,
|
||||
int aid, int val)
|
||||
int hostapd_set_wds_sta(struct hostapd_data *hapd, const u8 *addr, int aid,
|
||||
int val)
|
||||
{
|
||||
const char *bridge = NULL;
|
||||
|
||||
if (hapd->driver == NULL || hapd->driver->set_wds_sta == NULL)
|
||||
return 0;
|
||||
return hapd->driver->set_wds_sta(hapd->drv_priv, addr, aid, val);
|
||||
if (hapd->conf->wds_bridge[0])
|
||||
bridge = hapd->conf->wds_bridge;
|
||||
else if (hapd->conf->bridge[0])
|
||||
bridge = hapd->conf->bridge;
|
||||
return hapd->driver->set_wds_sta(hapd->drv_priv, addr, aid, val,
|
||||
bridge);
|
||||
}
|
||||
|
||||
|
||||
static int hostapd_set_sta_vlan(const char *ifname, struct hostapd_data *hapd,
|
||||
const u8 *addr, int vlan_id)
|
||||
int hostapd_add_sta_node(struct hostapd_data *hapd, const u8 *addr,
|
||||
u16 auth_alg)
|
||||
{
|
||||
if (hapd->driver == NULL || hapd->driver->set_sta_vlan == NULL)
|
||||
if (hapd->driver == NULL || hapd->driver->add_sta_node == NULL)
|
||||
return 0;
|
||||
return hapd->driver->set_sta_vlan(hapd->drv_priv, addr, ifname,
|
||||
vlan_id);
|
||||
return hapd->driver->add_sta_node(hapd->drv_priv, addr, auth_alg);
|
||||
}
|
||||
|
||||
|
||||
static int hostapd_get_inact_sec(struct hostapd_data *hapd, const u8 *addr)
|
||||
int hostapd_sta_auth(struct hostapd_data *hapd, const u8 *addr,
|
||||
u16 seq, u16 status, const u8 *ie, size_t len)
|
||||
{
|
||||
if (hapd->driver == NULL || hapd->driver->get_inact_sec == NULL)
|
||||
if (hapd->driver == NULL || hapd->driver->sta_auth == NULL)
|
||||
return 0;
|
||||
return hapd->driver->get_inact_sec(hapd->drv_priv, addr);
|
||||
return hapd->driver->sta_auth(hapd->drv_priv, hapd->own_addr, addr,
|
||||
seq, status, ie, len);
|
||||
}
|
||||
|
||||
|
||||
static int hostapd_sta_deauth(struct hostapd_data *hapd, const u8 *addr,
|
||||
int reason)
|
||||
int hostapd_sta_assoc(struct hostapd_data *hapd, const u8 *addr,
|
||||
int reassoc, u16 status, const u8 *ie, size_t len)
|
||||
{
|
||||
if (hapd->driver == NULL || hapd->driver->sta_deauth == NULL)
|
||||
if (hapd->driver == NULL || hapd->driver->sta_assoc == NULL)
|
||||
return 0;
|
||||
return hapd->driver->sta_deauth(hapd->drv_priv, hapd->own_addr, addr,
|
||||
reason);
|
||||
return hapd->driver->sta_assoc(hapd->drv_priv, hapd->own_addr, addr,
|
||||
reassoc, status, ie, len);
|
||||
}
|
||||
|
||||
|
||||
static int hostapd_sta_disassoc(struct hostapd_data *hapd, const u8 *addr,
|
||||
int reason)
|
||||
{
|
||||
if (hapd->driver == NULL || hapd->driver->sta_disassoc == NULL)
|
||||
return 0;
|
||||
return hapd->driver->sta_disassoc(hapd->drv_priv, hapd->own_addr, addr,
|
||||
reason);
|
||||
}
|
||||
|
||||
|
||||
static int hostapd_sta_add(struct hostapd_data *hapd,
|
||||
const u8 *addr, u16 aid, u16 capability,
|
||||
const u8 *supp_rates, size_t supp_rates_len,
|
||||
u16 listen_interval,
|
||||
const struct ieee80211_ht_capabilities *ht_capab)
|
||||
int hostapd_sta_add(struct hostapd_data *hapd,
|
||||
const u8 *addr, u16 aid, u16 capability,
|
||||
const u8 *supp_rates, size_t supp_rates_len,
|
||||
u16 listen_interval,
|
||||
const struct ieee80211_ht_capabilities *ht_capab,
|
||||
u32 flags, u8 qosinfo)
|
||||
{
|
||||
struct hostapd_sta_add_params params;
|
||||
|
||||
@ -330,52 +355,19 @@ static int hostapd_sta_add(struct hostapd_data *hapd,
|
||||
params.supp_rates_len = supp_rates_len;
|
||||
params.listen_interval = listen_interval;
|
||||
params.ht_capabilities = ht_capab;
|
||||
params.flags = hostapd_sta_flags_to_drv(flags);
|
||||
params.qosinfo = qosinfo;
|
||||
return hapd->driver->sta_add(hapd->drv_priv, ¶ms);
|
||||
}
|
||||
|
||||
|
||||
static int hostapd_sta_remove(struct hostapd_data *hapd, const u8 *addr)
|
||||
int hostapd_add_tspec(struct hostapd_data *hapd, const u8 *addr,
|
||||
u8 *tspec_ie, size_t tspec_ielen)
|
||||
{
|
||||
if (hapd->driver == NULL || hapd->driver->sta_remove == NULL)
|
||||
if (hapd->driver == NULL || hapd->driver->add_tspec == NULL)
|
||||
return 0;
|
||||
return hapd->driver->sta_remove(hapd->drv_priv, addr);
|
||||
}
|
||||
|
||||
|
||||
static int hostapd_set_countermeasures(struct hostapd_data *hapd, int enabled)
|
||||
{
|
||||
if (hapd->driver == NULL ||
|
||||
hapd->driver->hapd_set_countermeasures == NULL)
|
||||
return 0;
|
||||
return hapd->driver->hapd_set_countermeasures(hapd->drv_priv, enabled);
|
||||
}
|
||||
|
||||
|
||||
void hostapd_set_driver_ops(struct hostapd_driver_ops *ops)
|
||||
{
|
||||
ops->set_ap_wps_ie = hostapd_set_ap_wps_ie;
|
||||
ops->send_mgmt_frame = hostapd_send_mgmt_frame;
|
||||
ops->send_eapol = hostapd_send_eapol;
|
||||
ops->set_authorized = hostapd_set_authorized;
|
||||
ops->set_key = hostapd_set_key;
|
||||
ops->read_sta_data = hostapd_read_sta_data;
|
||||
ops->sta_clear_stats = hostapd_sta_clear_stats;
|
||||
ops->set_sta_flags = hostapd_set_sta_flags;
|
||||
ops->set_drv_ieee8021x = hostapd_set_drv_ieee8021x;
|
||||
ops->set_radius_acl_auth = hostapd_set_radius_acl_auth;
|
||||
ops->set_radius_acl_expire = hostapd_set_radius_acl_expire;
|
||||
ops->set_bss_params = hostapd_set_bss_params;
|
||||
ops->set_beacon = hostapd_set_beacon;
|
||||
ops->vlan_if_add = hostapd_vlan_if_add;
|
||||
ops->vlan_if_remove = hostapd_vlan_if_remove;
|
||||
ops->set_wds_sta = hostapd_set_wds_sta;
|
||||
ops->set_sta_vlan = hostapd_set_sta_vlan;
|
||||
ops->get_inact_sec = hostapd_get_inact_sec;
|
||||
ops->sta_deauth = hostapd_sta_deauth;
|
||||
ops->sta_disassoc = hostapd_sta_disassoc;
|
||||
ops->sta_add = hostapd_sta_add;
|
||||
ops->sta_remove = hostapd_sta_remove;
|
||||
ops->set_countermeasures = hostapd_set_countermeasures;
|
||||
return hapd->driver->add_tspec(hapd->drv_priv, addr, tspec_ie,
|
||||
tspec_ielen);
|
||||
}
|
||||
|
||||
|
||||
@ -414,12 +406,14 @@ int hostapd_set_ssid(struct hostapd_data *hapd, const u8 *buf, size_t len)
|
||||
|
||||
int hostapd_if_add(struct hostapd_data *hapd, enum wpa_driver_if_type type,
|
||||
const char *ifname, const u8 *addr, void *bss_ctx,
|
||||
void **drv_priv, char *force_ifname, u8 *if_addr)
|
||||
void **drv_priv, char *force_ifname, u8 *if_addr,
|
||||
const char *bridge)
|
||||
{
|
||||
if (hapd->driver == NULL || hapd->driver->if_add == NULL)
|
||||
return -1;
|
||||
return hapd->driver->if_add(hapd->drv_priv, type, ifname, addr,
|
||||
bss_ctx, drv_priv, force_ifname, if_addr);
|
||||
bss_ctx, drv_priv, force_ifname, if_addr,
|
||||
bridge);
|
||||
}
|
||||
|
||||
|
||||
@ -502,16 +496,6 @@ int hostapd_sta_set_flags(struct hostapd_data *hapd, u8 *addr,
|
||||
}
|
||||
|
||||
|
||||
int hostapd_set_rate_sets(struct hostapd_data *hapd, int *supp_rates,
|
||||
int *basic_rates, int mode)
|
||||
{
|
||||
if (hapd->driver == NULL || hapd->driver->set_rate_sets == NULL)
|
||||
return 0;
|
||||
return hapd->driver->set_rate_sets(hapd->drv_priv, supp_rates,
|
||||
basic_rates, mode);
|
||||
}
|
||||
|
||||
|
||||
int hostapd_set_country(struct hostapd_data *hapd, const char *country)
|
||||
{
|
||||
if (hapd->driver == NULL ||
|
||||
@ -521,30 +505,6 @@ int hostapd_set_country(struct hostapd_data *hapd, const char *country)
|
||||
}
|
||||
|
||||
|
||||
int hostapd_set_cts_protect(struct hostapd_data *hapd, int value)
|
||||
{
|
||||
if (hapd->driver == NULL || hapd->driver->set_cts_protect == NULL)
|
||||
return 0;
|
||||
return hapd->driver->set_cts_protect(hapd->drv_priv, value);
|
||||
}
|
||||
|
||||
|
||||
int hostapd_set_preamble(struct hostapd_data *hapd, int value)
|
||||
{
|
||||
if (hapd->driver == NULL || hapd->driver->set_preamble == NULL)
|
||||
return 0;
|
||||
return hapd->driver->set_preamble(hapd->drv_priv, value);
|
||||
}
|
||||
|
||||
|
||||
int hostapd_set_short_slot_time(struct hostapd_data *hapd, int value)
|
||||
{
|
||||
if (hapd->driver == NULL || hapd->driver->set_short_slot_time == NULL)
|
||||
return 0;
|
||||
return hapd->driver->set_short_slot_time(hapd->drv_priv, value);
|
||||
}
|
||||
|
||||
|
||||
int hostapd_set_tx_queue_params(struct hostapd_data *hapd, int queue, int aifs,
|
||||
int cw_min, int cw_max, int burst_time)
|
||||
{
|
||||
@ -555,15 +515,6 @@ int hostapd_set_tx_queue_params(struct hostapd_data *hapd, int queue, int aifs,
|
||||
}
|
||||
|
||||
|
||||
int hostapd_valid_bss_mask(struct hostapd_data *hapd, const u8 *addr,
|
||||
const u8 *mask)
|
||||
{
|
||||
if (hapd->driver == NULL || hapd->driver->valid_bss_mask == NULL)
|
||||
return 1;
|
||||
return hapd->driver->valid_bss_mask(hapd->drv_priv, addr, mask);
|
||||
}
|
||||
|
||||
|
||||
struct hostapd_hw_modes *
|
||||
hostapd_get_hw_feature_data(struct hostapd_data *hapd, u16 *num_modes,
|
||||
u16 *flags)
|
||||
@ -584,19 +535,6 @@ int hostapd_driver_commit(struct hostapd_data *hapd)
|
||||
}
|
||||
|
||||
|
||||
int hostapd_set_ht_params(struct hostapd_data *hapd,
|
||||
const u8 *ht_capab, size_t ht_capab_len,
|
||||
const u8 *ht_oper, size_t ht_oper_len)
|
||||
{
|
||||
if (hapd->driver == NULL || hapd->driver->set_ht_params == NULL ||
|
||||
ht_capab == NULL || ht_oper == NULL)
|
||||
return 0;
|
||||
return hapd->driver->set_ht_params(hapd->drv_priv,
|
||||
ht_capab, ht_capab_len,
|
||||
ht_oper, ht_oper_len);
|
||||
}
|
||||
|
||||
|
||||
int hostapd_drv_none(struct hostapd_data *hapd)
|
||||
{
|
||||
return hapd->driver && os_strcmp(hapd->driver->name, "none") == 0;
|
||||
@ -619,3 +557,78 @@ struct wpa_scan_results * hostapd_driver_get_scan_results(
|
||||
return hapd->driver->get_scan_results2(hapd->drv_priv);
|
||||
return NULL;
|
||||
}
|
||||
|
||||
|
||||
int hostapd_driver_set_noa(struct hostapd_data *hapd, u8 count, int start,
|
||||
int duration)
|
||||
{
|
||||
if (hapd->driver && hapd->driver->set_noa)
|
||||
return hapd->driver->set_noa(hapd->drv_priv, count, start,
|
||||
duration);
|
||||
return -1;
|
||||
}
|
||||
|
||||
|
||||
int hostapd_drv_set_key(const char *ifname, struct hostapd_data *hapd,
|
||||
enum wpa_alg alg, const u8 *addr,
|
||||
int key_idx, int set_tx,
|
||||
const u8 *seq, size_t seq_len,
|
||||
const u8 *key, size_t key_len)
|
||||
{
|
||||
if (hapd->driver == NULL || hapd->driver->set_key == NULL)
|
||||
return 0;
|
||||
return hapd->driver->set_key(ifname, hapd->drv_priv, alg, addr,
|
||||
key_idx, set_tx, seq, seq_len, key,
|
||||
key_len);
|
||||
}
|
||||
|
||||
|
||||
int hostapd_drv_send_mlme(struct hostapd_data *hapd,
|
||||
const void *msg, size_t len, int noack)
|
||||
{
|
||||
if (hapd->driver == NULL || hapd->driver->send_mlme == NULL)
|
||||
return 0;
|
||||
return hapd->driver->send_mlme(hapd->drv_priv, msg, len, noack);
|
||||
}
|
||||
|
||||
|
||||
int hostapd_drv_sta_deauth(struct hostapd_data *hapd,
|
||||
const u8 *addr, int reason)
|
||||
{
|
||||
if (hapd->driver == NULL || hapd->driver->sta_deauth == NULL)
|
||||
return 0;
|
||||
return hapd->driver->sta_deauth(hapd->drv_priv, hapd->own_addr, addr,
|
||||
reason);
|
||||
}
|
||||
|
||||
|
||||
int hostapd_drv_sta_disassoc(struct hostapd_data *hapd,
|
||||
const u8 *addr, int reason)
|
||||
{
|
||||
if (hapd->driver == NULL || hapd->driver->sta_disassoc == NULL)
|
||||
return 0;
|
||||
return hapd->driver->sta_disassoc(hapd->drv_priv, hapd->own_addr, addr,
|
||||
reason);
|
||||
}
|
||||
|
||||
|
||||
int hostapd_drv_wnm_oper(struct hostapd_data *hapd, enum wnm_oper oper,
|
||||
const u8 *peer, u8 *buf, u16 *buf_len)
|
||||
{
|
||||
if (hapd->driver == NULL || hapd->driver->wnm_oper == NULL)
|
||||
return 0;
|
||||
return hapd->driver->wnm_oper(hapd->drv_priv, oper, peer, buf,
|
||||
buf_len);
|
||||
}
|
||||
|
||||
|
||||
int hostapd_drv_send_action(struct hostapd_data *hapd, unsigned int freq,
|
||||
unsigned int wait, const u8 *dst, const u8 *data,
|
||||
size_t len)
|
||||
{
|
||||
if (hapd->driver == NULL || hapd->driver->send_action == NULL)
|
||||
return 0;
|
||||
return hapd->driver->send_action(hapd->drv_priv, freq, wait, dst,
|
||||
hapd->own_addr, hapd->own_addr, data,
|
||||
len, 0);
|
||||
}
|
||||
|
@ -2,14 +2,8 @@
|
||||
* hostapd - Driver operations
|
||||
* Copyright (c) 2009, Jouni Malinen <j@w1.fi>
|
||||
*
|
||||
* This program is free software; you can redistribute it and/or modify
|
||||
* it under the terms of the GNU General Public License version 2 as
|
||||
* published by the Free Software Foundation.
|
||||
*
|
||||
* Alternatively, this software may be distributed under the terms of BSD
|
||||
* license.
|
||||
*
|
||||
* See README and COPYING for more details.
|
||||
* This software may be distributed under the terms of the BSD license.
|
||||
* See README for more details.
|
||||
*/
|
||||
|
||||
#ifndef AP_DRV_OPS
|
||||
@ -18,8 +12,32 @@
|
||||
enum wpa_driver_if_type;
|
||||
struct wpa_bss_params;
|
||||
struct wpa_driver_scan_params;
|
||||
struct ieee80211_ht_capabilities;
|
||||
|
||||
void hostapd_set_driver_ops(struct hostapd_driver_ops *ops);
|
||||
u32 hostapd_sta_flags_to_drv(u32 flags);
|
||||
int hostapd_build_ap_extra_ies(struct hostapd_data *hapd,
|
||||
struct wpabuf **beacon,
|
||||
struct wpabuf **proberesp,
|
||||
struct wpabuf **assocresp);
|
||||
void hostapd_free_ap_extra_ies(struct hostapd_data *hapd, struct wpabuf *beacon,
|
||||
struct wpabuf *proberesp,
|
||||
struct wpabuf *assocresp);
|
||||
int hostapd_set_ap_wps_ie(struct hostapd_data *hapd);
|
||||
int hostapd_set_authorized(struct hostapd_data *hapd,
|
||||
struct sta_info *sta, int authorized);
|
||||
int hostapd_set_sta_flags(struct hostapd_data *hapd, struct sta_info *sta);
|
||||
int hostapd_set_drv_ieee8021x(struct hostapd_data *hapd, const char *ifname,
|
||||
int enabled);
|
||||
int hostapd_vlan_if_add(struct hostapd_data *hapd, const char *ifname);
|
||||
int hostapd_vlan_if_remove(struct hostapd_data *hapd, const char *ifname);
|
||||
int hostapd_set_wds_sta(struct hostapd_data *hapd, const u8 *addr, int aid,
|
||||
int val);
|
||||
int hostapd_sta_add(struct hostapd_data *hapd,
|
||||
const u8 *addr, u16 aid, u16 capability,
|
||||
const u8 *supp_rates, size_t supp_rates_len,
|
||||
u16 listen_interval,
|
||||
const struct ieee80211_ht_capabilities *ht_capab,
|
||||
u32 flags, u8 qosinfo);
|
||||
int hostapd_set_privacy(struct hostapd_data *hapd, int enabled);
|
||||
int hostapd_set_generic_elem(struct hostapd_data *hapd, const u8 *elem,
|
||||
size_t elem_len);
|
||||
@ -27,7 +45,8 @@ int hostapd_get_ssid(struct hostapd_data *hapd, u8 *buf, size_t len);
|
||||
int hostapd_set_ssid(struct hostapd_data *hapd, const u8 *buf, size_t len);
|
||||
int hostapd_if_add(struct hostapd_data *hapd, enum wpa_driver_if_type type,
|
||||
const char *ifname, const u8 *addr, void *bss_ctx,
|
||||
void **drv_priv, char *force_ifname, u8 *if_addr);
|
||||
void **drv_priv, char *force_ifname, u8 *if_addr,
|
||||
const char *bridge);
|
||||
int hostapd_if_remove(struct hostapd_data *hapd, enum wpa_driver_if_type type,
|
||||
const char *ifname);
|
||||
int hostapd_set_ieee8021x(struct hostapd_data *hapd,
|
||||
@ -41,27 +60,157 @@ int hostapd_set_rts(struct hostapd_data *hapd, int rts);
|
||||
int hostapd_set_frag(struct hostapd_data *hapd, int frag);
|
||||
int hostapd_sta_set_flags(struct hostapd_data *hapd, u8 *addr,
|
||||
int total_flags, int flags_or, int flags_and);
|
||||
int hostapd_set_rate_sets(struct hostapd_data *hapd, int *supp_rates,
|
||||
int *basic_rates, int mode);
|
||||
int hostapd_set_country(struct hostapd_data *hapd, const char *country);
|
||||
int hostapd_set_cts_protect(struct hostapd_data *hapd, int value);
|
||||
int hostapd_set_preamble(struct hostapd_data *hapd, int value);
|
||||
int hostapd_set_short_slot_time(struct hostapd_data *hapd, int value);
|
||||
int hostapd_set_tx_queue_params(struct hostapd_data *hapd, int queue, int aifs,
|
||||
int cw_min, int cw_max, int burst_time);
|
||||
int hostapd_valid_bss_mask(struct hostapd_data *hapd, const u8 *addr,
|
||||
const u8 *mask);
|
||||
struct hostapd_hw_modes *
|
||||
hostapd_get_hw_feature_data(struct hostapd_data *hapd, u16 *num_modes,
|
||||
u16 *flags);
|
||||
int hostapd_driver_commit(struct hostapd_data *hapd);
|
||||
int hostapd_set_ht_params(struct hostapd_data *hapd,
|
||||
const u8 *ht_capab, size_t ht_capab_len,
|
||||
const u8 *ht_oper, size_t ht_oper_len);
|
||||
int hostapd_drv_none(struct hostapd_data *hapd);
|
||||
int hostapd_driver_scan(struct hostapd_data *hapd,
|
||||
struct wpa_driver_scan_params *params);
|
||||
struct wpa_scan_results * hostapd_driver_get_scan_results(
|
||||
struct hostapd_data *hapd);
|
||||
int hostapd_driver_set_noa(struct hostapd_data *hapd, u8 count, int start,
|
||||
int duration);
|
||||
int hostapd_drv_set_key(const char *ifname,
|
||||
struct hostapd_data *hapd,
|
||||
enum wpa_alg alg, const u8 *addr,
|
||||
int key_idx, int set_tx,
|
||||
const u8 *seq, size_t seq_len,
|
||||
const u8 *key, size_t key_len);
|
||||
int hostapd_drv_send_mlme(struct hostapd_data *hapd,
|
||||
const void *msg, size_t len, int noack);
|
||||
int hostapd_drv_sta_deauth(struct hostapd_data *hapd,
|
||||
const u8 *addr, int reason);
|
||||
int hostapd_drv_sta_disassoc(struct hostapd_data *hapd,
|
||||
const u8 *addr, int reason);
|
||||
int hostapd_drv_send_action(struct hostapd_data *hapd, unsigned int freq,
|
||||
unsigned int wait, const u8 *dst, const u8 *data,
|
||||
size_t len);
|
||||
int hostapd_add_sta_node(struct hostapd_data *hapd, const u8 *addr,
|
||||
u16 auth_alg);
|
||||
int hostapd_sta_auth(struct hostapd_data *hapd, const u8 *addr,
|
||||
u16 seq, u16 status, const u8 *ie, size_t len);
|
||||
int hostapd_sta_assoc(struct hostapd_data *hapd, const u8 *addr,
|
||||
int reassoc, u16 status, const u8 *ie, size_t len);
|
||||
int hostapd_add_tspec(struct hostapd_data *hapd, const u8 *addr,
|
||||
u8 *tspec_ie, size_t tspec_ielen);
|
||||
|
||||
|
||||
#include "drivers/driver.h"
|
||||
|
||||
int hostapd_drv_wnm_oper(struct hostapd_data *hapd,
|
||||
enum wnm_oper oper, const u8 *peer,
|
||||
u8 *buf, u16 *buf_len);
|
||||
|
||||
static inline int hostapd_drv_set_countermeasures(struct hostapd_data *hapd,
|
||||
int enabled)
|
||||
{
|
||||
if (hapd->driver == NULL ||
|
||||
hapd->driver->hapd_set_countermeasures == NULL)
|
||||
return 0;
|
||||
return hapd->driver->hapd_set_countermeasures(hapd->drv_priv, enabled);
|
||||
}
|
||||
|
||||
static inline int hostapd_drv_set_sta_vlan(const char *ifname,
|
||||
struct hostapd_data *hapd,
|
||||
const u8 *addr, int vlan_id)
|
||||
{
|
||||
if (hapd->driver == NULL || hapd->driver->set_sta_vlan == NULL)
|
||||
return 0;
|
||||
return hapd->driver->set_sta_vlan(hapd->drv_priv, addr, ifname,
|
||||
vlan_id);
|
||||
}
|
||||
|
||||
static inline int hostapd_drv_get_inact_sec(struct hostapd_data *hapd,
|
||||
const u8 *addr)
|
||||
{
|
||||
if (hapd->driver == NULL || hapd->driver->get_inact_sec == NULL)
|
||||
return 0;
|
||||
return hapd->driver->get_inact_sec(hapd->drv_priv, addr);
|
||||
}
|
||||
|
||||
static inline int hostapd_drv_sta_remove(struct hostapd_data *hapd,
|
||||
const u8 *addr)
|
||||
{
|
||||
if (hapd->driver == NULL || hapd->driver->sta_remove == NULL)
|
||||
return 0;
|
||||
return hapd->driver->sta_remove(hapd->drv_priv, addr);
|
||||
}
|
||||
|
||||
static inline int hostapd_drv_hapd_send_eapol(struct hostapd_data *hapd,
|
||||
const u8 *addr, const u8 *data,
|
||||
size_t data_len, int encrypt,
|
||||
u32 flags)
|
||||
{
|
||||
if (hapd->driver == NULL || hapd->driver->hapd_send_eapol == NULL)
|
||||
return 0;
|
||||
return hapd->driver->hapd_send_eapol(hapd->drv_priv, addr, data,
|
||||
data_len, encrypt,
|
||||
hapd->own_addr, flags);
|
||||
}
|
||||
|
||||
static inline int hostapd_drv_read_sta_data(
|
||||
struct hostapd_data *hapd, struct hostap_sta_driver_data *data,
|
||||
const u8 *addr)
|
||||
{
|
||||
if (hapd->driver == NULL || hapd->driver->read_sta_data == NULL)
|
||||
return -1;
|
||||
return hapd->driver->read_sta_data(hapd->drv_priv, data, addr);
|
||||
}
|
||||
|
||||
static inline int hostapd_drv_sta_clear_stats(struct hostapd_data *hapd,
|
||||
const u8 *addr)
|
||||
{
|
||||
if (hapd->driver == NULL || hapd->driver->sta_clear_stats == NULL)
|
||||
return 0;
|
||||
return hapd->driver->sta_clear_stats(hapd->drv_priv, addr);
|
||||
}
|
||||
|
||||
static inline int hostapd_drv_set_ap(struct hostapd_data *hapd,
|
||||
struct wpa_driver_ap_params *params)
|
||||
{
|
||||
if (hapd->driver == NULL || hapd->driver->set_ap == NULL)
|
||||
return 0;
|
||||
return hapd->driver->set_ap(hapd->drv_priv, params);
|
||||
}
|
||||
|
||||
static inline int hostapd_drv_set_radius_acl_auth(struct hostapd_data *hapd,
|
||||
const u8 *mac, int accepted,
|
||||
u32 session_timeout)
|
||||
{
|
||||
if (hapd->driver == NULL || hapd->driver->set_radius_acl_auth == NULL)
|
||||
return 0;
|
||||
return hapd->driver->set_radius_acl_auth(hapd->drv_priv, mac, accepted,
|
||||
session_timeout);
|
||||
}
|
||||
|
||||
static inline int hostapd_drv_set_radius_acl_expire(struct hostapd_data *hapd,
|
||||
const u8 *mac)
|
||||
{
|
||||
if (hapd->driver == NULL ||
|
||||
hapd->driver->set_radius_acl_expire == NULL)
|
||||
return 0;
|
||||
return hapd->driver->set_radius_acl_expire(hapd->drv_priv, mac);
|
||||
}
|
||||
|
||||
static inline int hostapd_drv_set_authmode(struct hostapd_data *hapd,
|
||||
int auth_algs)
|
||||
{
|
||||
if (hapd->driver == NULL || hapd->driver->set_authmode == NULL)
|
||||
return 0;
|
||||
return hapd->driver->set_authmode(hapd->drv_priv, auth_algs);
|
||||
}
|
||||
|
||||
static inline void hostapd_drv_poll_client(struct hostapd_data *hapd,
|
||||
const u8 *own_addr, const u8 *addr,
|
||||
int qos)
|
||||
{
|
||||
if (hapd->driver == NULL || hapd->driver->poll_client == NULL)
|
||||
return;
|
||||
hapd->driver->poll_client(hapd->drv_priv, own_addr, addr, qos);
|
||||
}
|
||||
|
||||
#endif /* AP_DRV_OPS */
|
||||
|
@ -4,14 +4,8 @@
|
||||
* Copyright (c) 2003-2004, Instant802 Networks, Inc.
|
||||
* Copyright (c) 2006, Devicescape Software, Inc.
|
||||
*
|
||||
* This program is free software; you can redistribute it and/or modify
|
||||
* it under the terms of the GNU General Public License version 2 as
|
||||
* published by the Free Software Foundation.
|
||||
*
|
||||
* Alternatively, this software may be distributed under the terms of BSD
|
||||
* license.
|
||||
*
|
||||
* See README and COPYING for more details.
|
||||
* This software may be distributed under the terms of the BSD license.
|
||||
* See README for more details.
|
||||
*/
|
||||
|
||||
#include "utils/includes.h"
|
||||
@ -227,6 +221,7 @@ void ap_list_process_beacon(struct hostapd_iface *iface,
|
||||
struct hostapd_frame_info *fi)
|
||||
{
|
||||
struct ap_info *ap;
|
||||
struct os_time now;
|
||||
int new_ap = 0;
|
||||
size_t len;
|
||||
int set_beacon = 0;
|
||||
@ -256,23 +251,9 @@ void ap_list_process_beacon(struct hostapd_iface *iface,
|
||||
ap->ssid_len = len;
|
||||
}
|
||||
|
||||
os_memset(ap->supported_rates, 0, WLAN_SUPP_RATES_MAX);
|
||||
len = 0;
|
||||
if (elems->supp_rates) {
|
||||
len = elems->supp_rates_len;
|
||||
if (len > WLAN_SUPP_RATES_MAX)
|
||||
len = WLAN_SUPP_RATES_MAX;
|
||||
os_memcpy(ap->supported_rates, elems->supp_rates, len);
|
||||
}
|
||||
if (elems->ext_supp_rates) {
|
||||
int len2;
|
||||
if (len + elems->ext_supp_rates_len > WLAN_SUPP_RATES_MAX)
|
||||
len2 = WLAN_SUPP_RATES_MAX - len;
|
||||
else
|
||||
len2 = elems->ext_supp_rates_len;
|
||||
os_memcpy(ap->supported_rates + len, elems->ext_supp_rates,
|
||||
len2);
|
||||
}
|
||||
merge_byte_arrays(ap->supported_rates, WLAN_SUPP_RATES_MAX,
|
||||
elems->supp_rates, elems->supp_rates_len,
|
||||
elems->ext_supp_rates, elems->ext_supp_rates_len);
|
||||
|
||||
ap->wpa = elems->wpa_ie != NULL;
|
||||
|
||||
@ -292,11 +273,10 @@ void ap_list_process_beacon(struct hostapd_iface *iface,
|
||||
ap->ht_support = 0;
|
||||
|
||||
ap->num_beacons++;
|
||||
time(&ap->last_beacon);
|
||||
if (fi) {
|
||||
ap->ssi_signal = fi->ssi_signal;
|
||||
os_get_time(&now);
|
||||
ap->last_beacon = now.sec;
|
||||
if (fi)
|
||||
ap->datarate = fi->datarate;
|
||||
}
|
||||
|
||||
if (!new_ap && ap != iface->ap_list) {
|
||||
/* move AP entry into the beginning of the list so that the
|
||||
@ -324,14 +304,14 @@ void ap_list_process_beacon(struct hostapd_iface *iface,
|
||||
#endif /* CONFIG_IEEE80211N */
|
||||
|
||||
if (set_beacon)
|
||||
ieee802_11_set_beacons(iface);
|
||||
ieee802_11_update_beacons(iface);
|
||||
}
|
||||
|
||||
|
||||
static void ap_list_timer(void *eloop_ctx, void *timeout_ctx)
|
||||
{
|
||||
struct hostapd_iface *iface = eloop_ctx;
|
||||
time_t now;
|
||||
struct os_time now;
|
||||
struct ap_info *ap;
|
||||
int set_beacon = 0;
|
||||
|
||||
@ -340,12 +320,12 @@ static void ap_list_timer(void *eloop_ctx, void *timeout_ctx)
|
||||
if (!iface->ap_list)
|
||||
return;
|
||||
|
||||
time(&now);
|
||||
os_get_time(&now);
|
||||
|
||||
while (iface->ap_list) {
|
||||
ap = iface->ap_list->prev;
|
||||
if (ap->last_beacon + iface->conf->ap_table_expiration_time >=
|
||||
now)
|
||||
now.sec)
|
||||
break;
|
||||
|
||||
ap_free_ap(iface, ap);
|
||||
@ -379,7 +359,7 @@ static void ap_list_timer(void *eloop_ctx, void *timeout_ctx)
|
||||
}
|
||||
|
||||
if (set_beacon)
|
||||
ieee802_11_set_beacons(iface);
|
||||
ieee802_11_update_beacons(iface);
|
||||
}
|
||||
|
||||
|
||||
|
@ -4,14 +4,8 @@
|
||||
* Copyright (c) 2003-2004, Instant802 Networks, Inc.
|
||||
* Copyright (c) 2006, Devicescape Software, Inc.
|
||||
*
|
||||
* This program is free software; you can redistribute it and/or modify
|
||||
* it under the terms of the GNU General Public License version 2 as
|
||||
* published by the Free Software Foundation.
|
||||
*
|
||||
* Alternatively, this software may be distributed under the terms of BSD
|
||||
* license.
|
||||
*
|
||||
* See README and COPYING for more details.
|
||||
* This software may be distributed under the terms of the BSD license.
|
||||
* See README for more details.
|
||||
*/
|
||||
|
||||
#ifndef AP_LIST_H
|
||||
@ -40,12 +34,11 @@ struct ap_info {
|
||||
|
||||
int channel;
|
||||
int datarate; /* in 100 kbps */
|
||||
int ssi_signal;
|
||||
|
||||
int ht_support;
|
||||
|
||||
unsigned int num_beacons; /* number of beacon frames received */
|
||||
time_t last_beacon;
|
||||
os_time_t last_beacon;
|
||||
|
||||
int already_seen; /* whether API call AP-NEW has already fetched
|
||||
* information about this AP */
|
||||
|
@ -4,14 +4,8 @@
|
||||
* Copyright 2003-2004, Instant802 Networks, Inc.
|
||||
* Copyright 2005-2006, Devicescape Software, Inc.
|
||||
*
|
||||
* This program is free software; you can redistribute it and/or modify
|
||||
* it under the terms of the GNU General Public License version 2 as
|
||||
* published by the Free Software Foundation.
|
||||
*
|
||||
* Alternatively, this software may be distributed under the terms of BSD
|
||||
* license.
|
||||
*
|
||||
* See README and COPYING for more details.
|
||||
* This software may be distributed under the terms of the BSD license.
|
||||
* See README for more details.
|
||||
*/
|
||||
|
||||
#include "utils/includes.h"
|
||||
|
@ -4,14 +4,8 @@
|
||||
* Copyright 2003-2004, Instant802 Networks, Inc.
|
||||
* Copyright 2005-2006, Devicescape Software, Inc.
|
||||
*
|
||||
* This program is free software; you can redistribute it and/or modify
|
||||
* it under the terms of the GNU General Public License version 2 as
|
||||
* published by the Free Software Foundation.
|
||||
*
|
||||
* Alternatively, this software may be distributed under the terms of BSD
|
||||
* license.
|
||||
*
|
||||
* See README and COPYING for more details.
|
||||
* This software may be distributed under the terms of the BSD license.
|
||||
* See README for more details.
|
||||
*/
|
||||
|
||||
#ifndef MLME_H
|
||||
|
@ -2,14 +2,8 @@
|
||||
* Authentication server setup
|
||||
* Copyright (c) 2002-2009, Jouni Malinen <j@w1.fi>
|
||||
*
|
||||
* This program is free software; you can redistribute it and/or modify
|
||||
* it under the terms of the GNU General Public License version 2 as
|
||||
* published by the Free Software Foundation.
|
||||
*
|
||||
* Alternatively, this software may be distributed under the terms of BSD
|
||||
* license.
|
||||
*
|
||||
* See README and COPYING for more details.
|
||||
* This software may be distributed under the terms of the BSD license.
|
||||
* See README for more details.
|
||||
*/
|
||||
|
||||
#include "utils/includes.h"
|
||||
@ -60,7 +54,7 @@ static int hostapd_radius_get_eap_user(void *ctx, const u8 *identity,
|
||||
struct eap_user *user)
|
||||
{
|
||||
const struct hostapd_eap_user *eap_user;
|
||||
int i, count;
|
||||
int i;
|
||||
|
||||
eap_user = hostapd_get_eap_user(ctx, identity, identity_len, phase2);
|
||||
if (eap_user == NULL)
|
||||
@ -70,10 +64,7 @@ static int hostapd_radius_get_eap_user(void *ctx, const u8 *identity,
|
||||
return 0;
|
||||
|
||||
os_memset(user, 0, sizeof(*user));
|
||||
count = EAP_USER_MAX_METHODS;
|
||||
if (count > EAP_MAX_METHODS)
|
||||
count = EAP_MAX_METHODS;
|
||||
for (i = 0; i < count; i++) {
|
||||
for (i = 0; i < EAP_MAX_METHODS; i++) {
|
||||
user->methods[i].vendor = eap_user->methods[i].vendor;
|
||||
user->methods[i].method = eap_user->methods[i].method;
|
||||
}
|
||||
@ -101,7 +92,7 @@ static int hostapd_setup_radius_srv(struct hostapd_data *hapd)
|
||||
os_memset(&srv, 0, sizeof(srv));
|
||||
srv.client_file = conf->radius_server_clients;
|
||||
srv.auth_port = conf->radius_server_auth_port;
|
||||
srv.conf_ctx = conf;
|
||||
srv.conf_ctx = hapd;
|
||||
srv.eap_sim_db_priv = hapd->eap_sim_db_priv;
|
||||
srv.ssl_ctx = hapd->ssl_ctx;
|
||||
srv.msg_ctx = hapd->msg_ctx;
|
||||
@ -119,6 +110,10 @@ static int hostapd_setup_radius_srv(struct hostapd_data *hapd)
|
||||
srv.get_eap_user = hostapd_radius_get_eap_user;
|
||||
srv.eap_req_id_text = conf->eap_req_id_text;
|
||||
srv.eap_req_id_text_len = conf->eap_req_id_text_len;
|
||||
srv.pwd_group = conf->pwd_group;
|
||||
#ifdef CONFIG_RADIUS_TEST
|
||||
srv.dump_msk_file = conf->dump_msk_file;
|
||||
#endif /* CONFIG_RADIUS_TEST */
|
||||
|
||||
hapd->radius_srv = radius_server_init(&srv);
|
||||
if (hapd->radius_srv == NULL) {
|
||||
|
@ -2,14 +2,8 @@
|
||||
* Authentication server setup
|
||||
* Copyright (c) 2002-2009, Jouni Malinen <j@w1.fi>
|
||||
*
|
||||
* This program is free software; you can redistribute it and/or modify
|
||||
* it under the terms of the GNU General Public License version 2 as
|
||||
* published by the Free Software Foundation.
|
||||
*
|
||||
* Alternatively, this software may be distributed under the terms of BSD
|
||||
* license.
|
||||
*
|
||||
* See README and COPYING for more details.
|
||||
* This software may be distributed under the terms of the BSD license.
|
||||
* See README for more details.
|
||||
*/
|
||||
|
||||
#ifndef AUTHSRV_H
|
||||
|
553
src/ap/beacon.c
553
src/ap/beacon.c
@ -2,7 +2,7 @@
|
||||
* hostapd / IEEE 802.11 Management: Beacon and Probe Request/Response
|
||||
* Copyright (c) 2002-2004, Instant802 Networks, Inc.
|
||||
* Copyright (c) 2005-2006, Devicescape Software, Inc.
|
||||
* Copyright (c) 2008-2009, Jouni Malinen <j@w1.fi>
|
||||
* Copyright (c) 2008-2012, Jouni Malinen <j@w1.fi>
|
||||
*
|
||||
* This program is free software; you can redistribute it and/or modify
|
||||
* it under the terms of the GNU General Public License version 2 as
|
||||
@ -22,15 +22,22 @@
|
||||
#include "common/ieee802_11_defs.h"
|
||||
#include "common/ieee802_11_common.h"
|
||||
#include "drivers/driver.h"
|
||||
#include "wps/wps_defs.h"
|
||||
#include "p2p/p2p.h"
|
||||
#include "hostapd.h"
|
||||
#include "ieee802_11.h"
|
||||
#include "wpa_auth.h"
|
||||
#include "wmm.h"
|
||||
#include "ap_config.h"
|
||||
#include "sta_info.h"
|
||||
#include "p2p_hostapd.h"
|
||||
#include "ap_drv_ops.h"
|
||||
#include "beacon.h"
|
||||
#include "hs20.h"
|
||||
|
||||
|
||||
#ifdef NEED_AP_MLME
|
||||
|
||||
static u8 ieee802_11_erp_info(struct hostapd_data *hapd)
|
||||
{
|
||||
u8 erp = 0;
|
||||
@ -39,23 +46,11 @@ static u8 ieee802_11_erp_info(struct hostapd_data *hapd)
|
||||
hapd->iface->current_mode->mode != HOSTAPD_MODE_IEEE80211G)
|
||||
return 0;
|
||||
|
||||
switch (hapd->iconf->cts_protection_type) {
|
||||
case CTS_PROTECTION_FORCE_ENABLED:
|
||||
erp |= ERP_INFO_NON_ERP_PRESENT | ERP_INFO_USE_PROTECTION;
|
||||
break;
|
||||
case CTS_PROTECTION_FORCE_DISABLED:
|
||||
erp = 0;
|
||||
break;
|
||||
case CTS_PROTECTION_AUTOMATIC:
|
||||
if (hapd->iface->olbc)
|
||||
erp |= ERP_INFO_USE_PROTECTION;
|
||||
/* continue */
|
||||
case CTS_PROTECTION_AUTOMATIC_NO_OLBC:
|
||||
if (hapd->iface->num_sta_non_erp > 0) {
|
||||
erp |= ERP_INFO_NON_ERP_PRESENT |
|
||||
ERP_INFO_USE_PROTECTION;
|
||||
}
|
||||
break;
|
||||
if (hapd->iface->olbc)
|
||||
erp |= ERP_INFO_USE_PROTECTION;
|
||||
if (hapd->iface->num_sta_non_erp > 0) {
|
||||
erp |= ERP_INFO_NON_ERP_PRESENT |
|
||||
ERP_INFO_USE_PROTECTION;
|
||||
}
|
||||
if (hapd->iface->num_sta_no_short_preamble > 0 ||
|
||||
hapd->iconf->preamble == LONG_PREAMBLE)
|
||||
@ -178,8 +173,7 @@ static u8 * hostapd_eid_country(struct hostapd_data *hapd, u8 *eid,
|
||||
}
|
||||
|
||||
|
||||
static u8 * hostapd_eid_wpa(struct hostapd_data *hapd, u8 *eid, size_t len,
|
||||
struct sta_info *sta)
|
||||
static u8 * hostapd_eid_wpa(struct hostapd_data *hapd, u8 *eid, size_t len)
|
||||
{
|
||||
const u8 *ie;
|
||||
size_t ielen;
|
||||
@ -193,92 +187,37 @@ static u8 * hostapd_eid_wpa(struct hostapd_data *hapd, u8 *eid, size_t len,
|
||||
}
|
||||
|
||||
|
||||
void handle_probe_req(struct hostapd_data *hapd,
|
||||
const struct ieee80211_mgmt *mgmt, size_t len)
|
||||
static u8 * hostapd_gen_probe_resp(struct hostapd_data *hapd,
|
||||
struct sta_info *sta,
|
||||
const struct ieee80211_mgmt *req,
|
||||
int is_p2p, size_t *resp_len)
|
||||
{
|
||||
struct ieee80211_mgmt *resp;
|
||||
struct ieee802_11_elems elems;
|
||||
char *ssid;
|
||||
u8 *pos, *epos;
|
||||
const u8 *ie;
|
||||
size_t ssid_len, ie_len;
|
||||
struct sta_info *sta = NULL;
|
||||
size_t buflen;
|
||||
size_t i;
|
||||
|
||||
ie = mgmt->u.probe_req.variable;
|
||||
ie_len = len - (IEEE80211_HDRLEN + sizeof(mgmt->u.probe_req));
|
||||
|
||||
for (i = 0; hapd->probereq_cb && i < hapd->num_probereq_cb; i++)
|
||||
if (hapd->probereq_cb[i].cb(hapd->probereq_cb[i].ctx,
|
||||
mgmt->sa, ie, ie_len) > 0)
|
||||
return;
|
||||
|
||||
if (!hapd->iconf->send_probe_response)
|
||||
return;
|
||||
|
||||
if (ieee802_11_parse_elems(ie, ie_len, &elems, 0) == ParseFailed) {
|
||||
wpa_printf(MSG_DEBUG, "Could not parse ProbeReq from " MACSTR,
|
||||
MAC2STR(mgmt->sa));
|
||||
return;
|
||||
}
|
||||
|
||||
ssid = NULL;
|
||||
ssid_len = 0;
|
||||
|
||||
if ((!elems.ssid || !elems.supp_rates)) {
|
||||
wpa_printf(MSG_DEBUG, "STA " MACSTR " sent probe request "
|
||||
"without SSID or supported rates element",
|
||||
MAC2STR(mgmt->sa));
|
||||
return;
|
||||
}
|
||||
|
||||
if (hapd->conf->ignore_broadcast_ssid && elems.ssid_len == 0) {
|
||||
wpa_printf(MSG_MSGDUMP, "Probe Request from " MACSTR " for "
|
||||
"broadcast SSID ignored", MAC2STR(mgmt->sa));
|
||||
return;
|
||||
}
|
||||
|
||||
sta = ap_get_sta(hapd, mgmt->sa);
|
||||
|
||||
if (elems.ssid_len == 0 ||
|
||||
(elems.ssid_len == hapd->conf->ssid.ssid_len &&
|
||||
os_memcmp(elems.ssid, hapd->conf->ssid.ssid, elems.ssid_len) ==
|
||||
0)) {
|
||||
ssid = hapd->conf->ssid.ssid;
|
||||
ssid_len = hapd->conf->ssid.ssid_len;
|
||||
if (sta)
|
||||
sta->ssid_probe = &hapd->conf->ssid;
|
||||
}
|
||||
|
||||
if (!ssid) {
|
||||
if (!(mgmt->da[0] & 0x01)) {
|
||||
char ssid_txt[33];
|
||||
ieee802_11_print_ssid(ssid_txt, elems.ssid,
|
||||
elems.ssid_len);
|
||||
wpa_printf(MSG_MSGDUMP, "Probe Request from " MACSTR
|
||||
" for foreign SSID '%s'",
|
||||
MAC2STR(mgmt->sa), ssid_txt);
|
||||
}
|
||||
return;
|
||||
}
|
||||
|
||||
/* TODO: verify that supp_rates contains at least one matching rate
|
||||
* with AP configuration */
|
||||
#define MAX_PROBERESP_LEN 768
|
||||
buflen = MAX_PROBERESP_LEN;
|
||||
#ifdef CONFIG_WPS
|
||||
if (hapd->wps_probe_resp_ie)
|
||||
buflen += wpabuf_len(hapd->wps_probe_resp_ie);
|
||||
#endif /* CONFIG_WPS */
|
||||
#ifdef CONFIG_P2P
|
||||
if (hapd->p2p_probe_resp_ie)
|
||||
buflen += wpabuf_len(hapd->p2p_probe_resp_ie);
|
||||
#endif /* CONFIG_P2P */
|
||||
if (hapd->conf->vendor_elements)
|
||||
buflen += wpabuf_len(hapd->conf->vendor_elements);
|
||||
resp = os_zalloc(buflen);
|
||||
if (resp == NULL)
|
||||
return;
|
||||
return NULL;
|
||||
|
||||
epos = ((u8 *) resp) + MAX_PROBERESP_LEN;
|
||||
|
||||
resp->frame_control = IEEE80211_FC(WLAN_FC_TYPE_MGMT,
|
||||
WLAN_FC_STYPE_PROBE_RESP);
|
||||
os_memcpy(resp->da, mgmt->sa, ETH_ALEN);
|
||||
if (req)
|
||||
os_memcpy(resp->da, req->sa, ETH_ALEN);
|
||||
os_memcpy(resp->sa, hapd->own_addr, ETH_ALEN);
|
||||
|
||||
os_memcpy(resp->bssid, hapd->own_addr, ETH_ALEN);
|
||||
@ -291,9 +230,9 @@ void handle_probe_req(struct hostapd_data *hapd,
|
||||
|
||||
pos = resp->u.probe_resp.variable;
|
||||
*pos++ = WLAN_EID_SSID;
|
||||
*pos++ = ssid_len;
|
||||
os_memcpy(pos, ssid, ssid_len);
|
||||
pos += ssid_len;
|
||||
*pos++ = hapd->conf->ssid.ssid_len;
|
||||
os_memcpy(pos, hapd->conf->ssid.ssid, hapd->conf->ssid.ssid_len);
|
||||
pos += hapd->conf->ssid.ssid_len;
|
||||
|
||||
/* Supported rates */
|
||||
pos = hostapd_eid_supp_rates(hapd, pos);
|
||||
@ -310,13 +249,27 @@ void handle_probe_req(struct hostapd_data *hapd,
|
||||
pos = hostapd_eid_ext_supp_rates(hapd, pos);
|
||||
|
||||
/* RSN, MDIE, WPA */
|
||||
pos = hostapd_eid_wpa(hapd, pos, epos - pos, sta);
|
||||
pos = hostapd_eid_wpa(hapd, pos, epos - pos);
|
||||
|
||||
#ifdef CONFIG_IEEE80211N
|
||||
pos = hostapd_eid_ht_capabilities(hapd, pos);
|
||||
pos = hostapd_eid_ht_operation(hapd, pos);
|
||||
#endif /* CONFIG_IEEE80211N */
|
||||
|
||||
pos = hostapd_eid_ext_capab(hapd, pos);
|
||||
|
||||
pos = hostapd_eid_time_adv(hapd, pos);
|
||||
pos = hostapd_eid_time_zone(hapd, pos);
|
||||
|
||||
pos = hostapd_eid_interworking(hapd, pos);
|
||||
pos = hostapd_eid_adv_proto(hapd, pos);
|
||||
pos = hostapd_eid_roaming_consortium(hapd, pos);
|
||||
|
||||
#ifdef CONFIG_IEEE80211AC
|
||||
pos = hostapd_eid_vht_capabilities(hapd, pos);
|
||||
pos = hostapd_eid_vht_operation(hapd, pos);
|
||||
#endif /* CONFIG_IEEE80211AC */
|
||||
|
||||
/* Wi-Fi Alliance WMM */
|
||||
pos = hostapd_eid_wmm(hapd, pos);
|
||||
|
||||
@ -328,23 +281,291 @@ void handle_probe_req(struct hostapd_data *hapd,
|
||||
}
|
||||
#endif /* CONFIG_WPS */
|
||||
|
||||
if (hapd->drv.send_mgmt_frame(hapd, resp, pos - (u8 *) resp) < 0)
|
||||
#ifdef CONFIG_P2P
|
||||
if ((hapd->conf->p2p & P2P_ENABLED) && is_p2p &&
|
||||
hapd->p2p_probe_resp_ie) {
|
||||
os_memcpy(pos, wpabuf_head(hapd->p2p_probe_resp_ie),
|
||||
wpabuf_len(hapd->p2p_probe_resp_ie));
|
||||
pos += wpabuf_len(hapd->p2p_probe_resp_ie);
|
||||
}
|
||||
#endif /* CONFIG_P2P */
|
||||
#ifdef CONFIG_P2P_MANAGER
|
||||
if ((hapd->conf->p2p & (P2P_MANAGE | P2P_ENABLED | P2P_GROUP_OWNER)) ==
|
||||
P2P_MANAGE)
|
||||
pos = hostapd_eid_p2p_manage(hapd, pos);
|
||||
#endif /* CONFIG_P2P_MANAGER */
|
||||
|
||||
#ifdef CONFIG_HS20
|
||||
pos = hostapd_eid_hs20_indication(hapd, pos);
|
||||
#endif /* CONFIG_HS20 */
|
||||
|
||||
if (hapd->conf->vendor_elements) {
|
||||
os_memcpy(pos, wpabuf_head(hapd->conf->vendor_elements),
|
||||
wpabuf_len(hapd->conf->vendor_elements));
|
||||
pos += wpabuf_len(hapd->conf->vendor_elements);
|
||||
}
|
||||
|
||||
*resp_len = pos - (u8 *) resp;
|
||||
return (u8 *) resp;
|
||||
}
|
||||
|
||||
|
||||
enum ssid_match_result {
|
||||
NO_SSID_MATCH,
|
||||
EXACT_SSID_MATCH,
|
||||
WILDCARD_SSID_MATCH
|
||||
};
|
||||
|
||||
static enum ssid_match_result ssid_match(struct hostapd_data *hapd,
|
||||
const u8 *ssid, size_t ssid_len,
|
||||
const u8 *ssid_list,
|
||||
size_t ssid_list_len)
|
||||
{
|
||||
const u8 *pos, *end;
|
||||
int wildcard = 0;
|
||||
|
||||
if (ssid_len == 0)
|
||||
wildcard = 1;
|
||||
if (ssid_len == hapd->conf->ssid.ssid_len &&
|
||||
os_memcmp(ssid, hapd->conf->ssid.ssid, ssid_len) == 0)
|
||||
return EXACT_SSID_MATCH;
|
||||
|
||||
if (ssid_list == NULL)
|
||||
return wildcard ? WILDCARD_SSID_MATCH : NO_SSID_MATCH;
|
||||
|
||||
pos = ssid_list;
|
||||
end = ssid_list + ssid_list_len;
|
||||
while (pos + 1 <= end) {
|
||||
if (pos + 2 + pos[1] > end)
|
||||
break;
|
||||
if (pos[1] == 0)
|
||||
wildcard = 1;
|
||||
if (pos[1] == hapd->conf->ssid.ssid_len &&
|
||||
os_memcmp(pos + 2, hapd->conf->ssid.ssid, pos[1]) == 0)
|
||||
return EXACT_SSID_MATCH;
|
||||
pos += 2 + pos[1];
|
||||
}
|
||||
|
||||
return wildcard ? WILDCARD_SSID_MATCH : NO_SSID_MATCH;
|
||||
}
|
||||
|
||||
|
||||
void handle_probe_req(struct hostapd_data *hapd,
|
||||
const struct ieee80211_mgmt *mgmt, size_t len,
|
||||
int ssi_signal)
|
||||
{
|
||||
u8 *resp;
|
||||
struct ieee802_11_elems elems;
|
||||
const u8 *ie;
|
||||
size_t ie_len;
|
||||
struct sta_info *sta = NULL;
|
||||
size_t i, resp_len;
|
||||
int noack;
|
||||
enum ssid_match_result res;
|
||||
|
||||
ie = mgmt->u.probe_req.variable;
|
||||
if (len < IEEE80211_HDRLEN + sizeof(mgmt->u.probe_req))
|
||||
return;
|
||||
ie_len = len - (IEEE80211_HDRLEN + sizeof(mgmt->u.probe_req));
|
||||
|
||||
for (i = 0; hapd->probereq_cb && i < hapd->num_probereq_cb; i++)
|
||||
if (hapd->probereq_cb[i].cb(hapd->probereq_cb[i].ctx,
|
||||
mgmt->sa, mgmt->da, mgmt->bssid,
|
||||
ie, ie_len, ssi_signal) > 0)
|
||||
return;
|
||||
|
||||
if (!hapd->iconf->send_probe_response)
|
||||
return;
|
||||
|
||||
if (ieee802_11_parse_elems(ie, ie_len, &elems, 0) == ParseFailed) {
|
||||
wpa_printf(MSG_DEBUG, "Could not parse ProbeReq from " MACSTR,
|
||||
MAC2STR(mgmt->sa));
|
||||
return;
|
||||
}
|
||||
|
||||
if ((!elems.ssid || !elems.supp_rates)) {
|
||||
wpa_printf(MSG_DEBUG, "STA " MACSTR " sent probe request "
|
||||
"without SSID or supported rates element",
|
||||
MAC2STR(mgmt->sa));
|
||||
return;
|
||||
}
|
||||
|
||||
#ifdef CONFIG_P2P
|
||||
if (hapd->p2p && elems.wps_ie) {
|
||||
struct wpabuf *wps;
|
||||
wps = ieee802_11_vendor_ie_concat(ie, ie_len, WPS_DEV_OUI_WFA);
|
||||
if (wps && !p2p_group_match_dev_type(hapd->p2p_group, wps)) {
|
||||
wpa_printf(MSG_MSGDUMP, "P2P: Ignore Probe Request "
|
||||
"due to mismatch with Requested Device "
|
||||
"Type");
|
||||
wpabuf_free(wps);
|
||||
return;
|
||||
}
|
||||
wpabuf_free(wps);
|
||||
}
|
||||
|
||||
if (hapd->p2p && elems.p2p) {
|
||||
struct wpabuf *p2p;
|
||||
p2p = ieee802_11_vendor_ie_concat(ie, ie_len, P2P_IE_VENDOR_TYPE);
|
||||
if (p2p && !p2p_group_match_dev_id(hapd->p2p_group, p2p)) {
|
||||
wpa_printf(MSG_MSGDUMP, "P2P: Ignore Probe Request "
|
||||
"due to mismatch with Device ID");
|
||||
wpabuf_free(p2p);
|
||||
return;
|
||||
}
|
||||
wpabuf_free(p2p);
|
||||
}
|
||||
#endif /* CONFIG_P2P */
|
||||
|
||||
if (hapd->conf->ignore_broadcast_ssid && elems.ssid_len == 0 &&
|
||||
elems.ssid_list_len == 0) {
|
||||
wpa_printf(MSG_MSGDUMP, "Probe Request from " MACSTR " for "
|
||||
"broadcast SSID ignored", MAC2STR(mgmt->sa));
|
||||
return;
|
||||
}
|
||||
|
||||
sta = ap_get_sta(hapd, mgmt->sa);
|
||||
|
||||
#ifdef CONFIG_P2P
|
||||
if ((hapd->conf->p2p & P2P_GROUP_OWNER) &&
|
||||
elems.ssid_len == P2P_WILDCARD_SSID_LEN &&
|
||||
os_memcmp(elems.ssid, P2P_WILDCARD_SSID,
|
||||
P2P_WILDCARD_SSID_LEN) == 0) {
|
||||
/* Process P2P Wildcard SSID like Wildcard SSID */
|
||||
elems.ssid_len = 0;
|
||||
}
|
||||
#endif /* CONFIG_P2P */
|
||||
|
||||
res = ssid_match(hapd, elems.ssid, elems.ssid_len,
|
||||
elems.ssid_list, elems.ssid_list_len);
|
||||
if (res != NO_SSID_MATCH) {
|
||||
if (sta)
|
||||
sta->ssid_probe = &hapd->conf->ssid;
|
||||
} else {
|
||||
if (!(mgmt->da[0] & 0x01)) {
|
||||
char ssid_txt[33];
|
||||
ieee802_11_print_ssid(ssid_txt, elems.ssid,
|
||||
elems.ssid_len);
|
||||
wpa_printf(MSG_MSGDUMP, "Probe Request from " MACSTR
|
||||
" for foreign SSID '%s' (DA " MACSTR ")%s",
|
||||
MAC2STR(mgmt->sa), ssid_txt,
|
||||
MAC2STR(mgmt->da),
|
||||
elems.ssid_list ? " (SSID list)" : "");
|
||||
}
|
||||
return;
|
||||
}
|
||||
|
||||
#ifdef CONFIG_INTERWORKING
|
||||
if (elems.interworking && elems.interworking_len >= 1) {
|
||||
u8 ant = elems.interworking[0] & 0x0f;
|
||||
if (ant != INTERWORKING_ANT_WILDCARD &&
|
||||
ant != hapd->conf->access_network_type) {
|
||||
wpa_printf(MSG_MSGDUMP, "Probe Request from " MACSTR
|
||||
" for mismatching ANT %u ignored",
|
||||
MAC2STR(mgmt->sa), ant);
|
||||
return;
|
||||
}
|
||||
}
|
||||
|
||||
if (elems.interworking &&
|
||||
(elems.interworking_len == 7 || elems.interworking_len == 9)) {
|
||||
const u8 *hessid;
|
||||
if (elems.interworking_len == 7)
|
||||
hessid = elems.interworking + 1;
|
||||
else
|
||||
hessid = elems.interworking + 1 + 2;
|
||||
if (!is_broadcast_ether_addr(hessid) &&
|
||||
os_memcmp(hessid, hapd->conf->hessid, ETH_ALEN) != 0) {
|
||||
wpa_printf(MSG_MSGDUMP, "Probe Request from " MACSTR
|
||||
" for mismatching HESSID " MACSTR
|
||||
" ignored",
|
||||
MAC2STR(mgmt->sa), MAC2STR(hessid));
|
||||
return;
|
||||
}
|
||||
}
|
||||
#endif /* CONFIG_INTERWORKING */
|
||||
|
||||
/* TODO: verify that supp_rates contains at least one matching rate
|
||||
* with AP configuration */
|
||||
|
||||
resp = hostapd_gen_probe_resp(hapd, sta, mgmt, elems.p2p != NULL,
|
||||
&resp_len);
|
||||
if (resp == NULL)
|
||||
return;
|
||||
|
||||
/*
|
||||
* If this is a broadcast probe request, apply no ack policy to avoid
|
||||
* excessive retries.
|
||||
*/
|
||||
noack = !!(res == WILDCARD_SSID_MATCH &&
|
||||
is_broadcast_ether_addr(mgmt->da));
|
||||
|
||||
if (hostapd_drv_send_mlme(hapd, resp, resp_len, noack) < 0)
|
||||
perror("handle_probe_req: send");
|
||||
|
||||
os_free(resp);
|
||||
|
||||
wpa_printf(MSG_MSGDUMP, "STA " MACSTR " sent probe request for %s "
|
||||
wpa_printf(MSG_EXCESSIVE, "STA " MACSTR " sent probe request for %s "
|
||||
"SSID", MAC2STR(mgmt->sa),
|
||||
elems.ssid_len == 0 ? "broadcast" : "our");
|
||||
}
|
||||
|
||||
|
||||
static u8 * hostapd_probe_resp_offloads(struct hostapd_data *hapd,
|
||||
size_t *resp_len)
|
||||
{
|
||||
/* check probe response offloading caps and print warnings */
|
||||
if (!(hapd->iface->drv_flags & WPA_DRIVER_FLAGS_PROBE_RESP_OFFLOAD))
|
||||
return NULL;
|
||||
|
||||
#ifdef CONFIG_WPS
|
||||
if (hapd->conf->wps_state && hapd->wps_probe_resp_ie &&
|
||||
(!(hapd->iface->probe_resp_offloads &
|
||||
(WPA_DRIVER_PROBE_RESP_OFFLOAD_WPS |
|
||||
WPA_DRIVER_PROBE_RESP_OFFLOAD_WPS2))))
|
||||
wpa_printf(MSG_WARNING, "Device is trying to offload WPS "
|
||||
"Probe Response while not supporting this");
|
||||
#endif /* CONFIG_WPS */
|
||||
|
||||
#ifdef CONFIG_P2P
|
||||
if ((hapd->conf->p2p & P2P_ENABLED) && hapd->p2p_probe_resp_ie &&
|
||||
!(hapd->iface->probe_resp_offloads &
|
||||
WPA_DRIVER_PROBE_RESP_OFFLOAD_P2P))
|
||||
wpa_printf(MSG_WARNING, "Device is trying to offload P2P "
|
||||
"Probe Response while not supporting this");
|
||||
#endif /* CONFIG_P2P */
|
||||
|
||||
if (hapd->conf->interworking &&
|
||||
!(hapd->iface->probe_resp_offloads &
|
||||
WPA_DRIVER_PROBE_RESP_OFFLOAD_INTERWORKING))
|
||||
wpa_printf(MSG_WARNING, "Device is trying to offload "
|
||||
"Interworking Probe Response while not supporting "
|
||||
"this");
|
||||
|
||||
/* Generate a Probe Response template for the non-P2P case */
|
||||
return hostapd_gen_probe_resp(hapd, NULL, NULL, 0, resp_len);
|
||||
}
|
||||
|
||||
#endif /* NEED_AP_MLME */
|
||||
|
||||
|
||||
void ieee802_11_set_beacon(struct hostapd_data *hapd)
|
||||
{
|
||||
struct ieee80211_mgmt *head;
|
||||
u8 *pos, *tail, *tailpos;
|
||||
struct ieee80211_mgmt *head = NULL;
|
||||
u8 *tail = NULL;
|
||||
size_t head_len = 0, tail_len = 0;
|
||||
u8 *resp = NULL;
|
||||
size_t resp_len = 0;
|
||||
struct wpa_driver_ap_params params;
|
||||
struct wpabuf *beacon, *proberesp, *assocresp;
|
||||
#ifdef NEED_AP_MLME
|
||||
u16 capab_info;
|
||||
size_t head_len, tail_len;
|
||||
u8 *pos, *tailpos;
|
||||
#endif /* NEED_AP_MLME */
|
||||
|
||||
hapd->beacon_set_done = 1;
|
||||
|
||||
#ifdef NEED_AP_MLME
|
||||
|
||||
#define BEACON_HEAD_BUF_SIZE 256
|
||||
#define BEACON_TAIL_BUF_SIZE 512
|
||||
@ -354,6 +575,12 @@ void ieee802_11_set_beacon(struct hostapd_data *hapd)
|
||||
if (hapd->conf->wps_state && hapd->wps_beacon_ie)
|
||||
tail_len += wpabuf_len(hapd->wps_beacon_ie);
|
||||
#endif /* CONFIG_WPS */
|
||||
#ifdef CONFIG_P2P
|
||||
if (hapd->p2p_beacon_ie)
|
||||
tail_len += wpabuf_len(hapd->p2p_beacon_ie);
|
||||
#endif /* CONFIG_P2P */
|
||||
if (hapd->conf->vendor_elements)
|
||||
tail_len += wpabuf_len(hapd->conf->vendor_elements);
|
||||
tailpos = tail = os_malloc(tail_len);
|
||||
if (head == NULL || tail == NULL) {
|
||||
wpa_printf(MSG_ERROR, "Failed to set beacon data");
|
||||
@ -412,13 +639,30 @@ void ieee802_11_set_beacon(struct hostapd_data *hapd)
|
||||
|
||||
/* RSN, MDIE, WPA */
|
||||
tailpos = hostapd_eid_wpa(hapd, tailpos, tail + BEACON_TAIL_BUF_SIZE -
|
||||
tailpos, NULL);
|
||||
tailpos);
|
||||
|
||||
#ifdef CONFIG_IEEE80211N
|
||||
tailpos = hostapd_eid_ht_capabilities(hapd, tailpos);
|
||||
tailpos = hostapd_eid_ht_operation(hapd, tailpos);
|
||||
#endif /* CONFIG_IEEE80211N */
|
||||
|
||||
tailpos = hostapd_eid_ext_capab(hapd, tailpos);
|
||||
|
||||
/*
|
||||
* TODO: Time Advertisement element should only be included in some
|
||||
* DTIM Beacon frames.
|
||||
*/
|
||||
tailpos = hostapd_eid_time_adv(hapd, tailpos);
|
||||
|
||||
tailpos = hostapd_eid_interworking(hapd, tailpos);
|
||||
tailpos = hostapd_eid_adv_proto(hapd, tailpos);
|
||||
tailpos = hostapd_eid_roaming_consortium(hapd, tailpos);
|
||||
|
||||
#ifdef CONFIG_IEEE80211AC
|
||||
tailpos = hostapd_eid_vht_capabilities(hapd, tailpos);
|
||||
tailpos = hostapd_eid_vht_operation(hapd, tailpos);
|
||||
#endif /* CONFIG_IEEE80211AC */
|
||||
|
||||
/* Wi-Fi Alliance WMM */
|
||||
tailpos = hostapd_eid_wmm(hapd, tailpos);
|
||||
|
||||
@ -430,19 +674,104 @@ void ieee802_11_set_beacon(struct hostapd_data *hapd)
|
||||
}
|
||||
#endif /* CONFIG_WPS */
|
||||
|
||||
#ifdef CONFIG_P2P
|
||||
if ((hapd->conf->p2p & P2P_ENABLED) && hapd->p2p_beacon_ie) {
|
||||
os_memcpy(tailpos, wpabuf_head(hapd->p2p_beacon_ie),
|
||||
wpabuf_len(hapd->p2p_beacon_ie));
|
||||
tailpos += wpabuf_len(hapd->p2p_beacon_ie);
|
||||
}
|
||||
#endif /* CONFIG_P2P */
|
||||
#ifdef CONFIG_P2P_MANAGER
|
||||
if ((hapd->conf->p2p & (P2P_MANAGE | P2P_ENABLED | P2P_GROUP_OWNER)) ==
|
||||
P2P_MANAGE)
|
||||
tailpos = hostapd_eid_p2p_manage(hapd, tailpos);
|
||||
#endif /* CONFIG_P2P_MANAGER */
|
||||
|
||||
#ifdef CONFIG_HS20
|
||||
tailpos = hostapd_eid_hs20_indication(hapd, tailpos);
|
||||
#endif /* CONFIG_HS20 */
|
||||
|
||||
if (hapd->conf->vendor_elements) {
|
||||
os_memcpy(tailpos, wpabuf_head(hapd->conf->vendor_elements),
|
||||
wpabuf_len(hapd->conf->vendor_elements));
|
||||
tailpos += wpabuf_len(hapd->conf->vendor_elements);
|
||||
}
|
||||
|
||||
tail_len = tailpos > tail ? tailpos - tail : 0;
|
||||
|
||||
if (hapd->drv.set_beacon(hapd, (u8 *) head, head_len,
|
||||
tail, tail_len, hapd->conf->dtim_period,
|
||||
hapd->iconf->beacon_int))
|
||||
wpa_printf(MSG_ERROR, "Failed to set beacon head/tail or DTIM "
|
||||
"period");
|
||||
resp = hostapd_probe_resp_offloads(hapd, &resp_len);
|
||||
#endif /* NEED_AP_MLME */
|
||||
|
||||
os_memset(¶ms, 0, sizeof(params));
|
||||
params.head = (u8 *) head;
|
||||
params.head_len = head_len;
|
||||
params.tail = tail;
|
||||
params.tail_len = tail_len;
|
||||
params.proberesp = resp;
|
||||
params.proberesp_len = resp_len;
|
||||
params.dtim_period = hapd->conf->dtim_period;
|
||||
params.beacon_int = hapd->iconf->beacon_int;
|
||||
params.basic_rates = hapd->iface->basic_rates;
|
||||
params.ssid = hapd->conf->ssid.ssid;
|
||||
params.ssid_len = hapd->conf->ssid.ssid_len;
|
||||
params.pairwise_ciphers = hapd->conf->rsn_pairwise ?
|
||||
hapd->conf->rsn_pairwise : hapd->conf->wpa_pairwise;
|
||||
params.group_cipher = hapd->conf->wpa_group;
|
||||
params.key_mgmt_suites = hapd->conf->wpa_key_mgmt;
|
||||
params.auth_algs = hapd->conf->auth_algs;
|
||||
params.wpa_version = hapd->conf->wpa;
|
||||
params.privacy = hapd->conf->ssid.wep.keys_set || hapd->conf->wpa ||
|
||||
(hapd->conf->ieee802_1x &&
|
||||
(hapd->conf->default_wep_key_len ||
|
||||
hapd->conf->individual_wep_key_len));
|
||||
switch (hapd->conf->ignore_broadcast_ssid) {
|
||||
case 0:
|
||||
params.hide_ssid = NO_SSID_HIDING;
|
||||
break;
|
||||
case 1:
|
||||
params.hide_ssid = HIDDEN_SSID_ZERO_LEN;
|
||||
break;
|
||||
case 2:
|
||||
params.hide_ssid = HIDDEN_SSID_ZERO_CONTENTS;
|
||||
break;
|
||||
}
|
||||
hostapd_build_ap_extra_ies(hapd, &beacon, &proberesp, &assocresp);
|
||||
params.beacon_ies = beacon;
|
||||
params.proberesp_ies = proberesp;
|
||||
params.assocresp_ies = assocresp;
|
||||
params.isolate = hapd->conf->isolate;
|
||||
#ifdef NEED_AP_MLME
|
||||
params.cts_protect = !!(ieee802_11_erp_info(hapd) &
|
||||
ERP_INFO_USE_PROTECTION);
|
||||
params.preamble = hapd->iface->num_sta_no_short_preamble == 0 &&
|
||||
hapd->iconf->preamble == SHORT_PREAMBLE;
|
||||
if (hapd->iface->current_mode &&
|
||||
hapd->iface->current_mode->mode == HOSTAPD_MODE_IEEE80211G)
|
||||
params.short_slot_time =
|
||||
hapd->iface->num_sta_no_short_slot_time > 0 ? 0 : 1;
|
||||
else
|
||||
params.short_slot_time = -1;
|
||||
if (!hapd->iconf->ieee80211n || hapd->conf->disable_11n)
|
||||
params.ht_opmode = -1;
|
||||
else
|
||||
params.ht_opmode = hapd->iface->ht_op_mode;
|
||||
#endif /* NEED_AP_MLME */
|
||||
params.interworking = hapd->conf->interworking;
|
||||
if (hapd->conf->interworking &&
|
||||
!is_zero_ether_addr(hapd->conf->hessid))
|
||||
params.hessid = hapd->conf->hessid;
|
||||
params.access_network_type = hapd->conf->access_network_type;
|
||||
params.ap_max_inactivity = hapd->conf->ap_max_inactivity;
|
||||
#ifdef CONFIG_HS20
|
||||
params.disable_dgaf = hapd->conf->disable_dgaf;
|
||||
#endif /* CONFIG_HS20 */
|
||||
if (hostapd_drv_set_ap(hapd, ¶ms))
|
||||
wpa_printf(MSG_ERROR, "Failed to set beacon parameters");
|
||||
hostapd_free_ap_extra_ies(hapd, beacon, proberesp, assocresp);
|
||||
|
||||
os_free(tail);
|
||||
os_free(head);
|
||||
|
||||
hapd->drv.set_bss_params(hapd, !!(ieee802_11_erp_info(hapd) &
|
||||
ERP_INFO_USE_PROTECTION));
|
||||
os_free(resp);
|
||||
}
|
||||
|
||||
|
||||
@ -453,4 +782,14 @@ void ieee802_11_set_beacons(struct hostapd_iface *iface)
|
||||
ieee802_11_set_beacon(iface->bss[i]);
|
||||
}
|
||||
|
||||
|
||||
/* only update beacons if started */
|
||||
void ieee802_11_update_beacons(struct hostapd_iface *iface)
|
||||
{
|
||||
size_t i;
|
||||
for (i = 0; i < iface->num_bss; i++)
|
||||
if (iface->bss[i]->beacon_set_done)
|
||||
ieee802_11_set_beacon(iface->bss[i]);
|
||||
}
|
||||
|
||||
#endif /* CONFIG_NATIVE_WINDOWS */
|
||||
|
@ -19,18 +19,10 @@
|
||||
struct ieee80211_mgmt;
|
||||
|
||||
void handle_probe_req(struct hostapd_data *hapd,
|
||||
const struct ieee80211_mgmt *mgmt, size_t len);
|
||||
#ifdef NEED_AP_MLME
|
||||
const struct ieee80211_mgmt *mgmt, size_t len,
|
||||
int ssi_signal);
|
||||
void ieee802_11_set_beacon(struct hostapd_data *hapd);
|
||||
void ieee802_11_set_beacons(struct hostapd_iface *iface);
|
||||
#else /* NEED_AP_MLME */
|
||||
static inline void ieee802_11_set_beacon(struct hostapd_data *hapd)
|
||||
{
|
||||
}
|
||||
|
||||
static inline void ieee802_11_set_beacons(struct hostapd_iface *iface)
|
||||
{
|
||||
}
|
||||
#endif /* NEED_AP_MLME */
|
||||
void ieee802_11_update_beacons(struct hostapd_iface *iface);
|
||||
|
||||
#endif /* BEACON_H */
|
||||
|
@ -2,26 +2,45 @@
|
||||
* Control interface for shared AP commands
|
||||
* Copyright (c) 2004-2009, Jouni Malinen <j@w1.fi>
|
||||
*
|
||||
* This program is free software; you can redistribute it and/or modify
|
||||
* it under the terms of the GNU General Public License version 2 as
|
||||
* published by the Free Software Foundation.
|
||||
*
|
||||
* Alternatively, this software may be distributed under the terms of BSD
|
||||
* license.
|
||||
*
|
||||
* See README and COPYING for more details.
|
||||
* This software may be distributed under the terms of the BSD license.
|
||||
* See README for more details.
|
||||
*/
|
||||
|
||||
#include "utils/includes.h"
|
||||
|
||||
#include "utils/common.h"
|
||||
#include "common/ieee802_11_defs.h"
|
||||
#include "hostapd.h"
|
||||
#include "ieee802_1x.h"
|
||||
#include "wpa_auth.h"
|
||||
#include "ieee802_11.h"
|
||||
#include "sta_info.h"
|
||||
#include "wps_hostapd.h"
|
||||
#include "p2p_hostapd.h"
|
||||
#include "ctrl_iface_ap.h"
|
||||
#include "ap_drv_ops.h"
|
||||
|
||||
|
||||
static int hostapd_get_sta_conn_time(struct sta_info *sta,
|
||||
char *buf, size_t buflen)
|
||||
{
|
||||
struct os_time now, age;
|
||||
int len = 0, ret;
|
||||
|
||||
if (!sta->connected_time.sec)
|
||||
return 0;
|
||||
|
||||
os_get_time(&now);
|
||||
os_time_sub(&now, &sta->connected_time, &age);
|
||||
|
||||
ret = os_snprintf(buf + len, buflen - len, "connected_time=%u\n",
|
||||
(unsigned int) age.sec);
|
||||
if (ret < 0 || (size_t) ret >= buflen - len)
|
||||
return len;
|
||||
len += ret;
|
||||
|
||||
return len;
|
||||
}
|
||||
|
||||
|
||||
static int hostapd_ctrl_iface_sta_mib(struct hostapd_data *hapd,
|
||||
@ -57,6 +76,13 @@ static int hostapd_ctrl_iface_sta_mib(struct hostapd_data *hapd,
|
||||
buflen - len);
|
||||
if (res >= 0)
|
||||
len += res;
|
||||
res = hostapd_p2p_get_mib_sta(hapd, sta, buf + len, buflen - len);
|
||||
if (res >= 0)
|
||||
len += res;
|
||||
|
||||
res = hostapd_get_sta_conn_time(sta, buf + len, buflen - len);
|
||||
if (res >= 0)
|
||||
len += res;
|
||||
|
||||
return len;
|
||||
}
|
||||
@ -102,3 +128,170 @@ int hostapd_ctrl_iface_sta_next(struct hostapd_data *hapd, const char *txtaddr,
|
||||
}
|
||||
return hostapd_ctrl_iface_sta_mib(hapd, sta->next, buf, buflen);
|
||||
}
|
||||
|
||||
|
||||
#ifdef CONFIG_P2P_MANAGER
|
||||
static int p2p_manager_disconnect(struct hostapd_data *hapd, u16 stype,
|
||||
u8 minor_reason_code, const u8 *addr)
|
||||
{
|
||||
struct ieee80211_mgmt *mgmt;
|
||||
int ret;
|
||||
u8 *pos;
|
||||
|
||||
if (hapd->driver->send_frame == NULL)
|
||||
return -1;
|
||||
|
||||
mgmt = os_zalloc(sizeof(*mgmt) + 100);
|
||||
if (mgmt == NULL)
|
||||
return -1;
|
||||
|
||||
wpa_dbg(hapd->msg_ctx, MSG_DEBUG, "P2P: Disconnect STA " MACSTR
|
||||
" with minor reason code %u (stype=%u)",
|
||||
MAC2STR(addr), minor_reason_code, stype);
|
||||
|
||||
mgmt->frame_control = IEEE80211_FC(WLAN_FC_TYPE_MGMT, stype);
|
||||
os_memcpy(mgmt->da, addr, ETH_ALEN);
|
||||
os_memcpy(mgmt->sa, hapd->own_addr, ETH_ALEN);
|
||||
os_memcpy(mgmt->bssid, hapd->own_addr, ETH_ALEN);
|
||||
if (stype == WLAN_FC_STYPE_DEAUTH) {
|
||||
mgmt->u.deauth.reason_code =
|
||||
host_to_le16(WLAN_REASON_PREV_AUTH_NOT_VALID);
|
||||
pos = (u8 *) (&mgmt->u.deauth.reason_code + 1);
|
||||
} else {
|
||||
mgmt->u.disassoc.reason_code =
|
||||
host_to_le16(WLAN_REASON_PREV_AUTH_NOT_VALID);
|
||||
pos = (u8 *) (&mgmt->u.disassoc.reason_code + 1);
|
||||
}
|
||||
|
||||
*pos++ = WLAN_EID_VENDOR_SPECIFIC;
|
||||
*pos++ = 4 + 3 + 1;
|
||||
WPA_PUT_BE24(pos, OUI_WFA);
|
||||
pos += 3;
|
||||
*pos++ = P2P_OUI_TYPE;
|
||||
|
||||
*pos++ = P2P_ATTR_MINOR_REASON_CODE;
|
||||
WPA_PUT_LE16(pos, 1);
|
||||
pos += 2;
|
||||
*pos++ = minor_reason_code;
|
||||
|
||||
ret = hapd->driver->send_frame(hapd->drv_priv, (u8 *) mgmt,
|
||||
pos - (u8 *) mgmt, 1);
|
||||
os_free(mgmt);
|
||||
|
||||
return ret < 0 ? -1 : 0;
|
||||
}
|
||||
#endif /* CONFIG_P2P_MANAGER */
|
||||
|
||||
|
||||
int hostapd_ctrl_iface_deauthenticate(struct hostapd_data *hapd,
|
||||
const char *txtaddr)
|
||||
{
|
||||
u8 addr[ETH_ALEN];
|
||||
struct sta_info *sta;
|
||||
const char *pos;
|
||||
|
||||
wpa_dbg(hapd->msg_ctx, MSG_DEBUG, "CTRL_IFACE DEAUTHENTICATE %s",
|
||||
txtaddr);
|
||||
|
||||
if (hwaddr_aton(txtaddr, addr))
|
||||
return -1;
|
||||
|
||||
pos = os_strstr(txtaddr, " test=");
|
||||
if (pos) {
|
||||
struct ieee80211_mgmt mgmt;
|
||||
int encrypt;
|
||||
if (hapd->driver->send_frame == NULL)
|
||||
return -1;
|
||||
pos += 6;
|
||||
encrypt = atoi(pos);
|
||||
os_memset(&mgmt, 0, sizeof(mgmt));
|
||||
mgmt.frame_control = IEEE80211_FC(WLAN_FC_TYPE_MGMT,
|
||||
WLAN_FC_STYPE_DEAUTH);
|
||||
os_memcpy(mgmt.da, addr, ETH_ALEN);
|
||||
os_memcpy(mgmt.sa, hapd->own_addr, ETH_ALEN);
|
||||
os_memcpy(mgmt.bssid, hapd->own_addr, ETH_ALEN);
|
||||
mgmt.u.deauth.reason_code =
|
||||
host_to_le16(WLAN_REASON_PREV_AUTH_NOT_VALID);
|
||||
if (hapd->driver->send_frame(hapd->drv_priv, (u8 *) &mgmt,
|
||||
IEEE80211_HDRLEN +
|
||||
sizeof(mgmt.u.deauth),
|
||||
encrypt) < 0)
|
||||
return -1;
|
||||
return 0;
|
||||
}
|
||||
|
||||
#ifdef CONFIG_P2P_MANAGER
|
||||
pos = os_strstr(txtaddr, " p2p=");
|
||||
if (pos) {
|
||||
return p2p_manager_disconnect(hapd, WLAN_FC_STYPE_DEAUTH,
|
||||
atoi(pos + 5), addr);
|
||||
}
|
||||
#endif /* CONFIG_P2P_MANAGER */
|
||||
|
||||
hostapd_drv_sta_deauth(hapd, addr, WLAN_REASON_PREV_AUTH_NOT_VALID);
|
||||
sta = ap_get_sta(hapd, addr);
|
||||
if (sta)
|
||||
ap_sta_deauthenticate(hapd, sta,
|
||||
WLAN_REASON_PREV_AUTH_NOT_VALID);
|
||||
else if (addr[0] == 0xff)
|
||||
hostapd_free_stas(hapd);
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
|
||||
int hostapd_ctrl_iface_disassociate(struct hostapd_data *hapd,
|
||||
const char *txtaddr)
|
||||
{
|
||||
u8 addr[ETH_ALEN];
|
||||
struct sta_info *sta;
|
||||
const char *pos;
|
||||
|
||||
wpa_dbg(hapd->msg_ctx, MSG_DEBUG, "CTRL_IFACE DISASSOCIATE %s",
|
||||
txtaddr);
|
||||
|
||||
if (hwaddr_aton(txtaddr, addr))
|
||||
return -1;
|
||||
|
||||
pos = os_strstr(txtaddr, " test=");
|
||||
if (pos) {
|
||||
struct ieee80211_mgmt mgmt;
|
||||
int encrypt;
|
||||
if (hapd->driver->send_frame == NULL)
|
||||
return -1;
|
||||
pos += 6;
|
||||
encrypt = atoi(pos);
|
||||
os_memset(&mgmt, 0, sizeof(mgmt));
|
||||
mgmt.frame_control = IEEE80211_FC(WLAN_FC_TYPE_MGMT,
|
||||
WLAN_FC_STYPE_DISASSOC);
|
||||
os_memcpy(mgmt.da, addr, ETH_ALEN);
|
||||
os_memcpy(mgmt.sa, hapd->own_addr, ETH_ALEN);
|
||||
os_memcpy(mgmt.bssid, hapd->own_addr, ETH_ALEN);
|
||||
mgmt.u.disassoc.reason_code =
|
||||
host_to_le16(WLAN_REASON_PREV_AUTH_NOT_VALID);
|
||||
if (hapd->driver->send_frame(hapd->drv_priv, (u8 *) &mgmt,
|
||||
IEEE80211_HDRLEN +
|
||||
sizeof(mgmt.u.deauth),
|
||||
encrypt) < 0)
|
||||
return -1;
|
||||
return 0;
|
||||
}
|
||||
|
||||
#ifdef CONFIG_P2P_MANAGER
|
||||
pos = os_strstr(txtaddr, " p2p=");
|
||||
if (pos) {
|
||||
return p2p_manager_disconnect(hapd, WLAN_FC_STYPE_DISASSOC,
|
||||
atoi(pos + 5), addr);
|
||||
}
|
||||
#endif /* CONFIG_P2P_MANAGER */
|
||||
|
||||
hostapd_drv_sta_disassoc(hapd, addr, WLAN_REASON_PREV_AUTH_NOT_VALID);
|
||||
sta = ap_get_sta(hapd, addr);
|
||||
if (sta)
|
||||
ap_sta_disassociate(hapd, sta,
|
||||
WLAN_REASON_PREV_AUTH_NOT_VALID);
|
||||
else if (addr[0] == 0xff)
|
||||
hostapd_free_stas(hapd);
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
@ -2,14 +2,8 @@
|
||||
* Control interface for shared AP commands
|
||||
* Copyright (c) 2004-2009, Jouni Malinen <j@w1.fi>
|
||||
*
|
||||
* This program is free software; you can redistribute it and/or modify
|
||||
* it under the terms of the GNU General Public License version 2 as
|
||||
* published by the Free Software Foundation.
|
||||
*
|
||||
* Alternatively, this software may be distributed under the terms of BSD
|
||||
* license.
|
||||
*
|
||||
* See README and COPYING for more details.
|
||||
* This software may be distributed under the terms of the BSD license.
|
||||
* See README for more details.
|
||||
*/
|
||||
|
||||
#ifndef CTRL_IFACE_AP_H
|
||||
@ -21,5 +15,9 @@ int hostapd_ctrl_iface_sta(struct hostapd_data *hapd, const char *txtaddr,
|
||||
char *buf, size_t buflen);
|
||||
int hostapd_ctrl_iface_sta_next(struct hostapd_data *hapd, const char *txtaddr,
|
||||
char *buf, size_t buflen);
|
||||
int hostapd_ctrl_iface_deauthenticate(struct hostapd_data *hapd,
|
||||
const char *txtaddr);
|
||||
int hostapd_ctrl_iface_disassociate(struct hostapd_data *hapd,
|
||||
const char *txtaddr);
|
||||
|
||||
#endif /* CTRL_IFACE_AP_H */
|
||||
|
@ -2,14 +2,8 @@
|
||||
* hostapd / Callback functions for driver wrappers
|
||||
* Copyright (c) 2002-2009, Jouni Malinen <j@w1.fi>
|
||||
*
|
||||
* This program is free software; you can redistribute it and/or modify
|
||||
* it under the terms of the GNU General Public License version 2 as
|
||||
* published by the Free Software Foundation.
|
||||
*
|
||||
* Alternatively, this software may be distributed under the terms of BSD
|
||||
* license.
|
||||
*
|
||||
* See README and COPYING for more details.
|
||||
* This software may be distributed under the terms of the BSD license.
|
||||
* See README for more details.
|
||||
*/
|
||||
|
||||
#include "utils/includes.h"
|
||||
@ -19,26 +13,37 @@
|
||||
#include "drivers/driver.h"
|
||||
#include "common/ieee802_11_defs.h"
|
||||
#include "common/ieee802_11_common.h"
|
||||
#include "common/wpa_ctrl.h"
|
||||
#include "crypto/random.h"
|
||||
#include "p2p/p2p.h"
|
||||
#include "wps/wps.h"
|
||||
#include "wnm_ap.h"
|
||||
#include "hostapd.h"
|
||||
#include "ieee802_11.h"
|
||||
#include "sta_info.h"
|
||||
#include "accounting.h"
|
||||
#include "tkip_countermeasures.h"
|
||||
#include "iapp.h"
|
||||
#include "ieee802_1x.h"
|
||||
#include "wpa_auth.h"
|
||||
#include "wmm.h"
|
||||
#include "wps_hostapd.h"
|
||||
#include "ap_drv_ops.h"
|
||||
#include "ap_config.h"
|
||||
#include "hw_features.h"
|
||||
|
||||
|
||||
int hostapd_notif_assoc(struct hostapd_data *hapd, const u8 *addr,
|
||||
const u8 *ie, size_t ielen)
|
||||
const u8 *req_ies, size_t req_ies_len, int reassoc)
|
||||
{
|
||||
struct sta_info *sta;
|
||||
int new_assoc, res;
|
||||
struct ieee802_11_elems elems;
|
||||
const u8 *ie;
|
||||
size_t ielen;
|
||||
#ifdef CONFIG_IEEE80211R
|
||||
u8 buf[sizeof(struct ieee80211_mgmt) + 1024];
|
||||
u8 *p = buf;
|
||||
#endif /* CONFIG_IEEE80211R */
|
||||
u16 reason = WLAN_REASON_UNSPECIFIED;
|
||||
u16 status = WLAN_STATUS_SUCCESS;
|
||||
|
||||
if (addr == NULL) {
|
||||
/*
|
||||
@ -52,11 +57,12 @@ int hostapd_notif_assoc(struct hostapd_data *hapd, const u8 *addr,
|
||||
"no address");
|
||||
return -1;
|
||||
}
|
||||
random_add_randomness(addr, ETH_ALEN);
|
||||
|
||||
hostapd_logger(hapd, addr, HOSTAPD_MODULE_IEEE80211,
|
||||
HOSTAPD_LEVEL_INFO, "associated");
|
||||
|
||||
ieee802_11_parse_elems(ie, ielen, &elems, 0);
|
||||
ieee802_11_parse_elems(req_ies, req_ies_len, &elems, 0);
|
||||
if (elems.wps_ie) {
|
||||
ie = elems.wps_ie - 2;
|
||||
ielen = elems.wps_ie_len + 2;
|
||||
@ -79,15 +85,42 @@ int hostapd_notif_assoc(struct hostapd_data *hapd, const u8 *addr,
|
||||
sta = ap_get_sta(hapd, addr);
|
||||
if (sta) {
|
||||
accounting_sta_stop(hapd, sta);
|
||||
|
||||
/*
|
||||
* Make sure that the previously registered inactivity timer
|
||||
* will not remove the STA immediately.
|
||||
*/
|
||||
sta->timeout_next = STA_NULLFUNC;
|
||||
} else {
|
||||
sta = ap_sta_add(hapd, addr);
|
||||
if (sta == NULL)
|
||||
if (sta == NULL) {
|
||||
hostapd_drv_sta_disassoc(hapd, addr,
|
||||
WLAN_REASON_DISASSOC_AP_BUSY);
|
||||
return -1;
|
||||
}
|
||||
}
|
||||
sta->flags &= ~(WLAN_STA_WPS | WLAN_STA_MAYBE_WPS);
|
||||
sta->flags &= ~(WLAN_STA_WPS | WLAN_STA_MAYBE_WPS | WLAN_STA_WPS2);
|
||||
|
||||
#ifdef CONFIG_P2P
|
||||
if (elems.p2p) {
|
||||
wpabuf_free(sta->p2p_ie);
|
||||
sta->p2p_ie = ieee802_11_vendor_ie_concat(req_ies, req_ies_len,
|
||||
P2P_IE_VENDOR_TYPE);
|
||||
}
|
||||
#endif /* CONFIG_P2P */
|
||||
|
||||
#ifdef CONFIG_HS20
|
||||
wpabuf_free(sta->hs20_ie);
|
||||
if (elems.hs20 && elems.hs20_len > 4) {
|
||||
sta->hs20_ie = wpabuf_alloc_copy(elems.hs20 + 4,
|
||||
elems.hs20_len - 4);
|
||||
} else
|
||||
sta->hs20_ie = NULL;
|
||||
#endif /* CONFIG_HS20 */
|
||||
|
||||
if (hapd->conf->wpa) {
|
||||
if (ie == NULL || ielen == 0) {
|
||||
#ifdef CONFIG_WPS
|
||||
if (hapd->conf->wps_state) {
|
||||
wpa_printf(MSG_DEBUG, "STA did not include "
|
||||
"WPA/RSN IE in (Re)Association "
|
||||
@ -95,15 +128,29 @@ int hostapd_notif_assoc(struct hostapd_data *hapd, const u8 *addr,
|
||||
sta->flags |= WLAN_STA_MAYBE_WPS;
|
||||
goto skip_wpa_check;
|
||||
}
|
||||
#endif /* CONFIG_WPS */
|
||||
|
||||
wpa_printf(MSG_DEBUG, "No WPA/RSN IE from STA");
|
||||
return -1;
|
||||
}
|
||||
#ifdef CONFIG_WPS
|
||||
if (hapd->conf->wps_state && ie[0] == 0xdd && ie[1] >= 4 &&
|
||||
os_memcmp(ie + 2, "\x00\x50\xf2\x04", 4) == 0) {
|
||||
struct wpabuf *wps;
|
||||
sta->flags |= WLAN_STA_WPS;
|
||||
wps = ieee802_11_vendor_ie_concat(ie, ielen,
|
||||
WPS_IE_VENDOR_TYPE);
|
||||
if (wps) {
|
||||
if (wps_is_20(wps)) {
|
||||
wpa_printf(MSG_DEBUG, "WPS: STA "
|
||||
"supports WPS 2.0");
|
||||
sta->flags |= WLAN_STA_WPS2;
|
||||
}
|
||||
wpabuf_free(wps);
|
||||
}
|
||||
goto skip_wpa_check;
|
||||
}
|
||||
#endif /* CONFIG_WPS */
|
||||
|
||||
if (sta->wpa_sm == NULL)
|
||||
sta->wpa_sm = wpa_auth_sta_init(hapd->wpa_auth,
|
||||
@ -114,48 +161,156 @@ int hostapd_notif_assoc(struct hostapd_data *hapd, const u8 *addr,
|
||||
return -1;
|
||||
}
|
||||
res = wpa_validate_wpa_ie(hapd->wpa_auth, sta->wpa_sm,
|
||||
ie, ielen, NULL, 0);
|
||||
ie, ielen,
|
||||
elems.mdie, elems.mdie_len);
|
||||
if (res != WPA_IE_OK) {
|
||||
int resp;
|
||||
wpa_printf(MSG_DEBUG, "WPA/RSN information element "
|
||||
"rejected? (res %u)", res);
|
||||
wpa_hexdump(MSG_DEBUG, "IE", ie, ielen);
|
||||
if (res == WPA_INVALID_GROUP)
|
||||
resp = WLAN_REASON_GROUP_CIPHER_NOT_VALID;
|
||||
else if (res == WPA_INVALID_PAIRWISE)
|
||||
resp = WLAN_REASON_PAIRWISE_CIPHER_NOT_VALID;
|
||||
else if (res == WPA_INVALID_AKMP)
|
||||
resp = WLAN_REASON_AKMP_NOT_VALID;
|
||||
if (res == WPA_INVALID_GROUP) {
|
||||
reason = WLAN_REASON_GROUP_CIPHER_NOT_VALID;
|
||||
status = WLAN_STATUS_GROUP_CIPHER_NOT_VALID;
|
||||
} else if (res == WPA_INVALID_PAIRWISE) {
|
||||
reason = WLAN_REASON_PAIRWISE_CIPHER_NOT_VALID;
|
||||
status = WLAN_STATUS_PAIRWISE_CIPHER_NOT_VALID;
|
||||
} else if (res == WPA_INVALID_AKMP) {
|
||||
reason = WLAN_REASON_AKMP_NOT_VALID;
|
||||
status = WLAN_STATUS_AKMP_NOT_VALID;
|
||||
}
|
||||
#ifdef CONFIG_IEEE80211W
|
||||
else if (res == WPA_MGMT_FRAME_PROTECTION_VIOLATION)
|
||||
resp = WLAN_REASON_INVALID_IE;
|
||||
else if (res == WPA_INVALID_MGMT_GROUP_CIPHER)
|
||||
resp = WLAN_REASON_GROUP_CIPHER_NOT_VALID;
|
||||
else if (res == WPA_MGMT_FRAME_PROTECTION_VIOLATION) {
|
||||
reason = WLAN_REASON_INVALID_IE;
|
||||
status = WLAN_STATUS_INVALID_IE;
|
||||
} else if (res == WPA_INVALID_MGMT_GROUP_CIPHER) {
|
||||
reason = WLAN_REASON_GROUP_CIPHER_NOT_VALID;
|
||||
status = WLAN_STATUS_GROUP_CIPHER_NOT_VALID;
|
||||
}
|
||||
#endif /* CONFIG_IEEE80211W */
|
||||
else
|
||||
resp = WLAN_REASON_INVALID_IE;
|
||||
hapd->drv.sta_disassoc(hapd, sta->addr, resp);
|
||||
ap_free_sta(hapd, sta);
|
||||
return -1;
|
||||
else {
|
||||
reason = WLAN_REASON_INVALID_IE;
|
||||
status = WLAN_STATUS_INVALID_IE;
|
||||
}
|
||||
goto fail;
|
||||
}
|
||||
#ifdef CONFIG_IEEE80211W
|
||||
if ((sta->flags & WLAN_STA_MFP) && !sta->sa_query_timed_out &&
|
||||
sta->sa_query_count > 0)
|
||||
ap_check_sa_query_timeout(hapd, sta);
|
||||
if ((sta->flags & WLAN_STA_MFP) && !sta->sa_query_timed_out &&
|
||||
(sta->auth_alg != WLAN_AUTH_FT)) {
|
||||
/*
|
||||
* STA has already been associated with MFP and SA
|
||||
* Query timeout has not been reached. Reject the
|
||||
* association attempt temporarily and start SA Query,
|
||||
* if one is not pending.
|
||||
*/
|
||||
|
||||
if (sta->sa_query_count == 0)
|
||||
ap_sta_start_sa_query(hapd, sta);
|
||||
|
||||
#ifdef CONFIG_IEEE80211R
|
||||
status = WLAN_STATUS_ASSOC_REJECTED_TEMPORARILY;
|
||||
|
||||
p = hostapd_eid_assoc_comeback_time(hapd, sta, p);
|
||||
|
||||
hostapd_sta_assoc(hapd, addr, reassoc, status, buf,
|
||||
p - buf);
|
||||
#endif /* CONFIG_IEEE80211R */
|
||||
return 0;
|
||||
}
|
||||
|
||||
if (wpa_auth_uses_mfp(sta->wpa_sm))
|
||||
sta->flags |= WLAN_STA_MFP;
|
||||
else
|
||||
sta->flags &= ~WLAN_STA_MFP;
|
||||
#endif /* CONFIG_IEEE80211W */
|
||||
|
||||
#ifdef CONFIG_IEEE80211R
|
||||
if (sta->auth_alg == WLAN_AUTH_FT) {
|
||||
status = wpa_ft_validate_reassoc(sta->wpa_sm, req_ies,
|
||||
req_ies_len);
|
||||
if (status != WLAN_STATUS_SUCCESS) {
|
||||
if (status == WLAN_STATUS_INVALID_PMKID)
|
||||
reason = WLAN_REASON_INVALID_IE;
|
||||
if (status == WLAN_STATUS_INVALID_MDIE)
|
||||
reason = WLAN_REASON_INVALID_IE;
|
||||
if (status == WLAN_STATUS_INVALID_FTIE)
|
||||
reason = WLAN_REASON_INVALID_IE;
|
||||
goto fail;
|
||||
}
|
||||
}
|
||||
#endif /* CONFIG_IEEE80211R */
|
||||
} else if (hapd->conf->wps_state) {
|
||||
if (ie && ielen > 4 && ie[0] == 0xdd && ie[1] >= 4 &&
|
||||
os_memcmp(ie + 2, "\x00\x50\xf2\x04", 4) == 0) {
|
||||
#ifdef CONFIG_WPS
|
||||
struct wpabuf *wps;
|
||||
if (req_ies)
|
||||
wps = ieee802_11_vendor_ie_concat(req_ies, req_ies_len,
|
||||
WPS_IE_VENDOR_TYPE);
|
||||
else
|
||||
wps = NULL;
|
||||
#ifdef CONFIG_WPS_STRICT
|
||||
if (wps && wps_validate_assoc_req(wps) < 0) {
|
||||
reason = WLAN_REASON_INVALID_IE;
|
||||
status = WLAN_STATUS_INVALID_IE;
|
||||
wpabuf_free(wps);
|
||||
goto fail;
|
||||
}
|
||||
#endif /* CONFIG_WPS_STRICT */
|
||||
if (wps) {
|
||||
sta->flags |= WLAN_STA_WPS;
|
||||
if (wps_is_20(wps)) {
|
||||
wpa_printf(MSG_DEBUG, "WPS: STA supports "
|
||||
"WPS 2.0");
|
||||
sta->flags |= WLAN_STA_WPS2;
|
||||
}
|
||||
} else
|
||||
sta->flags |= WLAN_STA_MAYBE_WPS;
|
||||
wpabuf_free(wps);
|
||||
#endif /* CONFIG_WPS */
|
||||
}
|
||||
#ifdef CONFIG_WPS
|
||||
skip_wpa_check:
|
||||
#endif /* CONFIG_WPS */
|
||||
|
||||
#ifdef CONFIG_IEEE80211R
|
||||
p = wpa_sm_write_assoc_resp_ies(sta->wpa_sm, buf, sizeof(buf),
|
||||
sta->auth_alg, req_ies, req_ies_len);
|
||||
|
||||
hostapd_sta_assoc(hapd, addr, reassoc, status, buf, p - buf);
|
||||
#else /* CONFIG_IEEE80211R */
|
||||
/* Keep compiler silent about unused variables */
|
||||
if (status) {
|
||||
}
|
||||
#endif /* CONFIG_IEEE80211R */
|
||||
|
||||
new_assoc = (sta->flags & WLAN_STA_ASSOC) == 0;
|
||||
sta->flags |= WLAN_STA_AUTH | WLAN_STA_ASSOC;
|
||||
wpa_auth_sm_event(sta->wpa_sm, WPA_ASSOC);
|
||||
|
||||
if (reassoc && (sta->auth_alg == WLAN_AUTH_FT))
|
||||
wpa_auth_sm_event(sta->wpa_sm, WPA_ASSOC_FT);
|
||||
else
|
||||
wpa_auth_sm_event(sta->wpa_sm, WPA_ASSOC);
|
||||
|
||||
hostapd_new_assoc_sta(hapd, sta, !new_assoc);
|
||||
|
||||
ieee802_1x_notify_port_enabled(sta->eapol_sm, 1);
|
||||
|
||||
#ifdef CONFIG_P2P
|
||||
if (req_ies) {
|
||||
p2p_group_notif_assoc(hapd->p2p_group, sta->addr,
|
||||
req_ies, req_ies_len);
|
||||
}
|
||||
#endif /* CONFIG_P2P */
|
||||
|
||||
return 0;
|
||||
|
||||
fail:
|
||||
#ifdef CONFIG_IEEE80211R
|
||||
hostapd_sta_assoc(hapd, addr, reassoc, status, buf, p - buf);
|
||||
#endif /* CONFIG_IEEE80211R */
|
||||
hostapd_drv_sta_disassoc(hapd, sta->addr, reason);
|
||||
ap_free_sta(hapd, sta);
|
||||
return -1;
|
||||
}
|
||||
|
||||
|
||||
@ -163,6 +318,19 @@ void hostapd_notif_disassoc(struct hostapd_data *hapd, const u8 *addr)
|
||||
{
|
||||
struct sta_info *sta;
|
||||
|
||||
if (addr == NULL) {
|
||||
/*
|
||||
* This could potentially happen with unexpected event from the
|
||||
* driver wrapper. This was seen at least in one case where the
|
||||
* driver ended up reporting a station mode event while hostapd
|
||||
* was running, so better make sure we stop processing such an
|
||||
* event here.
|
||||
*/
|
||||
wpa_printf(MSG_DEBUG, "hostapd_notif_disassoc: Skip event "
|
||||
"with no address");
|
||||
return;
|
||||
}
|
||||
|
||||
hostapd_logger(hapd, addr, HOSTAPD_MODULE_IEEE80211,
|
||||
HOSTAPD_LEVEL_INFO, "disassociated");
|
||||
|
||||
@ -173,9 +341,8 @@ void hostapd_notif_disassoc(struct hostapd_data *hapd, const u8 *addr)
|
||||
return;
|
||||
}
|
||||
|
||||
ap_sta_set_authorized(hapd, sta, 0);
|
||||
sta->flags &= ~(WLAN_STA_AUTH | WLAN_STA_ASSOC);
|
||||
wpa_msg(hapd->msg_ctx, MSG_INFO, AP_STA_DISCONNECTED MACSTR,
|
||||
MAC2STR(sta->addr));
|
||||
wpa_auth_sm_event(sta->wpa_sm, WPA_DISASSOC);
|
||||
sta->acct_terminate_cause = RADIUS_ACCT_TERMINATE_CAUSE_USER_REQUEST;
|
||||
ieee802_1x_notify_port_enabled(sta->eapol_sm, 0);
|
||||
@ -183,50 +350,180 @@ void hostapd_notif_disassoc(struct hostapd_data *hapd, const u8 *addr)
|
||||
}
|
||||
|
||||
|
||||
#ifdef HOSTAPD
|
||||
|
||||
#ifdef NEED_AP_MLME
|
||||
|
||||
static const u8 * get_hdr_bssid(const struct ieee80211_hdr *hdr, size_t len)
|
||||
void hostapd_event_sta_low_ack(struct hostapd_data *hapd, const u8 *addr)
|
||||
{
|
||||
u16 fc, type, stype;
|
||||
struct sta_info *sta = ap_get_sta(hapd, addr);
|
||||
|
||||
/*
|
||||
* PS-Poll frames are 16 bytes. All other frames are
|
||||
* 24 bytes or longer.
|
||||
*/
|
||||
if (len < 16)
|
||||
return NULL;
|
||||
if (!sta || !hapd->conf->disassoc_low_ack)
|
||||
return;
|
||||
|
||||
fc = le_to_host16(hdr->frame_control);
|
||||
type = WLAN_FC_GET_TYPE(fc);
|
||||
stype = WLAN_FC_GET_STYPE(fc);
|
||||
|
||||
switch (type) {
|
||||
case WLAN_FC_TYPE_DATA:
|
||||
if (len < 24)
|
||||
return NULL;
|
||||
switch (fc & (WLAN_FC_FROMDS | WLAN_FC_TODS)) {
|
||||
case WLAN_FC_FROMDS | WLAN_FC_TODS:
|
||||
case WLAN_FC_TODS:
|
||||
return hdr->addr1;
|
||||
case WLAN_FC_FROMDS:
|
||||
return hdr->addr2;
|
||||
default:
|
||||
return NULL;
|
||||
}
|
||||
case WLAN_FC_TYPE_CTRL:
|
||||
if (stype != WLAN_FC_STYPE_PSPOLL)
|
||||
return NULL;
|
||||
return hdr->addr1;
|
||||
case WLAN_FC_TYPE_MGMT:
|
||||
return hdr->addr3;
|
||||
default:
|
||||
return NULL;
|
||||
}
|
||||
hostapd_logger(hapd, addr, HOSTAPD_MODULE_IEEE80211,
|
||||
HOSTAPD_LEVEL_INFO, "disconnected due to excessive "
|
||||
"missing ACKs");
|
||||
hostapd_drv_sta_disassoc(hapd, addr, WLAN_REASON_DISASSOC_LOW_ACK);
|
||||
if (sta)
|
||||
ap_sta_disassociate(hapd, sta, WLAN_REASON_DISASSOC_LOW_ACK);
|
||||
}
|
||||
|
||||
|
||||
void hostapd_event_ch_switch(struct hostapd_data *hapd, int freq, int ht,
|
||||
int offset)
|
||||
{
|
||||
#ifdef NEED_AP_MLME
|
||||
int channel;
|
||||
|
||||
hostapd_logger(hapd, NULL, HOSTAPD_MODULE_IEEE80211,
|
||||
HOSTAPD_LEVEL_INFO, "driver had channel switch: "
|
||||
"freq=%d, ht=%d, offset=%d", freq, ht, offset);
|
||||
|
||||
hapd->iface->freq = freq;
|
||||
|
||||
channel = hostapd_hw_get_channel(hapd, freq);
|
||||
if (!channel) {
|
||||
hostapd_logger(hapd, NULL, HOSTAPD_MODULE_IEEE80211,
|
||||
HOSTAPD_LEVEL_WARNING, "driver switched to "
|
||||
"bad channel!");
|
||||
return;
|
||||
}
|
||||
|
||||
hapd->iconf->channel = channel;
|
||||
hapd->iconf->ieee80211n = ht;
|
||||
hapd->iconf->secondary_channel = offset;
|
||||
#endif /* NEED_AP_MLME */
|
||||
}
|
||||
|
||||
|
||||
int hostapd_probe_req_rx(struct hostapd_data *hapd, const u8 *sa, const u8 *da,
|
||||
const u8 *bssid, const u8 *ie, size_t ie_len,
|
||||
int ssi_signal)
|
||||
{
|
||||
size_t i;
|
||||
int ret = 0;
|
||||
|
||||
if (sa == NULL || ie == NULL)
|
||||
return -1;
|
||||
|
||||
random_add_randomness(sa, ETH_ALEN);
|
||||
for (i = 0; hapd->probereq_cb && i < hapd->num_probereq_cb; i++) {
|
||||
if (hapd->probereq_cb[i].cb(hapd->probereq_cb[i].ctx,
|
||||
sa, da, bssid, ie, ie_len,
|
||||
ssi_signal) > 0) {
|
||||
ret = 1;
|
||||
break;
|
||||
}
|
||||
}
|
||||
return ret;
|
||||
}
|
||||
|
||||
|
||||
#ifdef HOSTAPD
|
||||
|
||||
#ifdef CONFIG_IEEE80211R
|
||||
static void hostapd_notify_auth_ft_finish(void *ctx, const u8 *dst,
|
||||
const u8 *bssid,
|
||||
u16 auth_transaction, u16 status,
|
||||
const u8 *ies, size_t ies_len)
|
||||
{
|
||||
struct hostapd_data *hapd = ctx;
|
||||
struct sta_info *sta;
|
||||
|
||||
sta = ap_get_sta(hapd, dst);
|
||||
if (sta == NULL)
|
||||
return;
|
||||
|
||||
hostapd_logger(hapd, dst, HOSTAPD_MODULE_IEEE80211,
|
||||
HOSTAPD_LEVEL_DEBUG, "authentication OK (FT)");
|
||||
sta->flags |= WLAN_STA_AUTH;
|
||||
|
||||
hostapd_sta_auth(hapd, dst, auth_transaction, status, ies, ies_len);
|
||||
}
|
||||
#endif /* CONFIG_IEEE80211R */
|
||||
|
||||
|
||||
static void hostapd_notif_auth(struct hostapd_data *hapd,
|
||||
struct auth_info *rx_auth)
|
||||
{
|
||||
struct sta_info *sta;
|
||||
u16 status = WLAN_STATUS_SUCCESS;
|
||||
u8 resp_ies[2 + WLAN_AUTH_CHALLENGE_LEN];
|
||||
size_t resp_ies_len = 0;
|
||||
|
||||
sta = ap_get_sta(hapd, rx_auth->peer);
|
||||
if (!sta) {
|
||||
sta = ap_sta_add(hapd, rx_auth->peer);
|
||||
if (sta == NULL) {
|
||||
status = WLAN_STATUS_UNSPECIFIED_FAILURE;
|
||||
goto fail;
|
||||
}
|
||||
}
|
||||
sta->flags &= ~WLAN_STA_PREAUTH;
|
||||
ieee802_1x_notify_pre_auth(sta->eapol_sm, 0);
|
||||
#ifdef CONFIG_IEEE80211R
|
||||
if (rx_auth->auth_type == WLAN_AUTH_FT && hapd->wpa_auth) {
|
||||
sta->auth_alg = WLAN_AUTH_FT;
|
||||
if (sta->wpa_sm == NULL)
|
||||
sta->wpa_sm = wpa_auth_sta_init(hapd->wpa_auth,
|
||||
sta->addr);
|
||||
if (sta->wpa_sm == NULL) {
|
||||
wpa_printf(MSG_DEBUG, "FT: Failed to initialize WPA "
|
||||
"state machine");
|
||||
status = WLAN_STATUS_UNSPECIFIED_FAILURE;
|
||||
goto fail;
|
||||
}
|
||||
wpa_ft_process_auth(sta->wpa_sm, rx_auth->bssid,
|
||||
rx_auth->auth_transaction, rx_auth->ies,
|
||||
rx_auth->ies_len,
|
||||
hostapd_notify_auth_ft_finish, hapd);
|
||||
return;
|
||||
}
|
||||
#endif /* CONFIG_IEEE80211R */
|
||||
fail:
|
||||
hostapd_sta_auth(hapd, rx_auth->peer, rx_auth->auth_transaction + 1,
|
||||
status, resp_ies, resp_ies_len);
|
||||
}
|
||||
|
||||
|
||||
static void hostapd_action_rx(struct hostapd_data *hapd,
|
||||
struct rx_action *action)
|
||||
{
|
||||
struct sta_info *sta;
|
||||
|
||||
wpa_printf(MSG_DEBUG, "RX_ACTION cat %d action plen %d",
|
||||
action->category, (int) action->len);
|
||||
|
||||
sta = ap_get_sta(hapd, action->sa);
|
||||
if (sta == NULL) {
|
||||
wpa_printf(MSG_DEBUG, "%s: station not found", __func__);
|
||||
return;
|
||||
}
|
||||
#ifdef CONFIG_IEEE80211R
|
||||
if (action->category == WLAN_ACTION_FT) {
|
||||
wpa_printf(MSG_DEBUG, "%s: FT_ACTION length %d",
|
||||
__func__, (int) action->len);
|
||||
wpa_ft_action_rx(sta->wpa_sm, action->data, action->len);
|
||||
}
|
||||
#endif /* CONFIG_IEEE80211R */
|
||||
#ifdef CONFIG_IEEE80211W
|
||||
if (action->category == WLAN_ACTION_SA_QUERY && action->len >= 4) {
|
||||
wpa_printf(MSG_DEBUG, "%s: SA_QUERY_ACTION length %d",
|
||||
__func__, (int) action->len);
|
||||
ieee802_11_sa_query_action(hapd, action->sa,
|
||||
*(action->data + 1),
|
||||
action->data + 2);
|
||||
}
|
||||
#endif /* CONFIG_IEEE80211W */
|
||||
#ifdef CONFIG_WNM
|
||||
if (action->category == WLAN_ACTION_WNM) {
|
||||
wpa_printf(MSG_DEBUG, "%s: WNM_ACTION length %d",
|
||||
__func__, (int) action->len);
|
||||
ieee802_11_rx_wnm_action_ap(hapd, action);
|
||||
}
|
||||
#endif /* CONFIG_WNM */
|
||||
}
|
||||
|
||||
|
||||
#ifdef NEED_AP_MLME
|
||||
|
||||
#define HAPD_BROADCAST ((struct hostapd_data *) -1)
|
||||
|
||||
static struct hostapd_data * get_hapd_bssid(struct hostapd_iface *iface,
|
||||
@ -250,17 +547,14 @@ static struct hostapd_data * get_hapd_bssid(struct hostapd_iface *iface,
|
||||
|
||||
|
||||
static void hostapd_rx_from_unknown_sta(struct hostapd_data *hapd,
|
||||
const u8 *frame, size_t len)
|
||||
const u8 *bssid, const u8 *addr,
|
||||
int wds)
|
||||
{
|
||||
const struct ieee80211_hdr *hdr = (const struct ieee80211_hdr *) frame;
|
||||
u16 fc = le_to_host16(hdr->frame_control);
|
||||
hapd = get_hapd_bssid(hapd->iface, get_hdr_bssid(hdr, len));
|
||||
hapd = get_hapd_bssid(hapd->iface, bssid);
|
||||
if (hapd == NULL || hapd == HAPD_BROADCAST)
|
||||
return;
|
||||
|
||||
ieee802_11_rx_from_unknown(hapd, hdr->addr2,
|
||||
(fc & (WLAN_FC_TODS | WLAN_FC_FROMDS)) ==
|
||||
(WLAN_FC_TODS | WLAN_FC_FROMDS));
|
||||
ieee802_11_rx_from_unknown(hapd, addr, wds);
|
||||
}
|
||||
|
||||
|
||||
@ -303,6 +597,48 @@ static void hostapd_mgmt_rx(struct hostapd_data *hapd, struct rx_mgmt *rx_mgmt)
|
||||
rx_mgmt->frame_len, &fi);
|
||||
} else
|
||||
ieee802_11_mgmt(hapd, rx_mgmt->frame, rx_mgmt->frame_len, &fi);
|
||||
|
||||
random_add_randomness(&fi, sizeof(fi));
|
||||
}
|
||||
|
||||
|
||||
static void hostapd_rx_action(struct hostapd_data *hapd,
|
||||
struct rx_action *rx_action)
|
||||
{
|
||||
struct rx_mgmt rx_mgmt;
|
||||
u8 *buf;
|
||||
struct ieee80211_hdr *hdr;
|
||||
|
||||
wpa_printf(MSG_DEBUG, "EVENT_RX_ACTION DA=" MACSTR " SA=" MACSTR
|
||||
" BSSID=" MACSTR " category=%u",
|
||||
MAC2STR(rx_action->da), MAC2STR(rx_action->sa),
|
||||
MAC2STR(rx_action->bssid), rx_action->category);
|
||||
wpa_hexdump(MSG_MSGDUMP, "Received action frame contents",
|
||||
rx_action->data, rx_action->len);
|
||||
|
||||
buf = os_zalloc(24 + 1 + rx_action->len);
|
||||
if (buf == NULL)
|
||||
return;
|
||||
hdr = (struct ieee80211_hdr *) buf;
|
||||
hdr->frame_control = IEEE80211_FC(WLAN_FC_TYPE_MGMT,
|
||||
WLAN_FC_STYPE_ACTION);
|
||||
if (rx_action->category == WLAN_ACTION_SA_QUERY) {
|
||||
/*
|
||||
* Assume frame was protected; it would have been dropped if
|
||||
* not.
|
||||
*/
|
||||
hdr->frame_control |= host_to_le16(WLAN_FC_ISWEP);
|
||||
}
|
||||
os_memcpy(hdr->addr1, rx_action->da, ETH_ALEN);
|
||||
os_memcpy(hdr->addr2, rx_action->sa, ETH_ALEN);
|
||||
os_memcpy(hdr->addr3, rx_action->bssid, ETH_ALEN);
|
||||
buf[24] = rx_action->category;
|
||||
os_memcpy(buf + 24 + 1, rx_action->data, rx_action->len);
|
||||
os_memset(&rx_mgmt, 0, sizeof(rx_mgmt));
|
||||
rx_mgmt.frame = buf;
|
||||
rx_mgmt.frame_len = 24 + 1 + rx_action->len;
|
||||
hostapd_mgmt_rx(hapd, &rx_mgmt);
|
||||
os_free(buf);
|
||||
}
|
||||
|
||||
|
||||
@ -320,23 +656,6 @@ static void hostapd_mgmt_tx_cb(struct hostapd_data *hapd, const u8 *buf,
|
||||
#endif /* NEED_AP_MLME */
|
||||
|
||||
|
||||
static int hostapd_probe_req_rx(struct hostapd_data *hapd, const u8 *sa,
|
||||
const u8 *ie, size_t ie_len)
|
||||
{
|
||||
size_t i;
|
||||
int ret = 0;
|
||||
|
||||
for (i = 0; hapd->probereq_cb && i < hapd->num_probereq_cb; i++) {
|
||||
if (hapd->probereq_cb[i].cb(hapd->probereq_cb[i].ctx,
|
||||
sa, ie, ie_len) > 0) {
|
||||
ret = 1;
|
||||
break;
|
||||
}
|
||||
}
|
||||
return ret;
|
||||
}
|
||||
|
||||
|
||||
static int hostapd_event_new_sta(struct hostapd_data *hapd, const u8 *addr)
|
||||
{
|
||||
struct sta_info *sta = ap_get_sta(hapd, addr);
|
||||
@ -362,12 +681,15 @@ static void hostapd_event_eapol_rx(struct hostapd_data *hapd, const u8 *src,
|
||||
const u8 *data, size_t data_len)
|
||||
{
|
||||
struct hostapd_iface *iface = hapd->iface;
|
||||
struct sta_info *sta;
|
||||
size_t j;
|
||||
|
||||
for (j = 0; j < iface->num_bss; j++) {
|
||||
if (ap_get_sta(iface->bss[j], src)) {
|
||||
hapd = iface->bss[j];
|
||||
break;
|
||||
if ((sta = ap_get_sta(iface->bss[j], src))) {
|
||||
if (sta->flags & WLAN_STA_ASSOC) {
|
||||
hapd = iface->bss[j];
|
||||
break;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@ -379,6 +701,23 @@ void wpa_supplicant_event(void *ctx, enum wpa_event_type event,
|
||||
union wpa_event_data *data)
|
||||
{
|
||||
struct hostapd_data *hapd = ctx;
|
||||
#ifndef CONFIG_NO_STDOUT_DEBUG
|
||||
int level = MSG_DEBUG;
|
||||
|
||||
if (event == EVENT_RX_MGMT && data->rx_mgmt.frame &&
|
||||
data->rx_mgmt.frame_len >= 24) {
|
||||
const struct ieee80211_hdr *hdr;
|
||||
u16 fc;
|
||||
hdr = (const struct ieee80211_hdr *) data->rx_mgmt.frame;
|
||||
fc = le_to_host16(hdr->frame_control);
|
||||
if (WLAN_FC_GET_TYPE(fc) == WLAN_FC_TYPE_MGMT &&
|
||||
WLAN_FC_GET_STYPE(fc) == WLAN_FC_STYPE_BEACON)
|
||||
level = MSG_EXCESSIVE;
|
||||
}
|
||||
|
||||
wpa_dbg(hapd->msg_ctx, level, "Event %s (%d) received",
|
||||
event_to_string(event), event);
|
||||
#endif /* CONFIG_NO_STDOUT_DEBUG */
|
||||
|
||||
switch (event) {
|
||||
case EVENT_MICHAEL_MIC_FAILURE:
|
||||
@ -395,7 +734,7 @@ void wpa_supplicant_event(void *ctx, enum wpa_event_type event,
|
||||
break;
|
||||
#endif /* CONFIG_IEEE80211R */
|
||||
case EVENT_WPS_BUTTON_PUSHED:
|
||||
hostapd_wps_button_pushed(hapd);
|
||||
hostapd_wps_button_pushed(hapd, NULL);
|
||||
break;
|
||||
#ifdef NEED_AP_MLME
|
||||
case EVENT_TX_STATUS:
|
||||
@ -414,18 +753,34 @@ void wpa_supplicant_event(void *ctx, enum wpa_event_type event,
|
||||
break;
|
||||
}
|
||||
break;
|
||||
case EVENT_EAPOL_TX_STATUS:
|
||||
hostapd_eapol_tx_status(hapd, data->eapol_tx_status.dst,
|
||||
data->eapol_tx_status.data,
|
||||
data->eapol_tx_status.data_len,
|
||||
data->eapol_tx_status.ack);
|
||||
break;
|
||||
case EVENT_DRIVER_CLIENT_POLL_OK:
|
||||
hostapd_client_poll_ok(hapd, data->client_poll.addr);
|
||||
break;
|
||||
case EVENT_RX_FROM_UNKNOWN:
|
||||
hostapd_rx_from_unknown_sta(hapd, data->rx_from_unknown.frame,
|
||||
data->rx_from_unknown.len);
|
||||
hostapd_rx_from_unknown_sta(hapd, data->rx_from_unknown.bssid,
|
||||
data->rx_from_unknown.addr,
|
||||
data->rx_from_unknown.wds);
|
||||
break;
|
||||
case EVENT_RX_MGMT:
|
||||
hostapd_mgmt_rx(hapd, &data->rx_mgmt);
|
||||
break;
|
||||
#endif /* NEED_AP_MLME */
|
||||
case EVENT_RX_PROBE_REQ:
|
||||
if (data->rx_probe_req.sa == NULL ||
|
||||
data->rx_probe_req.ie == NULL)
|
||||
break;
|
||||
hostapd_probe_req_rx(hapd, data->rx_probe_req.sa,
|
||||
data->rx_probe_req.da,
|
||||
data->rx_probe_req.bssid,
|
||||
data->rx_probe_req.ie,
|
||||
data->rx_probe_req.ie_len);
|
||||
data->rx_probe_req.ie_len,
|
||||
data->rx_probe_req.ssi_signal);
|
||||
break;
|
||||
case EVENT_NEW_STA:
|
||||
hostapd_event_new_sta(hapd, data->new_sta.addr);
|
||||
@ -438,7 +793,8 @@ void wpa_supplicant_event(void *ctx, enum wpa_event_type event,
|
||||
case EVENT_ASSOC:
|
||||
hostapd_notif_assoc(hapd, data->assoc_info.addr,
|
||||
data->assoc_info.req_ies,
|
||||
data->assoc_info.req_ies_len);
|
||||
data->assoc_info.req_ies_len,
|
||||
data->assoc_info.reassoc);
|
||||
break;
|
||||
case EVENT_DISASSOC:
|
||||
if (data)
|
||||
@ -448,6 +804,30 @@ void wpa_supplicant_event(void *ctx, enum wpa_event_type event,
|
||||
if (data)
|
||||
hostapd_notif_disassoc(hapd, data->deauth_info.addr);
|
||||
break;
|
||||
case EVENT_STATION_LOW_ACK:
|
||||
if (!data)
|
||||
break;
|
||||
hostapd_event_sta_low_ack(hapd, data->low_ack.addr);
|
||||
break;
|
||||
case EVENT_RX_ACTION:
|
||||
if (data->rx_action.da == NULL || data->rx_action.sa == NULL ||
|
||||
data->rx_action.bssid == NULL)
|
||||
break;
|
||||
#ifdef NEED_AP_MLME
|
||||
hostapd_rx_action(hapd, &data->rx_action);
|
||||
#endif /* NEED_AP_MLME */
|
||||
hostapd_action_rx(hapd, &data->rx_action);
|
||||
break;
|
||||
case EVENT_AUTH:
|
||||
hostapd_notif_auth(hapd, &data->auth);
|
||||
break;
|
||||
case EVENT_CH_SWITCH:
|
||||
if (!data)
|
||||
break;
|
||||
hostapd_event_ch_switch(hapd, data->ch_switch.freq,
|
||||
data->ch_switch.ht_enabled,
|
||||
data->ch_switch.ch_offset);
|
||||
break;
|
||||
default:
|
||||
wpa_printf(MSG_DEBUG, "Unknown event %d", event);
|
||||
break;
|
||||
|
270
src/ap/eap_user_db.c
Normal file
270
src/ap/eap_user_db.c
Normal file
@ -0,0 +1,270 @@
|
||||
/*
|
||||
* hostapd / EAP user database
|
||||
* Copyright (c) 2012, Jouni Malinen <j@w1.fi>
|
||||
*
|
||||
* This software may be distributed under the terms of the BSD license.
|
||||
* See README for more details.
|
||||
*/
|
||||
|
||||
#include "includes.h"
|
||||
#ifdef CONFIG_SQLITE
|
||||
#include <sqlite3.h>
|
||||
#endif /* CONFIG_SQLITE */
|
||||
|
||||
#include "common.h"
|
||||
#include "eap_common/eap_wsc_common.h"
|
||||
#include "eap_server/eap_methods.h"
|
||||
#include "eap_server/eap.h"
|
||||
#include "ap_config.h"
|
||||
#include "hostapd.h"
|
||||
|
||||
#ifdef CONFIG_SQLITE
|
||||
|
||||
static void set_user_methods(struct hostapd_eap_user *user, const char *methods)
|
||||
{
|
||||
char *buf, *start;
|
||||
int num_methods;
|
||||
|
||||
buf = os_strdup(methods);
|
||||
if (buf == NULL)
|
||||
return;
|
||||
|
||||
os_memset(&user->methods, 0, sizeof(user->methods));
|
||||
num_methods = 0;
|
||||
start = buf;
|
||||
while (*start) {
|
||||
char *pos3 = os_strchr(start, ',');
|
||||
if (pos3)
|
||||
*pos3++ = '\0';
|
||||
user->methods[num_methods].method =
|
||||
eap_server_get_type(start,
|
||||
&user->methods[num_methods].vendor);
|
||||
if (user->methods[num_methods].vendor == EAP_VENDOR_IETF &&
|
||||
user->methods[num_methods].method == EAP_TYPE_NONE) {
|
||||
if (os_strcmp(start, "TTLS-PAP") == 0) {
|
||||
user->ttls_auth |= EAP_TTLS_AUTH_PAP;
|
||||
goto skip_eap;
|
||||
}
|
||||
if (os_strcmp(start, "TTLS-CHAP") == 0) {
|
||||
user->ttls_auth |= EAP_TTLS_AUTH_CHAP;
|
||||
goto skip_eap;
|
||||
}
|
||||
if (os_strcmp(start, "TTLS-MSCHAP") == 0) {
|
||||
user->ttls_auth |= EAP_TTLS_AUTH_MSCHAP;
|
||||
goto skip_eap;
|
||||
}
|
||||
if (os_strcmp(start, "TTLS-MSCHAPV2") == 0) {
|
||||
user->ttls_auth |= EAP_TTLS_AUTH_MSCHAPV2;
|
||||
goto skip_eap;
|
||||
}
|
||||
wpa_printf(MSG_INFO, "DB: Unsupported EAP type '%s'",
|
||||
start);
|
||||
os_free(buf);
|
||||
return;
|
||||
}
|
||||
|
||||
num_methods++;
|
||||
if (num_methods >= EAP_MAX_METHODS)
|
||||
break;
|
||||
skip_eap:
|
||||
if (pos3 == NULL)
|
||||
break;
|
||||
start = pos3;
|
||||
}
|
||||
|
||||
os_free(buf);
|
||||
}
|
||||
|
||||
|
||||
static int get_user_cb(void *ctx, int argc, char *argv[], char *col[])
|
||||
{
|
||||
struct hostapd_eap_user *user = ctx;
|
||||
int i;
|
||||
|
||||
for (i = 0; i < argc; i++) {
|
||||
if (os_strcmp(col[i], "password") == 0 && argv[i]) {
|
||||
os_free(user->password);
|
||||
user->password_len = os_strlen(argv[i]);
|
||||
user->password = (u8 *) os_strdup(argv[i]);
|
||||
user->next = (void *) 1;
|
||||
} else if (os_strcmp(col[i], "methods") == 0 && argv[i]) {
|
||||
set_user_methods(user, argv[i]);
|
||||
}
|
||||
}
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
|
||||
static int get_wildcard_cb(void *ctx, int argc, char *argv[], char *col[])
|
||||
{
|
||||
struct hostapd_eap_user *user = ctx;
|
||||
int i, id = -1, methods = -1;
|
||||
size_t len;
|
||||
|
||||
for (i = 0; i < argc; i++) {
|
||||
if (os_strcmp(col[i], "identity") == 0 && argv[i])
|
||||
id = i;
|
||||
else if (os_strcmp(col[i], "methods") == 0 && argv[i])
|
||||
methods = i;
|
||||
}
|
||||
|
||||
if (id < 0 || methods < 0)
|
||||
return 0;
|
||||
|
||||
len = os_strlen(argv[id]);
|
||||
if (len <= user->identity_len &&
|
||||
os_memcmp(argv[id], user->identity, len) == 0 &&
|
||||
(user->password == NULL || len > user->password_len)) {
|
||||
os_free(user->password);
|
||||
user->password_len = os_strlen(argv[id]);
|
||||
user->password = (u8 *) os_strdup(argv[id]);
|
||||
user->next = (void *) 1;
|
||||
set_user_methods(user, argv[methods]);
|
||||
}
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
|
||||
static const struct hostapd_eap_user *
|
||||
eap_user_sqlite_get(struct hostapd_data *hapd, const u8 *identity,
|
||||
size_t identity_len, int phase2)
|
||||
{
|
||||
sqlite3 *db;
|
||||
struct hostapd_eap_user *user = NULL;
|
||||
char id_str[256], cmd[300];
|
||||
size_t i;
|
||||
|
||||
if (identity_len >= sizeof(id_str))
|
||||
return NULL;
|
||||
os_memcpy(id_str, identity, identity_len);
|
||||
id_str[identity_len] = '\0';
|
||||
for (i = 0; i < identity_len; i++) {
|
||||
if (id_str[i] >= 'a' && id_str[i] <= 'z')
|
||||
continue;
|
||||
if (id_str[i] >= 'A' && id_str[i] <= 'Z')
|
||||
continue;
|
||||
if (id_str[i] >= '0' && id_str[i] <= '9')
|
||||
continue;
|
||||
if (id_str[i] == '-' || id_str[i] == '_' || id_str[i] == '.' ||
|
||||
id_str[i] == ',' || id_str[i] == '@' || id_str[i] == '\\' ||
|
||||
id_str[i] == '!' || id_str[i] == '#' || id_str[i] == '%' ||
|
||||
id_str[i] == '=' || id_str[i] == ' ')
|
||||
continue;
|
||||
wpa_printf(MSG_INFO, "DB: Unsupported character in identity");
|
||||
return NULL;
|
||||
}
|
||||
|
||||
os_free(hapd->tmp_eap_user.identity);
|
||||
os_free(hapd->tmp_eap_user.password);
|
||||
os_memset(&hapd->tmp_eap_user, 0, sizeof(hapd->tmp_eap_user));
|
||||
hapd->tmp_eap_user.phase2 = phase2;
|
||||
hapd->tmp_eap_user.identity = os_zalloc(identity_len + 1);
|
||||
if (hapd->tmp_eap_user.identity == NULL)
|
||||
return NULL;
|
||||
os_memcpy(hapd->tmp_eap_user.identity, identity, identity_len);
|
||||
|
||||
if (sqlite3_open(hapd->conf->eap_user_sqlite, &db)) {
|
||||
wpa_printf(MSG_INFO, "DB: Failed to open database %s: %s",
|
||||
hapd->conf->eap_user_sqlite, sqlite3_errmsg(db));
|
||||
sqlite3_close(db);
|
||||
return NULL;
|
||||
}
|
||||
|
||||
os_snprintf(cmd, sizeof(cmd),
|
||||
"SELECT password,methods FROM users WHERE "
|
||||
"identity='%s' AND phase2=%d;", id_str, phase2);
|
||||
wpa_printf(MSG_DEBUG, "DB: %s", cmd);
|
||||
if (sqlite3_exec(db, cmd, get_user_cb, &hapd->tmp_eap_user, NULL) !=
|
||||
SQLITE_OK) {
|
||||
wpa_printf(MSG_DEBUG, "DB: Failed to complete SQL operation");
|
||||
} else if (hapd->tmp_eap_user.next)
|
||||
user = &hapd->tmp_eap_user;
|
||||
|
||||
if (user == NULL && !phase2) {
|
||||
os_snprintf(cmd, sizeof(cmd),
|
||||
"SELECT identity,methods FROM wildcards;");
|
||||
wpa_printf(MSG_DEBUG, "DB: %s", cmd);
|
||||
if (sqlite3_exec(db, cmd, get_wildcard_cb, &hapd->tmp_eap_user,
|
||||
NULL) != SQLITE_OK) {
|
||||
wpa_printf(MSG_DEBUG, "DB: Failed to complete SQL "
|
||||
"operation");
|
||||
} else if (hapd->tmp_eap_user.next) {
|
||||
user = &hapd->tmp_eap_user;
|
||||
os_free(user->identity);
|
||||
user->identity = user->password;
|
||||
user->identity_len = user->password_len;
|
||||
user->password = NULL;
|
||||
user->password_len = 0;
|
||||
}
|
||||
}
|
||||
|
||||
sqlite3_close(db);
|
||||
|
||||
return user;
|
||||
}
|
||||
|
||||
#endif /* CONFIG_SQLITE */
|
||||
|
||||
|
||||
const struct hostapd_eap_user *
|
||||
hostapd_get_eap_user(struct hostapd_data *hapd, const u8 *identity,
|
||||
size_t identity_len, int phase2)
|
||||
{
|
||||
const struct hostapd_bss_config *conf = hapd->conf;
|
||||
struct hostapd_eap_user *user = conf->eap_user;
|
||||
|
||||
#ifdef CONFIG_WPS
|
||||
if (conf->wps_state && identity_len == WSC_ID_ENROLLEE_LEN &&
|
||||
os_memcmp(identity, WSC_ID_ENROLLEE, WSC_ID_ENROLLEE_LEN) == 0) {
|
||||
static struct hostapd_eap_user wsc_enrollee;
|
||||
os_memset(&wsc_enrollee, 0, sizeof(wsc_enrollee));
|
||||
wsc_enrollee.methods[0].method = eap_server_get_type(
|
||||
"WSC", &wsc_enrollee.methods[0].vendor);
|
||||
return &wsc_enrollee;
|
||||
}
|
||||
|
||||
if (conf->wps_state && identity_len == WSC_ID_REGISTRAR_LEN &&
|
||||
os_memcmp(identity, WSC_ID_REGISTRAR, WSC_ID_REGISTRAR_LEN) == 0) {
|
||||
static struct hostapd_eap_user wsc_registrar;
|
||||
os_memset(&wsc_registrar, 0, sizeof(wsc_registrar));
|
||||
wsc_registrar.methods[0].method = eap_server_get_type(
|
||||
"WSC", &wsc_registrar.methods[0].vendor);
|
||||
wsc_registrar.password = (u8 *) conf->ap_pin;
|
||||
wsc_registrar.password_len = conf->ap_pin ?
|
||||
os_strlen(conf->ap_pin) : 0;
|
||||
return &wsc_registrar;
|
||||
}
|
||||
#endif /* CONFIG_WPS */
|
||||
|
||||
while (user) {
|
||||
if (!phase2 && user->identity == NULL) {
|
||||
/* Wildcard match */
|
||||
break;
|
||||
}
|
||||
|
||||
if (user->phase2 == !!phase2 && user->wildcard_prefix &&
|
||||
identity_len >= user->identity_len &&
|
||||
os_memcmp(user->identity, identity, user->identity_len) ==
|
||||
0) {
|
||||
/* Wildcard prefix match */
|
||||
break;
|
||||
}
|
||||
|
||||
if (user->phase2 == !!phase2 &&
|
||||
user->identity_len == identity_len &&
|
||||
os_memcmp(user->identity, identity, identity_len) == 0)
|
||||
break;
|
||||
user = user->next;
|
||||
}
|
||||
|
||||
#ifdef CONFIG_SQLITE
|
||||
if (user == NULL && conf->eap_user_sqlite) {
|
||||
return eap_user_sqlite_get(hapd, identity, identity_len,
|
||||
phase2);
|
||||
}
|
||||
#endif /* CONFIG_SQLITE */
|
||||
|
||||
return user;
|
||||
}
|
1172
src/ap/gas_serv.c
Normal file
1172
src/ap/gas_serv.c
Normal file
File diff suppressed because it is too large
Load Diff
71
src/ap/gas_serv.h
Normal file
71
src/ap/gas_serv.h
Normal file
@ -0,0 +1,71 @@
|
||||
/*
|
||||
* Generic advertisement service (GAS) server
|
||||
* Copyright (c) 2011-2012, Qualcomm Atheros, Inc.
|
||||
*
|
||||
* This software may be distributed under the terms of the BSD license.
|
||||
* See README for more details.
|
||||
*/
|
||||
|
||||
#ifndef GAS_SERV_H
|
||||
#define GAS_SERV_H
|
||||
|
||||
#define ANQP_REQ_CAPABILITY_LIST \
|
||||
(1 << (ANQP_CAPABILITY_LIST - ANQP_QUERY_LIST))
|
||||
#define ANQP_REQ_VENUE_NAME \
|
||||
(1 << (ANQP_VENUE_NAME - ANQP_QUERY_LIST))
|
||||
#define ANQP_REQ_NETWORK_AUTH_TYPE \
|
||||
(1 << (ANQP_NETWORK_AUTH_TYPE - ANQP_QUERY_LIST))
|
||||
#define ANQP_REQ_ROAMING_CONSORTIUM \
|
||||
(1 << (ANQP_ROAMING_CONSORTIUM - ANQP_QUERY_LIST))
|
||||
#define ANQP_REQ_IP_ADDR_TYPE_AVAILABILITY \
|
||||
(1 << (ANQP_IP_ADDR_TYPE_AVAILABILITY - ANQP_QUERY_LIST))
|
||||
#define ANQP_REQ_NAI_REALM \
|
||||
(1 << (ANQP_NAI_REALM - ANQP_QUERY_LIST))
|
||||
#define ANQP_REQ_3GPP_CELLULAR_NETWORK \
|
||||
(1 << (ANQP_3GPP_CELLULAR_NETWORK - ANQP_QUERY_LIST))
|
||||
#define ANQP_REQ_DOMAIN_NAME \
|
||||
(1 << (ANQP_DOMAIN_NAME - ANQP_QUERY_LIST))
|
||||
#define ANQP_REQ_HS_CAPABILITY_LIST \
|
||||
(0x10000 << HS20_STYPE_CAPABILITY_LIST)
|
||||
#define ANQP_REQ_OPERATOR_FRIENDLY_NAME \
|
||||
(0x10000 << HS20_STYPE_OPERATOR_FRIENDLY_NAME)
|
||||
#define ANQP_REQ_WAN_METRICS \
|
||||
(0x10000 << HS20_STYPE_WAN_METRICS)
|
||||
#define ANQP_REQ_CONNECTION_CAPABILITY \
|
||||
(0x10000 << HS20_STYPE_CONNECTION_CAPABILITY)
|
||||
#define ANQP_REQ_NAI_HOME_REALM \
|
||||
(0x10000 << HS20_STYPE_NAI_HOME_REALM_QUERY)
|
||||
#define ANQP_REQ_OPERATING_CLASS \
|
||||
(0x10000 << HS20_STYPE_OPERATING_CLASS)
|
||||
|
||||
/* To account for latencies between hostapd and external ANQP processor */
|
||||
#define GAS_SERV_COMEBACK_DELAY_FUDGE 10
|
||||
#define GAS_SERV_MIN_COMEBACK_DELAY 100 /* in TU */
|
||||
|
||||
struct gas_dialog_info {
|
||||
u8 valid;
|
||||
u8 index;
|
||||
struct wpabuf *sd_resp; /* Fragmented response */
|
||||
u8 dialog_token;
|
||||
size_t sd_resp_pos; /* Offset in sd_resp */
|
||||
u8 sd_frag_id;
|
||||
u16 comeback_delay;
|
||||
|
||||
unsigned int requested;
|
||||
unsigned int received;
|
||||
unsigned int all_requested;
|
||||
};
|
||||
|
||||
struct hostapd_data;
|
||||
|
||||
void gas_serv_tx_gas_response(struct hostapd_data *hapd, const u8 *dst,
|
||||
struct gas_dialog_info *dialog);
|
||||
struct gas_dialog_info *
|
||||
gas_serv_dialog_find(struct hostapd_data *hapd, const u8 *addr,
|
||||
u8 dialog_token);
|
||||
void gas_serv_dialog_clear(struct gas_dialog_info *dialog);
|
||||
|
||||
int gas_serv_init(struct hostapd_data *hapd);
|
||||
void gas_serv_deinit(struct hostapd_data *hapd);
|
||||
|
||||
#endif /* GAS_SERV_H */
|
752
src/ap/hostapd.c
752
src/ap/hostapd.c
File diff suppressed because it is too large
Load Diff
177
src/ap/hostapd.h
177
src/ap/hostapd.h
@ -2,34 +2,51 @@
|
||||
* hostapd / Initialization and configuration
|
||||
* Copyright (c) 2002-2009, Jouni Malinen <j@w1.fi>
|
||||
*
|
||||
* This program is free software; you can redistribute it and/or modify
|
||||
* it under the terms of the GNU General Public License version 2 as
|
||||
* published by the Free Software Foundation.
|
||||
*
|
||||
* Alternatively, this software may be distributed under the terms of BSD
|
||||
* license.
|
||||
*
|
||||
* See README and COPYING for more details.
|
||||
* This software may be distributed under the terms of the BSD license.
|
||||
* See README for more details.
|
||||
*/
|
||||
|
||||
#ifndef HOSTAPD_H
|
||||
#define HOSTAPD_H
|
||||
|
||||
#include "common/defs.h"
|
||||
#include "ap_config.h"
|
||||
|
||||
struct wpa_driver_ops;
|
||||
struct wpa_ctrl_dst;
|
||||
struct radius_server_data;
|
||||
struct upnp_wps_device_sm;
|
||||
struct hapd_interfaces;
|
||||
struct hostapd_data;
|
||||
struct sta_info;
|
||||
struct hostap_sta_driver_data;
|
||||
struct ieee80211_ht_capabilities;
|
||||
struct full_dynamic_vlan;
|
||||
enum wps_event;
|
||||
union wps_event_data;
|
||||
|
||||
struct hostapd_iface;
|
||||
|
||||
struct hapd_interfaces {
|
||||
int (*reload_config)(struct hostapd_iface *iface);
|
||||
struct hostapd_config * (*config_read_cb)(const char *config_fname);
|
||||
int (*ctrl_iface_init)(struct hostapd_data *hapd);
|
||||
void (*ctrl_iface_deinit)(struct hostapd_data *hapd);
|
||||
int (*for_each_interface)(struct hapd_interfaces *interfaces,
|
||||
int (*cb)(struct hostapd_iface *iface,
|
||||
void *ctx), void *ctx);
|
||||
int (*driver_init)(struct hostapd_iface *iface);
|
||||
|
||||
size_t count;
|
||||
int global_ctrl_sock;
|
||||
char *global_iface_path;
|
||||
char *global_iface_name;
|
||||
struct hostapd_iface **iface;
|
||||
};
|
||||
|
||||
|
||||
struct hostapd_probereq_cb {
|
||||
int (*cb)(void *ctx, const u8 *sa, const u8 *ie, size_t ie_len);
|
||||
int (*cb)(void *ctx, const u8 *sa, const u8 *da, const u8 *bssid,
|
||||
const u8 *ie, size_t ie_len, int ssi_signal);
|
||||
void *ctx;
|
||||
};
|
||||
|
||||
@ -43,59 +60,10 @@ struct hostapd_rate_data {
|
||||
struct hostapd_frame_info {
|
||||
u32 channel;
|
||||
u32 datarate;
|
||||
u32 ssi_signal;
|
||||
int ssi_signal; /* dBm */
|
||||
};
|
||||
|
||||
|
||||
struct hostapd_driver_ops {
|
||||
int (*set_ap_wps_ie)(struct hostapd_data *hapd);
|
||||
int (*send_mgmt_frame)(struct hostapd_data *hapd, const void *msg,
|
||||
size_t len);
|
||||
int (*send_eapol)(struct hostapd_data *hapd, const u8 *addr,
|
||||
const u8 *data, size_t data_len, int encrypt);
|
||||
int (*set_authorized)(struct hostapd_data *hapd, struct sta_info *sta,
|
||||
int authorized);
|
||||
int (*set_key)(const char *ifname, struct hostapd_data *hapd,
|
||||
enum wpa_alg alg, const u8 *addr, int key_idx,
|
||||
int set_tx, const u8 *seq, size_t seq_len,
|
||||
const u8 *key, size_t key_len);
|
||||
int (*read_sta_data)(struct hostapd_data *hapd,
|
||||
struct hostap_sta_driver_data *data,
|
||||
const u8 *addr);
|
||||
int (*sta_clear_stats)(struct hostapd_data *hapd, const u8 *addr);
|
||||
int (*set_sta_flags)(struct hostapd_data *hapd, struct sta_info *sta);
|
||||
int (*set_drv_ieee8021x)(struct hostapd_data *hapd, const char *ifname,
|
||||
int enabled);
|
||||
int (*set_radius_acl_auth)(struct hostapd_data *hapd,
|
||||
const u8 *mac, int accepted,
|
||||
u32 session_timeout);
|
||||
int (*set_radius_acl_expire)(struct hostapd_data *hapd,
|
||||
const u8 *mac);
|
||||
int (*set_bss_params)(struct hostapd_data *hapd, int use_protection);
|
||||
int (*set_beacon)(struct hostapd_data *hapd,
|
||||
const u8 *head, size_t head_len,
|
||||
const u8 *tail, size_t tail_len, int dtim_period,
|
||||
int beacon_int);
|
||||
int (*vlan_if_add)(struct hostapd_data *hapd, const char *ifname);
|
||||
int (*vlan_if_remove)(struct hostapd_data *hapd, const char *ifname);
|
||||
int (*set_wds_sta)(struct hostapd_data *hapd, const u8 *addr, int aid,
|
||||
int val);
|
||||
int (*set_sta_vlan)(const char *ifname, struct hostapd_data *hapd,
|
||||
const u8 *addr, int vlan_id);
|
||||
int (*get_inact_sec)(struct hostapd_data *hapd, const u8 *addr);
|
||||
int (*sta_deauth)(struct hostapd_data *hapd, const u8 *addr,
|
||||
int reason);
|
||||
int (*sta_disassoc)(struct hostapd_data *hapd, const u8 *addr,
|
||||
int reason);
|
||||
int (*sta_add)(struct hostapd_data *hapd,
|
||||
const u8 *addr, u16 aid, u16 capability,
|
||||
const u8 *supp_rates, size_t supp_rates_len,
|
||||
u16 listen_interval,
|
||||
const struct ieee80211_ht_capabilities *ht_capab);
|
||||
int (*sta_remove)(struct hostapd_data *hapd, const u8 *addr);
|
||||
int (*set_countermeasures)(struct hostapd_data *hapd, int enabled);
|
||||
};
|
||||
|
||||
/**
|
||||
* struct hostapd_data - hostapd per-BSS data structure
|
||||
*/
|
||||
@ -123,15 +91,16 @@ struct hostapd_data {
|
||||
|
||||
const struct wpa_driver_ops *driver;
|
||||
void *drv_priv;
|
||||
struct hostapd_driver_ops drv;
|
||||
|
||||
void (*new_assoc_sta_cb)(struct hostapd_data *hapd,
|
||||
struct sta_info *sta, int reassoc);
|
||||
|
||||
void *msg_ctx; /* ctx for wpa_msg() calls */
|
||||
void *msg_ctx_parent; /* parent interface ctx for wpa_msg() calls */
|
||||
|
||||
struct radius_client_data *radius;
|
||||
u32 acct_session_id_hi, acct_session_id_lo;
|
||||
struct radius_das_data *radius_das;
|
||||
|
||||
struct iapp_data *iapp;
|
||||
|
||||
@ -155,6 +124,10 @@ struct hostapd_data {
|
||||
|
||||
int parameter_set_count;
|
||||
|
||||
/* Time Advertisement */
|
||||
u8 time_update_counter;
|
||||
struct wpabuf *time_adv;
|
||||
|
||||
#ifdef CONFIG_FULL_DYNAMIC_VLAN
|
||||
struct full_dynamic_vlan *full_dynamic_vlan;
|
||||
#endif /* CONFIG_FULL_DYNAMIC_VLAN */
|
||||
@ -162,10 +135,12 @@ struct hostapd_data {
|
||||
struct l2_packet_data *l2;
|
||||
struct wps_context *wps;
|
||||
|
||||
int beacon_set_done;
|
||||
struct wpabuf *wps_beacon_ie;
|
||||
struct wpabuf *wps_probe_resp_ie;
|
||||
#ifdef CONFIG_WPS
|
||||
unsigned int ap_pin_failures;
|
||||
unsigned int ap_pin_failures_consecutive;
|
||||
struct upnp_wps_device_sm *wps_upnp;
|
||||
unsigned int ap_pin_lockout_time;
|
||||
#endif /* CONFIG_WPS */
|
||||
@ -177,9 +152,46 @@ struct hostapd_data {
|
||||
int freq);
|
||||
void *public_action_cb_ctx;
|
||||
|
||||
int (*vendor_action_cb)(void *ctx, const u8 *buf, size_t len,
|
||||
int freq);
|
||||
void *vendor_action_cb_ctx;
|
||||
|
||||
void (*wps_reg_success_cb)(void *ctx, const u8 *mac_addr,
|
||||
const u8 *uuid_e);
|
||||
void *wps_reg_success_cb_ctx;
|
||||
|
||||
void (*wps_event_cb)(void *ctx, enum wps_event event,
|
||||
union wps_event_data *data);
|
||||
void *wps_event_cb_ctx;
|
||||
|
||||
void (*sta_authorized_cb)(void *ctx, const u8 *mac_addr,
|
||||
int authorized, const u8 *p2p_dev_addr);
|
||||
void *sta_authorized_cb_ctx;
|
||||
|
||||
void (*setup_complete_cb)(void *ctx);
|
||||
void *setup_complete_cb_ctx;
|
||||
|
||||
#ifdef CONFIG_P2P
|
||||
struct p2p_data *p2p;
|
||||
struct p2p_group *p2p_group;
|
||||
struct wpabuf *p2p_beacon_ie;
|
||||
struct wpabuf *p2p_probe_resp_ie;
|
||||
|
||||
/* Number of non-P2P association stations */
|
||||
int num_sta_no_p2p;
|
||||
|
||||
/* Periodic NoA (used only when no non-P2P clients in the group) */
|
||||
int noa_enabled;
|
||||
int noa_start;
|
||||
int noa_duration;
|
||||
#endif /* CONFIG_P2P */
|
||||
#ifdef CONFIG_INTERWORKING
|
||||
size_t gas_frag_limit;
|
||||
#endif /* CONFIG_INTERWORKING */
|
||||
|
||||
#ifdef CONFIG_SQLITE
|
||||
struct hostapd_eap_user tmp_eap_user;
|
||||
#endif /* CONFIG_SQLITE */
|
||||
};
|
||||
|
||||
|
||||
@ -189,8 +201,6 @@ struct hostapd_data {
|
||||
struct hostapd_iface {
|
||||
struct hapd_interfaces *interfaces;
|
||||
void *owner;
|
||||
int (*reload_config)(struct hostapd_iface *iface);
|
||||
struct hostapd_config * (*config_read_cb)(const char *config_fname);
|
||||
char *config_fname;
|
||||
struct hostapd_config *conf;
|
||||
|
||||
@ -202,6 +212,14 @@ struct hostapd_iface {
|
||||
struct ap_info *ap_hash[STA_HASH_SIZE];
|
||||
struct ap_info *ap_iter_list;
|
||||
|
||||
unsigned int drv_flags;
|
||||
|
||||
/*
|
||||
* A bitmap of supported protocols for probe response offload. See
|
||||
* struct wpa_driver_capa in driver.h
|
||||
*/
|
||||
unsigned int probe_resp_offloads;
|
||||
|
||||
struct hostapd_hw_modes *hw_features;
|
||||
int num_hw_features;
|
||||
struct hostapd_hw_modes *current_mode;
|
||||
@ -209,6 +227,7 @@ struct hostapd_iface {
|
||||
* current_mode->channels */
|
||||
int num_rates;
|
||||
struct hostapd_rate_data *current_rates;
|
||||
int *basic_rates;
|
||||
int freq;
|
||||
|
||||
u16 hw_flags;
|
||||
@ -239,16 +258,12 @@ struct hostapd_iface {
|
||||
|
||||
u16 ht_op_mode;
|
||||
void (*scan_cb)(struct hostapd_iface *iface);
|
||||
|
||||
int (*ctrl_iface_init)(struct hostapd_data *hapd);
|
||||
void (*ctrl_iface_deinit)(struct hostapd_data *hapd);
|
||||
|
||||
int (*for_each_interface)(struct hapd_interfaces *interfaces,
|
||||
int (*cb)(struct hostapd_iface *iface,
|
||||
void *ctx), void *ctx);
|
||||
};
|
||||
|
||||
/* hostapd.c */
|
||||
int hostapd_for_each_interface(struct hapd_interfaces *interfaces,
|
||||
int (*cb)(struct hostapd_iface *iface,
|
||||
void *ctx), void *ctx);
|
||||
int hostapd_reload_config(struct hostapd_iface *iface);
|
||||
struct hostapd_data *
|
||||
hostapd_alloc_bss_data(struct hostapd_iface *hapd_iface,
|
||||
@ -260,17 +275,35 @@ void hostapd_interface_deinit(struct hostapd_iface *iface);
|
||||
void hostapd_interface_free(struct hostapd_iface *iface);
|
||||
void hostapd_new_assoc_sta(struct hostapd_data *hapd, struct sta_info *sta,
|
||||
int reassoc);
|
||||
void hostapd_interface_deinit_free(struct hostapd_iface *iface);
|
||||
int hostapd_enable_iface(struct hostapd_iface *hapd_iface);
|
||||
int hostapd_reload_iface(struct hostapd_iface *hapd_iface);
|
||||
int hostapd_disable_iface(struct hostapd_iface *hapd_iface);
|
||||
int hostapd_add_iface(struct hapd_interfaces *ifaces, char *buf);
|
||||
int hostapd_remove_iface(struct hapd_interfaces *ifaces, char *buf);
|
||||
|
||||
/* utils.c */
|
||||
int hostapd_register_probereq_cb(struct hostapd_data *hapd,
|
||||
int (*cb)(void *ctx, const u8 *sa,
|
||||
const u8 *ie, size_t ie_len),
|
||||
const u8 *da, const u8 *bssid,
|
||||
const u8 *ie, size_t ie_len,
|
||||
int ssi_signal),
|
||||
void *ctx);
|
||||
void hostapd_prune_associations(struct hostapd_data *hapd, const u8 *addr);
|
||||
|
||||
/* drv_callbacks.c (TODO: move to somewhere else?) */
|
||||
int hostapd_notif_assoc(struct hostapd_data *hapd, const u8 *addr,
|
||||
const u8 *ie, size_t ielen);
|
||||
const u8 *ie, size_t ielen, int reassoc);
|
||||
void hostapd_notif_disassoc(struct hostapd_data *hapd, const u8 *addr);
|
||||
void hostapd_event_sta_low_ack(struct hostapd_data *hapd, const u8 *addr);
|
||||
int hostapd_probe_req_rx(struct hostapd_data *hapd, const u8 *sa, const u8 *da,
|
||||
const u8 *bssid, const u8 *ie, size_t ie_len,
|
||||
int ssi_signal);
|
||||
void hostapd_event_ch_switch(struct hostapd_data *hapd, int freq, int ht,
|
||||
int offset);
|
||||
|
||||
const struct hostapd_eap_user *
|
||||
hostapd_get_eap_user(struct hostapd_data *hapd, const u8 *identity,
|
||||
size_t identity_len, int phase2);
|
||||
|
||||
#endif /* HOSTAPD_H */
|
||||
|
31
src/ap/hs20.c
Normal file
31
src/ap/hs20.c
Normal file
@ -0,0 +1,31 @@
|
||||
/*
|
||||
* Hotspot 2.0 AP ANQP processing
|
||||
* Copyright (c) 2009, Atheros Communications, Inc.
|
||||
* Copyright (c) 2011-2012, Qualcomm Atheros, Inc.
|
||||
*
|
||||
* This software may be distributed under the terms of the BSD license.
|
||||
* See README for more details.
|
||||
*/
|
||||
|
||||
#include "includes.h"
|
||||
|
||||
#include "common.h"
|
||||
#include "common/ieee802_11_defs.h"
|
||||
#include "hostapd.h"
|
||||
#include "ap_config.h"
|
||||
#include "hs20.h"
|
||||
|
||||
|
||||
u8 * hostapd_eid_hs20_indication(struct hostapd_data *hapd, u8 *eid)
|
||||
{
|
||||
if (!hapd->conf->hs20)
|
||||
return eid;
|
||||
*eid++ = WLAN_EID_VENDOR_SPECIFIC;
|
||||
*eid++ = 5;
|
||||
WPA_PUT_BE24(eid, OUI_WFA);
|
||||
eid += 3;
|
||||
*eid++ = HS20_INDICATION_OUI_TYPE;
|
||||
/* Hotspot Configuration: DGAF Enabled */
|
||||
*eid++ = hapd->conf->disable_dgaf ? 0x01 : 0x00;
|
||||
return eid;
|
||||
}
|
16
src/ap/hs20.h
Normal file
16
src/ap/hs20.h
Normal file
@ -0,0 +1,16 @@
|
||||
/*
|
||||
* Hotspot 2.0 AP ANQP processing
|
||||
* Copyright (c) 2011-2012, Qualcomm Atheros, Inc.
|
||||
*
|
||||
* This software may be distributed under the terms of the BSD license.
|
||||
* See README for more details.
|
||||
*/
|
||||
|
||||
#ifndef HS20_H
|
||||
#define HS20_H
|
||||
|
||||
struct hostapd_data;
|
||||
|
||||
u8 * hostapd_eid_hs20_indication(struct hostapd_data *hapd, u8 *eid);
|
||||
|
||||
#endif /* HS20_H */
|
@ -2,7 +2,7 @@
|
||||
* hostapd / Hardware feature query and different modes
|
||||
* Copyright 2002-2003, Instant802 Networks, Inc.
|
||||
* Copyright 2005-2006, Devicescape Software, Inc.
|
||||
* Copyright (c) 2008-2009, Jouni Malinen <j@w1.fi>
|
||||
* Copyright (c) 2008-2012, Jouni Malinen <j@w1.fi>
|
||||
*
|
||||
* This program is free software; you can redistribute it and/or modify
|
||||
* it under the terms of the GNU General Public License version 2 as
|
||||
@ -101,8 +101,8 @@ int hostapd_get_hw_features(struct hostapd_iface *iface)
|
||||
}
|
||||
|
||||
|
||||
static int hostapd_prepare_rates(struct hostapd_data *hapd,
|
||||
struct hostapd_hw_modes *mode)
|
||||
int hostapd_prepare_rates(struct hostapd_iface *iface,
|
||||
struct hostapd_hw_modes *mode)
|
||||
{
|
||||
int i, num_basic_rates = 0;
|
||||
int basic_rates_a[] = { 60, 120, 240, -1 };
|
||||
@ -110,8 +110,8 @@ static int hostapd_prepare_rates(struct hostapd_data *hapd,
|
||||
int basic_rates_g[] = { 10, 20, 55, 110, -1 };
|
||||
int *basic_rates;
|
||||
|
||||
if (hapd->iconf->basic_rates)
|
||||
basic_rates = hapd->iconf->basic_rates;
|
||||
if (iface->conf->basic_rates)
|
||||
basic_rates = iface->conf->basic_rates;
|
||||
else switch (mode->mode) {
|
||||
case HOSTAPD_MODE_IEEE80211A:
|
||||
basic_rates = basic_rates_a;
|
||||
@ -122,22 +122,28 @@ static int hostapd_prepare_rates(struct hostapd_data *hapd,
|
||||
case HOSTAPD_MODE_IEEE80211G:
|
||||
basic_rates = basic_rates_g;
|
||||
break;
|
||||
case HOSTAPD_MODE_IEEE80211AD:
|
||||
return 0; /* No basic rates for 11ad */
|
||||
default:
|
||||
return -1;
|
||||
}
|
||||
|
||||
if (hostapd_set_rate_sets(hapd, hapd->iconf->supported_rates,
|
||||
basic_rates, mode->mode)) {
|
||||
wpa_printf(MSG_ERROR, "Failed to update rate sets in kernel "
|
||||
"module");
|
||||
}
|
||||
i = 0;
|
||||
while (basic_rates[i] >= 0)
|
||||
i++;
|
||||
if (i)
|
||||
i++; /* -1 termination */
|
||||
os_free(iface->basic_rates);
|
||||
iface->basic_rates = os_malloc(i * sizeof(int));
|
||||
if (iface->basic_rates)
|
||||
os_memcpy(iface->basic_rates, basic_rates, i * sizeof(int));
|
||||
|
||||
os_free(hapd->iface->current_rates);
|
||||
hapd->iface->num_rates = 0;
|
||||
os_free(iface->current_rates);
|
||||
iface->num_rates = 0;
|
||||
|
||||
hapd->iface->current_rates =
|
||||
os_zalloc(mode->num_rates * sizeof(struct hostapd_rate_data));
|
||||
if (!hapd->iface->current_rates) {
|
||||
iface->current_rates =
|
||||
os_calloc(mode->num_rates, sizeof(struct hostapd_rate_data));
|
||||
if (!iface->current_rates) {
|
||||
wpa_printf(MSG_ERROR, "Failed to allocate memory for rate "
|
||||
"table.");
|
||||
return -1;
|
||||
@ -146,26 +152,27 @@ static int hostapd_prepare_rates(struct hostapd_data *hapd,
|
||||
for (i = 0; i < mode->num_rates; i++) {
|
||||
struct hostapd_rate_data *rate;
|
||||
|
||||
if (hapd->iconf->supported_rates &&
|
||||
!hostapd_rate_found(hapd->iconf->supported_rates,
|
||||
if (iface->conf->supported_rates &&
|
||||
!hostapd_rate_found(iface->conf->supported_rates,
|
||||
mode->rates[i]))
|
||||
continue;
|
||||
|
||||
rate = &hapd->iface->current_rates[hapd->iface->num_rates];
|
||||
rate = &iface->current_rates[iface->num_rates];
|
||||
rate->rate = mode->rates[i];
|
||||
if (hostapd_rate_found(basic_rates, rate->rate)) {
|
||||
rate->flags |= HOSTAPD_RATE_BASIC;
|
||||
num_basic_rates++;
|
||||
}
|
||||
wpa_printf(MSG_DEBUG, "RATE[%d] rate=%d flags=0x%x",
|
||||
hapd->iface->num_rates, rate->rate, rate->flags);
|
||||
hapd->iface->num_rates++;
|
||||
iface->num_rates, rate->rate, rate->flags);
|
||||
iface->num_rates++;
|
||||
}
|
||||
|
||||
if (hapd->iface->num_rates == 0 || num_basic_rates == 0) {
|
||||
if ((iface->num_rates == 0 || num_basic_rates == 0) &&
|
||||
(!iface->conf->ieee80211n || !iface->conf->require_ht)) {
|
||||
wpa_printf(MSG_ERROR, "No rates remaining in supported/basic "
|
||||
"rate sets (%d,%d).",
|
||||
hapd->iface->num_rates, num_basic_rates);
|
||||
iface->num_rates, num_basic_rates);
|
||||
return -1;
|
||||
}
|
||||
|
||||
@ -265,11 +272,11 @@ static void ieee80211n_get_pri_sec_chan(struct wpa_scan_res *bss,
|
||||
oper = (struct ieee80211_ht_operation *) elems.ht_operation;
|
||||
*pri_chan = oper->control_chan;
|
||||
if (oper->ht_param & HT_INFO_HT_PARAM_REC_TRANS_CHNL_WIDTH) {
|
||||
if (oper->ht_param &
|
||||
HT_INFO_HT_PARAM_SECONDARY_CHNL_ABOVE)
|
||||
int sec = oper->ht_param &
|
||||
HT_INFO_HT_PARAM_SECONDARY_CHNL_OFF_MASK;
|
||||
if (sec == HT_INFO_HT_PARAM_SECONDARY_CHNL_ABOVE)
|
||||
*sec_chan = *pri_chan + 4;
|
||||
else if (oper->ht_param &
|
||||
HT_INFO_HT_PARAM_SECONDARY_CHNL_BELOW)
|
||||
else if (sec == HT_INFO_HT_PARAM_SECONDARY_CHNL_BELOW)
|
||||
*sec_chan = *pri_chan - 4;
|
||||
}
|
||||
}
|
||||
@ -406,27 +413,14 @@ static int ieee80211n_check_40mhz_2g4(struct hostapd_iface *iface,
|
||||
}
|
||||
|
||||
|
||||
static void wpa_scan_results_free(struct wpa_scan_results *res)
|
||||
{
|
||||
size_t i;
|
||||
|
||||
if (res == NULL)
|
||||
return;
|
||||
|
||||
for (i = 0; i < res->num; i++)
|
||||
os_free(res->res[i]);
|
||||
os_free(res->res);
|
||||
os_free(res);
|
||||
}
|
||||
|
||||
|
||||
static void ieee80211n_check_scan(struct hostapd_iface *iface)
|
||||
{
|
||||
struct wpa_scan_results *scan_res;
|
||||
int oper40;
|
||||
int res;
|
||||
|
||||
/* Check list of neighboring BSSes (from scan) to see whether 40 MHz is
|
||||
* allowed per IEEE 802.11n/D7.0, 11.14.3.2 */
|
||||
* allowed per IEEE Std 802.11-2012, 10.15.3.2 */
|
||||
|
||||
iface->scan_cb = NULL;
|
||||
|
||||
@ -452,7 +446,48 @@ static void ieee80211n_check_scan(struct hostapd_iface *iface)
|
||||
iface->conf->ht_capab &= ~HT_CAP_INFO_SUPP_CHANNEL_WIDTH_SET;
|
||||
}
|
||||
|
||||
hostapd_setup_interface_complete(iface, 0);
|
||||
res = ieee80211n_allowed_ht40_channel_pair(iface);
|
||||
hostapd_setup_interface_complete(iface, !res);
|
||||
}
|
||||
|
||||
|
||||
static void ieee80211n_scan_channels_2g4(struct hostapd_iface *iface,
|
||||
struct wpa_driver_scan_params *params)
|
||||
{
|
||||
/* Scan only the affected frequency range */
|
||||
int pri_freq, sec_freq;
|
||||
int affected_start, affected_end;
|
||||
int i, pos;
|
||||
struct hostapd_hw_modes *mode;
|
||||
|
||||
if (iface->current_mode == NULL)
|
||||
return;
|
||||
|
||||
pri_freq = hostapd_hw_get_freq(iface->bss[0], iface->conf->channel);
|
||||
if (iface->conf->secondary_channel > 0)
|
||||
sec_freq = pri_freq + 20;
|
||||
else
|
||||
sec_freq = pri_freq - 20;
|
||||
affected_start = (pri_freq + sec_freq) / 2 - 25;
|
||||
affected_end = (pri_freq + sec_freq) / 2 + 25;
|
||||
wpa_printf(MSG_DEBUG, "40 MHz affected channel range: [%d,%d] MHz",
|
||||
affected_start, affected_end);
|
||||
|
||||
mode = iface->current_mode;
|
||||
params->freqs = os_calloc(mode->num_channels + 1, sizeof(int));
|
||||
if (params->freqs == NULL)
|
||||
return;
|
||||
pos = 0;
|
||||
|
||||
for (i = 0; i < mode->num_channels; i++) {
|
||||
struct hostapd_channel_data *chan = &mode->channels[i];
|
||||
if (chan->flag & HOSTAPD_CHAN_DISABLED)
|
||||
continue;
|
||||
if (chan->freq < affected_start ||
|
||||
chan->freq > affected_end)
|
||||
continue;
|
||||
params->freqs[pos++] = chan->freq;
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
@ -466,12 +501,15 @@ static int ieee80211n_check_40mhz(struct hostapd_iface *iface)
|
||||
wpa_printf(MSG_DEBUG, "Scan for neighboring BSSes prior to enabling "
|
||||
"40 MHz channel");
|
||||
os_memset(¶ms, 0, sizeof(params));
|
||||
/* TODO: scan only the needed frequency */
|
||||
if (iface->current_mode->mode == HOSTAPD_MODE_IEEE80211G)
|
||||
ieee80211n_scan_channels_2g4(iface, ¶ms);
|
||||
if (hostapd_driver_scan(iface->bss[0], ¶ms) < 0) {
|
||||
wpa_printf(MSG_ERROR, "Failed to request a scan of "
|
||||
"neighboring BSSes");
|
||||
os_free(params.freqs);
|
||||
return -1;
|
||||
}
|
||||
os_free(params.freqs);
|
||||
|
||||
iface->scan_cb = ieee80211n_check_scan;
|
||||
return 1;
|
||||
@ -483,9 +521,6 @@ static int ieee80211n_supported_ht_capab(struct hostapd_iface *iface)
|
||||
u16 hw = iface->current_mode->ht_capab;
|
||||
u16 conf = iface->conf->ht_capab;
|
||||
|
||||
if (!iface->conf->ieee80211n)
|
||||
return 1;
|
||||
|
||||
if ((conf & HT_CAP_INFO_LDPC_CODING_CAP) &&
|
||||
!(hw & HT_CAP_INFO_LDPC_CODING_CAP)) {
|
||||
wpa_printf(MSG_ERROR, "Driver does not support configured "
|
||||
@ -585,13 +620,15 @@ int hostapd_check_ht_capab(struct hostapd_iface *iface)
|
||||
{
|
||||
#ifdef CONFIG_IEEE80211N
|
||||
int ret;
|
||||
if (!iface->conf->ieee80211n)
|
||||
return 0;
|
||||
if (!ieee80211n_supported_ht_capab(iface))
|
||||
return -1;
|
||||
ret = ieee80211n_check_40mhz(iface);
|
||||
if (ret)
|
||||
return ret;
|
||||
if (!ieee80211n_allowed_ht40_channel_pair(iface))
|
||||
return -1;
|
||||
if (!ieee80211n_supported_ht_capab(iface))
|
||||
return -1;
|
||||
#endif /* CONFIG_IEEE80211N */
|
||||
|
||||
return 0;
|
||||
@ -601,7 +638,7 @@ int hostapd_check_ht_capab(struct hostapd_iface *iface)
|
||||
/**
|
||||
* hostapd_select_hw_mode - Select the hardware mode
|
||||
* @iface: Pointer to interface data.
|
||||
* Returns: 0 on success, -1 on failure
|
||||
* Returns: 0 on success, < 0 on failure
|
||||
*
|
||||
* Sets up the hardware mode, channel, rates, and passive scanning
|
||||
* based on the configuration.
|
||||
@ -628,18 +665,58 @@ int hostapd_select_hw_mode(struct hostapd_iface *iface)
|
||||
hostapd_logger(iface->bss[0], NULL, HOSTAPD_MODULE_IEEE80211,
|
||||
HOSTAPD_LEVEL_WARNING,
|
||||
"Hardware does not support configured mode "
|
||||
"(%d)", (int) iface->conf->hw_mode);
|
||||
return -1;
|
||||
"(%d) (hw_mode in hostapd.conf)",
|
||||
(int) iface->conf->hw_mode);
|
||||
return -2;
|
||||
}
|
||||
|
||||
ok = 0;
|
||||
for (j = 0; j < iface->current_mode->num_channels; j++) {
|
||||
struct hostapd_channel_data *chan =
|
||||
&iface->current_mode->channels[j];
|
||||
if (!(chan->flag & HOSTAPD_CHAN_DISABLED) &&
|
||||
(chan->chan == iface->conf->channel)) {
|
||||
ok = 1;
|
||||
break;
|
||||
if (chan->chan == iface->conf->channel) {
|
||||
if (chan->flag & HOSTAPD_CHAN_DISABLED) {
|
||||
wpa_printf(MSG_ERROR,
|
||||
"channel [%i] (%i) is disabled for "
|
||||
"use in AP mode, flags: 0x%x%s%s%s",
|
||||
j, chan->chan, chan->flag,
|
||||
chan->flag & HOSTAPD_CHAN_NO_IBSS ?
|
||||
" NO-IBSS" : "",
|
||||
chan->flag &
|
||||
HOSTAPD_CHAN_PASSIVE_SCAN ?
|
||||
" PASSIVE-SCAN" : "",
|
||||
chan->flag & HOSTAPD_CHAN_RADAR ?
|
||||
" RADAR" : "");
|
||||
} else {
|
||||
ok = 1;
|
||||
break;
|
||||
}
|
||||
}
|
||||
}
|
||||
if (ok && iface->conf->secondary_channel) {
|
||||
int sec_ok = 0;
|
||||
int sec_chan = iface->conf->channel +
|
||||
iface->conf->secondary_channel * 4;
|
||||
for (j = 0; j < iface->current_mode->num_channels; j++) {
|
||||
struct hostapd_channel_data *chan =
|
||||
&iface->current_mode->channels[j];
|
||||
if (!(chan->flag & HOSTAPD_CHAN_DISABLED) &&
|
||||
(chan->chan == sec_chan)) {
|
||||
sec_ok = 1;
|
||||
break;
|
||||
}
|
||||
}
|
||||
if (!sec_ok) {
|
||||
hostapd_logger(iface->bss[0], NULL,
|
||||
HOSTAPD_MODULE_IEEE80211,
|
||||
HOSTAPD_LEVEL_WARNING,
|
||||
"Configured HT40 secondary channel "
|
||||
"(%d) not found from the channel list "
|
||||
"of current mode (%d) %s",
|
||||
sec_chan, iface->current_mode->mode,
|
||||
hostapd_hw_mode_txt(
|
||||
iface->current_mode->mode));
|
||||
ok = 0;
|
||||
}
|
||||
}
|
||||
if (iface->conf->channel == 0) {
|
||||
@ -647,7 +724,7 @@ int hostapd_select_hw_mode(struct hostapd_iface *iface)
|
||||
* the channel automatically */
|
||||
wpa_printf(MSG_ERROR, "Channel not configured "
|
||||
"(hw_mode/channel in hostapd.conf)");
|
||||
return -1;
|
||||
return -3;
|
||||
}
|
||||
if (ok == 0 && iface->conf->channel != 0) {
|
||||
hostapd_logger(iface->bss[0], NULL,
|
||||
@ -665,15 +742,7 @@ int hostapd_select_hw_mode(struct hostapd_iface *iface)
|
||||
hostapd_logger(iface->bss[0], NULL, HOSTAPD_MODULE_IEEE80211,
|
||||
HOSTAPD_LEVEL_WARNING,
|
||||
"Hardware does not support configured channel");
|
||||
return -1;
|
||||
}
|
||||
|
||||
if (hostapd_prepare_rates(iface->bss[0], iface->current_mode)) {
|
||||
wpa_printf(MSG_ERROR, "Failed to prepare rates table.");
|
||||
hostapd_logger(iface->bss[0], NULL, HOSTAPD_MODULE_IEEE80211,
|
||||
HOSTAPD_LEVEL_WARNING,
|
||||
"Failed to prepare rates table.");
|
||||
return -1;
|
||||
return -4;
|
||||
}
|
||||
|
||||
return 0;
|
||||
@ -689,6 +758,8 @@ const char * hostapd_hw_mode_txt(int mode)
|
||||
return "IEEE 802.11b";
|
||||
case HOSTAPD_MODE_IEEE80211G:
|
||||
return "IEEE 802.11g";
|
||||
case HOSTAPD_MODE_IEEE80211AD:
|
||||
return "IEEE 802.11ad";
|
||||
default:
|
||||
return "UNKNOWN";
|
||||
}
|
||||
|
@ -2,6 +2,7 @@
|
||||
* hostapd / Hardware feature query and different modes
|
||||
* Copyright 2002-2003, Instant802 Networks, Inc.
|
||||
* Copyright 2005-2006, Devicescape Software, Inc.
|
||||
* Copyright (c) 2008-2011, Jouni Malinen <j@w1.fi>
|
||||
*
|
||||
* This program is free software; you can redistribute it and/or modify
|
||||
* it under the terms of the GNU General Public License version 2 as
|
||||
@ -25,6 +26,8 @@ const char * hostapd_hw_mode_txt(int mode);
|
||||
int hostapd_hw_get_freq(struct hostapd_data *hapd, int chan);
|
||||
int hostapd_hw_get_channel(struct hostapd_data *hapd, int freq);
|
||||
int hostapd_check_ht_capab(struct hostapd_iface *iface);
|
||||
int hostapd_prepare_rates(struct hostapd_iface *iface,
|
||||
struct hostapd_hw_modes *mode);
|
||||
#else /* NEED_AP_MLME */
|
||||
static inline void
|
||||
hostapd_free_hw_features(struct hostapd_hw_modes *hw_features,
|
||||
@ -39,7 +42,7 @@ static inline int hostapd_get_hw_features(struct hostapd_iface *iface)
|
||||
|
||||
static inline int hostapd_select_hw_mode(struct hostapd_iface *iface)
|
||||
{
|
||||
return -1;
|
||||
return -100;
|
||||
}
|
||||
|
||||
static inline const char * hostapd_hw_mode_txt(int mode)
|
||||
@ -57,6 +60,12 @@ static inline int hostapd_check_ht_capab(struct hostapd_iface *iface)
|
||||
return 0;
|
||||
}
|
||||
|
||||
static inline int hostapd_prepare_rates(struct hostapd_iface *iface,
|
||||
struct hostapd_hw_modes *mode)
|
||||
{
|
||||
return 0;
|
||||
}
|
||||
|
||||
#endif /* NEED_AP_MLME */
|
||||
|
||||
#endif /* HW_FEATURES_H */
|
||||
|
@ -2,14 +2,8 @@
|
||||
* hostapd / IEEE 802.11F-2003 Inter-Access Point Protocol (IAPP)
|
||||
* Copyright (c) 2002-2007, Jouni Malinen <j@w1.fi>
|
||||
*
|
||||
* This program is free software; you can redistribute it and/or modify
|
||||
* it under the terms of the GNU General Public License version 2 as
|
||||
* published by the Free Software Foundation.
|
||||
*
|
||||
* Alternatively, this software may be distributed under the terms of BSD
|
||||
* license.
|
||||
*
|
||||
* See README and COPYING for more details.
|
||||
* This software may be distributed under the terms of the BSD license.
|
||||
* See README for more details.
|
||||
*
|
||||
* Note: IEEE 802.11F-2003 was a experimental use specification. It has expired
|
||||
* and IEEE has withdrawn it. In other words, it is likely better to look at
|
||||
|
@ -2,14 +2,8 @@
|
||||
* hostapd / IEEE 802.11F-2003 Inter-Access Point Protocol (IAPP)
|
||||
* Copyright (c) 2002-2005, Jouni Malinen <j@w1.fi>
|
||||
*
|
||||
* This program is free software; you can redistribute it and/or modify
|
||||
* it under the terms of the GNU General Public License version 2 as
|
||||
* published by the Free Software Foundation.
|
||||
*
|
||||
* Alternatively, this software may be distributed under the terms of BSD
|
||||
* license.
|
||||
*
|
||||
* See README and COPYING for more details.
|
||||
* This software may be distributed under the terms of the BSD license.
|
||||
* See README for more details.
|
||||
*/
|
||||
|
||||
#ifndef IAPP_H
|
||||
|
File diff suppressed because it is too large
Load Diff
@ -2,14 +2,8 @@
|
||||
* hostapd / IEEE 802.11 Management
|
||||
* Copyright (c) 2002-2009, Jouni Malinen <j@w1.fi>
|
||||
*
|
||||
* This program is free software; you can redistribute it and/or modify
|
||||
* it under the terms of the GNU General Public License version 2 as
|
||||
* published by the Free Software Foundation.
|
||||
*
|
||||
* Alternatively, this software may be distributed under the terms of BSD
|
||||
* license.
|
||||
*
|
||||
* See README and COPYING for more details.
|
||||
* This software may be distributed under the terms of the BSD license.
|
||||
* See README for more details.
|
||||
*/
|
||||
|
||||
#ifndef IEEE802_11_H
|
||||
@ -46,22 +40,42 @@ static inline int ieee802_11_get_mib_sta(struct hostapd_data *hapd,
|
||||
#endif /* NEED_AP_MLME */
|
||||
u16 hostapd_own_capab_info(struct hostapd_data *hapd, struct sta_info *sta,
|
||||
int probe);
|
||||
u8 * hostapd_eid_ext_capab(struct hostapd_data *hapd, u8 *eid);
|
||||
u8 * hostapd_eid_supp_rates(struct hostapd_data *hapd, u8 *eid);
|
||||
u8 * hostapd_eid_ext_supp_rates(struct hostapd_data *hapd, u8 *eid);
|
||||
u8 * hostapd_eid_ht_capabilities(struct hostapd_data *hapd, u8 *eid);
|
||||
u8 * hostapd_eid_ht_operation(struct hostapd_data *hapd, u8 *eid);
|
||||
u8 * hostapd_eid_vht_capabilities(struct hostapd_data *hapd, u8 *eid);
|
||||
u8 * hostapd_eid_vht_operation(struct hostapd_data *hapd, u8 *eid);
|
||||
int hostapd_ht_operation_update(struct hostapd_iface *iface);
|
||||
void ieee802_11_send_sa_query_req(struct hostapd_data *hapd,
|
||||
const u8 *addr, const u8 *trans_id);
|
||||
void hostapd_get_ht_capab(struct hostapd_data *hapd,
|
||||
struct ieee80211_ht_capabilities *ht_cap,
|
||||
struct ieee80211_ht_capabilities *neg_ht_cap);
|
||||
u16 copy_sta_ht_capab(struct sta_info *sta, const u8 *ht_capab,
|
||||
size_t ht_capab_len);
|
||||
u16 copy_sta_ht_capab(struct hostapd_data *hapd, struct sta_info *sta,
|
||||
const u8 *ht_capab, size_t ht_capab_len);
|
||||
void update_ht_state(struct hostapd_data *hapd, struct sta_info *sta);
|
||||
u16 copy_sta_vht_capab(struct hostapd_data *hapd, struct sta_info *sta,
|
||||
const u8 *vht_capab, size_t vht_capab_len);
|
||||
void hostapd_tx_status(struct hostapd_data *hapd, const u8 *addr,
|
||||
const u8 *buf, size_t len, int ack);
|
||||
void hostapd_eapol_tx_status(struct hostapd_data *hapd, const u8 *dst,
|
||||
const u8 *data, size_t len, int ack);
|
||||
void ieee802_11_rx_from_unknown(struct hostapd_data *hapd, const u8 *src,
|
||||
int wds);
|
||||
u8 * hostapd_eid_assoc_comeback_time(struct hostapd_data *hapd,
|
||||
struct sta_info *sta, u8 *eid);
|
||||
void ieee802_11_sa_query_action(struct hostapd_data *hapd,
|
||||
const u8 *sa, const u8 action_type,
|
||||
const u8 *trans_id);
|
||||
u8 * hostapd_eid_interworking(struct hostapd_data *hapd, u8 *eid);
|
||||
u8 * hostapd_eid_adv_proto(struct hostapd_data *hapd, u8 *eid);
|
||||
u8 * hostapd_eid_roaming_consortium(struct hostapd_data *hapd, u8 *eid);
|
||||
u8 * hostapd_eid_time_adv(struct hostapd_data *hapd, u8 *eid);
|
||||
u8 * hostapd_eid_time_zone(struct hostapd_data *hapd, u8 *eid);
|
||||
int hostapd_update_time_adv(struct hostapd_data *hapd);
|
||||
void hostapd_client_poll_ok(struct hostapd_data *hapd, const u8 *addr);
|
||||
u8 * hostapd_eid_bss_max_idle_period(struct hostapd_data *hapd, u8 *eid);
|
||||
|
||||
#endif /* IEEE802_11_H */
|
||||
|
@ -1,15 +1,9 @@
|
||||
/*
|
||||
* hostapd / IEEE 802.11 authentication (ACL)
|
||||
* Copyright (c) 2003-2009, Jouni Malinen <j@w1.fi>
|
||||
* Copyright (c) 2003-2012, Jouni Malinen <j@w1.fi>
|
||||
*
|
||||
* This program is free software; you can redistribute it and/or modify
|
||||
* it under the terms of the GNU General Public License version 2 as
|
||||
* published by the Free Software Foundation.
|
||||
*
|
||||
* Alternatively, this software may be distributed under the terms of BSD
|
||||
* license.
|
||||
*
|
||||
* See README and COPYING for more details.
|
||||
* This software may be distributed under the terms of the BSD license.
|
||||
* See README for more details.
|
||||
*
|
||||
* Access control list for IEEE 802.11 authentication can uses statically
|
||||
* configured ACL from configuration files or an external RADIUS server.
|
||||
@ -21,29 +15,35 @@
|
||||
|
||||
#include "utils/common.h"
|
||||
#include "utils/eloop.h"
|
||||
#include "crypto/sha1.h"
|
||||
#include "radius/radius.h"
|
||||
#include "radius/radius_client.h"
|
||||
#include "hostapd.h"
|
||||
#include "ap_config.h"
|
||||
#include "ap_drv_ops.h"
|
||||
#include "ieee802_11.h"
|
||||
#include "ieee802_1x.h"
|
||||
#include "ieee802_11_auth.h"
|
||||
|
||||
#define RADIUS_ACL_TIMEOUT 30
|
||||
|
||||
|
||||
struct hostapd_cached_radius_acl {
|
||||
time_t timestamp;
|
||||
os_time_t timestamp;
|
||||
macaddr addr;
|
||||
int accepted; /* HOSTAPD_ACL_* */
|
||||
struct hostapd_cached_radius_acl *next;
|
||||
u32 session_timeout;
|
||||
u32 acct_interim_interval;
|
||||
int vlan_id;
|
||||
struct hostapd_sta_wpa_psk_short *psk;
|
||||
char *identity;
|
||||
char *radius_cui;
|
||||
};
|
||||
|
||||
|
||||
struct hostapd_acl_query_data {
|
||||
time_t timestamp;
|
||||
os_time_t timestamp;
|
||||
u8 radius_id;
|
||||
macaddr addr;
|
||||
u8 *auth_msg; /* IEEE 802.11 authentication frame from station */
|
||||
@ -53,6 +53,15 @@ struct hostapd_acl_query_data {
|
||||
|
||||
|
||||
#ifndef CONFIG_NO_RADIUS
|
||||
static void hostapd_acl_cache_free_entry(struct hostapd_cached_radius_acl *e)
|
||||
{
|
||||
os_free(e->identity);
|
||||
os_free(e->radius_cui);
|
||||
hostapd_free_psk_list(e->psk);
|
||||
os_free(e);
|
||||
}
|
||||
|
||||
|
||||
static void hostapd_acl_cache_free(struct hostapd_cached_radius_acl *acl_cache)
|
||||
{
|
||||
struct hostapd_cached_radius_acl *prev;
|
||||
@ -60,38 +69,73 @@ static void hostapd_acl_cache_free(struct hostapd_cached_radius_acl *acl_cache)
|
||||
while (acl_cache) {
|
||||
prev = acl_cache;
|
||||
acl_cache = acl_cache->next;
|
||||
os_free(prev);
|
||||
hostapd_acl_cache_free_entry(prev);
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
static void copy_psk_list(struct hostapd_sta_wpa_psk_short **psk,
|
||||
struct hostapd_sta_wpa_psk_short *src)
|
||||
{
|
||||
struct hostapd_sta_wpa_psk_short **copy_to;
|
||||
struct hostapd_sta_wpa_psk_short *copy_from;
|
||||
|
||||
/* Copy PSK linked list */
|
||||
copy_to = psk;
|
||||
copy_from = src;
|
||||
while (copy_from && copy_to) {
|
||||
*copy_to = os_zalloc(sizeof(struct hostapd_sta_wpa_psk_short));
|
||||
if (*copy_to == NULL)
|
||||
break;
|
||||
os_memcpy(*copy_to, copy_from,
|
||||
sizeof(struct hostapd_sta_wpa_psk_short));
|
||||
copy_from = copy_from->next;
|
||||
copy_to = &((*copy_to)->next);
|
||||
}
|
||||
if (copy_to)
|
||||
*copy_to = NULL;
|
||||
}
|
||||
|
||||
|
||||
static int hostapd_acl_cache_get(struct hostapd_data *hapd, const u8 *addr,
|
||||
u32 *session_timeout,
|
||||
u32 *acct_interim_interval, int *vlan_id)
|
||||
u32 *acct_interim_interval, int *vlan_id,
|
||||
struct hostapd_sta_wpa_psk_short **psk,
|
||||
char **identity, char **radius_cui)
|
||||
{
|
||||
struct hostapd_cached_radius_acl *entry;
|
||||
time_t now;
|
||||
struct os_time now;
|
||||
|
||||
time(&now);
|
||||
entry = hapd->acl_cache;
|
||||
os_get_time(&now);
|
||||
|
||||
while (entry) {
|
||||
if (os_memcmp(entry->addr, addr, ETH_ALEN) == 0) {
|
||||
if (now - entry->timestamp > RADIUS_ACL_TIMEOUT)
|
||||
return -1; /* entry has expired */
|
||||
if (entry->accepted == HOSTAPD_ACL_ACCEPT_TIMEOUT)
|
||||
if (session_timeout)
|
||||
*session_timeout =
|
||||
entry->session_timeout;
|
||||
if (acct_interim_interval)
|
||||
*acct_interim_interval =
|
||||
entry->acct_interim_interval;
|
||||
if (vlan_id)
|
||||
*vlan_id = entry->vlan_id;
|
||||
return entry->accepted;
|
||||
for (entry = hapd->acl_cache; entry; entry = entry->next) {
|
||||
if (os_memcmp(entry->addr, addr, ETH_ALEN) != 0)
|
||||
continue;
|
||||
|
||||
if (now.sec - entry->timestamp > RADIUS_ACL_TIMEOUT)
|
||||
return -1; /* entry has expired */
|
||||
if (entry->accepted == HOSTAPD_ACL_ACCEPT_TIMEOUT)
|
||||
if (session_timeout)
|
||||
*session_timeout = entry->session_timeout;
|
||||
if (acct_interim_interval)
|
||||
*acct_interim_interval =
|
||||
entry->acct_interim_interval;
|
||||
if (vlan_id)
|
||||
*vlan_id = entry->vlan_id;
|
||||
copy_psk_list(psk, entry->psk);
|
||||
if (identity) {
|
||||
if (entry->identity)
|
||||
*identity = os_strdup(entry->identity);
|
||||
else
|
||||
*identity = NULL;
|
||||
}
|
||||
|
||||
entry = entry->next;
|
||||
if (radius_cui) {
|
||||
if (entry->radius_cui)
|
||||
*radius_cui = os_strdup(entry->radius_cui);
|
||||
else
|
||||
*radius_cui = NULL;
|
||||
}
|
||||
return entry->accepted;
|
||||
}
|
||||
|
||||
return -1;
|
||||
@ -137,37 +181,9 @@ static int hostapd_radius_acl_query(struct hostapd_data *hapd, const u8 *addr,
|
||||
goto fail;
|
||||
}
|
||||
|
||||
if (hapd->conf->own_ip_addr.af == AF_INET &&
|
||||
!radius_msg_add_attr(msg, RADIUS_ATTR_NAS_IP_ADDRESS,
|
||||
(u8 *) &hapd->conf->own_ip_addr.u.v4, 4)) {
|
||||
wpa_printf(MSG_DEBUG, "Could not add NAS-IP-Address");
|
||||
if (add_common_radius_attr(hapd, hapd->conf->radius_auth_req_attr,
|
||||
NULL, msg) < 0)
|
||||
goto fail;
|
||||
}
|
||||
|
||||
#ifdef CONFIG_IPV6
|
||||
if (hapd->conf->own_ip_addr.af == AF_INET6 &&
|
||||
!radius_msg_add_attr(msg, RADIUS_ATTR_NAS_IPV6_ADDRESS,
|
||||
(u8 *) &hapd->conf->own_ip_addr.u.v6, 16)) {
|
||||
wpa_printf(MSG_DEBUG, "Could not add NAS-IPv6-Address");
|
||||
goto fail;
|
||||
}
|
||||
#endif /* CONFIG_IPV6 */
|
||||
|
||||
if (hapd->conf->nas_identifier &&
|
||||
!radius_msg_add_attr(msg, RADIUS_ATTR_NAS_IDENTIFIER,
|
||||
(u8 *) hapd->conf->nas_identifier,
|
||||
os_strlen(hapd->conf->nas_identifier))) {
|
||||
wpa_printf(MSG_DEBUG, "Could not add NAS-Identifier");
|
||||
goto fail;
|
||||
}
|
||||
|
||||
os_snprintf(buf, sizeof(buf), RADIUS_802_1X_ADDR_FORMAT ":%s",
|
||||
MAC2STR(hapd->own_addr), hapd->conf->ssid.ssid);
|
||||
if (!radius_msg_add_attr(msg, RADIUS_ATTR_CALLED_STATION_ID,
|
||||
(u8 *) buf, os_strlen(buf))) {
|
||||
wpa_printf(MSG_DEBUG, "Could not add Called-Station-Id");
|
||||
goto fail;
|
||||
}
|
||||
|
||||
os_snprintf(buf, sizeof(buf), RADIUS_802_1X_ADDR_FORMAT,
|
||||
MAC2STR(addr));
|
||||
@ -177,12 +193,6 @@ static int hostapd_radius_acl_query(struct hostapd_data *hapd, const u8 *addr,
|
||||
goto fail;
|
||||
}
|
||||
|
||||
if (!radius_msg_add_attr_int32(msg, RADIUS_ATTR_NAS_PORT_TYPE,
|
||||
RADIUS_NAS_PORT_TYPE_IEEE_802_11)) {
|
||||
wpa_printf(MSG_DEBUG, "Could not add NAS-Port-Type");
|
||||
goto fail;
|
||||
}
|
||||
|
||||
os_snprintf(buf, sizeof(buf), "CONNECT 11Mbps 802.11b");
|
||||
if (!radius_msg_add_attr(msg, RADIUS_ATTR_CONNECT_INFO,
|
||||
(u8 *) buf, os_strlen(buf))) {
|
||||
@ -190,7 +200,8 @@ static int hostapd_radius_acl_query(struct hostapd_data *hapd, const u8 *addr,
|
||||
goto fail;
|
||||
}
|
||||
|
||||
radius_client_send(hapd->radius, msg, RADIUS_AUTH, addr);
|
||||
if (radius_client_send(hapd->radius, msg, RADIUS_AUTH, addr) < 0)
|
||||
goto fail;
|
||||
return 0;
|
||||
|
||||
fail:
|
||||
@ -209,11 +220,19 @@ static int hostapd_radius_acl_query(struct hostapd_data *hapd, const u8 *addr,
|
||||
* @session_timeout: Buffer for returning session timeout (from RADIUS)
|
||||
* @acct_interim_interval: Buffer for returning account interval (from RADIUS)
|
||||
* @vlan_id: Buffer for returning VLAN ID
|
||||
* @psk: Linked list buffer for returning WPA PSK
|
||||
* @identity: Buffer for returning identity (from RADIUS)
|
||||
* @radius_cui: Buffer for returning CUI (from RADIUS)
|
||||
* Returns: HOSTAPD_ACL_ACCEPT, HOSTAPD_ACL_REJECT, or HOSTAPD_ACL_PENDING
|
||||
*
|
||||
* The caller is responsible for freeing the returned *identity and *radius_cui
|
||||
* values with os_free().
|
||||
*/
|
||||
int hostapd_allowed_address(struct hostapd_data *hapd, const u8 *addr,
|
||||
const u8 *msg, size_t len, u32 *session_timeout,
|
||||
u32 *acct_interim_interval, int *vlan_id)
|
||||
u32 *acct_interim_interval, int *vlan_id,
|
||||
struct hostapd_sta_wpa_psk_short **psk,
|
||||
char **identity, char **radius_cui)
|
||||
{
|
||||
if (session_timeout)
|
||||
*session_timeout = 0;
|
||||
@ -221,6 +240,12 @@ int hostapd_allowed_address(struct hostapd_data *hapd, const u8 *addr,
|
||||
*acct_interim_interval = 0;
|
||||
if (vlan_id)
|
||||
*vlan_id = 0;
|
||||
if (psk)
|
||||
*psk = NULL;
|
||||
if (identity)
|
||||
*identity = NULL;
|
||||
if (radius_cui)
|
||||
*radius_cui = NULL;
|
||||
|
||||
if (hostapd_maclist_found(hapd->conf->accept_mac,
|
||||
hapd->conf->num_accept_mac, addr, vlan_id))
|
||||
@ -240,11 +265,13 @@ int hostapd_allowed_address(struct hostapd_data *hapd, const u8 *addr,
|
||||
return HOSTAPD_ACL_REJECT;
|
||||
#else /* CONFIG_NO_RADIUS */
|
||||
struct hostapd_acl_query_data *query;
|
||||
struct os_time t;
|
||||
|
||||
/* Check whether ACL cache has an entry for this station */
|
||||
int res = hostapd_acl_cache_get(hapd, addr, session_timeout,
|
||||
acct_interim_interval,
|
||||
vlan_id);
|
||||
vlan_id, psk,
|
||||
identity, radius_cui);
|
||||
if (res == HOSTAPD_ACL_ACCEPT ||
|
||||
res == HOSTAPD_ACL_ACCEPT_TIMEOUT)
|
||||
return res;
|
||||
@ -256,6 +283,14 @@ int hostapd_allowed_address(struct hostapd_data *hapd, const u8 *addr,
|
||||
if (os_memcmp(query->addr, addr, ETH_ALEN) == 0) {
|
||||
/* pending query in RADIUS retransmit queue;
|
||||
* do not generate a new one */
|
||||
if (identity) {
|
||||
os_free(*identity);
|
||||
*identity = NULL;
|
||||
}
|
||||
if (radius_cui) {
|
||||
os_free(*radius_cui);
|
||||
*radius_cui = NULL;
|
||||
}
|
||||
return HOSTAPD_ACL_PENDING;
|
||||
}
|
||||
query = query->next;
|
||||
@ -270,7 +305,8 @@ int hostapd_allowed_address(struct hostapd_data *hapd, const u8 *addr,
|
||||
wpa_printf(MSG_ERROR, "malloc for query data failed");
|
||||
return HOSTAPD_ACL_REJECT;
|
||||
}
|
||||
time(&query->timestamp);
|
||||
os_get_time(&t);
|
||||
query->timestamp = t.sec;
|
||||
os_memcpy(query->addr, addr, ETH_ALEN);
|
||||
if (hostapd_radius_acl_query(hapd, addr, query)) {
|
||||
wpa_printf(MSG_DEBUG, "Failed to send Access-Request "
|
||||
@ -302,7 +338,7 @@ int hostapd_allowed_address(struct hostapd_data *hapd, const u8 *addr,
|
||||
|
||||
|
||||
#ifndef CONFIG_NO_RADIUS
|
||||
static void hostapd_acl_expire_cache(struct hostapd_data *hapd, time_t now)
|
||||
static void hostapd_acl_expire_cache(struct hostapd_data *hapd, os_time_t now)
|
||||
{
|
||||
struct hostapd_cached_radius_acl *prev, *entry, *tmp;
|
||||
|
||||
@ -317,12 +353,10 @@ static void hostapd_acl_expire_cache(struct hostapd_data *hapd, time_t now)
|
||||
prev->next = entry->next;
|
||||
else
|
||||
hapd->acl_cache = entry->next;
|
||||
#ifdef CONFIG_DRIVER_RADIUS_ACL
|
||||
hapd->drv.set_radius_acl_expire(hapd, entry->addr);
|
||||
#endif /* CONFIG_DRIVER_RADIUS_ACL */
|
||||
hostapd_drv_set_radius_acl_expire(hapd, entry->addr);
|
||||
tmp = entry;
|
||||
entry = entry->next;
|
||||
os_free(tmp);
|
||||
hostapd_acl_cache_free_entry(tmp);
|
||||
continue;
|
||||
}
|
||||
|
||||
@ -332,7 +366,8 @@ static void hostapd_acl_expire_cache(struct hostapd_data *hapd, time_t now)
|
||||
}
|
||||
|
||||
|
||||
static void hostapd_acl_expire_queries(struct hostapd_data *hapd, time_t now)
|
||||
static void hostapd_acl_expire_queries(struct hostapd_data *hapd,
|
||||
os_time_t now)
|
||||
{
|
||||
struct hostapd_acl_query_data *prev, *entry, *tmp;
|
||||
|
||||
@ -368,16 +403,64 @@ static void hostapd_acl_expire_queries(struct hostapd_data *hapd, time_t now)
|
||||
static void hostapd_acl_expire(void *eloop_ctx, void *timeout_ctx)
|
||||
{
|
||||
struct hostapd_data *hapd = eloop_ctx;
|
||||
time_t now;
|
||||
struct os_time now;
|
||||
|
||||
time(&now);
|
||||
hostapd_acl_expire_cache(hapd, now);
|
||||
hostapd_acl_expire_queries(hapd, now);
|
||||
os_get_time(&now);
|
||||
hostapd_acl_expire_cache(hapd, now.sec);
|
||||
hostapd_acl_expire_queries(hapd, now.sec);
|
||||
|
||||
eloop_register_timeout(10, 0, hostapd_acl_expire, hapd, NULL);
|
||||
}
|
||||
|
||||
|
||||
static void decode_tunnel_passwords(struct hostapd_data *hapd,
|
||||
const u8 *shared_secret,
|
||||
size_t shared_secret_len,
|
||||
struct radius_msg *msg,
|
||||
struct radius_msg *req,
|
||||
struct hostapd_cached_radius_acl *cache)
|
||||
{
|
||||
int passphraselen;
|
||||
char *passphrase, *strpassphrase;
|
||||
size_t i;
|
||||
struct hostapd_sta_wpa_psk_short *psk;
|
||||
|
||||
/*
|
||||
* Decode all tunnel passwords as PSK and save them into a linked list.
|
||||
*/
|
||||
for (i = 0; ; i++) {
|
||||
passphrase = radius_msg_get_tunnel_password(
|
||||
msg, &passphraselen, shared_secret, shared_secret_len,
|
||||
req, i);
|
||||
/*
|
||||
* Passphrase is NULL iff there is no i-th Tunnel-Password
|
||||
* attribute in msg.
|
||||
*/
|
||||
if (passphrase == NULL)
|
||||
break;
|
||||
/*
|
||||
* passphrase does not contain the NULL termination.
|
||||
* Add it here as pbkdf2_sha1() requires it.
|
||||
*/
|
||||
strpassphrase = os_zalloc(passphraselen + 1);
|
||||
psk = os_zalloc(sizeof(struct hostapd_sta_wpa_psk_short));
|
||||
if (strpassphrase && psk) {
|
||||
os_memcpy(strpassphrase, passphrase, passphraselen);
|
||||
pbkdf2_sha1(strpassphrase,
|
||||
hapd->conf->ssid.ssid,
|
||||
hapd->conf->ssid.ssid_len, 4096,
|
||||
psk->psk, PMK_LEN);
|
||||
psk->next = cache->psk;
|
||||
cache->psk = psk;
|
||||
psk = NULL;
|
||||
}
|
||||
os_free(strpassphrase);
|
||||
os_free(psk);
|
||||
os_free(passphrase);
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
/**
|
||||
* hostapd_acl_recv_radius - Process incoming RADIUS Authentication messages
|
||||
* @msg: RADIUS response message
|
||||
@ -397,6 +480,7 @@ hostapd_acl_recv_radius(struct radius_msg *msg, struct radius_msg *req,
|
||||
struct hostapd_acl_query_data *query, *prev;
|
||||
struct hostapd_cached_radius_acl *cache;
|
||||
struct radius_hdr *hdr = radius_msg_get_hdr(msg);
|
||||
struct os_time t;
|
||||
|
||||
query = hapd->acl_queries;
|
||||
prev = NULL;
|
||||
@ -431,9 +515,13 @@ hostapd_acl_recv_radius(struct radius_msg *msg, struct radius_msg *req,
|
||||
wpa_printf(MSG_DEBUG, "Failed to add ACL cache entry");
|
||||
goto done;
|
||||
}
|
||||
time(&cache->timestamp);
|
||||
os_get_time(&t);
|
||||
cache->timestamp = t.sec;
|
||||
os_memcpy(cache->addr, query->addr, sizeof(cache->addr));
|
||||
if (hdr->code == RADIUS_CODE_ACCESS_ACCEPT) {
|
||||
u8 *buf;
|
||||
size_t len;
|
||||
|
||||
if (radius_msg_get_attr_int32(msg, RADIUS_ATTR_SESSION_TIMEOUT,
|
||||
&cache->session_timeout) == 0)
|
||||
cache->accepted = HOSTAPD_ACL_ACCEPT_TIMEOUT;
|
||||
@ -452,14 +540,35 @@ hostapd_acl_recv_radius(struct radius_msg *msg, struct radius_msg *req,
|
||||
}
|
||||
|
||||
cache->vlan_id = radius_msg_get_vlanid(msg);
|
||||
|
||||
decode_tunnel_passwords(hapd, shared_secret, shared_secret_len,
|
||||
msg, req, cache);
|
||||
|
||||
if (radius_msg_get_attr_ptr(msg, RADIUS_ATTR_USER_NAME,
|
||||
&buf, &len, NULL) == 0) {
|
||||
cache->identity = os_zalloc(len + 1);
|
||||
if (cache->identity)
|
||||
os_memcpy(cache->identity, buf, len);
|
||||
}
|
||||
if (radius_msg_get_attr_ptr(
|
||||
msg, RADIUS_ATTR_CHARGEABLE_USER_IDENTITY,
|
||||
&buf, &len, NULL) == 0) {
|
||||
cache->radius_cui = os_zalloc(len + 1);
|
||||
if (cache->radius_cui)
|
||||
os_memcpy(cache->radius_cui, buf, len);
|
||||
}
|
||||
|
||||
if (hapd->conf->wpa_psk_radius == PSK_RADIUS_REQUIRED &&
|
||||
!cache->psk)
|
||||
cache->accepted = HOSTAPD_ACL_REJECT;
|
||||
} else
|
||||
cache->accepted = HOSTAPD_ACL_REJECT;
|
||||
cache->next = hapd->acl_cache;
|
||||
hapd->acl_cache = cache;
|
||||
|
||||
#ifdef CONFIG_DRIVER_RADIUS_ACL
|
||||
hapd->drv.set_radius_acl_auth(hapd, query->addr, cache->accepted,
|
||||
cache->session_timeout);
|
||||
hostapd_drv_set_radius_acl_auth(hapd, query->addr, cache->accepted,
|
||||
cache->session_timeout);
|
||||
#else /* CONFIG_DRIVER_RADIUS_ACL */
|
||||
#ifdef NEED_AP_MLME
|
||||
/* Re-send original authentication frame for 802.11 processing */
|
||||
@ -522,3 +631,13 @@ void hostapd_acl_deinit(struct hostapd_data *hapd)
|
||||
hostapd_acl_query_free(prev);
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
void hostapd_free_psk_list(struct hostapd_sta_wpa_psk_short *psk)
|
||||
{
|
||||
while (psk) {
|
||||
struct hostapd_sta_wpa_psk_short *prev = psk;
|
||||
psk = psk->next;
|
||||
os_free(prev);
|
||||
}
|
||||
}
|
||||
|
@ -2,14 +2,8 @@
|
||||
* hostapd / IEEE 802.11 authentication (ACL)
|
||||
* Copyright (c) 2003-2005, Jouni Malinen <j@w1.fi>
|
||||
*
|
||||
* This program is free software; you can redistribute it and/or modify
|
||||
* it under the terms of the GNU General Public License version 2 as
|
||||
* published by the Free Software Foundation.
|
||||
*
|
||||
* Alternatively, this software may be distributed under the terms of BSD
|
||||
* license.
|
||||
*
|
||||
* See README and COPYING for more details.
|
||||
* This software may be distributed under the terms of the BSD license.
|
||||
* See README for more details.
|
||||
*/
|
||||
|
||||
#ifndef IEEE802_11_AUTH_H
|
||||
@ -24,8 +18,11 @@ enum {
|
||||
|
||||
int hostapd_allowed_address(struct hostapd_data *hapd, const u8 *addr,
|
||||
const u8 *msg, size_t len, u32 *session_timeout,
|
||||
u32 *acct_interim_interval, int *vlan_id);
|
||||
u32 *acct_interim_interval, int *vlan_id,
|
||||
struct hostapd_sta_wpa_psk_short **psk,
|
||||
char **identity, char **radius_cui);
|
||||
int hostapd_acl_init(struct hostapd_data *hapd);
|
||||
void hostapd_acl_deinit(struct hostapd_data *hapd);
|
||||
void hostapd_free_psk_list(struct hostapd_sta_wpa_psk_short *psk);
|
||||
|
||||
#endif /* IEEE802_11_AUTH_H */
|
||||
|
@ -30,7 +30,8 @@ u8 * hostapd_eid_ht_capabilities(struct hostapd_data *hapd, u8 *eid)
|
||||
struct ieee80211_ht_capabilities *cap;
|
||||
u8 *pos = eid;
|
||||
|
||||
if (!hapd->iconf->ieee80211n || !hapd->iface->current_mode)
|
||||
if (!hapd->iconf->ieee80211n || !hapd->iface->current_mode ||
|
||||
hapd->conf->disable_11n)
|
||||
return eid;
|
||||
|
||||
*pos++ = WLAN_EID_HT_CAP;
|
||||
@ -58,7 +59,7 @@ u8 * hostapd_eid_ht_operation(struct hostapd_data *hapd, u8 *eid)
|
||||
struct ieee80211_ht_operation *oper;
|
||||
u8 *pos = eid;
|
||||
|
||||
if (!hapd->iconf->ieee80211n)
|
||||
if (!hapd->iconf->ieee80211n || hapd->conf->disable_11n)
|
||||
return eid;
|
||||
|
||||
*pos++ = WLAN_EID_HT_OPERATION;
|
||||
@ -92,7 +93,6 @@ Set to 1 (HT non-member protection) if there may be non-HT STAs
|
||||
Set to 2 if only HT STAs are associated in BSS,
|
||||
however and at least one 20 MHz HT STA is associated
|
||||
Set to 3 (HT mixed mode) when one or more non-HT STAs are associated
|
||||
(currently non-GF HT station is considered as non-HT STA also)
|
||||
*/
|
||||
int hostapd_ht_operation_update(struct hostapd_iface *iface)
|
||||
{
|
||||
@ -130,13 +130,8 @@ int hostapd_ht_operation_update(struct hostapd_iface *iface)
|
||||
op_mode_changes++;
|
||||
}
|
||||
|
||||
/* Note: currently we switch to the MIXED op mode if HT non-greenfield
|
||||
* station is associated. Probably it's a theoretical case, since
|
||||
* it looks like all known HT STAs support greenfield.
|
||||
*/
|
||||
new_op_mode = 0;
|
||||
if (iface->num_sta_no_ht ||
|
||||
(iface->ht_op_mode & HT_INFO_OPERATION_MODE_NON_GF_DEVS_PRESENT))
|
||||
if (iface->num_sta_no_ht)
|
||||
new_op_mode = OP_MODE_MIXED;
|
||||
else if ((iface->conf->ht_capab & HT_CAP_INFO_SUPP_CHANNEL_WIDTH_SET)
|
||||
&& iface->num_sta_ht_20mhz)
|
||||
@ -160,11 +155,13 @@ int hostapd_ht_operation_update(struct hostapd_iface *iface)
|
||||
}
|
||||
|
||||
|
||||
u16 copy_sta_ht_capab(struct sta_info *sta, const u8 *ht_capab,
|
||||
size_t ht_capab_len)
|
||||
u16 copy_sta_ht_capab(struct hostapd_data *hapd, struct sta_info *sta,
|
||||
const u8 *ht_capab, size_t ht_capab_len)
|
||||
{
|
||||
/* Disable HT caps for STAs associated to no-HT BSSes. */
|
||||
if (!ht_capab ||
|
||||
ht_capab_len < sizeof(struct ieee80211_ht_capabilities)) {
|
||||
ht_capab_len < sizeof(struct ieee80211_ht_capabilities) ||
|
||||
hapd->conf->disable_11n) {
|
||||
sta->flags &= ~WLAN_STA_HT;
|
||||
os_free(sta->ht_capabilities);
|
||||
sta->ht_capabilities = NULL;
|
||||
@ -253,8 +250,14 @@ void hostapd_get_ht_capab(struct hostapd_data *hapd,
|
||||
return;
|
||||
os_memcpy(neg_ht_cap, ht_cap, sizeof(*neg_ht_cap));
|
||||
cap = le_to_host16(neg_ht_cap->ht_capabilities_info);
|
||||
cap &= hapd->iconf->ht_capab;
|
||||
cap |= (hapd->iconf->ht_capab & HT_CAP_INFO_SMPS_DISABLED);
|
||||
|
||||
/*
|
||||
* Mask out HT features we don't support, but don't overwrite
|
||||
* non-symmetric features like STBC and SMPS. Just because
|
||||
* we're not in dynamic SMPS mode the STA might still be.
|
||||
*/
|
||||
cap &= (hapd->iconf->ht_capab | HT_CAP_INFO_RX_STBC_MASK |
|
||||
HT_CAP_INFO_TX_STBC | HT_CAP_INFO_SMPS_MASK);
|
||||
|
||||
/*
|
||||
* STBC needs to be handled specially
|
||||
|
458
src/ap/ieee802_11_shared.c
Normal file
458
src/ap/ieee802_11_shared.c
Normal file
@ -0,0 +1,458 @@
|
||||
/*
|
||||
* hostapd / IEEE 802.11 Management
|
||||
* Copyright (c) 2002-2012, Jouni Malinen <j@w1.fi>
|
||||
*
|
||||
* This software may be distributed under the terms of the BSD license.
|
||||
* See README for more details.
|
||||
*/
|
||||
|
||||
#include "utils/includes.h"
|
||||
|
||||
#include "utils/common.h"
|
||||
#include "common/ieee802_11_defs.h"
|
||||
#include "hostapd.h"
|
||||
#include "sta_info.h"
|
||||
#include "ap_config.h"
|
||||
#include "ap_drv_ops.h"
|
||||
#include "ieee802_11.h"
|
||||
|
||||
|
||||
#ifdef CONFIG_IEEE80211W
|
||||
|
||||
u8 * hostapd_eid_assoc_comeback_time(struct hostapd_data *hapd,
|
||||
struct sta_info *sta, u8 *eid)
|
||||
{
|
||||
u8 *pos = eid;
|
||||
u32 timeout, tu;
|
||||
struct os_time now, passed;
|
||||
|
||||
*pos++ = WLAN_EID_TIMEOUT_INTERVAL;
|
||||
*pos++ = 5;
|
||||
*pos++ = WLAN_TIMEOUT_ASSOC_COMEBACK;
|
||||
os_get_time(&now);
|
||||
os_time_sub(&now, &sta->sa_query_start, &passed);
|
||||
tu = (passed.sec * 1000000 + passed.usec) / 1024;
|
||||
if (hapd->conf->assoc_sa_query_max_timeout > tu)
|
||||
timeout = hapd->conf->assoc_sa_query_max_timeout - tu;
|
||||
else
|
||||
timeout = 0;
|
||||
if (timeout < hapd->conf->assoc_sa_query_max_timeout)
|
||||
timeout++; /* add some extra time for local timers */
|
||||
WPA_PUT_LE32(pos, timeout);
|
||||
pos += 4;
|
||||
|
||||
return pos;
|
||||
}
|
||||
|
||||
|
||||
/* MLME-SAQuery.request */
|
||||
void ieee802_11_send_sa_query_req(struct hostapd_data *hapd,
|
||||
const u8 *addr, const u8 *trans_id)
|
||||
{
|
||||
struct ieee80211_mgmt mgmt;
|
||||
u8 *end;
|
||||
|
||||
wpa_printf(MSG_DEBUG, "IEEE 802.11: Sending SA Query Request to "
|
||||
MACSTR, MAC2STR(addr));
|
||||
wpa_hexdump(MSG_DEBUG, "IEEE 802.11: SA Query Transaction ID",
|
||||
trans_id, WLAN_SA_QUERY_TR_ID_LEN);
|
||||
|
||||
os_memset(&mgmt, 0, sizeof(mgmt));
|
||||
mgmt.frame_control = IEEE80211_FC(WLAN_FC_TYPE_MGMT,
|
||||
WLAN_FC_STYPE_ACTION);
|
||||
os_memcpy(mgmt.da, addr, ETH_ALEN);
|
||||
os_memcpy(mgmt.sa, hapd->own_addr, ETH_ALEN);
|
||||
os_memcpy(mgmt.bssid, hapd->own_addr, ETH_ALEN);
|
||||
mgmt.u.action.category = WLAN_ACTION_SA_QUERY;
|
||||
mgmt.u.action.u.sa_query_req.action = WLAN_SA_QUERY_REQUEST;
|
||||
os_memcpy(mgmt.u.action.u.sa_query_req.trans_id, trans_id,
|
||||
WLAN_SA_QUERY_TR_ID_LEN);
|
||||
end = mgmt.u.action.u.sa_query_req.trans_id + WLAN_SA_QUERY_TR_ID_LEN;
|
||||
if (hostapd_drv_send_mlme(hapd, &mgmt, end - (u8 *) &mgmt, 0) < 0)
|
||||
perror("ieee802_11_send_sa_query_req: send");
|
||||
}
|
||||
|
||||
|
||||
static void ieee802_11_send_sa_query_resp(struct hostapd_data *hapd,
|
||||
const u8 *sa, const u8 *trans_id)
|
||||
{
|
||||
struct sta_info *sta;
|
||||
struct ieee80211_mgmt resp;
|
||||
u8 *end;
|
||||
|
||||
wpa_printf(MSG_DEBUG, "IEEE 802.11: Received SA Query Request from "
|
||||
MACSTR, MAC2STR(sa));
|
||||
wpa_hexdump(MSG_DEBUG, "IEEE 802.11: SA Query Transaction ID",
|
||||
trans_id, WLAN_SA_QUERY_TR_ID_LEN);
|
||||
|
||||
sta = ap_get_sta(hapd, sa);
|
||||
if (sta == NULL || !(sta->flags & WLAN_STA_ASSOC)) {
|
||||
wpa_printf(MSG_DEBUG, "IEEE 802.11: Ignore SA Query Request "
|
||||
"from unassociated STA " MACSTR, MAC2STR(sa));
|
||||
return;
|
||||
}
|
||||
|
||||
wpa_printf(MSG_DEBUG, "IEEE 802.11: Sending SA Query Response to "
|
||||
MACSTR, MAC2STR(sa));
|
||||
|
||||
os_memset(&resp, 0, sizeof(resp));
|
||||
resp.frame_control = IEEE80211_FC(WLAN_FC_TYPE_MGMT,
|
||||
WLAN_FC_STYPE_ACTION);
|
||||
os_memcpy(resp.da, sa, ETH_ALEN);
|
||||
os_memcpy(resp.sa, hapd->own_addr, ETH_ALEN);
|
||||
os_memcpy(resp.bssid, hapd->own_addr, ETH_ALEN);
|
||||
resp.u.action.category = WLAN_ACTION_SA_QUERY;
|
||||
resp.u.action.u.sa_query_req.action = WLAN_SA_QUERY_RESPONSE;
|
||||
os_memcpy(resp.u.action.u.sa_query_req.trans_id, trans_id,
|
||||
WLAN_SA_QUERY_TR_ID_LEN);
|
||||
end = resp.u.action.u.sa_query_req.trans_id + WLAN_SA_QUERY_TR_ID_LEN;
|
||||
if (hostapd_drv_send_mlme(hapd, &resp, end - (u8 *) &resp, 0) < 0)
|
||||
perror("ieee80211_mgmt_sa_query_request: send");
|
||||
}
|
||||
|
||||
|
||||
void ieee802_11_sa_query_action(struct hostapd_data *hapd, const u8 *sa,
|
||||
const u8 action_type, const u8 *trans_id)
|
||||
{
|
||||
struct sta_info *sta;
|
||||
int i;
|
||||
|
||||
if (action_type == WLAN_SA_QUERY_REQUEST) {
|
||||
ieee802_11_send_sa_query_resp(hapd, sa, trans_id);
|
||||
return;
|
||||
}
|
||||
|
||||
if (action_type != WLAN_SA_QUERY_RESPONSE) {
|
||||
wpa_printf(MSG_DEBUG, "IEEE 802.11: Unexpected SA Query "
|
||||
"Action %d", action_type);
|
||||
return;
|
||||
}
|
||||
|
||||
wpa_printf(MSG_DEBUG, "IEEE 802.11: Received SA Query Response from "
|
||||
MACSTR, MAC2STR(sa));
|
||||
wpa_hexdump(MSG_DEBUG, "IEEE 802.11: SA Query Transaction ID",
|
||||
trans_id, WLAN_SA_QUERY_TR_ID_LEN);
|
||||
|
||||
/* MLME-SAQuery.confirm */
|
||||
|
||||
sta = ap_get_sta(hapd, sa);
|
||||
if (sta == NULL || sta->sa_query_trans_id == NULL) {
|
||||
wpa_printf(MSG_DEBUG, "IEEE 802.11: No matching STA with "
|
||||
"pending SA Query request found");
|
||||
return;
|
||||
}
|
||||
|
||||
for (i = 0; i < sta->sa_query_count; i++) {
|
||||
if (os_memcmp(sta->sa_query_trans_id +
|
||||
i * WLAN_SA_QUERY_TR_ID_LEN,
|
||||
trans_id, WLAN_SA_QUERY_TR_ID_LEN) == 0)
|
||||
break;
|
||||
}
|
||||
|
||||
if (i >= sta->sa_query_count) {
|
||||
wpa_printf(MSG_DEBUG, "IEEE 802.11: No matching SA Query "
|
||||
"transaction identifier found");
|
||||
return;
|
||||
}
|
||||
|
||||
hostapd_logger(hapd, sta->addr, HOSTAPD_MODULE_IEEE80211,
|
||||
HOSTAPD_LEVEL_DEBUG,
|
||||
"Reply to pending SA Query received");
|
||||
ap_sta_stop_sa_query(hapd, sta);
|
||||
}
|
||||
|
||||
#endif /* CONFIG_IEEE80211W */
|
||||
|
||||
|
||||
u8 * hostapd_eid_ext_capab(struct hostapd_data *hapd, u8 *eid)
|
||||
{
|
||||
u8 *pos = eid;
|
||||
u8 len = 0;
|
||||
|
||||
if (hapd->conf->tdls & (TDLS_PROHIBIT | TDLS_PROHIBIT_CHAN_SWITCH))
|
||||
len = 5;
|
||||
if (len < 4 && hapd->conf->interworking)
|
||||
len = 4;
|
||||
if (len < 3 && hapd->conf->wnm_sleep_mode)
|
||||
len = 3;
|
||||
if (len < 7 && hapd->conf->ssid.utf8_ssid)
|
||||
len = 7;
|
||||
#ifdef CONFIG_WNM
|
||||
if (len < 4)
|
||||
len = 4;
|
||||
#endif /* CONFIG_WNM */
|
||||
if (len == 0)
|
||||
return eid;
|
||||
|
||||
*pos++ = WLAN_EID_EXT_CAPAB;
|
||||
*pos++ = len;
|
||||
*pos++ = 0x00;
|
||||
*pos++ = 0x00;
|
||||
|
||||
*pos = 0x00;
|
||||
if (hapd->conf->wnm_sleep_mode)
|
||||
*pos |= 0x02; /* Bit 17 - WNM-Sleep Mode */
|
||||
if (hapd->conf->bss_transition)
|
||||
*pos |= 0x08; /* Bit 19 - BSS Transition */
|
||||
pos++;
|
||||
|
||||
if (len < 4)
|
||||
return pos;
|
||||
*pos = 0x00;
|
||||
#ifdef CONFIG_WNM
|
||||
*pos |= 0x02; /* Bit 25 - SSID List */
|
||||
#endif /* CONFIG_WNM */
|
||||
if (hapd->conf->time_advertisement == 2)
|
||||
*pos |= 0x08; /* Bit 27 - UTC TSF Offset */
|
||||
if (hapd->conf->interworking)
|
||||
*pos |= 0x80; /* Bit 31 - Interworking */
|
||||
pos++;
|
||||
|
||||
if (len < 5)
|
||||
return pos;
|
||||
*pos = 0x00;
|
||||
if (hapd->conf->tdls & TDLS_PROHIBIT)
|
||||
*pos |= 0x40; /* Bit 38 - TDLS Prohibited */
|
||||
if (hapd->conf->tdls & TDLS_PROHIBIT_CHAN_SWITCH)
|
||||
*pos |= 0x80; /* Bit 39 - TDLS Channel Switching Prohibited */
|
||||
pos++;
|
||||
|
||||
if (len < 6)
|
||||
return pos;
|
||||
*pos = 0x00;
|
||||
pos++;
|
||||
|
||||
if (len < 7)
|
||||
return pos;
|
||||
*pos = 0x00;
|
||||
if (hapd->conf->ssid.utf8_ssid)
|
||||
*pos |= 0x01; /* Bit 48 - UTF-8 SSID */
|
||||
pos++;
|
||||
|
||||
return pos;
|
||||
}
|
||||
|
||||
|
||||
u8 * hostapd_eid_interworking(struct hostapd_data *hapd, u8 *eid)
|
||||
{
|
||||
u8 *pos = eid;
|
||||
#ifdef CONFIG_INTERWORKING
|
||||
u8 *len;
|
||||
|
||||
if (!hapd->conf->interworking)
|
||||
return eid;
|
||||
|
||||
*pos++ = WLAN_EID_INTERWORKING;
|
||||
len = pos++;
|
||||
|
||||
*pos = hapd->conf->access_network_type;
|
||||
if (hapd->conf->internet)
|
||||
*pos |= INTERWORKING_ANO_INTERNET;
|
||||
if (hapd->conf->asra)
|
||||
*pos |= INTERWORKING_ANO_ASRA;
|
||||
if (hapd->conf->esr)
|
||||
*pos |= INTERWORKING_ANO_ESR;
|
||||
if (hapd->conf->uesa)
|
||||
*pos |= INTERWORKING_ANO_UESA;
|
||||
pos++;
|
||||
|
||||
if (hapd->conf->venue_info_set) {
|
||||
*pos++ = hapd->conf->venue_group;
|
||||
*pos++ = hapd->conf->venue_type;
|
||||
}
|
||||
|
||||
if (!is_zero_ether_addr(hapd->conf->hessid)) {
|
||||
os_memcpy(pos, hapd->conf->hessid, ETH_ALEN);
|
||||
pos += ETH_ALEN;
|
||||
}
|
||||
|
||||
*len = pos - len - 1;
|
||||
#endif /* CONFIG_INTERWORKING */
|
||||
|
||||
return pos;
|
||||
}
|
||||
|
||||
|
||||
u8 * hostapd_eid_adv_proto(struct hostapd_data *hapd, u8 *eid)
|
||||
{
|
||||
u8 *pos = eid;
|
||||
#ifdef CONFIG_INTERWORKING
|
||||
|
||||
/* TODO: Separate configuration for ANQP? */
|
||||
if (!hapd->conf->interworking)
|
||||
return eid;
|
||||
|
||||
*pos++ = WLAN_EID_ADV_PROTO;
|
||||
*pos++ = 2;
|
||||
*pos++ = 0x7F; /* Query Response Length Limit | PAME-BI */
|
||||
*pos++ = ACCESS_NETWORK_QUERY_PROTOCOL;
|
||||
#endif /* CONFIG_INTERWORKING */
|
||||
|
||||
return pos;
|
||||
}
|
||||
|
||||
|
||||
u8 * hostapd_eid_roaming_consortium(struct hostapd_data *hapd, u8 *eid)
|
||||
{
|
||||
u8 *pos = eid;
|
||||
#ifdef CONFIG_INTERWORKING
|
||||
u8 *len;
|
||||
unsigned int i, count;
|
||||
|
||||
if (!hapd->conf->interworking ||
|
||||
hapd->conf->roaming_consortium == NULL ||
|
||||
hapd->conf->roaming_consortium_count == 0)
|
||||
return eid;
|
||||
|
||||
*pos++ = WLAN_EID_ROAMING_CONSORTIUM;
|
||||
len = pos++;
|
||||
|
||||
/* Number of ANQP OIs (in addition to the max 3 listed here) */
|
||||
if (hapd->conf->roaming_consortium_count > 3 + 255)
|
||||
*pos++ = 255;
|
||||
else if (hapd->conf->roaming_consortium_count > 3)
|
||||
*pos++ = hapd->conf->roaming_consortium_count - 3;
|
||||
else
|
||||
*pos++ = 0;
|
||||
|
||||
/* OU #1 and #2 Lengths */
|
||||
*pos = hapd->conf->roaming_consortium[0].len;
|
||||
if (hapd->conf->roaming_consortium_count > 1)
|
||||
*pos |= hapd->conf->roaming_consortium[1].len << 4;
|
||||
pos++;
|
||||
|
||||
if (hapd->conf->roaming_consortium_count > 3)
|
||||
count = 3;
|
||||
else
|
||||
count = hapd->conf->roaming_consortium_count;
|
||||
|
||||
for (i = 0; i < count; i++) {
|
||||
os_memcpy(pos, hapd->conf->roaming_consortium[i].oi,
|
||||
hapd->conf->roaming_consortium[i].len);
|
||||
pos += hapd->conf->roaming_consortium[i].len;
|
||||
}
|
||||
|
||||
*len = pos - len - 1;
|
||||
#endif /* CONFIG_INTERWORKING */
|
||||
|
||||
return pos;
|
||||
}
|
||||
|
||||
|
||||
u8 * hostapd_eid_time_adv(struct hostapd_data *hapd, u8 *eid)
|
||||
{
|
||||
if (hapd->conf->time_advertisement != 2)
|
||||
return eid;
|
||||
|
||||
if (hapd->time_adv == NULL &&
|
||||
hostapd_update_time_adv(hapd) < 0)
|
||||
return eid;
|
||||
|
||||
if (hapd->time_adv == NULL)
|
||||
return eid;
|
||||
|
||||
os_memcpy(eid, wpabuf_head(hapd->time_adv),
|
||||
wpabuf_len(hapd->time_adv));
|
||||
eid += wpabuf_len(hapd->time_adv);
|
||||
|
||||
return eid;
|
||||
}
|
||||
|
||||
|
||||
u8 * hostapd_eid_time_zone(struct hostapd_data *hapd, u8 *eid)
|
||||
{
|
||||
size_t len;
|
||||
|
||||
if (hapd->conf->time_advertisement != 2)
|
||||
return eid;
|
||||
|
||||
len = os_strlen(hapd->conf->time_zone);
|
||||
|
||||
*eid++ = WLAN_EID_TIME_ZONE;
|
||||
*eid++ = len;
|
||||
os_memcpy(eid, hapd->conf->time_zone, len);
|
||||
eid += len;
|
||||
|
||||
return eid;
|
||||
}
|
||||
|
||||
|
||||
int hostapd_update_time_adv(struct hostapd_data *hapd)
|
||||
{
|
||||
const int elen = 2 + 1 + 10 + 5 + 1;
|
||||
struct os_time t;
|
||||
struct os_tm tm;
|
||||
u8 *pos;
|
||||
|
||||
if (hapd->conf->time_advertisement != 2)
|
||||
return 0;
|
||||
|
||||
if (os_get_time(&t) < 0 || os_gmtime(t.sec, &tm) < 0)
|
||||
return -1;
|
||||
|
||||
if (!hapd->time_adv) {
|
||||
hapd->time_adv = wpabuf_alloc(elen);
|
||||
if (hapd->time_adv == NULL)
|
||||
return -1;
|
||||
pos = wpabuf_put(hapd->time_adv, elen);
|
||||
} else
|
||||
pos = wpabuf_mhead_u8(hapd->time_adv);
|
||||
|
||||
*pos++ = WLAN_EID_TIME_ADVERTISEMENT;
|
||||
*pos++ = 1 + 10 + 5 + 1;
|
||||
|
||||
*pos++ = 2; /* UTC time at which the TSF timer is 0 */
|
||||
|
||||
/* Time Value at TSF 0 */
|
||||
/* FIX: need to calculate this based on the current TSF value */
|
||||
WPA_PUT_LE16(pos, tm.year); /* Year */
|
||||
pos += 2;
|
||||
*pos++ = tm.month; /* Month */
|
||||
*pos++ = tm.day; /* Day of month */
|
||||
*pos++ = tm.hour; /* Hours */
|
||||
*pos++ = tm.min; /* Minutes */
|
||||
*pos++ = tm.sec; /* Seconds */
|
||||
WPA_PUT_LE16(pos, 0); /* Milliseconds (not used) */
|
||||
pos += 2;
|
||||
*pos++ = 0; /* Reserved */
|
||||
|
||||
/* Time Error */
|
||||
/* TODO: fill in an estimate on the error */
|
||||
*pos++ = 0;
|
||||
*pos++ = 0;
|
||||
*pos++ = 0;
|
||||
*pos++ = 0;
|
||||
*pos++ = 0;
|
||||
|
||||
*pos++ = hapd->time_update_counter++;
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
|
||||
u8 * hostapd_eid_bss_max_idle_period(struct hostapd_data *hapd, u8 *eid)
|
||||
{
|
||||
u8 *pos = eid;
|
||||
|
||||
#ifdef CONFIG_WNM
|
||||
if (hapd->conf->ap_max_inactivity > 0) {
|
||||
unsigned int val;
|
||||
*pos++ = WLAN_EID_BSS_MAX_IDLE_PERIOD;
|
||||
*pos++ = 3;
|
||||
val = hapd->conf->ap_max_inactivity;
|
||||
if (val > 68000)
|
||||
val = 68000;
|
||||
val *= 1000;
|
||||
val /= 1024;
|
||||
if (val == 0)
|
||||
val = 1;
|
||||
if (val > 65535)
|
||||
val = 65535;
|
||||
WPA_PUT_LE16(pos, val);
|
||||
pos += 2;
|
||||
*pos++ = 0x00; /* TODO: Protected Keep-Alive Required */
|
||||
}
|
||||
#endif /* CONFIG_WNM */
|
||||
|
||||
return pos;
|
||||
}
|
110
src/ap/ieee802_11_vht.c
Normal file
110
src/ap/ieee802_11_vht.c
Normal file
@ -0,0 +1,110 @@
|
||||
/*
|
||||
* hostapd / IEEE 802.11ac VHT
|
||||
* Copyright (c) 2002-2009, Jouni Malinen <j@w1.fi>
|
||||
*
|
||||
* This program is free software; you can redistribute it and/or modify
|
||||
* it under the terms of BSD license
|
||||
*
|
||||
* See README and COPYING for more details.
|
||||
*/
|
||||
|
||||
#include "utils/includes.h"
|
||||
|
||||
#include "utils/common.h"
|
||||
#include "common/ieee802_11_defs.h"
|
||||
#include "drivers/driver.h"
|
||||
#include "hostapd.h"
|
||||
#include "ap_config.h"
|
||||
#include "sta_info.h"
|
||||
#include "beacon.h"
|
||||
#include "ieee802_11.h"
|
||||
|
||||
|
||||
u8 * hostapd_eid_vht_capabilities(struct hostapd_data *hapd, u8 *eid)
|
||||
{
|
||||
struct ieee80211_vht_capabilities *cap;
|
||||
u8 *pos = eid;
|
||||
|
||||
if (!hapd->iconf->ieee80211ac || !hapd->iface->current_mode ||
|
||||
hapd->conf->disable_11ac)
|
||||
return eid;
|
||||
|
||||
*pos++ = WLAN_EID_VHT_CAP;
|
||||
*pos++ = sizeof(*cap);
|
||||
|
||||
cap = (struct ieee80211_vht_capabilities *) pos;
|
||||
os_memset(cap, 0, sizeof(*cap));
|
||||
cap->vht_capabilities_info = host_to_le32(
|
||||
hapd->iface->current_mode->vht_capab);
|
||||
|
||||
/* Supported MCS set comes from hw */
|
||||
os_memcpy(cap->vht_supported_mcs_set,
|
||||
hapd->iface->current_mode->vht_mcs_set, 8);
|
||||
|
||||
pos += sizeof(*cap);
|
||||
|
||||
return pos;
|
||||
}
|
||||
|
||||
|
||||
u8 * hostapd_eid_vht_operation(struct hostapd_data *hapd, u8 *eid)
|
||||
{
|
||||
struct ieee80211_vht_operation *oper;
|
||||
u8 *pos = eid;
|
||||
|
||||
if (!hapd->iconf->ieee80211ac || hapd->conf->disable_11ac)
|
||||
return eid;
|
||||
|
||||
*pos++ = WLAN_EID_VHT_OPERATION;
|
||||
*pos++ = sizeof(*oper);
|
||||
|
||||
oper = (struct ieee80211_vht_operation *) pos;
|
||||
os_memset(oper, 0, sizeof(*oper));
|
||||
|
||||
/*
|
||||
* center freq = 5 GHz + (5 * index)
|
||||
* So index 42 gives center freq 5.210 GHz
|
||||
* which is channel 42 in 5G band
|
||||
*/
|
||||
oper->vht_op_info_chan_center_freq_seg0_idx =
|
||||
hapd->iconf->vht_oper_centr_freq_seg0_idx;
|
||||
oper->vht_op_info_chan_center_freq_seg1_idx =
|
||||
hapd->iconf->vht_oper_centr_freq_seg1_idx;
|
||||
|
||||
oper->vht_op_info_chwidth = hapd->iconf->vht_oper_chwidth;
|
||||
|
||||
/* VHT Basic MCS set comes from hw */
|
||||
/* Hard code 1 stream, MCS0-7 is a min Basic VHT MCS rates */
|
||||
oper->vht_basic_mcs_set = host_to_le16(0xfffc);
|
||||
pos += sizeof(*oper);
|
||||
|
||||
return pos;
|
||||
}
|
||||
|
||||
|
||||
u16 copy_sta_vht_capab(struct hostapd_data *hapd, struct sta_info *sta,
|
||||
const u8 *vht_capab, size_t vht_capab_len)
|
||||
{
|
||||
/* Disable VHT caps for STAs associated to no-VHT BSSes. */
|
||||
if (!vht_capab ||
|
||||
vht_capab_len < sizeof(struct ieee80211_vht_capabilities) ||
|
||||
hapd->conf->disable_11ac) {
|
||||
sta->flags &= ~WLAN_STA_VHT;
|
||||
os_free(sta->vht_capabilities);
|
||||
sta->vht_capabilities = NULL;
|
||||
return WLAN_STATUS_SUCCESS;
|
||||
}
|
||||
|
||||
if (sta->vht_capabilities == NULL) {
|
||||
sta->vht_capabilities =
|
||||
os_zalloc(sizeof(struct ieee80211_vht_capabilities));
|
||||
if (sta->vht_capabilities == NULL)
|
||||
return WLAN_STATUS_UNSPECIFIED_FAILURE;
|
||||
}
|
||||
|
||||
sta->flags |= WLAN_STA_VHT;
|
||||
os_memcpy(sta->vht_capabilities, vht_capab,
|
||||
sizeof(struct ieee80211_vht_capabilities));
|
||||
|
||||
return WLAN_STATUS_SUCCESS;
|
||||
}
|
@ -1,15 +1,9 @@
|
||||
/*
|
||||
* hostapd / IEEE 802.1X-2004 Authenticator
|
||||
* Copyright (c) 2002-2009, Jouni Malinen <j@w1.fi>
|
||||
* Copyright (c) 2002-2012, Jouni Malinen <j@w1.fi>
|
||||
*
|
||||
* This program is free software; you can redistribute it and/or modify
|
||||
* it under the terms of the GNU General Public License version 2 as
|
||||
* published by the Free Software Foundation.
|
||||
*
|
||||
* Alternatively, this software may be distributed under the terms of BSD
|
||||
* license.
|
||||
*
|
||||
* See README and COPYING for more details.
|
||||
* This software may be distributed under the terms of the BSD license.
|
||||
* See README for more details.
|
||||
*/
|
||||
|
||||
#include "utils/includes.h"
|
||||
@ -18,14 +12,15 @@
|
||||
#include "utils/eloop.h"
|
||||
#include "crypto/md5.h"
|
||||
#include "crypto/crypto.h"
|
||||
#include "crypto/random.h"
|
||||
#include "common/ieee802_11_defs.h"
|
||||
#include "common/wpa_ctrl.h"
|
||||
#include "radius/radius.h"
|
||||
#include "radius/radius_client.h"
|
||||
#include "eap_server/eap.h"
|
||||
#include "eap_common/eap_wsc_common.h"
|
||||
#include "eapol_auth/eapol_auth_sm.h"
|
||||
#include "eapol_auth/eapol_auth_sm_i.h"
|
||||
#include "p2p/p2p.h"
|
||||
#include "hostapd.h"
|
||||
#include "accounting.h"
|
||||
#include "sta_info.h"
|
||||
@ -33,6 +28,7 @@
|
||||
#include "preauth_auth.h"
|
||||
#include "pmksa_cache_auth.h"
|
||||
#include "ap_config.h"
|
||||
#include "ap_drv_ops.h"
|
||||
#include "ieee802_1x.h"
|
||||
|
||||
|
||||
@ -70,7 +66,9 @@ static void ieee802_1x_send(struct hostapd_data *hapd, struct sta_info *sta,
|
||||
if (sta->flags & WLAN_STA_PREAUTH) {
|
||||
rsn_preauth_send(hapd, sta, buf, len);
|
||||
} else {
|
||||
hapd->drv.send_eapol(hapd, sta->addr, buf, len, encrypt);
|
||||
hostapd_drv_hapd_send_eapol(
|
||||
hapd, sta->addr, buf, len,
|
||||
encrypt, hostapd_sta_flags_to_drv(sta->flags));
|
||||
}
|
||||
|
||||
os_free(buf);
|
||||
@ -86,21 +84,13 @@ void ieee802_1x_set_sta_authorized(struct hostapd_data *hapd,
|
||||
return;
|
||||
|
||||
if (authorized) {
|
||||
if (!(sta->flags & WLAN_STA_AUTHORIZED))
|
||||
wpa_msg(hapd->msg_ctx, MSG_INFO,
|
||||
AP_STA_CONNECTED MACSTR, MAC2STR(sta->addr));
|
||||
sta->flags |= WLAN_STA_AUTHORIZED;
|
||||
res = hapd->drv.set_authorized(hapd, sta, 1);
|
||||
ap_sta_set_authorized(hapd, sta, 1);
|
||||
res = hostapd_set_authorized(hapd, sta, 1);
|
||||
hostapd_logger(hapd, sta->addr, HOSTAPD_MODULE_IEEE8021X,
|
||||
HOSTAPD_LEVEL_DEBUG, "authorizing port");
|
||||
} else {
|
||||
if ((sta->flags & (WLAN_STA_AUTHORIZED | WLAN_STA_ASSOC)) ==
|
||||
(WLAN_STA_AUTHORIZED | WLAN_STA_ASSOC))
|
||||
wpa_msg(hapd->msg_ctx, MSG_INFO,
|
||||
AP_STA_DISCONNECTED MACSTR,
|
||||
MAC2STR(sta->addr));
|
||||
sta->flags &= ~WLAN_STA_AUTHORIZED;
|
||||
res = hapd->drv.set_authorized(hapd, sta, 0);
|
||||
ap_sta_set_authorized(hapd, sta, 0);
|
||||
res = hostapd_set_authorized(hapd, sta, 0);
|
||||
hostapd_logger(hapd, sta->addr, HOSTAPD_MODULE_IEEE8021X,
|
||||
HOSTAPD_LEVEL_DEBUG, "unauthorizing port");
|
||||
}
|
||||
@ -110,8 +100,10 @@ void ieee802_1x_set_sta_authorized(struct hostapd_data *hapd,
|
||||
"driver (errno=%d).\n", MAC2STR(sta->addr), errno);
|
||||
}
|
||||
|
||||
if (authorized)
|
||||
if (authorized) {
|
||||
os_get_time(&sta->connected_time);
|
||||
accounting_sta_start(hapd, sta);
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
@ -137,10 +129,10 @@ static void ieee802_1x_tx_key_one(struct hostapd_data *hapd,
|
||||
hdr = (struct ieee802_1x_hdr *) buf;
|
||||
key = (struct ieee802_1x_eapol_key *) (hdr + 1);
|
||||
key->type = EAPOL_KEY_TYPE_RC4;
|
||||
key->key_length = htons(key_len);
|
||||
WPA_PUT_BE16(key->key_length, key_len);
|
||||
wpa_get_ntp_timestamp(key->replay_counter);
|
||||
|
||||
if (os_get_random(key->key_iv, sizeof(key->key_iv))) {
|
||||
if (random_get_bytes(key->key_iv, sizeof(key->key_iv))) {
|
||||
wpa_printf(MSG_ERROR, "Could not get random numbers");
|
||||
os_free(buf);
|
||||
return;
|
||||
@ -215,7 +207,7 @@ ieee802_1x_group_alloc(struct hostapd_data *hapd, const char *ifname)
|
||||
if (!key->key[key->idx])
|
||||
key->key[key->idx] = os_malloc(key->default_len);
|
||||
if (key->key[key->idx] == NULL ||
|
||||
os_get_random(key->key[key->idx], key->default_len)) {
|
||||
random_get_bytes(key->key[key->idx], key->default_len)) {
|
||||
printf("Could not generate random WEP key (dynamic VLAN).\n");
|
||||
os_free(key->key[key->idx]);
|
||||
key->key[key->idx] = NULL;
|
||||
@ -229,11 +221,13 @@ ieee802_1x_group_alloc(struct hostapd_data *hapd, const char *ifname)
|
||||
wpa_hexdump_key(MSG_DEBUG, "Default WEP key (dynamic VLAN)",
|
||||
key->key[key->idx], key->len[key->idx]);
|
||||
|
||||
if (hapd->drv.set_key(ifname, hapd, WPA_ALG_WEP, NULL, key->idx, 1,
|
||||
NULL, 0, key->key[key->idx], key->len[key->idx]))
|
||||
if (hostapd_drv_set_key(ifname, hapd, WPA_ALG_WEP,
|
||||
broadcast_ether_addr, key->idx, 1,
|
||||
NULL, 0, key->key[key->idx],
|
||||
key->len[key->idx]))
|
||||
printf("Could not set dynamic VLAN WEP encryption key.\n");
|
||||
|
||||
hapd->drv.set_drv_ieee8021x(hapd, ifname, 1);
|
||||
hostapd_set_drv_ieee8021x(hapd, ifname, 1);
|
||||
|
||||
return key;
|
||||
}
|
||||
@ -330,7 +324,8 @@ void ieee802_1x_tx_key(struct hostapd_data *hapd, struct sta_info *sta)
|
||||
u8 *ikey;
|
||||
ikey = os_malloc(hapd->conf->individual_wep_key_len);
|
||||
if (ikey == NULL ||
|
||||
os_get_random(ikey, hapd->conf->individual_wep_key_len)) {
|
||||
random_get_bytes(ikey, hapd->conf->individual_wep_key_len))
|
||||
{
|
||||
wpa_printf(MSG_ERROR, "Could not generate random "
|
||||
"individual WEP key.");
|
||||
os_free(ikey);
|
||||
@ -345,9 +340,9 @@ void ieee802_1x_tx_key(struct hostapd_data *hapd, struct sta_info *sta)
|
||||
|
||||
/* TODO: set encryption in TX callback, i.e., only after STA
|
||||
* has ACKed EAPOL-Key frame */
|
||||
if (hapd->drv.set_key(hapd->conf->iface, hapd, WPA_ALG_WEP,
|
||||
sta->addr, 0, 1, NULL, 0, ikey,
|
||||
hapd->conf->individual_wep_key_len)) {
|
||||
if (hostapd_drv_set_key(hapd->conf->iface, hapd, WPA_ALG_WEP,
|
||||
sta->addr, 0, 1, NULL, 0, ikey,
|
||||
hapd->conf->individual_wep_key_len)) {
|
||||
wpa_printf(MSG_ERROR, "Could not set individual WEP "
|
||||
"encryption.");
|
||||
}
|
||||
@ -360,6 +355,8 @@ void ieee802_1x_tx_key(struct hostapd_data *hapd, struct sta_info *sta)
|
||||
const char *radius_mode_txt(struct hostapd_data *hapd)
|
||||
{
|
||||
switch (hapd->iface->conf->hw_mode) {
|
||||
case HOSTAPD_MODE_IEEE80211AD:
|
||||
return "802.11ad";
|
||||
case HOSTAPD_MODE_IEEE80211A:
|
||||
return "802.11a";
|
||||
case HOSTAPD_MODE_IEEE80211G:
|
||||
@ -417,12 +414,142 @@ static void ieee802_1x_learn_identity(struct hostapd_data *hapd,
|
||||
}
|
||||
|
||||
|
||||
static int add_common_radius_sta_attr(struct hostapd_data *hapd,
|
||||
struct hostapd_radius_attr *req_attr,
|
||||
struct sta_info *sta,
|
||||
struct radius_msg *msg)
|
||||
{
|
||||
char buf[128];
|
||||
|
||||
if (!hostapd_config_get_radius_attr(req_attr,
|
||||
RADIUS_ATTR_NAS_PORT) &&
|
||||
!radius_msg_add_attr_int32(msg, RADIUS_ATTR_NAS_PORT, sta->aid)) {
|
||||
wpa_printf(MSG_ERROR, "Could not add NAS-Port");
|
||||
return -1;
|
||||
}
|
||||
|
||||
os_snprintf(buf, sizeof(buf), RADIUS_802_1X_ADDR_FORMAT,
|
||||
MAC2STR(sta->addr));
|
||||
buf[sizeof(buf) - 1] = '\0';
|
||||
if (!radius_msg_add_attr(msg, RADIUS_ATTR_CALLING_STATION_ID,
|
||||
(u8 *) buf, os_strlen(buf))) {
|
||||
wpa_printf(MSG_ERROR, "Could not add Calling-Station-Id");
|
||||
return -1;
|
||||
}
|
||||
|
||||
if (sta->flags & WLAN_STA_PREAUTH) {
|
||||
os_strlcpy(buf, "IEEE 802.11i Pre-Authentication",
|
||||
sizeof(buf));
|
||||
} else {
|
||||
os_snprintf(buf, sizeof(buf), "CONNECT %d%sMbps %s",
|
||||
radius_sta_rate(hapd, sta) / 2,
|
||||
(radius_sta_rate(hapd, sta) & 1) ? ".5" : "",
|
||||
radius_mode_txt(hapd));
|
||||
buf[sizeof(buf) - 1] = '\0';
|
||||
}
|
||||
if (!hostapd_config_get_radius_attr(req_attr,
|
||||
RADIUS_ATTR_CONNECT_INFO) &&
|
||||
!radius_msg_add_attr(msg, RADIUS_ATTR_CONNECT_INFO,
|
||||
(u8 *) buf, os_strlen(buf))) {
|
||||
wpa_printf(MSG_ERROR, "Could not add Connect-Info");
|
||||
return -1;
|
||||
}
|
||||
|
||||
if (sta->acct_session_id_hi || sta->acct_session_id_lo) {
|
||||
os_snprintf(buf, sizeof(buf), "%08X-%08X",
|
||||
sta->acct_session_id_hi, sta->acct_session_id_lo);
|
||||
if (!radius_msg_add_attr(msg, RADIUS_ATTR_ACCT_SESSION_ID,
|
||||
(u8 *) buf, os_strlen(buf))) {
|
||||
wpa_printf(MSG_ERROR, "Could not add Acct-Session-Id");
|
||||
return -1;
|
||||
}
|
||||
}
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
|
||||
int add_common_radius_attr(struct hostapd_data *hapd,
|
||||
struct hostapd_radius_attr *req_attr,
|
||||
struct sta_info *sta,
|
||||
struct radius_msg *msg)
|
||||
{
|
||||
char buf[128];
|
||||
struct hostapd_radius_attr *attr;
|
||||
|
||||
if (!hostapd_config_get_radius_attr(req_attr,
|
||||
RADIUS_ATTR_NAS_IP_ADDRESS) &&
|
||||
hapd->conf->own_ip_addr.af == AF_INET &&
|
||||
!radius_msg_add_attr(msg, RADIUS_ATTR_NAS_IP_ADDRESS,
|
||||
(u8 *) &hapd->conf->own_ip_addr.u.v4, 4)) {
|
||||
wpa_printf(MSG_ERROR, "Could not add NAS-IP-Address");
|
||||
return -1;
|
||||
}
|
||||
|
||||
#ifdef CONFIG_IPV6
|
||||
if (!hostapd_config_get_radius_attr(req_attr,
|
||||
RADIUS_ATTR_NAS_IPV6_ADDRESS) &&
|
||||
hapd->conf->own_ip_addr.af == AF_INET6 &&
|
||||
!radius_msg_add_attr(msg, RADIUS_ATTR_NAS_IPV6_ADDRESS,
|
||||
(u8 *) &hapd->conf->own_ip_addr.u.v6, 16)) {
|
||||
wpa_printf(MSG_ERROR, "Could not add NAS-IPv6-Address");
|
||||
return -1;
|
||||
}
|
||||
#endif /* CONFIG_IPV6 */
|
||||
|
||||
if (!hostapd_config_get_radius_attr(req_attr,
|
||||
RADIUS_ATTR_NAS_IDENTIFIER) &&
|
||||
hapd->conf->nas_identifier &&
|
||||
!radius_msg_add_attr(msg, RADIUS_ATTR_NAS_IDENTIFIER,
|
||||
(u8 *) hapd->conf->nas_identifier,
|
||||
os_strlen(hapd->conf->nas_identifier))) {
|
||||
wpa_printf(MSG_ERROR, "Could not add NAS-Identifier");
|
||||
return -1;
|
||||
}
|
||||
|
||||
os_snprintf(buf, sizeof(buf), RADIUS_802_1X_ADDR_FORMAT ":%s",
|
||||
MAC2STR(hapd->own_addr),
|
||||
wpa_ssid_txt(hapd->conf->ssid.ssid,
|
||||
hapd->conf->ssid.ssid_len));
|
||||
buf[sizeof(buf) - 1] = '\0';
|
||||
if (!hostapd_config_get_radius_attr(req_attr,
|
||||
RADIUS_ATTR_CALLED_STATION_ID) &&
|
||||
!radius_msg_add_attr(msg, RADIUS_ATTR_CALLED_STATION_ID,
|
||||
(u8 *) buf, os_strlen(buf))) {
|
||||
wpa_printf(MSG_ERROR, "Could not add Called-Station-Id");
|
||||
return -1;
|
||||
}
|
||||
|
||||
if (!hostapd_config_get_radius_attr(req_attr,
|
||||
RADIUS_ATTR_NAS_PORT_TYPE) &&
|
||||
!radius_msg_add_attr_int32(msg, RADIUS_ATTR_NAS_PORT_TYPE,
|
||||
RADIUS_NAS_PORT_TYPE_IEEE_802_11)) {
|
||||
wpa_printf(MSG_ERROR, "Could not add NAS-Port-Type");
|
||||
return -1;
|
||||
}
|
||||
|
||||
if (sta && add_common_radius_sta_attr(hapd, req_attr, sta, msg) < 0)
|
||||
return -1;
|
||||
|
||||
for (attr = req_attr; attr; attr = attr->next) {
|
||||
if (!radius_msg_add_attr(msg, attr->type,
|
||||
wpabuf_head(attr->val),
|
||||
wpabuf_len(attr->val))) {
|
||||
wpa_printf(MSG_ERROR, "Could not add RADIUS "
|
||||
"attribute");
|
||||
return -1;
|
||||
}
|
||||
}
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
|
||||
static void ieee802_1x_encapsulate_radius(struct hostapd_data *hapd,
|
||||
struct sta_info *sta,
|
||||
const u8 *eap, size_t len)
|
||||
{
|
||||
struct radius_msg *msg;
|
||||
char buf[128];
|
||||
struct eapol_state_machine *sm = sta->eapol_sm;
|
||||
|
||||
if (sm == NULL)
|
||||
@ -450,83 +577,20 @@ static void ieee802_1x_encapsulate_radius(struct hostapd_data *hapd,
|
||||
goto fail;
|
||||
}
|
||||
|
||||
if (hapd->conf->own_ip_addr.af == AF_INET &&
|
||||
!radius_msg_add_attr(msg, RADIUS_ATTR_NAS_IP_ADDRESS,
|
||||
(u8 *) &hapd->conf->own_ip_addr.u.v4, 4)) {
|
||||
printf("Could not add NAS-IP-Address\n");
|
||||
if (add_common_radius_attr(hapd, hapd->conf->radius_auth_req_attr, sta,
|
||||
msg) < 0)
|
||||
goto fail;
|
||||
}
|
||||
|
||||
#ifdef CONFIG_IPV6
|
||||
if (hapd->conf->own_ip_addr.af == AF_INET6 &&
|
||||
!radius_msg_add_attr(msg, RADIUS_ATTR_NAS_IPV6_ADDRESS,
|
||||
(u8 *) &hapd->conf->own_ip_addr.u.v6, 16)) {
|
||||
printf("Could not add NAS-IPv6-Address\n");
|
||||
goto fail;
|
||||
}
|
||||
#endif /* CONFIG_IPV6 */
|
||||
|
||||
if (hapd->conf->nas_identifier &&
|
||||
!radius_msg_add_attr(msg, RADIUS_ATTR_NAS_IDENTIFIER,
|
||||
(u8 *) hapd->conf->nas_identifier,
|
||||
os_strlen(hapd->conf->nas_identifier))) {
|
||||
printf("Could not add NAS-Identifier\n");
|
||||
goto fail;
|
||||
}
|
||||
|
||||
if (!radius_msg_add_attr_int32(msg, RADIUS_ATTR_NAS_PORT, sta->aid)) {
|
||||
printf("Could not add NAS-Port\n");
|
||||
goto fail;
|
||||
}
|
||||
|
||||
os_snprintf(buf, sizeof(buf), RADIUS_802_1X_ADDR_FORMAT ":%s",
|
||||
MAC2STR(hapd->own_addr), hapd->conf->ssid.ssid);
|
||||
buf[sizeof(buf) - 1] = '\0';
|
||||
if (!radius_msg_add_attr(msg, RADIUS_ATTR_CALLED_STATION_ID,
|
||||
(u8 *) buf, os_strlen(buf))) {
|
||||
printf("Could not add Called-Station-Id\n");
|
||||
goto fail;
|
||||
}
|
||||
|
||||
os_snprintf(buf, sizeof(buf), RADIUS_802_1X_ADDR_FORMAT,
|
||||
MAC2STR(sta->addr));
|
||||
buf[sizeof(buf) - 1] = '\0';
|
||||
if (!radius_msg_add_attr(msg, RADIUS_ATTR_CALLING_STATION_ID,
|
||||
(u8 *) buf, os_strlen(buf))) {
|
||||
printf("Could not add Calling-Station-Id\n");
|
||||
goto fail;
|
||||
}
|
||||
|
||||
/* TODO: should probably check MTU from driver config; 2304 is max for
|
||||
* IEEE 802.11, but use 1400 to avoid problems with too large packets
|
||||
*/
|
||||
if (!radius_msg_add_attr_int32(msg, RADIUS_ATTR_FRAMED_MTU, 1400)) {
|
||||
if (!hostapd_config_get_radius_attr(hapd->conf->radius_auth_req_attr,
|
||||
RADIUS_ATTR_FRAMED_MTU) &&
|
||||
!radius_msg_add_attr_int32(msg, RADIUS_ATTR_FRAMED_MTU, 1400)) {
|
||||
printf("Could not add Framed-MTU\n");
|
||||
goto fail;
|
||||
}
|
||||
|
||||
if (!radius_msg_add_attr_int32(msg, RADIUS_ATTR_NAS_PORT_TYPE,
|
||||
RADIUS_NAS_PORT_TYPE_IEEE_802_11)) {
|
||||
printf("Could not add NAS-Port-Type\n");
|
||||
goto fail;
|
||||
}
|
||||
|
||||
if (sta->flags & WLAN_STA_PREAUTH) {
|
||||
os_strlcpy(buf, "IEEE 802.11i Pre-Authentication",
|
||||
sizeof(buf));
|
||||
} else {
|
||||
os_snprintf(buf, sizeof(buf), "CONNECT %d%sMbps %s",
|
||||
radius_sta_rate(hapd, sta) / 2,
|
||||
(radius_sta_rate(hapd, sta) & 1) ? ".5" : "",
|
||||
radius_mode_txt(hapd));
|
||||
buf[sizeof(buf) - 1] = '\0';
|
||||
}
|
||||
if (!radius_msg_add_attr(msg, RADIUS_ATTR_CONNECT_INFO,
|
||||
(u8 *) buf, os_strlen(buf))) {
|
||||
printf("Could not add Connect-Info\n");
|
||||
goto fail;
|
||||
}
|
||||
|
||||
if (eap && !radius_msg_add_eap(msg, eap, len)) {
|
||||
printf("Could not add EAP-Message\n");
|
||||
goto fail;
|
||||
@ -549,7 +613,28 @@ static void ieee802_1x_encapsulate_radius(struct hostapd_data *hapd,
|
||||
}
|
||||
}
|
||||
|
||||
radius_client_send(hapd->radius, msg, RADIUS_AUTH, sta->addr);
|
||||
if (hapd->conf->radius_request_cui) {
|
||||
const u8 *cui;
|
||||
size_t cui_len;
|
||||
/* Add previously learned CUI or nul CUI to request CUI */
|
||||
if (sm->radius_cui) {
|
||||
cui = wpabuf_head(sm->radius_cui);
|
||||
cui_len = wpabuf_len(sm->radius_cui);
|
||||
} else {
|
||||
cui = (const u8 *) "\0";
|
||||
cui_len = 1;
|
||||
}
|
||||
if (!radius_msg_add_attr(msg,
|
||||
RADIUS_ATTR_CHARGEABLE_USER_IDENTITY,
|
||||
cui, cui_len)) {
|
||||
wpa_printf(MSG_ERROR, "Could not add CUI");
|
||||
goto fail;
|
||||
}
|
||||
}
|
||||
|
||||
if (radius_client_send(hapd->radius, msg, RADIUS_AUTH, sta->addr) < 0)
|
||||
goto fail;
|
||||
|
||||
return;
|
||||
|
||||
fail:
|
||||
@ -652,7 +737,8 @@ ieee802_1x_alloc_eapol_sm(struct hostapd_data *hapd, struct sta_info *sta)
|
||||
flags |= EAPOL_SM_FROM_PMKSA_CACHE;
|
||||
}
|
||||
return eapol_auth_alloc(hapd->eapol_auth, sta->addr, flags,
|
||||
sta->wps_ie, sta);
|
||||
sta->wps_ie, sta->p2p_ie, sta,
|
||||
sta->identity, sta->radius_cui);
|
||||
}
|
||||
|
||||
|
||||
@ -673,6 +759,7 @@ void ieee802_1x_receive(struct hostapd_data *hapd, const u8 *sa, const u8 *buf,
|
||||
struct ieee802_1x_eapol_key *key;
|
||||
u16 datalen;
|
||||
struct rsn_pmksa_cache_entry *pmksa;
|
||||
int key_mgmt;
|
||||
|
||||
if (!hapd->conf->ieee802_1x && !hapd->conf->wpa &&
|
||||
!hapd->conf->wps_state)
|
||||
@ -681,9 +768,10 @@ void ieee802_1x_receive(struct hostapd_data *hapd, const u8 *sa, const u8 *buf,
|
||||
wpa_printf(MSG_DEBUG, "IEEE 802.1X: %lu bytes from " MACSTR,
|
||||
(unsigned long) len, MAC2STR(sa));
|
||||
sta = ap_get_sta(hapd, sa);
|
||||
if (!sta || !(sta->flags & WLAN_STA_ASSOC)) {
|
||||
if (!sta || (!(sta->flags & (WLAN_STA_ASSOC | WLAN_STA_PREAUTH)) &&
|
||||
!(hapd->iface->drv_flags & WPA_DRIVER_FLAGS_WIRED))) {
|
||||
wpa_printf(MSG_DEBUG, "IEEE 802.1X data frame from not "
|
||||
"associated STA");
|
||||
"associated/Pre-authenticating STA");
|
||||
return;
|
||||
}
|
||||
|
||||
@ -724,10 +812,19 @@ void ieee802_1x_receive(struct hostapd_data *hapd, const u8 *sa, const u8 *buf,
|
||||
return;
|
||||
}
|
||||
|
||||
if ((!hapd->conf->ieee802_1x &&
|
||||
!(sta->flags & (WLAN_STA_WPS | WLAN_STA_MAYBE_WPS))) ||
|
||||
wpa_key_mgmt_wpa_psk(wpa_auth_sta_key_mgmt(sta->wpa_sm)))
|
||||
if (!hapd->conf->ieee802_1x &&
|
||||
!(sta->flags & (WLAN_STA_WPS | WLAN_STA_MAYBE_WPS))) {
|
||||
wpa_printf(MSG_DEBUG, "IEEE 802.1X: Ignore EAPOL message - "
|
||||
"802.1X not enabled and WPS not used");
|
||||
return;
|
||||
}
|
||||
|
||||
key_mgmt = wpa_auth_sta_key_mgmt(sta->wpa_sm);
|
||||
if (key_mgmt != -1 && wpa_key_mgmt_wpa_psk(key_mgmt)) {
|
||||
wpa_printf(MSG_DEBUG, "IEEE 802.1X: Ignore EAPOL message - "
|
||||
"STA is using PSK");
|
||||
return;
|
||||
}
|
||||
|
||||
if (!sta->eapol_sm) {
|
||||
sta->eapol_sm = ieee802_1x_alloc_eapol_sm(hapd, sta);
|
||||
@ -735,14 +832,24 @@ void ieee802_1x_receive(struct hostapd_data *hapd, const u8 *sa, const u8 *buf,
|
||||
return;
|
||||
|
||||
#ifdef CONFIG_WPS
|
||||
if (!hapd->conf->ieee802_1x &&
|
||||
((sta->flags & (WLAN_STA_WPS | WLAN_STA_MAYBE_WPS)) ==
|
||||
WLAN_STA_MAYBE_WPS)) {
|
||||
/*
|
||||
* Delay EAPOL frame transmission until a possible WPS
|
||||
* STA initiates the handshake with EAPOL-Start.
|
||||
*/
|
||||
sta->eapol_sm->flags |= EAPOL_SM_WAIT_START;
|
||||
if (!hapd->conf->ieee802_1x) {
|
||||
u32 wflags = sta->flags & (WLAN_STA_WPS |
|
||||
WLAN_STA_WPS2 |
|
||||
WLAN_STA_MAYBE_WPS);
|
||||
if (wflags == WLAN_STA_MAYBE_WPS ||
|
||||
wflags == (WLAN_STA_WPS | WLAN_STA_MAYBE_WPS)) {
|
||||
/*
|
||||
* Delay EAPOL frame transmission until a
|
||||
* possible WPS STA initiates the handshake
|
||||
* with EAPOL-Start. Only allow the wait to be
|
||||
* skipped if the STA is known to support WPS
|
||||
* 2.0.
|
||||
*/
|
||||
wpa_printf(MSG_DEBUG, "WPS: Do not start "
|
||||
"EAPOL until EAPOL-Start is "
|
||||
"received");
|
||||
sta->eapol_sm->flags |= EAPOL_SM_WAIT_START;
|
||||
}
|
||||
}
|
||||
#endif /* CONFIG_WPS */
|
||||
|
||||
@ -776,6 +883,7 @@ void ieee802_1x_receive(struct hostapd_data *hapd, const u8 *sa, const u8 *buf,
|
||||
}
|
||||
sta->eapol_sm->eapolStart = TRUE;
|
||||
sta->eapol_sm->dot1xAuthEapolStartFramesRx++;
|
||||
eap_server_clear_identity(sta->eapol_sm->eap);
|
||||
wpa_auth_sm_event(sta->wpa_sm, WPA_REAUTH_EAPOL);
|
||||
break;
|
||||
|
||||
@ -788,11 +896,12 @@ void ieee802_1x_receive(struct hostapd_data *hapd, const u8 *sa, const u8 *buf,
|
||||
accounting_sta_stop(hapd, sta);
|
||||
sta->eapol_sm->eapolLogoff = TRUE;
|
||||
sta->eapol_sm->dot1xAuthEapolLogoffFramesRx++;
|
||||
eap_server_clear_identity(sta->eapol_sm->eap);
|
||||
break;
|
||||
|
||||
case IEEE802_1X_TYPE_EAPOL_KEY:
|
||||
wpa_printf(MSG_DEBUG, " EAPOL-Key");
|
||||
if (!(sta->flags & WLAN_STA_AUTHORIZED)) {
|
||||
if (!ap_sta_is_authorized(sta)) {
|
||||
wpa_printf(MSG_DEBUG, " Dropped key data from "
|
||||
"unauthorized Supplicant");
|
||||
break;
|
||||
@ -827,6 +936,7 @@ void ieee802_1x_new_station(struct hostapd_data *hapd, struct sta_info *sta)
|
||||
struct rsn_pmksa_cache_entry *pmksa;
|
||||
int reassoc = 1;
|
||||
int force_1x = 0;
|
||||
int key_mgmt;
|
||||
|
||||
#ifdef CONFIG_WPS
|
||||
if (hapd->conf->wps_state && hapd->conf->wpa &&
|
||||
@ -840,9 +950,27 @@ void ieee802_1x_new_station(struct hostapd_data *hapd, struct sta_info *sta)
|
||||
}
|
||||
#endif /* CONFIG_WPS */
|
||||
|
||||
if ((!force_1x && !hapd->conf->ieee802_1x) ||
|
||||
wpa_key_mgmt_wpa_psk(wpa_auth_sta_key_mgmt(sta->wpa_sm)))
|
||||
if (!force_1x && !hapd->conf->ieee802_1x) {
|
||||
wpa_printf(MSG_DEBUG, "IEEE 802.1X: Ignore STA - "
|
||||
"802.1X not enabled or forced for WPS");
|
||||
/*
|
||||
* Clear any possible EAPOL authenticator state to support
|
||||
* reassociation change from WPS to PSK.
|
||||
*/
|
||||
ieee802_1x_free_station(sta);
|
||||
return;
|
||||
}
|
||||
|
||||
key_mgmt = wpa_auth_sta_key_mgmt(sta->wpa_sm);
|
||||
if (key_mgmt != -1 && wpa_key_mgmt_wpa_psk(key_mgmt)) {
|
||||
wpa_printf(MSG_DEBUG, "IEEE 802.1X: Ignore STA - using PSK");
|
||||
/*
|
||||
* Clear any possible EAPOL authenticator state to support
|
||||
* reassociation change from WPA-EAP to PSK.
|
||||
*/
|
||||
ieee802_1x_free_station(sta);
|
||||
return;
|
||||
}
|
||||
|
||||
if (sta->eapol_sm == NULL) {
|
||||
hostapd_logger(hapd, sta->addr, HOSTAPD_MODULE_IEEE8021X,
|
||||
@ -860,17 +988,40 @@ void ieee802_1x_new_station(struct hostapd_data *hapd, struct sta_info *sta)
|
||||
|
||||
#ifdef CONFIG_WPS
|
||||
sta->eapol_sm->flags &= ~EAPOL_SM_WAIT_START;
|
||||
if (!hapd->conf->ieee802_1x && !(sta->flags & WLAN_STA_WPS)) {
|
||||
if (!hapd->conf->ieee802_1x && !(sta->flags & WLAN_STA_WPS2)) {
|
||||
/*
|
||||
* Delay EAPOL frame transmission until a possible WPS
|
||||
* initiates the handshake with EAPOL-Start.
|
||||
* Delay EAPOL frame transmission until a possible WPS STA
|
||||
* initiates the handshake with EAPOL-Start. Only allow the
|
||||
* wait to be skipped if the STA is known to support WPS 2.0.
|
||||
*/
|
||||
wpa_printf(MSG_DEBUG, "WPS: Do not start EAPOL until "
|
||||
"EAPOL-Start is received");
|
||||
sta->eapol_sm->flags |= EAPOL_SM_WAIT_START;
|
||||
}
|
||||
#endif /* CONFIG_WPS */
|
||||
|
||||
sta->eapol_sm->eap_if->portEnabled = TRUE;
|
||||
|
||||
#ifdef CONFIG_IEEE80211R
|
||||
if (sta->auth_alg == WLAN_AUTH_FT) {
|
||||
hostapd_logger(hapd, sta->addr, HOSTAPD_MODULE_IEEE8021X,
|
||||
HOSTAPD_LEVEL_DEBUG,
|
||||
"PMK from FT - skip IEEE 802.1X/EAP");
|
||||
/* Setup EAPOL state machines to already authenticated state
|
||||
* because of existing FT information from R0KH. */
|
||||
sta->eapol_sm->keyRun = TRUE;
|
||||
sta->eapol_sm->eap_if->eapKeyAvailable = TRUE;
|
||||
sta->eapol_sm->auth_pae_state = AUTH_PAE_AUTHENTICATING;
|
||||
sta->eapol_sm->be_auth_state = BE_AUTH_SUCCESS;
|
||||
sta->eapol_sm->authSuccess = TRUE;
|
||||
sta->eapol_sm->authFail = FALSE;
|
||||
if (sta->eapol_sm->eap)
|
||||
eap_sm_notify_cached(sta->eapol_sm->eap);
|
||||
/* TODO: get vlan_id from R0KH using RRB message */
|
||||
return;
|
||||
}
|
||||
#endif /* CONFIG_IEEE80211R */
|
||||
|
||||
pmksa = wpa_auth_sta_get_pmksa(sta->wpa_sm);
|
||||
if (pmksa) {
|
||||
int old_vlanid;
|
||||
@ -885,6 +1036,7 @@ void ieee802_1x_new_station(struct hostapd_data *hapd, struct sta_info *sta)
|
||||
sta->eapol_sm->auth_pae_state = AUTH_PAE_AUTHENTICATING;
|
||||
sta->eapol_sm->be_auth_state = BE_AUTH_SUCCESS;
|
||||
sta->eapol_sm->authSuccess = TRUE;
|
||||
sta->eapol_sm->authFail = FALSE;
|
||||
if (sta->eapol_sm->eap)
|
||||
eap_sm_notify_cached(sta->eapol_sm->eap);
|
||||
old_vlanid = sta->vlan_id;
|
||||
@ -918,6 +1070,7 @@ void ieee802_1x_free_station(struct sta_info *sta)
|
||||
#ifndef CONFIG_NO_RADIUS
|
||||
radius_msg_free(sm->last_recv_radius);
|
||||
radius_free_class(&sm->radius_class);
|
||||
wpabuf_free(sm->radius_cui);
|
||||
#endif /* CONFIG_NO_RADIUS */
|
||||
|
||||
os_free(sm->identity);
|
||||
@ -929,9 +1082,8 @@ void ieee802_1x_free_station(struct sta_info *sta)
|
||||
static void ieee802_1x_decapsulate_radius(struct hostapd_data *hapd,
|
||||
struct sta_info *sta)
|
||||
{
|
||||
u8 *eap;
|
||||
size_t len;
|
||||
struct eap_hdr *hdr;
|
||||
struct wpabuf *eap;
|
||||
const struct eap_hdr *hdr;
|
||||
int eap_type = -1;
|
||||
char buf[64];
|
||||
struct radius_msg *msg;
|
||||
@ -945,7 +1097,7 @@ static void ieee802_1x_decapsulate_radius(struct hostapd_data *hapd,
|
||||
|
||||
msg = sm->last_recv_radius;
|
||||
|
||||
eap = radius_msg_get_eap(msg, &len);
|
||||
eap = radius_msg_get_eap(msg);
|
||||
if (eap == NULL) {
|
||||
/* RFC 3579, Chap. 2.6.3:
|
||||
* RADIUS server SHOULD NOT send Access-Reject/no EAP-Message
|
||||
@ -957,19 +1109,19 @@ static void ieee802_1x_decapsulate_radius(struct hostapd_data *hapd,
|
||||
return;
|
||||
}
|
||||
|
||||
if (len < sizeof(*hdr)) {
|
||||
if (wpabuf_len(eap) < sizeof(*hdr)) {
|
||||
hostapd_logger(hapd, sta->addr, HOSTAPD_MODULE_IEEE8021X,
|
||||
HOSTAPD_LEVEL_WARNING, "too short EAP packet "
|
||||
"received from authentication server");
|
||||
os_free(eap);
|
||||
wpabuf_free(eap);
|
||||
sm->eap_if->aaaEapNoReq = TRUE;
|
||||
return;
|
||||
}
|
||||
|
||||
if (len > sizeof(*hdr))
|
||||
eap_type = eap[sizeof(*hdr)];
|
||||
if (wpabuf_len(eap) > sizeof(*hdr))
|
||||
eap_type = (wpabuf_head_u8(eap))[sizeof(*hdr)];
|
||||
|
||||
hdr = (struct eap_hdr *) eap;
|
||||
hdr = wpabuf_head(eap);
|
||||
switch (hdr->code) {
|
||||
case EAP_CODE_REQUEST:
|
||||
if (eap_type >= 0)
|
||||
@ -1004,7 +1156,7 @@ static void ieee802_1x_decapsulate_radius(struct hostapd_data *hapd,
|
||||
sm->eap_if->aaaEapReq = TRUE;
|
||||
|
||||
wpabuf_free(sm->eap_if->aaaEapReqData);
|
||||
sm->eap_if->aaaEapReqData = wpabuf_alloc_ext_data(eap, len);
|
||||
sm->eap_if->aaaEapReqData = eap;
|
||||
}
|
||||
|
||||
|
||||
@ -1069,7 +1221,7 @@ static void ieee802_1x_store_radius_class(struct hostapd_data *hapd,
|
||||
if (count <= 0)
|
||||
return;
|
||||
|
||||
nclass = os_zalloc(count * sizeof(struct radius_attr_data));
|
||||
nclass = os_calloc(count, sizeof(struct radius_attr_data));
|
||||
if (nclass == NULL)
|
||||
return;
|
||||
|
||||
@ -1139,6 +1291,32 @@ static void ieee802_1x_update_sta_identity(struct hostapd_data *hapd,
|
||||
}
|
||||
|
||||
|
||||
/* Update CUI based on Chargeable-User-Identity attribute in Access-Accept */
|
||||
static void ieee802_1x_update_sta_cui(struct hostapd_data *hapd,
|
||||
struct sta_info *sta,
|
||||
struct radius_msg *msg)
|
||||
{
|
||||
struct eapol_state_machine *sm = sta->eapol_sm;
|
||||
struct wpabuf *cui;
|
||||
u8 *buf;
|
||||
size_t len;
|
||||
|
||||
if (sm == NULL)
|
||||
return;
|
||||
|
||||
if (radius_msg_get_attr_ptr(msg, RADIUS_ATTR_CHARGEABLE_USER_IDENTITY,
|
||||
&buf, &len, NULL) < 0)
|
||||
return;
|
||||
|
||||
cui = wpabuf_alloc_copy(buf, len);
|
||||
if (cui == NULL)
|
||||
return;
|
||||
|
||||
wpabuf_free(sm->radius_cui);
|
||||
sm->radius_cui = cui;
|
||||
}
|
||||
|
||||
|
||||
struct sta_id_search {
|
||||
u8 identifier;
|
||||
struct eapol_state_machine *sm;
|
||||
@ -1298,6 +1476,7 @@ ieee802_1x_receive_auth(struct radius_msg *msg, struct radius_msg *req,
|
||||
shared_secret_len);
|
||||
ieee802_1x_store_radius_class(hapd, sta, msg);
|
||||
ieee802_1x_update_sta_identity(hapd, sta, msg);
|
||||
ieee802_1x_update_sta_cui(hapd, sta, msg);
|
||||
if (sm->eap_if->eapKeyAvailable &&
|
||||
wpa_auth_pmksa_add(sta->wpa_sm, sm->eapol_key_crypt,
|
||||
session_timeout_set ?
|
||||
@ -1363,6 +1542,9 @@ void ieee802_1x_abort_auth(struct hostapd_data *hapd, struct sta_info *sta)
|
||||
* request and we cannot continue EAP processing (EAP-Failure
|
||||
* could only be sent if the EAP peer actually replied).
|
||||
*/
|
||||
wpa_dbg(hapd->msg_ctx, MSG_DEBUG, "EAP Timeout, STA " MACSTR,
|
||||
MAC2STR(sta->addr));
|
||||
|
||||
sm->eap_if->portEnabled = FALSE;
|
||||
ap_sta_disconnect(hapd, sta, sta->addr,
|
||||
WLAN_REASON_PREV_AUTH_NOT_VALID);
|
||||
@ -1380,8 +1562,8 @@ static int ieee802_1x_rekey_broadcast(struct hostapd_data *hapd)
|
||||
os_free(eapol->default_wep_key);
|
||||
eapol->default_wep_key = os_malloc(hapd->conf->default_wep_key_len);
|
||||
if (eapol->default_wep_key == NULL ||
|
||||
os_get_random(eapol->default_wep_key,
|
||||
hapd->conf->default_wep_key_len)) {
|
||||
random_get_bytes(eapol->default_wep_key,
|
||||
hapd->conf->default_wep_key_len)) {
|
||||
printf("Could not generate random WEP key.\n");
|
||||
os_free(eapol->default_wep_key);
|
||||
eapol->default_wep_key = NULL;
|
||||
@ -1432,10 +1614,11 @@ static void ieee802_1x_rekey(void *eloop_ctx, void *timeout_ctx)
|
||||
|
||||
/* TODO: Could setup key for RX here, but change default TX keyid only
|
||||
* after new broadcast key has been sent to all stations. */
|
||||
if (hapd->drv.set_key(hapd->conf->iface, hapd, WPA_ALG_WEP, NULL,
|
||||
eapol->default_wep_key_idx, 1, NULL, 0,
|
||||
eapol->default_wep_key,
|
||||
hapd->conf->default_wep_key_len)) {
|
||||
if (hostapd_drv_set_key(hapd->conf->iface, hapd, WPA_ALG_WEP,
|
||||
broadcast_ether_addr,
|
||||
eapol->default_wep_key_idx, 1, NULL, 0,
|
||||
eapol->default_wep_key,
|
||||
hapd->conf->default_wep_key_len)) {
|
||||
hostapd_logger(hapd, NULL, HOSTAPD_MODULE_IEEE8021X,
|
||||
HOSTAPD_LEVEL_WARNING, "failed to configure a "
|
||||
"new broadcast key");
|
||||
@ -1514,19 +1697,15 @@ static int ieee802_1x_get_eap_user(void *ctx, const u8 *identity,
|
||||
{
|
||||
struct hostapd_data *hapd = ctx;
|
||||
const struct hostapd_eap_user *eap_user;
|
||||
int i, count;
|
||||
int i;
|
||||
|
||||
eap_user = hostapd_get_eap_user(hapd->conf, identity,
|
||||
identity_len, phase2);
|
||||
eap_user = hostapd_get_eap_user(hapd, identity, identity_len, phase2);
|
||||
if (eap_user == NULL)
|
||||
return -1;
|
||||
|
||||
os_memset(user, 0, sizeof(*user));
|
||||
user->phase2 = phase2;
|
||||
count = EAP_USER_MAX_METHODS;
|
||||
if (count > EAP_MAX_METHODS)
|
||||
count = EAP_MAX_METHODS;
|
||||
for (i = 0; i < count; i++) {
|
||||
for (i = 0; i < EAP_MAX_METHODS; i++) {
|
||||
user->methods[i].vendor = eap_user->methods[i].vendor;
|
||||
user->methods[i].method = eap_user->methods[i].method;
|
||||
}
|
||||
@ -1538,6 +1717,7 @@ static int ieee802_1x_get_eap_user(void *ctx, const u8 *identity,
|
||||
os_memcpy(user->password, eap_user->password,
|
||||
eap_user->password_len);
|
||||
user->password_len = eap_user->password_len;
|
||||
user->password_hash = eap_user->password_hash;
|
||||
}
|
||||
user->force_version = eap_user->force_version;
|
||||
user->ttls_auth = eap_user->ttls_auth;
|
||||
@ -1651,6 +1831,9 @@ int ieee802_1x_init(struct hostapd_data *hapd)
|
||||
conf.eap_sim_aka_result_ind = hapd->conf->eap_sim_aka_result_ind;
|
||||
conf.tnc = hapd->conf->tnc;
|
||||
conf.wps = hapd->wps;
|
||||
conf.fragment_size = hapd->conf->fragment_size;
|
||||
conf.pwd_group = hapd->conf->pwd_group;
|
||||
conf.pbc_in_m1 = hapd->conf->pbc_in_m1;
|
||||
|
||||
os_memset(&cb, 0, sizeof(cb));
|
||||
cb.eapol_send = ieee802_1x_eapol_send;
|
||||
@ -1669,7 +1852,7 @@ int ieee802_1x_init(struct hostapd_data *hapd)
|
||||
return -1;
|
||||
|
||||
if ((hapd->conf->ieee802_1x || hapd->conf->wpa) &&
|
||||
hapd->drv.set_drv_ieee8021x(hapd, hapd->conf->iface, 1))
|
||||
hostapd_set_drv_ieee8021x(hapd, hapd->conf->iface, 1))
|
||||
return -1;
|
||||
|
||||
#ifndef CONFIG_NO_RADIUS
|
||||
@ -1680,9 +1863,9 @@ int ieee802_1x_init(struct hostapd_data *hapd)
|
||||
|
||||
if (hapd->conf->default_wep_key_len) {
|
||||
for (i = 0; i < 4; i++)
|
||||
hapd->drv.set_key(hapd->conf->iface, hapd,
|
||||
WPA_ALG_NONE, NULL, i, 0, NULL, 0,
|
||||
NULL, 0);
|
||||
hostapd_drv_set_key(hapd->conf->iface, hapd,
|
||||
WPA_ALG_NONE, NULL, i, 0, NULL, 0,
|
||||
NULL, 0);
|
||||
|
||||
ieee802_1x_rekey(hapd, NULL);
|
||||
|
||||
@ -1700,7 +1883,7 @@ void ieee802_1x_deinit(struct hostapd_data *hapd)
|
||||
|
||||
if (hapd->driver != NULL &&
|
||||
(hapd->conf->ieee802_1x || hapd->conf->wpa))
|
||||
hapd->drv.set_drv_ieee8021x(hapd, hapd->conf->iface, 0);
|
||||
hostapd_set_drv_ieee8021x(hapd, hapd->conf->iface, 0);
|
||||
|
||||
eapol_auth_deinit(hapd->eapol_auth);
|
||||
hapd->eapol_auth = NULL;
|
||||
@ -1711,15 +1894,13 @@ int ieee802_1x_tx_status(struct hostapd_data *hapd, struct sta_info *sta,
|
||||
const u8 *buf, size_t len, int ack)
|
||||
{
|
||||
struct ieee80211_hdr *hdr;
|
||||
struct ieee802_1x_hdr *xhdr;
|
||||
struct ieee802_1x_eapol_key *key;
|
||||
u8 *pos;
|
||||
const unsigned char rfc1042_hdr[ETH_ALEN] =
|
||||
{ 0xaa, 0xaa, 0x03, 0x00, 0x00, 0x00 };
|
||||
|
||||
if (sta == NULL)
|
||||
return -1;
|
||||
if (len < sizeof(*hdr) + sizeof(rfc1042_hdr) + 2 + sizeof(*xhdr))
|
||||
if (len < sizeof(*hdr) + sizeof(rfc1042_hdr) + 2)
|
||||
return 0;
|
||||
|
||||
hdr = (struct ieee80211_hdr *) buf;
|
||||
@ -1731,21 +1912,44 @@ int ieee802_1x_tx_status(struct hostapd_data *hapd, struct sta_info *sta,
|
||||
return 0;
|
||||
pos += 2;
|
||||
|
||||
xhdr = (struct ieee802_1x_hdr *) pos;
|
||||
pos += sizeof(*xhdr);
|
||||
return ieee802_1x_eapol_tx_status(hapd, sta, pos, buf + len - pos,
|
||||
ack);
|
||||
}
|
||||
|
||||
|
||||
int ieee802_1x_eapol_tx_status(struct hostapd_data *hapd, struct sta_info *sta,
|
||||
const u8 *buf, int len, int ack)
|
||||
{
|
||||
const struct ieee802_1x_hdr *xhdr =
|
||||
(const struct ieee802_1x_hdr *) buf;
|
||||
const u8 *pos = buf + sizeof(*xhdr);
|
||||
struct ieee802_1x_eapol_key *key;
|
||||
|
||||
if (len < (int) sizeof(*xhdr))
|
||||
return 0;
|
||||
wpa_printf(MSG_DEBUG, "IEEE 802.1X: " MACSTR " TX status - version=%d "
|
||||
"type=%d length=%d - ack=%d",
|
||||
MAC2STR(sta->addr), xhdr->version, xhdr->type,
|
||||
be_to_host16(xhdr->length), ack);
|
||||
|
||||
if (xhdr->type != IEEE802_1X_TYPE_EAPOL_KEY)
|
||||
return 0;
|
||||
|
||||
if (pos + sizeof(struct wpa_eapol_key) <= buf + len) {
|
||||
const struct wpa_eapol_key *wpa;
|
||||
wpa = (const struct wpa_eapol_key *) pos;
|
||||
if (wpa->type == EAPOL_KEY_TYPE_RSN ||
|
||||
wpa->type == EAPOL_KEY_TYPE_WPA)
|
||||
wpa_auth_eapol_key_tx_status(hapd->wpa_auth,
|
||||
sta->wpa_sm, ack);
|
||||
}
|
||||
|
||||
/* EAPOL EAP-Packet packets are eventually re-sent by either Supplicant
|
||||
* or Authenticator state machines, but EAPOL-Key packets are not
|
||||
* retransmitted in case of failure. Try to re-sent failed EAPOL-Key
|
||||
* retransmitted in case of failure. Try to re-send failed EAPOL-Key
|
||||
* packets couple of times because otherwise STA keys become
|
||||
* unsynchronized with AP. */
|
||||
if (xhdr->type == IEEE802_1X_TYPE_EAPOL_KEY && !ack &&
|
||||
pos + sizeof(*key) <= buf + len) {
|
||||
if (!ack && pos + sizeof(*key) <= buf + len) {
|
||||
key = (struct ieee802_1x_eapol_key *) pos;
|
||||
hostapd_logger(hapd, sta->addr, HOSTAPD_MODULE_IEEE8021X,
|
||||
HOSTAPD_LEVEL_DEBUG, "did not Ack EAPOL-Key "
|
||||
@ -1789,8 +1993,17 @@ u8 * ieee802_1x_get_radius_class(struct eapol_state_machine *sm, size_t *len,
|
||||
}
|
||||
|
||||
|
||||
struct wpabuf * ieee802_1x_get_radius_cui(struct eapol_state_machine *sm)
|
||||
{
|
||||
if (sm == NULL)
|
||||
return NULL;
|
||||
return sm->radius_cui;
|
||||
}
|
||||
|
||||
|
||||
const u8 * ieee802_1x_get_key(struct eapol_state_machine *sm, size_t *len)
|
||||
{
|
||||
*len = 0;
|
||||
if (sm == NULL)
|
||||
return NULL;
|
||||
|
||||
@ -1848,6 +2061,7 @@ int ieee802_1x_get_mib_sta(struct hostapd_data *hapd, struct sta_info *sta,
|
||||
{
|
||||
int len = 0, ret;
|
||||
struct eapol_state_machine *sm = sta->eapol_sm;
|
||||
struct os_time t;
|
||||
|
||||
if (sm == NULL)
|
||||
return 0;
|
||||
@ -1962,6 +2176,7 @@ int ieee802_1x_get_mib_sta(struct hostapd_data *hapd, struct sta_info *sta,
|
||||
len += ret;
|
||||
|
||||
/* dot1xAuthSessionStatsTable */
|
||||
os_get_time(&t);
|
||||
ret = os_snprintf(buf + len, buflen - len,
|
||||
/* TODO: dot1xAuthSessionOctetsRx */
|
||||
/* TODO: dot1xAuthSessionOctetsTx */
|
||||
@ -1976,8 +2191,7 @@ int ieee802_1x_get_mib_sta(struct hostapd_data *hapd, struct sta_info *sta,
|
||||
(wpa_key_mgmt_wpa_ieee8021x(
|
||||
wpa_auth_sta_key_mgmt(sta->wpa_sm))) ?
|
||||
1 : 2,
|
||||
(unsigned int) (time(NULL) -
|
||||
sta->acct_session_start),
|
||||
(unsigned int) (t.sec - sta->acct_session_start),
|
||||
sm->identity);
|
||||
if (ret < 0 || (size_t) ret >= buflen - len)
|
||||
return len;
|
||||
@ -2004,22 +2218,25 @@ static void ieee802_1x_finished(struct hostapd_data *hapd,
|
||||
"Added PMKSA cache entry (IEEE 802.1X)");
|
||||
}
|
||||
|
||||
#ifdef CONFIG_WPS
|
||||
if (!success && (sta->flags & WLAN_STA_WPS)) {
|
||||
if (!success) {
|
||||
/*
|
||||
* Many devices require deauthentication after WPS provisioning
|
||||
* and some may not be be able to do that themselves, so
|
||||
* disconnect the client here.
|
||||
* disconnect the client here. In addition, this may also
|
||||
* benefit IEEE 802.1X/EAPOL authentication cases, too since
|
||||
* the EAPOL PAE state machine would remain in HELD state for
|
||||
* considerable amount of time and some EAP methods, like
|
||||
* EAP-FAST with anonymous provisioning, may require another
|
||||
* EAPOL authentication to be started to complete connection.
|
||||
*/
|
||||
wpa_printf(MSG_DEBUG, "WPS: Force disconnection after "
|
||||
"EAP-Failure");
|
||||
wpa_dbg(hapd->msg_ctx, MSG_DEBUG, "IEEE 802.1X: Force "
|
||||
"disconnection after EAP-Failure");
|
||||
/* Add a small sleep to increase likelihood of previously
|
||||
* requested EAP-Failure TX getting out before this should the
|
||||
* driver reorder operations.
|
||||
*/
|
||||
os_sleep(0, 10000);
|
||||
ap_sta_disconnect(hapd, sta, sta->addr,
|
||||
WLAN_REASON_PREV_AUTH_NOT_VALID);
|
||||
WLAN_REASON_IEEE_802_1X_AUTH_FAILED);
|
||||
}
|
||||
#endif /* CONFIG_WPS */
|
||||
}
|
||||
|
@ -1,15 +1,9 @@
|
||||
/*
|
||||
* hostapd / IEEE 802.1X-2004 Authenticator
|
||||
* Copyright (c) 2002-2007, Jouni Malinen <j@w1.fi>
|
||||
* Copyright (c) 2002-2012, Jouni Malinen <j@w1.fi>
|
||||
*
|
||||
* This program is free software; you can redistribute it and/or modify
|
||||
* it under the terms of the GNU General Public License version 2 as
|
||||
* published by the Free Software Foundation.
|
||||
*
|
||||
* Alternatively, this software may be distributed under the terms of BSD
|
||||
* license.
|
||||
*
|
||||
* See README and COPYING for more details.
|
||||
* This software may be distributed under the terms of the BSD license.
|
||||
* See README for more details.
|
||||
*/
|
||||
|
||||
#ifndef IEEE802_1X_H
|
||||
@ -20,38 +14,8 @@ struct sta_info;
|
||||
struct eapol_state_machine;
|
||||
struct hostapd_config;
|
||||
struct hostapd_bss_config;
|
||||
|
||||
#ifdef _MSC_VER
|
||||
#pragma pack(push, 1)
|
||||
#endif /* _MSC_VER */
|
||||
|
||||
/* RFC 3580, 4. RC4 EAPOL-Key Frame */
|
||||
|
||||
struct ieee802_1x_eapol_key {
|
||||
u8 type;
|
||||
u16 key_length;
|
||||
u8 replay_counter[8]; /* does not repeat within the life of the keying
|
||||
* material used to encrypt the Key field;
|
||||
* 64-bit NTP timestamp MAY be used here */
|
||||
u8 key_iv[16]; /* cryptographically random number */
|
||||
u8 key_index; /* key flag in the most significant bit:
|
||||
* 0 = broadcast (default key),
|
||||
* 1 = unicast (key mapping key); key index is in the
|
||||
* 7 least significant bits */
|
||||
u8 key_signature[16]; /* HMAC-MD5 message integrity check computed with
|
||||
* MS-MPPE-Send-Key as the key */
|
||||
|
||||
/* followed by key: if packet body length = 44 + key length, then the
|
||||
* key field (of key_length bytes) contains the key in encrypted form;
|
||||
* if packet body length = 44, key field is absent and key_length
|
||||
* represents the number of least significant octets from
|
||||
* MS-MPPE-Send-Key attribute to be used as the keying material;
|
||||
* RC4 key used in encryption = Key-IV + MS-MPPE-Recv-Key */
|
||||
} STRUCT_PACKED;
|
||||
|
||||
#ifdef _MSC_VER
|
||||
#pragma pack(pop)
|
||||
#endif /* _MSC_VER */
|
||||
struct hostapd_radius_attr;
|
||||
struct radius_msg;
|
||||
|
||||
|
||||
void ieee802_1x_receive(struct hostapd_data *hapd, const u8 *sa, const u8 *buf,
|
||||
@ -68,9 +32,12 @@ int ieee802_1x_init(struct hostapd_data *hapd);
|
||||
void ieee802_1x_deinit(struct hostapd_data *hapd);
|
||||
int ieee802_1x_tx_status(struct hostapd_data *hapd, struct sta_info *sta,
|
||||
const u8 *buf, size_t len, int ack);
|
||||
int ieee802_1x_eapol_tx_status(struct hostapd_data *hapd, struct sta_info *sta,
|
||||
const u8 *data, int len, int ack);
|
||||
u8 * ieee802_1x_get_identity(struct eapol_state_machine *sm, size_t *len);
|
||||
u8 * ieee802_1x_get_radius_class(struct eapol_state_machine *sm, size_t *len,
|
||||
int idx);
|
||||
struct wpabuf * ieee802_1x_get_radius_cui(struct eapol_state_machine *sm);
|
||||
const u8 * ieee802_1x_get_key(struct eapol_state_machine *sm, size_t *len);
|
||||
void ieee802_1x_notify_port_enabled(struct eapol_state_machine *sm,
|
||||
int enabled);
|
||||
@ -86,4 +53,9 @@ char *eap_type_text(u8 type);
|
||||
const char *radius_mode_txt(struct hostapd_data *hapd);
|
||||
int radius_sta_rate(struct hostapd_data *hapd, struct sta_info *sta);
|
||||
|
||||
int add_common_radius_attr(struct hostapd_data *hapd,
|
||||
struct hostapd_radius_attr *req_attr,
|
||||
struct sta_info *sta,
|
||||
struct radius_msg *msg);
|
||||
|
||||
#endif /* IEEE802_1X_H */
|
||||
|
114
src/ap/p2p_hostapd.c
Normal file
114
src/ap/p2p_hostapd.c
Normal file
@ -0,0 +1,114 @@
|
||||
/*
|
||||
* hostapd / P2P integration
|
||||
* Copyright (c) 2009-2010, Atheros Communications
|
||||
*
|
||||
* This software may be distributed under the terms of the BSD license.
|
||||
* See README for more details.
|
||||
*/
|
||||
|
||||
#include "utils/includes.h"
|
||||
|
||||
#include "utils/common.h"
|
||||
#include "common/ieee802_11_defs.h"
|
||||
#include "p2p/p2p.h"
|
||||
#include "hostapd.h"
|
||||
#include "ap_config.h"
|
||||
#include "ap_drv_ops.h"
|
||||
#include "sta_info.h"
|
||||
#include "p2p_hostapd.h"
|
||||
|
||||
|
||||
#ifdef CONFIG_P2P
|
||||
|
||||
int hostapd_p2p_get_mib_sta(struct hostapd_data *hapd, struct sta_info *sta,
|
||||
char *buf, size_t buflen)
|
||||
{
|
||||
if (sta->p2p_ie == NULL)
|
||||
return 0;
|
||||
|
||||
return p2p_ie_text(sta->p2p_ie, buf, buf + buflen);
|
||||
}
|
||||
|
||||
|
||||
int hostapd_p2p_set_noa(struct hostapd_data *hapd, u8 count, int start,
|
||||
int duration)
|
||||
{
|
||||
wpa_printf(MSG_DEBUG, "P2P: Set NoA parameters: count=%u start=%d "
|
||||
"duration=%d", count, start, duration);
|
||||
|
||||
if (count == 0) {
|
||||
hapd->noa_enabled = 0;
|
||||
hapd->noa_start = 0;
|
||||
hapd->noa_duration = 0;
|
||||
}
|
||||
|
||||
if (count != 255) {
|
||||
wpa_printf(MSG_DEBUG, "P2P: Non-periodic NoA - set "
|
||||
"NoA parameters");
|
||||
return hostapd_driver_set_noa(hapd, count, start, duration);
|
||||
}
|
||||
|
||||
hapd->noa_enabled = 1;
|
||||
hapd->noa_start = start;
|
||||
hapd->noa_duration = duration;
|
||||
|
||||
if (hapd->num_sta_no_p2p == 0) {
|
||||
wpa_printf(MSG_DEBUG, "P2P: No legacy STAs connected - update "
|
||||
"periodic NoA parameters");
|
||||
return hostapd_driver_set_noa(hapd, count, start, duration);
|
||||
}
|
||||
|
||||
wpa_printf(MSG_DEBUG, "P2P: Legacy STA(s) connected - do not enable "
|
||||
"periodic NoA");
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
|
||||
void hostapd_p2p_non_p2p_sta_connected(struct hostapd_data *hapd)
|
||||
{
|
||||
wpa_printf(MSG_DEBUG, "P2P: First non-P2P device connected");
|
||||
|
||||
if (hapd->noa_enabled) {
|
||||
wpa_printf(MSG_DEBUG, "P2P: Disable periodic NoA");
|
||||
hostapd_driver_set_noa(hapd, 0, 0, 0);
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
void hostapd_p2p_non_p2p_sta_disconnected(struct hostapd_data *hapd)
|
||||
{
|
||||
wpa_printf(MSG_DEBUG, "P2P: Last non-P2P device disconnected");
|
||||
|
||||
if (hapd->noa_enabled) {
|
||||
wpa_printf(MSG_DEBUG, "P2P: Enable periodic NoA");
|
||||
hostapd_driver_set_noa(hapd, 255, hapd->noa_start,
|
||||
hapd->noa_duration);
|
||||
}
|
||||
}
|
||||
|
||||
#endif /* CONFIG_P2P */
|
||||
|
||||
|
||||
#ifdef CONFIG_P2P_MANAGER
|
||||
u8 * hostapd_eid_p2p_manage(struct hostapd_data *hapd, u8 *eid)
|
||||
{
|
||||
u8 bitmap;
|
||||
*eid++ = WLAN_EID_VENDOR_SPECIFIC;
|
||||
*eid++ = 4 + 3 + 1;
|
||||
WPA_PUT_BE24(eid, OUI_WFA);
|
||||
eid += 3;
|
||||
*eid++ = P2P_OUI_TYPE;
|
||||
|
||||
*eid++ = P2P_ATTR_MANAGEABILITY;
|
||||
WPA_PUT_LE16(eid, 1);
|
||||
eid += 2;
|
||||
bitmap = P2P_MAN_DEVICE_MANAGEMENT;
|
||||
if (hapd->conf->p2p & P2P_ALLOW_CROSS_CONNECTION)
|
||||
bitmap |= P2P_MAN_CROSS_CONNECTION_PERMITTED;
|
||||
bitmap |= P2P_MAN_COEXISTENCE_OPTIONAL;
|
||||
*eid++ = bitmap;
|
||||
|
||||
return eid;
|
||||
}
|
||||
#endif /* CONFIG_P2P_MANAGER */
|
35
src/ap/p2p_hostapd.h
Normal file
35
src/ap/p2p_hostapd.h
Normal file
@ -0,0 +1,35 @@
|
||||
/*
|
||||
* hostapd / P2P integration
|
||||
* Copyright (c) 2009-2010, Atheros Communications
|
||||
*
|
||||
* This software may be distributed under the terms of the BSD license.
|
||||
* See README for more details.
|
||||
*/
|
||||
|
||||
#ifndef P2P_HOSTAPD_H
|
||||
#define P2P_HOSTAPD_H
|
||||
|
||||
#ifdef CONFIG_P2P
|
||||
|
||||
int hostapd_p2p_get_mib_sta(struct hostapd_data *hapd, struct sta_info *sta,
|
||||
char *buf, size_t buflen);
|
||||
int hostapd_p2p_set_noa(struct hostapd_data *hapd, u8 count, int start,
|
||||
int duration);
|
||||
void hostapd_p2p_non_p2p_sta_connected(struct hostapd_data *hapd);
|
||||
void hostapd_p2p_non_p2p_sta_disconnected(struct hostapd_data *hapd);
|
||||
|
||||
|
||||
#else /* CONFIG_P2P */
|
||||
|
||||
static inline int hostapd_p2p_get_mib_sta(struct hostapd_data *hapd,
|
||||
struct sta_info *sta,
|
||||
char *buf, size_t buflen)
|
||||
{
|
||||
return 0;
|
||||
}
|
||||
|
||||
#endif /* CONFIG_P2P */
|
||||
|
||||
u8 * hostapd_eid_p2p_manage(struct hostapd_data *hapd, u8 *eid);
|
||||
|
||||
#endif /* P2P_HOSTAPD_H */
|
@ -2,14 +2,8 @@
|
||||
* hostapd - PeerKey for Direct Link Setup (DLS)
|
||||
* Copyright (c) 2006-2009, Jouni Malinen <j@w1.fi>
|
||||
*
|
||||
* This program is free software; you can redistribute it and/or modify
|
||||
* it under the terms of the GNU General Public License version 2 as
|
||||
* published by the Free Software Foundation.
|
||||
*
|
||||
* Alternatively, this software may be distributed under the terms of BSD
|
||||
* license.
|
||||
*
|
||||
* See README and COPYING for more details.
|
||||
* This software may be distributed under the terms of the BSD license.
|
||||
* See README for more details.
|
||||
*/
|
||||
|
||||
#include "utils/includes.h"
|
||||
@ -18,6 +12,7 @@
|
||||
#include "utils/eloop.h"
|
||||
#include "crypto/sha1.h"
|
||||
#include "crypto/sha256.h"
|
||||
#include "crypto/random.h"
|
||||
#include "wpa_auth.h"
|
||||
#include "wpa_auth_i.h"
|
||||
#include "wpa_auth_ie.h"
|
||||
@ -294,7 +289,7 @@ void wpa_smk_m3(struct wpa_authenticator *wpa_auth,
|
||||
return;
|
||||
}
|
||||
|
||||
if (os_get_random(smk, PMK_LEN)) {
|
||||
if (random_get_bytes(smk, PMK_LEN)) {
|
||||
wpa_printf(MSG_DEBUG, "RSN: Failed to generate SMK");
|
||||
return;
|
||||
}
|
||||
|
@ -1,15 +1,9 @@
|
||||
/*
|
||||
* hostapd - PMKSA cache for IEEE 802.11i RSN
|
||||
* Copyright (c) 2004-2008, Jouni Malinen <j@w1.fi>
|
||||
* Copyright (c) 2004-2008, 2012, Jouni Malinen <j@w1.fi>
|
||||
*
|
||||
* This program is free software; you can redistribute it and/or modify
|
||||
* it under the terms of the GNU General Public License version 2 as
|
||||
* published by the Free Software Foundation.
|
||||
*
|
||||
* Alternatively, this software may be distributed under the terms of BSD
|
||||
* license.
|
||||
*
|
||||
* See README and COPYING for more details.
|
||||
* This software may be distributed under the terms of the BSD license.
|
||||
* See README for more details.
|
||||
*/
|
||||
|
||||
#include "utils/includes.h"
|
||||
@ -46,6 +40,7 @@ static void _pmksa_cache_free_entry(struct rsn_pmksa_cache_entry *entry)
|
||||
if (entry == NULL)
|
||||
return;
|
||||
os_free(entry->identity);
|
||||
wpabuf_free(entry->cui);
|
||||
#ifndef CONFIG_NO_RADIUS
|
||||
radius_free_class(&entry->radius_class);
|
||||
#endif /* CONFIG_NO_RADIUS */
|
||||
@ -100,11 +95,9 @@ static void pmksa_cache_expire(void *eloop_ctx, void *timeout_ctx)
|
||||
|
||||
os_get_time(&now);
|
||||
while (pmksa->pmksa && pmksa->pmksa->expiration <= now.sec) {
|
||||
struct rsn_pmksa_cache_entry *entry = pmksa->pmksa;
|
||||
pmksa->pmksa = entry->next;
|
||||
wpa_printf(MSG_DEBUG, "RSN: expired PMKSA cache entry for "
|
||||
MACSTR, MAC2STR(entry->spa));
|
||||
pmksa_cache_free_entry(pmksa, entry);
|
||||
MACSTR, MAC2STR(pmksa->pmksa->spa));
|
||||
pmksa_cache_free_entry(pmksa, pmksa->pmksa);
|
||||
}
|
||||
|
||||
pmksa_cache_set_expiration(pmksa);
|
||||
@ -142,6 +135,9 @@ static void pmksa_cache_from_eapol_data(struct rsn_pmksa_cache_entry *entry,
|
||||
}
|
||||
}
|
||||
|
||||
if (eapol->radius_cui)
|
||||
entry->cui = wpabuf_dup(eapol->radius_cui);
|
||||
|
||||
#ifndef CONFIG_NO_RADIUS
|
||||
radius_copy_class(&entry->radius_class, &eapol->radius_class);
|
||||
#endif /* CONFIG_NO_RADIUS */
|
||||
@ -169,6 +165,11 @@ void pmksa_cache_to_eapol_data(struct rsn_pmksa_cache_entry *entry,
|
||||
eapol->identity, eapol->identity_len);
|
||||
}
|
||||
|
||||
if (entry->cui) {
|
||||
wpabuf_free(eapol->radius_cui);
|
||||
eapol->radius_cui = wpabuf_dup(entry->cui);
|
||||
}
|
||||
|
||||
#ifndef CONFIG_NO_RADIUS
|
||||
radius_free_class(&eapol->radius_class);
|
||||
radius_copy_class(&eapol->radius_class, &entry->radius_class);
|
||||
@ -208,6 +209,8 @@ static void pmksa_cache_link_entry(struct rsn_pmksa_cache *pmksa,
|
||||
pmksa->pmkid[PMKID_HASH(entry->pmkid)] = entry;
|
||||
|
||||
pmksa->pmksa_count++;
|
||||
if (prev == NULL)
|
||||
pmksa_cache_set_expiration(pmksa);
|
||||
wpa_printf(MSG_DEBUG, "RSN: added PMKSA cache entry for " MACSTR,
|
||||
MAC2STR(entry->spa));
|
||||
wpa_hexdump(MSG_DEBUG, "RSN: added PMKID", entry->pmkid, PMKID_LEN);
|
||||
@ -305,6 +308,8 @@ pmksa_cache_add_okc(struct rsn_pmksa_cache *pmksa,
|
||||
old_entry->identity_len);
|
||||
}
|
||||
}
|
||||
if (old_entry->cui)
|
||||
entry->cui = wpabuf_dup(old_entry->cui);
|
||||
#ifndef CONFIG_NO_RADIUS
|
||||
radius_copy_class(&entry->radius_class, &old_entry->radius_class);
|
||||
#endif /* CONFIG_NO_RADIUS */
|
||||
|
@ -1,15 +1,9 @@
|
||||
/*
|
||||
* hostapd - PMKSA cache for IEEE 802.11i RSN
|
||||
* Copyright (c) 2004-2008, Jouni Malinen <j@w1.fi>
|
||||
* Copyright (c) 2004-2008, 2012, Jouni Malinen <j@w1.fi>
|
||||
*
|
||||
* This program is free software; you can redistribute it and/or modify
|
||||
* it under the terms of the GNU General Public License version 2 as
|
||||
* published by the Free Software Foundation.
|
||||
*
|
||||
* Alternatively, this software may be distributed under the terms of BSD
|
||||
* license.
|
||||
*
|
||||
* See README and COPYING for more details.
|
||||
* This software may be distributed under the terms of the BSD license.
|
||||
* See README for more details.
|
||||
*/
|
||||
|
||||
#ifndef PMKSA_CACHE_H
|
||||
@ -31,6 +25,7 @@ struct rsn_pmksa_cache_entry {
|
||||
|
||||
u8 *identity;
|
||||
size_t identity_len;
|
||||
struct wpabuf *cui;
|
||||
struct radius_class_data radius_class;
|
||||
u8 eap_type_authsrv;
|
||||
int vlan_id;
|
||||
|
@ -2,14 +2,8 @@
|
||||
* hostapd - Authenticator for IEEE 802.11i RSN pre-authentication
|
||||
* Copyright (c) 2004-2007, Jouni Malinen <j@w1.fi>
|
||||
*
|
||||
* This program is free software; you can redistribute it and/or modify
|
||||
* it under the terms of the GNU General Public License version 2 as
|
||||
* published by the Free Software Foundation.
|
||||
*
|
||||
* Alternatively, this software may be distributed under the terms of BSD
|
||||
* license.
|
||||
*
|
||||
* See README and COPYING for more details.
|
||||
* This software may be distributed under the terms of the BSD license.
|
||||
* See README for more details.
|
||||
*/
|
||||
|
||||
#include "utils/includes.h"
|
||||
|
@ -2,14 +2,8 @@
|
||||
* hostapd - Authenticator for IEEE 802.11i RSN pre-authentication
|
||||
* Copyright (c) 2004-2005, Jouni Malinen <j@w1.fi>
|
||||
*
|
||||
* This program is free software; you can redistribute it and/or modify
|
||||
* it under the terms of the GNU General Public License version 2 as
|
||||
* published by the Free Software Foundation.
|
||||
*
|
||||
* Alternatively, this software may be distributed under the terms of BSD
|
||||
* license.
|
||||
*
|
||||
* See README and COPYING for more details.
|
||||
* This software may be distributed under the terms of the BSD license.
|
||||
* See README for more details.
|
||||
*/
|
||||
|
||||
#ifndef PREAUTH_H
|
||||
|
@ -1,15 +1,9 @@
|
||||
/*
|
||||
* hostapd / Station table
|
||||
* Copyright (c) 2002-2009, Jouni Malinen <j@w1.fi>
|
||||
* Copyright (c) 2002-2011, Jouni Malinen <j@w1.fi>
|
||||
*
|
||||
* This program is free software; you can redistribute it and/or modify
|
||||
* it under the terms of the GNU General Public License version 2 as
|
||||
* published by the Free Software Foundation.
|
||||
*
|
||||
* Alternatively, this software may be distributed under the terms of BSD
|
||||
* license.
|
||||
*
|
||||
* See README and COPYING for more details.
|
||||
* This software may be distributed under the terms of the BSD license.
|
||||
* See README for more details.
|
||||
*/
|
||||
|
||||
#include "utils/includes.h"
|
||||
@ -17,27 +11,36 @@
|
||||
#include "utils/common.h"
|
||||
#include "utils/eloop.h"
|
||||
#include "common/ieee802_11_defs.h"
|
||||
#include "common/wpa_ctrl.h"
|
||||
#include "radius/radius.h"
|
||||
#include "radius/radius_client.h"
|
||||
#include "drivers/driver.h"
|
||||
#include "p2p/p2p.h"
|
||||
#include "hostapd.h"
|
||||
#include "accounting.h"
|
||||
#include "ieee802_1x.h"
|
||||
#include "ieee802_11.h"
|
||||
#include "ieee802_11_auth.h"
|
||||
#include "wpa_auth.h"
|
||||
#include "preauth_auth.h"
|
||||
#include "ap_config.h"
|
||||
#include "beacon.h"
|
||||
#include "ap_mlme.h"
|
||||
#include "vlan_init.h"
|
||||
#include "p2p_hostapd.h"
|
||||
#include "ap_drv_ops.h"
|
||||
#include "gas_serv.h"
|
||||
#include "sta_info.h"
|
||||
|
||||
static void ap_sta_remove_in_other_bss(struct hostapd_data *hapd,
|
||||
struct sta_info *sta);
|
||||
static void ap_handle_session_timer(void *eloop_ctx, void *timeout_ctx);
|
||||
static void ap_sta_deauth_cb_timeout(void *eloop_ctx, void *timeout_ctx);
|
||||
static void ap_sta_disassoc_cb_timeout(void *eloop_ctx, void *timeout_ctx);
|
||||
#ifdef CONFIG_IEEE80211W
|
||||
static void ap_sa_query_timer(void *eloop_ctx, void *timeout_ctx);
|
||||
#endif /* CONFIG_IEEE80211W */
|
||||
static int ap_sta_remove(struct hostapd_data *hapd, struct sta_info *sta);
|
||||
|
||||
int ap_for_each_sta(struct hostapd_data *hapd,
|
||||
int (*cb)(struct hostapd_data *hapd, struct sta_info *sta,
|
||||
@ -121,11 +124,14 @@ void ap_free_sta(struct hostapd_data *hapd, struct sta_info *sta)
|
||||
|
||||
accounting_sta_stop(hapd, sta);
|
||||
|
||||
/* just in case */
|
||||
ap_sta_set_authorized(hapd, sta, 0);
|
||||
|
||||
if (sta->flags & WLAN_STA_WDS)
|
||||
hapd->drv.set_wds_sta(hapd, sta->addr, sta->aid, 0);
|
||||
hostapd_set_wds_sta(hapd, sta->addr, sta->aid, 0);
|
||||
|
||||
if (!(sta->flags & WLAN_STA_PREAUTH))
|
||||
hapd->drv.sta_remove(hapd, sta->addr);
|
||||
hostapd_drv_sta_remove(hapd, sta->addr);
|
||||
|
||||
ap_sta_hash_del(hapd, sta);
|
||||
ap_sta_list_del(hapd, sta);
|
||||
@ -173,6 +179,15 @@ void ap_free_sta(struct hostapd_data *hapd, struct sta_info *sta)
|
||||
hapd->iface->num_sta_ht_20mhz--;
|
||||
}
|
||||
|
||||
#ifdef CONFIG_P2P
|
||||
if (sta->no_p2p_set) {
|
||||
sta->no_p2p_set = 0;
|
||||
hapd->num_sta_no_p2p--;
|
||||
if (hapd->num_sta_no_p2p == 0)
|
||||
hostapd_p2p_non_p2p_sta_disconnected(hapd);
|
||||
}
|
||||
#endif /* CONFIG_P2P */
|
||||
|
||||
#if defined(NEED_AP_MLME) && defined(CONFIG_IEEE80211N)
|
||||
if (hostapd_ht_operation_update(hapd->iface) > 0)
|
||||
set_beacon++;
|
||||
@ -181,8 +196,12 @@ void ap_free_sta(struct hostapd_data *hapd, struct sta_info *sta)
|
||||
if (set_beacon)
|
||||
ieee802_11_set_beacons(hapd->iface);
|
||||
|
||||
wpa_printf(MSG_DEBUG, "%s: cancel ap_handle_timer for " MACSTR,
|
||||
__func__, MAC2STR(sta->addr));
|
||||
eloop_cancel_timeout(ap_handle_timer, hapd, sta);
|
||||
eloop_cancel_timeout(ap_handle_session_timer, hapd, sta);
|
||||
eloop_cancel_timeout(ap_sta_deauth_cb_timeout, hapd, sta);
|
||||
eloop_cancel_timeout(ap_sta_disassoc_cb_timeout, hapd, sta);
|
||||
|
||||
ieee802_1x_free_station(sta);
|
||||
wpa_auth_sta_deinit(sta->wpa_sm);
|
||||
@ -199,9 +218,27 @@ void ap_free_sta(struct hostapd_data *hapd, struct sta_info *sta)
|
||||
eloop_cancel_timeout(ap_sa_query_timer, hapd, sta);
|
||||
#endif /* CONFIG_IEEE80211W */
|
||||
|
||||
#ifdef CONFIG_P2P
|
||||
p2p_group_notif_disassoc(hapd->p2p_group, sta->addr);
|
||||
#endif /* CONFIG_P2P */
|
||||
|
||||
#ifdef CONFIG_INTERWORKING
|
||||
if (sta->gas_dialog) {
|
||||
int i;
|
||||
for (i = 0; i < GAS_DIALOG_MAX; i++)
|
||||
gas_serv_dialog_clear(&sta->gas_dialog[i]);
|
||||
os_free(sta->gas_dialog);
|
||||
}
|
||||
#endif /* CONFIG_INTERWORKING */
|
||||
|
||||
wpabuf_free(sta->wps_ie);
|
||||
wpabuf_free(sta->p2p_ie);
|
||||
wpabuf_free(sta->hs20_ie);
|
||||
|
||||
os_free(sta->ht_capabilities);
|
||||
hostapd_free_psk_list(sta->psk);
|
||||
os_free(sta->identity);
|
||||
os_free(sta->radius_cui);
|
||||
|
||||
os_free(sta);
|
||||
}
|
||||
@ -241,6 +278,9 @@ void ap_handle_timer(void *eloop_ctx, void *timeout_ctx)
|
||||
struct sta_info *sta = timeout_ctx;
|
||||
unsigned long next_time = 0;
|
||||
|
||||
wpa_printf(MSG_DEBUG, "%s: " MACSTR " flags=0x%x timeout_next=%d",
|
||||
__func__, MAC2STR(sta->addr), sta->flags,
|
||||
sta->timeout_next);
|
||||
if (sta->timeout_next == STA_REMOVE) {
|
||||
hostapd_logger(hapd, sta->addr, HOSTAPD_MODULE_IEEE80211,
|
||||
HOSTAPD_LEVEL_INFO, "deauthenticated due to "
|
||||
@ -253,27 +293,51 @@ void ap_handle_timer(void *eloop_ctx, void *timeout_ctx)
|
||||
(sta->timeout_next == STA_NULLFUNC ||
|
||||
sta->timeout_next == STA_DISASSOC)) {
|
||||
int inactive_sec;
|
||||
wpa_printf(MSG_DEBUG, "Checking STA " MACSTR " inactivity:",
|
||||
MAC2STR(sta->addr));
|
||||
inactive_sec = hapd->drv.get_inact_sec(hapd, sta->addr);
|
||||
/*
|
||||
* Add random value to timeout so that we don't end up bouncing
|
||||
* all stations at the same time if we have lots of associated
|
||||
* stations that are idle (but keep re-associating).
|
||||
*/
|
||||
int fuzz = os_random() % 20;
|
||||
inactive_sec = hostapd_drv_get_inact_sec(hapd, sta->addr);
|
||||
if (inactive_sec == -1) {
|
||||
wpa_printf(MSG_DEBUG, "Could not get station info "
|
||||
"from kernel driver for " MACSTR ".",
|
||||
MAC2STR(sta->addr));
|
||||
wpa_msg(hapd->msg_ctx, MSG_DEBUG,
|
||||
"Check inactivity: Could not "
|
||||
"get station info from kernel driver for "
|
||||
MACSTR, MAC2STR(sta->addr));
|
||||
/*
|
||||
* The driver may not support this functionality.
|
||||
* Anyway, try again after the next inactivity timeout,
|
||||
* but do not disconnect the station now.
|
||||
*/
|
||||
next_time = hapd->conf->ap_max_inactivity + fuzz;
|
||||
} else if (inactive_sec < hapd->conf->ap_max_inactivity &&
|
||||
sta->flags & WLAN_STA_ASSOC) {
|
||||
/* station activity detected; reset timeout state */
|
||||
wpa_printf(MSG_DEBUG, " Station has been active");
|
||||
wpa_msg(hapd->msg_ctx, MSG_DEBUG,
|
||||
"Station " MACSTR " has been active %is ago",
|
||||
MAC2STR(sta->addr), inactive_sec);
|
||||
sta->timeout_next = STA_NULLFUNC;
|
||||
next_time = hapd->conf->ap_max_inactivity -
|
||||
next_time = hapd->conf->ap_max_inactivity + fuzz -
|
||||
inactive_sec;
|
||||
} else {
|
||||
wpa_msg(hapd->msg_ctx, MSG_DEBUG,
|
||||
"Station " MACSTR " has been "
|
||||
"inactive too long: %d sec, max allowed: %d",
|
||||
MAC2STR(sta->addr), inactive_sec,
|
||||
hapd->conf->ap_max_inactivity);
|
||||
|
||||
if (hapd->conf->skip_inactivity_poll)
|
||||
sta->timeout_next = STA_DISASSOC;
|
||||
}
|
||||
}
|
||||
|
||||
if ((sta->flags & WLAN_STA_ASSOC) &&
|
||||
sta->timeout_next == STA_DISASSOC &&
|
||||
!(sta->flags & WLAN_STA_PENDING_POLL)) {
|
||||
wpa_printf(MSG_DEBUG, " Station has ACKed data poll");
|
||||
!(sta->flags & WLAN_STA_PENDING_POLL) &&
|
||||
!hapd->conf->skip_inactivity_poll) {
|
||||
wpa_msg(hapd->msg_ctx, MSG_DEBUG, "Station " MACSTR
|
||||
" has ACKed data poll", MAC2STR(sta->addr));
|
||||
/* data nullfunc frame poll did not produce TX errors; assume
|
||||
* station ACKed it */
|
||||
sta->timeout_next = STA_NULLFUNC;
|
||||
@ -281,6 +345,9 @@ void ap_handle_timer(void *eloop_ctx, void *timeout_ctx)
|
||||
}
|
||||
|
||||
if (next_time) {
|
||||
wpa_printf(MSG_DEBUG, "%s: register ap_handle_timer timeout "
|
||||
"for " MACSTR " (%lu seconds)",
|
||||
__func__, MAC2STR(sta->addr), next_time);
|
||||
eloop_register_timeout(next_time, 0, ap_handle_timer, hapd,
|
||||
sta);
|
||||
return;
|
||||
@ -288,52 +355,24 @@ void ap_handle_timer(void *eloop_ctx, void *timeout_ctx)
|
||||
|
||||
if (sta->timeout_next == STA_NULLFUNC &&
|
||||
(sta->flags & WLAN_STA_ASSOC)) {
|
||||
#ifndef CONFIG_NATIVE_WINDOWS
|
||||
/* send data frame to poll STA and check whether this frame
|
||||
* is ACKed */
|
||||
struct ieee80211_hdr hdr;
|
||||
|
||||
wpa_printf(MSG_DEBUG, " Polling STA with data frame");
|
||||
wpa_printf(MSG_DEBUG, " Polling STA");
|
||||
sta->flags |= WLAN_STA_PENDING_POLL;
|
||||
|
||||
os_memset(&hdr, 0, sizeof(hdr));
|
||||
if (hapd->driver &&
|
||||
os_strcmp(hapd->driver->name, "hostap") == 0) {
|
||||
/*
|
||||
* WLAN_FC_STYPE_NULLFUNC would be more appropriate,
|
||||
* but it is apparently not retried so TX Exc events
|
||||
* are not received for it.
|
||||
*/
|
||||
hdr.frame_control =
|
||||
IEEE80211_FC(WLAN_FC_TYPE_DATA,
|
||||
WLAN_FC_STYPE_DATA);
|
||||
} else {
|
||||
hdr.frame_control =
|
||||
IEEE80211_FC(WLAN_FC_TYPE_DATA,
|
||||
WLAN_FC_STYPE_NULLFUNC);
|
||||
}
|
||||
|
||||
hdr.frame_control |= host_to_le16(WLAN_FC_FROMDS);
|
||||
os_memcpy(hdr.IEEE80211_DA_FROMDS, sta->addr, ETH_ALEN);
|
||||
os_memcpy(hdr.IEEE80211_BSSID_FROMDS, hapd->own_addr,
|
||||
ETH_ALEN);
|
||||
os_memcpy(hdr.IEEE80211_SA_FROMDS, hapd->own_addr, ETH_ALEN);
|
||||
|
||||
if (hapd->drv.send_mgmt_frame(hapd, &hdr, sizeof(hdr)) < 0)
|
||||
perror("ap_handle_timer: send");
|
||||
#endif /* CONFIG_NATIVE_WINDOWS */
|
||||
hostapd_drv_poll_client(hapd, hapd->own_addr, sta->addr,
|
||||
sta->flags & WLAN_STA_WMM);
|
||||
} else if (sta->timeout_next != STA_REMOVE) {
|
||||
int deauth = sta->timeout_next == STA_DEAUTH;
|
||||
|
||||
wpa_printf(MSG_DEBUG, "Sending %s info to STA " MACSTR,
|
||||
deauth ? "deauthentication" : "disassociation",
|
||||
MAC2STR(sta->addr));
|
||||
wpa_dbg(hapd->msg_ctx, MSG_DEBUG,
|
||||
"Timeout, sending %s info to STA " MACSTR,
|
||||
deauth ? "deauthentication" : "disassociation",
|
||||
MAC2STR(sta->addr));
|
||||
|
||||
if (deauth) {
|
||||
hapd->drv.sta_deauth(hapd, sta->addr,
|
||||
WLAN_REASON_PREV_AUTH_NOT_VALID);
|
||||
hostapd_drv_sta_deauth(
|
||||
hapd, sta->addr,
|
||||
WLAN_REASON_PREV_AUTH_NOT_VALID);
|
||||
} else {
|
||||
hapd->drv.sta_disassoc(
|
||||
hostapd_drv_sta_disassoc(
|
||||
hapd, sta->addr,
|
||||
WLAN_REASON_DISASSOC_DUE_TO_INACTIVITY);
|
||||
}
|
||||
@ -342,10 +381,14 @@ void ap_handle_timer(void *eloop_ctx, void *timeout_ctx)
|
||||
switch (sta->timeout_next) {
|
||||
case STA_NULLFUNC:
|
||||
sta->timeout_next = STA_DISASSOC;
|
||||
wpa_printf(MSG_DEBUG, "%s: register ap_handle_timer timeout "
|
||||
"for " MACSTR " (%d seconds - AP_DISASSOC_DELAY)",
|
||||
__func__, MAC2STR(sta->addr), AP_DISASSOC_DELAY);
|
||||
eloop_register_timeout(AP_DISASSOC_DELAY, 0, ap_handle_timer,
|
||||
hapd, sta);
|
||||
break;
|
||||
case STA_DISASSOC:
|
||||
ap_sta_set_authorized(hapd, sta, 0);
|
||||
sta->flags &= ~WLAN_STA_ASSOC;
|
||||
ieee802_1x_notify_port_enabled(sta->eapol_sm, 0);
|
||||
if (!sta->acct_terminate_cause)
|
||||
@ -357,6 +400,9 @@ void ap_handle_timer(void *eloop_ctx, void *timeout_ctx)
|
||||
HOSTAPD_LEVEL_INFO, "disassociated due to "
|
||||
"inactivity");
|
||||
sta->timeout_next = STA_DEAUTH;
|
||||
wpa_printf(MSG_DEBUG, "%s: register ap_handle_timer timeout "
|
||||
"for " MACSTR " (%d seconds - AP_DEAUTH_DELAY)",
|
||||
__func__, MAC2STR(sta->addr), AP_DEAUTH_DELAY);
|
||||
eloop_register_timeout(AP_DEAUTH_DELAY, 0, ap_handle_timer,
|
||||
hapd, sta);
|
||||
mlme_disassociate_indication(
|
||||
@ -366,7 +412,7 @@ void ap_handle_timer(void *eloop_ctx, void *timeout_ctx)
|
||||
case STA_REMOVE:
|
||||
hostapd_logger(hapd, sta->addr, HOSTAPD_MODULE_IEEE80211,
|
||||
HOSTAPD_LEVEL_INFO, "deauthenticated due to "
|
||||
"inactivity");
|
||||
"inactivity (timer DEAUTH/REMOVE)");
|
||||
if (!sta->acct_terminate_cause)
|
||||
sta->acct_terminate_cause =
|
||||
RADIUS_ACCT_TERMINATE_CAUSE_IDLE_TIMEOUT;
|
||||
@ -385,8 +431,14 @@ static void ap_handle_session_timer(void *eloop_ctx, void *timeout_ctx)
|
||||
struct sta_info *sta = timeout_ctx;
|
||||
u8 addr[ETH_ALEN];
|
||||
|
||||
if (!(sta->flags & WLAN_STA_AUTH))
|
||||
if (!(sta->flags & WLAN_STA_AUTH)) {
|
||||
if (sta->flags & WLAN_STA_GAS) {
|
||||
wpa_printf(MSG_DEBUG, "GAS: Remove temporary STA "
|
||||
"entry " MACSTR, MAC2STR(sta->addr));
|
||||
ap_free_sta(hapd, sta);
|
||||
}
|
||||
return;
|
||||
}
|
||||
|
||||
mlme_deauthenticate_indication(hapd, sta,
|
||||
WLAN_REASON_PREV_AUTH_NOT_VALID);
|
||||
@ -397,7 +449,7 @@ static void ap_handle_session_timer(void *eloop_ctx, void *timeout_ctx)
|
||||
RADIUS_ACCT_TERMINATE_CAUSE_SESSION_TIMEOUT;
|
||||
os_memcpy(addr, sta->addr, ETH_ALEN);
|
||||
ap_free_sta(hapd, sta);
|
||||
hapd->drv.sta_deauth(hapd, addr, WLAN_REASON_PREV_AUTH_NOT_VALID);
|
||||
hostapd_drv_sta_deauth(hapd, addr, WLAN_REASON_PREV_AUTH_NOT_VALID);
|
||||
}
|
||||
|
||||
|
||||
@ -441,8 +493,13 @@ struct sta_info * ap_sta_add(struct hostapd_data *hapd, const u8 *addr)
|
||||
return NULL;
|
||||
}
|
||||
sta->acct_interim_interval = hapd->conf->acct_interim_interval;
|
||||
accounting_sta_get_id(hapd, sta);
|
||||
|
||||
/* initialize STA info data */
|
||||
wpa_printf(MSG_DEBUG, "%s: register ap_handle_timer timeout "
|
||||
"for " MACSTR " (%d seconds - ap_max_inactivity)",
|
||||
__func__, MAC2STR(addr),
|
||||
hapd->conf->ap_max_inactivity);
|
||||
eloop_register_timeout(hapd->conf->ap_max_inactivity, 0,
|
||||
ap_handle_timer, hapd, sta);
|
||||
os_memcpy(sta->addr, addr, ETH_ALEN);
|
||||
@ -463,7 +520,7 @@ static int ap_sta_remove(struct hostapd_data *hapd, struct sta_info *sta)
|
||||
|
||||
wpa_printf(MSG_DEBUG, "Removing STA " MACSTR " from kernel driver",
|
||||
MAC2STR(sta->addr));
|
||||
if (hapd->drv.sta_remove(hapd, sta->addr) &&
|
||||
if (hostapd_drv_sta_remove(hapd, sta->addr) &&
|
||||
sta->flags & WLAN_STA_ASSOC) {
|
||||
wpa_printf(MSG_DEBUG, "Could not remove station " MACSTR
|
||||
" from kernel driver.", MAC2STR(sta->addr));
|
||||
@ -498,21 +555,51 @@ static void ap_sta_remove_in_other_bss(struct hostapd_data *hapd,
|
||||
}
|
||||
|
||||
|
||||
static void ap_sta_disassoc_cb_timeout(void *eloop_ctx, void *timeout_ctx)
|
||||
{
|
||||
struct hostapd_data *hapd = eloop_ctx;
|
||||
struct sta_info *sta = timeout_ctx;
|
||||
|
||||
ap_sta_remove(hapd, sta);
|
||||
mlme_disassociate_indication(hapd, sta, sta->disassoc_reason);
|
||||
}
|
||||
|
||||
|
||||
void ap_sta_disassociate(struct hostapd_data *hapd, struct sta_info *sta,
|
||||
u16 reason)
|
||||
{
|
||||
wpa_printf(MSG_DEBUG, "%s: disassociate STA " MACSTR,
|
||||
hapd->conf->iface, MAC2STR(sta->addr));
|
||||
sta->flags &= ~WLAN_STA_ASSOC;
|
||||
ap_sta_remove(hapd, sta);
|
||||
ap_sta_set_authorized(hapd, sta, 0);
|
||||
sta->timeout_next = STA_DEAUTH;
|
||||
wpa_printf(MSG_DEBUG, "%s: reschedule ap_handle_timer timeout "
|
||||
"for " MACSTR " (%d seconds - "
|
||||
"AP_MAX_INACTIVITY_AFTER_DISASSOC)",
|
||||
__func__, MAC2STR(sta->addr),
|
||||
AP_MAX_INACTIVITY_AFTER_DISASSOC);
|
||||
eloop_cancel_timeout(ap_handle_timer, hapd, sta);
|
||||
eloop_register_timeout(AP_MAX_INACTIVITY_AFTER_DISASSOC, 0,
|
||||
ap_handle_timer, hapd, sta);
|
||||
accounting_sta_stop(hapd, sta);
|
||||
ieee802_1x_free_station(sta);
|
||||
|
||||
mlme_disassociate_indication(hapd, sta, reason);
|
||||
sta->disassoc_reason = reason;
|
||||
sta->flags |= WLAN_STA_PENDING_DISASSOC_CB;
|
||||
eloop_cancel_timeout(ap_sta_disassoc_cb_timeout, hapd, sta);
|
||||
eloop_register_timeout(hapd->iface->drv_flags &
|
||||
WPA_DRIVER_FLAGS_DEAUTH_TX_STATUS ? 2 : 0, 0,
|
||||
ap_sta_disassoc_cb_timeout, hapd, sta);
|
||||
}
|
||||
|
||||
|
||||
static void ap_sta_deauth_cb_timeout(void *eloop_ctx, void *timeout_ctx)
|
||||
{
|
||||
struct hostapd_data *hapd = eloop_ctx;
|
||||
struct sta_info *sta = timeout_ctx;
|
||||
|
||||
ap_sta_remove(hapd, sta);
|
||||
mlme_deauthenticate_indication(hapd, sta, sta->deauth_reason);
|
||||
}
|
||||
|
||||
|
||||
@ -522,18 +609,45 @@ void ap_sta_deauthenticate(struct hostapd_data *hapd, struct sta_info *sta,
|
||||
wpa_printf(MSG_DEBUG, "%s: deauthenticate STA " MACSTR,
|
||||
hapd->conf->iface, MAC2STR(sta->addr));
|
||||
sta->flags &= ~(WLAN_STA_AUTH | WLAN_STA_ASSOC);
|
||||
ap_sta_remove(hapd, sta);
|
||||
ap_sta_set_authorized(hapd, sta, 0);
|
||||
sta->timeout_next = STA_REMOVE;
|
||||
wpa_printf(MSG_DEBUG, "%s: reschedule ap_handle_timer timeout "
|
||||
"for " MACSTR " (%d seconds - "
|
||||
"AP_MAX_INACTIVITY_AFTER_DEAUTH)",
|
||||
__func__, MAC2STR(sta->addr),
|
||||
AP_MAX_INACTIVITY_AFTER_DEAUTH);
|
||||
eloop_cancel_timeout(ap_handle_timer, hapd, sta);
|
||||
eloop_register_timeout(AP_MAX_INACTIVITY_AFTER_DEAUTH, 0,
|
||||
ap_handle_timer, hapd, sta);
|
||||
accounting_sta_stop(hapd, sta);
|
||||
ieee802_1x_free_station(sta);
|
||||
|
||||
mlme_deauthenticate_indication(hapd, sta, reason);
|
||||
sta->deauth_reason = reason;
|
||||
sta->flags |= WLAN_STA_PENDING_DEAUTH_CB;
|
||||
eloop_cancel_timeout(ap_sta_deauth_cb_timeout, hapd, sta);
|
||||
eloop_register_timeout(hapd->iface->drv_flags &
|
||||
WPA_DRIVER_FLAGS_DEAUTH_TX_STATUS ? 2 : 0, 0,
|
||||
ap_sta_deauth_cb_timeout, hapd, sta);
|
||||
}
|
||||
|
||||
|
||||
#ifdef CONFIG_WPS
|
||||
int ap_sta_wps_cancel(struct hostapd_data *hapd,
|
||||
struct sta_info *sta, void *ctx)
|
||||
{
|
||||
if (sta && (sta->flags & WLAN_STA_WPS)) {
|
||||
ap_sta_deauthenticate(hapd, sta,
|
||||
WLAN_REASON_PREV_AUTH_NOT_VALID);
|
||||
wpa_printf(MSG_DEBUG, "WPS: %s: Deauth sta=" MACSTR,
|
||||
__func__, MAC2STR(sta->addr));
|
||||
return 1;
|
||||
}
|
||||
|
||||
return 0;
|
||||
}
|
||||
#endif /* CONFIG_WPS */
|
||||
|
||||
|
||||
int ap_sta_bind_vlan(struct hostapd_data *hapd, struct sta_info *sta,
|
||||
int old_vlanid)
|
||||
{
|
||||
@ -636,7 +750,7 @@ int ap_sta_bind_vlan(struct hostapd_data *hapd, struct sta_info *sta,
|
||||
if (wpa_auth_sta_set_vlan(sta->wpa_sm, sta->vlan_id) < 0)
|
||||
wpa_printf(MSG_INFO, "Failed to update VLAN-ID for WPA");
|
||||
|
||||
ret = hapd->drv.set_sta_vlan(iface, hapd, sta->addr, sta->vlan_id);
|
||||
ret = hostapd_drv_set_sta_vlan(iface, hapd, sta->addr, sta->vlan_id);
|
||||
if (ret < 0) {
|
||||
hostapd_logger(hapd, sta->addr, HOSTAPD_MODULE_IEEE80211,
|
||||
HOSTAPD_LEVEL_DEBUG, "could not bind the STA "
|
||||
@ -686,8 +800,9 @@ static void ap_sa_query_timer(void *eloop_ctx, void *timeout_ctx)
|
||||
ap_check_sa_query_timeout(hapd, sta))
|
||||
return;
|
||||
|
||||
nbuf = os_realloc(sta->sa_query_trans_id,
|
||||
(sta->sa_query_count + 1) * WLAN_SA_QUERY_TR_ID_LEN);
|
||||
nbuf = os_realloc_array(sta->sa_query_trans_id,
|
||||
sta->sa_query_count + 1,
|
||||
WLAN_SA_QUERY_TR_ID_LEN);
|
||||
if (nbuf == NULL)
|
||||
return;
|
||||
if (sta->sa_query_count == 0) {
|
||||
@ -709,9 +824,7 @@ static void ap_sa_query_timer(void *eloop_ctx, void *timeout_ctx)
|
||||
HOSTAPD_LEVEL_DEBUG,
|
||||
"association SA Query attempt %d", sta->sa_query_count);
|
||||
|
||||
#ifdef NEED_AP_MLME
|
||||
ieee802_11_send_sa_query_req(hapd, sta->addr, trans_id);
|
||||
#endif /* NEED_AP_MLME */
|
||||
}
|
||||
|
||||
|
||||
@ -732,6 +845,73 @@ void ap_sta_stop_sa_query(struct hostapd_data *hapd, struct sta_info *sta)
|
||||
#endif /* CONFIG_IEEE80211W */
|
||||
|
||||
|
||||
void ap_sta_set_authorized(struct hostapd_data *hapd, struct sta_info *sta,
|
||||
int authorized)
|
||||
{
|
||||
const u8 *dev_addr = NULL;
|
||||
#ifdef CONFIG_P2P
|
||||
u8 addr[ETH_ALEN];
|
||||
#endif /* CONFIG_P2P */
|
||||
|
||||
if (!!authorized == !!(sta->flags & WLAN_STA_AUTHORIZED))
|
||||
return;
|
||||
|
||||
#ifdef CONFIG_P2P
|
||||
if (hapd->p2p_group == NULL) {
|
||||
if (sta->p2p_ie != NULL &&
|
||||
p2p_parse_dev_addr_in_p2p_ie(sta->p2p_ie, addr) == 0)
|
||||
dev_addr = addr;
|
||||
} else
|
||||
dev_addr = p2p_group_get_dev_addr(hapd->p2p_group, sta->addr);
|
||||
#endif /* CONFIG_P2P */
|
||||
|
||||
if (authorized) {
|
||||
if (dev_addr)
|
||||
wpa_msg(hapd->msg_ctx, MSG_INFO, AP_STA_CONNECTED
|
||||
MACSTR " p2p_dev_addr=" MACSTR,
|
||||
MAC2STR(sta->addr), MAC2STR(dev_addr));
|
||||
else
|
||||
wpa_msg(hapd->msg_ctx, MSG_INFO, AP_STA_CONNECTED
|
||||
MACSTR, MAC2STR(sta->addr));
|
||||
if (hapd->msg_ctx_parent &&
|
||||
hapd->msg_ctx_parent != hapd->msg_ctx && dev_addr)
|
||||
wpa_msg(hapd->msg_ctx_parent, MSG_INFO,
|
||||
AP_STA_CONNECTED MACSTR " p2p_dev_addr="
|
||||
MACSTR,
|
||||
MAC2STR(sta->addr), MAC2STR(dev_addr));
|
||||
else if (hapd->msg_ctx_parent &&
|
||||
hapd->msg_ctx_parent != hapd->msg_ctx)
|
||||
wpa_msg(hapd->msg_ctx_parent, MSG_INFO,
|
||||
AP_STA_CONNECTED MACSTR, MAC2STR(sta->addr));
|
||||
|
||||
sta->flags |= WLAN_STA_AUTHORIZED;
|
||||
} else {
|
||||
if (dev_addr)
|
||||
wpa_msg(hapd->msg_ctx, MSG_INFO, AP_STA_DISCONNECTED
|
||||
MACSTR " p2p_dev_addr=" MACSTR,
|
||||
MAC2STR(sta->addr), MAC2STR(dev_addr));
|
||||
else
|
||||
wpa_msg(hapd->msg_ctx, MSG_INFO, AP_STA_DISCONNECTED
|
||||
MACSTR, MAC2STR(sta->addr));
|
||||
if (hapd->msg_ctx_parent &&
|
||||
hapd->msg_ctx_parent != hapd->msg_ctx && dev_addr)
|
||||
wpa_msg(hapd->msg_ctx_parent, MSG_INFO,
|
||||
AP_STA_DISCONNECTED MACSTR " p2p_dev_addr="
|
||||
MACSTR, MAC2STR(sta->addr), MAC2STR(dev_addr));
|
||||
else if (hapd->msg_ctx_parent &&
|
||||
hapd->msg_ctx_parent != hapd->msg_ctx)
|
||||
wpa_msg(hapd->msg_ctx_parent, MSG_INFO,
|
||||
AP_STA_DISCONNECTED MACSTR,
|
||||
MAC2STR(sta->addr));
|
||||
sta->flags &= ~WLAN_STA_AUTHORIZED;
|
||||
}
|
||||
|
||||
if (hapd->sta_authorized_cb)
|
||||
hapd->sta_authorized_cb(hapd->sta_authorized_cb_ctx,
|
||||
sta->addr, authorized, dev_addr);
|
||||
}
|
||||
|
||||
|
||||
void ap_sta_disconnect(struct hostapd_data *hapd, struct sta_info *sta,
|
||||
const u8 *addr, u16 reason)
|
||||
{
|
||||
@ -740,12 +920,52 @@ void ap_sta_disconnect(struct hostapd_data *hapd, struct sta_info *sta,
|
||||
sta = ap_get_sta(hapd, addr);
|
||||
|
||||
if (addr)
|
||||
hapd->drv.sta_deauth(hapd, addr, reason);
|
||||
hostapd_drv_sta_deauth(hapd, addr, reason);
|
||||
|
||||
if (sta == NULL)
|
||||
return;
|
||||
sta->flags &= ~(WLAN_STA_AUTH | WLAN_STA_ASSOC | WLAN_STA_AUTHORIZED);
|
||||
ap_sta_set_authorized(hapd, sta, 0);
|
||||
wpa_auth_sm_event(sta->wpa_sm, WPA_DEAUTH);
|
||||
ieee802_1x_notify_port_enabled(sta->eapol_sm, 0);
|
||||
sta->flags &= ~(WLAN_STA_AUTH | WLAN_STA_ASSOC);
|
||||
wpa_printf(MSG_DEBUG, "%s: reschedule ap_handle_timer timeout "
|
||||
"for " MACSTR " (%d seconds - "
|
||||
"AP_MAX_INACTIVITY_AFTER_DEAUTH)",
|
||||
__func__, MAC2STR(sta->addr),
|
||||
AP_MAX_INACTIVITY_AFTER_DEAUTH);
|
||||
eloop_cancel_timeout(ap_handle_timer, hapd, sta);
|
||||
eloop_register_timeout(0, 0, ap_handle_timer, hapd, sta);
|
||||
eloop_register_timeout(AP_MAX_INACTIVITY_AFTER_DEAUTH, 0,
|
||||
ap_handle_timer, hapd, sta);
|
||||
sta->timeout_next = STA_REMOVE;
|
||||
|
||||
sta->deauth_reason = reason;
|
||||
sta->flags |= WLAN_STA_PENDING_DEAUTH_CB;
|
||||
eloop_cancel_timeout(ap_sta_deauth_cb_timeout, hapd, sta);
|
||||
eloop_register_timeout(hapd->iface->drv_flags &
|
||||
WPA_DRIVER_FLAGS_DEAUTH_TX_STATUS ? 2 : 0, 0,
|
||||
ap_sta_deauth_cb_timeout, hapd, sta);
|
||||
}
|
||||
|
||||
|
||||
void ap_sta_deauth_cb(struct hostapd_data *hapd, struct sta_info *sta)
|
||||
{
|
||||
if (!(sta->flags & WLAN_STA_PENDING_DEAUTH_CB)) {
|
||||
wpa_printf(MSG_DEBUG, "Ignore deauth cb for test frame");
|
||||
return;
|
||||
}
|
||||
sta->flags &= ~WLAN_STA_PENDING_DEAUTH_CB;
|
||||
eloop_cancel_timeout(ap_sta_deauth_cb_timeout, hapd, sta);
|
||||
ap_sta_deauth_cb_timeout(hapd, sta);
|
||||
}
|
||||
|
||||
|
||||
void ap_sta_disassoc_cb(struct hostapd_data *hapd, struct sta_info *sta)
|
||||
{
|
||||
if (!(sta->flags & WLAN_STA_PENDING_DISASSOC_CB)) {
|
||||
wpa_printf(MSG_DEBUG, "Ignore disassoc cb for test frame");
|
||||
return;
|
||||
}
|
||||
sta->flags &= ~WLAN_STA_PENDING_DISASSOC_CB;
|
||||
eloop_cancel_timeout(ap_sta_disassoc_cb_timeout, hapd, sta);
|
||||
ap_sta_disassoc_cb_timeout(hapd, sta);
|
||||
}
|
||||
|
@ -1,15 +1,9 @@
|
||||
/*
|
||||
* hostapd / Station table
|
||||
* Copyright (c) 2002-2009, Jouni Malinen <j@w1.fi>
|
||||
* Copyright (c) 2002-2011, Jouni Malinen <j@w1.fi>
|
||||
*
|
||||
* This program is free software; you can redistribute it and/or modify
|
||||
* it under the terms of the GNU General Public License version 2 as
|
||||
* published by the Free Software Foundation.
|
||||
*
|
||||
* Alternatively, this software may be distributed under the terms of BSD
|
||||
* license.
|
||||
*
|
||||
* See README and COPYING for more details.
|
||||
* This software may be distributed under the terms of the BSD license.
|
||||
* See README for more details.
|
||||
*/
|
||||
|
||||
#ifndef STA_INFO_H
|
||||
@ -31,6 +25,12 @@
|
||||
#define WLAN_STA_WPS BIT(12)
|
||||
#define WLAN_STA_MAYBE_WPS BIT(13)
|
||||
#define WLAN_STA_WDS BIT(14)
|
||||
#define WLAN_STA_ASSOC_REQ_OK BIT(15)
|
||||
#define WLAN_STA_WPS2 BIT(16)
|
||||
#define WLAN_STA_GAS BIT(17)
|
||||
#define WLAN_STA_VHT BIT(18)
|
||||
#define WLAN_STA_PENDING_DISASSOC_CB BIT(29)
|
||||
#define WLAN_STA_PENDING_DEAUTH_CB BIT(30)
|
||||
#define WLAN_STA_NONERP BIT(31)
|
||||
|
||||
/* Maximum number of supported rates (from both Supported Rates and Extended
|
||||
@ -48,6 +48,7 @@ struct sta_info {
|
||||
u16 listen_interval; /* or beacon_int for APs */
|
||||
u8 supported_rates[WLAN_SUPP_RATES_MAX];
|
||||
int supported_rates_len;
|
||||
u8 qosinfo; /* Valid when WLAN_STA_WMM is set */
|
||||
|
||||
unsigned int nonerp_set:1;
|
||||
unsigned int no_short_slot_time_set:1;
|
||||
@ -55,6 +56,7 @@ struct sta_info {
|
||||
unsigned int no_ht_gf_set:1;
|
||||
unsigned int no_ht_set:1;
|
||||
unsigned int ht_20mhz_set:1;
|
||||
unsigned int no_p2p_set:1;
|
||||
|
||||
u16 auth_alg;
|
||||
u8 previous_ap[6];
|
||||
@ -63,6 +65,9 @@ struct sta_info {
|
||||
STA_NULLFUNC = 0, STA_DISASSOC, STA_DEAUTH, STA_REMOVE
|
||||
} timeout_next;
|
||||
|
||||
u16 deauth_reason;
|
||||
u16 disassoc_reason;
|
||||
|
||||
/* IEEE 802.1X related data */
|
||||
struct eapol_state_machine *eapol_sm;
|
||||
|
||||
@ -90,8 +95,14 @@ struct sta_info {
|
||||
struct hostapd_ssid *ssid_probe; /* SSID selection based on ProbeReq */
|
||||
|
||||
int vlan_id;
|
||||
/* PSKs from RADIUS authentication server */
|
||||
struct hostapd_sta_wpa_psk_short *psk;
|
||||
|
||||
char *identity; /* User-Name from RADIUS */
|
||||
char *radius_cui; /* Chargeable-User-Identity from RADIUS */
|
||||
|
||||
struct ieee80211_ht_capabilities *ht_capabilities;
|
||||
struct ieee80211_vht_capabilities *vht_capabilities;
|
||||
|
||||
#ifdef CONFIG_IEEE80211W
|
||||
int sa_query_count; /* number of pending SA Query requests;
|
||||
@ -103,7 +114,22 @@ struct sta_info {
|
||||
struct os_time sa_query_start;
|
||||
#endif /* CONFIG_IEEE80211W */
|
||||
|
||||
#ifdef CONFIG_INTERWORKING
|
||||
#define GAS_DIALOG_MAX 8 /* Max concurrent dialog number */
|
||||
struct gas_dialog_info *gas_dialog;
|
||||
u8 gas_dialog_next;
|
||||
#endif /* CONFIG_INTERWORKING */
|
||||
|
||||
struct wpabuf *wps_ie; /* WPS IE from (Re)Association Request */
|
||||
struct wpabuf *p2p_ie; /* P2P IE from (Re)Association Request */
|
||||
struct wpabuf *hs20_ie; /* HS 2.0 IE from (Re)Association Request */
|
||||
|
||||
struct os_time connected_time;
|
||||
|
||||
#ifdef CONFIG_SAE
|
||||
enum { SAE_INIT, SAE_COMMIT, SAE_CONFIRM } sae_state;
|
||||
u16 sae_send_confirm;
|
||||
#endif /* CONFIG_SAE */
|
||||
};
|
||||
|
||||
|
||||
@ -111,7 +137,7 @@ struct sta_info {
|
||||
* passed since last received frame from the station, a nullfunc data frame is
|
||||
* sent to the station. If this frame is not acknowledged and no other frames
|
||||
* have been received, the station will be disassociated after
|
||||
* AP_DISASSOC_DELAY seconds. Similarily, the station will be deauthenticated
|
||||
* AP_DISASSOC_DELAY seconds. Similarly, the station will be deauthenticated
|
||||
* after AP_DEAUTH_DELAY seconds has passed after disassociation. */
|
||||
#define AP_MAX_INACTIVITY (5 * 60)
|
||||
#define AP_DISASSOC_DELAY (1)
|
||||
@ -132,7 +158,6 @@ int ap_for_each_sta(struct hostapd_data *hapd,
|
||||
struct sta_info * ap_get_sta(struct hostapd_data *hapd, const u8 *sta);
|
||||
void ap_sta_hash_add(struct hostapd_data *hapd, struct sta_info *sta);
|
||||
void ap_free_sta(struct hostapd_data *hapd, struct sta_info *sta);
|
||||
void ap_free_sta(struct hostapd_data *hapd, struct sta_info *sta);
|
||||
void hostapd_free_stas(struct hostapd_data *hapd);
|
||||
void ap_handle_timer(void *eloop_ctx, void *timeout_ctx);
|
||||
void ap_sta_session_timeout(struct hostapd_data *hapd, struct sta_info *sta,
|
||||
@ -144,6 +169,10 @@ void ap_sta_disassociate(struct hostapd_data *hapd, struct sta_info *sta,
|
||||
u16 reason);
|
||||
void ap_sta_deauthenticate(struct hostapd_data *hapd, struct sta_info *sta,
|
||||
u16 reason);
|
||||
#ifdef CONFIG_WPS
|
||||
int ap_sta_wps_cancel(struct hostapd_data *hapd,
|
||||
struct sta_info *sta, void *ctx);
|
||||
#endif /* CONFIG_WPS */
|
||||
int ap_sta_bind_vlan(struct hostapd_data *hapd, struct sta_info *sta,
|
||||
int old_vlanid);
|
||||
void ap_sta_start_sa_query(struct hostapd_data *hapd, struct sta_info *sta);
|
||||
@ -152,4 +181,14 @@ int ap_check_sa_query_timeout(struct hostapd_data *hapd, struct sta_info *sta);
|
||||
void ap_sta_disconnect(struct hostapd_data *hapd, struct sta_info *sta,
|
||||
const u8 *addr, u16 reason);
|
||||
|
||||
void ap_sta_set_authorized(struct hostapd_data *hapd,
|
||||
struct sta_info *sta, int authorized);
|
||||
static inline int ap_sta_is_authorized(struct sta_info *sta)
|
||||
{
|
||||
return sta->flags & WLAN_STA_AUTHORIZED;
|
||||
}
|
||||
|
||||
void ap_sta_deauth_cb(struct hostapd_data *hapd, struct sta_info *sta);
|
||||
void ap_sta_disassoc_cb(struct hostapd_data *hapd, struct sta_info *sta);
|
||||
|
||||
#endif /* STA_INFO_H */
|
||||
|
@ -1,15 +1,9 @@
|
||||
/*
|
||||
* hostapd / TKIP countermeasures
|
||||
* Copyright (c) 2002-2009, Jouni Malinen <j@w1.fi>
|
||||
* Copyright (c) 2002-2012, Jouni Malinen <j@w1.fi>
|
||||
*
|
||||
* This program is free software; you can redistribute it and/or modify
|
||||
* it under the terms of the GNU General Public License version 2 as
|
||||
* published by the Free Software Foundation.
|
||||
*
|
||||
* Alternatively, this software may be distributed under the terms of BSD
|
||||
* license.
|
||||
*
|
||||
* See README and COPYING for more details.
|
||||
* This software may be distributed under the terms of the BSD license.
|
||||
* See README for more details.
|
||||
*/
|
||||
|
||||
#include "utils/includes.h"
|
||||
@ -17,10 +11,12 @@
|
||||
#include "utils/common.h"
|
||||
#include "utils/eloop.h"
|
||||
#include "common/ieee802_11_defs.h"
|
||||
#include "radius/radius.h"
|
||||
#include "hostapd.h"
|
||||
#include "sta_info.h"
|
||||
#include "ap_mlme.h"
|
||||
#include "wpa_auth.h"
|
||||
#include "ap_drv_ops.h"
|
||||
#include "tkip_countermeasures.h"
|
||||
|
||||
|
||||
@ -29,7 +25,7 @@ static void ieee80211_tkip_countermeasures_stop(void *eloop_ctx,
|
||||
{
|
||||
struct hostapd_data *hapd = eloop_ctx;
|
||||
hapd->tkip_countermeasures = 0;
|
||||
hapd->drv.set_countermeasures(hapd, 0);
|
||||
hostapd_drv_set_countermeasures(hapd, 0);
|
||||
hostapd_logger(hapd, NULL, HOSTAPD_MODULE_IEEE80211,
|
||||
HOSTAPD_LEVEL_INFO, "TKIP countermeasures ended");
|
||||
}
|
||||
@ -44,24 +40,36 @@ static void ieee80211_tkip_countermeasures_start(struct hostapd_data *hapd)
|
||||
|
||||
wpa_auth_countermeasures_start(hapd->wpa_auth);
|
||||
hapd->tkip_countermeasures = 1;
|
||||
hapd->drv.set_countermeasures(hapd, 1);
|
||||
hostapd_drv_set_countermeasures(hapd, 1);
|
||||
wpa_gtk_rekey(hapd->wpa_auth);
|
||||
eloop_cancel_timeout(ieee80211_tkip_countermeasures_stop, hapd, NULL);
|
||||
eloop_register_timeout(60, 0, ieee80211_tkip_countermeasures_stop,
|
||||
hapd, NULL);
|
||||
for (sta = hapd->sta_list; sta != NULL; sta = sta->next) {
|
||||
hapd->drv.sta_deauth(hapd, sta->addr,
|
||||
WLAN_REASON_MICHAEL_MIC_FAILURE);
|
||||
sta->flags &= ~(WLAN_STA_AUTH | WLAN_STA_ASSOC |
|
||||
WLAN_STA_AUTHORIZED);
|
||||
hapd->drv.sta_remove(hapd, sta->addr);
|
||||
while ((sta = hapd->sta_list)) {
|
||||
sta->acct_terminate_cause =
|
||||
RADIUS_ACCT_TERMINATE_CAUSE_ADMIN_RESET;
|
||||
if (sta->flags & WLAN_STA_AUTH) {
|
||||
mlme_deauthenticate_indication(
|
||||
hapd, sta,
|
||||
WLAN_REASON_MICHAEL_MIC_FAILURE);
|
||||
}
|
||||
hostapd_drv_sta_deauth(hapd, sta->addr,
|
||||
WLAN_REASON_MICHAEL_MIC_FAILURE);
|
||||
ap_free_sta(hapd, sta);
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
void michael_mic_failure(struct hostapd_data *hapd, const u8 *addr, int local)
|
||||
void ieee80211_tkip_countermeasures_deinit(struct hostapd_data *hapd)
|
||||
{
|
||||
time_t now;
|
||||
eloop_cancel_timeout(ieee80211_tkip_countermeasures_stop, hapd, NULL);
|
||||
}
|
||||
|
||||
|
||||
int michael_mic_failure(struct hostapd_data *hapd, const u8 *addr, int local)
|
||||
{
|
||||
struct os_time now;
|
||||
int ret = 0;
|
||||
|
||||
if (addr && local) {
|
||||
struct sta_info *sta = ap_get_sta(hapd, addr);
|
||||
@ -77,17 +85,21 @@ void michael_mic_failure(struct hostapd_data *hapd, const u8 *addr, int local)
|
||||
"MLME-MICHAELMICFAILURE.indication "
|
||||
"for not associated STA (" MACSTR
|
||||
") ignored", MAC2STR(addr));
|
||||
return;
|
||||
return ret;
|
||||
}
|
||||
}
|
||||
|
||||
time(&now);
|
||||
if (now > hapd->michael_mic_failure + 60) {
|
||||
os_get_time(&now);
|
||||
if (now.sec > hapd->michael_mic_failure + 60) {
|
||||
hapd->michael_mic_failures = 1;
|
||||
} else {
|
||||
hapd->michael_mic_failures++;
|
||||
if (hapd->michael_mic_failures > 1)
|
||||
if (hapd->michael_mic_failures > 1) {
|
||||
ieee80211_tkip_countermeasures_start(hapd);
|
||||
ret = 1;
|
||||
}
|
||||
}
|
||||
hapd->michael_mic_failure = now;
|
||||
hapd->michael_mic_failure = now.sec;
|
||||
|
||||
return ret;
|
||||
}
|
||||
|
@ -1,20 +1,15 @@
|
||||
/*
|
||||
* hostapd / TKIP countermeasures
|
||||
* Copyright (c) 2002-2009, Jouni Malinen <j@w1.fi>
|
||||
* Copyright (c) 2002-2012, Jouni Malinen <j@w1.fi>
|
||||
*
|
||||
* This program is free software; you can redistribute it and/or modify
|
||||
* it under the terms of the GNU General Public License version 2 as
|
||||
* published by the Free Software Foundation.
|
||||
*
|
||||
* Alternatively, this software may be distributed under the terms of BSD
|
||||
* license.
|
||||
*
|
||||
* See README and COPYING for more details.
|
||||
* This software may be distributed under the terms of the BSD license.
|
||||
* See README for more details.
|
||||
*/
|
||||
|
||||
#ifndef TKIP_COUNTERMEASURES_H
|
||||
#define TKIP_COUNTERMEASURES_H
|
||||
|
||||
void michael_mic_failure(struct hostapd_data *hapd, const u8 *addr, int local);
|
||||
int michael_mic_failure(struct hostapd_data *hapd, const u8 *addr, int local);
|
||||
void ieee80211_tkip_countermeasures_deinit(struct hostapd_data *hapd);
|
||||
|
||||
#endif /* TKIP_COUNTERMEASURES_H */
|
||||
|
@ -2,14 +2,8 @@
|
||||
* AP mode helper functions
|
||||
* Copyright (c) 2009, Jouni Malinen <j@w1.fi>
|
||||
*
|
||||
* This program is free software; you can redistribute it and/or modify
|
||||
* it under the terms of the GNU General Public License version 2 as
|
||||
* published by the Free Software Foundation.
|
||||
*
|
||||
* Alternatively, this software may be distributed under the terms of BSD
|
||||
* license.
|
||||
*
|
||||
* See README and COPYING for more details.
|
||||
* This software may be distributed under the terms of the BSD license.
|
||||
* See README for more details.
|
||||
*/
|
||||
|
||||
#include "includes.h"
|
||||
@ -22,13 +16,15 @@
|
||||
|
||||
int hostapd_register_probereq_cb(struct hostapd_data *hapd,
|
||||
int (*cb)(void *ctx, const u8 *sa,
|
||||
const u8 *ie, size_t ie_len),
|
||||
const u8 *da, const u8 *bssid,
|
||||
const u8 *ie, size_t ie_len,
|
||||
int ssi_signal),
|
||||
void *ctx)
|
||||
{
|
||||
struct hostapd_probereq_cb *n;
|
||||
|
||||
n = os_realloc(hapd->probereq_cb, (hapd->num_probereq_cb + 1) *
|
||||
sizeof(struct hostapd_probereq_cb));
|
||||
n = os_realloc_array(hapd->probereq_cb, hapd->num_probereq_cb + 1,
|
||||
sizeof(struct hostapd_probereq_cb));
|
||||
if (n == NULL)
|
||||
return -1;
|
||||
|
||||
@ -82,7 +78,8 @@ void hostapd_prune_associations(struct hostapd_data *hapd, const u8 *addr)
|
||||
struct prune_data data;
|
||||
data.hapd = hapd;
|
||||
data.addr = addr;
|
||||
if (hapd->iface->for_each_interface)
|
||||
hapd->iface->for_each_interface(hapd->iface->interfaces,
|
||||
prune_associations, &data);
|
||||
if (hapd->iface->interfaces &&
|
||||
hapd->iface->interfaces->for_each_interface)
|
||||
hapd->iface->interfaces->for_each_interface(
|
||||
hapd->iface->interfaces, prune_associations, &data);
|
||||
}
|
||||
|
@ -19,7 +19,9 @@
|
||||
#include "utils/common.h"
|
||||
#include "hostapd.h"
|
||||
#include "ap_config.h"
|
||||
#include "ap_drv_ops.h"
|
||||
#include "vlan_init.h"
|
||||
#include "vlan_util.h"
|
||||
|
||||
|
||||
#ifdef CONFIG_FULL_DYNAMIC_VLAN
|
||||
@ -334,7 +336,9 @@ static int br_getnumports(const char *br_name)
|
||||
}
|
||||
|
||||
|
||||
static int vlan_rem(const char *if_name)
|
||||
#ifndef CONFIG_VLAN_NETLINK
|
||||
|
||||
int vlan_rem(const char *if_name)
|
||||
{
|
||||
int fd;
|
||||
struct vlan_ioctl_args if_request;
|
||||
@ -377,7 +381,7 @@ static int vlan_rem(const char *if_name)
|
||||
returns 1 if the interface already exists
|
||||
returns 0 otherwise
|
||||
*/
|
||||
static int vlan_add(const char *if_name, int vid)
|
||||
int vlan_add(const char *if_name, int vid, const char *vlan_if_name)
|
||||
{
|
||||
int fd;
|
||||
struct vlan_ioctl_args if_request;
|
||||
@ -473,6 +477,8 @@ static int vlan_set_name_type(unsigned int name_type)
|
||||
return 0;
|
||||
}
|
||||
|
||||
#endif /* CONFIG_VLAN_NETLINK */
|
||||
|
||||
|
||||
static void vlan_newlink(char *ifname, struct hostapd_data *hapd)
|
||||
{
|
||||
@ -480,6 +486,7 @@ static void vlan_newlink(char *ifname, struct hostapd_data *hapd)
|
||||
char br_name[IFNAMSIZ];
|
||||
struct hostapd_vlan *vlan = hapd->conf->vlan;
|
||||
char *tagged_interface = hapd->conf->ssid.vlan_tagged_interface;
|
||||
int vlan_naming = hapd->conf->ssid.vlan_naming;
|
||||
|
||||
wpa_printf(MSG_DEBUG, "VLAN: vlan_newlink(%s)", ifname);
|
||||
|
||||
@ -495,13 +502,22 @@ static void vlan_newlink(char *ifname, struct hostapd_data *hapd)
|
||||
ifconfig_up(br_name);
|
||||
|
||||
if (tagged_interface) {
|
||||
if (vlan_naming ==
|
||||
DYNAMIC_VLAN_NAMING_WITH_DEVICE)
|
||||
os_snprintf(vlan_ifname,
|
||||
sizeof(vlan_ifname),
|
||||
"%s.%d", tagged_interface,
|
||||
vlan->vlan_id);
|
||||
else
|
||||
os_snprintf(vlan_ifname,
|
||||
sizeof(vlan_ifname),
|
||||
"vlan%d", vlan->vlan_id);
|
||||
|
||||
if (!vlan_add(tagged_interface, vlan->vlan_id))
|
||||
ifconfig_up(tagged_interface);
|
||||
if (!vlan_add(tagged_interface, vlan->vlan_id,
|
||||
vlan_ifname))
|
||||
vlan->clean |= DVLAN_CLEAN_VLAN;
|
||||
|
||||
os_snprintf(vlan_ifname, sizeof(vlan_ifname),
|
||||
"vlan%d", vlan->vlan_id);
|
||||
|
||||
if (!br_addif(br_name, vlan_ifname))
|
||||
vlan->clean |= DVLAN_CLEAN_VLAN_PORT;
|
||||
|
||||
@ -526,6 +542,7 @@ static void vlan_dellink(char *ifname, struct hostapd_data *hapd)
|
||||
char br_name[IFNAMSIZ];
|
||||
struct hostapd_vlan *first, *prev, *vlan = hapd->conf->vlan;
|
||||
char *tagged_interface = hapd->conf->ssid.vlan_tagged_interface;
|
||||
int vlan_naming = hapd->conf->ssid.vlan_naming;
|
||||
|
||||
wpa_printf(MSG_DEBUG, "VLAN: vlan_dellink(%s)", ifname);
|
||||
|
||||
@ -540,8 +557,16 @@ static void vlan_dellink(char *ifname, struct hostapd_data *hapd)
|
||||
br_delif(br_name, vlan->ifname);
|
||||
|
||||
if (tagged_interface) {
|
||||
os_snprintf(vlan_ifname, sizeof(vlan_ifname),
|
||||
"vlan%d", vlan->vlan_id);
|
||||
if (vlan_naming ==
|
||||
DYNAMIC_VLAN_NAMING_WITH_DEVICE)
|
||||
os_snprintf(vlan_ifname,
|
||||
sizeof(vlan_ifname),
|
||||
"%s.%d", tagged_interface,
|
||||
vlan->vlan_id);
|
||||
else
|
||||
os_snprintf(vlan_ifname,
|
||||
sizeof(vlan_ifname),
|
||||
"vlan%d", vlan->vlan_id);
|
||||
if (vlan->clean & DVLAN_CLEAN_VLAN_PORT)
|
||||
br_delif(br_name, vlan_ifname);
|
||||
ifconfig_down(vlan_ifname);
|
||||
@ -681,7 +706,12 @@ full_dynamic_vlan_init(struct hostapd_data *hapd)
|
||||
if (priv == NULL)
|
||||
return NULL;
|
||||
|
||||
vlan_set_name_type(VLAN_NAME_TYPE_PLUS_VID_NO_PAD);
|
||||
#ifndef CONFIG_VLAN_NETLINK
|
||||
vlan_set_name_type(hapd->conf->ssid.vlan_naming ==
|
||||
DYNAMIC_VLAN_NAMING_WITH_DEVICE ?
|
||||
VLAN_NAME_TYPE_RAW_PLUS_VID_NO_PAD :
|
||||
VLAN_NAME_TYPE_PLUS_VID_NO_PAD);
|
||||
#endif /* CONFIG_VLAN_NETLINK */
|
||||
|
||||
priv->s = socket(PF_NETLINK, SOCK_RAW, NETLINK_ROUTE);
|
||||
if (priv->s < 0) {
|
||||
@ -737,9 +767,10 @@ int vlan_setup_encryption_dyn(struct hostapd_data *hapd,
|
||||
* functions for setting up dynamic broadcast keys. */
|
||||
for (i = 0; i < 4; i++) {
|
||||
if (mssid->wep.key[i] &&
|
||||
hapd->drv.set_key(dyn_vlan, hapd, WPA_ALG_WEP, NULL, i,
|
||||
i == mssid->wep.idx, NULL, 0,
|
||||
mssid->wep.key[i], mssid->wep.len[i])) {
|
||||
hostapd_drv_set_key(dyn_vlan, hapd, WPA_ALG_WEP, NULL, i,
|
||||
i == mssid->wep.idx, NULL, 0,
|
||||
mssid->wep.key[i], mssid->wep.len[i]))
|
||||
{
|
||||
wpa_printf(MSG_ERROR, "VLAN: Could not set WEP "
|
||||
"encryption for dynamic VLAN");
|
||||
return -1;
|
||||
@ -755,7 +786,7 @@ static int vlan_dynamic_add(struct hostapd_data *hapd,
|
||||
{
|
||||
while (vlan) {
|
||||
if (vlan->vlan_id != VLAN_ID_WILDCARD) {
|
||||
if (hapd->drv.vlan_if_add(hapd, vlan->ifname)) {
|
||||
if (hostapd_vlan_if_add(hapd, vlan->ifname)) {
|
||||
if (errno != EEXIST) {
|
||||
wpa_printf(MSG_ERROR, "VLAN: Could "
|
||||
"not add VLAN %s: %s",
|
||||
@ -785,7 +816,7 @@ static void vlan_dynamic_remove(struct hostapd_data *hapd,
|
||||
next = vlan->next;
|
||||
|
||||
if (vlan->vlan_id != VLAN_ID_WILDCARD &&
|
||||
hapd->drv.vlan_if_remove(hapd, vlan->ifname)) {
|
||||
hostapd_vlan_if_remove(hapd, vlan->ifname)) {
|
||||
wpa_printf(MSG_ERROR, "VLAN: Could not remove VLAN "
|
||||
"iface: %s: %s",
|
||||
vlan->ifname, strerror(errno));
|
||||
@ -859,7 +890,7 @@ struct hostapd_vlan * vlan_add_dynamic(struct hostapd_data *hapd,
|
||||
pos);
|
||||
os_free(ifname);
|
||||
|
||||
if (hapd->drv.vlan_if_add(hapd, n->ifname)) {
|
||||
if (hostapd_vlan_if_add(hapd, n->ifname)) {
|
||||
os_free(n);
|
||||
return NULL;
|
||||
}
|
||||
@ -897,7 +928,7 @@ int vlan_remove_dynamic(struct hostapd_data *hapd, int vlan_id)
|
||||
return 1;
|
||||
|
||||
if (vlan->dynamic_vlan == 0)
|
||||
hapd->drv.vlan_if_remove(hapd, vlan->ifname);
|
||||
hostapd_vlan_if_remove(hapd, vlan->ifname);
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
177
src/ap/vlan_util.c
Normal file
177
src/ap/vlan_util.c
Normal file
@ -0,0 +1,177 @@
|
||||
/*
|
||||
* hostapd / VLAN netlink api
|
||||
* Copyright (c) 2012, Michael Braun <michael-dev@fami-braun.de>
|
||||
*
|
||||
* This software may be distributed under the terms of the BSD license.
|
||||
* See README for more details.
|
||||
*/
|
||||
|
||||
#include "utils/includes.h"
|
||||
#include <sys/ioctl.h>
|
||||
#include <linux/sockios.h>
|
||||
#include <linux/if_vlan.h>
|
||||
#include <netlink/genl/genl.h>
|
||||
#include <netlink/genl/family.h>
|
||||
#include <netlink/genl/ctrl.h>
|
||||
#include <netlink/route/link.h>
|
||||
#include <netlink/route/link/vlan.h>
|
||||
|
||||
#include "utils/common.h"
|
||||
#include "utils/eloop.h"
|
||||
#include "hostapd.h"
|
||||
#include "vlan_util.h"
|
||||
|
||||
/*
|
||||
* Add a vlan interface with name 'vlan_if_name', VLAN ID 'vid' and
|
||||
* tagged interface 'if_name'.
|
||||
*
|
||||
* returns -1 on error
|
||||
* returns 1 if the interface already exists
|
||||
* returns 0 otherwise
|
||||
*/
|
||||
int vlan_add(const char *if_name, int vid, const char *vlan_if_name)
|
||||
{
|
||||
int ret = -1;
|
||||
struct nl_sock *handle = NULL;
|
||||
struct nl_cache *cache = NULL;
|
||||
struct rtnl_link *rlink = NULL;
|
||||
int if_idx = 0;
|
||||
|
||||
wpa_printf(MSG_DEBUG, "VLAN: vlan_add(if_name=%s, vid=%d, "
|
||||
"vlan_if_name=%s)", if_name, vid, vlan_if_name);
|
||||
|
||||
if ((os_strlen(if_name) + 1) > IFNAMSIZ) {
|
||||
wpa_printf(MSG_ERROR, "VLAN: Interface name too long: '%s'",
|
||||
if_name);
|
||||
return -1;
|
||||
}
|
||||
|
||||
if ((os_strlen(vlan_if_name) + 1) > IFNAMSIZ) {
|
||||
wpa_printf(MSG_ERROR, "VLAN: Interface name too long: '%s'",
|
||||
vlan_if_name);
|
||||
return -1;
|
||||
}
|
||||
|
||||
handle = nl_socket_alloc();
|
||||
if (!handle) {
|
||||
wpa_printf(MSG_ERROR, "VLAN: failed to open netlink socket");
|
||||
goto vlan_add_error;
|
||||
}
|
||||
|
||||
if (nl_connect(handle, NETLINK_ROUTE) < 0) {
|
||||
wpa_printf(MSG_ERROR, "VLAN: failed to connect to netlink");
|
||||
goto vlan_add_error;
|
||||
}
|
||||
|
||||
if (rtnl_link_alloc_cache(handle, AF_UNSPEC, &cache) < 0) {
|
||||
cache = NULL;
|
||||
wpa_printf(MSG_ERROR, "VLAN: failed to alloc cache");
|
||||
goto vlan_add_error;
|
||||
}
|
||||
|
||||
if (!(if_idx = rtnl_link_name2i(cache, if_name))) {
|
||||
/* link does not exist */
|
||||
wpa_printf(MSG_ERROR, "VLAN: interface %s does not exist",
|
||||
if_name);
|
||||
goto vlan_add_error;
|
||||
}
|
||||
|
||||
if ((rlink = rtnl_link_get_by_name(cache, vlan_if_name))) {
|
||||
/* link does exist */
|
||||
rtnl_link_put(rlink);
|
||||
rlink = NULL;
|
||||
wpa_printf(MSG_ERROR, "VLAN: interface %s already exists",
|
||||
vlan_if_name);
|
||||
ret = 1;
|
||||
goto vlan_add_error;
|
||||
}
|
||||
|
||||
rlink = rtnl_link_alloc();
|
||||
if (!rlink) {
|
||||
wpa_printf(MSG_ERROR, "VLAN: failed to allocate new link");
|
||||
goto vlan_add_error;
|
||||
}
|
||||
|
||||
if (rtnl_link_set_type(rlink, "vlan") < 0) {
|
||||
wpa_printf(MSG_ERROR, "VLAN: failed to set link type");
|
||||
goto vlan_add_error;
|
||||
}
|
||||
|
||||
rtnl_link_set_link(rlink, if_idx);
|
||||
rtnl_link_set_name(rlink, vlan_if_name);
|
||||
|
||||
if (rtnl_link_vlan_set_id(rlink, vid) < 0) {
|
||||
wpa_printf(MSG_ERROR, "VLAN: failed to set link vlan id");
|
||||
goto vlan_add_error;
|
||||
}
|
||||
|
||||
if (rtnl_link_add(handle, rlink, NLM_F_CREATE) < 0) {
|
||||
wpa_printf(MSG_ERROR, "VLAN: failed to create link %s for "
|
||||
"vlan %d on %s (%d)",
|
||||
vlan_if_name, vid, if_name, if_idx);
|
||||
goto vlan_add_error;
|
||||
}
|
||||
|
||||
ret = 0;
|
||||
|
||||
vlan_add_error:
|
||||
if (rlink)
|
||||
rtnl_link_put(rlink);
|
||||
if (cache)
|
||||
nl_cache_free(cache);
|
||||
if (handle)
|
||||
nl_socket_free(handle);
|
||||
return ret;
|
||||
}
|
||||
|
||||
|
||||
int vlan_rem(const char *if_name)
|
||||
{
|
||||
int ret = -1;
|
||||
struct nl_sock *handle = NULL;
|
||||
struct nl_cache *cache = NULL;
|
||||
struct rtnl_link *rlink = NULL;
|
||||
|
||||
wpa_printf(MSG_DEBUG, "VLAN: vlan_rem(if_name=%s)", if_name);
|
||||
|
||||
handle = nl_socket_alloc();
|
||||
if (!handle) {
|
||||
wpa_printf(MSG_ERROR, "VLAN: failed to open netlink socket");
|
||||
goto vlan_rem_error;
|
||||
}
|
||||
|
||||
if (nl_connect(handle, NETLINK_ROUTE) < 0) {
|
||||
wpa_printf(MSG_ERROR, "VLAN: failed to connect to netlink");
|
||||
goto vlan_rem_error;
|
||||
}
|
||||
|
||||
if (rtnl_link_alloc_cache(handle, AF_UNSPEC, &cache) < 0) {
|
||||
cache = NULL;
|
||||
wpa_printf(MSG_ERROR, "VLAN: failed to alloc cache");
|
||||
goto vlan_rem_error;
|
||||
}
|
||||
|
||||
if (!(rlink = rtnl_link_get_by_name(cache, if_name))) {
|
||||
/* link does not exist */
|
||||
wpa_printf(MSG_ERROR, "VLAN: interface %s does not exists",
|
||||
if_name);
|
||||
goto vlan_rem_error;
|
||||
}
|
||||
|
||||
if (rtnl_link_delete(handle, rlink) < 0) {
|
||||
wpa_printf(MSG_ERROR, "VLAN: failed to remove link %s",
|
||||
if_name);
|
||||
goto vlan_rem_error;
|
||||
}
|
||||
|
||||
ret = 0;
|
||||
|
||||
vlan_rem_error:
|
||||
if (rlink)
|
||||
rtnl_link_put(rlink);
|
||||
if (cache)
|
||||
nl_cache_free(cache);
|
||||
if (handle)
|
||||
nl_socket_free(handle);
|
||||
return ret;
|
||||
}
|
15
src/ap/vlan_util.h
Normal file
15
src/ap/vlan_util.h
Normal file
@ -0,0 +1,15 @@
|
||||
/*
|
||||
* hostapd / VLAN netlink api
|
||||
* Copyright (c) 2012, Michael Braun <michael-dev@fami-braun.de>
|
||||
*
|
||||
* This software may be distributed under the terms of the BSD license.
|
||||
* See README for more details.
|
||||
*/
|
||||
|
||||
#ifndef VLAN_UTIL_H
|
||||
#define VLAN_UTIL_H
|
||||
|
||||
int vlan_add(const char *if_name, int vid, const char *vlan_if_name);
|
||||
int vlan_rem(const char *if_name);
|
||||
|
||||
#endif /* VLAN_UTIL_H */
|
22
src/ap/wmm.c
22
src/ap/wmm.c
@ -23,6 +23,7 @@
|
||||
#include "ieee802_11.h"
|
||||
#include "sta_info.h"
|
||||
#include "ap_config.h"
|
||||
#include "ap_drv_ops.h"
|
||||
#include "wmm.h"
|
||||
|
||||
|
||||
@ -71,9 +72,12 @@ u8 * hostapd_eid_wmm(struct hostapd_data *hapd, u8 *eid)
|
||||
wmm->version = WMM_VERSION;
|
||||
wmm->qos_info = hapd->parameter_set_count & 0xf;
|
||||
|
||||
if (hapd->conf->wmm_uapsd)
|
||||
if (hapd->conf->wmm_uapsd &&
|
||||
(hapd->iface->drv_flags & WPA_DRIVER_FLAGS_AP_UAPSD))
|
||||
wmm->qos_info |= 0x80;
|
||||
|
||||
wmm->reserved = 0;
|
||||
|
||||
/* fill in a parameter set record for each AC */
|
||||
for (e = 0; e < 4; e++) {
|
||||
struct wmm_ac_parameter *ac = &wmm->ac[e];
|
||||
@ -94,9 +98,11 @@ u8 * hostapd_eid_wmm(struct hostapd_data *hapd, u8 *eid)
|
||||
}
|
||||
|
||||
|
||||
/* This function is called when a station sends an association request with
|
||||
* WMM info element. The function returns zero on success or non-zero on any
|
||||
* error in WMM element. eid does not include Element ID and Length octets. */
|
||||
/*
|
||||
* This function is called when a station sends an association request with
|
||||
* WMM info element. The function returns 1 on success or 0 on any error in WMM
|
||||
* element. eid does not include Element ID and Length octets.
|
||||
*/
|
||||
int hostapd_eid_wmm_valid(struct hostapd_data *hapd, const u8 *eid, size_t len)
|
||||
{
|
||||
struct wmm_information_element *wmm;
|
||||
@ -106,7 +112,7 @@ int hostapd_eid_wmm_valid(struct hostapd_data *hapd, const u8 *eid, size_t len)
|
||||
if (len < sizeof(struct wmm_information_element)) {
|
||||
wpa_printf(MSG_DEBUG, "Too short WMM IE (len=%lu)",
|
||||
(unsigned long) len);
|
||||
return -1;
|
||||
return 0;
|
||||
}
|
||||
|
||||
wmm = (struct wmm_information_element *) eid;
|
||||
@ -117,10 +123,10 @@ int hostapd_eid_wmm_valid(struct hostapd_data *hapd, const u8 *eid, size_t len)
|
||||
if (wmm->oui_subtype != WMM_OUI_SUBTYPE_INFORMATION_ELEMENT ||
|
||||
wmm->version != WMM_VERSION) {
|
||||
wpa_printf(MSG_DEBUG, "Unsupported WMM IE Subtype/Version");
|
||||
return -1;
|
||||
return 0;
|
||||
}
|
||||
|
||||
return 0;
|
||||
return 1;
|
||||
}
|
||||
|
||||
|
||||
@ -150,7 +156,7 @@ static void wmm_send_action(struct hostapd_data *hapd, const u8 *addr,
|
||||
os_memcpy(t, tspec, sizeof(struct wmm_tspec_element));
|
||||
len = ((u8 *) (t + 1)) - buf;
|
||||
|
||||
if (hapd->drv.send_mgmt_frame(hapd, m, len) < 0)
|
||||
if (hostapd_drv_send_mlme(hapd, m, len, 0) < 0)
|
||||
perror("wmm_send_action: send");
|
||||
}
|
||||
|
||||
|
271
src/ap/wnm_ap.c
Normal file
271
src/ap/wnm_ap.c
Normal file
@ -0,0 +1,271 @@
|
||||
/*
|
||||
* hostapd - WNM
|
||||
* Copyright (c) 2011-2012, Qualcomm Atheros, Inc.
|
||||
*
|
||||
* This software may be distributed under the terms of the BSD license.
|
||||
* See README for more details.
|
||||
*/
|
||||
|
||||
#include "utils/includes.h"
|
||||
|
||||
#include "utils/common.h"
|
||||
#include "common/ieee802_11_defs.h"
|
||||
#include "ap/hostapd.h"
|
||||
#include "ap/sta_info.h"
|
||||
#include "ap/ap_config.h"
|
||||
#include "ap/ap_drv_ops.h"
|
||||
#include "ap/wpa_auth.h"
|
||||
#include "wnm_ap.h"
|
||||
|
||||
#define MAX_TFS_IE_LEN 1024
|
||||
|
||||
|
||||
/* get the TFS IE from driver */
|
||||
static int ieee80211_11_get_tfs_ie(struct hostapd_data *hapd, const u8 *addr,
|
||||
u8 *buf, u16 *buf_len, enum wnm_oper oper)
|
||||
{
|
||||
wpa_printf(MSG_DEBUG, "%s: TFS get operation %d", __func__, oper);
|
||||
|
||||
return hostapd_drv_wnm_oper(hapd, oper, addr, buf, buf_len);
|
||||
}
|
||||
|
||||
|
||||
/* set the TFS IE to driver */
|
||||
static int ieee80211_11_set_tfs_ie(struct hostapd_data *hapd, const u8 *addr,
|
||||
u8 *buf, u16 *buf_len, enum wnm_oper oper)
|
||||
{
|
||||
wpa_printf(MSG_DEBUG, "%s: TFS set operation %d", __func__, oper);
|
||||
|
||||
return hostapd_drv_wnm_oper(hapd, oper, addr, buf, buf_len);
|
||||
}
|
||||
|
||||
|
||||
/* MLME-SLEEPMODE.response */
|
||||
static int ieee802_11_send_wnmsleep_resp(struct hostapd_data *hapd,
|
||||
const u8 *addr, u8 dialog_token,
|
||||
u8 action_type, u16 intval)
|
||||
{
|
||||
struct ieee80211_mgmt *mgmt;
|
||||
int res;
|
||||
size_t len;
|
||||
size_t gtk_elem_len = 0;
|
||||
size_t igtk_elem_len = 0;
|
||||
struct wnm_sleep_element wnmsleep_ie;
|
||||
u8 *wnmtfs_ie;
|
||||
u8 wnmsleep_ie_len;
|
||||
u16 wnmtfs_ie_len;
|
||||
u8 *pos;
|
||||
struct sta_info *sta;
|
||||
enum wnm_oper tfs_oper = action_type == WNM_SLEEP_MODE_ENTER ?
|
||||
WNM_SLEEP_TFS_RESP_IE_ADD : WNM_SLEEP_TFS_RESP_IE_NONE;
|
||||
|
||||
sta = ap_get_sta(hapd, addr);
|
||||
if (sta == NULL) {
|
||||
wpa_printf(MSG_DEBUG, "%s: station not found", __func__);
|
||||
return -EINVAL;
|
||||
}
|
||||
|
||||
/* WNM-Sleep Mode IE */
|
||||
os_memset(&wnmsleep_ie, 0, sizeof(struct wnm_sleep_element));
|
||||
wnmsleep_ie_len = sizeof(struct wnm_sleep_element);
|
||||
wnmsleep_ie.eid = WLAN_EID_WNMSLEEP;
|
||||
wnmsleep_ie.len = wnmsleep_ie_len - 2;
|
||||
wnmsleep_ie.action_type = action_type;
|
||||
wnmsleep_ie.status = WNM_STATUS_SLEEP_ACCEPT;
|
||||
wnmsleep_ie.intval = intval;
|
||||
|
||||
/* TFS IE(s) */
|
||||
wnmtfs_ie = os_zalloc(MAX_TFS_IE_LEN);
|
||||
if (wnmtfs_ie == NULL)
|
||||
return -1;
|
||||
if (ieee80211_11_get_tfs_ie(hapd, addr, wnmtfs_ie, &wnmtfs_ie_len,
|
||||
tfs_oper)) {
|
||||
wnmtfs_ie_len = 0;
|
||||
os_free(wnmtfs_ie);
|
||||
wnmtfs_ie = NULL;
|
||||
}
|
||||
|
||||
#define MAX_GTK_SUBELEM_LEN 45
|
||||
#define MAX_IGTK_SUBELEM_LEN 26
|
||||
mgmt = os_zalloc(sizeof(*mgmt) + wnmsleep_ie_len +
|
||||
MAX_GTK_SUBELEM_LEN + MAX_IGTK_SUBELEM_LEN);
|
||||
if (mgmt == NULL) {
|
||||
wpa_printf(MSG_DEBUG, "MLME: Failed to allocate buffer for "
|
||||
"WNM-Sleep Response action frame");
|
||||
return -1;
|
||||
}
|
||||
os_memcpy(mgmt->da, addr, ETH_ALEN);
|
||||
os_memcpy(mgmt->sa, hapd->own_addr, ETH_ALEN);
|
||||
os_memcpy(mgmt->bssid, hapd->own_addr, ETH_ALEN);
|
||||
mgmt->frame_control = IEEE80211_FC(WLAN_FC_TYPE_MGMT,
|
||||
WLAN_FC_STYPE_ACTION);
|
||||
mgmt->u.action.category = WLAN_ACTION_WNM;
|
||||
mgmt->u.action.u.wnm_sleep_resp.action = WNM_SLEEP_MODE_RESP;
|
||||
mgmt->u.action.u.wnm_sleep_resp.dialogtoken = dialog_token;
|
||||
pos = (u8 *)mgmt->u.action.u.wnm_sleep_resp.variable;
|
||||
/* add key data if MFP is enabled */
|
||||
if (!wpa_auth_uses_mfp(sta->wpa_sm) ||
|
||||
action_type != WNM_SLEEP_MODE_EXIT) {
|
||||
mgmt->u.action.u.wnm_sleep_resp.keydata_len = 0;
|
||||
} else {
|
||||
gtk_elem_len = wpa_wnmsleep_gtk_subelem(sta->wpa_sm, pos);
|
||||
pos += gtk_elem_len;
|
||||
wpa_printf(MSG_DEBUG, "Pass 4, gtk_len = %d",
|
||||
(int) gtk_elem_len);
|
||||
#ifdef CONFIG_IEEE80211W
|
||||
res = wpa_wnmsleep_igtk_subelem(sta->wpa_sm, pos);
|
||||
if (res < 0) {
|
||||
os_free(wnmtfs_ie);
|
||||
os_free(mgmt);
|
||||
return -1;
|
||||
}
|
||||
igtk_elem_len = res;
|
||||
pos += igtk_elem_len;
|
||||
wpa_printf(MSG_DEBUG, "Pass 4 igtk_len = %d",
|
||||
(int) igtk_elem_len);
|
||||
#endif /* CONFIG_IEEE80211W */
|
||||
|
||||
WPA_PUT_LE16((u8 *)
|
||||
&mgmt->u.action.u.wnm_sleep_resp.keydata_len,
|
||||
gtk_elem_len + igtk_elem_len);
|
||||
}
|
||||
os_memcpy(pos, &wnmsleep_ie, wnmsleep_ie_len);
|
||||
/* copy TFS IE here */
|
||||
pos += wnmsleep_ie_len;
|
||||
if (wnmtfs_ie)
|
||||
os_memcpy(pos, wnmtfs_ie, wnmtfs_ie_len);
|
||||
|
||||
len = 1 + sizeof(mgmt->u.action.u.wnm_sleep_resp) + gtk_elem_len +
|
||||
igtk_elem_len + wnmsleep_ie_len + wnmtfs_ie_len;
|
||||
|
||||
/* In driver, response frame should be forced to sent when STA is in
|
||||
* PS mode */
|
||||
res = hostapd_drv_send_action(hapd, hapd->iface->freq, 0,
|
||||
mgmt->da, &mgmt->u.action.category, len);
|
||||
|
||||
if (!res) {
|
||||
wpa_printf(MSG_DEBUG, "Successfully send WNM-Sleep Response "
|
||||
"frame");
|
||||
|
||||
/* when entering wnmsleep
|
||||
* 1. pause the node in driver
|
||||
* 2. mark the node so that AP won't update GTK/IGTK during
|
||||
* WNM Sleep
|
||||
*/
|
||||
if (wnmsleep_ie.status == WNM_STATUS_SLEEP_ACCEPT &&
|
||||
wnmsleep_ie.action_type == WNM_SLEEP_MODE_ENTER) {
|
||||
hostapd_drv_wnm_oper(hapd, WNM_SLEEP_ENTER_CONFIRM,
|
||||
addr, NULL, NULL);
|
||||
wpa_set_wnmsleep(sta->wpa_sm, 1);
|
||||
}
|
||||
/* when exiting wnmsleep
|
||||
* 1. unmark the node
|
||||
* 2. start GTK/IGTK update if MFP is not used
|
||||
* 3. unpause the node in driver
|
||||
*/
|
||||
if ((wnmsleep_ie.status == WNM_STATUS_SLEEP_ACCEPT ||
|
||||
wnmsleep_ie.status ==
|
||||
WNM_STATUS_SLEEP_EXIT_ACCEPT_GTK_UPDATE) &&
|
||||
wnmsleep_ie.action_type == WNM_SLEEP_MODE_EXIT) {
|
||||
wpa_set_wnmsleep(sta->wpa_sm, 0);
|
||||
hostapd_drv_wnm_oper(hapd, WNM_SLEEP_EXIT_CONFIRM,
|
||||
addr, NULL, NULL);
|
||||
if (!wpa_auth_uses_mfp(sta->wpa_sm))
|
||||
wpa_wnmsleep_rekey_gtk(sta->wpa_sm);
|
||||
}
|
||||
} else
|
||||
wpa_printf(MSG_DEBUG, "Fail to send WNM-Sleep Response frame");
|
||||
|
||||
#undef MAX_GTK_SUBELEM_LEN
|
||||
#undef MAX_IGTK_SUBELEM_LEN
|
||||
os_free(wnmtfs_ie);
|
||||
os_free(mgmt);
|
||||
return res;
|
||||
}
|
||||
|
||||
|
||||
static void ieee802_11_rx_wnmsleep_req(struct hostapd_data *hapd,
|
||||
const u8 *addr, const u8 *frm, int len)
|
||||
{
|
||||
/* Dialog Token [1] | WNM-Sleep Mode IE | TFS Response IE */
|
||||
const u8 *pos = frm;
|
||||
u8 dialog_token;
|
||||
struct wnm_sleep_element *wnmsleep_ie = NULL;
|
||||
/* multiple TFS Req IE (assuming consecutive) */
|
||||
u8 *tfsreq_ie_start = NULL;
|
||||
u8 *tfsreq_ie_end = NULL;
|
||||
u16 tfsreq_ie_len = 0;
|
||||
|
||||
dialog_token = *pos++;
|
||||
while (pos + 1 < frm + len) {
|
||||
u8 ie_len = pos[1];
|
||||
if (pos + 2 + ie_len > frm + len)
|
||||
break;
|
||||
if (*pos == WLAN_EID_WNMSLEEP)
|
||||
wnmsleep_ie = (struct wnm_sleep_element *) pos;
|
||||
else if (*pos == WLAN_EID_TFS_REQ) {
|
||||
if (!tfsreq_ie_start)
|
||||
tfsreq_ie_start = (u8 *) pos;
|
||||
tfsreq_ie_end = (u8 *) pos;
|
||||
} else
|
||||
wpa_printf(MSG_DEBUG, "WNM: EID %d not recognized",
|
||||
*pos);
|
||||
pos += ie_len + 2;
|
||||
}
|
||||
|
||||
if (!wnmsleep_ie) {
|
||||
wpa_printf(MSG_DEBUG, "No WNM-Sleep IE found");
|
||||
return;
|
||||
}
|
||||
|
||||
if (wnmsleep_ie->action_type == WNM_SLEEP_MODE_ENTER &&
|
||||
tfsreq_ie_start && tfsreq_ie_end &&
|
||||
tfsreq_ie_end - tfsreq_ie_start >= 0) {
|
||||
tfsreq_ie_len = (tfsreq_ie_end + tfsreq_ie_end[1] + 2) -
|
||||
tfsreq_ie_start;
|
||||
wpa_printf(MSG_DEBUG, "TFS Req IE(s) found");
|
||||
/* pass the TFS Req IE(s) to driver for processing */
|
||||
if (ieee80211_11_set_tfs_ie(hapd, addr, tfsreq_ie_start,
|
||||
&tfsreq_ie_len,
|
||||
WNM_SLEEP_TFS_REQ_IE_SET))
|
||||
wpa_printf(MSG_DEBUG, "Fail to set TFS Req IE");
|
||||
}
|
||||
|
||||
ieee802_11_send_wnmsleep_resp(hapd, addr, dialog_token,
|
||||
wnmsleep_ie->action_type,
|
||||
wnmsleep_ie->intval);
|
||||
|
||||
if (wnmsleep_ie->action_type == WNM_SLEEP_MODE_EXIT) {
|
||||
/* clear the tfs after sending the resp frame */
|
||||
ieee80211_11_set_tfs_ie(hapd, addr, tfsreq_ie_start,
|
||||
&tfsreq_ie_len, WNM_SLEEP_TFS_IE_DEL);
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
int ieee802_11_rx_wnm_action_ap(struct hostapd_data *hapd,
|
||||
struct rx_action *action)
|
||||
{
|
||||
if (action->len < 1 || action->data == NULL)
|
||||
return -1;
|
||||
|
||||
switch (action->data[0]) {
|
||||
case WNM_BSS_TRANS_MGMT_QUERY:
|
||||
wpa_printf(MSG_DEBUG, "WNM: BSS Transition Management Query");
|
||||
/* TODO */
|
||||
return -1;
|
||||
case WNM_BSS_TRANS_MGMT_RESP:
|
||||
wpa_printf(MSG_DEBUG, "WNM: BSS Transition Management "
|
||||
"Response");
|
||||
/* TODO */
|
||||
return -1;
|
||||
case WNM_SLEEP_MODE_REQ:
|
||||
ieee802_11_rx_wnmsleep_req(hapd, action->sa, action->data + 1,
|
||||
action->len - 1);
|
||||
return 0;
|
||||
}
|
||||
|
||||
wpa_printf(MSG_DEBUG, "WNM: Unsupported WNM Action %u from " MACSTR,
|
||||
action->data[0], MAC2STR(action->sa));
|
||||
return -1;
|
||||
}
|
17
src/ap/wnm_ap.h
Normal file
17
src/ap/wnm_ap.h
Normal file
@ -0,0 +1,17 @@
|
||||
/*
|
||||
* IEEE 802.11v WNM related functions and structures
|
||||
* Copyright (c) 2011-2012, Qualcomm Atheros, Inc.
|
||||
*
|
||||
* This software may be distributed under the terms of the BSD license.
|
||||
* See README for more details.
|
||||
*/
|
||||
|
||||
#ifndef WNM_AP_H
|
||||
#define WNM_AP_H
|
||||
|
||||
struct rx_action;
|
||||
|
||||
int ieee802_11_rx_wnm_action_ap(struct hostapd_data *hapd,
|
||||
struct rx_action *action);
|
||||
|
||||
#endif /* WNM_AP_H */
|
File diff suppressed because it is too large
Load Diff
@ -2,14 +2,8 @@
|
||||
* hostapd - IEEE 802.11i-2004 / WPA Authenticator
|
||||
* Copyright (c) 2004-2007, Jouni Malinen <j@w1.fi>
|
||||
*
|
||||
* This program is free software; you can redistribute it and/or modify
|
||||
* it under the terms of the GNU General Public License version 2 as
|
||||
* published by the Free Software Foundation.
|
||||
*
|
||||
* Alternatively, this software may be distributed under the terms of BSD
|
||||
* license.
|
||||
*
|
||||
* See README and COPYING for more details.
|
||||
* This software may be distributed under the terms of the BSD license.
|
||||
* See README for more details.
|
||||
*/
|
||||
|
||||
#ifndef WPA_AUTH_H
|
||||
@ -143,7 +137,9 @@ struct wpa_auth_config {
|
||||
int peerkey;
|
||||
int wmm_enabled;
|
||||
int wmm_uapsd;
|
||||
int disable_pmksa_caching;
|
||||
int okc;
|
||||
int tx_status;
|
||||
#ifdef CONFIG_IEEE80211W
|
||||
enum mfp_options ieee80211w;
|
||||
#endif /* CONFIG_IEEE80211W */
|
||||
@ -160,7 +156,10 @@ struct wpa_auth_config {
|
||||
struct ft_remote_r0kh *r0kh_list;
|
||||
struct ft_remote_r1kh *r1kh_list;
|
||||
int pmk_r1_push;
|
||||
int ft_over_ds;
|
||||
#endif /* CONFIG_IEEE80211R */
|
||||
int disable_gtk;
|
||||
int ap_mlme;
|
||||
};
|
||||
|
||||
typedef enum {
|
||||
@ -178,7 +177,7 @@ struct wpa_auth_callbacks {
|
||||
void (*logger)(void *ctx, const u8 *addr, logger_level level,
|
||||
const char *txt);
|
||||
void (*disconnect)(void *ctx, const u8 *addr, u16 reason);
|
||||
void (*mic_failure_report)(void *ctx, const u8 *addr);
|
||||
int (*mic_failure_report)(void *ctx, const u8 *addr);
|
||||
void (*set_eapol)(void *ctx, const u8 *addr, wpa_eapol_variable var,
|
||||
int value);
|
||||
int (*get_eapol)(void *ctx, const u8 *addr, wpa_eapol_variable var);
|
||||
@ -199,12 +198,15 @@ struct wpa_auth_callbacks {
|
||||
struct wpa_state_machine * (*add_sta)(void *ctx, const u8 *sta_addr);
|
||||
int (*send_ft_action)(void *ctx, const u8 *dst,
|
||||
const u8 *data, size_t data_len);
|
||||
int (*add_tspec)(void *ctx, const u8 *sta_addr, u8 *tspec_ie,
|
||||
size_t tspec_ielen);
|
||||
#endif /* CONFIG_IEEE80211R */
|
||||
};
|
||||
|
||||
struct wpa_authenticator * wpa_init(const u8 *addr,
|
||||
struct wpa_auth_config *conf,
|
||||
struct wpa_auth_callbacks *cb);
|
||||
int wpa_init_keys(struct wpa_authenticator *wpa_auth);
|
||||
void wpa_deinit(struct wpa_authenticator *wpa_auth);
|
||||
int wpa_reconfig(struct wpa_authenticator *wpa_auth,
|
||||
struct wpa_auth_config *conf);
|
||||
@ -259,6 +261,8 @@ int wpa_auth_pmksa_add_preauth(struct wpa_authenticator *wpa_auth,
|
||||
int session_timeout,
|
||||
struct eapol_state_machine *eapol);
|
||||
int wpa_auth_sta_set_vlan(struct wpa_state_machine *sm, int vlan_id);
|
||||
void wpa_auth_eapol_key_tx_status(struct wpa_authenticator *wpa_auth,
|
||||
struct wpa_state_machine *sm, int ack);
|
||||
|
||||
#ifdef CONFIG_IEEE80211R
|
||||
u8 * wpa_sm_write_assoc_resp_ies(struct wpa_state_machine *sm, u8 *pos,
|
||||
@ -278,4 +282,11 @@ int wpa_ft_rrb_rx(struct wpa_authenticator *wpa_auth, const u8 *src_addr,
|
||||
void wpa_ft_push_pmk_r1(struct wpa_authenticator *wpa_auth, const u8 *addr);
|
||||
#endif /* CONFIG_IEEE80211R */
|
||||
|
||||
void wpa_wnmsleep_rekey_gtk(struct wpa_state_machine *sm);
|
||||
void wpa_set_wnmsleep(struct wpa_state_machine *sm, int flag);
|
||||
int wpa_wnmsleep_gtk_subelem(struct wpa_state_machine *sm, u8 *pos);
|
||||
int wpa_wnmsleep_igtk_subelem(struct wpa_state_machine *sm, u8 *pos);
|
||||
|
||||
int wpa_auth_uses_sae(struct wpa_state_machine *sm);
|
||||
|
||||
#endif /* WPA_AUTH_H */
|
||||
|
@ -2,14 +2,8 @@
|
||||
* hostapd - IEEE 802.11r - Fast BSS Transition
|
||||
* Copyright (c) 2004-2009, Jouni Malinen <j@w1.fi>
|
||||
*
|
||||
* This program is free software; you can redistribute it and/or modify
|
||||
* it under the terms of the GNU General Public License version 2 as
|
||||
* published by the Free Software Foundation.
|
||||
*
|
||||
* Alternatively, this software may be distributed under the terms of BSD
|
||||
* license.
|
||||
*
|
||||
* See README and COPYING for more details.
|
||||
* This software may be distributed under the terms of the BSD license.
|
||||
* See README for more details.
|
||||
*/
|
||||
|
||||
#include "utils/includes.h"
|
||||
@ -18,38 +12,16 @@
|
||||
#include "common/ieee802_11_defs.h"
|
||||
#include "common/ieee802_11_common.h"
|
||||
#include "crypto/aes_wrap.h"
|
||||
#include "crypto/random.h"
|
||||
#include "ap_config.h"
|
||||
#include "ieee802_11.h"
|
||||
#include "wmm.h"
|
||||
#include "wpa_auth.h"
|
||||
#include "wpa_auth_i.h"
|
||||
#include "wpa_auth_ie.h"
|
||||
|
||||
|
||||
#ifdef CONFIG_IEEE80211R
|
||||
|
||||
struct wpa_ft_ies {
|
||||
const u8 *mdie;
|
||||
size_t mdie_len;
|
||||
const u8 *ftie;
|
||||
size_t ftie_len;
|
||||
const u8 *r1kh_id;
|
||||
const u8 *gtk;
|
||||
size_t gtk_len;
|
||||
const u8 *r0kh_id;
|
||||
size_t r0kh_id_len;
|
||||
const u8 *rsn;
|
||||
size_t rsn_len;
|
||||
const u8 *rsn_pmkid;
|
||||
const u8 *ric;
|
||||
size_t ric_len;
|
||||
};
|
||||
|
||||
|
||||
static int wpa_ft_parse_ies(const u8 *ies, size_t ies_len,
|
||||
struct wpa_ft_ies *parse);
|
||||
|
||||
|
||||
static int wpa_ft_rrb_send(struct wpa_authenticator *wpa_auth, const u8 *dst,
|
||||
const u8 *data, size_t data_len)
|
||||
{
|
||||
@ -80,6 +52,19 @@ wpa_ft_add_sta(struct wpa_authenticator *wpa_auth, const u8 *sta_addr)
|
||||
}
|
||||
|
||||
|
||||
static int wpa_ft_add_tspec(struct wpa_authenticator *wpa_auth,
|
||||
const u8 *sta_addr,
|
||||
u8 *tspec_ie, size_t tspec_ielen)
|
||||
{
|
||||
if (wpa_auth->cb.add_tspec == NULL) {
|
||||
wpa_printf(MSG_DEBUG, "FT: add_tspec is not initialized");
|
||||
return -1;
|
||||
}
|
||||
return wpa_auth->cb.add_tspec(wpa_auth->cb.ctx, sta_addr, tspec_ie,
|
||||
tspec_ielen);
|
||||
}
|
||||
|
||||
|
||||
int wpa_write_mdie(struct wpa_auth_config *conf, u8 *buf, size_t len)
|
||||
{
|
||||
u8 *pos = buf;
|
||||
@ -91,7 +76,9 @@ int wpa_write_mdie(struct wpa_auth_config *conf, u8 *buf, size_t len)
|
||||
*pos++ = MOBILITY_DOMAIN_ID_LEN + 1;
|
||||
os_memcpy(pos, conf->mobility_domain, MOBILITY_DOMAIN_ID_LEN);
|
||||
pos += MOBILITY_DOMAIN_ID_LEN;
|
||||
capab = RSN_FT_CAPAB_FT_OVER_DS;
|
||||
capab = 0;
|
||||
if (conf->ft_over_ds)
|
||||
capab |= RSN_FT_CAPAB_FT_OVER_DS;
|
||||
*pos++ = capab;
|
||||
|
||||
return pos - buf;
|
||||
@ -334,7 +321,7 @@ static int wpa_ft_pull_pmk_r1(struct wpa_authenticator *wpa_auth,
|
||||
|
||||
/* aes_wrap() does not support inplace encryption, so use a temporary
|
||||
* buffer for the data. */
|
||||
if (os_get_random(f.nonce, sizeof(f.nonce))) {
|
||||
if (random_get_bytes(f.nonce, sizeof(f.nonce))) {
|
||||
wpa_printf(MSG_DEBUG, "FT: Failed to get random data for "
|
||||
"nonce");
|
||||
return -1;
|
||||
@ -497,7 +484,8 @@ static u8 * wpa_ft_igtk_subelem(struct wpa_state_machine *sm, size_t *len)
|
||||
#endif /* CONFIG_IEEE80211W */
|
||||
|
||||
|
||||
static u8 * wpa_ft_process_rdie(u8 *pos, u8 *end, u8 id, u8 descr_count,
|
||||
static u8 * wpa_ft_process_rdie(struct wpa_state_machine *sm,
|
||||
u8 *pos, u8 *end, u8 id, u8 descr_count,
|
||||
const u8 *ies, size_t ies_len)
|
||||
{
|
||||
struct ieee802_11_elems parse;
|
||||
@ -530,7 +518,7 @@ static u8 * wpa_ft_process_rdie(u8 *pos, u8 *end, u8 id, u8 descr_count,
|
||||
}
|
||||
|
||||
#ifdef NEED_AP_MLME
|
||||
if (parse.wmm_tspec) {
|
||||
if (parse.wmm_tspec && sm->wpa_auth->conf.ap_mlme) {
|
||||
struct wmm_tspec_element *tspec;
|
||||
int res;
|
||||
|
||||
@ -567,13 +555,35 @@ static u8 * wpa_ft_process_rdie(u8 *pos, u8 *end, u8 id, u8 descr_count,
|
||||
}
|
||||
#endif /* NEED_AP_MLME */
|
||||
|
||||
if (parse.wmm_tspec && !sm->wpa_auth->conf.ap_mlme) {
|
||||
struct wmm_tspec_element *tspec;
|
||||
int res;
|
||||
|
||||
tspec = (struct wmm_tspec_element *) pos;
|
||||
os_memcpy(tspec, parse.wmm_tspec - 2, sizeof(*tspec));
|
||||
res = wpa_ft_add_tspec(sm->wpa_auth, sm->addr, pos,
|
||||
sizeof(*tspec));
|
||||
if (res >= 0) {
|
||||
if (res)
|
||||
rdie->status_code = host_to_le16(res);
|
||||
else {
|
||||
/* TSPEC accepted; include updated TSPEC in
|
||||
* response */
|
||||
rdie->descr_count = 1;
|
||||
pos += sizeof(*tspec);
|
||||
}
|
||||
return pos;
|
||||
}
|
||||
}
|
||||
|
||||
wpa_printf(MSG_DEBUG, "FT: No supported resource requested");
|
||||
rdie->status_code = host_to_le16(WLAN_STATUS_UNSPECIFIED_FAILURE);
|
||||
return pos;
|
||||
}
|
||||
|
||||
|
||||
static u8 * wpa_ft_process_ric(u8 *pos, u8 *end, const u8 *ric, size_t ric_len)
|
||||
static u8 * wpa_ft_process_ric(struct wpa_state_machine *sm, u8 *pos, u8 *end,
|
||||
const u8 *ric, size_t ric_len)
|
||||
{
|
||||
const u8 *rpos, *start;
|
||||
const struct rsn_rdie *rdie;
|
||||
@ -595,7 +605,7 @@ static u8 * wpa_ft_process_ric(u8 *pos, u8 *end, const u8 *ric, size_t ric_len)
|
||||
break;
|
||||
rpos += 2 + rpos[1];
|
||||
}
|
||||
pos = wpa_ft_process_rdie(pos, end, rdie->id,
|
||||
pos = wpa_ft_process_rdie(sm, pos, end, rdie->id,
|
||||
rdie->descr_count,
|
||||
start, rpos - start);
|
||||
}
|
||||
@ -704,7 +714,8 @@ u8 * wpa_sm_write_assoc_resp_ies(struct wpa_state_machine *sm, u8 *pos,
|
||||
|
||||
ric_start = pos;
|
||||
if (wpa_ft_parse_ies(req_ies, req_ies_len, &parse) == 0 && parse.ric) {
|
||||
pos = wpa_ft_process_ric(pos, end, parse.ric, parse.ric_len);
|
||||
pos = wpa_ft_process_ric(sm, pos, end, parse.ric,
|
||||
parse.ric_len);
|
||||
if (auth_alg == WLAN_AUTH_FT)
|
||||
_ftie->mic_control[1] +=
|
||||
ieee802_11_ie_count(ric_start,
|
||||
@ -725,143 +736,6 @@ u8 * wpa_sm_write_assoc_resp_ies(struct wpa_state_machine *sm, u8 *pos,
|
||||
}
|
||||
|
||||
|
||||
static int wpa_ft_parse_ftie(const u8 *ie, size_t ie_len,
|
||||
struct wpa_ft_ies *parse)
|
||||
{
|
||||
const u8 *end, *pos;
|
||||
|
||||
parse->ftie = ie;
|
||||
parse->ftie_len = ie_len;
|
||||
|
||||
pos = ie + sizeof(struct rsn_ftie);
|
||||
end = ie + ie_len;
|
||||
|
||||
while (pos + 2 <= end && pos + 2 + pos[1] <= end) {
|
||||
switch (pos[0]) {
|
||||
case FTIE_SUBELEM_R1KH_ID:
|
||||
if (pos[1] != FT_R1KH_ID_LEN) {
|
||||
wpa_printf(MSG_DEBUG, "FT: Invalid R1KH-ID "
|
||||
"length in FTIE: %d", pos[1]);
|
||||
return -1;
|
||||
}
|
||||
parse->r1kh_id = pos + 2;
|
||||
break;
|
||||
case FTIE_SUBELEM_GTK:
|
||||
parse->gtk = pos + 2;
|
||||
parse->gtk_len = pos[1];
|
||||
break;
|
||||
case FTIE_SUBELEM_R0KH_ID:
|
||||
if (pos[1] < 1 || pos[1] > FT_R0KH_ID_MAX_LEN) {
|
||||
wpa_printf(MSG_DEBUG, "FT: Invalid R0KH-ID "
|
||||
"length in FTIE: %d", pos[1]);
|
||||
return -1;
|
||||
}
|
||||
parse->r0kh_id = pos + 2;
|
||||
parse->r0kh_id_len = pos[1];
|
||||
break;
|
||||
}
|
||||
|
||||
pos += 2 + pos[1];
|
||||
}
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
|
||||
static int wpa_ft_parse_ies(const u8 *ies, size_t ies_len,
|
||||
struct wpa_ft_ies *parse)
|
||||
{
|
||||
const u8 *end, *pos;
|
||||
struct wpa_ie_data data;
|
||||
int ret;
|
||||
const struct rsn_ftie *ftie;
|
||||
int prot_ie_count = 0;
|
||||
|
||||
os_memset(parse, 0, sizeof(*parse));
|
||||
if (ies == NULL)
|
||||
return 0;
|
||||
|
||||
pos = ies;
|
||||
end = ies + ies_len;
|
||||
while (pos + 2 <= end && pos + 2 + pos[1] <= end) {
|
||||
switch (pos[0]) {
|
||||
case WLAN_EID_RSN:
|
||||
parse->rsn = pos + 2;
|
||||
parse->rsn_len = pos[1];
|
||||
ret = wpa_parse_wpa_ie_rsn(parse->rsn - 2,
|
||||
parse->rsn_len + 2,
|
||||
&data);
|
||||
if (ret < 0) {
|
||||
wpa_printf(MSG_DEBUG, "FT: Failed to parse "
|
||||
"RSN IE: %d", ret);
|
||||
return -1;
|
||||
}
|
||||
if (data.num_pmkid == 1 && data.pmkid)
|
||||
parse->rsn_pmkid = data.pmkid;
|
||||
break;
|
||||
case WLAN_EID_MOBILITY_DOMAIN:
|
||||
parse->mdie = pos + 2;
|
||||
parse->mdie_len = pos[1];
|
||||
break;
|
||||
case WLAN_EID_FAST_BSS_TRANSITION:
|
||||
if (pos[1] < sizeof(*ftie))
|
||||
return -1;
|
||||
ftie = (const struct rsn_ftie *) (pos + 2);
|
||||
prot_ie_count = ftie->mic_control[1];
|
||||
if (wpa_ft_parse_ftie(pos + 2, pos[1], parse) < 0)
|
||||
return -1;
|
||||
break;
|
||||
case WLAN_EID_RIC_DATA:
|
||||
if (parse->ric == NULL)
|
||||
parse->ric = pos;
|
||||
}
|
||||
|
||||
pos += 2 + pos[1];
|
||||
}
|
||||
|
||||
if (prot_ie_count == 0)
|
||||
return 0; /* no MIC */
|
||||
|
||||
/*
|
||||
* Check that the protected IE count matches with IEs included in the
|
||||
* frame.
|
||||
*/
|
||||
if (parse->rsn)
|
||||
prot_ie_count--;
|
||||
if (parse->mdie)
|
||||
prot_ie_count--;
|
||||
if (parse->ftie)
|
||||
prot_ie_count--;
|
||||
if (prot_ie_count < 0) {
|
||||
wpa_printf(MSG_DEBUG, "FT: Some required IEs not included in "
|
||||
"the protected IE count");
|
||||
return -1;
|
||||
}
|
||||
|
||||
if (prot_ie_count == 0 && parse->ric) {
|
||||
wpa_printf(MSG_DEBUG, "FT: RIC IE(s) in the frame, but not "
|
||||
"included in protected IE count");
|
||||
return -1;
|
||||
}
|
||||
|
||||
/* Determine the end of the RIC IE(s) */
|
||||
pos = parse->ric;
|
||||
while (pos && pos + 2 <= end && pos + 2 + pos[1] <= end &&
|
||||
prot_ie_count) {
|
||||
prot_ie_count--;
|
||||
pos += 2 + pos[1];
|
||||
}
|
||||
parse->ric_len = pos - parse->ric;
|
||||
if (prot_ie_count) {
|
||||
wpa_printf(MSG_DEBUG, "FT: %d protected IEs missing from "
|
||||
"frame", (int) prot_ie_count);
|
||||
return -1;
|
||||
}
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
|
||||
static inline int wpa_auth_set_key(struct wpa_authenticator *wpa_auth,
|
||||
int vlan_id,
|
||||
enum wpa_alg alg, const u8 *addr, int idx,
|
||||
@ -880,13 +754,9 @@ void wpa_ft_install_ptk(struct wpa_state_machine *sm)
|
||||
int klen;
|
||||
|
||||
/* MLME-SETKEYS.request(PTK) */
|
||||
if (sm->pairwise == WPA_CIPHER_TKIP) {
|
||||
alg = WPA_ALG_TKIP;
|
||||
klen = 32;
|
||||
} else if (sm->pairwise == WPA_CIPHER_CCMP) {
|
||||
alg = WPA_ALG_CCMP;
|
||||
klen = 16;
|
||||
} else {
|
||||
alg = wpa_cipher_to_alg(sm->pairwise);
|
||||
klen = wpa_cipher_key_len(sm->pairwise);
|
||||
if (!wpa_cipher_valid_pairwise(sm->pairwise)) {
|
||||
wpa_printf(MSG_DEBUG, "FT: Unknown pairwise alg 0x%x - skip "
|
||||
"PTK configuration", sm->pairwise);
|
||||
return;
|
||||
@ -997,7 +867,7 @@ static u16 wpa_ft_process_auth_req(struct wpa_state_machine *sm,
|
||||
sm->pmk_r1_name_valid = 1;
|
||||
os_memcpy(sm->pmk_r1_name, pmk_r1_name, WPA_PMK_NAME_LEN);
|
||||
|
||||
if (os_get_random(sm->ANonce, WPA_NONCE_LEN)) {
|
||||
if (random_get_bytes(sm->ANonce, WPA_NONCE_LEN)) {
|
||||
wpa_printf(MSG_DEBUG, "FT: Failed to get random data for "
|
||||
"ANonce");
|
||||
return WLAN_STATUS_UNSPECIFIED_FAILURE;
|
||||
@ -1008,7 +878,7 @@ static u16 wpa_ft_process_auth_req(struct wpa_state_machine *sm,
|
||||
wpa_hexdump(MSG_DEBUG, "FT: Generated ANonce",
|
||||
sm->ANonce, WPA_NONCE_LEN);
|
||||
|
||||
ptk_len = pairwise != WPA_CIPHER_CCMP ? 64 : 48;
|
||||
ptk_len = pairwise == WPA_CIPHER_TKIP ? 64 : 48;
|
||||
wpa_pmk_r1_to_ptk(pmk_r1, sm->SNonce, sm->ANonce, sm->addr,
|
||||
sm->wpa_auth->addr, pmk_r1_name,
|
||||
(u8 *) &sm->PTK, ptk_len, ptk_name);
|
||||
@ -1204,7 +1074,7 @@ u16 wpa_ft_validate_reassoc(struct wpa_state_machine *sm, const u8 *ies,
|
||||
|
||||
count = 3;
|
||||
if (parse.ric)
|
||||
count++;
|
||||
count += ieee802_11_ie_count(parse.ric, parse.ric_len);
|
||||
if (ftie->mic_control[1] != count) {
|
||||
wpa_printf(MSG_DEBUG, "FT: Unexpected IE count in MIC "
|
||||
"Control: received %u expected %u",
|
||||
@ -1224,8 +1094,16 @@ u16 wpa_ft_validate_reassoc(struct wpa_state_machine *sm, const u8 *ies,
|
||||
|
||||
if (os_memcmp(mic, ftie->mic, 16) != 0) {
|
||||
wpa_printf(MSG_DEBUG, "FT: Invalid MIC in FTIE");
|
||||
wpa_printf(MSG_DEBUG, "FT: addr=" MACSTR " auth_addr=" MACSTR,
|
||||
MAC2STR(sm->addr), MAC2STR(sm->wpa_auth->addr));
|
||||
wpa_hexdump(MSG_MSGDUMP, "FT: Received MIC", ftie->mic, 16);
|
||||
wpa_hexdump(MSG_MSGDUMP, "FT: Calculated MIC", mic, 16);
|
||||
wpa_hexdump(MSG_MSGDUMP, "FT: MDIE",
|
||||
parse.mdie - 2, parse.mdie_len + 2);
|
||||
wpa_hexdump(MSG_MSGDUMP, "FT: FTIE",
|
||||
parse.ftie - 2, parse.ftie_len + 2);
|
||||
wpa_hexdump(MSG_MSGDUMP, "FT: RSN",
|
||||
parse.rsn - 2, parse.rsn_len + 2);
|
||||
return WLAN_STATUS_INVALID_FTIE;
|
||||
}
|
||||
|
||||
|
@ -1,15 +1,9 @@
|
||||
/*
|
||||
* hostapd / WPA authenticator glue code
|
||||
* Copyright (c) 2002-2009, Jouni Malinen <j@w1.fi>
|
||||
* Copyright (c) 2002-2011, Jouni Malinen <j@w1.fi>
|
||||
*
|
||||
* This program is free software; you can redistribute it and/or modify
|
||||
* it under the terms of the GNU General Public License version 2 as
|
||||
* published by the Free Software Foundation.
|
||||
*
|
||||
* Alternatively, this software may be distributed under the terms of BSD
|
||||
* license.
|
||||
*
|
||||
* See README and COPYING for more details.
|
||||
* This software may be distributed under the terms of the BSD license.
|
||||
* See README for more details.
|
||||
*/
|
||||
|
||||
#include "utils/includes.h"
|
||||
@ -29,17 +23,13 @@
|
||||
#include "ap_drv_ops.h"
|
||||
#include "ap_config.h"
|
||||
#include "wpa_auth.h"
|
||||
|
||||
|
||||
#ifdef CONFIG_IEEE80211R
|
||||
static void hostapd_rrb_receive(void *ctx, const u8 *src_addr, const u8 *buf,
|
||||
size_t len);
|
||||
#endif /* CONFIG_IEEE80211R */
|
||||
#include "wpa_auth_glue.h"
|
||||
|
||||
|
||||
static void hostapd_wpa_auth_conf(struct hostapd_bss_config *conf,
|
||||
struct wpa_auth_config *wconf)
|
||||
{
|
||||
os_memset(wconf, 0, sizeof(*wconf));
|
||||
wconf->wpa = conf->wpa;
|
||||
wconf->wpa_key_mgmt = conf->wpa_key_mgmt;
|
||||
wconf->wpa_pairwise = conf->wpa_pairwise;
|
||||
@ -54,6 +44,7 @@ static void hostapd_wpa_auth_conf(struct hostapd_bss_config *conf,
|
||||
wconf->peerkey = conf->peerkey;
|
||||
wconf->wmm_enabled = conf->wmm_enabled;
|
||||
wconf->wmm_uapsd = conf->wmm_uapsd;
|
||||
wconf->disable_pmksa_caching = conf->disable_pmksa_caching;
|
||||
wconf->okc = conf->okc;
|
||||
#ifdef CONFIG_IEEE80211W
|
||||
wconf->ieee80211w = conf->ieee80211w;
|
||||
@ -77,7 +68,11 @@ static void hostapd_wpa_auth_conf(struct hostapd_bss_config *conf,
|
||||
wconf->r0kh_list = conf->r0kh_list;
|
||||
wconf->r1kh_list = conf->r1kh_list;
|
||||
wconf->pmk_r1_push = conf->pmk_r1_push;
|
||||
wconf->ft_over_ds = conf->ft_over_ds;
|
||||
#endif /* CONFIG_IEEE80211R */
|
||||
#ifdef CONFIG_HS20
|
||||
wconf->disable_gtk = conf->disable_dgaf;
|
||||
#endif /* CONFIG_HS20 */
|
||||
}
|
||||
|
||||
|
||||
@ -117,10 +112,10 @@ static void hostapd_wpa_auth_disconnect(void *ctx, const u8 *addr,
|
||||
}
|
||||
|
||||
|
||||
static void hostapd_wpa_auth_mic_failure_report(void *ctx, const u8 *addr)
|
||||
static int hostapd_wpa_auth_mic_failure_report(void *ctx, const u8 *addr)
|
||||
{
|
||||
struct hostapd_data *hapd = ctx;
|
||||
michael_mic_failure(hapd, addr, 0);
|
||||
return michael_mic_failure(hapd, addr, 0);
|
||||
}
|
||||
|
||||
|
||||
@ -188,7 +183,24 @@ static const u8 * hostapd_wpa_auth_get_psk(void *ctx, const u8 *addr,
|
||||
const u8 *prev_psk)
|
||||
{
|
||||
struct hostapd_data *hapd = ctx;
|
||||
return hostapd_get_psk(hapd->conf, addr, prev_psk);
|
||||
struct sta_info *sta = ap_get_sta(hapd, addr);
|
||||
const u8 *psk = hostapd_get_psk(hapd->conf, addr, prev_psk);
|
||||
/*
|
||||
* This is about to iterate over all psks, prev_psk gives the last
|
||||
* returned psk which should not be returned again.
|
||||
* logic list (all hostapd_get_psk; all sta->psk)
|
||||
*/
|
||||
if (sta && sta->psk && !psk) {
|
||||
struct hostapd_sta_wpa_psk_short *pos;
|
||||
psk = sta->psk->psk;
|
||||
for (pos = sta->psk; pos; pos = pos->next) {
|
||||
if (pos->psk == prev_psk) {
|
||||
psk = pos->next ? pos->next->psk : NULL;
|
||||
break;
|
||||
}
|
||||
}
|
||||
}
|
||||
return psk;
|
||||
}
|
||||
|
||||
|
||||
@ -230,8 +242,8 @@ static int hostapd_wpa_auth_set_key(void *ctx, int vlan_id, enum wpa_alg alg,
|
||||
return -1;
|
||||
}
|
||||
|
||||
return hapd->drv.set_key(ifname, hapd, alg, addr, idx, 1, NULL, 0,
|
||||
key, key_len);
|
||||
return hostapd_drv_set_key(ifname, hapd, alg, addr, idx, 1, NULL, 0,
|
||||
key, key_len);
|
||||
}
|
||||
|
||||
|
||||
@ -248,7 +260,15 @@ static int hostapd_wpa_auth_send_eapol(void *ctx, const u8 *addr,
|
||||
int encrypt)
|
||||
{
|
||||
struct hostapd_data *hapd = ctx;
|
||||
return hapd->drv.send_eapol(hapd, addr, data, data_len, encrypt);
|
||||
struct sta_info *sta;
|
||||
u32 flags = 0;
|
||||
|
||||
sta = ap_get_sta(hapd, addr);
|
||||
if (sta)
|
||||
flags = hostapd_sta_flags_to_drv(sta->flags);
|
||||
|
||||
return hostapd_drv_hapd_send_eapol(hapd, addr, data, data_len,
|
||||
encrypt, flags);
|
||||
}
|
||||
|
||||
|
||||
@ -291,12 +311,13 @@ static int hostapd_wpa_auth_for_each_auth(
|
||||
{
|
||||
struct hostapd_data *hapd = ctx;
|
||||
struct wpa_auth_iface_iter_data data;
|
||||
if (hapd->iface->for_each_interface == NULL)
|
||||
if (hapd->iface->interfaces == NULL ||
|
||||
hapd->iface->interfaces->for_each_interface == NULL)
|
||||
return -1;
|
||||
data.cb = cb;
|
||||
data.cb_ctx = cb_ctx;
|
||||
return hapd->iface->for_each_interface(hapd->iface->interfaces,
|
||||
wpa_auth_iface_iter, &data);
|
||||
return hapd->iface->interfaces->for_each_interface(
|
||||
hapd->iface->interfaces, wpa_auth_iface_iter, &data);
|
||||
}
|
||||
|
||||
|
||||
@ -327,8 +348,9 @@ static int hostapd_wpa_auth_ft_iter(struct hostapd_iface *iface, void *ctx)
|
||||
MAC2STR(idata->src_hapd->own_addr),
|
||||
idata->src_hapd->conf->iface,
|
||||
MAC2STR(hapd->own_addr), hapd->conf->iface);
|
||||
hostapd_rrb_receive(hapd, idata->src_hapd->own_addr,
|
||||
idata->data, idata->data_len);
|
||||
wpa_ft_rrb_rx(hapd->wpa_auth,
|
||||
idata->src_hapd->own_addr,
|
||||
idata->data, idata->data_len);
|
||||
return 1;
|
||||
}
|
||||
}
|
||||
@ -343,18 +365,21 @@ static int hostapd_wpa_auth_send_ether(void *ctx, const u8 *dst, u16 proto,
|
||||
const u8 *data, size_t data_len)
|
||||
{
|
||||
struct hostapd_data *hapd = ctx;
|
||||
struct l2_ethhdr *buf;
|
||||
int ret;
|
||||
|
||||
#ifdef CONFIG_IEEE80211R
|
||||
if (proto == ETH_P_RRB && hapd->iface->for_each_interface) {
|
||||
if (proto == ETH_P_RRB && hapd->iface->interfaces &&
|
||||
hapd->iface->interfaces->for_each_interface) {
|
||||
int res;
|
||||
struct wpa_auth_ft_iface_iter_data idata;
|
||||
idata.src_hapd = hapd;
|
||||
idata.dst = dst;
|
||||
idata.data = data;
|
||||
idata.data_len = data_len;
|
||||
res = hapd->iface->for_each_interface(hapd->iface->interfaces,
|
||||
hostapd_wpa_auth_ft_iter,
|
||||
&idata);
|
||||
res = hapd->iface->interfaces->for_each_interface(
|
||||
hapd->iface->interfaces, hostapd_wpa_auth_ft_iter,
|
||||
&idata);
|
||||
if (res == 1)
|
||||
return data_len;
|
||||
}
|
||||
@ -366,7 +391,18 @@ static int hostapd_wpa_auth_send_ether(void *ctx, const u8 *dst, u16 proto,
|
||||
data, data_len);
|
||||
if (hapd->l2 == NULL)
|
||||
return -1;
|
||||
return l2_packet_send(hapd->l2, dst, proto, data, data_len);
|
||||
|
||||
buf = os_malloc(sizeof(*buf) + data_len);
|
||||
if (buf == NULL)
|
||||
return -1;
|
||||
os_memcpy(buf->h_dest, dst, ETH_ALEN);
|
||||
os_memcpy(buf->h_source, hapd->own_addr, ETH_ALEN);
|
||||
buf->h_proto = host_to_be16(proto);
|
||||
os_memcpy(buf + 1, data, data_len);
|
||||
ret = l2_packet_send(hapd->l2, dst, proto, (u8 *) buf,
|
||||
sizeof(*buf) + data_len);
|
||||
os_free(buf);
|
||||
return ret;
|
||||
}
|
||||
|
||||
|
||||
@ -396,7 +432,7 @@ static int hostapd_wpa_auth_send_ft_action(void *ctx, const u8 *dst,
|
||||
os_memcpy(m->bssid, hapd->own_addr, ETH_ALEN);
|
||||
os_memcpy(&m->u, data, data_len);
|
||||
|
||||
res = hapd->drv.send_mgmt_frame(hapd, (u8 *) m, mlen);
|
||||
res = hostapd_drv_send_mlme(hapd, (u8 *) m, mlen, 0);
|
||||
os_free(m);
|
||||
return res;
|
||||
}
|
||||
@ -408,6 +444,9 @@ hostapd_wpa_auth_add_sta(void *ctx, const u8 *sta_addr)
|
||||
struct hostapd_data *hapd = ctx;
|
||||
struct sta_info *sta;
|
||||
|
||||
if (hostapd_add_sta_node(hapd, sta_addr, WLAN_AUTH_FT) < 0)
|
||||
return NULL;
|
||||
|
||||
sta = ap_sta_add(hapd, sta_addr);
|
||||
if (sta == NULL)
|
||||
return NULL;
|
||||
@ -431,7 +470,22 @@ static void hostapd_rrb_receive(void *ctx, const u8 *src_addr, const u8 *buf,
|
||||
size_t len)
|
||||
{
|
||||
struct hostapd_data *hapd = ctx;
|
||||
wpa_ft_rrb_rx(hapd->wpa_auth, src_addr, buf, len);
|
||||
struct l2_ethhdr *ethhdr;
|
||||
if (len < sizeof(*ethhdr))
|
||||
return;
|
||||
ethhdr = (struct l2_ethhdr *) buf;
|
||||
wpa_printf(MSG_DEBUG, "FT: RRB received packet " MACSTR " -> "
|
||||
MACSTR, MAC2STR(ethhdr->h_source), MAC2STR(ethhdr->h_dest));
|
||||
wpa_ft_rrb_rx(hapd->wpa_auth, ethhdr->h_source, buf + sizeof(*ethhdr),
|
||||
len - sizeof(*ethhdr));
|
||||
}
|
||||
|
||||
|
||||
static int hostapd_wpa_auth_add_tspec(void *ctx, const u8 *sta_addr,
|
||||
u8 *tspec_ie, size_t tspec_ielen)
|
||||
{
|
||||
struct hostapd_data *hapd = ctx;
|
||||
return hostapd_add_tspec(hapd, sta_addr, tspec_ie, tspec_ielen);
|
||||
}
|
||||
|
||||
#endif /* CONFIG_IEEE80211R */
|
||||
@ -445,6 +499,10 @@ int hostapd_setup_wpa(struct hostapd_data *hapd)
|
||||
size_t wpa_ie_len;
|
||||
|
||||
hostapd_wpa_auth_conf(hapd->conf, &_conf);
|
||||
if (hapd->iface->drv_flags & WPA_DRIVER_FLAGS_EAPOL_TX_STATUS)
|
||||
_conf.tx_status = 1;
|
||||
if (hapd->iface->drv_flags & WPA_DRIVER_FLAGS_AP_MLME)
|
||||
_conf.ap_mlme = 1;
|
||||
os_memset(&cb, 0, sizeof(cb));
|
||||
cb.ctx = hapd;
|
||||
cb.logger = hostapd_wpa_auth_logger;
|
||||
@ -463,6 +521,7 @@ int hostapd_setup_wpa(struct hostapd_data *hapd)
|
||||
#ifdef CONFIG_IEEE80211R
|
||||
cb.send_ft_action = hostapd_wpa_auth_send_ft_action;
|
||||
cb.add_sta = hostapd_wpa_auth_add_sta;
|
||||
cb.add_tspec = hostapd_wpa_auth_add_tspec;
|
||||
#endif /* CONFIG_IEEE80211R */
|
||||
hapd->wpa_auth = wpa_init(hapd->own_addr, &_conf, &cb);
|
||||
if (hapd->wpa_auth == NULL) {
|
||||
@ -494,7 +553,7 @@ int hostapd_setup_wpa(struct hostapd_data *hapd)
|
||||
hapd->l2 = l2_packet_init(hapd->conf->bridge[0] ?
|
||||
hapd->conf->bridge :
|
||||
hapd->conf->iface, NULL, ETH_P_RRB,
|
||||
hostapd_rrb_receive, hapd, 0);
|
||||
hostapd_rrb_receive, hapd, 1);
|
||||
if (hapd->l2 == NULL &&
|
||||
(hapd->driver == NULL ||
|
||||
hapd->driver->send_ether == NULL)) {
|
||||
@ -520,6 +579,7 @@ void hostapd_reconfig_wpa(struct hostapd_data *hapd)
|
||||
|
||||
void hostapd_deinit_wpa(struct hostapd_data *hapd)
|
||||
{
|
||||
ieee80211_tkip_countermeasures_deinit(hapd);
|
||||
rsn_preauth_iface_deinit(hapd);
|
||||
if (hapd->wpa_auth) {
|
||||
wpa_deinit(hapd->wpa_auth);
|
||||
|
@ -2,14 +2,8 @@
|
||||
* hostapd / WPA authenticator glue code
|
||||
* Copyright (c) 2002-2009, Jouni Malinen <j@w1.fi>
|
||||
*
|
||||
* This program is free software; you can redistribute it and/or modify
|
||||
* it under the terms of the GNU General Public License version 2 as
|
||||
* published by the Free Software Foundation.
|
||||
*
|
||||
* Alternatively, this software may be distributed under the terms of BSD
|
||||
* license.
|
||||
*
|
||||
* See README and COPYING for more details.
|
||||
* This software may be distributed under the terms of the BSD license.
|
||||
* See README for more details.
|
||||
*/
|
||||
|
||||
#ifndef WPA_AUTH_GLUE_H
|
||||
|
@ -2,14 +2,8 @@
|
||||
* hostapd - IEEE 802.11i-2004 / WPA Authenticator: Internal definitions
|
||||
* Copyright (c) 2004-2007, Jouni Malinen <j@w1.fi>
|
||||
*
|
||||
* This program is free software; you can redistribute it and/or modify
|
||||
* it under the terms of the GNU General Public License version 2 as
|
||||
* published by the Free Software Foundation.
|
||||
*
|
||||
* Alternatively, this software may be distributed under the terms of BSD
|
||||
* license.
|
||||
*
|
||||
* See README and COPYING for more details.
|
||||
* This software may be distributed under the terms of the BSD license.
|
||||
* See README for more details.
|
||||
*/
|
||||
|
||||
#ifndef WPA_AUTH_I_H
|
||||
@ -69,10 +63,11 @@ struct wpa_state_machine {
|
||||
Boolean pairwise_set;
|
||||
int keycount;
|
||||
Boolean Pair;
|
||||
struct {
|
||||
struct wpa_key_replay_counter {
|
||||
u8 counter[WPA_REPLAY_COUNTER_LEN];
|
||||
Boolean valid;
|
||||
} key_replay[RSNA_MAX_EAPOL_RETRIES];
|
||||
} key_replay[RSNA_MAX_EAPOL_RETRIES],
|
||||
prev_key_replay[RSNA_MAX_EAPOL_RETRIES];
|
||||
Boolean PInitAKeys; /* WPA only, not in IEEE 802.11i */
|
||||
Boolean PTKRequest; /* not in IEEE 802.11i state machine */
|
||||
Boolean has_GTK;
|
||||
@ -86,10 +81,13 @@ struct wpa_state_machine {
|
||||
unsigned int pending_deinit:1;
|
||||
unsigned int started:1;
|
||||
unsigned int mgmt_frame_prot:1;
|
||||
unsigned int rx_eapol_key_secure:1;
|
||||
unsigned int update_snonce:1;
|
||||
#ifdef CONFIG_IEEE80211R
|
||||
unsigned int ft_completed:1;
|
||||
unsigned int pmk_r1_name_valid:1;
|
||||
#endif /* CONFIG_IEEE80211R */
|
||||
unsigned int is_wnmsleep:1;
|
||||
|
||||
u8 req_replay_counter[WPA_REPLAY_COUNTER_LEN];
|
||||
int req_replay_counter_used;
|
||||
@ -120,6 +118,8 @@ struct wpa_state_machine {
|
||||
* message 2/4 */
|
||||
u8 *assoc_resp_ftie;
|
||||
#endif /* CONFIG_IEEE80211R */
|
||||
|
||||
int pending_1_of_4_timeout;
|
||||
};
|
||||
|
||||
|
||||
@ -145,6 +145,8 @@ struct wpa_group {
|
||||
u8 GTK[2][WPA_GTK_MAX_LEN];
|
||||
u8 GNonce[WPA_NONCE_LEN];
|
||||
Boolean changed;
|
||||
Boolean first_sta_seen;
|
||||
Boolean reject_4way_hs_for_entropy;
|
||||
#ifdef CONFIG_IEEE80211W
|
||||
u8 IGTK[2][WPA_IGTK_LEN];
|
||||
int GN_igtk, GM_igtk;
|
||||
|
@ -2,14 +2,8 @@
|
||||
* hostapd - WPA/RSN IE and KDE definitions
|
||||
* Copyright (c) 2004-2008, Jouni Malinen <j@w1.fi>
|
||||
*
|
||||
* This program is free software; you can redistribute it and/or modify
|
||||
* it under the terms of the GNU General Public License version 2 as
|
||||
* published by the Free Software Foundation.
|
||||
*
|
||||
* Alternatively, this software may be distributed under the terms of BSD
|
||||
* license.
|
||||
*
|
||||
* See README and COPYING for more details.
|
||||
* This software may be distributed under the terms of the BSD license.
|
||||
* See README for more details.
|
||||
*/
|
||||
|
||||
#include "utils/includes.h"
|
||||
@ -25,11 +19,17 @@
|
||||
#include "wpa_auth_i.h"
|
||||
|
||||
|
||||
#ifdef CONFIG_RSN_TESTING
|
||||
int rsn_testing = 0;
|
||||
#endif /* CONFIG_RSN_TESTING */
|
||||
|
||||
|
||||
static int wpa_write_wpa_ie(struct wpa_auth_config *conf, u8 *buf, size_t len)
|
||||
{
|
||||
struct wpa_ie_hdr *hdr;
|
||||
int num_suites;
|
||||
u8 *pos, *count;
|
||||
u32 suite;
|
||||
|
||||
hdr = (struct wpa_ie_hdr *) buf;
|
||||
hdr->elem_id = WLAN_EID_VENDOR_SPECIFIC;
|
||||
@ -37,46 +37,25 @@ static int wpa_write_wpa_ie(struct wpa_auth_config *conf, u8 *buf, size_t len)
|
||||
WPA_PUT_LE16(hdr->version, WPA_VERSION);
|
||||
pos = (u8 *) (hdr + 1);
|
||||
|
||||
if (conf->wpa_group == WPA_CIPHER_CCMP) {
|
||||
RSN_SELECTOR_PUT(pos, WPA_CIPHER_SUITE_CCMP);
|
||||
} else if (conf->wpa_group == WPA_CIPHER_TKIP) {
|
||||
RSN_SELECTOR_PUT(pos, WPA_CIPHER_SUITE_TKIP);
|
||||
} else if (conf->wpa_group == WPA_CIPHER_WEP104) {
|
||||
RSN_SELECTOR_PUT(pos, WPA_CIPHER_SUITE_WEP104);
|
||||
} else if (conf->wpa_group == WPA_CIPHER_WEP40) {
|
||||
RSN_SELECTOR_PUT(pos, WPA_CIPHER_SUITE_WEP40);
|
||||
} else {
|
||||
suite = wpa_cipher_to_suite(WPA_PROTO_WPA, conf->wpa_group);
|
||||
if (suite == 0) {
|
||||
wpa_printf(MSG_DEBUG, "Invalid group cipher (%d).",
|
||||
conf->wpa_group);
|
||||
return -1;
|
||||
}
|
||||
RSN_SELECTOR_PUT(pos, suite);
|
||||
pos += WPA_SELECTOR_LEN;
|
||||
|
||||
num_suites = 0;
|
||||
count = pos;
|
||||
pos += 2;
|
||||
|
||||
if (conf->wpa_pairwise & WPA_CIPHER_CCMP) {
|
||||
RSN_SELECTOR_PUT(pos, WPA_CIPHER_SUITE_CCMP);
|
||||
pos += WPA_SELECTOR_LEN;
|
||||
num_suites++;
|
||||
}
|
||||
if (conf->wpa_pairwise & WPA_CIPHER_TKIP) {
|
||||
RSN_SELECTOR_PUT(pos, WPA_CIPHER_SUITE_TKIP);
|
||||
pos += WPA_SELECTOR_LEN;
|
||||
num_suites++;
|
||||
}
|
||||
if (conf->wpa_pairwise & WPA_CIPHER_NONE) {
|
||||
RSN_SELECTOR_PUT(pos, WPA_CIPHER_SUITE_NONE);
|
||||
pos += WPA_SELECTOR_LEN;
|
||||
num_suites++;
|
||||
}
|
||||
|
||||
num_suites = wpa_cipher_put_suites(pos, conf->wpa_pairwise);
|
||||
if (num_suites == 0) {
|
||||
wpa_printf(MSG_DEBUG, "Invalid pairwise cipher (%d).",
|
||||
conf->wpa_pairwise);
|
||||
return -1;
|
||||
}
|
||||
pos += num_suites * WPA_SELECTOR_LEN;
|
||||
WPA_PUT_LE16(count, num_suites);
|
||||
|
||||
num_suites = 0;
|
||||
@ -113,49 +92,48 @@ int wpa_write_rsn_ie(struct wpa_auth_config *conf, u8 *buf, size_t len,
|
||||
const u8 *pmkid)
|
||||
{
|
||||
struct rsn_ie_hdr *hdr;
|
||||
int num_suites;
|
||||
int num_suites, res;
|
||||
u8 *pos, *count;
|
||||
u16 capab;
|
||||
u32 suite;
|
||||
|
||||
hdr = (struct rsn_ie_hdr *) buf;
|
||||
hdr->elem_id = WLAN_EID_RSN;
|
||||
WPA_PUT_LE16(hdr->version, RSN_VERSION);
|
||||
pos = (u8 *) (hdr + 1);
|
||||
|
||||
if (conf->wpa_group == WPA_CIPHER_CCMP) {
|
||||
RSN_SELECTOR_PUT(pos, RSN_CIPHER_SUITE_CCMP);
|
||||
} else if (conf->wpa_group == WPA_CIPHER_TKIP) {
|
||||
RSN_SELECTOR_PUT(pos, RSN_CIPHER_SUITE_TKIP);
|
||||
} else if (conf->wpa_group == WPA_CIPHER_WEP104) {
|
||||
RSN_SELECTOR_PUT(pos, RSN_CIPHER_SUITE_WEP104);
|
||||
} else if (conf->wpa_group == WPA_CIPHER_WEP40) {
|
||||
RSN_SELECTOR_PUT(pos, RSN_CIPHER_SUITE_WEP40);
|
||||
} else {
|
||||
suite = wpa_cipher_to_suite(WPA_PROTO_RSN, conf->wpa_group);
|
||||
if (suite == 0) {
|
||||
wpa_printf(MSG_DEBUG, "Invalid group cipher (%d).",
|
||||
conf->wpa_group);
|
||||
return -1;
|
||||
}
|
||||
RSN_SELECTOR_PUT(pos, suite);
|
||||
pos += RSN_SELECTOR_LEN;
|
||||
|
||||
num_suites = 0;
|
||||
count = pos;
|
||||
pos += 2;
|
||||
|
||||
if (conf->rsn_pairwise & WPA_CIPHER_CCMP) {
|
||||
RSN_SELECTOR_PUT(pos, RSN_CIPHER_SUITE_CCMP);
|
||||
#ifdef CONFIG_RSN_TESTING
|
||||
if (rsn_testing) {
|
||||
RSN_SELECTOR_PUT(pos, RSN_SELECTOR(0x12, 0x34, 0x56, 1));
|
||||
pos += RSN_SELECTOR_LEN;
|
||||
num_suites++;
|
||||
}
|
||||
if (conf->rsn_pairwise & WPA_CIPHER_TKIP) {
|
||||
RSN_SELECTOR_PUT(pos, RSN_CIPHER_SUITE_TKIP);
|
||||
pos += RSN_SELECTOR_LEN;
|
||||
num_suites++;
|
||||
}
|
||||
if (conf->rsn_pairwise & WPA_CIPHER_NONE) {
|
||||
RSN_SELECTOR_PUT(pos, RSN_CIPHER_SUITE_NONE);
|
||||
#endif /* CONFIG_RSN_TESTING */
|
||||
|
||||
res = rsn_cipher_put_suites(pos, conf->rsn_pairwise);
|
||||
num_suites += res;
|
||||
pos += res * RSN_SELECTOR_LEN;
|
||||
|
||||
#ifdef CONFIG_RSN_TESTING
|
||||
if (rsn_testing) {
|
||||
RSN_SELECTOR_PUT(pos, RSN_SELECTOR(0x12, 0x34, 0x56, 2));
|
||||
pos += RSN_SELECTOR_LEN;
|
||||
num_suites++;
|
||||
}
|
||||
#endif /* CONFIG_RSN_TESTING */
|
||||
|
||||
if (num_suites == 0) {
|
||||
wpa_printf(MSG_DEBUG, "Invalid pairwise cipher (%d).",
|
||||
@ -168,6 +146,14 @@ int wpa_write_rsn_ie(struct wpa_auth_config *conf, u8 *buf, size_t len,
|
||||
count = pos;
|
||||
pos += 2;
|
||||
|
||||
#ifdef CONFIG_RSN_TESTING
|
||||
if (rsn_testing) {
|
||||
RSN_SELECTOR_PUT(pos, RSN_SELECTOR(0x12, 0x34, 0x56, 1));
|
||||
pos += RSN_SELECTOR_LEN;
|
||||
num_suites++;
|
||||
}
|
||||
#endif /* CONFIG_RSN_TESTING */
|
||||
|
||||
if (conf->wpa_key_mgmt & WPA_KEY_MGMT_IEEE8021X) {
|
||||
RSN_SELECTOR_PUT(pos, RSN_AUTH_KEY_MGMT_UNSPEC_802_1X);
|
||||
pos += RSN_SELECTOR_LEN;
|
||||
@ -202,6 +188,26 @@ int wpa_write_rsn_ie(struct wpa_auth_config *conf, u8 *buf, size_t len,
|
||||
num_suites++;
|
||||
}
|
||||
#endif /* CONFIG_IEEE80211W */
|
||||
#ifdef CONFIG_SAE
|
||||
if (conf->wpa_key_mgmt & WPA_KEY_MGMT_SAE) {
|
||||
RSN_SELECTOR_PUT(pos, RSN_AUTH_KEY_MGMT_SAE);
|
||||
pos += RSN_SELECTOR_LEN;
|
||||
num_suites++;
|
||||
}
|
||||
if (conf->wpa_key_mgmt & WPA_KEY_MGMT_FT_SAE) {
|
||||
RSN_SELECTOR_PUT(pos, RSN_AUTH_KEY_MGMT_FT_SAE);
|
||||
pos += RSN_SELECTOR_LEN;
|
||||
num_suites++;
|
||||
}
|
||||
#endif /* CONFIG_SAE */
|
||||
|
||||
#ifdef CONFIG_RSN_TESTING
|
||||
if (rsn_testing) {
|
||||
RSN_SELECTOR_PUT(pos, RSN_SELECTOR(0x12, 0x34, 0x56, 2));
|
||||
pos += RSN_SELECTOR_LEN;
|
||||
num_suites++;
|
||||
}
|
||||
#endif /* CONFIG_RSN_TESTING */
|
||||
|
||||
if (num_suites == 0) {
|
||||
wpa_printf(MSG_DEBUG, "Invalid key management type (%d).",
|
||||
@ -227,6 +233,10 @@ int wpa_write_rsn_ie(struct wpa_auth_config *conf, u8 *buf, size_t len,
|
||||
capab |= WPA_CAPABILITY_MFPR;
|
||||
}
|
||||
#endif /* CONFIG_IEEE80211W */
|
||||
#ifdef CONFIG_RSN_TESTING
|
||||
if (rsn_testing)
|
||||
capab |= BIT(8) | BIT(14) | BIT(15);
|
||||
#endif /* CONFIG_RSN_TESTING */
|
||||
WPA_PUT_LE16(pos, capab);
|
||||
pos += 2;
|
||||
|
||||
@ -256,6 +266,29 @@ int wpa_write_rsn_ie(struct wpa_auth_config *conf, u8 *buf, size_t len,
|
||||
}
|
||||
#endif /* CONFIG_IEEE80211W */
|
||||
|
||||
#ifdef CONFIG_RSN_TESTING
|
||||
if (rsn_testing) {
|
||||
/*
|
||||
* Fill in any defined fields and add extra data to the end of
|
||||
* the element.
|
||||
*/
|
||||
int pmkid_count_set = pmkid != NULL;
|
||||
if (conf->ieee80211w != NO_MGMT_FRAME_PROTECTION)
|
||||
pmkid_count_set = 1;
|
||||
/* PMKID Count */
|
||||
WPA_PUT_LE16(pos, 0);
|
||||
pos += 2;
|
||||
if (conf->ieee80211w == NO_MGMT_FRAME_PROTECTION) {
|
||||
/* Management Group Cipher Suite */
|
||||
RSN_SELECTOR_PUT(pos, RSN_CIPHER_SUITE_AES_128_CMAC);
|
||||
pos += RSN_SELECTOR_LEN;
|
||||
}
|
||||
|
||||
os_memset(pos, 0x12, 17);
|
||||
pos += 17;
|
||||
}
|
||||
#endif /* CONFIG_RSN_TESTING */
|
||||
|
||||
hdr->len = (pos - buf) - 2;
|
||||
|
||||
return pos - buf;
|
||||
@ -277,8 +310,7 @@ int wpa_auth_gen_wpa_ie(struct wpa_authenticator *wpa_auth)
|
||||
pos += res;
|
||||
}
|
||||
#ifdef CONFIG_IEEE80211R
|
||||
if (wpa_auth->conf.wpa_key_mgmt &
|
||||
(WPA_KEY_MGMT_FT_IEEE8021X | WPA_KEY_MGMT_FT_PSK)) {
|
||||
if (wpa_key_mgmt_ft(wpa_auth->conf.wpa_key_mgmt)) {
|
||||
res = wpa_write_mdie(&wpa_auth->conf, pos,
|
||||
buf + sizeof(buf) - pos);
|
||||
if (res < 0)
|
||||
@ -322,114 +354,6 @@ u8 * wpa_add_kde(u8 *pos, u32 kde, const u8 *data, size_t data_len,
|
||||
}
|
||||
|
||||
|
||||
static int wpa_selector_to_bitfield(const u8 *s)
|
||||
{
|
||||
if (RSN_SELECTOR_GET(s) == WPA_CIPHER_SUITE_NONE)
|
||||
return WPA_CIPHER_NONE;
|
||||
if (RSN_SELECTOR_GET(s) == WPA_CIPHER_SUITE_WEP40)
|
||||
return WPA_CIPHER_WEP40;
|
||||
if (RSN_SELECTOR_GET(s) == WPA_CIPHER_SUITE_TKIP)
|
||||
return WPA_CIPHER_TKIP;
|
||||
if (RSN_SELECTOR_GET(s) == WPA_CIPHER_SUITE_CCMP)
|
||||
return WPA_CIPHER_CCMP;
|
||||
if (RSN_SELECTOR_GET(s) == WPA_CIPHER_SUITE_WEP104)
|
||||
return WPA_CIPHER_WEP104;
|
||||
return 0;
|
||||
}
|
||||
|
||||
|
||||
static int wpa_key_mgmt_to_bitfield(const u8 *s)
|
||||
{
|
||||
if (RSN_SELECTOR_GET(s) == WPA_AUTH_KEY_MGMT_UNSPEC_802_1X)
|
||||
return WPA_KEY_MGMT_IEEE8021X;
|
||||
if (RSN_SELECTOR_GET(s) == WPA_AUTH_KEY_MGMT_PSK_OVER_802_1X)
|
||||
return WPA_KEY_MGMT_PSK;
|
||||
if (RSN_SELECTOR_GET(s) == WPA_AUTH_KEY_MGMT_NONE)
|
||||
return WPA_KEY_MGMT_WPA_NONE;
|
||||
return 0;
|
||||
}
|
||||
|
||||
|
||||
static int wpa_parse_wpa_ie_wpa(const u8 *wpa_ie, size_t wpa_ie_len,
|
||||
struct wpa_ie_data *data)
|
||||
{
|
||||
const struct wpa_ie_hdr *hdr;
|
||||
const u8 *pos;
|
||||
int left;
|
||||
int i, count;
|
||||
|
||||
os_memset(data, 0, sizeof(*data));
|
||||
data->pairwise_cipher = WPA_CIPHER_TKIP;
|
||||
data->group_cipher = WPA_CIPHER_TKIP;
|
||||
data->key_mgmt = WPA_KEY_MGMT_IEEE8021X;
|
||||
data->mgmt_group_cipher = 0;
|
||||
|
||||
if (wpa_ie_len < sizeof(struct wpa_ie_hdr))
|
||||
return -1;
|
||||
|
||||
hdr = (const struct wpa_ie_hdr *) wpa_ie;
|
||||
|
||||
if (hdr->elem_id != WLAN_EID_VENDOR_SPECIFIC ||
|
||||
hdr->len != wpa_ie_len - 2 ||
|
||||
RSN_SELECTOR_GET(hdr->oui) != WPA_OUI_TYPE ||
|
||||
WPA_GET_LE16(hdr->version) != WPA_VERSION) {
|
||||
return -2;
|
||||
}
|
||||
|
||||
pos = (const u8 *) (hdr + 1);
|
||||
left = wpa_ie_len - sizeof(*hdr);
|
||||
|
||||
if (left >= WPA_SELECTOR_LEN) {
|
||||
data->group_cipher = wpa_selector_to_bitfield(pos);
|
||||
pos += WPA_SELECTOR_LEN;
|
||||
left -= WPA_SELECTOR_LEN;
|
||||
} else if (left > 0)
|
||||
return -3;
|
||||
|
||||
if (left >= 2) {
|
||||
data->pairwise_cipher = 0;
|
||||
count = WPA_GET_LE16(pos);
|
||||
pos += 2;
|
||||
left -= 2;
|
||||
if (count == 0 || left < count * WPA_SELECTOR_LEN)
|
||||
return -4;
|
||||
for (i = 0; i < count; i++) {
|
||||
data->pairwise_cipher |= wpa_selector_to_bitfield(pos);
|
||||
pos += WPA_SELECTOR_LEN;
|
||||
left -= WPA_SELECTOR_LEN;
|
||||
}
|
||||
} else if (left == 1)
|
||||
return -5;
|
||||
|
||||
if (left >= 2) {
|
||||
data->key_mgmt = 0;
|
||||
count = WPA_GET_LE16(pos);
|
||||
pos += 2;
|
||||
left -= 2;
|
||||
if (count == 0 || left < count * WPA_SELECTOR_LEN)
|
||||
return -6;
|
||||
for (i = 0; i < count; i++) {
|
||||
data->key_mgmt |= wpa_key_mgmt_to_bitfield(pos);
|
||||
pos += WPA_SELECTOR_LEN;
|
||||
left -= WPA_SELECTOR_LEN;
|
||||
}
|
||||
} else if (left == 1)
|
||||
return -7;
|
||||
|
||||
if (left >= 2) {
|
||||
data->capabilities = WPA_GET_LE16(pos);
|
||||
pos += 2;
|
||||
left -= 2;
|
||||
}
|
||||
|
||||
if (left > 0) {
|
||||
return -8;
|
||||
}
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
|
||||
struct wpa_auth_okc_iter_data {
|
||||
struct rsn_pmksa_cache_entry *pmksa;
|
||||
const u8 *aa;
|
||||
@ -495,36 +419,28 @@ int wpa_validate_wpa_ie(struct wpa_authenticator *wpa_auth,
|
||||
else if (data.key_mgmt & WPA_KEY_MGMT_PSK_SHA256)
|
||||
selector = RSN_AUTH_KEY_MGMT_PSK_SHA256;
|
||||
#endif /* CONFIG_IEEE80211W */
|
||||
#ifdef CONFIG_SAE
|
||||
else if (data.key_mgmt & WPA_KEY_MGMT_SAE)
|
||||
selector = RSN_AUTH_KEY_MGMT_SAE;
|
||||
else if (data.key_mgmt & WPA_KEY_MGMT_FT_SAE)
|
||||
selector = RSN_AUTH_KEY_MGMT_FT_SAE;
|
||||
#endif /* CONFIG_SAE */
|
||||
else if (data.key_mgmt & WPA_KEY_MGMT_IEEE8021X)
|
||||
selector = RSN_AUTH_KEY_MGMT_UNSPEC_802_1X;
|
||||
else if (data.key_mgmt & WPA_KEY_MGMT_PSK)
|
||||
selector = RSN_AUTH_KEY_MGMT_PSK_OVER_802_1X;
|
||||
wpa_auth->dot11RSNAAuthenticationSuiteSelected = selector;
|
||||
|
||||
selector = RSN_CIPHER_SUITE_CCMP;
|
||||
if (data.pairwise_cipher & WPA_CIPHER_CCMP)
|
||||
selector = wpa_cipher_to_suite(WPA_PROTO_RSN,
|
||||
data.pairwise_cipher);
|
||||
if (!selector)
|
||||
selector = RSN_CIPHER_SUITE_CCMP;
|
||||
else if (data.pairwise_cipher & WPA_CIPHER_TKIP)
|
||||
selector = RSN_CIPHER_SUITE_TKIP;
|
||||
else if (data.pairwise_cipher & WPA_CIPHER_WEP104)
|
||||
selector = RSN_CIPHER_SUITE_WEP104;
|
||||
else if (data.pairwise_cipher & WPA_CIPHER_WEP40)
|
||||
selector = RSN_CIPHER_SUITE_WEP40;
|
||||
else if (data.pairwise_cipher & WPA_CIPHER_NONE)
|
||||
selector = RSN_CIPHER_SUITE_NONE;
|
||||
wpa_auth->dot11RSNAPairwiseCipherSelected = selector;
|
||||
|
||||
selector = RSN_CIPHER_SUITE_CCMP;
|
||||
if (data.group_cipher & WPA_CIPHER_CCMP)
|
||||
selector = wpa_cipher_to_suite(WPA_PROTO_RSN,
|
||||
data.group_cipher);
|
||||
if (!selector)
|
||||
selector = RSN_CIPHER_SUITE_CCMP;
|
||||
else if (data.group_cipher & WPA_CIPHER_TKIP)
|
||||
selector = RSN_CIPHER_SUITE_TKIP;
|
||||
else if (data.group_cipher & WPA_CIPHER_WEP104)
|
||||
selector = RSN_CIPHER_SUITE_WEP104;
|
||||
else if (data.group_cipher & WPA_CIPHER_WEP40)
|
||||
selector = RSN_CIPHER_SUITE_WEP40;
|
||||
else if (data.group_cipher & WPA_CIPHER_NONE)
|
||||
selector = RSN_CIPHER_SUITE_NONE;
|
||||
wpa_auth->dot11RSNAGroupCipherSelected = selector;
|
||||
} else {
|
||||
res = wpa_parse_wpa_ie_wpa(wpa_ie, wpa_ie_len, &data);
|
||||
@ -536,30 +452,16 @@ int wpa_validate_wpa_ie(struct wpa_authenticator *wpa_auth,
|
||||
selector = WPA_AUTH_KEY_MGMT_PSK_OVER_802_1X;
|
||||
wpa_auth->dot11RSNAAuthenticationSuiteSelected = selector;
|
||||
|
||||
selector = WPA_CIPHER_SUITE_TKIP;
|
||||
if (data.pairwise_cipher & WPA_CIPHER_CCMP)
|
||||
selector = WPA_CIPHER_SUITE_CCMP;
|
||||
else if (data.pairwise_cipher & WPA_CIPHER_TKIP)
|
||||
selector = WPA_CIPHER_SUITE_TKIP;
|
||||
else if (data.pairwise_cipher & WPA_CIPHER_WEP104)
|
||||
selector = WPA_CIPHER_SUITE_WEP104;
|
||||
else if (data.pairwise_cipher & WPA_CIPHER_WEP40)
|
||||
selector = WPA_CIPHER_SUITE_WEP40;
|
||||
else if (data.pairwise_cipher & WPA_CIPHER_NONE)
|
||||
selector = WPA_CIPHER_SUITE_NONE;
|
||||
selector = wpa_cipher_to_suite(WPA_PROTO_WPA,
|
||||
data.pairwise_cipher);
|
||||
if (!selector)
|
||||
selector = RSN_CIPHER_SUITE_TKIP;
|
||||
wpa_auth->dot11RSNAPairwiseCipherSelected = selector;
|
||||
|
||||
selector = WPA_CIPHER_SUITE_TKIP;
|
||||
if (data.group_cipher & WPA_CIPHER_CCMP)
|
||||
selector = WPA_CIPHER_SUITE_CCMP;
|
||||
else if (data.group_cipher & WPA_CIPHER_TKIP)
|
||||
selector = wpa_cipher_to_suite(WPA_PROTO_WPA,
|
||||
data.group_cipher);
|
||||
if (!selector)
|
||||
selector = WPA_CIPHER_SUITE_TKIP;
|
||||
else if (data.group_cipher & WPA_CIPHER_WEP104)
|
||||
selector = WPA_CIPHER_SUITE_WEP104;
|
||||
else if (data.group_cipher & WPA_CIPHER_WEP40)
|
||||
selector = WPA_CIPHER_SUITE_WEP40;
|
||||
else if (data.group_cipher & WPA_CIPHER_NONE)
|
||||
selector = WPA_CIPHER_SUITE_NONE;
|
||||
wpa_auth->dot11RSNAGroupCipherSelected = selector;
|
||||
}
|
||||
if (res) {
|
||||
@ -595,6 +497,12 @@ int wpa_validate_wpa_ie(struct wpa_authenticator *wpa_auth,
|
||||
else if (key_mgmt & WPA_KEY_MGMT_PSK_SHA256)
|
||||
sm->wpa_key_mgmt = WPA_KEY_MGMT_PSK_SHA256;
|
||||
#endif /* CONFIG_IEEE80211W */
|
||||
#ifdef CONFIG_SAE
|
||||
else if (key_mgmt & WPA_KEY_MGMT_SAE)
|
||||
sm->wpa_key_mgmt = WPA_KEY_MGMT_SAE;
|
||||
else if (key_mgmt & WPA_KEY_MGMT_FT_SAE)
|
||||
sm->wpa_key_mgmt = WPA_KEY_MGMT_FT_SAE;
|
||||
#endif /* CONFIG_SAE */
|
||||
else if (key_mgmt & WPA_KEY_MGMT_IEEE8021X)
|
||||
sm->wpa_key_mgmt = WPA_KEY_MGMT_IEEE8021X;
|
||||
else
|
||||
@ -658,6 +566,8 @@ int wpa_validate_wpa_ie(struct wpa_authenticator *wpa_auth,
|
||||
|
||||
if (ciphers & WPA_CIPHER_CCMP)
|
||||
sm->pairwise = WPA_CIPHER_CCMP;
|
||||
else if (ciphers & WPA_CIPHER_GCMP)
|
||||
sm->pairwise = WPA_CIPHER_GCMP;
|
||||
else
|
||||
sm->pairwise = WPA_CIPHER_TKIP;
|
||||
|
||||
|
@ -2,14 +2,8 @@
|
||||
* hostapd - WPA/RSN IE and KDE definitions
|
||||
* Copyright (c) 2004-2007, Jouni Malinen <j@w1.fi>
|
||||
*
|
||||
* This program is free software; you can redistribute it and/or modify
|
||||
* it under the terms of the GNU General Public License version 2 as
|
||||
* published by the Free Software Foundation.
|
||||
*
|
||||
* Alternatively, this software may be distributed under the terms of BSD
|
||||
* license.
|
||||
*
|
||||
* See README and COPYING for more details.
|
||||
* This software may be distributed under the terms of the BSD license.
|
||||
* See README for more details.
|
||||
*/
|
||||
|
||||
#ifndef WPA_AUTH_IE_H
|
||||
|
File diff suppressed because it is too large
Load Diff
@ -1,15 +1,9 @@
|
||||
/*
|
||||
* hostapd / WPS integration
|
||||
* Copyright (c) 2008-2010, Jouni Malinen <j@w1.fi>
|
||||
* Copyright (c) 2008-2012, Jouni Malinen <j@w1.fi>
|
||||
*
|
||||
* This program is free software; you can redistribute it and/or modify
|
||||
* it under the terms of the GNU General Public License version 2 as
|
||||
* published by the Free Software Foundation.
|
||||
*
|
||||
* Alternatively, this software may be distributed under the terms of BSD
|
||||
* license.
|
||||
*
|
||||
* See README and COPYING for more details.
|
||||
* This software may be distributed under the terms of the BSD license.
|
||||
* See README for more details.
|
||||
*/
|
||||
|
||||
#ifndef WPS_HOSTAPD_H
|
||||
@ -19,13 +13,14 @@
|
||||
|
||||
int hostapd_init_wps(struct hostapd_data *hapd,
|
||||
struct hostapd_bss_config *conf);
|
||||
int hostapd_init_wps_complete(struct hostapd_data *hapd);
|
||||
void hostapd_deinit_wps(struct hostapd_data *hapd);
|
||||
void hostapd_update_wps(struct hostapd_data *hapd);
|
||||
int hostapd_wps_add_pin(struct hostapd_data *hapd, const char *uuid,
|
||||
const char *pin, int timeout);
|
||||
int hostapd_wps_button_pushed(struct hostapd_data *hapd);
|
||||
int hostapd_wps_start_oob(struct hostapd_data *hapd, char *device_type,
|
||||
char *path, char *method, char *name);
|
||||
int hostapd_wps_add_pin(struct hostapd_data *hapd, const u8 *addr,
|
||||
const char *uuid, const char *pin, int timeout);
|
||||
int hostapd_wps_button_pushed(struct hostapd_data *hapd,
|
||||
const u8 *p2p_dev_addr);
|
||||
int hostapd_wps_cancel(struct hostapd_data *hapd);
|
||||
int hostapd_wps_get_mib_sta(struct hostapd_data *hapd, const u8 *addr,
|
||||
char *buf, size_t buflen);
|
||||
void hostapd_wps_ap_pin_disable(struct hostapd_data *hapd);
|
||||
@ -33,6 +28,16 @@ const char * hostapd_wps_ap_pin_random(struct hostapd_data *hapd, int timeout);
|
||||
const char * hostapd_wps_ap_pin_get(struct hostapd_data *hapd);
|
||||
int hostapd_wps_ap_pin_set(struct hostapd_data *hapd, const char *pin,
|
||||
int timeout);
|
||||
void hostapd_wps_update_ie(struct hostapd_data *hapd);
|
||||
int hostapd_wps_config_ap(struct hostapd_data *hapd, const char *ssid,
|
||||
const char *auth, const char *encr, const char *key);
|
||||
int hostapd_wps_nfc_tag_read(struct hostapd_data *hapd,
|
||||
const struct wpabuf *data);
|
||||
struct wpabuf * hostapd_wps_nfc_config_token(struct hostapd_data *hapd,
|
||||
int ndef);
|
||||
struct wpabuf * hostapd_wps_nfc_token_gen(struct hostapd_data *hapd, int ndef);
|
||||
int hostapd_wps_nfc_token_enable(struct hostapd_data *hapd);
|
||||
void hostapd_wps_nfc_token_disable(struct hostapd_data *hapd);
|
||||
|
||||
#else /* CONFIG_WPS */
|
||||
|
||||
@ -46,6 +51,11 @@ static inline void hostapd_deinit_wps(struct hostapd_data *hapd)
|
||||
{
|
||||
}
|
||||
|
||||
static inline int hostapd_init_wps_complete(struct hostapd_data *hapd)
|
||||
{
|
||||
return 0;
|
||||
}
|
||||
|
||||
static inline void hostapd_update_wps(struct hostapd_data *hapd)
|
||||
{
|
||||
}
|
||||
@ -57,7 +67,13 @@ static inline int hostapd_wps_get_mib_sta(struct hostapd_data *hapd,
|
||||
return 0;
|
||||
}
|
||||
|
||||
static inline int hostapd_wps_button_pushed(struct hostapd_data *hapd)
|
||||
static inline int hostapd_wps_button_pushed(struct hostapd_data *hapd,
|
||||
const u8 *p2p_dev_addr)
|
||||
{
|
||||
return 0;
|
||||
}
|
||||
|
||||
static inline int hostapd_wps_cancel(struct hostapd_data *hapd)
|
||||
{
|
||||
return 0;
|
||||
}
|
||||
|
@ -2,14 +2,8 @@
|
||||
* WPA Supplicant - Common definitions
|
||||
* Copyright (c) 2004-2008, Jouni Malinen <j@w1.fi>
|
||||
*
|
||||
* This program is free software; you can redistribute it and/or modify
|
||||
* it under the terms of the GNU General Public License version 2 as
|
||||
* published by the Free Software Foundation.
|
||||
*
|
||||
* Alternatively, this software may be distributed under the terms of BSD
|
||||
* license.
|
||||
*
|
||||
* See README and COPYING for more details.
|
||||
* This software may be distributed under the terms of the BSD license.
|
||||
* See README for more details.
|
||||
*/
|
||||
|
||||
#ifndef DEFS_H
|
||||
@ -32,6 +26,8 @@ typedef enum { FALSE = 0, TRUE = 1 } Boolean;
|
||||
#ifdef CONFIG_IEEE80211W
|
||||
#define WPA_CIPHER_AES_128_CMAC BIT(5)
|
||||
#endif /* CONFIG_IEEE80211W */
|
||||
#define WPA_CIPHER_GCMP BIT(6)
|
||||
#define WPA_CIPHER_SMS4 BIT(7)
|
||||
|
||||
#define WPA_KEY_MGMT_IEEE8021X BIT(0)
|
||||
#define WPA_KEY_MGMT_PSK BIT(1)
|
||||
@ -43,41 +39,73 @@ typedef enum { FALSE = 0, TRUE = 1 } Boolean;
|
||||
#define WPA_KEY_MGMT_IEEE8021X_SHA256 BIT(7)
|
||||
#define WPA_KEY_MGMT_PSK_SHA256 BIT(8)
|
||||
#define WPA_KEY_MGMT_WPS BIT(9)
|
||||
#define WPA_KEY_MGMT_SAE BIT(10)
|
||||
#define WPA_KEY_MGMT_FT_SAE BIT(11)
|
||||
#define WPA_KEY_MGMT_WAPI_PSK BIT(12)
|
||||
#define WPA_KEY_MGMT_WAPI_CERT BIT(13)
|
||||
#define WPA_KEY_MGMT_CCKM BIT(14)
|
||||
|
||||
static inline int wpa_key_mgmt_wpa_ieee8021x(int akm)
|
||||
{
|
||||
return akm == WPA_KEY_MGMT_IEEE8021X ||
|
||||
akm == WPA_KEY_MGMT_FT_IEEE8021X ||
|
||||
akm == WPA_KEY_MGMT_IEEE8021X_SHA256;
|
||||
return !!(akm & (WPA_KEY_MGMT_IEEE8021X |
|
||||
WPA_KEY_MGMT_FT_IEEE8021X |
|
||||
WPA_KEY_MGMT_CCKM |
|
||||
WPA_KEY_MGMT_IEEE8021X_SHA256));
|
||||
}
|
||||
|
||||
static inline int wpa_key_mgmt_wpa_psk(int akm)
|
||||
{
|
||||
return akm == WPA_KEY_MGMT_PSK ||
|
||||
akm == WPA_KEY_MGMT_FT_PSK ||
|
||||
akm == WPA_KEY_MGMT_PSK_SHA256;
|
||||
return !!(akm & (WPA_KEY_MGMT_PSK |
|
||||
WPA_KEY_MGMT_FT_PSK |
|
||||
WPA_KEY_MGMT_PSK_SHA256 |
|
||||
WPA_KEY_MGMT_SAE));
|
||||
}
|
||||
|
||||
static inline int wpa_key_mgmt_ft(int akm)
|
||||
{
|
||||
return akm == WPA_KEY_MGMT_FT_PSK ||
|
||||
akm == WPA_KEY_MGMT_FT_IEEE8021X;
|
||||
return !!(akm & (WPA_KEY_MGMT_FT_PSK |
|
||||
WPA_KEY_MGMT_FT_IEEE8021X |
|
||||
WPA_KEY_MGMT_FT_SAE));
|
||||
}
|
||||
|
||||
static inline int wpa_key_mgmt_sae(int akm)
|
||||
{
|
||||
return !!(akm & (WPA_KEY_MGMT_SAE |
|
||||
WPA_KEY_MGMT_FT_SAE));
|
||||
}
|
||||
|
||||
static inline int wpa_key_mgmt_sha256(int akm)
|
||||
{
|
||||
return akm == WPA_KEY_MGMT_PSK_SHA256 ||
|
||||
akm == WPA_KEY_MGMT_IEEE8021X_SHA256;
|
||||
return !!(akm & (WPA_KEY_MGMT_PSK_SHA256 |
|
||||
WPA_KEY_MGMT_IEEE8021X_SHA256));
|
||||
}
|
||||
|
||||
static inline int wpa_key_mgmt_wpa(int akm)
|
||||
{
|
||||
return wpa_key_mgmt_wpa_ieee8021x(akm) ||
|
||||
wpa_key_mgmt_wpa_psk(akm);
|
||||
}
|
||||
|
||||
static inline int wpa_key_mgmt_wpa_any(int akm)
|
||||
{
|
||||
return wpa_key_mgmt_wpa(akm) || (akm & WPA_KEY_MGMT_WPA_NONE);
|
||||
}
|
||||
|
||||
static inline int wpa_key_mgmt_cckm(int akm)
|
||||
{
|
||||
return akm == WPA_KEY_MGMT_CCKM;
|
||||
}
|
||||
|
||||
|
||||
#define WPA_PROTO_WPA BIT(0)
|
||||
#define WPA_PROTO_RSN BIT(1)
|
||||
#define WPA_PROTO_WAPI BIT(2)
|
||||
|
||||
#define WPA_AUTH_ALG_OPEN BIT(0)
|
||||
#define WPA_AUTH_ALG_SHARED BIT(1)
|
||||
#define WPA_AUTH_ALG_LEAP BIT(2)
|
||||
#define WPA_AUTH_ALG_FT BIT(3)
|
||||
#define WPA_AUTH_ALG_SAE BIT(4)
|
||||
|
||||
|
||||
enum wpa_alg {
|
||||
@ -86,7 +114,10 @@ enum wpa_alg {
|
||||
WPA_ALG_TKIP,
|
||||
WPA_ALG_CCMP,
|
||||
WPA_ALG_IGTK,
|
||||
WPA_ALG_PMK
|
||||
WPA_ALG_PMK,
|
||||
WPA_ALG_GCMP,
|
||||
WPA_ALG_SMS4,
|
||||
WPA_ALG_KRK
|
||||
};
|
||||
|
||||
/**
|
||||
@ -97,7 +128,9 @@ enum wpa_cipher {
|
||||
CIPHER_WEP40,
|
||||
CIPHER_TKIP,
|
||||
CIPHER_CCMP,
|
||||
CIPHER_WEP104
|
||||
CIPHER_WEP104,
|
||||
CIPHER_GCMP,
|
||||
CIPHER_SMS4
|
||||
};
|
||||
|
||||
/**
|
||||
@ -113,7 +146,12 @@ enum wpa_key_mgmt {
|
||||
KEY_MGMT_FT_PSK,
|
||||
KEY_MGMT_802_1X_SHA256,
|
||||
KEY_MGMT_PSK_SHA256,
|
||||
KEY_MGMT_WPS
|
||||
KEY_MGMT_WPS,
|
||||
KEY_MGMT_SAE,
|
||||
KEY_MGMT_FT_SAE,
|
||||
KEY_MGMT_WAPI_PSK,
|
||||
KEY_MGMT_WAPI_CERT,
|
||||
KEY_MGMT_CCKM
|
||||
};
|
||||
|
||||
/**
|
||||
@ -136,6 +174,15 @@ enum wpa_states {
|
||||
*/
|
||||
WPA_DISCONNECTED,
|
||||
|
||||
/**
|
||||
* WPA_INTERFACE_DISABLED - Interface disabled
|
||||
*
|
||||
* This stat eis entered if the network interface is disabled, e.g.,
|
||||
* due to rfkill. wpa_supplicant refuses any new operations that would
|
||||
* use the radio until the interface has been enabled.
|
||||
*/
|
||||
WPA_INTERFACE_DISABLED,
|
||||
|
||||
/**
|
||||
* WPA_INACTIVE - Inactive state (wpa_supplicant disabled)
|
||||
*
|
||||
@ -239,8 +286,9 @@ enum wpa_states {
|
||||
enum mfp_options {
|
||||
NO_MGMT_FRAME_PROTECTION = 0,
|
||||
MGMT_FRAME_PROTECTION_OPTIONAL = 1,
|
||||
MGMT_FRAME_PROTECTION_REQUIRED = 2
|
||||
MGMT_FRAME_PROTECTION_REQUIRED = 2,
|
||||
};
|
||||
#define MGMT_FRAME_PROTECTION_DEFAULT 3
|
||||
|
||||
/**
|
||||
* enum hostapd_hw_mode - Hardware mode
|
||||
@ -249,7 +297,25 @@ enum hostapd_hw_mode {
|
||||
HOSTAPD_MODE_IEEE80211B,
|
||||
HOSTAPD_MODE_IEEE80211G,
|
||||
HOSTAPD_MODE_IEEE80211A,
|
||||
HOSTAPD_MODE_IEEE80211AD,
|
||||
NUM_HOSTAPD_MODES
|
||||
};
|
||||
|
||||
/**
|
||||
* enum wpa_ctrl_req_type - Control interface request types
|
||||
*/
|
||||
enum wpa_ctrl_req_type {
|
||||
WPA_CTRL_REQ_UNKNOWN,
|
||||
WPA_CTRL_REQ_EAP_IDENTITY,
|
||||
WPA_CTRL_REQ_EAP_PASSWORD,
|
||||
WPA_CTRL_REQ_EAP_NEW_PASSWORD,
|
||||
WPA_CTRL_REQ_EAP_PIN,
|
||||
WPA_CTRL_REQ_EAP_OTP,
|
||||
WPA_CTRL_REQ_EAP_PASSPHRASE,
|
||||
NUM_WPA_CTRL_REQS
|
||||
};
|
||||
|
||||
/* Maximum number of EAP methods to store for EAP server user information */
|
||||
#define EAP_MAX_METHODS 8
|
||||
|
||||
#endif /* DEFS_H */
|
||||
|
@ -2,14 +2,8 @@
|
||||
* EAPOL definitions shared between hostapd and wpa_supplicant
|
||||
* Copyright (c) 2002-2007, Jouni Malinen <j@w1.fi>
|
||||
*
|
||||
* This program is free software; you can redistribute it and/or modify
|
||||
* it under the terms of the GNU General Public License version 2 as
|
||||
* published by the Free Software Foundation.
|
||||
*
|
||||
* Alternatively, this software may be distributed under the terms of BSD
|
||||
* license.
|
||||
*
|
||||
* See README and COPYING for more details.
|
||||
* This software may be distributed under the terms of the BSD license.
|
||||
* See README for more details.
|
||||
*/
|
||||
|
||||
#ifndef EAPOL_COMMON_H
|
||||
@ -44,4 +38,44 @@ enum { IEEE802_1X_TYPE_EAP_PACKET = 0,
|
||||
enum { EAPOL_KEY_TYPE_RC4 = 1, EAPOL_KEY_TYPE_RSN = 2,
|
||||
EAPOL_KEY_TYPE_WPA = 254 };
|
||||
|
||||
|
||||
#define IEEE8021X_REPLAY_COUNTER_LEN 8
|
||||
#define IEEE8021X_KEY_SIGN_LEN 16
|
||||
#define IEEE8021X_KEY_IV_LEN 16
|
||||
|
||||
#define IEEE8021X_KEY_INDEX_FLAG 0x80
|
||||
#define IEEE8021X_KEY_INDEX_MASK 0x03
|
||||
|
||||
#ifdef _MSC_VER
|
||||
#pragma pack(push, 1)
|
||||
#endif /* _MSC_VER */
|
||||
|
||||
struct ieee802_1x_eapol_key {
|
||||
u8 type;
|
||||
/* Note: key_length is unaligned */
|
||||
u8 key_length[2];
|
||||
/* does not repeat within the life of the keying material used to
|
||||
* encrypt the Key field; 64-bit NTP timestamp MAY be used here */
|
||||
u8 replay_counter[IEEE8021X_REPLAY_COUNTER_LEN];
|
||||
u8 key_iv[IEEE8021X_KEY_IV_LEN]; /* cryptographically random number */
|
||||
u8 key_index; /* key flag in the most significant bit:
|
||||
* 0 = broadcast (default key),
|
||||
* 1 = unicast (key mapping key); key index is in the
|
||||
* 7 least significant bits */
|
||||
/* HMAC-MD5 message integrity check computed with MS-MPPE-Send-Key as
|
||||
* the key */
|
||||
u8 key_signature[IEEE8021X_KEY_SIGN_LEN];
|
||||
|
||||
/* followed by key: if packet body length = 44 + key length, then the
|
||||
* key field (of key_length bytes) contains the key in encrypted form;
|
||||
* if packet body length = 44, key field is absent and key_length
|
||||
* represents the number of least significant octets from
|
||||
* MS-MPPE-Send-Key attribute to be used as the keying material;
|
||||
* RC4 key used in encryption = Key-IV + MS-MPPE-Recv-Key */
|
||||
} STRUCT_PACKED;
|
||||
|
||||
#ifdef _MSC_VER
|
||||
#pragma pack(pop)
|
||||
#endif /* _MSC_VER */
|
||||
|
||||
#endif /* EAPOL_COMMON_H */
|
||||
|
273
src/common/gas.c
Normal file
273
src/common/gas.c
Normal file
@ -0,0 +1,273 @@
|
||||
/*
|
||||
* Generic advertisement service (GAS) (IEEE 802.11u)
|
||||
* Copyright (c) 2009, Atheros Communications
|
||||
* Copyright (c) 2011-2012, Qualcomm Atheros
|
||||
*
|
||||
* This software may be distributed under the terms of the BSD license.
|
||||
* See README for more details.
|
||||
*/
|
||||
|
||||
#include "includes.h"
|
||||
|
||||
#include "common.h"
|
||||
#include "ieee802_11_defs.h"
|
||||
#include "gas.h"
|
||||
|
||||
|
||||
static struct wpabuf *
|
||||
gas_build_req(u8 action, u8 dialog_token, size_t size)
|
||||
{
|
||||
struct wpabuf *buf;
|
||||
|
||||
buf = wpabuf_alloc(100 + size);
|
||||
if (buf == NULL)
|
||||
return NULL;
|
||||
|
||||
wpabuf_put_u8(buf, WLAN_ACTION_PUBLIC);
|
||||
wpabuf_put_u8(buf, action);
|
||||
wpabuf_put_u8(buf, dialog_token);
|
||||
|
||||
return buf;
|
||||
}
|
||||
|
||||
|
||||
struct wpabuf * gas_build_initial_req(u8 dialog_token, size_t size)
|
||||
{
|
||||
return gas_build_req(WLAN_PA_GAS_INITIAL_REQ, dialog_token,
|
||||
size);
|
||||
}
|
||||
|
||||
|
||||
struct wpabuf * gas_build_comeback_req(u8 dialog_token)
|
||||
{
|
||||
return gas_build_req(WLAN_PA_GAS_COMEBACK_REQ, dialog_token, 0);
|
||||
}
|
||||
|
||||
|
||||
static struct wpabuf *
|
||||
gas_build_resp(u8 action, u8 dialog_token, u16 status_code, u8 frag_id,
|
||||
u8 more, u16 comeback_delay, size_t size)
|
||||
{
|
||||
struct wpabuf *buf;
|
||||
|
||||
buf = wpabuf_alloc(100 + size);
|
||||
if (buf == NULL)
|
||||
return NULL;
|
||||
|
||||
wpabuf_put_u8(buf, WLAN_ACTION_PUBLIC);
|
||||
wpabuf_put_u8(buf, action);
|
||||
wpabuf_put_u8(buf, dialog_token);
|
||||
wpabuf_put_le16(buf, status_code);
|
||||
if (action == WLAN_PA_GAS_COMEBACK_RESP)
|
||||
wpabuf_put_u8(buf, frag_id | (more ? 0x80 : 0));
|
||||
wpabuf_put_le16(buf, comeback_delay);
|
||||
|
||||
return buf;
|
||||
}
|
||||
|
||||
|
||||
struct wpabuf *
|
||||
gas_build_initial_resp(u8 dialog_token, u16 status_code, u16 comeback_delay,
|
||||
size_t size)
|
||||
{
|
||||
return gas_build_resp(WLAN_PA_GAS_INITIAL_RESP, dialog_token,
|
||||
status_code, 0, 0, comeback_delay, size);
|
||||
}
|
||||
|
||||
|
||||
static struct wpabuf *
|
||||
gas_build_comeback_resp(u8 dialog_token, u16 status_code, u8 frag_id, u8 more,
|
||||
u16 comeback_delay, size_t size)
|
||||
{
|
||||
return gas_build_resp(WLAN_PA_GAS_COMEBACK_RESP, dialog_token,
|
||||
status_code, frag_id, more, comeback_delay,
|
||||
size);
|
||||
}
|
||||
|
||||
|
||||
/**
|
||||
* gas_add_adv_proto_anqp - Add an Advertisement Protocol element
|
||||
* @buf: Buffer to which the element is added
|
||||
* @query_resp_len_limit: Query Response Length Limit in units of 256 octets
|
||||
* @pame_bi: Pre-Association Message Exchange BSSID Independent (0/1)
|
||||
*
|
||||
*
|
||||
* @query_resp_len_limit is 0 for request and 1-0x7f for response. 0x7f means
|
||||
* that the maximum limit is determined by the maximum allowable number of
|
||||
* fragments in the GAS Query Response Fragment ID.
|
||||
*/
|
||||
static void gas_add_adv_proto_anqp(struct wpabuf *buf, u8 query_resp_len_limit,
|
||||
u8 pame_bi)
|
||||
{
|
||||
/* Advertisement Protocol IE */
|
||||
wpabuf_put_u8(buf, WLAN_EID_ADV_PROTO);
|
||||
wpabuf_put_u8(buf, 2); /* Length */
|
||||
wpabuf_put_u8(buf, (query_resp_len_limit & 0x7f) |
|
||||
(pame_bi ? 0x80 : 0));
|
||||
/* Advertisement Protocol */
|
||||
wpabuf_put_u8(buf, ACCESS_NETWORK_QUERY_PROTOCOL);
|
||||
}
|
||||
|
||||
|
||||
struct wpabuf * gas_anqp_build_initial_req(u8 dialog_token, size_t size)
|
||||
{
|
||||
struct wpabuf *buf;
|
||||
|
||||
buf = gas_build_initial_req(dialog_token, 4 + size);
|
||||
if (buf == NULL)
|
||||
return NULL;
|
||||
|
||||
gas_add_adv_proto_anqp(buf, 0, 0);
|
||||
|
||||
wpabuf_put(buf, 2); /* Query Request Length to be filled */
|
||||
|
||||
return buf;
|
||||
}
|
||||
|
||||
|
||||
struct wpabuf * gas_anqp_build_initial_resp(u8 dialog_token, u16 status_code,
|
||||
u16 comeback_delay, size_t size)
|
||||
{
|
||||
struct wpabuf *buf;
|
||||
|
||||
buf = gas_build_initial_resp(dialog_token, status_code, comeback_delay,
|
||||
4 + size);
|
||||
if (buf == NULL)
|
||||
return NULL;
|
||||
|
||||
gas_add_adv_proto_anqp(buf, 0x7f, 0);
|
||||
|
||||
wpabuf_put(buf, 2); /* Query Response Length to be filled */
|
||||
|
||||
return buf;
|
||||
}
|
||||
|
||||
|
||||
struct wpabuf * gas_anqp_build_initial_resp_buf(u8 dialog_token,
|
||||
u16 status_code,
|
||||
u16 comeback_delay,
|
||||
struct wpabuf *payload)
|
||||
{
|
||||
struct wpabuf *buf;
|
||||
|
||||
buf = gas_anqp_build_initial_resp(dialog_token, status_code,
|
||||
comeback_delay,
|
||||
payload ? wpabuf_len(payload) : 0);
|
||||
if (buf == NULL)
|
||||
return NULL;
|
||||
|
||||
if (payload)
|
||||
wpabuf_put_buf(buf, payload);
|
||||
|
||||
gas_anqp_set_len(buf);
|
||||
|
||||
return buf;
|
||||
}
|
||||
|
||||
|
||||
struct wpabuf * gas_anqp_build_comeback_resp(u8 dialog_token, u16 status_code,
|
||||
u8 frag_id, u8 more,
|
||||
u16 comeback_delay, size_t size)
|
||||
{
|
||||
struct wpabuf *buf;
|
||||
|
||||
buf = gas_build_comeback_resp(dialog_token, status_code,
|
||||
frag_id, more, comeback_delay, 4 + size);
|
||||
if (buf == NULL)
|
||||
return NULL;
|
||||
|
||||
gas_add_adv_proto_anqp(buf, 0x7f, 0);
|
||||
|
||||
wpabuf_put(buf, 2); /* Query Response Length to be filled */
|
||||
|
||||
return buf;
|
||||
}
|
||||
|
||||
|
||||
struct wpabuf * gas_anqp_build_comeback_resp_buf(u8 dialog_token,
|
||||
u16 status_code,
|
||||
u8 frag_id, u8 more,
|
||||
u16 comeback_delay,
|
||||
struct wpabuf *payload)
|
||||
{
|
||||
struct wpabuf *buf;
|
||||
|
||||
buf = gas_anqp_build_comeback_resp(dialog_token, status_code, frag_id,
|
||||
more, comeback_delay,
|
||||
payload ? wpabuf_len(payload) : 0);
|
||||
if (buf == NULL)
|
||||
return NULL;
|
||||
|
||||
if (payload)
|
||||
wpabuf_put_buf(buf, payload);
|
||||
|
||||
gas_anqp_set_len(buf);
|
||||
|
||||
return buf;
|
||||
}
|
||||
|
||||
|
||||
/**
|
||||
* gas_anqp_set_len - Set Query Request/Response Length
|
||||
* @buf: GAS message
|
||||
*
|
||||
* This function is used to update the Query Request/Response Length field once
|
||||
* the payload has been filled.
|
||||
*/
|
||||
void gas_anqp_set_len(struct wpabuf *buf)
|
||||
{
|
||||
u8 action;
|
||||
size_t offset;
|
||||
u8 *len;
|
||||
|
||||
if (buf == NULL || wpabuf_len(buf) < 2)
|
||||
return;
|
||||
|
||||
action = *(wpabuf_head_u8(buf) + 1);
|
||||
switch (action) {
|
||||
case WLAN_PA_GAS_INITIAL_REQ:
|
||||
offset = 3 + 4;
|
||||
break;
|
||||
case WLAN_PA_GAS_INITIAL_RESP:
|
||||
offset = 7 + 4;
|
||||
break;
|
||||
case WLAN_PA_GAS_COMEBACK_RESP:
|
||||
offset = 8 + 4;
|
||||
break;
|
||||
default:
|
||||
return;
|
||||
}
|
||||
|
||||
if (wpabuf_len(buf) < offset + 2)
|
||||
return;
|
||||
|
||||
len = wpabuf_mhead_u8(buf) + offset;
|
||||
WPA_PUT_LE16(len, (u8 *) wpabuf_put(buf, 0) - len - 2);
|
||||
}
|
||||
|
||||
|
||||
/**
|
||||
* gas_anqp_add_element - Add ANQP element header
|
||||
* @buf: GAS message
|
||||
* @info_id: ANQP Info ID
|
||||
* Returns: Pointer to the Length field for gas_anqp_set_element_len()
|
||||
*/
|
||||
u8 * gas_anqp_add_element(struct wpabuf *buf, u16 info_id)
|
||||
{
|
||||
wpabuf_put_le16(buf, info_id);
|
||||
return wpabuf_put(buf, 2); /* Length to be filled */
|
||||
}
|
||||
|
||||
|
||||
/**
|
||||
* gas_anqp_set_element_len - Update ANQP element Length field
|
||||
* @buf: GAS message
|
||||
* @len_pos: Length field position from gas_anqp_add_element()
|
||||
*
|
||||
* This function is called after the ANQP element payload has been added to the
|
||||
* buffer.
|
||||
*/
|
||||
void gas_anqp_set_element_len(struct wpabuf *buf, u8 *len_pos)
|
||||
{
|
||||
WPA_PUT_LE16(len_pos, (u8 *) wpabuf_put(buf, 0) - len_pos - 2);
|
||||
}
|
37
src/common/gas.h
Normal file
37
src/common/gas.h
Normal file
@ -0,0 +1,37 @@
|
||||
/*
|
||||
* Generic advertisement service (GAS) (IEEE 802.11u)
|
||||
* Copyright (c) 2009, Atheros Communications
|
||||
* Copyright (c) 2011-2012, Qualcomm Atheros
|
||||
*
|
||||
* This software may be distributed under the terms of the BSD license.
|
||||
* See README for more details.
|
||||
*/
|
||||
|
||||
#ifndef GAS_H
|
||||
#define GAS_H
|
||||
|
||||
struct wpabuf * gas_build_initial_req(u8 dialog_token, size_t size);
|
||||
struct wpabuf * gas_build_comeback_req(u8 dialog_token);
|
||||
struct wpabuf * gas_build_initial_resp(u8 dialog_token, u16 status_code,
|
||||
u16 comeback_delay, size_t size);
|
||||
struct wpabuf * gas_anqp_build_initial_req(u8 dialog_token, size_t size);
|
||||
struct wpabuf * gas_anqp_build_initial_resp(u8 dialog_token, u16 status_code,
|
||||
u16 comeback_delay, size_t size);
|
||||
struct wpabuf * gas_anqp_build_initial_resp_buf(u8 dialog_token,
|
||||
u16 status_code,
|
||||
u16 comeback_delay,
|
||||
struct wpabuf *payload);
|
||||
struct wpabuf * gas_anqp_build_comeback_resp(u8 dialog_token, u16 status_code,
|
||||
u8 frag_id, u8 more,
|
||||
u16 comeback_delay, size_t size);
|
||||
struct wpabuf * gas_anqp_build_comeback_resp_buf(u8 dialog_token,
|
||||
u16 status_code,
|
||||
u8 frag_id, u8 more,
|
||||
u16 comeback_delay,
|
||||
struct wpabuf *payload);
|
||||
void gas_anqp_set_len(struct wpabuf *buf);
|
||||
|
||||
u8 * gas_anqp_add_element(struct wpabuf *buf, u16 info_id);
|
||||
void gas_anqp_set_element_len(struct wpabuf *buf, u8 *len_pos);
|
||||
|
||||
#endif /* GAS_H */
|
@ -1,15 +1,9 @@
|
||||
/*
|
||||
* IEEE 802.11 Common routines
|
||||
* Copyright (c) 2002-2009, Jouni Malinen <j@w1.fi>
|
||||
* Copyright (c) 2002-2012, Jouni Malinen <j@w1.fi>
|
||||
*
|
||||
* This program is free software; you can redistribute it and/or modify
|
||||
* it under the terms of the GNU General Public License version 2 as
|
||||
* published by the Free Software Foundation.
|
||||
*
|
||||
* Alternatively, this software may be distributed under the terms of BSD
|
||||
* license.
|
||||
*
|
||||
* See README and COPYING for more details.
|
||||
* This software may be distributed under the terms of the BSD license.
|
||||
* See README for more details.
|
||||
*/
|
||||
|
||||
#include "includes.h"
|
||||
@ -75,7 +69,7 @@ static int ieee802_11_parse_vendor_specific(const u8 *pos, size_t elen,
|
||||
elems->wmm_tspec_len = elen;
|
||||
break;
|
||||
default:
|
||||
wpa_printf(MSG_MSGDUMP, "unknown WMM "
|
||||
wpa_printf(MSG_EXCESSIVE, "unknown WMM "
|
||||
"information element ignored "
|
||||
"(subtype=%d len=%lu)",
|
||||
pos[4], (unsigned long) elen);
|
||||
@ -88,7 +82,33 @@ static int ieee802_11_parse_vendor_specific(const u8 *pos, size_t elen,
|
||||
elems->wps_ie_len = elen;
|
||||
break;
|
||||
default:
|
||||
wpa_printf(MSG_MSGDUMP, "Unknown Microsoft "
|
||||
wpa_printf(MSG_EXCESSIVE, "Unknown Microsoft "
|
||||
"information element ignored "
|
||||
"(type=%d len=%lu)",
|
||||
pos[3], (unsigned long) elen);
|
||||
return -1;
|
||||
}
|
||||
break;
|
||||
|
||||
case OUI_WFA:
|
||||
switch (pos[3]) {
|
||||
case P2P_OUI_TYPE:
|
||||
/* Wi-Fi Alliance - P2P IE */
|
||||
elems->p2p = pos;
|
||||
elems->p2p_len = elen;
|
||||
break;
|
||||
case WFD_OUI_TYPE:
|
||||
/* Wi-Fi Alliance - WFD IE */
|
||||
elems->wfd = pos;
|
||||
elems->wfd_len = elen;
|
||||
break;
|
||||
case HS20_INDICATION_OUI_TYPE:
|
||||
/* Hotspot 2.0 */
|
||||
elems->hs20 = pos;
|
||||
elems->hs20_len = elen;
|
||||
break;
|
||||
default:
|
||||
wpa_printf(MSG_MSGDUMP, "Unknown WFA "
|
||||
"information element ignored "
|
||||
"(type=%d len=%lu)\n",
|
||||
pos[3], (unsigned long) elen);
|
||||
@ -103,18 +123,18 @@ static int ieee802_11_parse_vendor_specific(const u8 *pos, size_t elen,
|
||||
elems->vendor_ht_cap_len = elen;
|
||||
break;
|
||||
default:
|
||||
wpa_printf(MSG_MSGDUMP, "Unknown Broadcom "
|
||||
wpa_printf(MSG_EXCESSIVE, "Unknown Broadcom "
|
||||
"information element ignored "
|
||||
"(type=%d len=%lu)\n",
|
||||
"(type=%d len=%lu)",
|
||||
pos[3], (unsigned long) elen);
|
||||
return -1;
|
||||
}
|
||||
break;
|
||||
|
||||
default:
|
||||
wpa_printf(MSG_MSGDUMP, "unknown vendor specific information "
|
||||
"element ignored (vendor OUI %02x:%02x:%02x "
|
||||
"len=%lu)",
|
||||
wpa_printf(MSG_EXCESSIVE, "unknown vendor specific "
|
||||
"information element ignored (vendor OUI "
|
||||
"%02x:%02x:%02x len=%lu)",
|
||||
pos[0], pos[1], pos[2], (unsigned long) elen);
|
||||
return -1;
|
||||
}
|
||||
@ -238,6 +258,36 @@ ParseRes ieee802_11_parse_elems(const u8 *start, size_t len,
|
||||
elems->ht_operation = pos;
|
||||
elems->ht_operation_len = elen;
|
||||
break;
|
||||
case WLAN_EID_VHT_CAP:
|
||||
elems->vht_capabilities = pos;
|
||||
elems->vht_capabilities_len = elen;
|
||||
break;
|
||||
case WLAN_EID_VHT_OPERATION:
|
||||
elems->vht_operation = pos;
|
||||
elems->vht_operation_len = elen;
|
||||
break;
|
||||
case WLAN_EID_LINK_ID:
|
||||
if (elen < 18)
|
||||
break;
|
||||
elems->link_id = pos;
|
||||
break;
|
||||
case WLAN_EID_INTERWORKING:
|
||||
elems->interworking = pos;
|
||||
elems->interworking_len = elen;
|
||||
break;
|
||||
case WLAN_EID_EXT_CAPAB:
|
||||
elems->ext_capab = pos;
|
||||
elems->ext_capab_len = elen;
|
||||
break;
|
||||
case WLAN_EID_BSS_MAX_IDLE_PERIOD:
|
||||
if (elen < 3)
|
||||
break;
|
||||
elems->bss_max_idle_period = pos;
|
||||
break;
|
||||
case WLAN_EID_SSID_LIST:
|
||||
elems->ssid_list = pos;
|
||||
elems->ssid_list_len = elen;
|
||||
break;
|
||||
default:
|
||||
unknown++;
|
||||
if (!show_errors)
|
||||
@ -324,3 +374,115 @@ struct wpabuf * ieee802_11_vendor_ie_concat(const u8 *ies, size_t ies_len,
|
||||
|
||||
return buf;
|
||||
}
|
||||
|
||||
|
||||
const u8 * get_hdr_bssid(const struct ieee80211_hdr *hdr, size_t len)
|
||||
{
|
||||
u16 fc, type, stype;
|
||||
|
||||
/*
|
||||
* PS-Poll frames are 16 bytes. All other frames are
|
||||
* 24 bytes or longer.
|
||||
*/
|
||||
if (len < 16)
|
||||
return NULL;
|
||||
|
||||
fc = le_to_host16(hdr->frame_control);
|
||||
type = WLAN_FC_GET_TYPE(fc);
|
||||
stype = WLAN_FC_GET_STYPE(fc);
|
||||
|
||||
switch (type) {
|
||||
case WLAN_FC_TYPE_DATA:
|
||||
if (len < 24)
|
||||
return NULL;
|
||||
switch (fc & (WLAN_FC_FROMDS | WLAN_FC_TODS)) {
|
||||
case WLAN_FC_FROMDS | WLAN_FC_TODS:
|
||||
case WLAN_FC_TODS:
|
||||
return hdr->addr1;
|
||||
case WLAN_FC_FROMDS:
|
||||
return hdr->addr2;
|
||||
default:
|
||||
return NULL;
|
||||
}
|
||||
case WLAN_FC_TYPE_CTRL:
|
||||
if (stype != WLAN_FC_STYPE_PSPOLL)
|
||||
return NULL;
|
||||
return hdr->addr1;
|
||||
case WLAN_FC_TYPE_MGMT:
|
||||
return hdr->addr3;
|
||||
default:
|
||||
return NULL;
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
int hostapd_config_wmm_ac(struct hostapd_wmm_ac_params wmm_ac_params[],
|
||||
const char *name, const char *val)
|
||||
{
|
||||
int num, v;
|
||||
const char *pos;
|
||||
struct hostapd_wmm_ac_params *ac;
|
||||
|
||||
/* skip 'wme_ac_' or 'wmm_ac_' prefix */
|
||||
pos = name + 7;
|
||||
if (os_strncmp(pos, "be_", 3) == 0) {
|
||||
num = 0;
|
||||
pos += 3;
|
||||
} else if (os_strncmp(pos, "bk_", 3) == 0) {
|
||||
num = 1;
|
||||
pos += 3;
|
||||
} else if (os_strncmp(pos, "vi_", 3) == 0) {
|
||||
num = 2;
|
||||
pos += 3;
|
||||
} else if (os_strncmp(pos, "vo_", 3) == 0) {
|
||||
num = 3;
|
||||
pos += 3;
|
||||
} else {
|
||||
wpa_printf(MSG_ERROR, "Unknown WMM name '%s'", pos);
|
||||
return -1;
|
||||
}
|
||||
|
||||
ac = &wmm_ac_params[num];
|
||||
|
||||
if (os_strcmp(pos, "aifs") == 0) {
|
||||
v = atoi(val);
|
||||
if (v < 1 || v > 255) {
|
||||
wpa_printf(MSG_ERROR, "Invalid AIFS value %d", v);
|
||||
return -1;
|
||||
}
|
||||
ac->aifs = v;
|
||||
} else if (os_strcmp(pos, "cwmin") == 0) {
|
||||
v = atoi(val);
|
||||
if (v < 0 || v > 12) {
|
||||
wpa_printf(MSG_ERROR, "Invalid cwMin value %d", v);
|
||||
return -1;
|
||||
}
|
||||
ac->cwmin = v;
|
||||
} else if (os_strcmp(pos, "cwmax") == 0) {
|
||||
v = atoi(val);
|
||||
if (v < 0 || v > 12) {
|
||||
wpa_printf(MSG_ERROR, "Invalid cwMax value %d", v);
|
||||
return -1;
|
||||
}
|
||||
ac->cwmax = v;
|
||||
} else if (os_strcmp(pos, "txop_limit") == 0) {
|
||||
v = atoi(val);
|
||||
if (v < 0 || v > 0xffff) {
|
||||
wpa_printf(MSG_ERROR, "Invalid txop value %d", v);
|
||||
return -1;
|
||||
}
|
||||
ac->txop_limit = v;
|
||||
} else if (os_strcmp(pos, "acm") == 0) {
|
||||
v = atoi(val);
|
||||
if (v < 0 || v > 1) {
|
||||
wpa_printf(MSG_ERROR, "Invalid acm value %d", v);
|
||||
return -1;
|
||||
}
|
||||
ac->admission_control_mandatory = v;
|
||||
} else {
|
||||
wpa_printf(MSG_ERROR, "Unknown wmm_ac_ field '%s'", pos);
|
||||
return -1;
|
||||
}
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
@ -1,15 +1,9 @@
|
||||
/*
|
||||
* IEEE 802.11 Common routines
|
||||
* Copyright (c) 2002-2009, Jouni Malinen <j@w1.fi>
|
||||
* Copyright (c) 2002-2012, Jouni Malinen <j@w1.fi>
|
||||
*
|
||||
* This program is free software; you can redistribute it and/or modify
|
||||
* it under the terms of the GNU General Public License version 2 as
|
||||
* published by the Free Software Foundation.
|
||||
*
|
||||
* Alternatively, this software may be distributed under the terms of BSD
|
||||
* license.
|
||||
*
|
||||
* See README and COPYING for more details.
|
||||
* This software may be distributed under the terms of the BSD license.
|
||||
* See README for more details.
|
||||
*/
|
||||
|
||||
#ifndef IEEE802_11_COMMON_H
|
||||
@ -39,7 +33,17 @@ struct ieee802_11_elems {
|
||||
const u8 *timeout_int;
|
||||
const u8 *ht_capabilities;
|
||||
const u8 *ht_operation;
|
||||
const u8 *vht_capabilities;
|
||||
const u8 *vht_operation;
|
||||
const u8 *vendor_ht_cap;
|
||||
const u8 *p2p;
|
||||
const u8 *wfd;
|
||||
const u8 *link_id;
|
||||
const u8 *interworking;
|
||||
const u8 *hs20;
|
||||
const u8 *ext_capab;
|
||||
const u8 *bss_max_idle_period;
|
||||
const u8 *ssid_list;
|
||||
|
||||
u8 ssid_len;
|
||||
u8 supp_rates_len;
|
||||
@ -63,7 +67,15 @@ struct ieee802_11_elems {
|
||||
u8 timeout_int_len;
|
||||
u8 ht_capabilities_len;
|
||||
u8 ht_operation_len;
|
||||
u8 vht_capabilities_len;
|
||||
u8 vht_operation_len;
|
||||
u8 vendor_ht_cap_len;
|
||||
u8 p2p_len;
|
||||
u8 wfd_len;
|
||||
u8 interworking_len;
|
||||
u8 hs20_len;
|
||||
u8 ext_capab_len;
|
||||
u8 ssid_list_len;
|
||||
};
|
||||
|
||||
typedef enum { ParseOK = 0, ParseUnknown = 1, ParseFailed = -1 } ParseRes;
|
||||
@ -74,5 +86,18 @@ ParseRes ieee802_11_parse_elems(const u8 *start, size_t len,
|
||||
int ieee802_11_ie_count(const u8 *ies, size_t ies_len);
|
||||
struct wpabuf * ieee802_11_vendor_ie_concat(const u8 *ies, size_t ies_len,
|
||||
u32 oui_type);
|
||||
struct ieee80211_hdr;
|
||||
const u8 * get_hdr_bssid(const struct ieee80211_hdr *hdr, size_t len);
|
||||
|
||||
struct hostapd_wmm_ac_params {
|
||||
int cwmin;
|
||||
int cwmax;
|
||||
int aifs;
|
||||
int txop_limit; /* in units of 32us */
|
||||
int admission_control_mandatory;
|
||||
};
|
||||
|
||||
int hostapd_config_wmm_ac(struct hostapd_wmm_ac_params wmm_ac_params[],
|
||||
const char *name, const char *val);
|
||||
|
||||
#endif /* IEEE802_11_COMMON_H */
|
||||
|
@ -3,14 +3,8 @@
|
||||
* Copyright (c) 2002-2009, Jouni Malinen <j@w1.fi>
|
||||
* Copyright (c) 2007-2008 Intel Corporation
|
||||
*
|
||||
* This program is free software; you can redistribute it and/or modify
|
||||
* it under the terms of the GNU General Public License version 2 as
|
||||
* published by the Free Software Foundation.
|
||||
*
|
||||
* Alternatively, this software may be distributed under the terms of BSD
|
||||
* license.
|
||||
*
|
||||
* See README and COPYING for more details.
|
||||
* This software may be distributed under the terms of the BSD license.
|
||||
* See README for more details.
|
||||
*/
|
||||
|
||||
#ifndef IEEE802_11_DEFS_H
|
||||
@ -71,11 +65,18 @@
|
||||
#define WLAN_FC_STYPE_CFPOLL 6
|
||||
#define WLAN_FC_STYPE_CFACKPOLL 7
|
||||
#define WLAN_FC_STYPE_QOS_DATA 8
|
||||
#define WLAN_FC_STYPE_QOS_DATA_CFACK 9
|
||||
#define WLAN_FC_STYPE_QOS_DATA_CFPOLL 10
|
||||
#define WLAN_FC_STYPE_QOS_DATA_CFACKPOLL 11
|
||||
#define WLAN_FC_STYPE_QOS_NULL 12
|
||||
#define WLAN_FC_STYPE_QOS_CFPOLL 14
|
||||
#define WLAN_FC_STYPE_QOS_CFACKPOLL 15
|
||||
|
||||
/* Authentication algorithms */
|
||||
#define WLAN_AUTH_OPEN 0
|
||||
#define WLAN_AUTH_SHARED_KEY 1
|
||||
#define WLAN_AUTH_FT 2
|
||||
#define WLAN_AUTH_SAE 3
|
||||
#define WLAN_AUTH_LEAP 128
|
||||
|
||||
#define WLAN_AUTH_CHALLENGE_LEN 128
|
||||
@ -95,6 +96,11 @@
|
||||
/* Status codes (IEEE 802.11-2007, 7.3.1.9, Table 7-23) */
|
||||
#define WLAN_STATUS_SUCCESS 0
|
||||
#define WLAN_STATUS_UNSPECIFIED_FAILURE 1
|
||||
#define WLAN_STATUS_TDLS_WAKEUP_ALTERNATE 2
|
||||
#define WLAN_STATUS_TDLS_WAKEUP_REJECT 3
|
||||
#define WLAN_STATUS_SECURITY_DISABLED 5
|
||||
#define WLAN_STATUS_UNACCEPTABLE_LIFETIME 6
|
||||
#define WLAN_STATUS_NOT_IN_SAME_BSS 7
|
||||
#define WLAN_STATUS_CAPS_UNSUPPORTED 10
|
||||
#define WLAN_STATUS_REASSOC_NO_ASSOC 11
|
||||
#define WLAN_STATUS_ASSOC_DENIED_UNSPEC 12
|
||||
@ -114,9 +120,10 @@
|
||||
#define WLAN_STATUS_SUPPORTED_CHANNEL_NOT_VALID 24
|
||||
/* IEEE 802.11g */
|
||||
#define WLAN_STATUS_ASSOC_DENIED_NO_SHORT_SLOT_TIME 25
|
||||
#define WLAN_STATUS_ASSOC_DENIED_NO_ER_PBCC 26
|
||||
#define WLAN_STATUS_ASSOC_DENIED_NO_DSSS_OFDM 27
|
||||
#define WLAN_STATUS_ASSOC_DENIED_NO_DSSS_OFDM 26
|
||||
#define WLAN_STATUS_ASSOC_DENIED_NO_HT 27
|
||||
#define WLAN_STATUS_R0KH_UNREACHABLE 28
|
||||
#define WLAN_STATUS_ASSOC_DENIED_NO_PCO 29
|
||||
/* IEEE 802.11w */
|
||||
#define WLAN_STATUS_ASSOC_REJECTED_TEMPORARILY 30
|
||||
#define WLAN_STATUS_ROBUST_MGMT_FRAME_POLICY_VIOLATION 31
|
||||
@ -141,6 +148,19 @@
|
||||
#define WLAN_STATUS_INVALID_PMKID 53
|
||||
#define WLAN_STATUS_INVALID_MDIE 54
|
||||
#define WLAN_STATUS_INVALID_FTIE 55
|
||||
#define WLAN_STATUS_GAS_ADV_PROTO_NOT_SUPPORTED 59
|
||||
#define WLAN_STATUS_NO_OUTSTANDING_GAS_REQ 60
|
||||
#define WLAN_STATUS_GAS_RESP_NOT_RECEIVED 61
|
||||
#define WLAN_STATUS_STA_TIMED_OUT_WAITING_FOR_GAS_RESP 62
|
||||
#define WLAN_STATUS_GAS_RESP_LARGER_THAN_LIMIT 63
|
||||
#define WLAN_STATUS_REQ_REFUSED_HOME 64
|
||||
#define WLAN_STATUS_ADV_SRV_UNREACHABLE 65
|
||||
#define WLAN_STATUS_REQ_REFUSED_SSPN 67
|
||||
#define WLAN_STATUS_REQ_REFUSED_UNAUTH_ACCESS 68
|
||||
#define WLAN_STATUS_INVALID_RSNIE 72
|
||||
#define WLAN_STATUS_ANTI_CLOGGING_TOKEN_REQ 76
|
||||
#define WLAN_STATUS_FINITE_CYCLIC_GROUP_NOT_SUPPORTED 77
|
||||
#define WLAN_STATUS_TRANSMISSION_FAILURE 79
|
||||
|
||||
/* Reason codes (IEEE 802.11-2007, 7.3.1.7, Table 7-22) */
|
||||
#define WLAN_REASON_UNSPECIFIED 1
|
||||
@ -168,6 +188,10 @@
|
||||
#define WLAN_REASON_INVALID_RSN_IE_CAPAB 22
|
||||
#define WLAN_REASON_IEEE_802_1X_AUTH_FAILED 23
|
||||
#define WLAN_REASON_CIPHER_SUITE_REJECTED 24
|
||||
#define WLAN_REASON_TDLS_TEARDOWN_UNREACHABLE 25
|
||||
#define WLAN_REASON_TDLS_TEARDOWN_UNSPECIFIED 26
|
||||
/* IEEE 802.11e */
|
||||
#define WLAN_REASON_DISASSOC_LOW_ACK 34
|
||||
|
||||
|
||||
/* Information Element IDs */
|
||||
@ -202,10 +226,33 @@
|
||||
#define WLAN_EID_RIC_DATA 57
|
||||
#define WLAN_EID_HT_OPERATION 61
|
||||
#define WLAN_EID_SECONDARY_CHANNEL_OFFSET 62
|
||||
#define WLAN_EID_WAPI 68
|
||||
#define WLAN_EID_TIME_ADVERTISEMENT 69
|
||||
#define WLAN_EID_20_40_BSS_COEXISTENCE 72
|
||||
#define WLAN_EID_20_40_BSS_INTOLERANT 73
|
||||
#define WLAN_EID_OVERLAPPING_BSS_SCAN_PARAMS 74
|
||||
#define WLAN_EID_MMIE 76
|
||||
#define WLAN_EID_SSID_LIST 84
|
||||
#define WLAN_EID_BSS_MAX_IDLE_PERIOD 90
|
||||
#define WLAN_EID_TFS_REQ 91
|
||||
#define WLAN_EID_TFS_RESP 92
|
||||
#define WLAN_EID_WNMSLEEP 93
|
||||
#define WLAN_EID_TIME_ZONE 98
|
||||
#define WLAN_EID_LINK_ID 101
|
||||
#define WLAN_EID_INTERWORKING 107
|
||||
#define WLAN_EID_ADV_PROTO 108
|
||||
#define WLAN_EID_ROAMING_CONSORTIUM 111
|
||||
#define WLAN_EID_EXT_CAPAB 127
|
||||
#define WLAN_EID_CCKM 156
|
||||
#define WLAN_EID_VHT_CAP 191
|
||||
#define WLAN_EID_VHT_OPERATION 192
|
||||
#define WLAN_EID_VHT_EXTENDED_BSS_LOAD 193
|
||||
#define WLAN_EID_VHT_WIDE_BW_CHSWITCH 194
|
||||
#define WLAN_EID_VHT_TRANSMIT_POWER_ENVELOPE 195
|
||||
#define WLAN_EID_VHT_CHANNEL_SWITCH_WRAPPER 196
|
||||
#define WLAN_EID_VHT_AID 197
|
||||
#define WLAN_EID_VHT_QUIET_CHANNEL 198
|
||||
#define WLAN_EID_VHT_OPERATING_MODE_NOTIFICATION 199
|
||||
#define WLAN_EID_VENDOR_SPECIFIC 221
|
||||
|
||||
|
||||
@ -219,7 +266,20 @@
|
||||
#define WLAN_ACTION_FT 6
|
||||
#define WLAN_ACTION_HT 7
|
||||
#define WLAN_ACTION_SA_QUERY 8
|
||||
#define WLAN_ACTION_WNM 10
|
||||
#define WLAN_ACTION_UNPROTECTED_WNM 11
|
||||
#define WLAN_ACTION_TDLS 12
|
||||
#define WLAN_ACTION_WMM 17 /* WMM Specification 1.1 */
|
||||
#define WLAN_ACTION_VENDOR_SPECIFIC 127
|
||||
|
||||
/* Public action codes */
|
||||
#define WLAN_PA_20_40_BSS_COEX 0
|
||||
#define WLAN_PA_VENDOR_SPECIFIC 9
|
||||
#define WLAN_PA_GAS_INITIAL_REQ 10
|
||||
#define WLAN_PA_GAS_INITIAL_RESP 11
|
||||
#define WLAN_PA_GAS_COMEBACK_REQ 12
|
||||
#define WLAN_PA_GAS_COMEBACK_RESP 13
|
||||
#define WLAN_TDLS_DISCOVERY_RESPONSE 14
|
||||
|
||||
/* SA Query Action frame (IEEE 802.11w/D8.0, 7.4.9) */
|
||||
#define WLAN_SA_QUERY_REQUEST 0
|
||||
@ -227,11 +287,99 @@
|
||||
|
||||
#define WLAN_SA_QUERY_TR_ID_LEN 2
|
||||
|
||||
/* TDLS action codes */
|
||||
#define WLAN_TDLS_SETUP_REQUEST 0
|
||||
#define WLAN_TDLS_SETUP_RESPONSE 1
|
||||
#define WLAN_TDLS_SETUP_CONFIRM 2
|
||||
#define WLAN_TDLS_TEARDOWN 3
|
||||
#define WLAN_TDLS_PEER_TRAFFIC_INDICATION 4
|
||||
#define WLAN_TDLS_CHANNEL_SWITCH_REQUEST 5
|
||||
#define WLAN_TDLS_CHANNEL_SWITCH_RESPONSE 6
|
||||
#define WLAN_TDLS_PEER_PSM_REQUEST 7
|
||||
#define WLAN_TDLS_PEER_PSM_RESPONSE 8
|
||||
#define WLAN_TDLS_PEER_TRAFFIC_RESPONSE 9
|
||||
#define WLAN_TDLS_DISCOVERY_REQUEST 10
|
||||
|
||||
/* Timeout Interval Type */
|
||||
#define WLAN_TIMEOUT_REASSOC_DEADLINE 1
|
||||
#define WLAN_TIMEOUT_KEY_LIFETIME 2
|
||||
#define WLAN_TIMEOUT_ASSOC_COMEBACK 3
|
||||
|
||||
/* Interworking element (IEEE 802.11u) - Access Network Options */
|
||||
#define INTERWORKING_ANO_ACCESS_NETWORK_MASK 0x0f
|
||||
#define INTERWORKING_ANO_INTERNET 0x10
|
||||
#define INTERWORKING_ANO_ASRA 0x20
|
||||
#define INTERWORKING_ANO_ESR 0x40
|
||||
#define INTERWORKING_ANO_UESA 0x80
|
||||
|
||||
#define INTERWORKING_ANT_PRIVATE 0
|
||||
#define INTERWORKING_ANT_PRIVATE_WITH_GUEST 1
|
||||
#define INTERWORKING_ANT_CHARGEABLE_PUBLIC 2
|
||||
#define INTERWORKING_ANT_FREE_PUBLIC 3
|
||||
#define INTERWORKING_ANT_PERSONAL_DEVICE 4
|
||||
#define INTERWORKING_ANT_EMERGENCY_SERVICES 5
|
||||
#define INTERWORKING_ANT_TEST 6
|
||||
#define INTERWORKING_ANT_WILDCARD 15
|
||||
|
||||
/* Advertisement Protocol ID definitions (IEEE Std 802.11u-2011) */
|
||||
enum adv_proto_id {
|
||||
ACCESS_NETWORK_QUERY_PROTOCOL = 0,
|
||||
MIH_INFO_SERVICE = 1,
|
||||
MIH_CMD_AND_EVENT_DISCOVERY = 2,
|
||||
EMERGENCY_ALERT_SYSTEM = 3,
|
||||
ADV_PROTO_VENDOR_SPECIFIC = 221
|
||||
};
|
||||
|
||||
/* Access Network Query Protocol info ID definitions (IEEE Std 802.11u-2011) */
|
||||
enum anqp_info_id {
|
||||
ANQP_QUERY_LIST = 256,
|
||||
ANQP_CAPABILITY_LIST = 257,
|
||||
ANQP_VENUE_NAME = 258,
|
||||
ANQP_EMERGENCY_CALL_NUMBER = 259,
|
||||
ANQP_NETWORK_AUTH_TYPE = 260,
|
||||
ANQP_ROAMING_CONSORTIUM = 261,
|
||||
ANQP_IP_ADDR_TYPE_AVAILABILITY = 262,
|
||||
ANQP_NAI_REALM = 263,
|
||||
ANQP_3GPP_CELLULAR_NETWORK = 264,
|
||||
ANQP_AP_GEOSPATIAL_LOCATION = 265,
|
||||
ANQP_AP_CIVIC_LOCATION = 266,
|
||||
ANQP_AP_LOCATION_PUBLIC_URI = 267,
|
||||
ANQP_DOMAIN_NAME = 268,
|
||||
ANQP_EMERGENCY_ALERT_URI = 269,
|
||||
ANQP_EMERGENCY_NAI = 271,
|
||||
ANQP_VENDOR_SPECIFIC = 56797
|
||||
};
|
||||
|
||||
/* NAI Realm list - EAP Method subfield - Authentication Parameter ID */
|
||||
enum nai_realm_eap_auth_param {
|
||||
NAI_REALM_EAP_AUTH_EXPANDED_EAP_METHOD = 1,
|
||||
NAI_REALM_EAP_AUTH_NON_EAP_INNER_AUTH = 2,
|
||||
NAI_REALM_EAP_AUTH_INNER_AUTH_EAP_METHOD = 3,
|
||||
NAI_REALM_EAP_AUTH_EXPANDED_INNER_EAP_METHOD = 4,
|
||||
NAI_REALM_EAP_AUTH_CRED_TYPE = 5,
|
||||
NAI_REALM_EAP_AUTH_TUNNELED_CRED_TYPE = 6,
|
||||
NAI_REALM_EAP_AUTH_VENDOR_SPECIFIC = 221
|
||||
};
|
||||
|
||||
enum nai_realm_eap_auth_inner_non_eap {
|
||||
NAI_REALM_INNER_NON_EAP_PAP = 1,
|
||||
NAI_REALM_INNER_NON_EAP_CHAP = 2,
|
||||
NAI_REALM_INNER_NON_EAP_MSCHAP = 3,
|
||||
NAI_REALM_INNER_NON_EAP_MSCHAPV2 = 4
|
||||
};
|
||||
|
||||
enum nai_realm_eap_cred_type {
|
||||
NAI_REALM_CRED_TYPE_SIM = 1,
|
||||
NAI_REALM_CRED_TYPE_USIM = 2,
|
||||
NAI_REALM_CRED_TYPE_NFC_SECURE_ELEMENT = 3,
|
||||
NAI_REALM_CRED_TYPE_HARDWARE_TOKEN = 4,
|
||||
NAI_REALM_CRED_TYPE_SOFTOKEN = 5,
|
||||
NAI_REALM_CRED_TYPE_CERTIFICATE = 6,
|
||||
NAI_REALM_CRED_TYPE_USERNAME_PASSWORD = 7,
|
||||
NAI_REALM_CRED_TYPE_NONE = 8,
|
||||
NAI_REALM_CRED_TYPE_ANONYMOUS = 9,
|
||||
NAI_REALM_CRED_TYPE_VENDOR_SPECIFIC = 10
|
||||
};
|
||||
|
||||
#ifdef _MSC_VER
|
||||
#pragma pack(push, 1)
|
||||
@ -273,6 +421,7 @@ struct ieee80211_mgmt {
|
||||
} STRUCT_PACKED auth;
|
||||
struct {
|
||||
le16 reason_code;
|
||||
u8 variable[0];
|
||||
} STRUCT_PACKED deauth;
|
||||
struct {
|
||||
le16 capab_info;
|
||||
@ -296,6 +445,7 @@ struct ieee80211_mgmt {
|
||||
} STRUCT_PACKED reassoc_req;
|
||||
struct {
|
||||
le16 reason_code;
|
||||
u8 variable[0];
|
||||
} STRUCT_PACKED disassoc;
|
||||
struct {
|
||||
u8 timestamp[8];
|
||||
@ -355,12 +505,58 @@ struct ieee80211_mgmt {
|
||||
u8 action; /* */
|
||||
u8 trans_id[WLAN_SA_QUERY_TR_ID_LEN];
|
||||
} STRUCT_PACKED sa_query_resp;
|
||||
struct {
|
||||
u8 action;
|
||||
u8 dialogtoken;
|
||||
u8 variable[0];
|
||||
} STRUCT_PACKED wnm_sleep_req;
|
||||
struct {
|
||||
u8 action;
|
||||
u8 dialogtoken;
|
||||
le16 keydata_len;
|
||||
u8 variable[0];
|
||||
} STRUCT_PACKED wnm_sleep_resp;
|
||||
struct {
|
||||
u8 action;
|
||||
u8 variable[0];
|
||||
} STRUCT_PACKED public_action;
|
||||
struct {
|
||||
u8 action; /* 9 */
|
||||
u8 oui[3];
|
||||
/* Vendor-specific content */
|
||||
u8 variable[0];
|
||||
} STRUCT_PACKED vs_public_action;
|
||||
struct {
|
||||
u8 action; /* 7 */
|
||||
u8 dialog_token;
|
||||
u8 req_mode;
|
||||
le16 disassoc_timer;
|
||||
u8 validity_interval;
|
||||
/* BSS Termination Duration (optional),
|
||||
* Session Information URL (optional),
|
||||
* BSS Transition Candidate List
|
||||
* Entries */
|
||||
u8 variable[0];
|
||||
} STRUCT_PACKED bss_tm_req;
|
||||
struct {
|
||||
u8 action; /* 8 */
|
||||
u8 dialog_token;
|
||||
u8 status_code;
|
||||
u8 bss_termination_delay;
|
||||
/* Target BSSID (optional),
|
||||
* BSS Transition Candidate List
|
||||
* Entries (optional) */
|
||||
u8 variable[0];
|
||||
} STRUCT_PACKED bss_tm_resp;
|
||||
} u;
|
||||
} STRUCT_PACKED action;
|
||||
} u;
|
||||
} STRUCT_PACKED;
|
||||
|
||||
|
||||
/* Rx MCS bitmask is in the first 77 bits of supported_mcs_set */
|
||||
#define IEEE80211_HT_MCS_MASK_LEN 10
|
||||
|
||||
struct ieee80211_ht_capabilities {
|
||||
le16 ht_capabilities_info;
|
||||
u8 a_mpdu_params;
|
||||
@ -379,6 +575,19 @@ struct ieee80211_ht_operation {
|
||||
u8 basic_set[16];
|
||||
} STRUCT_PACKED;
|
||||
|
||||
|
||||
struct ieee80211_vht_capabilities {
|
||||
le32 vht_capabilities_info;
|
||||
u8 vht_supported_mcs_set[8];
|
||||
} STRUCT_PACKED;
|
||||
|
||||
struct ieee80211_vht_operation {
|
||||
u8 vht_op_info_chwidth;
|
||||
u8 vht_op_info_chan_center_freq_seg0_idx;
|
||||
u8 vht_op_info_chan_center_freq_seg1_idx;
|
||||
le16 vht_basic_mcs_set;
|
||||
} STRUCT_PACKED;
|
||||
|
||||
#ifdef _MSC_VER
|
||||
#pragma pack(pop)
|
||||
#endif /* _MSC_VER */
|
||||
@ -460,7 +669,7 @@ struct ieee80211_ht_operation {
|
||||
#define OP_MODE_MIXED 3
|
||||
|
||||
#define HT_INFO_OPERATION_MODE_OP_MODE_MASK \
|
||||
((le16) (0x0001 | 0x0002))
|
||||
(0x0001 | 0x0002)
|
||||
#define HT_INFO_OPERATION_MODE_OP_MODE_OFFSET 0
|
||||
#define HT_INFO_OPERATION_MODE_NON_GF_DEVS_PRESENT ((u8) BIT(2))
|
||||
#define HT_INFO_OPERATION_MODE_TRANSMIT_BURST_LIMIT ((u8) BIT(3))
|
||||
@ -473,11 +682,45 @@ struct ieee80211_ht_operation {
|
||||
#define HT_INFO_STBC_PARAM_PCO_ACTIVE ((u16) BIT(10))
|
||||
#define HT_INFO_STBC_PARAM_PCO_PHASE ((u16) BIT(11))
|
||||
|
||||
#define BSS_MEMBERSHIP_SELECTOR_VHT_PHY 126
|
||||
#define BSS_MEMBERSHIP_SELECTOR_HT_PHY 127
|
||||
|
||||
/* VHT Defines */
|
||||
#define VHT_CAP_MAX_MPDU_LENGTH_7991 ((u32) BIT(0))
|
||||
#define VHT_CAP_MAX_MPDU_LENGTH_11454 ((u32) BIT(1))
|
||||
#define VHT_CAP_SUPP_CHAN_WIDTH_160MHZ ((u32) BIT(2))
|
||||
#define VHT_CAP_SUPP_CHAN_WIDTH_160_80PLUS80MHZ ((u32) BIT(3))
|
||||
#define VHT_CAP_RXLDPC ((u32) BIT(4))
|
||||
#define VHT_CAP_SHORT_GI_80 ((u32) BIT(5))
|
||||
#define VHT_CAP_SHORT_GI_160 ((u32) BIT(6))
|
||||
#define VHT_CAP_TXSTBC ((u32) BIT(7))
|
||||
#define VHT_CAP_RXSTBC_1 ((u32) BIT(8))
|
||||
#define VHT_CAP_RXSTBC_2 ((u32) BIT(9))
|
||||
#define VHT_CAP_RXSTBC_3 ((u32) BIT(8) | BIT(9))
|
||||
#define VHT_CAP_RXSTBC_4 ((u32) BIT(10))
|
||||
#define VHT_CAP_SU_BEAMFORMER_CAPABLE ((u32) BIT(11))
|
||||
#define VHT_CAP_SU_BEAMFORMEE_CAPABLE ((u32) BIT(12))
|
||||
#define VHT_CAP_BEAMFORMER_ANTENNAS_MAX ((u32) BIT(13) | BIT(14))
|
||||
#define VHT_CAP_SOUNDING_DIMENTION_MAX ((u32) BIT(16) | BIT(17))
|
||||
#define VHT_CAP_MU_BEAMFORMER_CAPABLE ((u32) BIT(19))
|
||||
#define VHT_CAP_MU_BEAMFORMEE_CAPABLE ((u32) BIT(20))
|
||||
#define VHT_CAP_VHT_TXOP_PS ((u32) BIT(21))
|
||||
#define VHT_CAP_HTC_VHT ((u32) BIT(22))
|
||||
#define VHT_CAP_MAX_A_MPDU_LENGTH_EXPONENT ((u32) BIT(23))
|
||||
#define VHT_CAP_VHT_LINK_ADAPTATION_VHT_UNSOL_MFB ((u32) BIT(27))
|
||||
#define VHT_CAP_VHT_LINK_ADAPTATION_VHT_MRQ_MFB ((u32) BIT(26) | BIT(27))
|
||||
#define VHT_CAP_RX_ANTENNA_PATTERN ((u32) BIT(28))
|
||||
#define VHT_CAP_TX_ANTENNA_PATTERN ((u32) BIT(29))
|
||||
|
||||
#define OUI_MICROSOFT 0x0050f2 /* Microsoft (also used in Wi-Fi specs)
|
||||
* 00:50:F2 */
|
||||
#define WPA_IE_VENDOR_TYPE 0x0050f201
|
||||
#define WPS_IE_VENDOR_TYPE 0x0050f204
|
||||
#define OUI_WFA 0x506f9a
|
||||
#define P2P_IE_VENDOR_TYPE 0x506f9a09
|
||||
#define WFD_IE_VENDOR_TYPE 0x506f9a0a
|
||||
#define WFD_OUI_TYPE 10
|
||||
#define HS20_IE_VENDOR_TYPE 0x506f9a10
|
||||
|
||||
#define WMM_OUI_TYPE 2
|
||||
#define WMM_OUI_SUBTYPE_INFORMATION_ELEMENT 0
|
||||
@ -516,6 +759,10 @@ struct wmm_information_element {
|
||||
|
||||
} STRUCT_PACKED;
|
||||
|
||||
#define WMM_QOSINFO_STA_AC_MASK 0x0f
|
||||
#define WMM_QOSINFO_STA_SP_MASK 0x03
|
||||
#define WMM_QOSINFO_STA_SP_SHIFT 5
|
||||
|
||||
#define WMM_AC_AIFSN_MASK 0x0f
|
||||
#define WMM_AC_AIFNS_SHIFT 0
|
||||
#define WMM_AC_ACM 0x10
|
||||
@ -544,7 +791,7 @@ struct wmm_parameter_element {
|
||||
u8 oui_type; /* 2 */
|
||||
u8 oui_subtype; /* 1 */
|
||||
u8 version; /* 1 for WMM version 1.0 */
|
||||
u8 qos_info; /* AP/STA specif QoS info */
|
||||
u8 qos_info; /* AP/STA specific QoS info */
|
||||
u8 reserved; /* 0 */
|
||||
struct wmm_ac_parameter ac[4]; /* AC_BE, AC_BK, AC_VI, AC_VO */
|
||||
|
||||
@ -587,6 +834,140 @@ enum {
|
||||
};
|
||||
|
||||
|
||||
#define HS20_INDICATION_OUI_TYPE 16
|
||||
#define HS20_ANQP_OUI_TYPE 17
|
||||
#define HS20_STYPE_QUERY_LIST 1
|
||||
#define HS20_STYPE_CAPABILITY_LIST 2
|
||||
#define HS20_STYPE_OPERATOR_FRIENDLY_NAME 3
|
||||
#define HS20_STYPE_WAN_METRICS 4
|
||||
#define HS20_STYPE_CONNECTION_CAPABILITY 5
|
||||
#define HS20_STYPE_NAI_HOME_REALM_QUERY 6
|
||||
#define HS20_STYPE_OPERATING_CLASS 7
|
||||
|
||||
/* Wi-Fi Direct (P2P) */
|
||||
|
||||
#define P2P_OUI_TYPE 9
|
||||
|
||||
enum p2p_attr_id {
|
||||
P2P_ATTR_STATUS = 0,
|
||||
P2P_ATTR_MINOR_REASON_CODE = 1,
|
||||
P2P_ATTR_CAPABILITY = 2,
|
||||
P2P_ATTR_DEVICE_ID = 3,
|
||||
P2P_ATTR_GROUP_OWNER_INTENT = 4,
|
||||
P2P_ATTR_CONFIGURATION_TIMEOUT = 5,
|
||||
P2P_ATTR_LISTEN_CHANNEL = 6,
|
||||
P2P_ATTR_GROUP_BSSID = 7,
|
||||
P2P_ATTR_EXT_LISTEN_TIMING = 8,
|
||||
P2P_ATTR_INTENDED_INTERFACE_ADDR = 9,
|
||||
P2P_ATTR_MANAGEABILITY = 10,
|
||||
P2P_ATTR_CHANNEL_LIST = 11,
|
||||
P2P_ATTR_NOTICE_OF_ABSENCE = 12,
|
||||
P2P_ATTR_DEVICE_INFO = 13,
|
||||
P2P_ATTR_GROUP_INFO = 14,
|
||||
P2P_ATTR_GROUP_ID = 15,
|
||||
P2P_ATTR_INTERFACE = 16,
|
||||
P2P_ATTR_OPERATING_CHANNEL = 17,
|
||||
P2P_ATTR_INVITATION_FLAGS = 18,
|
||||
P2P_ATTR_VENDOR_SPECIFIC = 221
|
||||
};
|
||||
|
||||
#define P2P_MAX_GO_INTENT 15
|
||||
|
||||
/* P2P Capability - Device Capability bitmap */
|
||||
#define P2P_DEV_CAPAB_SERVICE_DISCOVERY BIT(0)
|
||||
#define P2P_DEV_CAPAB_CLIENT_DISCOVERABILITY BIT(1)
|
||||
#define P2P_DEV_CAPAB_CONCURRENT_OPER BIT(2)
|
||||
#define P2P_DEV_CAPAB_INFRA_MANAGED BIT(3)
|
||||
#define P2P_DEV_CAPAB_DEVICE_LIMIT BIT(4)
|
||||
#define P2P_DEV_CAPAB_INVITATION_PROCEDURE BIT(5)
|
||||
|
||||
/* P2P Capability - Group Capability bitmap */
|
||||
#define P2P_GROUP_CAPAB_GROUP_OWNER BIT(0)
|
||||
#define P2P_GROUP_CAPAB_PERSISTENT_GROUP BIT(1)
|
||||
#define P2P_GROUP_CAPAB_GROUP_LIMIT BIT(2)
|
||||
#define P2P_GROUP_CAPAB_INTRA_BSS_DIST BIT(3)
|
||||
#define P2P_GROUP_CAPAB_CROSS_CONN BIT(4)
|
||||
#define P2P_GROUP_CAPAB_PERSISTENT_RECONN BIT(5)
|
||||
#define P2P_GROUP_CAPAB_GROUP_FORMATION BIT(6)
|
||||
|
||||
/* Invitation Flags */
|
||||
#define P2P_INVITATION_FLAGS_TYPE BIT(0)
|
||||
|
||||
/* P2P Manageability */
|
||||
#define P2P_MAN_DEVICE_MANAGEMENT BIT(0)
|
||||
#define P2P_MAN_CROSS_CONNECTION_PERMITTED BIT(1)
|
||||
#define P2P_MAN_COEXISTENCE_OPTIONAL BIT(2)
|
||||
|
||||
enum p2p_status_code {
|
||||
P2P_SC_SUCCESS = 0,
|
||||
P2P_SC_FAIL_INFO_CURRENTLY_UNAVAILABLE = 1,
|
||||
P2P_SC_FAIL_INCOMPATIBLE_PARAMS = 2,
|
||||
P2P_SC_FAIL_LIMIT_REACHED = 3,
|
||||
P2P_SC_FAIL_INVALID_PARAMS = 4,
|
||||
P2P_SC_FAIL_UNABLE_TO_ACCOMMODATE = 5,
|
||||
P2P_SC_FAIL_PREV_PROTOCOL_ERROR = 6,
|
||||
P2P_SC_FAIL_NO_COMMON_CHANNELS = 7,
|
||||
P2P_SC_FAIL_UNKNOWN_GROUP = 8,
|
||||
P2P_SC_FAIL_BOTH_GO_INTENT_15 = 9,
|
||||
P2P_SC_FAIL_INCOMPATIBLE_PROV_METHOD = 10,
|
||||
P2P_SC_FAIL_REJECTED_BY_USER = 11,
|
||||
};
|
||||
|
||||
#define P2P_WILDCARD_SSID "DIRECT-"
|
||||
#define P2P_WILDCARD_SSID_LEN 7
|
||||
|
||||
/* P2P action frames */
|
||||
enum p2p_act_frame_type {
|
||||
P2P_NOA = 0,
|
||||
P2P_PRESENCE_REQ = 1,
|
||||
P2P_PRESENCE_RESP = 2,
|
||||
P2P_GO_DISC_REQ = 3
|
||||
};
|
||||
|
||||
/* P2P public action frames */
|
||||
enum p2p_action_frame_type {
|
||||
P2P_GO_NEG_REQ = 0,
|
||||
P2P_GO_NEG_RESP = 1,
|
||||
P2P_GO_NEG_CONF = 2,
|
||||
P2P_INVITATION_REQ = 3,
|
||||
P2P_INVITATION_RESP = 4,
|
||||
P2P_DEV_DISC_REQ = 5,
|
||||
P2P_DEV_DISC_RESP = 6,
|
||||
P2P_PROV_DISC_REQ = 7,
|
||||
P2P_PROV_DISC_RESP = 8
|
||||
};
|
||||
|
||||
enum p2p_service_protocol_type {
|
||||
P2P_SERV_ALL_SERVICES = 0,
|
||||
P2P_SERV_BONJOUR = 1,
|
||||
P2P_SERV_UPNP = 2,
|
||||
P2P_SERV_WS_DISCOVERY = 3,
|
||||
P2P_SERV_WIFI_DISPLAY = 4,
|
||||
P2P_SERV_VENDOR_SPECIFIC = 255
|
||||
};
|
||||
|
||||
enum p2p_sd_status {
|
||||
P2P_SD_SUCCESS = 0,
|
||||
P2P_SD_PROTO_NOT_AVAILABLE = 1,
|
||||
P2P_SD_REQUESTED_INFO_NOT_AVAILABLE = 2,
|
||||
P2P_SD_BAD_REQUEST = 3
|
||||
};
|
||||
|
||||
|
||||
enum wifi_display_subelem {
|
||||
WFD_SUBELEM_DEVICE_INFO = 0,
|
||||
WFD_SUBELEM_ASSOCIATED_BSSID = 1,
|
||||
WFD_SUBELEM_AUDIO_FORMATS = 2,
|
||||
WFD_SUBELEM_VIDEO_FORMATS = 3,
|
||||
WFD_SUBELEM_3D_VIDEO_FORMATS = 4,
|
||||
WFD_SUBELEM_CONTENT_PROTECTION = 5,
|
||||
WFD_SUBELEM_COUPLED_SINK = 6,
|
||||
WFD_SUBELEM_EXT_CAPAB = 7,
|
||||
WFD_SUBELEM_LOCAL_IP_ADDRESS = 8,
|
||||
WFD_SUBELEM_SESSION_INFO = 9
|
||||
};
|
||||
|
||||
|
||||
#define OUI_BROADCOM 0x00904c /* Broadcom (Epigram) */
|
||||
|
||||
#define VENDOR_HT_CAPAB_OUI_TYPE 0x33 /* 00-90-4c:0x33 */
|
||||
@ -599,9 +980,106 @@ enum {
|
||||
#define WLAN_CIPHER_SUITE_CCMP 0x000FAC04
|
||||
#define WLAN_CIPHER_SUITE_WEP104 0x000FAC05
|
||||
#define WLAN_CIPHER_SUITE_AES_CMAC 0x000FAC06
|
||||
#define WLAN_CIPHER_SUITE_NO_GROUP_ADDR 0x000FAC07
|
||||
#define WLAN_CIPHER_SUITE_GCMP 0x000FAC08
|
||||
|
||||
#define WLAN_CIPHER_SUITE_SMS4 0x00147201
|
||||
|
||||
#define WLAN_CIPHER_SUITE_CKIP 0x00409600
|
||||
#define WLAN_CIPHER_SUITE_CKIP_CMIC 0x00409601
|
||||
#define WLAN_CIPHER_SUITE_CMIC 0x00409602
|
||||
#define WLAN_CIPHER_SUITE_KRK 0x004096FF /* for nl80211 use only */
|
||||
|
||||
/* AKM suite selectors */
|
||||
#define WLAN_AKM_SUITE_8021X 0x000FAC01
|
||||
#define WLAN_AKM_SUITE_PSK 0x000FAC02
|
||||
#define WLAN_AKM_SUITE_CCKM 0x00409600
|
||||
|
||||
|
||||
/* IEEE 802.11v - WNM Action field values */
|
||||
enum wnm_action {
|
||||
WNM_EVENT_REQ = 0,
|
||||
WNM_EVENT_REPORT = 1,
|
||||
WNM_DIAGNOSTIC_REQ = 2,
|
||||
WNM_DIAGNOSTIC_REPORT = 3,
|
||||
WNM_LOCATION_CFG_REQ = 4,
|
||||
WNM_LOCATION_CFG_RESP = 5,
|
||||
WNM_BSS_TRANS_MGMT_QUERY = 6,
|
||||
WNM_BSS_TRANS_MGMT_REQ = 7,
|
||||
WNM_BSS_TRANS_MGMT_RESP = 8,
|
||||
WNM_FMS_REQ = 9,
|
||||
WNM_FMS_RESP = 10,
|
||||
WNM_COLLOCATED_INTERFERENCE_REQ = 11,
|
||||
WNM_COLLOCATED_INTERFERENCE_REPORT = 12,
|
||||
WNM_TFS_REQ = 13,
|
||||
WNM_TFS_RESP = 14,
|
||||
WNM_TFS_NOTIFY = 15,
|
||||
WNM_SLEEP_MODE_REQ = 16,
|
||||
WNM_SLEEP_MODE_RESP = 17,
|
||||
WNM_TIM_BROADCAST_REQ = 18,
|
||||
WNM_TIM_BROADCAST_RESP = 19,
|
||||
WNM_QOS_TRAFFIC_CAPAB_UPDATE = 20,
|
||||
WNM_CHANNEL_USAGE_REQ = 21,
|
||||
WNM_CHANNEL_USAGE_RESP = 22,
|
||||
WNM_DMS_REQ = 23,
|
||||
WNM_DMS_RESP = 24,
|
||||
WNM_TIMING_MEASUREMENT_REQ = 25,
|
||||
WNM_NOTIFICATION_REQ = 26,
|
||||
WNM_NOTIFICATION_RESP = 27
|
||||
};
|
||||
|
||||
/* IEEE 802.11v - BSS Transition Management Request - Request Mode */
|
||||
#define WNM_BSS_TM_REQ_PREF_CAND_LIST_INCLUDED BIT(0)
|
||||
#define WNM_BSS_TM_REQ_ABRIDGED BIT(1)
|
||||
#define WNM_BSS_TM_REQ_DISASSOC_IMMINENT BIT(2)
|
||||
#define WNM_BSS_TM_REQ_BSS_TERMINATION_INCLUDED BIT(3)
|
||||
#define WNM_BSS_TM_REQ_ESS_DISASSOC_IMMINENT BIT(4)
|
||||
|
||||
/* IEEE Std 802.11-2012, 8.4.2.62 20/40 BSS Coexistence element */
|
||||
#define WLAN_20_40_BSS_COEX_INFO_REQ BIT(0)
|
||||
#define WLAN_20_40_BSS_COEX_40MHZ_INTOL BIT(1)
|
||||
#define WLAN_20_40_BSS_COEX_20MHZ_WIDTH_REQ BIT(2)
|
||||
#define WLAN_20_40_BSS_COEX_OBSS_EXEMPT_REQ BIT(3)
|
||||
#define WLAN_20_40_BSS_COEX_OBSS_EXEMPT_GRNT BIT(4)
|
||||
|
||||
struct ieee80211_2040_bss_coex_ie {
|
||||
u8 element_id;
|
||||
u8 length;
|
||||
u8 coex_param;
|
||||
} STRUCT_PACKED;
|
||||
|
||||
struct ieee80211_2040_intol_chan_report {
|
||||
u8 element_id;
|
||||
u8 length;
|
||||
u8 op_class;
|
||||
u8 variable[0]; /* Channel List */
|
||||
} STRUCT_PACKED;
|
||||
|
||||
/* IEEE 802.11v - WNM-Sleep Mode element */
|
||||
struct wnm_sleep_element {
|
||||
u8 eid; /* WLAN_EID_WNMSLEEP */
|
||||
u8 len;
|
||||
u8 action_type; /* WNM_SLEEP_ENTER/WNM_SLEEP_MODE_EXIT */
|
||||
u8 status;
|
||||
le16 intval;
|
||||
} STRUCT_PACKED;
|
||||
|
||||
#define WNM_SLEEP_MODE_ENTER 0
|
||||
#define WNM_SLEEP_MODE_EXIT 1
|
||||
|
||||
enum wnm_sleep_mode_response_status {
|
||||
WNM_STATUS_SLEEP_ACCEPT = 0,
|
||||
WNM_STATUS_SLEEP_EXIT_ACCEPT_GTK_UPDATE = 1,
|
||||
WNM_STATUS_DENIED_ACTION = 2,
|
||||
WNM_STATUS_DENIED_TMP = 3,
|
||||
WNM_STATUS_DENIED_KEY = 4,
|
||||
WNM_STATUS_DENIED_OTHER_WNM_SERVICE = 5
|
||||
};
|
||||
|
||||
/* WNM-Sleep Mode subelement IDs */
|
||||
enum wnm_sleep_mode_subelement_id {
|
||||
WNM_SLEEP_SUBELEM_GTK = 0,
|
||||
WNM_SLEEP_SUBELEM_IGTK = 1
|
||||
};
|
||||
|
||||
#endif /* IEEE802_11_DEFS_H */
|
||||
|
@ -2,14 +2,8 @@
|
||||
* WPA Supplicant - privilege separation commands
|
||||
* Copyright (c) 2007-2009, Jouni Malinen <j@w1.fi>
|
||||
*
|
||||
* This program is free software; you can redistribute it and/or modify
|
||||
* it under the terms of the GNU General Public License version 2 as
|
||||
* published by the Free Software Foundation.
|
||||
*
|
||||
* Alternatively, this software may be distributed under the terms of BSD
|
||||
* license.
|
||||
*
|
||||
* See README and COPYING for more details.
|
||||
* This software may be distributed under the terms of the BSD license.
|
||||
* See README for more details.
|
||||
*/
|
||||
|
||||
#ifndef PRIVSEP_COMMANDS_H
|
||||
|
@ -1,6 +1,10 @@
|
||||
#ifndef VERSION_H
|
||||
#define VERSION_H
|
||||
|
||||
#define VERSION_STR "0.7.3"
|
||||
#ifndef VERSION_STR_POSTFIX
|
||||
#define VERSION_STR_POSTFIX ""
|
||||
#endif /* VERSION_STR_POSTFIX */
|
||||
|
||||
#define VERSION_STR "2.0" VERSION_STR_POSTFIX
|
||||
|
||||
#endif /* VERSION_H */
|
||||
|
Some files were not shown because too many files have changed in this diff Show More
Loading…
x
Reference in New Issue
Block a user