import v2_0:
2013-01-12 - v2.0 * removed Qt3-based wpa_gui (obsoleted by wpa_qui-qt4) * removed unmaintained driver wrappers broadcom, iphone, osx, ralink, hostap, madwifi (hostap and madwifi remain available for hostapd; their wpa_supplicant functionality is obsoleted by wext) * improved debug logging (human readable event names, interface name included in more entries) * changed AP mode behavior to enable WPS only for open and WPA/WPA2-Personal configuration * improved P2P concurrency operations - better coordination of concurrent scan and P2P search operations - avoid concurrent remain-on-channel operation requests by canceling previous operations prior to starting a new one - reject operations that would require multi-channel concurrency if the driver does not support it - add parameter to select whether STA or P2P connection is preferred if the driver cannot support both at the same time - allow driver to indicate channel changes - added optional delay=<search delay in milliseconds> parameter for p2p_find to avoid taking all radio resources - use 500 ms p2p_find search delay by default during concurrent operations - allow all channels in GO Negotiation if the driver supports multi-channel concurrency * added number of small changes to make it easier for static analyzers to understand the implementation * fixed number of small bugs (see git logs for more details) * nl80211: number of updates to use new cfg80211/nl80211 functionality - replace monitor interface with nl80211 commands for AP mode - additional information for driver-based AP SME - STA entry authorization in RSN IBSS * EAP-pwd: - fixed 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 wpa_supplicant AP mode SME/MLME) * added "GET country" ctrl_iface command * do not save an invalid network block in wpa_supplicant.conf to avoid problems reading the file on next start * send STA connected/disconnected ctrl_iface events to both the P2P group and parent interfaces * added preliminary support for using TLS v1.2 (CONFIG_TLSV12=y) * added "SET pno <1/0>" ctrl_iface command to start/stop preferred network offload with sched_scan driver command * merged in number of changes from Android repository for P2P, nl80211, and build parameters * changed P2P GO mode configuration to use driver capabilities to automatically enable HT operations when supported * added "wpa_cli status wps" command to fetch WPA2-Personal passhrase for WPS use cases in AP mode * EAP-AKA: keep pseudonym identity across EAP exchanges to match EAP-SIM behavior * improved reassociation behavior in cases where association is rejected or when an AP disconnects us to handle common load balancing mechanisms - try to avoid extra scans when the needed information is available * added optional "join" argument for p2p_prov_disc ctrl_iface command * added group ifname to P2P-PROV-DISC-* events * added P2P Device Address to AP-STA-DISCONNECTED event and use p2p_dev_addr parameter name with AP-STA-CONNECTED * added workarounds for WPS PBC overlap detection for some P2P use cases where deployed stations work incorrectly * optimize WPS connection speed by disconnecting prior to WPS scan and by using single channel scans when AP channel is known * PCSC and SIM/USIM improvements: - accept 0x67 (Wrong length) as a response to READ RECORD to fix issues with some USIM cards - try to read MNC length from SIM/USIM - build realm according to 3GPP TS 23.003 with identity from the SIM - allow T1 protocol to be enabled * added more WPS and P2P information available through D-Bus * improve P2P negotiation robustness - extra waits to get ACK frames through - longer timeouts for cases where deployed devices have been identified have issues meeting the specification requirements - more retries for some P2P frames - handle race conditions in GO Negotiation start by both devices - ignore unexpected GO Negotiation Response frame * added support for libnl 3.2 and newer * added P2P persistent group info to P2P_PEER data * maintain a list of P2P Clients for persistent group on GO * AP: increased initial group key handshake retransmit timeout to 500 ms * added optional dev_id parameter for p2p_find * added P2P-FIND-STOPPED ctrl_iface event * fixed issues in WPA/RSN element validation when roaming with ap_scan=1 and driver-based BSS selection * do not expire P2P peer entries while connected with the peer in a group * fixed WSC element inclusion in cases where P2P is disabled * AP: added a WPS workaround for mixed mode AP Settings with Windows 7 * EAP-SIM: fixed AT_COUNTER_TOO_SMALL use * EAP-SIM/AKA: append realm to pseudonym identity * EAP-SIM/AKA: store pseudonym identity in network configuration to allow it to persist over multiple EAP sessions and wpa_supplicant restarts * EAP-AKA': updated to RFC 5448 (username prefixes changed); note: this breaks interoperability with older versions * added support for WFA Hotspot 2.0 - GAS/ANQP to fetch network information - credential configuration and automatic network selections based on credential match with ANQP information * limited PMKSA cache entries to be used only with the network context that was used to create them * improved PMKSA cache expiration to avoid unnecessary disconnections * adjusted bgscan_simple fast-scan backoff to avoid too frequent background scans * removed ctrl_iface event on P2P PD Response in join-group case * added option to fetch BSS table entry based on P2P Device Address ("BSS p2p_dev_addr=<P2P Device Address>") * added BSS entry age to ctrl_iface BSS command output * added optional MASK=0xH option for ctrl_iface BSS command to select which fields are included in the response * added optional RANGE=ALL|N1-N2 option for ctrl_iface BSS command to fetch information about several BSSes in one call * simplified licensing terms by selecting the BSD license as the only alternative * added "P2P_SET disallow_freq <freq list>" ctrl_iface command to disable channels from P2P use * added p2p_pref_chan configuration parameter to allow preferred P2P channels to be specified * added support for advertising immediate availability of a WPS credential for P2P use cases * optimized scan operations for P2P use cases (use single channel scan for a specific SSID when possible) * EAP-TTLS: fixed peer challenge generation for MSCHAPv2 * SME: do not use reassociation after explicit disconnection request (local or a notification from an AP) * added support for sending debug info to Linux tracing (-T on command line) * added support for using Deauthentication reason code 3 as an indication of P2P group termination * added wps_vendor_ext_m1 configuration parameter to allow vendor specific attributes to be added to WPS M1 * started using separate TLS library context for tunneled TLS (EAP-PEAP/TLS, EAP-TTLS/TLS, EAP-FAST/TLS) to support different CA certificate configuration between Phase 1 and Phase 2 * added optional "auto" parameter for p2p_connect to request automatic GO Negotiation vs. join-a-group selection * added disabled_scan_offload parameter to disable automatic scan offloading (sched_scan) * added optional persistent=<network id> parameter for p2p_connect to allow forcing of a specific SSID/passphrase for GO Negotiation * added support for OBSS scan requests and 20/40 BSS coexistence reports * reject PD Request for unknown group * removed scripts and notes related to Windows binary releases (which have not been used starting from 1.x) * added initial support for WNM operations - Keep-alive based on BSS max idle period - WNM-Sleep Mode - minimal BSS Transition Management processing * added autoscan module to control scanning behavior while not connected - autoscan_periodic and autoscan_exponential modules * added new WPS NFC ctrl_iface mechanism - added initial support NFC connection handover - removed obsoleted WPS_OOB command (including support for deprecated UFD config_method) * added optional framework for external password storage ("ext:<name>") * wpa_cli: added optional support for controlling wpa_supplicant remotely over UDP (CONFIG_CTRL_IFACE=udp-remote) for testing purposes * wpa_cli: extended tab completion to more commands * changed SSID output to use printf-escaped strings instead of masking of non-ASCII characters - SSID can now be configured in the same format: ssid=P"abc\x00test" * removed default ACM=1 from AC_VO and AC_VI * added optional "ht40" argument for P2P ctrl_iface commands to allow 40 MHz channels to be requested on the 5 GHz band * added optional parameters for p2p_invite command to specify channel when reinvoking a persistent group as the GO * improved FIPS mode builds with OpenSSL - "make fips" with CONFIG_FIPS=y to build wpa_supplicant with the OpenSSL FIPS object module - replace low level OpenSSL AES API calls to use EVP - use OpenSSL keying material exporter when possible - do not export TLS keys in FIPS mode - remove MD5 from CONFIG_FIPS=y builds - use OpenSSL function for PKBDF2 passphrase-to-PSK - use OpenSSL HMAC implementation - mix RAND_bytes() output into random_get_bytes() to force OpenSSL DRBG to be used in FIPS mode - use OpenSSL CMAC implementation * added mechanism to disable TLS Session Ticket extension - a workaround for servers that do not support TLS extensions that was enabled by default in recent OpenSSL versions - tls_disable_session_ticket=1 - automatically disable TLS Session Ticket extension by default when using EAP-TLS/PEAP/TTLS (i.e., only use it with EAP-FAST) * changed VENDOR-TEST EAP method to use proper private enterprise number (this will not interoperate with older versions) * disable network block temporarily on authentication failures * improved WPS AP selection during WPS PIN iteration * added support for configuring GCMP cipher for IEEE 802.11ad * added support for Wi-Fi Display extensions - WFD_SUBELEMENT_SET ctrl_iface command to configure WFD subelements - SET wifi_display <0/1> to disable/enable WFD support - WFD service discovery - an external program is needed to manage the audio/video streaming and codecs * optimized scan result use for network selection - use the internal BSS table instead of raw scan results - allow unnecessary scans to be skipped if fresh information is available (e.g., after GAS/ANQP round for Interworking) * added support for 256-bit AES with internal TLS implementation * allow peer to propose channel in P2P invitation process for a persistent group * added disallow_aps parameter to allow BSSIDs/SSIDs to be disallowed from network selection * re-enable the networks disabled during WPS operations * allow P2P functionality to be disabled per interface (p2p_disabled=1) * added secondary device types into P2P_PEER output * added an option to disable use of a separate P2P group interface (p2p_no_group_iface=1) * fixed P2P Bonjour SD to match entries with both compressed and not compressed domain name format and support multiple Bonjour PTR matches for the same key * use deauthentication instead of disassociation for all disconnection operations; this removes the now unused disassociate() wpa_driver_ops callback * optimized PSK generation on P2P GO by caching results to avoid multiple PBKDF2 operations * added okc=1 global configuration parameter to allow OKC to be enabled by default for all network blocks * 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 basic support for 60 GHz band * extend EAPOL frames processing workaround for roaming cases (postpone processing of unexpected EAPOL frame until association event to handle reordered events)
This commit is contained in:
parent
681c174ae4
commit
e604d8611d
|
@ -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.
|
||||
|
|
|
@ -4,9 +4,8 @@ wpa_supplicant and hostapd
|
|||
Copyright (c) 2002-2012, Jouni Malinen <j@w1.fi> and contributors
|
||||
All Rights Reserved.
|
||||
|
||||
These programs are dual-licensed under both the GPL version 2 and BSD
|
||||
license (the one with advertisement clause removed). 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.
|
||||
|
@ -26,26 +25,8 @@ builds).
|
|||
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
|
||||
|
|
|
@ -1,18 +1,26 @@
|
|||
# Copyright (C) 2008 The Android Open Source Project
|
||||
#
|
||||
# This software may be distributed under the terms of the BSD license.
|
||||
# See README for more details.
|
||||
#
|
||||
|
||||
LOCAL_PATH := $(call my-dir)
|
||||
|
||||
WPA_BUILD_HOSTAPD := false
|
||||
ifneq ($(TARGET_SIMULATOR),true)
|
||||
ifneq ($(BOARD_HOSTAPD_DRIVER),)
|
||||
WPA_BUILD_HOSTAPD := true
|
||||
CONFIG_DRIVER_$(BOARD_HOSTAPD_DRIVER) := y
|
||||
endif
|
||||
ifneq ($(BOARD_HOSTAPD_DRIVER),)
|
||||
WPA_BUILD_HOSTAPD := true
|
||||
CONFIG_DRIVER_$(BOARD_HOSTAPD_DRIVER) := y
|
||||
endif
|
||||
|
||||
include $(LOCAL_PATH)/.config
|
||||
ifeq ($(WPA_BUILD_HOSTAPD),true)
|
||||
|
||||
include $(LOCAL_PATH)/android.config
|
||||
|
||||
# To ignore possible wrong network configurations
|
||||
L_CFLAGS = -DWPA_IGNORE_CONFIG_ERRORS
|
||||
|
||||
L_CFLAGS += -DVERSION_STR_POSTFIX=\"-$(PLATFORM_VERSION)\"
|
||||
|
||||
# Set Android log name
|
||||
L_CFLAGS += -DANDROID_LOG_NAME=\"hostapd\"
|
||||
|
||||
|
@ -65,6 +73,7 @@ OBJS += src/ap/utils.c
|
|||
OBJS += src/ap/authsrv.c
|
||||
OBJS += src/ap/ieee802_1x.c
|
||||
OBJS += src/ap/ap_config.c
|
||||
OBJS += src/ap/eap_user_db.c
|
||||
OBJS += src/ap/ieee802_11_auth.c
|
||||
OBJS += src/ap/sta_info.c
|
||||
OBJS += src/ap/wpa_auth.c
|
||||
|
@ -143,6 +152,12 @@ ifdef CONFIG_NO_VLAN
|
|||
L_CFLAGS += -DCONFIG_NO_VLAN
|
||||
else
|
||||
OBJS += src/ap/vlan_init.c
|
||||
ifdef CONFIG_VLAN_NETLINK
|
||||
ifdef CONFIG_FULL_DYNAMIC_VLAN
|
||||
OBJS += src/ap/vlan_util.c
|
||||
endif
|
||||
L_CFLAGS += -DCONFIG_VLAN_NETLINK
|
||||
endif
|
||||
endif
|
||||
|
||||
ifdef CONFIG_NO_CTRL_IFACE
|
||||
|
@ -185,6 +200,10 @@ NEED_AES_OMAC1=y
|
|||
NEED_AES_UNWRAP=y
|
||||
endif
|
||||
|
||||
ifdef CONFIG_SAE
|
||||
L_CFLAGS += -DCONFIG_SAE
|
||||
endif
|
||||
|
||||
ifdef CONFIG_IEEE80211N
|
||||
L_CFLAGS += -DCONFIG_IEEE80211N
|
||||
endif
|
||||
|
@ -351,25 +370,10 @@ NEED_AES_CBC=y
|
|||
NEED_MODEXP=y
|
||||
CONFIG_EAP=y
|
||||
|
||||
ifdef CONFIG_WPS_UFD
|
||||
L_CFLAGS += -DCONFIG_WPS_UFD
|
||||
OBJS += src/wps/wps_ufd.c
|
||||
NEED_WPS_OOB=y
|
||||
endif
|
||||
|
||||
ifdef CONFIG_WPS_NFC
|
||||
L_CFLAGS += -DCONFIG_WPS_NFC
|
||||
OBJS += src/wps/ndef.c
|
||||
OBJS += src/wps/wps_nfc.c
|
||||
NEED_WPS_OOB=y
|
||||
ifdef CONFIG_WPS_NFC_PN531
|
||||
PN531_PATH ?= /usr/local/src/nfc
|
||||
L_CFLAGS += -DCONFIG_WPS_NFC_PN531
|
||||
L_CFLAGS += -I${PN531_PATH}/inc
|
||||
OBJS += src/wps/wps_nfc_pn531.c
|
||||
LIBS += ${PN531_PATH}/lib/wpsnfc.dll
|
||||
LIBS += ${PN531_PATH}/lib/libnfc_mapping_pn53x.dll
|
||||
endif
|
||||
endif
|
||||
|
||||
ifdef NEED_WPS_OOB
|
||||
|
@ -655,14 +659,19 @@ endif
|
|||
|
||||
SHA1OBJS =
|
||||
ifdef NEED_SHA1
|
||||
ifneq ($(CONFIG_TLS), openssl)
|
||||
SHA1OBJS += src/crypto/sha1.c
|
||||
endif
|
||||
SHA1OBJS += src/crypto/sha1-prf.c
|
||||
ifdef CONFIG_INTERNAL_SHA1
|
||||
SHA1OBJS += src/crypto/sha1-internal.c
|
||||
ifdef NEED_FIPS186_2_PRF
|
||||
SHA1OBJS += src/crypto/fips_prf_internal.c
|
||||
endif
|
||||
endif
|
||||
ifneq ($(CONFIG_TLS), openssl)
|
||||
SHA1OBJS += src/crypto/sha1-pbkdf2.c
|
||||
endif
|
||||
ifdef NEED_T_PRF
|
||||
SHA1OBJS += src/crypto/sha1-tprf.c
|
||||
endif
|
||||
|
@ -701,10 +710,17 @@ endif
|
|||
endif
|
||||
|
||||
ifdef NEED_SHA256
|
||||
L_CFLAGS += -DCONFIG_SHA256
|
||||
ifneq ($(CONFIG_TLS), openssl)
|
||||
OBJS += src/crypto/sha256.c
|
||||
endif
|
||||
OBJS += src/crypto/sha256-prf.c
|
||||
ifdef CONFIG_INTERNAL_SHA256
|
||||
OBJS += src/crypto/sha256-internal.c
|
||||
endif
|
||||
ifdef NEED_TLS_PRF_SHA256
|
||||
OBJS += ../src/crypto/sha256-tlsprf.c
|
||||
endif
|
||||
endif
|
||||
|
||||
ifdef NEED_DH_GROUPS
|
||||
|
@ -793,8 +809,6 @@ else
|
|||
OBJS_c += src/utils/edit_simple.c
|
||||
endif
|
||||
|
||||
ifeq ($(WPA_BUILD_HOSTAPD),true)
|
||||
|
||||
########################
|
||||
|
||||
include $(CLEAR_VARS)
|
||||
|
|
|
@ -1,30 +1,101 @@
|
|||
ChangeLog for hostapd
|
||||
|
||||
2012-11-06 - v1.1
|
||||
* Fix EAPOL processing when STA switches between multi-BSSes.
|
||||
* EAP-TLS server: Fix a bug with TLS Message Length validation that
|
||||
could result in the process terminating.
|
||||
* Fix memory allocation failure handling in EAP-TTLS/MSCHAPv2 server.
|
||||
* Fix EAP-FAST with OpenSSL 1.0.1.
|
||||
* Fix WPA GTK rekeying with multiple VLANs.
|
||||
* EAP-pwd: Increase maximum number of hunting-and-pecking iterations,
|
||||
which results in less authentication attempts failing.
|
||||
* hlr_auc_gw: Use 5 bit IND for SQN updates. The length of IND can be
|
||||
configured on the command line with the new -i<IND len> parameter.
|
||||
-i0 would make hlr_auc_gw behave the same as the prev implementation.
|
||||
* EAP-AKA'
|
||||
- Update to RFC 5448 in the leading characters used in the username.
|
||||
This will make EAP-AKA' not interoperate between the earlier draft
|
||||
version and the new version.
|
||||
- server: Fix identity for MK derivation, when the EAP client is using
|
||||
pseudonym.
|
||||
* WPS:
|
||||
- Fix nonce comparisons to compare all bytes, not just the first byte.
|
||||
- Fix NFC password token building with WPS 2.0 to avoid wpabuf
|
||||
overflow and application abort if NFC out-of-band mechanism is used
|
||||
with WPS 2.0 enabled.
|
||||
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-04-18 - v1.0
|
||||
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.
|
||||
|
|
|
@ -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
|
||||
|
@ -110,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
|
||||
|
@ -122,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
|
||||
|
@ -164,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)
|
||||
|
@ -203,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
|
||||
|
@ -329,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
|
||||
|
@ -440,6 +454,11 @@ 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
|
||||
|
@ -519,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
|
||||
|
@ -632,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
|
||||
|
@ -678,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
|
||||
|
@ -740,13 +774,25 @@ 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
|
||||
|
@ -765,6 +811,12 @@ 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)
|
||||
|
|
|
@ -5,34 +5,19 @@ hostapd - user space IEEE 802.11 AP and IEEE 802.1X/WPA/WPA2/EAP
|
|||
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
|
||||
|
|
|
@ -66,6 +66,10 @@ 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:
|
||||
|
@ -289,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.
|
||||
|
|
|
@ -0,0 +1,190 @@
|
|||
# Example hostapd build time configuration
|
||||
#
|
||||
# This file lists the configuration options that are used when building the
|
||||
# hostapd binary. All lines starting with # are ignored. Configuration option
|
||||
# lines must be commented out complete, if they are not to be included, i.e.,
|
||||
# just setting VARIABLE=n is not disabling that variable.
|
||||
#
|
||||
# This file is included in Makefile, so variables like CFLAGS and LIBS can also
|
||||
# be modified from here. In most cass, these lines should use += in order not
|
||||
# to override previous values of the variables.
|
||||
|
||||
# Driver interface for Host AP driver
|
||||
#CONFIG_DRIVER_HOSTAP=y
|
||||
|
||||
# Driver interface for wired authenticator
|
||||
#CONFIG_DRIVER_WIRED=y
|
||||
|
||||
# Driver interface for madwifi driver
|
||||
#CONFIG_DRIVER_MADWIFI=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_LIBNL20=y
|
||||
|
||||
# Driver interface for FreeBSD net80211 layer (e.g., Atheros driver)
|
||||
#CONFIG_DRIVER_BSD=y
|
||||
#CFLAGS += -I/usr/local/include
|
||||
#LIBS += -L/usr/local/lib
|
||||
#LIBS_p += -L/usr/local/lib
|
||||
#LIBS_c += -L/usr/local/lib
|
||||
|
||||
# Driver interface for no driver (e.g., RADIUS server only)
|
||||
#CONFIG_DRIVER_NONE=y
|
||||
|
||||
# IEEE 802.11F/IAPP
|
||||
#CONFIG_IAPP=y
|
||||
|
||||
# WPA2/IEEE 802.11i RSN pre-authentication
|
||||
#CONFIG_RSN_PREAUTH=y
|
||||
|
||||
# PeerKey handshake for Station to Station Link (IEEE 802.11e DLS)
|
||||
#CONFIG_PEERKEY=y
|
||||
|
||||
# IEEE 802.11w (management frame protection)
|
||||
# This version is an experimental implementation based on IEEE 802.11w/D1.0
|
||||
# draft and is subject to change since the standard has not yet been finalized.
|
||||
# Driver support is also needed for IEEE 802.11w.
|
||||
#CONFIG_IEEE80211W=y
|
||||
|
||||
# Integrated EAP server
|
||||
#CONFIG_EAP=y
|
||||
|
||||
# EAP-MD5 for the integrated EAP server
|
||||
#CONFIG_EAP_MD5=y
|
||||
|
||||
# EAP-TLS for the integrated EAP server
|
||||
#CONFIG_EAP_TLS=y
|
||||
|
||||
# EAP-MSCHAPv2 for the integrated EAP server
|
||||
#CONFIG_EAP_MSCHAPV2=y
|
||||
|
||||
# EAP-PEAP for the integrated EAP server
|
||||
#CONFIG_EAP_PEAP=y
|
||||
|
||||
# EAP-GTC for the integrated EAP server
|
||||
#CONFIG_EAP_GTC=y
|
||||
|
||||
# EAP-TTLS for the integrated EAP server
|
||||
#CONFIG_EAP_TTLS=y
|
||||
|
||||
# EAP-SIM for the integrated EAP server
|
||||
#CONFIG_EAP_SIM=y
|
||||
|
||||
# EAP-AKA for the integrated EAP server
|
||||
#CONFIG_EAP_AKA=y
|
||||
|
||||
# EAP-AKA' for the integrated EAP server
|
||||
# This requires CONFIG_EAP_AKA to be enabled, too.
|
||||
#CONFIG_EAP_AKA_PRIME=y
|
||||
|
||||
# EAP-PAX for the integrated EAP server
|
||||
#CONFIG_EAP_PAX=y
|
||||
|
||||
# EAP-PSK for the integrated EAP server (this is _not_ needed for WPA-PSK)
|
||||
#CONFIG_EAP_PSK=y
|
||||
|
||||
# EAP-SAKE for the integrated EAP server
|
||||
#CONFIG_EAP_SAKE=y
|
||||
|
||||
# EAP-GPSK for the integrated EAP server
|
||||
#CONFIG_EAP_GPSK=y
|
||||
# Include support for optional SHA256 cipher suite in EAP-GPSK
|
||||
#CONFIG_EAP_GPSK_SHA256=y
|
||||
|
||||
# EAP-FAST for the integrated EAP server
|
||||
# Note: Default OpenSSL package does not include support for all the
|
||||
# functionality needed for EAP-FAST. If EAP-FAST is enabled with OpenSSL,
|
||||
# the OpenSSL library must be patched (openssl-0.9.9-session-ticket.patch)
|
||||
# to add the needed functions.
|
||||
#CONFIG_EAP_FAST=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
|
||||
|
||||
# EAP-IKEv2
|
||||
#CONFIG_EAP_IKEV2=y
|
||||
|
||||
# Trusted Network Connect (EAP-TNC)
|
||||
#CONFIG_EAP_TNC=y
|
||||
|
||||
# PKCS#12 (PFX) support (used to read private key and certificate file from
|
||||
# a file that usually has extension .p12 or .pfx)
|
||||
CONFIG_PKCS12=y
|
||||
|
||||
# RADIUS authentication server. This provides access to the integrated EAP
|
||||
# server from external hosts using RADIUS.
|
||||
#CONFIG_RADIUS_SERVER=y
|
||||
|
||||
# Build IPv6 support for RADIUS operations
|
||||
CONFIG_IPV6=y
|
||||
|
||||
# IEEE Std 802.11r-2008 (Fast BSS Transition)
|
||||
#CONFIG_IEEE80211R=y
|
||||
|
||||
# Use the hostapd's IEEE 802.11 authentication (ACL), but without
|
||||
# the IEEE 802.11 Management capability (e.g., madwifi or FreeBSD/net80211)
|
||||
#CONFIG_DRIVER_RADIUS_ACL=y
|
||||
|
||||
# IEEE 802.11n (High Throughput) support
|
||||
CONFIG_IEEE80211N=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 Android logcat instead of standard output
|
||||
CONFIG_ANDROID_LOG=y
|
||||
|
||||
# Remove support for RADIUS accounting
|
||||
#CONFIG_NO_ACCOUNTING=y
|
||||
|
||||
# Remove support for RADIUS
|
||||
CONFIG_NO_RADIUS=y
|
||||
|
||||
# Remove support for VLANs
|
||||
#CONFIG_NO_VLAN=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.
|
||||
#CONFIG_NO_DUMP_STATE=y
|
||||
|
||||
# Select wrapper for operatins system and C library specific functions
|
||||
# unix = UNIX/POSIX like systems (default)
|
||||
# win32 = Windows systems
|
||||
# none = Empty template
|
||||
CONFIG_OS=unix
|
||||
|
||||
# Enable tracing code for developer debugging
|
||||
# This tracks use of memory allocations and other registrations and reports
|
||||
# incorrect use with a backtrace of call (or allocation) location.
|
||||
#CONFIG_WPA_TRACE=y
|
||||
# For BSD, comment out these.
|
||||
#LIBS += -lexecinfo
|
||||
#LIBS_p += -lexecinfo
|
||||
#LIBS_c += -lexecinfo
|
||||
|
||||
# Use libbfd to get more details for developer debugging
|
||||
# This enables use of libbfd to get more detailed symbols for the backtraces
|
||||
# generated by CONFIG_WPA_TRACE=y.
|
||||
#CONFIG_WPA_TRACE_BFD=y
|
||||
# For BSD, comment out these.
|
||||
#LIBS += -lbfd -liberty -lz
|
||||
#LIBS_p += -lbfd -liberty -lz
|
||||
#LIBS_c += -lbfd -liberty -lz
|
||||
|
||||
# Enable AP
|
||||
CONFIG_AP=y
|
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 */
|
||||
|
|
|
@ -1,15 +1,9 @@
|
|||
/*
|
||||
* hostapd / UNIX domain socket -based control interface
|
||||
* 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 "utils/includes.h"
|
||||
|
@ -32,12 +26,12 @@
|
|||
#include "ap/wpa_auth.h"
|
||||
#include "ap/ieee802_11.h"
|
||||
#include "ap/sta_info.h"
|
||||
#include "ap/accounting.h"
|
||||
#include "ap/wps_hostapd.h"
|
||||
#include "ap/ctrl_iface_ap.h"
|
||||
#include "ap/ap_drv_ops.h"
|
||||
#include "wps/wps_defs.h"
|
||||
#include "wps/wps.h"
|
||||
#include "config_file.h"
|
||||
#include "ctrl_iface.h"
|
||||
|
||||
|
||||
|
@ -159,171 +153,6 @@ static int hostapd_ctrl_iface_new_sta(struct hostapd_data *hapd,
|
|||
}
|
||||
|
||||
|
||||
#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_printf(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 */
|
||||
|
||||
|
||||
static int hostapd_ctrl_iface_deauthenticate(struct hostapd_data *hapd,
|
||||
const char *txtaddr)
|
||||
{
|
||||
u8 addr[ETH_ALEN];
|
||||
struct sta_info *sta;
|
||||
const char *pos;
|
||||
|
||||
wpa_printf(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;
|
||||
}
|
||||
|
||||
|
||||
static int hostapd_ctrl_iface_disassociate(struct hostapd_data *hapd,
|
||||
const char *txtaddr)
|
||||
{
|
||||
u8 addr[ETH_ALEN];
|
||||
struct sta_info *sta;
|
||||
const char *pos;
|
||||
|
||||
wpa_printf(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;
|
||||
}
|
||||
|
||||
|
||||
#ifdef CONFIG_IEEE80211W
|
||||
#ifdef NEED_AP_MLME
|
||||
static int hostapd_ctrl_iface_sa_query(struct hostapd_data *hapd,
|
||||
|
@ -421,28 +250,109 @@ static int hostapd_ctrl_iface_wps_check_pin(
|
|||
}
|
||||
|
||||
|
||||
#ifdef CONFIG_WPS_OOB
|
||||
static int hostapd_ctrl_iface_wps_oob(struct hostapd_data *hapd, char *txt)
|
||||
#ifdef CONFIG_WPS_NFC
|
||||
static int hostapd_ctrl_iface_wps_nfc_tag_read(struct hostapd_data *hapd,
|
||||
char *pos)
|
||||
{
|
||||
char *path, *method, *name;
|
||||
size_t len;
|
||||
struct wpabuf *buf;
|
||||
int ret;
|
||||
|
||||
path = os_strchr(txt, ' ');
|
||||
if (path == NULL)
|
||||
len = os_strlen(pos);
|
||||
if (len & 0x01)
|
||||
return -1;
|
||||
*path++ = '\0';
|
||||
len /= 2;
|
||||
|
||||
method = os_strchr(path, ' ');
|
||||
if (method == NULL)
|
||||
buf = wpabuf_alloc(len);
|
||||
if (buf == NULL)
|
||||
return -1;
|
||||
*method++ = '\0';
|
||||
if (hexstr2bin(pos, wpabuf_put(buf, len), len) < 0) {
|
||||
wpabuf_free(buf);
|
||||
return -1;
|
||||
}
|
||||
|
||||
name = os_strchr(method, ' ');
|
||||
if (name != NULL)
|
||||
*name++ = '\0';
|
||||
ret = hostapd_wps_nfc_tag_read(hapd, buf);
|
||||
wpabuf_free(buf);
|
||||
|
||||
return hostapd_wps_start_oob(hapd, txt, path, method, name);
|
||||
return ret;
|
||||
}
|
||||
#endif /* CONFIG_WPS_OOB */
|
||||
|
||||
|
||||
static int hostapd_ctrl_iface_wps_nfc_config_token(struct hostapd_data *hapd,
|
||||
char *cmd, char *reply,
|
||||
size_t max_len)
|
||||
{
|
||||
int ndef;
|
||||
struct wpabuf *buf;
|
||||
int res;
|
||||
|
||||
if (os_strcmp(cmd, "WPS") == 0)
|
||||
ndef = 0;
|
||||
else if (os_strcmp(cmd, "NDEF") == 0)
|
||||
ndef = 1;
|
||||
else
|
||||
return -1;
|
||||
|
||||
buf = hostapd_wps_nfc_config_token(hapd, ndef);
|
||||
if (buf == NULL)
|
||||
return -1;
|
||||
|
||||
res = wpa_snprintf_hex_uppercase(reply, max_len, wpabuf_head(buf),
|
||||
wpabuf_len(buf));
|
||||
reply[res++] = '\n';
|
||||
reply[res] = '\0';
|
||||
|
||||
wpabuf_free(buf);
|
||||
|
||||
return res;
|
||||
}
|
||||
|
||||
|
||||
static int hostapd_ctrl_iface_wps_nfc_token_gen(struct hostapd_data *hapd,
|
||||
char *reply, size_t max_len,
|
||||
int ndef)
|
||||
{
|
||||
struct wpabuf *buf;
|
||||
int res;
|
||||
|
||||
buf = hostapd_wps_nfc_token_gen(hapd, ndef);
|
||||
if (buf == NULL)
|
||||
return -1;
|
||||
|
||||
res = wpa_snprintf_hex_uppercase(reply, max_len, wpabuf_head(buf),
|
||||
wpabuf_len(buf));
|
||||
reply[res++] = '\n';
|
||||
reply[res] = '\0';
|
||||
|
||||
wpabuf_free(buf);
|
||||
|
||||
return res;
|
||||
}
|
||||
|
||||
|
||||
static int hostapd_ctrl_iface_wps_nfc_token(struct hostapd_data *hapd,
|
||||
char *cmd, char *reply,
|
||||
size_t max_len)
|
||||
{
|
||||
if (os_strcmp(cmd, "WPS") == 0)
|
||||
return hostapd_ctrl_iface_wps_nfc_token_gen(hapd, reply,
|
||||
max_len, 0);
|
||||
|
||||
if (os_strcmp(cmd, "NDEF") == 0)
|
||||
return hostapd_ctrl_iface_wps_nfc_token_gen(hapd, reply,
|
||||
max_len, 1);
|
||||
|
||||
if (os_strcmp(cmd, "enable") == 0)
|
||||
return hostapd_wps_nfc_token_enable(hapd);
|
||||
|
||||
if (os_strcmp(cmd, "disable") == 0) {
|
||||
hostapd_wps_nfc_token_disable(hapd);
|
||||
return 0;
|
||||
}
|
||||
|
||||
return -1;
|
||||
}
|
||||
#endif /* CONFIG_WPS_NFC */
|
||||
|
||||
|
||||
static int hostapd_ctrl_iface_wps_ap_pin(struct hostapd_data *hapd, char *txt,
|
||||
|
@ -526,6 +436,50 @@ static int hostapd_ctrl_iface_wps_config(struct hostapd_data *hapd, char *txt)
|
|||
#endif /* CONFIG_WPS */
|
||||
|
||||
|
||||
#ifdef CONFIG_WNM
|
||||
|
||||
static int hostapd_ctrl_iface_disassoc_imminent(struct hostapd_data *hapd,
|
||||
const char *cmd)
|
||||
{
|
||||
u8 addr[ETH_ALEN];
|
||||
u8 buf[1000], *pos;
|
||||
struct ieee80211_mgmt *mgmt;
|
||||
int disassoc_timer;
|
||||
|
||||
if (hwaddr_aton(cmd, addr))
|
||||
return -1;
|
||||
if (cmd[17] != ' ')
|
||||
return -1;
|
||||
disassoc_timer = atoi(cmd + 17);
|
||||
|
||||
os_memset(buf, 0, sizeof(buf));
|
||||
mgmt = (struct ieee80211_mgmt *) buf;
|
||||
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_WNM;
|
||||
mgmt->u.action.u.bss_tm_req.action = WNM_BSS_TRANS_MGMT_REQ;
|
||||
mgmt->u.action.u.bss_tm_req.dialog_token = 1;
|
||||
mgmt->u.action.u.bss_tm_req.req_mode =
|
||||
WNM_BSS_TM_REQ_DISASSOC_IMMINENT;
|
||||
mgmt->u.action.u.bss_tm_req.disassoc_timer =
|
||||
host_to_le16(disassoc_timer);
|
||||
mgmt->u.action.u.bss_tm_req.validity_interval = 0;
|
||||
|
||||
pos = mgmt->u.action.u.bss_tm_req.variable;
|
||||
|
||||
if (hostapd_drv_send_mlme(hapd, buf, pos - buf, 0) < 0) {
|
||||
wpa_printf(MSG_DEBUG, "Failed to send BSS Transition "
|
||||
"Management Request frame");
|
||||
return -1;
|
||||
}
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
|
||||
static int hostapd_ctrl_iface_ess_disassoc(struct hostapd_data *hapd,
|
||||
const char *cmd)
|
||||
{
|
||||
|
@ -567,7 +521,7 @@ static int hostapd_ctrl_iface_ess_disassoc(struct hostapd_data *hapd,
|
|||
os_memcpy(pos, url, url_len);
|
||||
pos += url_len;
|
||||
|
||||
if (hostapd_drv_send_mlme(hapd, buf, pos - buf) < 0) {
|
||||
if (hostapd_drv_send_mlme(hapd, buf, pos - buf, 0) < 0) {
|
||||
wpa_printf(MSG_DEBUG, "Failed to send BSS Transition "
|
||||
"Management Request frame");
|
||||
return -1;
|
||||
|
@ -576,6 +530,8 @@ static int hostapd_ctrl_iface_ess_disassoc(struct hostapd_data *hapd,
|
|||
return 0;
|
||||
}
|
||||
|
||||
#endif /* CONFIG_WNM */
|
||||
|
||||
|
||||
static int hostapd_ctrl_iface_get_config(struct hostapd_data *hapd,
|
||||
char *buf, size_t buflen)
|
||||
|
@ -589,7 +545,8 @@ static int hostapd_ctrl_iface_get_config(struct hostapd_data *hapd,
|
|||
ret = os_snprintf(pos, end - pos, "bssid=" MACSTR "\n"
|
||||
"ssid=%s\n",
|
||||
MAC2STR(hapd->own_addr),
|
||||
hapd->conf->ssid.ssid);
|
||||
wpa_ssid_txt(hapd->conf->ssid.ssid,
|
||||
hapd->conf->ssid.ssid_len));
|
||||
if (ret < 0 || ret >= end - pos)
|
||||
return pos - buf;
|
||||
pos += ret;
|
||||
|
@ -683,6 +640,12 @@ static int hostapd_ctrl_iface_get_config(struct hostapd_data *hapd,
|
|||
if (ret < 0 || ret >= end - pos)
|
||||
return pos - buf;
|
||||
pos += ret;
|
||||
} else if (hapd->conf->wpa &&
|
||||
hapd->conf->wpa_group == WPA_CIPHER_GCMP) {
|
||||
ret = os_snprintf(pos, end - pos, "group_cipher=GCMP\n");
|
||||
if (ret < 0 || ret >= end - pos)
|
||||
return pos - buf;
|
||||
pos += ret;
|
||||
} else if (hapd->conf->wpa &&
|
||||
hapd->conf->wpa_group == WPA_CIPHER_TKIP) {
|
||||
ret = os_snprintf(pos, end - pos, "group_cipher=TKIP\n");
|
||||
|
@ -703,6 +666,12 @@ static int hostapd_ctrl_iface_get_config(struct hostapd_data *hapd,
|
|||
return pos - buf;
|
||||
pos += ret;
|
||||
}
|
||||
if (hapd->conf->rsn_pairwise & WPA_CIPHER_GCMP) {
|
||||
ret = os_snprintf(pos, end - pos, "GCMP ");
|
||||
if (ret < 0 || ret >= end - pos)
|
||||
return pos - buf;
|
||||
pos += ret;
|
||||
}
|
||||
if (hapd->conf->rsn_pairwise & WPA_CIPHER_TKIP) {
|
||||
ret = os_snprintf(pos, end - pos, "TKIP ");
|
||||
if (ret < 0 || ret >= end - pos)
|
||||
|
@ -728,6 +697,12 @@ static int hostapd_ctrl_iface_get_config(struct hostapd_data *hapd,
|
|||
return pos - buf;
|
||||
pos += ret;
|
||||
}
|
||||
if (hapd->conf->wpa_pairwise & WPA_CIPHER_GCMP) {
|
||||
ret = os_snprintf(pos, end - pos, "GCMP ");
|
||||
if (ret < 0 || ret >= end - pos)
|
||||
return pos - buf;
|
||||
pos += ret;
|
||||
}
|
||||
if (hapd->conf->wpa_pairwise & WPA_CIPHER_TKIP) {
|
||||
ret = os_snprintf(pos, end - pos, "TKIP ");
|
||||
if (ret < 0 || ret >= end - pos)
|
||||
|
@ -778,8 +753,16 @@ static int hostapd_ctrl_iface_set(struct hostapd_data *hapd, char *cmd)
|
|||
wpa_printf(MSG_DEBUG, "WPS: Testing - dummy_cred=%d",
|
||||
wps_testing_dummy_cred);
|
||||
#endif /* CONFIG_WPS_TESTING */
|
||||
#ifdef CONFIG_INTERWORKING
|
||||
} else if (os_strcasecmp(cmd, "gas_frag_limit") == 0) {
|
||||
int val = atoi(value);
|
||||
if (val <= 0)
|
||||
ret = -1;
|
||||
else
|
||||
hapd->gas_frag_limit = val;
|
||||
#endif /* CONFIG_INTERWORKING */
|
||||
} else {
|
||||
ret = -1;
|
||||
ret = hostapd_set_iface(hapd->iconf, hapd->conf, cmd, value);
|
||||
}
|
||||
|
||||
return ret;
|
||||
|
@ -804,6 +787,36 @@ static int hostapd_ctrl_iface_get(struct hostapd_data *hapd, char *cmd,
|
|||
}
|
||||
|
||||
|
||||
static int hostapd_ctrl_iface_enable(struct hostapd_iface *iface)
|
||||
{
|
||||
if (hostapd_enable_iface(iface) < 0) {
|
||||
wpa_printf(MSG_ERROR, "Enabling of interface failed");
|
||||
return -1;
|
||||
}
|
||||
return 0;
|
||||
}
|
||||
|
||||
|
||||
static int hostapd_ctrl_iface_reload(struct hostapd_iface *iface)
|
||||
{
|
||||
if (hostapd_reload_iface(iface) < 0) {
|
||||
wpa_printf(MSG_ERROR, "Reloading of interface failed");
|
||||
return -1;
|
||||
}
|
||||
return 0;
|
||||
}
|
||||
|
||||
|
||||
static int hostapd_ctrl_iface_disable(struct hostapd_iface *iface)
|
||||
{
|
||||
if (hostapd_disable_iface(iface) < 0) {
|
||||
wpa_printf(MSG_ERROR, "Disabling of interface failed");
|
||||
return -1;
|
||||
}
|
||||
return 0;
|
||||
}
|
||||
|
||||
|
||||
static void hostapd_ctrl_iface_receive(int sock, void *eloop_ctx,
|
||||
void *sock_ctx)
|
||||
{
|
||||
|
@ -918,21 +931,35 @@ static void hostapd_ctrl_iface_receive(int sock, void *eloop_ctx,
|
|||
} else if (os_strcmp(buf, "WPS_PBC") == 0) {
|
||||
if (hostapd_wps_button_pushed(hapd, NULL))
|
||||
reply_len = -1;
|
||||
#ifdef CONFIG_WPS_OOB
|
||||
} else if (os_strncmp(buf, "WPS_OOB ", 8) == 0) {
|
||||
if (hostapd_ctrl_iface_wps_oob(hapd, buf + 8))
|
||||
} else if (os_strcmp(buf, "WPS_CANCEL") == 0) {
|
||||
if (hostapd_wps_cancel(hapd))
|
||||
reply_len = -1;
|
||||
#endif /* CONFIG_WPS_OOB */
|
||||
} else if (os_strncmp(buf, "WPS_AP_PIN ", 11) == 0) {
|
||||
reply_len = hostapd_ctrl_iface_wps_ap_pin(hapd, buf + 11,
|
||||
reply, reply_size);
|
||||
} else if (os_strncmp(buf, "WPS_CONFIG ", 11) == 0) {
|
||||
if (hostapd_ctrl_iface_wps_config(hapd, buf + 11) < 0)
|
||||
reply_len = -1;
|
||||
#ifdef CONFIG_WPS_NFC
|
||||
} else if (os_strncmp(buf, "WPS_NFC_TAG_READ ", 17) == 0) {
|
||||
if (hostapd_ctrl_iface_wps_nfc_tag_read(hapd, buf + 17))
|
||||
reply_len = -1;
|
||||
} else if (os_strncmp(buf, "WPS_NFC_CONFIG_TOKEN ", 21) == 0) {
|
||||
reply_len = hostapd_ctrl_iface_wps_nfc_config_token(
|
||||
hapd, buf + 21, reply, reply_size);
|
||||
} else if (os_strncmp(buf, "WPS_NFC_TOKEN ", 14) == 0) {
|
||||
reply_len = hostapd_ctrl_iface_wps_nfc_token(
|
||||
hapd, buf + 14, reply, reply_size);
|
||||
#endif /* CONFIG_WPS_NFC */
|
||||
#endif /* CONFIG_WPS */
|
||||
#ifdef CONFIG_WNM
|
||||
} else if (os_strncmp(buf, "DISASSOC_IMMINENT ", 18) == 0) {
|
||||
if (hostapd_ctrl_iface_disassoc_imminent(hapd, buf + 18))
|
||||
reply_len = -1;
|
||||
} else if (os_strncmp(buf, "ESS_DISASSOC ", 13) == 0) {
|
||||
if (hostapd_ctrl_iface_ess_disassoc(hapd, buf + 13))
|
||||
reply_len = -1;
|
||||
#endif /* CONFIG_WNM */
|
||||
} else if (os_strcmp(buf, "GET_CONFIG") == 0) {
|
||||
reply_len = hostapd_ctrl_iface_get_config(hapd, reply,
|
||||
reply_size);
|
||||
|
@ -942,6 +969,15 @@ static void hostapd_ctrl_iface_receive(int sock, void *eloop_ctx,
|
|||
} else if (os_strncmp(buf, "GET ", 4) == 0) {
|
||||
reply_len = hostapd_ctrl_iface_get(hapd, buf + 4, reply,
|
||||
reply_size);
|
||||
} else if (os_strncmp(buf, "ENABLE", 6) == 0) {
|
||||
if (hostapd_ctrl_iface_enable(hapd->iface))
|
||||
reply_len = -1;
|
||||
} else if (os_strncmp(buf, "RELOAD", 6) == 0) {
|
||||
if (hostapd_ctrl_iface_reload(hapd->iface))
|
||||
reply_len = -1;
|
||||
} else if (os_strncmp(buf, "DISABLE", 7) == 0) {
|
||||
if (hostapd_ctrl_iface_disable(hapd->iface))
|
||||
reply_len = -1;
|
||||
} else {
|
||||
os_memcpy(reply, "UNKNOWN COMMAND\n", 16);
|
||||
reply_len = 16;
|
||||
|
@ -993,7 +1029,10 @@ int hostapd_ctrl_iface_init(struct hostapd_data *hapd)
|
|||
int s = -1;
|
||||
char *fname = NULL;
|
||||
|
||||
hapd->ctrl_sock = -1;
|
||||
if (hapd->ctrl_sock > -1) {
|
||||
wpa_printf(MSG_DEBUG, "ctrl_iface already exists!");
|
||||
return 0;
|
||||
}
|
||||
|
||||
if (hapd->conf->ctrl_interface == NULL)
|
||||
return 0;
|
||||
|
@ -1009,12 +1048,27 @@ int hostapd_ctrl_iface_init(struct hostapd_data *hapd)
|
|||
}
|
||||
|
||||
if (hapd->conf->ctrl_interface_gid_set &&
|
||||
chown(hapd->conf->ctrl_interface, 0,
|
||||
chown(hapd->conf->ctrl_interface, -1,
|
||||
hapd->conf->ctrl_interface_gid) < 0) {
|
||||
perror("chown[ctrl_interface]");
|
||||
return -1;
|
||||
}
|
||||
|
||||
#ifdef ANDROID
|
||||
/*
|
||||
* Android is using umask 0077 which would leave the control interface
|
||||
* directory without group access. This breaks things since Wi-Fi
|
||||
* framework assumes that this directory can be accessed by other
|
||||
* applications in the wifi group. Fix this by adding group access even
|
||||
* if umask value would prevent this.
|
||||
*/
|
||||
if (chmod(hapd->conf->ctrl_interface, S_IRWXU | S_IRWXG) < 0) {
|
||||
wpa_printf(MSG_ERROR, "CTRL: Could not chmod directory: %s",
|
||||
strerror(errno));
|
||||
/* Try to continue anyway */
|
||||
}
|
||||
#endif /* ANDROID */
|
||||
|
||||
if (os_strlen(hapd->conf->ctrl_interface) + 1 +
|
||||
os_strlen(hapd->conf->iface) >= sizeof(addr.sun_path))
|
||||
goto fail;
|
||||
|
@ -1050,7 +1104,7 @@ int hostapd_ctrl_iface_init(struct hostapd_data *hapd)
|
|||
}
|
||||
if (bind(s, (struct sockaddr *) &addr, sizeof(addr)) <
|
||||
0) {
|
||||
perror("bind(PF_UNIX)");
|
||||
perror("hostapd-ctrl-iface: bind(PF_UNIX)");
|
||||
goto fail;
|
||||
}
|
||||
wpa_printf(MSG_DEBUG, "Successfully replaced leftover "
|
||||
|
@ -1067,7 +1121,7 @@ int hostapd_ctrl_iface_init(struct hostapd_data *hapd)
|
|||
}
|
||||
|
||||
if (hapd->conf->ctrl_interface_gid_set &&
|
||||
chown(fname, 0, hapd->conf->ctrl_interface_gid) < 0) {
|
||||
chown(fname, -1, hapd->conf->ctrl_interface_gid) < 0) {
|
||||
perror("chown[ctrl_interface/ifname]");
|
||||
goto fail;
|
||||
}
|
||||
|
@ -1132,6 +1186,220 @@ void hostapd_ctrl_iface_deinit(struct hostapd_data *hapd)
|
|||
}
|
||||
|
||||
|
||||
static int hostapd_ctrl_iface_add(struct hapd_interfaces *interfaces,
|
||||
char *buf)
|
||||
{
|
||||
if (hostapd_add_iface(interfaces, buf) < 0) {
|
||||
wpa_printf(MSG_ERROR, "Adding interface %s failed", buf);
|
||||
return -1;
|
||||
}
|
||||
return 0;
|
||||
}
|
||||
|
||||
|
||||
static int hostapd_ctrl_iface_remove(struct hapd_interfaces *interfaces,
|
||||
char *buf)
|
||||
{
|
||||
if (hostapd_remove_iface(interfaces, buf) < 0) {
|
||||
wpa_printf(MSG_ERROR, "Removing interface %s failed", buf);
|
||||
return -1;
|
||||
}
|
||||
return 0;
|
||||
}
|
||||
|
||||
|
||||
static void hostapd_global_ctrl_iface_receive(int sock, void *eloop_ctx,
|
||||
void *sock_ctx)
|
||||
{
|
||||
void *interfaces = eloop_ctx;
|
||||
char buf[256];
|
||||
int res;
|
||||
struct sockaddr_un from;
|
||||
socklen_t fromlen = sizeof(from);
|
||||
char reply[24];
|
||||
int reply_len;
|
||||
|
||||
res = recvfrom(sock, buf, sizeof(buf) - 1, 0,
|
||||
(struct sockaddr *) &from, &fromlen);
|
||||
if (res < 0) {
|
||||
perror("recvfrom(ctrl_iface)");
|
||||
return;
|
||||
}
|
||||
buf[res] = '\0';
|
||||
|
||||
os_memcpy(reply, "OK\n", 3);
|
||||
reply_len = 3;
|
||||
|
||||
if (os_strcmp(buf, "PING") == 0) {
|
||||
os_memcpy(reply, "PONG\n", 5);
|
||||
reply_len = 5;
|
||||
} else if (os_strncmp(buf, "ADD ", 4) == 0) {
|
||||
if (hostapd_ctrl_iface_add(interfaces, buf + 4) < 0)
|
||||
reply_len = -1;
|
||||
} else if (os_strncmp(buf, "REMOVE ", 7) == 0) {
|
||||
if (hostapd_ctrl_iface_remove(interfaces, buf + 7) < 0)
|
||||
reply_len = -1;
|
||||
} else {
|
||||
wpa_printf(MSG_DEBUG, "Unrecognized global ctrl_iface command "
|
||||
"ignored");
|
||||
reply_len = -1;
|
||||
}
|
||||
|
||||
if (reply_len < 0) {
|
||||
os_memcpy(reply, "FAIL\n", 5);
|
||||
reply_len = 5;
|
||||
}
|
||||
|
||||
sendto(sock, reply, reply_len, 0, (struct sockaddr *) &from, fromlen);
|
||||
}
|
||||
|
||||
|
||||
static char * hostapd_global_ctrl_iface_path(struct hapd_interfaces *interface)
|
||||
{
|
||||
char *buf;
|
||||
size_t len;
|
||||
|
||||
if (interface->global_iface_path == NULL)
|
||||
return NULL;
|
||||
|
||||
len = os_strlen(interface->global_iface_path) +
|
||||
os_strlen(interface->global_iface_name) + 2;
|
||||
buf = os_malloc(len);
|
||||
if (buf == NULL)
|
||||
return NULL;
|
||||
|
||||
os_snprintf(buf, len, "%s/%s", interface->global_iface_path,
|
||||
interface->global_iface_name);
|
||||
buf[len - 1] = '\0';
|
||||
return buf;
|
||||
}
|
||||
|
||||
|
||||
int hostapd_global_ctrl_iface_init(struct hapd_interfaces *interface)
|
||||
{
|
||||
struct sockaddr_un addr;
|
||||
int s = -1;
|
||||
char *fname = NULL;
|
||||
|
||||
if (interface->global_iface_path == NULL) {
|
||||
wpa_printf(MSG_DEBUG, "ctrl_iface not configured!");
|
||||
return 0;
|
||||
}
|
||||
|
||||
if (mkdir(interface->global_iface_path, S_IRWXU | S_IRWXG) < 0) {
|
||||
if (errno == EEXIST) {
|
||||
wpa_printf(MSG_DEBUG, "Using existing control "
|
||||
"interface directory.");
|
||||
} else {
|
||||
perror("mkdir[ctrl_interface]");
|
||||
goto fail;
|
||||
}
|
||||
}
|
||||
|
||||
if (os_strlen(interface->global_iface_path) + 1 +
|
||||
os_strlen(interface->global_iface_name) >= sizeof(addr.sun_path))
|
||||
goto fail;
|
||||
|
||||
s = socket(PF_UNIX, SOCK_DGRAM, 0);
|
||||
if (s < 0) {
|
||||
perror("socket(PF_UNIX)");
|
||||
goto fail;
|
||||
}
|
||||
|
||||
os_memset(&addr, 0, sizeof(addr));
|
||||
#ifdef __FreeBSD__
|
||||
addr.sun_len = sizeof(addr);
|
||||
#endif /* __FreeBSD__ */
|
||||
addr.sun_family = AF_UNIX;
|
||||
fname = hostapd_global_ctrl_iface_path(interface);
|
||||
if (fname == NULL)
|
||||
goto fail;
|
||||
os_strlcpy(addr.sun_path, fname, sizeof(addr.sun_path));
|
||||
if (bind(s, (struct sockaddr *) &addr, sizeof(addr)) < 0) {
|
||||
wpa_printf(MSG_DEBUG, "ctrl_iface bind(PF_UNIX) failed: %s",
|
||||
strerror(errno));
|
||||
if (connect(s, (struct sockaddr *) &addr, sizeof(addr)) < 0) {
|
||||
wpa_printf(MSG_DEBUG, "ctrl_iface exists, but does not"
|
||||
" allow connections - assuming it was left"
|
||||
"over from forced program termination");
|
||||
if (unlink(fname) < 0) {
|
||||
perror("unlink[ctrl_iface]");
|
||||
wpa_printf(MSG_ERROR, "Could not unlink "
|
||||
"existing ctrl_iface socket '%s'",
|
||||
fname);
|
||||
goto fail;
|
||||
}
|
||||
if (bind(s, (struct sockaddr *) &addr, sizeof(addr)) <
|
||||
0) {
|
||||
perror("bind(PF_UNIX)");
|
||||
goto fail;
|
||||
}
|
||||
wpa_printf(MSG_DEBUG, "Successfully replaced leftover "
|
||||
"ctrl_iface socket '%s'", fname);
|
||||
} else {
|
||||
wpa_printf(MSG_INFO, "ctrl_iface exists and seems to "
|
||||
"be in use - cannot override it");
|
||||
wpa_printf(MSG_INFO, "Delete '%s' manually if it is "
|
||||
"not used anymore", fname);
|
||||
os_free(fname);
|
||||
fname = NULL;
|
||||
goto fail;
|
||||
}
|
||||
}
|
||||
|
||||
if (chmod(fname, S_IRWXU | S_IRWXG) < 0) {
|
||||
perror("chmod[ctrl_interface/ifname]");
|
||||
goto fail;
|
||||
}
|
||||
os_free(fname);
|
||||
|
||||
interface->global_ctrl_sock = s;
|
||||
eloop_register_read_sock(s, hostapd_global_ctrl_iface_receive,
|
||||
interface, NULL);
|
||||
|
||||
return 0;
|
||||
|
||||
fail:
|
||||
if (s >= 0)
|
||||
close(s);
|
||||
if (fname) {
|
||||
unlink(fname);
|
||||
os_free(fname);
|
||||
}
|
||||
return -1;
|
||||
}
|
||||
|
||||
|
||||
void hostapd_global_ctrl_iface_deinit(struct hapd_interfaces *interfaces)
|
||||
{
|
||||
char *fname = NULL;
|
||||
|
||||
if (interfaces->global_ctrl_sock > -1) {
|
||||
eloop_unregister_read_sock(interfaces->global_ctrl_sock);
|
||||
close(interfaces->global_ctrl_sock);
|
||||
interfaces->global_ctrl_sock = -1;
|
||||
fname = hostapd_global_ctrl_iface_path(interfaces);
|
||||
if (fname) {
|
||||
unlink(fname);
|
||||
os_free(fname);
|
||||
}
|
||||
|
||||
if (interfaces->global_iface_path &&
|
||||
rmdir(interfaces->global_iface_path) < 0) {
|
||||
if (errno == ENOTEMPTY) {
|
||||
wpa_printf(MSG_DEBUG, "Control interface "
|
||||
"directory not empty - leaving it "
|
||||
"behind");
|
||||
} else {
|
||||
perror("rmdir[ctrl_interface]");
|
||||
}
|
||||
}
|
||||
os_free(interfaces->global_iface_path);
|
||||
interfaces->global_iface_path = NULL;
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
static void hostapd_ctrl_iface_send(struct hostapd_data *hapd, int level,
|
||||
const char *buf, size_t len)
|
||||
{
|
||||
|
|
|
@ -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 */
|
||||
|
|
|
@ -108,6 +108,8 @@ CONFIG_EAP_TTLS=y
|
|||
#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
|
||||
|
@ -136,6 +138,13 @@ 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.
|
||||
|
@ -158,6 +167,10 @@ CONFIG_IPV6=y
|
|||
# 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.
|
||||
|
@ -224,6 +237,10 @@ CONFIG_IPV6=y
|
|||
# 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
|
||||
|
@ -244,3 +261,9 @@ CONFIG_IPV6=y
|
|||
# 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,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.
|
||||
*/
|
||||
|
||||
#include "utils/includes.h"
|
||||
|
|
|
@ -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();
|
||||
|
|
|
@ -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
|
||||
|
@ -49,6 +43,9 @@
|
|||
|
||||
#include "includes.h"
|
||||
#include <sys/un.h>
|
||||
#ifdef CONFIG_SQLITE
|
||||
#include <sqlite3.h>
|
||||
#endif /* CONFIG_SQLITE */
|
||||
|
||||
#include "common.h"
|
||||
#include "crypto/milenage.h"
|
||||
|
@ -57,6 +54,9 @@
|
|||
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 */
|
||||
|
@ -78,6 +78,7 @@ struct milenage_parameters {
|
|||
u8 opc[16];
|
||||
u8 amf[2];
|
||||
u8 sqn[6];
|
||||
int set;
|
||||
};
|
||||
|
||||
static struct milenage_parameters *milenage_db = NULL;
|
||||
|
@ -92,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;
|
||||
|
@ -107,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;
|
||||
}
|
||||
|
@ -221,7 +360,7 @@ static int read_gsm_triplets(const char *fname)
|
|||
gsm_db = g;
|
||||
g = NULL;
|
||||
}
|
||||
free(g);
|
||||
os_free(g);
|
||||
|
||||
fclose(f);
|
||||
|
||||
|
@ -371,7 +510,7 @@ static int read_milenage(const char *fname)
|
|||
milenage_db = m;
|
||||
m = NULL;
|
||||
}
|
||||
free(m);
|
||||
os_free(m);
|
||||
|
||||
fclose(f);
|
||||
|
||||
|
@ -379,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;
|
||||
|
@ -389,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;
|
||||
}
|
||||
|
||||
|
@ -506,6 +724,7 @@ 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) {
|
||||
|
@ -513,6 +732,10 @@ static void aka_req_auth(int s, struct sockaddr_un *from, socklen_t fromlen,
|
|||
return;
|
||||
res_len = EAP_AKA_RES_MAX_LEN;
|
||||
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]);
|
||||
|
@ -529,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 */
|
||||
}
|
||||
|
||||
|
@ -539,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);
|
||||
|
@ -549,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,
|
||||
|
@ -596,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;
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -642,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 */
|
||||
}
|
||||
|
||||
|
||||
|
@ -672,19 +917,21 @@ 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>] "
|
||||
"hlr_auc_gw [-hu] [-s<socket path>] [-g<triplet file>] "
|
||||
"[-m<milenage file>] \\\n"
|
||||
" [-i<IND len in bits>]\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"
|
||||
" -D<DB file> = path to SQLite database\n"
|
||||
" -i<IND len in bits> = IND length for SQN (default: 5)\n",
|
||||
default_socket_path);
|
||||
}
|
||||
|
@ -693,16 +940,27 @@ 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:hi:m: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;
|
||||
|
@ -722,12 +980,25 @@ int main(int argc, char *argv[])
|
|||
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;
|
||||
|
||||
|
@ -747,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;
|
||||
}
|
||||
|
|
|
@ -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,6 +106,8 @@ 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=g
|
||||
|
||||
|
@ -196,6 +206,13 @@ 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)
|
||||
# tx_queue_<queue name>_<param>
|
||||
# queues: data0, data1, data2, data3, after_beacon, beacon
|
||||
|
@ -339,6 +356,12 @@ 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
|
||||
|
@ -410,6 +433,157 @@ wmm_ac_vo_acm=0
|
|||
# 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
|
||||
|
@ -466,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
|
||||
|
@ -510,12 +686,18 @@ eap_server=0
|
|||
# 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
|
||||
|
@ -622,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),
|
||||
|
@ -649,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 ##############################
|
||||
|
||||
|
@ -672,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.
|
||||
|
@ -696,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.
|
||||
|
@ -1007,6 +1260,24 @@ 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
|
||||
|
@ -1034,6 +1305,16 @@ own_ip_addr=127.0.0.1
|
|||
# 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
|
||||
|
@ -1087,11 +1368,138 @@ own_ip_addr=127.0.0.1
|
|||
# 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 a
|
||||
# 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
|
||||
|
|
|
@ -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');
|
|
@ -2,14 +2,8 @@
|
|||
* hostapd / main()
|
||||
* 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"
|
||||
|
@ -27,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"
|
||||
|
@ -48,29 +43,6 @@ struct hapd_global {
|
|||
static struct hapd_global global;
|
||||
|
||||
|
||||
struct hapd_interfaces {
|
||||
size_t count;
|
||||
struct hostapd_iface **iface;
|
||||
};
|
||||
|
||||
|
||||
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;
|
||||
}
|
||||
|
||||
|
||||
#ifndef CONFIG_NO_HOSTAPD_LOGGER
|
||||
static void hostapd_logger_cb(void *ctx, const u8 *addr, unsigned int module,
|
||||
int level, const char *txt, size_t len)
|
||||
|
@ -194,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)
|
||||
|
@ -209,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;
|
||||
|
@ -276,13 +243,13 @@ static int hostapd_driver_init(struct hostapd_iface *iface)
|
|||
}
|
||||
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++) {
|
||||
|
@ -303,28 +270,15 @@ static int hostapd_driver_init(struct hostapd_iface *iface)
|
|||
}
|
||||
|
||||
if (hapd->driver->get_capa &&
|
||||
hapd->driver->get_capa(hapd->drv_priv, &capa) == 0)
|
||||
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)
|
||||
|
@ -343,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;
|
||||
|
@ -434,7 +391,7 @@ static int hostapd_global_init(struct hapd_interfaces *interfaces,
|
|||
wpa_printf(MSG_ERROR, "No drivers enabled");
|
||||
return -1;
|
||||
}
|
||||
global.drv_priv = os_zalloc(global.drv_count * sizeof(void *));
|
||||
global.drv_priv = os_calloc(global.drv_count, sizeof(void *));
|
||||
if (global.drv_priv == NULL)
|
||||
return -1;
|
||||
|
||||
|
@ -522,13 +479,15 @@ static void usage(void)
|
|||
fprintf(stderr,
|
||||
"\n"
|
||||
"usage: hostapd [-hdBKtv] [-P <PID file>] [-e <entropy file>] "
|
||||
"<configuration file(s)>\n"
|
||||
"\\\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
|
||||
|
@ -550,6 +509,28 @@ static const char * hostapd_msg_ifname_cb(void *ctx)
|
|||
}
|
||||
|
||||
|
||||
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;
|
||||
|
@ -563,8 +544,19 @@ int main(int argc, char *argv[])
|
|||
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, "Bde:f:hKP:tv");
|
||||
c = getopt(argc, argv, "Bde:f:hKP:tvg:");
|
||||
if (c < 0)
|
||||
break;
|
||||
switch (c) {
|
||||
|
@ -599,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();
|
||||
|
@ -606,7 +601,7 @@ 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);
|
||||
|
@ -615,11 +610,13 @@ int main(int argc, char *argv[])
|
|||
wpa_debug_open_file(log_file);
|
||||
|
||||
interfaces.count = argc - optind;
|
||||
interfaces.iface = os_zalloc(interfaces.count *
|
||||
sizeof(struct hostapd_iface *));
|
||||
if (interfaces.iface == NULL) {
|
||||
wpa_printf(MSG_ERROR, "malloc failed");
|
||||
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, entropy_file))
|
||||
|
@ -634,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]);
|
||||
|
|
|
@ -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"
|
||||
|
|
|
@ -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,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"
|
||||
|
@ -32,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,
|
||||
|
@ -45,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));
|
||||
|
@ -73,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)) {
|
||||
|
@ -82,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));
|
||||
|
@ -97,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);
|
||||
|
@ -173,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;
|
||||
|
@ -242,7 +208,6 @@ void accounting_sta_start(struct hostapd_data *hapd, struct sta_info *sta)
|
|||
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",
|
||||
|
@ -381,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);
|
||||
|
@ -408,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++;
|
||||
|
|
|
@ -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"
|
||||
|
@ -93,6 +87,8 @@ void hostapd_config_defaults_bss(struct hostapd_bss_config *bss)
|
|||
#ifdef CONFIG_IEEE80211R
|
||||
bss->ft_over_ds = 1;
|
||||
#endif /* CONFIG_IEEE80211R */
|
||||
|
||||
bss->radius_das_time_window = 300;
|
||||
}
|
||||
|
||||
|
||||
|
@ -108,9 +104,9 @@ struct hostapd_config * hostapd_config_defaults(void)
|
|||
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 =
|
||||
|
@ -162,6 +158,9 @@ struct hostapd_config * hostapd_config_defaults(void)
|
|||
|
||||
conf->ht_capab = HT_CAP_INFO_SMPS_DISABLED;
|
||||
|
||||
conf->ap_table_max_size = 255;
|
||||
conf->ap_table_expiration_time = 60;
|
||||
|
||||
return conf;
|
||||
}
|
||||
|
||||
|
@ -342,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);
|
||||
|
@ -388,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);
|
||||
|
@ -398,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);
|
||||
|
@ -412,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;
|
||||
|
@ -468,9 +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);
|
||||
}
|
||||
|
||||
|
||||
|
@ -575,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,7 @@
|
|||
#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
|
||||
|
@ -54,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;
|
||||
|
@ -71,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 */
|
||||
|
@ -97,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;
|
||||
|
@ -104,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;
|
||||
|
@ -112,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;
|
||||
|
@ -123,6 +127,12 @@ 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 4
|
||||
|
||||
|
@ -133,14 +143,6 @@ struct hostapd_tx_queue_params {
|
|||
int burst; /* maximum burst time in 0.1 ms, i.e., 10 = 1 ms */
|
||||
};
|
||||
|
||||
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
|
||||
|
||||
|
@ -149,6 +151,29 @@ struct hostapd_roaming_consortium {
|
|||
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
|
||||
*/
|
||||
|
@ -173,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;
|
||||
|
||||
|
@ -220,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;
|
||||
|
@ -325,6 +365,10 @@ struct hostapd_bss_config {
|
|||
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;
|
||||
|
||||
|
@ -336,15 +380,19 @@ struct hostapd_bss_config {
|
|||
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;
|
||||
|
@ -361,6 +409,52 @@ struct hostapd_bss_config {
|
|||
/* 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;
|
||||
};
|
||||
|
||||
|
||||
|
@ -415,6 +509,12 @@ struct hostapd_config {
|
|||
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;
|
||||
};
|
||||
|
||||
|
||||
|
@ -433,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"
|
||||
|
@ -18,11 +12,13 @@
|
|||
#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"
|
||||
|
||||
|
||||
|
@ -153,6 +149,30 @@ int hostapd_build_ap_extra_ies(struct hostapd_data *hapd,
|
|||
}
|
||||
#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;
|
||||
|
@ -318,7 +338,7 @@ int hostapd_sta_add(struct hostapd_data *hapd,
|
|||
const u8 *supp_rates, size_t supp_rates_len,
|
||||
u16 listen_interval,
|
||||
const struct ieee80211_ht_capabilities *ht_capab,
|
||||
u32 flags)
|
||||
u32 flags, u8 qosinfo)
|
||||
{
|
||||
struct hostapd_sta_add_params params;
|
||||
|
||||
|
@ -336,6 +356,7 @@ int hostapd_sta_add(struct hostapd_data *hapd,
|
|||
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);
|
||||
}
|
||||
|
||||
|
@ -475,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 ||
|
||||
|
@ -573,11 +584,11 @@ int hostapd_drv_set_key(const char *ifname, struct hostapd_data *hapd,
|
|||
|
||||
|
||||
int hostapd_drv_send_mlme(struct hostapd_data *hapd,
|
||||
const void *msg, size_t len)
|
||||
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);
|
||||
return hapd->driver->send_mlme(hapd->drv_priv, msg, len, noack);
|
||||
}
|
||||
|
||||
|
||||
|
@ -599,3 +610,25 @@ int hostapd_drv_sta_disassoc(struct hostapd_data *hapd,
|
|||
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
|
||||
|
@ -43,7 +37,7 @@ int hostapd_sta_add(struct hostapd_data *hapd,
|
|||
const u8 *supp_rates, size_t supp_rates_len,
|
||||
u16 listen_interval,
|
||||
const struct ieee80211_ht_capabilities *ht_capab,
|
||||
u32 flags);
|
||||
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);
|
||||
|
@ -66,8 +60,6 @@ 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_tx_queue_params(struct hostapd_data *hapd, int queue, int aifs,
|
||||
int cw_min, int cw_max, int burst_time);
|
||||
|
@ -89,11 +81,14 @@ int hostapd_drv_set_key(const char *ifname,
|
|||
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);
|
||||
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,
|
||||
|
@ -106,6 +101,10 @@ int hostapd_add_tspec(struct hostapd_data *hapd, const u8 *addr,
|
|||
|
||||
#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)
|
||||
{
|
||||
|
|
|
@ -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"
|
||||
|
@ -257,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;
|
||||
|
||||
|
@ -295,10 +275,8 @@ void ap_list_process_beacon(struct hostapd_iface *iface,
|
|||
ap->num_beacons++;
|
||||
os_get_time(&now);
|
||||
ap->last_beacon = now.sec;
|
||||
if (fi) {
|
||||
ap->ssi_signal = fi->ssi_signal;
|
||||
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
|
||||
|
@ -326,7 +304,7 @@ 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);
|
||||
}
|
||||
|
||||
|
||||
|
@ -381,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,7 +34,6 @@ struct ap_info {
|
|||
|
||||
int channel;
|
||||
int datarate; /* in 100 kbps */
|
||||
int ssi_signal;
|
||||
|
||||
int ht_support;
|
||||
|
||||
|
|
|
@ -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;
|
||||
|
@ -120,6 +111,9 @@ static int hostapd_setup_radius_srv(struct hostapd_data *hapd)
|
|||
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
|
||||
|
|
|
@ -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
|
||||
|
@ -33,6 +33,7 @@
|
|||
#include "p2p_hostapd.h"
|
||||
#include "ap_drv_ops.h"
|
||||
#include "beacon.h"
|
||||
#include "hs20.h"
|
||||
|
||||
|
||||
#ifdef NEED_AP_MLME
|
||||
|
@ -186,18 +187,181 @@ 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;
|
||||
|
||||
#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 NULL;
|
||||
|
||||
epos = ((u8 *) resp) + MAX_PROBERESP_LEN;
|
||||
|
||||
resp->frame_control = IEEE80211_FC(WLAN_FC_TYPE_MGMT,
|
||||
WLAN_FC_STYPE_PROBE_RESP);
|
||||
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);
|
||||
resp->u.probe_resp.beacon_int =
|
||||
host_to_le16(hapd->iconf->beacon_int);
|
||||
|
||||
/* hardware or low-level driver will setup seq_ctrl and timestamp */
|
||||
resp->u.probe_resp.capab_info =
|
||||
host_to_le16(hostapd_own_capab_info(hapd, sta, 1));
|
||||
|
||||
pos = resp->u.probe_resp.variable;
|
||||
*pos++ = WLAN_EID_SSID;
|
||||
*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);
|
||||
|
||||
/* DS Params */
|
||||
pos = hostapd_eid_ds_params(hapd, pos);
|
||||
|
||||
pos = hostapd_eid_country(hapd, pos, epos - pos);
|
||||
|
||||
/* ERP Information element */
|
||||
pos = hostapd_eid_erp_info(hapd, pos);
|
||||
|
||||
/* Extended supported rates */
|
||||
pos = hostapd_eid_ext_supp_rates(hapd, pos);
|
||||
|
||||
/* RSN, MDIE, WPA */
|
||||
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);
|
||||
|
||||
#ifdef CONFIG_WPS
|
||||
if (hapd->conf->wps_state && hapd->wps_probe_resp_ie) {
|
||||
os_memcpy(pos, wpabuf_head(hapd->wps_probe_resp_ie),
|
||||
wpabuf_len(hapd->wps_probe_resp_ie));
|
||||
pos += wpabuf_len(hapd->wps_probe_resp_ie);
|
||||
}
|
||||
#endif /* CONFIG_WPS */
|
||||
|
||||
#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))
|
||||
|
@ -207,7 +371,7 @@ void handle_probe_req(struct hostapd_data *hapd,
|
|||
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) > 0)
|
||||
ie, ie_len, ssi_signal) > 0)
|
||||
return;
|
||||
|
||||
if (!hapd->iconf->send_probe_response)
|
||||
|
@ -219,9 +383,6 @@ void handle_probe_req(struct hostapd_data *hapd,
|
|||
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",
|
||||
|
@ -256,7 +417,8 @@ void handle_probe_req(struct hostapd_data *hapd,
|
|||
}
|
||||
#endif /* CONFIG_P2P */
|
||||
|
||||
if (hapd->conf->ignore_broadcast_ssid && elems.ssid_len == 0) {
|
||||
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;
|
||||
|
@ -274,25 +436,21 @@ void handle_probe_req(struct hostapd_data *hapd,
|
|||
}
|
||||
#endif /* CONFIG_P2P */
|
||||
|
||||
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;
|
||||
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;
|
||||
}
|
||||
|
||||
if (!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 ")",
|
||||
" for foreign SSID '%s' (DA " MACSTR ")%s",
|
||||
MAC2STR(mgmt->sa), ssid_txt,
|
||||
MAC2STR(mgmt->da));
|
||||
MAC2STR(mgmt->da),
|
||||
elems.ssid_list ? " (SSID list)" : "");
|
||||
}
|
||||
return;
|
||||
}
|
||||
|
@ -329,97 +487,20 @@ void handle_probe_req(struct hostapd_data *hapd,
|
|||
|
||||
/* 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 */
|
||||
resp = os_zalloc(buflen);
|
||||
|
||||
resp = hostapd_gen_probe_resp(hapd, sta, mgmt, elems.p2p != NULL,
|
||||
&resp_len);
|
||||
if (resp == NULL)
|
||||
return;
|
||||
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);
|
||||
os_memcpy(resp->sa, hapd->own_addr, ETH_ALEN);
|
||||
/*
|
||||
* 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));
|
||||
|
||||
os_memcpy(resp->bssid, hapd->own_addr, ETH_ALEN);
|
||||
resp->u.probe_resp.beacon_int =
|
||||
host_to_le16(hapd->iconf->beacon_int);
|
||||
|
||||
/* hardware or low-level driver will setup seq_ctrl and timestamp */
|
||||
resp->u.probe_resp.capab_info =
|
||||
host_to_le16(hostapd_own_capab_info(hapd, sta, 1));
|
||||
|
||||
pos = resp->u.probe_resp.variable;
|
||||
*pos++ = WLAN_EID_SSID;
|
||||
*pos++ = ssid_len;
|
||||
os_memcpy(pos, ssid, ssid_len);
|
||||
pos += ssid_len;
|
||||
|
||||
/* Supported rates */
|
||||
pos = hostapd_eid_supp_rates(hapd, pos);
|
||||
|
||||
/* DS Params */
|
||||
pos = hostapd_eid_ds_params(hapd, pos);
|
||||
|
||||
pos = hostapd_eid_country(hapd, pos, epos - pos);
|
||||
|
||||
/* ERP Information element */
|
||||
pos = hostapd_eid_erp_info(hapd, pos);
|
||||
|
||||
/* Extended supported rates */
|
||||
pos = hostapd_eid_ext_supp_rates(hapd, pos);
|
||||
|
||||
/* RSN, MDIE, WPA */
|
||||
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);
|
||||
|
||||
/* Wi-Fi Alliance WMM */
|
||||
pos = hostapd_eid_wmm(hapd, pos);
|
||||
|
||||
#ifdef CONFIG_WPS
|
||||
if (hapd->conf->wps_state && hapd->wps_probe_resp_ie) {
|
||||
os_memcpy(pos, wpabuf_head(hapd->wps_probe_resp_ie),
|
||||
wpabuf_len(hapd->wps_probe_resp_ie));
|
||||
pos += wpabuf_len(hapd->wps_probe_resp_ie);
|
||||
}
|
||||
#endif /* CONFIG_WPS */
|
||||
|
||||
#ifdef CONFIG_P2P
|
||||
if ((hapd->conf->p2p & P2P_ENABLED) && elems.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 */
|
||||
|
||||
if (hostapd_drv_send_mlme(hapd, resp, pos - (u8 *) resp) < 0)
|
||||
if (hostapd_drv_send_mlme(hapd, resp, resp_len, noack) < 0)
|
||||
perror("handle_probe_req: send");
|
||||
|
||||
os_free(resp);
|
||||
|
@ -429,6 +510,42 @@ void handle_probe_req(struct hostapd_data *hapd,
|
|||
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 */
|
||||
|
||||
|
||||
|
@ -437,6 +554,8 @@ void ieee802_11_set_beacon(struct hostapd_data *hapd)
|
|||
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
|
||||
|
@ -460,6 +579,8 @@ void ieee802_11_set_beacon(struct hostapd_data *hapd)
|
|||
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");
|
||||
|
@ -537,6 +658,11 @@ void ieee802_11_set_beacon(struct hostapd_data *hapd)
|
|||
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);
|
||||
|
||||
|
@ -561,8 +687,19 @@ void ieee802_11_set_beacon(struct hostapd_data *hapd)
|
|||
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;
|
||||
|
||||
resp = hostapd_probe_resp_offloads(hapd, &resp_len);
|
||||
#endif /* NEED_AP_MLME */
|
||||
|
||||
os_memset(¶ms, 0, sizeof(params));
|
||||
|
@ -570,9 +707,12 @@ void ieee802_11_set_beacon(struct hostapd_data *hapd)
|
|||
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.ssid = (u8 *) hapd->conf->ssid.ssid;
|
||||
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;
|
||||
|
@ -621,12 +761,17 @@ void ieee802_11_set_beacon(struct hostapd_data *hapd)
|
|||
!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);
|
||||
os_free(resp);
|
||||
}
|
||||
|
||||
|
||||
|
@ -637,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,8 +19,10 @@
|
|||
struct ieee80211_mgmt;
|
||||
|
||||
void handle_probe_req(struct hostapd_data *hapd,
|
||||
const struct ieee80211_mgmt *mgmt, size_t len);
|
||||
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);
|
||||
void ieee802_11_update_beacons(struct hostapd_iface *iface);
|
||||
|
||||
#endif /* BEACON_H */
|
||||
|
|
|
@ -2,19 +2,14 @@
|
|||
* 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"
|
||||
|
@ -23,6 +18,29 @@
|
|||
#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,
|
||||
|
@ -62,6 +80,10 @@ static int hostapd_ctrl_iface_sta_mib(struct hostapd_data *hapd,
|
|||
if (res >= 0)
|
||||
len += res;
|
||||
|
||||
res = hostapd_get_sta_conn_time(sta, buf + len, buflen - len);
|
||||
if (res >= 0)
|
||||
len += res;
|
||||
|
||||
return len;
|
||||
}
|
||||
|
||||
|
@ -106,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,22 +13,21 @@
|
|||
#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,
|
||||
|
@ -45,7 +38,12 @@ int hostapd_notif_assoc(struct hostapd_data *hapd, const u8 *addr,
|
|||
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) {
|
||||
/*
|
||||
|
@ -95,8 +93,11 @@ int hostapd_notif_assoc(struct hostapd_data *hapd, const u8 *addr,
|
|||
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 | WLAN_STA_WPS2);
|
||||
|
||||
|
@ -108,6 +109,15 @@ int hostapd_notif_assoc(struct hostapd_data *hapd, const u8 *addr,
|
|||
}
|
||||
#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
|
||||
|
@ -151,27 +161,85 @@ 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) {
|
||||
wpa_printf(MSG_DEBUG, "WPA/RSN information element "
|
||||
"rejected? (res %u)", res);
|
||||
wpa_hexdump(MSG_DEBUG, "IE", ie, ielen);
|
||||
if (res == WPA_INVALID_GROUP)
|
||||
if (res == WPA_INVALID_GROUP) {
|
||||
reason = WLAN_REASON_GROUP_CIPHER_NOT_VALID;
|
||||
else if (res == WPA_INVALID_PAIRWISE)
|
||||
status = WLAN_STATUS_GROUP_CIPHER_NOT_VALID;
|
||||
} else if (res == WPA_INVALID_PAIRWISE) {
|
||||
reason = WLAN_REASON_PAIRWISE_CIPHER_NOT_VALID;
|
||||
else if (res == WPA_INVALID_AKMP)
|
||||
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)
|
||||
else if (res == WPA_MGMT_FRAME_PROTECTION_VIOLATION) {
|
||||
reason = WLAN_REASON_INVALID_IE;
|
||||
else if (res == WPA_INVALID_MGMT_GROUP_CIPHER)
|
||||
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
|
||||
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) {
|
||||
#ifdef CONFIG_WPS
|
||||
struct wpabuf *wps;
|
||||
|
@ -183,6 +251,7 @@ int hostapd_notif_assoc(struct hostapd_data *hapd, const u8 *addr,
|
|||
#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;
|
||||
}
|
||||
|
@ -203,9 +272,24 @@ int hostapd_notif_assoc(struct hostapd_data *hapd, const u8 *addr,
|
|||
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);
|
||||
|
||||
|
@ -221,6 +305,9 @@ skip_wpa_check:
|
|||
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;
|
||||
|
@ -279,8 +366,36 @@ void hostapd_event_sta_low_ack(struct hostapd_data *hapd, const u8 *addr)
|
|||
}
|
||||
|
||||
|
||||
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)
|
||||
const u8 *bssid, const u8 *ie, size_t ie_len,
|
||||
int ssi_signal)
|
||||
{
|
||||
size_t i;
|
||||
int ret = 0;
|
||||
|
@ -291,7 +406,8 @@ int hostapd_probe_req_rx(struct hostapd_data *hapd, const u8 *sa, const u8 *da,
|
|||
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) > 0) {
|
||||
sa, da, bssid, ie, ie_len,
|
||||
ssi_signal) > 0) {
|
||||
ret = 1;
|
||||
break;
|
||||
}
|
||||
|
@ -302,6 +418,110 @@ int hostapd_probe_req_rx(struct hostapd_data *hapd, const u8 *sa, const u8 *da,
|
|||
|
||||
#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)
|
||||
|
@ -481,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:
|
||||
|
@ -516,6 +753,12 @@ 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;
|
||||
|
@ -536,7 +779,8 @@ void wpa_supplicant_event(void *ctx, enum wpa_event_type event,
|
|||
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);
|
||||
|
@ -565,14 +809,25 @@ void wpa_supplicant_event(void *ctx, enum wpa_event_type event,
|
|||
break;
|
||||
hostapd_event_sta_low_ack(hapd, data->low_ack.addr);
|
||||
break;
|
||||
#ifdef NEED_AP_MLME
|
||||
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);
|
||||
break;
|
||||
#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;
|
||||
|
|
|
@ -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;
|
||||
}
|
File diff suppressed because it is too large
Load Diff
|
@ -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 */
|
|
@ -1,15 +1,9 @@
|
|||
/*
|
||||
* hostapd / Initialization and configuration
|
||||
* 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,6 +12,7 @@
|
|||
#include "utils/eloop.h"
|
||||
#include "common/ieee802_11_defs.h"
|
||||
#include "radius/radius_client.h"
|
||||
#include "radius/radius_das.h"
|
||||
#include "drivers/driver.h"
|
||||
#include "hostapd.h"
|
||||
#include "authsrv.h"
|
||||
|
@ -36,6 +31,7 @@
|
|||
#include "ap_drv_ops.h"
|
||||
#include "ap_config.h"
|
||||
#include "p2p_hostapd.h"
|
||||
#include "gas_serv.h"
|
||||
|
||||
|
||||
static int hostapd_flush_old_stations(struct hostapd_data *hapd, u16 reason);
|
||||
|
@ -43,6 +39,24 @@ static int hostapd_setup_encryption(char *iface, struct hostapd_data *hapd);
|
|||
static int hostapd_broadcast_wep_clear(struct hostapd_data *hapd);
|
||||
|
||||
extern int wpa_debug_level;
|
||||
extern struct wpa_driver_ops *wpa_drivers[];
|
||||
|
||||
|
||||
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 void hostapd_reload_bss(struct hostapd_data *hapd)
|
||||
|
@ -85,7 +99,7 @@ static void hostapd_reload_bss(struct hostapd_data *hapd)
|
|||
hostapd_update_wps(hapd);
|
||||
|
||||
if (hapd->conf->ssid.ssid_set &&
|
||||
hostapd_set_ssid(hapd, (u8 *) hapd->conf->ssid.ssid,
|
||||
hostapd_set_ssid(hapd, hapd->conf->ssid.ssid,
|
||||
hapd->conf->ssid.ssid_len)) {
|
||||
wpa_printf(MSG_ERROR, "Could not set SSID for kernel driver");
|
||||
/* try to continue */
|
||||
|
@ -100,9 +114,10 @@ int hostapd_reload_config(struct hostapd_iface *iface)
|
|||
struct hostapd_config *newconf, *oldconf;
|
||||
size_t j;
|
||||
|
||||
if (iface->config_read_cb == NULL)
|
||||
if (iface->interfaces == NULL ||
|
||||
iface->interfaces->config_read_cb == NULL)
|
||||
return -1;
|
||||
newconf = iface->config_read_cb(iface->config_fname);
|
||||
newconf = iface->interfaces->config_read_cb(iface->config_fname);
|
||||
if (newconf == NULL)
|
||||
return -1;
|
||||
|
||||
|
@ -217,21 +232,9 @@ static int hostapd_broadcast_wep_set(struct hostapd_data *hapd)
|
|||
return errors;
|
||||
}
|
||||
|
||||
/**
|
||||
* hostapd_cleanup - Per-BSS cleanup (deinitialization)
|
||||
* @hapd: Pointer to BSS data
|
||||
*
|
||||
* This function is used to free all per-BSS data structures and resources.
|
||||
* This gets called in a loop for each BSS between calls to
|
||||
* hostapd_cleanup_iface_pre() and hostapd_cleanup_iface() when an interface
|
||||
* is deinitialized. Most of the modules that are initialized in
|
||||
* hostapd_setup_bss() are deinitialized here.
|
||||
*/
|
||||
static void hostapd_cleanup(struct hostapd_data *hapd)
|
||||
{
|
||||
if (hapd->iface->ctrl_iface_deinit)
|
||||
hapd->iface->ctrl_iface_deinit(hapd);
|
||||
|
||||
static void hostapd_free_hapd_data(struct hostapd_data *hapd)
|
||||
{
|
||||
iapp_deinit(hapd->iapp);
|
||||
hapd->iapp = NULL;
|
||||
accounting_deinit(hapd);
|
||||
|
@ -241,6 +244,8 @@ static void hostapd_cleanup(struct hostapd_data *hapd)
|
|||
#ifndef CONFIG_NO_RADIUS
|
||||
radius_client_deinit(hapd->radius);
|
||||
hapd->radius = NULL;
|
||||
radius_das_deinit(hapd->radius_das);
|
||||
hapd->radius_das = NULL;
|
||||
#endif /* CONFIG_NO_RADIUS */
|
||||
|
||||
hostapd_deinit_wps(hapd);
|
||||
|
@ -264,6 +269,34 @@ static void hostapd_cleanup(struct hostapd_data *hapd)
|
|||
#endif /* CONFIG_P2P */
|
||||
|
||||
wpabuf_free(hapd->time_adv);
|
||||
|
||||
#ifdef CONFIG_INTERWORKING
|
||||
gas_serv_deinit(hapd);
|
||||
#endif /* CONFIG_INTERWORKING */
|
||||
|
||||
#ifdef CONFIG_SQLITE
|
||||
os_free(hapd->tmp_eap_user.identity);
|
||||
os_free(hapd->tmp_eap_user.password);
|
||||
#endif /* CONFIG_SQLITE */
|
||||
}
|
||||
|
||||
|
||||
/**
|
||||
* hostapd_cleanup - Per-BSS cleanup (deinitialization)
|
||||
* @hapd: Pointer to BSS data
|
||||
*
|
||||
* This function is used to free all per-BSS data structures and resources.
|
||||
* This gets called in a loop for each BSS between calls to
|
||||
* hostapd_cleanup_iface_pre() and hostapd_cleanup_iface() when an interface
|
||||
* is deinitialized. Most of the modules that are initialized in
|
||||
* hostapd_setup_bss() are deinitialized here.
|
||||
*/
|
||||
static void hostapd_cleanup(struct hostapd_data *hapd)
|
||||
{
|
||||
if (hapd->iface->interfaces &&
|
||||
hapd->iface->interfaces->ctrl_iface_deinit)
|
||||
hapd->iface->interfaces->ctrl_iface_deinit(hapd);
|
||||
hostapd_free_hapd_data(hapd);
|
||||
}
|
||||
|
||||
|
||||
|
@ -279,6 +312,18 @@ static void hostapd_cleanup_iface_pre(struct hostapd_iface *iface)
|
|||
}
|
||||
|
||||
|
||||
static void hostapd_cleanup_iface_partial(struct hostapd_iface *iface)
|
||||
{
|
||||
hostapd_free_hw_features(iface->hw_features, iface->num_hw_features);
|
||||
iface->hw_features = NULL;
|
||||
os_free(iface->current_rates);
|
||||
iface->current_rates = NULL;
|
||||
os_free(iface->basic_rates);
|
||||
iface->basic_rates = NULL;
|
||||
ap_list_deinit(iface);
|
||||
}
|
||||
|
||||
|
||||
/**
|
||||
* hostapd_cleanup_iface - Complete per-interface cleanup
|
||||
* @iface: Pointer to interface data
|
||||
|
@ -288,11 +333,7 @@ static void hostapd_cleanup_iface_pre(struct hostapd_iface *iface)
|
|||
*/
|
||||
static void hostapd_cleanup_iface(struct hostapd_iface *iface)
|
||||
{
|
||||
hostapd_free_hw_features(iface->hw_features, iface->num_hw_features);
|
||||
iface->hw_features = NULL;
|
||||
os_free(iface->current_rates);
|
||||
iface->current_rates = NULL;
|
||||
ap_list_deinit(iface);
|
||||
hostapd_cleanup_iface_partial(iface);
|
||||
hostapd_config_free(iface->conf);
|
||||
iface->conf = NULL;
|
||||
|
||||
|
@ -302,6 +343,15 @@ static void hostapd_cleanup_iface(struct hostapd_iface *iface)
|
|||
}
|
||||
|
||||
|
||||
static void hostapd_clear_wep(struct hostapd_data *hapd)
|
||||
{
|
||||
if (hapd->drv_priv) {
|
||||
hostapd_set_privacy(hapd, 0);
|
||||
hostapd_broadcast_wep_clear(hapd);
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
static int hostapd_setup_encryption(char *iface, struct hostapd_data *hapd)
|
||||
{
|
||||
int i;
|
||||
|
@ -346,12 +396,13 @@ static int hostapd_flush_old_stations(struct hostapd_data *hapd, u16 reason)
|
|||
if (hostapd_drv_none(hapd) || hapd->drv_priv == NULL)
|
||||
return 0;
|
||||
|
||||
wpa_printf(MSG_DEBUG, "Flushing old station entries");
|
||||
wpa_dbg(hapd->msg_ctx, MSG_DEBUG, "Flushing old station entries");
|
||||
if (hostapd_flush(hapd)) {
|
||||
wpa_printf(MSG_WARNING, "Could not connect to kernel driver.");
|
||||
wpa_msg(hapd->msg_ctx, MSG_WARNING, "Could not connect to "
|
||||
"kernel driver");
|
||||
ret = -1;
|
||||
}
|
||||
wpa_printf(MSG_DEBUG, "Deauthenticate all stations");
|
||||
wpa_dbg(hapd->msg_ctx, MSG_DEBUG, "Deauthenticate all stations");
|
||||
os_memset(addr, 0xff, ETH_ALEN);
|
||||
hostapd_drv_sta_deauth(hapd, addr, reason);
|
||||
hostapd_free_stas(hapd);
|
||||
|
@ -468,6 +519,86 @@ static int mac_in_conf(struct hostapd_config *conf, const void *a)
|
|||
}
|
||||
|
||||
|
||||
#ifndef CONFIG_NO_RADIUS
|
||||
|
||||
static int hostapd_das_nas_mismatch(struct hostapd_data *hapd,
|
||||
struct radius_das_attrs *attr)
|
||||
{
|
||||
/* TODO */
|
||||
return 0;
|
||||
}
|
||||
|
||||
|
||||
static struct sta_info * hostapd_das_find_sta(struct hostapd_data *hapd,
|
||||
struct radius_das_attrs *attr)
|
||||
{
|
||||
struct sta_info *sta = NULL;
|
||||
char buf[128];
|
||||
|
||||
if (attr->sta_addr)
|
||||
sta = ap_get_sta(hapd, attr->sta_addr);
|
||||
|
||||
if (sta == NULL && attr->acct_session_id &&
|
||||
attr->acct_session_id_len == 17) {
|
||||
for (sta = hapd->sta_list; sta; sta = sta->next) {
|
||||
os_snprintf(buf, sizeof(buf), "%08X-%08X",
|
||||
sta->acct_session_id_hi,
|
||||
sta->acct_session_id_lo);
|
||||
if (os_memcmp(attr->acct_session_id, buf, 17) == 0)
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
if (sta == NULL && attr->cui) {
|
||||
for (sta = hapd->sta_list; sta; sta = sta->next) {
|
||||
struct wpabuf *cui;
|
||||
cui = ieee802_1x_get_radius_cui(sta->eapol_sm);
|
||||
if (cui && wpabuf_len(cui) == attr->cui_len &&
|
||||
os_memcmp(wpabuf_head(cui), attr->cui,
|
||||
attr->cui_len) == 0)
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
if (sta == NULL && attr->user_name) {
|
||||
for (sta = hapd->sta_list; sta; sta = sta->next) {
|
||||
u8 *identity;
|
||||
size_t identity_len;
|
||||
identity = ieee802_1x_get_identity(sta->eapol_sm,
|
||||
&identity_len);
|
||||
if (identity &&
|
||||
identity_len == attr->user_name_len &&
|
||||
os_memcmp(identity, attr->user_name, identity_len)
|
||||
== 0)
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
return sta;
|
||||
}
|
||||
|
||||
|
||||
static enum radius_das_res
|
||||
hostapd_das_disconnect(void *ctx, struct radius_das_attrs *attr)
|
||||
{
|
||||
struct hostapd_data *hapd = ctx;
|
||||
struct sta_info *sta;
|
||||
|
||||
if (hostapd_das_nas_mismatch(hapd, attr))
|
||||
return RADIUS_DAS_NAS_MISMATCH;
|
||||
|
||||
sta = hostapd_das_find_sta(hapd, attr);
|
||||
if (sta == NULL)
|
||||
return RADIUS_DAS_SESSION_NOT_FOUND;
|
||||
|
||||
hostapd_drv_sta_deauth(hapd, sta->addr,
|
||||
WLAN_REASON_PREV_AUTH_NOT_VALID);
|
||||
ap_sta_deauthenticate(hapd, sta, WLAN_REASON_PREV_AUTH_NOT_VALID);
|
||||
|
||||
return RADIUS_DAS_SUCCESS;
|
||||
}
|
||||
|
||||
#endif /* CONFIG_NO_RADIUS */
|
||||
|
||||
|
||||
/**
|
||||
|
@ -556,14 +687,14 @@ static int hostapd_setup_bss(struct hostapd_data *hapd, int first)
|
|||
set_ssid = 0;
|
||||
conf->ssid.ssid_len = ssid_len;
|
||||
os_memcpy(conf->ssid.ssid, ssid, conf->ssid.ssid_len);
|
||||
conf->ssid.ssid[conf->ssid.ssid_len] = '\0';
|
||||
}
|
||||
|
||||
if (!hostapd_drv_none(hapd)) {
|
||||
wpa_printf(MSG_ERROR, "Using interface %s with hwaddr " MACSTR
|
||||
" and ssid '%s'",
|
||||
" and ssid \"%s\"",
|
||||
hapd->conf->iface, MAC2STR(hapd->own_addr),
|
||||
hapd->conf->ssid.ssid);
|
||||
wpa_ssid_txt(hapd->conf->ssid.ssid,
|
||||
hapd->conf->ssid.ssid_len));
|
||||
}
|
||||
|
||||
if (hostapd_setup_wpa_psk(conf)) {
|
||||
|
@ -573,7 +704,7 @@ static int hostapd_setup_bss(struct hostapd_data *hapd, int first)
|
|||
|
||||
/* Set SSID for the kernel driver (to be used in beacon and probe
|
||||
* response frames) */
|
||||
if (set_ssid && hostapd_set_ssid(hapd, (u8 *) conf->ssid.ssid,
|
||||
if (set_ssid && hostapd_set_ssid(hapd, conf->ssid.ssid,
|
||||
conf->ssid.ssid_len)) {
|
||||
wpa_printf(MSG_ERROR, "Could not set SSID for kernel driver");
|
||||
return -1;
|
||||
|
@ -587,6 +718,27 @@ static int hostapd_setup_bss(struct hostapd_data *hapd, int first)
|
|||
wpa_printf(MSG_ERROR, "RADIUS client initialization failed.");
|
||||
return -1;
|
||||
}
|
||||
|
||||
if (hapd->conf->radius_das_port) {
|
||||
struct radius_das_conf das_conf;
|
||||
os_memset(&das_conf, 0, sizeof(das_conf));
|
||||
das_conf.port = hapd->conf->radius_das_port;
|
||||
das_conf.shared_secret = hapd->conf->radius_das_shared_secret;
|
||||
das_conf.shared_secret_len =
|
||||
hapd->conf->radius_das_shared_secret_len;
|
||||
das_conf.client_addr = &hapd->conf->radius_das_client_addr;
|
||||
das_conf.time_window = hapd->conf->radius_das_time_window;
|
||||
das_conf.require_event_timestamp =
|
||||
hapd->conf->radius_das_require_event_timestamp;
|
||||
das_conf.ctx = hapd;
|
||||
das_conf.disconnect = hostapd_das_disconnect;
|
||||
hapd->radius_das = radius_das_init(&das_conf);
|
||||
if (hapd->radius_das == NULL) {
|
||||
wpa_printf(MSG_ERROR, "RADIUS DAS initialization "
|
||||
"failed.");
|
||||
return -1;
|
||||
}
|
||||
}
|
||||
#endif /* CONFIG_NO_RADIUS */
|
||||
|
||||
if (hostapd_acl_init(hapd)) {
|
||||
|
@ -619,8 +771,16 @@ static int hostapd_setup_bss(struct hostapd_data *hapd, int first)
|
|||
return -1;
|
||||
}
|
||||
|
||||
if (hapd->iface->ctrl_iface_init &&
|
||||
hapd->iface->ctrl_iface_init(hapd)) {
|
||||
#ifdef CONFIG_INTERWORKING
|
||||
if (gas_serv_init(hapd)) {
|
||||
wpa_printf(MSG_ERROR, "GAS server initialization failed");
|
||||
return -1;
|
||||
}
|
||||
#endif /* CONFIG_INTERWORKING */
|
||||
|
||||
if (hapd->iface->interfaces &&
|
||||
hapd->iface->interfaces->ctrl_iface_init &&
|
||||
hapd->iface->interfaces->ctrl_iface_init(hapd)) {
|
||||
wpa_printf(MSG_ERROR, "Failed to setup control interface");
|
||||
return -1;
|
||||
}
|
||||
|
@ -742,7 +902,7 @@ int hostapd_setup_interface_complete(struct hostapd_iface *iface, int err)
|
|||
}
|
||||
|
||||
if (iface->current_mode) {
|
||||
if (hostapd_prepare_rates(hapd, iface->current_mode)) {
|
||||
if (hostapd_prepare_rates(iface, iface->current_mode)) {
|
||||
wpa_printf(MSG_ERROR, "Failed to prepare rates "
|
||||
"table.");
|
||||
hostapd_logger(hapd, NULL, HOSTAPD_MODULE_IEEE80211,
|
||||
|
@ -861,6 +1021,7 @@ hostapd_alloc_bss_data(struct hostapd_iface *hapd_iface,
|
|||
hapd->conf = bss;
|
||||
hapd->iface = hapd_iface;
|
||||
hapd->driver = hapd->iconf->driver;
|
||||
hapd->ctrl_sock = -1;
|
||||
|
||||
return hapd;
|
||||
}
|
||||
|
@ -878,6 +1039,7 @@ void hostapd_interface_deinit(struct hostapd_iface *iface)
|
|||
struct hostapd_data *hapd = iface->bss[j];
|
||||
hostapd_free_stas(hapd);
|
||||
hostapd_flush_old_stations(hapd, WLAN_REASON_DEAUTH_LEAVING);
|
||||
hostapd_clear_wep(hapd);
|
||||
hostapd_cleanup(hapd);
|
||||
}
|
||||
}
|
||||
|
@ -892,6 +1054,293 @@ void hostapd_interface_free(struct hostapd_iface *iface)
|
|||
}
|
||||
|
||||
|
||||
#ifdef HOSTAPD
|
||||
|
||||
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 && drv_priv)
|
||||
driver->hapd_deinit(drv_priv);
|
||||
hostapd_interface_free(iface);
|
||||
}
|
||||
|
||||
|
||||
int hostapd_enable_iface(struct hostapd_iface *hapd_iface)
|
||||
{
|
||||
if (hapd_iface->bss[0]->drv_priv != NULL) {
|
||||
wpa_printf(MSG_ERROR, "Interface %s already enabled",
|
||||
hapd_iface->conf->bss[0].iface);
|
||||
return -1;
|
||||
}
|
||||
|
||||
wpa_printf(MSG_DEBUG, "Enable interface %s",
|
||||
hapd_iface->conf->bss[0].iface);
|
||||
|
||||
if (hapd_iface->interfaces == NULL ||
|
||||
hapd_iface->interfaces->driver_init == NULL ||
|
||||
hapd_iface->interfaces->driver_init(hapd_iface) ||
|
||||
hostapd_setup_interface(hapd_iface)) {
|
||||
hostapd_interface_deinit_free(hapd_iface);
|
||||
return -1;
|
||||
}
|
||||
return 0;
|
||||
}
|
||||
|
||||
|
||||
int hostapd_reload_iface(struct hostapd_iface *hapd_iface)
|
||||
{
|
||||
size_t j;
|
||||
|
||||
wpa_printf(MSG_DEBUG, "Reload interface %s",
|
||||
hapd_iface->conf->bss[0].iface);
|
||||
for (j = 0; j < hapd_iface->num_bss; j++) {
|
||||
hostapd_flush_old_stations(hapd_iface->bss[j],
|
||||
WLAN_REASON_PREV_AUTH_NOT_VALID);
|
||||
|
||||
#ifndef CONFIG_NO_RADIUS
|
||||
/* TODO: update dynamic data based on changed configuration
|
||||
* items (e.g., open/close sockets, etc.) */
|
||||
radius_client_flush(hapd_iface->bss[j]->radius, 0);
|
||||
#endif /* CONFIG_NO_RADIUS */
|
||||
|
||||
hostapd_reload_bss(hapd_iface->bss[j]);
|
||||
}
|
||||
return 0;
|
||||
}
|
||||
|
||||
|
||||
int hostapd_disable_iface(struct hostapd_iface *hapd_iface)
|
||||
{
|
||||
size_t j;
|
||||
struct hostapd_bss_config *bss;
|
||||
const struct wpa_driver_ops *driver;
|
||||
void *drv_priv;
|
||||
|
||||
if (hapd_iface == NULL)
|
||||
return -1;
|
||||
bss = hapd_iface->bss[0]->conf;
|
||||
driver = hapd_iface->bss[0]->driver;
|
||||
drv_priv = hapd_iface->bss[0]->drv_priv;
|
||||
|
||||
/* whatever hostapd_interface_deinit does */
|
||||
for (j = 0; j < hapd_iface->num_bss; j++) {
|
||||
struct hostapd_data *hapd = hapd_iface->bss[j];
|
||||
hostapd_free_stas(hapd);
|
||||
hostapd_flush_old_stations(hapd, WLAN_REASON_DEAUTH_LEAVING);
|
||||
hostapd_clear_wep(hapd);
|
||||
hostapd_free_hapd_data(hapd);
|
||||
}
|
||||
|
||||
if (driver && driver->hapd_deinit && drv_priv) {
|
||||
driver->hapd_deinit(drv_priv);
|
||||
hapd_iface->bss[0]->drv_priv = NULL;
|
||||
}
|
||||
|
||||
/* From hostapd_cleanup_iface: These were initialized in
|
||||
* hostapd_setup_interface and hostapd_setup_interface_complete
|
||||
*/
|
||||
hostapd_cleanup_iface_partial(hapd_iface);
|
||||
bss->wpa = 0;
|
||||
bss->wpa_key_mgmt = -1;
|
||||
bss->wpa_pairwise = -1;
|
||||
|
||||
wpa_printf(MSG_DEBUG, "Interface %s disabled", bss->iface);
|
||||
return 0;
|
||||
}
|
||||
|
||||
|
||||
static struct hostapd_iface *
|
||||
hostapd_iface_alloc(struct hapd_interfaces *interfaces)
|
||||
{
|
||||
struct hostapd_iface **iface, *hapd_iface;
|
||||
|
||||
iface = os_realloc_array(interfaces->iface, interfaces->count + 1,
|
||||
sizeof(struct hostapd_iface *));
|
||||
if (iface == NULL)
|
||||
return NULL;
|
||||
interfaces->iface = iface;
|
||||
hapd_iface = interfaces->iface[interfaces->count] =
|
||||
os_zalloc(sizeof(*hapd_iface));
|
||||
if (hapd_iface == NULL) {
|
||||
wpa_printf(MSG_ERROR, "%s: Failed to allocate memory for "
|
||||
"the interface", __func__);
|
||||
return NULL;
|
||||
}
|
||||
interfaces->count++;
|
||||
hapd_iface->interfaces = interfaces;
|
||||
|
||||
return hapd_iface;
|
||||
}
|
||||
|
||||
|
||||
static struct hostapd_config *
|
||||
hostapd_config_alloc(struct hapd_interfaces *interfaces, const char *ifname,
|
||||
const char *ctrl_iface)
|
||||
{
|
||||
struct hostapd_bss_config *bss;
|
||||
struct hostapd_config *conf;
|
||||
|
||||
/* Allocates memory for bss and conf */
|
||||
conf = hostapd_config_defaults();
|
||||
if (conf == NULL) {
|
||||
wpa_printf(MSG_ERROR, "%s: Failed to allocate memory for "
|
||||
"configuration", __func__);
|
||||
return NULL;
|
||||
}
|
||||
|
||||
conf->driver = wpa_drivers[0];
|
||||
if (conf->driver == NULL) {
|
||||
wpa_printf(MSG_ERROR, "No driver wrappers registered!");
|
||||
hostapd_config_free(conf);
|
||||
return NULL;
|
||||
}
|
||||
|
||||
bss = conf->last_bss = conf->bss;
|
||||
|
||||
os_strlcpy(bss->iface, ifname, sizeof(bss->iface));
|
||||
bss->ctrl_interface = os_strdup(ctrl_iface);
|
||||
if (bss->ctrl_interface == NULL) {
|
||||
hostapd_config_free(conf);
|
||||
return NULL;
|
||||
}
|
||||
|
||||
/* Reading configuration file skipped, will be done in SET!
|
||||
* From reading the configuration till the end has to be done in
|
||||
* SET
|
||||
*/
|
||||
return conf;
|
||||
}
|
||||
|
||||
|
||||
static struct hostapd_iface * hostapd_data_alloc(
|
||||
struct hapd_interfaces *interfaces, struct hostapd_config *conf)
|
||||
{
|
||||
size_t i;
|
||||
struct hostapd_iface *hapd_iface =
|
||||
interfaces->iface[interfaces->count - 1];
|
||||
struct hostapd_data *hapd;
|
||||
|
||||
hapd_iface->conf = conf;
|
||||
hapd_iface->num_bss = conf->num_bss;
|
||||
|
||||
hapd_iface->bss = os_zalloc(conf->num_bss *
|
||||
sizeof(struct hostapd_data *));
|
||||
if (hapd_iface->bss == NULL)
|
||||
return NULL;
|
||||
|
||||
for (i = 0; i < conf->num_bss; i++) {
|
||||
hapd = hapd_iface->bss[i] =
|
||||
hostapd_alloc_bss_data(hapd_iface, conf,
|
||||
&conf->bss[i]);
|
||||
if (hapd == NULL)
|
||||
return NULL;
|
||||
hapd->msg_ctx = hapd;
|
||||
}
|
||||
|
||||
hapd_iface->interfaces = interfaces;
|
||||
|
||||
return hapd_iface;
|
||||
}
|
||||
|
||||
|
||||
int hostapd_add_iface(struct hapd_interfaces *interfaces, char *buf)
|
||||
{
|
||||
struct hostapd_config *conf = NULL;
|
||||
struct hostapd_iface *hapd_iface = NULL;
|
||||
char *ptr;
|
||||
size_t i;
|
||||
|
||||
ptr = os_strchr(buf, ' ');
|
||||
if (ptr == NULL)
|
||||
return -1;
|
||||
*ptr++ = '\0';
|
||||
|
||||
for (i = 0; i < interfaces->count; i++) {
|
||||
if (!os_strcmp(interfaces->iface[i]->conf->bss[0].iface,
|
||||
buf)) {
|
||||
wpa_printf(MSG_INFO, "Cannot add interface - it "
|
||||
"already exists");
|
||||
return -1;
|
||||
}
|
||||
}
|
||||
|
||||
hapd_iface = hostapd_iface_alloc(interfaces);
|
||||
if (hapd_iface == NULL) {
|
||||
wpa_printf(MSG_ERROR, "%s: Failed to allocate memory "
|
||||
"for interface", __func__);
|
||||
goto fail;
|
||||
}
|
||||
|
||||
conf = hostapd_config_alloc(interfaces, buf, ptr);
|
||||
if (conf == NULL) {
|
||||
wpa_printf(MSG_ERROR, "%s: Failed to allocate memory "
|
||||
"for configuration", __func__);
|
||||
goto fail;
|
||||
}
|
||||
|
||||
hapd_iface = hostapd_data_alloc(interfaces, conf);
|
||||
if (hapd_iface == NULL) {
|
||||
wpa_printf(MSG_ERROR, "%s: Failed to allocate memory "
|
||||
"for hostapd", __func__);
|
||||
goto fail;
|
||||
}
|
||||
|
||||
if (hapd_iface->interfaces &&
|
||||
hapd_iface->interfaces->ctrl_iface_init &&
|
||||
hapd_iface->interfaces->ctrl_iface_init(hapd_iface->bss[0])) {
|
||||
wpa_printf(MSG_ERROR, "%s: Failed to setup control "
|
||||
"interface", __func__);
|
||||
goto fail;
|
||||
}
|
||||
wpa_printf(MSG_INFO, "Add interface '%s'", conf->bss[0].iface);
|
||||
|
||||
return 0;
|
||||
|
||||
fail:
|
||||
if (conf)
|
||||
hostapd_config_free(conf);
|
||||
if (hapd_iface) {
|
||||
os_free(hapd_iface->bss[interfaces->count]);
|
||||
os_free(hapd_iface);
|
||||
}
|
||||
return -1;
|
||||
}
|
||||
|
||||
|
||||
int hostapd_remove_iface(struct hapd_interfaces *interfaces, char *buf)
|
||||
{
|
||||
struct hostapd_iface *hapd_iface;
|
||||
size_t i, k = 0;
|
||||
|
||||
for (i = 0; i < interfaces->count; i++) {
|
||||
hapd_iface = interfaces->iface[i];
|
||||
if (hapd_iface == NULL)
|
||||
return -1;
|
||||
if (!os_strcmp(hapd_iface->conf->bss[0].iface, buf)) {
|
||||
wpa_printf(MSG_INFO, "Remove interface '%s'", buf);
|
||||
hostapd_interface_deinit_free(hapd_iface);
|
||||
k = i;
|
||||
while (k < (interfaces->count - 1)) {
|
||||
interfaces->iface[k] =
|
||||
interfaces->iface[k + 1];
|
||||
k++;
|
||||
}
|
||||
interfaces->count--;
|
||||
return 0;
|
||||
}
|
||||
}
|
||||
return -1;
|
||||
}
|
||||
|
||||
#endif /* HOSTAPD */
|
||||
|
||||
|
||||
/**
|
||||
* hostapd_new_assoc_sta - Notify that a new station associated with the AP
|
||||
* @hapd: Pointer to BSS data
|
||||
|
@ -930,8 +1379,10 @@ void hostapd_new_assoc_sta(struct hostapd_data *hapd, struct sta_info *sta,
|
|||
/* Start accounting here, if IEEE 802.1X and WPA are not used.
|
||||
* IEEE 802.1X/WPA code will start accounting after the station has
|
||||
* been authorized. */
|
||||
if (!hapd->conf->ieee802_1x && !hapd->conf->wpa)
|
||||
if (!hapd->conf->ieee802_1x && !hapd->conf->wpa) {
|
||||
os_get_time(&sta->connected_time);
|
||||
accounting_sta_start(hapd, sta);
|
||||
}
|
||||
|
||||
/* Start IEEE 802.1X authentication process for new stations */
|
||||
ieee802_1x_new_station(hapd, sta);
|
||||
|
@ -941,4 +1392,12 @@ void hostapd_new_assoc_sta(struct hostapd_data *hapd, struct sta_info *sta,
|
|||
wpa_auth_sm_event(sta->wpa_sm, WPA_REAUTH);
|
||||
} else
|
||||
wpa_auth_sta_associated(hapd->wpa_auth, sta->wpa_sm);
|
||||
|
||||
wpa_printf(MSG_DEBUG, "%s: reschedule ap_handle_timer timeout "
|
||||
"for " MACSTR " (%d seconds - ap_max_inactivity)",
|
||||
__func__, MAC2STR(sta->addr),
|
||||
hapd->conf->ap_max_inactivity);
|
||||
eloop_cancel_timeout(ap_handle_timer, hapd, sta);
|
||||
eloop_register_timeout(hapd->conf->ap_max_inactivity, 0,
|
||||
ap_handle_timer, hapd, sta);
|
||||
}
|
||||
|
|
|
@ -2,26 +2,20 @@
|
|||
* 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;
|
||||
|
@ -30,9 +24,29 @@ 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 *da, const u8 *bssid,
|
||||
const u8 *ie, size_t ie_len);
|
||||
const u8 *ie, size_t ie_len, int ssi_signal);
|
||||
void *ctx;
|
||||
};
|
||||
|
||||
|
@ -46,7 +60,7 @@ struct hostapd_rate_data {
|
|||
struct hostapd_frame_info {
|
||||
u32 channel;
|
||||
u32 datarate;
|
||||
u32 ssi_signal;
|
||||
int ssi_signal; /* dBm */
|
||||
};
|
||||
|
||||
|
||||
|
@ -86,6 +100,7 @@ struct hostapd_data {
|
|||
|
||||
struct radius_client_data *radius;
|
||||
u32 acct_session_id_hi, acct_session_id_lo;
|
||||
struct radius_das_data *radius_das;
|
||||
|
||||
struct iapp_data *iapp;
|
||||
|
||||
|
@ -170,6 +185,13 @@ struct hostapd_data {
|
|||
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 */
|
||||
};
|
||||
|
||||
|
||||
|
@ -179,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;
|
||||
|
||||
|
@ -193,6 +213,13 @@ struct hostapd_iface {
|
|||
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;
|
||||
|
@ -200,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;
|
||||
|
@ -230,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,
|
||||
|
@ -251,12 +275,19 @@ 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 *da, const u8 *bssid,
|
||||
const u8 *ie, size_t ie_len),
|
||||
const u8 *ie, size_t ie_len,
|
||||
int ssi_signal),
|
||||
void *ctx);
|
||||
void hostapd_prune_associations(struct hostapd_data *hapd, const u8 *addr);
|
||||
|
||||
|
@ -266,6 +297,13 @@ int hostapd_notif_assoc(struct hostapd_data *hapd, const u8 *addr,
|
|||
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);
|
||||
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 */
|
||||
|
|
|
@ -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;
|
||||
}
|
|
@ -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,7 +101,7 @@ int hostapd_get_hw_features(struct hostapd_iface *iface)
|
|||
}
|
||||
|
||||
|
||||
int hostapd_prepare_rates(struct hostapd_data *hapd,
|
||||
int hostapd_prepare_rates(struct hostapd_iface *iface,
|
||||
struct hostapd_hw_modes *mode)
|
||||
{
|
||||
int i, num_basic_rates = 0;
|
||||
|
@ -110,8 +110,8 @@ 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 @@ 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,27 +152,27 @@ 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) &&
|
||||
(!hapd->iconf->ieee80211n || !hapd->iconf->require_ht)) {
|
||||
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;
|
||||
}
|
||||
|
||||
|
@ -414,7 +420,7 @@ static void ieee80211n_check_scan(struct hostapd_iface *iface)
|
|||
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;
|
||||
|
||||
|
@ -445,6 +451,46 @@ static void ieee80211n_check_scan(struct hostapd_iface *iface)
|
|||
}
|
||||
|
||||
|
||||
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;
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
static int ieee80211n_check_40mhz(struct hostapd_iface *iface)
|
||||
{
|
||||
struct wpa_driver_scan_params params;
|
||||
|
@ -455,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;
|
||||
|
@ -629,8 +678,15 @@ int hostapd_select_hw_mode(struct hostapd_iface *iface)
|
|||
if (chan->flag & HOSTAPD_CHAN_DISABLED) {
|
||||
wpa_printf(MSG_ERROR,
|
||||
"channel [%i] (%i) is disabled for "
|
||||
"use in AP mode, flags: 0x%x",
|
||||
j, chan->chan, chan->flag);
|
||||
"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;
|
||||
|
@ -702,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,7 +26,7 @@ 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_data *hapd,
|
||||
int hostapd_prepare_rates(struct hostapd_iface *iface,
|
||||
struct hostapd_hw_modes *mode);
|
||||
#else /* NEED_AP_MLME */
|
||||
static inline void
|
||||
|
@ -59,7 +60,7 @@ static inline int hostapd_check_ht_capab(struct hostapd_iface *iface)
|
|||
return 0;
|
||||
}
|
||||
|
||||
static inline int hostapd_prepare_rates(struct hostapd_data *hapd,
|
||||
static inline int hostapd_prepare_rates(struct hostapd_iface *iface,
|
||||
struct hostapd_hw_modes *mode)
|
||||
{
|
||||
return 0;
|
||||
|
|
|
@ -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
|
||||
|
|
|
@ -1,15 +1,9 @@
|
|||
/*
|
||||
* hostapd / IEEE 802.11 Management
|
||||
* Copyright (c) 2002-2011, 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"
|
||||
|
@ -40,6 +34,7 @@
|
|||
#include "ap_mlme.h"
|
||||
#include "p2p_hostapd.h"
|
||||
#include "ap_drv_ops.h"
|
||||
#include "wnm_ap.h"
|
||||
#include "ieee802_11.h"
|
||||
|
||||
|
||||
|
@ -55,6 +50,8 @@ u8 * hostapd_eid_supp_rates(struct hostapd_data *hapd, u8 *eid)
|
|||
num = hapd->iface->num_rates;
|
||||
if (hapd->iconf->ieee80211n && hapd->iconf->require_ht)
|
||||
num++;
|
||||
if (hapd->iconf->ieee80211ac && hapd->iconf->require_vht)
|
||||
num++;
|
||||
if (num > 8) {
|
||||
/* rest of the rates are encoded in Extended supported
|
||||
* rates element */
|
||||
|
@ -72,9 +69,15 @@ u8 * hostapd_eid_supp_rates(struct hostapd_data *hapd, u8 *eid)
|
|||
pos++;
|
||||
}
|
||||
|
||||
if (hapd->iconf->ieee80211n && hapd->iconf->require_ht &&
|
||||
hapd->iface->num_rates < 8)
|
||||
if (hapd->iconf->ieee80211n && hapd->iconf->require_ht && count < 8) {
|
||||
count++;
|
||||
*pos++ = 0x80 | BSS_MEMBERSHIP_SELECTOR_HT_PHY;
|
||||
}
|
||||
|
||||
if (hapd->iconf->ieee80211ac && hapd->iconf->require_vht && count < 8) {
|
||||
count++;
|
||||
*pos++ = 0x80 | BSS_MEMBERSHIP_SELECTOR_VHT_PHY;
|
||||
}
|
||||
|
||||
return pos;
|
||||
}
|
||||
|
@ -91,6 +94,8 @@ u8 * hostapd_eid_ext_supp_rates(struct hostapd_data *hapd, u8 *eid)
|
|||
num = hapd->iface->num_rates;
|
||||
if (hapd->iconf->ieee80211n && hapd->iconf->require_ht)
|
||||
num++;
|
||||
if (hapd->iconf->ieee80211ac && hapd->iconf->require_vht)
|
||||
num++;
|
||||
if (num <= 8)
|
||||
return eid;
|
||||
num -= 8;
|
||||
|
@ -109,9 +114,17 @@ u8 * hostapd_eid_ext_supp_rates(struct hostapd_data *hapd, u8 *eid)
|
|||
pos++;
|
||||
}
|
||||
|
||||
if (hapd->iconf->ieee80211n && hapd->iconf->require_ht &&
|
||||
hapd->iface->num_rates >= 8)
|
||||
*pos++ = 0x80 | BSS_MEMBERSHIP_SELECTOR_HT_PHY;
|
||||
if (hapd->iconf->ieee80211n && hapd->iconf->require_ht) {
|
||||
count++;
|
||||
if (count > 8)
|
||||
*pos++ = 0x80 | BSS_MEMBERSHIP_SELECTOR_HT_PHY;
|
||||
}
|
||||
|
||||
if (hapd->iconf->ieee80211ac && hapd->iconf->require_vht) {
|
||||
count++;
|
||||
if (count > 8)
|
||||
*pos++ = 0x80 | BSS_MEMBERSHIP_SELECTOR_VHT_PHY;
|
||||
}
|
||||
|
||||
return pos;
|
||||
}
|
||||
|
@ -269,7 +282,7 @@ static void send_auth_reply(struct hostapd_data *hapd,
|
|||
" auth_alg=%d auth_transaction=%d resp=%d (IE len=%lu)",
|
||||
MAC2STR(dst), auth_alg, auth_transaction,
|
||||
resp, (unsigned long) ies_len);
|
||||
if (hostapd_drv_send_mlme(hapd, reply, rlen) < 0)
|
||||
if (hostapd_drv_send_mlme(hapd, reply, rlen, 0) < 0)
|
||||
perror("send_auth_reply: send");
|
||||
|
||||
os_free(buf);
|
||||
|
@ -302,6 +315,142 @@ static void handle_auth_ft_finish(void *ctx, const u8 *dst, const u8 *bssid,
|
|||
#endif /* CONFIG_IEEE80211R */
|
||||
|
||||
|
||||
#ifdef CONFIG_SAE
|
||||
|
||||
static struct wpabuf * auth_build_sae_commit(struct hostapd_data *hapd,
|
||||
struct sta_info *sta)
|
||||
{
|
||||
struct wpabuf *buf;
|
||||
|
||||
buf = wpabuf_alloc(2);
|
||||
if (buf == NULL)
|
||||
return NULL;
|
||||
|
||||
wpabuf_put_le16(buf, 19); /* Finite Cyclic Group */
|
||||
/* TODO: Anti-Clogging Token (if requested) */
|
||||
/* TODO: Scalar */
|
||||
/* TODO: Element */
|
||||
|
||||
return buf;
|
||||
}
|
||||
|
||||
|
||||
static struct wpabuf * auth_build_sae_confirm(struct hostapd_data *hapd,
|
||||
struct sta_info *sta)
|
||||
{
|
||||
struct wpabuf *buf;
|
||||
|
||||
buf = wpabuf_alloc(2);
|
||||
if (buf == NULL)
|
||||
return NULL;
|
||||
|
||||
wpabuf_put_le16(buf, sta->sae_send_confirm);
|
||||
sta->sae_send_confirm++;
|
||||
/* TODO: Confirm */
|
||||
|
||||
return buf;
|
||||
}
|
||||
|
||||
|
||||
static u16 handle_sae_commit(struct hostapd_data *hapd, struct sta_info *sta,
|
||||
const u8 *data, size_t len)
|
||||
{
|
||||
wpa_hexdump(MSG_DEBUG, "SAE commit fields", data, len);
|
||||
|
||||
/* Check Finite Cyclic Group */
|
||||
if (len < 2)
|
||||
return WLAN_STATUS_UNSPECIFIED_FAILURE;
|
||||
if (WPA_GET_LE16(data) != 19) {
|
||||
wpa_printf(MSG_DEBUG, "SAE: Unsupported Finite Cyclic Group %u",
|
||||
WPA_GET_LE16(data));
|
||||
return WLAN_STATUS_FINITE_CYCLIC_GROUP_NOT_SUPPORTED;
|
||||
}
|
||||
|
||||
return WLAN_STATUS_SUCCESS;
|
||||
}
|
||||
|
||||
|
||||
static u16 handle_sae_confirm(struct hostapd_data *hapd, struct sta_info *sta,
|
||||
const u8 *data, size_t len)
|
||||
{
|
||||
u16 rc;
|
||||
|
||||
wpa_hexdump(MSG_DEBUG, "SAE confirm fields", data, len);
|
||||
|
||||
if (len < 2)
|
||||
return WLAN_STATUS_UNSPECIFIED_FAILURE;
|
||||
rc = WPA_GET_LE16(data);
|
||||
wpa_printf(MSG_DEBUG, "SAE: peer-send-confirm %u", rc);
|
||||
|
||||
return WLAN_STATUS_SUCCESS;
|
||||
}
|
||||
|
||||
|
||||
static void handle_auth_sae(struct hostapd_data *hapd, struct sta_info *sta,
|
||||
const struct ieee80211_mgmt *mgmt, size_t len,
|
||||
u8 auth_transaction)
|
||||
{
|
||||
u16 resp = WLAN_STATUS_SUCCESS;
|
||||
struct wpabuf *data;
|
||||
|
||||
if (auth_transaction == 1) {
|
||||
hostapd_logger(hapd, sta->addr, HOSTAPD_MODULE_IEEE80211,
|
||||
HOSTAPD_LEVEL_DEBUG,
|
||||
"start SAE authentication (RX commit)");
|
||||
resp = handle_sae_commit(hapd, sta, mgmt->u.auth.variable,
|
||||
((u8 *) mgmt) + len -
|
||||
mgmt->u.auth.variable);
|
||||
if (resp == WLAN_STATUS_SUCCESS)
|
||||
sta->sae_state = SAE_COMMIT;
|
||||
} else if (auth_transaction == 2) {
|
||||
if (sta->sae_state != SAE_COMMIT) {
|
||||
hostapd_logger(hapd, sta->addr,
|
||||
HOSTAPD_MODULE_IEEE80211,
|
||||
HOSTAPD_LEVEL_DEBUG,
|
||||
"SAE confirm before commit");
|
||||
resp = WLAN_STATUS_UNKNOWN_AUTH_TRANSACTION;
|
||||
}
|
||||
hostapd_logger(hapd, sta->addr, HOSTAPD_MODULE_IEEE80211,
|
||||
HOSTAPD_LEVEL_DEBUG,
|
||||
"SAE authentication (RX confirm)");
|
||||
resp = handle_sae_confirm(hapd, sta, mgmt->u.auth.variable,
|
||||
((u8 *) mgmt) + len -
|
||||
mgmt->u.auth.variable);
|
||||
if (resp == WLAN_STATUS_SUCCESS) {
|
||||
sta->flags |= WLAN_STA_AUTH;
|
||||
wpa_auth_sm_event(sta->wpa_sm, WPA_AUTH);
|
||||
sta->auth_alg = WLAN_AUTH_SAE;
|
||||
mlme_authenticate_indication(hapd, sta);
|
||||
}
|
||||
} else {
|
||||
hostapd_logger(hapd, sta->addr, HOSTAPD_MODULE_IEEE80211,
|
||||
HOSTAPD_LEVEL_DEBUG,
|
||||
"unexpected SAE authentication transaction %u",
|
||||
auth_transaction);
|
||||
resp = WLAN_STATUS_UNKNOWN_AUTH_TRANSACTION;
|
||||
}
|
||||
|
||||
sta->auth_alg = WLAN_AUTH_SAE;
|
||||
|
||||
if (resp == WLAN_STATUS_SUCCESS) {
|
||||
if (auth_transaction == 1)
|
||||
data = auth_build_sae_commit(hapd, sta);
|
||||
else
|
||||
data = auth_build_sae_confirm(hapd, sta);
|
||||
if (data == NULL)
|
||||
resp = WLAN_STATUS_UNSPECIFIED_FAILURE;
|
||||
} else
|
||||
data = NULL;
|
||||
|
||||
send_auth_reply(hapd, mgmt->sa, mgmt->bssid, WLAN_AUTH_SAE,
|
||||
auth_transaction, resp,
|
||||
data ? wpabuf_head(data) : (u8 *) "",
|
||||
data ? wpabuf_len(data) : 0);
|
||||
wpabuf_free(data);
|
||||
}
|
||||
#endif /* CONFIG_SAE */
|
||||
|
||||
|
||||
static void handle_auth(struct hostapd_data *hapd,
|
||||
const struct ieee80211_mgmt *mgmt, size_t len)
|
||||
{
|
||||
|
@ -313,8 +462,11 @@ static void handle_auth(struct hostapd_data *hapd,
|
|||
const u8 *challenge = NULL;
|
||||
u32 session_timeout, acct_interim_interval;
|
||||
int vlan_id = 0;
|
||||
struct hostapd_sta_wpa_psk_short *psk = NULL;
|
||||
u8 resp_ies[2 + WLAN_AUTH_CHALLENGE_LEN];
|
||||
size_t resp_ies_len = 0;
|
||||
char *identity = NULL;
|
||||
char *radius_cui = NULL;
|
||||
|
||||
if (len < IEEE80211_HDRLEN + sizeof(mgmt->u.auth)) {
|
||||
printf("handle_auth - too short payload (len=%lu)\n",
|
||||
|
@ -347,11 +499,13 @@ static void handle_auth(struct hostapd_data *hapd,
|
|||
if (!(((hapd->conf->auth_algs & WPA_AUTH_ALG_OPEN) &&
|
||||
auth_alg == WLAN_AUTH_OPEN) ||
|
||||
#ifdef CONFIG_IEEE80211R
|
||||
(hapd->conf->wpa &&
|
||||
(hapd->conf->wpa_key_mgmt &
|
||||
(WPA_KEY_MGMT_FT_IEEE8021X | WPA_KEY_MGMT_FT_PSK)) &&
|
||||
(hapd->conf->wpa && wpa_key_mgmt_ft(hapd->conf->wpa_key_mgmt) &&
|
||||
auth_alg == WLAN_AUTH_FT) ||
|
||||
#endif /* CONFIG_IEEE80211R */
|
||||
#ifdef CONFIG_SAE
|
||||
(hapd->conf->wpa && wpa_key_mgmt_sae(hapd->conf->wpa_key_mgmt) &&
|
||||
auth_alg == WLAN_AUTH_SAE) ||
|
||||
#endif /* CONFIG_SAE */
|
||||
((hapd->conf->auth_algs & WPA_AUTH_ALG_SHARED) &&
|
||||
auth_alg == WLAN_AUTH_SHARED_KEY))) {
|
||||
printf("Unsupported authentication algorithm (%d)\n",
|
||||
|
@ -360,7 +514,7 @@ static void handle_auth(struct hostapd_data *hapd,
|
|||
goto fail;
|
||||
}
|
||||
|
||||
if (!(auth_transaction == 1 ||
|
||||
if (!(auth_transaction == 1 || auth_alg == WLAN_AUTH_SAE ||
|
||||
(auth_alg == WLAN_AUTH_SHARED_KEY && auth_transaction == 3))) {
|
||||
printf("Unknown authentication transaction number (%d)\n",
|
||||
auth_transaction);
|
||||
|
@ -377,7 +531,9 @@ static void handle_auth(struct hostapd_data *hapd,
|
|||
|
||||
res = hostapd_allowed_address(hapd, mgmt->sa, (u8 *) mgmt, len,
|
||||
&session_timeout,
|
||||
&acct_interim_interval, &vlan_id);
|
||||
&acct_interim_interval, &vlan_id,
|
||||
&psk, &identity, &radius_cui);
|
||||
|
||||
if (res == HOSTAPD_ACL_REJECT) {
|
||||
printf("Station " MACSTR " not allowed to authenticate.\n",
|
||||
MAC2STR(mgmt->sa));
|
||||
|
@ -415,6 +571,19 @@ static void handle_auth(struct hostapd_data *hapd,
|
|||
HOSTAPD_LEVEL_INFO, "VLAN ID %d", sta->vlan_id);
|
||||
}
|
||||
|
||||
hostapd_free_psk_list(sta->psk);
|
||||
if (hapd->conf->wpa_psk_radius != PSK_RADIUS_IGNORED) {
|
||||
sta->psk = psk;
|
||||
psk = NULL;
|
||||
} else {
|
||||
sta->psk = NULL;
|
||||
}
|
||||
|
||||
sta->identity = identity;
|
||||
identity = NULL;
|
||||
sta->radius_cui = radius_cui;
|
||||
radius_cui = NULL;
|
||||
|
||||
sta->flags &= ~WLAN_STA_PREAUTH;
|
||||
ieee802_1x_notify_pre_auth(sta->eapol_sm, 0);
|
||||
|
||||
|
@ -473,9 +642,18 @@ static void handle_auth(struct hostapd_data *hapd,
|
|||
/* handle_auth_ft_finish() callback will complete auth. */
|
||||
return;
|
||||
#endif /* CONFIG_IEEE80211R */
|
||||
#ifdef CONFIG_SAE
|
||||
case WLAN_AUTH_SAE:
|
||||
handle_auth_sae(hapd, sta, mgmt, len, auth_transaction);
|
||||
return;
|
||||
#endif /* CONFIG_SAE */
|
||||
}
|
||||
|
||||
fail:
|
||||
os_free(identity);
|
||||
os_free(radius_cui);
|
||||
hostapd_free_psk_list(psk);
|
||||
|
||||
send_auth_reply(hapd, mgmt->sa, mgmt->bssid, auth_alg,
|
||||
auth_transaction + 1, resp, resp_ies, resp_ies_len);
|
||||
}
|
||||
|
@ -539,15 +717,22 @@ static u16 check_wmm(struct hostapd_data *hapd, struct sta_info *sta,
|
|||
const u8 *wmm_ie, size_t wmm_ie_len)
|
||||
{
|
||||
sta->flags &= ~WLAN_STA_WMM;
|
||||
sta->qosinfo = 0;
|
||||
if (wmm_ie && hapd->conf->wmm_enabled) {
|
||||
if (!hostapd_eid_wmm_valid(hapd, wmm_ie, wmm_ie_len))
|
||||
struct wmm_information_element *wmm;
|
||||
|
||||
if (!hostapd_eid_wmm_valid(hapd, wmm_ie, wmm_ie_len)) {
|
||||
hostapd_logger(hapd, sta->addr,
|
||||
HOSTAPD_MODULE_WPA,
|
||||
HOSTAPD_LEVEL_DEBUG,
|
||||
"invalid WMM element in association "
|
||||
"request");
|
||||
else
|
||||
sta->flags |= WLAN_STA_WMM;
|
||||
return WLAN_STATUS_UNSPECIFIED_FAILURE;
|
||||
}
|
||||
|
||||
sta->flags |= WLAN_STA_WMM;
|
||||
wmm = (struct wmm_information_element *) wmm_ie;
|
||||
sta->qosinfo = wmm->qos_info;
|
||||
}
|
||||
return WLAN_STATUS_SUCCESS;
|
||||
}
|
||||
|
@ -563,35 +748,20 @@ static u16 copy_supp_rates(struct hostapd_data *hapd, struct sta_info *sta,
|
|||
return WLAN_STATUS_UNSPECIFIED_FAILURE;
|
||||
}
|
||||
|
||||
if (elems->supp_rates_len > sizeof(sta->supported_rates)) {
|
||||
if (elems->supp_rates_len + elems->ext_supp_rates_len >
|
||||
sizeof(sta->supported_rates)) {
|
||||
hostapd_logger(hapd, sta->addr, HOSTAPD_MODULE_IEEE80211,
|
||||
HOSTAPD_LEVEL_DEBUG,
|
||||
"Invalid supported rates element length %d",
|
||||
elems->supp_rates_len);
|
||||
"Invalid supported rates element length %d+%d",
|
||||
elems->supp_rates_len,
|
||||
elems->ext_supp_rates_len);
|
||||
return WLAN_STATUS_UNSPECIFIED_FAILURE;
|
||||
}
|
||||
|
||||
os_memset(sta->supported_rates, 0, sizeof(sta->supported_rates));
|
||||
os_memcpy(sta->supported_rates, elems->supp_rates,
|
||||
elems->supp_rates_len);
|
||||
sta->supported_rates_len = elems->supp_rates_len;
|
||||
|
||||
if (elems->ext_supp_rates) {
|
||||
if (elems->supp_rates_len + elems->ext_supp_rates_len >
|
||||
sizeof(sta->supported_rates)) {
|
||||
hostapd_logger(hapd, sta->addr,
|
||||
HOSTAPD_MODULE_IEEE80211,
|
||||
HOSTAPD_LEVEL_DEBUG,
|
||||
"Invalid supported rates element length"
|
||||
" %d+%d", elems->supp_rates_len,
|
||||
elems->ext_supp_rates_len);
|
||||
return WLAN_STATUS_UNSPECIFIED_FAILURE;
|
||||
}
|
||||
|
||||
os_memcpy(sta->supported_rates + elems->supp_rates_len,
|
||||
elems->ext_supp_rates, elems->ext_supp_rates_len);
|
||||
sta->supported_rates_len += elems->ext_supp_rates_len;
|
||||
}
|
||||
sta->supported_rates_len = merge_byte_arrays(
|
||||
sta->supported_rates, sizeof(sta->supported_rates),
|
||||
elems->supp_rates, elems->supp_rates_len,
|
||||
elems->ext_supp_rates, elems->ext_supp_rates_len);
|
||||
|
||||
return WLAN_STATUS_SUCCESS;
|
||||
}
|
||||
|
@ -635,6 +805,20 @@ static u16 check_assoc_ies(struct hostapd_data *hapd, struct sta_info *sta,
|
|||
}
|
||||
#endif /* CONFIG_IEEE80211N */
|
||||
|
||||
#ifdef CONFIG_IEEE80211AC
|
||||
resp = copy_sta_vht_capab(hapd, sta, elems.vht_capabilities,
|
||||
elems.vht_capabilities_len);
|
||||
if (resp != WLAN_STATUS_SUCCESS)
|
||||
return resp;
|
||||
if (hapd->iconf->ieee80211ac && hapd->iconf->require_vht &&
|
||||
!(sta->flags & WLAN_STA_VHT)) {
|
||||
hostapd_logger(hapd, sta->addr, HOSTAPD_MODULE_IEEE80211,
|
||||
HOSTAPD_LEVEL_INFO, "Station does not support "
|
||||
"mandatory VHT PHY - reject association");
|
||||
return WLAN_STATUS_UNSPECIFIED_FAILURE;
|
||||
}
|
||||
#endif /* CONFIG_IEEE80211AC */
|
||||
|
||||
if ((hapd->conf->wpa & WPA_PROTO_RSN) && elems.rsn_ie) {
|
||||
wpa_ie = elems.rsn_ie;
|
||||
wpa_ie_len = elems.rsn_ie_len;
|
||||
|
@ -757,8 +941,18 @@ static u16 check_assoc_ies(struct hostapd_data *hapd, struct sta_info *sta,
|
|||
}
|
||||
#endif /* CONFIG_IEEE80211R */
|
||||
|
||||
#ifdef CONFIG_SAE
|
||||
if (wpa_auth_uses_sae(sta->wpa_sm) &&
|
||||
sta->auth_alg != WLAN_AUTH_SAE) {
|
||||
wpa_printf(MSG_DEBUG, "SAE: " MACSTR " tried to use "
|
||||
"SAE AKM after non-SAE auth_alg %u",
|
||||
MAC2STR(sta->addr), sta->auth_alg);
|
||||
return WLAN_STATUS_NOT_SUPPORTED_AUTH_ALG;
|
||||
}
|
||||
#endif /* CONFIG_SAE */
|
||||
|
||||
#ifdef CONFIG_IEEE80211N
|
||||
if ((sta->flags & WLAN_STA_HT) &&
|
||||
if ((sta->flags & (WLAN_STA_HT | WLAN_STA_VHT)) &&
|
||||
wpa_auth_get_pairwise(sta->wpa_sm) == WPA_CIPHER_TKIP) {
|
||||
hostapd_logger(hapd, sta->addr,
|
||||
HOSTAPD_MODULE_IEEE80211,
|
||||
|
@ -785,6 +979,15 @@ static u16 check_assoc_ies(struct hostapd_data *hapd, struct sta_info *sta,
|
|||
p2p_group_notif_assoc(hapd->p2p_group, sta->addr, ies, ies_len);
|
||||
#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 */
|
||||
|
||||
return WLAN_STATUS_SUCCESS;
|
||||
}
|
||||
|
||||
|
@ -805,7 +1008,7 @@ static void send_deauth(struct hostapd_data *hapd, const u8 *addr,
|
|||
send_len = IEEE80211_HDRLEN + sizeof(reply.u.deauth);
|
||||
reply.u.deauth.reason_code = host_to_le16(reason_code);
|
||||
|
||||
if (hostapd_drv_send_mlme(hapd, &reply, send_len) < 0)
|
||||
if (hostapd_drv_send_mlme(hapd, &reply, send_len, 0) < 0)
|
||||
wpa_printf(MSG_INFO, "Failed to send deauth: %s",
|
||||
strerror(errno));
|
||||
}
|
||||
|
@ -862,7 +1065,13 @@ static void send_assoc_resp(struct hostapd_data *hapd, struct sta_info *sta,
|
|||
p = hostapd_eid_ht_operation(hapd, p);
|
||||
#endif /* CONFIG_IEEE80211N */
|
||||
|
||||
#ifdef CONFIG_IEEE80211AC
|
||||
p = hostapd_eid_vht_capabilities(hapd, p);
|
||||
p = hostapd_eid_vht_operation(hapd, p);
|
||||
#endif /* CONFIG_IEEE80211AC */
|
||||
|
||||
p = hostapd_eid_ext_capab(hapd, p);
|
||||
p = hostapd_eid_bss_max_idle_period(hapd, p);
|
||||
|
||||
if (sta->flags & WLAN_STA_WMM)
|
||||
p = hostapd_eid_wmm(hapd, p);
|
||||
|
@ -911,7 +1120,7 @@ static void send_assoc_resp(struct hostapd_data *hapd, struct sta_info *sta,
|
|||
|
||||
send_len += p - reply->u.assoc_resp.variable;
|
||||
|
||||
if (hostapd_drv_send_mlme(hapd, reply, send_len) < 0)
|
||||
if (hostapd_drv_send_mlme(hapd, reply, send_len, 0) < 0)
|
||||
wpa_printf(MSG_INFO, "Failed to send assoc resp: %s",
|
||||
strerror(errno));
|
||||
}
|
||||
|
@ -1226,13 +1435,32 @@ static int robust_action_frame(u8 category)
|
|||
#endif /* CONFIG_IEEE80211W */
|
||||
|
||||
|
||||
#ifdef CONFIG_WNM
|
||||
static void hostapd_wnm_action(struct hostapd_data *hapd, struct sta_info *sta,
|
||||
const struct ieee80211_mgmt *mgmt,
|
||||
size_t len)
|
||||
{
|
||||
struct rx_action action;
|
||||
if (len < IEEE80211_HDRLEN + 2)
|
||||
return;
|
||||
os_memset(&action, 0, sizeof(action));
|
||||
action.da = mgmt->da;
|
||||
action.sa = mgmt->sa;
|
||||
action.bssid = mgmt->bssid;
|
||||
action.category = mgmt->u.action.category;
|
||||
action.data = (const u8 *) &mgmt->u.action.u.wnm_sleep_req.action;
|
||||
action.len = len - IEEE80211_HDRLEN - 1;
|
||||
action.freq = hapd->iface->freq;
|
||||
ieee802_11_rx_wnm_action_ap(hapd, &action);
|
||||
}
|
||||
#endif /* CONFIG_WNM */
|
||||
|
||||
|
||||
static void handle_action(struct hostapd_data *hapd,
|
||||
const struct ieee80211_mgmt *mgmt, size_t len)
|
||||
{
|
||||
#if defined(CONFIG_IEEE80211W) || defined(CONFIG_IEEE80211R)
|
||||
struct sta_info *sta;
|
||||
sta = ap_get_sta(hapd, mgmt->sa);
|
||||
#endif /* CONFIG_IEEE80211W || CONFIG_IEEE80211R */
|
||||
|
||||
if (len < IEEE80211_HDRLEN + 1) {
|
||||
hostapd_logger(hapd, mgmt->sa, HOSTAPD_MODULE_IEEE80211,
|
||||
|
@ -1242,6 +1470,14 @@ static void handle_action(struct hostapd_data *hapd,
|
|||
return;
|
||||
}
|
||||
|
||||
if (mgmt->u.action.category != WLAN_ACTION_PUBLIC &&
|
||||
(sta == NULL || !(sta->flags & WLAN_STA_ASSOC))) {
|
||||
wpa_printf(MSG_DEBUG, "IEEE 802.11: Ignored Action "
|
||||
"frame (category=%u) from unassociated STA " MACSTR,
|
||||
MAC2STR(mgmt->sa), mgmt->u.action.category);
|
||||
return;
|
||||
}
|
||||
|
||||
#ifdef CONFIG_IEEE80211W
|
||||
if (sta && (sta->flags & WLAN_STA_MFP) &&
|
||||
!(mgmt->frame_control & host_to_le16(WLAN_FC_ISWEP) &&
|
||||
|
@ -1257,20 +1493,10 @@ static void handle_action(struct hostapd_data *hapd,
|
|||
switch (mgmt->u.action.category) {
|
||||
#ifdef CONFIG_IEEE80211R
|
||||
case WLAN_ACTION_FT:
|
||||
{
|
||||
if (sta == NULL || !(sta->flags & WLAN_STA_ASSOC)) {
|
||||
wpa_printf(MSG_DEBUG, "IEEE 802.11: Ignored FT Action "
|
||||
"frame from unassociated STA " MACSTR,
|
||||
MAC2STR(mgmt->sa));
|
||||
return;
|
||||
}
|
||||
|
||||
if (wpa_ft_action_rx(sta->wpa_sm, (u8 *) &mgmt->u.action,
|
||||
len - IEEE80211_HDRLEN))
|
||||
break;
|
||||
|
||||
return;
|
||||
}
|
||||
#endif /* CONFIG_IEEE80211R */
|
||||
case WLAN_ACTION_WMM:
|
||||
hostapd_wmm_action(hapd, mgmt, len);
|
||||
|
@ -1280,6 +1506,11 @@ static void handle_action(struct hostapd_data *hapd,
|
|||
hostapd_sa_query_action(hapd, mgmt, len);
|
||||
return;
|
||||
#endif /* CONFIG_IEEE80211W */
|
||||
#ifdef CONFIG_WNM
|
||||
case WLAN_ACTION_WNM:
|
||||
hostapd_wnm_action(hapd, sta, mgmt, len);
|
||||
return;
|
||||
#endif /* CONFIG_WNM */
|
||||
case WLAN_ACTION_PUBLIC:
|
||||
if (hapd->public_action_cb) {
|
||||
hapd->public_action_cb(hapd->public_action_cb_ctx,
|
||||
|
@ -1323,7 +1554,10 @@ static void handle_action(struct hostapd_data *hapd,
|
|||
os_memcpy(resp->bssid, hapd->own_addr, ETH_ALEN);
|
||||
resp->u.action.category |= 0x80;
|
||||
|
||||
hostapd_drv_send_mlme(hapd, resp, len);
|
||||
if (hostapd_drv_send_mlme(hapd, resp, len, 0) < 0) {
|
||||
wpa_printf(MSG_ERROR, "IEEE 802.11: Failed to send "
|
||||
"Action frame");
|
||||
}
|
||||
os_free(resp);
|
||||
}
|
||||
}
|
||||
|
@ -1379,7 +1613,7 @@ void ieee802_11_mgmt(struct hostapd_data *hapd, const u8 *buf, size_t len,
|
|||
|
||||
|
||||
if (stype == WLAN_FC_STYPE_PROBE_REQ) {
|
||||
handle_probe_req(hapd, mgmt, len);
|
||||
handle_probe_req(hapd, mgmt, len, fi->ssi_signal);
|
||||
return;
|
||||
}
|
||||
|
||||
|
@ -1475,13 +1709,6 @@ static void handle_assoc_cb(struct hostapd_data *hapd,
|
|||
int new_assoc = 1;
|
||||
struct ieee80211_ht_capabilities ht_cap;
|
||||
|
||||
if (!ok) {
|
||||
hostapd_logger(hapd, mgmt->da, HOSTAPD_MODULE_IEEE80211,
|
||||
HOSTAPD_LEVEL_DEBUG,
|
||||
"did not acknowledge association response");
|
||||
return;
|
||||
}
|
||||
|
||||
if (len < IEEE80211_HDRLEN + (reassoc ? sizeof(mgmt->u.reassoc_resp) :
|
||||
sizeof(mgmt->u.assoc_resp))) {
|
||||
printf("handle_assoc_cb(reassoc=%d) - too short payload "
|
||||
|
@ -1489,11 +1716,6 @@ static void handle_assoc_cb(struct hostapd_data *hapd,
|
|||
return;
|
||||
}
|
||||
|
||||
if (reassoc)
|
||||
status = le_to_host16(mgmt->u.reassoc_resp.status_code);
|
||||
else
|
||||
status = le_to_host16(mgmt->u.assoc_resp.status_code);
|
||||
|
||||
sta = ap_get_sta(hapd, mgmt->da);
|
||||
if (!sta) {
|
||||
printf("handle_assoc_cb: STA " MACSTR " not found\n",
|
||||
|
@ -1501,6 +1723,19 @@ static void handle_assoc_cb(struct hostapd_data *hapd,
|
|||
return;
|
||||
}
|
||||
|
||||
if (!ok) {
|
||||
hostapd_logger(hapd, mgmt->da, HOSTAPD_MODULE_IEEE80211,
|
||||
HOSTAPD_LEVEL_DEBUG,
|
||||
"did not acknowledge association response");
|
||||
sta->flags &= ~WLAN_STA_ASSOC_REQ_OK;
|
||||
return;
|
||||
}
|
||||
|
||||
if (reassoc)
|
||||
status = le_to_host16(mgmt->u.reassoc_resp.status_code);
|
||||
else
|
||||
status = le_to_host16(mgmt->u.assoc_resp.status_code);
|
||||
|
||||
if (status != WLAN_STATUS_SUCCESS)
|
||||
goto fail;
|
||||
|
||||
|
@ -1550,7 +1785,7 @@ static void handle_assoc_cb(struct hostapd_data *hapd,
|
|||
sta->supported_rates, sta->supported_rates_len,
|
||||
sta->listen_interval,
|
||||
sta->flags & WLAN_STA_HT ? &ht_cap : NULL,
|
||||
sta->flags)) {
|
||||
sta->flags, sta->qosinfo)) {
|
||||
hostapd_logger(hapd, sta->addr, HOSTAPD_MODULE_IEEE80211,
|
||||
HOSTAPD_LEVEL_NOTICE,
|
||||
"Could not add STA to kernel driver");
|
||||
|
@ -1739,6 +1974,33 @@ void hostapd_tx_status(struct hostapd_data *hapd, const u8 *addr,
|
|||
}
|
||||
|
||||
|
||||
void hostapd_eapol_tx_status(struct hostapd_data *hapd, const u8 *dst,
|
||||
const u8 *data, size_t len, int ack)
|
||||
{
|
||||
struct sta_info *sta;
|
||||
struct hostapd_iface *iface = hapd->iface;
|
||||
|
||||
sta = ap_get_sta(hapd, dst);
|
||||
if (sta == NULL && iface->num_bss > 1) {
|
||||
size_t j;
|
||||
for (j = 0; j < iface->num_bss; j++) {
|
||||
hapd = iface->bss[j];
|
||||
sta = ap_get_sta(hapd, dst);
|
||||
if (sta)
|
||||
break;
|
||||
}
|
||||
}
|
||||
if (sta == NULL || !(sta->flags & WLAN_STA_ASSOC)) {
|
||||
wpa_printf(MSG_DEBUG, "Ignore TX status for Data frame to STA "
|
||||
MACSTR " that is not currently associated",
|
||||
MAC2STR(dst));
|
||||
return;
|
||||
}
|
||||
|
||||
ieee802_1x_eapol_tx_status(hapd, sta, data, len, ack);
|
||||
}
|
||||
|
||||
|
||||
void hostapd_client_poll_ok(struct hostapd_data *hapd, const u8 *addr)
|
||||
{
|
||||
struct sta_info *sta;
|
||||
|
@ -1772,6 +2034,9 @@ void ieee802_11_rx_from_unknown(struct hostapd_data *hapd, const u8 *src,
|
|||
|
||||
sta = ap_get_sta(hapd, src);
|
||||
if (sta && (sta->flags & WLAN_STA_ASSOC)) {
|
||||
if (!hapd->conf->wds_sta)
|
||||
return;
|
||||
|
||||
if (wds && !(sta->flags & WLAN_STA_WDS)) {
|
||||
wpa_printf(MSG_DEBUG, "Enable 4-address WDS mode for "
|
||||
"STA " MACSTR " (aid %u)",
|
||||
|
|
|
@ -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
|
||||
|
@ -51,6 +45,8 @@ 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);
|
||||
|
@ -60,8 +56,12 @@ void hostapd_get_ht_capab(struct hostapd_data *hapd,
|
|||
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,
|
||||
|
@ -76,5 +76,6 @@ 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,12 +15,14 @@
|
|||
|
||||
#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
|
||||
|
@ -40,6 +36,9 @@ struct hostapd_cached_radius_acl {
|
|||
u32 session_timeout;
|
||||
u32 acct_interim_interval;
|
||||
int vlan_id;
|
||||
struct hostapd_sta_wpa_psk_short *psk;
|
||||
char *identity;
|
||||
char *radius_cui;
|
||||
};
|
||||
|
||||
|
||||
|
@ -54,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;
|
||||
|
@ -61,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;
|
||||
struct os_time now;
|
||||
|
||||
os_get_time(&now);
|
||||
entry = hapd->acl_cache;
|
||||
|
||||
while (entry) {
|
||||
if (os_memcmp(entry->addr, addr, ETH_ALEN) == 0) {
|
||||
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;
|
||||
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;
|
||||
|
@ -138,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));
|
||||
|
@ -178,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))) {
|
||||
|
@ -211,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;
|
||||
|
@ -223,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))
|
||||
|
@ -247,7 +270,8 @@ int hostapd_allowed_address(struct hostapd_data *hapd, const u8 *addr,
|
|||
/* 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;
|
||||
|
@ -259,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;
|
||||
|
@ -324,7 +356,7 @@ static void hostapd_acl_expire_cache(struct hostapd_data *hapd, os_time_t now)
|
|||
hostapd_drv_set_radius_acl_expire(hapd, entry->addr);
|
||||
tmp = entry;
|
||||
entry = entry->next;
|
||||
os_free(tmp);
|
||||
hostapd_acl_cache_free_entry(tmp);
|
||||
continue;
|
||||
}
|
||||
|
||||
|
@ -381,6 +413,54 @@ static void hostapd_acl_expire(void *eloop_ctx, void *timeout_ctx)
|
|||
}
|
||||
|
||||
|
||||
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
|
||||
|
@ -439,6 +519,9 @@ hostapd_acl_recv_radius(struct radius_msg *msg, struct radius_msg *req,
|
|||
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;
|
||||
|
@ -457,6 +540,27 @@ 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;
|
||||
|
@ -527,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 */
|
||||
|
|
|
@ -1,15 +1,9 @@
|
|||
/*
|
||||
* hostapd / IEEE 802.11 Management
|
||||
* Copyright (c) 2002-2010, 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"
|
||||
|
@ -74,13 +68,13 @@ void ieee802_11_send_sa_query_req(struct hostapd_data *hapd,
|
|||
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)
|
||||
if (hostapd_drv_send_mlme(hapd, &mgmt, end - (u8 *) &mgmt, 0) < 0)
|
||||
perror("ieee802_11_send_sa_query_req: send");
|
||||
}
|
||||
|
||||
|
||||
void ieee802_11_send_sa_query_resp(struct hostapd_data *hapd,
|
||||
const u8 *sa, const u8 *trans_id)
|
||||
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;
|
||||
|
@ -112,7 +106,7 @@ void ieee802_11_send_sa_query_resp(struct hostapd_data *hapd,
|
|||
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)
|
||||
if (hostapd_drv_send_mlme(hapd, &resp, end - (u8 *) &resp, 0) < 0)
|
||||
perror("ieee80211_mgmt_sa_query_request: send");
|
||||
}
|
||||
|
||||
|
@ -179,6 +173,14 @@ u8 * hostapd_eid_ext_capab(struct hostapd_data *hapd, u8 *eid)
|
|||
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;
|
||||
|
||||
|
@ -186,9 +188,20 @@ u8 * hostapd_eid_ext_capab(struct hostapd_data *hapd, u8 *eid)
|
|||
*pos++ = len;
|
||||
*pos++ = 0x00;
|
||||
*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)
|
||||
|
@ -204,6 +217,18 @@ u8 * hostapd_eid_ext_capab(struct hostapd_data *hapd, u8 *eid)
|
|||
*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;
|
||||
}
|
||||
|
||||
|
@ -403,3 +428,31 @@ int hostapd_update_time_adv(struct hostapd_data *hapd)
|
|||
|
||||
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;
|
||||
}
|
||||
|
|
|
@ -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;
|
||||
}
|
|
@ -2,14 +2,8 @@
|
|||
* hostapd / IEEE 802.1X-2004 Authenticator
|
||||
* 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"
|
||||
|
@ -20,7 +14,6 @@
|
|||
#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"
|
||||
|
@ -73,8 +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 {
|
||||
hostapd_drv_hapd_send_eapol(hapd, sta->addr, buf, len,
|
||||
encrypt, sta->flags);
|
||||
hostapd_drv_hapd_send_eapol(
|
||||
hapd, sta->addr, buf, len,
|
||||
encrypt, hostapd_sta_flags_to_drv(sta->flags));
|
||||
}
|
||||
|
||||
os_free(buf);
|
||||
|
@ -106,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);
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
|
@ -133,7 +129,7 @@ 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 (random_get_bytes(key->key_iv, sizeof(key->key_iv))) {
|
||||
|
@ -359,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:
|
||||
|
@ -416,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)
|
||||
|
@ -449,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;
|
||||
|
@ -548,6 +613,25 @@ static void ieee802_1x_encapsulate_radius(struct hostapd_data *hapd,
|
|||
}
|
||||
}
|
||||
|
||||
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;
|
||||
|
||||
|
@ -653,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->p2p_ie, sta);
|
||||
sta->wps_ie, sta->p2p_ie, sta,
|
||||
sta->identity, sta->radius_cui);
|
||||
}
|
||||
|
||||
|
||||
|
@ -985,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);
|
||||
|
@ -996,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;
|
||||
|
@ -1012,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
|
||||
|
@ -1024,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)
|
||||
|
@ -1071,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;
|
||||
}
|
||||
|
||||
|
||||
|
@ -1136,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;
|
||||
|
||||
|
@ -1206,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;
|
||||
|
@ -1365,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 ?
|
||||
|
@ -1430,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);
|
||||
|
@ -1582,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;
|
||||
}
|
||||
|
@ -1783,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;
|
||||
|
@ -1803,16 +1912,30 @@ 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 &&
|
||||
pos + sizeof(struct wpa_eapol_key) <= buf + len) {
|
||||
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 ||
|
||||
|
@ -1826,8 +1949,7 @@ int ieee802_1x_tx_status(struct hostapd_data *hapd, struct sta_info *sta,
|
|||
* 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 "
|
||||
|
@ -1871,6 +1993,14 @@ 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;
|
||||
|
@ -2099,8 +2229,8 @@ static void ieee802_1x_finished(struct hostapd_data *hapd,
|
|||
* EAP-FAST with anonymous provisioning, may require another
|
||||
* EAPOL authentication to be started to complete connection.
|
||||
*/
|
||||
wpa_printf(MSG_DEBUG, "IEEE 802.1X: 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.
|
||||
|
|
|
@ -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 */
|
||||
|
|
|
@ -2,14 +2,8 @@
|
|||
* hostapd / P2P integration
|
||||
* Copyright (c) 2009-2010, Atheros Communications
|
||||
*
|
||||
* 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 / P2P integration
|
||||
* Copyright (c) 2009-2010, Atheros Communications
|
||||
*
|
||||
* 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 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"
|
||||
|
|
|
@ -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
|
||||
|
|
|
@ -2,14 +2,8 @@
|
|||
* hostapd / Station table
|
||||
* 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"
|
||||
|
@ -26,6 +20,7 @@
|
|||
#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"
|
||||
|
@ -34,6 +29,7 @@
|
|||
#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,
|
||||
|
@ -200,6 +196,8 @@ 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);
|
||||
|
@ -224,10 +222,23 @@ void ap_free_sta(struct hostapd_data *hapd, struct sta_info *sta)
|
|||
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);
|
||||
}
|
||||
|
@ -267,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 "
|
||||
|
@ -279,6 +293,12 @@ void ap_handle_timer(void *eloop_ctx, void *timeout_ctx)
|
|||
(sta->timeout_next == STA_NULLFUNC ||
|
||||
sta->timeout_next == STA_DISASSOC)) {
|
||||
int inactive_sec;
|
||||
/*
|
||||
* 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_msg(hapd->msg_ctx, MSG_DEBUG,
|
||||
|
@ -290,7 +310,7 @@ void ap_handle_timer(void *eloop_ctx, void *timeout_ctx)
|
|||
* Anyway, try again after the next inactivity timeout,
|
||||
* but do not disconnect the station now.
|
||||
*/
|
||||
next_time = hapd->conf->ap_max_inactivity;
|
||||
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 */
|
||||
|
@ -298,7 +318,7 @@ void ap_handle_timer(void *eloop_ctx, void *timeout_ctx)
|
|||
"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,
|
||||
|
@ -306,12 +326,16 @@ void ap_handle_timer(void *eloop_ctx, void *timeout_ctx)
|
|||
"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)) {
|
||||
!(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
|
||||
|
@ -321,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;
|
||||
|
@ -335,9 +362,10 @@ void ap_handle_timer(void *eloop_ctx, void *timeout_ctx)
|
|||
} 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) {
|
||||
hostapd_drv_sta_deauth(
|
||||
|
@ -353,6 +381,9 @@ 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;
|
||||
|
@ -369,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(
|
||||
|
@ -378,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;
|
||||
|
@ -397,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);
|
||||
|
@ -453,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);
|
||||
|
@ -528,6 +573,11 @@ void ap_sta_disassociate(struct hostapd_data *hapd, struct sta_info *sta,
|
|||
sta->flags &= ~WLAN_STA_ASSOC;
|
||||
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);
|
||||
|
@ -561,6 +611,11 @@ void ap_sta_deauthenticate(struct hostapd_data *hapd, struct sta_info *sta,
|
|||
sta->flags &= ~(WLAN_STA_AUTH | WLAN_STA_ASSOC);
|
||||
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);
|
||||
|
@ -576,6 +631,23 @@ void ap_sta_deauthenticate(struct hostapd_data *hapd, struct sta_info *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)
|
||||
{
|
||||
|
@ -728,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) {
|
||||
|
@ -751,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 */
|
||||
}
|
||||
|
||||
|
||||
|
@ -778,11 +849,20 @@ 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
|
||||
dev_addr = p2p_group_get_dev_addr(hapd->p2p_group, sta->addr);
|
||||
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) {
|
||||
|
@ -848,6 +928,11 @@ void ap_sta_disconnect(struct hostapd_data *hapd, struct sta_info *sta,
|
|||
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(AP_MAX_INACTIVITY_AFTER_DEAUTH, 0,
|
||||
ap_handle_timer, hapd, sta);
|
||||
|
|
|
@ -2,14 +2,8 @@
|
|||
* hostapd / Station table
|
||||
* 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
|
||||
|
@ -33,6 +27,8 @@
|
|||
#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)
|
||||
|
@ -52,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;
|
||||
|
@ -98,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;
|
||||
|
@ -111,8 +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 */
|
||||
};
|
||||
|
||||
|
||||
|
@ -141,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,
|
||||
|
@ -153,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);
|
||||
|
|
|
@ -1,15 +1,9 @@
|
|||
/*
|
||||
* hostapd / TKIP countermeasures
|
||||
* Copyright (c) 2002-2011, 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,6 +11,7 @@
|
|||
#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"
|
||||
|
@ -50,12 +45,17 @@ static void ieee80211_tkip_countermeasures_start(struct hostapd_data *hapd)
|
|||
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) {
|
||||
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_sta_set_authorized(hapd, sta, 0);
|
||||
sta->flags &= ~(WLAN_STA_AUTH | WLAN_STA_ASSOC);
|
||||
hostapd_drv_sta_remove(hapd, sta->addr);
|
||||
ap_free_sta(hapd, sta);
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -66,9 +66,10 @@ void ieee80211_tkip_countermeasures_deinit(struct hostapd_data *hapd)
|
|||
}
|
||||
|
||||
|
||||
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)
|
||||
{
|
||||
struct os_time now;
|
||||
int ret = 0;
|
||||
|
||||
if (addr && local) {
|
||||
struct sta_info *sta = ap_get_sta(hapd, addr);
|
||||
|
@ -84,7 +85,7 @@ 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;
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -93,8 +94,12 @@ void michael_mic_failure(struct hostapd_data *hapd, const u8 *addr, int local)
|
|||
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.sec;
|
||||
|
||||
return ret;
|
||||
}
|
||||
|
|
|
@ -1,21 +1,15 @@
|
|||
/*
|
||||
* hostapd / TKIP countermeasures
|
||||
* Copyright (c) 2002-2011, 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"
|
||||
|
@ -23,13 +17,14 @@
|
|||
int hostapd_register_probereq_cb(struct hostapd_data *hapd,
|
||||
int (*cb)(void *ctx, const u8 *sa,
|
||||
const u8 *da, const u8 *bssid,
|
||||
const u8 *ie, size_t ie_len),
|
||||
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;
|
||||
|
||||
|
@ -83,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);
|
||||
}
|
||||
|
|
|
@ -21,6 +21,7 @@
|
|||
#include "ap_config.h"
|
||||
#include "ap_drv_ops.h"
|
||||
#include "vlan_init.h"
|
||||
#include "vlan_util.h"
|
||||
|
||||
|
||||
#ifdef CONFIG_FULL_DYNAMIC_VLAN
|
||||
|
@ -335,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;
|
||||
|
@ -378,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;
|
||||
|
@ -474,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)
|
||||
{
|
||||
|
@ -481,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);
|
||||
|
||||
|
@ -496,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;
|
||||
|
||||
|
@ -527,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);
|
||||
|
||||
|
@ -541,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);
|
||||
|
@ -682,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) {
|
||||
|
|
|
@ -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;
|
||||
}
|
|
@ -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 */
|
|
@ -72,7 +72,8 @@ 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;
|
||||
|
@ -155,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 (hostapd_drv_send_mlme(hapd, m, len) < 0)
|
||||
if (hostapd_drv_send_mlme(hapd, m, len, 0) < 0)
|
||||
perror("wmm_send_action: send");
|
||||
}
|
||||
|
||||
|
|
|
@ -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;
|
||||
}
|
|
@ -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 */
|
|
@ -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
|
||||
|
@ -164,6 +158,8 @@ struct wpa_auth_config {
|
|||
int pmk_r1_push;
|
||||
int ft_over_ds;
|
||||
#endif /* CONFIG_IEEE80211R */
|
||||
int disable_gtk;
|
||||
int ap_mlme;
|
||||
};
|
||||
|
||||
typedef enum {
|
||||
|
@ -181,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);
|
||||
|
@ -202,6 +198,8 @@ 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 */
|
||||
};
|
||||
|
||||
|
@ -284,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"
|
||||
|
@ -24,7 +18,6 @@
|
|||
#include "wmm.h"
|
||||
#include "wpa_auth.h"
|
||||
#include "wpa_auth_i.h"
|
||||
#include "wpa_auth_ie.h"
|
||||
|
||||
|
||||
#ifdef CONFIG_IEEE80211R
|
||||
|
@ -59,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;
|
||||
|
@ -478,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;
|
||||
|
@ -511,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;
|
||||
|
||||
|
@ -548,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;
|
||||
|
@ -576,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);
|
||||
}
|
||||
|
@ -685,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,
|
||||
|
@ -724,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;
|
||||
|
@ -852,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);
|
||||
|
@ -1068,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;
|
||||
}
|
||||
|
||||
|
|
|
@ -2,14 +2,8 @@
|
|||
* hostapd / WPA authenticator glue code
|
||||
* 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,6 +23,7 @@
|
|||
#include "ap_drv_ops.h"
|
||||
#include "ap_config.h"
|
||||
#include "wpa_auth.h"
|
||||
#include "wpa_auth_glue.h"
|
||||
|
||||
|
||||
static void hostapd_wpa_auth_conf(struct hostapd_bss_config *conf,
|
||||
|
@ -75,6 +70,9 @@ static void hostapd_wpa_auth_conf(struct hostapd_bss_config *conf,
|
|||
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 */
|
||||
}
|
||||
|
||||
|
||||
|
@ -114,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);
|
||||
}
|
||||
|
||||
|
||||
|
@ -185,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;
|
||||
}
|
||||
|
||||
|
||||
|
@ -296,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);
|
||||
}
|
||||
|
||||
|
||||
|
@ -353,16 +369,17 @@ static int hostapd_wpa_auth_send_ether(void *ctx, const u8 *dst, u16 proto,
|
|||
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;
|
||||
}
|
||||
|
@ -415,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 = hostapd_drv_send_mlme(hapd, (u8 *) m, mlen);
|
||||
res = hostapd_drv_send_mlme(hapd, (u8 *) m, mlen, 0);
|
||||
os_free(m);
|
||||
return res;
|
||||
}
|
||||
|
@ -427,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;
|
||||
|
@ -460,6 +480,14 @@ static void hostapd_rrb_receive(void *ctx, const u8 *src_addr, const u8 *buf,
|
|||
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 */
|
||||
|
||||
|
||||
|
@ -473,6 +501,8 @@ int hostapd_setup_wpa(struct hostapd_data *hapd)
|
|||
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;
|
||||
|
@ -491,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) {
|
||||
|
|
|
@ -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;
|
||||
|
@ -87,10 +82,12 @@ struct wpa_state_machine {
|
|||
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;
|
||||
|
|
|
@ -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"
|
||||
|
@ -35,6 +29,7 @@ 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;
|
||||
|
@ -42,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;
|
||||
|
@ -118,28 +92,23 @@ 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;
|
||||
|
@ -154,21 +123,9 @@ int wpa_write_rsn_ie(struct wpa_auth_config *conf, u8 *buf, size_t len,
|
|||
}
|
||||
#endif /* CONFIG_RSN_TESTING */
|
||||
|
||||
if (conf->rsn_pairwise & WPA_CIPHER_CCMP) {
|
||||
RSN_SELECTOR_PUT(pos, RSN_CIPHER_SUITE_CCMP);
|
||||
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);
|
||||
pos += RSN_SELECTOR_LEN;
|
||||
num_suites++;
|
||||
}
|
||||
res = rsn_cipher_put_suites(pos, conf->rsn_pairwise);
|
||||
num_suites += res;
|
||||
pos += res * RSN_SELECTOR_LEN;
|
||||
|
||||
#ifdef CONFIG_RSN_TESTING
|
||||
if (rsn_testing) {
|
||||
|
@ -231,6 +188,18 @@ 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) {
|
||||
|
@ -341,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)
|
||||
|
@ -451,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);
|
||||
|
@ -492,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) {
|
||||
|
@ -551,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
|
||||
|
@ -614,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
|
||||
|
|
|
@ -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.
|
||||
*/
|
||||
|
||||
#include "utils/includes.h"
|
||||
|
@ -17,7 +11,6 @@
|
|||
#include "utils/common.h"
|
||||
#include "utils/eloop.h"
|
||||
#include "utils/uuid.h"
|
||||
#include "crypto/dh_groups.h"
|
||||
#include "common/wpa_ctrl.h"
|
||||
#include "common/ieee802_11_defs.h"
|
||||
#include "common/ieee802_11_common.h"
|
||||
|
@ -26,6 +19,7 @@
|
|||
#include "wps/wps.h"
|
||||
#include "wps/wps_defs.h"
|
||||
#include "wps/wps_dev_attr.h"
|
||||
#include "wps/wps_attr_parse.h"
|
||||
#include "hostapd.h"
|
||||
#include "ap_config.h"
|
||||
#include "ap_drv_ops.h"
|
||||
|
@ -43,7 +37,8 @@ static void hostapd_wps_upnp_deinit(struct hostapd_data *hapd);
|
|||
|
||||
static int hostapd_wps_probe_req_rx(void *ctx, const u8 *addr, const u8 *da,
|
||||
const u8 *bssid,
|
||||
const u8 *ie, size_t ie_len);
|
||||
const u8 *ie, size_t ie_len,
|
||||
int ssi_signal);
|
||||
static void hostapd_wps_ap_pin_timeout(void *eloop_data, void *user_ctx);
|
||||
|
||||
|
||||
|
@ -79,10 +74,11 @@ static int hostapd_wps_for_each(struct hostapd_data *hapd,
|
|||
struct wps_for_each_data data;
|
||||
data.func = func;
|
||||
data.ctx = ctx;
|
||||
if (iface->for_each_interface == NULL)
|
||||
if (iface->interfaces == NULL ||
|
||||
iface->interfaces->for_each_interface == NULL)
|
||||
return wps_for_each(iface, &data);
|
||||
return iface->for_each_interface(iface->interfaces, wps_for_each,
|
||||
&data);
|
||||
return iface->interfaces->for_each_interface(iface->interfaces,
|
||||
wps_for_each, &data);
|
||||
}
|
||||
|
||||
|
||||
|
@ -189,19 +185,23 @@ static void hostapd_wps_pin_needed_cb(void *ctx, const u8 *uuid_e,
|
|||
struct wps_stop_reg_data {
|
||||
struct hostapd_data *current_hapd;
|
||||
const u8 *uuid_e;
|
||||
const u8 *dev_pw;
|
||||
size_t dev_pw_len;
|
||||
};
|
||||
|
||||
static int wps_stop_registrar(struct hostapd_data *hapd, void *ctx)
|
||||
{
|
||||
struct wps_stop_reg_data *data = ctx;
|
||||
if (hapd != data->current_hapd && hapd->wps != NULL)
|
||||
wps_registrar_complete(hapd->wps->registrar, data->uuid_e);
|
||||
wps_registrar_complete(hapd->wps->registrar, data->uuid_e,
|
||||
data->dev_pw, data->dev_pw_len);
|
||||
return 0;
|
||||
}
|
||||
|
||||
|
||||
static void hostapd_wps_reg_success_cb(void *ctx, const u8 *mac_addr,
|
||||
const u8 *uuid_e)
|
||||
const u8 *uuid_e, const u8 *dev_pw,
|
||||
size_t dev_pw_len)
|
||||
{
|
||||
struct hostapd_data *hapd = ctx;
|
||||
char uuid[40];
|
||||
|
@ -215,6 +215,8 @@ static void hostapd_wps_reg_success_cb(void *ctx, const u8 *mac_addr,
|
|||
mac_addr, uuid_e);
|
||||
data.current_hapd = hapd;
|
||||
data.uuid_e = uuid_e;
|
||||
data.dev_pw = dev_pw;
|
||||
data.dev_pw_len = dev_pw_len;
|
||||
hostapd_wps_for_each(hapd, wps_stop_registrar, &data);
|
||||
}
|
||||
|
||||
|
@ -253,7 +255,8 @@ static void wps_reload_config(void *eloop_data, void *user_ctx)
|
|||
struct hostapd_iface *iface = eloop_data;
|
||||
|
||||
wpa_printf(MSG_DEBUG, "WPS: Reload configuration data");
|
||||
if (iface->reload_config(iface) < 0) {
|
||||
if (iface->interfaces == NULL ||
|
||||
iface->interfaces->reload_config(iface) < 0) {
|
||||
wpa_printf(MSG_WARNING, "WPS: Failed to reload the updated "
|
||||
"configuration");
|
||||
}
|
||||
|
@ -340,6 +343,8 @@ static int hapd_wps_cred_cb(struct hostapd_data *hapd, void *ctx)
|
|||
}
|
||||
hapd->wps->wps_state = WPS_STATE_CONFIGURED;
|
||||
|
||||
if (hapd->iface->config_fname == NULL)
|
||||
return 0;
|
||||
len = os_strlen(hapd->iface->config_fname) + 5;
|
||||
tmp_fname = os_malloc(len);
|
||||
if (tmp_fname == NULL)
|
||||
|
@ -367,10 +372,17 @@ static int hapd_wps_cred_cb(struct hostapd_data *hapd, void *ctx)
|
|||
|
||||
fprintf(nconf, "wps_state=2\n");
|
||||
|
||||
fprintf(nconf, "ssid=");
|
||||
for (i = 0; i < cred->ssid_len; i++)
|
||||
fputc(cred->ssid[i], nconf);
|
||||
fprintf(nconf, "\n");
|
||||
if (is_hex(cred->ssid, cred->ssid_len)) {
|
||||
fprintf(nconf, "ssid2=");
|
||||
for (i = 0; i < cred->ssid_len; i++)
|
||||
fprintf(nconf, "%02x", cred->ssid[i]);
|
||||
fprintf(nconf, "\n");
|
||||
} else {
|
||||
fprintf(nconf, "ssid=");
|
||||
for (i = 0; i < cred->ssid_len; i++)
|
||||
fputc(cred->ssid[i], nconf);
|
||||
fprintf(nconf, "\n");
|
||||
}
|
||||
|
||||
if ((cred->auth_type & (WPS_AUTH_WPA2 | WPS_AUTH_WPA2PSK)) &&
|
||||
(cred->auth_type & (WPS_AUTH_WPA | WPS_AUTH_WPAPSK)))
|
||||
|
@ -460,6 +472,7 @@ static int hapd_wps_cred_cb(struct hostapd_data *hapd, void *ctx)
|
|||
multi_bss = 1;
|
||||
if (!multi_bss &&
|
||||
(str_starts(buf, "ssid=") ||
|
||||
str_starts(buf, "ssid2=") ||
|
||||
str_starts(buf, "auth_algs=") ||
|
||||
str_starts(buf, "wep_default_key=") ||
|
||||
str_starts(buf, "wep_key") ||
|
||||
|
@ -706,10 +719,12 @@ static int get_uuid_cb(struct hostapd_iface *iface, void *ctx)
|
|||
static const u8 * get_own_uuid(struct hostapd_iface *iface)
|
||||
{
|
||||
const u8 *uuid;
|
||||
if (iface->for_each_interface == NULL)
|
||||
if (iface->interfaces == NULL ||
|
||||
iface->interfaces->for_each_interface == NULL)
|
||||
return NULL;
|
||||
uuid = NULL;
|
||||
iface->for_each_interface(iface->interfaces, get_uuid_cb, &uuid);
|
||||
iface->interfaces->for_each_interface(iface->interfaces, get_uuid_cb,
|
||||
&uuid);
|
||||
return uuid;
|
||||
}
|
||||
|
||||
|
@ -725,10 +740,11 @@ static int count_interface_cb(struct hostapd_iface *iface, void *ctx)
|
|||
static int interface_count(struct hostapd_iface *iface)
|
||||
{
|
||||
int count = 0;
|
||||
if (iface->for_each_interface == NULL)
|
||||
if (iface->interfaces == NULL ||
|
||||
iface->interfaces->for_each_interface == NULL)
|
||||
return 0;
|
||||
iface->for_each_interface(iface->interfaces, count_interface_cb,
|
||||
&count);
|
||||
iface->interfaces->for_each_interface(iface->interfaces,
|
||||
count_interface_cb, &count);
|
||||
return count;
|
||||
}
|
||||
|
||||
|
@ -838,8 +854,14 @@ int hostapd_init_wps(struct hostapd_data *hapd,
|
|||
}
|
||||
|
||||
wps->dev.os_version = WPA_GET_BE32(hapd->conf->os_version);
|
||||
wps->dev.rf_bands = hapd->iconf->hw_mode == HOSTAPD_MODE_IEEE80211A ?
|
||||
WPS_RF_50GHZ : WPS_RF_24GHZ; /* FIX: dualband AP */
|
||||
|
||||
if (conf->wps_rf_bands) {
|
||||
wps->dev.rf_bands = conf->wps_rf_bands;
|
||||
} else {
|
||||
wps->dev.rf_bands =
|
||||
hapd->iconf->hw_mode == HOSTAPD_MODE_IEEE80211A ?
|
||||
WPS_RF_50GHZ : WPS_RF_24GHZ; /* FIX: dualband AP */
|
||||
}
|
||||
|
||||
if (conf->wpa & WPA_PROTO_RSN) {
|
||||
if (conf->wpa_key_mgmt & WPA_KEY_MGMT_PSK)
|
||||
|
@ -935,6 +957,9 @@ int hostapd_init_wps(struct hostapd_data *hapd,
|
|||
if (conf->ssid.security_policy == SECURITY_STATIC_WEP)
|
||||
cfg.static_wep_only = 1;
|
||||
cfg.dualband = interface_count(hapd->iface) > 1;
|
||||
if ((wps->dev.rf_bands & (WPS_RF_50GHZ | WPS_RF_24GHZ)) ==
|
||||
(WPS_RF_50GHZ | WPS_RF_24GHZ))
|
||||
cfg.dualband = 1;
|
||||
if (cfg.dualband)
|
||||
wpa_printf(MSG_DEBUG, "WPS: Dualband AP");
|
||||
|
||||
|
@ -984,6 +1009,20 @@ int hostapd_init_wps_complete(struct hostapd_data *hapd)
|
|||
}
|
||||
|
||||
|
||||
static void hostapd_wps_nfc_clear(struct wps_context *wps)
|
||||
{
|
||||
#ifdef CONFIG_WPS_NFC
|
||||
wps->ap_nfc_dev_pw_id = 0;
|
||||
wpabuf_free(wps->ap_nfc_dh_pubkey);
|
||||
wps->ap_nfc_dh_pubkey = NULL;
|
||||
wpabuf_free(wps->ap_nfc_dh_privkey);
|
||||
wps->ap_nfc_dh_privkey = NULL;
|
||||
wpabuf_free(wps->ap_nfc_dev_pw);
|
||||
wps->ap_nfc_dev_pw = NULL;
|
||||
#endif /* CONFIG_WPS_NFC */
|
||||
}
|
||||
|
||||
|
||||
void hostapd_deinit_wps(struct hostapd_data *hapd)
|
||||
{
|
||||
eloop_cancel_timeout(hostapd_wps_reenable_ap_pin, hapd, NULL);
|
||||
|
@ -998,9 +1037,8 @@ void hostapd_deinit_wps(struct hostapd_data *hapd)
|
|||
wps_device_data_free(&hapd->wps->dev);
|
||||
wpabuf_free(hapd->wps->dh_pubkey);
|
||||
wpabuf_free(hapd->wps->dh_privkey);
|
||||
wpabuf_free(hapd->wps->oob_conf.pubkey_hash);
|
||||
wpabuf_free(hapd->wps->oob_conf.dev_password);
|
||||
wps_free_pending_msgs(hapd->wps->upnp_msgs);
|
||||
hostapd_wps_nfc_clear(hapd->wps);
|
||||
os_free(hapd->wps);
|
||||
hapd->wps = NULL;
|
||||
hostapd_wps_clear_ies(hapd);
|
||||
|
@ -1098,63 +1136,28 @@ int hostapd_wps_button_pushed(struct hostapd_data *hapd,
|
|||
}
|
||||
|
||||
|
||||
#ifdef CONFIG_WPS_OOB
|
||||
int hostapd_wps_start_oob(struct hostapd_data *hapd, char *device_type,
|
||||
char *path, char *method, char *name)
|
||||
static int wps_cancel(struct hostapd_data *hapd, void *ctx)
|
||||
{
|
||||
struct wps_context *wps = hapd->wps;
|
||||
struct oob_device_data *oob_dev;
|
||||
if (hapd->wps == NULL)
|
||||
return 0;
|
||||
|
||||
oob_dev = wps_get_oob_device(device_type);
|
||||
if (oob_dev == NULL)
|
||||
return -1;
|
||||
oob_dev->device_path = path;
|
||||
oob_dev->device_name = name;
|
||||
wps->oob_conf.oob_method = wps_get_oob_method(method);
|
||||
|
||||
if (wps->oob_conf.oob_method == OOB_METHOD_DEV_PWD_R) {
|
||||
/*
|
||||
* Use pre-configured DH keys in order to be able to write the
|
||||
* key hash into the OOB file.
|
||||
*/
|
||||
wpabuf_free(wps->dh_pubkey);
|
||||
wpabuf_free(wps->dh_privkey);
|
||||
wps->dh_privkey = NULL;
|
||||
wps->dh_pubkey = dh_init(dh_groups_get(WPS_DH_GROUP),
|
||||
&wps->dh_privkey);
|
||||
wps->dh_pubkey = wpabuf_zeropad(wps->dh_pubkey, 192);
|
||||
if (wps->dh_pubkey == NULL) {
|
||||
wpa_printf(MSG_ERROR, "WPS: Failed to initialize "
|
||||
"Diffie-Hellman handshake");
|
||||
return -1;
|
||||
}
|
||||
}
|
||||
|
||||
if (wps_process_oob(wps, oob_dev, 1) < 0)
|
||||
goto error;
|
||||
|
||||
if ((wps->oob_conf.oob_method == OOB_METHOD_DEV_PWD_E ||
|
||||
wps->oob_conf.oob_method == OOB_METHOD_DEV_PWD_R) &&
|
||||
hostapd_wps_add_pin(hapd, NULL, "any",
|
||||
wpabuf_head(wps->oob_conf.dev_password), 0) <
|
||||
0)
|
||||
goto error;
|
||||
wps_registrar_wps_cancel(hapd->wps->registrar);
|
||||
ap_for_each_sta(hapd, ap_sta_wps_cancel, NULL);
|
||||
|
||||
return 0;
|
||||
|
||||
error:
|
||||
wpabuf_free(wps->dh_pubkey);
|
||||
wps->dh_pubkey = NULL;
|
||||
wpabuf_free(wps->dh_privkey);
|
||||
wps->dh_privkey = NULL;
|
||||
return -1;
|
||||
}
|
||||
#endif /* CONFIG_WPS_OOB */
|
||||
|
||||
|
||||
int hostapd_wps_cancel(struct hostapd_data *hapd)
|
||||
{
|
||||
return hostapd_wps_for_each(hapd, wps_cancel, NULL);
|
||||
}
|
||||
|
||||
|
||||
static int hostapd_wps_probe_req_rx(void *ctx, const u8 *addr, const u8 *da,
|
||||
const u8 *bssid,
|
||||
const u8 *ie, size_t ie_len)
|
||||
const u8 *ie, size_t ie_len,
|
||||
int ssi_signal)
|
||||
{
|
||||
struct hostapd_data *hapd = ctx;
|
||||
struct wpabuf *wps_ie;
|
||||
|
@ -1471,3 +1474,156 @@ int hostapd_wps_config_ap(struct hostapd_data *hapd, const char *ssid,
|
|||
|
||||
return wps_registrar_config_ap(hapd->wps->registrar, &cred);
|
||||
}
|
||||
|
||||
|
||||
#ifdef CONFIG_WPS_NFC
|
||||
|
||||
struct wps_nfc_password_token_data {
|
||||
const u8 *oob_dev_pw;
|
||||
size_t oob_dev_pw_len;
|
||||
int added;
|
||||
};
|
||||
|
||||
|
||||
static int wps_add_nfc_password_token(struct hostapd_data *hapd, void *ctx)
|
||||
{
|
||||
struct wps_nfc_password_token_data *data = ctx;
|
||||
int ret;
|
||||
|
||||
if (hapd->wps == NULL)
|
||||
return 0;
|
||||
ret = wps_registrar_add_nfc_password_token(hapd->wps->registrar,
|
||||
data->oob_dev_pw,
|
||||
data->oob_dev_pw_len);
|
||||
if (ret == 0)
|
||||
data->added++;
|
||||
return ret;
|
||||
}
|
||||
|
||||
|
||||
static int hostapd_wps_add_nfc_password_token(struct hostapd_data *hapd,
|
||||
struct wps_parse_attr *attr)
|
||||
{
|
||||
struct wps_nfc_password_token_data data;
|
||||
|
||||
data.oob_dev_pw = attr->oob_dev_password;
|
||||
data.oob_dev_pw_len = attr->oob_dev_password_len;
|
||||
data.added = 0;
|
||||
if (hostapd_wps_for_each(hapd, wps_add_nfc_password_token, &data) < 0)
|
||||
return -1;
|
||||
return data.added ? 0 : -1;
|
||||
}
|
||||
|
||||
|
||||
static int hostapd_wps_nfc_tag_process(struct hostapd_data *hapd,
|
||||
const struct wpabuf *wps)
|
||||
{
|
||||
struct wps_parse_attr attr;
|
||||
|
||||
wpa_hexdump_buf(MSG_DEBUG, "WPS: Received NFC tag payload", wps);
|
||||
|
||||
if (wps_parse_msg(wps, &attr)) {
|
||||
wpa_printf(MSG_DEBUG, "WPS: Ignore invalid data from NFC tag");
|
||||
return -1;
|
||||
}
|
||||
|
||||
if (attr.oob_dev_password)
|
||||
return hostapd_wps_add_nfc_password_token(hapd, &attr);
|
||||
|
||||
wpa_printf(MSG_DEBUG, "WPS: Ignore unrecognized NFC tag");
|
||||
return -1;
|
||||
}
|
||||
|
||||
|
||||
int hostapd_wps_nfc_tag_read(struct hostapd_data *hapd,
|
||||
const struct wpabuf *data)
|
||||
{
|
||||
const struct wpabuf *wps = data;
|
||||
struct wpabuf *tmp = NULL;
|
||||
int ret;
|
||||
|
||||
if (wpabuf_len(data) < 4)
|
||||
return -1;
|
||||
|
||||
if (*wpabuf_head_u8(data) != 0x10) {
|
||||
/* Assume this contains full NDEF record */
|
||||
tmp = ndef_parse_wifi(data);
|
||||
if (tmp == NULL) {
|
||||
wpa_printf(MSG_DEBUG, "WPS: Could not parse NDEF");
|
||||
return -1;
|
||||
}
|
||||
wps = tmp;
|
||||
}
|
||||
|
||||
ret = hostapd_wps_nfc_tag_process(hapd, wps);
|
||||
wpabuf_free(tmp);
|
||||
return ret;
|
||||
}
|
||||
|
||||
|
||||
struct wpabuf * hostapd_wps_nfc_config_token(struct hostapd_data *hapd,
|
||||
int ndef)
|
||||
{
|
||||
struct wpabuf *ret;
|
||||
|
||||
if (hapd->wps == NULL)
|
||||
return NULL;
|
||||
|
||||
ret = wps_get_oob_cred(hapd->wps);
|
||||
if (ndef && ret) {
|
||||
struct wpabuf *tmp;
|
||||
tmp = ndef_build_wifi(ret);
|
||||
wpabuf_free(ret);
|
||||
if (tmp == NULL)
|
||||
return NULL;
|
||||
ret = tmp;
|
||||
}
|
||||
|
||||
return ret;
|
||||
}
|
||||
|
||||
|
||||
struct wpabuf * hostapd_wps_nfc_token_gen(struct hostapd_data *hapd, int ndef)
|
||||
{
|
||||
return wps_nfc_token_gen(ndef, &hapd->conf->wps_nfc_dev_pw_id,
|
||||
&hapd->conf->wps_nfc_dh_pubkey,
|
||||
&hapd->conf->wps_nfc_dh_privkey,
|
||||
&hapd->conf->wps_nfc_dev_pw);
|
||||
}
|
||||
|
||||
|
||||
int hostapd_wps_nfc_token_enable(struct hostapd_data *hapd)
|
||||
{
|
||||
struct wps_context *wps = hapd->wps;
|
||||
|
||||
if (wps == NULL)
|
||||
return -1;
|
||||
|
||||
if (!hapd->conf->wps_nfc_dh_pubkey ||
|
||||
!hapd->conf->wps_nfc_dh_privkey ||
|
||||
!hapd->conf->wps_nfc_dev_pw ||
|
||||
!hapd->conf->wps_nfc_dev_pw_id)
|
||||
return -1;
|
||||
|
||||
hostapd_wps_nfc_clear(wps);
|
||||
wps->ap_nfc_dev_pw_id = hapd->conf->wps_nfc_dev_pw_id;
|
||||
wps->ap_nfc_dh_pubkey = wpabuf_dup(hapd->conf->wps_nfc_dh_pubkey);
|
||||
wps->ap_nfc_dh_privkey = wpabuf_dup(hapd->conf->wps_nfc_dh_privkey);
|
||||
wps->ap_nfc_dev_pw = wpabuf_dup(hapd->conf->wps_nfc_dev_pw);
|
||||
|
||||
if (!wps->ap_nfc_dh_pubkey || !wps->ap_nfc_dh_privkey ||
|
||||
!wps->ap_nfc_dev_pw) {
|
||||
hostapd_wps_nfc_clear(wps);
|
||||
return -1;
|
||||
}
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
|
||||
void hostapd_wps_nfc_token_disable(struct hostapd_data *hapd)
|
||||
{
|
||||
hostapd_wps_nfc_clear(hapd->wps);
|
||||
}
|
||||
|
||||
#endif /* CONFIG_WPS_NFC */
|
||||
|
|
|
@ -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
|
||||
|
@ -26,8 +20,7 @@ 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_start_oob(struct hostapd_data *hapd, char *device_type,
|
||||
char *path, char *method, char *name);
|
||||
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);
|
||||
|
@ -38,6 +31,13 @@ int hostapd_wps_ap_pin_set(struct hostapd_data *hapd, const char *pin,
|
|||
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 */
|
||||
|
||||
|
@ -73,6 +73,11 @@ static inline int hostapd_wps_button_pushed(struct hostapd_data *hapd,
|
|||
return 0;
|
||||
}
|
||||
|
||||
static inline int hostapd_wps_cancel(struct hostapd_data *hapd)
|
||||
{
|
||||
return 0;
|
||||
}
|
||||
|
||||
#endif /* CONFIG_WPS */
|
||||
|
||||
#endif /* WPS_HOSTAPD_H */
|
||||
|
|
|
@ -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,11 +39,17 @@ 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 |
|
||||
WPA_KEY_MGMT_FT_IEEE8021X |
|
||||
WPA_KEY_MGMT_CCKM |
|
||||
WPA_KEY_MGMT_IEEE8021X_SHA256));
|
||||
}
|
||||
|
||||
|
@ -55,13 +57,21 @@ static inline int wpa_key_mgmt_wpa_psk(int akm)
|
|||
{
|
||||
return !!(akm & (WPA_KEY_MGMT_PSK |
|
||||
WPA_KEY_MGMT_FT_PSK |
|
||||
WPA_KEY_MGMT_PSK_SHA256));
|
||||
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 |
|
||||
WPA_KEY_MGMT_FT_IEEE8021X));
|
||||
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)
|
||||
|
@ -76,14 +86,26 @@ static inline int wpa_key_mgmt_wpa(int 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 {
|
||||
|
@ -92,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
|
||||
};
|
||||
|
||||
/**
|
||||
|
@ -103,7 +128,9 @@ enum wpa_cipher {
|
|||
CIPHER_WEP40,
|
||||
CIPHER_TKIP,
|
||||
CIPHER_CCMP,
|
||||
CIPHER_WEP104
|
||||
CIPHER_WEP104,
|
||||
CIPHER_GCMP,
|
||||
CIPHER_SMS4
|
||||
};
|
||||
|
||||
/**
|
||||
|
@ -119,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
|
||||
};
|
||||
|
||||
/**
|
||||
|
@ -254,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
|
||||
|
@ -264,6 +297,7 @@ enum hostapd_hw_mode {
|
|||
HOSTAPD_MODE_IEEE80211B,
|
||||
HOSTAPD_MODE_IEEE80211G,
|
||||
HOSTAPD_MODE_IEEE80211A,
|
||||
HOSTAPD_MODE_IEEE80211AD,
|
||||
NUM_HOSTAPD_MODES
|
||||
};
|
||||
|
||||
|
@ -281,4 +315,7 @@ enum wpa_ctrl_req_type {
|
|||
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 */
|
||||
|
|
|
@ -1,16 +1,10 @@
|
|||
/*
|
||||
* Generic advertisement service (GAS) (IEEE 802.11u)
|
||||
* Copyright (c) 2009, Atheros Communications
|
||||
* Copyright (c) 2011, Qualcomm Atheros
|
||||
* Copyright (c) 2011-2012, Qualcomm Atheros
|
||||
*
|
||||
* 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"
|
||||
|
@ -37,7 +31,7 @@ gas_build_req(u8 action, u8 dialog_token, size_t size)
|
|||
}
|
||||
|
||||
|
||||
static struct wpabuf * gas_build_initial_req(u8 dialog_token, size_t size)
|
||||
struct wpabuf * gas_build_initial_req(u8 dialog_token, size_t size)
|
||||
{
|
||||
return gas_build_req(WLAN_PA_GAS_INITIAL_REQ, dialog_token,
|
||||
size);
|
||||
|
|
|
@ -1,21 +1,16 @@
|
|||
/*
|
||||
* Generic advertisement service (GAS) (IEEE 802.11u)
|
||||
* Copyright (c) 2009, Atheros Communications
|
||||
* Copyright (c) 2011, Qualcomm Atheros
|
||||
* Copyright (c) 2011-2012, Qualcomm Atheros
|
||||
*
|
||||
* 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 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);
|
||||
|
|
|
@ -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"
|
||||
|
@ -103,6 +97,16 @@ static int ieee802_11_parse_vendor_specific(const u8 *pos, size_t elen,
|
|||
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 "
|
||||
|
@ -254,6 +258,14 @@ 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;
|
||||
|
@ -263,6 +275,19 @@ ParseRes ieee802_11_parse_elems(const u8 *start, size_t len,
|
|||
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)
|
||||
|
@ -389,3 +414,75 @@ const u8 * get_hdr_bssid(const struct ieee80211_hdr *hdr, size_t len)
|
|||
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,10 +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;
|
||||
|
@ -66,9 +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;
|
||||
|
@ -82,4 +89,15 @@ struct wpabuf * ieee802_11_vendor_ie_concat(const u8 *ies, size_t ies_len,
|
|||
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
|
||||
|
@ -82,6 +76,7 @@
|
|||
#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
|
||||
|
@ -163,6 +158,8 @@
|
|||
#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) */
|
||||
|
@ -229,17 +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
|
||||
|
||||
|
||||
|
@ -260,6 +273,7 @@
|
|||
#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
|
||||
|
@ -491,6 +505,17 @@ 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];
|
||||
|
@ -513,12 +538,25 @@ struct ieee80211_mgmt {
|
|||
* 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;
|
||||
|
@ -537,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 */
|
||||
|
@ -618,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))
|
||||
|
@ -631,14 +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
|
||||
|
@ -677,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
|
||||
|
@ -748,6 +834,16 @@ 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
|
||||
|
@ -846,6 +942,7 @@ enum p2p_service_protocol_type {
|
|||
P2P_SERV_BONJOUR = 1,
|
||||
P2P_SERV_UPNP = 2,
|
||||
P2P_SERV_WS_DISCOVERY = 3,
|
||||
P2P_SERV_WIFI_DISPLAY = 4,
|
||||
P2P_SERV_VENDOR_SPECIFIC = 255
|
||||
};
|
||||
|
||||
|
@ -857,6 +954,20 @@ enum p2p_sd_status {
|
|||
};
|
||||
|
||||
|
||||
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 */
|
||||
|
@ -869,10 +980,20 @@ enum p2p_sd_status {
|
|||
#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 */
|
||||
|
@ -914,4 +1035,51 @@ enum wnm_action {
|
|||
#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
|
||||
|
|
|
@ -5,6 +5,6 @@
|
|||
#define VERSION_STR_POSTFIX ""
|
||||
#endif /* VERSION_STR_POSTFIX */
|
||||
|
||||
#define VERSION_STR "1.1" VERSION_STR_POSTFIX
|
||||
#define VERSION_STR "2.0" VERSION_STR_POSTFIX
|
||||
|
||||
#endif /* VERSION_H */
|
||||
|
|
|
@ -2,14 +2,8 @@
|
|||
* WPA/RSN - Shared functions for supplicant and authenticator
|
||||
* Copyright (c) 2002-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 "includes.h"
|
||||
|
@ -49,8 +43,10 @@ int wpa_eapol_key_mic(const u8 *key, int ver, const u8 *buf, size_t len,
|
|||
u8 hash[SHA1_MAC_LEN];
|
||||
|
||||
switch (ver) {
|
||||
#ifndef CONFIG_FIPS
|
||||
case WPA_KEY_INFO_TYPE_HMAC_MD5_RC4:
|
||||
return hmac_md5(key, 16, buf, len, mic);
|
||||
#endif /* CONFIG_FIPS */
|
||||
case WPA_KEY_INFO_TYPE_HMAC_SHA1_AES:
|
||||
if (hmac_sha1(key, 16, buf, len, hash))
|
||||
return -1;
|
||||
|
@ -356,6 +352,8 @@ static int rsn_selector_to_bitfield(const u8 *s)
|
|||
if (RSN_SELECTOR_GET(s) == RSN_CIPHER_SUITE_AES_128_CMAC)
|
||||
return WPA_CIPHER_AES_128_CMAC;
|
||||
#endif /* CONFIG_IEEE80211W */
|
||||
if (RSN_SELECTOR_GET(s) == RSN_CIPHER_SUITE_GCMP)
|
||||
return WPA_CIPHER_GCMP;
|
||||
return 0;
|
||||
}
|
||||
|
||||
|
@ -378,6 +376,12 @@ static int rsn_key_mgmt_to_bitfield(const u8 *s)
|
|||
if (RSN_SELECTOR_GET(s) == RSN_AUTH_KEY_MGMT_PSK_SHA256)
|
||||
return WPA_KEY_MGMT_PSK_SHA256;
|
||||
#endif /* CONFIG_IEEE80211W */
|
||||
#ifdef CONFIG_SAE
|
||||
if (RSN_SELECTOR_GET(s) == RSN_AUTH_KEY_MGMT_SAE)
|
||||
return WPA_KEY_MGMT_SAE;
|
||||
if (RSN_SELECTOR_GET(s) == RSN_AUTH_KEY_MGMT_FT_SAE)
|
||||
return WPA_KEY_MGMT_FT_SAE;
|
||||
#endif /* CONFIG_SAE */
|
||||
return 0;
|
||||
}
|
||||
#endif /* CONFIG_NO_WPA2 */
|
||||
|
@ -912,6 +916,8 @@ const char * wpa_cipher_txt(int cipher)
|
|||
return "CCMP";
|
||||
case WPA_CIPHER_CCMP | WPA_CIPHER_TKIP:
|
||||
return "CCMP+TKIP";
|
||||
case WPA_CIPHER_GCMP:
|
||||
return "GCMP";
|
||||
default:
|
||||
return "UNKNOWN";
|
||||
}
|
||||
|
@ -1073,3 +1079,138 @@ int wpa_insert_pmkid(u8 *ies, size_t ies_len, const u8 *pmkid)
|
|||
return added;
|
||||
}
|
||||
#endif /* CONFIG_IEEE80211R */
|
||||
|
||||
|
||||
int wpa_cipher_key_len(int cipher)
|
||||
{
|
||||
switch (cipher) {
|
||||
case WPA_CIPHER_CCMP:
|
||||
case WPA_CIPHER_GCMP:
|
||||
return 16;
|
||||
case WPA_CIPHER_TKIP:
|
||||
return 32;
|
||||
case WPA_CIPHER_WEP104:
|
||||
return 13;
|
||||
case WPA_CIPHER_WEP40:
|
||||
return 5;
|
||||
}
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
|
||||
int wpa_cipher_rsc_len(int cipher)
|
||||
{
|
||||
switch (cipher) {
|
||||
case WPA_CIPHER_CCMP:
|
||||
case WPA_CIPHER_GCMP:
|
||||
case WPA_CIPHER_TKIP:
|
||||
return 6;
|
||||
case WPA_CIPHER_WEP104:
|
||||
case WPA_CIPHER_WEP40:
|
||||
return 0;
|
||||
}
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
|
||||
int wpa_cipher_to_alg(int cipher)
|
||||
{
|
||||
switch (cipher) {
|
||||
case WPA_CIPHER_CCMP:
|
||||
return WPA_ALG_CCMP;
|
||||
case WPA_CIPHER_GCMP:
|
||||
return WPA_ALG_GCMP;
|
||||
case WPA_CIPHER_TKIP:
|
||||
return WPA_ALG_TKIP;
|
||||
case WPA_CIPHER_WEP104:
|
||||
case WPA_CIPHER_WEP40:
|
||||
return WPA_ALG_WEP;
|
||||
}
|
||||
return WPA_ALG_NONE;
|
||||
}
|
||||
|
||||
|
||||
int wpa_cipher_valid_pairwise(int cipher)
|
||||
{
|
||||
return cipher == WPA_CIPHER_CCMP ||
|
||||
cipher == WPA_CIPHER_GCMP ||
|
||||
cipher == WPA_CIPHER_TKIP;
|
||||
}
|
||||
|
||||
|
||||
u32 wpa_cipher_to_suite(int proto, int cipher)
|
||||
{
|
||||
if (cipher & WPA_CIPHER_CCMP)
|
||||
return (proto == WPA_PROTO_RSN ?
|
||||
RSN_CIPHER_SUITE_CCMP : WPA_CIPHER_SUITE_CCMP);
|
||||
if (cipher & WPA_CIPHER_GCMP)
|
||||
return RSN_CIPHER_SUITE_GCMP;
|
||||
if (cipher & WPA_CIPHER_TKIP)
|
||||
return (proto == WPA_PROTO_RSN ?
|
||||
RSN_CIPHER_SUITE_TKIP : WPA_CIPHER_SUITE_TKIP);
|
||||
if (cipher & WPA_CIPHER_WEP104)
|
||||
return (proto == WPA_PROTO_RSN ?
|
||||
RSN_CIPHER_SUITE_WEP104 : WPA_CIPHER_SUITE_WEP104);
|
||||
if (cipher & WPA_CIPHER_WEP40)
|
||||
return (proto == WPA_PROTO_RSN ?
|
||||
RSN_CIPHER_SUITE_WEP40 : WPA_CIPHER_SUITE_WEP40);
|
||||
if (cipher & WPA_CIPHER_NONE)
|
||||
return (proto == WPA_PROTO_RSN ?
|
||||
RSN_CIPHER_SUITE_NONE : WPA_CIPHER_SUITE_NONE);
|
||||
return 0;
|
||||
}
|
||||
|
||||
|
||||
int rsn_cipher_put_suites(u8 *pos, int ciphers)
|
||||
{
|
||||
int num_suites = 0;
|
||||
|
||||
if (ciphers & WPA_CIPHER_CCMP) {
|
||||
RSN_SELECTOR_PUT(pos, RSN_CIPHER_SUITE_CCMP);
|
||||
pos += RSN_SELECTOR_LEN;
|
||||
num_suites++;
|
||||
}
|
||||
if (ciphers & WPA_CIPHER_GCMP) {
|
||||
RSN_SELECTOR_PUT(pos, RSN_CIPHER_SUITE_GCMP);
|
||||
pos += RSN_SELECTOR_LEN;
|
||||
num_suites++;
|
||||
}
|
||||
if (ciphers & WPA_CIPHER_TKIP) {
|
||||
RSN_SELECTOR_PUT(pos, RSN_CIPHER_SUITE_TKIP);
|
||||
pos += RSN_SELECTOR_LEN;
|
||||
num_suites++;
|
||||
}
|
||||
if (ciphers & WPA_CIPHER_NONE) {
|
||||
RSN_SELECTOR_PUT(pos, RSN_CIPHER_SUITE_NONE);
|
||||
pos += RSN_SELECTOR_LEN;
|
||||
num_suites++;
|
||||
}
|
||||
|
||||
return num_suites;
|
||||
}
|
||||
|
||||
|
||||
int wpa_cipher_put_suites(u8 *pos, int ciphers)
|
||||
{
|
||||
int num_suites = 0;
|
||||
|
||||
if (ciphers & WPA_CIPHER_CCMP) {
|
||||
RSN_SELECTOR_PUT(pos, WPA_CIPHER_SUITE_CCMP);
|
||||
pos += WPA_SELECTOR_LEN;
|
||||
num_suites++;
|
||||
}
|
||||
if (ciphers & WPA_CIPHER_TKIP) {
|
||||
RSN_SELECTOR_PUT(pos, WPA_CIPHER_SUITE_TKIP);
|
||||
pos += WPA_SELECTOR_LEN;
|
||||
num_suites++;
|
||||
}
|
||||
if (ciphers & WPA_CIPHER_NONE) {
|
||||
RSN_SELECTOR_PUT(pos, WPA_CIPHER_SUITE_NONE);
|
||||
pos += WPA_SELECTOR_LEN;
|
||||
num_suites++;
|
||||
}
|
||||
|
||||
return num_suites;
|
||||
}
|
||||
|
|
|
@ -2,14 +2,8 @@
|
|||
* WPA definitions shared between hostapd and wpa_supplicant
|
||||
* Copyright (c) 2002-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 WPA_COMMON_H
|
||||
|
@ -38,6 +32,7 @@
|
|||
#define WPA_AUTH_KEY_MGMT_NONE RSN_SELECTOR(0x00, 0x50, 0xf2, 0)
|
||||
#define WPA_AUTH_KEY_MGMT_UNSPEC_802_1X RSN_SELECTOR(0x00, 0x50, 0xf2, 1)
|
||||
#define WPA_AUTH_KEY_MGMT_PSK_OVER_802_1X RSN_SELECTOR(0x00, 0x50, 0xf2, 2)
|
||||
#define WPA_AUTH_KEY_MGMT_CCKM RSN_SELECTOR(0x00, 0x40, 0x96, 0)
|
||||
#define WPA_CIPHER_SUITE_NONE RSN_SELECTOR(0x00, 0x50, 0xf2, 0)
|
||||
#define WPA_CIPHER_SUITE_WEP40 RSN_SELECTOR(0x00, 0x50, 0xf2, 1)
|
||||
#define WPA_CIPHER_SUITE_TKIP RSN_SELECTOR(0x00, 0x50, 0xf2, 2)
|
||||
|
@ -57,6 +52,9 @@
|
|||
#define RSN_AUTH_KEY_MGMT_802_1X_SHA256 RSN_SELECTOR(0x00, 0x0f, 0xac, 5)
|
||||
#define RSN_AUTH_KEY_MGMT_PSK_SHA256 RSN_SELECTOR(0x00, 0x0f, 0xac, 6)
|
||||
#define RSN_AUTH_KEY_MGMT_TPK_HANDSHAKE RSN_SELECTOR(0x00, 0x0f, 0xac, 7)
|
||||
#define RSN_AUTH_KEY_MGMT_SAE RSN_SELECTOR(0x00, 0x0f, 0xac, 8)
|
||||
#define RSN_AUTH_KEY_MGMT_FT_SAE RSN_SELECTOR(0x00, 0x0f, 0xac, 9)
|
||||
#define RSN_AUTH_KEY_MGMT_CCKM RSN_SELECTOR(0x00, 0x40, 0x96, 0x00)
|
||||
|
||||
#define RSN_CIPHER_SUITE_NONE RSN_SELECTOR(0x00, 0x0f, 0xac, 0)
|
||||
#define RSN_CIPHER_SUITE_WEP40 RSN_SELECTOR(0x00, 0x0f, 0xac, 1)
|
||||
|
@ -70,6 +68,7 @@
|
|||
#define RSN_CIPHER_SUITE_AES_128_CMAC RSN_SELECTOR(0x00, 0x0f, 0xac, 6)
|
||||
#endif /* CONFIG_IEEE80211W */
|
||||
#define RSN_CIPHER_SUITE_NO_GROUP_ADDRESSED RSN_SELECTOR(0x00, 0x0f, 0xac, 7)
|
||||
#define RSN_CIPHER_SUITE_GCMP RSN_SELECTOR(0x00, 0x0f, 0xac, 8)
|
||||
|
||||
/* EAPOL-Key Key Data Encapsulation
|
||||
* GroupKey and PeerKey require encryption, otherwise, encryption is optional.
|
||||
|
@ -89,6 +88,9 @@
|
|||
#ifdef CONFIG_IEEE80211W
|
||||
#define RSN_KEY_DATA_IGTK RSN_SELECTOR(0x00, 0x0f, 0xac, 9)
|
||||
#endif /* CONFIG_IEEE80211W */
|
||||
#define RSN_KEY_DATA_KEYID RSN_SELECTOR(0x00, 0x0f, 0xac, 10)
|
||||
#define RSN_KEY_DATA_MULTIBAND_GTK RSN_SELECTOR(0x00, 0x0f, 0xac, 11)
|
||||
#define RSN_KEY_DATA_MULTIBAND_KEYID RSN_SELECTOR(0x00, 0x0f, 0xac, 12)
|
||||
|
||||
#define WPA_OUI_TYPE RSN_SELECTOR(0x00, 0x50, 0xf2, 1)
|
||||
|
||||
|
@ -381,4 +383,12 @@ struct wpa_ft_ies {
|
|||
|
||||
int wpa_ft_parse_ies(const u8 *ies, size_t ies_len, struct wpa_ft_ies *parse);
|
||||
|
||||
int wpa_cipher_key_len(int cipher);
|
||||
int wpa_cipher_rsc_len(int cipher);
|
||||
int wpa_cipher_to_alg(int cipher);
|
||||
int wpa_cipher_valid_pairwise(int cipher);
|
||||
u32 wpa_cipher_to_suite(int proto, int cipher);
|
||||
int rsn_cipher_put_suites(u8 *pos, int ciphers);
|
||||
int wpa_cipher_put_suites(u8 *pos, int ciphers);
|
||||
|
||||
#endif /* WPA_COMMON_H */
|
||||
|
|
|
@ -2,14 +2,8 @@
|
|||
* wpa_supplicant/hostapd control interface library
|
||||
* 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 "includes.h"
|
||||
|
@ -18,7 +12,12 @@
|
|||
|
||||
#ifdef CONFIG_CTRL_IFACE_UNIX
|
||||
#include <sys/un.h>
|
||||
#include <unistd.h>
|
||||
#include <fcntl.h>
|
||||
#endif /* CONFIG_CTRL_IFACE_UNIX */
|
||||
#ifdef CONFIG_CTRL_IFACE_UDP_REMOTE
|
||||
#include <netdb.h>
|
||||
#endif /* CONFIG_CTRL_IFACE_UDP_REMOTE */
|
||||
|
||||
#ifdef ANDROID
|
||||
#include <dirent.h>
|
||||
|
@ -50,6 +49,8 @@ struct wpa_ctrl {
|
|||
struct sockaddr_in local;
|
||||
struct sockaddr_in dest;
|
||||
char *cookie;
|
||||
char *remote_ifname;
|
||||
char *remote_ip;
|
||||
#endif /* CONFIG_CTRL_IFACE_UDP */
|
||||
#ifdef CONFIG_CTRL_IFACE_UNIX
|
||||
int s;
|
||||
|
@ -79,6 +80,7 @@ struct wpa_ctrl * wpa_ctrl_open(const char *ctrl_path)
|
|||
int ret;
|
||||
size_t res;
|
||||
int tries = 0;
|
||||
int flags;
|
||||
|
||||
ctrl = os_malloc(sizeof(*ctrl));
|
||||
if (ctrl == NULL)
|
||||
|
@ -162,6 +164,19 @@ try_again:
|
|||
return NULL;
|
||||
}
|
||||
|
||||
/*
|
||||
* Make socket non-blocking so that we don't hang forever if
|
||||
* target dies unexpectedly.
|
||||
*/
|
||||
flags = fcntl(ctrl->s, F_GETFL);
|
||||
if (flags >= 0) {
|
||||
flags |= O_NONBLOCK;
|
||||
if (fcntl(ctrl->s, F_SETFL, flags) < 0) {
|
||||
perror("fcntl(ctrl->s, O_NONBLOCK)");
|
||||
/* Not fatal, continue on.*/
|
||||
}
|
||||
}
|
||||
|
||||
return ctrl;
|
||||
}
|
||||
|
||||
|
@ -236,6 +251,9 @@ struct wpa_ctrl * wpa_ctrl_open(const char *ctrl_path)
|
|||
struct wpa_ctrl *ctrl;
|
||||
char buf[128];
|
||||
size_t len;
|
||||
#ifdef CONFIG_CTRL_IFACE_UDP_REMOTE
|
||||
struct hostent *h;
|
||||
#endif /* CONFIG_CTRL_IFACE_UDP_REMOTE */
|
||||
|
||||
ctrl = os_malloc(sizeof(*ctrl));
|
||||
if (ctrl == NULL)
|
||||
|
@ -250,7 +268,11 @@ struct wpa_ctrl * wpa_ctrl_open(const char *ctrl_path)
|
|||
}
|
||||
|
||||
ctrl->local.sin_family = AF_INET;
|
||||
#ifdef CONFIG_CTRL_IFACE_UDP_REMOTE
|
||||
ctrl->local.sin_addr.s_addr = INADDR_ANY;
|
||||
#else /* CONFIG_CTRL_IFACE_UDP_REMOTE */
|
||||
ctrl->local.sin_addr.s_addr = htonl((127 << 24) | 1);
|
||||
#endif /* CONFIG_CTRL_IFACE_UDP_REMOTE */
|
||||
if (bind(ctrl->s, (struct sockaddr *) &ctrl->local,
|
||||
sizeof(ctrl->local)) < 0) {
|
||||
close(ctrl->s);
|
||||
|
@ -261,10 +283,48 @@ struct wpa_ctrl * wpa_ctrl_open(const char *ctrl_path)
|
|||
ctrl->dest.sin_family = AF_INET;
|
||||
ctrl->dest.sin_addr.s_addr = htonl((127 << 24) | 1);
|
||||
ctrl->dest.sin_port = htons(WPA_CTRL_IFACE_PORT);
|
||||
|
||||
#ifdef CONFIG_CTRL_IFACE_UDP_REMOTE
|
||||
if (ctrl_path) {
|
||||
char *port, *name;
|
||||
int port_id;
|
||||
|
||||
name = os_strdup(ctrl_path);
|
||||
if (name == NULL) {
|
||||
close(ctrl->s);
|
||||
os_free(ctrl);
|
||||
return NULL;
|
||||
}
|
||||
port = os_strchr(name, ':');
|
||||
|
||||
if (port) {
|
||||
port_id = atoi(&port[1]);
|
||||
port[0] = '\0';
|
||||
} else
|
||||
port_id = WPA_CTRL_IFACE_PORT;
|
||||
|
||||
h = gethostbyname(name);
|
||||
ctrl->remote_ip = os_strdup(name);
|
||||
os_free(name);
|
||||
if (h == NULL) {
|
||||
perror("gethostbyname");
|
||||
close(ctrl->s);
|
||||
os_free(ctrl->remote_ip);
|
||||
os_free(ctrl);
|
||||
return NULL;
|
||||
}
|
||||
ctrl->dest.sin_port = htons(port_id);
|
||||
os_memcpy(h->h_addr, (char *) &ctrl->dest.sin_addr.s_addr,
|
||||
h->h_length);
|
||||
} else
|
||||
ctrl->remote_ip = os_strdup("localhost");
|
||||
#endif /* CONFIG_CTRL_IFACE_UDP_REMOTE */
|
||||
|
||||
if (connect(ctrl->s, (struct sockaddr *) &ctrl->dest,
|
||||
sizeof(ctrl->dest)) < 0) {
|
||||
perror("connect");
|
||||
close(ctrl->s);
|
||||
os_free(ctrl->remote_ip);
|
||||
os_free(ctrl);
|
||||
return NULL;
|
||||
}
|
||||
|
@ -275,14 +335,31 @@ struct wpa_ctrl * wpa_ctrl_open(const char *ctrl_path)
|
|||
ctrl->cookie = os_strdup(buf);
|
||||
}
|
||||
|
||||
if (wpa_ctrl_request(ctrl, "IFNAME", 6, buf, &len, NULL) == 0) {
|
||||
buf[len] = '\0';
|
||||
ctrl->remote_ifname = os_strdup(buf);
|
||||
}
|
||||
|
||||
return ctrl;
|
||||
}
|
||||
|
||||
|
||||
char * wpa_ctrl_get_remote_ifname(struct wpa_ctrl *ctrl)
|
||||
{
|
||||
#define WPA_CTRL_MAX_PS_NAME 100
|
||||
static char ps[WPA_CTRL_MAX_PS_NAME] = {};
|
||||
os_snprintf(ps, WPA_CTRL_MAX_PS_NAME, "%s/%s",
|
||||
ctrl->remote_ip, ctrl->remote_ifname);
|
||||
return ps;
|
||||
}
|
||||
|
||||
|
||||
void wpa_ctrl_close(struct wpa_ctrl *ctrl)
|
||||
{
|
||||
close(ctrl->s);
|
||||
os_free(ctrl->cookie);
|
||||
os_free(ctrl->remote_ifname);
|
||||
os_free(ctrl->remote_ip);
|
||||
os_free(ctrl);
|
||||
}
|
||||
|
||||
|
@ -295,6 +372,7 @@ int wpa_ctrl_request(struct wpa_ctrl *ctrl, const char *cmd, size_t cmd_len,
|
|||
void (*msg_cb)(char *msg, size_t len))
|
||||
{
|
||||
struct timeval tv;
|
||||
struct os_time started_at;
|
||||
int res;
|
||||
fd_set rfds;
|
||||
const char *_cmd;
|
||||
|
@ -321,7 +399,30 @@ int wpa_ctrl_request(struct wpa_ctrl *ctrl, const char *cmd, size_t cmd_len,
|
|||
_cmd_len = cmd_len;
|
||||
}
|
||||
|
||||
errno = 0;
|
||||
started_at.sec = 0;
|
||||
started_at.usec = 0;
|
||||
retry_send:
|
||||
if (send(ctrl->s, _cmd, _cmd_len, 0) < 0) {
|
||||
if (errno == EAGAIN || errno == EBUSY || errno == EWOULDBLOCK)
|
||||
{
|
||||
/*
|
||||
* Must be a non-blocking socket... Try for a bit
|
||||
* longer before giving up.
|
||||
*/
|
||||
if (started_at.sec == 0)
|
||||
os_get_time(&started_at);
|
||||
else {
|
||||
struct os_time n;
|
||||
os_get_time(&n);
|
||||
/* Try for a few seconds. */
|
||||
if (n.sec > started_at.sec + 5)
|
||||
goto send_err;
|
||||
}
|
||||
os_sleep(1, 0);
|
||||
goto retry_send;
|
||||
}
|
||||
send_err:
|
||||
os_free(cmd_buf);
|
||||
return -1;
|
||||
}
|
||||
|
|
|
@ -2,14 +2,8 @@
|
|||
* wpa_supplicant/hostapd control interface library
|
||||
* Copyright (c) 2004-2006, 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_CTRL_H
|
||||
|
@ -54,6 +48,10 @@ extern "C" {
|
|||
#define WPA_EVENT_EAP_SUCCESS "CTRL-EVENT-EAP-SUCCESS "
|
||||
/** EAP authentication failed (EAP-Failure received) */
|
||||
#define WPA_EVENT_EAP_FAILURE "CTRL-EVENT-EAP-FAILURE "
|
||||
/** Network block temporarily disabled (e.g., due to authentication failure) */
|
||||
#define WPA_EVENT_TEMP_DISABLED "CTRL-EVENT-SSID-TEMP-DISABLED "
|
||||
/** Temporarily disabled network block re-enabled */
|
||||
#define WPA_EVENT_REENABLED "CTRL-EVENT-SSID-REENABLED "
|
||||
/** New scan results available */
|
||||
#define WPA_EVENT_SCAN_RESULTS "CTRL-EVENT-SCAN-RESULTS "
|
||||
/** wpa_supplicant state change */
|
||||
|
@ -122,6 +120,8 @@ extern "C" {
|
|||
#define P2P_EVENT_PROV_DISC_PBC_REQ "P2P-PROV-DISC-PBC-REQ "
|
||||
/* parameters: <peer address> */
|
||||
#define P2P_EVENT_PROV_DISC_PBC_RESP "P2P-PROV-DISC-PBC-RESP "
|
||||
/* parameters: <peer address> <status> */
|
||||
#define P2P_EVENT_PROV_DISC_FAILURE "P2P-PROV-DISC-FAILURE"
|
||||
/* parameters: <freq> <src addr> <dialog token> <update indicator> <TLVs> */
|
||||
#define P2P_EVENT_SERV_DISC_REQ "P2P-SERV-DISC-REQ "
|
||||
/* parameters: <src addr> <update indicator> <TLVs> */
|
||||
|
@ -133,6 +133,8 @@ extern "C" {
|
|||
#define INTERWORKING_AP "INTERWORKING-AP "
|
||||
#define INTERWORKING_NO_MATCH "INTERWORKING-NO-MATCH "
|
||||
|
||||
#define GAS_RESPONSE_INFO "GAS-RESPONSE-INFO "
|
||||
|
||||
/* hostapd control interface - fixed message prefixes */
|
||||
#define WPS_EVENT_PIN_NEEDED "WPS-PIN-NEEDED "
|
||||
#define WPS_EVENT_NEW_AP_SETTINGS "WPS-NEW-AP-SETTINGS "
|
||||
|
@ -145,6 +147,28 @@ extern "C" {
|
|||
#define AP_STA_DISCONNECTED "AP-STA-DISCONNECTED "
|
||||
|
||||
|
||||
/* BSS command information masks */
|
||||
|
||||
#define WPA_BSS_MASK_ALL 0xFFFFFFFF
|
||||
#define WPA_BSS_MASK_ID BIT(0)
|
||||
#define WPA_BSS_MASK_BSSID BIT(1)
|
||||
#define WPA_BSS_MASK_FREQ BIT(2)
|
||||
#define WPA_BSS_MASK_BEACON_INT BIT(3)
|
||||
#define WPA_BSS_MASK_CAPABILITIES BIT(4)
|
||||
#define WPA_BSS_MASK_QUAL BIT(5)
|
||||
#define WPA_BSS_MASK_NOISE BIT(6)
|
||||
#define WPA_BSS_MASK_LEVEL BIT(7)
|
||||
#define WPA_BSS_MASK_TSF BIT(8)
|
||||
#define WPA_BSS_MASK_AGE BIT(9)
|
||||
#define WPA_BSS_MASK_IE BIT(10)
|
||||
#define WPA_BSS_MASK_FLAGS BIT(11)
|
||||
#define WPA_BSS_MASK_SSID BIT(12)
|
||||
#define WPA_BSS_MASK_WPS_SCAN BIT(13)
|
||||
#define WPA_BSS_MASK_P2P_SCAN BIT(14)
|
||||
#define WPA_BSS_MASK_INTERNETW BIT(15)
|
||||
#define WPA_BSS_MASK_WIFI_DISPLAY BIT(16)
|
||||
|
||||
|
||||
/* wpa_supplicant/hostapd control interface access */
|
||||
|
||||
/**
|
||||
|
@ -269,6 +293,8 @@ int wpa_ctrl_pending(struct wpa_ctrl *ctrl);
|
|||
*/
|
||||
int wpa_ctrl_get_fd(struct wpa_ctrl *ctrl);
|
||||
|
||||
char * wpa_ctrl_get_remote_ifname(struct wpa_ctrl *ctrl);
|
||||
|
||||
#ifdef ANDROID
|
||||
/**
|
||||
* wpa_ctrl_cleanup() - Delete any local UNIX domain socket files that
|
||||
|
@ -281,8 +307,11 @@ void wpa_ctrl_cleanup(void);
|
|||
#endif /* ANDROID */
|
||||
|
||||
#ifdef CONFIG_CTRL_IFACE_UDP
|
||||
/* Port range for multiple wpa_supplicant instances and multiple VIFs */
|
||||
#define WPA_CTRL_IFACE_PORT 9877
|
||||
#define WPA_CTRL_IFACE_PORT_LIMIT 50 /* decremented from start */
|
||||
#define WPA_GLOBAL_CTRL_IFACE_PORT 9878
|
||||
#define WPA_GLOBAL_CTRL_IFACE_PORT_LIMIT 20 /* incremented from start */
|
||||
#endif /* CONFIG_CTRL_IFACE_UDP */
|
||||
|
||||
|
||||
|
|
Some files were not shown because too many files have changed in this diff Show More
Loading…
Reference in New Issue