mirror of
https://github.com/freebsd/freebsd-src.git
synced 2024-11-27 00:33:30 +00:00
Merge hostapd / wpa_supplicant 2.0.
Reviewed by: adrian (driver_bsd + usr.sbin/wpa)
This commit is contained in:
commit
f05cddf940
Notes:
svn2git
2020-12-20 02:59:44 +00:00
svn path=/head/; revision=252726
@ -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.
|
||||
|
@ -1,19 +1,56 @@
|
||||
wpa_supplicant and hostapd v0.6.x
|
||||
---------------------------------
|
||||
wpa_supplicant and hostapd
|
||||
--------------------------
|
||||
|
||||
Copyright (c) 2002-2007, Jouni Malinen <j@w1.fi> and contributors
|
||||
Copyright (c) 2002-2012, Jouni Malinen <j@w1.fi> and contributors
|
||||
All Rights Reserved.
|
||||
|
||||
These program is dual-licensed under both the GPL version 2 and BSD
|
||||
license. Either license may be used at your option.
|
||||
These programs are licensed under the BSD license (the one with
|
||||
advertisement clause removed).
|
||||
|
||||
If you are submitting changes to the project, please see CONTRIBUTIONS
|
||||
file for more instructions.
|
||||
|
||||
|
||||
This package may include either wpa_supplicant, hostapd, or both. See
|
||||
README file respective subdirectories (wpa_supplicant/README or
|
||||
hostapd/README) for more details.
|
||||
|
||||
Source code files have been moved around in v0.6.x releases and
|
||||
compared to earlier releases, the programs are now build by first
|
||||
going to a subdirectory (wpa_supplicant or hostapd) and creating
|
||||
build configuration (.config) and running 'make' there (for
|
||||
Linux/BSD/cygwin builds).
|
||||
Source code files were moved around in v0.6.x releases and compared to
|
||||
earlier releases, the programs are now built by first going to a
|
||||
subdirectory (wpa_supplicant or hostapd) and creating build
|
||||
configuration (.config) and running 'make' there (for Linux/BSD/cygwin
|
||||
builds).
|
||||
|
||||
|
||||
License
|
||||
-------
|
||||
|
||||
This software may be distributed, used, and modified under the terms of
|
||||
BSD license:
|
||||
|
||||
Redistribution and use in source and binary forms, with or without
|
||||
modification, are permitted provided that the following conditions are
|
||||
met:
|
||||
|
||||
1. Redistributions of source code must retain the above copyright
|
||||
notice, this list of conditions and the following disclaimer.
|
||||
|
||||
2. Redistributions in binary form must reproduce the above copyright
|
||||
notice, this list of conditions and the following disclaimer in the
|
||||
documentation and/or other materials provided with the distribution.
|
||||
|
||||
3. Neither the name(s) of the above-listed copyright holder(s) nor the
|
||||
names of its contributors may be used to endorse or promote products
|
||||
derived from this software without specific prior written permission.
|
||||
|
||||
THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
|
||||
"AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
|
||||
LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
|
||||
A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
|
||||
OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
|
||||
SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
|
||||
LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
|
||||
DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
|
||||
THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
|
||||
(INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
|
||||
OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
|
||||
|
7
contrib/wpa/hostapd/.gitignore
vendored
7
contrib/wpa/hostapd/.gitignore
vendored
@ -1,7 +0,0 @@
|
||||
*.d
|
||||
.config
|
||||
driver_conf.c
|
||||
hostapd
|
||||
hostapd_cli
|
||||
hlr_auc_gw
|
||||
nt_password_hash
|
@ -1,20 +1,206 @@
|
||||
ChangeLog for hostapd
|
||||
|
||||
2010-09-07 - v0.7.3
|
||||
* fixed re-association after WPS not initializing WPA state machine in
|
||||
some cases
|
||||
* fixed WPS IE update on reconfiguration
|
||||
* fixed WPS code not to proxy Probe Request frames for foreign SSIDs
|
||||
* added WPS workaround for open networks and some known interop issues
|
||||
* fixed WPS Diffie-Hellman derivation to use correct public key length
|
||||
* fixed FT RRB messages on big endian CPUs
|
||||
* changed WPS protection for brute force AP PIN attacks to disable AP
|
||||
PIN only temporarily (but with increasing time) to avoid usability
|
||||
issues on Label-only devices
|
||||
* added wps_ap_pin command for more secure handling of AP PIN
|
||||
operations (e.g., to generate a random AP PIN and only use it for
|
||||
short amount of time)
|
||||
* fixed HT STBC negotiation
|
||||
2013-01-12 - v2.0
|
||||
* added AP-STA-DISCONNECTED ctrl_iface event
|
||||
* improved debug logging (human readable event names, interface name
|
||||
included in more entries)
|
||||
* added number of small changes to make it easier for static analyzers
|
||||
to understand the implementation
|
||||
* added a workaround for Windows 7 Michael MIC failure reporting and
|
||||
use of the Secure bit in EAPOL-Key msg 3/4
|
||||
* fixed number of small bugs (see git logs for more details)
|
||||
* changed OpenSSL to read full certificate chain from server_cert file
|
||||
* nl80211: number of updates to use new cfg80211/nl80211 functionality
|
||||
- replace monitor interface with nl80211 commands
|
||||
- additional information for driver-based AP SME
|
||||
* EAP-pwd:
|
||||
- fix KDF for group 21 and zero-padding
|
||||
- added support for fragmentation
|
||||
- increased maximum number of hunting-and-pecking iterations
|
||||
* avoid excessive Probe Response retries for broadcast Probe Request
|
||||
frames (only with drivers using hostapd SME/MLME)
|
||||
* added preliminary support for using TLS v1.2 (CONFIG_TLSV12=y)
|
||||
* fixed WPS operation stopping on dual concurrent AP
|
||||
* added wps_rf_bands configuration parameter for overriding RF Bands
|
||||
value for WPS
|
||||
* added support for getting per-device PSK from RADIUS Tunnel-Password
|
||||
* added support for libnl 3.2 and newer
|
||||
* increased initial group key handshake retransmit timeout to 500 ms
|
||||
* added a workaround for 4-way handshake to update SNonce even after
|
||||
having sent EAPOL-Key 3/4 to avoid issues with some supplicant
|
||||
implementations that can change SNonce for each EAP-Key 2/4
|
||||
* added a workaround for EAPOL-Key 4/4 using incorrect type value in
|
||||
WPA2 mode (some deployed stations use WPA type in that message)
|
||||
* added a WPS workaround for mixed mode AP Settings with Windows 7
|
||||
* changed WPS AP PIN disabling mechanism to disable the PIN after 10
|
||||
consecutive failures in addition to using the exponential lockout
|
||||
period
|
||||
* added support for WFA Hotspot 2.0
|
||||
- GAS/ANQP advertisement of network information
|
||||
- disable_dgaf parameter to disable downstream group-addressed
|
||||
forwarding
|
||||
* simplified licensing terms by selecting the BSD license as the only
|
||||
alternative
|
||||
* EAP-SIM: fixed re-authentication not to update pseudonym
|
||||
* EAP-SIM: use Notification round before EAP-Failure
|
||||
* EAP-AKA: added support for AT_COUNTER_TOO_SMALL
|
||||
* EAP-AKA: skip AKA/Identity exchange if EAP identity is recognized
|
||||
* EAP-AKA': fixed identity for MK derivation
|
||||
* EAP-AKA': updated to RFC 5448 (username prefixes changed); note: this
|
||||
breaks interoperability with older versions
|
||||
* EAP-SIM/AKA: allow pseudonym to be used after unknown reauth id
|
||||
* changed ANonce to be a random number instead of Counter-based
|
||||
* added support for canceling WPS operations with hostapd_cli wps_cancel
|
||||
* fixed EAP/WPS to PSK transition on reassociation in cases where
|
||||
deauthentication is missed
|
||||
* hlr_auc_gw enhancements:
|
||||
- a new command line parameter -u can be used to enable updating of
|
||||
SQN in Milenage file
|
||||
- use 5 bit IND for SQN updates
|
||||
- SQLite database can now be used to store Milenage information
|
||||
* EAP-SIM/AKA DB: added optional use of SQLite database for pseudonyms
|
||||
and reauth data
|
||||
* added support for Chargeable-User-Identity (RFC 4372)
|
||||
* added radius_auth_req_attr and radius_acct_req_attr configuration
|
||||
parameters to allow adding/overriding of RADIUS attributes in
|
||||
Access-Request and Accounting-Request packets
|
||||
* added support for RADIUS dynamic authorization server (RFC 5176)
|
||||
* added initial support for WNM operations
|
||||
- BSS max idle period
|
||||
- WNM-Sleep Mode
|
||||
* added new WPS NFC ctrl_iface mechanism
|
||||
- removed obsoleted WPS_OOB command (including support for deprecated
|
||||
UFD config_method)
|
||||
* added FT support for drivers that implement MLME internally
|
||||
* added SA Query support for drivers that implement MLME internally
|
||||
* removed default ACM=1 from AC_VO and AC_VI
|
||||
* changed VENDOR-TEST EAP method to use proper private enterprise number
|
||||
(this will not interoperate with older versions)
|
||||
* added hostapd.conf parameter vendor_elements to allow arbitrary vendor
|
||||
specific elements to be added to the Beacon and Probe Response frames
|
||||
* added support for configuring GCMP cipher for IEEE 802.11ad
|
||||
* added support for 256-bit AES with internal TLS implementation
|
||||
* changed EAPOL transmission to use AC_VO if WMM is active
|
||||
* fixed EAP-TLS/PEAP/TTLS/FAST server to validate TLS Message Length
|
||||
correctly; invalid messages could have caused the hostapd process to
|
||||
terminate before this fix [CVE-2012-4445]
|
||||
* limit number of active wildcard PINs for WPS Registrar to one to avoid
|
||||
confusing behavior with multiple wildcard PINs
|
||||
* added a workaround for WPS PBC session overlap detection to avoid
|
||||
interop issues with deployed station implementations that do not
|
||||
remove active PBC indication from Probe Request frames properly
|
||||
* added support for using SQLite for the eap_user database
|
||||
* added Acct-Session-Id attribute into Access-Request messages
|
||||
* fixed EAPOL frame transmission to non-QoS STAs with nl80211
|
||||
(do not send QoS frames if the STA did not negotiate use of QoS for
|
||||
this association)
|
||||
|
||||
2012-05-10 - v1.0
|
||||
* Add channel selection support in hostapd. See hostapd.conf.
|
||||
* Add support for IEEE 802.11v Time Advertisement mechanism with UTC
|
||||
TSF offset. See hostapd.conf for config info.
|
||||
* Delay STA entry removal until Deauth/Disassoc TX status in AP mode.
|
||||
This allows the driver to use PS buffering of Deauthentication and
|
||||
Disassociation frames when the STA is in power save sleep. Only
|
||||
available with drivers that provide TX status events for Deauth/
|
||||
Disassoc frames (nl80211).
|
||||
* Allow PMKSA caching to be disabled on the Authenticator. See
|
||||
hostap.conf config parameter disable_pmksa_caching.
|
||||
* atheros: Add support for IEEE 802.11w configuration.
|
||||
* bsd: Add support for setting HT values in IFM_MMASK.
|
||||
* Allow client isolation to be configured with ap_isolate. Client
|
||||
isolation can be used to prevent low-level bridging of frames
|
||||
between associated stations in the BSS. By default, this bridging
|
||||
is allowed.
|
||||
* Allow coexistance of HT BSSes with WEP/TKIP BSSes.
|
||||
* Add require_ht config parameter, which can be used to configure
|
||||
hostapd to reject association with any station that does not support
|
||||
HT PHY.
|
||||
* Add support for writing debug log to a file using "-f" option. Also
|
||||
add relog CLI command to re-open the log file.
|
||||
* Add bridge handling for WDS STA interfaces. By default they are
|
||||
added to the configured bridge of the AP interface (if present),
|
||||
but the user can also specify a separate bridge using cli command
|
||||
wds_bridge.
|
||||
* hostapd_cli:
|
||||
- Add wds_bridge command for specifying bridge for WDS STA
|
||||
interfaces.
|
||||
- Add relog command for reopening log file.
|
||||
- Send AP-STA-DISCONNECTED event when an AP disconnects a station
|
||||
due to inactivity.
|
||||
- Add wps_config ctrl_interface command for configuring AP. This
|
||||
command can be used to configure the AP using the internal WPS
|
||||
registrar. It works in the same way as new AP settings received
|
||||
from an ER.
|
||||
- Many WPS/WPS ER commands - see WPS/WPS ER sections for details.
|
||||
- Add command get version, that returns hostapd version string.
|
||||
* WNM: Add BSS Transition Management Request for ESS Disassoc Imminent.
|
||||
Use hostapd_cli ess_disassoc (STA addr) (URL) to send the
|
||||
notification to the STA.
|
||||
* Allow AP mode to disconnect STAs based on low ACK condition (when
|
||||
the data connection is not working properly, e.g., due to the STA
|
||||
going outside the range of the AP). Disabled by default, enable by
|
||||
config option disassoc_low_ack.
|
||||
* Add WPA_IGNORE_CONFIG_ERRORS build option to continue in case of bad
|
||||
config file.
|
||||
* WPS:
|
||||
- Send AP Settings as a wrapped Credential attribute to ctrl_iface
|
||||
in WPS-NEW-AP-SETTINGS.
|
||||
- Dispatch more WPS events through hostapd ctrl_iface.
|
||||
- Add mechanism for indicating non-standard WPS errors.
|
||||
- Change concurrent radio AP to use only one WPS UPnP instance.
|
||||
- Add wps_check_pin command for processing PIN from user input.
|
||||
UIs can use this command to process a PIN entered by a user and to
|
||||
validate the checksum digit (if present).
|
||||
- Add hostap_cli get_config command to display current AP config.
|
||||
- Add new hostapd_cli command, wps_ap_pin, to manage AP PIN at
|
||||
runtime and support dynamic AP PIN management.
|
||||
- Disable AP PIN after 10 consecutive failures. Slow down attacks
|
||||
on failures up to 10.
|
||||
- Allow AP to start in Enrollee mode without AP PIN for probing,
|
||||
to be compatible with Windows 7.
|
||||
- Add Config Error into WPS-FAIL events to provide more info
|
||||
to the user on how to resolve the issue.
|
||||
- When controlling multiple interfaces:
|
||||
- apply WPS commands to all interfaces configured to use WPS
|
||||
- apply WPS config changes to all interfaces that use WPS
|
||||
- when an attack is detected on any interface, disable AP PIN on
|
||||
all interfaces
|
||||
* WPS ER:
|
||||
- Show SetSelectedRegistrar events as ctrl_iface events.
|
||||
- Add special AP Setup Locked mode to allow read only ER.
|
||||
ap_setup_locked=2 can now be used to enable a special mode where
|
||||
WPS ER can learn the current AP settings, but cannot change them.
|
||||
* WPS 2.0: Add support for WPS 2.0 (CONFIG_WPS2)
|
||||
- Add build option CONFIG_WPS_EXTENSIBILITY_TESTING to enable tool
|
||||
for testing protocol extensibility.
|
||||
- Add build option CONFIG_WPS_STRICT to allow disabling of WPS
|
||||
workarounds.
|
||||
- Add support for AuthorizedMACs attribute.
|
||||
* TDLS:
|
||||
- Allow TDLS use or TDLS channel switching in the BSS to be
|
||||
prohibited in the BSS, using config params tdls_prohibit and
|
||||
tdls_prohibit_chan_switch.
|
||||
* EAP server: Add support for configuring fragment size (see
|
||||
fragment_size in hostapd.conf).
|
||||
* wlantest: Add a tool wlantest for IEEE802.11 protocol testing.
|
||||
wlantest can be used to capture frames from a monitor interface
|
||||
for realtime capturing or from pcap files for offline analysis.
|
||||
* Interworking: Support added for 802.11u. Enable in .config with
|
||||
CONFIG_INTERWORKING. See hostapd.conf for config parameters for
|
||||
interworking.
|
||||
* Android: Add build and runtime support for Android hostapd.
|
||||
* Add a new debug message level for excessive information. Use
|
||||
-ddd to enable.
|
||||
* TLS: Add support for tls_disable_time_checks=1 in client mode.
|
||||
* Internal TLS:
|
||||
- Add support for TLS v1.1 (RFC 4346). Enable with build parameter
|
||||
CONFIG_TLSV11.
|
||||
- Add domainComponent parser for X.509 names
|
||||
* Reorder some IEs to get closer to IEEE 802.11 standard. Move
|
||||
WMM into end of Beacon, Probe Resp and (Re)Assoc Resp frames.
|
||||
Move HT IEs to be later in (Re)Assoc Resp.
|
||||
* Many bugfixes.
|
||||
|
||||
2010-04-18 - v0.7.2
|
||||
* fix WPS internal Registrar use when an external Registrar is also
|
||||
@ -98,7 +284,7 @@ ChangeLog for hostapd
|
||||
* updated management frame protection to use IEEE Std 802.11w-2009
|
||||
* fixed number of small WPS issues and added workarounds to
|
||||
interoperate with common deployed broken implementations
|
||||
* added some IEEE 802.11n co-existance rules to disable 40 MHz channels
|
||||
* added some IEEE 802.11n co-existence rules to disable 40 MHz channels
|
||||
or modify primary/secondary channels if needed based on neighboring
|
||||
networks
|
||||
* added support for NFC out-of-band mechanism with WPS
|
||||
|
@ -43,6 +43,7 @@ OBJS += ../src/ap/utils.o
|
||||
OBJS += ../src/ap/authsrv.o
|
||||
OBJS += ../src/ap/ieee802_1x.o
|
||||
OBJS += ../src/ap/ap_config.o
|
||||
OBJS += ../src/ap/eap_user_db.o
|
||||
OBJS += ../src/ap/ieee802_11_auth.o
|
||||
OBJS += ../src/ap/sta_info.o
|
||||
OBJS += ../src/ap/wpa_auth.o
|
||||
@ -51,6 +52,10 @@ OBJS += ../src/ap/ap_mlme.o
|
||||
OBJS += ../src/ap/wpa_auth_ie.o
|
||||
OBJS += ../src/ap/preauth_auth.o
|
||||
OBJS += ../src/ap/pmksa_cache_auth.o
|
||||
OBJS += ../src/ap/ieee802_11_shared.o
|
||||
OBJS += ../src/ap/beacon.o
|
||||
|
||||
OBJS_c = hostapd_cli.o ../src/common/wpa_ctrl.o ../src/utils/os_$(CONFIG_OS).o
|
||||
|
||||
NEED_RC4=y
|
||||
NEED_AES=y
|
||||
@ -63,18 +68,25 @@ CFLAGS += -DHOSTAPD
|
||||
ifdef CONFIG_WPA_TRACE
|
||||
CFLAGS += -DWPA_TRACE
|
||||
OBJS += ../src/utils/trace.o
|
||||
HOBJS += ../src/utils/trace.o
|
||||
LDFLAGS += -rdynamic
|
||||
CFLAGS += -funwind-tables
|
||||
ifdef CONFIG_WPA_TRACE_BFD
|
||||
CFLAGS += -DWPA_TRACE_BFD
|
||||
LIBS += -lbfd
|
||||
LIBS_c += -lbfd
|
||||
LIBS_h += -lbfd
|
||||
endif
|
||||
endif
|
||||
|
||||
OBJS += ../src/utils/eloop.o
|
||||
ifndef CONFIG_ELOOP
|
||||
CONFIG_ELOOP=eloop
|
||||
endif
|
||||
OBJS += ../src/utils/$(CONFIG_ELOOP).o
|
||||
OBJS_c += ../src/utils/$(CONFIG_ELOOP).o
|
||||
OBJS += ../src/utils/common.o
|
||||
OBJS += ../src/utils/wpa_debug.o
|
||||
OBJS_c += ../src/utils/wpa_debug.o
|
||||
OBJS += ../src/utils/wpabuf.o
|
||||
OBJS += ../src/utils/os_$(CONFIG_OS).o
|
||||
OBJS += ../src/utils/ip_addr.o
|
||||
@ -99,6 +111,7 @@ CONFIG_NO_ACCOUNTING=y
|
||||
else
|
||||
OBJS += ../src/radius/radius.o
|
||||
OBJS += ../src/radius/radius_client.o
|
||||
OBJS += ../src/radius/radius_das.o
|
||||
endif
|
||||
|
||||
ifdef CONFIG_NO_ACCOUNTING
|
||||
@ -111,6 +124,12 @@ ifdef CONFIG_NO_VLAN
|
||||
CFLAGS += -DCONFIG_NO_VLAN
|
||||
else
|
||||
OBJS += ../src/ap/vlan_init.o
|
||||
ifdef CONFIG_VLAN_NETLINK
|
||||
ifdef CONFIG_FULL_DYNAMIC_VLAN
|
||||
OBJS += ../src/ap/vlan_util.o
|
||||
endif
|
||||
CFLAGS += -DCONFIG_VLAN_NETLINK
|
||||
endif
|
||||
endif
|
||||
|
||||
ifdef CONFIG_NO_CTRL_IFACE
|
||||
@ -153,10 +172,23 @@ NEED_AES_OMAC1=y
|
||||
NEED_AES_UNWRAP=y
|
||||
endif
|
||||
|
||||
ifdef CONFIG_SAE
|
||||
CFLAGS += -DCONFIG_SAE
|
||||
endif
|
||||
|
||||
ifdef CONFIG_WNM
|
||||
CFLAGS += -DCONFIG_WNM
|
||||
OBJS += ../src/ap/wnm_ap.o
|
||||
endif
|
||||
|
||||
ifdef CONFIG_IEEE80211N
|
||||
CFLAGS += -DCONFIG_IEEE80211N
|
||||
endif
|
||||
|
||||
ifdef CONFIG_IEEE80211AC
|
||||
CFLAGS += -DCONFIG_IEEE80211AC
|
||||
endif
|
||||
|
||||
include ../src/drivers/drivers.mak
|
||||
OBJS += $(DRV_AP_OBJS)
|
||||
CFLAGS += $(DRV_AP_CFLAGS)
|
||||
@ -192,6 +224,14 @@ OBJS += ../src/eap_server/eap_server_tls.o
|
||||
TLS_FUNCS=y
|
||||
endif
|
||||
|
||||
ifdef CONFIG_EAP_UNAUTH_TLS
|
||||
CFLAGS += -DEAP_SERVER_UNAUTH_TLS
|
||||
ifndef CONFIG_EAP_TLS
|
||||
OBJS += ../src/eap_server/eap_server_tls.o
|
||||
TLS_FUNCS=y
|
||||
endif
|
||||
endif
|
||||
|
||||
ifdef CONFIG_EAP_PEAP
|
||||
CFLAGS += -DEAP_SERVER_PEAP
|
||||
OBJS += ../src/eap_server/eap_server_peap.o
|
||||
@ -274,6 +314,12 @@ NEED_SHA256=y
|
||||
NEED_AES_OMAC1=y
|
||||
endif
|
||||
|
||||
ifdef CONFIG_EAP_PWD
|
||||
CFLAGS += -DEAP_SERVER_PWD
|
||||
OBJS += ../src/eap_server/eap_server_pwd.o ../src/eap_common/eap_pwd_common.o
|
||||
NEED_SHA256=y
|
||||
endif
|
||||
|
||||
ifdef CONFIG_EAP_VENDOR_TEST
|
||||
CFLAGS += -DEAP_SERVER_VENDOR_TEST
|
||||
OBJS += ../src/eap_server/eap_server_vendor_test.o
|
||||
@ -289,6 +335,10 @@ NEED_AES_UNWRAP=y
|
||||
endif
|
||||
|
||||
ifdef CONFIG_WPS
|
||||
ifdef CONFIG_WPS2
|
||||
CFLAGS += -DCONFIG_WPS2
|
||||
endif
|
||||
|
||||
CFLAGS += -DCONFIG_WPS -DEAP_SERVER_WSC
|
||||
OBJS += ../src/utils/uuid.o
|
||||
OBJS += ../src/ap/wps_hostapd.o
|
||||
@ -308,25 +358,10 @@ NEED_AES_CBC=y
|
||||
NEED_MODEXP=y
|
||||
CONFIG_EAP=y
|
||||
|
||||
ifdef CONFIG_WPS_UFD
|
||||
CFLAGS += -DCONFIG_WPS_UFD
|
||||
OBJS += ../src/wps/wps_ufd.o
|
||||
NEED_WPS_OOB=y
|
||||
endif
|
||||
|
||||
ifdef CONFIG_WPS_NFC
|
||||
CFLAGS += -DCONFIG_WPS_NFC
|
||||
OBJS += ../src/wps/ndef.o
|
||||
OBJS += ../src/wps/wps_nfc.o
|
||||
NEED_WPS_OOB=y
|
||||
ifdef CONFIG_WPS_NFC_PN531
|
||||
PN531_PATH ?= /usr/local/src/nfc
|
||||
CFLAGS += -DCONFIG_WPS_NFC_PN531
|
||||
CFLAGS += -I${PN531_PATH}/inc
|
||||
OBJS += ../src/wps/wps_nfc_pn531.o
|
||||
LIBS += ${PN531_PATH}/lib/wpsnfc.dll
|
||||
LIBS += ${PN531_PATH}/lib/libnfc_mapping_pn53x.dll
|
||||
endif
|
||||
endif
|
||||
|
||||
ifdef NEED_WPS_OOB
|
||||
@ -346,6 +381,15 @@ OBJS += ../src/wps/http_client.o
|
||||
OBJS += ../src/wps/http_server.o
|
||||
endif
|
||||
|
||||
ifdef CONFIG_WPS_STRICT
|
||||
CFLAGS += -DCONFIG_WPS_STRICT
|
||||
OBJS += ../src/wps/wps_validate.o
|
||||
endif
|
||||
|
||||
ifdef CONFIG_WPS_TESTING
|
||||
CFLAGS += -DCONFIG_WPS_TESTING
|
||||
endif
|
||||
|
||||
endif
|
||||
|
||||
ifdef CONFIG_EAP_IKEV2
|
||||
@ -406,6 +450,15 @@ ifndef CONFIG_TLS
|
||||
CONFIG_TLS=openssl
|
||||
endif
|
||||
|
||||
ifdef CONFIG_TLSV11
|
||||
CFLAGS += -DCONFIG_TLSV11
|
||||
endif
|
||||
|
||||
ifdef CONFIG_TLSV12
|
||||
CFLAGS += -DCONFIG_TLSV12
|
||||
NEED_SHA256=y
|
||||
endif
|
||||
|
||||
ifeq ($(CONFIG_TLS), openssl)
|
||||
ifdef TLS_FUNCS
|
||||
OBJS += ../src/crypto/tls_openssl.o
|
||||
@ -424,10 +477,6 @@ ifeq ($(CONFIG_TLS), gnutls)
|
||||
ifdef TLS_FUNCS
|
||||
OBJS += ../src/crypto/tls_gnutls.o
|
||||
LIBS += -lgnutls -lgpg-error
|
||||
ifdef CONFIG_GNUTLS_EXTRA
|
||||
CFLAGS += -DCONFIG_GNUTLS_EXTRA
|
||||
LIBS += -lgnutls-extra
|
||||
endif
|
||||
endif
|
||||
OBJS += ../src/crypto/crypto_gnutls.o
|
||||
HOBJS += ../src/crypto/crypto_gnutls.o
|
||||
@ -489,6 +538,9 @@ OBJS += ../src/tls/pkcs8.o
|
||||
NEED_SHA256=y
|
||||
NEED_BASE64=y
|
||||
NEED_TLS_PRF=y
|
||||
ifdef CONFIG_TLSV12
|
||||
NEED_TLS_PRF_SHA256=y
|
||||
endif
|
||||
NEED_MODEXP=y
|
||||
NEED_CIPHER=y
|
||||
CFLAGS += -DCONFIG_TLS_INTERNAL
|
||||
@ -602,14 +654,19 @@ OBJS += $(AESOBJS)
|
||||
endif
|
||||
|
||||
ifdef NEED_SHA1
|
||||
ifneq ($(CONFIG_TLS), openssl)
|
||||
SHA1OBJS += ../src/crypto/sha1.o
|
||||
endif
|
||||
SHA1OBJS += ../src/crypto/sha1-prf.o
|
||||
ifdef CONFIG_INTERNAL_SHA1
|
||||
SHA1OBJS += ../src/crypto/sha1-internal.o
|
||||
ifdef NEED_FIPS186_2_PRF
|
||||
SHA1OBJS += ../src/crypto/fips_prf_internal.o
|
||||
endif
|
||||
endif
|
||||
ifneq ($(CONFIG_TLS), openssl)
|
||||
SHA1OBJS += ../src/crypto/sha1-pbkdf2.o
|
||||
endif
|
||||
ifdef NEED_T_PRF
|
||||
SHA1OBJS += ../src/crypto/sha1-tprf.o
|
||||
endif
|
||||
@ -625,6 +682,7 @@ endif
|
||||
ifdef NEED_MD5
|
||||
ifdef CONFIG_INTERNAL_MD5
|
||||
OBJS += ../src/crypto/md5-internal.o
|
||||
HOBJS += ../src/crypto/md5-internal.o
|
||||
endif
|
||||
endif
|
||||
|
||||
@ -647,10 +705,17 @@ endif
|
||||
endif
|
||||
|
||||
ifdef NEED_SHA256
|
||||
CFLAGS += -DCONFIG_SHA256
|
||||
ifneq ($(CONFIG_TLS), openssl)
|
||||
OBJS += ../src/crypto/sha256.o
|
||||
endif
|
||||
OBJS += ../src/crypto/sha256-prf.o
|
||||
ifdef CONFIG_INTERNAL_SHA256
|
||||
OBJS += ../src/crypto/sha256-internal.o
|
||||
endif
|
||||
ifdef NEED_TLS_PRF_SHA256
|
||||
OBJS += ../src/crypto/sha256-tlsprf.o
|
||||
endif
|
||||
endif
|
||||
|
||||
ifdef NEED_DH_GROUPS
|
||||
@ -665,6 +730,16 @@ OBJS += ../src/crypto/dh_group5.o
|
||||
endif
|
||||
endif
|
||||
|
||||
ifdef CONFIG_NO_RANDOM_POOL
|
||||
CFLAGS += -DCONFIG_NO_RANDOM_POOL
|
||||
else
|
||||
OBJS += ../src/crypto/random.o
|
||||
HOBJS += ../src/crypto/random.o
|
||||
HOBJS += ../src/utils/eloop.o
|
||||
HOBJS += $(SHA1OBJS)
|
||||
HOBJS += ../src/crypto/md5.o
|
||||
endif
|
||||
|
||||
ifdef CONFIG_RADIUS_SERVER
|
||||
CFLAGS += -DRADIUS_SERVER
|
||||
OBJS += ../src/radius/radius_server.o
|
||||
@ -689,7 +764,6 @@ OBJS += ../src/utils/base64.o
|
||||
endif
|
||||
|
||||
ifdef NEED_AP_MLME
|
||||
OBJS += ../src/ap/beacon.o
|
||||
OBJS += ../src/ap/wmm.o
|
||||
OBJS += ../src/ap/ap_list.o
|
||||
OBJS += ../src/ap/ieee802_11.o
|
||||
@ -700,10 +774,49 @@ ifdef CONFIG_IEEE80211N
|
||||
OBJS += ../src/ap/ieee802_11_ht.o
|
||||
endif
|
||||
|
||||
ifdef CONFIG_IEEE80211AC
|
||||
OBJS += ../src/ap/ieee802_11_vht.o
|
||||
endif
|
||||
|
||||
ifdef CONFIG_P2P_MANAGER
|
||||
CFLAGS += -DCONFIG_P2P_MANAGER
|
||||
OBJS += ../src/ap/p2p_hostapd.o
|
||||
endif
|
||||
|
||||
ifdef CONFIG_HS20
|
||||
CFLAGS += -DCONFIG_HS20
|
||||
OBJS += ../src/ap/hs20.o
|
||||
CONFIG_INTERWORKING=y
|
||||
endif
|
||||
|
||||
ifdef CONFIG_INTERWORKING
|
||||
CFLAGS += -DCONFIG_INTERWORKING
|
||||
OBJS += ../src/common/gas.o
|
||||
OBJS += ../src/ap/gas_serv.o
|
||||
endif
|
||||
|
||||
OBJS += ../src/drivers/driver_common.o
|
||||
|
||||
ifdef CONFIG_WPA_CLI_EDIT
|
||||
OBJS_c += ../src/utils/edit.o
|
||||
else
|
||||
OBJS_c += ../src/utils/edit_simple.o
|
||||
endif
|
||||
|
||||
ifdef CONFIG_NO_STDOUT_DEBUG
|
||||
CFLAGS += -DCONFIG_NO_STDOUT_DEBUG
|
||||
endif
|
||||
|
||||
ifdef CONFIG_DEBUG_FILE
|
||||
CFLAGS += -DCONFIG_DEBUG_FILE
|
||||
endif
|
||||
|
||||
ifdef CONFIG_SQLITE
|
||||
CFLAGS += -DCONFIG_SQLITE
|
||||
LIBS += -lsqlite3
|
||||
LIBS_h += -lsqlite3
|
||||
endif
|
||||
|
||||
ALL=hostapd hostapd_cli
|
||||
|
||||
all: verify_config $(ALL)
|
||||
@ -729,7 +842,8 @@ verify_config:
|
||||
fi
|
||||
|
||||
install: all
|
||||
for i in $(ALL); do cp -f $$i /usr/local/bin/$$i; done
|
||||
mkdir -p $(DESTDIR)/usr/local/bin
|
||||
for i in $(ALL); do cp -f $$i $(DESTDIR)/usr/local/bin/$$i; done
|
||||
|
||||
../src/drivers/build.hostapd:
|
||||
@if [ -f ../src/drivers/build.wpa_supplicant ]; then \
|
||||
@ -740,15 +854,15 @@ install: all
|
||||
BCHECK=../src/drivers/build.hostapd
|
||||
|
||||
hostapd: $(BCHECK) $(OBJS)
|
||||
$(CC) $(LDFLAGS) -o hostapd $(OBJS) $(LIBS)
|
||||
$(Q)$(CC) $(LDFLAGS) -o hostapd $(OBJS) $(LIBS)
|
||||
@$(E) " LD " $@
|
||||
|
||||
OBJS_c = hostapd_cli.o ../src/common/wpa_ctrl.o ../src/utils/os_$(CONFIG_OS).o
|
||||
ifdef CONFIG_WPA_TRACE
|
||||
OBJS_c += ../src/utils/trace.o
|
||||
OBJS_c += ../src/utils/wpa_debug.o
|
||||
endif
|
||||
hostapd_cli: $(OBJS_c)
|
||||
$(CC) $(LDFLAGS) -o hostapd_cli $(OBJS_c) $(LIBS_c)
|
||||
$(Q)$(CC) $(LDFLAGS) -o hostapd_cli $(OBJS_c) $(LIBS_c)
|
||||
@$(E) " LD " $@
|
||||
|
||||
NOBJS = nt_password_hash.o ../src/crypto/ms_funcs.o $(SHA1OBJS) ../src/crypto/md5.o
|
||||
ifdef NEED_RC4
|
||||
@ -778,10 +892,12 @@ HOBJS += ../src/crypto/aes-internal-enc.o
|
||||
endif
|
||||
|
||||
nt_password_hash: $(NOBJS)
|
||||
$(CC) $(LDFLAGS) -o nt_password_hash $(NOBJS) $(LIBS_n)
|
||||
$(Q)$(CC) $(LDFLAGS) -o nt_password_hash $(NOBJS) $(LIBS_n)
|
||||
@$(E) " LD " $@
|
||||
|
||||
hlr_auc_gw: $(HOBJS)
|
||||
$(CC) $(LDFLAGS) -o hlr_auc_gw $(HOBJS) $(LIBS_h)
|
||||
$(Q)$(CC) $(LDFLAGS) -o hlr_auc_gw $(HOBJS) $(LIBS_h)
|
||||
@$(E) " LD " $@
|
||||
|
||||
clean:
|
||||
$(MAKE) -C ../src clean
|
||||
|
@ -2,37 +2,22 @@ hostapd - user space IEEE 802.11 AP and IEEE 802.1X/WPA/WPA2/EAP
|
||||
Authenticator and RADIUS authentication server
|
||||
================================================================
|
||||
|
||||
Copyright (c) 2002-2010, Jouni Malinen <j@w1.fi> and contributors
|
||||
Copyright (c) 2002-2012, Jouni Malinen <j@w1.fi> and contributors
|
||||
All Rights Reserved.
|
||||
|
||||
This program is dual-licensed under both the GPL version 2 and BSD
|
||||
license. Either license may be used at your option.
|
||||
This program is licensed under the BSD license (the one with
|
||||
advertisement clause removed).
|
||||
|
||||
If you are submitting changes to the project, please see CONTRIBUTIONS
|
||||
file for more instructions.
|
||||
|
||||
|
||||
|
||||
License
|
||||
-------
|
||||
|
||||
GPL v2:
|
||||
|
||||
This program is free software; you can redistribute it and/or modify
|
||||
it under the terms of the GNU General Public License version 2 as
|
||||
published by the Free Software Foundation.
|
||||
|
||||
This program is distributed in the hope that it will be useful,
|
||||
but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||
GNU General Public License for more details.
|
||||
|
||||
You should have received a copy of the GNU General Public License
|
||||
along with this program; if not, write to the Free Software
|
||||
Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA
|
||||
|
||||
(this copy of the license is in COPYING file)
|
||||
|
||||
|
||||
Alternatively, this software may be distributed, used, and modified
|
||||
under the terms of BSD license:
|
||||
This software may be distributed, used, and modified under the terms of
|
||||
BSD license:
|
||||
|
||||
Redistribution and use in source and binary forms, with or without
|
||||
modification, are permitted provided that the following conditions are
|
||||
|
@ -63,8 +63,13 @@ includes WPS support and uses madwifi driver interface:
|
||||
CONFIG_DRIVER_MADWIFI=y
|
||||
CFLAGS += -I/usr/src/madwifi-0.9.3
|
||||
CONFIG_WPS=y
|
||||
CONFIG_WPS2=y
|
||||
CONFIG_WPS_UPNP=y
|
||||
|
||||
Following parameter can be used to enable support for NFC config method:
|
||||
|
||||
CONFIG_WPS_NFC=y
|
||||
|
||||
|
||||
Following section shows an example runtime configuration
|
||||
(hostapd.conf) that enables WPS:
|
||||
@ -119,6 +124,13 @@ pushbutton event (for PBC) to allow a new WPS Enrollee to join the
|
||||
network. hostapd uses the control interface as an input channel for
|
||||
these events.
|
||||
|
||||
The PIN value used in the commands must be processed by an UI to
|
||||
remove non-digit characters and potentially, to verify the checksum
|
||||
digit. "hostapd_cli wps_check_pin <PIN>" can be used to do such
|
||||
processing. It returns FAIL if the PIN is invalid, or FAIL-CHECKSUM if
|
||||
the checksum digit is incorrect, or the processed PIN (non-digit
|
||||
characters removed) if the PIN is valid.
|
||||
|
||||
When a client device (WPS Enrollee) connects to hostapd (WPS
|
||||
Registrar) in order to start PIN mode negotiation for WPS, an
|
||||
identifier (Enrollee UUID) is sent. hostapd will need to be configured
|
||||
@ -171,10 +183,17 @@ hostapd_cli wps_pin any 12345670
|
||||
|
||||
To reduce likelihood of PIN being used with other devices or of
|
||||
forgetting an active PIN available for potential attackers, expiration
|
||||
time can be set for the new PIN:
|
||||
time in seconds can be set for the new PIN (value 0 indicates no
|
||||
expiration):
|
||||
|
||||
hostapd_cli wps_pin any 12345670 300
|
||||
|
||||
If the MAC address of the enrollee is known, it should be configured
|
||||
to allow the AP to advertise list of authorized enrollees:
|
||||
|
||||
hostapd_cli wps_pin 53b63a98-d29e-4457-a2ed-094d7e6a669c \
|
||||
12345670 300 00:11:22:33:44:55
|
||||
|
||||
|
||||
After this, the Enrollee can connect to the AP again and complete WPS
|
||||
negotiation. At that point, a new, random WPA PSK is generated for the
|
||||
@ -221,6 +240,17 @@ hostapd_cli wps_ap_pin set <PIN> [timeout]
|
||||
- if the optional timeout parameter is given, the AP PIN will be enabled
|
||||
for the specified number of seconds
|
||||
|
||||
hostapd_cli get_config
|
||||
- display the current configuration
|
||||
|
||||
hostapd_cli wps_config <new SSID> <auth> <encr> <new key>
|
||||
examples:
|
||||
hostapd_cli wps_config testing WPA2PSK CCMP 12345678
|
||||
hostapd_cli wps_config "no security" OPEN NONE ""
|
||||
|
||||
<auth> must be one of the following: OPEN WPAPSK WPA2PSK
|
||||
<encr> must be one of the following: NONE WEP TKIP CCMP
|
||||
|
||||
|
||||
Credential generation and configuration changes
|
||||
-----------------------------------------------
|
||||
@ -251,7 +281,7 @@ WPS-REG-SUCCESS <Enrollee MAC address <UUID-E>
|
||||
For example:
|
||||
<2>WPS-REG-SUCCESS 02:66:a0:ee:17:27 2b7093f1-d6fb-5108-adbb-bea66bb87333
|
||||
|
||||
This can be used to tricker change from unconfigured to configured
|
||||
This can be used to trigger change from unconfigured to configured
|
||||
state (random configuration based on the first successful WPS
|
||||
registration). In addition, this can be used to update AP UI about the
|
||||
status of WPS registration progress.
|
||||
@ -263,3 +293,48 @@ For example:
|
||||
|
||||
This can be used to update the externally stored AP configuration and
|
||||
then update hostapd configuration (followed by restarting of hostapd).
|
||||
|
||||
|
||||
WPS with NFC
|
||||
------------
|
||||
|
||||
WPS can be used with NFC-based configuration method. An NFC tag
|
||||
containing a password token from the Enrollee can be used to
|
||||
authenticate the connection instead of the PIN. In addition, an NFC tag
|
||||
with a configuration token can be used to transfer AP settings without
|
||||
going through the WPS protocol.
|
||||
|
||||
When the AP acts as an Enrollee, a local NFC tag with a password token
|
||||
can be used by touching the NFC interface of an external Registrar. The
|
||||
wps_nfc_token command is used to manage use of the NFC password token
|
||||
from the AP. "wps_nfc_token enable" enables the use of the AP's NFC
|
||||
password token (in place of AP PIN) and "wps_nfc_token disable" disables
|
||||
the NFC password token.
|
||||
|
||||
The NFC password token that is either pre-configured in the
|
||||
configuration file (wps_nfc_dev_pw_id, wps_nfc_dh_pubkey,
|
||||
wps_nfc_dh_privkey, wps_nfc_dev_pw) or generated dynamically with
|
||||
"wps_nfc_token <WPS|NDEF>" command. The nfc_pw_token tool from
|
||||
wpa_supplicant can be used to generate NFC password tokens during
|
||||
manufacturing (each AP needs to have its own random keys).
|
||||
|
||||
The "wps_nfc_config_token <WPS/NDEF>" command can be used to build an
|
||||
NFC configuration token. The output value from this command is a hexdump
|
||||
of the current AP configuration (WPS parameter requests this to include
|
||||
only the WPS attributes; NDEF parameter requests additional NDEF
|
||||
encapsulation to be included). This data needs to be written to an NFC
|
||||
tag with an external program. Once written, the NFC configuration token
|
||||
can be used to touch an NFC interface on a station to provision the
|
||||
credentials needed to access the network.
|
||||
|
||||
When the NFC device on the AP reads an NFC tag with a MIME media type
|
||||
"application/vnd.wfa.wsc", the NDEF message payload (with or without
|
||||
NDEF encapsulation) can be delivered to hostapd using the
|
||||
following hostapd_cli command:
|
||||
|
||||
wps_nfc_tag_read <hexdump of payload>
|
||||
|
||||
If the NFC tag contains a password token, the token is added to the
|
||||
internal Registrar. This allows station Enrollee from which the password
|
||||
token was received to run through WPS protocol to provision the
|
||||
credential.
|
||||
|
File diff suppressed because it is too large
Load Diff
@ -2,19 +2,16 @@
|
||||
* hostapd / Configuration file parser
|
||||
* Copyright (c) 2003-2009, Jouni Malinen <j@w1.fi>
|
||||
*
|
||||
* This program is free software; you can redistribute it and/or modify
|
||||
* it under the terms of the GNU General Public License version 2 as
|
||||
* published by the Free Software Foundation.
|
||||
*
|
||||
* Alternatively, this software may be distributed under the terms of BSD
|
||||
* license.
|
||||
*
|
||||
* See README and COPYING for more details.
|
||||
* This software may be distributed under the terms of the BSD license.
|
||||
* See README for more details.
|
||||
*/
|
||||
|
||||
#ifndef CONFIG_FILE_H
|
||||
#define CONFIG_FILE_H
|
||||
|
||||
struct hostapd_config * hostapd_config_read(const char *fname);
|
||||
int hostapd_set_iface(struct hostapd_config *conf,
|
||||
struct hostapd_bss_config *bss, char *field,
|
||||
char *value);
|
||||
|
||||
#endif /* CONFIG_FILE_H */
|
||||
|
File diff suppressed because it is too large
Load Diff
@ -2,14 +2,8 @@
|
||||
* hostapd / UNIX domain socket -based control interface
|
||||
* Copyright (c) 2004, Jouni Malinen <j@w1.fi>
|
||||
*
|
||||
* This program is free software; you can redistribute it and/or modify
|
||||
* it under the terms of the GNU General Public License version 2 as
|
||||
* published by the Free Software Foundation.
|
||||
*
|
||||
* Alternatively, this software may be distributed under the terms of BSD
|
||||
* license.
|
||||
*
|
||||
* See README and COPYING for more details.
|
||||
* This software may be distributed under the terms of the BSD license.
|
||||
* See README for more details.
|
||||
*/
|
||||
|
||||
#ifndef CTRL_IFACE_H
|
||||
@ -18,6 +12,8 @@
|
||||
#ifndef CONFIG_NO_CTRL_IFACE
|
||||
int hostapd_ctrl_iface_init(struct hostapd_data *hapd);
|
||||
void hostapd_ctrl_iface_deinit(struct hostapd_data *hapd);
|
||||
int hostapd_global_ctrl_iface_init(struct hapd_interfaces *interface);
|
||||
void hostapd_global_ctrl_iface_deinit(struct hapd_interfaces *interface);
|
||||
#else /* CONFIG_NO_CTRL_IFACE */
|
||||
static inline int hostapd_ctrl_iface_init(struct hostapd_data *hapd)
|
||||
{
|
||||
@ -27,6 +23,17 @@ static inline int hostapd_ctrl_iface_init(struct hostapd_data *hapd)
|
||||
static inline void hostapd_ctrl_iface_deinit(struct hostapd_data *hapd)
|
||||
{
|
||||
}
|
||||
|
||||
static inline int
|
||||
hostapd_global_ctrl_iface_init(struct hapd_interfaces *interface)
|
||||
{
|
||||
return 0;
|
||||
}
|
||||
|
||||
static inline void
|
||||
hostapd_global_ctrl_iface_deinit(struct hapd_interfaces *interface)
|
||||
{
|
||||
}
|
||||
#endif /* CONFIG_NO_CTRL_IFACE */
|
||||
|
||||
#endif /* CTRL_IFACE_H */
|
||||
|
@ -20,13 +20,7 @@ CONFIG_DRIVER_HOSTAP=y
|
||||
#CFLAGS += -I../../madwifi # change to the madwifi source directory
|
||||
|
||||
# Driver interface for drivers using the nl80211 kernel interface
|
||||
#CONFIG_DRIVER_NL80211=y
|
||||
# driver_nl80211.c requires a rather new libnl (version 1.1) which may not be
|
||||
# shipped with your distribution yet. If that is the case, you need to build
|
||||
# newer libnl version and point the hostapd build to use it.
|
||||
#LIBNL=/usr/src/libnl
|
||||
#CFLAGS += -I$(LIBNL)/include
|
||||
#LIBS += -L$(LIBNL)/lib
|
||||
CONFIG_DRIVER_NL80211=y
|
||||
|
||||
# Driver interface for FreeBSD net80211 layer (e.g., Atheros driver)
|
||||
#CONFIG_DRIVER_BSD=y
|
||||
@ -90,6 +84,9 @@ CONFIG_EAP_TTLS=y
|
||||
# EAP-PSK for the integrated EAP server (this is _not_ needed for WPA-PSK)
|
||||
#CONFIG_EAP_PSK=y
|
||||
|
||||
# EAP-pwd for the integrated EAP server (secure authentication with a password)
|
||||
#CONFIG_EAP_PWD=y
|
||||
|
||||
# EAP-SAKE for the integrated EAP server
|
||||
#CONFIG_EAP_SAKE=y
|
||||
|
||||
@ -107,8 +104,12 @@ CONFIG_EAP_TTLS=y
|
||||
|
||||
# Wi-Fi Protected Setup (WPS)
|
||||
#CONFIG_WPS=y
|
||||
# Enable WSC 2.0 support
|
||||
#CONFIG_WPS2=y
|
||||
# Enable UPnP support for external WPS Registrars
|
||||
#CONFIG_WPS_UPNP=y
|
||||
# Enable WPS support with NFC config method
|
||||
#CONFIG_WPS_NFC=y
|
||||
|
||||
# EAP-IKEv2
|
||||
#CONFIG_EAP_IKEV2=y
|
||||
@ -137,11 +138,22 @@ CONFIG_IPV6=y
|
||||
# IEEE 802.11n (High Throughput) support
|
||||
#CONFIG_IEEE80211N=y
|
||||
|
||||
# Wireless Network Management (IEEE Std 802.11v-2011)
|
||||
# Note: This is experimental and not complete implementation.
|
||||
#CONFIG_WNM=y
|
||||
|
||||
# IEEE 802.11ac (Very High Throughput) support
|
||||
#CONFIG_IEEE80211AC=y
|
||||
|
||||
# Remove debugging code that is printing out debug messages to stdout.
|
||||
# This can be used to reduce the size of the hostapd considerably if debugging
|
||||
# code is not needed.
|
||||
#CONFIG_NO_STDOUT_DEBUG=y
|
||||
|
||||
# Add support for writing debug log to a file: -f /tmp/hostapd.log
|
||||
# Disabled by default.
|
||||
#CONFIG_DEBUG_FILE=y
|
||||
|
||||
# Remove support for RADIUS accounting
|
||||
#CONFIG_NO_ACCOUNTING=y
|
||||
|
||||
@ -151,6 +163,14 @@ CONFIG_IPV6=y
|
||||
# Remove support for VLANs
|
||||
#CONFIG_NO_VLAN=y
|
||||
|
||||
# Enable support for fully dynamic VLANs. This enables hostapd to
|
||||
# automatically create bridge and VLAN interfaces if necessary.
|
||||
#CONFIG_FULL_DYNAMIC_VLAN=y
|
||||
|
||||
# Use netlink-based kernel API for VLAN operations instead of ioctl()
|
||||
# Note: This requires libnl 3.1 or newer.
|
||||
#CONFIG_VLAN_NETLINK=y
|
||||
|
||||
# Remove support for dumping state into a file on SIGUSR1 signal
|
||||
# This can be used to reduce binary size at the cost of disabling a debugging
|
||||
# option.
|
||||
@ -173,3 +193,77 @@ CONFIG_IPV6=y
|
||||
#LIBS += -lbfd -liberty -lz
|
||||
#LIBS_p += -lbfd -liberty -lz
|
||||
#LIBS_c += -lbfd -liberty -lz
|
||||
|
||||
# hostapd depends on strong random number generation being available from the
|
||||
# operating system. os_get_random() function is used to fetch random data when
|
||||
# needed, e.g., for key generation. On Linux and BSD systems, this works by
|
||||
# reading /dev/urandom. It should be noted that the OS entropy pool needs to be
|
||||
# properly initialized before hostapd is started. This is important especially
|
||||
# on embedded devices that do not have a hardware random number generator and
|
||||
# may by default start up with minimal entropy available for random number
|
||||
# generation.
|
||||
#
|
||||
# As a safety net, hostapd is by default trying to internally collect
|
||||
# additional entropy for generating random data to mix in with the data
|
||||
# fetched from the OS. This by itself is not considered to be very strong, but
|
||||
# it may help in cases where the system pool is not initialized properly.
|
||||
# However, it is very strongly recommended that the system pool is initialized
|
||||
# with enough entropy either by using hardware assisted random number
|
||||
# generator or by storing state over device reboots.
|
||||
#
|
||||
# hostapd can be configured to maintain its own entropy store over restarts to
|
||||
# enhance random number generation. This is not perfect, but it is much more
|
||||
# secure than using the same sequence of random numbers after every reboot.
|
||||
# This can be enabled with -e<entropy file> command line option. The specified
|
||||
# file needs to be readable and writable by hostapd.
|
||||
#
|
||||
# If the os_get_random() is known to provide strong random data (e.g., on
|
||||
# Linux/BSD, the board in question is known to have reliable source of random
|
||||
# data from /dev/urandom), the internal hostapd random pool can be disabled.
|
||||
# This will save some in binary size and CPU use. However, this should only be
|
||||
# considered for builds that are known to be used on devices that meet the
|
||||
# requirements described above.
|
||||
#CONFIG_NO_RANDOM_POOL=y
|
||||
|
||||
# Select TLS implementation
|
||||
# openssl = OpenSSL (default)
|
||||
# gnutls = GnuTLS
|
||||
# internal = Internal TLSv1 implementation (experimental)
|
||||
# none = Empty template
|
||||
#CONFIG_TLS=openssl
|
||||
|
||||
# TLS-based EAP methods require at least TLS v1.0. Newer version of TLS (v1.1)
|
||||
# can be enabled to get a stronger construction of messages when block ciphers
|
||||
# are used.
|
||||
#CONFIG_TLSV11=y
|
||||
|
||||
# TLS-based EAP methods require at least TLS v1.0. Newer version of TLS (v1.2)
|
||||
# can be enabled to enable use of stronger crypto algorithms.
|
||||
#CONFIG_TLSV12=y
|
||||
|
||||
# If CONFIG_TLS=internal is used, additional library and include paths are
|
||||
# needed for LibTomMath. Alternatively, an integrated, minimal version of
|
||||
# LibTomMath can be used. See beginning of libtommath.c for details on benefits
|
||||
# and drawbacks of this option.
|
||||
#CONFIG_INTERNAL_LIBTOMMATH=y
|
||||
#ifndef CONFIG_INTERNAL_LIBTOMMATH
|
||||
#LTM_PATH=/usr/src/libtommath-0.39
|
||||
#CFLAGS += -I$(LTM_PATH)
|
||||
#LIBS += -L$(LTM_PATH)
|
||||
#LIBS_p += -L$(LTM_PATH)
|
||||
#endif
|
||||
# At the cost of about 4 kB of additional binary size, the internal LibTomMath
|
||||
# can be configured to include faster routines for exptmod, sqr, and div to
|
||||
# speed up DH and RSA calculation considerably
|
||||
#CONFIG_INTERNAL_LIBTOMMATH_FAST=y
|
||||
|
||||
# Interworking (IEEE 802.11u)
|
||||
# This can be used to enable functionality to improve interworking with
|
||||
# external networks.
|
||||
#CONFIG_INTERWORKING=y
|
||||
|
||||
# Hotspot 2.0
|
||||
#CONFIG_HS20=y
|
||||
|
||||
# Enable SQLite database support in hlr_auc_gw, EAP-SIM DB, and eap_user_file
|
||||
#CONFIG_SQLITE=y
|
||||
|
@ -2,17 +2,12 @@
|
||||
* hostapd / State dump
|
||||
* Copyright (c) 2002-2009, Jouni Malinen <j@w1.fi>
|
||||
*
|
||||
* This program is free software; you can redistribute it and/or modify
|
||||
* it under the terms of the GNU General Public License version 2 as
|
||||
* published by the Free Software Foundation.
|
||||
*
|
||||
* Alternatively, this software may be distributed under the terms of BSD
|
||||
* license.
|
||||
*
|
||||
* See README and COPYING for more details.
|
||||
* This software may be distributed under the terms of the BSD license.
|
||||
* See README for more details.
|
||||
*/
|
||||
|
||||
#include "utils/includes.h"
|
||||
#include <time.h>
|
||||
|
||||
#include "utils/common.h"
|
||||
#include "radius/radius_client.h"
|
||||
@ -106,7 +101,8 @@ static void hostapd_dump_state(struct hostapd_data *hapd)
|
||||
fprintf(f, "\nSTA=" MACSTR "\n", MAC2STR(sta->addr));
|
||||
|
||||
fprintf(f,
|
||||
" AID=%d flags=0x%x %s%s%s%s%s%s%s%s%s%s%s%s%s%s%s\n"
|
||||
" AID=%d flags=0x%x %s%s%s%s%s%s%s%s%s%s%s%s%s%s%s%s"
|
||||
"\n"
|
||||
" capability=0x%x listen_interval=%d\n",
|
||||
sta->aid,
|
||||
sta->flags,
|
||||
@ -115,8 +111,7 @@ static void hostapd_dump_state(struct hostapd_data *hapd)
|
||||
(sta->flags & WLAN_STA_PS ? "[PS]" : ""),
|
||||
(sta->flags & WLAN_STA_TIM ? "[TIM]" : ""),
|
||||
(sta->flags & WLAN_STA_PERM ? "[PERM]" : ""),
|
||||
(sta->flags & WLAN_STA_AUTHORIZED ? "[AUTHORIZED]" :
|
||||
""),
|
||||
(ap_sta_is_authorized(sta) ? "[AUTHORIZED]" : ""),
|
||||
(sta->flags & WLAN_STA_PENDING_POLL ? "[PENDING_POLL" :
|
||||
""),
|
||||
(sta->flags & WLAN_STA_SHORT_PREAMBLE ?
|
||||
@ -128,6 +123,7 @@ static void hostapd_dump_state(struct hostapd_data *hapd)
|
||||
(sta->flags & WLAN_STA_MAYBE_WPS ? "[MAYBE_WPS]" : ""),
|
||||
(sta->flags & WLAN_STA_WDS ? "[WDS]" : ""),
|
||||
(sta->flags & WLAN_STA_NONERP ? "[NonERP]" : ""),
|
||||
(sta->flags & WLAN_STA_WPS2 ? "[WPS2]" : ""),
|
||||
sta->capability,
|
||||
sta->listen_interval);
|
||||
|
||||
|
@ -2,14 +2,8 @@
|
||||
* hostapd / State dump
|
||||
* Copyright (c) 2002-2009, Jouni Malinen <j@w1.fi>
|
||||
*
|
||||
* This program is free software; you can redistribute it and/or modify
|
||||
* it under the terms of the GNU General Public License version 2 as
|
||||
* published by the Free Software Foundation.
|
||||
*
|
||||
* Alternatively, this software may be distributed under the terms of BSD
|
||||
* license.
|
||||
*
|
||||
* See README and COPYING for more details.
|
||||
* This software may be distributed under the terms of the BSD license.
|
||||
* See README for more details.
|
||||
*/
|
||||
|
||||
#ifndef DUMP_STATE_H
|
||||
|
@ -2,14 +2,8 @@
|
||||
* EAP method registration
|
||||
* Copyright (c) 2004-2009, Jouni Malinen <j@w1.fi>
|
||||
*
|
||||
* This program is free software; you can redistribute it and/or modify
|
||||
* it under the terms of the GNU General Public License version 2 as
|
||||
* published by the Free Software Foundation.
|
||||
*
|
||||
* Alternatively, this software may be distributed under the terms of BSD
|
||||
* license.
|
||||
*
|
||||
* See README and COPYING for more details.
|
||||
* This software may be distributed under the terms of the BSD license.
|
||||
* See README for more details.
|
||||
*/
|
||||
|
||||
#include "includes.h"
|
||||
@ -45,6 +39,11 @@ int eap_server_register_methods(void)
|
||||
ret = eap_server_tls_register();
|
||||
#endif /* EAP_SERVER_TLS */
|
||||
|
||||
#ifdef EAP_SERVER_UNAUTH_TLS
|
||||
if (ret == 0)
|
||||
ret = eap_server_unauth_tls_register();
|
||||
#endif /* EAP_SERVER_TLS */
|
||||
|
||||
#ifdef EAP_SERVER_MSCHAPV2
|
||||
if (ret == 0)
|
||||
ret = eap_server_mschapv2_register();
|
||||
@ -130,5 +129,10 @@ int eap_server_register_methods(void)
|
||||
ret = eap_server_tnc_register();
|
||||
#endif /* EAP_SERVER_TNC */
|
||||
|
||||
#ifdef EAP_SERVER_PWD
|
||||
if (ret == 0)
|
||||
ret = eap_server_pwd_register();
|
||||
#endif /* EAP_SERVER_PWD */
|
||||
|
||||
return ret;
|
||||
}
|
||||
|
@ -2,14 +2,8 @@
|
||||
* EAP method registration
|
||||
* Copyright (c) 2004-2009, Jouni Malinen <j@w1.fi>
|
||||
*
|
||||
* This program is free software; you can redistribute it and/or modify
|
||||
* it under the terms of the GNU General Public License version 2 as
|
||||
* published by the Free Software Foundation.
|
||||
*
|
||||
* Alternatively, this software may be distributed under the terms of BSD
|
||||
* license.
|
||||
*
|
||||
* See README and COPYING for more details.
|
||||
* This software may be distributed under the terms of the BSD license.
|
||||
* See README for more details.
|
||||
*/
|
||||
|
||||
#ifndef EAP_REGISTER_H
|
||||
|
@ -1,15 +1,9 @@
|
||||
/*
|
||||
* HLR/AuC testing gateway for hostapd EAP-SIM/AKA database/authenticator
|
||||
* Copyright (c) 2005-2007, Jouni Malinen <j@w1.fi>
|
||||
* Copyright (c) 2005-2007, 2012, Jouni Malinen <j@w1.fi>
|
||||
*
|
||||
* This program is free software; you can redistribute it and/or modify
|
||||
* it under the terms of the GNU General Public License version 2 as
|
||||
* published by the Free Software Foundation.
|
||||
*
|
||||
* Alternatively, this software may be distributed under the terms of BSD
|
||||
* license.
|
||||
*
|
||||
* See README and COPYING for more details.
|
||||
* This software may be distributed under the terms of the BSD license.
|
||||
* See README for more details.
|
||||
*
|
||||
* This is an example implementation of the EAP-SIM/AKA database/authentication
|
||||
* gateway interface to HLR/AuC. It is expected to be replaced with an
|
||||
@ -40,18 +34,30 @@
|
||||
* text file in IMSI:Kc:SRES:RAND format, IMSI in ASCII, other fields as hex
|
||||
* strings. This is used to simulate an HLR/AuC. As such, it is not very useful
|
||||
* for real life authentication, but it is useful both as an example
|
||||
* implementation and for EAP-SIM testing.
|
||||
* implementation and for EAP-SIM/AKA/AKA' testing.
|
||||
*
|
||||
* SQN generation follows the not time-based Profile 2 described in
|
||||
* 3GPP TS 33.102 Annex C.3.2. The length of IND is 5 bits by default, but this
|
||||
* can be changed with a command line options if needed.
|
||||
*/
|
||||
|
||||
#include "includes.h"
|
||||
#include <sys/un.h>
|
||||
#ifdef CONFIG_SQLITE
|
||||
#include <sqlite3.h>
|
||||
#endif /* CONFIG_SQLITE */
|
||||
|
||||
#include "common.h"
|
||||
#include "crypto/milenage.h"
|
||||
#include "crypto/random.h"
|
||||
|
||||
static const char *default_socket_path = "/tmp/hlr_auc_gw.sock";
|
||||
static const char *socket_path;
|
||||
static int serv_sock = -1;
|
||||
static char *milenage_file = NULL;
|
||||
static int update_milenage = 0;
|
||||
static int sqn_changes = 0;
|
||||
static int ind_len = 5;
|
||||
|
||||
/* GSM triplets */
|
||||
struct gsm_triplet {
|
||||
@ -72,6 +78,7 @@ struct milenage_parameters {
|
||||
u8 opc[16];
|
||||
u8 amf[2];
|
||||
u8 sqn[6];
|
||||
int set;
|
||||
};
|
||||
|
||||
static struct milenage_parameters *milenage_db = NULL;
|
||||
@ -86,6 +93,144 @@ static struct milenage_parameters *milenage_db = NULL;
|
||||
#define EAP_AKA_CK_LEN 16
|
||||
|
||||
|
||||
#ifdef CONFIG_SQLITE
|
||||
|
||||
static sqlite3 *sqlite_db = NULL;
|
||||
static struct milenage_parameters db_tmp_milenage;
|
||||
|
||||
|
||||
static int db_table_exists(sqlite3 *db, const char *name)
|
||||
{
|
||||
char cmd[128];
|
||||
os_snprintf(cmd, sizeof(cmd), "SELECT 1 FROM %s;", name);
|
||||
return sqlite3_exec(db, cmd, NULL, NULL, NULL) == SQLITE_OK;
|
||||
}
|
||||
|
||||
|
||||
static int db_table_create_milenage(sqlite3 *db)
|
||||
{
|
||||
char *err = NULL;
|
||||
const char *sql =
|
||||
"CREATE TABLE milenage("
|
||||
" imsi INTEGER PRIMARY KEY NOT NULL,"
|
||||
" ki CHAR(32) NOT NULL,"
|
||||
" opc CHAR(32) NOT NULL,"
|
||||
" amf CHAR(4) NOT NULL,"
|
||||
" sqn CHAR(12) NOT NULL"
|
||||
");";
|
||||
|
||||
printf("Adding database table for milenage information\n");
|
||||
if (sqlite3_exec(db, sql, NULL, NULL, &err) != SQLITE_OK) {
|
||||
printf("SQLite error: %s\n", err);
|
||||
sqlite3_free(err);
|
||||
return -1;
|
||||
}
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
|
||||
static sqlite3 * db_open(const char *db_file)
|
||||
{
|
||||
sqlite3 *db;
|
||||
|
||||
if (sqlite3_open(db_file, &db)) {
|
||||
printf("Failed to open database %s: %s\n",
|
||||
db_file, sqlite3_errmsg(db));
|
||||
sqlite3_close(db);
|
||||
return NULL;
|
||||
}
|
||||
|
||||
if (!db_table_exists(db, "milenage") &&
|
||||
db_table_create_milenage(db) < 0) {
|
||||
sqlite3_close(db);
|
||||
return NULL;
|
||||
}
|
||||
|
||||
return db;
|
||||
}
|
||||
|
||||
|
||||
static int get_milenage_cb(void *ctx, int argc, char *argv[], char *col[])
|
||||
{
|
||||
struct milenage_parameters *m = ctx;
|
||||
int i;
|
||||
|
||||
m->set = 1;
|
||||
|
||||
for (i = 0; i < argc; i++) {
|
||||
if (os_strcmp(col[i], "ki") == 0 && argv[i] &&
|
||||
hexstr2bin(argv[i], m->ki, sizeof(m->ki))) {
|
||||
printf("Invalid ki value in database\n");
|
||||
return -1;
|
||||
}
|
||||
|
||||
if (os_strcmp(col[i], "opc") == 0 && argv[i] &&
|
||||
hexstr2bin(argv[i], m->opc, sizeof(m->opc))) {
|
||||
printf("Invalid opcvalue in database\n");
|
||||
return -1;
|
||||
}
|
||||
|
||||
if (os_strcmp(col[i], "amf") == 0 && argv[i] &&
|
||||
hexstr2bin(argv[i], m->amf, sizeof(m->amf))) {
|
||||
printf("Invalid amf value in database\n");
|
||||
return -1;
|
||||
}
|
||||
|
||||
if (os_strcmp(col[i], "sqn") == 0 && argv[i] &&
|
||||
hexstr2bin(argv[i], m->sqn, sizeof(m->sqn))) {
|
||||
printf("Invalid sqn value in database\n");
|
||||
return -1;
|
||||
}
|
||||
}
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
|
||||
static struct milenage_parameters * db_get_milenage(const char *imsi_txt)
|
||||
{
|
||||
char cmd[128];
|
||||
unsigned long long imsi;
|
||||
|
||||
os_memset(&db_tmp_milenage, 0, sizeof(db_tmp_milenage));
|
||||
imsi = atoll(imsi_txt);
|
||||
os_snprintf(db_tmp_milenage.imsi, sizeof(db_tmp_milenage.imsi),
|
||||
"%llu", imsi);
|
||||
os_snprintf(cmd, sizeof(cmd),
|
||||
"SELECT ki,opc,amf,sqn FROM milenage WHERE imsi=%llu;",
|
||||
imsi);
|
||||
if (sqlite3_exec(sqlite_db, cmd, get_milenage_cb, &db_tmp_milenage,
|
||||
NULL) != SQLITE_OK)
|
||||
return NULL;
|
||||
|
||||
if (!db_tmp_milenage.set)
|
||||
return NULL;
|
||||
return &db_tmp_milenage;
|
||||
}
|
||||
|
||||
|
||||
static int db_update_milenage_sqn(struct milenage_parameters *m)
|
||||
{
|
||||
char cmd[128], val[13], *pos;
|
||||
|
||||
pos = val;
|
||||
pos += wpa_snprintf_hex(pos, sizeof(val), m->sqn, 6);
|
||||
*pos = '\0';
|
||||
os_snprintf(cmd, sizeof(cmd),
|
||||
"UPDATE milenage SET sqn='%s' WHERE imsi=%s;",
|
||||
val, m->imsi);
|
||||
if (sqlite3_exec(sqlite_db, cmd, NULL, NULL, NULL) != SQLITE_OK) {
|
||||
printf("Failed to update SQN in database for IMSI %s\n",
|
||||
m->imsi);
|
||||
return -1;
|
||||
}
|
||||
return 0;
|
||||
}
|
||||
|
||||
#endif /* CONFIG_SQLITE */
|
||||
|
||||
|
||||
static int open_socket(const char *path)
|
||||
{
|
||||
struct sockaddr_un addr;
|
||||
@ -101,7 +246,7 @@ static int open_socket(const char *path)
|
||||
addr.sun_family = AF_UNIX;
|
||||
os_strlcpy(addr.sun_path, path, sizeof(addr.sun_path));
|
||||
if (bind(s, (struct sockaddr *) &addr, sizeof(addr)) < 0) {
|
||||
perror("bind(PF_UNIX)");
|
||||
perror("hlr-auc-gw: bind(PF_UNIX)");
|
||||
close(s);
|
||||
return -1;
|
||||
}
|
||||
@ -215,7 +360,7 @@ static int read_gsm_triplets(const char *fname)
|
||||
gsm_db = g;
|
||||
g = NULL;
|
||||
}
|
||||
free(g);
|
||||
os_free(g);
|
||||
|
||||
fclose(f);
|
||||
|
||||
@ -365,7 +510,7 @@ static int read_milenage(const char *fname)
|
||||
milenage_db = m;
|
||||
m = NULL;
|
||||
}
|
||||
free(m);
|
||||
os_free(m);
|
||||
|
||||
fclose(f);
|
||||
|
||||
@ -373,6 +518,80 @@ static int read_milenage(const char *fname)
|
||||
}
|
||||
|
||||
|
||||
static void update_milenage_file(const char *fname)
|
||||
{
|
||||
FILE *f, *f2;
|
||||
char buf[500], *pos;
|
||||
char *end = buf + sizeof(buf);
|
||||
struct milenage_parameters *m;
|
||||
size_t imsi_len;
|
||||
|
||||
f = fopen(fname, "r");
|
||||
if (f == NULL) {
|
||||
printf("Could not open Milenage data file '%s'\n", fname);
|
||||
return;
|
||||
}
|
||||
|
||||
snprintf(buf, sizeof(buf), "%s.new", fname);
|
||||
f2 = fopen(buf, "w");
|
||||
if (f2 == NULL) {
|
||||
printf("Could not write Milenage data file '%s'\n", buf);
|
||||
fclose(f);
|
||||
return;
|
||||
}
|
||||
|
||||
while (fgets(buf, sizeof(buf), f)) {
|
||||
/* IMSI Ki OPc AMF SQN */
|
||||
buf[sizeof(buf) - 1] = '\0';
|
||||
|
||||
pos = strchr(buf, ' ');
|
||||
if (buf[0] == '#' || pos == NULL || pos - buf >= 20)
|
||||
goto no_update;
|
||||
|
||||
imsi_len = pos - buf;
|
||||
|
||||
for (m = milenage_db; m; m = m->next) {
|
||||
if (strncmp(buf, m->imsi, imsi_len) == 0 &&
|
||||
m->imsi[imsi_len] == '\0')
|
||||
break;
|
||||
}
|
||||
|
||||
if (!m)
|
||||
goto no_update;
|
||||
|
||||
pos = buf;
|
||||
pos += snprintf(pos, end - pos, "%s ", m->imsi);
|
||||
pos += wpa_snprintf_hex(pos, end - pos, m->ki, 16);
|
||||
*pos++ = ' ';
|
||||
pos += wpa_snprintf_hex(pos, end - pos, m->opc, 16);
|
||||
*pos++ = ' ';
|
||||
pos += wpa_snprintf_hex(pos, end - pos, m->amf, 2);
|
||||
*pos++ = ' ';
|
||||
pos += wpa_snprintf_hex(pos, end - pos, m->sqn, 6);
|
||||
*pos++ = '\n';
|
||||
|
||||
no_update:
|
||||
fprintf(f2, "%s", buf);
|
||||
}
|
||||
|
||||
fclose(f2);
|
||||
fclose(f);
|
||||
|
||||
snprintf(buf, sizeof(buf), "%s.bak", fname);
|
||||
if (rename(fname, buf) < 0) {
|
||||
perror("rename");
|
||||
return;
|
||||
}
|
||||
|
||||
snprintf(buf, sizeof(buf), "%s.new", fname);
|
||||
if (rename(buf, fname) < 0) {
|
||||
perror("rename");
|
||||
return;
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
|
||||
static struct milenage_parameters * get_milenage(const char *imsi)
|
||||
{
|
||||
struct milenage_parameters *m = milenage_db;
|
||||
@ -383,6 +602,11 @@ static struct milenage_parameters * get_milenage(const char *imsi)
|
||||
m = m->next;
|
||||
}
|
||||
|
||||
#ifdef CONFIG_SQLITE
|
||||
if (!m)
|
||||
m = db_get_milenage(imsi);
|
||||
#endif /* CONFIG_SQLITE */
|
||||
|
||||
return m;
|
||||
}
|
||||
|
||||
@ -418,7 +642,7 @@ static void sim_req_auth(int s, struct sockaddr_un *from, socklen_t fromlen,
|
||||
if (m) {
|
||||
u8 _rand[16], sres[4], kc[8];
|
||||
for (count = 0; count < max_chal; count++) {
|
||||
if (os_get_random(_rand, 16) < 0)
|
||||
if (random_get_bytes(_rand, 16) < 0)
|
||||
return;
|
||||
gsm_milenage(m->opc, m->ki, _rand, sres, kc);
|
||||
*rpos++ = ' ';
|
||||
@ -465,6 +689,28 @@ send:
|
||||
}
|
||||
|
||||
|
||||
static void inc_sqn(u8 *sqn)
|
||||
{
|
||||
u64 val, seq, ind;
|
||||
|
||||
/*
|
||||
* SQN = SEQ | IND = SEQ1 | SEQ2 | IND
|
||||
*
|
||||
* The mechanism used here is not time-based, so SEQ2 is void and
|
||||
* SQN = SEQ1 | IND. The length of IND is ind_len bits and the length
|
||||
* of SEQ1 is 48 - ind_len bits.
|
||||
*/
|
||||
|
||||
/* Increment both SEQ and IND by one */
|
||||
val = ((u64) WPA_GET_BE32(sqn) << 16) | ((u64) WPA_GET_BE16(sqn + 4));
|
||||
seq = (val >> ind_len) + 1;
|
||||
ind = (val + 1) & ((1 << ind_len) - 1);
|
||||
val = (seq << ind_len) | ind;
|
||||
WPA_PUT_BE32(sqn, val >> 16);
|
||||
WPA_PUT_BE16(sqn + 4, val & 0xffff);
|
||||
}
|
||||
|
||||
|
||||
static void aka_req_auth(int s, struct sockaddr_un *from, socklen_t fromlen,
|
||||
char *imsi)
|
||||
{
|
||||
@ -478,13 +724,18 @@ static void aka_req_auth(int s, struct sockaddr_un *from, socklen_t fromlen,
|
||||
size_t res_len;
|
||||
int ret;
|
||||
struct milenage_parameters *m;
|
||||
int failed = 0;
|
||||
|
||||
m = get_milenage(imsi);
|
||||
if (m) {
|
||||
if (os_get_random(_rand, EAP_AKA_RAND_LEN) < 0)
|
||||
if (random_get_bytes(_rand, EAP_AKA_RAND_LEN) < 0)
|
||||
return;
|
||||
res_len = EAP_AKA_RES_MAX_LEN;
|
||||
inc_byte_array(m->sqn, 6);
|
||||
inc_sqn(m->sqn);
|
||||
#ifdef CONFIG_SQLITE
|
||||
db_update_milenage_sqn(m);
|
||||
#endif /* CONFIG_SQLITE */
|
||||
sqn_changes = 1;
|
||||
printf("AKA: Milenage with SQN=%02x%02x%02x%02x%02x%02x\n",
|
||||
m->sqn[0], m->sqn[1], m->sqn[2],
|
||||
m->sqn[3], m->sqn[4], m->sqn[5]);
|
||||
@ -501,7 +752,7 @@ static void aka_req_auth(int s, struct sockaddr_un *from, socklen_t fromlen,
|
||||
memset(res, '2', EAP_AKA_RES_MAX_LEN);
|
||||
res_len = EAP_AKA_RES_MAX_LEN;
|
||||
#else /* AKA_USE_FIXED_TEST_VALUES */
|
||||
return;
|
||||
failed = 1;
|
||||
#endif /* AKA_USE_FIXED_TEST_VALUES */
|
||||
}
|
||||
|
||||
@ -511,6 +762,13 @@ static void aka_req_auth(int s, struct sockaddr_un *from, socklen_t fromlen,
|
||||
if (ret < 0 || ret >= end - pos)
|
||||
return;
|
||||
pos += ret;
|
||||
if (failed) {
|
||||
ret = snprintf(pos, end - pos, "FAILURE");
|
||||
if (ret < 0 || ret >= end - pos)
|
||||
return;
|
||||
pos += ret;
|
||||
goto done;
|
||||
}
|
||||
pos += wpa_snprintf_hex(pos, end - pos, _rand, EAP_AKA_RAND_LEN);
|
||||
*pos++ = ' ';
|
||||
pos += wpa_snprintf_hex(pos, end - pos, autn, EAP_AKA_AUTN_LEN);
|
||||
@ -521,6 +779,7 @@ static void aka_req_auth(int s, struct sockaddr_un *from, socklen_t fromlen,
|
||||
*pos++ = ' ';
|
||||
pos += wpa_snprintf_hex(pos, end - pos, res, res_len);
|
||||
|
||||
done:
|
||||
printf("Send: %s\n", reply);
|
||||
|
||||
if (sendto(s, reply, pos - reply, 0, (struct sockaddr *) from,
|
||||
@ -568,6 +827,10 @@ static void aka_auts(int s, struct sockaddr_un *from, socklen_t fromlen,
|
||||
printf("AKA-AUTS: Re-synchronized: "
|
||||
"SQN=%02x%02x%02x%02x%02x%02x\n",
|
||||
sqn[0], sqn[1], sqn[2], sqn[3], sqn[4], sqn[5]);
|
||||
#ifdef CONFIG_SQLITE
|
||||
db_update_milenage_sqn(m);
|
||||
#endif /* CONFIG_SQLITE */
|
||||
sqn_changes = 1;
|
||||
}
|
||||
}
|
||||
|
||||
@ -614,22 +877,32 @@ static void cleanup(void)
|
||||
struct gsm_triplet *g, *gprev;
|
||||
struct milenage_parameters *m, *prev;
|
||||
|
||||
if (update_milenage && milenage_file && sqn_changes)
|
||||
update_milenage_file(milenage_file);
|
||||
|
||||
g = gsm_db;
|
||||
while (g) {
|
||||
gprev = g;
|
||||
g = g->next;
|
||||
free(gprev);
|
||||
os_free(gprev);
|
||||
}
|
||||
|
||||
m = milenage_db;
|
||||
while (m) {
|
||||
prev = m;
|
||||
m = m->next;
|
||||
free(prev);
|
||||
os_free(prev);
|
||||
}
|
||||
|
||||
close(serv_sock);
|
||||
unlink(socket_path);
|
||||
|
||||
#ifdef CONFIG_SQLITE
|
||||
if (sqlite_db) {
|
||||
sqlite3_close(sqlite_db);
|
||||
sqlite_db = NULL;
|
||||
}
|
||||
#endif /* CONFIG_SQLITE */
|
||||
}
|
||||
|
||||
|
||||
@ -644,18 +917,22 @@ static void usage(void)
|
||||
{
|
||||
printf("HLR/AuC testing gateway for hostapd EAP-SIM/AKA "
|
||||
"database/authenticator\n"
|
||||
"Copyright (c) 2005-2007, Jouni Malinen <j@w1.fi>\n"
|
||||
"Copyright (c) 2005-2007, 2012, Jouni Malinen <j@w1.fi>\n"
|
||||
"\n"
|
||||
"usage:\n"
|
||||
"hlr_auc_gw [-h] [-s<socket path>] [-g<triplet file>] "
|
||||
"[-m<milenage file>]\n"
|
||||
"hlr_auc_gw [-hu] [-s<socket path>] [-g<triplet file>] "
|
||||
"[-m<milenage file>] \\\n"
|
||||
" [-D<DB file>] [-i<IND len in bits>]\n"
|
||||
"\n"
|
||||
"options:\n"
|
||||
" -h = show this usage help\n"
|
||||
" -u = update SQN in Milenage file on exit\n"
|
||||
" -s<socket path> = path for UNIX domain socket\n"
|
||||
" (default: %s)\n"
|
||||
" -g<triplet file> = path for GSM authentication triplets\n"
|
||||
" -m<milenage file> = path for Milenage keys\n",
|
||||
" -m<milenage file> = path for Milenage keys\n"
|
||||
" -D<DB file> = path to SQLite database\n"
|
||||
" -i<IND len in bits> = IND length for SQN (default: 5)\n",
|
||||
default_socket_path);
|
||||
}
|
||||
|
||||
@ -663,34 +940,65 @@ static void usage(void)
|
||||
int main(int argc, char *argv[])
|
||||
{
|
||||
int c;
|
||||
char *milenage_file = NULL;
|
||||
char *gsm_triplet_file = NULL;
|
||||
char *sqlite_db_file = NULL;
|
||||
|
||||
if (os_program_init())
|
||||
return -1;
|
||||
|
||||
socket_path = default_socket_path;
|
||||
|
||||
for (;;) {
|
||||
c = getopt(argc, argv, "g:hm:s:");
|
||||
c = getopt(argc, argv, "D:g:hi:m:s:u");
|
||||
if (c < 0)
|
||||
break;
|
||||
switch (c) {
|
||||
case 'D':
|
||||
#ifdef CONFIG_SQLITE
|
||||
sqlite_db_file = optarg;
|
||||
break;
|
||||
#else /* CONFIG_SQLITE */
|
||||
printf("No SQLite support included in the build\n");
|
||||
return -1;
|
||||
#endif /* CONFIG_SQLITE */
|
||||
case 'g':
|
||||
gsm_triplet_file = optarg;
|
||||
break;
|
||||
case 'h':
|
||||
usage();
|
||||
return 0;
|
||||
case 'i':
|
||||
ind_len = atoi(optarg);
|
||||
if (ind_len < 0 || ind_len > 32) {
|
||||
printf("Invalid IND length\n");
|
||||
return -1;
|
||||
}
|
||||
break;
|
||||
case 'm':
|
||||
milenage_file = optarg;
|
||||
break;
|
||||
case 's':
|
||||
socket_path = optarg;
|
||||
break;
|
||||
case 'u':
|
||||
update_milenage = 1;
|
||||
break;
|
||||
default:
|
||||
usage();
|
||||
return -1;
|
||||
}
|
||||
}
|
||||
|
||||
if (!gsm_triplet_file && !milenage_file && !sqlite_db_file) {
|
||||
usage();
|
||||
return -1;
|
||||
}
|
||||
|
||||
#ifdef CONFIG_SQLITE
|
||||
if (sqlite_db_file && (sqlite_db = db_open(sqlite_db_file)) == NULL)
|
||||
return -1;
|
||||
#endif /* CONFIG_SQLITE */
|
||||
|
||||
if (gsm_triplet_file && read_gsm_triplets(gsm_triplet_file) < 0)
|
||||
return -1;
|
||||
|
||||
@ -710,5 +1018,14 @@ int main(int argc, char *argv[])
|
||||
for (;;)
|
||||
process(serv_sock);
|
||||
|
||||
#ifdef CONFIG_SQLITE
|
||||
if (sqlite_db) {
|
||||
sqlite3_close(sqlite_db);
|
||||
sqlite_db = NULL;
|
||||
}
|
||||
#endif /* CONFIG_SQLITE */
|
||||
|
||||
os_program_deinit();
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
104
contrib/wpa/hostapd/hlr_auc_gw.txt
Normal file
104
contrib/wpa/hostapd/hlr_auc_gw.txt
Normal file
@ -0,0 +1,104 @@
|
||||
HLR/AuC testing gateway for hostapd EAP-SIM/AKA database/authenticator
|
||||
|
||||
hlr_auc_gw is an example implementation of the EAP-SIM/AKA/AKA'
|
||||
database/authentication gateway interface to HLR/AuC. It could be
|
||||
replaced with an implementation of SS7 gateway to GSM/UMTS
|
||||
authentication center (HLR/AuC). hostapd will send SIM/AKA
|
||||
authentication queries over a UNIX domain socket to and external
|
||||
program, e.g., hlr_auc_gw.
|
||||
|
||||
hlr_auc_gw can be configured with GSM and UMTS authentication data with
|
||||
text files: GSM triplet file (see hostapd.sim_db) and Milenage file (see
|
||||
hlr_auc_gw.milenage_db). Milenage parameters can be used to generate
|
||||
dynamic authentication data for EAP-SIM, EAP-AKA, and EAP-AKA' while the
|
||||
GSM triplet data is used for a more static configuration (e.g., triplets
|
||||
extracted from a SIM card).
|
||||
|
||||
Alternatively, hlr_auc_gw can be built with support for an SQLite
|
||||
database for more dynamic operations. This is enabled by adding
|
||||
"CONFIG_SQLITE=y" into hostapd/.config before building hlr_auc_gw ("make
|
||||
clean; make hlr_auc_gw" in this directory).
|
||||
|
||||
hostapd is configured to use hlr_auc_gw with the eap_sim_db parameter in
|
||||
hostapd.conf (e.g., "eap_sim_db=unix:/tmp/hlr_auc_gw.sock"). hlr_auc_gw
|
||||
is configured with command line parameters:
|
||||
|
||||
hlr_auc_gw [-hu] [-s<socket path>] [-g<triplet file>] [-m<milenage file>] \
|
||||
[-D<DB file>] [-i<IND len in bits>]
|
||||
|
||||
options:
|
||||
-h = show this usage help
|
||||
-u = update SQN in Milenage file on exit
|
||||
-s<socket path> = path for UNIX domain socket
|
||||
(default: /tmp/hlr_auc_gw.sock)
|
||||
-g<triplet file> = path for GSM authentication triplets
|
||||
-m<milenage file> = path for Milenage keys
|
||||
-D<DB file> = path to SQLite database
|
||||
-i<IND len in bits> = IND length for SQN (default: 5)
|
||||
|
||||
|
||||
The SQLite database can be initialized with sqlite, e.g., by running
|
||||
following commands in "sqlite3 /path/to/hlr_auc_gw.db":
|
||||
|
||||
CREATE TABLE milenage(
|
||||
imsi INTEGER PRIMARY KEY NOT NULL,
|
||||
ki CHAR(32) NOT NULL,
|
||||
opc CHAR(32) NOT NULL,
|
||||
amf CHAR(4) NOT NULL,
|
||||
sqn CHAR(12) NOT NULL
|
||||
);
|
||||
INSERT INTO milenage(imsi,ki,opc,amf,sqn) VALUES(
|
||||
232010000000000,
|
||||
'90dca4eda45b53cf0f12d7c9c3bc6a89',
|
||||
'cb9cccc4b9258e6dca4760379fb82581',
|
||||
'61df',
|
||||
'000000000000'
|
||||
);
|
||||
INSERT INTO milenage(imsi,ki,opc,amf,sqn) VALUES(
|
||||
555444333222111,
|
||||
'5122250214c33e723a5dd523fc145fc0',
|
||||
'981d464c7c52eb6e5036234984ad0bcf',
|
||||
'c3ab',
|
||||
'16f3b3f70fc1'
|
||||
);
|
||||
|
||||
|
||||
hostapd (EAP server) can also be configured to store the EAP-SIM/AKA
|
||||
pseudonyms and reauth information into a SQLite database. This is
|
||||
configured with the db parameter within the eap_sim_db configuration
|
||||
option.
|
||||
|
||||
|
||||
"hlr_auc_gw -D /path/to/hlr_auc_gw.db" can then be used to fetch
|
||||
Milenage parameters based on IMSI from the database. The database can be
|
||||
updated dynamically while hlr_auc_gw is running to add/remove/modify
|
||||
entries.
|
||||
|
||||
|
||||
Example configuration files for hostapd to operate as a RADIUS
|
||||
authentication server for EAP-SIM/AKA/AKA':
|
||||
|
||||
hostapd.conf:
|
||||
|
||||
driver=none
|
||||
radius_server_clients=hostapd.radius_clients
|
||||
eap_server=1
|
||||
eap_user_file=hostapd.eap_user
|
||||
eap_sim_db=unix:/tmp/hlr_auc_gw.sock db=/tmp/eap_sim.db
|
||||
eap_sim_aka_result_ind=1
|
||||
|
||||
hostapd.radius_clients:
|
||||
|
||||
0.0.0.0/0 radius
|
||||
|
||||
hostapd.eap_user:
|
||||
|
||||
"0"* AKA
|
||||
"1"* SIM
|
||||
"2"* AKA
|
||||
"3"* SIM
|
||||
"4"* AKA
|
||||
"5"* SIM
|
||||
"6"* AKA'
|
||||
"7"* AKA'
|
||||
"8"* AKA'
|
@ -84,6 +84,14 @@ ctrl_interface_group=0
|
||||
|
||||
# SSID to be used in IEEE 802.11 management frames
|
||||
ssid=test
|
||||
# Alternative formats for configuring SSID
|
||||
# (double quoted string, hexdump, printf-escaped string)
|
||||
#ssid2="test"
|
||||
#ssid2=74657374
|
||||
#ssid2=P"hello\nthere"
|
||||
|
||||
# UTF-8 SSID: Whether the SSID is to be interpreted using UTF-8 encoding
|
||||
#utf8_ssid=1
|
||||
|
||||
# Country code (ISO/IEC 3166-1). Used to set regulatory domain.
|
||||
# Set as needed to indicate country in which device is operating.
|
||||
@ -98,20 +106,21 @@ ssid=test
|
||||
#ieee80211d=1
|
||||
|
||||
# Operation mode (a = IEEE 802.11a, b = IEEE 802.11b, g = IEEE 802.11g,
|
||||
# ad = IEEE 802.11ad (60 GHz); a/g options are used with IEEE 802.11n, too, to
|
||||
# specify band)
|
||||
# Default: IEEE 802.11b
|
||||
hw_mode=a
|
||||
hw_mode=g
|
||||
|
||||
# Channel number (IEEE 802.11)
|
||||
# (default: 0, i.e., not set)
|
||||
# Please note that some drivers (e.g., madwifi) do not use this value from
|
||||
# hostapd and the channel will need to be configuration separately with
|
||||
# iwconfig.
|
||||
channel=60
|
||||
# Please note that some drivers do not use this value from hostapd and the
|
||||
# channel will need to be configured separately with iwconfig.
|
||||
channel=1
|
||||
|
||||
# Beacon interval in kus (1.024 ms) (default: 100; range 15..65535)
|
||||
beacon_int=100
|
||||
|
||||
# DTIM (delivery trafic information message) period (range 1..255):
|
||||
# DTIM (delivery traffic information message) period (range 1..255):
|
||||
# number of beacons between DTIMs (1 = every beacon includes DTIM element)
|
||||
# (default: 2)
|
||||
dtim_period=2
|
||||
@ -197,8 +206,14 @@ auth_algs=3
|
||||
# requests for broadcast SSID
|
||||
ignore_broadcast_ssid=0
|
||||
|
||||
# Additional vendor specfic elements for Beacon and Probe Response frames
|
||||
# This parameter can be used to add additional vendor specific element(s) into
|
||||
# the end of the Beacon and Probe Response frames. The format for these
|
||||
# element(s) is a hexdump of the raw information elements (id+len+payload for
|
||||
# one or more elements)
|
||||
#vendor_elements=dd0411223301
|
||||
|
||||
# TX queue parameters (EDCF / bursting)
|
||||
# default for all these fields: not set, use hardware defaults
|
||||
# tx_queue_<queue name>_<param>
|
||||
# queues: data0, data1, data2, data3, after_beacon, beacon
|
||||
# (data0 is the highest priority queue)
|
||||
@ -240,18 +255,6 @@ ignore_broadcast_ssid=0
|
||||
#tx_queue_data0_cwmax=7
|
||||
#tx_queue_data0_burst=1.5
|
||||
# Note: for IEEE 802.11b mode: cWmin=7 cWmax=15 burst=3.3
|
||||
#
|
||||
# Special queues; normally not user configurable
|
||||
#
|
||||
#tx_queue_after_beacon_aifs=2
|
||||
#tx_queue_after_beacon_cwmin=15
|
||||
#tx_queue_after_beacon_cwmax=1023
|
||||
#tx_queue_after_beacon_burst=0
|
||||
#
|
||||
#tx_queue_beacon_aifs=2
|
||||
#tx_queue_beacon_cwmin=3
|
||||
#tx_queue_beacon_cwmax=7
|
||||
#tx_queue_beacon_burst=1.5
|
||||
|
||||
# 802.1D Tag (= UP) to AC mappings
|
||||
# WMM specifies following mapping of data frames to different ACs. This mapping
|
||||
@ -353,6 +356,17 @@ wmm_ac_vo_acm=0
|
||||
# the STA with a data frame.
|
||||
# default: 300 (i.e., 5 minutes)
|
||||
#ap_max_inactivity=300
|
||||
#
|
||||
# The inactivity polling can be disabled to disconnect stations based on
|
||||
# inactivity timeout so that idle stations are more likely to be disconnected
|
||||
# even if they are still in range of the AP. This can be done by setting
|
||||
# skip_inactivity_poll to 1 (default 0).
|
||||
#skip_inactivity_poll=0
|
||||
|
||||
# Disassociate stations based on excessive transmission failures or other
|
||||
# indications of connection loss. This depends on the driver capabilities and
|
||||
# may not be available with all drivers.
|
||||
#disassoc_low_ack=1
|
||||
|
||||
# Maximum allowed Listen Interval (how many Beacon periods STAs are allowed to
|
||||
# remain asleep). Default: 65535 (no limit apart from field size)
|
||||
@ -364,6 +378,15 @@ wmm_ac_vo_acm=0
|
||||
# bridging to be used.
|
||||
#wds_sta=1
|
||||
|
||||
# If bridge parameter is set, the WDS STA interface will be added to the same
|
||||
# bridge by default. This can be overridden with the wds_bridge parameter to
|
||||
# use a separate bridge.
|
||||
#wds_bridge=wds-br0
|
||||
|
||||
# Client isolation can be used to prevent low-level bridging of frames between
|
||||
# associated stations in the BSS. By default, this bridging is allowed.
|
||||
#ap_isolate=1
|
||||
|
||||
##### IEEE 802.11n related configuration ######################################
|
||||
|
||||
# ieee80211n: Whether IEEE 802.11n (HT) is enabled
|
||||
@ -407,6 +430,160 @@ wmm_ac_vo_acm=0
|
||||
# L-SIG TXOP protection support: [LSIG-TXOP-PROT] (disabled if not set)
|
||||
#ht_capab=[HT40-][SHORT-GI-20][SHORT-GI-40]
|
||||
|
||||
# Require stations to support HT PHY (reject association if they do not)
|
||||
#require_ht=1
|
||||
|
||||
##### IEEE 802.11ac related configuration #####################################
|
||||
|
||||
# ieee80211ac: Whether IEEE 802.11ac (VHT) is enabled
|
||||
# 0 = disabled (default)
|
||||
# 1 = enabled
|
||||
# Note: You will also need to enable WMM for full VHT functionality.
|
||||
#ieee80211ac=1
|
||||
|
||||
# vht_capab: VHT capabilities (list of flags)
|
||||
#
|
||||
# vht_max_mpdu_len: [MAX-MPDU-7991] [MAX-MPDU-11454]
|
||||
# Indicates maximum MPDU length
|
||||
# 0 = 3895 octets (default)
|
||||
# 1 = 7991 octets
|
||||
# 2 = 11454 octets
|
||||
# 3 = reserved
|
||||
#
|
||||
# supported_chan_width: [VHT160] [VHT160-80PLUS80]
|
||||
# Indicates supported Channel widths
|
||||
# 0 = 160 MHz & 80+80 channel widths are not supported (default)
|
||||
# 1 = 160 MHz channel width is supported
|
||||
# 2 = 160 MHz & 80+80 channel widths are supported
|
||||
# 3 = reserved
|
||||
#
|
||||
# Rx LDPC coding capability: [RXLDPC]
|
||||
# Indicates support for receiving LDPC coded pkts
|
||||
# 0 = Not supported (default)
|
||||
# 1 = Supported
|
||||
#
|
||||
# Short GI for 80 MHz: [SHORT-GI-80]
|
||||
# Indicates short GI support for reception of packets transmitted with TXVECTOR
|
||||
# params format equal to VHT and CBW = 80Mhz
|
||||
# 0 = Not supported (default)
|
||||
# 1 = Supported
|
||||
#
|
||||
# Short GI for 160 MHz: [SHORT-GI-160]
|
||||
# Indicates short GI support for reception of packets transmitted with TXVECTOR
|
||||
# params format equal to VHT and CBW = 160Mhz
|
||||
# 0 = Not supported (default)
|
||||
# 1 = Supported
|
||||
#
|
||||
# Tx STBC: [TX-STBC-2BY1]
|
||||
# Indicates support for the transmission of at least 2x1 STBC
|
||||
# 0 = Not supported (default)
|
||||
# 1 = Supported
|
||||
#
|
||||
# Rx STBC: [RX-STBC-1] [RX-STBC-12] [RX-STBC-123] [RX-STBC-1234]
|
||||
# Indicates support for the reception of PPDUs using STBC
|
||||
# 0 = Not supported (default)
|
||||
# 1 = support of one spatial stream
|
||||
# 2 = support of one and two spatial streams
|
||||
# 3 = support of one, two and three spatial streams
|
||||
# 4 = support of one, two, three and four spatial streams
|
||||
# 5,6,7 = reserved
|
||||
#
|
||||
# SU Beamformer Capable: [SU-BEAMFORMER]
|
||||
# Indicates support for operation as a single user beamformer
|
||||
# 0 = Not supported (default)
|
||||
# 1 = Supported
|
||||
#
|
||||
# SU Beamformee Capable: [SU-BEAMFORMEE]
|
||||
# Indicates support for operation as a single user beamformee
|
||||
# 0 = Not supported (default)
|
||||
# 1 = Supported
|
||||
#
|
||||
# Compressed Steering Number of Beamformer Antennas Supported: [BF-ANTENNA-2]
|
||||
# Beamformee's capability indicating the maximum number of beamformer
|
||||
# antennas the beamformee can support when sending compressed beamforming
|
||||
# feedback
|
||||
# If SU beamformer capable, set to maximum value minus 1
|
||||
# else reserved (default)
|
||||
#
|
||||
# Number of Sounding Dimensions: [SOUNDING-DIMENSION-2]
|
||||
# Beamformer's capability indicating the maximum value of the NUM_STS parameter
|
||||
# in the TXVECTOR of a VHT NDP
|
||||
# If SU beamformer capable, set to maximum value minus 1
|
||||
# else reserved (default)
|
||||
#
|
||||
# MU Beamformer Capable: [MU-BEAMFORMER]
|
||||
# Indicates support for operation as an MU beamformer
|
||||
# 0 = Not supported or sent by Non-AP STA (default)
|
||||
# 1 = Supported
|
||||
#
|
||||
# MU Beamformee Capable: [MU-BEAMFORMEE]
|
||||
# Indicates support for operation as an MU beamformee
|
||||
# 0 = Not supported or sent by AP (default)
|
||||
# 1 = Supported
|
||||
#
|
||||
# VHT TXOP PS: [VHT-TXOP-PS]
|
||||
# Indicates whether or not the AP supports VHT TXOP Power Save Mode
|
||||
# or whether or not the STA is in VHT TXOP Power Save mode
|
||||
# 0 = VHT AP doesnt support VHT TXOP PS mode (OR) VHT Sta not in VHT TXOP PS
|
||||
# mode
|
||||
# 1 = VHT AP supports VHT TXOP PS mode (OR) VHT Sta is in VHT TXOP power save
|
||||
# mode
|
||||
#
|
||||
# +HTC-VHT Capable: [HTC-VHT]
|
||||
# Indicates whether or not the STA supports receiving a VHT variant HT Control
|
||||
# field.
|
||||
# 0 = Not supported (default)
|
||||
# 1 = supported
|
||||
#
|
||||
# Maximum A-MPDU Length Exponent: [MAX-A-MPDU-LEN-EXP0]..[MAX-A-MPDU-LEN-EXP7]
|
||||
# Indicates the maximum length of A-MPDU pre-EOF padding that the STA can recv
|
||||
# This field is an integer in the range of 0 to 7.
|
||||
# The length defined by this field is equal to
|
||||
# 2 pow(13 + Maximum A-MPDU Length Exponent) -1 octets
|
||||
#
|
||||
# VHT Link Adaptation Capable: [VHT-LINK-ADAPT2] [VHT-LINK-ADAPT3]
|
||||
# Indicates whether or not the STA supports link adaptation using VHT variant
|
||||
# HT Control field
|
||||
# If +HTC-VHTcapable is 1
|
||||
# 0 = (no feedback) if the STA does not provide VHT MFB (default)
|
||||
# 1 = reserved
|
||||
# 2 = (Unsolicited) if the STA provides only unsolicited VHT MFB
|
||||
# 3 = (Both) if the STA can provide VHT MFB in response to VHT MRQ and if the
|
||||
# STA provides unsolicited VHT MFB
|
||||
# Reserved if +HTC-VHTcapable is 0
|
||||
#
|
||||
# Rx Antenna Pattern Consistency: [RX-ANTENNA-PATTERN]
|
||||
# Indicates the possibility of Rx antenna pattern change
|
||||
# 0 = Rx antenna pattern might change during the lifetime of an association
|
||||
# 1 = Rx antenna pattern does not change during the lifetime of an association
|
||||
#
|
||||
# Tx Antenna Pattern Consistency: [TX-ANTENNA-PATTERN]
|
||||
# Indicates the possibility of Tx antenna pattern change
|
||||
# 0 = Tx antenna pattern might change during the lifetime of an association
|
||||
# 1 = Tx antenna pattern does not change during the lifetime of an association
|
||||
#vht_capab=[SHORT-GI-80][HTC-VHT]
|
||||
#
|
||||
# Require stations to support VHT PHY (reject association if they do not)
|
||||
#require_vht=1
|
||||
|
||||
# 0 = 20 or 40 MHz operating Channel width
|
||||
# 1 = 80 MHz channel width
|
||||
# 2 = 160 MHz channel width
|
||||
# 3 = 80+80 MHz channel width
|
||||
#vht_oper_chwidth=1
|
||||
#
|
||||
# center freq = 5 GHz + (5 * index)
|
||||
# So index 42 gives center freq 5.210 GHz
|
||||
# which is channel 42 in 5G band
|
||||
#
|
||||
#vht_oper_centr_freq_seg0_idx=42
|
||||
#
|
||||
# center freq = 5 GHz + (5 * index)
|
||||
# So index 159 gives center freq 5.795 GHz
|
||||
# which is channel 159 in 5G band
|
||||
#
|
||||
#vht_oper_centr_freq_seg1_idx=159
|
||||
|
||||
##### IEEE 802.1X-2004 related configuration ##################################
|
||||
|
||||
# Require IEEE 802.1X authorization
|
||||
@ -463,6 +640,8 @@ eapol_key_index_workaround=0
|
||||
eap_server=0
|
||||
|
||||
# Path for EAP server user database
|
||||
# If SQLite support is included, this can be set to "sqlite:/path/to/sqlite.db"
|
||||
# to use SQLite database instead of a text file.
|
||||
#eap_user_file=/etc/hostapd.eap_user
|
||||
|
||||
# CA certificate (PEM or DER file) for EAP-TLS/PEAP/TTLS
|
||||
@ -504,12 +683,21 @@ eap_server=0
|
||||
# "openssl dhparam -out /etc/hostapd.dh.pem 1024"
|
||||
#dh_file=/etc/hostapd.dh.pem
|
||||
|
||||
# Fragment size for EAP methods
|
||||
#fragment_size=1400
|
||||
|
||||
# Finite cyclic group for EAP-pwd. Number maps to group of domain parameters
|
||||
# using the IANA repository for IKE (RFC 2409).
|
||||
#pwd_group=19
|
||||
|
||||
# Configuration data for EAP-SIM database/authentication gateway interface.
|
||||
# This is a text string in implementation specific format. The example
|
||||
# implementation in eap_sim_db.c uses this as the UNIX domain socket name for
|
||||
# the HLR/AuC gateway (e.g., hlr_auc_gw). In this case, the path uses "unix:"
|
||||
# prefix.
|
||||
# prefix. If hostapd is built with SQLite support (CONFIG_SQLITE=y in .config),
|
||||
# database file can be described with an optional db=<path> parameter.
|
||||
#eap_sim_db=unix:/tmp/hlr_auc_gw.sock
|
||||
#eap_sim_db=unix:/tmp/hlr_auc_gw.sock db=/tmp/hostapd.db
|
||||
|
||||
# Encryption key for EAP-FAST PAC-Opaque values. This key must be a secret,
|
||||
# random value. It is configured as a 16-octet value in hex format. It can be
|
||||
@ -616,6 +804,12 @@ own_ip_addr=127.0.0.1
|
||||
# 60 (1 minute).
|
||||
#radius_acct_interim_interval=600
|
||||
|
||||
# Request Chargeable-User-Identity (RFC 4372)
|
||||
# This parameter can be used to configure hostapd to request CUI from the
|
||||
# RADIUS server by including Chargeable-User-Identity attribute into
|
||||
# Access-Request packets.
|
||||
#radius_request_cui=1
|
||||
|
||||
# Dynamic VLAN mode; allow RADIUS authentication server to decide which VLAN
|
||||
# is used for the stations. This information is parsed from following RADIUS
|
||||
# attributes based on RFC 3580 and RFC 2868: Tunnel-Type (value 13 = VLAN),
|
||||
@ -643,6 +837,61 @@ own_ip_addr=127.0.0.1
|
||||
# to the bridge.
|
||||
#vlan_tagged_interface=eth0
|
||||
|
||||
# When hostapd creates a VLAN interface on vlan_tagged_interfaces, it needs
|
||||
# to know how to name it.
|
||||
# 0 = vlan<XXX>, e.g., vlan1
|
||||
# 1 = <vlan_tagged_interface>.<XXX>, e.g. eth0.1
|
||||
#vlan_naming=0
|
||||
|
||||
# Arbitrary RADIUS attributes can be added into Access-Request and
|
||||
# Accounting-Request packets by specifying the contents of the attributes with
|
||||
# the following configuration parameters. There can be multiple of these to
|
||||
# add multiple attributes. These parameters can also be used to override some
|
||||
# of the attributes added automatically by hostapd.
|
||||
# Format: <attr_id>[:<syntax:value>]
|
||||
# attr_id: RADIUS attribute type (e.g., 26 = Vendor-Specific)
|
||||
# syntax: s = string (UTF-8), d = integer, x = octet string
|
||||
# value: attribute value in format indicated by the syntax
|
||||
# If syntax and value parts are omitted, a null value (single 0x00 octet) is
|
||||
# used.
|
||||
#
|
||||
# Additional Access-Request attributes
|
||||
# radius_auth_req_attr=<attr_id>[:<syntax:value>]
|
||||
# Examples:
|
||||
# Operator-Name = "Operator"
|
||||
#radius_auth_req_attr=126:s:Operator
|
||||
# Service-Type = Framed (2)
|
||||
#radius_auth_req_attr=6:d:2
|
||||
# Connect-Info = "testing" (this overrides the automatically generated value)
|
||||
#radius_auth_req_attr=77:s:testing
|
||||
# Same Connect-Info value set as a hexdump
|
||||
#radius_auth_req_attr=77:x:74657374696e67
|
||||
|
||||
#
|
||||
# Additional Accounting-Request attributes
|
||||
# radius_acct_req_attr=<attr_id>[:<syntax:value>]
|
||||
# Examples:
|
||||
# Operator-Name = "Operator"
|
||||
#radius_acct_req_attr=126:s:Operator
|
||||
|
||||
# Dynamic Authorization Extensions (RFC 5176)
|
||||
# This mechanism can be used to allow dynamic changes to user session based on
|
||||
# commands from a RADIUS server (or some other disconnect client that has the
|
||||
# needed session information). For example, Disconnect message can be used to
|
||||
# request an associated station to be disconnected.
|
||||
#
|
||||
# This is disabled by default. Set radius_das_port to non-zero UDP port
|
||||
# number to enable.
|
||||
#radius_das_port=3799
|
||||
#
|
||||
# DAS client (the host that can send Disconnect/CoA requests) and shared secret
|
||||
#radius_das_client=192.168.1.123 shared secret here
|
||||
#
|
||||
# DAS Event-Timestamp time window in seconds
|
||||
#radius_das_time_window=300
|
||||
#
|
||||
# DAS require Event-Timestamp
|
||||
#radius_das_require_event_timestamp=1
|
||||
|
||||
##### RADIUS authentication server configuration ##############################
|
||||
|
||||
@ -666,6 +915,7 @@ own_ip_addr=127.0.0.1
|
||||
# Enable WPA. Setting this variable configures the AP to require WPA (either
|
||||
# WPA-PSK or WPA-RADIUS/EAP based on other configuration). For WPA-PSK, either
|
||||
# wpa_psk or wpa_passphrase must be set and wpa_key_mgmt must include WPA-PSK.
|
||||
# Instead of wpa_psk / wpa_passphrase, wpa_psk_radius might suffice.
|
||||
# For WPA-RADIUS/EAP, ieee8021x must be set (but without dynamic WEP keys),
|
||||
# RADIUS authentication server must be configured, and WPA-EAP must be included
|
||||
# in wpa_key_mgmt.
|
||||
@ -690,6 +940,15 @@ own_ip_addr=127.0.0.1
|
||||
# configuration reloads.
|
||||
#wpa_psk_file=/etc/hostapd.wpa_psk
|
||||
|
||||
# Optionally, WPA passphrase can be received from RADIUS authentication server
|
||||
# This requires macaddr_acl to be set to 2 (RADIUS)
|
||||
# 0 = disabled (default)
|
||||
# 1 = optional; use default passphrase/psk if RADIUS server does not include
|
||||
# Tunnel-Password
|
||||
# 2 = required; reject authentication if RADIUS server does not include
|
||||
# Tunnel-Password
|
||||
#wpa_psk_radius=0
|
||||
|
||||
# Set of accepted key management algorithms (WPA-PSK, WPA-EAP, or both). The
|
||||
# entries are separated with a space. WPA-PSK-SHA256 and WPA-EAP-SHA256 can be
|
||||
# added to enable SHA256-based stronger algorithms.
|
||||
@ -763,6 +1022,13 @@ own_ip_addr=127.0.0.1
|
||||
# dot11AssociationSAQueryRetryTimeout, 1...4294967295
|
||||
#assoc_sa_query_retry_timeout=201
|
||||
|
||||
# disable_pmksa_caching: Disable PMKSA caching
|
||||
# This parameter can be used to disable caching of PMKSA created through EAP
|
||||
# authentication. RSN preauthentication may still end up using PMKSA caching if
|
||||
# it is enabled (rsn_preauth=1).
|
||||
# 0 = PMKSA caching enabled (default)
|
||||
# 1 = PMKSA caching disabled
|
||||
#disable_pmksa_caching=0
|
||||
|
||||
# okc: Opportunistic Key Caching (aka Proactive Key Caching)
|
||||
# Allow PMK cache to be shared opportunistically among configured interfaces
|
||||
@ -910,8 +1176,21 @@ own_ip_addr=127.0.0.1
|
||||
# Config Methods
|
||||
# List of the supported configuration methods
|
||||
# Available methods: usba ethernet label display ext_nfc_token int_nfc_token
|
||||
# nfc_interface push_button keypad
|
||||
#config_methods=label display push_button keypad
|
||||
# nfc_interface push_button keypad virtual_display physical_display
|
||||
# virtual_push_button physical_push_button
|
||||
#config_methods=label virtual_display virtual_push_button keypad
|
||||
|
||||
# WPS capability discovery workaround for PBC with Windows 7
|
||||
# Windows 7 uses incorrect way of figuring out AP's WPS capabilities by acting
|
||||
# as a Registrar and using M1 from the AP. The config methods attribute in that
|
||||
# message is supposed to indicate only the configuration method supported by
|
||||
# the AP in Enrollee role, i.e., to add an external Registrar. For that case,
|
||||
# PBC shall not be used and as such, the PushButton config method is removed
|
||||
# from M1 by default. If pbc_in_m1=1 is included in the configuration file,
|
||||
# the PushButton config method is left in M1 (if included in config_methods
|
||||
# parameter) to allow Windows 7 to use PBC instead of PIN (e.g., from a label
|
||||
# in the AP).
|
||||
#pbc_in_m1=1
|
||||
|
||||
# Static access point PIN for initial configuration and adding Registrars
|
||||
# If not set, hostapd will not allow external WPS Registrars to control the
|
||||
@ -981,6 +1260,246 @@ own_ip_addr=127.0.0.1
|
||||
# 12-digit, all-numeric code that identifies the consumer package.
|
||||
#upc=123456789012
|
||||
|
||||
# WPS RF Bands (a = 5G, b = 2.4G, g = 2.4G, ag = dual band)
|
||||
# This value should be set according to RF band(s) supported by the AP if
|
||||
# hw_mode is not set. For dual band dual concurrent devices, this needs to be
|
||||
# set to ag to allow both RF bands to be advertized.
|
||||
#wps_rf_bands=ag
|
||||
|
||||
# NFC password token for WPS
|
||||
# These parameters can be used to configure a fixed NFC password token for the
|
||||
# AP. This can be generated, e.g., with nfc_pw_token from wpa_supplicant. When
|
||||
# these parameters are used, the AP is assumed to be deployed with a NFC tag
|
||||
# that includes the matching NFC password token (e.g., written based on the
|
||||
# NDEF record from nfc_pw_token).
|
||||
#
|
||||
#wps_nfc_dev_pw_id: Device Password ID (16..65535)
|
||||
#wps_nfc_dh_pubkey: Hexdump of DH Public Key
|
||||
#wps_nfc_dh_privkey: Hexdump of DH Private Key
|
||||
#wps_nfc_dev_pw: Hexdump of Device Password
|
||||
|
||||
##### Wi-Fi Direct (P2P) ######################################################
|
||||
|
||||
# Enable P2P Device management
|
||||
#manage_p2p=1
|
||||
|
||||
# Allow cross connection
|
||||
#allow_cross_connection=1
|
||||
|
||||
#### TDLS (IEEE 802.11z-2010) #################################################
|
||||
|
||||
# Prohibit use of TDLS in this BSS
|
||||
#tdls_prohibit=1
|
||||
|
||||
# Prohibit use of TDLS Channel Switching in this BSS
|
||||
#tdls_prohibit_chan_switch=1
|
||||
|
||||
##### IEEE 802.11v-2011 #######################################################
|
||||
|
||||
# Time advertisement
|
||||
# 0 = disabled (default)
|
||||
# 2 = UTC time at which the TSF timer is 0
|
||||
#time_advertisement=2
|
||||
|
||||
# Local time zone as specified in 8.3 of IEEE Std 1003.1-2004:
|
||||
# stdoffset[dst[offset][,start[/time],end[/time]]]
|
||||
#time_zone=EST5
|
||||
|
||||
# WNM-Sleep Mode (extended sleep mode for stations)
|
||||
# 0 = disabled (default)
|
||||
# 1 = enabled (allow stations to use WNM-Sleep Mode)
|
||||
#wnm_sleep_mode=1
|
||||
|
||||
# BSS Transition Management
|
||||
# 0 = disabled (default)
|
||||
# 1 = enabled
|
||||
#bss_transition=1
|
||||
|
||||
##### IEEE 802.11u-2011 #######################################################
|
||||
|
||||
# Enable Interworking service
|
||||
#interworking=1
|
||||
|
||||
# Access Network Type
|
||||
# 0 = Private network
|
||||
# 1 = Private network with guest access
|
||||
# 2 = Chargeable public network
|
||||
# 3 = Free public network
|
||||
# 4 = Personal device network
|
||||
# 5 = Emergency services only network
|
||||
# 14 = Test or experimental
|
||||
# 15 = Wildcard
|
||||
#access_network_type=0
|
||||
|
||||
# Whether the network provides connectivity to the Internet
|
||||
# 0 = Unspecified
|
||||
# 1 = Network provides connectivity to the Internet
|
||||
#internet=1
|
||||
|
||||
# Additional Step Required for Access
|
||||
# Note: This is only used with open network, i.e., ASRA shall ne set to 0 if
|
||||
# RSN is used.
|
||||
#asra=0
|
||||
|
||||
# Emergency services reachable
|
||||
#esr=0
|
||||
|
||||
# Unauthenticated emergency service accessible
|
||||
#uesa=0
|
||||
|
||||
# Venue Info (optional)
|
||||
# The available values are defined in IEEE Std 802.11u-2011, 7.3.1.34.
|
||||
# Example values (group,type):
|
||||
# 0,0 = Unspecified
|
||||
# 1,7 = Convention Center
|
||||
# 1,13 = Coffee Shop
|
||||
# 2,0 = Unspecified Business
|
||||
# 7,1 Private Residence
|
||||
#venue_group=7
|
||||
#venue_type=1
|
||||
|
||||
# Homogeneous ESS identifier (optional; dot11HESSID)
|
||||
# If set, this shall be identifical to one of the BSSIDs in the homogeneous
|
||||
# ESS and this shall be set to the same value across all BSSs in homogeneous
|
||||
# ESS.
|
||||
#hessid=02:03:04:05:06:07
|
||||
|
||||
# Roaming Consortium List
|
||||
# Arbitrary number of Roaming Consortium OIs can be configured with each line
|
||||
# adding a new OI to the list. The first three entries are available through
|
||||
# Beacon and Probe Response frames. Any additional entry will be available only
|
||||
# through ANQP queries. Each OI is between 3 and 15 octets and is configured as
|
||||
# a hexstring.
|
||||
#roaming_consortium=021122
|
||||
#roaming_consortium=2233445566
|
||||
|
||||
# Venue Name information
|
||||
# This parameter can be used to configure one or more Venue Name Duples for
|
||||
# Venue Name ANQP information. Each entry has a two or three character language
|
||||
# code (ISO-639) separated by colon from the venue name string.
|
||||
# Note that venue_group and venue_type have to be set for Venue Name
|
||||
# information to be complete.
|
||||
#venue_name=eng:Example venue
|
||||
#venue_name=fin:Esimerkkipaikka
|
||||
|
||||
# Network Authentication Type
|
||||
# This parameter indicates what type of network authentication is used in the
|
||||
# network.
|
||||
# format: <network auth type indicator (1-octet hex str)> [redirect URL]
|
||||
# Network Authentication Type Indicator values:
|
||||
# 00 = Acceptance of terms and conditions
|
||||
# 01 = On-line enrollment supported
|
||||
# 02 = http/https redirection
|
||||
# 03 = DNS redirection
|
||||
#network_auth_type=00
|
||||
#network_auth_type=02http://www.example.com/redirect/me/here/
|
||||
|
||||
# IP Address Type Availability
|
||||
# format: <1-octet encoded value as hex str>
|
||||
# (ipv4_type & 0x3f) << 2 | (ipv6_type & 0x3)
|
||||
# ipv4_type:
|
||||
# 0 = Address type not available
|
||||
# 1 = Public IPv4 address available
|
||||
# 2 = Port-restricted IPv4 address available
|
||||
# 3 = Single NATed private IPv4 address available
|
||||
# 4 = Double NATed private IPv4 address available
|
||||
# 5 = Port-restricted IPv4 address and single NATed IPv4 address available
|
||||
# 6 = Port-restricted IPv4 address and double NATed IPv4 address available
|
||||
# 7 = Availability of the address type is not known
|
||||
# ipv6_type:
|
||||
# 0 = Address type not available
|
||||
# 1 = Address type available
|
||||
# 2 = Availability of the address type not known
|
||||
#ipaddr_type_availability=14
|
||||
|
||||
# Domain Name
|
||||
# format: <variable-octet str>[,<variable-octet str>]
|
||||
#domain_name=example.com,another.example.com,yet-another.example.com
|
||||
|
||||
# 3GPP Cellular Network information
|
||||
# format: <MCC1,MNC1>[;<MCC2,MNC2>][;...]
|
||||
#anqp_3gpp_cell_net=244,91;310,026;234,56
|
||||
|
||||
# NAI Realm information
|
||||
# One or more realm can be advertised. Each nai_realm line adds a new realm to
|
||||
# the set. These parameters provide information for stations using Interworking
|
||||
# network selection to allow automatic connection to a network based on
|
||||
# credentials.
|
||||
# format: <encoding>,<NAI Realm(s)>[,<EAP Method 1>][,<EAP Method 2>][,...]
|
||||
# encoding:
|
||||
# 0 = Realm formatted in accordance with IETF RFC 4282
|
||||
# 1 = UTF-8 formatted character string that is not formatted in
|
||||
# accordance with IETF RFC 4282
|
||||
# NAI Realm(s): Semi-colon delimited NAI Realm(s)
|
||||
# EAP Method: <EAP Method>[:<[AuthParam1:Val1]>][<[AuthParam2:Val2]>][...]
|
||||
# AuthParam (Table 8-188 in IEEE Std 802.11-2012):
|
||||
# ID 2 = Non-EAP Inner Authentication Type
|
||||
# 1 = PAP, 2 = CHAP, 3 = MSCHAP, 4 = MSCHAPV2
|
||||
# ID 3 = Inner authentication EAP Method Type
|
||||
# ID 5 = Credential Type
|
||||
# 1 = SIM, 2 = USIM, 3 = NFC Secure Element, 4 = Hardware Token,
|
||||
# 5 = Softoken, 6 = Certificate, 7 = username/password, 9 = Anonymous,
|
||||
# 10 = Vendor Specific
|
||||
#nai_realm=0,example.com;example.net
|
||||
# EAP methods EAP-TLS with certificate and EAP-TTLS/MSCHAPv2 with
|
||||
# username/password
|
||||
#nai_realm=0,example.org,13[5:6],21[2:4][5:7]
|
||||
|
||||
##### Hotspot 2.0 #############################################################
|
||||
|
||||
# Enable Hotspot 2.0 support
|
||||
#hs20=1
|
||||
|
||||
# Disable Downstream Group-Addressed Forwarding (DGAF)
|
||||
# This can be used to configure a network where no group-addressed frames are
|
||||
# allowed. The AP will not forward any group-address frames to the stations and
|
||||
# random GTKs are issued for each station to prevent associated stations from
|
||||
# forging such frames to other stations in the BSS.
|
||||
#disable_dgaf=1
|
||||
|
||||
# Operator Friendly Name
|
||||
# This parameter can be used to configure one or more Operator Friendly Name
|
||||
# Duples. Each entry has a two or three character language code (ISO-639)
|
||||
# separated by colon from the operator friendly name string.
|
||||
#hs20_oper_friendly_name=eng:Example operator
|
||||
#hs20_oper_friendly_name=fin:Esimerkkioperaattori
|
||||
|
||||
# Connection Capability
|
||||
# This can be used to advertise what type of IP traffic can be sent through the
|
||||
# hotspot (e.g., due to firewall allowing/blocking protocols/ports).
|
||||
# format: <IP Protocol>:<Port Number>:<Status>
|
||||
# IP Protocol: 1 = ICMP, 6 = TCP, 17 = UDP
|
||||
# Port Number: 0..65535
|
||||
# Status: 0 = Closed, 1 = Open, 2 = Unknown
|
||||
# Each hs20_conn_capab line is added to the list of advertised tuples.
|
||||
#hs20_conn_capab=1:0:2
|
||||
#hs20_conn_capab=6:22:1
|
||||
#hs20_conn_capab=17:5060:0
|
||||
|
||||
# WAN Metrics
|
||||
# format: <WAN Info>:<DL Speed>:<UL Speed>:<DL Load>:<UL Load>:<LMD>
|
||||
# WAN Info: B0-B1: Link Status, B2: Symmetric Link, B3: At Capabity
|
||||
# (encoded as two hex digits)
|
||||
# Link Status: 1 = Link up, 2 = Link down, 3 = Link in test state
|
||||
# Downlink Speed: Estimate of WAN backhaul link current downlink speed in kbps;
|
||||
# 1..4294967295; 0 = unknown
|
||||
# Uplink Speed: Estimate of WAN backhaul link current uplink speed in kbps
|
||||
# 1..4294967295; 0 = unknown
|
||||
# Downlink Load: Current load of downlink WAN connection (scaled to 255 = 100%)
|
||||
# Uplink Load: Current load of uplink WAN connection (scaled to 255 = 100%)
|
||||
# Load Measurement Duration: Duration for measuring downlink/uplink load in
|
||||
# tenths of a second (1..65535); 0 if load cannot be determined
|
||||
#hs20_wan_metrics=01:8000:1000:80:240:3000
|
||||
|
||||
# Operating Class Indication
|
||||
# List of operating classes the BSSes in this ESS use. The Global operating
|
||||
# classes in Table E-4 of IEEE Std 802.11-2012 Annex E define the values that
|
||||
# can be used in this.
|
||||
# format: hexdump of operating class octets
|
||||
# for example, operating classes 81 (2.4 GHz channels 1-13) and 115 (5 GHz
|
||||
# channels 36-48):
|
||||
#hs20_operating_class=5173
|
||||
|
||||
##### Multiple BSSID support ##################################################
|
||||
#
|
||||
# Above configuration is using the default interface (wlan#, or multi-SSID VLAN
|
||||
|
@ -69,6 +69,9 @@
|
||||
"3"* SIM,TTLS,TLS,PEAP,AKA
|
||||
"4"* AKA,TTLS,TLS,PEAP,SIM
|
||||
"5"* SIM,TTLS,TLS,PEAP,AKA
|
||||
"6"* AKA'
|
||||
"7"* AKA'
|
||||
"8"* AKA'
|
||||
|
||||
# Wildcard for all other identities
|
||||
* PEAP,TTLS,TLS,SIM,AKA
|
||||
@ -89,3 +92,6 @@
|
||||
"3"* SIM [2]
|
||||
"4"* AKA [2]
|
||||
"5"* SIM [2]
|
||||
"6"* AKA' [2]
|
||||
"7"* AKA' [2]
|
||||
"8"* AKA' [2]
|
||||
|
17
contrib/wpa/hostapd/hostapd.eap_user_sqlite
Normal file
17
contrib/wpa/hostapd/hostapd.eap_user_sqlite
Normal file
@ -0,0 +1,17 @@
|
||||
CREATE TABLE users(
|
||||
identity TEXT PRIMARY KEY,
|
||||
methods TEXT,
|
||||
password TEXT,
|
||||
phase2 INTEGER
|
||||
);
|
||||
|
||||
CREATE TABLE wildcards(
|
||||
identity TEXT PRIMARY KEY,
|
||||
methods TEXT
|
||||
);
|
||||
|
||||
INSERT INTO users(identity,methods,password,phase2) VALUES ('user','TTLS-MSCHAPV2','password',1);
|
||||
INSERT INTO users(identity,methods,password,phase2) VALUES ('DOMAIN\mschapv2 user','TTLS-MSCHAPV2','password',1);
|
||||
|
||||
INSERT INTO wildcards(identity,methods) VALUES ('','TTLS,TLS');
|
||||
INSERT INTO wildcards(identity,methods) VALUES ('0','AKA');
|
@ -1,53 +1,32 @@
|
||||
/*
|
||||
* hostapd - command line interface for hostapd daemon
|
||||
* Copyright (c) 2004-2010, Jouni Malinen <j@w1.fi>
|
||||
* Copyright (c) 2004-2012, Jouni Malinen <j@w1.fi>
|
||||
*
|
||||
* This program is free software; you can redistribute it and/or modify
|
||||
* it under the terms of the GNU General Public License version 2 as
|
||||
* published by the Free Software Foundation.
|
||||
*
|
||||
* Alternatively, this software may be distributed under the terms of BSD
|
||||
* license.
|
||||
*
|
||||
* See README and COPYING for more details.
|
||||
* This software may be distributed under the terms of the BSD license.
|
||||
* See README for more details.
|
||||
*/
|
||||
|
||||
#include "includes.h"
|
||||
#include <dirent.h>
|
||||
|
||||
#include "common/wpa_ctrl.h"
|
||||
#include "common.h"
|
||||
#include "utils/common.h"
|
||||
#include "utils/eloop.h"
|
||||
#include "utils/edit.h"
|
||||
#include "common/version.h"
|
||||
|
||||
|
||||
static const char *hostapd_cli_version =
|
||||
"hostapd_cli v" VERSION_STR "\n"
|
||||
"Copyright (c) 2004-2010, Jouni Malinen <j@w1.fi> and contributors";
|
||||
"Copyright (c) 2004-2012, Jouni Malinen <j@w1.fi> and contributors";
|
||||
|
||||
|
||||
static const char *hostapd_cli_license =
|
||||
"This program is free software. You can distribute it and/or modify it\n"
|
||||
"under the terms of the GNU General Public License version 2.\n"
|
||||
"\n"
|
||||
"Alternatively, this software may be distributed under the terms of the\n"
|
||||
"BSD license. See README and COPYING for more details.\n";
|
||||
"This software may be distributed under the terms of the BSD license.\n"
|
||||
"See README for more details.\n";
|
||||
|
||||
static const char *hostapd_cli_full_license =
|
||||
"This program is free software; you can redistribute it and/or modify\n"
|
||||
"it under the terms of the GNU General Public License version 2 as\n"
|
||||
"published by the Free Software Foundation.\n"
|
||||
"\n"
|
||||
"This program is distributed in the hope that it will be useful,\n"
|
||||
"but WITHOUT ANY WARRANTY; without even the implied warranty of\n"
|
||||
"MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the\n"
|
||||
"GNU General Public License for more details.\n"
|
||||
"\n"
|
||||
"You should have received a copy of the GNU General Public License\n"
|
||||
"along with this program; if not, write to the Free Software\n"
|
||||
"Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA\n"
|
||||
"\n"
|
||||
"Alternatively, this software may be distributed under the terms of the\n"
|
||||
"BSD license.\n"
|
||||
"This software may be distributed under the terms of the BSD license.\n"
|
||||
"\n"
|
||||
"Redistribution and use in source and binary forms, with or without\n"
|
||||
"modification, are permitted provided that the following conditions are\n"
|
||||
@ -89,13 +68,19 @@ static const char *commands_help =
|
||||
" sa_query <addr> send SA Query to a station\n"
|
||||
#endif /* CONFIG_IEEE80211W */
|
||||
#ifdef CONFIG_WPS
|
||||
" wps_pin <uuid> <pin> [timeout] add WPS Enrollee PIN (Device Password)\n"
|
||||
" wps_pin <uuid> <pin> [timeout] [addr] add WPS Enrollee PIN\n"
|
||||
" wps_check_pin <PIN> verify PIN checksum\n"
|
||||
" wps_pbc indicate button pushed to initiate PBC\n"
|
||||
#ifdef CONFIG_WPS_OOB
|
||||
" wps_oob <type> <path> <method> use WPS with out-of-band (UFD)\n"
|
||||
#endif /* CONFIG_WPS_OOB */
|
||||
" wps_cancel cancel the pending WPS operation\n"
|
||||
#ifdef CONFIG_WPS_NFC
|
||||
" wps_nfc_tag_read <hexdump> report read NFC tag with WPS data\n"
|
||||
" wps_nfc_config_token <WPS/NDEF> build NFC configuration token\n"
|
||||
" wps_nfc_token <WPS/NDEF/enable/disable> manager NFC password token\n"
|
||||
#endif /* CONFIG_WPS_NFC */
|
||||
" wps_ap_pin <cmd> [params..] enable/disable AP PIN\n"
|
||||
" wps_config <SSID> <auth> <encr> <key> configure AP\n"
|
||||
#endif /* CONFIG_WPS */
|
||||
" get_config show current configuration\n"
|
||||
" help show this usage help\n"
|
||||
" interface [ifname] show interfaces/select interface\n"
|
||||
" level <debug level> change debug level\n"
|
||||
@ -110,6 +95,7 @@ static char *ctrl_ifname = NULL;
|
||||
static const char *pid_file = NULL;
|
||||
static const char *action_file = NULL;
|
||||
static int ping_interval = 5;
|
||||
static int interactive = 0;
|
||||
|
||||
|
||||
static void usage(void)
|
||||
@ -218,6 +204,12 @@ static int hostapd_cli_cmd_ping(struct wpa_ctrl *ctrl, int argc, char *argv[])
|
||||
}
|
||||
|
||||
|
||||
static int hostapd_cli_cmd_relog(struct wpa_ctrl *ctrl, int argc, char *argv[])
|
||||
{
|
||||
return wpa_ctrl_command(ctrl, "RELOG");
|
||||
}
|
||||
|
||||
|
||||
static int hostapd_cli_cmd_mib(struct wpa_ctrl *ctrl, int argc, char *argv[])
|
||||
{
|
||||
return wpa_ctrl_command(ctrl, "MIB");
|
||||
@ -352,13 +344,16 @@ static int hostapd_cli_cmd_sa_query(struct wpa_ctrl *ctrl, int argc,
|
||||
static int hostapd_cli_cmd_wps_pin(struct wpa_ctrl *ctrl, int argc,
|
||||
char *argv[])
|
||||
{
|
||||
char buf[64];
|
||||
char buf[256];
|
||||
if (argc < 2) {
|
||||
printf("Invalid 'wps_pin' command - at least two arguments, "
|
||||
"UUID and PIN, are required.\n");
|
||||
return -1;
|
||||
}
|
||||
if (argc > 2)
|
||||
if (argc > 3)
|
||||
snprintf(buf, sizeof(buf), "WPS_PIN %s %s %s %s",
|
||||
argv[0], argv[1], argv[2], argv[3]);
|
||||
else if (argc > 2)
|
||||
snprintf(buf, sizeof(buf), "WPS_PIN %s %s %s",
|
||||
argv[0], argv[1], argv[2]);
|
||||
else
|
||||
@ -367,6 +362,32 @@ static int hostapd_cli_cmd_wps_pin(struct wpa_ctrl *ctrl, int argc,
|
||||
}
|
||||
|
||||
|
||||
static int hostapd_cli_cmd_wps_check_pin(struct wpa_ctrl *ctrl, int argc,
|
||||
char *argv[])
|
||||
{
|
||||
char cmd[256];
|
||||
int res;
|
||||
|
||||
if (argc != 1 && argc != 2) {
|
||||
printf("Invalid WPS_CHECK_PIN command: needs one argument:\n"
|
||||
"- PIN to be verified\n");
|
||||
return -1;
|
||||
}
|
||||
|
||||
if (argc == 2)
|
||||
res = os_snprintf(cmd, sizeof(cmd), "WPS_CHECK_PIN %s %s",
|
||||
argv[0], argv[1]);
|
||||
else
|
||||
res = os_snprintf(cmd, sizeof(cmd), "WPS_CHECK_PIN %s",
|
||||
argv[0]);
|
||||
if (res < 0 || (size_t) res >= sizeof(cmd) - 1) {
|
||||
printf("Too long WPS_CHECK_PIN command.\n");
|
||||
return -1;
|
||||
}
|
||||
return wpa_ctrl_command(ctrl, cmd);
|
||||
}
|
||||
|
||||
|
||||
static int hostapd_cli_cmd_wps_pbc(struct wpa_ctrl *ctrl, int argc,
|
||||
char *argv[])
|
||||
{
|
||||
@ -374,38 +395,82 @@ static int hostapd_cli_cmd_wps_pbc(struct wpa_ctrl *ctrl, int argc,
|
||||
}
|
||||
|
||||
|
||||
#ifdef CONFIG_WPS_OOB
|
||||
static int hostapd_cli_cmd_wps_oob(struct wpa_ctrl *ctrl, int argc,
|
||||
char *argv[])
|
||||
static int hostapd_cli_cmd_wps_cancel(struct wpa_ctrl *ctrl, int argc,
|
||||
char *argv[])
|
||||
{
|
||||
char cmd[256];
|
||||
int res;
|
||||
return wpa_ctrl_command(ctrl, "WPS_CANCEL");
|
||||
}
|
||||
|
||||
if (argc != 3 && argc != 4) {
|
||||
printf("Invalid WPS_OOB command: need three or four "
|
||||
"arguments:\n"
|
||||
"- DEV_TYPE: use 'ufd' or 'nfc'\n"
|
||||
"- PATH: path of OOB device like '/mnt'\n"
|
||||
"- METHOD: OOB method 'pin-e' or 'pin-r', "
|
||||
"'cred'\n"
|
||||
"- DEV_NAME: (only for NFC) device name like "
|
||||
"'pn531'\n");
|
||||
|
||||
#ifdef CONFIG_WPS_NFC
|
||||
static int hostapd_cli_cmd_wps_nfc_tag_read(struct wpa_ctrl *ctrl, int argc,
|
||||
char *argv[])
|
||||
{
|
||||
int ret;
|
||||
char *buf;
|
||||
size_t buflen;
|
||||
|
||||
if (argc != 1) {
|
||||
printf("Invalid 'wps_nfc_tag_read' command - one argument "
|
||||
"is required.\n");
|
||||
return -1;
|
||||
}
|
||||
|
||||
if (argc == 3)
|
||||
res = os_snprintf(cmd, sizeof(cmd), "WPS_OOB %s %s %s",
|
||||
argv[0], argv[1], argv[2]);
|
||||
else
|
||||
res = os_snprintf(cmd, sizeof(cmd), "WPS_OOB %s %s %s %s",
|
||||
argv[0], argv[1], argv[2], argv[3]);
|
||||
buflen = 18 + os_strlen(argv[0]);
|
||||
buf = os_malloc(buflen);
|
||||
if (buf == NULL)
|
||||
return -1;
|
||||
os_snprintf(buf, buflen, "WPS_NFC_TAG_READ %s", argv[0]);
|
||||
|
||||
ret = wpa_ctrl_command(ctrl, buf);
|
||||
os_free(buf);
|
||||
|
||||
return ret;
|
||||
}
|
||||
|
||||
|
||||
static int hostapd_cli_cmd_wps_nfc_config_token(struct wpa_ctrl *ctrl,
|
||||
int argc, char *argv[])
|
||||
{
|
||||
char cmd[64];
|
||||
int res;
|
||||
|
||||
if (argc != 1) {
|
||||
printf("Invalid 'wps_nfc_config_token' command - one argument "
|
||||
"is required.\n");
|
||||
return -1;
|
||||
}
|
||||
|
||||
res = os_snprintf(cmd, sizeof(cmd), "WPS_NFC_CONFIG_TOKEN %s",
|
||||
argv[0]);
|
||||
if (res < 0 || (size_t) res >= sizeof(cmd) - 1) {
|
||||
printf("Too long WPS_OOB command.\n");
|
||||
printf("Too long WPS_NFC_CONFIG_TOKEN command.\n");
|
||||
return -1;
|
||||
}
|
||||
return wpa_ctrl_command(ctrl, cmd);
|
||||
}
|
||||
#endif /* CONFIG_WPS_OOB */
|
||||
|
||||
|
||||
static int hostapd_cli_cmd_wps_nfc_token(struct wpa_ctrl *ctrl,
|
||||
int argc, char *argv[])
|
||||
{
|
||||
char cmd[64];
|
||||
int res;
|
||||
|
||||
if (argc != 1) {
|
||||
printf("Invalid 'wps_nfc_token' command - one argument is "
|
||||
"required.\n");
|
||||
return -1;
|
||||
}
|
||||
|
||||
res = os_snprintf(cmd, sizeof(cmd), "WPS_NFC_TOKEN %s", argv[0]);
|
||||
if (res < 0 || (size_t) res >= sizeof(cmd) - 1) {
|
||||
printf("Too long WPS_NFC_TOKEN command.\n");
|
||||
return -1;
|
||||
}
|
||||
return wpa_ctrl_command(ctrl, cmd);
|
||||
}
|
||||
#endif /* CONFIG_WPS_NFC */
|
||||
|
||||
|
||||
static int hostapd_cli_cmd_wps_ap_pin(struct wpa_ctrl *ctrl, int argc,
|
||||
@ -427,9 +492,100 @@ static int hostapd_cli_cmd_wps_ap_pin(struct wpa_ctrl *ctrl, int argc,
|
||||
snprintf(buf, sizeof(buf), "WPS_AP_PIN %s", argv[0]);
|
||||
return wpa_ctrl_command(ctrl, buf);
|
||||
}
|
||||
|
||||
|
||||
static int hostapd_cli_cmd_wps_config(struct wpa_ctrl *ctrl, int argc,
|
||||
char *argv[])
|
||||
{
|
||||
char buf[256];
|
||||
char ssid_hex[2 * 32 + 1];
|
||||
char key_hex[2 * 64 + 1];
|
||||
int i;
|
||||
|
||||
if (argc < 1) {
|
||||
printf("Invalid 'wps_config' command - at least two arguments "
|
||||
"are required.\n");
|
||||
return -1;
|
||||
}
|
||||
|
||||
ssid_hex[0] = '\0';
|
||||
for (i = 0; i < 32; i++) {
|
||||
if (argv[0][i] == '\0')
|
||||
break;
|
||||
os_snprintf(&ssid_hex[i * 2], 3, "%02x", argv[0][i]);
|
||||
}
|
||||
|
||||
key_hex[0] = '\0';
|
||||
if (argc > 3) {
|
||||
for (i = 0; i < 64; i++) {
|
||||
if (argv[3][i] == '\0')
|
||||
break;
|
||||
os_snprintf(&key_hex[i * 2], 3, "%02x",
|
||||
argv[3][i]);
|
||||
}
|
||||
}
|
||||
|
||||
if (argc > 3)
|
||||
snprintf(buf, sizeof(buf), "WPS_CONFIG %s %s %s %s",
|
||||
ssid_hex, argv[1], argv[2], key_hex);
|
||||
else if (argc > 2)
|
||||
snprintf(buf, sizeof(buf), "WPS_CONFIG %s %s %s",
|
||||
ssid_hex, argv[1], argv[2]);
|
||||
else
|
||||
snprintf(buf, sizeof(buf), "WPS_CONFIG %s %s",
|
||||
ssid_hex, argv[1]);
|
||||
return wpa_ctrl_command(ctrl, buf);
|
||||
}
|
||||
#endif /* CONFIG_WPS */
|
||||
|
||||
|
||||
static int hostapd_cli_cmd_disassoc_imminent(struct wpa_ctrl *ctrl, int argc,
|
||||
char *argv[])
|
||||
{
|
||||
char buf[300];
|
||||
int res;
|
||||
|
||||
if (argc < 2) {
|
||||
printf("Invalid 'disassoc_imminent' command - two arguments "
|
||||
"(STA addr and Disassociation Timer) are needed\n");
|
||||
return -1;
|
||||
}
|
||||
|
||||
res = os_snprintf(buf, sizeof(buf), "DISASSOC_IMMINENT %s %s",
|
||||
argv[0], argv[1]);
|
||||
if (res < 0 || res >= (int) sizeof(buf))
|
||||
return -1;
|
||||
return wpa_ctrl_command(ctrl, buf);
|
||||
}
|
||||
|
||||
|
||||
static int hostapd_cli_cmd_ess_disassoc(struct wpa_ctrl *ctrl, int argc,
|
||||
char *argv[])
|
||||
{
|
||||
char buf[300];
|
||||
int res;
|
||||
|
||||
if (argc < 2) {
|
||||
printf("Invalid 'ess_disassoc' command - two arguments (STA "
|
||||
"addr and URL) are needed\n");
|
||||
return -1;
|
||||
}
|
||||
|
||||
res = os_snprintf(buf, sizeof(buf), "ESS_DISASSOC %s %s",
|
||||
argv[0], argv[1]);
|
||||
if (res < 0 || res >= (int) sizeof(buf))
|
||||
return -1;
|
||||
return wpa_ctrl_command(ctrl, buf);
|
||||
}
|
||||
|
||||
|
||||
static int hostapd_cli_cmd_get_config(struct wpa_ctrl *ctrl, int argc,
|
||||
char *argv[])
|
||||
{
|
||||
return wpa_ctrl_command(ctrl, "GET_CONFIG");
|
||||
}
|
||||
|
||||
|
||||
static int wpa_ctrl_command_sta(struct wpa_ctrl *ctrl, char *cmd,
|
||||
char *addr, size_t addr_len)
|
||||
{
|
||||
@ -499,6 +655,8 @@ static int hostapd_cli_cmd_license(struct wpa_ctrl *ctrl, int argc,
|
||||
static int hostapd_cli_cmd_quit(struct wpa_ctrl *ctrl, int argc, char *argv[])
|
||||
{
|
||||
hostapd_cli_quit = 1;
|
||||
if (interactive)
|
||||
eloop_terminate();
|
||||
return 0;
|
||||
}
|
||||
|
||||
@ -567,6 +725,46 @@ static int hostapd_cli_cmd_interface(struct wpa_ctrl *ctrl, int argc,
|
||||
}
|
||||
|
||||
|
||||
static int hostapd_cli_cmd_set(struct wpa_ctrl *ctrl, int argc, char *argv[])
|
||||
{
|
||||
char cmd[256];
|
||||
int res;
|
||||
|
||||
if (argc != 2) {
|
||||
printf("Invalid SET command: needs two arguments (variable "
|
||||
"name and value)\n");
|
||||
return -1;
|
||||
}
|
||||
|
||||
res = os_snprintf(cmd, sizeof(cmd), "SET %s %s", argv[0], argv[1]);
|
||||
if (res < 0 || (size_t) res >= sizeof(cmd) - 1) {
|
||||
printf("Too long SET command.\n");
|
||||
return -1;
|
||||
}
|
||||
return wpa_ctrl_command(ctrl, cmd);
|
||||
}
|
||||
|
||||
|
||||
static int hostapd_cli_cmd_get(struct wpa_ctrl *ctrl, int argc, char *argv[])
|
||||
{
|
||||
char cmd[256];
|
||||
int res;
|
||||
|
||||
if (argc != 1) {
|
||||
printf("Invalid GET command: needs one argument (variable "
|
||||
"name)\n");
|
||||
return -1;
|
||||
}
|
||||
|
||||
res = os_snprintf(cmd, sizeof(cmd), "GET %s", argv[0]);
|
||||
if (res < 0 || (size_t) res >= sizeof(cmd) - 1) {
|
||||
printf("Too long GET command.\n");
|
||||
return -1;
|
||||
}
|
||||
return wpa_ctrl_command(ctrl, cmd);
|
||||
}
|
||||
|
||||
|
||||
struct hostapd_cli_cmd {
|
||||
const char *cmd;
|
||||
int (*handler)(struct wpa_ctrl *ctrl, int argc, char *argv[]);
|
||||
@ -575,6 +773,7 @@ struct hostapd_cli_cmd {
|
||||
static struct hostapd_cli_cmd hostapd_cli_commands[] = {
|
||||
{ "ping", hostapd_cli_cmd_ping },
|
||||
{ "mib", hostapd_cli_cmd_mib },
|
||||
{ "relog", hostapd_cli_cmd_relog },
|
||||
{ "sta", hostapd_cli_cmd_sta },
|
||||
{ "all_sta", hostapd_cli_cmd_all_sta },
|
||||
{ "new_sta", hostapd_cli_cmd_new_sta },
|
||||
@ -585,17 +784,27 @@ static struct hostapd_cli_cmd hostapd_cli_commands[] = {
|
||||
#endif /* CONFIG_IEEE80211W */
|
||||
#ifdef CONFIG_WPS
|
||||
{ "wps_pin", hostapd_cli_cmd_wps_pin },
|
||||
{ "wps_check_pin", hostapd_cli_cmd_wps_check_pin },
|
||||
{ "wps_pbc", hostapd_cli_cmd_wps_pbc },
|
||||
#ifdef CONFIG_WPS_OOB
|
||||
{ "wps_oob", hostapd_cli_cmd_wps_oob },
|
||||
#endif /* CONFIG_WPS_OOB */
|
||||
{ "wps_cancel", hostapd_cli_cmd_wps_cancel },
|
||||
#ifdef CONFIG_WPS_NFC
|
||||
{ "wps_nfc_tag_read", hostapd_cli_cmd_wps_nfc_tag_read },
|
||||
{ "wps_nfc_config_token", hostapd_cli_cmd_wps_nfc_config_token },
|
||||
{ "wps_nfc_token", hostapd_cli_cmd_wps_nfc_token },
|
||||
#endif /* CONFIG_WPS_NFC */
|
||||
{ "wps_ap_pin", hostapd_cli_cmd_wps_ap_pin },
|
||||
{ "wps_config", hostapd_cli_cmd_wps_config },
|
||||
#endif /* CONFIG_WPS */
|
||||
{ "disassoc_imminent", hostapd_cli_cmd_disassoc_imminent },
|
||||
{ "ess_disassoc", hostapd_cli_cmd_ess_disassoc },
|
||||
{ "get_config", hostapd_cli_cmd_get_config },
|
||||
{ "help", hostapd_cli_cmd_help },
|
||||
{ "interface", hostapd_cli_cmd_interface },
|
||||
{ "level", hostapd_cli_cmd_level },
|
||||
{ "license", hostapd_cli_cmd_license },
|
||||
{ "quit", hostapd_cli_cmd_quit },
|
||||
{ "set", hostapd_cli_cmd_set },
|
||||
{ "get", hostapd_cli_cmd_get },
|
||||
{ NULL, NULL }
|
||||
};
|
||||
|
||||
@ -610,6 +819,11 @@ static void wpa_request(struct wpa_ctrl *ctrl, int argc, char *argv[])
|
||||
while (cmd->cmd) {
|
||||
if (strncasecmp(cmd->cmd, argv[0], strlen(argv[0])) == 0) {
|
||||
match = cmd;
|
||||
if (os_strcasecmp(cmd->cmd, argv[0]) == 0) {
|
||||
/* we have an exact match */
|
||||
count = 1;
|
||||
break;
|
||||
}
|
||||
count++;
|
||||
}
|
||||
cmd++;
|
||||
@ -661,70 +875,39 @@ static void hostapd_cli_recv_pending(struct wpa_ctrl *ctrl, int in_read,
|
||||
}
|
||||
|
||||
|
||||
static void hostapd_cli_interactive(void)
|
||||
#define max_args 10
|
||||
|
||||
static int tokenize_cmd(char *cmd, char *argv[])
|
||||
{
|
||||
const int max_args = 10;
|
||||
char cmd[256], *res, *argv[max_args], *pos;
|
||||
int argc;
|
||||
char *pos;
|
||||
int argc = 0;
|
||||
|
||||
printf("\nInteractive mode\n\n");
|
||||
|
||||
do {
|
||||
hostapd_cli_recv_pending(ctrl_conn, 0, 0);
|
||||
printf("> ");
|
||||
alarm(ping_interval);
|
||||
res = fgets(cmd, sizeof(cmd), stdin);
|
||||
alarm(0);
|
||||
if (res == NULL)
|
||||
break;
|
||||
pos = cmd;
|
||||
while (*pos != '\0') {
|
||||
if (*pos == '\n') {
|
||||
*pos = '\0';
|
||||
break;
|
||||
}
|
||||
pos = cmd;
|
||||
for (;;) {
|
||||
while (*pos == ' ')
|
||||
pos++;
|
||||
if (*pos == '\0')
|
||||
break;
|
||||
argv[argc] = pos;
|
||||
argc++;
|
||||
if (argc == max_args)
|
||||
break;
|
||||
if (*pos == '"') {
|
||||
char *pos2 = os_strrchr(pos, '"');
|
||||
if (pos2)
|
||||
pos = pos2 + 1;
|
||||
}
|
||||
argc = 0;
|
||||
pos = cmd;
|
||||
for (;;) {
|
||||
while (*pos == ' ')
|
||||
pos++;
|
||||
if (*pos == '\0')
|
||||
break;
|
||||
argv[argc] = pos;
|
||||
argc++;
|
||||
if (argc == max_args)
|
||||
break;
|
||||
while (*pos != '\0' && *pos != ' ')
|
||||
pos++;
|
||||
if (*pos == ' ')
|
||||
*pos++ = '\0';
|
||||
}
|
||||
if (argc)
|
||||
wpa_request(ctrl_conn, argc, argv);
|
||||
} while (!hostapd_cli_quit);
|
||||
while (*pos != '\0' && *pos != ' ')
|
||||
pos++;
|
||||
if (*pos == ' ')
|
||||
*pos++ = '\0';
|
||||
}
|
||||
|
||||
return argc;
|
||||
}
|
||||
|
||||
|
||||
static void hostapd_cli_cleanup(void)
|
||||
{
|
||||
hostapd_cli_close_connection();
|
||||
if (pid_file)
|
||||
os_daemonize_terminate(pid_file);
|
||||
|
||||
os_program_deinit();
|
||||
}
|
||||
|
||||
|
||||
static void hostapd_cli_terminate(int sig)
|
||||
{
|
||||
hostapd_cli_cleanup();
|
||||
exit(0);
|
||||
}
|
||||
|
||||
|
||||
static void hostapd_cli_alarm(int sig)
|
||||
static void hostapd_cli_ping(void *eloop_ctx, void *timeout_ctx)
|
||||
{
|
||||
if (ctrl_conn && _wpa_ctrl_command(ctrl_conn, "PING", 0)) {
|
||||
printf("Connection to hostapd lost - trying to reconnect\n");
|
||||
@ -744,7 +927,55 @@ static void hostapd_cli_alarm(int sig)
|
||||
}
|
||||
if (ctrl_conn)
|
||||
hostapd_cli_recv_pending(ctrl_conn, 1, 0);
|
||||
alarm(ping_interval);
|
||||
eloop_register_timeout(ping_interval, 0, hostapd_cli_ping, NULL, NULL);
|
||||
}
|
||||
|
||||
|
||||
static void hostapd_cli_eloop_terminate(int sig, void *signal_ctx)
|
||||
{
|
||||
eloop_terminate();
|
||||
}
|
||||
|
||||
|
||||
static void hostapd_cli_edit_cmd_cb(void *ctx, char *cmd)
|
||||
{
|
||||
char *argv[max_args];
|
||||
int argc;
|
||||
argc = tokenize_cmd(cmd, argv);
|
||||
if (argc)
|
||||
wpa_request(ctrl_conn, argc, argv);
|
||||
}
|
||||
|
||||
|
||||
static void hostapd_cli_edit_eof_cb(void *ctx)
|
||||
{
|
||||
eloop_terminate();
|
||||
}
|
||||
|
||||
|
||||
static void hostapd_cli_interactive(void)
|
||||
{
|
||||
printf("\nInteractive mode\n\n");
|
||||
|
||||
eloop_register_signal_terminate(hostapd_cli_eloop_terminate, NULL);
|
||||
edit_init(hostapd_cli_edit_cmd_cb, hostapd_cli_edit_eof_cb,
|
||||
NULL, NULL, NULL, NULL);
|
||||
eloop_register_timeout(ping_interval, 0, hostapd_cli_ping, NULL, NULL);
|
||||
|
||||
eloop_run();
|
||||
|
||||
edit_deinit(NULL, NULL);
|
||||
eloop_cancel_timeout(hostapd_cli_ping, NULL, NULL);
|
||||
}
|
||||
|
||||
|
||||
static void hostapd_cli_cleanup(void)
|
||||
{
|
||||
hostapd_cli_close_connection();
|
||||
if (pid_file)
|
||||
os_daemonize_terminate(pid_file);
|
||||
|
||||
os_program_deinit();
|
||||
}
|
||||
|
||||
|
||||
@ -787,7 +1018,6 @@ static void hostapd_cli_action(struct wpa_ctrl *ctrl)
|
||||
|
||||
int main(int argc, char *argv[])
|
||||
{
|
||||
int interactive;
|
||||
int warning_displayed = 0;
|
||||
int c;
|
||||
int daemonize = 0;
|
||||
@ -835,6 +1065,9 @@ int main(int argc, char *argv[])
|
||||
hostapd_cli_license);
|
||||
}
|
||||
|
||||
if (eloop_init())
|
||||
return -1;
|
||||
|
||||
for (;;) {
|
||||
if (ctrl_ifname == NULL) {
|
||||
struct dirent *dent;
|
||||
@ -874,10 +1107,6 @@ int main(int argc, char *argv[])
|
||||
continue;
|
||||
}
|
||||
|
||||
signal(SIGINT, hostapd_cli_terminate);
|
||||
signal(SIGTERM, hostapd_cli_terminate);
|
||||
signal(SIGALRM, hostapd_cli_alarm);
|
||||
|
||||
if (interactive || action_file) {
|
||||
if (wpa_ctrl_attach(ctrl_conn) == 0) {
|
||||
hostapd_cli_attached = 1;
|
||||
@ -899,6 +1128,7 @@ int main(int argc, char *argv[])
|
||||
wpa_request(ctrl_conn, argc - optind, &argv[optind]);
|
||||
|
||||
os_free(ctrl_ifname);
|
||||
eloop_destroy();
|
||||
hostapd_cli_cleanup();
|
||||
return 0;
|
||||
}
|
||||
|
@ -1,15 +1,9 @@
|
||||
/*
|
||||
* hostapd / main()
|
||||
* Copyright (c) 2002-2010, Jouni Malinen <j@w1.fi>
|
||||
* Copyright (c) 2002-2011, Jouni Malinen <j@w1.fi>
|
||||
*
|
||||
* This program is free software; you can redistribute it and/or modify
|
||||
* it under the terms of the GNU General Public License version 2 as
|
||||
* published by the Free Software Foundation.
|
||||
*
|
||||
* Alternatively, this software may be distributed under the terms of BSD
|
||||
* license.
|
||||
*
|
||||
* See README and COPYING for more details.
|
||||
* This software may be distributed under the terms of the BSD license.
|
||||
* See README for more details.
|
||||
*/
|
||||
|
||||
#include "utils/includes.h"
|
||||
@ -19,6 +13,7 @@
|
||||
|
||||
#include "utils/common.h"
|
||||
#include "utils/eloop.h"
|
||||
#include "crypto/random.h"
|
||||
#include "crypto/tls.h"
|
||||
#include "common/version.h"
|
||||
#include "drivers/driver.h"
|
||||
@ -26,6 +21,7 @@
|
||||
#include "eap_server/tncs.h"
|
||||
#include "ap/hostapd.h"
|
||||
#include "ap/ap_config.h"
|
||||
#include "ap/ap_drv_ops.h"
|
||||
#include "config_file.h"
|
||||
#include "eap_register.h"
|
||||
#include "dump_state.h"
|
||||
@ -36,28 +32,15 @@ extern int wpa_debug_level;
|
||||
extern int wpa_debug_show_keys;
|
||||
extern int wpa_debug_timestamp;
|
||||
|
||||
extern struct wpa_driver_ops *wpa_drivers[];
|
||||
|
||||
struct hapd_interfaces {
|
||||
size_t count;
|
||||
struct hostapd_iface **iface;
|
||||
|
||||
struct hapd_global {
|
||||
void **drv_priv;
|
||||
size_t drv_count;
|
||||
};
|
||||
|
||||
|
||||
static int hostapd_for_each_interface(struct hapd_interfaces *interfaces,
|
||||
int (*cb)(struct hostapd_iface *iface,
|
||||
void *ctx), void *ctx)
|
||||
{
|
||||
size_t i;
|
||||
int ret;
|
||||
|
||||
for (i = 0; i < interfaces->count; i++) {
|
||||
ret = cb(interfaces->iface[i], ctx);
|
||||
if (ret)
|
||||
return ret;
|
||||
}
|
||||
|
||||
return 0;
|
||||
}
|
||||
static struct hapd_global global;
|
||||
|
||||
|
||||
#ifndef CONFIG_NO_HOSTAPD_LOGGER
|
||||
@ -183,14 +166,9 @@ static struct hostapd_iface * hostapd_init(const char *config_file)
|
||||
if (hapd_iface == NULL)
|
||||
goto fail;
|
||||
|
||||
hapd_iface->reload_config = hostapd_reload_config;
|
||||
hapd_iface->config_read_cb = hostapd_config_read;
|
||||
hapd_iface->config_fname = os_strdup(config_file);
|
||||
if (hapd_iface->config_fname == NULL)
|
||||
goto fail;
|
||||
hapd_iface->ctrl_iface_init = hostapd_ctrl_iface_init;
|
||||
hapd_iface->ctrl_iface_deinit = hostapd_ctrl_iface_deinit;
|
||||
hapd_iface->for_each_interface = hostapd_for_each_interface;
|
||||
|
||||
conf = hostapd_config_read(hapd_iface->config_fname);
|
||||
if (conf == NULL)
|
||||
@ -198,7 +176,7 @@ static struct hostapd_iface * hostapd_init(const char *config_file)
|
||||
hapd_iface->conf = conf;
|
||||
|
||||
hapd_iface->num_bss = conf->num_bss;
|
||||
hapd_iface->bss = os_zalloc(conf->num_bss *
|
||||
hapd_iface->bss = os_calloc(conf->num_bss,
|
||||
sizeof(struct hostapd_data *));
|
||||
if (hapd_iface->bss == NULL)
|
||||
goto fail;
|
||||
@ -233,6 +211,7 @@ static int hostapd_driver_init(struct hostapd_iface *iface)
|
||||
struct hostapd_data *hapd = iface->bss[0];
|
||||
struct hostapd_bss_config *conf = hapd->conf;
|
||||
u8 *b = conf->bssid;
|
||||
struct wpa_driver_capa capa;
|
||||
|
||||
if (hapd->driver == NULL || hapd->driver->hapd_init == NULL) {
|
||||
wpa_printf(MSG_ERROR, "No hostapd driver wrapper available");
|
||||
@ -244,15 +223,33 @@ static int hostapd_driver_init(struct hostapd_iface *iface)
|
||||
b = NULL;
|
||||
|
||||
os_memset(¶ms, 0, sizeof(params));
|
||||
for (i = 0; wpa_drivers[i]; i++) {
|
||||
if (wpa_drivers[i] != hapd->driver)
|
||||
continue;
|
||||
|
||||
if (global.drv_priv[i] == NULL &&
|
||||
wpa_drivers[i]->global_init) {
|
||||
global.drv_priv[i] = wpa_drivers[i]->global_init();
|
||||
if (global.drv_priv[i] == NULL) {
|
||||
wpa_printf(MSG_ERROR, "Failed to initialize "
|
||||
"driver '%s'",
|
||||
wpa_drivers[i]->name);
|
||||
return -1;
|
||||
}
|
||||
}
|
||||
|
||||
params.global_priv = global.drv_priv[i];
|
||||
break;
|
||||
}
|
||||
params.bssid = b;
|
||||
params.ifname = hapd->conf->iface;
|
||||
params.ssid = (const u8 *) hapd->conf->ssid.ssid;
|
||||
params.ssid = hapd->conf->ssid.ssid;
|
||||
params.ssid_len = hapd->conf->ssid.ssid_len;
|
||||
params.test_socket = hapd->conf->test_socket;
|
||||
params.use_pae_group_addr = hapd->conf->use_pae_group_addr;
|
||||
|
||||
params.num_bridge = hapd->iface->num_bss;
|
||||
params.bridge = os_zalloc(hapd->iface->num_bss * sizeof(char *));
|
||||
params.bridge = os_calloc(hapd->iface->num_bss, sizeof(char *));
|
||||
if (params.bridge == NULL)
|
||||
return -1;
|
||||
for (i = 0; i < hapd->iface->num_bss; i++) {
|
||||
@ -272,25 +269,16 @@ static int hostapd_driver_init(struct hostapd_iface *iface)
|
||||
return -1;
|
||||
}
|
||||
|
||||
if (hapd->driver->get_capa &&
|
||||
hapd->driver->get_capa(hapd->drv_priv, &capa) == 0) {
|
||||
iface->drv_flags = capa.flags;
|
||||
iface->probe_resp_offloads = capa.probe_resp_offloads;
|
||||
}
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
|
||||
static void hostapd_interface_deinit_free(struct hostapd_iface *iface)
|
||||
{
|
||||
const struct wpa_driver_ops *driver;
|
||||
void *drv_priv;
|
||||
if (iface == NULL)
|
||||
return;
|
||||
driver = iface->bss[0]->driver;
|
||||
drv_priv = iface->bss[0]->drv_priv;
|
||||
hostapd_interface_deinit(iface);
|
||||
if (driver && driver->hapd_deinit)
|
||||
driver->hapd_deinit(drv_priv);
|
||||
hostapd_interface_free(iface);
|
||||
}
|
||||
|
||||
|
||||
static struct hostapd_iface *
|
||||
hostapd_interface_init(struct hapd_interfaces *interfaces,
|
||||
const char *config_fname, int debug)
|
||||
@ -309,10 +297,13 @@ hostapd_interface_init(struct hapd_interfaces *interfaces,
|
||||
iface->bss[0]->conf->logger_stdout_level--;
|
||||
}
|
||||
|
||||
if (hostapd_driver_init(iface) ||
|
||||
hostapd_setup_interface(iface)) {
|
||||
hostapd_interface_deinit_free(iface);
|
||||
return NULL;
|
||||
if (iface->conf->bss[0].iface[0] != 0 ||
|
||||
hostapd_drv_none(iface->bss[0])) {
|
||||
if (hostapd_driver_init(iface) ||
|
||||
hostapd_setup_interface(iface)) {
|
||||
hostapd_interface_deinit_free(iface);
|
||||
return NULL;
|
||||
}
|
||||
}
|
||||
|
||||
return iface;
|
||||
@ -363,8 +354,13 @@ static void handle_dump_state(int sig, void *signal_ctx)
|
||||
#endif /* CONFIG_NATIVE_WINDOWS */
|
||||
|
||||
|
||||
static int hostapd_global_init(struct hapd_interfaces *interfaces)
|
||||
static int hostapd_global_init(struct hapd_interfaces *interfaces,
|
||||
const char *entropy_file)
|
||||
{
|
||||
int i;
|
||||
|
||||
os_memset(&global, 0, sizeof(global));
|
||||
|
||||
hostapd_logger_register_cb(hostapd_logger_cb);
|
||||
|
||||
if (eap_server_register_methods()) {
|
||||
@ -377,6 +373,8 @@ static int hostapd_global_init(struct hapd_interfaces *interfaces)
|
||||
return -1;
|
||||
}
|
||||
|
||||
random_init(entropy_file);
|
||||
|
||||
#ifndef CONFIG_NATIVE_WINDOWS
|
||||
eloop_register_signal(SIGHUP, handle_reload, interfaces);
|
||||
eloop_register_signal(SIGUSR1, handle_dump_state, interfaces);
|
||||
@ -387,16 +385,38 @@ static int hostapd_global_init(struct hapd_interfaces *interfaces)
|
||||
openlog("hostapd", 0, LOG_DAEMON);
|
||||
#endif /* CONFIG_NATIVE_WINDOWS */
|
||||
|
||||
for (i = 0; wpa_drivers[i]; i++)
|
||||
global.drv_count++;
|
||||
if (global.drv_count == 0) {
|
||||
wpa_printf(MSG_ERROR, "No drivers enabled");
|
||||
return -1;
|
||||
}
|
||||
global.drv_priv = os_calloc(global.drv_count, sizeof(void *));
|
||||
if (global.drv_priv == NULL)
|
||||
return -1;
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
|
||||
static void hostapd_global_deinit(const char *pid_file)
|
||||
{
|
||||
int i;
|
||||
|
||||
for (i = 0; wpa_drivers[i] && global.drv_priv; i++) {
|
||||
if (!global.drv_priv[i])
|
||||
continue;
|
||||
wpa_drivers[i]->global_deinit(global.drv_priv[i]);
|
||||
}
|
||||
os_free(global.drv_priv);
|
||||
global.drv_priv = NULL;
|
||||
|
||||
#ifdef EAP_SERVER_TNC
|
||||
tncs_global_deinit();
|
||||
#endif /* EAP_SERVER_TNC */
|
||||
|
||||
random_deinit();
|
||||
|
||||
eloop_destroy();
|
||||
|
||||
#ifndef CONFIG_NATIVE_WINDOWS
|
||||
@ -448,7 +468,7 @@ static void show_version(void)
|
||||
"hostapd v" VERSION_STR "\n"
|
||||
"User space daemon for IEEE 802.11 AP management,\n"
|
||||
"IEEE 802.1X/WPA/WPA2/EAP/RADIUS Authenticator\n"
|
||||
"Copyright (c) 2002-2010, Jouni Malinen <j@w1.fi> "
|
||||
"Copyright (c) 2002-2012, Jouni Malinen <j@w1.fi> "
|
||||
"and contributors\n");
|
||||
}
|
||||
|
||||
@ -458,15 +478,21 @@ static void usage(void)
|
||||
show_version();
|
||||
fprintf(stderr,
|
||||
"\n"
|
||||
"usage: hostapd [-hdBKtv] [-P <PID file>] "
|
||||
"<configuration file(s)>\n"
|
||||
"usage: hostapd [-hdBKtv] [-P <PID file>] [-e <entropy file>] "
|
||||
"\\\n"
|
||||
" [-g <global ctrl_iface>] <configuration file(s)>\n"
|
||||
"\n"
|
||||
"options:\n"
|
||||
" -h show this usage\n"
|
||||
" -d show more debug messages (-dd for even more)\n"
|
||||
" -B run daemon in the background\n"
|
||||
" -e entropy file\n"
|
||||
" -g global control interface path\n"
|
||||
" -P PID file\n"
|
||||
" -K include key data in debug messages\n"
|
||||
#ifdef CONFIG_DEBUG_FILE
|
||||
" -f log output to debug file instead of stdout\n"
|
||||
#endif /* CONFIG_DEBUG_FILE */
|
||||
" -t include timestamps in some debug messages\n"
|
||||
" -v show hostapd version\n");
|
||||
|
||||
@ -474,6 +500,37 @@ static void usage(void)
|
||||
}
|
||||
|
||||
|
||||
static const char * hostapd_msg_ifname_cb(void *ctx)
|
||||
{
|
||||
struct hostapd_data *hapd = ctx;
|
||||
if (hapd && hapd->iconf && hapd->iconf->bss)
|
||||
return hapd->iconf->bss->iface;
|
||||
return NULL;
|
||||
}
|
||||
|
||||
|
||||
static int hostapd_get_global_ctrl_iface(struct hapd_interfaces *interfaces,
|
||||
const char *path)
|
||||
{
|
||||
char *pos;
|
||||
os_free(interfaces->global_iface_path);
|
||||
interfaces->global_iface_path = os_strdup(path);
|
||||
if (interfaces->global_iface_path == NULL)
|
||||
return -1;
|
||||
pos = os_strrchr(interfaces->global_iface_path, '/');
|
||||
if (pos == NULL) {
|
||||
os_free(interfaces->global_iface_path);
|
||||
interfaces->global_iface_path = NULL;
|
||||
return -1;
|
||||
}
|
||||
|
||||
*pos = '\0';
|
||||
interfaces->global_iface_name = pos + 1;
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
|
||||
int main(int argc, char *argv[])
|
||||
{
|
||||
struct hapd_interfaces interfaces;
|
||||
@ -481,12 +538,25 @@ int main(int argc, char *argv[])
|
||||
size_t i;
|
||||
int c, debug = 0, daemonize = 0;
|
||||
char *pid_file = NULL;
|
||||
const char *log_file = NULL;
|
||||
const char *entropy_file = NULL;
|
||||
|
||||
if (os_program_init())
|
||||
return -1;
|
||||
|
||||
os_memset(&interfaces, 0, sizeof(interfaces));
|
||||
interfaces.reload_config = hostapd_reload_config;
|
||||
interfaces.config_read_cb = hostapd_config_read;
|
||||
interfaces.for_each_interface = hostapd_for_each_interface;
|
||||
interfaces.ctrl_iface_init = hostapd_ctrl_iface_init;
|
||||
interfaces.ctrl_iface_deinit = hostapd_ctrl_iface_deinit;
|
||||
interfaces.driver_init = hostapd_driver_init;
|
||||
interfaces.global_iface_path = NULL;
|
||||
interfaces.global_iface_name = NULL;
|
||||
interfaces.global_ctrl_sock = -1;
|
||||
|
||||
for (;;) {
|
||||
c = getopt(argc, argv, "BdhKP:tv");
|
||||
c = getopt(argc, argv, "Bde:f:hKP:tvg:");
|
||||
if (c < 0)
|
||||
break;
|
||||
switch (c) {
|
||||
@ -501,6 +571,12 @@ int main(int argc, char *argv[])
|
||||
case 'B':
|
||||
daemonize++;
|
||||
break;
|
||||
case 'e':
|
||||
entropy_file = optarg;
|
||||
break;
|
||||
case 'f':
|
||||
log_file = optarg;
|
||||
break;
|
||||
case 'K':
|
||||
wpa_debug_show_keys++;
|
||||
break;
|
||||
@ -515,6 +591,9 @@ int main(int argc, char *argv[])
|
||||
show_version();
|
||||
exit(1);
|
||||
break;
|
||||
case 'g':
|
||||
hostapd_get_global_ctrl_iface(&interfaces, optarg);
|
||||
break;
|
||||
|
||||
default:
|
||||
usage();
|
||||
@ -522,18 +601,25 @@ int main(int argc, char *argv[])
|
||||
}
|
||||
}
|
||||
|
||||
if (optind == argc)
|
||||
if (optind == argc && interfaces.global_iface_path == NULL)
|
||||
usage();
|
||||
|
||||
wpa_msg_register_ifname_cb(hostapd_msg_ifname_cb);
|
||||
|
||||
if (log_file)
|
||||
wpa_debug_open_file(log_file);
|
||||
|
||||
interfaces.count = argc - optind;
|
||||
interfaces.iface = os_malloc(interfaces.count *
|
||||
sizeof(struct hostapd_iface *));
|
||||
if (interfaces.iface == NULL) {
|
||||
wpa_printf(MSG_ERROR, "malloc failed\n");
|
||||
return -1;
|
||||
if (interfaces.count) {
|
||||
interfaces.iface = os_calloc(interfaces.count,
|
||||
sizeof(struct hostapd_iface *));
|
||||
if (interfaces.iface == NULL) {
|
||||
wpa_printf(MSG_ERROR, "malloc failed");
|
||||
return -1;
|
||||
}
|
||||
}
|
||||
|
||||
if (hostapd_global_init(&interfaces))
|
||||
if (hostapd_global_init(&interfaces, entropy_file))
|
||||
return -1;
|
||||
|
||||
/* Initialize interfaces */
|
||||
@ -545,12 +631,15 @@ int main(int argc, char *argv[])
|
||||
goto out;
|
||||
}
|
||||
|
||||
hostapd_global_ctrl_iface_init(&interfaces);
|
||||
|
||||
if (hostapd_global_run(&interfaces, daemonize, pid_file))
|
||||
goto out;
|
||||
|
||||
ret = 0;
|
||||
|
||||
out:
|
||||
hostapd_global_ctrl_iface_deinit(&interfaces);
|
||||
/* Deinitialize all interfaces */
|
||||
for (i = 0; i < interfaces.count; i++)
|
||||
hostapd_interface_deinit_free(interfaces.iface[i]);
|
||||
@ -559,6 +648,9 @@ int main(int argc, char *argv[])
|
||||
hostapd_global_deinit(pid_file);
|
||||
os_free(pid_file);
|
||||
|
||||
if (log_file)
|
||||
wpa_debug_close_file();
|
||||
|
||||
os_program_deinit();
|
||||
|
||||
return ret;
|
||||
|
@ -2,14 +2,8 @@
|
||||
* hostapd - Plaintext password to NtPasswordHash
|
||||
* Copyright (c) 2005, Jouni Malinen <j@w1.fi>
|
||||
*
|
||||
* This program is free software; you can redistribute it and/or modify
|
||||
* it under the terms of the GNU General Public License version 2 as
|
||||
* published by the Free Software Foundation.
|
||||
*
|
||||
* Alternatively, this software may be distributed under the terms of BSD
|
||||
* license.
|
||||
*
|
||||
* See README and COPYING for more details.
|
||||
* This software may be distributed under the terms of the BSD license.
|
||||
* See README for more details.
|
||||
*/
|
||||
|
||||
#include "includes.h"
|
||||
|
396
contrib/wpa/patches/openssl-0.9.8x-tls-extensions.patch
Normal file
396
contrib/wpa/patches/openssl-0.9.8x-tls-extensions.patch
Normal file
@ -0,0 +1,396 @@
|
||||
This patch adds support for TLS SessionTicket extension (RFC 5077) for
|
||||
the parts used by EAP-FAST (RFC 4851).
|
||||
|
||||
This is based on the patch from Alexey Kobozev <akobozev@cisco.com>
|
||||
(sent to openssl-dev mailing list on Tue, 07 Jun 2005 15:40:58 +0300).
|
||||
|
||||
OpenSSL 0.9.8x does not enable TLS extension support by default, so it
|
||||
will need to be enabled by adding enable-tlsext to config script
|
||||
command line.
|
||||
|
||||
|
||||
diff -upr openssl-0.9.8x.orig/ssl/s3_clnt.c openssl-0.9.8x/ssl/s3_clnt.c
|
||||
--- openssl-0.9.8x.orig/ssl/s3_clnt.c 2011-12-26 21:38:28.000000000 +0200
|
||||
+++ openssl-0.9.8x/ssl/s3_clnt.c 2012-07-07 10:46:31.501140621 +0300
|
||||
@@ -757,6 +757,21 @@ int ssl3_get_server_hello(SSL *s)
|
||||
goto f_err;
|
||||
}
|
||||
|
||||
+#ifndef OPENSSL_NO_TLSEXT
|
||||
+ /* check if we want to resume the session based on external pre-shared secret */
|
||||
+ if (s->version >= TLS1_VERSION && s->tls_session_secret_cb)
|
||||
+ {
|
||||
+ SSL_CIPHER *pref_cipher=NULL;
|
||||
+ s->session->master_key_length=sizeof(s->session->master_key);
|
||||
+ if (s->tls_session_secret_cb(s, s->session->master_key, &s->session->master_key_length,
|
||||
+ NULL, &pref_cipher, s->tls_session_secret_cb_arg))
|
||||
+ {
|
||||
+ s->session->cipher=pref_cipher ?
|
||||
+ pref_cipher : ssl_get_cipher_by_char(s,p+j);
|
||||
+ }
|
||||
+ }
|
||||
+#endif /* OPENSSL_NO_TLSEXT */
|
||||
+
|
||||
if (j != 0 && j == s->session->session_id_length
|
||||
&& memcmp(p,s->session->session_id,j) == 0)
|
||||
{
|
||||
@@ -2725,11 +2740,8 @@ int ssl3_check_finished(SSL *s)
|
||||
{
|
||||
int ok;
|
||||
long n;
|
||||
- /* If we have no ticket or session ID is non-zero length (a match of
|
||||
- * a non-zero session length would never reach here) it cannot be a
|
||||
- * resumed session.
|
||||
- */
|
||||
- if (!s->session->tlsext_tick || s->session->session_id_length)
|
||||
+ /* If we have no ticket it cannot be a resumed session. */
|
||||
+ if (!s->session->tlsext_tick)
|
||||
return 1;
|
||||
/* this function is called when we really expect a Certificate
|
||||
* message, so permit appropriate message length */
|
||||
diff -upr openssl-0.9.8x.orig/ssl/s3_srvr.c openssl-0.9.8x/ssl/s3_srvr.c
|
||||
--- openssl-0.9.8x.orig/ssl/s3_srvr.c 2012-02-16 17:21:17.000000000 +0200
|
||||
+++ openssl-0.9.8x/ssl/s3_srvr.c 2012-07-07 10:46:31.501140621 +0300
|
||||
@@ -1009,6 +1009,59 @@ int ssl3_get_client_hello(SSL *s)
|
||||
SSLerr(SSL_F_SSL3_GET_CLIENT_HELLO,SSL_R_CLIENTHELLO_TLSEXT);
|
||||
goto err;
|
||||
}
|
||||
+
|
||||
+ /* Check if we want to use external pre-shared secret for this
|
||||
+ * handshake for not reused session only. We need to generate
|
||||
+ * server_random before calling tls_session_secret_cb in order to allow
|
||||
+ * SessionTicket processing to use it in key derivation. */
|
||||
+ {
|
||||
+ unsigned long Time;
|
||||
+ unsigned char *pos;
|
||||
+ Time=(unsigned long)time(NULL); /* Time */
|
||||
+ pos=s->s3->server_random;
|
||||
+ l2n(Time,pos);
|
||||
+ if (RAND_pseudo_bytes(pos,SSL3_RANDOM_SIZE-4) <= 0)
|
||||
+ {
|
||||
+ al=SSL_AD_INTERNAL_ERROR;
|
||||
+ goto f_err;
|
||||
+ }
|
||||
+ }
|
||||
+
|
||||
+ if (!s->hit && s->version >= TLS1_VERSION && s->tls_session_secret_cb)
|
||||
+ {
|
||||
+ SSL_CIPHER *pref_cipher=NULL;
|
||||
+
|
||||
+ s->session->master_key_length=sizeof(s->session->master_key);
|
||||
+ if(s->tls_session_secret_cb(s, s->session->master_key, &s->session->master_key_length,
|
||||
+ ciphers, &pref_cipher, s->tls_session_secret_cb_arg))
|
||||
+ {
|
||||
+ s->hit=1;
|
||||
+ s->session->ciphers=ciphers;
|
||||
+ s->session->verify_result=X509_V_OK;
|
||||
+
|
||||
+ ciphers=NULL;
|
||||
+
|
||||
+ /* check if some cipher was preferred by call back */
|
||||
+ pref_cipher=pref_cipher ? pref_cipher : ssl3_choose_cipher(s, s->session->ciphers, SSL_get_ciphers(s));
|
||||
+ if (pref_cipher == NULL)
|
||||
+ {
|
||||
+ al=SSL_AD_HANDSHAKE_FAILURE;
|
||||
+ SSLerr(SSL_F_SSL3_GET_CLIENT_HELLO,SSL_R_NO_SHARED_CIPHER);
|
||||
+ goto f_err;
|
||||
+ }
|
||||
+
|
||||
+ s->session->cipher=pref_cipher;
|
||||
+
|
||||
+ if (s->cipher_list)
|
||||
+ sk_SSL_CIPHER_free(s->cipher_list);
|
||||
+
|
||||
+ if (s->cipher_list_by_id)
|
||||
+ sk_SSL_CIPHER_free(s->cipher_list_by_id);
|
||||
+
|
||||
+ s->cipher_list = sk_SSL_CIPHER_dup(s->session->ciphers);
|
||||
+ s->cipher_list_by_id = sk_SSL_CIPHER_dup(s->session->ciphers);
|
||||
+ }
|
||||
+ }
|
||||
#endif
|
||||
/* Worst case, we will use the NULL compression, but if we have other
|
||||
* options, we will now look for them. We have i-1 compression
|
||||
@@ -1147,16 +1200,22 @@ int ssl3_send_server_hello(SSL *s)
|
||||
unsigned char *buf;
|
||||
unsigned char *p,*d;
|
||||
int i,sl;
|
||||
- unsigned long l,Time;
|
||||
+ unsigned long l;
|
||||
+#ifdef OPENSSL_NO_TLSEXT
|
||||
+ unsigned long Time;
|
||||
+#endif
|
||||
|
||||
if (s->state == SSL3_ST_SW_SRVR_HELLO_A)
|
||||
{
|
||||
buf=(unsigned char *)s->init_buf->data;
|
||||
+#ifdef OPENSSL_NO_TLSEXT
|
||||
p=s->s3->server_random;
|
||||
+ /* Generate server_random if it was not needed previously */
|
||||
Time=(unsigned long)time(NULL); /* Time */
|
||||
l2n(Time,p);
|
||||
if (RAND_pseudo_bytes(p,SSL3_RANDOM_SIZE-4) <= 0)
|
||||
return -1;
|
||||
+#endif
|
||||
/* Do the message type and length last */
|
||||
d=p= &(buf[4]);
|
||||
|
||||
diff -upr openssl-0.9.8x.orig/ssl/ssl_err.c openssl-0.9.8x/ssl/ssl_err.c
|
||||
--- openssl-0.9.8x.orig/ssl/ssl_err.c 2012-03-12 16:50:55.000000000 +0200
|
||||
+++ openssl-0.9.8x/ssl/ssl_err.c 2012-07-07 10:46:31.501140621 +0300
|
||||
@@ -264,6 +264,7 @@ static ERR_STRING_DATA SSL_str_functs[]=
|
||||
{ERR_FUNC(SSL_F_TLS1_ENC), "TLS1_ENC"},
|
||||
{ERR_FUNC(SSL_F_TLS1_SETUP_KEY_BLOCK), "TLS1_SETUP_KEY_BLOCK"},
|
||||
{ERR_FUNC(SSL_F_WRITE_PENDING), "WRITE_PENDING"},
|
||||
+{ERR_FUNC(SSL_F_SSL_SET_SESSION_TICKET_EXT), "SSL_set_session_ticket_ext"},
|
||||
{0,NULL}
|
||||
};
|
||||
|
||||
diff -upr openssl-0.9.8x.orig/ssl/ssl.h openssl-0.9.8x/ssl/ssl.h
|
||||
--- openssl-0.9.8x.orig/ssl/ssl.h 2012-03-12 16:50:55.000000000 +0200
|
||||
+++ openssl-0.9.8x/ssl/ssl.h 2012-07-07 10:46:31.501140621 +0300
|
||||
@@ -344,6 +344,7 @@ extern "C" {
|
||||
* 'struct ssl_st *' function parameters used to prototype callbacks
|
||||
* in SSL_CTX. */
|
||||
typedef struct ssl_st *ssl_crock_st;
|
||||
+typedef struct tls_session_ticket_ext_st TLS_SESSION_TICKET_EXT;
|
||||
|
||||
/* used to hold info on the particular ciphers used */
|
||||
typedef struct ssl_cipher_st
|
||||
@@ -362,6 +363,9 @@ typedef struct ssl_cipher_st
|
||||
|
||||
DECLARE_STACK_OF(SSL_CIPHER)
|
||||
|
||||
+typedef int (*tls_session_ticket_ext_cb_fn)(SSL *s, const unsigned char *data, int len, void *arg);
|
||||
+typedef int (*tls_session_secret_cb_fn)(SSL *s, void *secret, int *secret_len, STACK_OF(SSL_CIPHER) *peer_ciphers, SSL_CIPHER **cipher, void *arg);
|
||||
+
|
||||
/* Used to hold functions for SSLv2 or SSLv3/TLSv1 functions */
|
||||
typedef struct ssl_method_st
|
||||
{
|
||||
@@ -1050,6 +1054,18 @@ struct ssl_st
|
||||
|
||||
/* RFC4507 session ticket expected to be received or sent */
|
||||
int tlsext_ticket_expected;
|
||||
+
|
||||
+ /* TLS Session Ticket extension override */
|
||||
+ TLS_SESSION_TICKET_EXT *tlsext_session_ticket;
|
||||
+
|
||||
+ /* TLS Session Ticket extension callback */
|
||||
+ tls_session_ticket_ext_cb_fn tls_session_ticket_ext_cb;
|
||||
+ void *tls_session_ticket_ext_cb_arg;
|
||||
+
|
||||
+ /* TLS pre-shared secret session resumption */
|
||||
+ tls_session_secret_cb_fn tls_session_secret_cb;
|
||||
+ void *tls_session_secret_cb_arg;
|
||||
+
|
||||
SSL_CTX * initial_ctx; /* initial ctx, used to store sessions */
|
||||
#define session_ctx initial_ctx
|
||||
#else
|
||||
@@ -1663,6 +1679,15 @@ void *SSL_COMP_get_compression_methods(v
|
||||
int SSL_COMP_add_compression_method(int id,void *cm);
|
||||
#endif
|
||||
|
||||
+/* TLS extensions functions */
|
||||
+int SSL_set_session_ticket_ext(SSL *s, void *ext_data, int ext_len);
|
||||
+
|
||||
+int SSL_set_session_ticket_ext_cb(SSL *s, tls_session_ticket_ext_cb_fn cb,
|
||||
+ void *arg);
|
||||
+
|
||||
+/* Pre-shared secret session resumption functions */
|
||||
+int SSL_set_session_secret_cb(SSL *s, tls_session_secret_cb_fn tls_session_secret_cb, void *arg);
|
||||
+
|
||||
/* BEGIN ERROR CODES */
|
||||
/* The following lines are auto generated by the script mkerr.pl. Any changes
|
||||
* made after this point may be overwritten when the script is next run.
|
||||
@@ -1866,6 +1891,7 @@ void ERR_load_SSL_strings(void);
|
||||
#define SSL_F_TLS1_ENC 210
|
||||
#define SSL_F_TLS1_SETUP_KEY_BLOCK 211
|
||||
#define SSL_F_WRITE_PENDING 212
|
||||
+#define SSL_F_SSL_SET_SESSION_TICKET_EXT 213
|
||||
|
||||
/* Reason codes. */
|
||||
#define SSL_R_APP_DATA_IN_HANDSHAKE 100
|
||||
diff -upr openssl-0.9.8x.orig/ssl/ssl_sess.c openssl-0.9.8x/ssl/ssl_sess.c
|
||||
--- openssl-0.9.8x.orig/ssl/ssl_sess.c 2010-02-01 18:48:40.000000000 +0200
|
||||
+++ openssl-0.9.8x/ssl/ssl_sess.c 2012-07-07 10:46:31.501140621 +0300
|
||||
@@ -712,6 +712,61 @@ long SSL_CTX_get_timeout(const SSL_CTX *
|
||||
return(s->session_timeout);
|
||||
}
|
||||
|
||||
+#ifndef OPENSSL_NO_TLSEXT
|
||||
+int SSL_set_session_secret_cb(SSL *s, int (*tls_session_secret_cb)(SSL *s, void *secret, int *secret_len,
|
||||
+ STACK_OF(SSL_CIPHER) *peer_ciphers, SSL_CIPHER **cipher, void *arg), void *arg)
|
||||
+ {
|
||||
+ if (s == NULL) return(0);
|
||||
+ s->tls_session_secret_cb = tls_session_secret_cb;
|
||||
+ s->tls_session_secret_cb_arg = arg;
|
||||
+ return(1);
|
||||
+ }
|
||||
+
|
||||
+int SSL_set_session_ticket_ext_cb(SSL *s, tls_session_ticket_ext_cb_fn cb,
|
||||
+ void *arg)
|
||||
+ {
|
||||
+ if (s == NULL) return(0);
|
||||
+ s->tls_session_ticket_ext_cb = cb;
|
||||
+ s->tls_session_ticket_ext_cb_arg = arg;
|
||||
+ return(1);
|
||||
+ }
|
||||
+
|
||||
+int SSL_set_session_ticket_ext(SSL *s, void *ext_data, int ext_len)
|
||||
+ {
|
||||
+ if (s->version >= TLS1_VERSION)
|
||||
+ {
|
||||
+ if (s->tlsext_session_ticket)
|
||||
+ {
|
||||
+ OPENSSL_free(s->tlsext_session_ticket);
|
||||
+ s->tlsext_session_ticket = NULL;
|
||||
+ }
|
||||
+
|
||||
+ s->tlsext_session_ticket = OPENSSL_malloc(sizeof(TLS_SESSION_TICKET_EXT) + ext_len);
|
||||
+ if (!s->tlsext_session_ticket)
|
||||
+ {
|
||||
+ SSLerr(SSL_F_SSL_SET_SESSION_TICKET_EXT, ERR_R_MALLOC_FAILURE);
|
||||
+ return 0;
|
||||
+ }
|
||||
+
|
||||
+ if (ext_data)
|
||||
+ {
|
||||
+ s->tlsext_session_ticket->length = ext_len;
|
||||
+ s->tlsext_session_ticket->data = s->tlsext_session_ticket + 1;
|
||||
+ memcpy(s->tlsext_session_ticket->data, ext_data, ext_len);
|
||||
+ }
|
||||
+ else
|
||||
+ {
|
||||
+ s->tlsext_session_ticket->length = 0;
|
||||
+ s->tlsext_session_ticket->data = NULL;
|
||||
+ }
|
||||
+
|
||||
+ return 1;
|
||||
+ }
|
||||
+
|
||||
+ return 0;
|
||||
+ }
|
||||
+#endif /* OPENSSL_NO_TLSEXT */
|
||||
+
|
||||
typedef struct timeout_param_st
|
||||
{
|
||||
SSL_CTX *ctx;
|
||||
diff -upr openssl-0.9.8x.orig/ssl/t1_lib.c openssl-0.9.8x/ssl/t1_lib.c
|
||||
--- openssl-0.9.8x.orig/ssl/t1_lib.c 2012-01-04 16:25:10.000000000 +0200
|
||||
+++ openssl-0.9.8x/ssl/t1_lib.c 2012-07-07 10:47:31.153140501 +0300
|
||||
@@ -106,6 +106,12 @@ int tls1_new(SSL *s)
|
||||
|
||||
void tls1_free(SSL *s)
|
||||
{
|
||||
+#ifndef OPENSSL_NO_TLSEXT
|
||||
+ if (s->tlsext_session_ticket)
|
||||
+ {
|
||||
+ OPENSSL_free(s->tlsext_session_ticket);
|
||||
+ }
|
||||
+#endif
|
||||
ssl3_free(s);
|
||||
}
|
||||
|
||||
@@ -206,8 +212,23 @@ unsigned char *ssl_add_clienthello_tlsex
|
||||
int ticklen;
|
||||
if (!s->new_session && s->session && s->session->tlsext_tick)
|
||||
ticklen = s->session->tlsext_ticklen;
|
||||
+ else if (s->session && s->tlsext_session_ticket &&
|
||||
+ s->tlsext_session_ticket->data)
|
||||
+ {
|
||||
+ ticklen = s->tlsext_session_ticket->length;
|
||||
+ s->session->tlsext_tick = OPENSSL_malloc(ticklen);
|
||||
+ if (!s->session->tlsext_tick)
|
||||
+ return NULL;
|
||||
+ memcpy(s->session->tlsext_tick,
|
||||
+ s->tlsext_session_ticket->data,
|
||||
+ ticklen);
|
||||
+ s->session->tlsext_ticklen = ticklen;
|
||||
+ }
|
||||
else
|
||||
ticklen = 0;
|
||||
+ if (ticklen == 0 && s->tlsext_session_ticket &&
|
||||
+ s->tlsext_session_ticket->data == NULL)
|
||||
+ goto skip_ext;
|
||||
/* Check for enough room 2 for extension type, 2 for len
|
||||
* rest for ticket
|
||||
*/
|
||||
@@ -221,6 +242,7 @@ unsigned char *ssl_add_clienthello_tlsex
|
||||
ret += ticklen;
|
||||
}
|
||||
}
|
||||
+ skip_ext:
|
||||
|
||||
if (s->tlsext_status_type == TLSEXT_STATUSTYPE_ocsp &&
|
||||
s->version != DTLS1_VERSION)
|
||||
@@ -486,6 +508,15 @@ int ssl_parse_clienthello_tlsext(SSL *s,
|
||||
return 0;
|
||||
renegotiate_seen = 1;
|
||||
}
|
||||
+ else if (type == TLSEXT_TYPE_session_ticket)
|
||||
+ {
|
||||
+ if (s->tls_session_ticket_ext_cb &&
|
||||
+ !s->tls_session_ticket_ext_cb(s, data, size, s->tls_session_ticket_ext_cb_arg))
|
||||
+ {
|
||||
+ *al = TLS1_AD_INTERNAL_ERROR;
|
||||
+ return 0;
|
||||
+ }
|
||||
+ }
|
||||
else if (type == TLSEXT_TYPE_status_request &&
|
||||
s->version != DTLS1_VERSION && s->ctx->tlsext_status_cb)
|
||||
{
|
||||
@@ -663,6 +694,12 @@ int ssl_parse_serverhello_tlsext(SSL *s,
|
||||
}
|
||||
else if (type == TLSEXT_TYPE_session_ticket)
|
||||
{
|
||||
+ if (s->tls_session_ticket_ext_cb &&
|
||||
+ !s->tls_session_ticket_ext_cb(s, data, size, s->tls_session_ticket_ext_cb_arg))
|
||||
+ {
|
||||
+ *al = TLS1_AD_INTERNAL_ERROR;
|
||||
+ return 0;
|
||||
+ }
|
||||
if ((SSL_get_options(s) & SSL_OP_NO_TICKET)
|
||||
|| (size > 0))
|
||||
{
|
||||
@@ -920,6 +957,15 @@ int tls1_process_ticket(SSL *s, unsigned
|
||||
s->tlsext_ticket_expected = 1;
|
||||
return 0; /* Cache miss */
|
||||
}
|
||||
+ if (s->tls_session_secret_cb)
|
||||
+ {
|
||||
+ /* Indicate cache miss here and instead of
|
||||
+ * generating the session from ticket now,
|
||||
+ * trigger abbreviated handshake based on
|
||||
+ * external mechanism to calculate the master
|
||||
+ * secret later. */
|
||||
+ return 0;
|
||||
+ }
|
||||
return tls_decrypt_ticket(s, p, size, session_id, len,
|
||||
ret);
|
||||
}
|
||||
diff -upr openssl-0.9.8x.orig/ssl/tls1.h openssl-0.9.8x/ssl/tls1.h
|
||||
--- openssl-0.9.8x.orig/ssl/tls1.h 2009-11-08 16:51:54.000000000 +0200
|
||||
+++ openssl-0.9.8x/ssl/tls1.h 2012-07-07 10:46:31.501140621 +0300
|
||||
@@ -401,6 +401,13 @@ SSL_CTX_callback_ctrl(ssl,SSL_CTRL_SET_T
|
||||
#define TLS_MD_MASTER_SECRET_CONST "\x6d\x61\x73\x74\x65\x72\x20\x73\x65\x63\x72\x65\x74" /*master secret*/
|
||||
#endif
|
||||
|
||||
+/* TLS extension struct */
|
||||
+struct tls_session_ticket_ext_st
|
||||
+ {
|
||||
+ unsigned short length;
|
||||
+ void *data;
|
||||
+ };
|
||||
+
|
||||
#ifdef __cplusplus
|
||||
}
|
||||
#endif
|
||||
diff -upr openssl-0.9.8x.orig/util/ssleay.num openssl-0.9.8x/util/ssleay.num
|
||||
--- openssl-0.9.8x.orig/util/ssleay.num 2008-06-05 13:57:21.000000000 +0300
|
||||
+++ openssl-0.9.8x/util/ssleay.num 2012-07-07 10:46:31.505140623 +0300
|
||||
@@ -242,3 +242,5 @@ SSL_set_SSL_CTX
|
||||
SSL_get_servername 291 EXIST::FUNCTION:TLSEXT
|
||||
SSL_get_servername_type 292 EXIST::FUNCTION:TLSEXT
|
||||
SSL_CTX_set_client_cert_engine 293 EXIST::FUNCTION:ENGINE
|
||||
+SSL_set_session_ticket_ext 306 EXIST::FUNCTION:TLSEXT
|
||||
+SSL_set_session_secret_cb 307 EXIST::FUNCTION:TLSEXT
|
@ -1,4 +1,4 @@
|
||||
SUBDIRS=ap common crypto drivers eapol_auth eapol_supp eap_common eap_peer eap_server l2_packet radius rsn_supp tls utils wps
|
||||
SUBDIRS=ap common crypto drivers eapol_auth eapol_supp eap_common eap_peer eap_server l2_packet p2p radius rsn_supp tls utils wps
|
||||
|
||||
all:
|
||||
for d in $(SUBDIRS); do [ -d $$d ] && $(MAKE) -C $$d; done
|
||||
|
@ -1,15 +1,9 @@
|
||||
/*
|
||||
* hostapd / RADIUS Accounting
|
||||
* Copyright (c) 2002-2009, Jouni Malinen <j@w1.fi>
|
||||
* Copyright (c) 2002-2009, 2012, Jouni Malinen <j@w1.fi>
|
||||
*
|
||||
* This program is free software; you can redistribute it and/or modify
|
||||
* it under the terms of the GNU General Public License version 2 as
|
||||
* published by the Free Software Foundation.
|
||||
*
|
||||
* Alternatively, this software may be distributed under the terms of BSD
|
||||
* license.
|
||||
*
|
||||
* See README and COPYING for more details.
|
||||
* This software may be distributed under the terms of the BSD license.
|
||||
* See README for more details.
|
||||
*/
|
||||
|
||||
#include "utils/includes.h"
|
||||
@ -23,6 +17,7 @@
|
||||
#include "ieee802_1x.h"
|
||||
#include "ap_config.h"
|
||||
#include "sta_info.h"
|
||||
#include "ap_drv_ops.h"
|
||||
#include "accounting.h"
|
||||
|
||||
|
||||
@ -31,8 +26,8 @@
|
||||
* input/output octets and updates Acct-{Input,Output}-Gigawords. */
|
||||
#define ACCT_DEFAULT_UPDATE_INTERVAL 300
|
||||
|
||||
static void accounting_sta_get_id(struct hostapd_data *hapd,
|
||||
struct sta_info *sta);
|
||||
static void accounting_sta_interim(struct hostapd_data *hapd,
|
||||
struct sta_info *sta);
|
||||
|
||||
|
||||
static struct radius_msg * accounting_msg(struct hostapd_data *hapd,
|
||||
@ -44,6 +39,7 @@ static struct radius_msg * accounting_msg(struct hostapd_data *hapd,
|
||||
u8 *val;
|
||||
size_t len;
|
||||
int i;
|
||||
struct wpabuf *b;
|
||||
|
||||
msg = radius_msg_new(RADIUS_CODE_ACCOUNTING_REQUEST,
|
||||
radius_client_get_id(hapd->radius));
|
||||
@ -72,7 +68,9 @@ static struct radius_msg * accounting_msg(struct hostapd_data *hapd,
|
||||
goto fail;
|
||||
}
|
||||
|
||||
if (!radius_msg_add_attr_int32(msg, RADIUS_ATTR_ACCT_AUTHENTIC,
|
||||
if (!hostapd_config_get_radius_attr(hapd->conf->radius_acct_req_attr,
|
||||
RADIUS_ATTR_ACCT_AUTHENTIC) &&
|
||||
!radius_msg_add_attr_int32(msg, RADIUS_ATTR_ACCT_AUTHENTIC,
|
||||
hapd->conf->ieee802_1x ?
|
||||
RADIUS_ACCT_AUTHENTIC_RADIUS :
|
||||
RADIUS_ACCT_AUTHENTIC_LOCAL)) {
|
||||
@ -81,7 +79,17 @@ static struct radius_msg * accounting_msg(struct hostapd_data *hapd,
|
||||
}
|
||||
|
||||
if (sta) {
|
||||
/* Use 802.1X identity if available */
|
||||
val = ieee802_1x_get_identity(sta->eapol_sm, &len);
|
||||
|
||||
/* Use RADIUS ACL identity if 802.1X provides no identity */
|
||||
if (!val && sta->identity) {
|
||||
val = (u8 *) sta->identity;
|
||||
len = os_strlen(sta->identity);
|
||||
}
|
||||
|
||||
/* Use STA MAC if neither 802.1X nor RADIUS ACL provided
|
||||
* identity */
|
||||
if (!val) {
|
||||
os_snprintf(buf, sizeof(buf), RADIUS_ADDR_FORMAT,
|
||||
MAC2STR(sta->addr));
|
||||
@ -96,70 +104,11 @@ static struct radius_msg * accounting_msg(struct hostapd_data *hapd,
|
||||
}
|
||||
}
|
||||
|
||||
if (hapd->conf->own_ip_addr.af == AF_INET &&
|
||||
!radius_msg_add_attr(msg, RADIUS_ATTR_NAS_IP_ADDRESS,
|
||||
(u8 *) &hapd->conf->own_ip_addr.u.v4, 4)) {
|
||||
printf("Could not add NAS-IP-Address\n");
|
||||
if (add_common_radius_attr(hapd, hapd->conf->radius_acct_req_attr, sta,
|
||||
msg) < 0)
|
||||
goto fail;
|
||||
}
|
||||
|
||||
#ifdef CONFIG_IPV6
|
||||
if (hapd->conf->own_ip_addr.af == AF_INET6 &&
|
||||
!radius_msg_add_attr(msg, RADIUS_ATTR_NAS_IPV6_ADDRESS,
|
||||
(u8 *) &hapd->conf->own_ip_addr.u.v6, 16)) {
|
||||
printf("Could not add NAS-IPv6-Address\n");
|
||||
goto fail;
|
||||
}
|
||||
#endif /* CONFIG_IPV6 */
|
||||
|
||||
if (hapd->conf->nas_identifier &&
|
||||
!radius_msg_add_attr(msg, RADIUS_ATTR_NAS_IDENTIFIER,
|
||||
(u8 *) hapd->conf->nas_identifier,
|
||||
os_strlen(hapd->conf->nas_identifier))) {
|
||||
printf("Could not add NAS-Identifier\n");
|
||||
goto fail;
|
||||
}
|
||||
|
||||
if (sta &&
|
||||
!radius_msg_add_attr_int32(msg, RADIUS_ATTR_NAS_PORT, sta->aid)) {
|
||||
printf("Could not add NAS-Port\n");
|
||||
goto fail;
|
||||
}
|
||||
|
||||
os_snprintf(buf, sizeof(buf), RADIUS_802_1X_ADDR_FORMAT ":%s",
|
||||
MAC2STR(hapd->own_addr), hapd->conf->ssid.ssid);
|
||||
if (!radius_msg_add_attr(msg, RADIUS_ATTR_CALLED_STATION_ID,
|
||||
(u8 *) buf, os_strlen(buf))) {
|
||||
printf("Could not add Called-Station-Id\n");
|
||||
goto fail;
|
||||
}
|
||||
|
||||
if (sta) {
|
||||
os_snprintf(buf, sizeof(buf), RADIUS_802_1X_ADDR_FORMAT,
|
||||
MAC2STR(sta->addr));
|
||||
if (!radius_msg_add_attr(msg, RADIUS_ATTR_CALLING_STATION_ID,
|
||||
(u8 *) buf, os_strlen(buf))) {
|
||||
printf("Could not add Calling-Station-Id\n");
|
||||
goto fail;
|
||||
}
|
||||
|
||||
if (!radius_msg_add_attr_int32(
|
||||
msg, RADIUS_ATTR_NAS_PORT_TYPE,
|
||||
RADIUS_NAS_PORT_TYPE_IEEE_802_11)) {
|
||||
printf("Could not add NAS-Port-Type\n");
|
||||
goto fail;
|
||||
}
|
||||
|
||||
os_snprintf(buf, sizeof(buf), "CONNECT %d%sMbps %s",
|
||||
radius_sta_rate(hapd, sta) / 2,
|
||||
(radius_sta_rate(hapd, sta) & 1) ? ".5" : "",
|
||||
radius_mode_txt(hapd));
|
||||
if (!radius_msg_add_attr(msg, RADIUS_ATTR_CONNECT_INFO,
|
||||
(u8 *) buf, os_strlen(buf))) {
|
||||
printf("Could not add Connect-Info\n");
|
||||
goto fail;
|
||||
}
|
||||
|
||||
for (i = 0; ; i++) {
|
||||
val = ieee802_1x_get_radius_class(sta->eapol_sm, &len,
|
||||
i);
|
||||
@ -172,6 +121,24 @@ static struct radius_msg * accounting_msg(struct hostapd_data *hapd,
|
||||
goto fail;
|
||||
}
|
||||
}
|
||||
|
||||
b = ieee802_1x_get_radius_cui(sta->eapol_sm);
|
||||
if (b &&
|
||||
!radius_msg_add_attr(msg,
|
||||
RADIUS_ATTR_CHARGEABLE_USER_IDENTITY,
|
||||
wpabuf_head(b), wpabuf_len(b))) {
|
||||
wpa_printf(MSG_ERROR, "Could not add CUI");
|
||||
goto fail;
|
||||
}
|
||||
|
||||
if (!b && sta->radius_cui &&
|
||||
!radius_msg_add_attr(msg,
|
||||
RADIUS_ATTR_CHARGEABLE_USER_IDENTITY,
|
||||
(u8 *) sta->radius_cui,
|
||||
os_strlen(sta->radius_cui))) {
|
||||
wpa_printf(MSG_ERROR, "Could not add CUI from ACL");
|
||||
goto fail;
|
||||
}
|
||||
}
|
||||
|
||||
return msg;
|
||||
@ -186,7 +153,7 @@ static int accounting_sta_update_stats(struct hostapd_data *hapd,
|
||||
struct sta_info *sta,
|
||||
struct hostap_sta_driver_data *data)
|
||||
{
|
||||
if (hapd->drv.read_sta_data(hapd, data, sta->addr))
|
||||
if (hostapd_drv_read_sta_data(hapd, data, sta->addr))
|
||||
return -1;
|
||||
|
||||
if (sta->last_rx_bytes > data->rx_bytes)
|
||||
@ -235,21 +202,22 @@ static void accounting_interim_update(void *eloop_ctx, void *timeout_ctx)
|
||||
void accounting_sta_start(struct hostapd_data *hapd, struct sta_info *sta)
|
||||
{
|
||||
struct radius_msg *msg;
|
||||
struct os_time t;
|
||||
int interval;
|
||||
|
||||
if (sta->acct_session_started)
|
||||
return;
|
||||
|
||||
accounting_sta_get_id(hapd, sta);
|
||||
hostapd_logger(hapd, sta->addr, HOSTAPD_MODULE_RADIUS,
|
||||
HOSTAPD_LEVEL_INFO,
|
||||
"starting accounting session %08X-%08X",
|
||||
sta->acct_session_id_hi, sta->acct_session_id_lo);
|
||||
|
||||
time(&sta->acct_session_start);
|
||||
os_get_time(&t);
|
||||
sta->acct_session_start = t.sec;
|
||||
sta->last_rx_bytes = sta->last_tx_bytes = 0;
|
||||
sta->acct_input_gigawords = sta->acct_output_gigawords = 0;
|
||||
hapd->drv.sta_clear_stats(hapd, sta->addr);
|
||||
hostapd_drv_sta_clear_stats(hapd, sta->addr);
|
||||
|
||||
if (!hapd->conf->radius->acct_server)
|
||||
return;
|
||||
@ -262,8 +230,9 @@ void accounting_sta_start(struct hostapd_data *hapd, struct sta_info *sta)
|
||||
hapd, sta);
|
||||
|
||||
msg = accounting_msg(hapd, sta, RADIUS_ACCT_STATUS_TYPE_START);
|
||||
if (msg)
|
||||
radius_client_send(hapd->radius, msg, RADIUS_ACCT, sta->addr);
|
||||
if (msg &&
|
||||
radius_client_send(hapd->radius, msg, RADIUS_ACCT, sta->addr) < 0)
|
||||
radius_msg_free(msg);
|
||||
|
||||
sta->acct_session_started = 1;
|
||||
}
|
||||
@ -275,6 +244,7 @@ static void accounting_sta_report(struct hostapd_data *hapd,
|
||||
struct radius_msg *msg;
|
||||
int cause = sta->acct_terminate_cause;
|
||||
struct hostap_sta_driver_data data;
|
||||
struct os_time now;
|
||||
u32 gigawords;
|
||||
|
||||
if (!hapd->conf->radius->acct_server)
|
||||
@ -288,8 +258,9 @@ static void accounting_sta_report(struct hostapd_data *hapd,
|
||||
return;
|
||||
}
|
||||
|
||||
os_get_time(&now);
|
||||
if (!radius_msg_add_attr_int32(msg, RADIUS_ATTR_ACCT_SESSION_TIME,
|
||||
time(NULL) - sta->acct_session_start)) {
|
||||
now.sec - sta->acct_session_start)) {
|
||||
printf("Could not add Acct-Session-Time\n");
|
||||
goto fail;
|
||||
}
|
||||
@ -344,7 +315,7 @@ static void accounting_sta_report(struct hostapd_data *hapd,
|
||||
}
|
||||
|
||||
if (!radius_msg_add_attr_int32(msg, RADIUS_ATTR_EVENT_TIMESTAMP,
|
||||
time(NULL))) {
|
||||
now.sec)) {
|
||||
printf("Could not add Event-Timestamp\n");
|
||||
goto fail;
|
||||
}
|
||||
@ -359,9 +330,10 @@ static void accounting_sta_report(struct hostapd_data *hapd,
|
||||
goto fail;
|
||||
}
|
||||
|
||||
radius_client_send(hapd->radius, msg,
|
||||
stop ? RADIUS_ACCT : RADIUS_ACCT_INTERIM,
|
||||
sta->addr);
|
||||
if (radius_client_send(hapd->radius, msg,
|
||||
stop ? RADIUS_ACCT : RADIUS_ACCT_INTERIM,
|
||||
sta->addr) < 0)
|
||||
goto fail;
|
||||
return;
|
||||
|
||||
fail:
|
||||
@ -374,7 +346,8 @@ static void accounting_sta_report(struct hostapd_data *hapd,
|
||||
* @hapd: hostapd BSS data
|
||||
* @sta: The station
|
||||
*/
|
||||
void accounting_sta_interim(struct hostapd_data *hapd, struct sta_info *sta)
|
||||
static void accounting_sta_interim(struct hostapd_data *hapd,
|
||||
struct sta_info *sta)
|
||||
{
|
||||
if (sta->acct_session_started)
|
||||
accounting_sta_report(hapd, sta, 0);
|
||||
@ -401,7 +374,7 @@ void accounting_sta_stop(struct hostapd_data *hapd, struct sta_info *sta)
|
||||
}
|
||||
|
||||
|
||||
static void accounting_sta_get_id(struct hostapd_data *hapd,
|
||||
void accounting_sta_get_id(struct hostapd_data *hapd,
|
||||
struct sta_info *sta)
|
||||
{
|
||||
sta->acct_session_id_lo = hapd->acct_session_id_lo++;
|
||||
@ -464,7 +437,8 @@ static void accounting_report_state(struct hostapd_data *hapd, int on)
|
||||
return;
|
||||
}
|
||||
|
||||
radius_client_send(hapd->radius, msg, RADIUS_ACCT, NULL);
|
||||
if (radius_client_send(hapd->radius, msg, RADIUS_ACCT, NULL) < 0)
|
||||
radius_msg_free(msg);
|
||||
}
|
||||
|
||||
|
||||
@ -475,9 +449,12 @@ static void accounting_report_state(struct hostapd_data *hapd, int on)
|
||||
*/
|
||||
int accounting_init(struct hostapd_data *hapd)
|
||||
{
|
||||
struct os_time now;
|
||||
|
||||
/* Acct-Session-Id should be unique over reboots. If reliable clock is
|
||||
* not available, this could be replaced with reboot counter, etc. */
|
||||
hapd->acct_session_id_hi = time(NULL);
|
||||
os_get_time(&now);
|
||||
hapd->acct_session_id_hi = now.sec;
|
||||
|
||||
if (radius_client_register(hapd->radius, RADIUS_ACCT,
|
||||
accounting_receive, hapd))
|
||||
|
@ -2,21 +2,19 @@
|
||||
* hostapd / RADIUS Accounting
|
||||
* Copyright (c) 2002-2005, Jouni Malinen <j@w1.fi>
|
||||
*
|
||||
* This program is free software; you can redistribute it and/or modify
|
||||
* it under the terms of the GNU General Public License version 2 as
|
||||
* published by the Free Software Foundation.
|
||||
*
|
||||
* Alternatively, this software may be distributed under the terms of BSD
|
||||
* license.
|
||||
*
|
||||
* See README and COPYING for more details.
|
||||
* This software may be distributed under the terms of the BSD license.
|
||||
* See README for more details.
|
||||
*/
|
||||
|
||||
#ifndef ACCOUNTING_H
|
||||
#define ACCOUNTING_H
|
||||
|
||||
void accounting_sta_interim(struct hostapd_data *hapd, struct sta_info *sta);
|
||||
#ifdef CONFIG_NO_ACCOUNTING
|
||||
static inline void accounting_sta_get_id(struct hostapd_data *hapd,
|
||||
struct sta_info *sta)
|
||||
{
|
||||
}
|
||||
|
||||
static inline void accounting_sta_start(struct hostapd_data *hapd,
|
||||
struct sta_info *sta)
|
||||
{
|
||||
@ -36,6 +34,7 @@ static inline void accounting_deinit(struct hostapd_data *hapd)
|
||||
{
|
||||
}
|
||||
#else /* CONFIG_NO_ACCOUNTING */
|
||||
void accounting_sta_get_id(struct hostapd_data *hapd, struct sta_info *sta);
|
||||
void accounting_sta_start(struct hostapd_data *hapd, struct sta_info *sta);
|
||||
void accounting_sta_stop(struct hostapd_data *hapd, struct sta_info *sta);
|
||||
int accounting_init(struct hostapd_data *hapd);
|
||||
|
@ -1,15 +1,9 @@
|
||||
/*
|
||||
* hostapd / Configuration helper functions
|
||||
* Copyright (c) 2003-2009, Jouni Malinen <j@w1.fi>
|
||||
* Copyright (c) 2003-2012, Jouni Malinen <j@w1.fi>
|
||||
*
|
||||
* This program is free software; you can redistribute it and/or modify
|
||||
* it under the terms of the GNU General Public License version 2 as
|
||||
* published by the Free Software Foundation.
|
||||
*
|
||||
* Alternatively, this software may be distributed under the terms of BSD
|
||||
* license.
|
||||
*
|
||||
* See README and COPYING for more details.
|
||||
* This software may be distributed under the terms of the BSD license.
|
||||
* See README for more details.
|
||||
*/
|
||||
|
||||
#include "utils/includes.h"
|
||||
@ -74,6 +68,8 @@ void hostapd_config_defaults_bss(struct hostapd_bss_config *bss)
|
||||
|
||||
bss->max_listen_interval = 65535;
|
||||
|
||||
bss->pwd_group = 19; /* ECC: GF(p=256) */
|
||||
|
||||
#ifdef CONFIG_IEEE80211W
|
||||
bss->assoc_sa_query_max_timeout = 1000;
|
||||
bss->assoc_sa_query_retry_timeout = 201;
|
||||
@ -84,23 +80,44 @@ void hostapd_config_defaults_bss(struct hostapd_bss_config *bss)
|
||||
bss->pac_key_lifetime = 7 * 24 * 60 * 60;
|
||||
bss->pac_key_refresh_time = 1 * 24 * 60 * 60;
|
||||
#endif /* EAP_SERVER_FAST */
|
||||
|
||||
/* Set to -1 as defaults depends on HT in setup */
|
||||
bss->wmm_enabled = -1;
|
||||
|
||||
#ifdef CONFIG_IEEE80211R
|
||||
bss->ft_over_ds = 1;
|
||||
#endif /* CONFIG_IEEE80211R */
|
||||
|
||||
bss->radius_das_time_window = 300;
|
||||
}
|
||||
|
||||
|
||||
struct hostapd_config * hostapd_config_defaults(void)
|
||||
{
|
||||
#define ecw2cw(ecw) ((1 << (ecw)) - 1)
|
||||
|
||||
struct hostapd_config *conf;
|
||||
struct hostapd_bss_config *bss;
|
||||
int i;
|
||||
const int aCWmin = 4, aCWmax = 10;
|
||||
const struct hostapd_wmm_ac_params ac_bk =
|
||||
{ aCWmin, aCWmax, 7, 0, 0 }; /* background traffic */
|
||||
const struct hostapd_wmm_ac_params ac_be =
|
||||
{ aCWmin, aCWmax, 3, 0, 0 }; /* best effort traffic */
|
||||
const struct hostapd_wmm_ac_params ac_vi = /* video traffic */
|
||||
{ aCWmin - 1, aCWmin, 2, 3000 / 32, 1 };
|
||||
{ aCWmin - 1, aCWmin, 2, 3000 / 32, 0 };
|
||||
const struct hostapd_wmm_ac_params ac_vo = /* voice traffic */
|
||||
{ aCWmin - 2, aCWmin - 1, 2, 1500 / 32, 1 };
|
||||
{ aCWmin - 2, aCWmin - 1, 2, 1500 / 32, 0 };
|
||||
const struct hostapd_tx_queue_params txq_bk =
|
||||
{ 7, ecw2cw(aCWmin), ecw2cw(aCWmax), 0 };
|
||||
const struct hostapd_tx_queue_params txq_be =
|
||||
{ 3, ecw2cw(aCWmin), 4 * (ecw2cw(aCWmin) + 1) - 1, 0};
|
||||
const struct hostapd_tx_queue_params txq_vi =
|
||||
{ 1, (ecw2cw(aCWmin) + 1) / 2 - 1, ecw2cw(aCWmin), 30};
|
||||
const struct hostapd_tx_queue_params txq_vo =
|
||||
{ 1, (ecw2cw(aCWmin) + 1) / 4 - 1,
|
||||
(ecw2cw(aCWmin) + 1) / 2 - 1, 15};
|
||||
|
||||
#undef ecw2cw
|
||||
|
||||
conf = os_zalloc(sizeof(*conf));
|
||||
bss = os_zalloc(sizeof(*bss));
|
||||
@ -129,16 +146,21 @@ struct hostapd_config * hostapd_config_defaults(void)
|
||||
conf->fragm_threshold = -1; /* user driver default: 2346 */
|
||||
conf->send_probe_response = 1;
|
||||
|
||||
for (i = 0; i < NUM_TX_QUEUES; i++)
|
||||
conf->tx_queue[i].aifs = -1; /* use hw default */
|
||||
|
||||
conf->wmm_ac_params[0] = ac_be;
|
||||
conf->wmm_ac_params[1] = ac_bk;
|
||||
conf->wmm_ac_params[2] = ac_vi;
|
||||
conf->wmm_ac_params[3] = ac_vo;
|
||||
|
||||
conf->tx_queue[0] = txq_vo;
|
||||
conf->tx_queue[1] = txq_vi;
|
||||
conf->tx_queue[2] = txq_be;
|
||||
conf->tx_queue[3] = txq_bk;
|
||||
|
||||
conf->ht_capab = HT_CAP_INFO_SMPS_DISABLED;
|
||||
|
||||
conf->ap_table_max_size = 255;
|
||||
conf->ap_table_expiration_time = 60;
|
||||
|
||||
return conf;
|
||||
}
|
||||
|
||||
@ -319,6 +341,30 @@ static void hostapd_config_free_radius(struct hostapd_radius_server *servers,
|
||||
}
|
||||
|
||||
|
||||
struct hostapd_radius_attr *
|
||||
hostapd_config_get_radius_attr(struct hostapd_radius_attr *attr, u8 type)
|
||||
{
|
||||
for (; attr; attr = attr->next) {
|
||||
if (attr->type == type)
|
||||
return attr;
|
||||
}
|
||||
return NULL;
|
||||
}
|
||||
|
||||
|
||||
static void hostapd_config_free_radius_attr(struct hostapd_radius_attr *attr)
|
||||
{
|
||||
struct hostapd_radius_attr *prev;
|
||||
|
||||
while (attr) {
|
||||
prev = attr;
|
||||
attr = attr->next;
|
||||
wpabuf_free(prev->val);
|
||||
os_free(prev);
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
static void hostapd_config_free_eap_user(struct hostapd_eap_user *user)
|
||||
{
|
||||
os_free(user->identity);
|
||||
@ -365,6 +411,7 @@ static void hostapd_config_free_bss(struct hostapd_bss_config *conf)
|
||||
user = user->next;
|
||||
hostapd_config_free_eap_user(prev_user);
|
||||
}
|
||||
os_free(conf->eap_user_sqlite);
|
||||
|
||||
os_free(conf->dump_log_name);
|
||||
os_free(conf->eap_req_id_text);
|
||||
@ -375,6 +422,8 @@ static void hostapd_config_free_bss(struct hostapd_bss_config *conf)
|
||||
conf->radius->num_auth_servers);
|
||||
hostapd_config_free_radius(conf->radius->acct_servers,
|
||||
conf->radius->num_acct_servers);
|
||||
hostapd_config_free_radius_attr(conf->radius_auth_req_attr);
|
||||
hostapd_config_free_radius_attr(conf->radius_acct_req_attr);
|
||||
os_free(conf->rsn_preauth_interfaces);
|
||||
os_free(conf->ctrl_interface);
|
||||
os_free(conf->ca_cert);
|
||||
@ -389,6 +438,7 @@ static void hostapd_config_free_bss(struct hostapd_bss_config *conf)
|
||||
os_free(conf->radius_server_clients);
|
||||
os_free(conf->test_socket);
|
||||
os_free(conf->radius);
|
||||
os_free(conf->radius_das_shared_secret);
|
||||
hostapd_config_free_vlan(conf);
|
||||
if (conf->ssid.dyn_vlan_keys) {
|
||||
struct hostapd_ssid *ssid = &conf->ssid;
|
||||
@ -403,6 +453,8 @@ static void hostapd_config_free_bss(struct hostapd_bss_config *conf)
|
||||
ssid->dyn_vlan_keys = NULL;
|
||||
}
|
||||
|
||||
os_free(conf->time_zone);
|
||||
|
||||
#ifdef CONFIG_IEEE80211R
|
||||
{
|
||||
struct ft_remote_r0kh *r0kh, *r0kh_prev;
|
||||
@ -433,7 +485,6 @@ static void hostapd_config_free_bss(struct hostapd_bss_config *conf)
|
||||
os_free(conf->model_name);
|
||||
os_free(conf->model_number);
|
||||
os_free(conf->serial_number);
|
||||
os_free(conf->device_type);
|
||||
os_free(conf->config_methods);
|
||||
os_free(conf->ap_pin);
|
||||
os_free(conf->extra_cred);
|
||||
@ -444,7 +495,30 @@ static void hostapd_config_free_bss(struct hostapd_bss_config *conf)
|
||||
os_free(conf->model_description);
|
||||
os_free(conf->model_url);
|
||||
os_free(conf->upc);
|
||||
wpabuf_free(conf->wps_nfc_dh_pubkey);
|
||||
wpabuf_free(conf->wps_nfc_dh_privkey);
|
||||
wpabuf_free(conf->wps_nfc_dev_pw);
|
||||
#endif /* CONFIG_WPS */
|
||||
|
||||
os_free(conf->roaming_consortium);
|
||||
os_free(conf->venue_name);
|
||||
os_free(conf->nai_realm_data);
|
||||
os_free(conf->network_auth_type);
|
||||
os_free(conf->anqp_3gpp_cell_net);
|
||||
os_free(conf->domain_name);
|
||||
|
||||
#ifdef CONFIG_RADIUS_TEST
|
||||
os_free(conf->dump_msk_file);
|
||||
#endif /* CONFIG_RADIUS_TEST */
|
||||
|
||||
#ifdef CONFIG_HS20
|
||||
os_free(conf->hs20_oper_friendly_name);
|
||||
os_free(conf->hs20_wan_metrics);
|
||||
os_free(conf->hs20_connection_capability);
|
||||
os_free(conf->hs20_operating_class);
|
||||
#endif /* CONFIG_HS20 */
|
||||
|
||||
wpabuf_free(conf->vendor_elements);
|
||||
}
|
||||
|
||||
|
||||
@ -549,57 +623,3 @@ const u8 * hostapd_get_psk(const struct hostapd_bss_config *conf,
|
||||
|
||||
return NULL;
|
||||
}
|
||||
|
||||
|
||||
const struct hostapd_eap_user *
|
||||
hostapd_get_eap_user(const struct hostapd_bss_config *conf, const u8 *identity,
|
||||
size_t identity_len, int phase2)
|
||||
{
|
||||
struct hostapd_eap_user *user = conf->eap_user;
|
||||
|
||||
#ifdef CONFIG_WPS
|
||||
if (conf->wps_state && identity_len == WSC_ID_ENROLLEE_LEN &&
|
||||
os_memcmp(identity, WSC_ID_ENROLLEE, WSC_ID_ENROLLEE_LEN) == 0) {
|
||||
static struct hostapd_eap_user wsc_enrollee;
|
||||
os_memset(&wsc_enrollee, 0, sizeof(wsc_enrollee));
|
||||
wsc_enrollee.methods[0].method = eap_server_get_type(
|
||||
"WSC", &wsc_enrollee.methods[0].vendor);
|
||||
return &wsc_enrollee;
|
||||
}
|
||||
|
||||
if (conf->wps_state && identity_len == WSC_ID_REGISTRAR_LEN &&
|
||||
os_memcmp(identity, WSC_ID_REGISTRAR, WSC_ID_REGISTRAR_LEN) == 0) {
|
||||
static struct hostapd_eap_user wsc_registrar;
|
||||
os_memset(&wsc_registrar, 0, sizeof(wsc_registrar));
|
||||
wsc_registrar.methods[0].method = eap_server_get_type(
|
||||
"WSC", &wsc_registrar.methods[0].vendor);
|
||||
wsc_registrar.password = (u8 *) conf->ap_pin;
|
||||
wsc_registrar.password_len = conf->ap_pin ?
|
||||
os_strlen(conf->ap_pin) : 0;
|
||||
return &wsc_registrar;
|
||||
}
|
||||
#endif /* CONFIG_WPS */
|
||||
|
||||
while (user) {
|
||||
if (!phase2 && user->identity == NULL) {
|
||||
/* Wildcard match */
|
||||
break;
|
||||
}
|
||||
|
||||
if (user->phase2 == !!phase2 && user->wildcard_prefix &&
|
||||
identity_len >= user->identity_len &&
|
||||
os_memcmp(user->identity, identity, user->identity_len) ==
|
||||
0) {
|
||||
/* Wildcard prefix match */
|
||||
break;
|
||||
}
|
||||
|
||||
if (user->phase2 == !!phase2 &&
|
||||
user->identity_len == identity_len &&
|
||||
os_memcmp(user->identity, identity, identity_len) == 0)
|
||||
break;
|
||||
user = user->next;
|
||||
}
|
||||
|
||||
return user;
|
||||
}
|
||||
|
@ -1,15 +1,9 @@
|
||||
/*
|
||||
* hostapd / Configuration definitions and helpers functions
|
||||
* Copyright (c) 2003-2009, Jouni Malinen <j@w1.fi>
|
||||
* Copyright (c) 2003-2012, Jouni Malinen <j@w1.fi>
|
||||
*
|
||||
* This program is free software; you can redistribute it and/or modify
|
||||
* it under the terms of the GNU General Public License version 2 as
|
||||
* published by the Free Software Foundation.
|
||||
*
|
||||
* Alternatively, this software may be distributed under the terms of BSD
|
||||
* license.
|
||||
*
|
||||
* See README and COPYING for more details.
|
||||
* This software may be distributed under the terms of the BSD license.
|
||||
* See README for more details.
|
||||
*/
|
||||
|
||||
#ifndef HOSTAPD_CONFIG_H
|
||||
@ -18,6 +12,8 @@
|
||||
#include "common/defs.h"
|
||||
#include "ip_addr.h"
|
||||
#include "common/wpa_common.h"
|
||||
#include "common/ieee802_11_common.h"
|
||||
#include "wps/wps.h"
|
||||
|
||||
#define MAX_STA_COUNT 2007
|
||||
#define MAX_VLAN_ID 4094
|
||||
@ -53,9 +49,10 @@ typedef enum hostap_security_policy {
|
||||
} secpolicy;
|
||||
|
||||
struct hostapd_ssid {
|
||||
char ssid[HOSTAPD_MAX_SSID_LEN + 1];
|
||||
u8 ssid[HOSTAPD_MAX_SSID_LEN];
|
||||
size_t ssid_len;
|
||||
int ssid_set;
|
||||
unsigned int ssid_set:1;
|
||||
unsigned int utf8_ssid:1;
|
||||
|
||||
char vlan[IFNAMSIZ + 1];
|
||||
secpolicy security_policy;
|
||||
@ -70,6 +67,10 @@ struct hostapd_ssid {
|
||||
#define DYNAMIC_VLAN_OPTIONAL 1
|
||||
#define DYNAMIC_VLAN_REQUIRED 2
|
||||
int dynamic_vlan;
|
||||
#define DYNAMIC_VLAN_NAMING_WITHOUT_DEVICE 0
|
||||
#define DYNAMIC_VLAN_NAMING_WITH_DEVICE 1
|
||||
#define DYNAMIC_VLAN_NAMING_END 2
|
||||
int vlan_naming;
|
||||
#ifdef CONFIG_FULL_DYNAMIC_VLAN
|
||||
char *vlan_tagged_interface;
|
||||
#endif /* CONFIG_FULL_DYNAMIC_VLAN */
|
||||
@ -96,6 +97,11 @@ struct hostapd_vlan {
|
||||
};
|
||||
|
||||
#define PMK_LEN 32
|
||||
struct hostapd_sta_wpa_psk_short {
|
||||
struct hostapd_sta_wpa_psk_short *next;
|
||||
u8 psk[PMK_LEN];
|
||||
};
|
||||
|
||||
struct hostapd_wpa_psk {
|
||||
struct hostapd_wpa_psk *next;
|
||||
int group;
|
||||
@ -103,7 +109,6 @@ struct hostapd_wpa_psk {
|
||||
u8 addr[ETH_ALEN];
|
||||
};
|
||||
|
||||
#define EAP_USER_MAX_METHODS 8
|
||||
struct hostapd_eap_user {
|
||||
struct hostapd_eap_user *next;
|
||||
u8 *identity;
|
||||
@ -111,7 +116,7 @@ struct hostapd_eap_user {
|
||||
struct {
|
||||
int vendor;
|
||||
u32 method;
|
||||
} methods[EAP_USER_MAX_METHODS];
|
||||
} methods[EAP_MAX_METHODS];
|
||||
u8 *password;
|
||||
size_t password_len;
|
||||
int phase2;
|
||||
@ -122,25 +127,52 @@ struct hostapd_eap_user {
|
||||
int ttls_auth; /* EAP_TTLS_AUTH_* bitfield */
|
||||
};
|
||||
|
||||
struct hostapd_radius_attr {
|
||||
u8 type;
|
||||
struct wpabuf *val;
|
||||
struct hostapd_radius_attr *next;
|
||||
};
|
||||
|
||||
#define NUM_TX_QUEUES 8
|
||||
|
||||
#define NUM_TX_QUEUES 4
|
||||
|
||||
struct hostapd_tx_queue_params {
|
||||
int aifs;
|
||||
int cwmin;
|
||||
int cwmax;
|
||||
int burst; /* maximum burst time in 0.1 ms, i.e., 10 = 1 ms */
|
||||
int configured;
|
||||
};
|
||||
|
||||
struct hostapd_wmm_ac_params {
|
||||
int cwmin;
|
||||
int cwmax;
|
||||
int aifs;
|
||||
int txop_limit; /* in units of 32us */
|
||||
int admission_control_mandatory;
|
||||
|
||||
#define MAX_ROAMING_CONSORTIUM_LEN 15
|
||||
|
||||
struct hostapd_roaming_consortium {
|
||||
u8 len;
|
||||
u8 oi[MAX_ROAMING_CONSORTIUM_LEN];
|
||||
};
|
||||
|
||||
struct hostapd_lang_string {
|
||||
u8 lang[3];
|
||||
u8 name_len;
|
||||
u8 name[252];
|
||||
};
|
||||
|
||||
#define MAX_NAI_REALMS 10
|
||||
#define MAX_NAI_REALMLEN 255
|
||||
#define MAX_NAI_EAP_METHODS 5
|
||||
#define MAX_NAI_AUTH_TYPES 4
|
||||
struct hostapd_nai_realm_data {
|
||||
u8 encoding;
|
||||
char realm_buf[MAX_NAI_REALMLEN + 1];
|
||||
char *realm[MAX_NAI_REALMS];
|
||||
u8 eap_method_count;
|
||||
struct hostapd_nai_realm_eap {
|
||||
u8 eap_method;
|
||||
u8 num_auths;
|
||||
u8 auth_id[MAX_NAI_AUTH_TYPES];
|
||||
u8 auth_val[MAX_NAI_AUTH_TYPES];
|
||||
} eap_method[MAX_NAI_EAP_METHODS];
|
||||
};
|
||||
|
||||
/**
|
||||
* struct hostapd_bss_config - Per-BSS configuration
|
||||
@ -148,6 +180,7 @@ struct hostapd_wmm_ac_params {
|
||||
struct hostapd_bss_config {
|
||||
char iface[IFNAMSIZ + 1];
|
||||
char bridge[IFNAMSIZ + 1];
|
||||
char wds_bridge[IFNAMSIZ + 1];
|
||||
|
||||
enum hostapd_logger_level logger_syslog_level, logger_stdout_level;
|
||||
|
||||
@ -165,11 +198,21 @@ struct hostapd_bss_config {
|
||||
int eap_server; /* Use internal EAP server instead of external
|
||||
* RADIUS server */
|
||||
struct hostapd_eap_user *eap_user;
|
||||
char *eap_user_sqlite;
|
||||
char *eap_sim_db;
|
||||
struct hostapd_ip_addr own_ip_addr;
|
||||
char *nas_identifier;
|
||||
struct hostapd_radius_servers *radius;
|
||||
int acct_interim_interval;
|
||||
int radius_request_cui;
|
||||
struct hostapd_radius_attr *radius_auth_req_attr;
|
||||
struct hostapd_radius_attr *radius_acct_req_attr;
|
||||
int radius_das_port;
|
||||
unsigned int radius_das_time_window;
|
||||
int radius_das_require_event_timestamp;
|
||||
struct hostapd_ip_addr radius_das_client_addr;
|
||||
u8 *radius_das_shared_secret;
|
||||
size_t radius_das_shared_secret_len;
|
||||
|
||||
struct hostapd_ssid ssid;
|
||||
|
||||
@ -198,6 +241,7 @@ struct hostapd_bss_config {
|
||||
struct mac_acl_entry *deny_mac;
|
||||
int num_deny_mac;
|
||||
int wds_sta;
|
||||
int isolate;
|
||||
|
||||
int auth_algs; /* bitfield of allowed IEEE 802.11 authentication
|
||||
* algorithms, WPA_AUTH_ALG_{OPEN,SHARED,LEAP} */
|
||||
@ -211,6 +255,11 @@ struct hostapd_bss_config {
|
||||
/* dot11AssociationSAQueryRetryTimeout (in TUs) */
|
||||
int assoc_sa_query_retry_timeout;
|
||||
#endif /* CONFIG_IEEE80211W */
|
||||
enum {
|
||||
PSK_RADIUS_IGNORED = 0,
|
||||
PSK_RADIUS_ACCEPTED = 1,
|
||||
PSK_RADIUS_REQUIRED = 2
|
||||
} wpa_psk_radius;
|
||||
int wpa_pairwise;
|
||||
int wpa_group;
|
||||
int wpa_group_rekey;
|
||||
@ -231,6 +280,7 @@ struct hostapd_bss_config {
|
||||
struct ft_remote_r0kh *r0kh_list;
|
||||
struct ft_remote_r1kh *r1kh_list;
|
||||
int pmk_r1_push;
|
||||
int ft_over_ds;
|
||||
#endif /* CONFIG_IEEE80211R */
|
||||
|
||||
char *ctrl_interface; /* directory for UNIX domain sockets */
|
||||
@ -254,6 +304,8 @@ struct hostapd_bss_config {
|
||||
int pac_key_refresh_time;
|
||||
int eap_sim_aka_result_ind;
|
||||
int tnc;
|
||||
int fragment_size;
|
||||
u16 pwd_group;
|
||||
|
||||
char *radius_server_clients;
|
||||
int radius_server_auth_port;
|
||||
@ -283,6 +335,7 @@ struct hostapd_bss_config {
|
||||
*/
|
||||
u16 max_listen_interval;
|
||||
|
||||
int disable_pmksa_caching;
|
||||
int okc; /* Opportunistic Key Caching */
|
||||
|
||||
int wps_state;
|
||||
@ -295,7 +348,7 @@ struct hostapd_bss_config {
|
||||
char *model_name;
|
||||
char *model_number;
|
||||
char *serial_number;
|
||||
char *device_type;
|
||||
u8 device_type[WPS_DEV_TYPE_LEN];
|
||||
char *config_methods;
|
||||
u8 os_version[4];
|
||||
char *ap_pin;
|
||||
@ -311,7 +364,97 @@ struct hostapd_bss_config {
|
||||
char *model_description;
|
||||
char *model_url;
|
||||
char *upc;
|
||||
struct wpabuf *wps_vendor_ext[MAX_WPS_VENDOR_EXTENSIONS];
|
||||
int wps_nfc_dev_pw_id;
|
||||
struct wpabuf *wps_nfc_dh_pubkey;
|
||||
struct wpabuf *wps_nfc_dh_privkey;
|
||||
struct wpabuf *wps_nfc_dev_pw;
|
||||
#endif /* CONFIG_WPS */
|
||||
int pbc_in_m1;
|
||||
|
||||
#define P2P_ENABLED BIT(0)
|
||||
#define P2P_GROUP_OWNER BIT(1)
|
||||
#define P2P_GROUP_FORMATION BIT(2)
|
||||
#define P2P_MANAGE BIT(3)
|
||||
#define P2P_ALLOW_CROSS_CONNECTION BIT(4)
|
||||
int p2p;
|
||||
|
||||
int disassoc_low_ack;
|
||||
int skip_inactivity_poll;
|
||||
|
||||
#define TDLS_PROHIBIT BIT(0)
|
||||
#define TDLS_PROHIBIT_CHAN_SWITCH BIT(1)
|
||||
int tdls;
|
||||
int disable_11n;
|
||||
int disable_11ac;
|
||||
|
||||
/* IEEE 802.11v */
|
||||
int time_advertisement;
|
||||
char *time_zone;
|
||||
int wnm_sleep_mode;
|
||||
int bss_transition;
|
||||
|
||||
/* IEEE 802.11u - Interworking */
|
||||
int interworking;
|
||||
int access_network_type;
|
||||
int internet;
|
||||
int asra;
|
||||
int esr;
|
||||
int uesa;
|
||||
int venue_info_set;
|
||||
u8 venue_group;
|
||||
u8 venue_type;
|
||||
u8 hessid[ETH_ALEN];
|
||||
|
||||
/* IEEE 802.11u - Roaming Consortium list */
|
||||
unsigned int roaming_consortium_count;
|
||||
struct hostapd_roaming_consortium *roaming_consortium;
|
||||
|
||||
/* IEEE 802.11u - Venue Name duples */
|
||||
unsigned int venue_name_count;
|
||||
struct hostapd_lang_string *venue_name;
|
||||
|
||||
/* IEEE 802.11u - Network Authentication Type */
|
||||
u8 *network_auth_type;
|
||||
size_t network_auth_type_len;
|
||||
|
||||
/* IEEE 802.11u - IP Address Type Availability */
|
||||
u8 ipaddr_type_availability;
|
||||
u8 ipaddr_type_configured;
|
||||
|
||||
/* IEEE 802.11u - 3GPP Cellular Network */
|
||||
u8 *anqp_3gpp_cell_net;
|
||||
size_t anqp_3gpp_cell_net_len;
|
||||
|
||||
/* IEEE 802.11u - Domain Name */
|
||||
u8 *domain_name;
|
||||
size_t domain_name_len;
|
||||
|
||||
unsigned int nai_realm_count;
|
||||
struct hostapd_nai_realm_data *nai_realm_data;
|
||||
|
||||
u16 gas_comeback_delay;
|
||||
int gas_frag_limit;
|
||||
|
||||
#ifdef CONFIG_HS20
|
||||
int hs20;
|
||||
int disable_dgaf;
|
||||
unsigned int hs20_oper_friendly_name_count;
|
||||
struct hostapd_lang_string *hs20_oper_friendly_name;
|
||||
u8 *hs20_wan_metrics;
|
||||
u8 *hs20_connection_capability;
|
||||
size_t hs20_connection_capability_len;
|
||||
u8 *hs20_operating_class;
|
||||
u8 hs20_operating_class_len;
|
||||
#endif /* CONFIG_HS20 */
|
||||
|
||||
u8 wps_rf_bands; /* RF bands for WPS (WPS_RF_*) */
|
||||
|
||||
#ifdef CONFIG_RADIUS_TEST
|
||||
char *dump_msk_file;
|
||||
#endif /* CONFIG_RADIUS_TEST */
|
||||
|
||||
struct wpabuf *vendor_elements;
|
||||
};
|
||||
|
||||
|
||||
@ -332,12 +475,6 @@ struct hostapd_config {
|
||||
LONG_PREAMBLE = 0,
|
||||
SHORT_PREAMBLE = 1
|
||||
} preamble;
|
||||
enum {
|
||||
CTS_PROTECTION_AUTOMATIC = 0,
|
||||
CTS_PROTECTION_FORCE_ENABLED = 1,
|
||||
CTS_PROTECTION_FORCE_DISABLED = 2,
|
||||
CTS_PROTECTION_AUTOMATIC_NO_OLBC = 3,
|
||||
} cts_protection_type;
|
||||
|
||||
int *supported_rates;
|
||||
int *basic_rates;
|
||||
@ -371,6 +508,13 @@ struct hostapd_config {
|
||||
u16 ht_capab;
|
||||
int ieee80211n;
|
||||
int secondary_channel;
|
||||
int require_ht;
|
||||
u32 vht_capab;
|
||||
int ieee80211ac;
|
||||
int require_vht;
|
||||
u8 vht_oper_chwidth;
|
||||
u8 vht_oper_centr_freq_seg0_idx;
|
||||
u8 vht_oper_centr_freq_seg1_idx;
|
||||
};
|
||||
|
||||
|
||||
@ -389,8 +533,7 @@ const u8 * hostapd_get_psk(const struct hostapd_bss_config *conf,
|
||||
int hostapd_setup_wpa_psk(struct hostapd_bss_config *conf);
|
||||
const char * hostapd_get_vlan_id_ifname(struct hostapd_vlan *vlan,
|
||||
int vlan_id);
|
||||
const struct hostapd_eap_user *
|
||||
hostapd_get_eap_user(const struct hostapd_bss_config *conf, const u8 *identity,
|
||||
size_t identity_len, int phase2);
|
||||
struct hostapd_radius_attr *
|
||||
hostapd_config_get_radius_attr(struct hostapd_radius_attr *attr, u8 type);
|
||||
|
||||
#endif /* HOSTAPD_CONFIG_H */
|
||||
|
@ -2,14 +2,8 @@
|
||||
* hostapd - Driver operations
|
||||
* Copyright (c) 2009-2010, Jouni Malinen <j@w1.fi>
|
||||
*
|
||||
* This program is free software; you can redistribute it and/or modify
|
||||
* it under the terms of the GNU General Public License version 2 as
|
||||
* published by the Free Software Foundation.
|
||||
*
|
||||
* Alternatively, this software may be distributed under the terms of BSD
|
||||
* license.
|
||||
*
|
||||
* See README and COPYING for more details.
|
||||
* This software may be distributed under the terms of the BSD license.
|
||||
* See README for more details.
|
||||
*/
|
||||
|
||||
#include "utils/includes.h"
|
||||
@ -17,14 +11,18 @@
|
||||
#include "utils/common.h"
|
||||
#include "drivers/driver.h"
|
||||
#include "common/ieee802_11_defs.h"
|
||||
#include "wps/wps.h"
|
||||
#include "p2p/p2p.h"
|
||||
#include "hostapd.h"
|
||||
#include "ieee802_11.h"
|
||||
#include "sta_info.h"
|
||||
#include "ap_config.h"
|
||||
#include "p2p_hostapd.h"
|
||||
#include "hs20.h"
|
||||
#include "ap_drv_ops.h"
|
||||
|
||||
|
||||
static int hostapd_sta_flags_to_drv(int flags)
|
||||
u32 hostapd_sta_flags_to_drv(u32 flags)
|
||||
{
|
||||
int res = 0;
|
||||
if (flags & WLAN_STA_AUTHORIZED)
|
||||
@ -39,45 +37,190 @@ static int hostapd_sta_flags_to_drv(int flags)
|
||||
}
|
||||
|
||||
|
||||
static int hostapd_set_ap_wps_ie(struct hostapd_data *hapd)
|
||||
int hostapd_build_ap_extra_ies(struct hostapd_data *hapd,
|
||||
struct wpabuf **beacon_ret,
|
||||
struct wpabuf **proberesp_ret,
|
||||
struct wpabuf **assocresp_ret)
|
||||
{
|
||||
struct wpabuf *beacon, *proberesp;
|
||||
struct wpabuf *beacon = NULL, *proberesp = NULL, *assocresp = NULL;
|
||||
u8 buf[200], *pos;
|
||||
|
||||
*beacon_ret = *proberesp_ret = *assocresp_ret = NULL;
|
||||
|
||||
pos = buf;
|
||||
pos = hostapd_eid_time_adv(hapd, pos);
|
||||
if (pos != buf) {
|
||||
if (wpabuf_resize(&beacon, pos - buf) != 0)
|
||||
goto fail;
|
||||
wpabuf_put_data(beacon, buf, pos - buf);
|
||||
}
|
||||
pos = hostapd_eid_time_zone(hapd, pos);
|
||||
if (pos != buf) {
|
||||
if (wpabuf_resize(&proberesp, pos - buf) != 0)
|
||||
goto fail;
|
||||
wpabuf_put_data(proberesp, buf, pos - buf);
|
||||
}
|
||||
|
||||
pos = buf;
|
||||
pos = hostapd_eid_ext_capab(hapd, pos);
|
||||
if (pos != buf) {
|
||||
if (wpabuf_resize(&assocresp, pos - buf) != 0)
|
||||
goto fail;
|
||||
wpabuf_put_data(assocresp, buf, pos - buf);
|
||||
}
|
||||
pos = hostapd_eid_interworking(hapd, pos);
|
||||
pos = hostapd_eid_adv_proto(hapd, pos);
|
||||
pos = hostapd_eid_roaming_consortium(hapd, pos);
|
||||
if (pos != buf) {
|
||||
if (wpabuf_resize(&beacon, pos - buf) != 0)
|
||||
goto fail;
|
||||
wpabuf_put_data(beacon, buf, pos - buf);
|
||||
|
||||
if (wpabuf_resize(&proberesp, pos - buf) != 0)
|
||||
goto fail;
|
||||
wpabuf_put_data(proberesp, buf, pos - buf);
|
||||
}
|
||||
|
||||
if (hapd->wps_beacon_ie) {
|
||||
if (wpabuf_resize(&beacon, wpabuf_len(hapd->wps_beacon_ie)) <
|
||||
0)
|
||||
goto fail;
|
||||
wpabuf_put_buf(beacon, hapd->wps_beacon_ie);
|
||||
}
|
||||
|
||||
if (hapd->wps_probe_resp_ie) {
|
||||
if (wpabuf_resize(&proberesp,
|
||||
wpabuf_len(hapd->wps_probe_resp_ie)) < 0)
|
||||
goto fail;
|
||||
wpabuf_put_buf(proberesp, hapd->wps_probe_resp_ie);
|
||||
}
|
||||
|
||||
#ifdef CONFIG_P2P
|
||||
if (hapd->p2p_beacon_ie) {
|
||||
if (wpabuf_resize(&beacon, wpabuf_len(hapd->p2p_beacon_ie)) <
|
||||
0)
|
||||
goto fail;
|
||||
wpabuf_put_buf(beacon, hapd->p2p_beacon_ie);
|
||||
}
|
||||
|
||||
if (hapd->p2p_probe_resp_ie) {
|
||||
if (wpabuf_resize(&proberesp,
|
||||
wpabuf_len(hapd->p2p_probe_resp_ie)) < 0)
|
||||
goto fail;
|
||||
wpabuf_put_buf(proberesp, hapd->p2p_probe_resp_ie);
|
||||
}
|
||||
#endif /* CONFIG_P2P */
|
||||
|
||||
#ifdef CONFIG_P2P_MANAGER
|
||||
if (hapd->conf->p2p & P2P_MANAGE) {
|
||||
if (wpabuf_resize(&beacon, 100) == 0) {
|
||||
u8 *start, *p;
|
||||
start = wpabuf_put(beacon, 0);
|
||||
p = hostapd_eid_p2p_manage(hapd, start);
|
||||
wpabuf_put(beacon, p - start);
|
||||
}
|
||||
|
||||
if (wpabuf_resize(&proberesp, 100) == 0) {
|
||||
u8 *start, *p;
|
||||
start = wpabuf_put(proberesp, 0);
|
||||
p = hostapd_eid_p2p_manage(hapd, start);
|
||||
wpabuf_put(proberesp, p - start);
|
||||
}
|
||||
}
|
||||
#endif /* CONFIG_P2P_MANAGER */
|
||||
|
||||
#ifdef CONFIG_WPS2
|
||||
if (hapd->conf->wps_state) {
|
||||
struct wpabuf *a = wps_build_assoc_resp_ie();
|
||||
if (a && wpabuf_resize(&assocresp, wpabuf_len(a)) == 0)
|
||||
wpabuf_put_buf(assocresp, a);
|
||||
wpabuf_free(a);
|
||||
}
|
||||
#endif /* CONFIG_WPS2 */
|
||||
|
||||
#ifdef CONFIG_P2P_MANAGER
|
||||
if (hapd->conf->p2p & P2P_MANAGE) {
|
||||
if (wpabuf_resize(&assocresp, 100) == 0) {
|
||||
u8 *start, *p;
|
||||
start = wpabuf_put(assocresp, 0);
|
||||
p = hostapd_eid_p2p_manage(hapd, start);
|
||||
wpabuf_put(assocresp, p - start);
|
||||
}
|
||||
}
|
||||
#endif /* CONFIG_P2P_MANAGER */
|
||||
|
||||
#ifdef CONFIG_WIFI_DISPLAY
|
||||
if (hapd->p2p_group) {
|
||||
struct wpabuf *a;
|
||||
a = p2p_group_assoc_resp_ie(hapd->p2p_group, P2P_SC_SUCCESS);
|
||||
if (a && wpabuf_resize(&assocresp, wpabuf_len(a)) == 0)
|
||||
wpabuf_put_buf(assocresp, a);
|
||||
wpabuf_free(a);
|
||||
}
|
||||
#endif /* CONFIG_WIFI_DISPLAY */
|
||||
|
||||
#ifdef CONFIG_HS20
|
||||
pos = buf;
|
||||
pos = hostapd_eid_hs20_indication(hapd, pos);
|
||||
if (pos != buf) {
|
||||
if (wpabuf_resize(&beacon, pos - buf) != 0)
|
||||
goto fail;
|
||||
wpabuf_put_data(beacon, buf, pos - buf);
|
||||
|
||||
if (wpabuf_resize(&proberesp, pos - buf) != 0)
|
||||
goto fail;
|
||||
wpabuf_put_data(proberesp, buf, pos - buf);
|
||||
}
|
||||
#endif /* CONFIG_HS20 */
|
||||
|
||||
*beacon_ret = beacon;
|
||||
*proberesp_ret = proberesp;
|
||||
*assocresp_ret = assocresp;
|
||||
|
||||
return 0;
|
||||
|
||||
fail:
|
||||
wpabuf_free(beacon);
|
||||
wpabuf_free(proberesp);
|
||||
wpabuf_free(assocresp);
|
||||
return -1;
|
||||
}
|
||||
|
||||
|
||||
void hostapd_free_ap_extra_ies(struct hostapd_data *hapd,
|
||||
struct wpabuf *beacon,
|
||||
struct wpabuf *proberesp,
|
||||
struct wpabuf *assocresp)
|
||||
{
|
||||
wpabuf_free(beacon);
|
||||
wpabuf_free(proberesp);
|
||||
wpabuf_free(assocresp);
|
||||
}
|
||||
|
||||
|
||||
int hostapd_set_ap_wps_ie(struct hostapd_data *hapd)
|
||||
{
|
||||
struct wpabuf *beacon, *proberesp, *assocresp;
|
||||
int ret;
|
||||
|
||||
if (hapd->driver == NULL || hapd->driver->set_ap_wps_ie == NULL)
|
||||
return 0;
|
||||
|
||||
beacon = hapd->wps_beacon_ie;
|
||||
proberesp = hapd->wps_probe_resp_ie;
|
||||
if (hostapd_build_ap_extra_ies(hapd, &beacon, &proberesp, &assocresp) <
|
||||
0)
|
||||
return -1;
|
||||
|
||||
ret = hapd->driver->set_ap_wps_ie(hapd->drv_priv, beacon, proberesp);
|
||||
ret = hapd->driver->set_ap_wps_ie(hapd->drv_priv, beacon, proberesp,
|
||||
assocresp);
|
||||
|
||||
hostapd_free_ap_extra_ies(hapd, beacon, proberesp, assocresp);
|
||||
|
||||
return ret;
|
||||
}
|
||||
|
||||
|
||||
static int hostapd_send_mgmt_frame(struct hostapd_data *hapd, const void *msg,
|
||||
size_t len)
|
||||
{
|
||||
if (hapd->driver == NULL || hapd->driver->send_mlme == NULL)
|
||||
return 0;
|
||||
return hapd->driver->send_mlme(hapd->drv_priv, msg, len);
|
||||
}
|
||||
|
||||
|
||||
static int hostapd_send_eapol(struct hostapd_data *hapd, const u8 *addr,
|
||||
const u8 *data, size_t data_len, int encrypt)
|
||||
{
|
||||
if (hapd->driver == NULL || hapd->driver->hapd_send_eapol == NULL)
|
||||
return 0;
|
||||
return hapd->driver->hapd_send_eapol(hapd->drv_priv, addr, data,
|
||||
data_len, encrypt,
|
||||
hapd->own_addr);
|
||||
}
|
||||
|
||||
|
||||
static int hostapd_set_authorized(struct hostapd_data *hapd,
|
||||
struct sta_info *sta, int authorized)
|
||||
int hostapd_set_authorized(struct hostapd_data *hapd,
|
||||
struct sta_info *sta, int authorized)
|
||||
{
|
||||
if (authorized) {
|
||||
return hostapd_sta_set_flags(hapd, sta->addr,
|
||||
@ -92,39 +235,7 @@ static int hostapd_set_authorized(struct hostapd_data *hapd,
|
||||
}
|
||||
|
||||
|
||||
static int hostapd_set_key(const char *ifname, struct hostapd_data *hapd,
|
||||
enum wpa_alg alg, const u8 *addr, int key_idx,
|
||||
int set_tx, const u8 *seq, size_t seq_len,
|
||||
const u8 *key, size_t key_len)
|
||||
{
|
||||
if (hapd->driver == NULL || hapd->driver->set_key == NULL)
|
||||
return 0;
|
||||
return hapd->driver->set_key(ifname, hapd->drv_priv, alg, addr,
|
||||
key_idx, set_tx, seq, seq_len, key,
|
||||
key_len);
|
||||
}
|
||||
|
||||
|
||||
static int hostapd_read_sta_data(struct hostapd_data *hapd,
|
||||
struct hostap_sta_driver_data *data,
|
||||
const u8 *addr)
|
||||
{
|
||||
if (hapd->driver == NULL || hapd->driver->read_sta_data == NULL)
|
||||
return -1;
|
||||
return hapd->driver->read_sta_data(hapd->drv_priv, data, addr);
|
||||
}
|
||||
|
||||
|
||||
static int hostapd_sta_clear_stats(struct hostapd_data *hapd, const u8 *addr)
|
||||
{
|
||||
if (hapd->driver == NULL || hapd->driver->sta_clear_stats == NULL)
|
||||
return 0;
|
||||
return hapd->driver->sta_clear_stats(hapd->drv_priv, addr);
|
||||
}
|
||||
|
||||
|
||||
static int hostapd_set_sta_flags(struct hostapd_data *hapd,
|
||||
struct sta_info *sta)
|
||||
int hostapd_set_sta_flags(struct hostapd_data *hapd, struct sta_info *sta)
|
||||
{
|
||||
int set_flags, total_flags, flags_and, flags_or;
|
||||
total_flags = hostapd_sta_flags_to_drv(sta->flags);
|
||||
@ -140,8 +251,8 @@ static int hostapd_set_sta_flags(struct hostapd_data *hapd,
|
||||
}
|
||||
|
||||
|
||||
static int hostapd_set_drv_ieee8021x(struct hostapd_data *hapd,
|
||||
const char *ifname, int enabled)
|
||||
int hostapd_set_drv_ieee8021x(struct hostapd_data *hapd, const char *ifname,
|
||||
int enabled)
|
||||
{
|
||||
struct wpa_bss_params params;
|
||||
os_memset(¶ms, 0, sizeof(params));
|
||||
@ -154,166 +265,80 @@ static int hostapd_set_drv_ieee8021x(struct hostapd_data *hapd,
|
||||
params.wpa_pairwise = hapd->conf->wpa_pairwise;
|
||||
params.wpa_key_mgmt = hapd->conf->wpa_key_mgmt;
|
||||
params.rsn_preauth = hapd->conf->rsn_preauth;
|
||||
#ifdef CONFIG_IEEE80211W
|
||||
params.ieee80211w = hapd->conf->ieee80211w;
|
||||
#endif /* CONFIG_IEEE80211W */
|
||||
}
|
||||
return hostapd_set_ieee8021x(hapd, ¶ms);
|
||||
}
|
||||
|
||||
|
||||
static int hostapd_set_radius_acl_auth(struct hostapd_data *hapd,
|
||||
const u8 *mac, int accepted,
|
||||
u32 session_timeout)
|
||||
{
|
||||
if (hapd->driver == NULL || hapd->driver->set_radius_acl_auth == NULL)
|
||||
return 0;
|
||||
return hapd->driver->set_radius_acl_auth(hapd->drv_priv, mac, accepted,
|
||||
session_timeout);
|
||||
}
|
||||
|
||||
|
||||
static int hostapd_set_radius_acl_expire(struct hostapd_data *hapd,
|
||||
const u8 *mac)
|
||||
{
|
||||
if (hapd->driver == NULL ||
|
||||
hapd->driver->set_radius_acl_expire == NULL)
|
||||
return 0;
|
||||
return hapd->driver->set_radius_acl_expire(hapd->drv_priv, mac);
|
||||
}
|
||||
|
||||
|
||||
static int hostapd_set_bss_params(struct hostapd_data *hapd,
|
||||
int use_protection)
|
||||
{
|
||||
int ret = 0;
|
||||
int preamble;
|
||||
#ifdef CONFIG_IEEE80211N
|
||||
u8 buf[60], *ht_capab, *ht_oper, *pos;
|
||||
|
||||
pos = buf;
|
||||
ht_capab = pos;
|
||||
pos = hostapd_eid_ht_capabilities(hapd, pos);
|
||||
ht_oper = pos;
|
||||
pos = hostapd_eid_ht_operation(hapd, pos);
|
||||
if (pos > ht_oper && ht_oper > ht_capab &&
|
||||
hostapd_set_ht_params(hapd, ht_capab + 2, ht_capab[1],
|
||||
ht_oper + 2, ht_oper[1])) {
|
||||
wpa_printf(MSG_ERROR, "Could not set HT capabilities "
|
||||
"for kernel driver");
|
||||
ret = -1;
|
||||
}
|
||||
|
||||
#endif /* CONFIG_IEEE80211N */
|
||||
|
||||
if (hostapd_set_cts_protect(hapd, use_protection)) {
|
||||
wpa_printf(MSG_ERROR, "Failed to set CTS protect in kernel "
|
||||
"driver");
|
||||
ret = -1;
|
||||
}
|
||||
|
||||
if (hapd->iface->current_mode &&
|
||||
hapd->iface->current_mode->mode == HOSTAPD_MODE_IEEE80211G &&
|
||||
hostapd_set_short_slot_time(hapd,
|
||||
hapd->iface->num_sta_no_short_slot_time
|
||||
> 0 ? 0 : 1)) {
|
||||
wpa_printf(MSG_ERROR, "Failed to set Short Slot Time option "
|
||||
"in kernel driver");
|
||||
ret = -1;
|
||||
}
|
||||
|
||||
if (hapd->iface->num_sta_no_short_preamble == 0 &&
|
||||
hapd->iconf->preamble == SHORT_PREAMBLE)
|
||||
preamble = SHORT_PREAMBLE;
|
||||
else
|
||||
preamble = LONG_PREAMBLE;
|
||||
if (hostapd_set_preamble(hapd, preamble)) {
|
||||
wpa_printf(MSG_ERROR, "Could not set preamble for kernel "
|
||||
"driver");
|
||||
ret = -1;
|
||||
}
|
||||
|
||||
return ret;
|
||||
}
|
||||
|
||||
|
||||
static int hostapd_set_beacon(struct hostapd_data *hapd,
|
||||
const u8 *head, size_t head_len,
|
||||
const u8 *tail, size_t tail_len, int dtim_period,
|
||||
int beacon_int)
|
||||
{
|
||||
if (hapd->driver == NULL || hapd->driver->set_beacon == NULL)
|
||||
return 0;
|
||||
return hapd->driver->set_beacon(hapd->drv_priv,
|
||||
head, head_len, tail, tail_len,
|
||||
dtim_period, beacon_int);
|
||||
}
|
||||
|
||||
|
||||
static int hostapd_vlan_if_add(struct hostapd_data *hapd, const char *ifname)
|
||||
int hostapd_vlan_if_add(struct hostapd_data *hapd, const char *ifname)
|
||||
{
|
||||
char force_ifname[IFNAMSIZ];
|
||||
u8 if_addr[ETH_ALEN];
|
||||
return hostapd_if_add(hapd, WPA_IF_AP_VLAN, ifname, NULL, NULL, NULL,
|
||||
force_ifname, if_addr);
|
||||
return hostapd_if_add(hapd, WPA_IF_AP_VLAN, ifname, hapd->own_addr,
|
||||
NULL, NULL, force_ifname, if_addr, NULL);
|
||||
}
|
||||
|
||||
static int hostapd_vlan_if_remove(struct hostapd_data *hapd,
|
||||
const char *ifname)
|
||||
|
||||
int hostapd_vlan_if_remove(struct hostapd_data *hapd, const char *ifname)
|
||||
{
|
||||
return hostapd_if_remove(hapd, WPA_IF_AP_VLAN, ifname);
|
||||
}
|
||||
|
||||
|
||||
static int hostapd_set_wds_sta(struct hostapd_data *hapd, const u8 *addr,
|
||||
int aid, int val)
|
||||
int hostapd_set_wds_sta(struct hostapd_data *hapd, const u8 *addr, int aid,
|
||||
int val)
|
||||
{
|
||||
const char *bridge = NULL;
|
||||
|
||||
if (hapd->driver == NULL || hapd->driver->set_wds_sta == NULL)
|
||||
return 0;
|
||||
return hapd->driver->set_wds_sta(hapd->drv_priv, addr, aid, val);
|
||||
if (hapd->conf->wds_bridge[0])
|
||||
bridge = hapd->conf->wds_bridge;
|
||||
else if (hapd->conf->bridge[0])
|
||||
bridge = hapd->conf->bridge;
|
||||
return hapd->driver->set_wds_sta(hapd->drv_priv, addr, aid, val,
|
||||
bridge);
|
||||
}
|
||||
|
||||
|
||||
static int hostapd_set_sta_vlan(const char *ifname, struct hostapd_data *hapd,
|
||||
const u8 *addr, int vlan_id)
|
||||
int hostapd_add_sta_node(struct hostapd_data *hapd, const u8 *addr,
|
||||
u16 auth_alg)
|
||||
{
|
||||
if (hapd->driver == NULL || hapd->driver->set_sta_vlan == NULL)
|
||||
if (hapd->driver == NULL || hapd->driver->add_sta_node == NULL)
|
||||
return 0;
|
||||
return hapd->driver->set_sta_vlan(hapd->drv_priv, addr, ifname,
|
||||
vlan_id);
|
||||
return hapd->driver->add_sta_node(hapd->drv_priv, addr, auth_alg);
|
||||
}
|
||||
|
||||
|
||||
static int hostapd_get_inact_sec(struct hostapd_data *hapd, const u8 *addr)
|
||||
int hostapd_sta_auth(struct hostapd_data *hapd, const u8 *addr,
|
||||
u16 seq, u16 status, const u8 *ie, size_t len)
|
||||
{
|
||||
if (hapd->driver == NULL || hapd->driver->get_inact_sec == NULL)
|
||||
if (hapd->driver == NULL || hapd->driver->sta_auth == NULL)
|
||||
return 0;
|
||||
return hapd->driver->get_inact_sec(hapd->drv_priv, addr);
|
||||
return hapd->driver->sta_auth(hapd->drv_priv, hapd->own_addr, addr,
|
||||
seq, status, ie, len);
|
||||
}
|
||||
|
||||
|
||||
static int hostapd_sta_deauth(struct hostapd_data *hapd, const u8 *addr,
|
||||
int reason)
|
||||
int hostapd_sta_assoc(struct hostapd_data *hapd, const u8 *addr,
|
||||
int reassoc, u16 status, const u8 *ie, size_t len)
|
||||
{
|
||||
if (hapd->driver == NULL || hapd->driver->sta_deauth == NULL)
|
||||
if (hapd->driver == NULL || hapd->driver->sta_assoc == NULL)
|
||||
return 0;
|
||||
return hapd->driver->sta_deauth(hapd->drv_priv, hapd->own_addr, addr,
|
||||
reason);
|
||||
return hapd->driver->sta_assoc(hapd->drv_priv, hapd->own_addr, addr,
|
||||
reassoc, status, ie, len);
|
||||
}
|
||||
|
||||
|
||||
static int hostapd_sta_disassoc(struct hostapd_data *hapd, const u8 *addr,
|
||||
int reason)
|
||||
{
|
||||
if (hapd->driver == NULL || hapd->driver->sta_disassoc == NULL)
|
||||
return 0;
|
||||
return hapd->driver->sta_disassoc(hapd->drv_priv, hapd->own_addr, addr,
|
||||
reason);
|
||||
}
|
||||
|
||||
|
||||
static int hostapd_sta_add(struct hostapd_data *hapd,
|
||||
const u8 *addr, u16 aid, u16 capability,
|
||||
const u8 *supp_rates, size_t supp_rates_len,
|
||||
u16 listen_interval,
|
||||
const struct ieee80211_ht_capabilities *ht_capab)
|
||||
int hostapd_sta_add(struct hostapd_data *hapd,
|
||||
const u8 *addr, u16 aid, u16 capability,
|
||||
const u8 *supp_rates, size_t supp_rates_len,
|
||||
u16 listen_interval,
|
||||
const struct ieee80211_ht_capabilities *ht_capab,
|
||||
u32 flags, u8 qosinfo)
|
||||
{
|
||||
struct hostapd_sta_add_params params;
|
||||
|
||||
@ -330,52 +355,19 @@ static int hostapd_sta_add(struct hostapd_data *hapd,
|
||||
params.supp_rates_len = supp_rates_len;
|
||||
params.listen_interval = listen_interval;
|
||||
params.ht_capabilities = ht_capab;
|
||||
params.flags = hostapd_sta_flags_to_drv(flags);
|
||||
params.qosinfo = qosinfo;
|
||||
return hapd->driver->sta_add(hapd->drv_priv, ¶ms);
|
||||
}
|
||||
|
||||
|
||||
static int hostapd_sta_remove(struct hostapd_data *hapd, const u8 *addr)
|
||||
int hostapd_add_tspec(struct hostapd_data *hapd, const u8 *addr,
|
||||
u8 *tspec_ie, size_t tspec_ielen)
|
||||
{
|
||||
if (hapd->driver == NULL || hapd->driver->sta_remove == NULL)
|
||||
if (hapd->driver == NULL || hapd->driver->add_tspec == NULL)
|
||||
return 0;
|
||||
return hapd->driver->sta_remove(hapd->drv_priv, addr);
|
||||
}
|
||||
|
||||
|
||||
static int hostapd_set_countermeasures(struct hostapd_data *hapd, int enabled)
|
||||
{
|
||||
if (hapd->driver == NULL ||
|
||||
hapd->driver->hapd_set_countermeasures == NULL)
|
||||
return 0;
|
||||
return hapd->driver->hapd_set_countermeasures(hapd->drv_priv, enabled);
|
||||
}
|
||||
|
||||
|
||||
void hostapd_set_driver_ops(struct hostapd_driver_ops *ops)
|
||||
{
|
||||
ops->set_ap_wps_ie = hostapd_set_ap_wps_ie;
|
||||
ops->send_mgmt_frame = hostapd_send_mgmt_frame;
|
||||
ops->send_eapol = hostapd_send_eapol;
|
||||
ops->set_authorized = hostapd_set_authorized;
|
||||
ops->set_key = hostapd_set_key;
|
||||
ops->read_sta_data = hostapd_read_sta_data;
|
||||
ops->sta_clear_stats = hostapd_sta_clear_stats;
|
||||
ops->set_sta_flags = hostapd_set_sta_flags;
|
||||
ops->set_drv_ieee8021x = hostapd_set_drv_ieee8021x;
|
||||
ops->set_radius_acl_auth = hostapd_set_radius_acl_auth;
|
||||
ops->set_radius_acl_expire = hostapd_set_radius_acl_expire;
|
||||
ops->set_bss_params = hostapd_set_bss_params;
|
||||
ops->set_beacon = hostapd_set_beacon;
|
||||
ops->vlan_if_add = hostapd_vlan_if_add;
|
||||
ops->vlan_if_remove = hostapd_vlan_if_remove;
|
||||
ops->set_wds_sta = hostapd_set_wds_sta;
|
||||
ops->set_sta_vlan = hostapd_set_sta_vlan;
|
||||
ops->get_inact_sec = hostapd_get_inact_sec;
|
||||
ops->sta_deauth = hostapd_sta_deauth;
|
||||
ops->sta_disassoc = hostapd_sta_disassoc;
|
||||
ops->sta_add = hostapd_sta_add;
|
||||
ops->sta_remove = hostapd_sta_remove;
|
||||
ops->set_countermeasures = hostapd_set_countermeasures;
|
||||
return hapd->driver->add_tspec(hapd->drv_priv, addr, tspec_ie,
|
||||
tspec_ielen);
|
||||
}
|
||||
|
||||
|
||||
@ -414,12 +406,14 @@ int hostapd_set_ssid(struct hostapd_data *hapd, const u8 *buf, size_t len)
|
||||
|
||||
int hostapd_if_add(struct hostapd_data *hapd, enum wpa_driver_if_type type,
|
||||
const char *ifname, const u8 *addr, void *bss_ctx,
|
||||
void **drv_priv, char *force_ifname, u8 *if_addr)
|
||||
void **drv_priv, char *force_ifname, u8 *if_addr,
|
||||
const char *bridge)
|
||||
{
|
||||
if (hapd->driver == NULL || hapd->driver->if_add == NULL)
|
||||
return -1;
|
||||
return hapd->driver->if_add(hapd->drv_priv, type, ifname, addr,
|
||||
bss_ctx, drv_priv, force_ifname, if_addr);
|
||||
bss_ctx, drv_priv, force_ifname, if_addr,
|
||||
bridge);
|
||||
}
|
||||
|
||||
|
||||
@ -502,16 +496,6 @@ int hostapd_sta_set_flags(struct hostapd_data *hapd, u8 *addr,
|
||||
}
|
||||
|
||||
|
||||
int hostapd_set_rate_sets(struct hostapd_data *hapd, int *supp_rates,
|
||||
int *basic_rates, int mode)
|
||||
{
|
||||
if (hapd->driver == NULL || hapd->driver->set_rate_sets == NULL)
|
||||
return 0;
|
||||
return hapd->driver->set_rate_sets(hapd->drv_priv, supp_rates,
|
||||
basic_rates, mode);
|
||||
}
|
||||
|
||||
|
||||
int hostapd_set_country(struct hostapd_data *hapd, const char *country)
|
||||
{
|
||||
if (hapd->driver == NULL ||
|
||||
@ -521,30 +505,6 @@ int hostapd_set_country(struct hostapd_data *hapd, const char *country)
|
||||
}
|
||||
|
||||
|
||||
int hostapd_set_cts_protect(struct hostapd_data *hapd, int value)
|
||||
{
|
||||
if (hapd->driver == NULL || hapd->driver->set_cts_protect == NULL)
|
||||
return 0;
|
||||
return hapd->driver->set_cts_protect(hapd->drv_priv, value);
|
||||
}
|
||||
|
||||
|
||||
int hostapd_set_preamble(struct hostapd_data *hapd, int value)
|
||||
{
|
||||
if (hapd->driver == NULL || hapd->driver->set_preamble == NULL)
|
||||
return 0;
|
||||
return hapd->driver->set_preamble(hapd->drv_priv, value);
|
||||
}
|
||||
|
||||
|
||||
int hostapd_set_short_slot_time(struct hostapd_data *hapd, int value)
|
||||
{
|
||||
if (hapd->driver == NULL || hapd->driver->set_short_slot_time == NULL)
|
||||
return 0;
|
||||
return hapd->driver->set_short_slot_time(hapd->drv_priv, value);
|
||||
}
|
||||
|
||||
|
||||
int hostapd_set_tx_queue_params(struct hostapd_data *hapd, int queue, int aifs,
|
||||
int cw_min, int cw_max, int burst_time)
|
||||
{
|
||||
@ -555,15 +515,6 @@ int hostapd_set_tx_queue_params(struct hostapd_data *hapd, int queue, int aifs,
|
||||
}
|
||||
|
||||
|
||||
int hostapd_valid_bss_mask(struct hostapd_data *hapd, const u8 *addr,
|
||||
const u8 *mask)
|
||||
{
|
||||
if (hapd->driver == NULL || hapd->driver->valid_bss_mask == NULL)
|
||||
return 1;
|
||||
return hapd->driver->valid_bss_mask(hapd->drv_priv, addr, mask);
|
||||
}
|
||||
|
||||
|
||||
struct hostapd_hw_modes *
|
||||
hostapd_get_hw_feature_data(struct hostapd_data *hapd, u16 *num_modes,
|
||||
u16 *flags)
|
||||
@ -584,19 +535,6 @@ int hostapd_driver_commit(struct hostapd_data *hapd)
|
||||
}
|
||||
|
||||
|
||||
int hostapd_set_ht_params(struct hostapd_data *hapd,
|
||||
const u8 *ht_capab, size_t ht_capab_len,
|
||||
const u8 *ht_oper, size_t ht_oper_len)
|
||||
{
|
||||
if (hapd->driver == NULL || hapd->driver->set_ht_params == NULL ||
|
||||
ht_capab == NULL || ht_oper == NULL)
|
||||
return 0;
|
||||
return hapd->driver->set_ht_params(hapd->drv_priv,
|
||||
ht_capab, ht_capab_len,
|
||||
ht_oper, ht_oper_len);
|
||||
}
|
||||
|
||||
|
||||
int hostapd_drv_none(struct hostapd_data *hapd)
|
||||
{
|
||||
return hapd->driver && os_strcmp(hapd->driver->name, "none") == 0;
|
||||
@ -619,3 +557,78 @@ struct wpa_scan_results * hostapd_driver_get_scan_results(
|
||||
return hapd->driver->get_scan_results2(hapd->drv_priv);
|
||||
return NULL;
|
||||
}
|
||||
|
||||
|
||||
int hostapd_driver_set_noa(struct hostapd_data *hapd, u8 count, int start,
|
||||
int duration)
|
||||
{
|
||||
if (hapd->driver && hapd->driver->set_noa)
|
||||
return hapd->driver->set_noa(hapd->drv_priv, count, start,
|
||||
duration);
|
||||
return -1;
|
||||
}
|
||||
|
||||
|
||||
int hostapd_drv_set_key(const char *ifname, struct hostapd_data *hapd,
|
||||
enum wpa_alg alg, const u8 *addr,
|
||||
int key_idx, int set_tx,
|
||||
const u8 *seq, size_t seq_len,
|
||||
const u8 *key, size_t key_len)
|
||||
{
|
||||
if (hapd->driver == NULL || hapd->driver->set_key == NULL)
|
||||
return 0;
|
||||
return hapd->driver->set_key(ifname, hapd->drv_priv, alg, addr,
|
||||
key_idx, set_tx, seq, seq_len, key,
|
||||
key_len);
|
||||
}
|
||||
|
||||
|
||||
int hostapd_drv_send_mlme(struct hostapd_data *hapd,
|
||||
const void *msg, size_t len, int noack)
|
||||
{
|
||||
if (hapd->driver == NULL || hapd->driver->send_mlme == NULL)
|
||||
return 0;
|
||||
return hapd->driver->send_mlme(hapd->drv_priv, msg, len, noack);
|
||||
}
|
||||
|
||||
|
||||
int hostapd_drv_sta_deauth(struct hostapd_data *hapd,
|
||||
const u8 *addr, int reason)
|
||||
{
|
||||
if (hapd->driver == NULL || hapd->driver->sta_deauth == NULL)
|
||||
return 0;
|
||||
return hapd->driver->sta_deauth(hapd->drv_priv, hapd->own_addr, addr,
|
||||
reason);
|
||||
}
|
||||
|
||||
|
||||
int hostapd_drv_sta_disassoc(struct hostapd_data *hapd,
|
||||
const u8 *addr, int reason)
|
||||
{
|
||||
if (hapd->driver == NULL || hapd->driver->sta_disassoc == NULL)
|
||||
return 0;
|
||||
return hapd->driver->sta_disassoc(hapd->drv_priv, hapd->own_addr, addr,
|
||||
reason);
|
||||
}
|
||||
|
||||
|
||||
int hostapd_drv_wnm_oper(struct hostapd_data *hapd, enum wnm_oper oper,
|
||||
const u8 *peer, u8 *buf, u16 *buf_len)
|
||||
{
|
||||
if (hapd->driver == NULL || hapd->driver->wnm_oper == NULL)
|
||||
return 0;
|
||||
return hapd->driver->wnm_oper(hapd->drv_priv, oper, peer, buf,
|
||||
buf_len);
|
||||
}
|
||||
|
||||
|
||||
int hostapd_drv_send_action(struct hostapd_data *hapd, unsigned int freq,
|
||||
unsigned int wait, const u8 *dst, const u8 *data,
|
||||
size_t len)
|
||||
{
|
||||
if (hapd->driver == NULL || hapd->driver->send_action == NULL)
|
||||
return 0;
|
||||
return hapd->driver->send_action(hapd->drv_priv, freq, wait, dst,
|
||||
hapd->own_addr, hapd->own_addr, data,
|
||||
len, 0);
|
||||
}
|
||||
|
@ -2,14 +2,8 @@
|
||||
* hostapd - Driver operations
|
||||
* Copyright (c) 2009, Jouni Malinen <j@w1.fi>
|
||||
*
|
||||
* This program is free software; you can redistribute it and/or modify
|
||||
* it under the terms of the GNU General Public License version 2 as
|
||||
* published by the Free Software Foundation.
|
||||
*
|
||||
* Alternatively, this software may be distributed under the terms of BSD
|
||||
* license.
|
||||
*
|
||||
* See README and COPYING for more details.
|
||||
* This software may be distributed under the terms of the BSD license.
|
||||
* See README for more details.
|
||||
*/
|
||||
|
||||
#ifndef AP_DRV_OPS
|
||||
@ -18,8 +12,32 @@
|
||||
enum wpa_driver_if_type;
|
||||
struct wpa_bss_params;
|
||||
struct wpa_driver_scan_params;
|
||||
struct ieee80211_ht_capabilities;
|
||||
|
||||
void hostapd_set_driver_ops(struct hostapd_driver_ops *ops);
|
||||
u32 hostapd_sta_flags_to_drv(u32 flags);
|
||||
int hostapd_build_ap_extra_ies(struct hostapd_data *hapd,
|
||||
struct wpabuf **beacon,
|
||||
struct wpabuf **proberesp,
|
||||
struct wpabuf **assocresp);
|
||||
void hostapd_free_ap_extra_ies(struct hostapd_data *hapd, struct wpabuf *beacon,
|
||||
struct wpabuf *proberesp,
|
||||
struct wpabuf *assocresp);
|
||||
int hostapd_set_ap_wps_ie(struct hostapd_data *hapd);
|
||||
int hostapd_set_authorized(struct hostapd_data *hapd,
|
||||
struct sta_info *sta, int authorized);
|
||||
int hostapd_set_sta_flags(struct hostapd_data *hapd, struct sta_info *sta);
|
||||
int hostapd_set_drv_ieee8021x(struct hostapd_data *hapd, const char *ifname,
|
||||
int enabled);
|
||||
int hostapd_vlan_if_add(struct hostapd_data *hapd, const char *ifname);
|
||||
int hostapd_vlan_if_remove(struct hostapd_data *hapd, const char *ifname);
|
||||
int hostapd_set_wds_sta(struct hostapd_data *hapd, const u8 *addr, int aid,
|
||||
int val);
|
||||
int hostapd_sta_add(struct hostapd_data *hapd,
|
||||
const u8 *addr, u16 aid, u16 capability,
|
||||
const u8 *supp_rates, size_t supp_rates_len,
|
||||
u16 listen_interval,
|
||||
const struct ieee80211_ht_capabilities *ht_capab,
|
||||
u32 flags, u8 qosinfo);
|
||||
int hostapd_set_privacy(struct hostapd_data *hapd, int enabled);
|
||||
int hostapd_set_generic_elem(struct hostapd_data *hapd, const u8 *elem,
|
||||
size_t elem_len);
|
||||
@ -27,7 +45,8 @@ int hostapd_get_ssid(struct hostapd_data *hapd, u8 *buf, size_t len);
|
||||
int hostapd_set_ssid(struct hostapd_data *hapd, const u8 *buf, size_t len);
|
||||
int hostapd_if_add(struct hostapd_data *hapd, enum wpa_driver_if_type type,
|
||||
const char *ifname, const u8 *addr, void *bss_ctx,
|
||||
void **drv_priv, char *force_ifname, u8 *if_addr);
|
||||
void **drv_priv, char *force_ifname, u8 *if_addr,
|
||||
const char *bridge);
|
||||
int hostapd_if_remove(struct hostapd_data *hapd, enum wpa_driver_if_type type,
|
||||
const char *ifname);
|
||||
int hostapd_set_ieee8021x(struct hostapd_data *hapd,
|
||||
@ -41,27 +60,157 @@ int hostapd_set_rts(struct hostapd_data *hapd, int rts);
|
||||
int hostapd_set_frag(struct hostapd_data *hapd, int frag);
|
||||
int hostapd_sta_set_flags(struct hostapd_data *hapd, u8 *addr,
|
||||
int total_flags, int flags_or, int flags_and);
|
||||
int hostapd_set_rate_sets(struct hostapd_data *hapd, int *supp_rates,
|
||||
int *basic_rates, int mode);
|
||||
int hostapd_set_country(struct hostapd_data *hapd, const char *country);
|
||||
int hostapd_set_cts_protect(struct hostapd_data *hapd, int value);
|
||||
int hostapd_set_preamble(struct hostapd_data *hapd, int value);
|
||||
int hostapd_set_short_slot_time(struct hostapd_data *hapd, int value);
|
||||
int hostapd_set_tx_queue_params(struct hostapd_data *hapd, int queue, int aifs,
|
||||
int cw_min, int cw_max, int burst_time);
|
||||
int hostapd_valid_bss_mask(struct hostapd_data *hapd, const u8 *addr,
|
||||
const u8 *mask);
|
||||
struct hostapd_hw_modes *
|
||||
hostapd_get_hw_feature_data(struct hostapd_data *hapd, u16 *num_modes,
|
||||
u16 *flags);
|
||||
int hostapd_driver_commit(struct hostapd_data *hapd);
|
||||
int hostapd_set_ht_params(struct hostapd_data *hapd,
|
||||
const u8 *ht_capab, size_t ht_capab_len,
|
||||
const u8 *ht_oper, size_t ht_oper_len);
|
||||
int hostapd_drv_none(struct hostapd_data *hapd);
|
||||
int hostapd_driver_scan(struct hostapd_data *hapd,
|
||||
struct wpa_driver_scan_params *params);
|
||||
struct wpa_scan_results * hostapd_driver_get_scan_results(
|
||||
struct hostapd_data *hapd);
|
||||
int hostapd_driver_set_noa(struct hostapd_data *hapd, u8 count, int start,
|
||||
int duration);
|
||||
int hostapd_drv_set_key(const char *ifname,
|
||||
struct hostapd_data *hapd,
|
||||
enum wpa_alg alg, const u8 *addr,
|
||||
int key_idx, int set_tx,
|
||||
const u8 *seq, size_t seq_len,
|
||||
const u8 *key, size_t key_len);
|
||||
int hostapd_drv_send_mlme(struct hostapd_data *hapd,
|
||||
const void *msg, size_t len, int noack);
|
||||
int hostapd_drv_sta_deauth(struct hostapd_data *hapd,
|
||||
const u8 *addr, int reason);
|
||||
int hostapd_drv_sta_disassoc(struct hostapd_data *hapd,
|
||||
const u8 *addr, int reason);
|
||||
int hostapd_drv_send_action(struct hostapd_data *hapd, unsigned int freq,
|
||||
unsigned int wait, const u8 *dst, const u8 *data,
|
||||
size_t len);
|
||||
int hostapd_add_sta_node(struct hostapd_data *hapd, const u8 *addr,
|
||||
u16 auth_alg);
|
||||
int hostapd_sta_auth(struct hostapd_data *hapd, const u8 *addr,
|
||||
u16 seq, u16 status, const u8 *ie, size_t len);
|
||||
int hostapd_sta_assoc(struct hostapd_data *hapd, const u8 *addr,
|
||||
int reassoc, u16 status, const u8 *ie, size_t len);
|
||||
int hostapd_add_tspec(struct hostapd_data *hapd, const u8 *addr,
|
||||
u8 *tspec_ie, size_t tspec_ielen);
|
||||
|
||||
|
||||
#include "drivers/driver.h"
|
||||
|
||||
int hostapd_drv_wnm_oper(struct hostapd_data *hapd,
|
||||
enum wnm_oper oper, const u8 *peer,
|
||||
u8 *buf, u16 *buf_len);
|
||||
|
||||
static inline int hostapd_drv_set_countermeasures(struct hostapd_data *hapd,
|
||||
int enabled)
|
||||
{
|
||||
if (hapd->driver == NULL ||
|
||||
hapd->driver->hapd_set_countermeasures == NULL)
|
||||
return 0;
|
||||
return hapd->driver->hapd_set_countermeasures(hapd->drv_priv, enabled);
|
||||
}
|
||||
|
||||
static inline int hostapd_drv_set_sta_vlan(const char *ifname,
|
||||
struct hostapd_data *hapd,
|
||||
const u8 *addr, int vlan_id)
|
||||
{
|
||||
if (hapd->driver == NULL || hapd->driver->set_sta_vlan == NULL)
|
||||
return 0;
|
||||
return hapd->driver->set_sta_vlan(hapd->drv_priv, addr, ifname,
|
||||
vlan_id);
|
||||
}
|
||||
|
||||
static inline int hostapd_drv_get_inact_sec(struct hostapd_data *hapd,
|
||||
const u8 *addr)
|
||||
{
|
||||
if (hapd->driver == NULL || hapd->driver->get_inact_sec == NULL)
|
||||
return 0;
|
||||
return hapd->driver->get_inact_sec(hapd->drv_priv, addr);
|
||||
}
|
||||
|
||||
static inline int hostapd_drv_sta_remove(struct hostapd_data *hapd,
|
||||
const u8 *addr)
|
||||
{
|
||||
if (hapd->driver == NULL || hapd->driver->sta_remove == NULL)
|
||||
return 0;
|
||||
return hapd->driver->sta_remove(hapd->drv_priv, addr);
|
||||
}
|
||||
|
||||
static inline int hostapd_drv_hapd_send_eapol(struct hostapd_data *hapd,
|
||||
const u8 *addr, const u8 *data,
|
||||
size_t data_len, int encrypt,
|
||||
u32 flags)
|
||||
{
|
||||
if (hapd->driver == NULL || hapd->driver->hapd_send_eapol == NULL)
|
||||
return 0;
|
||||
return hapd->driver->hapd_send_eapol(hapd->drv_priv, addr, data,
|
||||
data_len, encrypt,
|
||||
hapd->own_addr, flags);
|
||||
}
|
||||
|
||||
static inline int hostapd_drv_read_sta_data(
|
||||
struct hostapd_data *hapd, struct hostap_sta_driver_data *data,
|
||||
const u8 *addr)
|
||||
{
|
||||
if (hapd->driver == NULL || hapd->driver->read_sta_data == NULL)
|
||||
return -1;
|
||||
return hapd->driver->read_sta_data(hapd->drv_priv, data, addr);
|
||||
}
|
||||
|
||||
static inline int hostapd_drv_sta_clear_stats(struct hostapd_data *hapd,
|
||||
const u8 *addr)
|
||||
{
|
||||
if (hapd->driver == NULL || hapd->driver->sta_clear_stats == NULL)
|
||||
return 0;
|
||||
return hapd->driver->sta_clear_stats(hapd->drv_priv, addr);
|
||||
}
|
||||
|
||||
static inline int hostapd_drv_set_ap(struct hostapd_data *hapd,
|
||||
struct wpa_driver_ap_params *params)
|
||||
{
|
||||
if (hapd->driver == NULL || hapd->driver->set_ap == NULL)
|
||||
return 0;
|
||||
return hapd->driver->set_ap(hapd->drv_priv, params);
|
||||
}
|
||||
|
||||
static inline int hostapd_drv_set_radius_acl_auth(struct hostapd_data *hapd,
|
||||
const u8 *mac, int accepted,
|
||||
u32 session_timeout)
|
||||
{
|
||||
if (hapd->driver == NULL || hapd->driver->set_radius_acl_auth == NULL)
|
||||
return 0;
|
||||
return hapd->driver->set_radius_acl_auth(hapd->drv_priv, mac, accepted,
|
||||
session_timeout);
|
||||
}
|
||||
|
||||
static inline int hostapd_drv_set_radius_acl_expire(struct hostapd_data *hapd,
|
||||
const u8 *mac)
|
||||
{
|
||||
if (hapd->driver == NULL ||
|
||||
hapd->driver->set_radius_acl_expire == NULL)
|
||||
return 0;
|
||||
return hapd->driver->set_radius_acl_expire(hapd->drv_priv, mac);
|
||||
}
|
||||
|
||||
static inline int hostapd_drv_set_authmode(struct hostapd_data *hapd,
|
||||
int auth_algs)
|
||||
{
|
||||
if (hapd->driver == NULL || hapd->driver->set_authmode == NULL)
|
||||
return 0;
|
||||
return hapd->driver->set_authmode(hapd->drv_priv, auth_algs);
|
||||
}
|
||||
|
||||
static inline void hostapd_drv_poll_client(struct hostapd_data *hapd,
|
||||
const u8 *own_addr, const u8 *addr,
|
||||
int qos)
|
||||
{
|
||||
if (hapd->driver == NULL || hapd->driver->poll_client == NULL)
|
||||
return;
|
||||
hapd->driver->poll_client(hapd->drv_priv, own_addr, addr, qos);
|
||||
}
|
||||
|
||||
#endif /* AP_DRV_OPS */
|
||||
|
@ -4,14 +4,8 @@
|
||||
* Copyright (c) 2003-2004, Instant802 Networks, Inc.
|
||||
* Copyright (c) 2006, Devicescape Software, Inc.
|
||||
*
|
||||
* This program is free software; you can redistribute it and/or modify
|
||||
* it under the terms of the GNU General Public License version 2 as
|
||||
* published by the Free Software Foundation.
|
||||
*
|
||||
* Alternatively, this software may be distributed under the terms of BSD
|
||||
* license.
|
||||
*
|
||||
* See README and COPYING for more details.
|
||||
* This software may be distributed under the terms of the BSD license.
|
||||
* See README for more details.
|
||||
*/
|
||||
|
||||
#include "utils/includes.h"
|
||||
@ -227,6 +221,7 @@ void ap_list_process_beacon(struct hostapd_iface *iface,
|
||||
struct hostapd_frame_info *fi)
|
||||
{
|
||||
struct ap_info *ap;
|
||||
struct os_time now;
|
||||
int new_ap = 0;
|
||||
size_t len;
|
||||
int set_beacon = 0;
|
||||
@ -256,23 +251,9 @@ void ap_list_process_beacon(struct hostapd_iface *iface,
|
||||
ap->ssid_len = len;
|
||||
}
|
||||
|
||||
os_memset(ap->supported_rates, 0, WLAN_SUPP_RATES_MAX);
|
||||
len = 0;
|
||||
if (elems->supp_rates) {
|
||||
len = elems->supp_rates_len;
|
||||
if (len > WLAN_SUPP_RATES_MAX)
|
||||
len = WLAN_SUPP_RATES_MAX;
|
||||
os_memcpy(ap->supported_rates, elems->supp_rates, len);
|
||||
}
|
||||
if (elems->ext_supp_rates) {
|
||||
int len2;
|
||||
if (len + elems->ext_supp_rates_len > WLAN_SUPP_RATES_MAX)
|
||||
len2 = WLAN_SUPP_RATES_MAX - len;
|
||||
else
|
||||
len2 = elems->ext_supp_rates_len;
|
||||
os_memcpy(ap->supported_rates + len, elems->ext_supp_rates,
|
||||
len2);
|
||||
}
|
||||
merge_byte_arrays(ap->supported_rates, WLAN_SUPP_RATES_MAX,
|
||||
elems->supp_rates, elems->supp_rates_len,
|
||||
elems->ext_supp_rates, elems->ext_supp_rates_len);
|
||||
|
||||
ap->wpa = elems->wpa_ie != NULL;
|
||||
|
||||
@ -292,11 +273,10 @@ void ap_list_process_beacon(struct hostapd_iface *iface,
|
||||
ap->ht_support = 0;
|
||||
|
||||
ap->num_beacons++;
|
||||
time(&ap->last_beacon);
|
||||
if (fi) {
|
||||
ap->ssi_signal = fi->ssi_signal;
|
||||
os_get_time(&now);
|
||||
ap->last_beacon = now.sec;
|
||||
if (fi)
|
||||
ap->datarate = fi->datarate;
|
||||
}
|
||||
|
||||
if (!new_ap && ap != iface->ap_list) {
|
||||
/* move AP entry into the beginning of the list so that the
|
||||
@ -324,14 +304,14 @@ void ap_list_process_beacon(struct hostapd_iface *iface,
|
||||
#endif /* CONFIG_IEEE80211N */
|
||||
|
||||
if (set_beacon)
|
||||
ieee802_11_set_beacons(iface);
|
||||
ieee802_11_update_beacons(iface);
|
||||
}
|
||||
|
||||
|
||||
static void ap_list_timer(void *eloop_ctx, void *timeout_ctx)
|
||||
{
|
||||
struct hostapd_iface *iface = eloop_ctx;
|
||||
time_t now;
|
||||
struct os_time now;
|
||||
struct ap_info *ap;
|
||||
int set_beacon = 0;
|
||||
|
||||
@ -340,12 +320,12 @@ static void ap_list_timer(void *eloop_ctx, void *timeout_ctx)
|
||||
if (!iface->ap_list)
|
||||
return;
|
||||
|
||||
time(&now);
|
||||
os_get_time(&now);
|
||||
|
||||
while (iface->ap_list) {
|
||||
ap = iface->ap_list->prev;
|
||||
if (ap->last_beacon + iface->conf->ap_table_expiration_time >=
|
||||
now)
|
||||
now.sec)
|
||||
break;
|
||||
|
||||
ap_free_ap(iface, ap);
|
||||
@ -379,7 +359,7 @@ static void ap_list_timer(void *eloop_ctx, void *timeout_ctx)
|
||||
}
|
||||
|
||||
if (set_beacon)
|
||||
ieee802_11_set_beacons(iface);
|
||||
ieee802_11_update_beacons(iface);
|
||||
}
|
||||
|
||||
|
||||
|
@ -4,14 +4,8 @@
|
||||
* Copyright (c) 2003-2004, Instant802 Networks, Inc.
|
||||
* Copyright (c) 2006, Devicescape Software, Inc.
|
||||
*
|
||||
* This program is free software; you can redistribute it and/or modify
|
||||
* it under the terms of the GNU General Public License version 2 as
|
||||
* published by the Free Software Foundation.
|
||||
*
|
||||
* Alternatively, this software may be distributed under the terms of BSD
|
||||
* license.
|
||||
*
|
||||
* See README and COPYING for more details.
|
||||
* This software may be distributed under the terms of the BSD license.
|
||||
* See README for more details.
|
||||
*/
|
||||
|
||||
#ifndef AP_LIST_H
|
||||
@ -40,12 +34,11 @@ struct ap_info {
|
||||
|
||||
int channel;
|
||||
int datarate; /* in 100 kbps */
|
||||
int ssi_signal;
|
||||
|
||||
int ht_support;
|
||||
|
||||
unsigned int num_beacons; /* number of beacon frames received */
|
||||
time_t last_beacon;
|
||||
os_time_t last_beacon;
|
||||
|
||||
int already_seen; /* whether API call AP-NEW has already fetched
|
||||
* information about this AP */
|
||||
|
@ -4,14 +4,8 @@
|
||||
* Copyright 2003-2004, Instant802 Networks, Inc.
|
||||
* Copyright 2005-2006, Devicescape Software, Inc.
|
||||
*
|
||||
* This program is free software; you can redistribute it and/or modify
|
||||
* it under the terms of the GNU General Public License version 2 as
|
||||
* published by the Free Software Foundation.
|
||||
*
|
||||
* Alternatively, this software may be distributed under the terms of BSD
|
||||
* license.
|
||||
*
|
||||
* See README and COPYING for more details.
|
||||
* This software may be distributed under the terms of the BSD license.
|
||||
* See README for more details.
|
||||
*/
|
||||
|
||||
#include "utils/includes.h"
|
||||
|
@ -4,14 +4,8 @@
|
||||
* Copyright 2003-2004, Instant802 Networks, Inc.
|
||||
* Copyright 2005-2006, Devicescape Software, Inc.
|
||||
*
|
||||
* This program is free software; you can redistribute it and/or modify
|
||||
* it under the terms of the GNU General Public License version 2 as
|
||||
* published by the Free Software Foundation.
|
||||
*
|
||||
* Alternatively, this software may be distributed under the terms of BSD
|
||||
* license.
|
||||
*
|
||||
* See README and COPYING for more details.
|
||||
* This software may be distributed under the terms of the BSD license.
|
||||
* See README for more details.
|
||||
*/
|
||||
|
||||
#ifndef MLME_H
|
||||
|
@ -2,14 +2,8 @@
|
||||
* Authentication server setup
|
||||
* Copyright (c) 2002-2009, Jouni Malinen <j@w1.fi>
|
||||
*
|
||||
* This program is free software; you can redistribute it and/or modify
|
||||
* it under the terms of the GNU General Public License version 2 as
|
||||
* published by the Free Software Foundation.
|
||||
*
|
||||
* Alternatively, this software may be distributed under the terms of BSD
|
||||
* license.
|
||||
*
|
||||
* See README and COPYING for more details.
|
||||
* This software may be distributed under the terms of the BSD license.
|
||||
* See README for more details.
|
||||
*/
|
||||
|
||||
#include "utils/includes.h"
|
||||
@ -60,7 +54,7 @@ static int hostapd_radius_get_eap_user(void *ctx, const u8 *identity,
|
||||
struct eap_user *user)
|
||||
{
|
||||
const struct hostapd_eap_user *eap_user;
|
||||
int i, count;
|
||||
int i;
|
||||
|
||||
eap_user = hostapd_get_eap_user(ctx, identity, identity_len, phase2);
|
||||
if (eap_user == NULL)
|
||||
@ -70,10 +64,7 @@ static int hostapd_radius_get_eap_user(void *ctx, const u8 *identity,
|
||||
return 0;
|
||||
|
||||
os_memset(user, 0, sizeof(*user));
|
||||
count = EAP_USER_MAX_METHODS;
|
||||
if (count > EAP_MAX_METHODS)
|
||||
count = EAP_MAX_METHODS;
|
||||
for (i = 0; i < count; i++) {
|
||||
for (i = 0; i < EAP_MAX_METHODS; i++) {
|
||||
user->methods[i].vendor = eap_user->methods[i].vendor;
|
||||
user->methods[i].method = eap_user->methods[i].method;
|
||||
}
|
||||
@ -101,7 +92,7 @@ static int hostapd_setup_radius_srv(struct hostapd_data *hapd)
|
||||
os_memset(&srv, 0, sizeof(srv));
|
||||
srv.client_file = conf->radius_server_clients;
|
||||
srv.auth_port = conf->radius_server_auth_port;
|
||||
srv.conf_ctx = conf;
|
||||
srv.conf_ctx = hapd;
|
||||
srv.eap_sim_db_priv = hapd->eap_sim_db_priv;
|
||||
srv.ssl_ctx = hapd->ssl_ctx;
|
||||
srv.msg_ctx = hapd->msg_ctx;
|
||||
@ -119,6 +110,10 @@ static int hostapd_setup_radius_srv(struct hostapd_data *hapd)
|
||||
srv.get_eap_user = hostapd_radius_get_eap_user;
|
||||
srv.eap_req_id_text = conf->eap_req_id_text;
|
||||
srv.eap_req_id_text_len = conf->eap_req_id_text_len;
|
||||
srv.pwd_group = conf->pwd_group;
|
||||
#ifdef CONFIG_RADIUS_TEST
|
||||
srv.dump_msk_file = conf->dump_msk_file;
|
||||
#endif /* CONFIG_RADIUS_TEST */
|
||||
|
||||
hapd->radius_srv = radius_server_init(&srv);
|
||||
if (hapd->radius_srv == NULL) {
|
||||
|
@ -2,14 +2,8 @@
|
||||
* Authentication server setup
|
||||
* Copyright (c) 2002-2009, Jouni Malinen <j@w1.fi>
|
||||
*
|
||||
* This program is free software; you can redistribute it and/or modify
|
||||
* it under the terms of the GNU General Public License version 2 as
|
||||
* published by the Free Software Foundation.
|
||||
*
|
||||
* Alternatively, this software may be distributed under the terms of BSD
|
||||
* license.
|
||||
*
|
||||
* See README and COPYING for more details.
|
||||
* This software may be distributed under the terms of the BSD license.
|
||||
* See README for more details.
|
||||
*/
|
||||
|
||||
#ifndef AUTHSRV_H
|
||||
|
@ -2,7 +2,7 @@
|
||||
* hostapd / IEEE 802.11 Management: Beacon and Probe Request/Response
|
||||
* Copyright (c) 2002-2004, Instant802 Networks, Inc.
|
||||
* Copyright (c) 2005-2006, Devicescape Software, Inc.
|
||||
* Copyright (c) 2008-2009, Jouni Malinen <j@w1.fi>
|
||||
* Copyright (c) 2008-2012, Jouni Malinen <j@w1.fi>
|
||||
*
|
||||
* This program is free software; you can redistribute it and/or modify
|
||||
* it under the terms of the GNU General Public License version 2 as
|
||||
@ -22,15 +22,22 @@
|
||||
#include "common/ieee802_11_defs.h"
|
||||
#include "common/ieee802_11_common.h"
|
||||
#include "drivers/driver.h"
|
||||
#include "wps/wps_defs.h"
|
||||
#include "p2p/p2p.h"
|
||||
#include "hostapd.h"
|
||||
#include "ieee802_11.h"
|
||||
#include "wpa_auth.h"
|
||||
#include "wmm.h"
|
||||
#include "ap_config.h"
|
||||
#include "sta_info.h"
|
||||
#include "p2p_hostapd.h"
|
||||
#include "ap_drv_ops.h"
|
||||
#include "beacon.h"
|
||||
#include "hs20.h"
|
||||
|
||||
|
||||
#ifdef NEED_AP_MLME
|
||||
|
||||
static u8 ieee802_11_erp_info(struct hostapd_data *hapd)
|
||||
{
|
||||
u8 erp = 0;
|
||||
@ -39,23 +46,11 @@ static u8 ieee802_11_erp_info(struct hostapd_data *hapd)
|
||||
hapd->iface->current_mode->mode != HOSTAPD_MODE_IEEE80211G)
|
||||
return 0;
|
||||
|
||||
switch (hapd->iconf->cts_protection_type) {
|
||||
case CTS_PROTECTION_FORCE_ENABLED:
|
||||
erp |= ERP_INFO_NON_ERP_PRESENT | ERP_INFO_USE_PROTECTION;
|
||||
break;
|
||||
case CTS_PROTECTION_FORCE_DISABLED:
|
||||
erp = 0;
|
||||
break;
|
||||
case CTS_PROTECTION_AUTOMATIC:
|
||||
if (hapd->iface->olbc)
|
||||
erp |= ERP_INFO_USE_PROTECTION;
|
||||
/* continue */
|
||||
case CTS_PROTECTION_AUTOMATIC_NO_OLBC:
|
||||
if (hapd->iface->num_sta_non_erp > 0) {
|
||||
erp |= ERP_INFO_NON_ERP_PRESENT |
|
||||
ERP_INFO_USE_PROTECTION;
|
||||
}
|
||||
break;
|
||||
if (hapd->iface->olbc)
|
||||
erp |= ERP_INFO_USE_PROTECTION;
|
||||
if (hapd->iface->num_sta_non_erp > 0) {
|
||||
erp |= ERP_INFO_NON_ERP_PRESENT |
|
||||
ERP_INFO_USE_PROTECTION;
|
||||
}
|
||||
if (hapd->iface->num_sta_no_short_preamble > 0 ||
|
||||
hapd->iconf->preamble == LONG_PREAMBLE)
|
||||
@ -178,8 +173,7 @@ static u8 * hostapd_eid_country(struct hostapd_data *hapd, u8 *eid,
|
||||
}
|
||||
|
||||
|
||||
static u8 * hostapd_eid_wpa(struct hostapd_data *hapd, u8 *eid, size_t len,
|
||||
struct sta_info *sta)
|
||||
static u8 * hostapd_eid_wpa(struct hostapd_data *hapd, u8 *eid, size_t len)
|
||||
{
|
||||
const u8 *ie;
|
||||
size_t ielen;
|
||||
@ -193,92 +187,37 @@ static u8 * hostapd_eid_wpa(struct hostapd_data *hapd, u8 *eid, size_t len,
|
||||
}
|
||||
|
||||
|
||||
void handle_probe_req(struct hostapd_data *hapd,
|
||||
const struct ieee80211_mgmt *mgmt, size_t len)
|
||||
static u8 * hostapd_gen_probe_resp(struct hostapd_data *hapd,
|
||||
struct sta_info *sta,
|
||||
const struct ieee80211_mgmt *req,
|
||||
int is_p2p, size_t *resp_len)
|
||||
{
|
||||
struct ieee80211_mgmt *resp;
|
||||
struct ieee802_11_elems elems;
|
||||
char *ssid;
|
||||
u8 *pos, *epos;
|
||||
const u8 *ie;
|
||||
size_t ssid_len, ie_len;
|
||||
struct sta_info *sta = NULL;
|
||||
size_t buflen;
|
||||
size_t i;
|
||||
|
||||
ie = mgmt->u.probe_req.variable;
|
||||
ie_len = len - (IEEE80211_HDRLEN + sizeof(mgmt->u.probe_req));
|
||||
|
||||
for (i = 0; hapd->probereq_cb && i < hapd->num_probereq_cb; i++)
|
||||
if (hapd->probereq_cb[i].cb(hapd->probereq_cb[i].ctx,
|
||||
mgmt->sa, ie, ie_len) > 0)
|
||||
return;
|
||||
|
||||
if (!hapd->iconf->send_probe_response)
|
||||
return;
|
||||
|
||||
if (ieee802_11_parse_elems(ie, ie_len, &elems, 0) == ParseFailed) {
|
||||
wpa_printf(MSG_DEBUG, "Could not parse ProbeReq from " MACSTR,
|
||||
MAC2STR(mgmt->sa));
|
||||
return;
|
||||
}
|
||||
|
||||
ssid = NULL;
|
||||
ssid_len = 0;
|
||||
|
||||
if ((!elems.ssid || !elems.supp_rates)) {
|
||||
wpa_printf(MSG_DEBUG, "STA " MACSTR " sent probe request "
|
||||
"without SSID or supported rates element",
|
||||
MAC2STR(mgmt->sa));
|
||||
return;
|
||||
}
|
||||
|
||||
if (hapd->conf->ignore_broadcast_ssid && elems.ssid_len == 0) {
|
||||
wpa_printf(MSG_MSGDUMP, "Probe Request from " MACSTR " for "
|
||||
"broadcast SSID ignored", MAC2STR(mgmt->sa));
|
||||
return;
|
||||
}
|
||||
|
||||
sta = ap_get_sta(hapd, mgmt->sa);
|
||||
|
||||
if (elems.ssid_len == 0 ||
|
||||
(elems.ssid_len == hapd->conf->ssid.ssid_len &&
|
||||
os_memcmp(elems.ssid, hapd->conf->ssid.ssid, elems.ssid_len) ==
|
||||
0)) {
|
||||
ssid = hapd->conf->ssid.ssid;
|
||||
ssid_len = hapd->conf->ssid.ssid_len;
|
||||
if (sta)
|
||||
sta->ssid_probe = &hapd->conf->ssid;
|
||||
}
|
||||
|
||||
if (!ssid) {
|
||||
if (!(mgmt->da[0] & 0x01)) {
|
||||
char ssid_txt[33];
|
||||
ieee802_11_print_ssid(ssid_txt, elems.ssid,
|
||||
elems.ssid_len);
|
||||
wpa_printf(MSG_MSGDUMP, "Probe Request from " MACSTR
|
||||
" for foreign SSID '%s'",
|
||||
MAC2STR(mgmt->sa), ssid_txt);
|
||||
}
|
||||
return;
|
||||
}
|
||||
|
||||
/* TODO: verify that supp_rates contains at least one matching rate
|
||||
* with AP configuration */
|
||||
#define MAX_PROBERESP_LEN 768
|
||||
buflen = MAX_PROBERESP_LEN;
|
||||
#ifdef CONFIG_WPS
|
||||
if (hapd->wps_probe_resp_ie)
|
||||
buflen += wpabuf_len(hapd->wps_probe_resp_ie);
|
||||
#endif /* CONFIG_WPS */
|
||||
#ifdef CONFIG_P2P
|
||||
if (hapd->p2p_probe_resp_ie)
|
||||
buflen += wpabuf_len(hapd->p2p_probe_resp_ie);
|
||||
#endif /* CONFIG_P2P */
|
||||
if (hapd->conf->vendor_elements)
|
||||
buflen += wpabuf_len(hapd->conf->vendor_elements);
|
||||
resp = os_zalloc(buflen);
|
||||
if (resp == NULL)
|
||||
return;
|
||||
return NULL;
|
||||
|
||||
epos = ((u8 *) resp) + MAX_PROBERESP_LEN;
|
||||
|
||||
resp->frame_control = IEEE80211_FC(WLAN_FC_TYPE_MGMT,
|
||||
WLAN_FC_STYPE_PROBE_RESP);
|
||||
os_memcpy(resp->da, mgmt->sa, ETH_ALEN);
|
||||
if (req)
|
||||
os_memcpy(resp->da, req->sa, ETH_ALEN);
|
||||
os_memcpy(resp->sa, hapd->own_addr, ETH_ALEN);
|
||||
|
||||
os_memcpy(resp->bssid, hapd->own_addr, ETH_ALEN);
|
||||
@ -291,9 +230,9 @@ void handle_probe_req(struct hostapd_data *hapd,
|
||||
|
||||
pos = resp->u.probe_resp.variable;
|
||||
*pos++ = WLAN_EID_SSID;
|
||||
*pos++ = ssid_len;
|
||||
os_memcpy(pos, ssid, ssid_len);
|
||||
pos += ssid_len;
|
||||
*pos++ = hapd->conf->ssid.ssid_len;
|
||||
os_memcpy(pos, hapd->conf->ssid.ssid, hapd->conf->ssid.ssid_len);
|
||||
pos += hapd->conf->ssid.ssid_len;
|
||||
|
||||
/* Supported rates */
|
||||
pos = hostapd_eid_supp_rates(hapd, pos);
|
||||
@ -310,13 +249,27 @@ void handle_probe_req(struct hostapd_data *hapd,
|
||||
pos = hostapd_eid_ext_supp_rates(hapd, pos);
|
||||
|
||||
/* RSN, MDIE, WPA */
|
||||
pos = hostapd_eid_wpa(hapd, pos, epos - pos, sta);
|
||||
pos = hostapd_eid_wpa(hapd, pos, epos - pos);
|
||||
|
||||
#ifdef CONFIG_IEEE80211N
|
||||
pos = hostapd_eid_ht_capabilities(hapd, pos);
|
||||
pos = hostapd_eid_ht_operation(hapd, pos);
|
||||
#endif /* CONFIG_IEEE80211N */
|
||||
|
||||
pos = hostapd_eid_ext_capab(hapd, pos);
|
||||
|
||||
pos = hostapd_eid_time_adv(hapd, pos);
|
||||
pos = hostapd_eid_time_zone(hapd, pos);
|
||||
|
||||
pos = hostapd_eid_interworking(hapd, pos);
|
||||
pos = hostapd_eid_adv_proto(hapd, pos);
|
||||
pos = hostapd_eid_roaming_consortium(hapd, pos);
|
||||
|
||||
#ifdef CONFIG_IEEE80211AC
|
||||
pos = hostapd_eid_vht_capabilities(hapd, pos);
|
||||
pos = hostapd_eid_vht_operation(hapd, pos);
|
||||
#endif /* CONFIG_IEEE80211AC */
|
||||
|
||||
/* Wi-Fi Alliance WMM */
|
||||
pos = hostapd_eid_wmm(hapd, pos);
|
||||
|
||||
@ -328,23 +281,291 @@ void handle_probe_req(struct hostapd_data *hapd,
|
||||
}
|
||||
#endif /* CONFIG_WPS */
|
||||
|
||||
if (hapd->drv.send_mgmt_frame(hapd, resp, pos - (u8 *) resp) < 0)
|
||||
#ifdef CONFIG_P2P
|
||||
if ((hapd->conf->p2p & P2P_ENABLED) && is_p2p &&
|
||||
hapd->p2p_probe_resp_ie) {
|
||||
os_memcpy(pos, wpabuf_head(hapd->p2p_probe_resp_ie),
|
||||
wpabuf_len(hapd->p2p_probe_resp_ie));
|
||||
pos += wpabuf_len(hapd->p2p_probe_resp_ie);
|
||||
}
|
||||
#endif /* CONFIG_P2P */
|
||||
#ifdef CONFIG_P2P_MANAGER
|
||||
if ((hapd->conf->p2p & (P2P_MANAGE | P2P_ENABLED | P2P_GROUP_OWNER)) ==
|
||||
P2P_MANAGE)
|
||||
pos = hostapd_eid_p2p_manage(hapd, pos);
|
||||
#endif /* CONFIG_P2P_MANAGER */
|
||||
|
||||
#ifdef CONFIG_HS20
|
||||
pos = hostapd_eid_hs20_indication(hapd, pos);
|
||||
#endif /* CONFIG_HS20 */
|
||||
|
||||
if (hapd->conf->vendor_elements) {
|
||||
os_memcpy(pos, wpabuf_head(hapd->conf->vendor_elements),
|
||||
wpabuf_len(hapd->conf->vendor_elements));
|
||||
pos += wpabuf_len(hapd->conf->vendor_elements);
|
||||
}
|
||||
|
||||
*resp_len = pos - (u8 *) resp;
|
||||
return (u8 *) resp;
|
||||
}
|
||||
|
||||
|
||||
enum ssid_match_result {
|
||||
NO_SSID_MATCH,
|
||||
EXACT_SSID_MATCH,
|
||||
WILDCARD_SSID_MATCH
|
||||
};
|
||||
|
||||
static enum ssid_match_result ssid_match(struct hostapd_data *hapd,
|
||||
const u8 *ssid, size_t ssid_len,
|
||||
const u8 *ssid_list,
|
||||
size_t ssid_list_len)
|
||||
{
|
||||
const u8 *pos, *end;
|
||||
int wildcard = 0;
|
||||
|
||||
if (ssid_len == 0)
|
||||
wildcard = 1;
|
||||
if (ssid_len == hapd->conf->ssid.ssid_len &&
|
||||
os_memcmp(ssid, hapd->conf->ssid.ssid, ssid_len) == 0)
|
||||
return EXACT_SSID_MATCH;
|
||||
|
||||
if (ssid_list == NULL)
|
||||
return wildcard ? WILDCARD_SSID_MATCH : NO_SSID_MATCH;
|
||||
|
||||
pos = ssid_list;
|
||||
end = ssid_list + ssid_list_len;
|
||||
while (pos + 1 <= end) {
|
||||
if (pos + 2 + pos[1] > end)
|
||||
break;
|
||||
if (pos[1] == 0)
|
||||
wildcard = 1;
|
||||
if (pos[1] == hapd->conf->ssid.ssid_len &&
|
||||
os_memcmp(pos + 2, hapd->conf->ssid.ssid, pos[1]) == 0)
|
||||
return EXACT_SSID_MATCH;
|
||||
pos += 2 + pos[1];
|
||||
}
|
||||
|
||||
return wildcard ? WILDCARD_SSID_MATCH : NO_SSID_MATCH;
|
||||
}
|
||||
|
||||
|
||||
void handle_probe_req(struct hostapd_data *hapd,
|
||||
const struct ieee80211_mgmt *mgmt, size_t len,
|
||||
int ssi_signal)
|
||||
{
|
||||
u8 *resp;
|
||||
struct ieee802_11_elems elems;
|
||||
const u8 *ie;
|
||||
size_t ie_len;
|
||||
struct sta_info *sta = NULL;
|
||||
size_t i, resp_len;
|
||||
int noack;
|
||||
enum ssid_match_result res;
|
||||
|
||||
ie = mgmt->u.probe_req.variable;
|
||||
if (len < IEEE80211_HDRLEN + sizeof(mgmt->u.probe_req))
|
||||
return;
|
||||
ie_len = len - (IEEE80211_HDRLEN + sizeof(mgmt->u.probe_req));
|
||||
|
||||
for (i = 0; hapd->probereq_cb && i < hapd->num_probereq_cb; i++)
|
||||
if (hapd->probereq_cb[i].cb(hapd->probereq_cb[i].ctx,
|
||||
mgmt->sa, mgmt->da, mgmt->bssid,
|
||||
ie, ie_len, ssi_signal) > 0)
|
||||
return;
|
||||
|
||||
if (!hapd->iconf->send_probe_response)
|
||||
return;
|
||||
|
||||
if (ieee802_11_parse_elems(ie, ie_len, &elems, 0) == ParseFailed) {
|
||||
wpa_printf(MSG_DEBUG, "Could not parse ProbeReq from " MACSTR,
|
||||
MAC2STR(mgmt->sa));
|
||||
return;
|
||||
}
|
||||
|
||||
if ((!elems.ssid || !elems.supp_rates)) {
|
||||
wpa_printf(MSG_DEBUG, "STA " MACSTR " sent probe request "
|
||||
"without SSID or supported rates element",
|
||||
MAC2STR(mgmt->sa));
|
||||
return;
|
||||
}
|
||||
|
||||
#ifdef CONFIG_P2P
|
||||
if (hapd->p2p && elems.wps_ie) {
|
||||
struct wpabuf *wps;
|
||||
wps = ieee802_11_vendor_ie_concat(ie, ie_len, WPS_DEV_OUI_WFA);
|
||||
if (wps && !p2p_group_match_dev_type(hapd->p2p_group, wps)) {
|
||||
wpa_printf(MSG_MSGDUMP, "P2P: Ignore Probe Request "
|
||||
"due to mismatch with Requested Device "
|
||||
"Type");
|
||||
wpabuf_free(wps);
|
||||
return;
|
||||
}
|
||||
wpabuf_free(wps);
|
||||
}
|
||||
|
||||
if (hapd->p2p && elems.p2p) {
|
||||
struct wpabuf *p2p;
|
||||
p2p = ieee802_11_vendor_ie_concat(ie, ie_len, P2P_IE_VENDOR_TYPE);
|
||||
if (p2p && !p2p_group_match_dev_id(hapd->p2p_group, p2p)) {
|
||||
wpa_printf(MSG_MSGDUMP, "P2P: Ignore Probe Request "
|
||||
"due to mismatch with Device ID");
|
||||
wpabuf_free(p2p);
|
||||
return;
|
||||
}
|
||||
wpabuf_free(p2p);
|
||||
}
|
||||
#endif /* CONFIG_P2P */
|
||||
|
||||
if (hapd->conf->ignore_broadcast_ssid && elems.ssid_len == 0 &&
|
||||
elems.ssid_list_len == 0) {
|
||||
wpa_printf(MSG_MSGDUMP, "Probe Request from " MACSTR " for "
|
||||
"broadcast SSID ignored", MAC2STR(mgmt->sa));
|
||||
return;
|
||||
}
|
||||
|
||||
sta = ap_get_sta(hapd, mgmt->sa);
|
||||
|
||||
#ifdef CONFIG_P2P
|
||||
if ((hapd->conf->p2p & P2P_GROUP_OWNER) &&
|
||||
elems.ssid_len == P2P_WILDCARD_SSID_LEN &&
|
||||
os_memcmp(elems.ssid, P2P_WILDCARD_SSID,
|
||||
P2P_WILDCARD_SSID_LEN) == 0) {
|
||||
/* Process P2P Wildcard SSID like Wildcard SSID */
|
||||
elems.ssid_len = 0;
|
||||
}
|
||||
#endif /* CONFIG_P2P */
|
||||
|
||||
res = ssid_match(hapd, elems.ssid, elems.ssid_len,
|
||||
elems.ssid_list, elems.ssid_list_len);
|
||||
if (res != NO_SSID_MATCH) {
|
||||
if (sta)
|
||||
sta->ssid_probe = &hapd->conf->ssid;
|
||||
} else {
|
||||
if (!(mgmt->da[0] & 0x01)) {
|
||||
char ssid_txt[33];
|
||||
ieee802_11_print_ssid(ssid_txt, elems.ssid,
|
||||
elems.ssid_len);
|
||||
wpa_printf(MSG_MSGDUMP, "Probe Request from " MACSTR
|
||||
" for foreign SSID '%s' (DA " MACSTR ")%s",
|
||||
MAC2STR(mgmt->sa), ssid_txt,
|
||||
MAC2STR(mgmt->da),
|
||||
elems.ssid_list ? " (SSID list)" : "");
|
||||
}
|
||||
return;
|
||||
}
|
||||
|
||||
#ifdef CONFIG_INTERWORKING
|
||||
if (elems.interworking && elems.interworking_len >= 1) {
|
||||
u8 ant = elems.interworking[0] & 0x0f;
|
||||
if (ant != INTERWORKING_ANT_WILDCARD &&
|
||||
ant != hapd->conf->access_network_type) {
|
||||
wpa_printf(MSG_MSGDUMP, "Probe Request from " MACSTR
|
||||
" for mismatching ANT %u ignored",
|
||||
MAC2STR(mgmt->sa), ant);
|
||||
return;
|
||||
}
|
||||
}
|
||||
|
||||
if (elems.interworking &&
|
||||
(elems.interworking_len == 7 || elems.interworking_len == 9)) {
|
||||
const u8 *hessid;
|
||||
if (elems.interworking_len == 7)
|
||||
hessid = elems.interworking + 1;
|
||||
else
|
||||
hessid = elems.interworking + 1 + 2;
|
||||
if (!is_broadcast_ether_addr(hessid) &&
|
||||
os_memcmp(hessid, hapd->conf->hessid, ETH_ALEN) != 0) {
|
||||
wpa_printf(MSG_MSGDUMP, "Probe Request from " MACSTR
|
||||
" for mismatching HESSID " MACSTR
|
||||
" ignored",
|
||||
MAC2STR(mgmt->sa), MAC2STR(hessid));
|
||||
return;
|
||||
}
|
||||
}
|
||||
#endif /* CONFIG_INTERWORKING */
|
||||
|
||||
/* TODO: verify that supp_rates contains at least one matching rate
|
||||
* with AP configuration */
|
||||
|
||||
resp = hostapd_gen_probe_resp(hapd, sta, mgmt, elems.p2p != NULL,
|
||||
&resp_len);
|
||||
if (resp == NULL)
|
||||
return;
|
||||
|
||||
/*
|
||||
* If this is a broadcast probe request, apply no ack policy to avoid
|
||||
* excessive retries.
|
||||
*/
|
||||
noack = !!(res == WILDCARD_SSID_MATCH &&
|
||||
is_broadcast_ether_addr(mgmt->da));
|
||||
|
||||
if (hostapd_drv_send_mlme(hapd, resp, resp_len, noack) < 0)
|
||||
perror("handle_probe_req: send");
|
||||
|
||||
os_free(resp);
|
||||
|
||||
wpa_printf(MSG_MSGDUMP, "STA " MACSTR " sent probe request for %s "
|
||||
wpa_printf(MSG_EXCESSIVE, "STA " MACSTR " sent probe request for %s "
|
||||
"SSID", MAC2STR(mgmt->sa),
|
||||
elems.ssid_len == 0 ? "broadcast" : "our");
|
||||
}
|
||||
|
||||
|
||||
static u8 * hostapd_probe_resp_offloads(struct hostapd_data *hapd,
|
||||
size_t *resp_len)
|
||||
{
|
||||
/* check probe response offloading caps and print warnings */
|
||||
if (!(hapd->iface->drv_flags & WPA_DRIVER_FLAGS_PROBE_RESP_OFFLOAD))
|
||||
return NULL;
|
||||
|
||||
#ifdef CONFIG_WPS
|
||||
if (hapd->conf->wps_state && hapd->wps_probe_resp_ie &&
|
||||
(!(hapd->iface->probe_resp_offloads &
|
||||
(WPA_DRIVER_PROBE_RESP_OFFLOAD_WPS |
|
||||
WPA_DRIVER_PROBE_RESP_OFFLOAD_WPS2))))
|
||||
wpa_printf(MSG_WARNING, "Device is trying to offload WPS "
|
||||
"Probe Response while not supporting this");
|
||||
#endif /* CONFIG_WPS */
|
||||
|
||||
#ifdef CONFIG_P2P
|
||||
if ((hapd->conf->p2p & P2P_ENABLED) && hapd->p2p_probe_resp_ie &&
|
||||
!(hapd->iface->probe_resp_offloads &
|
||||
WPA_DRIVER_PROBE_RESP_OFFLOAD_P2P))
|
||||
wpa_printf(MSG_WARNING, "Device is trying to offload P2P "
|
||||
"Probe Response while not supporting this");
|
||||
#endif /* CONFIG_P2P */
|
||||
|
||||
if (hapd->conf->interworking &&
|
||||
!(hapd->iface->probe_resp_offloads &
|
||||
WPA_DRIVER_PROBE_RESP_OFFLOAD_INTERWORKING))
|
||||
wpa_printf(MSG_WARNING, "Device is trying to offload "
|
||||
"Interworking Probe Response while not supporting "
|
||||
"this");
|
||||
|
||||
/* Generate a Probe Response template for the non-P2P case */
|
||||
return hostapd_gen_probe_resp(hapd, NULL, NULL, 0, resp_len);
|
||||
}
|
||||
|
||||
#endif /* NEED_AP_MLME */
|
||||
|
||||
|
||||
void ieee802_11_set_beacon(struct hostapd_data *hapd)
|
||||
{
|
||||
struct ieee80211_mgmt *head;
|
||||
u8 *pos, *tail, *tailpos;
|
||||
struct ieee80211_mgmt *head = NULL;
|
||||
u8 *tail = NULL;
|
||||
size_t head_len = 0, tail_len = 0;
|
||||
u8 *resp = NULL;
|
||||
size_t resp_len = 0;
|
||||
struct wpa_driver_ap_params params;
|
||||
struct wpabuf *beacon, *proberesp, *assocresp;
|
||||
#ifdef NEED_AP_MLME
|
||||
u16 capab_info;
|
||||
size_t head_len, tail_len;
|
||||
u8 *pos, *tailpos;
|
||||
#endif /* NEED_AP_MLME */
|
||||
|
||||
hapd->beacon_set_done = 1;
|
||||
|
||||
#ifdef NEED_AP_MLME
|
||||
|
||||
#define BEACON_HEAD_BUF_SIZE 256
|
||||
#define BEACON_TAIL_BUF_SIZE 512
|
||||
@ -354,6 +575,12 @@ void ieee802_11_set_beacon(struct hostapd_data *hapd)
|
||||
if (hapd->conf->wps_state && hapd->wps_beacon_ie)
|
||||
tail_len += wpabuf_len(hapd->wps_beacon_ie);
|
||||
#endif /* CONFIG_WPS */
|
||||
#ifdef CONFIG_P2P
|
||||
if (hapd->p2p_beacon_ie)
|
||||
tail_len += wpabuf_len(hapd->p2p_beacon_ie);
|
||||
#endif /* CONFIG_P2P */
|
||||
if (hapd->conf->vendor_elements)
|
||||
tail_len += wpabuf_len(hapd->conf->vendor_elements);
|
||||
tailpos = tail = os_malloc(tail_len);
|
||||
if (head == NULL || tail == NULL) {
|
||||
wpa_printf(MSG_ERROR, "Failed to set beacon data");
|
||||
@ -412,13 +639,30 @@ void ieee802_11_set_beacon(struct hostapd_data *hapd)
|
||||
|
||||
/* RSN, MDIE, WPA */
|
||||
tailpos = hostapd_eid_wpa(hapd, tailpos, tail + BEACON_TAIL_BUF_SIZE -
|
||||
tailpos, NULL);
|
||||
tailpos);
|
||||
|
||||
#ifdef CONFIG_IEEE80211N
|
||||
tailpos = hostapd_eid_ht_capabilities(hapd, tailpos);
|
||||
tailpos = hostapd_eid_ht_operation(hapd, tailpos);
|
||||
#endif /* CONFIG_IEEE80211N */
|
||||
|
||||
tailpos = hostapd_eid_ext_capab(hapd, tailpos);
|
||||
|
||||
/*
|
||||
* TODO: Time Advertisement element should only be included in some
|
||||
* DTIM Beacon frames.
|
||||
*/
|
||||
tailpos = hostapd_eid_time_adv(hapd, tailpos);
|
||||
|
||||
tailpos = hostapd_eid_interworking(hapd, tailpos);
|
||||
tailpos = hostapd_eid_adv_proto(hapd, tailpos);
|
||||
tailpos = hostapd_eid_roaming_consortium(hapd, tailpos);
|
||||
|
||||
#ifdef CONFIG_IEEE80211AC
|
||||
tailpos = hostapd_eid_vht_capabilities(hapd, tailpos);
|
||||
tailpos = hostapd_eid_vht_operation(hapd, tailpos);
|
||||
#endif /* CONFIG_IEEE80211AC */
|
||||
|
||||
/* Wi-Fi Alliance WMM */
|
||||
tailpos = hostapd_eid_wmm(hapd, tailpos);
|
||||
|
||||
@ -430,19 +674,104 @@ void ieee802_11_set_beacon(struct hostapd_data *hapd)
|
||||
}
|
||||
#endif /* CONFIG_WPS */
|
||||
|
||||
#ifdef CONFIG_P2P
|
||||
if ((hapd->conf->p2p & P2P_ENABLED) && hapd->p2p_beacon_ie) {
|
||||
os_memcpy(tailpos, wpabuf_head(hapd->p2p_beacon_ie),
|
||||
wpabuf_len(hapd->p2p_beacon_ie));
|
||||
tailpos += wpabuf_len(hapd->p2p_beacon_ie);
|
||||
}
|
||||
#endif /* CONFIG_P2P */
|
||||
#ifdef CONFIG_P2P_MANAGER
|
||||
if ((hapd->conf->p2p & (P2P_MANAGE | P2P_ENABLED | P2P_GROUP_OWNER)) ==
|
||||
P2P_MANAGE)
|
||||
tailpos = hostapd_eid_p2p_manage(hapd, tailpos);
|
||||
#endif /* CONFIG_P2P_MANAGER */
|
||||
|
||||
#ifdef CONFIG_HS20
|
||||
tailpos = hostapd_eid_hs20_indication(hapd, tailpos);
|
||||
#endif /* CONFIG_HS20 */
|
||||
|
||||
if (hapd->conf->vendor_elements) {
|
||||
os_memcpy(tailpos, wpabuf_head(hapd->conf->vendor_elements),
|
||||
wpabuf_len(hapd->conf->vendor_elements));
|
||||
tailpos += wpabuf_len(hapd->conf->vendor_elements);
|
||||
}
|
||||
|
||||
tail_len = tailpos > tail ? tailpos - tail : 0;
|
||||
|
||||
if (hapd->drv.set_beacon(hapd, (u8 *) head, head_len,
|
||||
tail, tail_len, hapd->conf->dtim_period,
|
||||
hapd->iconf->beacon_int))
|
||||
wpa_printf(MSG_ERROR, "Failed to set beacon head/tail or DTIM "
|
||||
"period");
|
||||
resp = hostapd_probe_resp_offloads(hapd, &resp_len);
|
||||
#endif /* NEED_AP_MLME */
|
||||
|
||||
os_memset(¶ms, 0, sizeof(params));
|
||||
params.head = (u8 *) head;
|
||||
params.head_len = head_len;
|
||||
params.tail = tail;
|
||||
params.tail_len = tail_len;
|
||||
params.proberesp = resp;
|
||||
params.proberesp_len = resp_len;
|
||||
params.dtim_period = hapd->conf->dtim_period;
|
||||
params.beacon_int = hapd->iconf->beacon_int;
|
||||
params.basic_rates = hapd->iface->basic_rates;
|
||||
params.ssid = hapd->conf->ssid.ssid;
|
||||
params.ssid_len = hapd->conf->ssid.ssid_len;
|
||||
params.pairwise_ciphers = hapd->conf->rsn_pairwise ?
|
||||
hapd->conf->rsn_pairwise : hapd->conf->wpa_pairwise;
|
||||
params.group_cipher = hapd->conf->wpa_group;
|
||||
params.key_mgmt_suites = hapd->conf->wpa_key_mgmt;
|
||||
params.auth_algs = hapd->conf->auth_algs;
|
||||
params.wpa_version = hapd->conf->wpa;
|
||||
params.privacy = hapd->conf->ssid.wep.keys_set || hapd->conf->wpa ||
|
||||
(hapd->conf->ieee802_1x &&
|
||||
(hapd->conf->default_wep_key_len ||
|
||||
hapd->conf->individual_wep_key_len));
|
||||
switch (hapd->conf->ignore_broadcast_ssid) {
|
||||
case 0:
|
||||
params.hide_ssid = NO_SSID_HIDING;
|
||||
break;
|
||||
case 1:
|
||||
params.hide_ssid = HIDDEN_SSID_ZERO_LEN;
|
||||
break;
|
||||
case 2:
|
||||
params.hide_ssid = HIDDEN_SSID_ZERO_CONTENTS;
|
||||
break;
|
||||
}
|
||||
hostapd_build_ap_extra_ies(hapd, &beacon, &proberesp, &assocresp);
|
||||
params.beacon_ies = beacon;
|
||||
params.proberesp_ies = proberesp;
|
||||
params.assocresp_ies = assocresp;
|
||||
params.isolate = hapd->conf->isolate;
|
||||
#ifdef NEED_AP_MLME
|
||||
params.cts_protect = !!(ieee802_11_erp_info(hapd) &
|
||||
ERP_INFO_USE_PROTECTION);
|
||||
params.preamble = hapd->iface->num_sta_no_short_preamble == 0 &&
|
||||
hapd->iconf->preamble == SHORT_PREAMBLE;
|
||||
if (hapd->iface->current_mode &&
|
||||
hapd->iface->current_mode->mode == HOSTAPD_MODE_IEEE80211G)
|
||||
params.short_slot_time =
|
||||
hapd->iface->num_sta_no_short_slot_time > 0 ? 0 : 1;
|
||||
else
|
||||
params.short_slot_time = -1;
|
||||
if (!hapd->iconf->ieee80211n || hapd->conf->disable_11n)
|
||||
params.ht_opmode = -1;
|
||||
else
|
||||
params.ht_opmode = hapd->iface->ht_op_mode;
|
||||
#endif /* NEED_AP_MLME */
|
||||
params.interworking = hapd->conf->interworking;
|
||||
if (hapd->conf->interworking &&
|
||||
!is_zero_ether_addr(hapd->conf->hessid))
|
||||
params.hessid = hapd->conf->hessid;
|
||||
params.access_network_type = hapd->conf->access_network_type;
|
||||
params.ap_max_inactivity = hapd->conf->ap_max_inactivity;
|
||||
#ifdef CONFIG_HS20
|
||||
params.disable_dgaf = hapd->conf->disable_dgaf;
|
||||
#endif /* CONFIG_HS20 */
|
||||
if (hostapd_drv_set_ap(hapd, ¶ms))
|
||||
wpa_printf(MSG_ERROR, "Failed to set beacon parameters");
|
||||
hostapd_free_ap_extra_ies(hapd, beacon, proberesp, assocresp);
|
||||
|
||||
os_free(tail);
|
||||
os_free(head);
|
||||
|
||||
hapd->drv.set_bss_params(hapd, !!(ieee802_11_erp_info(hapd) &
|
||||
ERP_INFO_USE_PROTECTION));
|
||||
os_free(resp);
|
||||
}
|
||||
|
||||
|
||||
@ -453,4 +782,14 @@ void ieee802_11_set_beacons(struct hostapd_iface *iface)
|
||||
ieee802_11_set_beacon(iface->bss[i]);
|
||||
}
|
||||
|
||||
|
||||
/* only update beacons if started */
|
||||
void ieee802_11_update_beacons(struct hostapd_iface *iface)
|
||||
{
|
||||
size_t i;
|
||||
for (i = 0; i < iface->num_bss; i++)
|
||||
if (iface->bss[i]->beacon_set_done)
|
||||
ieee802_11_set_beacon(iface->bss[i]);
|
||||
}
|
||||
|
||||
#endif /* CONFIG_NATIVE_WINDOWS */
|
||||
|
@ -19,18 +19,10 @@
|
||||
struct ieee80211_mgmt;
|
||||
|
||||
void handle_probe_req(struct hostapd_data *hapd,
|
||||
const struct ieee80211_mgmt *mgmt, size_t len);
|
||||
#ifdef NEED_AP_MLME
|
||||
const struct ieee80211_mgmt *mgmt, size_t len,
|
||||
int ssi_signal);
|
||||
void ieee802_11_set_beacon(struct hostapd_data *hapd);
|
||||
void ieee802_11_set_beacons(struct hostapd_iface *iface);
|
||||
#else /* NEED_AP_MLME */
|
||||
static inline void ieee802_11_set_beacon(struct hostapd_data *hapd)
|
||||
{
|
||||
}
|
||||
|
||||
static inline void ieee802_11_set_beacons(struct hostapd_iface *iface)
|
||||
{
|
||||
}
|
||||
#endif /* NEED_AP_MLME */
|
||||
void ieee802_11_update_beacons(struct hostapd_iface *iface);
|
||||
|
||||
#endif /* BEACON_H */
|
||||
|
@ -2,26 +2,45 @@
|
||||
* Control interface for shared AP commands
|
||||
* Copyright (c) 2004-2009, Jouni Malinen <j@w1.fi>
|
||||
*
|
||||
* This program is free software; you can redistribute it and/or modify
|
||||
* it under the terms of the GNU General Public License version 2 as
|
||||
* published by the Free Software Foundation.
|
||||
*
|
||||
* Alternatively, this software may be distributed under the terms of BSD
|
||||
* license.
|
||||
*
|
||||
* See README and COPYING for more details.
|
||||
* This software may be distributed under the terms of the BSD license.
|
||||
* See README for more details.
|
||||
*/
|
||||
|
||||
#include "utils/includes.h"
|
||||
|
||||
#include "utils/common.h"
|
||||
#include "common/ieee802_11_defs.h"
|
||||
#include "hostapd.h"
|
||||
#include "ieee802_1x.h"
|
||||
#include "wpa_auth.h"
|
||||
#include "ieee802_11.h"
|
||||
#include "sta_info.h"
|
||||
#include "wps_hostapd.h"
|
||||
#include "p2p_hostapd.h"
|
||||
#include "ctrl_iface_ap.h"
|
||||
#include "ap_drv_ops.h"
|
||||
|
||||
|
||||
static int hostapd_get_sta_conn_time(struct sta_info *sta,
|
||||
char *buf, size_t buflen)
|
||||
{
|
||||
struct os_time now, age;
|
||||
int len = 0, ret;
|
||||
|
||||
if (!sta->connected_time.sec)
|
||||
return 0;
|
||||
|
||||
os_get_time(&now);
|
||||
os_time_sub(&now, &sta->connected_time, &age);
|
||||
|
||||
ret = os_snprintf(buf + len, buflen - len, "connected_time=%u\n",
|
||||
(unsigned int) age.sec);
|
||||
if (ret < 0 || (size_t) ret >= buflen - len)
|
||||
return len;
|
||||
len += ret;
|
||||
|
||||
return len;
|
||||
}
|
||||
|
||||
|
||||
static int hostapd_ctrl_iface_sta_mib(struct hostapd_data *hapd,
|
||||
@ -57,6 +76,13 @@ static int hostapd_ctrl_iface_sta_mib(struct hostapd_data *hapd,
|
||||
buflen - len);
|
||||
if (res >= 0)
|
||||
len += res;
|
||||
res = hostapd_p2p_get_mib_sta(hapd, sta, buf + len, buflen - len);
|
||||
if (res >= 0)
|
||||
len += res;
|
||||
|
||||
res = hostapd_get_sta_conn_time(sta, buf + len, buflen - len);
|
||||
if (res >= 0)
|
||||
len += res;
|
||||
|
||||
return len;
|
||||
}
|
||||
@ -102,3 +128,170 @@ int hostapd_ctrl_iface_sta_next(struct hostapd_data *hapd, const char *txtaddr,
|
||||
}
|
||||
return hostapd_ctrl_iface_sta_mib(hapd, sta->next, buf, buflen);
|
||||
}
|
||||
|
||||
|
||||
#ifdef CONFIG_P2P_MANAGER
|
||||
static int p2p_manager_disconnect(struct hostapd_data *hapd, u16 stype,
|
||||
u8 minor_reason_code, const u8 *addr)
|
||||
{
|
||||
struct ieee80211_mgmt *mgmt;
|
||||
int ret;
|
||||
u8 *pos;
|
||||
|
||||
if (hapd->driver->send_frame == NULL)
|
||||
return -1;
|
||||
|
||||
mgmt = os_zalloc(sizeof(*mgmt) + 100);
|
||||
if (mgmt == NULL)
|
||||
return -1;
|
||||
|
||||
wpa_dbg(hapd->msg_ctx, MSG_DEBUG, "P2P: Disconnect STA " MACSTR
|
||||
" with minor reason code %u (stype=%u)",
|
||||
MAC2STR(addr), minor_reason_code, stype);
|
||||
|
||||
mgmt->frame_control = IEEE80211_FC(WLAN_FC_TYPE_MGMT, stype);
|
||||
os_memcpy(mgmt->da, addr, ETH_ALEN);
|
||||
os_memcpy(mgmt->sa, hapd->own_addr, ETH_ALEN);
|
||||
os_memcpy(mgmt->bssid, hapd->own_addr, ETH_ALEN);
|
||||
if (stype == WLAN_FC_STYPE_DEAUTH) {
|
||||
mgmt->u.deauth.reason_code =
|
||||
host_to_le16(WLAN_REASON_PREV_AUTH_NOT_VALID);
|
||||
pos = (u8 *) (&mgmt->u.deauth.reason_code + 1);
|
||||
} else {
|
||||
mgmt->u.disassoc.reason_code =
|
||||
host_to_le16(WLAN_REASON_PREV_AUTH_NOT_VALID);
|
||||
pos = (u8 *) (&mgmt->u.disassoc.reason_code + 1);
|
||||
}
|
||||
|
||||
*pos++ = WLAN_EID_VENDOR_SPECIFIC;
|
||||
*pos++ = 4 + 3 + 1;
|
||||
WPA_PUT_BE24(pos, OUI_WFA);
|
||||
pos += 3;
|
||||
*pos++ = P2P_OUI_TYPE;
|
||||
|
||||
*pos++ = P2P_ATTR_MINOR_REASON_CODE;
|
||||
WPA_PUT_LE16(pos, 1);
|
||||
pos += 2;
|
||||
*pos++ = minor_reason_code;
|
||||
|
||||
ret = hapd->driver->send_frame(hapd->drv_priv, (u8 *) mgmt,
|
||||
pos - (u8 *) mgmt, 1);
|
||||
os_free(mgmt);
|
||||
|
||||
return ret < 0 ? -1 : 0;
|
||||
}
|
||||
#endif /* CONFIG_P2P_MANAGER */
|
||||
|
||||
|
||||
int hostapd_ctrl_iface_deauthenticate(struct hostapd_data *hapd,
|
||||
const char *txtaddr)
|
||||
{
|
||||
u8 addr[ETH_ALEN];
|
||||
struct sta_info *sta;
|
||||
const char *pos;
|
||||
|
||||
wpa_dbg(hapd->msg_ctx, MSG_DEBUG, "CTRL_IFACE DEAUTHENTICATE %s",
|
||||
txtaddr);
|
||||
|
||||
if (hwaddr_aton(txtaddr, addr))
|
||||
return -1;
|
||||
|
||||
pos = os_strstr(txtaddr, " test=");
|
||||
if (pos) {
|
||||
struct ieee80211_mgmt mgmt;
|
||||
int encrypt;
|
||||
if (hapd->driver->send_frame == NULL)
|
||||
return -1;
|
||||
pos += 6;
|
||||
encrypt = atoi(pos);
|
||||
os_memset(&mgmt, 0, sizeof(mgmt));
|
||||
mgmt.frame_control = IEEE80211_FC(WLAN_FC_TYPE_MGMT,
|
||||
WLAN_FC_STYPE_DEAUTH);
|
||||
os_memcpy(mgmt.da, addr, ETH_ALEN);
|
||||
os_memcpy(mgmt.sa, hapd->own_addr, ETH_ALEN);
|
||||
os_memcpy(mgmt.bssid, hapd->own_addr, ETH_ALEN);
|
||||
mgmt.u.deauth.reason_code =
|
||||
host_to_le16(WLAN_REASON_PREV_AUTH_NOT_VALID);
|
||||
if (hapd->driver->send_frame(hapd->drv_priv, (u8 *) &mgmt,
|
||||
IEEE80211_HDRLEN +
|
||||
sizeof(mgmt.u.deauth),
|
||||
encrypt) < 0)
|
||||
return -1;
|
||||
return 0;
|
||||
}
|
||||
|
||||
#ifdef CONFIG_P2P_MANAGER
|
||||
pos = os_strstr(txtaddr, " p2p=");
|
||||
if (pos) {
|
||||
return p2p_manager_disconnect(hapd, WLAN_FC_STYPE_DEAUTH,
|
||||
atoi(pos + 5), addr);
|
||||
}
|
||||
#endif /* CONFIG_P2P_MANAGER */
|
||||
|
||||
hostapd_drv_sta_deauth(hapd, addr, WLAN_REASON_PREV_AUTH_NOT_VALID);
|
||||
sta = ap_get_sta(hapd, addr);
|
||||
if (sta)
|
||||
ap_sta_deauthenticate(hapd, sta,
|
||||
WLAN_REASON_PREV_AUTH_NOT_VALID);
|
||||
else if (addr[0] == 0xff)
|
||||
hostapd_free_stas(hapd);
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
|
||||
int hostapd_ctrl_iface_disassociate(struct hostapd_data *hapd,
|
||||
const char *txtaddr)
|
||||
{
|
||||
u8 addr[ETH_ALEN];
|
||||
struct sta_info *sta;
|
||||
const char *pos;
|
||||
|
||||
wpa_dbg(hapd->msg_ctx, MSG_DEBUG, "CTRL_IFACE DISASSOCIATE %s",
|
||||
txtaddr);
|
||||
|
||||
if (hwaddr_aton(txtaddr, addr))
|
||||
return -1;
|
||||
|
||||
pos = os_strstr(txtaddr, " test=");
|
||||
if (pos) {
|
||||
struct ieee80211_mgmt mgmt;
|
||||
int encrypt;
|
||||
if (hapd->driver->send_frame == NULL)
|
||||
return -1;
|
||||
pos += 6;
|
||||
encrypt = atoi(pos);
|
||||
os_memset(&mgmt, 0, sizeof(mgmt));
|
||||
mgmt.frame_control = IEEE80211_FC(WLAN_FC_TYPE_MGMT,
|
||||
WLAN_FC_STYPE_DISASSOC);
|
||||
os_memcpy(mgmt.da, addr, ETH_ALEN);
|
||||
os_memcpy(mgmt.sa, hapd->own_addr, ETH_ALEN);
|
||||
os_memcpy(mgmt.bssid, hapd->own_addr, ETH_ALEN);
|
||||
mgmt.u.disassoc.reason_code =
|
||||
host_to_le16(WLAN_REASON_PREV_AUTH_NOT_VALID);
|
||||
if (hapd->driver->send_frame(hapd->drv_priv, (u8 *) &mgmt,
|
||||
IEEE80211_HDRLEN +
|
||||
sizeof(mgmt.u.deauth),
|
||||
encrypt) < 0)
|
||||
return -1;
|
||||
return 0;
|
||||
}
|
||||
|
||||
#ifdef CONFIG_P2P_MANAGER
|
||||
pos = os_strstr(txtaddr, " p2p=");
|
||||
if (pos) {
|
||||
return p2p_manager_disconnect(hapd, WLAN_FC_STYPE_DISASSOC,
|
||||
atoi(pos + 5), addr);
|
||||
}
|
||||
#endif /* CONFIG_P2P_MANAGER */
|
||||
|
||||
hostapd_drv_sta_disassoc(hapd, addr, WLAN_REASON_PREV_AUTH_NOT_VALID);
|
||||
sta = ap_get_sta(hapd, addr);
|
||||
if (sta)
|
||||
ap_sta_disassociate(hapd, sta,
|
||||
WLAN_REASON_PREV_AUTH_NOT_VALID);
|
||||
else if (addr[0] == 0xff)
|
||||
hostapd_free_stas(hapd);
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
@ -2,14 +2,8 @@
|
||||
* Control interface for shared AP commands
|
||||
* Copyright (c) 2004-2009, Jouni Malinen <j@w1.fi>
|
||||
*
|
||||
* This program is free software; you can redistribute it and/or modify
|
||||
* it under the terms of the GNU General Public License version 2 as
|
||||
* published by the Free Software Foundation.
|
||||
*
|
||||
* Alternatively, this software may be distributed under the terms of BSD
|
||||
* license.
|
||||
*
|
||||
* See README and COPYING for more details.
|
||||
* This software may be distributed under the terms of the BSD license.
|
||||
* See README for more details.
|
||||
*/
|
||||
|
||||
#ifndef CTRL_IFACE_AP_H
|
||||
@ -21,5 +15,9 @@ int hostapd_ctrl_iface_sta(struct hostapd_data *hapd, const char *txtaddr,
|
||||
char *buf, size_t buflen);
|
||||
int hostapd_ctrl_iface_sta_next(struct hostapd_data *hapd, const char *txtaddr,
|
||||
char *buf, size_t buflen);
|
||||
int hostapd_ctrl_iface_deauthenticate(struct hostapd_data *hapd,
|
||||
const char *txtaddr);
|
||||
int hostapd_ctrl_iface_disassociate(struct hostapd_data *hapd,
|
||||
const char *txtaddr);
|
||||
|
||||
#endif /* CTRL_IFACE_AP_H */
|
||||
|
@ -2,14 +2,8 @@
|
||||
* hostapd / Callback functions for driver wrappers
|
||||
* Copyright (c) 2002-2009, Jouni Malinen <j@w1.fi>
|
||||
*
|
||||
* This program is free software; you can redistribute it and/or modify
|
||||
* it under the terms of the GNU General Public License version 2 as
|
||||
* published by the Free Software Foundation.
|
||||
*
|
||||
* Alternatively, this software may be distributed under the terms of BSD
|
||||
* license.
|
||||
*
|
||||
* See README and COPYING for more details.
|
||||
* This software may be distributed under the terms of the BSD license.
|
||||
* See README for more details.
|
||||
*/
|
||||
|
||||
#include "utils/includes.h"
|
||||
@ -19,26 +13,37 @@
|
||||
#include "drivers/driver.h"
|
||||
#include "common/ieee802_11_defs.h"
|
||||
#include "common/ieee802_11_common.h"
|
||||
#include "common/wpa_ctrl.h"
|
||||
#include "crypto/random.h"
|
||||
#include "p2p/p2p.h"
|
||||
#include "wps/wps.h"
|
||||
#include "wnm_ap.h"
|
||||
#include "hostapd.h"
|
||||
#include "ieee802_11.h"
|
||||
#include "sta_info.h"
|
||||
#include "accounting.h"
|
||||
#include "tkip_countermeasures.h"
|
||||
#include "iapp.h"
|
||||
#include "ieee802_1x.h"
|
||||
#include "wpa_auth.h"
|
||||
#include "wmm.h"
|
||||
#include "wps_hostapd.h"
|
||||
#include "ap_drv_ops.h"
|
||||
#include "ap_config.h"
|
||||
#include "hw_features.h"
|
||||
|
||||
|
||||
int hostapd_notif_assoc(struct hostapd_data *hapd, const u8 *addr,
|
||||
const u8 *ie, size_t ielen)
|
||||
const u8 *req_ies, size_t req_ies_len, int reassoc)
|
||||
{
|
||||
struct sta_info *sta;
|
||||
int new_assoc, res;
|
||||
struct ieee802_11_elems elems;
|
||||
const u8 *ie;
|
||||
size_t ielen;
|
||||
#ifdef CONFIG_IEEE80211R
|
||||
u8 buf[sizeof(struct ieee80211_mgmt) + 1024];
|
||||
u8 *p = buf;
|
||||
#endif /* CONFIG_IEEE80211R */
|
||||
u16 reason = WLAN_REASON_UNSPECIFIED;
|
||||
u16 status = WLAN_STATUS_SUCCESS;
|
||||
|
||||
if (addr == NULL) {
|
||||
/*
|
||||
@ -52,11 +57,12 @@ int hostapd_notif_assoc(struct hostapd_data *hapd, const u8 *addr,
|
||||
"no address");
|
||||
return -1;
|
||||
}
|
||||
random_add_randomness(addr, ETH_ALEN);
|
||||
|
||||
hostapd_logger(hapd, addr, HOSTAPD_MODULE_IEEE80211,
|
||||
HOSTAPD_LEVEL_INFO, "associated");
|
||||
|
||||
ieee802_11_parse_elems(ie, ielen, &elems, 0);
|
||||
ieee802_11_parse_elems(req_ies, req_ies_len, &elems, 0);
|
||||
if (elems.wps_ie) {
|
||||
ie = elems.wps_ie - 2;
|
||||
ielen = elems.wps_ie_len + 2;
|
||||
@ -79,15 +85,42 @@ int hostapd_notif_assoc(struct hostapd_data *hapd, const u8 *addr,
|
||||
sta = ap_get_sta(hapd, addr);
|
||||
if (sta) {
|
||||
accounting_sta_stop(hapd, sta);
|
||||
|
||||
/*
|
||||
* Make sure that the previously registered inactivity timer
|
||||
* will not remove the STA immediately.
|
||||
*/
|
||||
sta->timeout_next = STA_NULLFUNC;
|
||||
} else {
|
||||
sta = ap_sta_add(hapd, addr);
|
||||
if (sta == NULL)
|
||||
if (sta == NULL) {
|
||||
hostapd_drv_sta_disassoc(hapd, addr,
|
||||
WLAN_REASON_DISASSOC_AP_BUSY);
|
||||
return -1;
|
||||
}
|
||||
}
|
||||
sta->flags &= ~(WLAN_STA_WPS | WLAN_STA_MAYBE_WPS);
|
||||
sta->flags &= ~(WLAN_STA_WPS | WLAN_STA_MAYBE_WPS | WLAN_STA_WPS2);
|
||||
|
||||
#ifdef CONFIG_P2P
|
||||
if (elems.p2p) {
|
||||
wpabuf_free(sta->p2p_ie);
|
||||
sta->p2p_ie = ieee802_11_vendor_ie_concat(req_ies, req_ies_len,
|
||||
P2P_IE_VENDOR_TYPE);
|
||||
}
|
||||
#endif /* CONFIG_P2P */
|
||||
|
||||
#ifdef CONFIG_HS20
|
||||
wpabuf_free(sta->hs20_ie);
|
||||
if (elems.hs20 && elems.hs20_len > 4) {
|
||||
sta->hs20_ie = wpabuf_alloc_copy(elems.hs20 + 4,
|
||||
elems.hs20_len - 4);
|
||||
} else
|
||||
sta->hs20_ie = NULL;
|
||||
#endif /* CONFIG_HS20 */
|
||||
|
||||
if (hapd->conf->wpa) {
|
||||
if (ie == NULL || ielen == 0) {
|
||||
#ifdef CONFIG_WPS
|
||||
if (hapd->conf->wps_state) {
|
||||
wpa_printf(MSG_DEBUG, "STA did not include "
|
||||
"WPA/RSN IE in (Re)Association "
|
||||
@ -95,15 +128,29 @@ int hostapd_notif_assoc(struct hostapd_data *hapd, const u8 *addr,
|
||||
sta->flags |= WLAN_STA_MAYBE_WPS;
|
||||
goto skip_wpa_check;
|
||||
}
|
||||
#endif /* CONFIG_WPS */
|
||||
|
||||
wpa_printf(MSG_DEBUG, "No WPA/RSN IE from STA");
|
||||
return -1;
|
||||
}
|
||||
#ifdef CONFIG_WPS
|
||||
if (hapd->conf->wps_state && ie[0] == 0xdd && ie[1] >= 4 &&
|
||||
os_memcmp(ie + 2, "\x00\x50\xf2\x04", 4) == 0) {
|
||||
struct wpabuf *wps;
|
||||
sta->flags |= WLAN_STA_WPS;
|
||||
wps = ieee802_11_vendor_ie_concat(ie, ielen,
|
||||
WPS_IE_VENDOR_TYPE);
|
||||
if (wps) {
|
||||
if (wps_is_20(wps)) {
|
||||
wpa_printf(MSG_DEBUG, "WPS: STA "
|
||||
"supports WPS 2.0");
|
||||
sta->flags |= WLAN_STA_WPS2;
|
||||
}
|
||||
wpabuf_free(wps);
|
||||
}
|
||||
goto skip_wpa_check;
|
||||
}
|
||||
#endif /* CONFIG_WPS */
|
||||
|
||||
if (sta->wpa_sm == NULL)
|
||||
sta->wpa_sm = wpa_auth_sta_init(hapd->wpa_auth,
|
||||
@ -114,48 +161,156 @@ int hostapd_notif_assoc(struct hostapd_data *hapd, const u8 *addr,
|
||||
return -1;
|
||||
}
|
||||
res = wpa_validate_wpa_ie(hapd->wpa_auth, sta->wpa_sm,
|
||||
ie, ielen, NULL, 0);
|
||||
ie, ielen,
|
||||
elems.mdie, elems.mdie_len);
|
||||
if (res != WPA_IE_OK) {
|
||||
int resp;
|
||||
wpa_printf(MSG_DEBUG, "WPA/RSN information element "
|
||||
"rejected? (res %u)", res);
|
||||
wpa_hexdump(MSG_DEBUG, "IE", ie, ielen);
|
||||
if (res == WPA_INVALID_GROUP)
|
||||
resp = WLAN_REASON_GROUP_CIPHER_NOT_VALID;
|
||||
else if (res == WPA_INVALID_PAIRWISE)
|
||||
resp = WLAN_REASON_PAIRWISE_CIPHER_NOT_VALID;
|
||||
else if (res == WPA_INVALID_AKMP)
|
||||
resp = WLAN_REASON_AKMP_NOT_VALID;
|
||||
if (res == WPA_INVALID_GROUP) {
|
||||
reason = WLAN_REASON_GROUP_CIPHER_NOT_VALID;
|
||||
status = WLAN_STATUS_GROUP_CIPHER_NOT_VALID;
|
||||
} else if (res == WPA_INVALID_PAIRWISE) {
|
||||
reason = WLAN_REASON_PAIRWISE_CIPHER_NOT_VALID;
|
||||
status = WLAN_STATUS_PAIRWISE_CIPHER_NOT_VALID;
|
||||
} else if (res == WPA_INVALID_AKMP) {
|
||||
reason = WLAN_REASON_AKMP_NOT_VALID;
|
||||
status = WLAN_STATUS_AKMP_NOT_VALID;
|
||||
}
|
||||
#ifdef CONFIG_IEEE80211W
|
||||
else if (res == WPA_MGMT_FRAME_PROTECTION_VIOLATION)
|
||||
resp = WLAN_REASON_INVALID_IE;
|
||||
else if (res == WPA_INVALID_MGMT_GROUP_CIPHER)
|
||||
resp = WLAN_REASON_GROUP_CIPHER_NOT_VALID;
|
||||
else if (res == WPA_MGMT_FRAME_PROTECTION_VIOLATION) {
|
||||
reason = WLAN_REASON_INVALID_IE;
|
||||
status = WLAN_STATUS_INVALID_IE;
|
||||
} else if (res == WPA_INVALID_MGMT_GROUP_CIPHER) {
|
||||
reason = WLAN_REASON_GROUP_CIPHER_NOT_VALID;
|
||||
status = WLAN_STATUS_GROUP_CIPHER_NOT_VALID;
|
||||
}
|
||||
#endif /* CONFIG_IEEE80211W */
|
||||
else
|
||||
resp = WLAN_REASON_INVALID_IE;
|
||||
hapd->drv.sta_disassoc(hapd, sta->addr, resp);
|
||||
ap_free_sta(hapd, sta);
|
||||
return -1;
|
||||
else {
|
||||
reason = WLAN_REASON_INVALID_IE;
|
||||
status = WLAN_STATUS_INVALID_IE;
|
||||
}
|
||||
goto fail;
|
||||
}
|
||||
#ifdef CONFIG_IEEE80211W
|
||||
if ((sta->flags & WLAN_STA_MFP) && !sta->sa_query_timed_out &&
|
||||
sta->sa_query_count > 0)
|
||||
ap_check_sa_query_timeout(hapd, sta);
|
||||
if ((sta->flags & WLAN_STA_MFP) && !sta->sa_query_timed_out &&
|
||||
(sta->auth_alg != WLAN_AUTH_FT)) {
|
||||
/*
|
||||
* STA has already been associated with MFP and SA
|
||||
* Query timeout has not been reached. Reject the
|
||||
* association attempt temporarily and start SA Query,
|
||||
* if one is not pending.
|
||||
*/
|
||||
|
||||
if (sta->sa_query_count == 0)
|
||||
ap_sta_start_sa_query(hapd, sta);
|
||||
|
||||
#ifdef CONFIG_IEEE80211R
|
||||
status = WLAN_STATUS_ASSOC_REJECTED_TEMPORARILY;
|
||||
|
||||
p = hostapd_eid_assoc_comeback_time(hapd, sta, p);
|
||||
|
||||
hostapd_sta_assoc(hapd, addr, reassoc, status, buf,
|
||||
p - buf);
|
||||
#endif /* CONFIG_IEEE80211R */
|
||||
return 0;
|
||||
}
|
||||
|
||||
if (wpa_auth_uses_mfp(sta->wpa_sm))
|
||||
sta->flags |= WLAN_STA_MFP;
|
||||
else
|
||||
sta->flags &= ~WLAN_STA_MFP;
|
||||
#endif /* CONFIG_IEEE80211W */
|
||||
|
||||
#ifdef CONFIG_IEEE80211R
|
||||
if (sta->auth_alg == WLAN_AUTH_FT) {
|
||||
status = wpa_ft_validate_reassoc(sta->wpa_sm, req_ies,
|
||||
req_ies_len);
|
||||
if (status != WLAN_STATUS_SUCCESS) {
|
||||
if (status == WLAN_STATUS_INVALID_PMKID)
|
||||
reason = WLAN_REASON_INVALID_IE;
|
||||
if (status == WLAN_STATUS_INVALID_MDIE)
|
||||
reason = WLAN_REASON_INVALID_IE;
|
||||
if (status == WLAN_STATUS_INVALID_FTIE)
|
||||
reason = WLAN_REASON_INVALID_IE;
|
||||
goto fail;
|
||||
}
|
||||
}
|
||||
#endif /* CONFIG_IEEE80211R */
|
||||
} else if (hapd->conf->wps_state) {
|
||||
if (ie && ielen > 4 && ie[0] == 0xdd && ie[1] >= 4 &&
|
||||
os_memcmp(ie + 2, "\x00\x50\xf2\x04", 4) == 0) {
|
||||
#ifdef CONFIG_WPS
|
||||
struct wpabuf *wps;
|
||||
if (req_ies)
|
||||
wps = ieee802_11_vendor_ie_concat(req_ies, req_ies_len,
|
||||
WPS_IE_VENDOR_TYPE);
|
||||
else
|
||||
wps = NULL;
|
||||
#ifdef CONFIG_WPS_STRICT
|
||||
if (wps && wps_validate_assoc_req(wps) < 0) {
|
||||
reason = WLAN_REASON_INVALID_IE;
|
||||
status = WLAN_STATUS_INVALID_IE;
|
||||
wpabuf_free(wps);
|
||||
goto fail;
|
||||
}
|
||||
#endif /* CONFIG_WPS_STRICT */
|
||||
if (wps) {
|
||||
sta->flags |= WLAN_STA_WPS;
|
||||
if (wps_is_20(wps)) {
|
||||
wpa_printf(MSG_DEBUG, "WPS: STA supports "
|
||||
"WPS 2.0");
|
||||
sta->flags |= WLAN_STA_WPS2;
|
||||
}
|
||||
} else
|
||||
sta->flags |= WLAN_STA_MAYBE_WPS;
|
||||
wpabuf_free(wps);
|
||||
#endif /* CONFIG_WPS */
|
||||
}
|
||||
#ifdef CONFIG_WPS
|
||||
skip_wpa_check:
|
||||
#endif /* CONFIG_WPS */
|
||||
|
||||
#ifdef CONFIG_IEEE80211R
|
||||
p = wpa_sm_write_assoc_resp_ies(sta->wpa_sm, buf, sizeof(buf),
|
||||
sta->auth_alg, req_ies, req_ies_len);
|
||||
|
||||
hostapd_sta_assoc(hapd, addr, reassoc, status, buf, p - buf);
|
||||
#else /* CONFIG_IEEE80211R */
|
||||
/* Keep compiler silent about unused variables */
|
||||
if (status) {
|
||||
}
|
||||
#endif /* CONFIG_IEEE80211R */
|
||||
|
||||
new_assoc = (sta->flags & WLAN_STA_ASSOC) == 0;
|
||||
sta->flags |= WLAN_STA_AUTH | WLAN_STA_ASSOC;
|
||||
wpa_auth_sm_event(sta->wpa_sm, WPA_ASSOC);
|
||||
|
||||
if (reassoc && (sta->auth_alg == WLAN_AUTH_FT))
|
||||
wpa_auth_sm_event(sta->wpa_sm, WPA_ASSOC_FT);
|
||||
else
|
||||
wpa_auth_sm_event(sta->wpa_sm, WPA_ASSOC);
|
||||
|
||||
hostapd_new_assoc_sta(hapd, sta, !new_assoc);
|
||||
|
||||
ieee802_1x_notify_port_enabled(sta->eapol_sm, 1);
|
||||
|
||||
#ifdef CONFIG_P2P
|
||||
if (req_ies) {
|
||||
p2p_group_notif_assoc(hapd->p2p_group, sta->addr,
|
||||
req_ies, req_ies_len);
|
||||
}
|
||||
#endif /* CONFIG_P2P */
|
||||
|
||||
return 0;
|
||||
|
||||
fail:
|
||||
#ifdef CONFIG_IEEE80211R
|
||||
hostapd_sta_assoc(hapd, addr, reassoc, status, buf, p - buf);
|
||||
#endif /* CONFIG_IEEE80211R */
|
||||
hostapd_drv_sta_disassoc(hapd, sta->addr, reason);
|
||||
ap_free_sta(hapd, sta);
|
||||
return -1;
|
||||
}
|
||||
|
||||
|
||||
@ -163,6 +318,19 @@ void hostapd_notif_disassoc(struct hostapd_data *hapd, const u8 *addr)
|
||||
{
|
||||
struct sta_info *sta;
|
||||
|
||||
if (addr == NULL) {
|
||||
/*
|
||||
* This could potentially happen with unexpected event from the
|
||||
* driver wrapper. This was seen at least in one case where the
|
||||
* driver ended up reporting a station mode event while hostapd
|
||||
* was running, so better make sure we stop processing such an
|
||||
* event here.
|
||||
*/
|
||||
wpa_printf(MSG_DEBUG, "hostapd_notif_disassoc: Skip event "
|
||||
"with no address");
|
||||
return;
|
||||
}
|
||||
|
||||
hostapd_logger(hapd, addr, HOSTAPD_MODULE_IEEE80211,
|
||||
HOSTAPD_LEVEL_INFO, "disassociated");
|
||||
|
||||
@ -173,9 +341,8 @@ void hostapd_notif_disassoc(struct hostapd_data *hapd, const u8 *addr)
|
||||
return;
|
||||
}
|
||||
|
||||
ap_sta_set_authorized(hapd, sta, 0);
|
||||
sta->flags &= ~(WLAN_STA_AUTH | WLAN_STA_ASSOC);
|
||||
wpa_msg(hapd->msg_ctx, MSG_INFO, AP_STA_DISCONNECTED MACSTR,
|
||||
MAC2STR(sta->addr));
|
||||
wpa_auth_sm_event(sta->wpa_sm, WPA_DISASSOC);
|
||||
sta->acct_terminate_cause = RADIUS_ACCT_TERMINATE_CAUSE_USER_REQUEST;
|
||||
ieee802_1x_notify_port_enabled(sta->eapol_sm, 0);
|
||||
@ -183,50 +350,180 @@ void hostapd_notif_disassoc(struct hostapd_data *hapd, const u8 *addr)
|
||||
}
|
||||
|
||||
|
||||
#ifdef HOSTAPD
|
||||
|
||||
#ifdef NEED_AP_MLME
|
||||
|
||||
static const u8 * get_hdr_bssid(const struct ieee80211_hdr *hdr, size_t len)
|
||||
void hostapd_event_sta_low_ack(struct hostapd_data *hapd, const u8 *addr)
|
||||
{
|
||||
u16 fc, type, stype;
|
||||
struct sta_info *sta = ap_get_sta(hapd, addr);
|
||||
|
||||
/*
|
||||
* PS-Poll frames are 16 bytes. All other frames are
|
||||
* 24 bytes or longer.
|
||||
*/
|
||||
if (len < 16)
|
||||
return NULL;
|
||||
if (!sta || !hapd->conf->disassoc_low_ack)
|
||||
return;
|
||||
|
||||
fc = le_to_host16(hdr->frame_control);
|
||||
type = WLAN_FC_GET_TYPE(fc);
|
||||
stype = WLAN_FC_GET_STYPE(fc);
|
||||
|
||||
switch (type) {
|
||||
case WLAN_FC_TYPE_DATA:
|
||||
if (len < 24)
|
||||
return NULL;
|
||||
switch (fc & (WLAN_FC_FROMDS | WLAN_FC_TODS)) {
|
||||
case WLAN_FC_FROMDS | WLAN_FC_TODS:
|
||||
case WLAN_FC_TODS:
|
||||
return hdr->addr1;
|
||||
case WLAN_FC_FROMDS:
|
||||
return hdr->addr2;
|
||||
default:
|
||||
return NULL;
|
||||
}
|
||||
case WLAN_FC_TYPE_CTRL:
|
||||
if (stype != WLAN_FC_STYPE_PSPOLL)
|
||||
return NULL;
|
||||
return hdr->addr1;
|
||||
case WLAN_FC_TYPE_MGMT:
|
||||
return hdr->addr3;
|
||||
default:
|
||||
return NULL;
|
||||
}
|
||||
hostapd_logger(hapd, addr, HOSTAPD_MODULE_IEEE80211,
|
||||
HOSTAPD_LEVEL_INFO, "disconnected due to excessive "
|
||||
"missing ACKs");
|
||||
hostapd_drv_sta_disassoc(hapd, addr, WLAN_REASON_DISASSOC_LOW_ACK);
|
||||
if (sta)
|
||||
ap_sta_disassociate(hapd, sta, WLAN_REASON_DISASSOC_LOW_ACK);
|
||||
}
|
||||
|
||||
|
||||
void hostapd_event_ch_switch(struct hostapd_data *hapd, int freq, int ht,
|
||||
int offset)
|
||||
{
|
||||
#ifdef NEED_AP_MLME
|
||||
int channel;
|
||||
|
||||
hostapd_logger(hapd, NULL, HOSTAPD_MODULE_IEEE80211,
|
||||
HOSTAPD_LEVEL_INFO, "driver had channel switch: "
|
||||
"freq=%d, ht=%d, offset=%d", freq, ht, offset);
|
||||
|
||||
hapd->iface->freq = freq;
|
||||
|
||||
channel = hostapd_hw_get_channel(hapd, freq);
|
||||
if (!channel) {
|
||||
hostapd_logger(hapd, NULL, HOSTAPD_MODULE_IEEE80211,
|
||||
HOSTAPD_LEVEL_WARNING, "driver switched to "
|
||||
"bad channel!");
|
||||
return;
|
||||
}
|
||||
|
||||
hapd->iconf->channel = channel;
|
||||
hapd->iconf->ieee80211n = ht;
|
||||
hapd->iconf->secondary_channel = offset;
|
||||
#endif /* NEED_AP_MLME */
|
||||
}
|
||||
|
||||
|
||||
int hostapd_probe_req_rx(struct hostapd_data *hapd, const u8 *sa, const u8 *da,
|
||||
const u8 *bssid, const u8 *ie, size_t ie_len,
|
||||
int ssi_signal)
|
||||
{
|
||||
size_t i;
|
||||
int ret = 0;
|
||||
|
||||
if (sa == NULL || ie == NULL)
|
||||
return -1;
|
||||
|
||||
random_add_randomness(sa, ETH_ALEN);
|
||||
for (i = 0; hapd->probereq_cb && i < hapd->num_probereq_cb; i++) {
|
||||
if (hapd->probereq_cb[i].cb(hapd->probereq_cb[i].ctx,
|
||||
sa, da, bssid, ie, ie_len,
|
||||
ssi_signal) > 0) {
|
||||
ret = 1;
|
||||
break;
|
||||
}
|
||||
}
|
||||
return ret;
|
||||
}
|
||||
|
||||
|
||||
#ifdef HOSTAPD
|
||||
|
||||
#ifdef CONFIG_IEEE80211R
|
||||
static void hostapd_notify_auth_ft_finish(void *ctx, const u8 *dst,
|
||||
const u8 *bssid,
|
||||
u16 auth_transaction, u16 status,
|
||||
const u8 *ies, size_t ies_len)
|
||||
{
|
||||
struct hostapd_data *hapd = ctx;
|
||||
struct sta_info *sta;
|
||||
|
||||
sta = ap_get_sta(hapd, dst);
|
||||
if (sta == NULL)
|
||||
return;
|
||||
|
||||
hostapd_logger(hapd, dst, HOSTAPD_MODULE_IEEE80211,
|
||||
HOSTAPD_LEVEL_DEBUG, "authentication OK (FT)");
|
||||
sta->flags |= WLAN_STA_AUTH;
|
||||
|
||||
hostapd_sta_auth(hapd, dst, auth_transaction, status, ies, ies_len);
|
||||
}
|
||||
#endif /* CONFIG_IEEE80211R */
|
||||
|
||||
|
||||
static void hostapd_notif_auth(struct hostapd_data *hapd,
|
||||
struct auth_info *rx_auth)
|
||||
{
|
||||
struct sta_info *sta;
|
||||
u16 status = WLAN_STATUS_SUCCESS;
|
||||
u8 resp_ies[2 + WLAN_AUTH_CHALLENGE_LEN];
|
||||
size_t resp_ies_len = 0;
|
||||
|
||||
sta = ap_get_sta(hapd, rx_auth->peer);
|
||||
if (!sta) {
|
||||
sta = ap_sta_add(hapd, rx_auth->peer);
|
||||
if (sta == NULL) {
|
||||
status = WLAN_STATUS_UNSPECIFIED_FAILURE;
|
||||
goto fail;
|
||||
}
|
||||
}
|
||||
sta->flags &= ~WLAN_STA_PREAUTH;
|
||||
ieee802_1x_notify_pre_auth(sta->eapol_sm, 0);
|
||||
#ifdef CONFIG_IEEE80211R
|
||||
if (rx_auth->auth_type == WLAN_AUTH_FT && hapd->wpa_auth) {
|
||||
sta->auth_alg = WLAN_AUTH_FT;
|
||||
if (sta->wpa_sm == NULL)
|
||||
sta->wpa_sm = wpa_auth_sta_init(hapd->wpa_auth,
|
||||
sta->addr);
|
||||
if (sta->wpa_sm == NULL) {
|
||||
wpa_printf(MSG_DEBUG, "FT: Failed to initialize WPA "
|
||||
"state machine");
|
||||
status = WLAN_STATUS_UNSPECIFIED_FAILURE;
|
||||
goto fail;
|
||||
}
|
||||
wpa_ft_process_auth(sta->wpa_sm, rx_auth->bssid,
|
||||
rx_auth->auth_transaction, rx_auth->ies,
|
||||
rx_auth->ies_len,
|
||||
hostapd_notify_auth_ft_finish, hapd);
|
||||
return;
|
||||
}
|
||||
#endif /* CONFIG_IEEE80211R */
|
||||
fail:
|
||||
hostapd_sta_auth(hapd, rx_auth->peer, rx_auth->auth_transaction + 1,
|
||||
status, resp_ies, resp_ies_len);
|
||||
}
|
||||
|
||||
|
||||
static void hostapd_action_rx(struct hostapd_data *hapd,
|
||||
struct rx_action *action)
|
||||
{
|
||||
struct sta_info *sta;
|
||||
|
||||
wpa_printf(MSG_DEBUG, "RX_ACTION cat %d action plen %d",
|
||||
action->category, (int) action->len);
|
||||
|
||||
sta = ap_get_sta(hapd, action->sa);
|
||||
if (sta == NULL) {
|
||||
wpa_printf(MSG_DEBUG, "%s: station not found", __func__);
|
||||
return;
|
||||
}
|
||||
#ifdef CONFIG_IEEE80211R
|
||||
if (action->category == WLAN_ACTION_FT) {
|
||||
wpa_printf(MSG_DEBUG, "%s: FT_ACTION length %d",
|
||||
__func__, (int) action->len);
|
||||
wpa_ft_action_rx(sta->wpa_sm, action->data, action->len);
|
||||
}
|
||||
#endif /* CONFIG_IEEE80211R */
|
||||
#ifdef CONFIG_IEEE80211W
|
||||
if (action->category == WLAN_ACTION_SA_QUERY && action->len >= 4) {
|
||||
wpa_printf(MSG_DEBUG, "%s: SA_QUERY_ACTION length %d",
|
||||
__func__, (int) action->len);
|
||||
ieee802_11_sa_query_action(hapd, action->sa,
|
||||
*(action->data + 1),
|
||||
action->data + 2);
|
||||
}
|
||||
#endif /* CONFIG_IEEE80211W */
|
||||
#ifdef CONFIG_WNM
|
||||
if (action->category == WLAN_ACTION_WNM) {
|
||||
wpa_printf(MSG_DEBUG, "%s: WNM_ACTION length %d",
|
||||
__func__, (int) action->len);
|
||||
ieee802_11_rx_wnm_action_ap(hapd, action);
|
||||
}
|
||||
#endif /* CONFIG_WNM */
|
||||
}
|
||||
|
||||
|
||||
#ifdef NEED_AP_MLME
|
||||
|
||||
#define HAPD_BROADCAST ((struct hostapd_data *) -1)
|
||||
|
||||
static struct hostapd_data * get_hapd_bssid(struct hostapd_iface *iface,
|
||||
@ -250,17 +547,14 @@ static struct hostapd_data * get_hapd_bssid(struct hostapd_iface *iface,
|
||||
|
||||
|
||||
static void hostapd_rx_from_unknown_sta(struct hostapd_data *hapd,
|
||||
const u8 *frame, size_t len)
|
||||
const u8 *bssid, const u8 *addr,
|
||||
int wds)
|
||||
{
|
||||
const struct ieee80211_hdr *hdr = (const struct ieee80211_hdr *) frame;
|
||||
u16 fc = le_to_host16(hdr->frame_control);
|
||||
hapd = get_hapd_bssid(hapd->iface, get_hdr_bssid(hdr, len));
|
||||
hapd = get_hapd_bssid(hapd->iface, bssid);
|
||||
if (hapd == NULL || hapd == HAPD_BROADCAST)
|
||||
return;
|
||||
|
||||
ieee802_11_rx_from_unknown(hapd, hdr->addr2,
|
||||
(fc & (WLAN_FC_TODS | WLAN_FC_FROMDS)) ==
|
||||
(WLAN_FC_TODS | WLAN_FC_FROMDS));
|
||||
ieee802_11_rx_from_unknown(hapd, addr, wds);
|
||||
}
|
||||
|
||||
|
||||
@ -303,6 +597,48 @@ static void hostapd_mgmt_rx(struct hostapd_data *hapd, struct rx_mgmt *rx_mgmt)
|
||||
rx_mgmt->frame_len, &fi);
|
||||
} else
|
||||
ieee802_11_mgmt(hapd, rx_mgmt->frame, rx_mgmt->frame_len, &fi);
|
||||
|
||||
random_add_randomness(&fi, sizeof(fi));
|
||||
}
|
||||
|
||||
|
||||
static void hostapd_rx_action(struct hostapd_data *hapd,
|
||||
struct rx_action *rx_action)
|
||||
{
|
||||
struct rx_mgmt rx_mgmt;
|
||||
u8 *buf;
|
||||
struct ieee80211_hdr *hdr;
|
||||
|
||||
wpa_printf(MSG_DEBUG, "EVENT_RX_ACTION DA=" MACSTR " SA=" MACSTR
|
||||
" BSSID=" MACSTR " category=%u",
|
||||
MAC2STR(rx_action->da), MAC2STR(rx_action->sa),
|
||||
MAC2STR(rx_action->bssid), rx_action->category);
|
||||
wpa_hexdump(MSG_MSGDUMP, "Received action frame contents",
|
||||
rx_action->data, rx_action->len);
|
||||
|
||||
buf = os_zalloc(24 + 1 + rx_action->len);
|
||||
if (buf == NULL)
|
||||
return;
|
||||
hdr = (struct ieee80211_hdr *) buf;
|
||||
hdr->frame_control = IEEE80211_FC(WLAN_FC_TYPE_MGMT,
|
||||
WLAN_FC_STYPE_ACTION);
|
||||
if (rx_action->category == WLAN_ACTION_SA_QUERY) {
|
||||
/*
|
||||
* Assume frame was protected; it would have been dropped if
|
||||
* not.
|
||||
*/
|
||||
hdr->frame_control |= host_to_le16(WLAN_FC_ISWEP);
|
||||
}
|
||||
os_memcpy(hdr->addr1, rx_action->da, ETH_ALEN);
|
||||
os_memcpy(hdr->addr2, rx_action->sa, ETH_ALEN);
|
||||
os_memcpy(hdr->addr3, rx_action->bssid, ETH_ALEN);
|
||||
buf[24] = rx_action->category;
|
||||
os_memcpy(buf + 24 + 1, rx_action->data, rx_action->len);
|
||||
os_memset(&rx_mgmt, 0, sizeof(rx_mgmt));
|
||||
rx_mgmt.frame = buf;
|
||||
rx_mgmt.frame_len = 24 + 1 + rx_action->len;
|
||||
hostapd_mgmt_rx(hapd, &rx_mgmt);
|
||||
os_free(buf);
|
||||
}
|
||||
|
||||
|
||||
@ -320,23 +656,6 @@ static void hostapd_mgmt_tx_cb(struct hostapd_data *hapd, const u8 *buf,
|
||||
#endif /* NEED_AP_MLME */
|
||||
|
||||
|
||||
static int hostapd_probe_req_rx(struct hostapd_data *hapd, const u8 *sa,
|
||||
const u8 *ie, size_t ie_len)
|
||||
{
|
||||
size_t i;
|
||||
int ret = 0;
|
||||
|
||||
for (i = 0; hapd->probereq_cb && i < hapd->num_probereq_cb; i++) {
|
||||
if (hapd->probereq_cb[i].cb(hapd->probereq_cb[i].ctx,
|
||||
sa, ie, ie_len) > 0) {
|
||||
ret = 1;
|
||||
break;
|
||||
}
|
||||
}
|
||||
return ret;
|
||||
}
|
||||
|
||||
|
||||
static int hostapd_event_new_sta(struct hostapd_data *hapd, const u8 *addr)
|
||||
{
|
||||
struct sta_info *sta = ap_get_sta(hapd, addr);
|
||||
@ -362,12 +681,15 @@ static void hostapd_event_eapol_rx(struct hostapd_data *hapd, const u8 *src,
|
||||
const u8 *data, size_t data_len)
|
||||
{
|
||||
struct hostapd_iface *iface = hapd->iface;
|
||||
struct sta_info *sta;
|
||||
size_t j;
|
||||
|
||||
for (j = 0; j < iface->num_bss; j++) {
|
||||
if (ap_get_sta(iface->bss[j], src)) {
|
||||
hapd = iface->bss[j];
|
||||
break;
|
||||
if ((sta = ap_get_sta(iface->bss[j], src))) {
|
||||
if (sta->flags & WLAN_STA_ASSOC) {
|
||||
hapd = iface->bss[j];
|
||||
break;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@ -379,6 +701,23 @@ void wpa_supplicant_event(void *ctx, enum wpa_event_type event,
|
||||
union wpa_event_data *data)
|
||||
{
|
||||
struct hostapd_data *hapd = ctx;
|
||||
#ifndef CONFIG_NO_STDOUT_DEBUG
|
||||
int level = MSG_DEBUG;
|
||||
|
||||
if (event == EVENT_RX_MGMT && data->rx_mgmt.frame &&
|
||||
data->rx_mgmt.frame_len >= 24) {
|
||||
const struct ieee80211_hdr *hdr;
|
||||
u16 fc;
|
||||
hdr = (const struct ieee80211_hdr *) data->rx_mgmt.frame;
|
||||
fc = le_to_host16(hdr->frame_control);
|
||||
if (WLAN_FC_GET_TYPE(fc) == WLAN_FC_TYPE_MGMT &&
|
||||
WLAN_FC_GET_STYPE(fc) == WLAN_FC_STYPE_BEACON)
|
||||
level = MSG_EXCESSIVE;
|
||||
}
|
||||
|
||||
wpa_dbg(hapd->msg_ctx, level, "Event %s (%d) received",
|
||||
event_to_string(event), event);
|
||||
#endif /* CONFIG_NO_STDOUT_DEBUG */
|
||||
|
||||
switch (event) {
|
||||
case EVENT_MICHAEL_MIC_FAILURE:
|
||||
@ -395,7 +734,7 @@ void wpa_supplicant_event(void *ctx, enum wpa_event_type event,
|
||||
break;
|
||||
#endif /* CONFIG_IEEE80211R */
|
||||
case EVENT_WPS_BUTTON_PUSHED:
|
||||
hostapd_wps_button_pushed(hapd);
|
||||
hostapd_wps_button_pushed(hapd, NULL);
|
||||
break;
|
||||
#ifdef NEED_AP_MLME
|
||||
case EVENT_TX_STATUS:
|
||||
@ -414,18 +753,34 @@ void wpa_supplicant_event(void *ctx, enum wpa_event_type event,
|
||||
break;
|
||||
}
|
||||
break;
|
||||
case EVENT_EAPOL_TX_STATUS:
|
||||
hostapd_eapol_tx_status(hapd, data->eapol_tx_status.dst,
|
||||
data->eapol_tx_status.data,
|
||||
data->eapol_tx_status.data_len,
|
||||
data->eapol_tx_status.ack);
|
||||
break;
|
||||
case EVENT_DRIVER_CLIENT_POLL_OK:
|
||||
hostapd_client_poll_ok(hapd, data->client_poll.addr);
|
||||
break;
|
||||
case EVENT_RX_FROM_UNKNOWN:
|
||||
hostapd_rx_from_unknown_sta(hapd, data->rx_from_unknown.frame,
|
||||
data->rx_from_unknown.len);
|
||||
hostapd_rx_from_unknown_sta(hapd, data->rx_from_unknown.bssid,
|
||||
data->rx_from_unknown.addr,
|
||||
data->rx_from_unknown.wds);
|
||||
break;
|
||||
case EVENT_RX_MGMT:
|
||||
hostapd_mgmt_rx(hapd, &data->rx_mgmt);
|
||||
break;
|
||||
#endif /* NEED_AP_MLME */
|
||||
case EVENT_RX_PROBE_REQ:
|
||||
if (data->rx_probe_req.sa == NULL ||
|
||||
data->rx_probe_req.ie == NULL)
|
||||
break;
|
||||
hostapd_probe_req_rx(hapd, data->rx_probe_req.sa,
|
||||
data->rx_probe_req.da,
|
||||
data->rx_probe_req.bssid,
|
||||
data->rx_probe_req.ie,
|
||||
data->rx_probe_req.ie_len);
|
||||
data->rx_probe_req.ie_len,
|
||||
data->rx_probe_req.ssi_signal);
|
||||
break;
|
||||
case EVENT_NEW_STA:
|
||||
hostapd_event_new_sta(hapd, data->new_sta.addr);
|
||||
@ -438,7 +793,8 @@ void wpa_supplicant_event(void *ctx, enum wpa_event_type event,
|
||||
case EVENT_ASSOC:
|
||||
hostapd_notif_assoc(hapd, data->assoc_info.addr,
|
||||
data->assoc_info.req_ies,
|
||||
data->assoc_info.req_ies_len);
|
||||
data->assoc_info.req_ies_len,
|
||||
data->assoc_info.reassoc);
|
||||
break;
|
||||
case EVENT_DISASSOC:
|
||||
if (data)
|
||||
@ -448,6 +804,30 @@ void wpa_supplicant_event(void *ctx, enum wpa_event_type event,
|
||||
if (data)
|
||||
hostapd_notif_disassoc(hapd, data->deauth_info.addr);
|
||||
break;
|
||||
case EVENT_STATION_LOW_ACK:
|
||||
if (!data)
|
||||
break;
|
||||
hostapd_event_sta_low_ack(hapd, data->low_ack.addr);
|
||||
break;
|
||||
case EVENT_RX_ACTION:
|
||||
if (data->rx_action.da == NULL || data->rx_action.sa == NULL ||
|
||||
data->rx_action.bssid == NULL)
|
||||
break;
|
||||
#ifdef NEED_AP_MLME
|
||||
hostapd_rx_action(hapd, &data->rx_action);
|
||||
#endif /* NEED_AP_MLME */
|
||||
hostapd_action_rx(hapd, &data->rx_action);
|
||||
break;
|
||||
case EVENT_AUTH:
|
||||
hostapd_notif_auth(hapd, &data->auth);
|
||||
break;
|
||||
case EVENT_CH_SWITCH:
|
||||
if (!data)
|
||||
break;
|
||||
hostapd_event_ch_switch(hapd, data->ch_switch.freq,
|
||||
data->ch_switch.ht_enabled,
|
||||
data->ch_switch.ch_offset);
|
||||
break;
|
||||
default:
|
||||
wpa_printf(MSG_DEBUG, "Unknown event %d", event);
|
||||
break;
|
||||
|
270
contrib/wpa/src/ap/eap_user_db.c
Normal file
270
contrib/wpa/src/ap/eap_user_db.c
Normal file
@ -0,0 +1,270 @@
|
||||
/*
|
||||
* hostapd / EAP user database
|
||||
* Copyright (c) 2012, Jouni Malinen <j@w1.fi>
|
||||
*
|
||||
* This software may be distributed under the terms of the BSD license.
|
||||
* See README for more details.
|
||||
*/
|
||||
|
||||
#include "includes.h"
|
||||
#ifdef CONFIG_SQLITE
|
||||
#include <sqlite3.h>
|
||||
#endif /* CONFIG_SQLITE */
|
||||
|
||||
#include "common.h"
|
||||
#include "eap_common/eap_wsc_common.h"
|
||||
#include "eap_server/eap_methods.h"
|
||||
#include "eap_server/eap.h"
|
||||
#include "ap_config.h"
|
||||
#include "hostapd.h"
|
||||
|
||||
#ifdef CONFIG_SQLITE
|
||||
|
||||
static void set_user_methods(struct hostapd_eap_user *user, const char *methods)
|
||||
{
|
||||
char *buf, *start;
|
||||
int num_methods;
|
||||
|
||||
buf = os_strdup(methods);
|
||||
if (buf == NULL)
|
||||
return;
|
||||
|
||||
os_memset(&user->methods, 0, sizeof(user->methods));
|
||||
num_methods = 0;
|
||||
start = buf;
|
||||
while (*start) {
|
||||
char *pos3 = os_strchr(start, ',');
|
||||
if (pos3)
|
||||
*pos3++ = '\0';
|
||||
user->methods[num_methods].method =
|
||||
eap_server_get_type(start,
|
||||
&user->methods[num_methods].vendor);
|
||||
if (user->methods[num_methods].vendor == EAP_VENDOR_IETF &&
|
||||
user->methods[num_methods].method == EAP_TYPE_NONE) {
|
||||
if (os_strcmp(start, "TTLS-PAP") == 0) {
|
||||
user->ttls_auth |= EAP_TTLS_AUTH_PAP;
|
||||
goto skip_eap;
|
||||
}
|
||||
if (os_strcmp(start, "TTLS-CHAP") == 0) {
|
||||
user->ttls_auth |= EAP_TTLS_AUTH_CHAP;
|
||||
goto skip_eap;
|
||||
}
|
||||
if (os_strcmp(start, "TTLS-MSCHAP") == 0) {
|
||||
user->ttls_auth |= EAP_TTLS_AUTH_MSCHAP;
|
||||
goto skip_eap;
|
||||
}
|
||||
if (os_strcmp(start, "TTLS-MSCHAPV2") == 0) {
|
||||
user->ttls_auth |= EAP_TTLS_AUTH_MSCHAPV2;
|
||||
goto skip_eap;
|
||||
}
|
||||
wpa_printf(MSG_INFO, "DB: Unsupported EAP type '%s'",
|
||||
start);
|
||||
os_free(buf);
|
||||
return;
|
||||
}
|
||||
|
||||
num_methods++;
|
||||
if (num_methods >= EAP_MAX_METHODS)
|
||||
break;
|
||||
skip_eap:
|
||||
if (pos3 == NULL)
|
||||
break;
|
||||
start = pos3;
|
||||
}
|
||||
|
||||
os_free(buf);
|
||||
}
|
||||
|
||||
|
||||
static int get_user_cb(void *ctx, int argc, char *argv[], char *col[])
|
||||
{
|
||||
struct hostapd_eap_user *user = ctx;
|
||||
int i;
|
||||
|
||||
for (i = 0; i < argc; i++) {
|
||||
if (os_strcmp(col[i], "password") == 0 && argv[i]) {
|
||||
os_free(user->password);
|
||||
user->password_len = os_strlen(argv[i]);
|
||||
user->password = (u8 *) os_strdup(argv[i]);
|
||||
user->next = (void *) 1;
|
||||
} else if (os_strcmp(col[i], "methods") == 0 && argv[i]) {
|
||||
set_user_methods(user, argv[i]);
|
||||
}
|
||||
}
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
|
||||
static int get_wildcard_cb(void *ctx, int argc, char *argv[], char *col[])
|
||||
{
|
||||
struct hostapd_eap_user *user = ctx;
|
||||
int i, id = -1, methods = -1;
|
||||
size_t len;
|
||||
|
||||
for (i = 0; i < argc; i++) {
|
||||
if (os_strcmp(col[i], "identity") == 0 && argv[i])
|
||||
id = i;
|
||||
else if (os_strcmp(col[i], "methods") == 0 && argv[i])
|
||||
methods = i;
|
||||
}
|
||||
|
||||
if (id < 0 || methods < 0)
|
||||
return 0;
|
||||
|
||||
len = os_strlen(argv[id]);
|
||||
if (len <= user->identity_len &&
|
||||
os_memcmp(argv[id], user->identity, len) == 0 &&
|
||||
(user->password == NULL || len > user->password_len)) {
|
||||
os_free(user->password);
|
||||
user->password_len = os_strlen(argv[id]);
|
||||
user->password = (u8 *) os_strdup(argv[id]);
|
||||
user->next = (void *) 1;
|
||||
set_user_methods(user, argv[methods]);
|
||||
}
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
|
||||
static const struct hostapd_eap_user *
|
||||
eap_user_sqlite_get(struct hostapd_data *hapd, const u8 *identity,
|
||||
size_t identity_len, int phase2)
|
||||
{
|
||||
sqlite3 *db;
|
||||
struct hostapd_eap_user *user = NULL;
|
||||
char id_str[256], cmd[300];
|
||||
size_t i;
|
||||
|
||||
if (identity_len >= sizeof(id_str))
|
||||
return NULL;
|
||||
os_memcpy(id_str, identity, identity_len);
|
||||
id_str[identity_len] = '\0';
|
||||
for (i = 0; i < identity_len; i++) {
|
||||
if (id_str[i] >= 'a' && id_str[i] <= 'z')
|
||||
continue;
|
||||
if (id_str[i] >= 'A' && id_str[i] <= 'Z')
|
||||
continue;
|
||||
if (id_str[i] >= '0' && id_str[i] <= '9')
|
||||
continue;
|
||||
if (id_str[i] == '-' || id_str[i] == '_' || id_str[i] == '.' ||
|
||||
id_str[i] == ',' || id_str[i] == '@' || id_str[i] == '\\' ||
|
||||
id_str[i] == '!' || id_str[i] == '#' || id_str[i] == '%' ||
|
||||
id_str[i] == '=' || id_str[i] == ' ')
|
||||
continue;
|
||||
wpa_printf(MSG_INFO, "DB: Unsupported character in identity");
|
||||
return NULL;
|
||||
}
|
||||
|
||||
os_free(hapd->tmp_eap_user.identity);
|
||||
os_free(hapd->tmp_eap_user.password);
|
||||
os_memset(&hapd->tmp_eap_user, 0, sizeof(hapd->tmp_eap_user));
|
||||
hapd->tmp_eap_user.phase2 = phase2;
|
||||
hapd->tmp_eap_user.identity = os_zalloc(identity_len + 1);
|
||||
if (hapd->tmp_eap_user.identity == NULL)
|
||||
return NULL;
|
||||
os_memcpy(hapd->tmp_eap_user.identity, identity, identity_len);
|
||||
|
||||
if (sqlite3_open(hapd->conf->eap_user_sqlite, &db)) {
|
||||
wpa_printf(MSG_INFO, "DB: Failed to open database %s: %s",
|
||||
hapd->conf->eap_user_sqlite, sqlite3_errmsg(db));
|
||||
sqlite3_close(db);
|
||||
return NULL;
|
||||
}
|
||||
|
||||
os_snprintf(cmd, sizeof(cmd),
|
||||
"SELECT password,methods FROM users WHERE "
|
||||
"identity='%s' AND phase2=%d;", id_str, phase2);
|
||||
wpa_printf(MSG_DEBUG, "DB: %s", cmd);
|
||||
if (sqlite3_exec(db, cmd, get_user_cb, &hapd->tmp_eap_user, NULL) !=
|
||||
SQLITE_OK) {
|
||||
wpa_printf(MSG_DEBUG, "DB: Failed to complete SQL operation");
|
||||
} else if (hapd->tmp_eap_user.next)
|
||||
user = &hapd->tmp_eap_user;
|
||||
|
||||
if (user == NULL && !phase2) {
|
||||
os_snprintf(cmd, sizeof(cmd),
|
||||
"SELECT identity,methods FROM wildcards;");
|
||||
wpa_printf(MSG_DEBUG, "DB: %s", cmd);
|
||||
if (sqlite3_exec(db, cmd, get_wildcard_cb, &hapd->tmp_eap_user,
|
||||
NULL) != SQLITE_OK) {
|
||||
wpa_printf(MSG_DEBUG, "DB: Failed to complete SQL "
|
||||
"operation");
|
||||
} else if (hapd->tmp_eap_user.next) {
|
||||
user = &hapd->tmp_eap_user;
|
||||
os_free(user->identity);
|
||||
user->identity = user->password;
|
||||
user->identity_len = user->password_len;
|
||||
user->password = NULL;
|
||||
user->password_len = 0;
|
||||
}
|
||||
}
|
||||
|
||||
sqlite3_close(db);
|
||||
|
||||
return user;
|
||||
}
|
||||
|
||||
#endif /* CONFIG_SQLITE */
|
||||
|
||||
|
||||
const struct hostapd_eap_user *
|
||||
hostapd_get_eap_user(struct hostapd_data *hapd, const u8 *identity,
|
||||
size_t identity_len, int phase2)
|
||||
{
|
||||
const struct hostapd_bss_config *conf = hapd->conf;
|
||||
struct hostapd_eap_user *user = conf->eap_user;
|
||||
|
||||
#ifdef CONFIG_WPS
|
||||
if (conf->wps_state && identity_len == WSC_ID_ENROLLEE_LEN &&
|
||||
os_memcmp(identity, WSC_ID_ENROLLEE, WSC_ID_ENROLLEE_LEN) == 0) {
|
||||
static struct hostapd_eap_user wsc_enrollee;
|
||||
os_memset(&wsc_enrollee, 0, sizeof(wsc_enrollee));
|
||||
wsc_enrollee.methods[0].method = eap_server_get_type(
|
||||
"WSC", &wsc_enrollee.methods[0].vendor);
|
||||
return &wsc_enrollee;
|
||||
}
|
||||
|
||||
if (conf->wps_state && identity_len == WSC_ID_REGISTRAR_LEN &&
|
||||
os_memcmp(identity, WSC_ID_REGISTRAR, WSC_ID_REGISTRAR_LEN) == 0) {
|
||||
static struct hostapd_eap_user wsc_registrar;
|
||||
os_memset(&wsc_registrar, 0, sizeof(wsc_registrar));
|
||||
wsc_registrar.methods[0].method = eap_server_get_type(
|
||||
"WSC", &wsc_registrar.methods[0].vendor);
|
||||
wsc_registrar.password = (u8 *) conf->ap_pin;
|
||||
wsc_registrar.password_len = conf->ap_pin ?
|
||||
os_strlen(conf->ap_pin) : 0;
|
||||
return &wsc_registrar;
|
||||
}
|
||||
#endif /* CONFIG_WPS */
|
||||
|
||||
while (user) {
|
||||
if (!phase2 && user->identity == NULL) {
|
||||
/* Wildcard match */
|
||||
break;
|
||||
}
|
||||
|
||||
if (user->phase2 == !!phase2 && user->wildcard_prefix &&
|
||||
identity_len >= user->identity_len &&
|
||||
os_memcmp(user->identity, identity, user->identity_len) ==
|
||||
0) {
|
||||
/* Wildcard prefix match */
|
||||
break;
|
||||
}
|
||||
|
||||
if (user->phase2 == !!phase2 &&
|
||||
user->identity_len == identity_len &&
|
||||
os_memcmp(user->identity, identity, identity_len) == 0)
|
||||
break;
|
||||
user = user->next;
|
||||
}
|
||||
|
||||
#ifdef CONFIG_SQLITE
|
||||
if (user == NULL && conf->eap_user_sqlite) {
|
||||
return eap_user_sqlite_get(hapd, identity, identity_len,
|
||||
phase2);
|
||||
}
|
||||
#endif /* CONFIG_SQLITE */
|
||||
|
||||
return user;
|
||||
}
|
1172
contrib/wpa/src/ap/gas_serv.c
Normal file
1172
contrib/wpa/src/ap/gas_serv.c
Normal file
File diff suppressed because it is too large
Load Diff
71
contrib/wpa/src/ap/gas_serv.h
Normal file
71
contrib/wpa/src/ap/gas_serv.h
Normal file
@ -0,0 +1,71 @@
|
||||
/*
|
||||
* Generic advertisement service (GAS) server
|
||||
* Copyright (c) 2011-2012, Qualcomm Atheros, Inc.
|
||||
*
|
||||
* This software may be distributed under the terms of the BSD license.
|
||||
* See README for more details.
|
||||
*/
|
||||
|
||||
#ifndef GAS_SERV_H
|
||||
#define GAS_SERV_H
|
||||
|
||||
#define ANQP_REQ_CAPABILITY_LIST \
|
||||
(1 << (ANQP_CAPABILITY_LIST - ANQP_QUERY_LIST))
|
||||
#define ANQP_REQ_VENUE_NAME \
|
||||
(1 << (ANQP_VENUE_NAME - ANQP_QUERY_LIST))
|
||||
#define ANQP_REQ_NETWORK_AUTH_TYPE \
|
||||
(1 << (ANQP_NETWORK_AUTH_TYPE - ANQP_QUERY_LIST))
|
||||
#define ANQP_REQ_ROAMING_CONSORTIUM \
|
||||
(1 << (ANQP_ROAMING_CONSORTIUM - ANQP_QUERY_LIST))
|
||||
#define ANQP_REQ_IP_ADDR_TYPE_AVAILABILITY \
|
||||
(1 << (ANQP_IP_ADDR_TYPE_AVAILABILITY - ANQP_QUERY_LIST))
|
||||
#define ANQP_REQ_NAI_REALM \
|
||||
(1 << (ANQP_NAI_REALM - ANQP_QUERY_LIST))
|
||||
#define ANQP_REQ_3GPP_CELLULAR_NETWORK \
|
||||
(1 << (ANQP_3GPP_CELLULAR_NETWORK - ANQP_QUERY_LIST))
|
||||
#define ANQP_REQ_DOMAIN_NAME \
|
||||
(1 << (ANQP_DOMAIN_NAME - ANQP_QUERY_LIST))
|
||||
#define ANQP_REQ_HS_CAPABILITY_LIST \
|
||||
(0x10000 << HS20_STYPE_CAPABILITY_LIST)
|
||||
#define ANQP_REQ_OPERATOR_FRIENDLY_NAME \
|
||||
(0x10000 << HS20_STYPE_OPERATOR_FRIENDLY_NAME)
|
||||
#define ANQP_REQ_WAN_METRICS \
|
||||
(0x10000 << HS20_STYPE_WAN_METRICS)
|
||||
#define ANQP_REQ_CONNECTION_CAPABILITY \
|
||||
(0x10000 << HS20_STYPE_CONNECTION_CAPABILITY)
|
||||
#define ANQP_REQ_NAI_HOME_REALM \
|
||||
(0x10000 << HS20_STYPE_NAI_HOME_REALM_QUERY)
|
||||
#define ANQP_REQ_OPERATING_CLASS \
|
||||
(0x10000 << HS20_STYPE_OPERATING_CLASS)
|
||||
|
||||
/* To account for latencies between hostapd and external ANQP processor */
|
||||
#define GAS_SERV_COMEBACK_DELAY_FUDGE 10
|
||||
#define GAS_SERV_MIN_COMEBACK_DELAY 100 /* in TU */
|
||||
|
||||
struct gas_dialog_info {
|
||||
u8 valid;
|
||||
u8 index;
|
||||
struct wpabuf *sd_resp; /* Fragmented response */
|
||||
u8 dialog_token;
|
||||
size_t sd_resp_pos; /* Offset in sd_resp */
|
||||
u8 sd_frag_id;
|
||||
u16 comeback_delay;
|
||||
|
||||
unsigned int requested;
|
||||
unsigned int received;
|
||||
unsigned int all_requested;
|
||||
};
|
||||
|
||||
struct hostapd_data;
|
||||
|
||||
void gas_serv_tx_gas_response(struct hostapd_data *hapd, const u8 *dst,
|
||||
struct gas_dialog_info *dialog);
|
||||
struct gas_dialog_info *
|
||||
gas_serv_dialog_find(struct hostapd_data *hapd, const u8 *addr,
|
||||
u8 dialog_token);
|
||||
void gas_serv_dialog_clear(struct gas_dialog_info *dialog);
|
||||
|
||||
int gas_serv_init(struct hostapd_data *hapd);
|
||||
void gas_serv_deinit(struct hostapd_data *hapd);
|
||||
|
||||
#endif /* GAS_SERV_H */
|
File diff suppressed because it is too large
Load Diff
@ -2,34 +2,51 @@
|
||||
* hostapd / Initialization and configuration
|
||||
* Copyright (c) 2002-2009, Jouni Malinen <j@w1.fi>
|
||||
*
|
||||
* This program is free software; you can redistribute it and/or modify
|
||||
* it under the terms of the GNU General Public License version 2 as
|
||||
* published by the Free Software Foundation.
|
||||
*
|
||||
* Alternatively, this software may be distributed under the terms of BSD
|
||||
* license.
|
||||
*
|
||||
* See README and COPYING for more details.
|
||||
* This software may be distributed under the terms of the BSD license.
|
||||
* See README for more details.
|
||||
*/
|
||||
|
||||
#ifndef HOSTAPD_H
|
||||
#define HOSTAPD_H
|
||||
|
||||
#include "common/defs.h"
|
||||
#include "ap_config.h"
|
||||
|
||||
struct wpa_driver_ops;
|
||||
struct wpa_ctrl_dst;
|
||||
struct radius_server_data;
|
||||
struct upnp_wps_device_sm;
|
||||
struct hapd_interfaces;
|
||||
struct hostapd_data;
|
||||
struct sta_info;
|
||||
struct hostap_sta_driver_data;
|
||||
struct ieee80211_ht_capabilities;
|
||||
struct full_dynamic_vlan;
|
||||
enum wps_event;
|
||||
union wps_event_data;
|
||||
|
||||
struct hostapd_iface;
|
||||
|
||||
struct hapd_interfaces {
|
||||
int (*reload_config)(struct hostapd_iface *iface);
|
||||
struct hostapd_config * (*config_read_cb)(const char *config_fname);
|
||||
int (*ctrl_iface_init)(struct hostapd_data *hapd);
|
||||
void (*ctrl_iface_deinit)(struct hostapd_data *hapd);
|
||||
int (*for_each_interface)(struct hapd_interfaces *interfaces,
|
||||
int (*cb)(struct hostapd_iface *iface,
|
||||
void *ctx), void *ctx);
|
||||
int (*driver_init)(struct hostapd_iface *iface);
|
||||
|
||||
size_t count;
|
||||
int global_ctrl_sock;
|
||||
char *global_iface_path;
|
||||
char *global_iface_name;
|
||||
struct hostapd_iface **iface;
|
||||
};
|
||||
|
||||
|
||||
struct hostapd_probereq_cb {
|
||||
int (*cb)(void *ctx, const u8 *sa, const u8 *ie, size_t ie_len);
|
||||
int (*cb)(void *ctx, const u8 *sa, const u8 *da, const u8 *bssid,
|
||||
const u8 *ie, size_t ie_len, int ssi_signal);
|
||||
void *ctx;
|
||||
};
|
||||
|
||||
@ -43,59 +60,10 @@ struct hostapd_rate_data {
|
||||
struct hostapd_frame_info {
|
||||
u32 channel;
|
||||
u32 datarate;
|
||||
u32 ssi_signal;
|
||||
int ssi_signal; /* dBm */
|
||||
};
|
||||
|
||||
|
||||
struct hostapd_driver_ops {
|
||||
int (*set_ap_wps_ie)(struct hostapd_data *hapd);
|
||||
int (*send_mgmt_frame)(struct hostapd_data *hapd, const void *msg,
|
||||
size_t len);
|
||||
int (*send_eapol)(struct hostapd_data *hapd, const u8 *addr,
|
||||
const u8 *data, size_t data_len, int encrypt);
|
||||
int (*set_authorized)(struct hostapd_data *hapd, struct sta_info *sta,
|
||||
int authorized);
|
||||
int (*set_key)(const char *ifname, struct hostapd_data *hapd,
|
||||
enum wpa_alg alg, const u8 *addr, int key_idx,
|
||||
int set_tx, const u8 *seq, size_t seq_len,
|
||||
const u8 *key, size_t key_len);
|
||||
int (*read_sta_data)(struct hostapd_data *hapd,
|
||||
struct hostap_sta_driver_data *data,
|
||||
const u8 *addr);
|
||||
int (*sta_clear_stats)(struct hostapd_data *hapd, const u8 *addr);
|
||||
int (*set_sta_flags)(struct hostapd_data *hapd, struct sta_info *sta);
|
||||
int (*set_drv_ieee8021x)(struct hostapd_data *hapd, const char *ifname,
|
||||
int enabled);
|
||||
int (*set_radius_acl_auth)(struct hostapd_data *hapd,
|
||||
const u8 *mac, int accepted,
|
||||
u32 session_timeout);
|
||||
int (*set_radius_acl_expire)(struct hostapd_data *hapd,
|
||||
const u8 *mac);
|
||||
int (*set_bss_params)(struct hostapd_data *hapd, int use_protection);
|
||||
int (*set_beacon)(struct hostapd_data *hapd,
|
||||
const u8 *head, size_t head_len,
|
||||
const u8 *tail, size_t tail_len, int dtim_period,
|
||||
int beacon_int);
|
||||
int (*vlan_if_add)(struct hostapd_data *hapd, const char *ifname);
|
||||
int (*vlan_if_remove)(struct hostapd_data *hapd, const char *ifname);
|
||||
int (*set_wds_sta)(struct hostapd_data *hapd, const u8 *addr, int aid,
|
||||
int val);
|
||||
int (*set_sta_vlan)(const char *ifname, struct hostapd_data *hapd,
|
||||
const u8 *addr, int vlan_id);
|
||||
int (*get_inact_sec)(struct hostapd_data *hapd, const u8 *addr);
|
||||
int (*sta_deauth)(struct hostapd_data *hapd, const u8 *addr,
|
||||
int reason);
|
||||
int (*sta_disassoc)(struct hostapd_data *hapd, const u8 *addr,
|
||||
int reason);
|
||||
int (*sta_add)(struct hostapd_data *hapd,
|
||||
const u8 *addr, u16 aid, u16 capability,
|
||||
const u8 *supp_rates, size_t supp_rates_len,
|
||||
u16 listen_interval,
|
||||
const struct ieee80211_ht_capabilities *ht_capab);
|
||||
int (*sta_remove)(struct hostapd_data *hapd, const u8 *addr);
|
||||
int (*set_countermeasures)(struct hostapd_data *hapd, int enabled);
|
||||
};
|
||||
|
||||
/**
|
||||
* struct hostapd_data - hostapd per-BSS data structure
|
||||
*/
|
||||
@ -123,15 +91,16 @@ struct hostapd_data {
|
||||
|
||||
const struct wpa_driver_ops *driver;
|
||||
void *drv_priv;
|
||||
struct hostapd_driver_ops drv;
|
||||
|
||||
void (*new_assoc_sta_cb)(struct hostapd_data *hapd,
|
||||
struct sta_info *sta, int reassoc);
|
||||
|
||||
void *msg_ctx; /* ctx for wpa_msg() calls */
|
||||
void *msg_ctx_parent; /* parent interface ctx for wpa_msg() calls */
|
||||
|
||||
struct radius_client_data *radius;
|
||||
u32 acct_session_id_hi, acct_session_id_lo;
|
||||
struct radius_das_data *radius_das;
|
||||
|
||||
struct iapp_data *iapp;
|
||||
|
||||
@ -155,6 +124,10 @@ struct hostapd_data {
|
||||
|
||||
int parameter_set_count;
|
||||
|
||||
/* Time Advertisement */
|
||||
u8 time_update_counter;
|
||||
struct wpabuf *time_adv;
|
||||
|
||||
#ifdef CONFIG_FULL_DYNAMIC_VLAN
|
||||
struct full_dynamic_vlan *full_dynamic_vlan;
|
||||
#endif /* CONFIG_FULL_DYNAMIC_VLAN */
|
||||
@ -162,10 +135,12 @@ struct hostapd_data {
|
||||
struct l2_packet_data *l2;
|
||||
struct wps_context *wps;
|
||||
|
||||
int beacon_set_done;
|
||||
struct wpabuf *wps_beacon_ie;
|
||||
struct wpabuf *wps_probe_resp_ie;
|
||||
#ifdef CONFIG_WPS
|
||||
unsigned int ap_pin_failures;
|
||||
unsigned int ap_pin_failures_consecutive;
|
||||
struct upnp_wps_device_sm *wps_upnp;
|
||||
unsigned int ap_pin_lockout_time;
|
||||
#endif /* CONFIG_WPS */
|
||||
@ -177,9 +152,46 @@ struct hostapd_data {
|
||||
int freq);
|
||||
void *public_action_cb_ctx;
|
||||
|
||||
int (*vendor_action_cb)(void *ctx, const u8 *buf, size_t len,
|
||||
int freq);
|
||||
void *vendor_action_cb_ctx;
|
||||
|
||||
void (*wps_reg_success_cb)(void *ctx, const u8 *mac_addr,
|
||||
const u8 *uuid_e);
|
||||
void *wps_reg_success_cb_ctx;
|
||||
|
||||
void (*wps_event_cb)(void *ctx, enum wps_event event,
|
||||
union wps_event_data *data);
|
||||
void *wps_event_cb_ctx;
|
||||
|
||||
void (*sta_authorized_cb)(void *ctx, const u8 *mac_addr,
|
||||
int authorized, const u8 *p2p_dev_addr);
|
||||
void *sta_authorized_cb_ctx;
|
||||
|
||||
void (*setup_complete_cb)(void *ctx);
|
||||
void *setup_complete_cb_ctx;
|
||||
|
||||
#ifdef CONFIG_P2P
|
||||
struct p2p_data *p2p;
|
||||
struct p2p_group *p2p_group;
|
||||
struct wpabuf *p2p_beacon_ie;
|
||||
struct wpabuf *p2p_probe_resp_ie;
|
||||
|
||||
/* Number of non-P2P association stations */
|
||||
int num_sta_no_p2p;
|
||||
|
||||
/* Periodic NoA (used only when no non-P2P clients in the group) */
|
||||
int noa_enabled;
|
||||
int noa_start;
|
||||
int noa_duration;
|
||||
#endif /* CONFIG_P2P */
|
||||
#ifdef CONFIG_INTERWORKING
|
||||
size_t gas_frag_limit;
|
||||
#endif /* CONFIG_INTERWORKING */
|
||||
|
||||
#ifdef CONFIG_SQLITE
|
||||
struct hostapd_eap_user tmp_eap_user;
|
||||
#endif /* CONFIG_SQLITE */
|
||||
};
|
||||
|
||||
|
||||
@ -189,8 +201,6 @@ struct hostapd_data {
|
||||
struct hostapd_iface {
|
||||
struct hapd_interfaces *interfaces;
|
||||
void *owner;
|
||||
int (*reload_config)(struct hostapd_iface *iface);
|
||||
struct hostapd_config * (*config_read_cb)(const char *config_fname);
|
||||
char *config_fname;
|
||||
struct hostapd_config *conf;
|
||||
|
||||
@ -202,6 +212,14 @@ struct hostapd_iface {
|
||||
struct ap_info *ap_hash[STA_HASH_SIZE];
|
||||
struct ap_info *ap_iter_list;
|
||||
|
||||
unsigned int drv_flags;
|
||||
|
||||
/*
|
||||
* A bitmap of supported protocols for probe response offload. See
|
||||
* struct wpa_driver_capa in driver.h
|
||||
*/
|
||||
unsigned int probe_resp_offloads;
|
||||
|
||||
struct hostapd_hw_modes *hw_features;
|
||||
int num_hw_features;
|
||||
struct hostapd_hw_modes *current_mode;
|
||||
@ -209,6 +227,7 @@ struct hostapd_iface {
|
||||
* current_mode->channels */
|
||||
int num_rates;
|
||||
struct hostapd_rate_data *current_rates;
|
||||
int *basic_rates;
|
||||
int freq;
|
||||
|
||||
u16 hw_flags;
|
||||
@ -239,16 +258,12 @@ struct hostapd_iface {
|
||||
|
||||
u16 ht_op_mode;
|
||||
void (*scan_cb)(struct hostapd_iface *iface);
|
||||
|
||||
int (*ctrl_iface_init)(struct hostapd_data *hapd);
|
||||
void (*ctrl_iface_deinit)(struct hostapd_data *hapd);
|
||||
|
||||
int (*for_each_interface)(struct hapd_interfaces *interfaces,
|
||||
int (*cb)(struct hostapd_iface *iface,
|
||||
void *ctx), void *ctx);
|
||||
};
|
||||
|
||||
/* hostapd.c */
|
||||
int hostapd_for_each_interface(struct hapd_interfaces *interfaces,
|
||||
int (*cb)(struct hostapd_iface *iface,
|
||||
void *ctx), void *ctx);
|
||||
int hostapd_reload_config(struct hostapd_iface *iface);
|
||||
struct hostapd_data *
|
||||
hostapd_alloc_bss_data(struct hostapd_iface *hapd_iface,
|
||||
@ -260,17 +275,35 @@ void hostapd_interface_deinit(struct hostapd_iface *iface);
|
||||
void hostapd_interface_free(struct hostapd_iface *iface);
|
||||
void hostapd_new_assoc_sta(struct hostapd_data *hapd, struct sta_info *sta,
|
||||
int reassoc);
|
||||
void hostapd_interface_deinit_free(struct hostapd_iface *iface);
|
||||
int hostapd_enable_iface(struct hostapd_iface *hapd_iface);
|
||||
int hostapd_reload_iface(struct hostapd_iface *hapd_iface);
|
||||
int hostapd_disable_iface(struct hostapd_iface *hapd_iface);
|
||||
int hostapd_add_iface(struct hapd_interfaces *ifaces, char *buf);
|
||||
int hostapd_remove_iface(struct hapd_interfaces *ifaces, char *buf);
|
||||
|
||||
/* utils.c */
|
||||
int hostapd_register_probereq_cb(struct hostapd_data *hapd,
|
||||
int (*cb)(void *ctx, const u8 *sa,
|
||||
const u8 *ie, size_t ie_len),
|
||||
const u8 *da, const u8 *bssid,
|
||||
const u8 *ie, size_t ie_len,
|
||||
int ssi_signal),
|
||||
void *ctx);
|
||||
void hostapd_prune_associations(struct hostapd_data *hapd, const u8 *addr);
|
||||
|
||||
/* drv_callbacks.c (TODO: move to somewhere else?) */
|
||||
int hostapd_notif_assoc(struct hostapd_data *hapd, const u8 *addr,
|
||||
const u8 *ie, size_t ielen);
|
||||
const u8 *ie, size_t ielen, int reassoc);
|
||||
void hostapd_notif_disassoc(struct hostapd_data *hapd, const u8 *addr);
|
||||
void hostapd_event_sta_low_ack(struct hostapd_data *hapd, const u8 *addr);
|
||||
int hostapd_probe_req_rx(struct hostapd_data *hapd, const u8 *sa, const u8 *da,
|
||||
const u8 *bssid, const u8 *ie, size_t ie_len,
|
||||
int ssi_signal);
|
||||
void hostapd_event_ch_switch(struct hostapd_data *hapd, int freq, int ht,
|
||||
int offset);
|
||||
|
||||
const struct hostapd_eap_user *
|
||||
hostapd_get_eap_user(struct hostapd_data *hapd, const u8 *identity,
|
||||
size_t identity_len, int phase2);
|
||||
|
||||
#endif /* HOSTAPD_H */
|
||||
|
31
contrib/wpa/src/ap/hs20.c
Normal file
31
contrib/wpa/src/ap/hs20.c
Normal file
@ -0,0 +1,31 @@
|
||||
/*
|
||||
* Hotspot 2.0 AP ANQP processing
|
||||
* Copyright (c) 2009, Atheros Communications, Inc.
|
||||
* Copyright (c) 2011-2012, Qualcomm Atheros, Inc.
|
||||
*
|
||||
* This software may be distributed under the terms of the BSD license.
|
||||
* See README for more details.
|
||||
*/
|
||||
|
||||
#include "includes.h"
|
||||
|
||||
#include "common.h"
|
||||
#include "common/ieee802_11_defs.h"
|
||||
#include "hostapd.h"
|
||||
#include "ap_config.h"
|
||||
#include "hs20.h"
|
||||
|
||||
|
||||
u8 * hostapd_eid_hs20_indication(struct hostapd_data *hapd, u8 *eid)
|
||||
{
|
||||
if (!hapd->conf->hs20)
|
||||
return eid;
|
||||
*eid++ = WLAN_EID_VENDOR_SPECIFIC;
|
||||
*eid++ = 5;
|
||||
WPA_PUT_BE24(eid, OUI_WFA);
|
||||
eid += 3;
|
||||
*eid++ = HS20_INDICATION_OUI_TYPE;
|
||||
/* Hotspot Configuration: DGAF Enabled */
|
||||
*eid++ = hapd->conf->disable_dgaf ? 0x01 : 0x00;
|
||||
return eid;
|
||||
}
|
16
contrib/wpa/src/ap/hs20.h
Normal file
16
contrib/wpa/src/ap/hs20.h
Normal file
@ -0,0 +1,16 @@
|
||||
/*
|
||||
* Hotspot 2.0 AP ANQP processing
|
||||
* Copyright (c) 2011-2012, Qualcomm Atheros, Inc.
|
||||
*
|
||||
* This software may be distributed under the terms of the BSD license.
|
||||
* See README for more details.
|
||||
*/
|
||||
|
||||
#ifndef HS20_H
|
||||
#define HS20_H
|
||||
|
||||
struct hostapd_data;
|
||||
|
||||
u8 * hostapd_eid_hs20_indication(struct hostapd_data *hapd, u8 *eid);
|
||||
|
||||
#endif /* HS20_H */
|
@ -2,7 +2,7 @@
|
||||
* hostapd / Hardware feature query and different modes
|
||||
* Copyright 2002-2003, Instant802 Networks, Inc.
|
||||
* Copyright 2005-2006, Devicescape Software, Inc.
|
||||
* Copyright (c) 2008-2009, Jouni Malinen <j@w1.fi>
|
||||
* Copyright (c) 2008-2012, Jouni Malinen <j@w1.fi>
|
||||
*
|
||||
* This program is free software; you can redistribute it and/or modify
|
||||
* it under the terms of the GNU General Public License version 2 as
|
||||
@ -101,8 +101,8 @@ int hostapd_get_hw_features(struct hostapd_iface *iface)
|
||||
}
|
||||
|
||||
|
||||
static int hostapd_prepare_rates(struct hostapd_data *hapd,
|
||||
struct hostapd_hw_modes *mode)
|
||||
int hostapd_prepare_rates(struct hostapd_iface *iface,
|
||||
struct hostapd_hw_modes *mode)
|
||||
{
|
||||
int i, num_basic_rates = 0;
|
||||
int basic_rates_a[] = { 60, 120, 240, -1 };
|
||||
@ -110,8 +110,8 @@ static int hostapd_prepare_rates(struct hostapd_data *hapd,
|
||||
int basic_rates_g[] = { 10, 20, 55, 110, -1 };
|
||||
int *basic_rates;
|
||||
|
||||
if (hapd->iconf->basic_rates)
|
||||
basic_rates = hapd->iconf->basic_rates;
|
||||
if (iface->conf->basic_rates)
|
||||
basic_rates = iface->conf->basic_rates;
|
||||
else switch (mode->mode) {
|
||||
case HOSTAPD_MODE_IEEE80211A:
|
||||
basic_rates = basic_rates_a;
|
||||
@ -122,22 +122,28 @@ static int hostapd_prepare_rates(struct hostapd_data *hapd,
|
||||
case HOSTAPD_MODE_IEEE80211G:
|
||||
basic_rates = basic_rates_g;
|
||||
break;
|
||||
case HOSTAPD_MODE_IEEE80211AD:
|
||||
return 0; /* No basic rates for 11ad */
|
||||
default:
|
||||
return -1;
|
||||
}
|
||||
|
||||
if (hostapd_set_rate_sets(hapd, hapd->iconf->supported_rates,
|
||||
basic_rates, mode->mode)) {
|
||||
wpa_printf(MSG_ERROR, "Failed to update rate sets in kernel "
|
||||
"module");
|
||||
}
|
||||
i = 0;
|
||||
while (basic_rates[i] >= 0)
|
||||
i++;
|
||||
if (i)
|
||||
i++; /* -1 termination */
|
||||
os_free(iface->basic_rates);
|
||||
iface->basic_rates = os_malloc(i * sizeof(int));
|
||||
if (iface->basic_rates)
|
||||
os_memcpy(iface->basic_rates, basic_rates, i * sizeof(int));
|
||||
|
||||
os_free(hapd->iface->current_rates);
|
||||
hapd->iface->num_rates = 0;
|
||||
os_free(iface->current_rates);
|
||||
iface->num_rates = 0;
|
||||
|
||||
hapd->iface->current_rates =
|
||||
os_zalloc(mode->num_rates * sizeof(struct hostapd_rate_data));
|
||||
if (!hapd->iface->current_rates) {
|
||||
iface->current_rates =
|
||||
os_calloc(mode->num_rates, sizeof(struct hostapd_rate_data));
|
||||
if (!iface->current_rates) {
|
||||
wpa_printf(MSG_ERROR, "Failed to allocate memory for rate "
|
||||
"table.");
|
||||
return -1;
|
||||
@ -146,26 +152,27 @@ static int hostapd_prepare_rates(struct hostapd_data *hapd,
|
||||
for (i = 0; i < mode->num_rates; i++) {
|
||||
struct hostapd_rate_data *rate;
|
||||
|
||||
if (hapd->iconf->supported_rates &&
|
||||
!hostapd_rate_found(hapd->iconf->supported_rates,
|
||||
if (iface->conf->supported_rates &&
|
||||
!hostapd_rate_found(iface->conf->supported_rates,
|
||||
mode->rates[i]))
|
||||
continue;
|
||||
|
||||
rate = &hapd->iface->current_rates[hapd->iface->num_rates];
|
||||
rate = &iface->current_rates[iface->num_rates];
|
||||
rate->rate = mode->rates[i];
|
||||
if (hostapd_rate_found(basic_rates, rate->rate)) {
|
||||
rate->flags |= HOSTAPD_RATE_BASIC;
|
||||
num_basic_rates++;
|
||||
}
|
||||
wpa_printf(MSG_DEBUG, "RATE[%d] rate=%d flags=0x%x",
|
||||
hapd->iface->num_rates, rate->rate, rate->flags);
|
||||
hapd->iface->num_rates++;
|
||||
iface->num_rates, rate->rate, rate->flags);
|
||||
iface->num_rates++;
|
||||
}
|
||||
|
||||
if (hapd->iface->num_rates == 0 || num_basic_rates == 0) {
|
||||
if ((iface->num_rates == 0 || num_basic_rates == 0) &&
|
||||
(!iface->conf->ieee80211n || !iface->conf->require_ht)) {
|
||||
wpa_printf(MSG_ERROR, "No rates remaining in supported/basic "
|
||||
"rate sets (%d,%d).",
|
||||
hapd->iface->num_rates, num_basic_rates);
|
||||
iface->num_rates, num_basic_rates);
|
||||
return -1;
|
||||
}
|
||||
|
||||
@ -265,11 +272,11 @@ static void ieee80211n_get_pri_sec_chan(struct wpa_scan_res *bss,
|
||||
oper = (struct ieee80211_ht_operation *) elems.ht_operation;
|
||||
*pri_chan = oper->control_chan;
|
||||
if (oper->ht_param & HT_INFO_HT_PARAM_REC_TRANS_CHNL_WIDTH) {
|
||||
if (oper->ht_param &
|
||||
HT_INFO_HT_PARAM_SECONDARY_CHNL_ABOVE)
|
||||
int sec = oper->ht_param &
|
||||
HT_INFO_HT_PARAM_SECONDARY_CHNL_OFF_MASK;
|
||||
if (sec == HT_INFO_HT_PARAM_SECONDARY_CHNL_ABOVE)
|
||||
*sec_chan = *pri_chan + 4;
|
||||
else if (oper->ht_param &
|
||||
HT_INFO_HT_PARAM_SECONDARY_CHNL_BELOW)
|
||||
else if (sec == HT_INFO_HT_PARAM_SECONDARY_CHNL_BELOW)
|
||||
*sec_chan = *pri_chan - 4;
|
||||
}
|
||||
}
|
||||
@ -406,27 +413,14 @@ static int ieee80211n_check_40mhz_2g4(struct hostapd_iface *iface,
|
||||
}
|
||||
|
||||
|
||||
static void wpa_scan_results_free(struct wpa_scan_results *res)
|
||||
{
|
||||
size_t i;
|
||||
|
||||
if (res == NULL)
|
||||
return;
|
||||
|
||||
for (i = 0; i < res->num; i++)
|
||||
os_free(res->res[i]);
|
||||
os_free(res->res);
|
||||
os_free(res);
|
||||
}
|
||||
|
||||
|
||||
static void ieee80211n_check_scan(struct hostapd_iface *iface)
|
||||
{
|
||||
struct wpa_scan_results *scan_res;
|
||||
int oper40;
|
||||
int res;
|
||||
|
||||
/* Check list of neighboring BSSes (from scan) to see whether 40 MHz is
|
||||
* allowed per IEEE 802.11n/D7.0, 11.14.3.2 */
|
||||
* allowed per IEEE Std 802.11-2012, 10.15.3.2 */
|
||||
|
||||
iface->scan_cb = NULL;
|
||||
|
||||
@ -452,7 +446,48 @@ static void ieee80211n_check_scan(struct hostapd_iface *iface)
|
||||
iface->conf->ht_capab &= ~HT_CAP_INFO_SUPP_CHANNEL_WIDTH_SET;
|
||||
}
|
||||
|
||||
hostapd_setup_interface_complete(iface, 0);
|
||||
res = ieee80211n_allowed_ht40_channel_pair(iface);
|
||||
hostapd_setup_interface_complete(iface, !res);
|
||||
}
|
||||
|
||||
|
||||
static void ieee80211n_scan_channels_2g4(struct hostapd_iface *iface,
|
||||
struct wpa_driver_scan_params *params)
|
||||
{
|
||||
/* Scan only the affected frequency range */
|
||||
int pri_freq, sec_freq;
|
||||
int affected_start, affected_end;
|
||||
int i, pos;
|
||||
struct hostapd_hw_modes *mode;
|
||||
|
||||
if (iface->current_mode == NULL)
|
||||
return;
|
||||
|
||||
pri_freq = hostapd_hw_get_freq(iface->bss[0], iface->conf->channel);
|
||||
if (iface->conf->secondary_channel > 0)
|
||||
sec_freq = pri_freq + 20;
|
||||
else
|
||||
sec_freq = pri_freq - 20;
|
||||
affected_start = (pri_freq + sec_freq) / 2 - 25;
|
||||
affected_end = (pri_freq + sec_freq) / 2 + 25;
|
||||
wpa_printf(MSG_DEBUG, "40 MHz affected channel range: [%d,%d] MHz",
|
||||
affected_start, affected_end);
|
||||
|
||||
mode = iface->current_mode;
|
||||
params->freqs = os_calloc(mode->num_channels + 1, sizeof(int));
|
||||
if (params->freqs == NULL)
|
||||
return;
|
||||
pos = 0;
|
||||
|
||||
for (i = 0; i < mode->num_channels; i++) {
|
||||
struct hostapd_channel_data *chan = &mode->channels[i];
|
||||
if (chan->flag & HOSTAPD_CHAN_DISABLED)
|
||||
continue;
|
||||
if (chan->freq < affected_start ||
|
||||
chan->freq > affected_end)
|
||||
continue;
|
||||
params->freqs[pos++] = chan->freq;
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
@ -466,12 +501,15 @@ static int ieee80211n_check_40mhz(struct hostapd_iface *iface)
|
||||
wpa_printf(MSG_DEBUG, "Scan for neighboring BSSes prior to enabling "
|
||||
"40 MHz channel");
|
||||
os_memset(¶ms, 0, sizeof(params));
|
||||
/* TODO: scan only the needed frequency */
|
||||
if (iface->current_mode->mode == HOSTAPD_MODE_IEEE80211G)
|
||||
ieee80211n_scan_channels_2g4(iface, ¶ms);
|
||||
if (hostapd_driver_scan(iface->bss[0], ¶ms) < 0) {
|
||||
wpa_printf(MSG_ERROR, "Failed to request a scan of "
|
||||
"neighboring BSSes");
|
||||
os_free(params.freqs);
|
||||
return -1;
|
||||
}
|
||||
os_free(params.freqs);
|
||||
|
||||
iface->scan_cb = ieee80211n_check_scan;
|
||||
return 1;
|
||||
@ -483,9 +521,6 @@ static int ieee80211n_supported_ht_capab(struct hostapd_iface *iface)
|
||||
u16 hw = iface->current_mode->ht_capab;
|
||||
u16 conf = iface->conf->ht_capab;
|
||||
|
||||
if (!iface->conf->ieee80211n)
|
||||
return 1;
|
||||
|
||||
if ((conf & HT_CAP_INFO_LDPC_CODING_CAP) &&
|
||||
!(hw & HT_CAP_INFO_LDPC_CODING_CAP)) {
|
||||
wpa_printf(MSG_ERROR, "Driver does not support configured "
|
||||
@ -585,13 +620,15 @@ int hostapd_check_ht_capab(struct hostapd_iface *iface)
|
||||
{
|
||||
#ifdef CONFIG_IEEE80211N
|
||||
int ret;
|
||||
if (!iface->conf->ieee80211n)
|
||||
return 0;
|
||||
if (!ieee80211n_supported_ht_capab(iface))
|
||||
return -1;
|
||||
ret = ieee80211n_check_40mhz(iface);
|
||||
if (ret)
|
||||
return ret;
|
||||
if (!ieee80211n_allowed_ht40_channel_pair(iface))
|
||||
return -1;
|
||||
if (!ieee80211n_supported_ht_capab(iface))
|
||||
return -1;
|
||||
#endif /* CONFIG_IEEE80211N */
|
||||
|
||||
return 0;
|
||||
@ -601,7 +638,7 @@ int hostapd_check_ht_capab(struct hostapd_iface *iface)
|
||||
/**
|
||||
* hostapd_select_hw_mode - Select the hardware mode
|
||||
* @iface: Pointer to interface data.
|
||||
* Returns: 0 on success, -1 on failure
|
||||
* Returns: 0 on success, < 0 on failure
|
||||
*
|
||||
* Sets up the hardware mode, channel, rates, and passive scanning
|
||||
* based on the configuration.
|
||||
@ -628,18 +665,58 @@ int hostapd_select_hw_mode(struct hostapd_iface *iface)
|
||||
hostapd_logger(iface->bss[0], NULL, HOSTAPD_MODULE_IEEE80211,
|
||||
HOSTAPD_LEVEL_WARNING,
|
||||
"Hardware does not support configured mode "
|
||||
"(%d)", (int) iface->conf->hw_mode);
|
||||
return -1;
|
||||
"(%d) (hw_mode in hostapd.conf)",
|
||||
(int) iface->conf->hw_mode);
|
||||
return -2;
|
||||
}
|
||||
|
||||
ok = 0;
|
||||
for (j = 0; j < iface->current_mode->num_channels; j++) {
|
||||
struct hostapd_channel_data *chan =
|
||||
&iface->current_mode->channels[j];
|
||||
if (!(chan->flag & HOSTAPD_CHAN_DISABLED) &&
|
||||
(chan->chan == iface->conf->channel)) {
|
||||
ok = 1;
|
||||
break;
|
||||
if (chan->chan == iface->conf->channel) {
|
||||
if (chan->flag & HOSTAPD_CHAN_DISABLED) {
|
||||
wpa_printf(MSG_ERROR,
|
||||
"channel [%i] (%i) is disabled for "
|
||||
"use in AP mode, flags: 0x%x%s%s%s",
|
||||
j, chan->chan, chan->flag,
|
||||
chan->flag & HOSTAPD_CHAN_NO_IBSS ?
|
||||
" NO-IBSS" : "",
|
||||
chan->flag &
|
||||
HOSTAPD_CHAN_PASSIVE_SCAN ?
|
||||
" PASSIVE-SCAN" : "",
|
||||
chan->flag & HOSTAPD_CHAN_RADAR ?
|
||||
" RADAR" : "");
|
||||
} else {
|
||||
ok = 1;
|
||||
break;
|
||||
}
|
||||
}
|
||||
}
|
||||
if (ok && iface->conf->secondary_channel) {
|
||||
int sec_ok = 0;
|
||||
int sec_chan = iface->conf->channel +
|
||||
iface->conf->secondary_channel * 4;
|
||||
for (j = 0; j < iface->current_mode->num_channels; j++) {
|
||||
struct hostapd_channel_data *chan =
|
||||
&iface->current_mode->channels[j];
|
||||
if (!(chan->flag & HOSTAPD_CHAN_DISABLED) &&
|
||||
(chan->chan == sec_chan)) {
|
||||
sec_ok = 1;
|
||||
break;
|
||||
}
|
||||
}
|
||||
if (!sec_ok) {
|
||||
hostapd_logger(iface->bss[0], NULL,
|
||||
HOSTAPD_MODULE_IEEE80211,
|
||||
HOSTAPD_LEVEL_WARNING,
|
||||
"Configured HT40 secondary channel "
|
||||
"(%d) not found from the channel list "
|
||||
"of current mode (%d) %s",
|
||||
sec_chan, iface->current_mode->mode,
|
||||
hostapd_hw_mode_txt(
|
||||
iface->current_mode->mode));
|
||||
ok = 0;
|
||||
}
|
||||
}
|
||||
if (iface->conf->channel == 0) {
|
||||
@ -647,7 +724,7 @@ int hostapd_select_hw_mode(struct hostapd_iface *iface)
|
||||
* the channel automatically */
|
||||
wpa_printf(MSG_ERROR, "Channel not configured "
|
||||
"(hw_mode/channel in hostapd.conf)");
|
||||
return -1;
|
||||
return -3;
|
||||
}
|
||||
if (ok == 0 && iface->conf->channel != 0) {
|
||||
hostapd_logger(iface->bss[0], NULL,
|
||||
@ -665,15 +742,7 @@ int hostapd_select_hw_mode(struct hostapd_iface *iface)
|
||||
hostapd_logger(iface->bss[0], NULL, HOSTAPD_MODULE_IEEE80211,
|
||||
HOSTAPD_LEVEL_WARNING,
|
||||
"Hardware does not support configured channel");
|
||||
return -1;
|
||||
}
|
||||
|
||||
if (hostapd_prepare_rates(iface->bss[0], iface->current_mode)) {
|
||||
wpa_printf(MSG_ERROR, "Failed to prepare rates table.");
|
||||
hostapd_logger(iface->bss[0], NULL, HOSTAPD_MODULE_IEEE80211,
|
||||
HOSTAPD_LEVEL_WARNING,
|
||||
"Failed to prepare rates table.");
|
||||
return -1;
|
||||
return -4;
|
||||
}
|
||||
|
||||
return 0;
|
||||
@ -689,6 +758,8 @@ const char * hostapd_hw_mode_txt(int mode)
|
||||
return "IEEE 802.11b";
|
||||
case HOSTAPD_MODE_IEEE80211G:
|
||||
return "IEEE 802.11g";
|
||||
case HOSTAPD_MODE_IEEE80211AD:
|
||||
return "IEEE 802.11ad";
|
||||
default:
|
||||
return "UNKNOWN";
|
||||
}
|
||||
|
@ -2,6 +2,7 @@
|
||||
* hostapd / Hardware feature query and different modes
|
||||
* Copyright 2002-2003, Instant802 Networks, Inc.
|
||||
* Copyright 2005-2006, Devicescape Software, Inc.
|
||||
* Copyright (c) 2008-2011, Jouni Malinen <j@w1.fi>
|
||||
*
|
||||
* This program is free software; you can redistribute it and/or modify
|
||||
* it under the terms of the GNU General Public License version 2 as
|
||||
@ -25,6 +26,8 @@ const char * hostapd_hw_mode_txt(int mode);
|
||||
int hostapd_hw_get_freq(struct hostapd_data *hapd, int chan);
|
||||
int hostapd_hw_get_channel(struct hostapd_data *hapd, int freq);
|
||||
int hostapd_check_ht_capab(struct hostapd_iface *iface);
|
||||
int hostapd_prepare_rates(struct hostapd_iface *iface,
|
||||
struct hostapd_hw_modes *mode);
|
||||
#else /* NEED_AP_MLME */
|
||||
static inline void
|
||||
hostapd_free_hw_features(struct hostapd_hw_modes *hw_features,
|
||||
@ -39,7 +42,7 @@ static inline int hostapd_get_hw_features(struct hostapd_iface *iface)
|
||||
|
||||
static inline int hostapd_select_hw_mode(struct hostapd_iface *iface)
|
||||
{
|
||||
return -1;
|
||||
return -100;
|
||||
}
|
||||
|
||||
static inline const char * hostapd_hw_mode_txt(int mode)
|
||||
@ -57,6 +60,12 @@ static inline int hostapd_check_ht_capab(struct hostapd_iface *iface)
|
||||
return 0;
|
||||
}
|
||||
|
||||
static inline int hostapd_prepare_rates(struct hostapd_iface *iface,
|
||||
struct hostapd_hw_modes *mode)
|
||||
{
|
||||
return 0;
|
||||
}
|
||||
|
||||
#endif /* NEED_AP_MLME */
|
||||
|
||||
#endif /* HW_FEATURES_H */
|
||||
|
@ -2,14 +2,8 @@
|
||||
* hostapd / IEEE 802.11F-2003 Inter-Access Point Protocol (IAPP)
|
||||
* Copyright (c) 2002-2007, Jouni Malinen <j@w1.fi>
|
||||
*
|
||||
* This program is free software; you can redistribute it and/or modify
|
||||
* it under the terms of the GNU General Public License version 2 as
|
||||
* published by the Free Software Foundation.
|
||||
*
|
||||
* Alternatively, this software may be distributed under the terms of BSD
|
||||
* license.
|
||||
*
|
||||
* See README and COPYING for more details.
|
||||
* This software may be distributed under the terms of the BSD license.
|
||||
* See README for more details.
|
||||
*
|
||||
* Note: IEEE 802.11F-2003 was a experimental use specification. It has expired
|
||||
* and IEEE has withdrawn it. In other words, it is likely better to look at
|
||||
|
@ -2,14 +2,8 @@
|
||||
* hostapd / IEEE 802.11F-2003 Inter-Access Point Protocol (IAPP)
|
||||
* Copyright (c) 2002-2005, Jouni Malinen <j@w1.fi>
|
||||
*
|
||||
* This program is free software; you can redistribute it and/or modify
|
||||
* it under the terms of the GNU General Public License version 2 as
|
||||
* published by the Free Software Foundation.
|
||||
*
|
||||
* Alternatively, this software may be distributed under the terms of BSD
|
||||
* license.
|
||||
*
|
||||
* See README and COPYING for more details.
|
||||
* This software may be distributed under the terms of the BSD license.
|
||||
* See README for more details.
|
||||
*/
|
||||
|
||||
#ifndef IAPP_H
|
||||
|
File diff suppressed because it is too large
Load Diff
@ -2,14 +2,8 @@
|
||||
* hostapd / IEEE 802.11 Management
|
||||
* Copyright (c) 2002-2009, Jouni Malinen <j@w1.fi>
|
||||
*
|
||||
* This program is free software; you can redistribute it and/or modify
|
||||
* it under the terms of the GNU General Public License version 2 as
|
||||
* published by the Free Software Foundation.
|
||||
*
|
||||
* Alternatively, this software may be distributed under the terms of BSD
|
||||
* license.
|
||||
*
|
||||
* See README and COPYING for more details.
|
||||
* This software may be distributed under the terms of the BSD license.
|
||||
* See README for more details.
|
||||
*/
|
||||
|
||||
#ifndef IEEE802_11_H
|
||||
@ -46,22 +40,42 @@ static inline int ieee802_11_get_mib_sta(struct hostapd_data *hapd,
|
||||
#endif /* NEED_AP_MLME */
|
||||
u16 hostapd_own_capab_info(struct hostapd_data *hapd, struct sta_info *sta,
|
||||
int probe);
|
||||
u8 * hostapd_eid_ext_capab(struct hostapd_data *hapd, u8 *eid);
|
||||
u8 * hostapd_eid_supp_rates(struct hostapd_data *hapd, u8 *eid);
|
||||
u8 * hostapd_eid_ext_supp_rates(struct hostapd_data *hapd, u8 *eid);
|
||||
u8 * hostapd_eid_ht_capabilities(struct hostapd_data *hapd, u8 *eid);
|
||||
u8 * hostapd_eid_ht_operation(struct hostapd_data *hapd, u8 *eid);
|
||||
u8 * hostapd_eid_vht_capabilities(struct hostapd_data *hapd, u8 *eid);
|
||||
u8 * hostapd_eid_vht_operation(struct hostapd_data *hapd, u8 *eid);
|
||||
int hostapd_ht_operation_update(struct hostapd_iface *iface);
|
||||
void ieee802_11_send_sa_query_req(struct hostapd_data *hapd,
|
||||
const u8 *addr, const u8 *trans_id);
|
||||
void hostapd_get_ht_capab(struct hostapd_data *hapd,
|
||||
struct ieee80211_ht_capabilities *ht_cap,
|
||||
struct ieee80211_ht_capabilities *neg_ht_cap);
|
||||
u16 copy_sta_ht_capab(struct sta_info *sta, const u8 *ht_capab,
|
||||
size_t ht_capab_len);
|
||||
u16 copy_sta_ht_capab(struct hostapd_data *hapd, struct sta_info *sta,
|
||||
const u8 *ht_capab, size_t ht_capab_len);
|
||||
void update_ht_state(struct hostapd_data *hapd, struct sta_info *sta);
|
||||
u16 copy_sta_vht_capab(struct hostapd_data *hapd, struct sta_info *sta,
|
||||
const u8 *vht_capab, size_t vht_capab_len);
|
||||
void hostapd_tx_status(struct hostapd_data *hapd, const u8 *addr,
|
||||
const u8 *buf, size_t len, int ack);
|
||||
void hostapd_eapol_tx_status(struct hostapd_data *hapd, const u8 *dst,
|
||||
const u8 *data, size_t len, int ack);
|
||||
void ieee802_11_rx_from_unknown(struct hostapd_data *hapd, const u8 *src,
|
||||
int wds);
|
||||
u8 * hostapd_eid_assoc_comeback_time(struct hostapd_data *hapd,
|
||||
struct sta_info *sta, u8 *eid);
|
||||
void ieee802_11_sa_query_action(struct hostapd_data *hapd,
|
||||
const u8 *sa, const u8 action_type,
|
||||
const u8 *trans_id);
|
||||
u8 * hostapd_eid_interworking(struct hostapd_data *hapd, u8 *eid);
|
||||
u8 * hostapd_eid_adv_proto(struct hostapd_data *hapd, u8 *eid);
|
||||
u8 * hostapd_eid_roaming_consortium(struct hostapd_data *hapd, u8 *eid);
|
||||
u8 * hostapd_eid_time_adv(struct hostapd_data *hapd, u8 *eid);
|
||||
u8 * hostapd_eid_time_zone(struct hostapd_data *hapd, u8 *eid);
|
||||
int hostapd_update_time_adv(struct hostapd_data *hapd);
|
||||
void hostapd_client_poll_ok(struct hostapd_data *hapd, const u8 *addr);
|
||||
u8 * hostapd_eid_bss_max_idle_period(struct hostapd_data *hapd, u8 *eid);
|
||||
|
||||
#endif /* IEEE802_11_H */
|
||||
|
@ -1,15 +1,9 @@
|
||||
/*
|
||||
* hostapd / IEEE 802.11 authentication (ACL)
|
||||
* Copyright (c) 2003-2009, Jouni Malinen <j@w1.fi>
|
||||
* Copyright (c) 2003-2012, Jouni Malinen <j@w1.fi>
|
||||
*
|
||||
* This program is free software; you can redistribute it and/or modify
|
||||
* it under the terms of the GNU General Public License version 2 as
|
||||
* published by the Free Software Foundation.
|
||||
*
|
||||
* Alternatively, this software may be distributed under the terms of BSD
|
||||
* license.
|
||||
*
|
||||
* See README and COPYING for more details.
|
||||
* This software may be distributed under the terms of the BSD license.
|
||||
* See README for more details.
|
||||
*
|
||||
* Access control list for IEEE 802.11 authentication can uses statically
|
||||
* configured ACL from configuration files or an external RADIUS server.
|
||||
@ -21,29 +15,35 @@
|
||||
|
||||
#include "utils/common.h"
|
||||
#include "utils/eloop.h"
|
||||
#include "crypto/sha1.h"
|
||||
#include "radius/radius.h"
|
||||
#include "radius/radius_client.h"
|
||||
#include "hostapd.h"
|
||||
#include "ap_config.h"
|
||||
#include "ap_drv_ops.h"
|
||||
#include "ieee802_11.h"
|
||||
#include "ieee802_1x.h"
|
||||
#include "ieee802_11_auth.h"
|
||||
|
||||
#define RADIUS_ACL_TIMEOUT 30
|
||||
|
||||
|
||||
struct hostapd_cached_radius_acl {
|
||||
time_t timestamp;
|
||||
os_time_t timestamp;
|
||||
macaddr addr;
|
||||
int accepted; /* HOSTAPD_ACL_* */
|
||||
struct hostapd_cached_radius_acl *next;
|
||||
u32 session_timeout;
|
||||
u32 acct_interim_interval;
|
||||
int vlan_id;
|
||||
struct hostapd_sta_wpa_psk_short *psk;
|
||||
char *identity;
|
||||
char *radius_cui;
|
||||
};
|
||||
|
||||
|
||||
struct hostapd_acl_query_data {
|
||||
time_t timestamp;
|
||||
os_time_t timestamp;
|
||||
u8 radius_id;
|
||||
macaddr addr;
|
||||
u8 *auth_msg; /* IEEE 802.11 authentication frame from station */
|
||||
@ -53,6 +53,15 @@ struct hostapd_acl_query_data {
|
||||
|
||||
|
||||
#ifndef CONFIG_NO_RADIUS
|
||||
static void hostapd_acl_cache_free_entry(struct hostapd_cached_radius_acl *e)
|
||||
{
|
||||
os_free(e->identity);
|
||||
os_free(e->radius_cui);
|
||||
hostapd_free_psk_list(e->psk);
|
||||
os_free(e);
|
||||
}
|
||||
|
||||
|
||||
static void hostapd_acl_cache_free(struct hostapd_cached_radius_acl *acl_cache)
|
||||
{
|
||||
struct hostapd_cached_radius_acl *prev;
|
||||
@ -60,38 +69,73 @@ static void hostapd_acl_cache_free(struct hostapd_cached_radius_acl *acl_cache)
|
||||
while (acl_cache) {
|
||||
prev = acl_cache;
|
||||
acl_cache = acl_cache->next;
|
||||
os_free(prev);
|
||||
hostapd_acl_cache_free_entry(prev);
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
static void copy_psk_list(struct hostapd_sta_wpa_psk_short **psk,
|
||||
struct hostapd_sta_wpa_psk_short *src)
|
||||
{
|
||||
struct hostapd_sta_wpa_psk_short **copy_to;
|
||||
struct hostapd_sta_wpa_psk_short *copy_from;
|
||||
|
||||
/* Copy PSK linked list */
|
||||
copy_to = psk;
|
||||
copy_from = src;
|
||||
while (copy_from && copy_to) {
|
||||
*copy_to = os_zalloc(sizeof(struct hostapd_sta_wpa_psk_short));
|
||||
if (*copy_to == NULL)
|
||||
break;
|
||||
os_memcpy(*copy_to, copy_from,
|
||||
sizeof(struct hostapd_sta_wpa_psk_short));
|
||||
copy_from = copy_from->next;
|
||||
copy_to = &((*copy_to)->next);
|
||||
}
|
||||
if (copy_to)
|
||||
*copy_to = NULL;
|
||||
}
|
||||
|
||||
|
||||
static int hostapd_acl_cache_get(struct hostapd_data *hapd, const u8 *addr,
|
||||
u32 *session_timeout,
|
||||
u32 *acct_interim_interval, int *vlan_id)
|
||||
u32 *acct_interim_interval, int *vlan_id,
|
||||
struct hostapd_sta_wpa_psk_short **psk,
|
||||
char **identity, char **radius_cui)
|
||||
{
|
||||
struct hostapd_cached_radius_acl *entry;
|
||||
time_t now;
|
||||
struct os_time now;
|
||||
|
||||
time(&now);
|
||||
entry = hapd->acl_cache;
|
||||
os_get_time(&now);
|
||||
|
||||
while (entry) {
|
||||
if (os_memcmp(entry->addr, addr, ETH_ALEN) == 0) {
|
||||
if (now - entry->timestamp > RADIUS_ACL_TIMEOUT)
|
||||
return -1; /* entry has expired */
|
||||
if (entry->accepted == HOSTAPD_ACL_ACCEPT_TIMEOUT)
|
||||
if (session_timeout)
|
||||
*session_timeout =
|
||||
entry->session_timeout;
|
||||
if (acct_interim_interval)
|
||||
*acct_interim_interval =
|
||||
entry->acct_interim_interval;
|
||||
if (vlan_id)
|
||||
*vlan_id = entry->vlan_id;
|
||||
return entry->accepted;
|
||||
for (entry = hapd->acl_cache; entry; entry = entry->next) {
|
||||
if (os_memcmp(entry->addr, addr, ETH_ALEN) != 0)
|
||||
continue;
|
||||
|
||||
if (now.sec - entry->timestamp > RADIUS_ACL_TIMEOUT)
|
||||
return -1; /* entry has expired */
|
||||
if (entry->accepted == HOSTAPD_ACL_ACCEPT_TIMEOUT)
|
||||
if (session_timeout)
|
||||
*session_timeout = entry->session_timeout;
|
||||
if (acct_interim_interval)
|
||||
*acct_interim_interval =
|
||||
entry->acct_interim_interval;
|
||||
if (vlan_id)
|
||||
*vlan_id = entry->vlan_id;
|
||||
copy_psk_list(psk, entry->psk);
|
||||
if (identity) {
|
||||
if (entry->identity)
|
||||
*identity = os_strdup(entry->identity);
|
||||
else
|
||||
*identity = NULL;
|
||||
}
|
||||
|
||||
entry = entry->next;
|
||||
if (radius_cui) {
|
||||
if (entry->radius_cui)
|
||||
*radius_cui = os_strdup(entry->radius_cui);
|
||||
else
|
||||
*radius_cui = NULL;
|
||||
}
|
||||
return entry->accepted;
|
||||
}
|
||||
|
||||
return -1;
|
||||
@ -137,37 +181,9 @@ static int hostapd_radius_acl_query(struct hostapd_data *hapd, const u8 *addr,
|
||||
goto fail;
|
||||
}
|
||||
|
||||
if (hapd->conf->own_ip_addr.af == AF_INET &&
|
||||
!radius_msg_add_attr(msg, RADIUS_ATTR_NAS_IP_ADDRESS,
|
||||
(u8 *) &hapd->conf->own_ip_addr.u.v4, 4)) {
|
||||
wpa_printf(MSG_DEBUG, "Could not add NAS-IP-Address");
|
||||
if (add_common_radius_attr(hapd, hapd->conf->radius_auth_req_attr,
|
||||
NULL, msg) < 0)
|
||||
goto fail;
|
||||
}
|
||||
|
||||
#ifdef CONFIG_IPV6
|
||||
if (hapd->conf->own_ip_addr.af == AF_INET6 &&
|
||||
!radius_msg_add_attr(msg, RADIUS_ATTR_NAS_IPV6_ADDRESS,
|
||||
(u8 *) &hapd->conf->own_ip_addr.u.v6, 16)) {
|
||||
wpa_printf(MSG_DEBUG, "Could not add NAS-IPv6-Address");
|
||||
goto fail;
|
||||
}
|
||||
#endif /* CONFIG_IPV6 */
|
||||
|
||||
if (hapd->conf->nas_identifier &&
|
||||
!radius_msg_add_attr(msg, RADIUS_ATTR_NAS_IDENTIFIER,
|
||||
(u8 *) hapd->conf->nas_identifier,
|
||||
os_strlen(hapd->conf->nas_identifier))) {
|
||||
wpa_printf(MSG_DEBUG, "Could not add NAS-Identifier");
|
||||
goto fail;
|
||||
}
|
||||
|
||||
os_snprintf(buf, sizeof(buf), RADIUS_802_1X_ADDR_FORMAT ":%s",
|
||||
MAC2STR(hapd->own_addr), hapd->conf->ssid.ssid);
|
||||
if (!radius_msg_add_attr(msg, RADIUS_ATTR_CALLED_STATION_ID,
|
||||
(u8 *) buf, os_strlen(buf))) {
|
||||
wpa_printf(MSG_DEBUG, "Could not add Called-Station-Id");
|
||||
goto fail;
|
||||
}
|
||||
|
||||
os_snprintf(buf, sizeof(buf), RADIUS_802_1X_ADDR_FORMAT,
|
||||
MAC2STR(addr));
|
||||
@ -177,12 +193,6 @@ static int hostapd_radius_acl_query(struct hostapd_data *hapd, const u8 *addr,
|
||||
goto fail;
|
||||
}
|
||||
|
||||
if (!radius_msg_add_attr_int32(msg, RADIUS_ATTR_NAS_PORT_TYPE,
|
||||
RADIUS_NAS_PORT_TYPE_IEEE_802_11)) {
|
||||
wpa_printf(MSG_DEBUG, "Could not add NAS-Port-Type");
|
||||
goto fail;
|
||||
}
|
||||
|
||||
os_snprintf(buf, sizeof(buf), "CONNECT 11Mbps 802.11b");
|
||||
if (!radius_msg_add_attr(msg, RADIUS_ATTR_CONNECT_INFO,
|
||||
(u8 *) buf, os_strlen(buf))) {
|
||||
@ -190,7 +200,8 @@ static int hostapd_radius_acl_query(struct hostapd_data *hapd, const u8 *addr,
|
||||
goto fail;
|
||||
}
|
||||
|
||||
radius_client_send(hapd->radius, msg, RADIUS_AUTH, addr);
|
||||
if (radius_client_send(hapd->radius, msg, RADIUS_AUTH, addr) < 0)
|
||||
goto fail;
|
||||
return 0;
|
||||
|
||||
fail:
|
||||
@ -209,11 +220,19 @@ static int hostapd_radius_acl_query(struct hostapd_data *hapd, const u8 *addr,
|
||||
* @session_timeout: Buffer for returning session timeout (from RADIUS)
|
||||
* @acct_interim_interval: Buffer for returning account interval (from RADIUS)
|
||||
* @vlan_id: Buffer for returning VLAN ID
|
||||
* @psk: Linked list buffer for returning WPA PSK
|
||||
* @identity: Buffer for returning identity (from RADIUS)
|
||||
* @radius_cui: Buffer for returning CUI (from RADIUS)
|
||||
* Returns: HOSTAPD_ACL_ACCEPT, HOSTAPD_ACL_REJECT, or HOSTAPD_ACL_PENDING
|
||||
*
|
||||
* The caller is responsible for freeing the returned *identity and *radius_cui
|
||||
* values with os_free().
|
||||
*/
|
||||
int hostapd_allowed_address(struct hostapd_data *hapd, const u8 *addr,
|
||||
const u8 *msg, size_t len, u32 *session_timeout,
|
||||
u32 *acct_interim_interval, int *vlan_id)
|
||||
u32 *acct_interim_interval, int *vlan_id,
|
||||
struct hostapd_sta_wpa_psk_short **psk,
|
||||
char **identity, char **radius_cui)
|
||||
{
|
||||
if (session_timeout)
|
||||
*session_timeout = 0;
|
||||
@ -221,6 +240,12 @@ int hostapd_allowed_address(struct hostapd_data *hapd, const u8 *addr,
|
||||
*acct_interim_interval = 0;
|
||||
if (vlan_id)
|
||||
*vlan_id = 0;
|
||||
if (psk)
|
||||
*psk = NULL;
|
||||
if (identity)
|
||||
*identity = NULL;
|
||||
if (radius_cui)
|
||||
*radius_cui = NULL;
|
||||
|
||||
if (hostapd_maclist_found(hapd->conf->accept_mac,
|
||||
hapd->conf->num_accept_mac, addr, vlan_id))
|
||||
@ -240,11 +265,13 @@ int hostapd_allowed_address(struct hostapd_data *hapd, const u8 *addr,
|
||||
return HOSTAPD_ACL_REJECT;
|
||||
#else /* CONFIG_NO_RADIUS */
|
||||
struct hostapd_acl_query_data *query;
|
||||
struct os_time t;
|
||||
|
||||
/* Check whether ACL cache has an entry for this station */
|
||||
int res = hostapd_acl_cache_get(hapd, addr, session_timeout,
|
||||
acct_interim_interval,
|
||||
vlan_id);
|
||||
vlan_id, psk,
|
||||
identity, radius_cui);
|
||||
if (res == HOSTAPD_ACL_ACCEPT ||
|
||||
res == HOSTAPD_ACL_ACCEPT_TIMEOUT)
|
||||
return res;
|
||||
@ -256,6 +283,14 @@ int hostapd_allowed_address(struct hostapd_data *hapd, const u8 *addr,
|
||||
if (os_memcmp(query->addr, addr, ETH_ALEN) == 0) {
|
||||
/* pending query in RADIUS retransmit queue;
|
||||
* do not generate a new one */
|
||||
if (identity) {
|
||||
os_free(*identity);
|
||||
*identity = NULL;
|
||||
}
|
||||
if (radius_cui) {
|
||||
os_free(*radius_cui);
|
||||
*radius_cui = NULL;
|
||||
}
|
||||
return HOSTAPD_ACL_PENDING;
|
||||
}
|
||||
query = query->next;
|
||||
@ -270,7 +305,8 @@ int hostapd_allowed_address(struct hostapd_data *hapd, const u8 *addr,
|
||||
wpa_printf(MSG_ERROR, "malloc for query data failed");
|
||||
return HOSTAPD_ACL_REJECT;
|
||||
}
|
||||
time(&query->timestamp);
|
||||
os_get_time(&t);
|
||||
query->timestamp = t.sec;
|
||||
os_memcpy(query->addr, addr, ETH_ALEN);
|
||||
if (hostapd_radius_acl_query(hapd, addr, query)) {
|
||||
wpa_printf(MSG_DEBUG, "Failed to send Access-Request "
|
||||
@ -302,7 +338,7 @@ int hostapd_allowed_address(struct hostapd_data *hapd, const u8 *addr,
|
||||
|
||||
|
||||
#ifndef CONFIG_NO_RADIUS
|
||||
static void hostapd_acl_expire_cache(struct hostapd_data *hapd, time_t now)
|
||||
static void hostapd_acl_expire_cache(struct hostapd_data *hapd, os_time_t now)
|
||||
{
|
||||
struct hostapd_cached_radius_acl *prev, *entry, *tmp;
|
||||
|
||||
@ -317,12 +353,10 @@ static void hostapd_acl_expire_cache(struct hostapd_data *hapd, time_t now)
|
||||
prev->next = entry->next;
|
||||
else
|
||||
hapd->acl_cache = entry->next;
|
||||
#ifdef CONFIG_DRIVER_RADIUS_ACL
|
||||
hapd->drv.set_radius_acl_expire(hapd, entry->addr);
|
||||
#endif /* CONFIG_DRIVER_RADIUS_ACL */
|
||||
hostapd_drv_set_radius_acl_expire(hapd, entry->addr);
|
||||
tmp = entry;
|
||||
entry = entry->next;
|
||||
os_free(tmp);
|
||||
hostapd_acl_cache_free_entry(tmp);
|
||||
continue;
|
||||
}
|
||||
|
||||
@ -332,7 +366,8 @@ static void hostapd_acl_expire_cache(struct hostapd_data *hapd, time_t now)
|
||||
}
|
||||
|
||||
|
||||
static void hostapd_acl_expire_queries(struct hostapd_data *hapd, time_t now)
|
||||
static void hostapd_acl_expire_queries(struct hostapd_data *hapd,
|
||||
os_time_t now)
|
||||
{
|
||||
struct hostapd_acl_query_data *prev, *entry, *tmp;
|
||||
|
||||
@ -368,16 +403,64 @@ static void hostapd_acl_expire_queries(struct hostapd_data *hapd, time_t now)
|
||||
static void hostapd_acl_expire(void *eloop_ctx, void *timeout_ctx)
|
||||
{
|
||||
struct hostapd_data *hapd = eloop_ctx;
|
||||
time_t now;
|
||||
struct os_time now;
|
||||
|
||||
time(&now);
|
||||
hostapd_acl_expire_cache(hapd, now);
|
||||
hostapd_acl_expire_queries(hapd, now);
|
||||
os_get_time(&now);
|
||||
hostapd_acl_expire_cache(hapd, now.sec);
|
||||
hostapd_acl_expire_queries(hapd, now.sec);
|
||||
|
||||
eloop_register_timeout(10, 0, hostapd_acl_expire, hapd, NULL);
|
||||
}
|
||||
|
||||
|
||||
static void decode_tunnel_passwords(struct hostapd_data *hapd,
|
||||
const u8 *shared_secret,
|
||||
size_t shared_secret_len,
|
||||
struct radius_msg *msg,
|
||||
struct radius_msg *req,
|
||||
struct hostapd_cached_radius_acl *cache)
|
||||
{
|
||||
int passphraselen;
|
||||
char *passphrase, *strpassphrase;
|
||||
size_t i;
|
||||
struct hostapd_sta_wpa_psk_short *psk;
|
||||
|
||||
/*
|
||||
* Decode all tunnel passwords as PSK and save them into a linked list.
|
||||
*/
|
||||
for (i = 0; ; i++) {
|
||||
passphrase = radius_msg_get_tunnel_password(
|
||||
msg, &passphraselen, shared_secret, shared_secret_len,
|
||||
req, i);
|
||||
/*
|
||||
* Passphrase is NULL iff there is no i-th Tunnel-Password
|
||||
* attribute in msg.
|
||||
*/
|
||||
if (passphrase == NULL)
|
||||
break;
|
||||
/*
|
||||
* passphrase does not contain the NULL termination.
|
||||
* Add it here as pbkdf2_sha1() requires it.
|
||||
*/
|
||||
strpassphrase = os_zalloc(passphraselen + 1);
|
||||
psk = os_zalloc(sizeof(struct hostapd_sta_wpa_psk_short));
|
||||
if (strpassphrase && psk) {
|
||||
os_memcpy(strpassphrase, passphrase, passphraselen);
|
||||
pbkdf2_sha1(strpassphrase,
|
||||
hapd->conf->ssid.ssid,
|
||||
hapd->conf->ssid.ssid_len, 4096,
|
||||
psk->psk, PMK_LEN);
|
||||
psk->next = cache->psk;
|
||||
cache->psk = psk;
|
||||
psk = NULL;
|
||||
}
|
||||
os_free(strpassphrase);
|
||||
os_free(psk);
|
||||
os_free(passphrase);
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
/**
|
||||
* hostapd_acl_recv_radius - Process incoming RADIUS Authentication messages
|
||||
* @msg: RADIUS response message
|
||||
@ -397,6 +480,7 @@ hostapd_acl_recv_radius(struct radius_msg *msg, struct radius_msg *req,
|
||||
struct hostapd_acl_query_data *query, *prev;
|
||||
struct hostapd_cached_radius_acl *cache;
|
||||
struct radius_hdr *hdr = radius_msg_get_hdr(msg);
|
||||
struct os_time t;
|
||||
|
||||
query = hapd->acl_queries;
|
||||
prev = NULL;
|
||||
@ -431,9 +515,13 @@ hostapd_acl_recv_radius(struct radius_msg *msg, struct radius_msg *req,
|
||||
wpa_printf(MSG_DEBUG, "Failed to add ACL cache entry");
|
||||
goto done;
|
||||
}
|
||||
time(&cache->timestamp);
|
||||
os_get_time(&t);
|
||||
cache->timestamp = t.sec;
|
||||
os_memcpy(cache->addr, query->addr, sizeof(cache->addr));
|
||||
if (hdr->code == RADIUS_CODE_ACCESS_ACCEPT) {
|
||||
u8 *buf;
|
||||
size_t len;
|
||||
|
||||
if (radius_msg_get_attr_int32(msg, RADIUS_ATTR_SESSION_TIMEOUT,
|
||||
&cache->session_timeout) == 0)
|
||||
cache->accepted = HOSTAPD_ACL_ACCEPT_TIMEOUT;
|
||||
@ -452,14 +540,35 @@ hostapd_acl_recv_radius(struct radius_msg *msg, struct radius_msg *req,
|
||||
}
|
||||
|
||||
cache->vlan_id = radius_msg_get_vlanid(msg);
|
||||
|
||||
decode_tunnel_passwords(hapd, shared_secret, shared_secret_len,
|
||||
msg, req, cache);
|
||||
|
||||
if (radius_msg_get_attr_ptr(msg, RADIUS_ATTR_USER_NAME,
|
||||
&buf, &len, NULL) == 0) {
|
||||
cache->identity = os_zalloc(len + 1);
|
||||
if (cache->identity)
|
||||
os_memcpy(cache->identity, buf, len);
|
||||
}
|
||||
if (radius_msg_get_attr_ptr(
|
||||
msg, RADIUS_ATTR_CHARGEABLE_USER_IDENTITY,
|
||||
&buf, &len, NULL) == 0) {
|
||||
cache->radius_cui = os_zalloc(len + 1);
|
||||
if (cache->radius_cui)
|
||||
os_memcpy(cache->radius_cui, buf, len);
|
||||
}
|
||||
|
||||
if (hapd->conf->wpa_psk_radius == PSK_RADIUS_REQUIRED &&
|
||||
!cache->psk)
|
||||
cache->accepted = HOSTAPD_ACL_REJECT;
|
||||
} else
|
||||
cache->accepted = HOSTAPD_ACL_REJECT;
|
||||
cache->next = hapd->acl_cache;
|
||||
hapd->acl_cache = cache;
|
||||
|
||||
#ifdef CONFIG_DRIVER_RADIUS_ACL
|
||||
hapd->drv.set_radius_acl_auth(hapd, query->addr, cache->accepted,
|
||||
cache->session_timeout);
|
||||
hostapd_drv_set_radius_acl_auth(hapd, query->addr, cache->accepted,
|
||||
cache->session_timeout);
|
||||
#else /* CONFIG_DRIVER_RADIUS_ACL */
|
||||
#ifdef NEED_AP_MLME
|
||||
/* Re-send original authentication frame for 802.11 processing */
|
||||
@ -522,3 +631,13 @@ void hostapd_acl_deinit(struct hostapd_data *hapd)
|
||||
hostapd_acl_query_free(prev);
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
void hostapd_free_psk_list(struct hostapd_sta_wpa_psk_short *psk)
|
||||
{
|
||||
while (psk) {
|
||||
struct hostapd_sta_wpa_psk_short *prev = psk;
|
||||
psk = psk->next;
|
||||
os_free(prev);
|
||||
}
|
||||
}
|
||||
|
@ -2,14 +2,8 @@
|
||||
* hostapd / IEEE 802.11 authentication (ACL)
|
||||
* Copyright (c) 2003-2005, Jouni Malinen <j@w1.fi>
|
||||
*
|
||||
* This program is free software; you can redistribute it and/or modify
|
||||
* it under the terms of the GNU General Public License version 2 as
|
||||
* published by the Free Software Foundation.
|
||||
*
|
||||
* Alternatively, this software may be distributed under the terms of BSD
|
||||
* license.
|
||||
*
|
||||
* See README and COPYING for more details.
|
||||
* This software may be distributed under the terms of the BSD license.
|
||||
* See README for more details.
|
||||
*/
|
||||
|
||||
#ifndef IEEE802_11_AUTH_H
|
||||
@ -24,8 +18,11 @@ enum {
|
||||
|
||||
int hostapd_allowed_address(struct hostapd_data *hapd, const u8 *addr,
|
||||
const u8 *msg, size_t len, u32 *session_timeout,
|
||||
u32 *acct_interim_interval, int *vlan_id);
|
||||
u32 *acct_interim_interval, int *vlan_id,
|
||||
struct hostapd_sta_wpa_psk_short **psk,
|
||||
char **identity, char **radius_cui);
|
||||
int hostapd_acl_init(struct hostapd_data *hapd);
|
||||
void hostapd_acl_deinit(struct hostapd_data *hapd);
|
||||
void hostapd_free_psk_list(struct hostapd_sta_wpa_psk_short *psk);
|
||||
|
||||
#endif /* IEEE802_11_AUTH_H */
|
||||
|
@ -30,7 +30,8 @@ u8 * hostapd_eid_ht_capabilities(struct hostapd_data *hapd, u8 *eid)
|
||||
struct ieee80211_ht_capabilities *cap;
|
||||
u8 *pos = eid;
|
||||
|
||||
if (!hapd->iconf->ieee80211n || !hapd->iface->current_mode)
|
||||
if (!hapd->iconf->ieee80211n || !hapd->iface->current_mode ||
|
||||
hapd->conf->disable_11n)
|
||||
return eid;
|
||||
|
||||
*pos++ = WLAN_EID_HT_CAP;
|
||||
@ -58,7 +59,7 @@ u8 * hostapd_eid_ht_operation(struct hostapd_data *hapd, u8 *eid)
|
||||
struct ieee80211_ht_operation *oper;
|
||||
u8 *pos = eid;
|
||||
|
||||
if (!hapd->iconf->ieee80211n)
|
||||
if (!hapd->iconf->ieee80211n || hapd->conf->disable_11n)
|
||||
return eid;
|
||||
|
||||
*pos++ = WLAN_EID_HT_OPERATION;
|
||||
@ -92,7 +93,6 @@ Set to 1 (HT non-member protection) if there may be non-HT STAs
|
||||
Set to 2 if only HT STAs are associated in BSS,
|
||||
however and at least one 20 MHz HT STA is associated
|
||||
Set to 3 (HT mixed mode) when one or more non-HT STAs are associated
|
||||
(currently non-GF HT station is considered as non-HT STA also)
|
||||
*/
|
||||
int hostapd_ht_operation_update(struct hostapd_iface *iface)
|
||||
{
|
||||
@ -130,13 +130,8 @@ int hostapd_ht_operation_update(struct hostapd_iface *iface)
|
||||
op_mode_changes++;
|
||||
}
|
||||
|
||||
/* Note: currently we switch to the MIXED op mode if HT non-greenfield
|
||||
* station is associated. Probably it's a theoretical case, since
|
||||
* it looks like all known HT STAs support greenfield.
|
||||
*/
|
||||
new_op_mode = 0;
|
||||
if (iface->num_sta_no_ht ||
|
||||
(iface->ht_op_mode & HT_INFO_OPERATION_MODE_NON_GF_DEVS_PRESENT))
|
||||
if (iface->num_sta_no_ht)
|
||||
new_op_mode = OP_MODE_MIXED;
|
||||
else if ((iface->conf->ht_capab & HT_CAP_INFO_SUPP_CHANNEL_WIDTH_SET)
|
||||
&& iface->num_sta_ht_20mhz)
|
||||
@ -160,11 +155,13 @@ int hostapd_ht_operation_update(struct hostapd_iface *iface)
|
||||
}
|
||||
|
||||
|
||||
u16 copy_sta_ht_capab(struct sta_info *sta, const u8 *ht_capab,
|
||||
size_t ht_capab_len)
|
||||
u16 copy_sta_ht_capab(struct hostapd_data *hapd, struct sta_info *sta,
|
||||
const u8 *ht_capab, size_t ht_capab_len)
|
||||
{
|
||||
/* Disable HT caps for STAs associated to no-HT BSSes. */
|
||||
if (!ht_capab ||
|
||||
ht_capab_len < sizeof(struct ieee80211_ht_capabilities)) {
|
||||
ht_capab_len < sizeof(struct ieee80211_ht_capabilities) ||
|
||||
hapd->conf->disable_11n) {
|
||||
sta->flags &= ~WLAN_STA_HT;
|
||||
os_free(sta->ht_capabilities);
|
||||
sta->ht_capabilities = NULL;
|
||||
@ -253,8 +250,14 @@ void hostapd_get_ht_capab(struct hostapd_data *hapd,
|
||||
return;
|
||||
os_memcpy(neg_ht_cap, ht_cap, sizeof(*neg_ht_cap));
|
||||
cap = le_to_host16(neg_ht_cap->ht_capabilities_info);
|
||||
cap &= hapd->iconf->ht_capab;
|
||||
cap |= (hapd->iconf->ht_capab & HT_CAP_INFO_SMPS_DISABLED);
|
||||
|
||||
/*
|
||||
* Mask out HT features we don't support, but don't overwrite
|
||||
* non-symmetric features like STBC and SMPS. Just because
|
||||
* we're not in dynamic SMPS mode the STA might still be.
|
||||
*/
|
||||
cap &= (hapd->iconf->ht_capab | HT_CAP_INFO_RX_STBC_MASK |
|
||||
HT_CAP_INFO_TX_STBC | HT_CAP_INFO_SMPS_MASK);
|
||||
|
||||
/*
|
||||
* STBC needs to be handled specially
|
||||
|
458
contrib/wpa/src/ap/ieee802_11_shared.c
Normal file
458
contrib/wpa/src/ap/ieee802_11_shared.c
Normal file
@ -0,0 +1,458 @@
|
||||
/*
|
||||
* hostapd / IEEE 802.11 Management
|
||||
* Copyright (c) 2002-2012, Jouni Malinen <j@w1.fi>
|
||||
*
|
||||
* This software may be distributed under the terms of the BSD license.
|
||||
* See README for more details.
|
||||
*/
|
||||
|
||||
#include "utils/includes.h"
|
||||
|
||||
#include "utils/common.h"
|
||||
#include "common/ieee802_11_defs.h"
|
||||
#include "hostapd.h"
|
||||
#include "sta_info.h"
|
||||
#include "ap_config.h"
|
||||
#include "ap_drv_ops.h"
|
||||
#include "ieee802_11.h"
|
||||
|
||||
|
||||
#ifdef CONFIG_IEEE80211W
|
||||
|
||||
u8 * hostapd_eid_assoc_comeback_time(struct hostapd_data *hapd,
|
||||
struct sta_info *sta, u8 *eid)
|
||||
{
|
||||
u8 *pos = eid;
|
||||
u32 timeout, tu;
|
||||
struct os_time now, passed;
|
||||
|
||||
*pos++ = WLAN_EID_TIMEOUT_INTERVAL;
|
||||
*pos++ = 5;
|
||||
*pos++ = WLAN_TIMEOUT_ASSOC_COMEBACK;
|
||||
os_get_time(&now);
|
||||
os_time_sub(&now, &sta->sa_query_start, &passed);
|
||||
tu = (passed.sec * 1000000 + passed.usec) / 1024;
|
||||
if (hapd->conf->assoc_sa_query_max_timeout > tu)
|
||||
timeout = hapd->conf->assoc_sa_query_max_timeout - tu;
|
||||
else
|
||||
timeout = 0;
|
||||
if (timeout < hapd->conf->assoc_sa_query_max_timeout)
|
||||
timeout++; /* add some extra time for local timers */
|
||||
WPA_PUT_LE32(pos, timeout);
|
||||
pos += 4;
|
||||
|
||||
return pos;
|
||||
}
|
||||
|
||||
|
||||
/* MLME-SAQuery.request */
|
||||
void ieee802_11_send_sa_query_req(struct hostapd_data *hapd,
|
||||
const u8 *addr, const u8 *trans_id)
|
||||
{
|
||||
struct ieee80211_mgmt mgmt;
|
||||
u8 *end;
|
||||
|
||||
wpa_printf(MSG_DEBUG, "IEEE 802.11: Sending SA Query Request to "
|
||||
MACSTR, MAC2STR(addr));
|
||||
wpa_hexdump(MSG_DEBUG, "IEEE 802.11: SA Query Transaction ID",
|
||||
trans_id, WLAN_SA_QUERY_TR_ID_LEN);
|
||||
|
||||
os_memset(&mgmt, 0, sizeof(mgmt));
|
||||
mgmt.frame_control = IEEE80211_FC(WLAN_FC_TYPE_MGMT,
|
||||
WLAN_FC_STYPE_ACTION);
|
||||
os_memcpy(mgmt.da, addr, ETH_ALEN);
|
||||
os_memcpy(mgmt.sa, hapd->own_addr, ETH_ALEN);
|
||||
os_memcpy(mgmt.bssid, hapd->own_addr, ETH_ALEN);
|
||||
mgmt.u.action.category = WLAN_ACTION_SA_QUERY;
|
||||
mgmt.u.action.u.sa_query_req.action = WLAN_SA_QUERY_REQUEST;
|
||||
os_memcpy(mgmt.u.action.u.sa_query_req.trans_id, trans_id,
|
||||
WLAN_SA_QUERY_TR_ID_LEN);
|
||||
end = mgmt.u.action.u.sa_query_req.trans_id + WLAN_SA_QUERY_TR_ID_LEN;
|
||||
if (hostapd_drv_send_mlme(hapd, &mgmt, end - (u8 *) &mgmt, 0) < 0)
|
||||
perror("ieee802_11_send_sa_query_req: send");
|
||||
}
|
||||
|
||||
|
||||
static void ieee802_11_send_sa_query_resp(struct hostapd_data *hapd,
|
||||
const u8 *sa, const u8 *trans_id)
|
||||
{
|
||||
struct sta_info *sta;
|
||||
struct ieee80211_mgmt resp;
|
||||
u8 *end;
|
||||
|
||||
wpa_printf(MSG_DEBUG, "IEEE 802.11: Received SA Query Request from "
|
||||
MACSTR, MAC2STR(sa));
|
||||
wpa_hexdump(MSG_DEBUG, "IEEE 802.11: SA Query Transaction ID",
|
||||
trans_id, WLAN_SA_QUERY_TR_ID_LEN);
|
||||
|
||||
sta = ap_get_sta(hapd, sa);
|
||||
if (sta == NULL || !(sta->flags & WLAN_STA_ASSOC)) {
|
||||
wpa_printf(MSG_DEBUG, "IEEE 802.11: Ignore SA Query Request "
|
||||
"from unassociated STA " MACSTR, MAC2STR(sa));
|
||||
return;
|
||||
}
|
||||
|
||||
wpa_printf(MSG_DEBUG, "IEEE 802.11: Sending SA Query Response to "
|
||||
MACSTR, MAC2STR(sa));
|
||||
|
||||
os_memset(&resp, 0, sizeof(resp));
|
||||
resp.frame_control = IEEE80211_FC(WLAN_FC_TYPE_MGMT,
|
||||
WLAN_FC_STYPE_ACTION);
|
||||
os_memcpy(resp.da, sa, ETH_ALEN);
|
||||
os_memcpy(resp.sa, hapd->own_addr, ETH_ALEN);
|
||||
os_memcpy(resp.bssid, hapd->own_addr, ETH_ALEN);
|
||||
resp.u.action.category = WLAN_ACTION_SA_QUERY;
|
||||
resp.u.action.u.sa_query_req.action = WLAN_SA_QUERY_RESPONSE;
|
||||
os_memcpy(resp.u.action.u.sa_query_req.trans_id, trans_id,
|
||||
WLAN_SA_QUERY_TR_ID_LEN);
|
||||
end = resp.u.action.u.sa_query_req.trans_id + WLAN_SA_QUERY_TR_ID_LEN;
|
||||
if (hostapd_drv_send_mlme(hapd, &resp, end - (u8 *) &resp, 0) < 0)
|
||||
perror("ieee80211_mgmt_sa_query_request: send");
|
||||
}
|
||||
|
||||
|
||||
void ieee802_11_sa_query_action(struct hostapd_data *hapd, const u8 *sa,
|
||||
const u8 action_type, const u8 *trans_id)
|
||||
{
|
||||
struct sta_info *sta;
|
||||
int i;
|
||||
|
||||
if (action_type == WLAN_SA_QUERY_REQUEST) {
|
||||
ieee802_11_send_sa_query_resp(hapd, sa, trans_id);
|
||||
return;
|
||||
}
|
||||
|
||||
if (action_type != WLAN_SA_QUERY_RESPONSE) {
|
||||
wpa_printf(MSG_DEBUG, "IEEE 802.11: Unexpected SA Query "
|
||||
"Action %d", action_type);
|
||||
return;
|
||||
}
|
||||
|
||||
wpa_printf(MSG_DEBUG, "IEEE 802.11: Received SA Query Response from "
|
||||
MACSTR, MAC2STR(sa));
|
||||
wpa_hexdump(MSG_DEBUG, "IEEE 802.11: SA Query Transaction ID",
|
||||
trans_id, WLAN_SA_QUERY_TR_ID_LEN);
|
||||
|
||||
/* MLME-SAQuery.confirm */
|
||||
|
||||
sta = ap_get_sta(hapd, sa);
|
||||
if (sta == NULL || sta->sa_query_trans_id == NULL) {
|
||||
wpa_printf(MSG_DEBUG, "IEEE 802.11: No matching STA with "
|
||||
"pending SA Query request found");
|
||||
return;
|
||||
}
|
||||
|
||||
for (i = 0; i < sta->sa_query_count; i++) {
|
||||
if (os_memcmp(sta->sa_query_trans_id +
|
||||
i * WLAN_SA_QUERY_TR_ID_LEN,
|
||||
trans_id, WLAN_SA_QUERY_TR_ID_LEN) == 0)
|
||||
break;
|
||||
}
|
||||
|
||||
if (i >= sta->sa_query_count) {
|
||||
wpa_printf(MSG_DEBUG, "IEEE 802.11: No matching SA Query "
|
||||
"transaction identifier found");
|
||||
return;
|
||||
}
|
||||
|
||||
hostapd_logger(hapd, sta->addr, HOSTAPD_MODULE_IEEE80211,
|
||||
HOSTAPD_LEVEL_DEBUG,
|
||||
"Reply to pending SA Query received");
|
||||
ap_sta_stop_sa_query(hapd, sta);
|
||||
}
|
||||
|
||||
#endif /* CONFIG_IEEE80211W */
|
||||
|
||||
|
||||
u8 * hostapd_eid_ext_capab(struct hostapd_data *hapd, u8 *eid)
|
||||
{
|
||||
u8 *pos = eid;
|
||||
u8 len = 0;
|
||||
|
||||
if (hapd->conf->tdls & (TDLS_PROHIBIT | TDLS_PROHIBIT_CHAN_SWITCH))
|
||||
len = 5;
|
||||
if (len < 4 && hapd->conf->interworking)
|
||||
len = 4;
|
||||
if (len < 3 && hapd->conf->wnm_sleep_mode)
|
||||
len = 3;
|
||||
if (len < 7 && hapd->conf->ssid.utf8_ssid)
|
||||
len = 7;
|
||||
#ifdef CONFIG_WNM
|
||||
if (len < 4)
|
||||
len = 4;
|
||||
#endif /* CONFIG_WNM */
|
||||
if (len == 0)
|
||||
return eid;
|
||||
|
||||
*pos++ = WLAN_EID_EXT_CAPAB;
|
||||
*pos++ = len;
|
||||
*pos++ = 0x00;
|
||||
*pos++ = 0x00;
|
||||
|
||||
*pos = 0x00;
|
||||
if (hapd->conf->wnm_sleep_mode)
|
||||
*pos |= 0x02; /* Bit 17 - WNM-Sleep Mode */
|
||||
if (hapd->conf->bss_transition)
|
||||
*pos |= 0x08; /* Bit 19 - BSS Transition */
|
||||
pos++;
|
||||
|
||||
if (len < 4)
|
||||
return pos;
|
||||
*pos = 0x00;
|
||||
#ifdef CONFIG_WNM
|
||||
*pos |= 0x02; /* Bit 25 - SSID List */
|
||||
#endif /* CONFIG_WNM */
|
||||
if (hapd->conf->time_advertisement == 2)
|
||||
*pos |= 0x08; /* Bit 27 - UTC TSF Offset */
|
||||
if (hapd->conf->interworking)
|
||||
*pos |= 0x80; /* Bit 31 - Interworking */
|
||||
pos++;
|
||||
|
||||
if (len < 5)
|
||||
return pos;
|
||||
*pos = 0x00;
|
||||
if (hapd->conf->tdls & TDLS_PROHIBIT)
|
||||
*pos |= 0x40; /* Bit 38 - TDLS Prohibited */
|
||||
if (hapd->conf->tdls & TDLS_PROHIBIT_CHAN_SWITCH)
|
||||
*pos |= 0x80; /* Bit 39 - TDLS Channel Switching Prohibited */
|
||||
pos++;
|
||||
|
||||
if (len < 6)
|
||||
return pos;
|
||||
*pos = 0x00;
|
||||
pos++;
|
||||
|
||||
if (len < 7)
|
||||
return pos;
|
||||
*pos = 0x00;
|
||||
if (hapd->conf->ssid.utf8_ssid)
|
||||
*pos |= 0x01; /* Bit 48 - UTF-8 SSID */
|
||||
pos++;
|
||||
|
||||
return pos;
|
||||
}
|
||||
|
||||
|
||||
u8 * hostapd_eid_interworking(struct hostapd_data *hapd, u8 *eid)
|
||||
{
|
||||
u8 *pos = eid;
|
||||
#ifdef CONFIG_INTERWORKING
|
||||
u8 *len;
|
||||
|
||||
if (!hapd->conf->interworking)
|
||||
return eid;
|
||||
|
||||
*pos++ = WLAN_EID_INTERWORKING;
|
||||
len = pos++;
|
||||
|
||||
*pos = hapd->conf->access_network_type;
|
||||
if (hapd->conf->internet)
|
||||
*pos |= INTERWORKING_ANO_INTERNET;
|
||||
if (hapd->conf->asra)
|
||||
*pos |= INTERWORKING_ANO_ASRA;
|
||||
if (hapd->conf->esr)
|
||||
*pos |= INTERWORKING_ANO_ESR;
|
||||
if (hapd->conf->uesa)
|
||||
*pos |= INTERWORKING_ANO_UESA;
|
||||
pos++;
|
||||
|
||||
if (hapd->conf->venue_info_set) {
|
||||
*pos++ = hapd->conf->venue_group;
|
||||
*pos++ = hapd->conf->venue_type;
|
||||
}
|
||||
|
||||
if (!is_zero_ether_addr(hapd->conf->hessid)) {
|
||||
os_memcpy(pos, hapd->conf->hessid, ETH_ALEN);
|
||||
pos += ETH_ALEN;
|
||||
}
|
||||
|
||||
*len = pos - len - 1;
|
||||
#endif /* CONFIG_INTERWORKING */
|
||||
|
||||
return pos;
|
||||
}
|
||||
|
||||
|
||||
u8 * hostapd_eid_adv_proto(struct hostapd_data *hapd, u8 *eid)
|
||||
{
|
||||
u8 *pos = eid;
|
||||
#ifdef CONFIG_INTERWORKING
|
||||
|
||||
/* TODO: Separate configuration for ANQP? */
|
||||
if (!hapd->conf->interworking)
|
||||
return eid;
|
||||
|
||||
*pos++ = WLAN_EID_ADV_PROTO;
|
||||
*pos++ = 2;
|
||||
*pos++ = 0x7F; /* Query Response Length Limit | PAME-BI */
|
||||
*pos++ = ACCESS_NETWORK_QUERY_PROTOCOL;
|
||||
#endif /* CONFIG_INTERWORKING */
|
||||
|
||||
return pos;
|
||||
}
|
||||
|
||||
|
||||
u8 * hostapd_eid_roaming_consortium(struct hostapd_data *hapd, u8 *eid)
|
||||
{
|
||||
u8 *pos = eid;
|
||||
#ifdef CONFIG_INTERWORKING
|
||||
u8 *len;
|
||||
unsigned int i, count;
|
||||
|
||||
if (!hapd->conf->interworking ||
|
||||
hapd->conf->roaming_consortium == NULL ||
|
||||
hapd->conf->roaming_consortium_count == 0)
|
||||
return eid;
|
||||
|
||||
*pos++ = WLAN_EID_ROAMING_CONSORTIUM;
|
||||
len = pos++;
|
||||
|
||||
/* Number of ANQP OIs (in addition to the max 3 listed here) */
|
||||
if (hapd->conf->roaming_consortium_count > 3 + 255)
|
||||
*pos++ = 255;
|
||||
else if (hapd->conf->roaming_consortium_count > 3)
|
||||
*pos++ = hapd->conf->roaming_consortium_count - 3;
|
||||
else
|
||||
*pos++ = 0;
|
||||
|
||||
/* OU #1 and #2 Lengths */
|
||||
*pos = hapd->conf->roaming_consortium[0].len;
|
||||
if (hapd->conf->roaming_consortium_count > 1)
|
||||
*pos |= hapd->conf->roaming_consortium[1].len << 4;
|
||||
pos++;
|
||||
|
||||
if (hapd->conf->roaming_consortium_count > 3)
|
||||
count = 3;
|
||||
else
|
||||
count = hapd->conf->roaming_consortium_count;
|
||||
|
||||
for (i = 0; i < count; i++) {
|
||||
os_memcpy(pos, hapd->conf->roaming_consortium[i].oi,
|
||||
hapd->conf->roaming_consortium[i].len);
|
||||
pos += hapd->conf->roaming_consortium[i].len;
|
||||
}
|
||||
|
||||
*len = pos - len - 1;
|
||||
#endif /* CONFIG_INTERWORKING */
|
||||
|
||||
return pos;
|
||||
}
|
||||
|
||||
|
||||
u8 * hostapd_eid_time_adv(struct hostapd_data *hapd, u8 *eid)
|
||||
{
|
||||
if (hapd->conf->time_advertisement != 2)
|
||||
return eid;
|
||||
|
||||
if (hapd->time_adv == NULL &&
|
||||
hostapd_update_time_adv(hapd) < 0)
|
||||
return eid;
|
||||
|
||||
if (hapd->time_adv == NULL)
|
||||
return eid;
|
||||
|
||||
os_memcpy(eid, wpabuf_head(hapd->time_adv),
|
||||
wpabuf_len(hapd->time_adv));
|
||||
eid += wpabuf_len(hapd->time_adv);
|
||||
|
||||
return eid;
|
||||
}
|
||||
|
||||
|
||||
u8 * hostapd_eid_time_zone(struct hostapd_data *hapd, u8 *eid)
|
||||
{
|
||||
size_t len;
|
||||
|
||||
if (hapd->conf->time_advertisement != 2)
|
||||
return eid;
|
||||
|
||||
len = os_strlen(hapd->conf->time_zone);
|
||||
|
||||
*eid++ = WLAN_EID_TIME_ZONE;
|
||||
*eid++ = len;
|
||||
os_memcpy(eid, hapd->conf->time_zone, len);
|
||||
eid += len;
|
||||
|
||||
return eid;
|
||||
}
|
||||
|
||||
|
||||
int hostapd_update_time_adv(struct hostapd_data *hapd)
|
||||
{
|
||||
const int elen = 2 + 1 + 10 + 5 + 1;
|
||||
struct os_time t;
|
||||
struct os_tm tm;
|
||||
u8 *pos;
|
||||
|
||||
if (hapd->conf->time_advertisement != 2)
|
||||
return 0;
|
||||
|
||||
if (os_get_time(&t) < 0 || os_gmtime(t.sec, &tm) < 0)
|
||||
return -1;
|
||||
|
||||
if (!hapd->time_adv) {
|
||||
hapd->time_adv = wpabuf_alloc(elen);
|
||||
if (hapd->time_adv == NULL)
|
||||
return -1;
|
||||
pos = wpabuf_put(hapd->time_adv, elen);
|
||||
} else
|
||||
pos = wpabuf_mhead_u8(hapd->time_adv);
|
||||
|
||||
*pos++ = WLAN_EID_TIME_ADVERTISEMENT;
|
||||
*pos++ = 1 + 10 + 5 + 1;
|
||||
|
||||
*pos++ = 2; /* UTC time at which the TSF timer is 0 */
|
||||
|
||||
/* Time Value at TSF 0 */
|
||||
/* FIX: need to calculate this based on the current TSF value */
|
||||
WPA_PUT_LE16(pos, tm.year); /* Year */
|
||||
pos += 2;
|
||||
*pos++ = tm.month; /* Month */
|
||||
*pos++ = tm.day; /* Day of month */
|
||||
*pos++ = tm.hour; /* Hours */
|
||||
*pos++ = tm.min; /* Minutes */
|
||||
*pos++ = tm.sec; /* Seconds */
|
||||
WPA_PUT_LE16(pos, 0); /* Milliseconds (not used) */
|
||||
pos += 2;
|
||||
*pos++ = 0; /* Reserved */
|
||||
|
||||
/* Time Error */
|
||||
/* TODO: fill in an estimate on the error */
|
||||
*pos++ = 0;
|
||||
*pos++ = 0;
|
||||
*pos++ = 0;
|
||||
*pos++ = 0;
|
||||
*pos++ = 0;
|
||||
|
||||
*pos++ = hapd->time_update_counter++;
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
|
||||
u8 * hostapd_eid_bss_max_idle_period(struct hostapd_data *hapd, u8 *eid)
|
||||
{
|
||||
u8 *pos = eid;
|
||||
|
||||
#ifdef CONFIG_WNM
|
||||
if (hapd->conf->ap_max_inactivity > 0) {
|
||||
unsigned int val;
|
||||
*pos++ = WLAN_EID_BSS_MAX_IDLE_PERIOD;
|
||||
*pos++ = 3;
|
||||
val = hapd->conf->ap_max_inactivity;
|
||||
if (val > 68000)
|
||||
val = 68000;
|
||||
val *= 1000;
|
||||
val /= 1024;
|
||||
if (val == 0)
|
||||
val = 1;
|
||||
if (val > 65535)
|
||||
val = 65535;
|
||||
WPA_PUT_LE16(pos, val);
|
||||
pos += 2;
|
||||
*pos++ = 0x00; /* TODO: Protected Keep-Alive Required */
|
||||
}
|
||||
#endif /* CONFIG_WNM */
|
||||
|
||||
return pos;
|
||||
}
|
110
contrib/wpa/src/ap/ieee802_11_vht.c
Normal file
110
contrib/wpa/src/ap/ieee802_11_vht.c
Normal file
@ -0,0 +1,110 @@
|
||||
/*
|
||||
* hostapd / IEEE 802.11ac VHT
|
||||
* Copyright (c) 2002-2009, Jouni Malinen <j@w1.fi>
|
||||
*
|
||||
* This program is free software; you can redistribute it and/or modify
|
||||
* it under the terms of BSD license
|
||||
*
|
||||
* See README and COPYING for more details.
|
||||
*/
|
||||
|
||||
#include "utils/includes.h"
|
||||
|
||||
#include "utils/common.h"
|
||||
#include "common/ieee802_11_defs.h"
|
||||
#include "drivers/driver.h"
|
||||
#include "hostapd.h"
|
||||
#include "ap_config.h"
|
||||
#include "sta_info.h"
|
||||
#include "beacon.h"
|
||||
#include "ieee802_11.h"
|
||||
|
||||
|
||||
u8 * hostapd_eid_vht_capabilities(struct hostapd_data *hapd, u8 *eid)
|
||||
{
|
||||
struct ieee80211_vht_capabilities *cap;
|
||||
u8 *pos = eid;
|
||||
|
||||
if (!hapd->iconf->ieee80211ac || !hapd->iface->current_mode ||
|
||||
hapd->conf->disable_11ac)
|
||||
return eid;
|
||||
|
||||
*pos++ = WLAN_EID_VHT_CAP;
|
||||
*pos++ = sizeof(*cap);
|
||||
|
||||
cap = (struct ieee80211_vht_capabilities *) pos;
|
||||
os_memset(cap, 0, sizeof(*cap));
|
||||
cap->vht_capabilities_info = host_to_le32(
|
||||
hapd->iface->current_mode->vht_capab);
|
||||
|
||||
/* Supported MCS set comes from hw */
|
||||
os_memcpy(cap->vht_supported_mcs_set,
|
||||
hapd->iface->current_mode->vht_mcs_set, 8);
|
||||
|
||||
pos += sizeof(*cap);
|
||||
|
||||
return pos;
|
||||
}
|
||||
|
||||
|
||||
u8 * hostapd_eid_vht_operation(struct hostapd_data *hapd, u8 *eid)
|
||||
{
|
||||
struct ieee80211_vht_operation *oper;
|
||||
u8 *pos = eid;
|
||||
|
||||
if (!hapd->iconf->ieee80211ac || hapd->conf->disable_11ac)
|
||||
return eid;
|
||||
|
||||
*pos++ = WLAN_EID_VHT_OPERATION;
|
||||
*pos++ = sizeof(*oper);
|
||||
|
||||
oper = (struct ieee80211_vht_operation *) pos;
|
||||
os_memset(oper, 0, sizeof(*oper));
|
||||
|
||||
/*
|
||||
* center freq = 5 GHz + (5 * index)
|
||||
* So index 42 gives center freq 5.210 GHz
|
||||
* which is channel 42 in 5G band
|
||||
*/
|
||||
oper->vht_op_info_chan_center_freq_seg0_idx =
|
||||
hapd->iconf->vht_oper_centr_freq_seg0_idx;
|
||||
oper->vht_op_info_chan_center_freq_seg1_idx =
|
||||
hapd->iconf->vht_oper_centr_freq_seg1_idx;
|
||||
|
||||
oper->vht_op_info_chwidth = hapd->iconf->vht_oper_chwidth;
|
||||
|
||||
/* VHT Basic MCS set comes from hw */
|
||||
/* Hard code 1 stream, MCS0-7 is a min Basic VHT MCS rates */
|
||||
oper->vht_basic_mcs_set = host_to_le16(0xfffc);
|
||||
pos += sizeof(*oper);
|
||||
|
||||
return pos;
|
||||
}
|
||||
|
||||
|
||||
u16 copy_sta_vht_capab(struct hostapd_data *hapd, struct sta_info *sta,
|
||||
const u8 *vht_capab, size_t vht_capab_len)
|
||||
{
|
||||
/* Disable VHT caps for STAs associated to no-VHT BSSes. */
|
||||
if (!vht_capab ||
|
||||
vht_capab_len < sizeof(struct ieee80211_vht_capabilities) ||
|
||||
hapd->conf->disable_11ac) {
|
||||
sta->flags &= ~WLAN_STA_VHT;
|
||||
os_free(sta->vht_capabilities);
|
||||
sta->vht_capabilities = NULL;
|
||||
return WLAN_STATUS_SUCCESS;
|
||||
}
|
||||
|
||||
if (sta->vht_capabilities == NULL) {
|
||||
sta->vht_capabilities =
|
||||
os_zalloc(sizeof(struct ieee80211_vht_capabilities));
|
||||
if (sta->vht_capabilities == NULL)
|
||||
return WLAN_STATUS_UNSPECIFIED_FAILURE;
|
||||
}
|
||||
|
||||
sta->flags |= WLAN_STA_VHT;
|
||||
os_memcpy(sta->vht_capabilities, vht_capab,
|
||||
sizeof(struct ieee80211_vht_capabilities));
|
||||
|
||||
return WLAN_STATUS_SUCCESS;
|
||||
}
|
@ -1,15 +1,9 @@
|
||||
/*
|
||||
* hostapd / IEEE 802.1X-2004 Authenticator
|
||||
* Copyright (c) 2002-2009, Jouni Malinen <j@w1.fi>
|
||||
* Copyright (c) 2002-2012, Jouni Malinen <j@w1.fi>
|
||||
*
|
||||
* This program is free software; you can redistribute it and/or modify
|
||||
* it under the terms of the GNU General Public License version 2 as
|
||||
* published by the Free Software Foundation.
|
||||
*
|
||||
* Alternatively, this software may be distributed under the terms of BSD
|
||||
* license.
|
||||
*
|
||||
* See README and COPYING for more details.
|
||||
* This software may be distributed under the terms of the BSD license.
|
||||
* See README for more details.
|
||||
*/
|
||||
|
||||
#include "utils/includes.h"
|
||||
@ -18,14 +12,15 @@
|
||||
#include "utils/eloop.h"
|
||||
#include "crypto/md5.h"
|
||||
#include "crypto/crypto.h"
|
||||
#include "crypto/random.h"
|
||||
#include "common/ieee802_11_defs.h"
|
||||
#include "common/wpa_ctrl.h"
|
||||
#include "radius/radius.h"
|
||||
#include "radius/radius_client.h"
|
||||
#include "eap_server/eap.h"
|
||||
#include "eap_common/eap_wsc_common.h"
|
||||
#include "eapol_auth/eapol_auth_sm.h"
|
||||
#include "eapol_auth/eapol_auth_sm_i.h"
|
||||
#include "p2p/p2p.h"
|
||||
#include "hostapd.h"
|
||||
#include "accounting.h"
|
||||
#include "sta_info.h"
|
||||
@ -33,6 +28,7 @@
|
||||
#include "preauth_auth.h"
|
||||
#include "pmksa_cache_auth.h"
|
||||
#include "ap_config.h"
|
||||
#include "ap_drv_ops.h"
|
||||
#include "ieee802_1x.h"
|
||||
|
||||
|
||||
@ -70,7 +66,9 @@ static void ieee802_1x_send(struct hostapd_data *hapd, struct sta_info *sta,
|
||||
if (sta->flags & WLAN_STA_PREAUTH) {
|
||||
rsn_preauth_send(hapd, sta, buf, len);
|
||||
} else {
|
||||
hapd->drv.send_eapol(hapd, sta->addr, buf, len, encrypt);
|
||||
hostapd_drv_hapd_send_eapol(
|
||||
hapd, sta->addr, buf, len,
|
||||
encrypt, hostapd_sta_flags_to_drv(sta->flags));
|
||||
}
|
||||
|
||||
os_free(buf);
|
||||
@ -86,21 +84,13 @@ void ieee802_1x_set_sta_authorized(struct hostapd_data *hapd,
|
||||
return;
|
||||
|
||||
if (authorized) {
|
||||
if (!(sta->flags & WLAN_STA_AUTHORIZED))
|
||||
wpa_msg(hapd->msg_ctx, MSG_INFO,
|
||||
AP_STA_CONNECTED MACSTR, MAC2STR(sta->addr));
|
||||
sta->flags |= WLAN_STA_AUTHORIZED;
|
||||
res = hapd->drv.set_authorized(hapd, sta, 1);
|
||||
ap_sta_set_authorized(hapd, sta, 1);
|
||||
res = hostapd_set_authorized(hapd, sta, 1);
|
||||
hostapd_logger(hapd, sta->addr, HOSTAPD_MODULE_IEEE8021X,
|
||||
HOSTAPD_LEVEL_DEBUG, "authorizing port");
|
||||
} else {
|
||||
if ((sta->flags & (WLAN_STA_AUTHORIZED | WLAN_STA_ASSOC)) ==
|
||||
(WLAN_STA_AUTHORIZED | WLAN_STA_ASSOC))
|
||||
wpa_msg(hapd->msg_ctx, MSG_INFO,
|
||||
AP_STA_DISCONNECTED MACSTR,
|
||||
MAC2STR(sta->addr));
|
||||
sta->flags &= ~WLAN_STA_AUTHORIZED;
|
||||
res = hapd->drv.set_authorized(hapd, sta, 0);
|
||||
ap_sta_set_authorized(hapd, sta, 0);
|
||||
res = hostapd_set_authorized(hapd, sta, 0);
|
||||
hostapd_logger(hapd, sta->addr, HOSTAPD_MODULE_IEEE8021X,
|
||||
HOSTAPD_LEVEL_DEBUG, "unauthorizing port");
|
||||
}
|
||||
@ -110,8 +100,10 @@ void ieee802_1x_set_sta_authorized(struct hostapd_data *hapd,
|
||||
"driver (errno=%d).\n", MAC2STR(sta->addr), errno);
|
||||
}
|
||||
|
||||
if (authorized)
|
||||
if (authorized) {
|
||||
os_get_time(&sta->connected_time);
|
||||
accounting_sta_start(hapd, sta);
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
@ -137,10 +129,10 @@ static void ieee802_1x_tx_key_one(struct hostapd_data *hapd,
|
||||
hdr = (struct ieee802_1x_hdr *) buf;
|
||||
key = (struct ieee802_1x_eapol_key *) (hdr + 1);
|
||||
key->type = EAPOL_KEY_TYPE_RC4;
|
||||
key->key_length = htons(key_len);
|
||||
WPA_PUT_BE16(key->key_length, key_len);
|
||||
wpa_get_ntp_timestamp(key->replay_counter);
|
||||
|
||||
if (os_get_random(key->key_iv, sizeof(key->key_iv))) {
|
||||
if (random_get_bytes(key->key_iv, sizeof(key->key_iv))) {
|
||||
wpa_printf(MSG_ERROR, "Could not get random numbers");
|
||||
os_free(buf);
|
||||
return;
|
||||
@ -215,7 +207,7 @@ ieee802_1x_group_alloc(struct hostapd_data *hapd, const char *ifname)
|
||||
if (!key->key[key->idx])
|
||||
key->key[key->idx] = os_malloc(key->default_len);
|
||||
if (key->key[key->idx] == NULL ||
|
||||
os_get_random(key->key[key->idx], key->default_len)) {
|
||||
random_get_bytes(key->key[key->idx], key->default_len)) {
|
||||
printf("Could not generate random WEP key (dynamic VLAN).\n");
|
||||
os_free(key->key[key->idx]);
|
||||
key->key[key->idx] = NULL;
|
||||
@ -229,11 +221,13 @@ ieee802_1x_group_alloc(struct hostapd_data *hapd, const char *ifname)
|
||||
wpa_hexdump_key(MSG_DEBUG, "Default WEP key (dynamic VLAN)",
|
||||
key->key[key->idx], key->len[key->idx]);
|
||||
|
||||
if (hapd->drv.set_key(ifname, hapd, WPA_ALG_WEP, NULL, key->idx, 1,
|
||||
NULL, 0, key->key[key->idx], key->len[key->idx]))
|
||||
if (hostapd_drv_set_key(ifname, hapd, WPA_ALG_WEP,
|
||||
broadcast_ether_addr, key->idx, 1,
|
||||
NULL, 0, key->key[key->idx],
|
||||
key->len[key->idx]))
|
||||
printf("Could not set dynamic VLAN WEP encryption key.\n");
|
||||
|
||||
hapd->drv.set_drv_ieee8021x(hapd, ifname, 1);
|
||||
hostapd_set_drv_ieee8021x(hapd, ifname, 1);
|
||||
|
||||
return key;
|
||||
}
|
||||
@ -330,7 +324,8 @@ void ieee802_1x_tx_key(struct hostapd_data *hapd, struct sta_info *sta)
|
||||
u8 *ikey;
|
||||
ikey = os_malloc(hapd->conf->individual_wep_key_len);
|
||||
if (ikey == NULL ||
|
||||
os_get_random(ikey, hapd->conf->individual_wep_key_len)) {
|
||||
random_get_bytes(ikey, hapd->conf->individual_wep_key_len))
|
||||
{
|
||||
wpa_printf(MSG_ERROR, "Could not generate random "
|
||||
"individual WEP key.");
|
||||
os_free(ikey);
|
||||
@ -345,9 +340,9 @@ void ieee802_1x_tx_key(struct hostapd_data *hapd, struct sta_info *sta)
|
||||
|
||||
/* TODO: set encryption in TX callback, i.e., only after STA
|
||||
* has ACKed EAPOL-Key frame */
|
||||
if (hapd->drv.set_key(hapd->conf->iface, hapd, WPA_ALG_WEP,
|
||||
sta->addr, 0, 1, NULL, 0, ikey,
|
||||
hapd->conf->individual_wep_key_len)) {
|
||||
if (hostapd_drv_set_key(hapd->conf->iface, hapd, WPA_ALG_WEP,
|
||||
sta->addr, 0, 1, NULL, 0, ikey,
|
||||
hapd->conf->individual_wep_key_len)) {
|
||||
wpa_printf(MSG_ERROR, "Could not set individual WEP "
|
||||
"encryption.");
|
||||
}
|
||||
@ -360,6 +355,8 @@ void ieee802_1x_tx_key(struct hostapd_data *hapd, struct sta_info *sta)
|
||||
const char *radius_mode_txt(struct hostapd_data *hapd)
|
||||
{
|
||||
switch (hapd->iface->conf->hw_mode) {
|
||||
case HOSTAPD_MODE_IEEE80211AD:
|
||||
return "802.11ad";
|
||||
case HOSTAPD_MODE_IEEE80211A:
|
||||
return "802.11a";
|
||||
case HOSTAPD_MODE_IEEE80211G:
|
||||
@ -417,12 +414,142 @@ static void ieee802_1x_learn_identity(struct hostapd_data *hapd,
|
||||
}
|
||||
|
||||
|
||||
static int add_common_radius_sta_attr(struct hostapd_data *hapd,
|
||||
struct hostapd_radius_attr *req_attr,
|
||||
struct sta_info *sta,
|
||||
struct radius_msg *msg)
|
||||
{
|
||||
char buf[128];
|
||||
|
||||
if (!hostapd_config_get_radius_attr(req_attr,
|
||||
RADIUS_ATTR_NAS_PORT) &&
|
||||
!radius_msg_add_attr_int32(msg, RADIUS_ATTR_NAS_PORT, sta->aid)) {
|
||||
wpa_printf(MSG_ERROR, "Could not add NAS-Port");
|
||||
return -1;
|
||||
}
|
||||
|
||||
os_snprintf(buf, sizeof(buf), RADIUS_802_1X_ADDR_FORMAT,
|
||||
MAC2STR(sta->addr));
|
||||
buf[sizeof(buf) - 1] = '\0';
|
||||
if (!radius_msg_add_attr(msg, RADIUS_ATTR_CALLING_STATION_ID,
|
||||
(u8 *) buf, os_strlen(buf))) {
|
||||
wpa_printf(MSG_ERROR, "Could not add Calling-Station-Id");
|
||||
return -1;
|
||||
}
|
||||
|
||||
if (sta->flags & WLAN_STA_PREAUTH) {
|
||||
os_strlcpy(buf, "IEEE 802.11i Pre-Authentication",
|
||||
sizeof(buf));
|
||||
} else {
|
||||
os_snprintf(buf, sizeof(buf), "CONNECT %d%sMbps %s",
|
||||
radius_sta_rate(hapd, sta) / 2,
|
||||
(radius_sta_rate(hapd, sta) & 1) ? ".5" : "",
|
||||
radius_mode_txt(hapd));
|
||||
buf[sizeof(buf) - 1] = '\0';
|
||||
}
|
||||
if (!hostapd_config_get_radius_attr(req_attr,
|
||||
RADIUS_ATTR_CONNECT_INFO) &&
|
||||
!radius_msg_add_attr(msg, RADIUS_ATTR_CONNECT_INFO,
|
||||
(u8 *) buf, os_strlen(buf))) {
|
||||
wpa_printf(MSG_ERROR, "Could not add Connect-Info");
|
||||
return -1;
|
||||
}
|
||||
|
||||
if (sta->acct_session_id_hi || sta->acct_session_id_lo) {
|
||||
os_snprintf(buf, sizeof(buf), "%08X-%08X",
|
||||
sta->acct_session_id_hi, sta->acct_session_id_lo);
|
||||
if (!radius_msg_add_attr(msg, RADIUS_ATTR_ACCT_SESSION_ID,
|
||||
(u8 *) buf, os_strlen(buf))) {
|
||||
wpa_printf(MSG_ERROR, "Could not add Acct-Session-Id");
|
||||
return -1;
|
||||
}
|
||||
}
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
|
||||
int add_common_radius_attr(struct hostapd_data *hapd,
|
||||
struct hostapd_radius_attr *req_attr,
|
||||
struct sta_info *sta,
|
||||
struct radius_msg *msg)
|
||||
{
|
||||
char buf[128];
|
||||
struct hostapd_radius_attr *attr;
|
||||
|
||||
if (!hostapd_config_get_radius_attr(req_attr,
|
||||
RADIUS_ATTR_NAS_IP_ADDRESS) &&
|
||||
hapd->conf->own_ip_addr.af == AF_INET &&
|
||||
!radius_msg_add_attr(msg, RADIUS_ATTR_NAS_IP_ADDRESS,
|
||||
(u8 *) &hapd->conf->own_ip_addr.u.v4, 4)) {
|
||||
wpa_printf(MSG_ERROR, "Could not add NAS-IP-Address");
|
||||
return -1;
|
||||
}
|
||||
|
||||
#ifdef CONFIG_IPV6
|
||||
if (!hostapd_config_get_radius_attr(req_attr,
|
||||
RADIUS_ATTR_NAS_IPV6_ADDRESS) &&
|
||||
hapd->conf->own_ip_addr.af == AF_INET6 &&
|
||||
!radius_msg_add_attr(msg, RADIUS_ATTR_NAS_IPV6_ADDRESS,
|
||||
(u8 *) &hapd->conf->own_ip_addr.u.v6, 16)) {
|
||||
wpa_printf(MSG_ERROR, "Could not add NAS-IPv6-Address");
|
||||
return -1;
|
||||
}
|
||||
#endif /* CONFIG_IPV6 */
|
||||
|
||||
if (!hostapd_config_get_radius_attr(req_attr,
|
||||
RADIUS_ATTR_NAS_IDENTIFIER) &&
|
||||
hapd->conf->nas_identifier &&
|
||||
!radius_msg_add_attr(msg, RADIUS_ATTR_NAS_IDENTIFIER,
|
||||
(u8 *) hapd->conf->nas_identifier,
|
||||
os_strlen(hapd->conf->nas_identifier))) {
|
||||
wpa_printf(MSG_ERROR, "Could not add NAS-Identifier");
|
||||
return -1;
|
||||
}
|
||||
|
||||
os_snprintf(buf, sizeof(buf), RADIUS_802_1X_ADDR_FORMAT ":%s",
|
||||
MAC2STR(hapd->own_addr),
|
||||
wpa_ssid_txt(hapd->conf->ssid.ssid,
|
||||
hapd->conf->ssid.ssid_len));
|
||||
buf[sizeof(buf) - 1] = '\0';
|
||||
if (!hostapd_config_get_radius_attr(req_attr,
|
||||
RADIUS_ATTR_CALLED_STATION_ID) &&
|
||||
!radius_msg_add_attr(msg, RADIUS_ATTR_CALLED_STATION_ID,
|
||||
(u8 *) buf, os_strlen(buf))) {
|
||||
wpa_printf(MSG_ERROR, "Could not add Called-Station-Id");
|
||||
return -1;
|
||||
}
|
||||
|
||||
if (!hostapd_config_get_radius_attr(req_attr,
|
||||
RADIUS_ATTR_NAS_PORT_TYPE) &&
|
||||
!radius_msg_add_attr_int32(msg, RADIUS_ATTR_NAS_PORT_TYPE,
|
||||
RADIUS_NAS_PORT_TYPE_IEEE_802_11)) {
|
||||
wpa_printf(MSG_ERROR, "Could not add NAS-Port-Type");
|
||||
return -1;
|
||||
}
|
||||
|
||||
if (sta && add_common_radius_sta_attr(hapd, req_attr, sta, msg) < 0)
|
||||
return -1;
|
||||
|
||||
for (attr = req_attr; attr; attr = attr->next) {
|
||||
if (!radius_msg_add_attr(msg, attr->type,
|
||||
wpabuf_head(attr->val),
|
||||
wpabuf_len(attr->val))) {
|
||||
wpa_printf(MSG_ERROR, "Could not add RADIUS "
|
||||
"attribute");
|
||||
return -1;
|
||||
}
|
||||
}
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
|
||||
static void ieee802_1x_encapsulate_radius(struct hostapd_data *hapd,
|
||||
struct sta_info *sta,
|
||||
const u8 *eap, size_t len)
|
||||
{
|
||||
struct radius_msg *msg;
|
||||
char buf[128];
|
||||
struct eapol_state_machine *sm = sta->eapol_sm;
|
||||
|
||||
if (sm == NULL)
|
||||
@ -450,83 +577,20 @@ static void ieee802_1x_encapsulate_radius(struct hostapd_data *hapd,
|
||||
goto fail;
|
||||
}
|
||||
|
||||
if (hapd->conf->own_ip_addr.af == AF_INET &&
|
||||
!radius_msg_add_attr(msg, RADIUS_ATTR_NAS_IP_ADDRESS,
|
||||
(u8 *) &hapd->conf->own_ip_addr.u.v4, 4)) {
|
||||
printf("Could not add NAS-IP-Address\n");
|
||||
if (add_common_radius_attr(hapd, hapd->conf->radius_auth_req_attr, sta,
|
||||
msg) < 0)
|
||||
goto fail;
|
||||
}
|
||||
|
||||
#ifdef CONFIG_IPV6
|
||||
if (hapd->conf->own_ip_addr.af == AF_INET6 &&
|
||||
!radius_msg_add_attr(msg, RADIUS_ATTR_NAS_IPV6_ADDRESS,
|
||||
(u8 *) &hapd->conf->own_ip_addr.u.v6, 16)) {
|
||||
printf("Could not add NAS-IPv6-Address\n");
|
||||
goto fail;
|
||||
}
|
||||
#endif /* CONFIG_IPV6 */
|
||||
|
||||
if (hapd->conf->nas_identifier &&
|
||||
!radius_msg_add_attr(msg, RADIUS_ATTR_NAS_IDENTIFIER,
|
||||
(u8 *) hapd->conf->nas_identifier,
|
||||
os_strlen(hapd->conf->nas_identifier))) {
|
||||
printf("Could not add NAS-Identifier\n");
|
||||
goto fail;
|
||||
}
|
||||
|
||||
if (!radius_msg_add_attr_int32(msg, RADIUS_ATTR_NAS_PORT, sta->aid)) {
|
||||
printf("Could not add NAS-Port\n");
|
||||
goto fail;
|
||||
}
|
||||
|
||||
os_snprintf(buf, sizeof(buf), RADIUS_802_1X_ADDR_FORMAT ":%s",
|
||||
MAC2STR(hapd->own_addr), hapd->conf->ssid.ssid);
|
||||
buf[sizeof(buf) - 1] = '\0';
|
||||
if (!radius_msg_add_attr(msg, RADIUS_ATTR_CALLED_STATION_ID,
|
||||
(u8 *) buf, os_strlen(buf))) {
|
||||
printf("Could not add Called-Station-Id\n");
|
||||
goto fail;
|
||||
}
|
||||
|
||||
os_snprintf(buf, sizeof(buf), RADIUS_802_1X_ADDR_FORMAT,
|
||||
MAC2STR(sta->addr));
|
||||
buf[sizeof(buf) - 1] = '\0';
|
||||
if (!radius_msg_add_attr(msg, RADIUS_ATTR_CALLING_STATION_ID,
|
||||
(u8 *) buf, os_strlen(buf))) {
|
||||
printf("Could not add Calling-Station-Id\n");
|
||||
goto fail;
|
||||
}
|
||||
|
||||
/* TODO: should probably check MTU from driver config; 2304 is max for
|
||||
* IEEE 802.11, but use 1400 to avoid problems with too large packets
|
||||
*/
|
||||
if (!radius_msg_add_attr_int32(msg, RADIUS_ATTR_FRAMED_MTU, 1400)) {
|
||||
if (!hostapd_config_get_radius_attr(hapd->conf->radius_auth_req_attr,
|
||||
RADIUS_ATTR_FRAMED_MTU) &&
|
||||
!radius_msg_add_attr_int32(msg, RADIUS_ATTR_FRAMED_MTU, 1400)) {
|
||||
printf("Could not add Framed-MTU\n");
|
||||
goto fail;
|
||||
}
|
||||
|
||||
if (!radius_msg_add_attr_int32(msg, RADIUS_ATTR_NAS_PORT_TYPE,
|
||||
RADIUS_NAS_PORT_TYPE_IEEE_802_11)) {
|
||||
printf("Could not add NAS-Port-Type\n");
|
||||
goto fail;
|
||||
}
|
||||
|
||||
if (sta->flags & WLAN_STA_PREAUTH) {
|
||||
os_strlcpy(buf, "IEEE 802.11i Pre-Authentication",
|
||||
sizeof(buf));
|
||||
} else {
|
||||
os_snprintf(buf, sizeof(buf), "CONNECT %d%sMbps %s",
|
||||
radius_sta_rate(hapd, sta) / 2,
|
||||
(radius_sta_rate(hapd, sta) & 1) ? ".5" : "",
|
||||
radius_mode_txt(hapd));
|
||||
buf[sizeof(buf) - 1] = '\0';
|
||||
}
|
||||
if (!radius_msg_add_attr(msg, RADIUS_ATTR_CONNECT_INFO,
|
||||
(u8 *) buf, os_strlen(buf))) {
|
||||
printf("Could not add Connect-Info\n");
|
||||
goto fail;
|
||||
}
|
||||
|
||||
if (eap && !radius_msg_add_eap(msg, eap, len)) {
|
||||
printf("Could not add EAP-Message\n");
|
||||
goto fail;
|
||||
@ -549,7 +613,28 @@ static void ieee802_1x_encapsulate_radius(struct hostapd_data *hapd,
|
||||
}
|
||||
}
|
||||
|
||||
radius_client_send(hapd->radius, msg, RADIUS_AUTH, sta->addr);
|
||||
if (hapd->conf->radius_request_cui) {
|
||||
const u8 *cui;
|
||||
size_t cui_len;
|
||||
/* Add previously learned CUI or nul CUI to request CUI */
|
||||
if (sm->radius_cui) {
|
||||
cui = wpabuf_head(sm->radius_cui);
|
||||
cui_len = wpabuf_len(sm->radius_cui);
|
||||
} else {
|
||||
cui = (const u8 *) "\0";
|
||||
cui_len = 1;
|
||||
}
|
||||
if (!radius_msg_add_attr(msg,
|
||||
RADIUS_ATTR_CHARGEABLE_USER_IDENTITY,
|
||||
cui, cui_len)) {
|
||||
wpa_printf(MSG_ERROR, "Could not add CUI");
|
||||
goto fail;
|
||||
}
|
||||
}
|
||||
|
||||
if (radius_client_send(hapd->radius, msg, RADIUS_AUTH, sta->addr) < 0)
|
||||
goto fail;
|
||||
|
||||
return;
|
||||
|
||||
fail:
|
||||
@ -652,7 +737,8 @@ ieee802_1x_alloc_eapol_sm(struct hostapd_data *hapd, struct sta_info *sta)
|
||||
flags |= EAPOL_SM_FROM_PMKSA_CACHE;
|
||||
}
|
||||
return eapol_auth_alloc(hapd->eapol_auth, sta->addr, flags,
|
||||
sta->wps_ie, sta);
|
||||
sta->wps_ie, sta->p2p_ie, sta,
|
||||
sta->identity, sta->radius_cui);
|
||||
}
|
||||
|
||||
|
||||
@ -673,6 +759,7 @@ void ieee802_1x_receive(struct hostapd_data *hapd, const u8 *sa, const u8 *buf,
|
||||
struct ieee802_1x_eapol_key *key;
|
||||
u16 datalen;
|
||||
struct rsn_pmksa_cache_entry *pmksa;
|
||||
int key_mgmt;
|
||||
|
||||
if (!hapd->conf->ieee802_1x && !hapd->conf->wpa &&
|
||||
!hapd->conf->wps_state)
|
||||
@ -681,9 +768,10 @@ void ieee802_1x_receive(struct hostapd_data *hapd, const u8 *sa, const u8 *buf,
|
||||
wpa_printf(MSG_DEBUG, "IEEE 802.1X: %lu bytes from " MACSTR,
|
||||
(unsigned long) len, MAC2STR(sa));
|
||||
sta = ap_get_sta(hapd, sa);
|
||||
if (!sta || !(sta->flags & WLAN_STA_ASSOC)) {
|
||||
if (!sta || (!(sta->flags & (WLAN_STA_ASSOC | WLAN_STA_PREAUTH)) &&
|
||||
!(hapd->iface->drv_flags & WPA_DRIVER_FLAGS_WIRED))) {
|
||||
wpa_printf(MSG_DEBUG, "IEEE 802.1X data frame from not "
|
||||
"associated STA");
|
||||
"associated/Pre-authenticating STA");
|
||||
return;
|
||||
}
|
||||
|
||||
@ -724,10 +812,19 @@ void ieee802_1x_receive(struct hostapd_data *hapd, const u8 *sa, const u8 *buf,
|
||||
return;
|
||||
}
|
||||
|
||||
if ((!hapd->conf->ieee802_1x &&
|
||||
!(sta->flags & (WLAN_STA_WPS | WLAN_STA_MAYBE_WPS))) ||
|
||||
wpa_key_mgmt_wpa_psk(wpa_auth_sta_key_mgmt(sta->wpa_sm)))
|
||||
if (!hapd->conf->ieee802_1x &&
|
||||
!(sta->flags & (WLAN_STA_WPS | WLAN_STA_MAYBE_WPS))) {
|
||||
wpa_printf(MSG_DEBUG, "IEEE 802.1X: Ignore EAPOL message - "
|
||||
"802.1X not enabled and WPS not used");
|
||||
return;
|
||||
}
|
||||
|
||||
key_mgmt = wpa_auth_sta_key_mgmt(sta->wpa_sm);
|
||||
if (key_mgmt != -1 && wpa_key_mgmt_wpa_psk(key_mgmt)) {
|
||||
wpa_printf(MSG_DEBUG, "IEEE 802.1X: Ignore EAPOL message - "
|
||||
"STA is using PSK");
|
||||
return;
|
||||
}
|
||||
|
||||
if (!sta->eapol_sm) {
|
||||
sta->eapol_sm = ieee802_1x_alloc_eapol_sm(hapd, sta);
|
||||
@ -735,14 +832,24 @@ void ieee802_1x_receive(struct hostapd_data *hapd, const u8 *sa, const u8 *buf,
|
||||
return;
|
||||
|
||||
#ifdef CONFIG_WPS
|
||||
if (!hapd->conf->ieee802_1x &&
|
||||
((sta->flags & (WLAN_STA_WPS | WLAN_STA_MAYBE_WPS)) ==
|
||||
WLAN_STA_MAYBE_WPS)) {
|
||||
/*
|
||||
* Delay EAPOL frame transmission until a possible WPS
|
||||
* STA initiates the handshake with EAPOL-Start.
|
||||
*/
|
||||
sta->eapol_sm->flags |= EAPOL_SM_WAIT_START;
|
||||
if (!hapd->conf->ieee802_1x) {
|
||||
u32 wflags = sta->flags & (WLAN_STA_WPS |
|
||||
WLAN_STA_WPS2 |
|
||||
WLAN_STA_MAYBE_WPS);
|
||||
if (wflags == WLAN_STA_MAYBE_WPS ||
|
||||
wflags == (WLAN_STA_WPS | WLAN_STA_MAYBE_WPS)) {
|
||||
/*
|
||||
* Delay EAPOL frame transmission until a
|
||||
* possible WPS STA initiates the handshake
|
||||
* with EAPOL-Start. Only allow the wait to be
|
||||
* skipped if the STA is known to support WPS
|
||||
* 2.0.
|
||||
*/
|
||||
wpa_printf(MSG_DEBUG, "WPS: Do not start "
|
||||
"EAPOL until EAPOL-Start is "
|
||||
"received");
|
||||
sta->eapol_sm->flags |= EAPOL_SM_WAIT_START;
|
||||
}
|
||||
}
|
||||
#endif /* CONFIG_WPS */
|
||||
|
||||
@ -776,6 +883,7 @@ void ieee802_1x_receive(struct hostapd_data *hapd, const u8 *sa, const u8 *buf,
|
||||
}
|
||||
sta->eapol_sm->eapolStart = TRUE;
|
||||
sta->eapol_sm->dot1xAuthEapolStartFramesRx++;
|
||||
eap_server_clear_identity(sta->eapol_sm->eap);
|
||||
wpa_auth_sm_event(sta->wpa_sm, WPA_REAUTH_EAPOL);
|
||||
break;
|
||||
|
||||
@ -788,11 +896,12 @@ void ieee802_1x_receive(struct hostapd_data *hapd, const u8 *sa, const u8 *buf,
|
||||
accounting_sta_stop(hapd, sta);
|
||||
sta->eapol_sm->eapolLogoff = TRUE;
|
||||
sta->eapol_sm->dot1xAuthEapolLogoffFramesRx++;
|
||||
eap_server_clear_identity(sta->eapol_sm->eap);
|
||||
break;
|
||||
|
||||
case IEEE802_1X_TYPE_EAPOL_KEY:
|
||||
wpa_printf(MSG_DEBUG, " EAPOL-Key");
|
||||
if (!(sta->flags & WLAN_STA_AUTHORIZED)) {
|
||||
if (!ap_sta_is_authorized(sta)) {
|
||||
wpa_printf(MSG_DEBUG, " Dropped key data from "
|
||||
"unauthorized Supplicant");
|
||||
break;
|
||||
@ -827,6 +936,7 @@ void ieee802_1x_new_station(struct hostapd_data *hapd, struct sta_info *sta)
|
||||
struct rsn_pmksa_cache_entry *pmksa;
|
||||
int reassoc = 1;
|
||||
int force_1x = 0;
|
||||
int key_mgmt;
|
||||
|
||||
#ifdef CONFIG_WPS
|
||||
if (hapd->conf->wps_state && hapd->conf->wpa &&
|
||||
@ -840,9 +950,27 @@ void ieee802_1x_new_station(struct hostapd_data *hapd, struct sta_info *sta)
|
||||
}
|
||||
#endif /* CONFIG_WPS */
|
||||
|
||||
if ((!force_1x && !hapd->conf->ieee802_1x) ||
|
||||
wpa_key_mgmt_wpa_psk(wpa_auth_sta_key_mgmt(sta->wpa_sm)))
|
||||
if (!force_1x && !hapd->conf->ieee802_1x) {
|
||||
wpa_printf(MSG_DEBUG, "IEEE 802.1X: Ignore STA - "
|
||||
"802.1X not enabled or forced for WPS");
|
||||
/*
|
||||
* Clear any possible EAPOL authenticator state to support
|
||||
* reassociation change from WPS to PSK.
|
||||
*/
|
||||
ieee802_1x_free_station(sta);
|
||||
return;
|
||||
}
|
||||
|
||||
key_mgmt = wpa_auth_sta_key_mgmt(sta->wpa_sm);
|
||||
if (key_mgmt != -1 && wpa_key_mgmt_wpa_psk(key_mgmt)) {
|
||||
wpa_printf(MSG_DEBUG, "IEEE 802.1X: Ignore STA - using PSK");
|
||||
/*
|
||||
* Clear any possible EAPOL authenticator state to support
|
||||
* reassociation change from WPA-EAP to PSK.
|
||||
*/
|
||||
ieee802_1x_free_station(sta);
|
||||
return;
|
||||
}
|
||||
|
||||
if (sta->eapol_sm == NULL) {
|
||||
hostapd_logger(hapd, sta->addr, HOSTAPD_MODULE_IEEE8021X,
|
||||
@ -860,17 +988,40 @@ void ieee802_1x_new_station(struct hostapd_data *hapd, struct sta_info *sta)
|
||||
|
||||
#ifdef CONFIG_WPS
|
||||
sta->eapol_sm->flags &= ~EAPOL_SM_WAIT_START;
|
||||
if (!hapd->conf->ieee802_1x && !(sta->flags & WLAN_STA_WPS)) {
|
||||
if (!hapd->conf->ieee802_1x && !(sta->flags & WLAN_STA_WPS2)) {
|
||||
/*
|
||||
* Delay EAPOL frame transmission until a possible WPS
|
||||
* initiates the handshake with EAPOL-Start.
|
||||
* Delay EAPOL frame transmission until a possible WPS STA
|
||||
* initiates the handshake with EAPOL-Start. Only allow the
|
||||
* wait to be skipped if the STA is known to support WPS 2.0.
|
||||
*/
|
||||
wpa_printf(MSG_DEBUG, "WPS: Do not start EAPOL until "
|
||||
"EAPOL-Start is received");
|
||||
sta->eapol_sm->flags |= EAPOL_SM_WAIT_START;
|
||||
}
|
||||
#endif /* CONFIG_WPS */
|
||||
|
||||
sta->eapol_sm->eap_if->portEnabled = TRUE;
|
||||
|
||||
#ifdef CONFIG_IEEE80211R
|
||||
if (sta->auth_alg == WLAN_AUTH_FT) {
|
||||
hostapd_logger(hapd, sta->addr, HOSTAPD_MODULE_IEEE8021X,
|
||||
HOSTAPD_LEVEL_DEBUG,
|
||||
"PMK from FT - skip IEEE 802.1X/EAP");
|
||||
/* Setup EAPOL state machines to already authenticated state
|
||||
* because of existing FT information from R0KH. */
|
||||
sta->eapol_sm->keyRun = TRUE;
|
||||
sta->eapol_sm->eap_if->eapKeyAvailable = TRUE;
|
||||
sta->eapol_sm->auth_pae_state = AUTH_PAE_AUTHENTICATING;
|
||||
sta->eapol_sm->be_auth_state = BE_AUTH_SUCCESS;
|
||||
sta->eapol_sm->authSuccess = TRUE;
|
||||
sta->eapol_sm->authFail = FALSE;
|
||||
if (sta->eapol_sm->eap)
|
||||
eap_sm_notify_cached(sta->eapol_sm->eap);
|
||||
/* TODO: get vlan_id from R0KH using RRB message */
|
||||
return;
|
||||
}
|
||||
#endif /* CONFIG_IEEE80211R */
|
||||
|
||||
pmksa = wpa_auth_sta_get_pmksa(sta->wpa_sm);
|
||||
if (pmksa) {
|
||||
int old_vlanid;
|
||||
@ -885,6 +1036,7 @@ void ieee802_1x_new_station(struct hostapd_data *hapd, struct sta_info *sta)
|
||||
sta->eapol_sm->auth_pae_state = AUTH_PAE_AUTHENTICATING;
|
||||
sta->eapol_sm->be_auth_state = BE_AUTH_SUCCESS;
|
||||
sta->eapol_sm->authSuccess = TRUE;
|
||||
sta->eapol_sm->authFail = FALSE;
|
||||
if (sta->eapol_sm->eap)
|
||||
eap_sm_notify_cached(sta->eapol_sm->eap);
|
||||
old_vlanid = sta->vlan_id;
|
||||
@ -918,6 +1070,7 @@ void ieee802_1x_free_station(struct sta_info *sta)
|
||||
#ifndef CONFIG_NO_RADIUS
|
||||
radius_msg_free(sm->last_recv_radius);
|
||||
radius_free_class(&sm->radius_class);
|
||||
wpabuf_free(sm->radius_cui);
|
||||
#endif /* CONFIG_NO_RADIUS */
|
||||
|
||||
os_free(sm->identity);
|
||||
@ -929,9 +1082,8 @@ void ieee802_1x_free_station(struct sta_info *sta)
|
||||
static void ieee802_1x_decapsulate_radius(struct hostapd_data *hapd,
|
||||
struct sta_info *sta)
|
||||
{
|
||||
u8 *eap;
|
||||
size_t len;
|
||||
struct eap_hdr *hdr;
|
||||
struct wpabuf *eap;
|
||||
const struct eap_hdr *hdr;
|
||||
int eap_type = -1;
|
||||
char buf[64];
|
||||
struct radius_msg *msg;
|
||||
@ -945,7 +1097,7 @@ static void ieee802_1x_decapsulate_radius(struct hostapd_data *hapd,
|
||||
|
||||
msg = sm->last_recv_radius;
|
||||
|
||||
eap = radius_msg_get_eap(msg, &len);
|
||||
eap = radius_msg_get_eap(msg);
|
||||
if (eap == NULL) {
|
||||
/* RFC 3579, Chap. 2.6.3:
|
||||
* RADIUS server SHOULD NOT send Access-Reject/no EAP-Message
|
||||
@ -957,19 +1109,19 @@ static void ieee802_1x_decapsulate_radius(struct hostapd_data *hapd,
|
||||
return;
|
||||
}
|
||||
|
||||
if (len < sizeof(*hdr)) {
|
||||
if (wpabuf_len(eap) < sizeof(*hdr)) {
|
||||
hostapd_logger(hapd, sta->addr, HOSTAPD_MODULE_IEEE8021X,
|
||||
HOSTAPD_LEVEL_WARNING, "too short EAP packet "
|
||||
"received from authentication server");
|
||||
os_free(eap);
|
||||
wpabuf_free(eap);
|
||||
sm->eap_if->aaaEapNoReq = TRUE;
|
||||
return;
|
||||
}
|
||||
|
||||
if (len > sizeof(*hdr))
|
||||
eap_type = eap[sizeof(*hdr)];
|
||||
if (wpabuf_len(eap) > sizeof(*hdr))
|
||||
eap_type = (wpabuf_head_u8(eap))[sizeof(*hdr)];
|
||||
|
||||
hdr = (struct eap_hdr *) eap;
|
||||
hdr = wpabuf_head(eap);
|
||||
switch (hdr->code) {
|
||||
case EAP_CODE_REQUEST:
|
||||
if (eap_type >= 0)
|
||||
@ -1004,7 +1156,7 @@ static void ieee802_1x_decapsulate_radius(struct hostapd_data *hapd,
|
||||
sm->eap_if->aaaEapReq = TRUE;
|
||||
|
||||
wpabuf_free(sm->eap_if->aaaEapReqData);
|
||||
sm->eap_if->aaaEapReqData = wpabuf_alloc_ext_data(eap, len);
|
||||
sm->eap_if->aaaEapReqData = eap;
|
||||
}
|
||||
|
||||
|
||||
@ -1069,7 +1221,7 @@ static void ieee802_1x_store_radius_class(struct hostapd_data *hapd,
|
||||
if (count <= 0)
|
||||
return;
|
||||
|
||||
nclass = os_zalloc(count * sizeof(struct radius_attr_data));
|
||||
nclass = os_calloc(count, sizeof(struct radius_attr_data));
|
||||
if (nclass == NULL)
|
||||
return;
|
||||
|
||||
@ -1139,6 +1291,32 @@ static void ieee802_1x_update_sta_identity(struct hostapd_data *hapd,
|
||||
}
|
||||
|
||||
|
||||
/* Update CUI based on Chargeable-User-Identity attribute in Access-Accept */
|
||||
static void ieee802_1x_update_sta_cui(struct hostapd_data *hapd,
|
||||
struct sta_info *sta,
|
||||
struct radius_msg *msg)
|
||||
{
|
||||
struct eapol_state_machine *sm = sta->eapol_sm;
|
||||
struct wpabuf *cui;
|
||||
u8 *buf;
|
||||
size_t len;
|
||||
|
||||
if (sm == NULL)
|
||||
return;
|
||||
|
||||
if (radius_msg_get_attr_ptr(msg, RADIUS_ATTR_CHARGEABLE_USER_IDENTITY,
|
||||
&buf, &len, NULL) < 0)
|
||||
return;
|
||||
|
||||
cui = wpabuf_alloc_copy(buf, len);
|
||||
if (cui == NULL)
|
||||
return;
|
||||
|
||||
wpabuf_free(sm->radius_cui);
|
||||
sm->radius_cui = cui;
|
||||
}
|
||||
|
||||
|
||||
struct sta_id_search {
|
||||
u8 identifier;
|
||||
struct eapol_state_machine *sm;
|
||||
@ -1298,6 +1476,7 @@ ieee802_1x_receive_auth(struct radius_msg *msg, struct radius_msg *req,
|
||||
shared_secret_len);
|
||||
ieee802_1x_store_radius_class(hapd, sta, msg);
|
||||
ieee802_1x_update_sta_identity(hapd, sta, msg);
|
||||
ieee802_1x_update_sta_cui(hapd, sta, msg);
|
||||
if (sm->eap_if->eapKeyAvailable &&
|
||||
wpa_auth_pmksa_add(sta->wpa_sm, sm->eapol_key_crypt,
|
||||
session_timeout_set ?
|
||||
@ -1363,6 +1542,9 @@ void ieee802_1x_abort_auth(struct hostapd_data *hapd, struct sta_info *sta)
|
||||
* request and we cannot continue EAP processing (EAP-Failure
|
||||
* could only be sent if the EAP peer actually replied).
|
||||
*/
|
||||
wpa_dbg(hapd->msg_ctx, MSG_DEBUG, "EAP Timeout, STA " MACSTR,
|
||||
MAC2STR(sta->addr));
|
||||
|
||||
sm->eap_if->portEnabled = FALSE;
|
||||
ap_sta_disconnect(hapd, sta, sta->addr,
|
||||
WLAN_REASON_PREV_AUTH_NOT_VALID);
|
||||
@ -1380,8 +1562,8 @@ static int ieee802_1x_rekey_broadcast(struct hostapd_data *hapd)
|
||||
os_free(eapol->default_wep_key);
|
||||
eapol->default_wep_key = os_malloc(hapd->conf->default_wep_key_len);
|
||||
if (eapol->default_wep_key == NULL ||
|
||||
os_get_random(eapol->default_wep_key,
|
||||
hapd->conf->default_wep_key_len)) {
|
||||
random_get_bytes(eapol->default_wep_key,
|
||||
hapd->conf->default_wep_key_len)) {
|
||||
printf("Could not generate random WEP key.\n");
|
||||
os_free(eapol->default_wep_key);
|
||||
eapol->default_wep_key = NULL;
|
||||
@ -1432,10 +1614,11 @@ static void ieee802_1x_rekey(void *eloop_ctx, void *timeout_ctx)
|
||||
|
||||
/* TODO: Could setup key for RX here, but change default TX keyid only
|
||||
* after new broadcast key has been sent to all stations. */
|
||||
if (hapd->drv.set_key(hapd->conf->iface, hapd, WPA_ALG_WEP, NULL,
|
||||
eapol->default_wep_key_idx, 1, NULL, 0,
|
||||
eapol->default_wep_key,
|
||||
hapd->conf->default_wep_key_len)) {
|
||||
if (hostapd_drv_set_key(hapd->conf->iface, hapd, WPA_ALG_WEP,
|
||||
broadcast_ether_addr,
|
||||
eapol->default_wep_key_idx, 1, NULL, 0,
|
||||
eapol->default_wep_key,
|
||||
hapd->conf->default_wep_key_len)) {
|
||||
hostapd_logger(hapd, NULL, HOSTAPD_MODULE_IEEE8021X,
|
||||
HOSTAPD_LEVEL_WARNING, "failed to configure a "
|
||||
"new broadcast key");
|
||||
@ -1514,19 +1697,15 @@ static int ieee802_1x_get_eap_user(void *ctx, const u8 *identity,
|
||||
{
|
||||
struct hostapd_data *hapd = ctx;
|
||||
const struct hostapd_eap_user *eap_user;
|
||||
int i, count;
|
||||
int i;
|
||||
|
||||
eap_user = hostapd_get_eap_user(hapd->conf, identity,
|
||||
identity_len, phase2);
|
||||
eap_user = hostapd_get_eap_user(hapd, identity, identity_len, phase2);
|
||||
if (eap_user == NULL)
|
||||
return -1;
|
||||
|
||||
os_memset(user, 0, sizeof(*user));
|
||||
user->phase2 = phase2;
|
||||
count = EAP_USER_MAX_METHODS;
|
||||
if (count > EAP_MAX_METHODS)
|
||||
count = EAP_MAX_METHODS;
|
||||
for (i = 0; i < count; i++) {
|
||||
for (i = 0; i < EAP_MAX_METHODS; i++) {
|
||||
user->methods[i].vendor = eap_user->methods[i].vendor;
|
||||
user->methods[i].method = eap_user->methods[i].method;
|
||||
}
|
||||
@ -1538,6 +1717,7 @@ static int ieee802_1x_get_eap_user(void *ctx, const u8 *identity,
|
||||
os_memcpy(user->password, eap_user->password,
|
||||
eap_user->password_len);
|
||||
user->password_len = eap_user->password_len;
|
||||
user->password_hash = eap_user->password_hash;
|
||||
}
|
||||
user->force_version = eap_user->force_version;
|
||||
user->ttls_auth = eap_user->ttls_auth;
|
||||
@ -1651,6 +1831,9 @@ int ieee802_1x_init(struct hostapd_data *hapd)
|
||||
conf.eap_sim_aka_result_ind = hapd->conf->eap_sim_aka_result_ind;
|
||||
conf.tnc = hapd->conf->tnc;
|
||||
conf.wps = hapd->wps;
|
||||
conf.fragment_size = hapd->conf->fragment_size;
|
||||
conf.pwd_group = hapd->conf->pwd_group;
|
||||
conf.pbc_in_m1 = hapd->conf->pbc_in_m1;
|
||||
|
||||
os_memset(&cb, 0, sizeof(cb));
|
||||
cb.eapol_send = ieee802_1x_eapol_send;
|
||||
@ -1669,7 +1852,7 @@ int ieee802_1x_init(struct hostapd_data *hapd)
|
||||
return -1;
|
||||
|
||||
if ((hapd->conf->ieee802_1x || hapd->conf->wpa) &&
|
||||
hapd->drv.set_drv_ieee8021x(hapd, hapd->conf->iface, 1))
|
||||
hostapd_set_drv_ieee8021x(hapd, hapd->conf->iface, 1))
|
||||
return -1;
|
||||
|
||||
#ifndef CONFIG_NO_RADIUS
|
||||
@ -1680,9 +1863,9 @@ int ieee802_1x_init(struct hostapd_data *hapd)
|
||||
|
||||
if (hapd->conf->default_wep_key_len) {
|
||||
for (i = 0; i < 4; i++)
|
||||
hapd->drv.set_key(hapd->conf->iface, hapd,
|
||||
WPA_ALG_NONE, NULL, i, 0, NULL, 0,
|
||||
NULL, 0);
|
||||
hostapd_drv_set_key(hapd->conf->iface, hapd,
|
||||
WPA_ALG_NONE, NULL, i, 0, NULL, 0,
|
||||
NULL, 0);
|
||||
|
||||
ieee802_1x_rekey(hapd, NULL);
|
||||
|
||||
@ -1700,7 +1883,7 @@ void ieee802_1x_deinit(struct hostapd_data *hapd)
|
||||
|
||||
if (hapd->driver != NULL &&
|
||||
(hapd->conf->ieee802_1x || hapd->conf->wpa))
|
||||
hapd->drv.set_drv_ieee8021x(hapd, hapd->conf->iface, 0);
|
||||
hostapd_set_drv_ieee8021x(hapd, hapd->conf->iface, 0);
|
||||
|
||||
eapol_auth_deinit(hapd->eapol_auth);
|
||||
hapd->eapol_auth = NULL;
|
||||
@ -1711,15 +1894,13 @@ int ieee802_1x_tx_status(struct hostapd_data *hapd, struct sta_info *sta,
|
||||
const u8 *buf, size_t len, int ack)
|
||||
{
|
||||
struct ieee80211_hdr *hdr;
|
||||
struct ieee802_1x_hdr *xhdr;
|
||||
struct ieee802_1x_eapol_key *key;
|
||||
u8 *pos;
|
||||
const unsigned char rfc1042_hdr[ETH_ALEN] =
|
||||
{ 0xaa, 0xaa, 0x03, 0x00, 0x00, 0x00 };
|
||||
|
||||
if (sta == NULL)
|
||||
return -1;
|
||||
if (len < sizeof(*hdr) + sizeof(rfc1042_hdr) + 2 + sizeof(*xhdr))
|
||||
if (len < sizeof(*hdr) + sizeof(rfc1042_hdr) + 2)
|
||||
return 0;
|
||||
|
||||
hdr = (struct ieee80211_hdr *) buf;
|
||||
@ -1731,21 +1912,44 @@ int ieee802_1x_tx_status(struct hostapd_data *hapd, struct sta_info *sta,
|
||||
return 0;
|
||||
pos += 2;
|
||||
|
||||
xhdr = (struct ieee802_1x_hdr *) pos;
|
||||
pos += sizeof(*xhdr);
|
||||
return ieee802_1x_eapol_tx_status(hapd, sta, pos, buf + len - pos,
|
||||
ack);
|
||||
}
|
||||
|
||||
|
||||
int ieee802_1x_eapol_tx_status(struct hostapd_data *hapd, struct sta_info *sta,
|
||||
const u8 *buf, int len, int ack)
|
||||
{
|
||||
const struct ieee802_1x_hdr *xhdr =
|
||||
(const struct ieee802_1x_hdr *) buf;
|
||||
const u8 *pos = buf + sizeof(*xhdr);
|
||||
struct ieee802_1x_eapol_key *key;
|
||||
|
||||
if (len < (int) sizeof(*xhdr))
|
||||
return 0;
|
||||
wpa_printf(MSG_DEBUG, "IEEE 802.1X: " MACSTR " TX status - version=%d "
|
||||
"type=%d length=%d - ack=%d",
|
||||
MAC2STR(sta->addr), xhdr->version, xhdr->type,
|
||||
be_to_host16(xhdr->length), ack);
|
||||
|
||||
if (xhdr->type != IEEE802_1X_TYPE_EAPOL_KEY)
|
||||
return 0;
|
||||
|
||||
if (pos + sizeof(struct wpa_eapol_key) <= buf + len) {
|
||||
const struct wpa_eapol_key *wpa;
|
||||
wpa = (const struct wpa_eapol_key *) pos;
|
||||
if (wpa->type == EAPOL_KEY_TYPE_RSN ||
|
||||
wpa->type == EAPOL_KEY_TYPE_WPA)
|
||||
wpa_auth_eapol_key_tx_status(hapd->wpa_auth,
|
||||
sta->wpa_sm, ack);
|
||||
}
|
||||
|
||||
/* EAPOL EAP-Packet packets are eventually re-sent by either Supplicant
|
||||
* or Authenticator state machines, but EAPOL-Key packets are not
|
||||
* retransmitted in case of failure. Try to re-sent failed EAPOL-Key
|
||||
* retransmitted in case of failure. Try to re-send failed EAPOL-Key
|
||||
* packets couple of times because otherwise STA keys become
|
||||
* unsynchronized with AP. */
|
||||
if (xhdr->type == IEEE802_1X_TYPE_EAPOL_KEY && !ack &&
|
||||
pos + sizeof(*key) <= buf + len) {
|
||||
if (!ack && pos + sizeof(*key) <= buf + len) {
|
||||
key = (struct ieee802_1x_eapol_key *) pos;
|
||||
hostapd_logger(hapd, sta->addr, HOSTAPD_MODULE_IEEE8021X,
|
||||
HOSTAPD_LEVEL_DEBUG, "did not Ack EAPOL-Key "
|
||||
@ -1789,8 +1993,17 @@ u8 * ieee802_1x_get_radius_class(struct eapol_state_machine *sm, size_t *len,
|
||||
}
|
||||
|
||||
|
||||
struct wpabuf * ieee802_1x_get_radius_cui(struct eapol_state_machine *sm)
|
||||
{
|
||||
if (sm == NULL)
|
||||
return NULL;
|
||||
return sm->radius_cui;
|
||||
}
|
||||
|
||||
|
||||
const u8 * ieee802_1x_get_key(struct eapol_state_machine *sm, size_t *len)
|
||||
{
|
||||
*len = 0;
|
||||
if (sm == NULL)
|
||||
return NULL;
|
||||
|
||||
@ -1848,6 +2061,7 @@ int ieee802_1x_get_mib_sta(struct hostapd_data *hapd, struct sta_info *sta,
|
||||
{
|
||||
int len = 0, ret;
|
||||
struct eapol_state_machine *sm = sta->eapol_sm;
|
||||
struct os_time t;
|
||||
|
||||
if (sm == NULL)
|
||||
return 0;
|
||||
@ -1962,6 +2176,7 @@ int ieee802_1x_get_mib_sta(struct hostapd_data *hapd, struct sta_info *sta,
|
||||
len += ret;
|
||||
|
||||
/* dot1xAuthSessionStatsTable */
|
||||
os_get_time(&t);
|
||||
ret = os_snprintf(buf + len, buflen - len,
|
||||
/* TODO: dot1xAuthSessionOctetsRx */
|
||||
/* TODO: dot1xAuthSessionOctetsTx */
|
||||
@ -1976,8 +2191,7 @@ int ieee802_1x_get_mib_sta(struct hostapd_data *hapd, struct sta_info *sta,
|
||||
(wpa_key_mgmt_wpa_ieee8021x(
|
||||
wpa_auth_sta_key_mgmt(sta->wpa_sm))) ?
|
||||
1 : 2,
|
||||
(unsigned int) (time(NULL) -
|
||||
sta->acct_session_start),
|
||||
(unsigned int) (t.sec - sta->acct_session_start),
|
||||
sm->identity);
|
||||
if (ret < 0 || (size_t) ret >= buflen - len)
|
||||
return len;
|
||||
@ -2004,22 +2218,25 @@ static void ieee802_1x_finished(struct hostapd_data *hapd,
|
||||
"Added PMKSA cache entry (IEEE 802.1X)");
|
||||
}
|
||||
|
||||
#ifdef CONFIG_WPS
|
||||
if (!success && (sta->flags & WLAN_STA_WPS)) {
|
||||
if (!success) {
|
||||
/*
|
||||
* Many devices require deauthentication after WPS provisioning
|
||||
* and some may not be be able to do that themselves, so
|
||||
* disconnect the client here.
|
||||
* disconnect the client here. In addition, this may also
|
||||
* benefit IEEE 802.1X/EAPOL authentication cases, too since
|
||||
* the EAPOL PAE state machine would remain in HELD state for
|
||||
* considerable amount of time and some EAP methods, like
|
||||
* EAP-FAST with anonymous provisioning, may require another
|
||||
* EAPOL authentication to be started to complete connection.
|
||||
*/
|
||||
wpa_printf(MSG_DEBUG, "WPS: Force disconnection after "
|
||||
"EAP-Failure");
|
||||
wpa_dbg(hapd->msg_ctx, MSG_DEBUG, "IEEE 802.1X: Force "
|
||||
"disconnection after EAP-Failure");
|
||||
/* Add a small sleep to increase likelihood of previously
|
||||
* requested EAP-Failure TX getting out before this should the
|
||||
* driver reorder operations.
|
||||
*/
|
||||
os_sleep(0, 10000);
|
||||
ap_sta_disconnect(hapd, sta, sta->addr,
|
||||
WLAN_REASON_PREV_AUTH_NOT_VALID);
|
||||
WLAN_REASON_IEEE_802_1X_AUTH_FAILED);
|
||||
}
|
||||
#endif /* CONFIG_WPS */
|
||||
}
|
||||
|
@ -1,15 +1,9 @@
|
||||
/*
|
||||
* hostapd / IEEE 802.1X-2004 Authenticator
|
||||
* Copyright (c) 2002-2007, Jouni Malinen <j@w1.fi>
|
||||
* Copyright (c) 2002-2012, Jouni Malinen <j@w1.fi>
|
||||
*
|
||||
* This program is free software; you can redistribute it and/or modify
|
||||
* it under the terms of the GNU General Public License version 2 as
|
||||
* published by the Free Software Foundation.
|
||||
*
|
||||
* Alternatively, this software may be distributed under the terms of BSD
|
||||
* license.
|
||||
*
|
||||
* See README and COPYING for more details.
|
||||
* This software may be distributed under the terms of the BSD license.
|
||||
* See README for more details.
|
||||
*/
|
||||
|
||||
#ifndef IEEE802_1X_H
|
||||
@ -20,38 +14,8 @@ struct sta_info;
|
||||
struct eapol_state_machine;
|
||||
struct hostapd_config;
|
||||
struct hostapd_bss_config;
|
||||
|
||||
#ifdef _MSC_VER
|
||||
#pragma pack(push, 1)
|
||||
#endif /* _MSC_VER */
|
||||
|
||||
/* RFC 3580, 4. RC4 EAPOL-Key Frame */
|
||||
|
||||
struct ieee802_1x_eapol_key {
|
||||
u8 type;
|
||||
u16 key_length;
|
||||
u8 replay_counter[8]; /* does not repeat within the life of the keying
|
||||
* material used to encrypt the Key field;
|
||||
* 64-bit NTP timestamp MAY be used here */
|
||||
u8 key_iv[16]; /* cryptographically random number */
|
||||
u8 key_index; /* key flag in the most significant bit:
|
||||
* 0 = broadcast (default key),
|
||||
* 1 = unicast (key mapping key); key index is in the
|
||||
* 7 least significant bits */
|
||||
u8 key_signature[16]; /* HMAC-MD5 message integrity check computed with
|
||||
* MS-MPPE-Send-Key as the key */
|
||||
|
||||
/* followed by key: if packet body length = 44 + key length, then the
|
||||
* key field (of key_length bytes) contains the key in encrypted form;
|
||||
* if packet body length = 44, key field is absent and key_length
|
||||
* represents the number of least significant octets from
|
||||
* MS-MPPE-Send-Key attribute to be used as the keying material;
|
||||
* RC4 key used in encryption = Key-IV + MS-MPPE-Recv-Key */
|
||||
} STRUCT_PACKED;
|
||||
|
||||
#ifdef _MSC_VER
|
||||
#pragma pack(pop)
|
||||
#endif /* _MSC_VER */
|
||||
struct hostapd_radius_attr;
|
||||
struct radius_msg;
|
||||
|
||||
|
||||
void ieee802_1x_receive(struct hostapd_data *hapd, const u8 *sa, const u8 *buf,
|
||||
@ -68,9 +32,12 @@ int ieee802_1x_init(struct hostapd_data *hapd);
|
||||
void ieee802_1x_deinit(struct hostapd_data *hapd);
|
||||
int ieee802_1x_tx_status(struct hostapd_data *hapd, struct sta_info *sta,
|
||||
const u8 *buf, size_t len, int ack);
|
||||
int ieee802_1x_eapol_tx_status(struct hostapd_data *hapd, struct sta_info *sta,
|
||||
const u8 *data, int len, int ack);
|
||||
u8 * ieee802_1x_get_identity(struct eapol_state_machine *sm, size_t *len);
|
||||
u8 * ieee802_1x_get_radius_class(struct eapol_state_machine *sm, size_t *len,
|
||||
int idx);
|
||||
struct wpabuf * ieee802_1x_get_radius_cui(struct eapol_state_machine *sm);
|
||||
const u8 * ieee802_1x_get_key(struct eapol_state_machine *sm, size_t *len);
|
||||
void ieee802_1x_notify_port_enabled(struct eapol_state_machine *sm,
|
||||
int enabled);
|
||||
@ -86,4 +53,9 @@ char *eap_type_text(u8 type);
|
||||
const char *radius_mode_txt(struct hostapd_data *hapd);
|
||||
int radius_sta_rate(struct hostapd_data *hapd, struct sta_info *sta);
|
||||
|
||||
int add_common_radius_attr(struct hostapd_data *hapd,
|
||||
struct hostapd_radius_attr *req_attr,
|
||||
struct sta_info *sta,
|
||||
struct radius_msg *msg);
|
||||
|
||||
#endif /* IEEE802_1X_H */
|
||||
|
114
contrib/wpa/src/ap/p2p_hostapd.c
Normal file
114
contrib/wpa/src/ap/p2p_hostapd.c
Normal file
@ -0,0 +1,114 @@
|
||||
/*
|
||||
* hostapd / P2P integration
|
||||
* Copyright (c) 2009-2010, Atheros Communications
|
||||
*
|
||||
* This software may be distributed under the terms of the BSD license.
|
||||
* See README for more details.
|
||||
*/
|
||||
|
||||
#include "utils/includes.h"
|
||||
|
||||
#include "utils/common.h"
|
||||
#include "common/ieee802_11_defs.h"
|
||||
#include "p2p/p2p.h"
|
||||
#include "hostapd.h"
|
||||
#include "ap_config.h"
|
||||
#include "ap_drv_ops.h"
|
||||
#include "sta_info.h"
|
||||
#include "p2p_hostapd.h"
|
||||
|
||||
|
||||
#ifdef CONFIG_P2P
|
||||
|
||||
int hostapd_p2p_get_mib_sta(struct hostapd_data *hapd, struct sta_info *sta,
|
||||
char *buf, size_t buflen)
|
||||
{
|
||||
if (sta->p2p_ie == NULL)
|
||||
return 0;
|
||||
|
||||
return p2p_ie_text(sta->p2p_ie, buf, buf + buflen);
|
||||
}
|
||||
|
||||
|
||||
int hostapd_p2p_set_noa(struct hostapd_data *hapd, u8 count, int start,
|
||||
int duration)
|
||||
{
|
||||
wpa_printf(MSG_DEBUG, "P2P: Set NoA parameters: count=%u start=%d "
|
||||
"duration=%d", count, start, duration);
|
||||
|
||||
if (count == 0) {
|
||||
hapd->noa_enabled = 0;
|
||||
hapd->noa_start = 0;
|
||||
hapd->noa_duration = 0;
|
||||
}
|
||||
|
||||
if (count != 255) {
|
||||
wpa_printf(MSG_DEBUG, "P2P: Non-periodic NoA - set "
|
||||
"NoA parameters");
|
||||
return hostapd_driver_set_noa(hapd, count, start, duration);
|
||||
}
|
||||
|
||||
hapd->noa_enabled = 1;
|
||||
hapd->noa_start = start;
|
||||
hapd->noa_duration = duration;
|
||||
|
||||
if (hapd->num_sta_no_p2p == 0) {
|
||||
wpa_printf(MSG_DEBUG, "P2P: No legacy STAs connected - update "
|
||||
"periodic NoA parameters");
|
||||
return hostapd_driver_set_noa(hapd, count, start, duration);
|
||||
}
|
||||
|
||||
wpa_printf(MSG_DEBUG, "P2P: Legacy STA(s) connected - do not enable "
|
||||
"periodic NoA");
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
|
||||
void hostapd_p2p_non_p2p_sta_connected(struct hostapd_data *hapd)
|
||||
{
|
||||
wpa_printf(MSG_DEBUG, "P2P: First non-P2P device connected");
|
||||
|
||||
if (hapd->noa_enabled) {
|
||||
wpa_printf(MSG_DEBUG, "P2P: Disable periodic NoA");
|
||||
hostapd_driver_set_noa(hapd, 0, 0, 0);
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
void hostapd_p2p_non_p2p_sta_disconnected(struct hostapd_data *hapd)
|
||||
{
|
||||
wpa_printf(MSG_DEBUG, "P2P: Last non-P2P device disconnected");
|
||||
|
||||
if (hapd->noa_enabled) {
|
||||
wpa_printf(MSG_DEBUG, "P2P: Enable periodic NoA");
|
||||
hostapd_driver_set_noa(hapd, 255, hapd->noa_start,
|
||||
hapd->noa_duration);
|
||||
}
|
||||
}
|
||||
|
||||
#endif /* CONFIG_P2P */
|
||||
|
||||
|
||||
#ifdef CONFIG_P2P_MANAGER
|
||||
u8 * hostapd_eid_p2p_manage(struct hostapd_data *hapd, u8 *eid)
|
||||
{
|
||||
u8 bitmap;
|
||||
*eid++ = WLAN_EID_VENDOR_SPECIFIC;
|
||||
*eid++ = 4 + 3 + 1;
|
||||
WPA_PUT_BE24(eid, OUI_WFA);
|
||||
eid += 3;
|
||||
*eid++ = P2P_OUI_TYPE;
|
||||
|
||||
*eid++ = P2P_ATTR_MANAGEABILITY;
|
||||
WPA_PUT_LE16(eid, 1);
|
||||
eid += 2;
|
||||
bitmap = P2P_MAN_DEVICE_MANAGEMENT;
|
||||
if (hapd->conf->p2p & P2P_ALLOW_CROSS_CONNECTION)
|
||||
bitmap |= P2P_MAN_CROSS_CONNECTION_PERMITTED;
|
||||
bitmap |= P2P_MAN_COEXISTENCE_OPTIONAL;
|
||||
*eid++ = bitmap;
|
||||
|
||||
return eid;
|
||||
}
|
||||
#endif /* CONFIG_P2P_MANAGER */
|
35
contrib/wpa/src/ap/p2p_hostapd.h
Normal file
35
contrib/wpa/src/ap/p2p_hostapd.h
Normal file
@ -0,0 +1,35 @@
|
||||
/*
|
||||
* hostapd / P2P integration
|
||||
* Copyright (c) 2009-2010, Atheros Communications
|
||||
*
|
||||
* This software may be distributed under the terms of the BSD license.
|
||||
* See README for more details.
|
||||
*/
|
||||
|
||||
#ifndef P2P_HOSTAPD_H
|
||||
#define P2P_HOSTAPD_H
|
||||
|
||||
#ifdef CONFIG_P2P
|
||||
|
||||
int hostapd_p2p_get_mib_sta(struct hostapd_data *hapd, struct sta_info *sta,
|
||||
char *buf, size_t buflen);
|
||||
int hostapd_p2p_set_noa(struct hostapd_data *hapd, u8 count, int start,
|
||||
int duration);
|
||||
void hostapd_p2p_non_p2p_sta_connected(struct hostapd_data *hapd);
|
||||
void hostapd_p2p_non_p2p_sta_disconnected(struct hostapd_data *hapd);
|
||||
|
||||
|
||||
#else /* CONFIG_P2P */
|
||||
|
||||
static inline int hostapd_p2p_get_mib_sta(struct hostapd_data *hapd,
|
||||
struct sta_info *sta,
|
||||
char *buf, size_t buflen)
|
||||
{
|
||||
return 0;
|
||||
}
|
||||
|
||||
#endif /* CONFIG_P2P */
|
||||
|
||||
u8 * hostapd_eid_p2p_manage(struct hostapd_data *hapd, u8 *eid);
|
||||
|
||||
#endif /* P2P_HOSTAPD_H */
|
@ -2,14 +2,8 @@
|
||||
* hostapd - PeerKey for Direct Link Setup (DLS)
|
||||
* Copyright (c) 2006-2009, Jouni Malinen <j@w1.fi>
|
||||
*
|
||||
* This program is free software; you can redistribute it and/or modify
|
||||
* it under the terms of the GNU General Public License version 2 as
|
||||
* published by the Free Software Foundation.
|
||||
*
|
||||
* Alternatively, this software may be distributed under the terms of BSD
|
||||
* license.
|
||||
*
|
||||
* See README and COPYING for more details.
|
||||
* This software may be distributed under the terms of the BSD license.
|
||||
* See README for more details.
|
||||
*/
|
||||
|
||||
#include "utils/includes.h"
|
||||
@ -18,6 +12,7 @@
|
||||
#include "utils/eloop.h"
|
||||
#include "crypto/sha1.h"
|
||||
#include "crypto/sha256.h"
|
||||
#include "crypto/random.h"
|
||||
#include "wpa_auth.h"
|
||||
#include "wpa_auth_i.h"
|
||||
#include "wpa_auth_ie.h"
|
||||
@ -294,7 +289,7 @@ void wpa_smk_m3(struct wpa_authenticator *wpa_auth,
|
||||
return;
|
||||
}
|
||||
|
||||
if (os_get_random(smk, PMK_LEN)) {
|
||||
if (random_get_bytes(smk, PMK_LEN)) {
|
||||
wpa_printf(MSG_DEBUG, "RSN: Failed to generate SMK");
|
||||
return;
|
||||
}
|
||||
|
@ -1,15 +1,9 @@
|
||||
/*
|
||||
* hostapd - PMKSA cache for IEEE 802.11i RSN
|
||||
* Copyright (c) 2004-2008, Jouni Malinen <j@w1.fi>
|
||||
* Copyright (c) 2004-2008, 2012, Jouni Malinen <j@w1.fi>
|
||||
*
|
||||
* This program is free software; you can redistribute it and/or modify
|
||||
* it under the terms of the GNU General Public License version 2 as
|
||||
* published by the Free Software Foundation.
|
||||
*
|
||||
* Alternatively, this software may be distributed under the terms of BSD
|
||||
* license.
|
||||
*
|
||||
* See README and COPYING for more details.
|
||||
* This software may be distributed under the terms of the BSD license.
|
||||
* See README for more details.
|
||||
*/
|
||||
|
||||
#include "utils/includes.h"
|
||||
@ -46,6 +40,7 @@ static void _pmksa_cache_free_entry(struct rsn_pmksa_cache_entry *entry)
|
||||
if (entry == NULL)
|
||||
return;
|
||||
os_free(entry->identity);
|
||||
wpabuf_free(entry->cui);
|
||||
#ifndef CONFIG_NO_RADIUS
|
||||
radius_free_class(&entry->radius_class);
|
||||
#endif /* CONFIG_NO_RADIUS */
|
||||
@ -100,11 +95,9 @@ static void pmksa_cache_expire(void *eloop_ctx, void *timeout_ctx)
|
||||
|
||||
os_get_time(&now);
|
||||
while (pmksa->pmksa && pmksa->pmksa->expiration <= now.sec) {
|
||||
struct rsn_pmksa_cache_entry *entry = pmksa->pmksa;
|
||||
pmksa->pmksa = entry->next;
|
||||
wpa_printf(MSG_DEBUG, "RSN: expired PMKSA cache entry for "
|
||||
MACSTR, MAC2STR(entry->spa));
|
||||
pmksa_cache_free_entry(pmksa, entry);
|
||||
MACSTR, MAC2STR(pmksa->pmksa->spa));
|
||||
pmksa_cache_free_entry(pmksa, pmksa->pmksa);
|
||||
}
|
||||
|
||||
pmksa_cache_set_expiration(pmksa);
|
||||
@ -142,6 +135,9 @@ static void pmksa_cache_from_eapol_data(struct rsn_pmksa_cache_entry *entry,
|
||||
}
|
||||
}
|
||||
|
||||
if (eapol->radius_cui)
|
||||
entry->cui = wpabuf_dup(eapol->radius_cui);
|
||||
|
||||
#ifndef CONFIG_NO_RADIUS
|
||||
radius_copy_class(&entry->radius_class, &eapol->radius_class);
|
||||
#endif /* CONFIG_NO_RADIUS */
|
||||
@ -169,6 +165,11 @@ void pmksa_cache_to_eapol_data(struct rsn_pmksa_cache_entry *entry,
|
||||
eapol->identity, eapol->identity_len);
|
||||
}
|
||||
|
||||
if (entry->cui) {
|
||||
wpabuf_free(eapol->radius_cui);
|
||||
eapol->radius_cui = wpabuf_dup(entry->cui);
|
||||
}
|
||||
|
||||
#ifndef CONFIG_NO_RADIUS
|
||||
radius_free_class(&eapol->radius_class);
|
||||
radius_copy_class(&eapol->radius_class, &entry->radius_class);
|
||||
@ -208,6 +209,8 @@ static void pmksa_cache_link_entry(struct rsn_pmksa_cache *pmksa,
|
||||
pmksa->pmkid[PMKID_HASH(entry->pmkid)] = entry;
|
||||
|
||||
pmksa->pmksa_count++;
|
||||
if (prev == NULL)
|
||||
pmksa_cache_set_expiration(pmksa);
|
||||
wpa_printf(MSG_DEBUG, "RSN: added PMKSA cache entry for " MACSTR,
|
||||
MAC2STR(entry->spa));
|
||||
wpa_hexdump(MSG_DEBUG, "RSN: added PMKID", entry->pmkid, PMKID_LEN);
|
||||
@ -305,6 +308,8 @@ pmksa_cache_add_okc(struct rsn_pmksa_cache *pmksa,
|
||||
old_entry->identity_len);
|
||||
}
|
||||
}
|
||||
if (old_entry->cui)
|
||||
entry->cui = wpabuf_dup(old_entry->cui);
|
||||
#ifndef CONFIG_NO_RADIUS
|
||||
radius_copy_class(&entry->radius_class, &old_entry->radius_class);
|
||||
#endif /* CONFIG_NO_RADIUS */
|
||||
|
@ -1,15 +1,9 @@
|
||||
/*
|
||||
* hostapd - PMKSA cache for IEEE 802.11i RSN
|
||||
* Copyright (c) 2004-2008, Jouni Malinen <j@w1.fi>
|
||||
* Copyright (c) 2004-2008, 2012, Jouni Malinen <j@w1.fi>
|
||||
*
|
||||
* This program is free software; you can redistribute it and/or modify
|
||||
* it under the terms of the GNU General Public License version 2 as
|
||||
* published by the Free Software Foundation.
|
||||
*
|
||||
* Alternatively, this software may be distributed under the terms of BSD
|
||||
* license.
|
||||
*
|
||||
* See README and COPYING for more details.
|
||||
* This software may be distributed under the terms of the BSD license.
|
||||
* See README for more details.
|
||||
*/
|
||||
|
||||
#ifndef PMKSA_CACHE_H
|
||||
@ -31,6 +25,7 @@ struct rsn_pmksa_cache_entry {
|
||||
|
||||
u8 *identity;
|
||||
size_t identity_len;
|
||||
struct wpabuf *cui;
|
||||
struct radius_class_data radius_class;
|
||||
u8 eap_type_authsrv;
|
||||
int vlan_id;
|
||||
|
@ -2,14 +2,8 @@
|
||||
* hostapd - Authenticator for IEEE 802.11i RSN pre-authentication
|
||||
* Copyright (c) 2004-2007, Jouni Malinen <j@w1.fi>
|
||||
*
|
||||
* This program is free software; you can redistribute it and/or modify
|
||||
* it under the terms of the GNU General Public License version 2 as
|
||||
* published by the Free Software Foundation.
|
||||
*
|
||||
* Alternatively, this software may be distributed under the terms of BSD
|
||||
* license.
|
||||
*
|
||||
* See README and COPYING for more details.
|
||||
* This software may be distributed under the terms of the BSD license.
|
||||
* See README for more details.
|
||||
*/
|
||||
|
||||
#include "utils/includes.h"
|
||||
|
@ -2,14 +2,8 @@
|
||||
* hostapd - Authenticator for IEEE 802.11i RSN pre-authentication
|
||||
* Copyright (c) 2004-2005, Jouni Malinen <j@w1.fi>
|
||||
*
|
||||
* This program is free software; you can redistribute it and/or modify
|
||||
* it under the terms of the GNU General Public License version 2 as
|
||||
* published by the Free Software Foundation.
|
||||
*
|
||||
* Alternatively, this software may be distributed under the terms of BSD
|
||||
* license.
|
||||
*
|
||||
* See README and COPYING for more details.
|
||||
* This software may be distributed under the terms of the BSD license.
|
||||
* See README for more details.
|
||||
*/
|
||||
|
||||
#ifndef PREAUTH_H
|
||||
|
@ -1,15 +1,9 @@
|
||||
/*
|
||||
* hostapd / Station table
|
||||
* Copyright (c) 2002-2009, Jouni Malinen <j@w1.fi>
|
||||
* Copyright (c) 2002-2011, Jouni Malinen <j@w1.fi>
|
||||
*
|
||||
* This program is free software; you can redistribute it and/or modify
|
||||
* it under the terms of the GNU General Public License version 2 as
|
||||
* published by the Free Software Foundation.
|
||||
*
|
||||
* Alternatively, this software may be distributed under the terms of BSD
|
||||
* license.
|
||||
*
|
||||
* See README and COPYING for more details.
|
||||
* This software may be distributed under the terms of the BSD license.
|
||||
* See README for more details.
|
||||
*/
|
||||
|
||||
#include "utils/includes.h"
|
||||
@ -17,27 +11,36 @@
|
||||
#include "utils/common.h"
|
||||
#include "utils/eloop.h"
|
||||
#include "common/ieee802_11_defs.h"
|
||||
#include "common/wpa_ctrl.h"
|
||||
#include "radius/radius.h"
|
||||
#include "radius/radius_client.h"
|
||||
#include "drivers/driver.h"
|
||||
#include "p2p/p2p.h"
|
||||
#include "hostapd.h"
|
||||
#include "accounting.h"
|
||||
#include "ieee802_1x.h"
|
||||
#include "ieee802_11.h"
|
||||
#include "ieee802_11_auth.h"
|
||||
#include "wpa_auth.h"
|
||||
#include "preauth_auth.h"
|
||||
#include "ap_config.h"
|
||||
#include "beacon.h"
|
||||
#include "ap_mlme.h"
|
||||
#include "vlan_init.h"
|
||||
#include "p2p_hostapd.h"
|
||||
#include "ap_drv_ops.h"
|
||||
#include "gas_serv.h"
|
||||
#include "sta_info.h"
|
||||
|
||||
static void ap_sta_remove_in_other_bss(struct hostapd_data *hapd,
|
||||
struct sta_info *sta);
|
||||
static void ap_handle_session_timer(void *eloop_ctx, void *timeout_ctx);
|
||||
static void ap_sta_deauth_cb_timeout(void *eloop_ctx, void *timeout_ctx);
|
||||
static void ap_sta_disassoc_cb_timeout(void *eloop_ctx, void *timeout_ctx);
|
||||
#ifdef CONFIG_IEEE80211W
|
||||
static void ap_sa_query_timer(void *eloop_ctx, void *timeout_ctx);
|
||||
#endif /* CONFIG_IEEE80211W */
|
||||
static int ap_sta_remove(struct hostapd_data *hapd, struct sta_info *sta);
|
||||
|
||||
int ap_for_each_sta(struct hostapd_data *hapd,
|
||||
int (*cb)(struct hostapd_data *hapd, struct sta_info *sta,
|
||||
@ -121,11 +124,14 @@ void ap_free_sta(struct hostapd_data *hapd, struct sta_info *sta)
|
||||
|
||||
accounting_sta_stop(hapd, sta);
|
||||
|
||||
/* just in case */
|
||||
ap_sta_set_authorized(hapd, sta, 0);
|
||||
|
||||
if (sta->flags & WLAN_STA_WDS)
|
||||
hapd->drv.set_wds_sta(hapd, sta->addr, sta->aid, 0);
|
||||
hostapd_set_wds_sta(hapd, sta->addr, sta->aid, 0);
|
||||
|
||||
if (!(sta->flags & WLAN_STA_PREAUTH))
|
||||
hapd->drv.sta_remove(hapd, sta->addr);
|
||||
hostapd_drv_sta_remove(hapd, sta->addr);
|
||||
|
||||
ap_sta_hash_del(hapd, sta);
|
||||
ap_sta_list_del(hapd, sta);
|
||||
@ -173,6 +179,15 @@ void ap_free_sta(struct hostapd_data *hapd, struct sta_info *sta)
|
||||
hapd->iface->num_sta_ht_20mhz--;
|
||||
}
|
||||
|
||||
#ifdef CONFIG_P2P
|
||||
if (sta->no_p2p_set) {
|
||||
sta->no_p2p_set = 0;
|
||||
hapd->num_sta_no_p2p--;
|
||||
if (hapd->num_sta_no_p2p == 0)
|
||||
hostapd_p2p_non_p2p_sta_disconnected(hapd);
|
||||
}
|
||||
#endif /* CONFIG_P2P */
|
||||
|
||||
#if defined(NEED_AP_MLME) && defined(CONFIG_IEEE80211N)
|
||||
if (hostapd_ht_operation_update(hapd->iface) > 0)
|
||||
set_beacon++;
|
||||
@ -181,8 +196,12 @@ void ap_free_sta(struct hostapd_data *hapd, struct sta_info *sta)
|
||||
if (set_beacon)
|
||||
ieee802_11_set_beacons(hapd->iface);
|
||||
|
||||
wpa_printf(MSG_DEBUG, "%s: cancel ap_handle_timer for " MACSTR,
|
||||
__func__, MAC2STR(sta->addr));
|
||||
eloop_cancel_timeout(ap_handle_timer, hapd, sta);
|
||||
eloop_cancel_timeout(ap_handle_session_timer, hapd, sta);
|
||||
eloop_cancel_timeout(ap_sta_deauth_cb_timeout, hapd, sta);
|
||||
eloop_cancel_timeout(ap_sta_disassoc_cb_timeout, hapd, sta);
|
||||
|
||||
ieee802_1x_free_station(sta);
|
||||
wpa_auth_sta_deinit(sta->wpa_sm);
|
||||
@ -199,9 +218,27 @@ void ap_free_sta(struct hostapd_data *hapd, struct sta_info *sta)
|
||||
eloop_cancel_timeout(ap_sa_query_timer, hapd, sta);
|
||||
#endif /* CONFIG_IEEE80211W */
|
||||
|
||||
#ifdef CONFIG_P2P
|
||||
p2p_group_notif_disassoc(hapd->p2p_group, sta->addr);
|
||||
#endif /* CONFIG_P2P */
|
||||
|
||||
#ifdef CONFIG_INTERWORKING
|
||||
if (sta->gas_dialog) {
|
||||
int i;
|
||||
for (i = 0; i < GAS_DIALOG_MAX; i++)
|
||||
gas_serv_dialog_clear(&sta->gas_dialog[i]);
|
||||
os_free(sta->gas_dialog);
|
||||
}
|
||||
#endif /* CONFIG_INTERWORKING */
|
||||
|
||||
wpabuf_free(sta->wps_ie);
|
||||
wpabuf_free(sta->p2p_ie);
|
||||
wpabuf_free(sta->hs20_ie);
|
||||
|
||||
os_free(sta->ht_capabilities);
|
||||
hostapd_free_psk_list(sta->psk);
|
||||
os_free(sta->identity);
|
||||
os_free(sta->radius_cui);
|
||||
|
||||
os_free(sta);
|
||||
}
|
||||
@ -241,6 +278,9 @@ void ap_handle_timer(void *eloop_ctx, void *timeout_ctx)
|
||||
struct sta_info *sta = timeout_ctx;
|
||||
unsigned long next_time = 0;
|
||||
|
||||
wpa_printf(MSG_DEBUG, "%s: " MACSTR " flags=0x%x timeout_next=%d",
|
||||
__func__, MAC2STR(sta->addr), sta->flags,
|
||||
sta->timeout_next);
|
||||
if (sta->timeout_next == STA_REMOVE) {
|
||||
hostapd_logger(hapd, sta->addr, HOSTAPD_MODULE_IEEE80211,
|
||||
HOSTAPD_LEVEL_INFO, "deauthenticated due to "
|
||||
@ -253,27 +293,51 @@ void ap_handle_timer(void *eloop_ctx, void *timeout_ctx)
|
||||
(sta->timeout_next == STA_NULLFUNC ||
|
||||
sta->timeout_next == STA_DISASSOC)) {
|
||||
int inactive_sec;
|
||||
wpa_printf(MSG_DEBUG, "Checking STA " MACSTR " inactivity:",
|
||||
MAC2STR(sta->addr));
|
||||
inactive_sec = hapd->drv.get_inact_sec(hapd, sta->addr);
|
||||
/*
|
||||
* Add random value to timeout so that we don't end up bouncing
|
||||
* all stations at the same time if we have lots of associated
|
||||
* stations that are idle (but keep re-associating).
|
||||
*/
|
||||
int fuzz = os_random() % 20;
|
||||
inactive_sec = hostapd_drv_get_inact_sec(hapd, sta->addr);
|
||||
if (inactive_sec == -1) {
|
||||
wpa_printf(MSG_DEBUG, "Could not get station info "
|
||||
"from kernel driver for " MACSTR ".",
|
||||
MAC2STR(sta->addr));
|
||||
wpa_msg(hapd->msg_ctx, MSG_DEBUG,
|
||||
"Check inactivity: Could not "
|
||||
"get station info from kernel driver for "
|
||||
MACSTR, MAC2STR(sta->addr));
|
||||
/*
|
||||
* The driver may not support this functionality.
|
||||
* Anyway, try again after the next inactivity timeout,
|
||||
* but do not disconnect the station now.
|
||||
*/
|
||||
next_time = hapd->conf->ap_max_inactivity + fuzz;
|
||||
} else if (inactive_sec < hapd->conf->ap_max_inactivity &&
|
||||
sta->flags & WLAN_STA_ASSOC) {
|
||||
/* station activity detected; reset timeout state */
|
||||
wpa_printf(MSG_DEBUG, " Station has been active");
|
||||
wpa_msg(hapd->msg_ctx, MSG_DEBUG,
|
||||
"Station " MACSTR " has been active %is ago",
|
||||
MAC2STR(sta->addr), inactive_sec);
|
||||
sta->timeout_next = STA_NULLFUNC;
|
||||
next_time = hapd->conf->ap_max_inactivity -
|
||||
next_time = hapd->conf->ap_max_inactivity + fuzz -
|
||||
inactive_sec;
|
||||
} else {
|
||||
wpa_msg(hapd->msg_ctx, MSG_DEBUG,
|
||||
"Station " MACSTR " has been "
|
||||
"inactive too long: %d sec, max allowed: %d",
|
||||
MAC2STR(sta->addr), inactive_sec,
|
||||
hapd->conf->ap_max_inactivity);
|
||||
|
||||
if (hapd->conf->skip_inactivity_poll)
|
||||
sta->timeout_next = STA_DISASSOC;
|
||||
}
|
||||
}
|
||||
|
||||
if ((sta->flags & WLAN_STA_ASSOC) &&
|
||||
sta->timeout_next == STA_DISASSOC &&
|
||||
!(sta->flags & WLAN_STA_PENDING_POLL)) {
|
||||
wpa_printf(MSG_DEBUG, " Station has ACKed data poll");
|
||||
!(sta->flags & WLAN_STA_PENDING_POLL) &&
|
||||
!hapd->conf->skip_inactivity_poll) {
|
||||
wpa_msg(hapd->msg_ctx, MSG_DEBUG, "Station " MACSTR
|
||||
" has ACKed data poll", MAC2STR(sta->addr));
|
||||
/* data nullfunc frame poll did not produce TX errors; assume
|
||||
* station ACKed it */
|
||||
sta->timeout_next = STA_NULLFUNC;
|
||||
@ -281,6 +345,9 @@ void ap_handle_timer(void *eloop_ctx, void *timeout_ctx)
|
||||
}
|
||||
|
||||
if (next_time) {
|
||||
wpa_printf(MSG_DEBUG, "%s: register ap_handle_timer timeout "
|
||||
"for " MACSTR " (%lu seconds)",
|
||||
__func__, MAC2STR(sta->addr), next_time);
|
||||
eloop_register_timeout(next_time, 0, ap_handle_timer, hapd,
|
||||
sta);
|
||||
return;
|
||||
@ -288,52 +355,24 @@ void ap_handle_timer(void *eloop_ctx, void *timeout_ctx)
|
||||
|
||||
if (sta->timeout_next == STA_NULLFUNC &&
|
||||
(sta->flags & WLAN_STA_ASSOC)) {
|
||||
#ifndef CONFIG_NATIVE_WINDOWS
|
||||
/* send data frame to poll STA and check whether this frame
|
||||
* is ACKed */
|
||||
struct ieee80211_hdr hdr;
|
||||
|
||||
wpa_printf(MSG_DEBUG, " Polling STA with data frame");
|
||||
wpa_printf(MSG_DEBUG, " Polling STA");
|
||||
sta->flags |= WLAN_STA_PENDING_POLL;
|
||||
|
||||
os_memset(&hdr, 0, sizeof(hdr));
|
||||
if (hapd->driver &&
|
||||
os_strcmp(hapd->driver->name, "hostap") == 0) {
|
||||
/*
|
||||
* WLAN_FC_STYPE_NULLFUNC would be more appropriate,
|
||||
* but it is apparently not retried so TX Exc events
|
||||
* are not received for it.
|
||||
*/
|
||||
hdr.frame_control =
|
||||
IEEE80211_FC(WLAN_FC_TYPE_DATA,
|
||||
WLAN_FC_STYPE_DATA);
|
||||
} else {
|
||||
hdr.frame_control =
|
||||
IEEE80211_FC(WLAN_FC_TYPE_DATA,
|
||||
WLAN_FC_STYPE_NULLFUNC);
|
||||
}
|
||||
|
||||
hdr.frame_control |= host_to_le16(WLAN_FC_FROMDS);
|
||||
os_memcpy(hdr.IEEE80211_DA_FROMDS, sta->addr, ETH_ALEN);
|
||||
os_memcpy(hdr.IEEE80211_BSSID_FROMDS, hapd->own_addr,
|
||||
ETH_ALEN);
|
||||
os_memcpy(hdr.IEEE80211_SA_FROMDS, hapd->own_addr, ETH_ALEN);
|
||||
|
||||
if (hapd->drv.send_mgmt_frame(hapd, &hdr, sizeof(hdr)) < 0)
|
||||
perror("ap_handle_timer: send");
|
||||
#endif /* CONFIG_NATIVE_WINDOWS */
|
||||
hostapd_drv_poll_client(hapd, hapd->own_addr, sta->addr,
|
||||
sta->flags & WLAN_STA_WMM);
|
||||
} else if (sta->timeout_next != STA_REMOVE) {
|
||||
int deauth = sta->timeout_next == STA_DEAUTH;
|
||||
|
||||
wpa_printf(MSG_DEBUG, "Sending %s info to STA " MACSTR,
|
||||
deauth ? "deauthentication" : "disassociation",
|
||||
MAC2STR(sta->addr));
|
||||
wpa_dbg(hapd->msg_ctx, MSG_DEBUG,
|
||||
"Timeout, sending %s info to STA " MACSTR,
|
||||
deauth ? "deauthentication" : "disassociation",
|
||||
MAC2STR(sta->addr));
|
||||
|
||||
if (deauth) {
|
||||
hapd->drv.sta_deauth(hapd, sta->addr,
|
||||
WLAN_REASON_PREV_AUTH_NOT_VALID);
|
||||
hostapd_drv_sta_deauth(
|
||||
hapd, sta->addr,
|
||||
WLAN_REASON_PREV_AUTH_NOT_VALID);
|
||||
} else {
|
||||
hapd->drv.sta_disassoc(
|
||||
hostapd_drv_sta_disassoc(
|
||||
hapd, sta->addr,
|
||||
WLAN_REASON_DISASSOC_DUE_TO_INACTIVITY);
|
||||
}
|
||||
@ -342,10 +381,14 @@ void ap_handle_timer(void *eloop_ctx, void *timeout_ctx)
|
||||
switch (sta->timeout_next) {
|
||||
case STA_NULLFUNC:
|
||||
sta->timeout_next = STA_DISASSOC;
|
||||
wpa_printf(MSG_DEBUG, "%s: register ap_handle_timer timeout "
|
||||
"for " MACSTR " (%d seconds - AP_DISASSOC_DELAY)",
|
||||
__func__, MAC2STR(sta->addr), AP_DISASSOC_DELAY);
|
||||
eloop_register_timeout(AP_DISASSOC_DELAY, 0, ap_handle_timer,
|
||||
hapd, sta);
|
||||
break;
|
||||
case STA_DISASSOC:
|
||||
ap_sta_set_authorized(hapd, sta, 0);
|
||||
sta->flags &= ~WLAN_STA_ASSOC;
|
||||
ieee802_1x_notify_port_enabled(sta->eapol_sm, 0);
|
||||
if (!sta->acct_terminate_cause)
|
||||
@ -357,6 +400,9 @@ void ap_handle_timer(void *eloop_ctx, void *timeout_ctx)
|
||||
HOSTAPD_LEVEL_INFO, "disassociated due to "
|
||||
"inactivity");
|
||||
sta->timeout_next = STA_DEAUTH;
|
||||
wpa_printf(MSG_DEBUG, "%s: register ap_handle_timer timeout "
|
||||
"for " MACSTR " (%d seconds - AP_DEAUTH_DELAY)",
|
||||
__func__, MAC2STR(sta->addr), AP_DEAUTH_DELAY);
|
||||
eloop_register_timeout(AP_DEAUTH_DELAY, 0, ap_handle_timer,
|
||||
hapd, sta);
|
||||
mlme_disassociate_indication(
|
||||
@ -366,7 +412,7 @@ void ap_handle_timer(void *eloop_ctx, void *timeout_ctx)
|
||||
case STA_REMOVE:
|
||||
hostapd_logger(hapd, sta->addr, HOSTAPD_MODULE_IEEE80211,
|
||||
HOSTAPD_LEVEL_INFO, "deauthenticated due to "
|
||||
"inactivity");
|
||||
"inactivity (timer DEAUTH/REMOVE)");
|
||||
if (!sta->acct_terminate_cause)
|
||||
sta->acct_terminate_cause =
|
||||
RADIUS_ACCT_TERMINATE_CAUSE_IDLE_TIMEOUT;
|
||||
@ -385,8 +431,14 @@ static void ap_handle_session_timer(void *eloop_ctx, void *timeout_ctx)
|
||||
struct sta_info *sta = timeout_ctx;
|
||||
u8 addr[ETH_ALEN];
|
||||
|
||||
if (!(sta->flags & WLAN_STA_AUTH))
|
||||
if (!(sta->flags & WLAN_STA_AUTH)) {
|
||||
if (sta->flags & WLAN_STA_GAS) {
|
||||
wpa_printf(MSG_DEBUG, "GAS: Remove temporary STA "
|
||||
"entry " MACSTR, MAC2STR(sta->addr));
|
||||
ap_free_sta(hapd, sta);
|
||||
}
|
||||
return;
|
||||
}
|
||||
|
||||
mlme_deauthenticate_indication(hapd, sta,
|
||||
WLAN_REASON_PREV_AUTH_NOT_VALID);
|
||||
@ -397,7 +449,7 @@ static void ap_handle_session_timer(void *eloop_ctx, void *timeout_ctx)
|
||||
RADIUS_ACCT_TERMINATE_CAUSE_SESSION_TIMEOUT;
|
||||
os_memcpy(addr, sta->addr, ETH_ALEN);
|
||||
ap_free_sta(hapd, sta);
|
||||
hapd->drv.sta_deauth(hapd, addr, WLAN_REASON_PREV_AUTH_NOT_VALID);
|
||||
hostapd_drv_sta_deauth(hapd, addr, WLAN_REASON_PREV_AUTH_NOT_VALID);
|
||||
}
|
||||
|
||||
|
||||
@ -441,8 +493,13 @@ struct sta_info * ap_sta_add(struct hostapd_data *hapd, const u8 *addr)
|
||||
return NULL;
|
||||
}
|
||||
sta->acct_interim_interval = hapd->conf->acct_interim_interval;
|
||||
accounting_sta_get_id(hapd, sta);
|
||||
|
||||
/* initialize STA info data */
|
||||
wpa_printf(MSG_DEBUG, "%s: register ap_handle_timer timeout "
|
||||
"for " MACSTR " (%d seconds - ap_max_inactivity)",
|
||||
__func__, MAC2STR(addr),
|
||||
hapd->conf->ap_max_inactivity);
|
||||
eloop_register_timeout(hapd->conf->ap_max_inactivity, 0,
|
||||
ap_handle_timer, hapd, sta);
|
||||
os_memcpy(sta->addr, addr, ETH_ALEN);
|
||||
@ -463,7 +520,7 @@ static int ap_sta_remove(struct hostapd_data *hapd, struct sta_info *sta)
|
||||
|
||||
wpa_printf(MSG_DEBUG, "Removing STA " MACSTR " from kernel driver",
|
||||
MAC2STR(sta->addr));
|
||||
if (hapd->drv.sta_remove(hapd, sta->addr) &&
|
||||
if (hostapd_drv_sta_remove(hapd, sta->addr) &&
|
||||
sta->flags & WLAN_STA_ASSOC) {
|
||||
wpa_printf(MSG_DEBUG, "Could not remove station " MACSTR
|
||||
" from kernel driver.", MAC2STR(sta->addr));
|
||||
@ -498,21 +555,51 @@ static void ap_sta_remove_in_other_bss(struct hostapd_data *hapd,
|
||||
}
|
||||
|
||||
|
||||
static void ap_sta_disassoc_cb_timeout(void *eloop_ctx, void *timeout_ctx)
|
||||
{
|
||||
struct hostapd_data *hapd = eloop_ctx;
|
||||
struct sta_info *sta = timeout_ctx;
|
||||
|
||||
ap_sta_remove(hapd, sta);
|
||||
mlme_disassociate_indication(hapd, sta, sta->disassoc_reason);
|
||||
}
|
||||
|
||||
|
||||
void ap_sta_disassociate(struct hostapd_data *hapd, struct sta_info *sta,
|
||||
u16 reason)
|
||||
{
|
||||
wpa_printf(MSG_DEBUG, "%s: disassociate STA " MACSTR,
|
||||
hapd->conf->iface, MAC2STR(sta->addr));
|
||||
sta->flags &= ~WLAN_STA_ASSOC;
|
||||
ap_sta_remove(hapd, sta);
|
||||
ap_sta_set_authorized(hapd, sta, 0);
|
||||
sta->timeout_next = STA_DEAUTH;
|
||||
wpa_printf(MSG_DEBUG, "%s: reschedule ap_handle_timer timeout "
|
||||
"for " MACSTR " (%d seconds - "
|
||||
"AP_MAX_INACTIVITY_AFTER_DISASSOC)",
|
||||
__func__, MAC2STR(sta->addr),
|
||||
AP_MAX_INACTIVITY_AFTER_DISASSOC);
|
||||
eloop_cancel_timeout(ap_handle_timer, hapd, sta);
|
||||
eloop_register_timeout(AP_MAX_INACTIVITY_AFTER_DISASSOC, 0,
|
||||
ap_handle_timer, hapd, sta);
|
||||
accounting_sta_stop(hapd, sta);
|
||||
ieee802_1x_free_station(sta);
|
||||
|
||||
mlme_disassociate_indication(hapd, sta, reason);
|
||||
sta->disassoc_reason = reason;
|
||||
sta->flags |= WLAN_STA_PENDING_DISASSOC_CB;
|
||||
eloop_cancel_timeout(ap_sta_disassoc_cb_timeout, hapd, sta);
|
||||
eloop_register_timeout(hapd->iface->drv_flags &
|
||||
WPA_DRIVER_FLAGS_DEAUTH_TX_STATUS ? 2 : 0, 0,
|
||||
ap_sta_disassoc_cb_timeout, hapd, sta);
|
||||
}
|
||||
|
||||
|
||||
static void ap_sta_deauth_cb_timeout(void *eloop_ctx, void *timeout_ctx)
|
||||
{
|
||||
struct hostapd_data *hapd = eloop_ctx;
|
||||
struct sta_info *sta = timeout_ctx;
|
||||
|
||||
ap_sta_remove(hapd, sta);
|
||||
mlme_deauthenticate_indication(hapd, sta, sta->deauth_reason);
|
||||
}
|
||||
|
||||
|
||||
@ -522,18 +609,45 @@ void ap_sta_deauthenticate(struct hostapd_data *hapd, struct sta_info *sta,
|
||||
wpa_printf(MSG_DEBUG, "%s: deauthenticate STA " MACSTR,
|
||||
hapd->conf->iface, MAC2STR(sta->addr));
|
||||
sta->flags &= ~(WLAN_STA_AUTH | WLAN_STA_ASSOC);
|
||||
ap_sta_remove(hapd, sta);
|
||||
ap_sta_set_authorized(hapd, sta, 0);
|
||||
sta->timeout_next = STA_REMOVE;
|
||||
wpa_printf(MSG_DEBUG, "%s: reschedule ap_handle_timer timeout "
|
||||
"for " MACSTR " (%d seconds - "
|
||||
"AP_MAX_INACTIVITY_AFTER_DEAUTH)",
|
||||
__func__, MAC2STR(sta->addr),
|
||||
AP_MAX_INACTIVITY_AFTER_DEAUTH);
|
||||
eloop_cancel_timeout(ap_handle_timer, hapd, sta);
|
||||
eloop_register_timeout(AP_MAX_INACTIVITY_AFTER_DEAUTH, 0,
|
||||
ap_handle_timer, hapd, sta);
|
||||
accounting_sta_stop(hapd, sta);
|
||||
ieee802_1x_free_station(sta);
|
||||
|
||||
mlme_deauthenticate_indication(hapd, sta, reason);
|
||||
sta->deauth_reason = reason;
|
||||
sta->flags |= WLAN_STA_PENDING_DEAUTH_CB;
|
||||
eloop_cancel_timeout(ap_sta_deauth_cb_timeout, hapd, sta);
|
||||
eloop_register_timeout(hapd->iface->drv_flags &
|
||||
WPA_DRIVER_FLAGS_DEAUTH_TX_STATUS ? 2 : 0, 0,
|
||||
ap_sta_deauth_cb_timeout, hapd, sta);
|
||||
}
|
||||
|
||||
|
||||
#ifdef CONFIG_WPS
|
||||
int ap_sta_wps_cancel(struct hostapd_data *hapd,
|
||||
struct sta_info *sta, void *ctx)
|
||||
{
|
||||
if (sta && (sta->flags & WLAN_STA_WPS)) {
|
||||
ap_sta_deauthenticate(hapd, sta,
|
||||
WLAN_REASON_PREV_AUTH_NOT_VALID);
|
||||
wpa_printf(MSG_DEBUG, "WPS: %s: Deauth sta=" MACSTR,
|
||||
__func__, MAC2STR(sta->addr));
|
||||
return 1;
|
||||
}
|
||||
|
||||
return 0;
|
||||
}
|
||||
#endif /* CONFIG_WPS */
|
||||
|
||||
|
||||
int ap_sta_bind_vlan(struct hostapd_data *hapd, struct sta_info *sta,
|
||||
int old_vlanid)
|
||||
{
|
||||
@ -636,7 +750,7 @@ int ap_sta_bind_vlan(struct hostapd_data *hapd, struct sta_info *sta,
|
||||
if (wpa_auth_sta_set_vlan(sta->wpa_sm, sta->vlan_id) < 0)
|
||||
wpa_printf(MSG_INFO, "Failed to update VLAN-ID for WPA");
|
||||
|
||||
ret = hapd->drv.set_sta_vlan(iface, hapd, sta->addr, sta->vlan_id);
|
||||
ret = hostapd_drv_set_sta_vlan(iface, hapd, sta->addr, sta->vlan_id);
|
||||
if (ret < 0) {
|
||||
hostapd_logger(hapd, sta->addr, HOSTAPD_MODULE_IEEE80211,
|
||||
HOSTAPD_LEVEL_DEBUG, "could not bind the STA "
|
||||
@ -686,8 +800,9 @@ static void ap_sa_query_timer(void *eloop_ctx, void *timeout_ctx)
|
||||
ap_check_sa_query_timeout(hapd, sta))
|
||||
return;
|
||||
|
||||
nbuf = os_realloc(sta->sa_query_trans_id,
|
||||
(sta->sa_query_count + 1) * WLAN_SA_QUERY_TR_ID_LEN);
|
||||
nbuf = os_realloc_array(sta->sa_query_trans_id,
|
||||
sta->sa_query_count + 1,
|
||||
WLAN_SA_QUERY_TR_ID_LEN);
|
||||
if (nbuf == NULL)
|
||||
return;
|
||||
if (sta->sa_query_count == 0) {
|
||||
@ -709,9 +824,7 @@ static void ap_sa_query_timer(void *eloop_ctx, void *timeout_ctx)
|
||||
HOSTAPD_LEVEL_DEBUG,
|
||||
"association SA Query attempt %d", sta->sa_query_count);
|
||||
|
||||
#ifdef NEED_AP_MLME
|
||||
ieee802_11_send_sa_query_req(hapd, sta->addr, trans_id);
|
||||
#endif /* NEED_AP_MLME */
|
||||
}
|
||||
|
||||
|
||||
@ -732,6 +845,73 @@ void ap_sta_stop_sa_query(struct hostapd_data *hapd, struct sta_info *sta)
|
||||
#endif /* CONFIG_IEEE80211W */
|
||||
|
||||
|
||||
void ap_sta_set_authorized(struct hostapd_data *hapd, struct sta_info *sta,
|
||||
int authorized)
|
||||
{
|
||||
const u8 *dev_addr = NULL;
|
||||
#ifdef CONFIG_P2P
|
||||
u8 addr[ETH_ALEN];
|
||||
#endif /* CONFIG_P2P */
|
||||
|
||||
if (!!authorized == !!(sta->flags & WLAN_STA_AUTHORIZED))
|
||||
return;
|
||||
|
||||
#ifdef CONFIG_P2P
|
||||
if (hapd->p2p_group == NULL) {
|
||||
if (sta->p2p_ie != NULL &&
|
||||
p2p_parse_dev_addr_in_p2p_ie(sta->p2p_ie, addr) == 0)
|
||||
dev_addr = addr;
|
||||
} else
|
||||
dev_addr = p2p_group_get_dev_addr(hapd->p2p_group, sta->addr);
|
||||
#endif /* CONFIG_P2P */
|
||||
|
||||
if (authorized) {
|
||||
if (dev_addr)
|
||||
wpa_msg(hapd->msg_ctx, MSG_INFO, AP_STA_CONNECTED
|
||||
MACSTR " p2p_dev_addr=" MACSTR,
|
||||
MAC2STR(sta->addr), MAC2STR(dev_addr));
|
||||
else
|
||||
wpa_msg(hapd->msg_ctx, MSG_INFO, AP_STA_CONNECTED
|
||||
MACSTR, MAC2STR(sta->addr));
|
||||
if (hapd->msg_ctx_parent &&
|
||||
hapd->msg_ctx_parent != hapd->msg_ctx && dev_addr)
|
||||
wpa_msg(hapd->msg_ctx_parent, MSG_INFO,
|
||||
AP_STA_CONNECTED MACSTR " p2p_dev_addr="
|
||||
MACSTR,
|
||||
MAC2STR(sta->addr), MAC2STR(dev_addr));
|
||||
else if (hapd->msg_ctx_parent &&
|
||||
hapd->msg_ctx_parent != hapd->msg_ctx)
|
||||
wpa_msg(hapd->msg_ctx_parent, MSG_INFO,
|
||||
AP_STA_CONNECTED MACSTR, MAC2STR(sta->addr));
|
||||
|
||||
sta->flags |= WLAN_STA_AUTHORIZED;
|
||||
} else {
|
||||
if (dev_addr)
|
||||
wpa_msg(hapd->msg_ctx, MSG_INFO, AP_STA_DISCONNECTED
|
||||
MACSTR " p2p_dev_addr=" MACSTR,
|
||||
MAC2STR(sta->addr), MAC2STR(dev_addr));
|
||||
else
|
||||
wpa_msg(hapd->msg_ctx, MSG_INFO, AP_STA_DISCONNECTED
|
||||
MACSTR, MAC2STR(sta->addr));
|
||||
if (hapd->msg_ctx_parent &&
|
||||
hapd->msg_ctx_parent != hapd->msg_ctx && dev_addr)
|
||||
wpa_msg(hapd->msg_ctx_parent, MSG_INFO,
|
||||
AP_STA_DISCONNECTED MACSTR " p2p_dev_addr="
|
||||
MACSTR, MAC2STR(sta->addr), MAC2STR(dev_addr));
|
||||
else if (hapd->msg_ctx_parent &&
|
||||
hapd->msg_ctx_parent != hapd->msg_ctx)
|
||||
wpa_msg(hapd->msg_ctx_parent, MSG_INFO,
|
||||
AP_STA_DISCONNECTED MACSTR,
|
||||
MAC2STR(sta->addr));
|
||||
sta->flags &= ~WLAN_STA_AUTHORIZED;
|
||||
}
|
||||
|
||||
if (hapd->sta_authorized_cb)
|
||||
hapd->sta_authorized_cb(hapd->sta_authorized_cb_ctx,
|
||||
sta->addr, authorized, dev_addr);
|
||||
}
|
||||
|
||||
|
||||
void ap_sta_disconnect(struct hostapd_data *hapd, struct sta_info *sta,
|
||||
const u8 *addr, u16 reason)
|
||||
{
|
||||
@ -740,12 +920,52 @@ void ap_sta_disconnect(struct hostapd_data *hapd, struct sta_info *sta,
|
||||
sta = ap_get_sta(hapd, addr);
|
||||
|
||||
if (addr)
|
||||
hapd->drv.sta_deauth(hapd, addr, reason);
|
||||
hostapd_drv_sta_deauth(hapd, addr, reason);
|
||||
|
||||
if (sta == NULL)
|
||||
return;
|
||||
sta->flags &= ~(WLAN_STA_AUTH | WLAN_STA_ASSOC | WLAN_STA_AUTHORIZED);
|
||||
ap_sta_set_authorized(hapd, sta, 0);
|
||||
wpa_auth_sm_event(sta->wpa_sm, WPA_DEAUTH);
|
||||
ieee802_1x_notify_port_enabled(sta->eapol_sm, 0);
|
||||
sta->flags &= ~(WLAN_STA_AUTH | WLAN_STA_ASSOC);
|
||||
wpa_printf(MSG_DEBUG, "%s: reschedule ap_handle_timer timeout "
|
||||
"for " MACSTR " (%d seconds - "
|
||||
"AP_MAX_INACTIVITY_AFTER_DEAUTH)",
|
||||
__func__, MAC2STR(sta->addr),
|
||||
AP_MAX_INACTIVITY_AFTER_DEAUTH);
|
||||
eloop_cancel_timeout(ap_handle_timer, hapd, sta);
|
||||
eloop_register_timeout(0, 0, ap_handle_timer, hapd, sta);
|
||||
eloop_register_timeout(AP_MAX_INACTIVITY_AFTER_DEAUTH, 0,
|
||||
ap_handle_timer, hapd, sta);
|
||||
sta->timeout_next = STA_REMOVE;
|
||||
|
||||
sta->deauth_reason = reason;
|
||||
sta->flags |= WLAN_STA_PENDING_DEAUTH_CB;
|
||||
eloop_cancel_timeout(ap_sta_deauth_cb_timeout, hapd, sta);
|
||||
eloop_register_timeout(hapd->iface->drv_flags &
|
||||
WPA_DRIVER_FLAGS_DEAUTH_TX_STATUS ? 2 : 0, 0,
|
||||
ap_sta_deauth_cb_timeout, hapd, sta);
|
||||
}
|
||||
|
||||
|
||||
void ap_sta_deauth_cb(struct hostapd_data *hapd, struct sta_info *sta)
|
||||
{
|
||||
if (!(sta->flags & WLAN_STA_PENDING_DEAUTH_CB)) {
|
||||
wpa_printf(MSG_DEBUG, "Ignore deauth cb for test frame");
|
||||
return;
|
||||
}
|
||||
sta->flags &= ~WLAN_STA_PENDING_DEAUTH_CB;
|
||||
eloop_cancel_timeout(ap_sta_deauth_cb_timeout, hapd, sta);
|
||||
ap_sta_deauth_cb_timeout(hapd, sta);
|
||||
}
|
||||
|
||||
|
||||
void ap_sta_disassoc_cb(struct hostapd_data *hapd, struct sta_info *sta)
|
||||
{
|
||||
if (!(sta->flags & WLAN_STA_PENDING_DISASSOC_CB)) {
|
||||
wpa_printf(MSG_DEBUG, "Ignore disassoc cb for test frame");
|
||||
return;
|
||||
}
|
||||
sta->flags &= ~WLAN_STA_PENDING_DISASSOC_CB;
|
||||
eloop_cancel_timeout(ap_sta_disassoc_cb_timeout, hapd, sta);
|
||||
ap_sta_disassoc_cb_timeout(hapd, sta);
|
||||
}
|
||||
|
@ -1,15 +1,9 @@
|
||||
/*
|
||||
* hostapd / Station table
|
||||
* Copyright (c) 2002-2009, Jouni Malinen <j@w1.fi>
|
||||
* Copyright (c) 2002-2011, Jouni Malinen <j@w1.fi>
|
||||
*
|
||||
* This program is free software; you can redistribute it and/or modify
|
||||
* it under the terms of the GNU General Public License version 2 as
|
||||
* published by the Free Software Foundation.
|
||||
*
|
||||
* Alternatively, this software may be distributed under the terms of BSD
|
||||
* license.
|
||||
*
|
||||
* See README and COPYING for more details.
|
||||
* This software may be distributed under the terms of the BSD license.
|
||||
* See README for more details.
|
||||
*/
|
||||
|
||||
#ifndef STA_INFO_H
|
||||
@ -31,6 +25,12 @@
|
||||
#define WLAN_STA_WPS BIT(12)
|
||||
#define WLAN_STA_MAYBE_WPS BIT(13)
|
||||
#define WLAN_STA_WDS BIT(14)
|
||||
#define WLAN_STA_ASSOC_REQ_OK BIT(15)
|
||||
#define WLAN_STA_WPS2 BIT(16)
|
||||
#define WLAN_STA_GAS BIT(17)
|
||||
#define WLAN_STA_VHT BIT(18)
|
||||
#define WLAN_STA_PENDING_DISASSOC_CB BIT(29)
|
||||
#define WLAN_STA_PENDING_DEAUTH_CB BIT(30)
|
||||
#define WLAN_STA_NONERP BIT(31)
|
||||
|
||||
/* Maximum number of supported rates (from both Supported Rates and Extended
|
||||
@ -48,6 +48,7 @@ struct sta_info {
|
||||
u16 listen_interval; /* or beacon_int for APs */
|
||||
u8 supported_rates[WLAN_SUPP_RATES_MAX];
|
||||
int supported_rates_len;
|
||||
u8 qosinfo; /* Valid when WLAN_STA_WMM is set */
|
||||
|
||||
unsigned int nonerp_set:1;
|
||||
unsigned int no_short_slot_time_set:1;
|
||||
@ -55,6 +56,7 @@ struct sta_info {
|
||||
unsigned int no_ht_gf_set:1;
|
||||
unsigned int no_ht_set:1;
|
||||
unsigned int ht_20mhz_set:1;
|
||||
unsigned int no_p2p_set:1;
|
||||
|
||||
u16 auth_alg;
|
||||
u8 previous_ap[6];
|
||||
@ -63,6 +65,9 @@ struct sta_info {
|
||||
STA_NULLFUNC = 0, STA_DISASSOC, STA_DEAUTH, STA_REMOVE
|
||||
} timeout_next;
|
||||
|
||||
u16 deauth_reason;
|
||||
u16 disassoc_reason;
|
||||
|
||||
/* IEEE 802.1X related data */
|
||||
struct eapol_state_machine *eapol_sm;
|
||||
|
||||
@ -90,8 +95,14 @@ struct sta_info {
|
||||
struct hostapd_ssid *ssid_probe; /* SSID selection based on ProbeReq */
|
||||
|
||||
int vlan_id;
|
||||
/* PSKs from RADIUS authentication server */
|
||||
struct hostapd_sta_wpa_psk_short *psk;
|
||||
|
||||
char *identity; /* User-Name from RADIUS */
|
||||
char *radius_cui; /* Chargeable-User-Identity from RADIUS */
|
||||
|
||||
struct ieee80211_ht_capabilities *ht_capabilities;
|
||||
struct ieee80211_vht_capabilities *vht_capabilities;
|
||||
|
||||
#ifdef CONFIG_IEEE80211W
|
||||
int sa_query_count; /* number of pending SA Query requests;
|
||||
@ -103,7 +114,22 @@ struct sta_info {
|
||||
struct os_time sa_query_start;
|
||||
#endif /* CONFIG_IEEE80211W */
|
||||
|
||||
#ifdef CONFIG_INTERWORKING
|
||||
#define GAS_DIALOG_MAX 8 /* Max concurrent dialog number */
|
||||
struct gas_dialog_info *gas_dialog;
|
||||
u8 gas_dialog_next;
|
||||
#endif /* CONFIG_INTERWORKING */
|
||||
|
||||
struct wpabuf *wps_ie; /* WPS IE from (Re)Association Request */
|
||||
struct wpabuf *p2p_ie; /* P2P IE from (Re)Association Request */
|
||||
struct wpabuf *hs20_ie; /* HS 2.0 IE from (Re)Association Request */
|
||||
|
||||
struct os_time connected_time;
|
||||
|
||||
#ifdef CONFIG_SAE
|
||||
enum { SAE_INIT, SAE_COMMIT, SAE_CONFIRM } sae_state;
|
||||
u16 sae_send_confirm;
|
||||
#endif /* CONFIG_SAE */
|
||||
};
|
||||
|
||||
|
||||
@ -111,7 +137,7 @@ struct sta_info {
|
||||
* passed since last received frame from the station, a nullfunc data frame is
|
||||
* sent to the station. If this frame is not acknowledged and no other frames
|
||||
* have been received, the station will be disassociated after
|
||||
* AP_DISASSOC_DELAY seconds. Similarily, the station will be deauthenticated
|
||||
* AP_DISASSOC_DELAY seconds. Similarly, the station will be deauthenticated
|
||||
* after AP_DEAUTH_DELAY seconds has passed after disassociation. */
|
||||
#define AP_MAX_INACTIVITY (5 * 60)
|
||||
#define AP_DISASSOC_DELAY (1)
|
||||
@ -132,7 +158,6 @@ int ap_for_each_sta(struct hostapd_data *hapd,
|
||||
struct sta_info * ap_get_sta(struct hostapd_data *hapd, const u8 *sta);
|
||||
void ap_sta_hash_add(struct hostapd_data *hapd, struct sta_info *sta);
|
||||
void ap_free_sta(struct hostapd_data *hapd, struct sta_info *sta);
|
||||
void ap_free_sta(struct hostapd_data *hapd, struct sta_info *sta);
|
||||
void hostapd_free_stas(struct hostapd_data *hapd);
|
||||
void ap_handle_timer(void *eloop_ctx, void *timeout_ctx);
|
||||
void ap_sta_session_timeout(struct hostapd_data *hapd, struct sta_info *sta,
|
||||
@ -144,6 +169,10 @@ void ap_sta_disassociate(struct hostapd_data *hapd, struct sta_info *sta,
|
||||
u16 reason);
|
||||
void ap_sta_deauthenticate(struct hostapd_data *hapd, struct sta_info *sta,
|
||||
u16 reason);
|
||||
#ifdef CONFIG_WPS
|
||||
int ap_sta_wps_cancel(struct hostapd_data *hapd,
|
||||
struct sta_info *sta, void *ctx);
|
||||
#endif /* CONFIG_WPS */
|
||||
int ap_sta_bind_vlan(struct hostapd_data *hapd, struct sta_info *sta,
|
||||
int old_vlanid);
|
||||
void ap_sta_start_sa_query(struct hostapd_data *hapd, struct sta_info *sta);
|
||||
@ -152,4 +181,14 @@ int ap_check_sa_query_timeout(struct hostapd_data *hapd, struct sta_info *sta);
|
||||
void ap_sta_disconnect(struct hostapd_data *hapd, struct sta_info *sta,
|
||||
const u8 *addr, u16 reason);
|
||||
|
||||
void ap_sta_set_authorized(struct hostapd_data *hapd,
|
||||
struct sta_info *sta, int authorized);
|
||||
static inline int ap_sta_is_authorized(struct sta_info *sta)
|
||||
{
|
||||
return sta->flags & WLAN_STA_AUTHORIZED;
|
||||
}
|
||||
|
||||
void ap_sta_deauth_cb(struct hostapd_data *hapd, struct sta_info *sta);
|
||||
void ap_sta_disassoc_cb(struct hostapd_data *hapd, struct sta_info *sta);
|
||||
|
||||
#endif /* STA_INFO_H */
|
||||
|
@ -1,15 +1,9 @@
|
||||
/*
|
||||
* hostapd / TKIP countermeasures
|
||||
* Copyright (c) 2002-2009, Jouni Malinen <j@w1.fi>
|
||||
* Copyright (c) 2002-2012, Jouni Malinen <j@w1.fi>
|
||||
*
|
||||
* This program is free software; you can redistribute it and/or modify
|
||||
* it under the terms of the GNU General Public License version 2 as
|
||||
* published by the Free Software Foundation.
|
||||
*
|
||||
* Alternatively, this software may be distributed under the terms of BSD
|
||||
* license.
|
||||
*
|
||||
* See README and COPYING for more details.
|
||||
* This software may be distributed under the terms of the BSD license.
|
||||
* See README for more details.
|
||||
*/
|
||||
|
||||
#include "utils/includes.h"
|
||||
@ -17,10 +11,12 @@
|
||||
#include "utils/common.h"
|
||||
#include "utils/eloop.h"
|
||||
#include "common/ieee802_11_defs.h"
|
||||
#include "radius/radius.h"
|
||||
#include "hostapd.h"
|
||||
#include "sta_info.h"
|
||||
#include "ap_mlme.h"
|
||||
#include "wpa_auth.h"
|
||||
#include "ap_drv_ops.h"
|
||||
#include "tkip_countermeasures.h"
|
||||
|
||||
|
||||
@ -29,7 +25,7 @@ static void ieee80211_tkip_countermeasures_stop(void *eloop_ctx,
|
||||
{
|
||||
struct hostapd_data *hapd = eloop_ctx;
|
||||
hapd->tkip_countermeasures = 0;
|
||||
hapd->drv.set_countermeasures(hapd, 0);
|
||||
hostapd_drv_set_countermeasures(hapd, 0);
|
||||
hostapd_logger(hapd, NULL, HOSTAPD_MODULE_IEEE80211,
|
||||
HOSTAPD_LEVEL_INFO, "TKIP countermeasures ended");
|
||||
}
|
||||
@ -44,24 +40,36 @@ static void ieee80211_tkip_countermeasures_start(struct hostapd_data *hapd)
|
||||
|
||||
wpa_auth_countermeasures_start(hapd->wpa_auth);
|
||||
hapd->tkip_countermeasures = 1;
|
||||
hapd->drv.set_countermeasures(hapd, 1);
|
||||
hostapd_drv_set_countermeasures(hapd, 1);
|
||||
wpa_gtk_rekey(hapd->wpa_auth);
|
||||
eloop_cancel_timeout(ieee80211_tkip_countermeasures_stop, hapd, NULL);
|
||||
eloop_register_timeout(60, 0, ieee80211_tkip_countermeasures_stop,
|
||||
hapd, NULL);
|
||||
for (sta = hapd->sta_list; sta != NULL; sta = sta->next) {
|
||||
hapd->drv.sta_deauth(hapd, sta->addr,
|
||||
WLAN_REASON_MICHAEL_MIC_FAILURE);
|
||||
sta->flags &= ~(WLAN_STA_AUTH | WLAN_STA_ASSOC |
|
||||
WLAN_STA_AUTHORIZED);
|
||||
hapd->drv.sta_remove(hapd, sta->addr);
|
||||
while ((sta = hapd->sta_list)) {
|
||||
sta->acct_terminate_cause =
|
||||
RADIUS_ACCT_TERMINATE_CAUSE_ADMIN_RESET;
|
||||
if (sta->flags & WLAN_STA_AUTH) {
|
||||
mlme_deauthenticate_indication(
|
||||
hapd, sta,
|
||||
WLAN_REASON_MICHAEL_MIC_FAILURE);
|
||||
}
|
||||
hostapd_drv_sta_deauth(hapd, sta->addr,
|
||||
WLAN_REASON_MICHAEL_MIC_FAILURE);
|
||||
ap_free_sta(hapd, sta);
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
void michael_mic_failure(struct hostapd_data *hapd, const u8 *addr, int local)
|
||||
void ieee80211_tkip_countermeasures_deinit(struct hostapd_data *hapd)
|
||||
{
|
||||
time_t now;
|
||||
eloop_cancel_timeout(ieee80211_tkip_countermeasures_stop, hapd, NULL);
|
||||
}
|
||||
|
||||
|
||||
int michael_mic_failure(struct hostapd_data *hapd, const u8 *addr, int local)
|
||||
{
|
||||
struct os_time now;
|
||||
int ret = 0;
|
||||
|
||||
if (addr && local) {
|
||||
struct sta_info *sta = ap_get_sta(hapd, addr);
|
||||
@ -77,17 +85,21 @@ void michael_mic_failure(struct hostapd_data *hapd, const u8 *addr, int local)
|
||||
"MLME-MICHAELMICFAILURE.indication "
|
||||
"for not associated STA (" MACSTR
|
||||
") ignored", MAC2STR(addr));
|
||||
return;
|
||||
return ret;
|
||||
}
|
||||
}
|
||||
|
||||
time(&now);
|
||||
if (now > hapd->michael_mic_failure + 60) {
|
||||
os_get_time(&now);
|
||||
if (now.sec > hapd->michael_mic_failure + 60) {
|
||||
hapd->michael_mic_failures = 1;
|
||||
} else {
|
||||
hapd->michael_mic_failures++;
|
||||
if (hapd->michael_mic_failures > 1)
|
||||
if (hapd->michael_mic_failures > 1) {
|
||||
ieee80211_tkip_countermeasures_start(hapd);
|
||||
ret = 1;
|
||||
}
|
||||
}
|
||||
hapd->michael_mic_failure = now;
|
||||
hapd->michael_mic_failure = now.sec;
|
||||
|
||||
return ret;
|
||||
}
|
||||
|
@ -1,20 +1,15 @@
|
||||
/*
|
||||
* hostapd / TKIP countermeasures
|
||||
* Copyright (c) 2002-2009, Jouni Malinen <j@w1.fi>
|
||||
* Copyright (c) 2002-2012, Jouni Malinen <j@w1.fi>
|
||||
*
|
||||
* This program is free software; you can redistribute it and/or modify
|
||||
* it under the terms of the GNU General Public License version 2 as
|
||||
* published by the Free Software Foundation.
|
||||
*
|
||||
* Alternatively, this software may be distributed under the terms of BSD
|
||||
* license.
|
||||
*
|
||||
* See README and COPYING for more details.
|
||||
* This software may be distributed under the terms of the BSD license.
|
||||
* See README for more details.
|
||||
*/
|
||||
|
||||
#ifndef TKIP_COUNTERMEASURES_H
|
||||
#define TKIP_COUNTERMEASURES_H
|
||||
|
||||
void michael_mic_failure(struct hostapd_data *hapd, const u8 *addr, int local);
|
||||
int michael_mic_failure(struct hostapd_data *hapd, const u8 *addr, int local);
|
||||
void ieee80211_tkip_countermeasures_deinit(struct hostapd_data *hapd);
|
||||
|
||||
#endif /* TKIP_COUNTERMEASURES_H */
|
||||
|
@ -2,14 +2,8 @@
|
||||
* AP mode helper functions
|
||||
* Copyright (c) 2009, Jouni Malinen <j@w1.fi>
|
||||
*
|
||||
* This program is free software; you can redistribute it and/or modify
|
||||
* it under the terms of the GNU General Public License version 2 as
|
||||
* published by the Free Software Foundation.
|
||||
*
|
||||
* Alternatively, this software may be distributed under the terms of BSD
|
||||
* license.
|
||||
*
|
||||
* See README and COPYING for more details.
|
||||
* This software may be distributed under the terms of the BSD license.
|
||||
* See README for more details.
|
||||
*/
|
||||
|
||||
#include "includes.h"
|
||||
@ -22,13 +16,15 @@
|
||||
|
||||
int hostapd_register_probereq_cb(struct hostapd_data *hapd,
|
||||
int (*cb)(void *ctx, const u8 *sa,
|
||||
const u8 *ie, size_t ie_len),
|
||||
const u8 *da, const u8 *bssid,
|
||||
const u8 *ie, size_t ie_len,
|
||||
int ssi_signal),
|
||||
void *ctx)
|
||||
{
|
||||
struct hostapd_probereq_cb *n;
|
||||
|
||||
n = os_realloc(hapd->probereq_cb, (hapd->num_probereq_cb + 1) *
|
||||
sizeof(struct hostapd_probereq_cb));
|
||||
n = os_realloc_array(hapd->probereq_cb, hapd->num_probereq_cb + 1,
|
||||
sizeof(struct hostapd_probereq_cb));
|
||||
if (n == NULL)
|
||||
return -1;
|
||||
|
||||
@ -82,7 +78,8 @@ void hostapd_prune_associations(struct hostapd_data *hapd, const u8 *addr)
|
||||
struct prune_data data;
|
||||
data.hapd = hapd;
|
||||
data.addr = addr;
|
||||
if (hapd->iface->for_each_interface)
|
||||
hapd->iface->for_each_interface(hapd->iface->interfaces,
|
||||
prune_associations, &data);
|
||||
if (hapd->iface->interfaces &&
|
||||
hapd->iface->interfaces->for_each_interface)
|
||||
hapd->iface->interfaces->for_each_interface(
|
||||
hapd->iface->interfaces, prune_associations, &data);
|
||||
}
|
||||
|
@ -19,7 +19,9 @@
|
||||
#include "utils/common.h"
|
||||
#include "hostapd.h"
|
||||
#include "ap_config.h"
|
||||
#include "ap_drv_ops.h"
|
||||
#include "vlan_init.h"
|
||||
#include "vlan_util.h"
|
||||
|
||||
|
||||
#ifdef CONFIG_FULL_DYNAMIC_VLAN
|
||||
@ -334,7 +336,9 @@ static int br_getnumports(const char *br_name)
|
||||
}
|
||||
|
||||
|
||||
static int vlan_rem(const char *if_name)
|
||||
#ifndef CONFIG_VLAN_NETLINK
|
||||
|
||||
int vlan_rem(const char *if_name)
|
||||
{
|
||||
int fd;
|
||||
struct vlan_ioctl_args if_request;
|
||||
@ -377,7 +381,7 @@ static int vlan_rem(const char *if_name)
|
||||
returns 1 if the interface already exists
|
||||
returns 0 otherwise
|
||||
*/
|
||||
static int vlan_add(const char *if_name, int vid)
|
||||
int vlan_add(const char *if_name, int vid, const char *vlan_if_name)
|
||||
{
|
||||
int fd;
|
||||
struct vlan_ioctl_args if_request;
|
||||
@ -473,6 +477,8 @@ static int vlan_set_name_type(unsigned int name_type)
|
||||
return 0;
|
||||
}
|
||||
|
||||
#endif /* CONFIG_VLAN_NETLINK */
|
||||
|
||||
|
||||
static void vlan_newlink(char *ifname, struct hostapd_data *hapd)
|
||||
{
|
||||
@ -480,6 +486,7 @@ static void vlan_newlink(char *ifname, struct hostapd_data *hapd)
|
||||
char br_name[IFNAMSIZ];
|
||||
struct hostapd_vlan *vlan = hapd->conf->vlan;
|
||||
char *tagged_interface = hapd->conf->ssid.vlan_tagged_interface;
|
||||
int vlan_naming = hapd->conf->ssid.vlan_naming;
|
||||
|
||||
wpa_printf(MSG_DEBUG, "VLAN: vlan_newlink(%s)", ifname);
|
||||
|
||||
@ -495,13 +502,22 @@ static void vlan_newlink(char *ifname, struct hostapd_data *hapd)
|
||||
ifconfig_up(br_name);
|
||||
|
||||
if (tagged_interface) {
|
||||
if (vlan_naming ==
|
||||
DYNAMIC_VLAN_NAMING_WITH_DEVICE)
|
||||
os_snprintf(vlan_ifname,
|
||||
sizeof(vlan_ifname),
|
||||
"%s.%d", tagged_interface,
|
||||
vlan->vlan_id);
|
||||
else
|
||||
os_snprintf(vlan_ifname,
|
||||
sizeof(vlan_ifname),
|
||||
"vlan%d", vlan->vlan_id);
|
||||
|
||||
if (!vlan_add(tagged_interface, vlan->vlan_id))
|
||||
ifconfig_up(tagged_interface);
|
||||
if (!vlan_add(tagged_interface, vlan->vlan_id,
|
||||
vlan_ifname))
|
||||
vlan->clean |= DVLAN_CLEAN_VLAN;
|
||||
|
||||
os_snprintf(vlan_ifname, sizeof(vlan_ifname),
|
||||
"vlan%d", vlan->vlan_id);
|
||||
|
||||
if (!br_addif(br_name, vlan_ifname))
|
||||
vlan->clean |= DVLAN_CLEAN_VLAN_PORT;
|
||||
|
||||
@ -526,6 +542,7 @@ static void vlan_dellink(char *ifname, struct hostapd_data *hapd)
|
||||
char br_name[IFNAMSIZ];
|
||||
struct hostapd_vlan *first, *prev, *vlan = hapd->conf->vlan;
|
||||
char *tagged_interface = hapd->conf->ssid.vlan_tagged_interface;
|
||||
int vlan_naming = hapd->conf->ssid.vlan_naming;
|
||||
|
||||
wpa_printf(MSG_DEBUG, "VLAN: vlan_dellink(%s)", ifname);
|
||||
|
||||
@ -540,8 +557,16 @@ static void vlan_dellink(char *ifname, struct hostapd_data *hapd)
|
||||
br_delif(br_name, vlan->ifname);
|
||||
|
||||
if (tagged_interface) {
|
||||
os_snprintf(vlan_ifname, sizeof(vlan_ifname),
|
||||
"vlan%d", vlan->vlan_id);
|
||||
if (vlan_naming ==
|
||||
DYNAMIC_VLAN_NAMING_WITH_DEVICE)
|
||||
os_snprintf(vlan_ifname,
|
||||
sizeof(vlan_ifname),
|
||||
"%s.%d", tagged_interface,
|
||||
vlan->vlan_id);
|
||||
else
|
||||
os_snprintf(vlan_ifname,
|
||||
sizeof(vlan_ifname),
|
||||
"vlan%d", vlan->vlan_id);
|
||||
if (vlan->clean & DVLAN_CLEAN_VLAN_PORT)
|
||||
br_delif(br_name, vlan_ifname);
|
||||
ifconfig_down(vlan_ifname);
|
||||
@ -681,7 +706,12 @@ full_dynamic_vlan_init(struct hostapd_data *hapd)
|
||||
if (priv == NULL)
|
||||
return NULL;
|
||||
|
||||
vlan_set_name_type(VLAN_NAME_TYPE_PLUS_VID_NO_PAD);
|
||||
#ifndef CONFIG_VLAN_NETLINK
|
||||
vlan_set_name_type(hapd->conf->ssid.vlan_naming ==
|
||||
DYNAMIC_VLAN_NAMING_WITH_DEVICE ?
|
||||
VLAN_NAME_TYPE_RAW_PLUS_VID_NO_PAD :
|
||||
VLAN_NAME_TYPE_PLUS_VID_NO_PAD);
|
||||
#endif /* CONFIG_VLAN_NETLINK */
|
||||
|
||||
priv->s = socket(PF_NETLINK, SOCK_RAW, NETLINK_ROUTE);
|
||||
if (priv->s < 0) {
|
||||
@ -737,9 +767,10 @@ int vlan_setup_encryption_dyn(struct hostapd_data *hapd,
|
||||
* functions for setting up dynamic broadcast keys. */
|
||||
for (i = 0; i < 4; i++) {
|
||||
if (mssid->wep.key[i] &&
|
||||
hapd->drv.set_key(dyn_vlan, hapd, WPA_ALG_WEP, NULL, i,
|
||||
i == mssid->wep.idx, NULL, 0,
|
||||
mssid->wep.key[i], mssid->wep.len[i])) {
|
||||
hostapd_drv_set_key(dyn_vlan, hapd, WPA_ALG_WEP, NULL, i,
|
||||
i == mssid->wep.idx, NULL, 0,
|
||||
mssid->wep.key[i], mssid->wep.len[i]))
|
||||
{
|
||||
wpa_printf(MSG_ERROR, "VLAN: Could not set WEP "
|
||||
"encryption for dynamic VLAN");
|
||||
return -1;
|
||||
@ -755,7 +786,7 @@ static int vlan_dynamic_add(struct hostapd_data *hapd,
|
||||
{
|
||||
while (vlan) {
|
||||
if (vlan->vlan_id != VLAN_ID_WILDCARD) {
|
||||
if (hapd->drv.vlan_if_add(hapd, vlan->ifname)) {
|
||||
if (hostapd_vlan_if_add(hapd, vlan->ifname)) {
|
||||
if (errno != EEXIST) {
|
||||
wpa_printf(MSG_ERROR, "VLAN: Could "
|
||||
"not add VLAN %s: %s",
|
||||
@ -785,7 +816,7 @@ static void vlan_dynamic_remove(struct hostapd_data *hapd,
|
||||
next = vlan->next;
|
||||
|
||||
if (vlan->vlan_id != VLAN_ID_WILDCARD &&
|
||||
hapd->drv.vlan_if_remove(hapd, vlan->ifname)) {
|
||||
hostapd_vlan_if_remove(hapd, vlan->ifname)) {
|
||||
wpa_printf(MSG_ERROR, "VLAN: Could not remove VLAN "
|
||||
"iface: %s: %s",
|
||||
vlan->ifname, strerror(errno));
|
||||
@ -859,7 +890,7 @@ struct hostapd_vlan * vlan_add_dynamic(struct hostapd_data *hapd,
|
||||
pos);
|
||||
os_free(ifname);
|
||||
|
||||
if (hapd->drv.vlan_if_add(hapd, n->ifname)) {
|
||||
if (hostapd_vlan_if_add(hapd, n->ifname)) {
|
||||
os_free(n);
|
||||
return NULL;
|
||||
}
|
||||
@ -897,7 +928,7 @@ int vlan_remove_dynamic(struct hostapd_data *hapd, int vlan_id)
|
||||
return 1;
|
||||
|
||||
if (vlan->dynamic_vlan == 0)
|
||||
hapd->drv.vlan_if_remove(hapd, vlan->ifname);
|
||||
hostapd_vlan_if_remove(hapd, vlan->ifname);
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
177
contrib/wpa/src/ap/vlan_util.c
Normal file
177
contrib/wpa/src/ap/vlan_util.c
Normal file
@ -0,0 +1,177 @@
|
||||
/*
|
||||
* hostapd / VLAN netlink api
|
||||
* Copyright (c) 2012, Michael Braun <michael-dev@fami-braun.de>
|
||||
*
|
||||
* This software may be distributed under the terms of the BSD license.
|
||||
* See README for more details.
|
||||
*/
|
||||
|
||||
#include "utils/includes.h"
|
||||
#include <sys/ioctl.h>
|
||||
#include <linux/sockios.h>
|
||||
#include <linux/if_vlan.h>
|
||||
#include <netlink/genl/genl.h>
|
||||
#include <netlink/genl/family.h>
|
||||
#include <netlink/genl/ctrl.h>
|
||||
#include <netlink/route/link.h>
|
||||
#include <netlink/route/link/vlan.h>
|
||||
|
||||
#include "utils/common.h"
|
||||
#include "utils/eloop.h"
|
||||
#include "hostapd.h"
|
||||
#include "vlan_util.h"
|
||||
|
||||
/*
|
||||
* Add a vlan interface with name 'vlan_if_name', VLAN ID 'vid' and
|
||||
* tagged interface 'if_name'.
|
||||
*
|
||||
* returns -1 on error
|
||||
* returns 1 if the interface already exists
|
||||
* returns 0 otherwise
|
||||
*/
|
||||
int vlan_add(const char *if_name, int vid, const char *vlan_if_name)
|
||||
{
|
||||
int ret = -1;
|
||||
struct nl_sock *handle = NULL;
|
||||
struct nl_cache *cache = NULL;
|
||||
struct rtnl_link *rlink = NULL;
|
||||
int if_idx = 0;
|
||||
|
||||
wpa_printf(MSG_DEBUG, "VLAN: vlan_add(if_name=%s, vid=%d, "
|
||||
"vlan_if_name=%s)", if_name, vid, vlan_if_name);
|
||||
|
||||
if ((os_strlen(if_name) + 1) > IFNAMSIZ) {
|
||||
wpa_printf(MSG_ERROR, "VLAN: Interface name too long: '%s'",
|
||||
if_name);
|
||||
return -1;
|
||||
}
|
||||
|
||||
if ((os_strlen(vlan_if_name) + 1) > IFNAMSIZ) {
|
||||
wpa_printf(MSG_ERROR, "VLAN: Interface name too long: '%s'",
|
||||
vlan_if_name);
|
||||
return -1;
|
||||
}
|
||||
|
||||
handle = nl_socket_alloc();
|
||||
if (!handle) {
|
||||
wpa_printf(MSG_ERROR, "VLAN: failed to open netlink socket");
|
||||
goto vlan_add_error;
|
||||
}
|
||||
|
||||
if (nl_connect(handle, NETLINK_ROUTE) < 0) {
|
||||
wpa_printf(MSG_ERROR, "VLAN: failed to connect to netlink");
|
||||
goto vlan_add_error;
|
||||
}
|
||||
|
||||
if (rtnl_link_alloc_cache(handle, AF_UNSPEC, &cache) < 0) {
|
||||
cache = NULL;
|
||||
wpa_printf(MSG_ERROR, "VLAN: failed to alloc cache");
|
||||
goto vlan_add_error;
|
||||
}
|
||||
|
||||
if (!(if_idx = rtnl_link_name2i(cache, if_name))) {
|
||||
/* link does not exist */
|
||||
wpa_printf(MSG_ERROR, "VLAN: interface %s does not exist",
|
||||
if_name);
|
||||
goto vlan_add_error;
|
||||
}
|
||||
|
||||
if ((rlink = rtnl_link_get_by_name(cache, vlan_if_name))) {
|
||||
/* link does exist */
|
||||
rtnl_link_put(rlink);
|
||||
rlink = NULL;
|
||||
wpa_printf(MSG_ERROR, "VLAN: interface %s already exists",
|
||||
vlan_if_name);
|
||||
ret = 1;
|
||||
goto vlan_add_error;
|
||||
}
|
||||
|
||||
rlink = rtnl_link_alloc();
|
||||
if (!rlink) {
|
||||
wpa_printf(MSG_ERROR, "VLAN: failed to allocate new link");
|
||||
goto vlan_add_error;
|
||||
}
|
||||
|
||||
if (rtnl_link_set_type(rlink, "vlan") < 0) {
|
||||
wpa_printf(MSG_ERROR, "VLAN: failed to set link type");
|
||||
goto vlan_add_error;
|
||||
}
|
||||
|
||||
rtnl_link_set_link(rlink, if_idx);
|
||||
rtnl_link_set_name(rlink, vlan_if_name);
|
||||
|
||||
if (rtnl_link_vlan_set_id(rlink, vid) < 0) {
|
||||
wpa_printf(MSG_ERROR, "VLAN: failed to set link vlan id");
|
||||
goto vlan_add_error;
|
||||
}
|
||||
|
||||
if (rtnl_link_add(handle, rlink, NLM_F_CREATE) < 0) {
|
||||
wpa_printf(MSG_ERROR, "VLAN: failed to create link %s for "
|
||||
"vlan %d on %s (%d)",
|
||||
vlan_if_name, vid, if_name, if_idx);
|
||||
goto vlan_add_error;
|
||||
}
|
||||
|
||||
ret = 0;
|
||||
|
||||
vlan_add_error:
|
||||
if (rlink)
|
||||
rtnl_link_put(rlink);
|
||||
if (cache)
|
||||
nl_cache_free(cache);
|
||||
if (handle)
|
||||
nl_socket_free(handle);
|
||||
return ret;
|
||||
}
|
||||
|
||||
|
||||
int vlan_rem(const char *if_name)
|
||||
{
|
||||
int ret = -1;
|
||||
struct nl_sock *handle = NULL;
|
||||
struct nl_cache *cache = NULL;
|
||||
struct rtnl_link *rlink = NULL;
|
||||
|
||||
wpa_printf(MSG_DEBUG, "VLAN: vlan_rem(if_name=%s)", if_name);
|
||||
|
||||
handle = nl_socket_alloc();
|
||||
if (!handle) {
|
||||
wpa_printf(MSG_ERROR, "VLAN: failed to open netlink socket");
|
||||
goto vlan_rem_error;
|
||||
}
|
||||
|
||||
if (nl_connect(handle, NETLINK_ROUTE) < 0) {
|
||||
wpa_printf(MSG_ERROR, "VLAN: failed to connect to netlink");
|
||||
goto vlan_rem_error;
|
||||
}
|
||||
|
||||
if (rtnl_link_alloc_cache(handle, AF_UNSPEC, &cache) < 0) {
|
||||
cache = NULL;
|
||||
wpa_printf(MSG_ERROR, "VLAN: failed to alloc cache");
|
||||
goto vlan_rem_error;
|
||||
}
|
||||
|
||||
if (!(rlink = rtnl_link_get_by_name(cache, if_name))) {
|
||||
/* link does not exist */
|
||||
wpa_printf(MSG_ERROR, "VLAN: interface %s does not exists",
|
||||
if_name);
|
||||
goto vlan_rem_error;
|
||||
}
|
||||
|
||||
if (rtnl_link_delete(handle, rlink) < 0) {
|
||||
wpa_printf(MSG_ERROR, "VLAN: failed to remove link %s",
|
||||
if_name);
|
||||
goto vlan_rem_error;
|
||||
}
|
||||
|
||||
ret = 0;
|
||||
|
||||
vlan_rem_error:
|
||||
if (rlink)
|
||||
rtnl_link_put(rlink);
|
||||
if (cache)
|
||||
nl_cache_free(cache);
|
||||
if (handle)
|
||||
nl_socket_free(handle);
|
||||
return ret;
|
||||
}
|
15
contrib/wpa/src/ap/vlan_util.h
Normal file
15
contrib/wpa/src/ap/vlan_util.h
Normal file
@ -0,0 +1,15 @@
|
||||
/*
|
||||
* hostapd / VLAN netlink api
|
||||
* Copyright (c) 2012, Michael Braun <michael-dev@fami-braun.de>
|
||||
*
|
||||
* This software may be distributed under the terms of the BSD license.
|
||||
* See README for more details.
|
||||
*/
|
||||
|
||||
#ifndef VLAN_UTIL_H
|
||||
#define VLAN_UTIL_H
|
||||
|
||||
int vlan_add(const char *if_name, int vid, const char *vlan_if_name);
|
||||
int vlan_rem(const char *if_name);
|
||||
|
||||
#endif /* VLAN_UTIL_H */
|
@ -23,6 +23,7 @@
|
||||
#include "ieee802_11.h"
|
||||
#include "sta_info.h"
|
||||
#include "ap_config.h"
|
||||
#include "ap_drv_ops.h"
|
||||
#include "wmm.h"
|
||||
|
||||
|
||||
@ -71,9 +72,12 @@ u8 * hostapd_eid_wmm(struct hostapd_data *hapd, u8 *eid)
|
||||
wmm->version = WMM_VERSION;
|
||||
wmm->qos_info = hapd->parameter_set_count & 0xf;
|
||||
|
||||
if (hapd->conf->wmm_uapsd)
|
||||
if (hapd->conf->wmm_uapsd &&
|
||||
(hapd->iface->drv_flags & WPA_DRIVER_FLAGS_AP_UAPSD))
|
||||
wmm->qos_info |= 0x80;
|
||||
|
||||
wmm->reserved = 0;
|
||||
|
||||
/* fill in a parameter set record for each AC */
|
||||
for (e = 0; e < 4; e++) {
|
||||
struct wmm_ac_parameter *ac = &wmm->ac[e];
|
||||
@ -94,9 +98,11 @@ u8 * hostapd_eid_wmm(struct hostapd_data *hapd, u8 *eid)
|
||||
}
|
||||
|
||||
|
||||
/* This function is called when a station sends an association request with
|
||||
* WMM info element. The function returns zero on success or non-zero on any
|
||||
* error in WMM element. eid does not include Element ID and Length octets. */
|
||||
/*
|
||||
* This function is called when a station sends an association request with
|
||||
* WMM info element. The function returns 1 on success or 0 on any error in WMM
|
||||
* element. eid does not include Element ID and Length octets.
|
||||
*/
|
||||
int hostapd_eid_wmm_valid(struct hostapd_data *hapd, const u8 *eid, size_t len)
|
||||
{
|
||||
struct wmm_information_element *wmm;
|
||||
@ -106,7 +112,7 @@ int hostapd_eid_wmm_valid(struct hostapd_data *hapd, const u8 *eid, size_t len)
|
||||
if (len < sizeof(struct wmm_information_element)) {
|
||||
wpa_printf(MSG_DEBUG, "Too short WMM IE (len=%lu)",
|
||||
(unsigned long) len);
|
||||
return -1;
|
||||
return 0;
|
||||
}
|
||||
|
||||
wmm = (struct wmm_information_element *) eid;
|
||||
@ -117,10 +123,10 @@ int hostapd_eid_wmm_valid(struct hostapd_data *hapd, const u8 *eid, size_t len)
|
||||
if (wmm->oui_subtype != WMM_OUI_SUBTYPE_INFORMATION_ELEMENT ||
|
||||
wmm->version != WMM_VERSION) {
|
||||
wpa_printf(MSG_DEBUG, "Unsupported WMM IE Subtype/Version");
|
||||
return -1;
|
||||
return 0;
|
||||
}
|
||||
|
||||
return 0;
|
||||
return 1;
|
||||
}
|
||||
|
||||
|
||||
@ -150,7 +156,7 @@ static void wmm_send_action(struct hostapd_data *hapd, const u8 *addr,
|
||||
os_memcpy(t, tspec, sizeof(struct wmm_tspec_element));
|
||||
len = ((u8 *) (t + 1)) - buf;
|
||||
|
||||
if (hapd->drv.send_mgmt_frame(hapd, m, len) < 0)
|
||||
if (hostapd_drv_send_mlme(hapd, m, len, 0) < 0)
|
||||
perror("wmm_send_action: send");
|
||||
}
|
||||
|
||||
|
271
contrib/wpa/src/ap/wnm_ap.c
Normal file
271
contrib/wpa/src/ap/wnm_ap.c
Normal file
@ -0,0 +1,271 @@
|
||||
/*
|
||||
* hostapd - WNM
|
||||
* Copyright (c) 2011-2012, Qualcomm Atheros, Inc.
|
||||
*
|
||||
* This software may be distributed under the terms of the BSD license.
|
||||
* See README for more details.
|
||||
*/
|
||||
|
||||
#include "utils/includes.h"
|
||||
|
||||
#include "utils/common.h"
|
||||
#include "common/ieee802_11_defs.h"
|
||||
#include "ap/hostapd.h"
|
||||
#include "ap/sta_info.h"
|
||||
#include "ap/ap_config.h"
|
||||
#include "ap/ap_drv_ops.h"
|
||||
#include "ap/wpa_auth.h"
|
||||
#include "wnm_ap.h"
|
||||
|
||||
#define MAX_TFS_IE_LEN 1024
|
||||
|
||||
|
||||
/* get the TFS IE from driver */
|
||||
static int ieee80211_11_get_tfs_ie(struct hostapd_data *hapd, const u8 *addr,
|
||||
u8 *buf, u16 *buf_len, enum wnm_oper oper)
|
||||
{
|
||||
wpa_printf(MSG_DEBUG, "%s: TFS get operation %d", __func__, oper);
|
||||
|
||||
return hostapd_drv_wnm_oper(hapd, oper, addr, buf, buf_len);
|
||||
}
|
||||
|
||||
|
||||
/* set the TFS IE to driver */
|
||||
static int ieee80211_11_set_tfs_ie(struct hostapd_data *hapd, const u8 *addr,
|
||||
u8 *buf, u16 *buf_len, enum wnm_oper oper)
|
||||
{
|
||||
wpa_printf(MSG_DEBUG, "%s: TFS set operation %d", __func__, oper);
|
||||
|
||||
return hostapd_drv_wnm_oper(hapd, oper, addr, buf, buf_len);
|
||||
}
|
||||
|
||||
|
||||
/* MLME-SLEEPMODE.response */
|
||||
static int ieee802_11_send_wnmsleep_resp(struct hostapd_data *hapd,
|
||||
const u8 *addr, u8 dialog_token,
|
||||
u8 action_type, u16 intval)
|
||||
{
|
||||
struct ieee80211_mgmt *mgmt;
|
||||
int res;
|
||||
size_t len;
|
||||
size_t gtk_elem_len = 0;
|
||||
size_t igtk_elem_len = 0;
|
||||
struct wnm_sleep_element wnmsleep_ie;
|
||||
u8 *wnmtfs_ie;
|
||||
u8 wnmsleep_ie_len;
|
||||
u16 wnmtfs_ie_len;
|
||||
u8 *pos;
|
||||
struct sta_info *sta;
|
||||
enum wnm_oper tfs_oper = action_type == WNM_SLEEP_MODE_ENTER ?
|
||||
WNM_SLEEP_TFS_RESP_IE_ADD : WNM_SLEEP_TFS_RESP_IE_NONE;
|
||||
|
||||
sta = ap_get_sta(hapd, addr);
|
||||
if (sta == NULL) {
|
||||
wpa_printf(MSG_DEBUG, "%s: station not found", __func__);
|
||||
return -EINVAL;
|
||||
}
|
||||
|
||||
/* WNM-Sleep Mode IE */
|
||||
os_memset(&wnmsleep_ie, 0, sizeof(struct wnm_sleep_element));
|
||||
wnmsleep_ie_len = sizeof(struct wnm_sleep_element);
|
||||
wnmsleep_ie.eid = WLAN_EID_WNMSLEEP;
|
||||
wnmsleep_ie.len = wnmsleep_ie_len - 2;
|
||||
wnmsleep_ie.action_type = action_type;
|
||||
wnmsleep_ie.status = WNM_STATUS_SLEEP_ACCEPT;
|
||||
wnmsleep_ie.intval = intval;
|
||||
|
||||
/* TFS IE(s) */
|
||||
wnmtfs_ie = os_zalloc(MAX_TFS_IE_LEN);
|
||||
if (wnmtfs_ie == NULL)
|
||||
return -1;
|
||||
if (ieee80211_11_get_tfs_ie(hapd, addr, wnmtfs_ie, &wnmtfs_ie_len,
|
||||
tfs_oper)) {
|
||||
wnmtfs_ie_len = 0;
|
||||
os_free(wnmtfs_ie);
|
||||
wnmtfs_ie = NULL;
|
||||
}
|
||||
|
||||
#define MAX_GTK_SUBELEM_LEN 45
|
||||
#define MAX_IGTK_SUBELEM_LEN 26
|
||||
mgmt = os_zalloc(sizeof(*mgmt) + wnmsleep_ie_len +
|
||||
MAX_GTK_SUBELEM_LEN + MAX_IGTK_SUBELEM_LEN);
|
||||
if (mgmt == NULL) {
|
||||
wpa_printf(MSG_DEBUG, "MLME: Failed to allocate buffer for "
|
||||
"WNM-Sleep Response action frame");
|
||||
return -1;
|
||||
}
|
||||
os_memcpy(mgmt->da, addr, ETH_ALEN);
|
||||
os_memcpy(mgmt->sa, hapd->own_addr, ETH_ALEN);
|
||||
os_memcpy(mgmt->bssid, hapd->own_addr, ETH_ALEN);
|
||||
mgmt->frame_control = IEEE80211_FC(WLAN_FC_TYPE_MGMT,
|
||||
WLAN_FC_STYPE_ACTION);
|
||||
mgmt->u.action.category = WLAN_ACTION_WNM;
|
||||
mgmt->u.action.u.wnm_sleep_resp.action = WNM_SLEEP_MODE_RESP;
|
||||
mgmt->u.action.u.wnm_sleep_resp.dialogtoken = dialog_token;
|
||||
pos = (u8 *)mgmt->u.action.u.wnm_sleep_resp.variable;
|
||||
/* add key data if MFP is enabled */
|
||||
if (!wpa_auth_uses_mfp(sta->wpa_sm) ||
|
||||
action_type != WNM_SLEEP_MODE_EXIT) {
|
||||
mgmt->u.action.u.wnm_sleep_resp.keydata_len = 0;
|
||||
} else {
|
||||
gtk_elem_len = wpa_wnmsleep_gtk_subelem(sta->wpa_sm, pos);
|
||||
pos += gtk_elem_len;
|
||||
wpa_printf(MSG_DEBUG, "Pass 4, gtk_len = %d",
|
||||
(int) gtk_elem_len);
|
||||
#ifdef CONFIG_IEEE80211W
|
||||
res = wpa_wnmsleep_igtk_subelem(sta->wpa_sm, pos);
|
||||
if (res < 0) {
|
||||
os_free(wnmtfs_ie);
|
||||
os_free(mgmt);
|
||||
return -1;
|
||||
}
|
||||
igtk_elem_len = res;
|
||||
pos += igtk_elem_len;
|
||||
wpa_printf(MSG_DEBUG, "Pass 4 igtk_len = %d",
|
||||
(int) igtk_elem_len);
|
||||
#endif /* CONFIG_IEEE80211W */
|
||||
|
||||
WPA_PUT_LE16((u8 *)
|
||||
&mgmt->u.action.u.wnm_sleep_resp.keydata_len,
|
||||
gtk_elem_len + igtk_elem_len);
|
||||
}
|
||||
os_memcpy(pos, &wnmsleep_ie, wnmsleep_ie_len);
|
||||
/* copy TFS IE here */
|
||||
pos += wnmsleep_ie_len;
|
||||
if (wnmtfs_ie)
|
||||
os_memcpy(pos, wnmtfs_ie, wnmtfs_ie_len);
|
||||
|
||||
len = 1 + sizeof(mgmt->u.action.u.wnm_sleep_resp) + gtk_elem_len +
|
||||
igtk_elem_len + wnmsleep_ie_len + wnmtfs_ie_len;
|
||||
|
||||
/* In driver, response frame should be forced to sent when STA is in
|
||||
* PS mode */
|
||||
res = hostapd_drv_send_action(hapd, hapd->iface->freq, 0,
|
||||
mgmt->da, &mgmt->u.action.category, len);
|
||||
|
||||
if (!res) {
|
||||
wpa_printf(MSG_DEBUG, "Successfully send WNM-Sleep Response "
|
||||
"frame");
|
||||
|
||||
/* when entering wnmsleep
|
||||
* 1. pause the node in driver
|
||||
* 2. mark the node so that AP won't update GTK/IGTK during
|
||||
* WNM Sleep
|
||||
*/
|
||||
if (wnmsleep_ie.status == WNM_STATUS_SLEEP_ACCEPT &&
|
||||
wnmsleep_ie.action_type == WNM_SLEEP_MODE_ENTER) {
|
||||
hostapd_drv_wnm_oper(hapd, WNM_SLEEP_ENTER_CONFIRM,
|
||||
addr, NULL, NULL);
|
||||
wpa_set_wnmsleep(sta->wpa_sm, 1);
|
||||
}
|
||||
/* when exiting wnmsleep
|
||||
* 1. unmark the node
|
||||
* 2. start GTK/IGTK update if MFP is not used
|
||||
* 3. unpause the node in driver
|
||||
*/
|
||||
if ((wnmsleep_ie.status == WNM_STATUS_SLEEP_ACCEPT ||
|
||||
wnmsleep_ie.status ==
|
||||
WNM_STATUS_SLEEP_EXIT_ACCEPT_GTK_UPDATE) &&
|
||||
wnmsleep_ie.action_type == WNM_SLEEP_MODE_EXIT) {
|
||||
wpa_set_wnmsleep(sta->wpa_sm, 0);
|
||||
hostapd_drv_wnm_oper(hapd, WNM_SLEEP_EXIT_CONFIRM,
|
||||
addr, NULL, NULL);
|
||||
if (!wpa_auth_uses_mfp(sta->wpa_sm))
|
||||
wpa_wnmsleep_rekey_gtk(sta->wpa_sm);
|
||||
}
|
||||
} else
|
||||
wpa_printf(MSG_DEBUG, "Fail to send WNM-Sleep Response frame");
|
||||
|
||||
#undef MAX_GTK_SUBELEM_LEN
|
||||
#undef MAX_IGTK_SUBELEM_LEN
|
||||
os_free(wnmtfs_ie);
|
||||
os_free(mgmt);
|
||||
return res;
|
||||
}
|
||||
|
||||
|
||||
static void ieee802_11_rx_wnmsleep_req(struct hostapd_data *hapd,
|
||||
const u8 *addr, const u8 *frm, int len)
|
||||
{
|
||||
/* Dialog Token [1] | WNM-Sleep Mode IE | TFS Response IE */
|
||||
const u8 *pos = frm;
|
||||
u8 dialog_token;
|
||||
struct wnm_sleep_element *wnmsleep_ie = NULL;
|
||||
/* multiple TFS Req IE (assuming consecutive) */
|
||||
u8 *tfsreq_ie_start = NULL;
|
||||
u8 *tfsreq_ie_end = NULL;
|
||||
u16 tfsreq_ie_len = 0;
|
||||
|
||||
dialog_token = *pos++;
|
||||
while (pos + 1 < frm + len) {
|
||||
u8 ie_len = pos[1];
|
||||
if (pos + 2 + ie_len > frm + len)
|
||||
break;
|
||||
if (*pos == WLAN_EID_WNMSLEEP)
|
||||
wnmsleep_ie = (struct wnm_sleep_element *) pos;
|
||||
else if (*pos == WLAN_EID_TFS_REQ) {
|
||||
if (!tfsreq_ie_start)
|
||||
tfsreq_ie_start = (u8 *) pos;
|
||||
tfsreq_ie_end = (u8 *) pos;
|
||||
} else
|
||||
wpa_printf(MSG_DEBUG, "WNM: EID %d not recognized",
|
||||
*pos);
|
||||
pos += ie_len + 2;
|
||||
}
|
||||
|
||||
if (!wnmsleep_ie) {
|
||||
wpa_printf(MSG_DEBUG, "No WNM-Sleep IE found");
|
||||
return;
|
||||
}
|
||||
|
||||
if (wnmsleep_ie->action_type == WNM_SLEEP_MODE_ENTER &&
|
||||
tfsreq_ie_start && tfsreq_ie_end &&
|
||||
tfsreq_ie_end - tfsreq_ie_start >= 0) {
|
||||
tfsreq_ie_len = (tfsreq_ie_end + tfsreq_ie_end[1] + 2) -
|
||||
tfsreq_ie_start;
|
||||
wpa_printf(MSG_DEBUG, "TFS Req IE(s) found");
|
||||
/* pass the TFS Req IE(s) to driver for processing */
|
||||
if (ieee80211_11_set_tfs_ie(hapd, addr, tfsreq_ie_start,
|
||||
&tfsreq_ie_len,
|
||||
WNM_SLEEP_TFS_REQ_IE_SET))
|
||||
wpa_printf(MSG_DEBUG, "Fail to set TFS Req IE");
|
||||
}
|
||||
|
||||
ieee802_11_send_wnmsleep_resp(hapd, addr, dialog_token,
|
||||
wnmsleep_ie->action_type,
|
||||
wnmsleep_ie->intval);
|
||||
|
||||
if (wnmsleep_ie->action_type == WNM_SLEEP_MODE_EXIT) {
|
||||
/* clear the tfs after sending the resp frame */
|
||||
ieee80211_11_set_tfs_ie(hapd, addr, tfsreq_ie_start,
|
||||
&tfsreq_ie_len, WNM_SLEEP_TFS_IE_DEL);
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
int ieee802_11_rx_wnm_action_ap(struct hostapd_data *hapd,
|
||||
struct rx_action *action)
|
||||
{
|
||||
if (action->len < 1 || action->data == NULL)
|
||||
return -1;
|
||||
|
||||
switch (action->data[0]) {
|
||||
case WNM_BSS_TRANS_MGMT_QUERY:
|
||||
wpa_printf(MSG_DEBUG, "WNM: BSS Transition Management Query");
|
||||
/* TODO */
|
||||
return -1;
|
||||
case WNM_BSS_TRANS_MGMT_RESP:
|
||||
wpa_printf(MSG_DEBUG, "WNM: BSS Transition Management "
|
||||
"Response");
|
||||
/* TODO */
|
||||
return -1;
|
||||
case WNM_SLEEP_MODE_REQ:
|
||||
ieee802_11_rx_wnmsleep_req(hapd, action->sa, action->data + 1,
|
||||
action->len - 1);
|
||||
return 0;
|
||||
}
|
||||
|
||||
wpa_printf(MSG_DEBUG, "WNM: Unsupported WNM Action %u from " MACSTR,
|
||||
action->data[0], MAC2STR(action->sa));
|
||||
return -1;
|
||||
}
|
17
contrib/wpa/src/ap/wnm_ap.h
Normal file
17
contrib/wpa/src/ap/wnm_ap.h
Normal file
@ -0,0 +1,17 @@
|
||||
/*
|
||||
* IEEE 802.11v WNM related functions and structures
|
||||
* Copyright (c) 2011-2012, Qualcomm Atheros, Inc.
|
||||
*
|
||||
* This software may be distributed under the terms of the BSD license.
|
||||
* See README for more details.
|
||||
*/
|
||||
|
||||
#ifndef WNM_AP_H
|
||||
#define WNM_AP_H
|
||||
|
||||
struct rx_action;
|
||||
|
||||
int ieee802_11_rx_wnm_action_ap(struct hostapd_data *hapd,
|
||||
struct rx_action *action);
|
||||
|
||||
#endif /* WNM_AP_H */
|
File diff suppressed because it is too large
Load Diff
@ -2,14 +2,8 @@
|
||||
* hostapd - IEEE 802.11i-2004 / WPA Authenticator
|
||||
* Copyright (c) 2004-2007, Jouni Malinen <j@w1.fi>
|
||||
*
|
||||
* This program is free software; you can redistribute it and/or modify
|
||||
* it under the terms of the GNU General Public License version 2 as
|
||||
* published by the Free Software Foundation.
|
||||
*
|
||||
* Alternatively, this software may be distributed under the terms of BSD
|
||||
* license.
|
||||
*
|
||||
* See README and COPYING for more details.
|
||||
* This software may be distributed under the terms of the BSD license.
|
||||
* See README for more details.
|
||||
*/
|
||||
|
||||
#ifndef WPA_AUTH_H
|
||||
@ -143,7 +137,9 @@ struct wpa_auth_config {
|
||||
int peerkey;
|
||||
int wmm_enabled;
|
||||
int wmm_uapsd;
|
||||
int disable_pmksa_caching;
|
||||
int okc;
|
||||
int tx_status;
|
||||
#ifdef CONFIG_IEEE80211W
|
||||
enum mfp_options ieee80211w;
|
||||
#endif /* CONFIG_IEEE80211W */
|
||||
@ -160,7 +156,10 @@ struct wpa_auth_config {
|
||||
struct ft_remote_r0kh *r0kh_list;
|
||||
struct ft_remote_r1kh *r1kh_list;
|
||||
int pmk_r1_push;
|
||||
int ft_over_ds;
|
||||
#endif /* CONFIG_IEEE80211R */
|
||||
int disable_gtk;
|
||||
int ap_mlme;
|
||||
};
|
||||
|
||||
typedef enum {
|
||||
@ -178,7 +177,7 @@ struct wpa_auth_callbacks {
|
||||
void (*logger)(void *ctx, const u8 *addr, logger_level level,
|
||||
const char *txt);
|
||||
void (*disconnect)(void *ctx, const u8 *addr, u16 reason);
|
||||
void (*mic_failure_report)(void *ctx, const u8 *addr);
|
||||
int (*mic_failure_report)(void *ctx, const u8 *addr);
|
||||
void (*set_eapol)(void *ctx, const u8 *addr, wpa_eapol_variable var,
|
||||
int value);
|
||||
int (*get_eapol)(void *ctx, const u8 *addr, wpa_eapol_variable var);
|
||||
@ -199,12 +198,15 @@ struct wpa_auth_callbacks {
|
||||
struct wpa_state_machine * (*add_sta)(void *ctx, const u8 *sta_addr);
|
||||
int (*send_ft_action)(void *ctx, const u8 *dst,
|
||||
const u8 *data, size_t data_len);
|
||||
int (*add_tspec)(void *ctx, const u8 *sta_addr, u8 *tspec_ie,
|
||||
size_t tspec_ielen);
|
||||
#endif /* CONFIG_IEEE80211R */
|
||||
};
|
||||
|
||||
struct wpa_authenticator * wpa_init(const u8 *addr,
|
||||
struct wpa_auth_config *conf,
|
||||
struct wpa_auth_callbacks *cb);
|
||||
int wpa_init_keys(struct wpa_authenticator *wpa_auth);
|
||||
void wpa_deinit(struct wpa_authenticator *wpa_auth);
|
||||
int wpa_reconfig(struct wpa_authenticator *wpa_auth,
|
||||
struct wpa_auth_config *conf);
|
||||
@ -259,6 +261,8 @@ int wpa_auth_pmksa_add_preauth(struct wpa_authenticator *wpa_auth,
|
||||
int session_timeout,
|
||||
struct eapol_state_machine *eapol);
|
||||
int wpa_auth_sta_set_vlan(struct wpa_state_machine *sm, int vlan_id);
|
||||
void wpa_auth_eapol_key_tx_status(struct wpa_authenticator *wpa_auth,
|
||||
struct wpa_state_machine *sm, int ack);
|
||||
|
||||
#ifdef CONFIG_IEEE80211R
|
||||
u8 * wpa_sm_write_assoc_resp_ies(struct wpa_state_machine *sm, u8 *pos,
|
||||
@ -278,4 +282,11 @@ int wpa_ft_rrb_rx(struct wpa_authenticator *wpa_auth, const u8 *src_addr,
|
||||
void wpa_ft_push_pmk_r1(struct wpa_authenticator *wpa_auth, const u8 *addr);
|
||||
#endif /* CONFIG_IEEE80211R */
|
||||
|
||||
void wpa_wnmsleep_rekey_gtk(struct wpa_state_machine *sm);
|
||||
void wpa_set_wnmsleep(struct wpa_state_machine *sm, int flag);
|
||||
int wpa_wnmsleep_gtk_subelem(struct wpa_state_machine *sm, u8 *pos);
|
||||
int wpa_wnmsleep_igtk_subelem(struct wpa_state_machine *sm, u8 *pos);
|
||||
|
||||
int wpa_auth_uses_sae(struct wpa_state_machine *sm);
|
||||
|
||||
#endif /* WPA_AUTH_H */
|
||||
|
@ -2,14 +2,8 @@
|
||||
* hostapd - IEEE 802.11r - Fast BSS Transition
|
||||
* Copyright (c) 2004-2009, Jouni Malinen <j@w1.fi>
|
||||
*
|
||||
* This program is free software; you can redistribute it and/or modify
|
||||
* it under the terms of the GNU General Public License version 2 as
|
||||
* published by the Free Software Foundation.
|
||||
*
|
||||
* Alternatively, this software may be distributed under the terms of BSD
|
||||
* license.
|
||||
*
|
||||
* See README and COPYING for more details.
|
||||
* This software may be distributed under the terms of the BSD license.
|
||||
* See README for more details.
|
||||
*/
|
||||
|
||||
#include "utils/includes.h"
|
||||
@ -18,38 +12,16 @@
|
||||
#include "common/ieee802_11_defs.h"
|
||||
#include "common/ieee802_11_common.h"
|
||||
#include "crypto/aes_wrap.h"
|
||||
#include "crypto/random.h"
|
||||
#include "ap_config.h"
|
||||
#include "ieee802_11.h"
|
||||
#include "wmm.h"
|
||||
#include "wpa_auth.h"
|
||||
#include "wpa_auth_i.h"
|
||||
#include "wpa_auth_ie.h"
|
||||
|
||||
|
||||
#ifdef CONFIG_IEEE80211R
|
||||
|
||||
struct wpa_ft_ies {
|
||||
const u8 *mdie;
|
||||
size_t mdie_len;
|
||||
const u8 *ftie;
|
||||
size_t ftie_len;
|
||||
const u8 *r1kh_id;
|
||||
const u8 *gtk;
|
||||
size_t gtk_len;
|
||||
const u8 *r0kh_id;
|
||||
size_t r0kh_id_len;
|
||||
const u8 *rsn;
|
||||
size_t rsn_len;
|
||||
const u8 *rsn_pmkid;
|
||||
const u8 *ric;
|
||||
size_t ric_len;
|
||||
};
|
||||
|
||||
|
||||
static int wpa_ft_parse_ies(const u8 *ies, size_t ies_len,
|
||||
struct wpa_ft_ies *parse);
|
||||
|
||||
|
||||
static int wpa_ft_rrb_send(struct wpa_authenticator *wpa_auth, const u8 *dst,
|
||||
const u8 *data, size_t data_len)
|
||||
{
|
||||
@ -80,6 +52,19 @@ wpa_ft_add_sta(struct wpa_authenticator *wpa_auth, const u8 *sta_addr)
|
||||
}
|
||||
|
||||
|
||||
static int wpa_ft_add_tspec(struct wpa_authenticator *wpa_auth,
|
||||
const u8 *sta_addr,
|
||||
u8 *tspec_ie, size_t tspec_ielen)
|
||||
{
|
||||
if (wpa_auth->cb.add_tspec == NULL) {
|
||||
wpa_printf(MSG_DEBUG, "FT: add_tspec is not initialized");
|
||||
return -1;
|
||||
}
|
||||
return wpa_auth->cb.add_tspec(wpa_auth->cb.ctx, sta_addr, tspec_ie,
|
||||
tspec_ielen);
|
||||
}
|
||||
|
||||
|
||||
int wpa_write_mdie(struct wpa_auth_config *conf, u8 *buf, size_t len)
|
||||
{
|
||||
u8 *pos = buf;
|
||||
@ -91,7 +76,9 @@ int wpa_write_mdie(struct wpa_auth_config *conf, u8 *buf, size_t len)
|
||||
*pos++ = MOBILITY_DOMAIN_ID_LEN + 1;
|
||||
os_memcpy(pos, conf->mobility_domain, MOBILITY_DOMAIN_ID_LEN);
|
||||
pos += MOBILITY_DOMAIN_ID_LEN;
|
||||
capab = RSN_FT_CAPAB_FT_OVER_DS;
|
||||
capab = 0;
|
||||
if (conf->ft_over_ds)
|
||||
capab |= RSN_FT_CAPAB_FT_OVER_DS;
|
||||
*pos++ = capab;
|
||||
|
||||
return pos - buf;
|
||||
@ -334,7 +321,7 @@ static int wpa_ft_pull_pmk_r1(struct wpa_authenticator *wpa_auth,
|
||||
|
||||
/* aes_wrap() does not support inplace encryption, so use a temporary
|
||||
* buffer for the data. */
|
||||
if (os_get_random(f.nonce, sizeof(f.nonce))) {
|
||||
if (random_get_bytes(f.nonce, sizeof(f.nonce))) {
|
||||
wpa_printf(MSG_DEBUG, "FT: Failed to get random data for "
|
||||
"nonce");
|
||||
return -1;
|
||||
@ -497,7 +484,8 @@ static u8 * wpa_ft_igtk_subelem(struct wpa_state_machine *sm, size_t *len)
|
||||
#endif /* CONFIG_IEEE80211W */
|
||||
|
||||
|
||||
static u8 * wpa_ft_process_rdie(u8 *pos, u8 *end, u8 id, u8 descr_count,
|
||||
static u8 * wpa_ft_process_rdie(struct wpa_state_machine *sm,
|
||||
u8 *pos, u8 *end, u8 id, u8 descr_count,
|
||||
const u8 *ies, size_t ies_len)
|
||||
{
|
||||
struct ieee802_11_elems parse;
|
||||
@ -530,7 +518,7 @@ static u8 * wpa_ft_process_rdie(u8 *pos, u8 *end, u8 id, u8 descr_count,
|
||||
}
|
||||
|
||||
#ifdef NEED_AP_MLME
|
||||
if (parse.wmm_tspec) {
|
||||
if (parse.wmm_tspec && sm->wpa_auth->conf.ap_mlme) {
|
||||
struct wmm_tspec_element *tspec;
|
||||
int res;
|
||||
|
||||
@ -567,13 +555,35 @@ static u8 * wpa_ft_process_rdie(u8 *pos, u8 *end, u8 id, u8 descr_count,
|
||||
}
|
||||
#endif /* NEED_AP_MLME */
|
||||
|
||||
if (parse.wmm_tspec && !sm->wpa_auth->conf.ap_mlme) {
|
||||
struct wmm_tspec_element *tspec;
|
||||
int res;
|
||||
|
||||
tspec = (struct wmm_tspec_element *) pos;
|
||||
os_memcpy(tspec, parse.wmm_tspec - 2, sizeof(*tspec));
|
||||
res = wpa_ft_add_tspec(sm->wpa_auth, sm->addr, pos,
|
||||
sizeof(*tspec));
|
||||
if (res >= 0) {
|
||||
if (res)
|
||||
rdie->status_code = host_to_le16(res);
|
||||
else {
|
||||
/* TSPEC accepted; include updated TSPEC in
|
||||
* response */
|
||||
rdie->descr_count = 1;
|
||||
pos += sizeof(*tspec);
|
||||
}
|
||||
return pos;
|
||||
}
|
||||
}
|
||||
|
||||
wpa_printf(MSG_DEBUG, "FT: No supported resource requested");
|
||||
rdie->status_code = host_to_le16(WLAN_STATUS_UNSPECIFIED_FAILURE);
|
||||
return pos;
|
||||
}
|
||||
|
||||
|
||||
static u8 * wpa_ft_process_ric(u8 *pos, u8 *end, const u8 *ric, size_t ric_len)
|
||||
static u8 * wpa_ft_process_ric(struct wpa_state_machine *sm, u8 *pos, u8 *end,
|
||||
const u8 *ric, size_t ric_len)
|
||||
{
|
||||
const u8 *rpos, *start;
|
||||
const struct rsn_rdie *rdie;
|
||||
@ -595,7 +605,7 @@ static u8 * wpa_ft_process_ric(u8 *pos, u8 *end, const u8 *ric, size_t ric_len)
|
||||
break;
|
||||
rpos += 2 + rpos[1];
|
||||
}
|
||||
pos = wpa_ft_process_rdie(pos, end, rdie->id,
|
||||
pos = wpa_ft_process_rdie(sm, pos, end, rdie->id,
|
||||
rdie->descr_count,
|
||||
start, rpos - start);
|
||||
}
|
||||
@ -704,7 +714,8 @@ u8 * wpa_sm_write_assoc_resp_ies(struct wpa_state_machine *sm, u8 *pos,
|
||||
|
||||
ric_start = pos;
|
||||
if (wpa_ft_parse_ies(req_ies, req_ies_len, &parse) == 0 && parse.ric) {
|
||||
pos = wpa_ft_process_ric(pos, end, parse.ric, parse.ric_len);
|
||||
pos = wpa_ft_process_ric(sm, pos, end, parse.ric,
|
||||
parse.ric_len);
|
||||
if (auth_alg == WLAN_AUTH_FT)
|
||||
_ftie->mic_control[1] +=
|
||||
ieee802_11_ie_count(ric_start,
|
||||
@ -725,143 +736,6 @@ u8 * wpa_sm_write_assoc_resp_ies(struct wpa_state_machine *sm, u8 *pos,
|
||||
}
|
||||
|
||||
|
||||
static int wpa_ft_parse_ftie(const u8 *ie, size_t ie_len,
|
||||
struct wpa_ft_ies *parse)
|
||||
{
|
||||
const u8 *end, *pos;
|
||||
|
||||
parse->ftie = ie;
|
||||
parse->ftie_len = ie_len;
|
||||
|
||||
pos = ie + sizeof(struct rsn_ftie);
|
||||
end = ie + ie_len;
|
||||
|
||||
while (pos + 2 <= end && pos + 2 + pos[1] <= end) {
|
||||
switch (pos[0]) {
|
||||
case FTIE_SUBELEM_R1KH_ID:
|
||||
if (pos[1] != FT_R1KH_ID_LEN) {
|
||||
wpa_printf(MSG_DEBUG, "FT: Invalid R1KH-ID "
|
||||
"length in FTIE: %d", pos[1]);
|
||||
return -1;
|
||||
}
|
||||
parse->r1kh_id = pos + 2;
|
||||
break;
|
||||
case FTIE_SUBELEM_GTK:
|
||||
parse->gtk = pos + 2;
|
||||
parse->gtk_len = pos[1];
|
||||
break;
|
||||
case FTIE_SUBELEM_R0KH_ID:
|
||||
if (pos[1] < 1 || pos[1] > FT_R0KH_ID_MAX_LEN) {
|
||||
wpa_printf(MSG_DEBUG, "FT: Invalid R0KH-ID "
|
||||
"length in FTIE: %d", pos[1]);
|
||||
return -1;
|
||||
}
|
||||
parse->r0kh_id = pos + 2;
|
||||
parse->r0kh_id_len = pos[1];
|
||||
break;
|
||||
}
|
||||
|
||||
pos += 2 + pos[1];
|
||||
}
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
|
||||
static int wpa_ft_parse_ies(const u8 *ies, size_t ies_len,
|
||||
struct wpa_ft_ies *parse)
|
||||
{
|
||||
const u8 *end, *pos;
|
||||
struct wpa_ie_data data;
|
||||
int ret;
|
||||
const struct rsn_ftie *ftie;
|
||||
int prot_ie_count = 0;
|
||||
|
||||
os_memset(parse, 0, sizeof(*parse));
|
||||
if (ies == NULL)
|
||||
return 0;
|
||||
|
||||
pos = ies;
|
||||
end = ies + ies_len;
|
||||
while (pos + 2 <= end && pos + 2 + pos[1] <= end) {
|
||||
switch (pos[0]) {
|
||||
case WLAN_EID_RSN:
|
||||
parse->rsn = pos + 2;
|
||||
parse->rsn_len = pos[1];
|
||||
ret = wpa_parse_wpa_ie_rsn(parse->rsn - 2,
|
||||
parse->rsn_len + 2,
|
||||
&data);
|
||||
if (ret < 0) {
|
||||
wpa_printf(MSG_DEBUG, "FT: Failed to parse "
|
||||
"RSN IE: %d", ret);
|
||||
return -1;
|
||||
}
|
||||
if (data.num_pmkid == 1 && data.pmkid)
|
||||
parse->rsn_pmkid = data.pmkid;
|
||||
break;
|
||||
case WLAN_EID_MOBILITY_DOMAIN:
|
||||
parse->mdie = pos + 2;
|
||||
parse->mdie_len = pos[1];
|
||||
break;
|
||||
case WLAN_EID_FAST_BSS_TRANSITION:
|
||||
if (pos[1] < sizeof(*ftie))
|
||||
return -1;
|
||||
ftie = (const struct rsn_ftie *) (pos + 2);
|
||||
prot_ie_count = ftie->mic_control[1];
|
||||
if (wpa_ft_parse_ftie(pos + 2, pos[1], parse) < 0)
|
||||
return -1;
|
||||
break;
|
||||
case WLAN_EID_RIC_DATA:
|
||||
if (parse->ric == NULL)
|
||||
parse->ric = pos;
|
||||
}
|
||||
|
||||
pos += 2 + pos[1];
|
||||
}
|
||||
|
||||
if (prot_ie_count == 0)
|
||||
return 0; /* no MIC */
|
||||
|
||||
/*
|
||||
* Check that the protected IE count matches with IEs included in the
|
||||
* frame.
|
||||
*/
|
||||
if (parse->rsn)
|
||||
prot_ie_count--;
|
||||
if (parse->mdie)
|
||||
prot_ie_count--;
|
||||
if (parse->ftie)
|
||||
prot_ie_count--;
|
||||
if (prot_ie_count < 0) {
|
||||
wpa_printf(MSG_DEBUG, "FT: Some required IEs not included in "
|
||||
"the protected IE count");
|
||||
return -1;
|
||||
}
|
||||
|
||||
if (prot_ie_count == 0 && parse->ric) {
|
||||
wpa_printf(MSG_DEBUG, "FT: RIC IE(s) in the frame, but not "
|
||||
"included in protected IE count");
|
||||
return -1;
|
||||
}
|
||||
|
||||
/* Determine the end of the RIC IE(s) */
|
||||
pos = parse->ric;
|
||||
while (pos && pos + 2 <= end && pos + 2 + pos[1] <= end &&
|
||||
prot_ie_count) {
|
||||
prot_ie_count--;
|
||||
pos += 2 + pos[1];
|
||||
}
|
||||
parse->ric_len = pos - parse->ric;
|
||||
if (prot_ie_count) {
|
||||
wpa_printf(MSG_DEBUG, "FT: %d protected IEs missing from "
|
||||
"frame", (int) prot_ie_count);
|
||||
return -1;
|
||||
}
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
|
||||
static inline int wpa_auth_set_key(struct wpa_authenticator *wpa_auth,
|
||||
int vlan_id,
|
||||
enum wpa_alg alg, const u8 *addr, int idx,
|
||||
@ -880,13 +754,9 @@ void wpa_ft_install_ptk(struct wpa_state_machine *sm)
|
||||
int klen;
|
||||
|
||||
/* MLME-SETKEYS.request(PTK) */
|
||||
if (sm->pairwise == WPA_CIPHER_TKIP) {
|
||||
alg = WPA_ALG_TKIP;
|
||||
klen = 32;
|
||||
} else if (sm->pairwise == WPA_CIPHER_CCMP) {
|
||||
alg = WPA_ALG_CCMP;
|
||||
klen = 16;
|
||||
} else {
|
||||
alg = wpa_cipher_to_alg(sm->pairwise);
|
||||
klen = wpa_cipher_key_len(sm->pairwise);
|
||||
if (!wpa_cipher_valid_pairwise(sm->pairwise)) {
|
||||
wpa_printf(MSG_DEBUG, "FT: Unknown pairwise alg 0x%x - skip "
|
||||
"PTK configuration", sm->pairwise);
|
||||
return;
|
||||
@ -997,7 +867,7 @@ static u16 wpa_ft_process_auth_req(struct wpa_state_machine *sm,
|
||||
sm->pmk_r1_name_valid = 1;
|
||||
os_memcpy(sm->pmk_r1_name, pmk_r1_name, WPA_PMK_NAME_LEN);
|
||||
|
||||
if (os_get_random(sm->ANonce, WPA_NONCE_LEN)) {
|
||||
if (random_get_bytes(sm->ANonce, WPA_NONCE_LEN)) {
|
||||
wpa_printf(MSG_DEBUG, "FT: Failed to get random data for "
|
||||
"ANonce");
|
||||
return WLAN_STATUS_UNSPECIFIED_FAILURE;
|
||||
@ -1008,7 +878,7 @@ static u16 wpa_ft_process_auth_req(struct wpa_state_machine *sm,
|
||||
wpa_hexdump(MSG_DEBUG, "FT: Generated ANonce",
|
||||
sm->ANonce, WPA_NONCE_LEN);
|
||||
|
||||
ptk_len = pairwise != WPA_CIPHER_CCMP ? 64 : 48;
|
||||
ptk_len = pairwise == WPA_CIPHER_TKIP ? 64 : 48;
|
||||
wpa_pmk_r1_to_ptk(pmk_r1, sm->SNonce, sm->ANonce, sm->addr,
|
||||
sm->wpa_auth->addr, pmk_r1_name,
|
||||
(u8 *) &sm->PTK, ptk_len, ptk_name);
|
||||
@ -1204,7 +1074,7 @@ u16 wpa_ft_validate_reassoc(struct wpa_state_machine *sm, const u8 *ies,
|
||||
|
||||
count = 3;
|
||||
if (parse.ric)
|
||||
count++;
|
||||
count += ieee802_11_ie_count(parse.ric, parse.ric_len);
|
||||
if (ftie->mic_control[1] != count) {
|
||||
wpa_printf(MSG_DEBUG, "FT: Unexpected IE count in MIC "
|
||||
"Control: received %u expected %u",
|
||||
@ -1224,8 +1094,16 @@ u16 wpa_ft_validate_reassoc(struct wpa_state_machine *sm, const u8 *ies,
|
||||
|
||||
if (os_memcmp(mic, ftie->mic, 16) != 0) {
|
||||
wpa_printf(MSG_DEBUG, "FT: Invalid MIC in FTIE");
|
||||
wpa_printf(MSG_DEBUG, "FT: addr=" MACSTR " auth_addr=" MACSTR,
|
||||
MAC2STR(sm->addr), MAC2STR(sm->wpa_auth->addr));
|
||||
wpa_hexdump(MSG_MSGDUMP, "FT: Received MIC", ftie->mic, 16);
|
||||
wpa_hexdump(MSG_MSGDUMP, "FT: Calculated MIC", mic, 16);
|
||||
wpa_hexdump(MSG_MSGDUMP, "FT: MDIE",
|
||||
parse.mdie - 2, parse.mdie_len + 2);
|
||||
wpa_hexdump(MSG_MSGDUMP, "FT: FTIE",
|
||||
parse.ftie - 2, parse.ftie_len + 2);
|
||||
wpa_hexdump(MSG_MSGDUMP, "FT: RSN",
|
||||
parse.rsn - 2, parse.rsn_len + 2);
|
||||
return WLAN_STATUS_INVALID_FTIE;
|
||||
}
|
||||
|
||||
|
@ -1,15 +1,9 @@
|
||||
/*
|
||||
* hostapd / WPA authenticator glue code
|
||||
* Copyright (c) 2002-2009, Jouni Malinen <j@w1.fi>
|
||||
* Copyright (c) 2002-2011, Jouni Malinen <j@w1.fi>
|
||||
*
|
||||
* This program is free software; you can redistribute it and/or modify
|
||||
* it under the terms of the GNU General Public License version 2 as
|
||||
* published by the Free Software Foundation.
|
||||
*
|
||||
* Alternatively, this software may be distributed under the terms of BSD
|
||||
* license.
|
||||
*
|
||||
* See README and COPYING for more details.
|
||||
* This software may be distributed under the terms of the BSD license.
|
||||
* See README for more details.
|
||||
*/
|
||||
|
||||
#include "utils/includes.h"
|
||||
@ -29,17 +23,13 @@
|
||||
#include "ap_drv_ops.h"
|
||||
#include "ap_config.h"
|
||||
#include "wpa_auth.h"
|
||||
|
||||
|
||||
#ifdef CONFIG_IEEE80211R
|
||||
static void hostapd_rrb_receive(void *ctx, const u8 *src_addr, const u8 *buf,
|
||||
size_t len);
|
||||
#endif /* CONFIG_IEEE80211R */
|
||||
#include "wpa_auth_glue.h"
|
||||
|
||||
|
||||
static void hostapd_wpa_auth_conf(struct hostapd_bss_config *conf,
|
||||
struct wpa_auth_config *wconf)
|
||||
{
|
||||
os_memset(wconf, 0, sizeof(*wconf));
|
||||
wconf->wpa = conf->wpa;
|
||||
wconf->wpa_key_mgmt = conf->wpa_key_mgmt;
|
||||
wconf->wpa_pairwise = conf->wpa_pairwise;
|
||||
@ -54,6 +44,7 @@ static void hostapd_wpa_auth_conf(struct hostapd_bss_config *conf,
|
||||
wconf->peerkey = conf->peerkey;
|
||||
wconf->wmm_enabled = conf->wmm_enabled;
|
||||
wconf->wmm_uapsd = conf->wmm_uapsd;
|
||||
wconf->disable_pmksa_caching = conf->disable_pmksa_caching;
|
||||
wconf->okc = conf->okc;
|
||||
#ifdef CONFIG_IEEE80211W
|
||||
wconf->ieee80211w = conf->ieee80211w;
|
||||
@ -77,7 +68,11 @@ static void hostapd_wpa_auth_conf(struct hostapd_bss_config *conf,
|
||||
wconf->r0kh_list = conf->r0kh_list;
|
||||
wconf->r1kh_list = conf->r1kh_list;
|
||||
wconf->pmk_r1_push = conf->pmk_r1_push;
|
||||
wconf->ft_over_ds = conf->ft_over_ds;
|
||||
#endif /* CONFIG_IEEE80211R */
|
||||
#ifdef CONFIG_HS20
|
||||
wconf->disable_gtk = conf->disable_dgaf;
|
||||
#endif /* CONFIG_HS20 */
|
||||
}
|
||||
|
||||
|
||||
@ -117,10 +112,10 @@ static void hostapd_wpa_auth_disconnect(void *ctx, const u8 *addr,
|
||||
}
|
||||
|
||||
|
||||
static void hostapd_wpa_auth_mic_failure_report(void *ctx, const u8 *addr)
|
||||
static int hostapd_wpa_auth_mic_failure_report(void *ctx, const u8 *addr)
|
||||
{
|
||||
struct hostapd_data *hapd = ctx;
|
||||
michael_mic_failure(hapd, addr, 0);
|
||||
return michael_mic_failure(hapd, addr, 0);
|
||||
}
|
||||
|
||||
|
||||
@ -188,7 +183,24 @@ static const u8 * hostapd_wpa_auth_get_psk(void *ctx, const u8 *addr,
|
||||
const u8 *prev_psk)
|
||||
{
|
||||
struct hostapd_data *hapd = ctx;
|
||||
return hostapd_get_psk(hapd->conf, addr, prev_psk);
|
||||
struct sta_info *sta = ap_get_sta(hapd, addr);
|
||||
const u8 *psk = hostapd_get_psk(hapd->conf, addr, prev_psk);
|
||||
/*
|
||||
* This is about to iterate over all psks, prev_psk gives the last
|
||||
* returned psk which should not be returned again.
|
||||
* logic list (all hostapd_get_psk; all sta->psk)
|
||||
*/
|
||||
if (sta && sta->psk && !psk) {
|
||||
struct hostapd_sta_wpa_psk_short *pos;
|
||||
psk = sta->psk->psk;
|
||||
for (pos = sta->psk; pos; pos = pos->next) {
|
||||
if (pos->psk == prev_psk) {
|
||||
psk = pos->next ? pos->next->psk : NULL;
|
||||
break;
|
||||
}
|
||||
}
|
||||
}
|
||||
return psk;
|
||||
}
|
||||
|
||||
|
||||
@ -230,8 +242,8 @@ static int hostapd_wpa_auth_set_key(void *ctx, int vlan_id, enum wpa_alg alg,
|
||||
return -1;
|
||||
}
|
||||
|
||||
return hapd->drv.set_key(ifname, hapd, alg, addr, idx, 1, NULL, 0,
|
||||
key, key_len);
|
||||
return hostapd_drv_set_key(ifname, hapd, alg, addr, idx, 1, NULL, 0,
|
||||
key, key_len);
|
||||
}
|
||||
|
||||
|
||||
@ -248,7 +260,15 @@ static int hostapd_wpa_auth_send_eapol(void *ctx, const u8 *addr,
|
||||
int encrypt)
|
||||
{
|
||||
struct hostapd_data *hapd = ctx;
|
||||
return hapd->drv.send_eapol(hapd, addr, data, data_len, encrypt);
|
||||
struct sta_info *sta;
|
||||
u32 flags = 0;
|
||||
|
||||
sta = ap_get_sta(hapd, addr);
|
||||
if (sta)
|
||||
flags = hostapd_sta_flags_to_drv(sta->flags);
|
||||
|
||||
return hostapd_drv_hapd_send_eapol(hapd, addr, data, data_len,
|
||||
encrypt, flags);
|
||||
}
|
||||
|
||||
|
||||
@ -291,12 +311,13 @@ static int hostapd_wpa_auth_for_each_auth(
|
||||
{
|
||||
struct hostapd_data *hapd = ctx;
|
||||
struct wpa_auth_iface_iter_data data;
|
||||
if (hapd->iface->for_each_interface == NULL)
|
||||
if (hapd->iface->interfaces == NULL ||
|
||||
hapd->iface->interfaces->for_each_interface == NULL)
|
||||
return -1;
|
||||
data.cb = cb;
|
||||
data.cb_ctx = cb_ctx;
|
||||
return hapd->iface->for_each_interface(hapd->iface->interfaces,
|
||||
wpa_auth_iface_iter, &data);
|
||||
return hapd->iface->interfaces->for_each_interface(
|
||||
hapd->iface->interfaces, wpa_auth_iface_iter, &data);
|
||||
}
|
||||
|
||||
|
||||
@ -327,8 +348,9 @@ static int hostapd_wpa_auth_ft_iter(struct hostapd_iface *iface, void *ctx)
|
||||
MAC2STR(idata->src_hapd->own_addr),
|
||||
idata->src_hapd->conf->iface,
|
||||
MAC2STR(hapd->own_addr), hapd->conf->iface);
|
||||
hostapd_rrb_receive(hapd, idata->src_hapd->own_addr,
|
||||
idata->data, idata->data_len);
|
||||
wpa_ft_rrb_rx(hapd->wpa_auth,
|
||||
idata->src_hapd->own_addr,
|
||||
idata->data, idata->data_len);
|
||||
return 1;
|
||||
}
|
||||
}
|
||||
@ -343,18 +365,21 @@ static int hostapd_wpa_auth_send_ether(void *ctx, const u8 *dst, u16 proto,
|
||||
const u8 *data, size_t data_len)
|
||||
{
|
||||
struct hostapd_data *hapd = ctx;
|
||||
struct l2_ethhdr *buf;
|
||||
int ret;
|
||||
|
||||
#ifdef CONFIG_IEEE80211R
|
||||
if (proto == ETH_P_RRB && hapd->iface->for_each_interface) {
|
||||
if (proto == ETH_P_RRB && hapd->iface->interfaces &&
|
||||
hapd->iface->interfaces->for_each_interface) {
|
||||
int res;
|
||||
struct wpa_auth_ft_iface_iter_data idata;
|
||||
idata.src_hapd = hapd;
|
||||
idata.dst = dst;
|
||||
idata.data = data;
|
||||
idata.data_len = data_len;
|
||||
res = hapd->iface->for_each_interface(hapd->iface->interfaces,
|
||||
hostapd_wpa_auth_ft_iter,
|
||||
&idata);
|
||||
res = hapd->iface->interfaces->for_each_interface(
|
||||
hapd->iface->interfaces, hostapd_wpa_auth_ft_iter,
|
||||
&idata);
|
||||
if (res == 1)
|
||||
return data_len;
|
||||
}
|
||||
@ -366,7 +391,18 @@ static int hostapd_wpa_auth_send_ether(void *ctx, const u8 *dst, u16 proto,
|
||||
data, data_len);
|
||||
if (hapd->l2 == NULL)
|
||||
return -1;
|
||||
return l2_packet_send(hapd->l2, dst, proto, data, data_len);
|
||||
|
||||
buf = os_malloc(sizeof(*buf) + data_len);
|
||||
if (buf == NULL)
|
||||
return -1;
|
||||
os_memcpy(buf->h_dest, dst, ETH_ALEN);
|
||||
os_memcpy(buf->h_source, hapd->own_addr, ETH_ALEN);
|
||||
buf->h_proto = host_to_be16(proto);
|
||||
os_memcpy(buf + 1, data, data_len);
|
||||
ret = l2_packet_send(hapd->l2, dst, proto, (u8 *) buf,
|
||||
sizeof(*buf) + data_len);
|
||||
os_free(buf);
|
||||
return ret;
|
||||
}
|
||||
|
||||
|
||||
@ -396,7 +432,7 @@ static int hostapd_wpa_auth_send_ft_action(void *ctx, const u8 *dst,
|
||||
os_memcpy(m->bssid, hapd->own_addr, ETH_ALEN);
|
||||
os_memcpy(&m->u, data, data_len);
|
||||
|
||||
res = hapd->drv.send_mgmt_frame(hapd, (u8 *) m, mlen);
|
||||
res = hostapd_drv_send_mlme(hapd, (u8 *) m, mlen, 0);
|
||||
os_free(m);
|
||||
return res;
|
||||
}
|
||||
@ -408,6 +444,9 @@ hostapd_wpa_auth_add_sta(void *ctx, const u8 *sta_addr)
|
||||
struct hostapd_data *hapd = ctx;
|
||||
struct sta_info *sta;
|
||||
|
||||
if (hostapd_add_sta_node(hapd, sta_addr, WLAN_AUTH_FT) < 0)
|
||||
return NULL;
|
||||
|
||||
sta = ap_sta_add(hapd, sta_addr);
|
||||
if (sta == NULL)
|
||||
return NULL;
|
||||
@ -431,7 +470,22 @@ static void hostapd_rrb_receive(void *ctx, const u8 *src_addr, const u8 *buf,
|
||||
size_t len)
|
||||
{
|
||||
struct hostapd_data *hapd = ctx;
|
||||
wpa_ft_rrb_rx(hapd->wpa_auth, src_addr, buf, len);
|
||||
struct l2_ethhdr *ethhdr;
|
||||
if (len < sizeof(*ethhdr))
|
||||
return;
|
||||
ethhdr = (struct l2_ethhdr *) buf;
|
||||
wpa_printf(MSG_DEBUG, "FT: RRB received packet " MACSTR " -> "
|
||||
MACSTR, MAC2STR(ethhdr->h_source), MAC2STR(ethhdr->h_dest));
|
||||
wpa_ft_rrb_rx(hapd->wpa_auth, ethhdr->h_source, buf + sizeof(*ethhdr),
|
||||
len - sizeof(*ethhdr));
|
||||
}
|
||||
|
||||
|
||||
static int hostapd_wpa_auth_add_tspec(void *ctx, const u8 *sta_addr,
|
||||
u8 *tspec_ie, size_t tspec_ielen)
|
||||
{
|
||||
struct hostapd_data *hapd = ctx;
|
||||
return hostapd_add_tspec(hapd, sta_addr, tspec_ie, tspec_ielen);
|
||||
}
|
||||
|
||||
#endif /* CONFIG_IEEE80211R */
|
||||
@ -445,6 +499,10 @@ int hostapd_setup_wpa(struct hostapd_data *hapd)
|
||||
size_t wpa_ie_len;
|
||||
|
||||
hostapd_wpa_auth_conf(hapd->conf, &_conf);
|
||||
if (hapd->iface->drv_flags & WPA_DRIVER_FLAGS_EAPOL_TX_STATUS)
|
||||
_conf.tx_status = 1;
|
||||
if (hapd->iface->drv_flags & WPA_DRIVER_FLAGS_AP_MLME)
|
||||
_conf.ap_mlme = 1;
|
||||
os_memset(&cb, 0, sizeof(cb));
|
||||
cb.ctx = hapd;
|
||||
cb.logger = hostapd_wpa_auth_logger;
|
||||
@ -463,6 +521,7 @@ int hostapd_setup_wpa(struct hostapd_data *hapd)
|
||||
#ifdef CONFIG_IEEE80211R
|
||||
cb.send_ft_action = hostapd_wpa_auth_send_ft_action;
|
||||
cb.add_sta = hostapd_wpa_auth_add_sta;
|
||||
cb.add_tspec = hostapd_wpa_auth_add_tspec;
|
||||
#endif /* CONFIG_IEEE80211R */
|
||||
hapd->wpa_auth = wpa_init(hapd->own_addr, &_conf, &cb);
|
||||
if (hapd->wpa_auth == NULL) {
|
||||
@ -494,7 +553,7 @@ int hostapd_setup_wpa(struct hostapd_data *hapd)
|
||||
hapd->l2 = l2_packet_init(hapd->conf->bridge[0] ?
|
||||
hapd->conf->bridge :
|
||||
hapd->conf->iface, NULL, ETH_P_RRB,
|
||||
hostapd_rrb_receive, hapd, 0);
|
||||
hostapd_rrb_receive, hapd, 1);
|
||||
if (hapd->l2 == NULL &&
|
||||
(hapd->driver == NULL ||
|
||||
hapd->driver->send_ether == NULL)) {
|
||||
@ -520,6 +579,7 @@ void hostapd_reconfig_wpa(struct hostapd_data *hapd)
|
||||
|
||||
void hostapd_deinit_wpa(struct hostapd_data *hapd)
|
||||
{
|
||||
ieee80211_tkip_countermeasures_deinit(hapd);
|
||||
rsn_preauth_iface_deinit(hapd);
|
||||
if (hapd->wpa_auth) {
|
||||
wpa_deinit(hapd->wpa_auth);
|
||||
|
@ -2,14 +2,8 @@
|
||||
* hostapd / WPA authenticator glue code
|
||||
* Copyright (c) 2002-2009, Jouni Malinen <j@w1.fi>
|
||||
*
|
||||
* This program is free software; you can redistribute it and/or modify
|
||||
* it under the terms of the GNU General Public License version 2 as
|
||||
* published by the Free Software Foundation.
|
||||
*
|
||||
* Alternatively, this software may be distributed under the terms of BSD
|
||||
* license.
|
||||
*
|
||||
* See README and COPYING for more details.
|
||||
* This software may be distributed under the terms of the BSD license.
|
||||
* See README for more details.
|
||||
*/
|
||||
|
||||
#ifndef WPA_AUTH_GLUE_H
|
||||
|
@ -2,14 +2,8 @@
|
||||
* hostapd - IEEE 802.11i-2004 / WPA Authenticator: Internal definitions
|
||||
* Copyright (c) 2004-2007, Jouni Malinen <j@w1.fi>
|
||||
*
|
||||
* This program is free software; you can redistribute it and/or modify
|
||||
* it under the terms of the GNU General Public License version 2 as
|
||||
* published by the Free Software Foundation.
|
||||
*
|
||||
* Alternatively, this software may be distributed under the terms of BSD
|
||||
* license.
|
||||
*
|
||||
* See README and COPYING for more details.
|
||||
* This software may be distributed under the terms of the BSD license.
|
||||
* See README for more details.
|
||||
*/
|
||||
|
||||
#ifndef WPA_AUTH_I_H
|
||||
@ -69,10 +63,11 @@ struct wpa_state_machine {
|
||||
Boolean pairwise_set;
|
||||
int keycount;
|
||||
Boolean Pair;
|
||||
struct {
|
||||
struct wpa_key_replay_counter {
|
||||
u8 counter[WPA_REPLAY_COUNTER_LEN];
|
||||
Boolean valid;
|
||||
} key_replay[RSNA_MAX_EAPOL_RETRIES];
|
||||
} key_replay[RSNA_MAX_EAPOL_RETRIES],
|
||||
prev_key_replay[RSNA_MAX_EAPOL_RETRIES];
|
||||
Boolean PInitAKeys; /* WPA only, not in IEEE 802.11i */
|
||||
Boolean PTKRequest; /* not in IEEE 802.11i state machine */
|
||||
Boolean has_GTK;
|
||||
@ -86,10 +81,13 @@ struct wpa_state_machine {
|
||||
unsigned int pending_deinit:1;
|
||||
unsigned int started:1;
|
||||
unsigned int mgmt_frame_prot:1;
|
||||
unsigned int rx_eapol_key_secure:1;
|
||||
unsigned int update_snonce:1;
|
||||
#ifdef CONFIG_IEEE80211R
|
||||
unsigned int ft_completed:1;
|
||||
unsigned int pmk_r1_name_valid:1;
|
||||
#endif /* CONFIG_IEEE80211R */
|
||||
unsigned int is_wnmsleep:1;
|
||||
|
||||
u8 req_replay_counter[WPA_REPLAY_COUNTER_LEN];
|
||||
int req_replay_counter_used;
|
||||
@ -120,6 +118,8 @@ struct wpa_state_machine {
|
||||
* message 2/4 */
|
||||
u8 *assoc_resp_ftie;
|
||||
#endif /* CONFIG_IEEE80211R */
|
||||
|
||||
int pending_1_of_4_timeout;
|
||||
};
|
||||
|
||||
|
||||
@ -145,6 +145,8 @@ struct wpa_group {
|
||||
u8 GTK[2][WPA_GTK_MAX_LEN];
|
||||
u8 GNonce[WPA_NONCE_LEN];
|
||||
Boolean changed;
|
||||
Boolean first_sta_seen;
|
||||
Boolean reject_4way_hs_for_entropy;
|
||||
#ifdef CONFIG_IEEE80211W
|
||||
u8 IGTK[2][WPA_IGTK_LEN];
|
||||
int GN_igtk, GM_igtk;
|
||||
|
@ -2,14 +2,8 @@
|
||||
* hostapd - WPA/RSN IE and KDE definitions
|
||||
* Copyright (c) 2004-2008, Jouni Malinen <j@w1.fi>
|
||||
*
|
||||
* This program is free software; you can redistribute it and/or modify
|
||||
* it under the terms of the GNU General Public License version 2 as
|
||||
* published by the Free Software Foundation.
|
||||
*
|
||||
* Alternatively, this software may be distributed under the terms of BSD
|
||||
* license.
|
||||
*
|
||||
* See README and COPYING for more details.
|
||||
* This software may be distributed under the terms of the BSD license.
|
||||
* See README for more details.
|
||||
*/
|
||||
|
||||
#include "utils/includes.h"
|
||||
@ -25,11 +19,17 @@
|
||||
#include "wpa_auth_i.h"
|
||||
|
||||
|
||||
#ifdef CONFIG_RSN_TESTING
|
||||
int rsn_testing = 0;
|
||||
#endif /* CONFIG_RSN_TESTING */
|
||||
|
||||
|
||||
static int wpa_write_wpa_ie(struct wpa_auth_config *conf, u8 *buf, size_t len)
|
||||
{
|
||||
struct wpa_ie_hdr *hdr;
|
||||
int num_suites;
|
||||
u8 *pos, *count;
|
||||
u32 suite;
|
||||
|
||||
hdr = (struct wpa_ie_hdr *) buf;
|
||||
hdr->elem_id = WLAN_EID_VENDOR_SPECIFIC;
|
||||
@ -37,46 +37,25 @@ static int wpa_write_wpa_ie(struct wpa_auth_config *conf, u8 *buf, size_t len)
|
||||
WPA_PUT_LE16(hdr->version, WPA_VERSION);
|
||||
pos = (u8 *) (hdr + 1);
|
||||
|
||||
if (conf->wpa_group == WPA_CIPHER_CCMP) {
|
||||
RSN_SELECTOR_PUT(pos, WPA_CIPHER_SUITE_CCMP);
|
||||
} else if (conf->wpa_group == WPA_CIPHER_TKIP) {
|
||||
RSN_SELECTOR_PUT(pos, WPA_CIPHER_SUITE_TKIP);
|
||||
} else if (conf->wpa_group == WPA_CIPHER_WEP104) {
|
||||
RSN_SELECTOR_PUT(pos, WPA_CIPHER_SUITE_WEP104);
|
||||
} else if (conf->wpa_group == WPA_CIPHER_WEP40) {
|
||||
RSN_SELECTOR_PUT(pos, WPA_CIPHER_SUITE_WEP40);
|
||||
} else {
|
||||
suite = wpa_cipher_to_suite(WPA_PROTO_WPA, conf->wpa_group);
|
||||
if (suite == 0) {
|
||||
wpa_printf(MSG_DEBUG, "Invalid group cipher (%d).",
|
||||
conf->wpa_group);
|
||||
return -1;
|
||||
}
|
||||
RSN_SELECTOR_PUT(pos, suite);
|
||||
pos += WPA_SELECTOR_LEN;
|
||||
|
||||
num_suites = 0;
|
||||
count = pos;
|
||||
pos += 2;
|
||||
|
||||
if (conf->wpa_pairwise & WPA_CIPHER_CCMP) {
|
||||
RSN_SELECTOR_PUT(pos, WPA_CIPHER_SUITE_CCMP);
|
||||
pos += WPA_SELECTOR_LEN;
|
||||
num_suites++;
|
||||
}
|
||||
if (conf->wpa_pairwise & WPA_CIPHER_TKIP) {
|
||||
RSN_SELECTOR_PUT(pos, WPA_CIPHER_SUITE_TKIP);
|
||||
pos += WPA_SELECTOR_LEN;
|
||||
num_suites++;
|
||||
}
|
||||
if (conf->wpa_pairwise & WPA_CIPHER_NONE) {
|
||||
RSN_SELECTOR_PUT(pos, WPA_CIPHER_SUITE_NONE);
|
||||
pos += WPA_SELECTOR_LEN;
|
||||
num_suites++;
|
||||
}
|
||||
|
||||
num_suites = wpa_cipher_put_suites(pos, conf->wpa_pairwise);
|
||||
if (num_suites == 0) {
|
||||
wpa_printf(MSG_DEBUG, "Invalid pairwise cipher (%d).",
|
||||
conf->wpa_pairwise);
|
||||
return -1;
|
||||
}
|
||||
pos += num_suites * WPA_SELECTOR_LEN;
|
||||
WPA_PUT_LE16(count, num_suites);
|
||||
|
||||
num_suites = 0;
|
||||
@ -113,49 +92,48 @@ int wpa_write_rsn_ie(struct wpa_auth_config *conf, u8 *buf, size_t len,
|
||||
const u8 *pmkid)
|
||||
{
|
||||
struct rsn_ie_hdr *hdr;
|
||||
int num_suites;
|
||||
int num_suites, res;
|
||||
u8 *pos, *count;
|
||||
u16 capab;
|
||||
u32 suite;
|
||||
|
||||
hdr = (struct rsn_ie_hdr *) buf;
|
||||
hdr->elem_id = WLAN_EID_RSN;
|
||||
WPA_PUT_LE16(hdr->version, RSN_VERSION);
|
||||
pos = (u8 *) (hdr + 1);
|
||||
|
||||
if (conf->wpa_group == WPA_CIPHER_CCMP) {
|
||||
RSN_SELECTOR_PUT(pos, RSN_CIPHER_SUITE_CCMP);
|
||||
} else if (conf->wpa_group == WPA_CIPHER_TKIP) {
|
||||
RSN_SELECTOR_PUT(pos, RSN_CIPHER_SUITE_TKIP);
|
||||
} else if (conf->wpa_group == WPA_CIPHER_WEP104) {
|
||||
RSN_SELECTOR_PUT(pos, RSN_CIPHER_SUITE_WEP104);
|
||||
} else if (conf->wpa_group == WPA_CIPHER_WEP40) {
|
||||
RSN_SELECTOR_PUT(pos, RSN_CIPHER_SUITE_WEP40);
|
||||
} else {
|
||||
suite = wpa_cipher_to_suite(WPA_PROTO_RSN, conf->wpa_group);
|
||||
if (suite == 0) {
|
||||
wpa_printf(MSG_DEBUG, "Invalid group cipher (%d).",
|
||||
conf->wpa_group);
|
||||
return -1;
|
||||
}
|
||||
RSN_SELECTOR_PUT(pos, suite);
|
||||
pos += RSN_SELECTOR_LEN;
|
||||
|
||||
num_suites = 0;
|
||||
count = pos;
|
||||
pos += 2;
|
||||
|
||||
if (conf->rsn_pairwise & WPA_CIPHER_CCMP) {
|
||||
RSN_SELECTOR_PUT(pos, RSN_CIPHER_SUITE_CCMP);
|
||||
#ifdef CONFIG_RSN_TESTING
|
||||
if (rsn_testing) {
|
||||
RSN_SELECTOR_PUT(pos, RSN_SELECTOR(0x12, 0x34, 0x56, 1));
|
||||
pos += RSN_SELECTOR_LEN;
|
||||
num_suites++;
|
||||
}
|
||||
if (conf->rsn_pairwise & WPA_CIPHER_TKIP) {
|
||||
RSN_SELECTOR_PUT(pos, RSN_CIPHER_SUITE_TKIP);
|
||||
pos += RSN_SELECTOR_LEN;
|
||||
num_suites++;
|
||||
}
|
||||
if (conf->rsn_pairwise & WPA_CIPHER_NONE) {
|
||||
RSN_SELECTOR_PUT(pos, RSN_CIPHER_SUITE_NONE);
|
||||
#endif /* CONFIG_RSN_TESTING */
|
||||
|
||||
res = rsn_cipher_put_suites(pos, conf->rsn_pairwise);
|
||||
num_suites += res;
|
||||
pos += res * RSN_SELECTOR_LEN;
|
||||
|
||||
#ifdef CONFIG_RSN_TESTING
|
||||
if (rsn_testing) {
|
||||
RSN_SELECTOR_PUT(pos, RSN_SELECTOR(0x12, 0x34, 0x56, 2));
|
||||
pos += RSN_SELECTOR_LEN;
|
||||
num_suites++;
|
||||
}
|
||||
#endif /* CONFIG_RSN_TESTING */
|
||||
|
||||
if (num_suites == 0) {
|
||||
wpa_printf(MSG_DEBUG, "Invalid pairwise cipher (%d).",
|
||||
@ -168,6 +146,14 @@ int wpa_write_rsn_ie(struct wpa_auth_config *conf, u8 *buf, size_t len,
|
||||
count = pos;
|
||||
pos += 2;
|
||||
|
||||
#ifdef CONFIG_RSN_TESTING
|
||||
if (rsn_testing) {
|
||||
RSN_SELECTOR_PUT(pos, RSN_SELECTOR(0x12, 0x34, 0x56, 1));
|
||||
pos += RSN_SELECTOR_LEN;
|
||||
num_suites++;
|
||||
}
|
||||
#endif /* CONFIG_RSN_TESTING */
|
||||
|
||||
if (conf->wpa_key_mgmt & WPA_KEY_MGMT_IEEE8021X) {
|
||||
RSN_SELECTOR_PUT(pos, RSN_AUTH_KEY_MGMT_UNSPEC_802_1X);
|
||||
pos += RSN_SELECTOR_LEN;
|
||||
@ -202,6 +188,26 @@ int wpa_write_rsn_ie(struct wpa_auth_config *conf, u8 *buf, size_t len,
|
||||
num_suites++;
|
||||
}
|
||||
#endif /* CONFIG_IEEE80211W */
|
||||
#ifdef CONFIG_SAE
|
||||
if (conf->wpa_key_mgmt & WPA_KEY_MGMT_SAE) {
|
||||
RSN_SELECTOR_PUT(pos, RSN_AUTH_KEY_MGMT_SAE);
|
||||
pos += RSN_SELECTOR_LEN;
|
||||
num_suites++;
|
||||
}
|
||||
if (conf->wpa_key_mgmt & WPA_KEY_MGMT_FT_SAE) {
|
||||
RSN_SELECTOR_PUT(pos, RSN_AUTH_KEY_MGMT_FT_SAE);
|
||||
pos += RSN_SELECTOR_LEN;
|
||||
num_suites++;
|
||||
}
|
||||
#endif /* CONFIG_SAE */
|
||||
|
||||
#ifdef CONFIG_RSN_TESTING
|
||||
if (rsn_testing) {
|
||||
RSN_SELECTOR_PUT(pos, RSN_SELECTOR(0x12, 0x34, 0x56, 2));
|
||||
pos += RSN_SELECTOR_LEN;
|
||||
num_suites++;
|
||||
}
|
||||
#endif /* CONFIG_RSN_TESTING */
|
||||
|
||||
if (num_suites == 0) {
|
||||
wpa_printf(MSG_DEBUG, "Invalid key management type (%d).",
|
||||
@ -227,6 +233,10 @@ int wpa_write_rsn_ie(struct wpa_auth_config *conf, u8 *buf, size_t len,
|
||||
capab |= WPA_CAPABILITY_MFPR;
|
||||
}
|
||||
#endif /* CONFIG_IEEE80211W */
|
||||
#ifdef CONFIG_RSN_TESTING
|
||||
if (rsn_testing)
|
||||
capab |= BIT(8) | BIT(14) | BIT(15);
|
||||
#endif /* CONFIG_RSN_TESTING */
|
||||
WPA_PUT_LE16(pos, capab);
|
||||
pos += 2;
|
||||
|
||||
@ -256,6 +266,29 @@ int wpa_write_rsn_ie(struct wpa_auth_config *conf, u8 *buf, size_t len,
|
||||
}
|
||||
#endif /* CONFIG_IEEE80211W */
|
||||
|
||||
#ifdef CONFIG_RSN_TESTING
|
||||
if (rsn_testing) {
|
||||
/*
|
||||
* Fill in any defined fields and add extra data to the end of
|
||||
* the element.
|
||||
*/
|
||||
int pmkid_count_set = pmkid != NULL;
|
||||
if (conf->ieee80211w != NO_MGMT_FRAME_PROTECTION)
|
||||
pmkid_count_set = 1;
|
||||
/* PMKID Count */
|
||||
WPA_PUT_LE16(pos, 0);
|
||||
pos += 2;
|
||||
if (conf->ieee80211w == NO_MGMT_FRAME_PROTECTION) {
|
||||
/* Management Group Cipher Suite */
|
||||
RSN_SELECTOR_PUT(pos, RSN_CIPHER_SUITE_AES_128_CMAC);
|
||||
pos += RSN_SELECTOR_LEN;
|
||||
}
|
||||
|
||||
os_memset(pos, 0x12, 17);
|
||||
pos += 17;
|
||||
}
|
||||
#endif /* CONFIG_RSN_TESTING */
|
||||
|
||||
hdr->len = (pos - buf) - 2;
|
||||
|
||||
return pos - buf;
|
||||
@ -277,8 +310,7 @@ int wpa_auth_gen_wpa_ie(struct wpa_authenticator *wpa_auth)
|
||||
pos += res;
|
||||
}
|
||||
#ifdef CONFIG_IEEE80211R
|
||||
if (wpa_auth->conf.wpa_key_mgmt &
|
||||
(WPA_KEY_MGMT_FT_IEEE8021X | WPA_KEY_MGMT_FT_PSK)) {
|
||||
if (wpa_key_mgmt_ft(wpa_auth->conf.wpa_key_mgmt)) {
|
||||
res = wpa_write_mdie(&wpa_auth->conf, pos,
|
||||
buf + sizeof(buf) - pos);
|
||||
if (res < 0)
|
||||
@ -322,114 +354,6 @@ u8 * wpa_add_kde(u8 *pos, u32 kde, const u8 *data, size_t data_len,
|
||||
}
|
||||
|
||||
|
||||
static int wpa_selector_to_bitfield(const u8 *s)
|
||||
{
|
||||
if (RSN_SELECTOR_GET(s) == WPA_CIPHER_SUITE_NONE)
|
||||
return WPA_CIPHER_NONE;
|
||||
if (RSN_SELECTOR_GET(s) == WPA_CIPHER_SUITE_WEP40)
|
||||
return WPA_CIPHER_WEP40;
|
||||
if (RSN_SELECTOR_GET(s) == WPA_CIPHER_SUITE_TKIP)
|
||||
return WPA_CIPHER_TKIP;
|
||||
if (RSN_SELECTOR_GET(s) == WPA_CIPHER_SUITE_CCMP)
|
||||
return WPA_CIPHER_CCMP;
|
||||
if (RSN_SELECTOR_GET(s) == WPA_CIPHER_SUITE_WEP104)
|
||||
return WPA_CIPHER_WEP104;
|
||||
return 0;
|
||||
}
|
||||
|
||||
|
||||
static int wpa_key_mgmt_to_bitfield(const u8 *s)
|
||||
{
|
||||
if (RSN_SELECTOR_GET(s) == WPA_AUTH_KEY_MGMT_UNSPEC_802_1X)
|
||||
return WPA_KEY_MGMT_IEEE8021X;
|
||||
if (RSN_SELECTOR_GET(s) == WPA_AUTH_KEY_MGMT_PSK_OVER_802_1X)
|
||||
return WPA_KEY_MGMT_PSK;
|
||||
if (RSN_SELECTOR_GET(s) == WPA_AUTH_KEY_MGMT_NONE)
|
||||
return WPA_KEY_MGMT_WPA_NONE;
|
||||
return 0;
|
||||
}
|
||||
|
||||
|
||||
static int wpa_parse_wpa_ie_wpa(const u8 *wpa_ie, size_t wpa_ie_len,
|
||||
struct wpa_ie_data *data)
|
||||
{
|
||||
const struct wpa_ie_hdr *hdr;
|
||||
const u8 *pos;
|
||||
int left;
|
||||
int i, count;
|
||||
|
||||
os_memset(data, 0, sizeof(*data));
|
||||
data->pairwise_cipher = WPA_CIPHER_TKIP;
|
||||
data->group_cipher = WPA_CIPHER_TKIP;
|
||||
data->key_mgmt = WPA_KEY_MGMT_IEEE8021X;
|
||||
data->mgmt_group_cipher = 0;
|
||||
|
||||
if (wpa_ie_len < sizeof(struct wpa_ie_hdr))
|
||||
return -1;
|
||||
|
||||
hdr = (const struct wpa_ie_hdr *) wpa_ie;
|
||||
|
||||
if (hdr->elem_id != WLAN_EID_VENDOR_SPECIFIC ||
|
||||
hdr->len != wpa_ie_len - 2 ||
|
||||
RSN_SELECTOR_GET(hdr->oui) != WPA_OUI_TYPE ||
|
||||
WPA_GET_LE16(hdr->version) != WPA_VERSION) {
|
||||
return -2;
|
||||
}
|
||||
|
||||
pos = (const u8 *) (hdr + 1);
|
||||
left = wpa_ie_len - sizeof(*hdr);
|
||||
|
||||
if (left >= WPA_SELECTOR_LEN) {
|
||||
data->group_cipher = wpa_selector_to_bitfield(pos);
|
||||
pos += WPA_SELECTOR_LEN;
|
||||
left -= WPA_SELECTOR_LEN;
|
||||
} else if (left > 0)
|
||||
return -3;
|
||||
|
||||
if (left >= 2) {
|
||||
data->pairwise_cipher = 0;
|
||||
count = WPA_GET_LE16(pos);
|
||||
pos += 2;
|
||||
left -= 2;
|
||||
if (count == 0 || left < count * WPA_SELECTOR_LEN)
|
||||
return -4;
|
||||
for (i = 0; i < count; i++) {
|
||||
data->pairwise_cipher |= wpa_selector_to_bitfield(pos);
|
||||
pos += WPA_SELECTOR_LEN;
|
||||
left -= WPA_SELECTOR_LEN;
|
||||
}
|
||||
} else if (left == 1)
|
||||
return -5;
|
||||
|
||||
if (left >= 2) {
|
||||
data->key_mgmt = 0;
|
||||
count = WPA_GET_LE16(pos);
|
||||
pos += 2;
|
||||
left -= 2;
|
||||
if (count == 0 || left < count * WPA_SELECTOR_LEN)
|
||||
return -6;
|
||||
for (i = 0; i < count; i++) {
|
||||
data->key_mgmt |= wpa_key_mgmt_to_bitfield(pos);
|
||||
pos += WPA_SELECTOR_LEN;
|
||||
left -= WPA_SELECTOR_LEN;
|
||||
}
|
||||
} else if (left == 1)
|
||||
return -7;
|
||||
|
||||
if (left >= 2) {
|
||||
data->capabilities = WPA_GET_LE16(pos);
|
||||
pos += 2;
|
||||
left -= 2;
|
||||
}
|
||||
|
||||
if (left > 0) {
|
||||
return -8;
|
||||
}
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
|
||||
struct wpa_auth_okc_iter_data {
|
||||
struct rsn_pmksa_cache_entry *pmksa;
|
||||
const u8 *aa;
|
||||
@ -495,36 +419,28 @@ int wpa_validate_wpa_ie(struct wpa_authenticator *wpa_auth,
|
||||
else if (data.key_mgmt & WPA_KEY_MGMT_PSK_SHA256)
|
||||
selector = RSN_AUTH_KEY_MGMT_PSK_SHA256;
|
||||
#endif /* CONFIG_IEEE80211W */
|
||||
#ifdef CONFIG_SAE
|
||||
else if (data.key_mgmt & WPA_KEY_MGMT_SAE)
|
||||
selector = RSN_AUTH_KEY_MGMT_SAE;
|
||||
else if (data.key_mgmt & WPA_KEY_MGMT_FT_SAE)
|
||||
selector = RSN_AUTH_KEY_MGMT_FT_SAE;
|
||||
#endif /* CONFIG_SAE */
|
||||
else if (data.key_mgmt & WPA_KEY_MGMT_IEEE8021X)
|
||||
selector = RSN_AUTH_KEY_MGMT_UNSPEC_802_1X;
|
||||
else if (data.key_mgmt & WPA_KEY_MGMT_PSK)
|
||||
selector = RSN_AUTH_KEY_MGMT_PSK_OVER_802_1X;
|
||||
wpa_auth->dot11RSNAAuthenticationSuiteSelected = selector;
|
||||
|
||||
selector = RSN_CIPHER_SUITE_CCMP;
|
||||
if (data.pairwise_cipher & WPA_CIPHER_CCMP)
|
||||
selector = wpa_cipher_to_suite(WPA_PROTO_RSN,
|
||||
data.pairwise_cipher);
|
||||
if (!selector)
|
||||
selector = RSN_CIPHER_SUITE_CCMP;
|
||||
else if (data.pairwise_cipher & WPA_CIPHER_TKIP)
|
||||
selector = RSN_CIPHER_SUITE_TKIP;
|
||||
else if (data.pairwise_cipher & WPA_CIPHER_WEP104)
|
||||
selector = RSN_CIPHER_SUITE_WEP104;
|
||||
else if (data.pairwise_cipher & WPA_CIPHER_WEP40)
|
||||
selector = RSN_CIPHER_SUITE_WEP40;
|
||||
else if (data.pairwise_cipher & WPA_CIPHER_NONE)
|
||||
selector = RSN_CIPHER_SUITE_NONE;
|
||||
wpa_auth->dot11RSNAPairwiseCipherSelected = selector;
|
||||
|
||||
selector = RSN_CIPHER_SUITE_CCMP;
|
||||
if (data.group_cipher & WPA_CIPHER_CCMP)
|
||||
selector = wpa_cipher_to_suite(WPA_PROTO_RSN,
|
||||
data.group_cipher);
|
||||
if (!selector)
|
||||
selector = RSN_CIPHER_SUITE_CCMP;
|
||||
else if (data.group_cipher & WPA_CIPHER_TKIP)
|
||||
selector = RSN_CIPHER_SUITE_TKIP;
|
||||
else if (data.group_cipher & WPA_CIPHER_WEP104)
|
||||
selector = RSN_CIPHER_SUITE_WEP104;
|
||||
else if (data.group_cipher & WPA_CIPHER_WEP40)
|
||||
selector = RSN_CIPHER_SUITE_WEP40;
|
||||
else if (data.group_cipher & WPA_CIPHER_NONE)
|
||||
selector = RSN_CIPHER_SUITE_NONE;
|
||||
wpa_auth->dot11RSNAGroupCipherSelected = selector;
|
||||
} else {
|
||||
res = wpa_parse_wpa_ie_wpa(wpa_ie, wpa_ie_len, &data);
|
||||
@ -536,30 +452,16 @@ int wpa_validate_wpa_ie(struct wpa_authenticator *wpa_auth,
|
||||
selector = WPA_AUTH_KEY_MGMT_PSK_OVER_802_1X;
|
||||
wpa_auth->dot11RSNAAuthenticationSuiteSelected = selector;
|
||||
|
||||
selector = WPA_CIPHER_SUITE_TKIP;
|
||||
if (data.pairwise_cipher & WPA_CIPHER_CCMP)
|
||||
selector = WPA_CIPHER_SUITE_CCMP;
|
||||
else if (data.pairwise_cipher & WPA_CIPHER_TKIP)
|
||||
selector = WPA_CIPHER_SUITE_TKIP;
|
||||
else if (data.pairwise_cipher & WPA_CIPHER_WEP104)
|
||||
selector = WPA_CIPHER_SUITE_WEP104;
|
||||
else if (data.pairwise_cipher & WPA_CIPHER_WEP40)
|
||||
selector = WPA_CIPHER_SUITE_WEP40;
|
||||
else if (data.pairwise_cipher & WPA_CIPHER_NONE)
|
||||
selector = WPA_CIPHER_SUITE_NONE;
|
||||
selector = wpa_cipher_to_suite(WPA_PROTO_WPA,
|
||||
data.pairwise_cipher);
|
||||
if (!selector)
|
||||
selector = RSN_CIPHER_SUITE_TKIP;
|
||||
wpa_auth->dot11RSNAPairwiseCipherSelected = selector;
|
||||
|
||||
selector = WPA_CIPHER_SUITE_TKIP;
|
||||
if (data.group_cipher & WPA_CIPHER_CCMP)
|
||||
selector = WPA_CIPHER_SUITE_CCMP;
|
||||
else if (data.group_cipher & WPA_CIPHER_TKIP)
|
||||
selector = wpa_cipher_to_suite(WPA_PROTO_WPA,
|
||||
data.group_cipher);
|
||||
if (!selector)
|
||||
selector = WPA_CIPHER_SUITE_TKIP;
|
||||
else if (data.group_cipher & WPA_CIPHER_WEP104)
|
||||
selector = WPA_CIPHER_SUITE_WEP104;
|
||||
else if (data.group_cipher & WPA_CIPHER_WEP40)
|
||||
selector = WPA_CIPHER_SUITE_WEP40;
|
||||
else if (data.group_cipher & WPA_CIPHER_NONE)
|
||||
selector = WPA_CIPHER_SUITE_NONE;
|
||||
wpa_auth->dot11RSNAGroupCipherSelected = selector;
|
||||
}
|
||||
if (res) {
|
||||
@ -595,6 +497,12 @@ int wpa_validate_wpa_ie(struct wpa_authenticator *wpa_auth,
|
||||
else if (key_mgmt & WPA_KEY_MGMT_PSK_SHA256)
|
||||
sm->wpa_key_mgmt = WPA_KEY_MGMT_PSK_SHA256;
|
||||
#endif /* CONFIG_IEEE80211W */
|
||||
#ifdef CONFIG_SAE
|
||||
else if (key_mgmt & WPA_KEY_MGMT_SAE)
|
||||
sm->wpa_key_mgmt = WPA_KEY_MGMT_SAE;
|
||||
else if (key_mgmt & WPA_KEY_MGMT_FT_SAE)
|
||||
sm->wpa_key_mgmt = WPA_KEY_MGMT_FT_SAE;
|
||||
#endif /* CONFIG_SAE */
|
||||
else if (key_mgmt & WPA_KEY_MGMT_IEEE8021X)
|
||||
sm->wpa_key_mgmt = WPA_KEY_MGMT_IEEE8021X;
|
||||
else
|
||||
@ -658,6 +566,8 @@ int wpa_validate_wpa_ie(struct wpa_authenticator *wpa_auth,
|
||||
|
||||
if (ciphers & WPA_CIPHER_CCMP)
|
||||
sm->pairwise = WPA_CIPHER_CCMP;
|
||||
else if (ciphers & WPA_CIPHER_GCMP)
|
||||
sm->pairwise = WPA_CIPHER_GCMP;
|
||||
else
|
||||
sm->pairwise = WPA_CIPHER_TKIP;
|
||||
|
||||
|
@ -2,14 +2,8 @@
|
||||
* hostapd - WPA/RSN IE and KDE definitions
|
||||
* Copyright (c) 2004-2007, Jouni Malinen <j@w1.fi>
|
||||
*
|
||||
* This program is free software; you can redistribute it and/or modify
|
||||
* it under the terms of the GNU General Public License version 2 as
|
||||
* published by the Free Software Foundation.
|
||||
*
|
||||
* Alternatively, this software may be distributed under the terms of BSD
|
||||
* license.
|
||||
*
|
||||
* See README and COPYING for more details.
|
||||
* This software may be distributed under the terms of the BSD license.
|
||||
* See README for more details.
|
||||
*/
|
||||
|
||||
#ifndef WPA_AUTH_IE_H
|
||||
|
File diff suppressed because it is too large
Load Diff
@ -1,15 +1,9 @@
|
||||
/*
|
||||
* hostapd / WPS integration
|
||||
* Copyright (c) 2008-2010, Jouni Malinen <j@w1.fi>
|
||||
* Copyright (c) 2008-2012, Jouni Malinen <j@w1.fi>
|
||||
*
|
||||
* This program is free software; you can redistribute it and/or modify
|
||||
* it under the terms of the GNU General Public License version 2 as
|
||||
* published by the Free Software Foundation.
|
||||
*
|
||||
* Alternatively, this software may be distributed under the terms of BSD
|
||||
* license.
|
||||
*
|
||||
* See README and COPYING for more details.
|
||||
* This software may be distributed under the terms of the BSD license.
|
||||
* See README for more details.
|
||||
*/
|
||||
|
||||
#ifndef WPS_HOSTAPD_H
|
||||
@ -19,13 +13,14 @@
|
||||
|
||||
int hostapd_init_wps(struct hostapd_data *hapd,
|
||||
struct hostapd_bss_config *conf);
|
||||
int hostapd_init_wps_complete(struct hostapd_data *hapd);
|
||||
void hostapd_deinit_wps(struct hostapd_data *hapd);
|
||||
void hostapd_update_wps(struct hostapd_data *hapd);
|
||||
int hostapd_wps_add_pin(struct hostapd_data *hapd, const char *uuid,
|
||||
const char *pin, int timeout);
|
||||
int hostapd_wps_button_pushed(struct hostapd_data *hapd);
|
||||
int hostapd_wps_start_oob(struct hostapd_data *hapd, char *device_type,
|
||||
char *path, char *method, char *name);
|
||||
int hostapd_wps_add_pin(struct hostapd_data *hapd, const u8 *addr,
|
||||
const char *uuid, const char *pin, int timeout);
|
||||
int hostapd_wps_button_pushed(struct hostapd_data *hapd,
|
||||
const u8 *p2p_dev_addr);
|
||||
int hostapd_wps_cancel(struct hostapd_data *hapd);
|
||||
int hostapd_wps_get_mib_sta(struct hostapd_data *hapd, const u8 *addr,
|
||||
char *buf, size_t buflen);
|
||||
void hostapd_wps_ap_pin_disable(struct hostapd_data *hapd);
|
||||
@ -33,6 +28,16 @@ const char * hostapd_wps_ap_pin_random(struct hostapd_data *hapd, int timeout);
|
||||
const char * hostapd_wps_ap_pin_get(struct hostapd_data *hapd);
|
||||
int hostapd_wps_ap_pin_set(struct hostapd_data *hapd, const char *pin,
|
||||
int timeout);
|
||||
void hostapd_wps_update_ie(struct hostapd_data *hapd);
|
||||
int hostapd_wps_config_ap(struct hostapd_data *hapd, const char *ssid,
|
||||
const char *auth, const char *encr, const char *key);
|
||||
int hostapd_wps_nfc_tag_read(struct hostapd_data *hapd,
|
||||
const struct wpabuf *data);
|
||||
struct wpabuf * hostapd_wps_nfc_config_token(struct hostapd_data *hapd,
|
||||
int ndef);
|
||||
struct wpabuf * hostapd_wps_nfc_token_gen(struct hostapd_data *hapd, int ndef);
|
||||
int hostapd_wps_nfc_token_enable(struct hostapd_data *hapd);
|
||||
void hostapd_wps_nfc_token_disable(struct hostapd_data *hapd);
|
||||
|
||||
#else /* CONFIG_WPS */
|
||||
|
||||
@ -46,6 +51,11 @@ static inline void hostapd_deinit_wps(struct hostapd_data *hapd)
|
||||
{
|
||||
}
|
||||
|
||||
static inline int hostapd_init_wps_complete(struct hostapd_data *hapd)
|
||||
{
|
||||
return 0;
|
||||
}
|
||||
|
||||
static inline void hostapd_update_wps(struct hostapd_data *hapd)
|
||||
{
|
||||
}
|
||||
@ -57,7 +67,13 @@ static inline int hostapd_wps_get_mib_sta(struct hostapd_data *hapd,
|
||||
return 0;
|
||||
}
|
||||
|
||||
static inline int hostapd_wps_button_pushed(struct hostapd_data *hapd)
|
||||
static inline int hostapd_wps_button_pushed(struct hostapd_data *hapd,
|
||||
const u8 *p2p_dev_addr)
|
||||
{
|
||||
return 0;
|
||||
}
|
||||
|
||||
static inline int hostapd_wps_cancel(struct hostapd_data *hapd)
|
||||
{
|
||||
return 0;
|
||||
}
|
||||
|
@ -2,14 +2,8 @@
|
||||
* WPA Supplicant - Common definitions
|
||||
* Copyright (c) 2004-2008, Jouni Malinen <j@w1.fi>
|
||||
*
|
||||
* This program is free software; you can redistribute it and/or modify
|
||||
* it under the terms of the GNU General Public License version 2 as
|
||||
* published by the Free Software Foundation.
|
||||
*
|
||||
* Alternatively, this software may be distributed under the terms of BSD
|
||||
* license.
|
||||
*
|
||||
* See README and COPYING for more details.
|
||||
* This software may be distributed under the terms of the BSD license.
|
||||
* See README for more details.
|
||||
*/
|
||||
|
||||
#ifndef DEFS_H
|
||||
@ -32,6 +26,8 @@ typedef enum { FALSE = 0, TRUE = 1 } Boolean;
|
||||
#ifdef CONFIG_IEEE80211W
|
||||
#define WPA_CIPHER_AES_128_CMAC BIT(5)
|
||||
#endif /* CONFIG_IEEE80211W */
|
||||
#define WPA_CIPHER_GCMP BIT(6)
|
||||
#define WPA_CIPHER_SMS4 BIT(7)
|
||||
|
||||
#define WPA_KEY_MGMT_IEEE8021X BIT(0)
|
||||
#define WPA_KEY_MGMT_PSK BIT(1)
|
||||
@ -43,41 +39,73 @@ typedef enum { FALSE = 0, TRUE = 1 } Boolean;
|
||||
#define WPA_KEY_MGMT_IEEE8021X_SHA256 BIT(7)
|
||||
#define WPA_KEY_MGMT_PSK_SHA256 BIT(8)
|
||||
#define WPA_KEY_MGMT_WPS BIT(9)
|
||||
#define WPA_KEY_MGMT_SAE BIT(10)
|
||||
#define WPA_KEY_MGMT_FT_SAE BIT(11)
|
||||
#define WPA_KEY_MGMT_WAPI_PSK BIT(12)
|
||||
#define WPA_KEY_MGMT_WAPI_CERT BIT(13)
|
||||
#define WPA_KEY_MGMT_CCKM BIT(14)
|
||||
|
||||
static inline int wpa_key_mgmt_wpa_ieee8021x(int akm)
|
||||
{
|
||||
return akm == WPA_KEY_MGMT_IEEE8021X ||
|
||||
akm == WPA_KEY_MGMT_FT_IEEE8021X ||
|
||||
akm == WPA_KEY_MGMT_IEEE8021X_SHA256;
|
||||
return !!(akm & (WPA_KEY_MGMT_IEEE8021X |
|
||||
WPA_KEY_MGMT_FT_IEEE8021X |
|
||||
WPA_KEY_MGMT_CCKM |
|
||||
WPA_KEY_MGMT_IEEE8021X_SHA256));
|
||||
}
|
||||
|
||||
static inline int wpa_key_mgmt_wpa_psk(int akm)
|
||||
{
|
||||
return akm == WPA_KEY_MGMT_PSK ||
|
||||
akm == WPA_KEY_MGMT_FT_PSK ||
|
||||
akm == WPA_KEY_MGMT_PSK_SHA256;
|
||||
return !!(akm & (WPA_KEY_MGMT_PSK |
|
||||
WPA_KEY_MGMT_FT_PSK |
|
||||
WPA_KEY_MGMT_PSK_SHA256 |
|
||||
WPA_KEY_MGMT_SAE));
|
||||
}
|
||||
|
||||
static inline int wpa_key_mgmt_ft(int akm)
|
||||
{
|
||||
return akm == WPA_KEY_MGMT_FT_PSK ||
|
||||
akm == WPA_KEY_MGMT_FT_IEEE8021X;
|
||||
return !!(akm & (WPA_KEY_MGMT_FT_PSK |
|
||||
WPA_KEY_MGMT_FT_IEEE8021X |
|
||||
WPA_KEY_MGMT_FT_SAE));
|
||||
}
|
||||
|
||||
static inline int wpa_key_mgmt_sae(int akm)
|
||||
{
|
||||
return !!(akm & (WPA_KEY_MGMT_SAE |
|
||||
WPA_KEY_MGMT_FT_SAE));
|
||||
}
|
||||
|
||||
static inline int wpa_key_mgmt_sha256(int akm)
|
||||
{
|
||||
return akm == WPA_KEY_MGMT_PSK_SHA256 ||
|
||||
akm == WPA_KEY_MGMT_IEEE8021X_SHA256;
|
||||
return !!(akm & (WPA_KEY_MGMT_PSK_SHA256 |
|
||||
WPA_KEY_MGMT_IEEE8021X_SHA256));
|
||||
}
|
||||
|
||||
static inline int wpa_key_mgmt_wpa(int akm)
|
||||
{
|
||||
return wpa_key_mgmt_wpa_ieee8021x(akm) ||
|
||||
wpa_key_mgmt_wpa_psk(akm);
|
||||
}
|
||||
|
||||
static inline int wpa_key_mgmt_wpa_any(int akm)
|
||||
{
|
||||
return wpa_key_mgmt_wpa(akm) || (akm & WPA_KEY_MGMT_WPA_NONE);
|
||||
}
|
||||
|
||||
static inline int wpa_key_mgmt_cckm(int akm)
|
||||
{
|
||||
return akm == WPA_KEY_MGMT_CCKM;
|
||||
}
|
||||
|
||||
|
||||
#define WPA_PROTO_WPA BIT(0)
|
||||
#define WPA_PROTO_RSN BIT(1)
|
||||
#define WPA_PROTO_WAPI BIT(2)
|
||||
|
||||
#define WPA_AUTH_ALG_OPEN BIT(0)
|
||||
#define WPA_AUTH_ALG_SHARED BIT(1)
|
||||
#define WPA_AUTH_ALG_LEAP BIT(2)
|
||||
#define WPA_AUTH_ALG_FT BIT(3)
|
||||
#define WPA_AUTH_ALG_SAE BIT(4)
|
||||
|
||||
|
||||
enum wpa_alg {
|
||||
@ -86,7 +114,10 @@ enum wpa_alg {
|
||||
WPA_ALG_TKIP,
|
||||
WPA_ALG_CCMP,
|
||||
WPA_ALG_IGTK,
|
||||
WPA_ALG_PMK
|
||||
WPA_ALG_PMK,
|
||||
WPA_ALG_GCMP,
|
||||
WPA_ALG_SMS4,
|
||||
WPA_ALG_KRK
|
||||
};
|
||||
|
||||
/**
|
||||
@ -97,7 +128,9 @@ enum wpa_cipher {
|
||||
CIPHER_WEP40,
|
||||
CIPHER_TKIP,
|
||||
CIPHER_CCMP,
|
||||
CIPHER_WEP104
|
||||
CIPHER_WEP104,
|
||||
CIPHER_GCMP,
|
||||
CIPHER_SMS4
|
||||
};
|
||||
|
||||
/**
|
||||
@ -113,7 +146,12 @@ enum wpa_key_mgmt {
|
||||
KEY_MGMT_FT_PSK,
|
||||
KEY_MGMT_802_1X_SHA256,
|
||||
KEY_MGMT_PSK_SHA256,
|
||||
KEY_MGMT_WPS
|
||||
KEY_MGMT_WPS,
|
||||
KEY_MGMT_SAE,
|
||||
KEY_MGMT_FT_SAE,
|
||||
KEY_MGMT_WAPI_PSK,
|
||||
KEY_MGMT_WAPI_CERT,
|
||||
KEY_MGMT_CCKM
|
||||
};
|
||||
|
||||
/**
|
||||
@ -136,6 +174,15 @@ enum wpa_states {
|
||||
*/
|
||||
WPA_DISCONNECTED,
|
||||
|
||||
/**
|
||||
* WPA_INTERFACE_DISABLED - Interface disabled
|
||||
*
|
||||
* This stat eis entered if the network interface is disabled, e.g.,
|
||||
* due to rfkill. wpa_supplicant refuses any new operations that would
|
||||
* use the radio until the interface has been enabled.
|
||||
*/
|
||||
WPA_INTERFACE_DISABLED,
|
||||
|
||||
/**
|
||||
* WPA_INACTIVE - Inactive state (wpa_supplicant disabled)
|
||||
*
|
||||
@ -239,8 +286,9 @@ enum wpa_states {
|
||||
enum mfp_options {
|
||||
NO_MGMT_FRAME_PROTECTION = 0,
|
||||
MGMT_FRAME_PROTECTION_OPTIONAL = 1,
|
||||
MGMT_FRAME_PROTECTION_REQUIRED = 2
|
||||
MGMT_FRAME_PROTECTION_REQUIRED = 2,
|
||||
};
|
||||
#define MGMT_FRAME_PROTECTION_DEFAULT 3
|
||||
|
||||
/**
|
||||
* enum hostapd_hw_mode - Hardware mode
|
||||
@ -249,7 +297,25 @@ enum hostapd_hw_mode {
|
||||
HOSTAPD_MODE_IEEE80211B,
|
||||
HOSTAPD_MODE_IEEE80211G,
|
||||
HOSTAPD_MODE_IEEE80211A,
|
||||
HOSTAPD_MODE_IEEE80211AD,
|
||||
NUM_HOSTAPD_MODES
|
||||
};
|
||||
|
||||
/**
|
||||
* enum wpa_ctrl_req_type - Control interface request types
|
||||
*/
|
||||
enum wpa_ctrl_req_type {
|
||||
WPA_CTRL_REQ_UNKNOWN,
|
||||
WPA_CTRL_REQ_EAP_IDENTITY,
|
||||
WPA_CTRL_REQ_EAP_PASSWORD,
|
||||
WPA_CTRL_REQ_EAP_NEW_PASSWORD,
|
||||
WPA_CTRL_REQ_EAP_PIN,
|
||||
WPA_CTRL_REQ_EAP_OTP,
|
||||
WPA_CTRL_REQ_EAP_PASSPHRASE,
|
||||
NUM_WPA_CTRL_REQS
|
||||
};
|
||||
|
||||
/* Maximum number of EAP methods to store for EAP server user information */
|
||||
#define EAP_MAX_METHODS 8
|
||||
|
||||
#endif /* DEFS_H */
|
||||
|
@ -2,14 +2,8 @@
|
||||
* EAPOL definitions shared between hostapd and wpa_supplicant
|
||||
* Copyright (c) 2002-2007, Jouni Malinen <j@w1.fi>
|
||||
*
|
||||
* This program is free software; you can redistribute it and/or modify
|
||||
* it under the terms of the GNU General Public License version 2 as
|
||||
* published by the Free Software Foundation.
|
||||
*
|
||||
* Alternatively, this software may be distributed under the terms of BSD
|
||||
* license.
|
||||
*
|
||||
* See README and COPYING for more details.
|
||||
* This software may be distributed under the terms of the BSD license.
|
||||
* See README for more details.
|
||||
*/
|
||||
|
||||
#ifndef EAPOL_COMMON_H
|
||||
@ -44,4 +38,44 @@ enum { IEEE802_1X_TYPE_EAP_PACKET = 0,
|
||||
enum { EAPOL_KEY_TYPE_RC4 = 1, EAPOL_KEY_TYPE_RSN = 2,
|
||||
EAPOL_KEY_TYPE_WPA = 254 };
|
||||
|
||||
|
||||
#define IEEE8021X_REPLAY_COUNTER_LEN 8
|
||||
#define IEEE8021X_KEY_SIGN_LEN 16
|
||||
#define IEEE8021X_KEY_IV_LEN 16
|
||||
|
||||
#define IEEE8021X_KEY_INDEX_FLAG 0x80
|
||||
#define IEEE8021X_KEY_INDEX_MASK 0x03
|
||||
|
||||
#ifdef _MSC_VER
|
||||
#pragma pack(push, 1)
|
||||
#endif /* _MSC_VER */
|
||||
|
||||
struct ieee802_1x_eapol_key {
|
||||
u8 type;
|
||||
/* Note: key_length is unaligned */
|
||||
u8 key_length[2];
|
||||
/* does not repeat within the life of the keying material used to
|
||||
* encrypt the Key field; 64-bit NTP timestamp MAY be used here */
|
||||
u8 replay_counter[IEEE8021X_REPLAY_COUNTER_LEN];
|
||||
u8 key_iv[IEEE8021X_KEY_IV_LEN]; /* cryptographically random number */
|
||||
u8 key_index; /* key flag in the most significant bit:
|
||||
* 0 = broadcast (default key),
|
||||
* 1 = unicast (key mapping key); key index is in the
|
||||
* 7 least significant bits */
|
||||
/* HMAC-MD5 message integrity check computed with MS-MPPE-Send-Key as
|
||||
* the key */
|
||||
u8 key_signature[IEEE8021X_KEY_SIGN_LEN];
|
||||
|
||||
/* followed by key: if packet body length = 44 + key length, then the
|
||||
* key field (of key_length bytes) contains the key in encrypted form;
|
||||
* if packet body length = 44, key field is absent and key_length
|
||||
* represents the number of least significant octets from
|
||||
* MS-MPPE-Send-Key attribute to be used as the keying material;
|
||||
* RC4 key used in encryption = Key-IV + MS-MPPE-Recv-Key */
|
||||
} STRUCT_PACKED;
|
||||
|
||||
#ifdef _MSC_VER
|
||||
#pragma pack(pop)
|
||||
#endif /* _MSC_VER */
|
||||
|
||||
#endif /* EAPOL_COMMON_H */
|
||||
|
273
contrib/wpa/src/common/gas.c
Normal file
273
contrib/wpa/src/common/gas.c
Normal file
@ -0,0 +1,273 @@
|
||||
/*
|
||||
* Generic advertisement service (GAS) (IEEE 802.11u)
|
||||
* Copyright (c) 2009, Atheros Communications
|
||||
* Copyright (c) 2011-2012, Qualcomm Atheros
|
||||
*
|
||||
* This software may be distributed under the terms of the BSD license.
|
||||
* See README for more details.
|
||||
*/
|
||||
|
||||
#include "includes.h"
|
||||
|
||||
#include "common.h"
|
||||
#include "ieee802_11_defs.h"
|
||||
#include "gas.h"
|
||||
|
||||
|
||||
static struct wpabuf *
|
||||
gas_build_req(u8 action, u8 dialog_token, size_t size)
|
||||
{
|
||||
struct wpabuf *buf;
|
||||
|
||||
buf = wpabuf_alloc(100 + size);
|
||||
if (buf == NULL)
|
||||
return NULL;
|
||||
|
||||
wpabuf_put_u8(buf, WLAN_ACTION_PUBLIC);
|
||||
wpabuf_put_u8(buf, action);
|
||||
wpabuf_put_u8(buf, dialog_token);
|
||||
|
||||
return buf;
|
||||
}
|
||||
|
||||
|
||||
struct wpabuf * gas_build_initial_req(u8 dialog_token, size_t size)
|
||||
{
|
||||
return gas_build_req(WLAN_PA_GAS_INITIAL_REQ, dialog_token,
|
||||
size);
|
||||
}
|
||||
|
||||
|
||||
struct wpabuf * gas_build_comeback_req(u8 dialog_token)
|
||||
{
|
||||
return gas_build_req(WLAN_PA_GAS_COMEBACK_REQ, dialog_token, 0);
|
||||
}
|
||||
|
||||
|
||||
static struct wpabuf *
|
||||
gas_build_resp(u8 action, u8 dialog_token, u16 status_code, u8 frag_id,
|
||||
u8 more, u16 comeback_delay, size_t size)
|
||||
{
|
||||
struct wpabuf *buf;
|
||||
|
||||
buf = wpabuf_alloc(100 + size);
|
||||
if (buf == NULL)
|
||||
return NULL;
|
||||
|
||||
wpabuf_put_u8(buf, WLAN_ACTION_PUBLIC);
|
||||
wpabuf_put_u8(buf, action);
|
||||
wpabuf_put_u8(buf, dialog_token);
|
||||
wpabuf_put_le16(buf, status_code);
|
||||
if (action == WLAN_PA_GAS_COMEBACK_RESP)
|
||||
wpabuf_put_u8(buf, frag_id | (more ? 0x80 : 0));
|
||||
wpabuf_put_le16(buf, comeback_delay);
|
||||
|
||||
return buf;
|
||||
}
|
||||
|
||||
|
||||
struct wpabuf *
|
||||
gas_build_initial_resp(u8 dialog_token, u16 status_code, u16 comeback_delay,
|
||||
size_t size)
|
||||
{
|
||||
return gas_build_resp(WLAN_PA_GAS_INITIAL_RESP, dialog_token,
|
||||
status_code, 0, 0, comeback_delay, size);
|
||||
}
|
||||
|
||||
|
||||
static struct wpabuf *
|
||||
gas_build_comeback_resp(u8 dialog_token, u16 status_code, u8 frag_id, u8 more,
|
||||
u16 comeback_delay, size_t size)
|
||||
{
|
||||
return gas_build_resp(WLAN_PA_GAS_COMEBACK_RESP, dialog_token,
|
||||
status_code, frag_id, more, comeback_delay,
|
||||
size);
|
||||
}
|
||||
|
||||
|
||||
/**
|
||||
* gas_add_adv_proto_anqp - Add an Advertisement Protocol element
|
||||
* @buf: Buffer to which the element is added
|
||||
* @query_resp_len_limit: Query Response Length Limit in units of 256 octets
|
||||
* @pame_bi: Pre-Association Message Exchange BSSID Independent (0/1)
|
||||
*
|
||||
*
|
||||
* @query_resp_len_limit is 0 for request and 1-0x7f for response. 0x7f means
|
||||
* that the maximum limit is determined by the maximum allowable number of
|
||||
* fragments in the GAS Query Response Fragment ID.
|
||||
*/
|
||||
static void gas_add_adv_proto_anqp(struct wpabuf *buf, u8 query_resp_len_limit,
|
||||
u8 pame_bi)
|
||||
{
|
||||
/* Advertisement Protocol IE */
|
||||
wpabuf_put_u8(buf, WLAN_EID_ADV_PROTO);
|
||||
wpabuf_put_u8(buf, 2); /* Length */
|
||||
wpabuf_put_u8(buf, (query_resp_len_limit & 0x7f) |
|
||||
(pame_bi ? 0x80 : 0));
|
||||
/* Advertisement Protocol */
|
||||
wpabuf_put_u8(buf, ACCESS_NETWORK_QUERY_PROTOCOL);
|
||||
}
|
||||
|
||||
|
||||
struct wpabuf * gas_anqp_build_initial_req(u8 dialog_token, size_t size)
|
||||
{
|
||||
struct wpabuf *buf;
|
||||
|
||||
buf = gas_build_initial_req(dialog_token, 4 + size);
|
||||
if (buf == NULL)
|
||||
return NULL;
|
||||
|
||||
gas_add_adv_proto_anqp(buf, 0, 0);
|
||||
|
||||
wpabuf_put(buf, 2); /* Query Request Length to be filled */
|
||||
|
||||
return buf;
|
||||
}
|
||||
|
||||
|
||||
struct wpabuf * gas_anqp_build_initial_resp(u8 dialog_token, u16 status_code,
|
||||
u16 comeback_delay, size_t size)
|
||||
{
|
||||
struct wpabuf *buf;
|
||||
|
||||
buf = gas_build_initial_resp(dialog_token, status_code, comeback_delay,
|
||||
4 + size);
|
||||
if (buf == NULL)
|
||||
return NULL;
|
||||
|
||||
gas_add_adv_proto_anqp(buf, 0x7f, 0);
|
||||
|
||||
wpabuf_put(buf, 2); /* Query Response Length to be filled */
|
||||
|
||||
return buf;
|
||||
}
|
||||
|
||||
|
||||
struct wpabuf * gas_anqp_build_initial_resp_buf(u8 dialog_token,
|
||||
u16 status_code,
|
||||
u16 comeback_delay,
|
||||
struct wpabuf *payload)
|
||||
{
|
||||
struct wpabuf *buf;
|
||||
|
||||
buf = gas_anqp_build_initial_resp(dialog_token, status_code,
|
||||
comeback_delay,
|
||||
payload ? wpabuf_len(payload) : 0);
|
||||
if (buf == NULL)
|
||||
return NULL;
|
||||
|
||||
if (payload)
|
||||
wpabuf_put_buf(buf, payload);
|
||||
|
||||
gas_anqp_set_len(buf);
|
||||
|
||||
return buf;
|
||||
}
|
||||
|
||||
|
||||
struct wpabuf * gas_anqp_build_comeback_resp(u8 dialog_token, u16 status_code,
|
||||
u8 frag_id, u8 more,
|
||||
u16 comeback_delay, size_t size)
|
||||
{
|
||||
struct wpabuf *buf;
|
||||
|
||||
buf = gas_build_comeback_resp(dialog_token, status_code,
|
||||
frag_id, more, comeback_delay, 4 + size);
|
||||
if (buf == NULL)
|
||||
return NULL;
|
||||
|
||||
gas_add_adv_proto_anqp(buf, 0x7f, 0);
|
||||
|
||||
wpabuf_put(buf, 2); /* Query Response Length to be filled */
|
||||
|
||||
return buf;
|
||||
}
|
||||
|
||||
|
||||
struct wpabuf * gas_anqp_build_comeback_resp_buf(u8 dialog_token,
|
||||
u16 status_code,
|
||||
u8 frag_id, u8 more,
|
||||
u16 comeback_delay,
|
||||
struct wpabuf *payload)
|
||||
{
|
||||
struct wpabuf *buf;
|
||||
|
||||
buf = gas_anqp_build_comeback_resp(dialog_token, status_code, frag_id,
|
||||
more, comeback_delay,
|
||||
payload ? wpabuf_len(payload) : 0);
|
||||
if (buf == NULL)
|
||||
return NULL;
|
||||
|
||||
if (payload)
|
||||
wpabuf_put_buf(buf, payload);
|
||||
|
||||
gas_anqp_set_len(buf);
|
||||
|
||||
return buf;
|
||||
}
|
||||
|
||||
|
||||
/**
|
||||
* gas_anqp_set_len - Set Query Request/Response Length
|
||||
* @buf: GAS message
|
||||
*
|
||||
* This function is used to update the Query Request/Response Length field once
|
||||
* the payload has been filled.
|
||||
*/
|
||||
void gas_anqp_set_len(struct wpabuf *buf)
|
||||
{
|
||||
u8 action;
|
||||
size_t offset;
|
||||
u8 *len;
|
||||
|
||||
if (buf == NULL || wpabuf_len(buf) < 2)
|
||||
return;
|
||||
|
||||
action = *(wpabuf_head_u8(buf) + 1);
|
||||
switch (action) {
|
||||
case WLAN_PA_GAS_INITIAL_REQ:
|
||||
offset = 3 + 4;
|
||||
break;
|
||||
case WLAN_PA_GAS_INITIAL_RESP:
|
||||
offset = 7 + 4;
|
||||
break;
|
||||
case WLAN_PA_GAS_COMEBACK_RESP:
|
||||
offset = 8 + 4;
|
||||
break;
|
||||
default:
|
||||
return;
|
||||
}
|
||||
|
||||
if (wpabuf_len(buf) < offset + 2)
|
||||
return;
|
||||
|
||||
len = wpabuf_mhead_u8(buf) + offset;
|
||||
WPA_PUT_LE16(len, (u8 *) wpabuf_put(buf, 0) - len - 2);
|
||||
}
|
||||
|
||||
|
||||
/**
|
||||
* gas_anqp_add_element - Add ANQP element header
|
||||
* @buf: GAS message
|
||||
* @info_id: ANQP Info ID
|
||||
* Returns: Pointer to the Length field for gas_anqp_set_element_len()
|
||||
*/
|
||||
u8 * gas_anqp_add_element(struct wpabuf *buf, u16 info_id)
|
||||
{
|
||||
wpabuf_put_le16(buf, info_id);
|
||||
return wpabuf_put(buf, 2); /* Length to be filled */
|
||||
}
|
||||
|
||||
|
||||
/**
|
||||
* gas_anqp_set_element_len - Update ANQP element Length field
|
||||
* @buf: GAS message
|
||||
* @len_pos: Length field position from gas_anqp_add_element()
|
||||
*
|
||||
* This function is called after the ANQP element payload has been added to the
|
||||
* buffer.
|
||||
*/
|
||||
void gas_anqp_set_element_len(struct wpabuf *buf, u8 *len_pos)
|
||||
{
|
||||
WPA_PUT_LE16(len_pos, (u8 *) wpabuf_put(buf, 0) - len_pos - 2);
|
||||
}
|
37
contrib/wpa/src/common/gas.h
Normal file
37
contrib/wpa/src/common/gas.h
Normal file
@ -0,0 +1,37 @@
|
||||
/*
|
||||
* Generic advertisement service (GAS) (IEEE 802.11u)
|
||||
* Copyright (c) 2009, Atheros Communications
|
||||
* Copyright (c) 2011-2012, Qualcomm Atheros
|
||||
*
|
||||
* This software may be distributed under the terms of the BSD license.
|
||||
* See README for more details.
|
||||
*/
|
||||
|
||||
#ifndef GAS_H
|
||||
#define GAS_H
|
||||
|
||||
struct wpabuf * gas_build_initial_req(u8 dialog_token, size_t size);
|
||||
struct wpabuf * gas_build_comeback_req(u8 dialog_token);
|
||||
struct wpabuf * gas_build_initial_resp(u8 dialog_token, u16 status_code,
|
||||
u16 comeback_delay, size_t size);
|
||||
struct wpabuf * gas_anqp_build_initial_req(u8 dialog_token, size_t size);
|
||||
struct wpabuf * gas_anqp_build_initial_resp(u8 dialog_token, u16 status_code,
|
||||
u16 comeback_delay, size_t size);
|
||||
struct wpabuf * gas_anqp_build_initial_resp_buf(u8 dialog_token,
|
||||
u16 status_code,
|
||||
u16 comeback_delay,
|
||||
struct wpabuf *payload);
|
||||
struct wpabuf * gas_anqp_build_comeback_resp(u8 dialog_token, u16 status_code,
|
||||
u8 frag_id, u8 more,
|
||||
u16 comeback_delay, size_t size);
|
||||
struct wpabuf * gas_anqp_build_comeback_resp_buf(u8 dialog_token,
|
||||
u16 status_code,
|
||||
u8 frag_id, u8 more,
|
||||
u16 comeback_delay,
|
||||
struct wpabuf *payload);
|
||||
void gas_anqp_set_len(struct wpabuf *buf);
|
||||
|
||||
u8 * gas_anqp_add_element(struct wpabuf *buf, u16 info_id);
|
||||
void gas_anqp_set_element_len(struct wpabuf *buf, u8 *len_pos);
|
||||
|
||||
#endif /* GAS_H */
|
@ -1,15 +1,9 @@
|
||||
/*
|
||||
* IEEE 802.11 Common routines
|
||||
* Copyright (c) 2002-2009, Jouni Malinen <j@w1.fi>
|
||||
* Copyright (c) 2002-2012, Jouni Malinen <j@w1.fi>
|
||||
*
|
||||
* This program is free software; you can redistribute it and/or modify
|
||||
* it under the terms of the GNU General Public License version 2 as
|
||||
* published by the Free Software Foundation.
|
||||
*
|
||||
* Alternatively, this software may be distributed under the terms of BSD
|
||||
* license.
|
||||
*
|
||||
* See README and COPYING for more details.
|
||||
* This software may be distributed under the terms of the BSD license.
|
||||
* See README for more details.
|
||||
*/
|
||||
|
||||
#include "includes.h"
|
||||
@ -75,7 +69,7 @@ static int ieee802_11_parse_vendor_specific(const u8 *pos, size_t elen,
|
||||
elems->wmm_tspec_len = elen;
|
||||
break;
|
||||
default:
|
||||
wpa_printf(MSG_MSGDUMP, "unknown WMM "
|
||||
wpa_printf(MSG_EXCESSIVE, "unknown WMM "
|
||||
"information element ignored "
|
||||
"(subtype=%d len=%lu)",
|
||||
pos[4], (unsigned long) elen);
|
||||
@ -88,7 +82,33 @@ static int ieee802_11_parse_vendor_specific(const u8 *pos, size_t elen,
|
||||
elems->wps_ie_len = elen;
|
||||
break;
|
||||
default:
|
||||
wpa_printf(MSG_MSGDUMP, "Unknown Microsoft "
|
||||
wpa_printf(MSG_EXCESSIVE, "Unknown Microsoft "
|
||||
"information element ignored "
|
||||
"(type=%d len=%lu)",
|
||||
pos[3], (unsigned long) elen);
|
||||
return -1;
|
||||
}
|
||||
break;
|
||||
|
||||
case OUI_WFA:
|
||||
switch (pos[3]) {
|
||||
case P2P_OUI_TYPE:
|
||||
/* Wi-Fi Alliance - P2P IE */
|
||||
elems->p2p = pos;
|
||||
elems->p2p_len = elen;
|
||||
break;
|
||||
case WFD_OUI_TYPE:
|
||||
/* Wi-Fi Alliance - WFD IE */
|
||||
elems->wfd = pos;
|
||||
elems->wfd_len = elen;
|
||||
break;
|
||||
case HS20_INDICATION_OUI_TYPE:
|
||||
/* Hotspot 2.0 */
|
||||
elems->hs20 = pos;
|
||||
elems->hs20_len = elen;
|
||||
break;
|
||||
default:
|
||||
wpa_printf(MSG_MSGDUMP, "Unknown WFA "
|
||||
"information element ignored "
|
||||
"(type=%d len=%lu)\n",
|
||||
pos[3], (unsigned long) elen);
|
||||
@ -103,18 +123,18 @@ static int ieee802_11_parse_vendor_specific(const u8 *pos, size_t elen,
|
||||
elems->vendor_ht_cap_len = elen;
|
||||
break;
|
||||
default:
|
||||
wpa_printf(MSG_MSGDUMP, "Unknown Broadcom "
|
||||
wpa_printf(MSG_EXCESSIVE, "Unknown Broadcom "
|
||||
"information element ignored "
|
||||
"(type=%d len=%lu)\n",
|
||||
"(type=%d len=%lu)",
|
||||
pos[3], (unsigned long) elen);
|
||||
return -1;
|
||||
}
|
||||
break;
|
||||
|
||||
default:
|
||||
wpa_printf(MSG_MSGDUMP, "unknown vendor specific information "
|
||||
"element ignored (vendor OUI %02x:%02x:%02x "
|
||||
"len=%lu)",
|
||||
wpa_printf(MSG_EXCESSIVE, "unknown vendor specific "
|
||||
"information element ignored (vendor OUI "
|
||||
"%02x:%02x:%02x len=%lu)",
|
||||
pos[0], pos[1], pos[2], (unsigned long) elen);
|
||||
return -1;
|
||||
}
|
||||
@ -238,6 +258,36 @@ ParseRes ieee802_11_parse_elems(const u8 *start, size_t len,
|
||||
elems->ht_operation = pos;
|
||||
elems->ht_operation_len = elen;
|
||||
break;
|
||||
case WLAN_EID_VHT_CAP:
|
||||
elems->vht_capabilities = pos;
|
||||
elems->vht_capabilities_len = elen;
|
||||
break;
|
||||
case WLAN_EID_VHT_OPERATION:
|
||||
elems->vht_operation = pos;
|
||||
elems->vht_operation_len = elen;
|
||||
break;
|
||||
case WLAN_EID_LINK_ID:
|
||||
if (elen < 18)
|
||||
break;
|
||||
elems->link_id = pos;
|
||||
break;
|
||||
case WLAN_EID_INTERWORKING:
|
||||
elems->interworking = pos;
|
||||
elems->interworking_len = elen;
|
||||
break;
|
||||
case WLAN_EID_EXT_CAPAB:
|
||||
elems->ext_capab = pos;
|
||||
elems->ext_capab_len = elen;
|
||||
break;
|
||||
case WLAN_EID_BSS_MAX_IDLE_PERIOD:
|
||||
if (elen < 3)
|
||||
break;
|
||||
elems->bss_max_idle_period = pos;
|
||||
break;
|
||||
case WLAN_EID_SSID_LIST:
|
||||
elems->ssid_list = pos;
|
||||
elems->ssid_list_len = elen;
|
||||
break;
|
||||
default:
|
||||
unknown++;
|
||||
if (!show_errors)
|
||||
@ -324,3 +374,115 @@ struct wpabuf * ieee802_11_vendor_ie_concat(const u8 *ies, size_t ies_len,
|
||||
|
||||
return buf;
|
||||
}
|
||||
|
||||
|
||||
const u8 * get_hdr_bssid(const struct ieee80211_hdr *hdr, size_t len)
|
||||
{
|
||||
u16 fc, type, stype;
|
||||
|
||||
/*
|
||||
* PS-Poll frames are 16 bytes. All other frames are
|
||||
* 24 bytes or longer.
|
||||
*/
|
||||
if (len < 16)
|
||||
return NULL;
|
||||
|
||||
fc = le_to_host16(hdr->frame_control);
|
||||
type = WLAN_FC_GET_TYPE(fc);
|
||||
stype = WLAN_FC_GET_STYPE(fc);
|
||||
|
||||
switch (type) {
|
||||
case WLAN_FC_TYPE_DATA:
|
||||
if (len < 24)
|
||||
return NULL;
|
||||
switch (fc & (WLAN_FC_FROMDS | WLAN_FC_TODS)) {
|
||||
case WLAN_FC_FROMDS | WLAN_FC_TODS:
|
||||
case WLAN_FC_TODS:
|
||||
return hdr->addr1;
|
||||
case WLAN_FC_FROMDS:
|
||||
return hdr->addr2;
|
||||
default:
|
||||
return NULL;
|
||||
}
|
||||
case WLAN_FC_TYPE_CTRL:
|
||||
if (stype != WLAN_FC_STYPE_PSPOLL)
|
||||
return NULL;
|
||||
return hdr->addr1;
|
||||
case WLAN_FC_TYPE_MGMT:
|
||||
return hdr->addr3;
|
||||
default:
|
||||
return NULL;
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
int hostapd_config_wmm_ac(struct hostapd_wmm_ac_params wmm_ac_params[],
|
||||
const char *name, const char *val)
|
||||
{
|
||||
int num, v;
|
||||
const char *pos;
|
||||
struct hostapd_wmm_ac_params *ac;
|
||||
|
||||
/* skip 'wme_ac_' or 'wmm_ac_' prefix */
|
||||
pos = name + 7;
|
||||
if (os_strncmp(pos, "be_", 3) == 0) {
|
||||
num = 0;
|
||||
pos += 3;
|
||||
} else if (os_strncmp(pos, "bk_", 3) == 0) {
|
||||
num = 1;
|
||||
pos += 3;
|
||||
} else if (os_strncmp(pos, "vi_", 3) == 0) {
|
||||
num = 2;
|
||||
pos += 3;
|
||||
} else if (os_strncmp(pos, "vo_", 3) == 0) {
|
||||
num = 3;
|
||||
pos += 3;
|
||||
} else {
|
||||
wpa_printf(MSG_ERROR, "Unknown WMM name '%s'", pos);
|
||||
return -1;
|
||||
}
|
||||
|
||||
ac = &wmm_ac_params[num];
|
||||
|
||||
if (os_strcmp(pos, "aifs") == 0) {
|
||||
v = atoi(val);
|
||||
if (v < 1 || v > 255) {
|
||||
wpa_printf(MSG_ERROR, "Invalid AIFS value %d", v);
|
||||
return -1;
|
||||
}
|
||||
ac->aifs = v;
|
||||
} else if (os_strcmp(pos, "cwmin") == 0) {
|
||||
v = atoi(val);
|
||||
if (v < 0 || v > 12) {
|
||||
wpa_printf(MSG_ERROR, "Invalid cwMin value %d", v);
|
||||
return -1;
|
||||
}
|
||||
ac->cwmin = v;
|
||||
} else if (os_strcmp(pos, "cwmax") == 0) {
|
||||
v = atoi(val);
|
||||
if (v < 0 || v > 12) {
|
||||
wpa_printf(MSG_ERROR, "Invalid cwMax value %d", v);
|
||||
return -1;
|
||||
}
|
||||
ac->cwmax = v;
|
||||
} else if (os_strcmp(pos, "txop_limit") == 0) {
|
||||
v = atoi(val);
|
||||
if (v < 0 || v > 0xffff) {
|
||||
wpa_printf(MSG_ERROR, "Invalid txop value %d", v);
|
||||
return -1;
|
||||
}
|
||||
ac->txop_limit = v;
|
||||
} else if (os_strcmp(pos, "acm") == 0) {
|
||||
v = atoi(val);
|
||||
if (v < 0 || v > 1) {
|
||||
wpa_printf(MSG_ERROR, "Invalid acm value %d", v);
|
||||
return -1;
|
||||
}
|
||||
ac->admission_control_mandatory = v;
|
||||
} else {
|
||||
wpa_printf(MSG_ERROR, "Unknown wmm_ac_ field '%s'", pos);
|
||||
return -1;
|
||||
}
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
@ -1,15 +1,9 @@
|
||||
/*
|
||||
* IEEE 802.11 Common routines
|
||||
* Copyright (c) 2002-2009, Jouni Malinen <j@w1.fi>
|
||||
* Copyright (c) 2002-2012, Jouni Malinen <j@w1.fi>
|
||||
*
|
||||
* This program is free software; you can redistribute it and/or modify
|
||||
* it under the terms of the GNU General Public License version 2 as
|
||||
* published by the Free Software Foundation.
|
||||
*
|
||||
* Alternatively, this software may be distributed under the terms of BSD
|
||||
* license.
|
||||
*
|
||||
* See README and COPYING for more details.
|
||||
* This software may be distributed under the terms of the BSD license.
|
||||
* See README for more details.
|
||||
*/
|
||||
|
||||
#ifndef IEEE802_11_COMMON_H
|
||||
@ -39,7 +33,17 @@ struct ieee802_11_elems {
|
||||
const u8 *timeout_int;
|
||||
const u8 *ht_capabilities;
|
||||
const u8 *ht_operation;
|
||||
const u8 *vht_capabilities;
|
||||
const u8 *vht_operation;
|
||||
const u8 *vendor_ht_cap;
|
||||
const u8 *p2p;
|
||||
const u8 *wfd;
|
||||
const u8 *link_id;
|
||||
const u8 *interworking;
|
||||
const u8 *hs20;
|
||||
const u8 *ext_capab;
|
||||
const u8 *bss_max_idle_period;
|
||||
const u8 *ssid_list;
|
||||
|
||||
u8 ssid_len;
|
||||
u8 supp_rates_len;
|
||||
@ -63,7 +67,15 @@ struct ieee802_11_elems {
|
||||
u8 timeout_int_len;
|
||||
u8 ht_capabilities_len;
|
||||
u8 ht_operation_len;
|
||||
u8 vht_capabilities_len;
|
||||
u8 vht_operation_len;
|
||||
u8 vendor_ht_cap_len;
|
||||
u8 p2p_len;
|
||||
u8 wfd_len;
|
||||
u8 interworking_len;
|
||||
u8 hs20_len;
|
||||
u8 ext_capab_len;
|
||||
u8 ssid_list_len;
|
||||
};
|
||||
|
||||
typedef enum { ParseOK = 0, ParseUnknown = 1, ParseFailed = -1 } ParseRes;
|
||||
@ -74,5 +86,18 @@ ParseRes ieee802_11_parse_elems(const u8 *start, size_t len,
|
||||
int ieee802_11_ie_count(const u8 *ies, size_t ies_len);
|
||||
struct wpabuf * ieee802_11_vendor_ie_concat(const u8 *ies, size_t ies_len,
|
||||
u32 oui_type);
|
||||
struct ieee80211_hdr;
|
||||
const u8 * get_hdr_bssid(const struct ieee80211_hdr *hdr, size_t len);
|
||||
|
||||
struct hostapd_wmm_ac_params {
|
||||
int cwmin;
|
||||
int cwmax;
|
||||
int aifs;
|
||||
int txop_limit; /* in units of 32us */
|
||||
int admission_control_mandatory;
|
||||
};
|
||||
|
||||
int hostapd_config_wmm_ac(struct hostapd_wmm_ac_params wmm_ac_params[],
|
||||
const char *name, const char *val);
|
||||
|
||||
#endif /* IEEE802_11_COMMON_H */
|
||||
|
@ -3,14 +3,8 @@
|
||||
* Copyright (c) 2002-2009, Jouni Malinen <j@w1.fi>
|
||||
* Copyright (c) 2007-2008 Intel Corporation
|
||||
*
|
||||
* This program is free software; you can redistribute it and/or modify
|
||||
* it under the terms of the GNU General Public License version 2 as
|
||||
* published by the Free Software Foundation.
|
||||
*
|
||||
* Alternatively, this software may be distributed under the terms of BSD
|
||||
* license.
|
||||
*
|
||||
* See README and COPYING for more details.
|
||||
* This software may be distributed under the terms of the BSD license.
|
||||
* See README for more details.
|
||||
*/
|
||||
|
||||
#ifndef IEEE802_11_DEFS_H
|
||||
@ -71,11 +65,18 @@
|
||||
#define WLAN_FC_STYPE_CFPOLL 6
|
||||
#define WLAN_FC_STYPE_CFACKPOLL 7
|
||||
#define WLAN_FC_STYPE_QOS_DATA 8
|
||||
#define WLAN_FC_STYPE_QOS_DATA_CFACK 9
|
||||
#define WLAN_FC_STYPE_QOS_DATA_CFPOLL 10
|
||||
#define WLAN_FC_STYPE_QOS_DATA_CFACKPOLL 11
|
||||
#define WLAN_FC_STYPE_QOS_NULL 12
|
||||
#define WLAN_FC_STYPE_QOS_CFPOLL 14
|
||||
#define WLAN_FC_STYPE_QOS_CFACKPOLL 15
|
||||
|
||||
/* Authentication algorithms */
|
||||
#define WLAN_AUTH_OPEN 0
|
||||
#define WLAN_AUTH_SHARED_KEY 1
|
||||
#define WLAN_AUTH_FT 2
|
||||
#define WLAN_AUTH_SAE 3
|
||||
#define WLAN_AUTH_LEAP 128
|
||||
|
||||
#define WLAN_AUTH_CHALLENGE_LEN 128
|
||||
@ -95,6 +96,11 @@
|
||||
/* Status codes (IEEE 802.11-2007, 7.3.1.9, Table 7-23) */
|
||||
#define WLAN_STATUS_SUCCESS 0
|
||||
#define WLAN_STATUS_UNSPECIFIED_FAILURE 1
|
||||
#define WLAN_STATUS_TDLS_WAKEUP_ALTERNATE 2
|
||||
#define WLAN_STATUS_TDLS_WAKEUP_REJECT 3
|
||||
#define WLAN_STATUS_SECURITY_DISABLED 5
|
||||
#define WLAN_STATUS_UNACCEPTABLE_LIFETIME 6
|
||||
#define WLAN_STATUS_NOT_IN_SAME_BSS 7
|
||||
#define WLAN_STATUS_CAPS_UNSUPPORTED 10
|
||||
#define WLAN_STATUS_REASSOC_NO_ASSOC 11
|
||||
#define WLAN_STATUS_ASSOC_DENIED_UNSPEC 12
|
||||
@ -114,9 +120,10 @@
|
||||
#define WLAN_STATUS_SUPPORTED_CHANNEL_NOT_VALID 24
|
||||
/* IEEE 802.11g */
|
||||
#define WLAN_STATUS_ASSOC_DENIED_NO_SHORT_SLOT_TIME 25
|
||||
#define WLAN_STATUS_ASSOC_DENIED_NO_ER_PBCC 26
|
||||
#define WLAN_STATUS_ASSOC_DENIED_NO_DSSS_OFDM 27
|
||||
#define WLAN_STATUS_ASSOC_DENIED_NO_DSSS_OFDM 26
|
||||
#define WLAN_STATUS_ASSOC_DENIED_NO_HT 27
|
||||
#define WLAN_STATUS_R0KH_UNREACHABLE 28
|
||||
#define WLAN_STATUS_ASSOC_DENIED_NO_PCO 29
|
||||
/* IEEE 802.11w */
|
||||
#define WLAN_STATUS_ASSOC_REJECTED_TEMPORARILY 30
|
||||
#define WLAN_STATUS_ROBUST_MGMT_FRAME_POLICY_VIOLATION 31
|
||||
@ -141,6 +148,19 @@
|
||||
#define WLAN_STATUS_INVALID_PMKID 53
|
||||
#define WLAN_STATUS_INVALID_MDIE 54
|
||||
#define WLAN_STATUS_INVALID_FTIE 55
|
||||
#define WLAN_STATUS_GAS_ADV_PROTO_NOT_SUPPORTED 59
|
||||
#define WLAN_STATUS_NO_OUTSTANDING_GAS_REQ 60
|
||||
#define WLAN_STATUS_GAS_RESP_NOT_RECEIVED 61
|
||||
#define WLAN_STATUS_STA_TIMED_OUT_WAITING_FOR_GAS_RESP 62
|
||||
#define WLAN_STATUS_GAS_RESP_LARGER_THAN_LIMIT 63
|
||||
#define WLAN_STATUS_REQ_REFUSED_HOME 64
|
||||
#define WLAN_STATUS_ADV_SRV_UNREACHABLE 65
|
||||
#define WLAN_STATUS_REQ_REFUSED_SSPN 67
|
||||
#define WLAN_STATUS_REQ_REFUSED_UNAUTH_ACCESS 68
|
||||
#define WLAN_STATUS_INVALID_RSNIE 72
|
||||
#define WLAN_STATUS_ANTI_CLOGGING_TOKEN_REQ 76
|
||||
#define WLAN_STATUS_FINITE_CYCLIC_GROUP_NOT_SUPPORTED 77
|
||||
#define WLAN_STATUS_TRANSMISSION_FAILURE 79
|
||||
|
||||
/* Reason codes (IEEE 802.11-2007, 7.3.1.7, Table 7-22) */
|
||||
#define WLAN_REASON_UNSPECIFIED 1
|
||||
@ -168,6 +188,10 @@
|
||||
#define WLAN_REASON_INVALID_RSN_IE_CAPAB 22
|
||||
#define WLAN_REASON_IEEE_802_1X_AUTH_FAILED 23
|
||||
#define WLAN_REASON_CIPHER_SUITE_REJECTED 24
|
||||
#define WLAN_REASON_TDLS_TEARDOWN_UNREACHABLE 25
|
||||
#define WLAN_REASON_TDLS_TEARDOWN_UNSPECIFIED 26
|
||||
/* IEEE 802.11e */
|
||||
#define WLAN_REASON_DISASSOC_LOW_ACK 34
|
||||
|
||||
|
||||
/* Information Element IDs */
|
||||
@ -202,10 +226,33 @@
|
||||
#define WLAN_EID_RIC_DATA 57
|
||||
#define WLAN_EID_HT_OPERATION 61
|
||||
#define WLAN_EID_SECONDARY_CHANNEL_OFFSET 62
|
||||
#define WLAN_EID_WAPI 68
|
||||
#define WLAN_EID_TIME_ADVERTISEMENT 69
|
||||
#define WLAN_EID_20_40_BSS_COEXISTENCE 72
|
||||
#define WLAN_EID_20_40_BSS_INTOLERANT 73
|
||||
#define WLAN_EID_OVERLAPPING_BSS_SCAN_PARAMS 74
|
||||
#define WLAN_EID_MMIE 76
|
||||
#define WLAN_EID_SSID_LIST 84
|
||||
#define WLAN_EID_BSS_MAX_IDLE_PERIOD 90
|
||||
#define WLAN_EID_TFS_REQ 91
|
||||
#define WLAN_EID_TFS_RESP 92
|
||||
#define WLAN_EID_WNMSLEEP 93
|
||||
#define WLAN_EID_TIME_ZONE 98
|
||||
#define WLAN_EID_LINK_ID 101
|
||||
#define WLAN_EID_INTERWORKING 107
|
||||
#define WLAN_EID_ADV_PROTO 108
|
||||
#define WLAN_EID_ROAMING_CONSORTIUM 111
|
||||
#define WLAN_EID_EXT_CAPAB 127
|
||||
#define WLAN_EID_CCKM 156
|
||||
#define WLAN_EID_VHT_CAP 191
|
||||
#define WLAN_EID_VHT_OPERATION 192
|
||||
#define WLAN_EID_VHT_EXTENDED_BSS_LOAD 193
|
||||
#define WLAN_EID_VHT_WIDE_BW_CHSWITCH 194
|
||||
#define WLAN_EID_VHT_TRANSMIT_POWER_ENVELOPE 195
|
||||
#define WLAN_EID_VHT_CHANNEL_SWITCH_WRAPPER 196
|
||||
#define WLAN_EID_VHT_AID 197
|
||||
#define WLAN_EID_VHT_QUIET_CHANNEL 198
|
||||
#define WLAN_EID_VHT_OPERATING_MODE_NOTIFICATION 199
|
||||
#define WLAN_EID_VENDOR_SPECIFIC 221
|
||||
|
||||
|
||||
@ -219,7 +266,20 @@
|
||||
#define WLAN_ACTION_FT 6
|
||||
#define WLAN_ACTION_HT 7
|
||||
#define WLAN_ACTION_SA_QUERY 8
|
||||
#define WLAN_ACTION_WNM 10
|
||||
#define WLAN_ACTION_UNPROTECTED_WNM 11
|
||||
#define WLAN_ACTION_TDLS 12
|
||||
#define WLAN_ACTION_WMM 17 /* WMM Specification 1.1 */
|
||||
#define WLAN_ACTION_VENDOR_SPECIFIC 127
|
||||
|
||||
/* Public action codes */
|
||||
#define WLAN_PA_20_40_BSS_COEX 0
|
||||
#define WLAN_PA_VENDOR_SPECIFIC 9
|
||||
#define WLAN_PA_GAS_INITIAL_REQ 10
|
||||
#define WLAN_PA_GAS_INITIAL_RESP 11
|
||||
#define WLAN_PA_GAS_COMEBACK_REQ 12
|
||||
#define WLAN_PA_GAS_COMEBACK_RESP 13
|
||||
#define WLAN_TDLS_DISCOVERY_RESPONSE 14
|
||||
|
||||
/* SA Query Action frame (IEEE 802.11w/D8.0, 7.4.9) */
|
||||
#define WLAN_SA_QUERY_REQUEST 0
|
||||
@ -227,11 +287,99 @@
|
||||
|
||||
#define WLAN_SA_QUERY_TR_ID_LEN 2
|
||||
|
||||
/* TDLS action codes */
|
||||
#define WLAN_TDLS_SETUP_REQUEST 0
|
||||
#define WLAN_TDLS_SETUP_RESPONSE 1
|
||||
#define WLAN_TDLS_SETUP_CONFIRM 2
|
||||
#define WLAN_TDLS_TEARDOWN 3
|
||||
#define WLAN_TDLS_PEER_TRAFFIC_INDICATION 4
|
||||
#define WLAN_TDLS_CHANNEL_SWITCH_REQUEST 5
|
||||
#define WLAN_TDLS_CHANNEL_SWITCH_RESPONSE 6
|
||||
#define WLAN_TDLS_PEER_PSM_REQUEST 7
|
||||
#define WLAN_TDLS_PEER_PSM_RESPONSE 8
|
||||
#define WLAN_TDLS_PEER_TRAFFIC_RESPONSE 9
|
||||
#define WLAN_TDLS_DISCOVERY_REQUEST 10
|
||||
|
||||
/* Timeout Interval Type */
|
||||
#define WLAN_TIMEOUT_REASSOC_DEADLINE 1
|
||||
#define WLAN_TIMEOUT_KEY_LIFETIME 2
|
||||
#define WLAN_TIMEOUT_ASSOC_COMEBACK 3
|
||||
|
||||
/* Interworking element (IEEE 802.11u) - Access Network Options */
|
||||
#define INTERWORKING_ANO_ACCESS_NETWORK_MASK 0x0f
|
||||
#define INTERWORKING_ANO_INTERNET 0x10
|
||||
#define INTERWORKING_ANO_ASRA 0x20
|
||||
#define INTERWORKING_ANO_ESR 0x40
|
||||
#define INTERWORKING_ANO_UESA 0x80
|
||||
|
||||
#define INTERWORKING_ANT_PRIVATE 0
|
||||
#define INTERWORKING_ANT_PRIVATE_WITH_GUEST 1
|
||||
#define INTERWORKING_ANT_CHARGEABLE_PUBLIC 2
|
||||
#define INTERWORKING_ANT_FREE_PUBLIC 3
|
||||
#define INTERWORKING_ANT_PERSONAL_DEVICE 4
|
||||
#define INTERWORKING_ANT_EMERGENCY_SERVICES 5
|
||||
#define INTERWORKING_ANT_TEST 6
|
||||
#define INTERWORKING_ANT_WILDCARD 15
|
||||
|
||||
/* Advertisement Protocol ID definitions (IEEE Std 802.11u-2011) */
|
||||
enum adv_proto_id {
|
||||
ACCESS_NETWORK_QUERY_PROTOCOL = 0,
|
||||
MIH_INFO_SERVICE = 1,
|
||||
MIH_CMD_AND_EVENT_DISCOVERY = 2,
|
||||
EMERGENCY_ALERT_SYSTEM = 3,
|
||||
ADV_PROTO_VENDOR_SPECIFIC = 221
|
||||
};
|
||||
|
||||
/* Access Network Query Protocol info ID definitions (IEEE Std 802.11u-2011) */
|
||||
enum anqp_info_id {
|
||||
ANQP_QUERY_LIST = 256,
|
||||
ANQP_CAPABILITY_LIST = 257,
|
||||
ANQP_VENUE_NAME = 258,
|
||||
ANQP_EMERGENCY_CALL_NUMBER = 259,
|
||||
ANQP_NETWORK_AUTH_TYPE = 260,
|
||||
ANQP_ROAMING_CONSORTIUM = 261,
|
||||
ANQP_IP_ADDR_TYPE_AVAILABILITY = 262,
|
||||
ANQP_NAI_REALM = 263,
|
||||
ANQP_3GPP_CELLULAR_NETWORK = 264,
|
||||
ANQP_AP_GEOSPATIAL_LOCATION = 265,
|
||||
ANQP_AP_CIVIC_LOCATION = 266,
|
||||
ANQP_AP_LOCATION_PUBLIC_URI = 267,
|
||||
ANQP_DOMAIN_NAME = 268,
|
||||
ANQP_EMERGENCY_ALERT_URI = 269,
|
||||
ANQP_EMERGENCY_NAI = 271,
|
||||
ANQP_VENDOR_SPECIFIC = 56797
|
||||
};
|
||||
|
||||
/* NAI Realm list - EAP Method subfield - Authentication Parameter ID */
|
||||
enum nai_realm_eap_auth_param {
|
||||
NAI_REALM_EAP_AUTH_EXPANDED_EAP_METHOD = 1,
|
||||
NAI_REALM_EAP_AUTH_NON_EAP_INNER_AUTH = 2,
|
||||
NAI_REALM_EAP_AUTH_INNER_AUTH_EAP_METHOD = 3,
|
||||
NAI_REALM_EAP_AUTH_EXPANDED_INNER_EAP_METHOD = 4,
|
||||
NAI_REALM_EAP_AUTH_CRED_TYPE = 5,
|
||||
NAI_REALM_EAP_AUTH_TUNNELED_CRED_TYPE = 6,
|
||||
NAI_REALM_EAP_AUTH_VENDOR_SPECIFIC = 221
|
||||
};
|
||||
|
||||
enum nai_realm_eap_auth_inner_non_eap {
|
||||
NAI_REALM_INNER_NON_EAP_PAP = 1,
|
||||
NAI_REALM_INNER_NON_EAP_CHAP = 2,
|
||||
NAI_REALM_INNER_NON_EAP_MSCHAP = 3,
|
||||
NAI_REALM_INNER_NON_EAP_MSCHAPV2 = 4
|
||||
};
|
||||
|
||||
enum nai_realm_eap_cred_type {
|
||||
NAI_REALM_CRED_TYPE_SIM = 1,
|
||||
NAI_REALM_CRED_TYPE_USIM = 2,
|
||||
NAI_REALM_CRED_TYPE_NFC_SECURE_ELEMENT = 3,
|
||||
NAI_REALM_CRED_TYPE_HARDWARE_TOKEN = 4,
|
||||
NAI_REALM_CRED_TYPE_SOFTOKEN = 5,
|
||||
NAI_REALM_CRED_TYPE_CERTIFICATE = 6,
|
||||
NAI_REALM_CRED_TYPE_USERNAME_PASSWORD = 7,
|
||||
NAI_REALM_CRED_TYPE_NONE = 8,
|
||||
NAI_REALM_CRED_TYPE_ANONYMOUS = 9,
|
||||
NAI_REALM_CRED_TYPE_VENDOR_SPECIFIC = 10
|
||||
};
|
||||
|
||||
#ifdef _MSC_VER
|
||||
#pragma pack(push, 1)
|
||||
@ -273,6 +421,7 @@ struct ieee80211_mgmt {
|
||||
} STRUCT_PACKED auth;
|
||||
struct {
|
||||
le16 reason_code;
|
||||
u8 variable[0];
|
||||
} STRUCT_PACKED deauth;
|
||||
struct {
|
||||
le16 capab_info;
|
||||
@ -296,6 +445,7 @@ struct ieee80211_mgmt {
|
||||
} STRUCT_PACKED reassoc_req;
|
||||
struct {
|
||||
le16 reason_code;
|
||||
u8 variable[0];
|
||||
} STRUCT_PACKED disassoc;
|
||||
struct {
|
||||
u8 timestamp[8];
|
||||
@ -355,12 +505,58 @@ struct ieee80211_mgmt {
|
||||
u8 action; /* */
|
||||
u8 trans_id[WLAN_SA_QUERY_TR_ID_LEN];
|
||||
} STRUCT_PACKED sa_query_resp;
|
||||
struct {
|
||||
u8 action;
|
||||
u8 dialogtoken;
|
||||
u8 variable[0];
|
||||
} STRUCT_PACKED wnm_sleep_req;
|
||||
struct {
|
||||
u8 action;
|
||||
u8 dialogtoken;
|
||||
le16 keydata_len;
|
||||
u8 variable[0];
|
||||
} STRUCT_PACKED wnm_sleep_resp;
|
||||
struct {
|
||||
u8 action;
|
||||
u8 variable[0];
|
||||
} STRUCT_PACKED public_action;
|
||||
struct {
|
||||
u8 action; /* 9 */
|
||||
u8 oui[3];
|
||||
/* Vendor-specific content */
|
||||
u8 variable[0];
|
||||
} STRUCT_PACKED vs_public_action;
|
||||
struct {
|
||||
u8 action; /* 7 */
|
||||
u8 dialog_token;
|
||||
u8 req_mode;
|
||||
le16 disassoc_timer;
|
||||
u8 validity_interval;
|
||||
/* BSS Termination Duration (optional),
|
||||
* Session Information URL (optional),
|
||||
* BSS Transition Candidate List
|
||||
* Entries */
|
||||
u8 variable[0];
|
||||
} STRUCT_PACKED bss_tm_req;
|
||||
struct {
|
||||
u8 action; /* 8 */
|
||||
u8 dialog_token;
|
||||
u8 status_code;
|
||||
u8 bss_termination_delay;
|
||||
/* Target BSSID (optional),
|
||||
* BSS Transition Candidate List
|
||||
* Entries (optional) */
|
||||
u8 variable[0];
|
||||
} STRUCT_PACKED bss_tm_resp;
|
||||
} u;
|
||||
} STRUCT_PACKED action;
|
||||
} u;
|
||||
} STRUCT_PACKED;
|
||||
|
||||
|
||||
/* Rx MCS bitmask is in the first 77 bits of supported_mcs_set */
|
||||
#define IEEE80211_HT_MCS_MASK_LEN 10
|
||||
|
||||
struct ieee80211_ht_capabilities {
|
||||
le16 ht_capabilities_info;
|
||||
u8 a_mpdu_params;
|
||||
@ -379,6 +575,19 @@ struct ieee80211_ht_operation {
|
||||
u8 basic_set[16];
|
||||
} STRUCT_PACKED;
|
||||
|
||||
|
||||
struct ieee80211_vht_capabilities {
|
||||
le32 vht_capabilities_info;
|
||||
u8 vht_supported_mcs_set[8];
|
||||
} STRUCT_PACKED;
|
||||
|
||||
struct ieee80211_vht_operation {
|
||||
u8 vht_op_info_chwidth;
|
||||
u8 vht_op_info_chan_center_freq_seg0_idx;
|
||||
u8 vht_op_info_chan_center_freq_seg1_idx;
|
||||
le16 vht_basic_mcs_set;
|
||||
} STRUCT_PACKED;
|
||||
|
||||
#ifdef _MSC_VER
|
||||
#pragma pack(pop)
|
||||
#endif /* _MSC_VER */
|
||||
@ -460,7 +669,7 @@ struct ieee80211_ht_operation {
|
||||
#define OP_MODE_MIXED 3
|
||||
|
||||
#define HT_INFO_OPERATION_MODE_OP_MODE_MASK \
|
||||
((le16) (0x0001 | 0x0002))
|
||||
(0x0001 | 0x0002)
|
||||
#define HT_INFO_OPERATION_MODE_OP_MODE_OFFSET 0
|
||||
#define HT_INFO_OPERATION_MODE_NON_GF_DEVS_PRESENT ((u8) BIT(2))
|
||||
#define HT_INFO_OPERATION_MODE_TRANSMIT_BURST_LIMIT ((u8) BIT(3))
|
||||
@ -473,11 +682,45 @@ struct ieee80211_ht_operation {
|
||||
#define HT_INFO_STBC_PARAM_PCO_ACTIVE ((u16) BIT(10))
|
||||
#define HT_INFO_STBC_PARAM_PCO_PHASE ((u16) BIT(11))
|
||||
|
||||
#define BSS_MEMBERSHIP_SELECTOR_VHT_PHY 126
|
||||
#define BSS_MEMBERSHIP_SELECTOR_HT_PHY 127
|
||||
|
||||
/* VHT Defines */
|
||||
#define VHT_CAP_MAX_MPDU_LENGTH_7991 ((u32) BIT(0))
|
||||
#define VHT_CAP_MAX_MPDU_LENGTH_11454 ((u32) BIT(1))
|
||||
#define VHT_CAP_SUPP_CHAN_WIDTH_160MHZ ((u32) BIT(2))
|
||||
#define VHT_CAP_SUPP_CHAN_WIDTH_160_80PLUS80MHZ ((u32) BIT(3))
|
||||
#define VHT_CAP_RXLDPC ((u32) BIT(4))
|
||||
#define VHT_CAP_SHORT_GI_80 ((u32) BIT(5))
|
||||
#define VHT_CAP_SHORT_GI_160 ((u32) BIT(6))
|
||||
#define VHT_CAP_TXSTBC ((u32) BIT(7))
|
||||
#define VHT_CAP_RXSTBC_1 ((u32) BIT(8))
|
||||
#define VHT_CAP_RXSTBC_2 ((u32) BIT(9))
|
||||
#define VHT_CAP_RXSTBC_3 ((u32) BIT(8) | BIT(9))
|
||||
#define VHT_CAP_RXSTBC_4 ((u32) BIT(10))
|
||||
#define VHT_CAP_SU_BEAMFORMER_CAPABLE ((u32) BIT(11))
|
||||
#define VHT_CAP_SU_BEAMFORMEE_CAPABLE ((u32) BIT(12))
|
||||
#define VHT_CAP_BEAMFORMER_ANTENNAS_MAX ((u32) BIT(13) | BIT(14))
|
||||
#define VHT_CAP_SOUNDING_DIMENTION_MAX ((u32) BIT(16) | BIT(17))
|
||||
#define VHT_CAP_MU_BEAMFORMER_CAPABLE ((u32) BIT(19))
|
||||
#define VHT_CAP_MU_BEAMFORMEE_CAPABLE ((u32) BIT(20))
|
||||
#define VHT_CAP_VHT_TXOP_PS ((u32) BIT(21))
|
||||
#define VHT_CAP_HTC_VHT ((u32) BIT(22))
|
||||
#define VHT_CAP_MAX_A_MPDU_LENGTH_EXPONENT ((u32) BIT(23))
|
||||
#define VHT_CAP_VHT_LINK_ADAPTATION_VHT_UNSOL_MFB ((u32) BIT(27))
|
||||
#define VHT_CAP_VHT_LINK_ADAPTATION_VHT_MRQ_MFB ((u32) BIT(26) | BIT(27))
|
||||
#define VHT_CAP_RX_ANTENNA_PATTERN ((u32) BIT(28))
|
||||
#define VHT_CAP_TX_ANTENNA_PATTERN ((u32) BIT(29))
|
||||
|
||||
#define OUI_MICROSOFT 0x0050f2 /* Microsoft (also used in Wi-Fi specs)
|
||||
* 00:50:F2 */
|
||||
#define WPA_IE_VENDOR_TYPE 0x0050f201
|
||||
#define WPS_IE_VENDOR_TYPE 0x0050f204
|
||||
#define OUI_WFA 0x506f9a
|
||||
#define P2P_IE_VENDOR_TYPE 0x506f9a09
|
||||
#define WFD_IE_VENDOR_TYPE 0x506f9a0a
|
||||
#define WFD_OUI_TYPE 10
|
||||
#define HS20_IE_VENDOR_TYPE 0x506f9a10
|
||||
|
||||
#define WMM_OUI_TYPE 2
|
||||
#define WMM_OUI_SUBTYPE_INFORMATION_ELEMENT 0
|
||||
@ -516,6 +759,10 @@ struct wmm_information_element {
|
||||
|
||||
} STRUCT_PACKED;
|
||||
|
||||
#define WMM_QOSINFO_STA_AC_MASK 0x0f
|
||||
#define WMM_QOSINFO_STA_SP_MASK 0x03
|
||||
#define WMM_QOSINFO_STA_SP_SHIFT 5
|
||||
|
||||
#define WMM_AC_AIFSN_MASK 0x0f
|
||||
#define WMM_AC_AIFNS_SHIFT 0
|
||||
#define WMM_AC_ACM 0x10
|
||||
@ -544,7 +791,7 @@ struct wmm_parameter_element {
|
||||
u8 oui_type; /* 2 */
|
||||
u8 oui_subtype; /* 1 */
|
||||
u8 version; /* 1 for WMM version 1.0 */
|
||||
u8 qos_info; /* AP/STA specif QoS info */
|
||||
u8 qos_info; /* AP/STA specific QoS info */
|
||||
u8 reserved; /* 0 */
|
||||
struct wmm_ac_parameter ac[4]; /* AC_BE, AC_BK, AC_VI, AC_VO */
|
||||
|
||||
@ -587,6 +834,140 @@ enum {
|
||||
};
|
||||
|
||||
|
||||
#define HS20_INDICATION_OUI_TYPE 16
|
||||
#define HS20_ANQP_OUI_TYPE 17
|
||||
#define HS20_STYPE_QUERY_LIST 1
|
||||
#define HS20_STYPE_CAPABILITY_LIST 2
|
||||
#define HS20_STYPE_OPERATOR_FRIENDLY_NAME 3
|
||||
#define HS20_STYPE_WAN_METRICS 4
|
||||
#define HS20_STYPE_CONNECTION_CAPABILITY 5
|
||||
#define HS20_STYPE_NAI_HOME_REALM_QUERY 6
|
||||
#define HS20_STYPE_OPERATING_CLASS 7
|
||||
|
||||
/* Wi-Fi Direct (P2P) */
|
||||
|
||||
#define P2P_OUI_TYPE 9
|
||||
|
||||
enum p2p_attr_id {
|
||||
P2P_ATTR_STATUS = 0,
|
||||
P2P_ATTR_MINOR_REASON_CODE = 1,
|
||||
P2P_ATTR_CAPABILITY = 2,
|
||||
P2P_ATTR_DEVICE_ID = 3,
|
||||
P2P_ATTR_GROUP_OWNER_INTENT = 4,
|
||||
P2P_ATTR_CONFIGURATION_TIMEOUT = 5,
|
||||
P2P_ATTR_LISTEN_CHANNEL = 6,
|
||||
P2P_ATTR_GROUP_BSSID = 7,
|
||||
P2P_ATTR_EXT_LISTEN_TIMING = 8,
|
||||
P2P_ATTR_INTENDED_INTERFACE_ADDR = 9,
|
||||
P2P_ATTR_MANAGEABILITY = 10,
|
||||
P2P_ATTR_CHANNEL_LIST = 11,
|
||||
P2P_ATTR_NOTICE_OF_ABSENCE = 12,
|
||||
P2P_ATTR_DEVICE_INFO = 13,
|
||||
P2P_ATTR_GROUP_INFO = 14,
|
||||
P2P_ATTR_GROUP_ID = 15,
|
||||
P2P_ATTR_INTERFACE = 16,
|
||||
P2P_ATTR_OPERATING_CHANNEL = 17,
|
||||
P2P_ATTR_INVITATION_FLAGS = 18,
|
||||
P2P_ATTR_VENDOR_SPECIFIC = 221
|
||||
};
|
||||
|
||||
#define P2P_MAX_GO_INTENT 15
|
||||
|
||||
/* P2P Capability - Device Capability bitmap */
|
||||
#define P2P_DEV_CAPAB_SERVICE_DISCOVERY BIT(0)
|
||||
#define P2P_DEV_CAPAB_CLIENT_DISCOVERABILITY BIT(1)
|
||||
#define P2P_DEV_CAPAB_CONCURRENT_OPER BIT(2)
|
||||
#define P2P_DEV_CAPAB_INFRA_MANAGED BIT(3)
|
||||
#define P2P_DEV_CAPAB_DEVICE_LIMIT BIT(4)
|
||||
#define P2P_DEV_CAPAB_INVITATION_PROCEDURE BIT(5)
|
||||
|
||||
/* P2P Capability - Group Capability bitmap */
|
||||
#define P2P_GROUP_CAPAB_GROUP_OWNER BIT(0)
|
||||
#define P2P_GROUP_CAPAB_PERSISTENT_GROUP BIT(1)
|
||||
#define P2P_GROUP_CAPAB_GROUP_LIMIT BIT(2)
|
||||
#define P2P_GROUP_CAPAB_INTRA_BSS_DIST BIT(3)
|
||||
#define P2P_GROUP_CAPAB_CROSS_CONN BIT(4)
|
||||
#define P2P_GROUP_CAPAB_PERSISTENT_RECONN BIT(5)
|
||||
#define P2P_GROUP_CAPAB_GROUP_FORMATION BIT(6)
|
||||
|
||||
/* Invitation Flags */
|
||||
#define P2P_INVITATION_FLAGS_TYPE BIT(0)
|
||||
|
||||
/* P2P Manageability */
|
||||
#define P2P_MAN_DEVICE_MANAGEMENT BIT(0)
|
||||
#define P2P_MAN_CROSS_CONNECTION_PERMITTED BIT(1)
|
||||
#define P2P_MAN_COEXISTENCE_OPTIONAL BIT(2)
|
||||
|
||||
enum p2p_status_code {
|
||||
P2P_SC_SUCCESS = 0,
|
||||
P2P_SC_FAIL_INFO_CURRENTLY_UNAVAILABLE = 1,
|
||||
P2P_SC_FAIL_INCOMPATIBLE_PARAMS = 2,
|
||||
P2P_SC_FAIL_LIMIT_REACHED = 3,
|
||||
P2P_SC_FAIL_INVALID_PARAMS = 4,
|
||||
P2P_SC_FAIL_UNABLE_TO_ACCOMMODATE = 5,
|
||||
P2P_SC_FAIL_PREV_PROTOCOL_ERROR = 6,
|
||||
P2P_SC_FAIL_NO_COMMON_CHANNELS = 7,
|
||||
P2P_SC_FAIL_UNKNOWN_GROUP = 8,
|
||||
P2P_SC_FAIL_BOTH_GO_INTENT_15 = 9,
|
||||
P2P_SC_FAIL_INCOMPATIBLE_PROV_METHOD = 10,
|
||||
P2P_SC_FAIL_REJECTED_BY_USER = 11,
|
||||
};
|
||||
|
||||
#define P2P_WILDCARD_SSID "DIRECT-"
|
||||
#define P2P_WILDCARD_SSID_LEN 7
|
||||
|
||||
/* P2P action frames */
|
||||
enum p2p_act_frame_type {
|
||||
P2P_NOA = 0,
|
||||
P2P_PRESENCE_REQ = 1,
|
||||
P2P_PRESENCE_RESP = 2,
|
||||
P2P_GO_DISC_REQ = 3
|
||||
};
|
||||
|
||||
/* P2P public action frames */
|
||||
enum p2p_action_frame_type {
|
||||
P2P_GO_NEG_REQ = 0,
|
||||
P2P_GO_NEG_RESP = 1,
|
||||
P2P_GO_NEG_CONF = 2,
|
||||
P2P_INVITATION_REQ = 3,
|
||||
P2P_INVITATION_RESP = 4,
|
||||
P2P_DEV_DISC_REQ = 5,
|
||||
P2P_DEV_DISC_RESP = 6,
|
||||
P2P_PROV_DISC_REQ = 7,
|
||||
P2P_PROV_DISC_RESP = 8
|
||||
};
|
||||
|
||||
enum p2p_service_protocol_type {
|
||||
P2P_SERV_ALL_SERVICES = 0,
|
||||
P2P_SERV_BONJOUR = 1,
|
||||
P2P_SERV_UPNP = 2,
|
||||
P2P_SERV_WS_DISCOVERY = 3,
|
||||
P2P_SERV_WIFI_DISPLAY = 4,
|
||||
P2P_SERV_VENDOR_SPECIFIC = 255
|
||||
};
|
||||
|
||||
enum p2p_sd_status {
|
||||
P2P_SD_SUCCESS = 0,
|
||||
P2P_SD_PROTO_NOT_AVAILABLE = 1,
|
||||
P2P_SD_REQUESTED_INFO_NOT_AVAILABLE = 2,
|
||||
P2P_SD_BAD_REQUEST = 3
|
||||
};
|
||||
|
||||
|
||||
enum wifi_display_subelem {
|
||||
WFD_SUBELEM_DEVICE_INFO = 0,
|
||||
WFD_SUBELEM_ASSOCIATED_BSSID = 1,
|
||||
WFD_SUBELEM_AUDIO_FORMATS = 2,
|
||||
WFD_SUBELEM_VIDEO_FORMATS = 3,
|
||||
WFD_SUBELEM_3D_VIDEO_FORMATS = 4,
|
||||
WFD_SUBELEM_CONTENT_PROTECTION = 5,
|
||||
WFD_SUBELEM_COUPLED_SINK = 6,
|
||||
WFD_SUBELEM_EXT_CAPAB = 7,
|
||||
WFD_SUBELEM_LOCAL_IP_ADDRESS = 8,
|
||||
WFD_SUBELEM_SESSION_INFO = 9
|
||||
};
|
||||
|
||||
|
||||
#define OUI_BROADCOM 0x00904c /* Broadcom (Epigram) */
|
||||
|
||||
#define VENDOR_HT_CAPAB_OUI_TYPE 0x33 /* 00-90-4c:0x33 */
|
||||
@ -599,9 +980,106 @@ enum {
|
||||
#define WLAN_CIPHER_SUITE_CCMP 0x000FAC04
|
||||
#define WLAN_CIPHER_SUITE_WEP104 0x000FAC05
|
||||
#define WLAN_CIPHER_SUITE_AES_CMAC 0x000FAC06
|
||||
#define WLAN_CIPHER_SUITE_NO_GROUP_ADDR 0x000FAC07
|
||||
#define WLAN_CIPHER_SUITE_GCMP 0x000FAC08
|
||||
|
||||
#define WLAN_CIPHER_SUITE_SMS4 0x00147201
|
||||
|
||||
#define WLAN_CIPHER_SUITE_CKIP 0x00409600
|
||||
#define WLAN_CIPHER_SUITE_CKIP_CMIC 0x00409601
|
||||
#define WLAN_CIPHER_SUITE_CMIC 0x00409602
|
||||
#define WLAN_CIPHER_SUITE_KRK 0x004096FF /* for nl80211 use only */
|
||||
|
||||
/* AKM suite selectors */
|
||||
#define WLAN_AKM_SUITE_8021X 0x000FAC01
|
||||
#define WLAN_AKM_SUITE_PSK 0x000FAC02
|
||||
#define WLAN_AKM_SUITE_CCKM 0x00409600
|
||||
|
||||
|
||||
/* IEEE 802.11v - WNM Action field values */
|
||||
enum wnm_action {
|
||||
WNM_EVENT_REQ = 0,
|
||||
WNM_EVENT_REPORT = 1,
|
||||
WNM_DIAGNOSTIC_REQ = 2,
|
||||
WNM_DIAGNOSTIC_REPORT = 3,
|
||||
WNM_LOCATION_CFG_REQ = 4,
|
||||
WNM_LOCATION_CFG_RESP = 5,
|
||||
WNM_BSS_TRANS_MGMT_QUERY = 6,
|
||||
WNM_BSS_TRANS_MGMT_REQ = 7,
|
||||
WNM_BSS_TRANS_MGMT_RESP = 8,
|
||||
WNM_FMS_REQ = 9,
|
||||
WNM_FMS_RESP = 10,
|
||||
WNM_COLLOCATED_INTERFERENCE_REQ = 11,
|
||||
WNM_COLLOCATED_INTERFERENCE_REPORT = 12,
|
||||
WNM_TFS_REQ = 13,
|
||||
WNM_TFS_RESP = 14,
|
||||
WNM_TFS_NOTIFY = 15,
|
||||
WNM_SLEEP_MODE_REQ = 16,
|
||||
WNM_SLEEP_MODE_RESP = 17,
|
||||
WNM_TIM_BROADCAST_REQ = 18,
|
||||
WNM_TIM_BROADCAST_RESP = 19,
|
||||
WNM_QOS_TRAFFIC_CAPAB_UPDATE = 20,
|
||||
WNM_CHANNEL_USAGE_REQ = 21,
|
||||
WNM_CHANNEL_USAGE_RESP = 22,
|
||||
WNM_DMS_REQ = 23,
|
||||
WNM_DMS_RESP = 24,
|
||||
WNM_TIMING_MEASUREMENT_REQ = 25,
|
||||
WNM_NOTIFICATION_REQ = 26,
|
||||
WNM_NOTIFICATION_RESP = 27
|
||||
};
|
||||
|
||||
/* IEEE 802.11v - BSS Transition Management Request - Request Mode */
|
||||
#define WNM_BSS_TM_REQ_PREF_CAND_LIST_INCLUDED BIT(0)
|
||||
#define WNM_BSS_TM_REQ_ABRIDGED BIT(1)
|
||||
#define WNM_BSS_TM_REQ_DISASSOC_IMMINENT BIT(2)
|
||||
#define WNM_BSS_TM_REQ_BSS_TERMINATION_INCLUDED BIT(3)
|
||||
#define WNM_BSS_TM_REQ_ESS_DISASSOC_IMMINENT BIT(4)
|
||||
|
||||
/* IEEE Std 802.11-2012, 8.4.2.62 20/40 BSS Coexistence element */
|
||||
#define WLAN_20_40_BSS_COEX_INFO_REQ BIT(0)
|
||||
#define WLAN_20_40_BSS_COEX_40MHZ_INTOL BIT(1)
|
||||
#define WLAN_20_40_BSS_COEX_20MHZ_WIDTH_REQ BIT(2)
|
||||
#define WLAN_20_40_BSS_COEX_OBSS_EXEMPT_REQ BIT(3)
|
||||
#define WLAN_20_40_BSS_COEX_OBSS_EXEMPT_GRNT BIT(4)
|
||||
|
||||
struct ieee80211_2040_bss_coex_ie {
|
||||
u8 element_id;
|
||||
u8 length;
|
||||
u8 coex_param;
|
||||
} STRUCT_PACKED;
|
||||
|
||||
struct ieee80211_2040_intol_chan_report {
|
||||
u8 element_id;
|
||||
u8 length;
|
||||
u8 op_class;
|
||||
u8 variable[0]; /* Channel List */
|
||||
} STRUCT_PACKED;
|
||||
|
||||
/* IEEE 802.11v - WNM-Sleep Mode element */
|
||||
struct wnm_sleep_element {
|
||||
u8 eid; /* WLAN_EID_WNMSLEEP */
|
||||
u8 len;
|
||||
u8 action_type; /* WNM_SLEEP_ENTER/WNM_SLEEP_MODE_EXIT */
|
||||
u8 status;
|
||||
le16 intval;
|
||||
} STRUCT_PACKED;
|
||||
|
||||
#define WNM_SLEEP_MODE_ENTER 0
|
||||
#define WNM_SLEEP_MODE_EXIT 1
|
||||
|
||||
enum wnm_sleep_mode_response_status {
|
||||
WNM_STATUS_SLEEP_ACCEPT = 0,
|
||||
WNM_STATUS_SLEEP_EXIT_ACCEPT_GTK_UPDATE = 1,
|
||||
WNM_STATUS_DENIED_ACTION = 2,
|
||||
WNM_STATUS_DENIED_TMP = 3,
|
||||
WNM_STATUS_DENIED_KEY = 4,
|
||||
WNM_STATUS_DENIED_OTHER_WNM_SERVICE = 5
|
||||
};
|
||||
|
||||
/* WNM-Sleep Mode subelement IDs */
|
||||
enum wnm_sleep_mode_subelement_id {
|
||||
WNM_SLEEP_SUBELEM_GTK = 0,
|
||||
WNM_SLEEP_SUBELEM_IGTK = 1
|
||||
};
|
||||
|
||||
#endif /* IEEE802_11_DEFS_H */
|
||||
|
@ -2,14 +2,8 @@
|
||||
* WPA Supplicant - privilege separation commands
|
||||
* Copyright (c) 2007-2009, Jouni Malinen <j@w1.fi>
|
||||
*
|
||||
* This program is free software; you can redistribute it and/or modify
|
||||
* it under the terms of the GNU General Public License version 2 as
|
||||
* published by the Free Software Foundation.
|
||||
*
|
||||
* Alternatively, this software may be distributed under the terms of BSD
|
||||
* license.
|
||||
*
|
||||
* See README and COPYING for more details.
|
||||
* This software may be distributed under the terms of the BSD license.
|
||||
* See README for more details.
|
||||
*/
|
||||
|
||||
#ifndef PRIVSEP_COMMANDS_H
|
||||
|
@ -1,6 +1,10 @@
|
||||
#ifndef VERSION_H
|
||||
#define VERSION_H
|
||||
|
||||
#define VERSION_STR "0.7.3"
|
||||
#ifndef VERSION_STR_POSTFIX
|
||||
#define VERSION_STR_POSTFIX ""
|
||||
#endif /* VERSION_STR_POSTFIX */
|
||||
|
||||
#define VERSION_STR "2.0" VERSION_STR_POSTFIX
|
||||
|
||||
#endif /* VERSION_H */
|
||||
|
Some files were not shown because too many files have changed in this diff Show More
Loading…
Reference in New Issue
Block a user