import v2_0:

2013-01-12 - v2.0
	* removed Qt3-based wpa_gui (obsoleted by wpa_qui-qt4)
	* removed unmaintained driver wrappers broadcom, iphone, osx, ralink,
	  hostap, madwifi (hostap and madwifi remain available for hostapd;
	  their wpa_supplicant functionality is obsoleted by wext)
	* improved debug logging (human readable event names, interface name
	  included in more entries)
	* changed AP mode behavior to enable WPS only for open and
	  WPA/WPA2-Personal configuration
	* improved P2P concurrency operations
	  - better coordination of concurrent scan and P2P search operations
	  - avoid concurrent remain-on-channel operation requests by canceling
	    previous operations prior to starting a new one
	  - reject operations that would require multi-channel concurrency if
	    the driver does not support it
	  - add parameter to select whether STA or P2P connection is preferred
	    if the driver cannot support both at the same time
	  - allow driver to indicate channel changes
	  - added optional delay=<search delay in milliseconds> parameter for
	    p2p_find to avoid taking all radio resources
	  - use 500 ms p2p_find search delay by default during concurrent
	    operations
	  - allow all channels in GO Negotiation if the driver supports
	    multi-channel concurrency
	* added number of small changes to make it easier for static analyzers
	  to understand the implementation
	* fixed number of small bugs (see git logs for more details)
	* nl80211: number of updates to use new cfg80211/nl80211 functionality
	  - replace monitor interface with nl80211 commands for AP mode
	  - additional information for driver-based AP SME
	  - STA entry authorization in RSN IBSS
	* EAP-pwd:
	  - fixed KDF for group 21 and zero-padding
	  - added support for fragmentation
	  - increased maximum number of hunting-and-pecking iterations
	* avoid excessive Probe Response retries for broadcast Probe Request
	  frames (only with drivers using wpa_supplicant AP mode SME/MLME)
	* added "GET country" ctrl_iface command
	* do not save an invalid network block in wpa_supplicant.conf to avoid
	  problems reading the file on next start
	* send STA connected/disconnected ctrl_iface events to both the P2P
	  group and parent interfaces
	* added preliminary support for using TLS v1.2 (CONFIG_TLSV12=y)
	* added "SET pno <1/0>" ctrl_iface command to start/stop preferred
	  network offload with sched_scan driver command
	* merged in number of changes from Android repository for P2P, nl80211,
	  and build parameters
	* changed P2P GO mode configuration to use driver capabilities to
	  automatically enable HT operations when supported
	* added "wpa_cli status wps" command to fetch WPA2-Personal passhrase
	  for WPS use cases in AP mode
	* EAP-AKA: keep pseudonym identity across EAP exchanges to match EAP-SIM
	  behavior
	* improved reassociation behavior in cases where association is rejected
	  or when an AP disconnects us to handle common load balancing
	  mechanisms
	  - try to avoid extra scans when the needed information is available
	* added optional "join" argument for p2p_prov_disc ctrl_iface command
	* added group ifname to P2P-PROV-DISC-* events
	* added P2P Device Address to AP-STA-DISCONNECTED event and use
	  p2p_dev_addr parameter name with AP-STA-CONNECTED
	* added workarounds for WPS PBC overlap detection for some P2P use cases
	  where deployed stations work incorrectly
	* optimize WPS connection speed by disconnecting prior to WPS scan and
	  by using single channel scans when AP channel is known
	* PCSC and SIM/USIM improvements:
	  - accept 0x67 (Wrong length) as a response to READ RECORD to fix
	    issues with some USIM cards
	  - try to read MNC length from SIM/USIM
	  - build realm according to 3GPP TS 23.003 with identity from the SIM
	  - allow T1 protocol to be enabled
	* added more WPS and P2P information available through D-Bus
	* improve P2P negotiation robustness
	  - extra waits to get ACK frames through
	  - longer timeouts for cases where deployed devices have been
	    identified have issues meeting the specification requirements
	  - more retries for some P2P frames
	  - handle race conditions in GO Negotiation start by both devices
	  - ignore unexpected GO Negotiation Response frame
	* added support for libnl 3.2 and newer
	* added P2P persistent group info to P2P_PEER data
	* maintain a list of P2P Clients for persistent group on GO
	* AP: increased initial group key handshake retransmit timeout to 500 ms
	* added optional dev_id parameter for p2p_find
	* added P2P-FIND-STOPPED ctrl_iface event
	* fixed issues in WPA/RSN element validation when roaming with ap_scan=1
	  and driver-based BSS selection
	* do not expire P2P peer entries while connected with the peer in a
	  group
	* fixed WSC element inclusion in cases where P2P is disabled
	* AP: added a WPS workaround for mixed mode AP Settings with Windows 7
	* EAP-SIM: fixed AT_COUNTER_TOO_SMALL use
	* EAP-SIM/AKA: append realm to pseudonym identity
	* EAP-SIM/AKA: store pseudonym identity in network configuration to
	  allow it to persist over multiple EAP sessions and wpa_supplicant
	  restarts
	* EAP-AKA': updated to RFC 5448 (username prefixes changed); note: this
	  breaks interoperability with older versions
	* added support for WFA Hotspot 2.0
	  - GAS/ANQP to fetch network information
	  - credential configuration and automatic network selections based on
	    credential match with ANQP information
	* limited PMKSA cache entries to be used only with the network context
	  that was used to create them
	* improved PMKSA cache expiration to avoid unnecessary disconnections
	* adjusted bgscan_simple fast-scan backoff to avoid too frequent
	  background scans
	* removed ctrl_iface event on P2P PD Response in join-group case
	* added option to fetch BSS table entry based on P2P Device Address
	  ("BSS p2p_dev_addr=<P2P Device Address>")
	* added BSS entry age to ctrl_iface BSS command output
	* added optional MASK=0xH option for ctrl_iface BSS command to select
	  which fields are included in the response
	* added optional RANGE=ALL|N1-N2 option for ctrl_iface BSS command to
	  fetch information about several BSSes in one call
	* simplified licensing terms by selecting the BSD license as the only
	  alternative
	* added "P2P_SET disallow_freq <freq list>" ctrl_iface command to
	  disable channels from P2P use
	* added p2p_pref_chan configuration parameter to allow preferred P2P
	  channels to be specified
	* added support for advertising immediate availability of a WPS
	  credential for P2P use cases
	* optimized scan operations for P2P use cases (use single channel scan
	  for a specific SSID when possible)
	* EAP-TTLS: fixed peer challenge generation for MSCHAPv2
	* SME: do not use reassociation after explicit disconnection request
	  (local or a notification from an AP)
	* added support for sending debug info to Linux tracing (-T on command
	  line)
	* added support for using Deauthentication reason code 3 as an
	  indication of P2P group termination
	* added wps_vendor_ext_m1 configuration parameter to allow vendor
	  specific attributes to be added to WPS M1
	* started using separate TLS library context for tunneled TLS
	  (EAP-PEAP/TLS, EAP-TTLS/TLS, EAP-FAST/TLS) to support different CA
	  certificate configuration between Phase 1 and Phase 2
	* added optional "auto" parameter for p2p_connect to request automatic
	  GO Negotiation vs. join-a-group selection
	* added disabled_scan_offload parameter to disable automatic scan
	  offloading (sched_scan)
	* added optional persistent=<network id> parameter for p2p_connect to
	  allow forcing of a specific SSID/passphrase for GO Negotiation
	* added support for OBSS scan requests and 20/40 BSS coexistence reports
	* reject PD Request for unknown group
	* removed scripts and notes related to Windows binary releases (which
	  have not been used starting from 1.x)
	* added initial support for WNM operations
	  - Keep-alive based on BSS max idle period
	  - WNM-Sleep Mode
	  - minimal BSS Transition Management processing
	* added autoscan module to control scanning behavior while not connected
	  - autoscan_periodic and autoscan_exponential modules
	* added new WPS NFC ctrl_iface mechanism
	  - added initial support NFC connection handover
	  - removed obsoleted WPS_OOB command (including support for deprecated
	    UFD config_method)
	* added optional framework for external password storage ("ext:<name>")
	* wpa_cli: added optional support for controlling wpa_supplicant
	  remotely over UDP (CONFIG_CTRL_IFACE=udp-remote) for testing purposes
	* wpa_cli: extended tab completion to more commands
	* changed SSID output to use printf-escaped strings instead of masking
	  of non-ASCII characters
	  - SSID can now be configured in the same format: ssid=P"abc\x00test"
	* removed default ACM=1 from AC_VO and AC_VI
	* added optional "ht40" argument for P2P ctrl_iface commands to allow
	  40 MHz channels to be requested on the 5 GHz band
	* added optional parameters for p2p_invite command to specify channel
	  when reinvoking a persistent group as the GO
	* improved FIPS mode builds with OpenSSL
	  - "make fips" with CONFIG_FIPS=y to build wpa_supplicant with the
	    OpenSSL FIPS object module
	  - replace low level OpenSSL AES API calls to use EVP
	  - use OpenSSL keying material exporter when possible
	  - do not export TLS keys in FIPS mode
	  - remove MD5 from CONFIG_FIPS=y builds
	  - use OpenSSL function for PKBDF2 passphrase-to-PSK
	  - use OpenSSL HMAC implementation
	  - mix RAND_bytes() output into random_get_bytes() to force OpenSSL
	    DRBG to be used in FIPS mode
	  - use OpenSSL CMAC implementation
	* added mechanism to disable TLS Session Ticket extension
	  - a workaround for servers that do not support TLS extensions that
	    was enabled by default in recent OpenSSL versions
	  - tls_disable_session_ticket=1
	  - automatically disable TLS Session Ticket extension by default when
	    using EAP-TLS/PEAP/TTLS (i.e., only use it with EAP-FAST)
	* changed VENDOR-TEST EAP method to use proper private enterprise number
	  (this will not interoperate with older versions)
	* disable network block temporarily on authentication failures
	* improved WPS AP selection during WPS PIN iteration
	* added support for configuring GCMP cipher for IEEE 802.11ad
	* added support for Wi-Fi Display extensions
	  - WFD_SUBELEMENT_SET ctrl_iface command to configure WFD subelements
	  - SET wifi_display <0/1> to disable/enable WFD support
	  - WFD service discovery
	  - an external program is needed to manage the audio/video streaming
	    and codecs
	* optimized scan result use for network selection
	  - use the internal BSS table instead of raw scan results
	  - allow unnecessary scans to be skipped if fresh information is
	    available (e.g., after GAS/ANQP round for Interworking)
	* added support for 256-bit AES with internal TLS implementation
	* allow peer to propose channel in P2P invitation process for a
	  persistent group
	* added disallow_aps parameter to allow BSSIDs/SSIDs to be disallowed
	  from network selection
	* re-enable the networks disabled during WPS operations
	* allow P2P functionality to be disabled per interface (p2p_disabled=1)
	* added secondary device types into P2P_PEER output
	* added an option to disable use of a separate P2P group interface
	  (p2p_no_group_iface=1)
	* fixed P2P Bonjour SD to match entries with both compressed and not
	  compressed domain name format and support multiple Bonjour PTR matches
	  for the same key
	* use deauthentication instead of disassociation for all disconnection
	  operations; this removes the now unused disassociate() wpa_driver_ops
	  callback
	* optimized PSK generation on P2P GO by caching results to avoid
	  multiple PBKDF2 operations
	* added okc=1 global configuration parameter to allow OKC to be enabled
	  by default for all network blocks
	* added a workaround for WPS PBC session overlap detection to avoid
	  interop issues with deployed station implementations that do not
	  remove active PBC indication from Probe Request frames properly
	* added basic support for 60 GHz band
	* extend EAPOL frames processing workaround for roaming cases
	  (postpone processing of unexpected EAPOL frame until association
	  event to handle reordered events)
This commit is contained in:
christos 2014-01-03 02:04:55 +00:00
parent 681c174ae4
commit e604d8611d
592 changed files with 39473 additions and 12781 deletions

View File

@ -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.

View File

@ -4,9 +4,8 @@ wpa_supplicant and hostapd
Copyright (c) 2002-2012, Jouni Malinen <j@w1.fi> and contributors
All Rights Reserved.
These programs are dual-licensed under both the GPL version 2 and BSD
license (the one with advertisement clause removed). Either license
may be used at your option.
These programs are licensed under the BSD license (the one with
advertisement clause removed).
If you are submitting changes to the project, please see CONTRIBUTIONS
file for more instructions.
@ -26,26 +25,8 @@ builds).
License
-------
GPL v2:
This program is free software; you can redistribute it and/or modify
it under the terms of the GNU General Public License version 2 as
published by the Free Software Foundation.
This program is distributed in the hope that it will be useful,
but WITHOUT ANY WARRANTY; without even the implied warranty of
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
GNU General Public License for more details.
You should have received a copy of the GNU General Public License
along with this program; if not, write to the Free Software
Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA
(this copy of the license is in COPYING file)
Alternatively, this software may be distributed, used, and modified
under the terms of BSD license:
This software may be distributed, used, and modified under the terms of
BSD license:
Redistribution and use in source and binary forms, with or without
modification, are permitted provided that the following conditions are

View File

@ -1,18 +1,26 @@
# Copyright (C) 2008 The Android Open Source Project
#
# This software may be distributed under the terms of the BSD license.
# See README for more details.
#
LOCAL_PATH := $(call my-dir)
WPA_BUILD_HOSTAPD := false
ifneq ($(TARGET_SIMULATOR),true)
ifneq ($(BOARD_HOSTAPD_DRIVER),)
WPA_BUILD_HOSTAPD := true
CONFIG_DRIVER_$(BOARD_HOSTAPD_DRIVER) := y
endif
ifneq ($(BOARD_HOSTAPD_DRIVER),)
WPA_BUILD_HOSTAPD := true
CONFIG_DRIVER_$(BOARD_HOSTAPD_DRIVER) := y
endif
include $(LOCAL_PATH)/.config
ifeq ($(WPA_BUILD_HOSTAPD),true)
include $(LOCAL_PATH)/android.config
# To ignore possible wrong network configurations
L_CFLAGS = -DWPA_IGNORE_CONFIG_ERRORS
L_CFLAGS += -DVERSION_STR_POSTFIX=\"-$(PLATFORM_VERSION)\"
# Set Android log name
L_CFLAGS += -DANDROID_LOG_NAME=\"hostapd\"
@ -65,6 +73,7 @@ OBJS += src/ap/utils.c
OBJS += src/ap/authsrv.c
OBJS += src/ap/ieee802_1x.c
OBJS += src/ap/ap_config.c
OBJS += src/ap/eap_user_db.c
OBJS += src/ap/ieee802_11_auth.c
OBJS += src/ap/sta_info.c
OBJS += src/ap/wpa_auth.c
@ -143,6 +152,12 @@ ifdef CONFIG_NO_VLAN
L_CFLAGS += -DCONFIG_NO_VLAN
else
OBJS += src/ap/vlan_init.c
ifdef CONFIG_VLAN_NETLINK
ifdef CONFIG_FULL_DYNAMIC_VLAN
OBJS += src/ap/vlan_util.c
endif
L_CFLAGS += -DCONFIG_VLAN_NETLINK
endif
endif
ifdef CONFIG_NO_CTRL_IFACE
@ -185,6 +200,10 @@ NEED_AES_OMAC1=y
NEED_AES_UNWRAP=y
endif
ifdef CONFIG_SAE
L_CFLAGS += -DCONFIG_SAE
endif
ifdef CONFIG_IEEE80211N
L_CFLAGS += -DCONFIG_IEEE80211N
endif
@ -351,25 +370,10 @@ NEED_AES_CBC=y
NEED_MODEXP=y
CONFIG_EAP=y
ifdef CONFIG_WPS_UFD
L_CFLAGS += -DCONFIG_WPS_UFD
OBJS += src/wps/wps_ufd.c
NEED_WPS_OOB=y
endif
ifdef CONFIG_WPS_NFC
L_CFLAGS += -DCONFIG_WPS_NFC
OBJS += src/wps/ndef.c
OBJS += src/wps/wps_nfc.c
NEED_WPS_OOB=y
ifdef CONFIG_WPS_NFC_PN531
PN531_PATH ?= /usr/local/src/nfc
L_CFLAGS += -DCONFIG_WPS_NFC_PN531
L_CFLAGS += -I${PN531_PATH}/inc
OBJS += src/wps/wps_nfc_pn531.c
LIBS += ${PN531_PATH}/lib/wpsnfc.dll
LIBS += ${PN531_PATH}/lib/libnfc_mapping_pn53x.dll
endif
endif
ifdef NEED_WPS_OOB
@ -655,14 +659,19 @@ endif
SHA1OBJS =
ifdef NEED_SHA1
ifneq ($(CONFIG_TLS), openssl)
SHA1OBJS += src/crypto/sha1.c
endif
SHA1OBJS += src/crypto/sha1-prf.c
ifdef CONFIG_INTERNAL_SHA1
SHA1OBJS += src/crypto/sha1-internal.c
ifdef NEED_FIPS186_2_PRF
SHA1OBJS += src/crypto/fips_prf_internal.c
endif
endif
ifneq ($(CONFIG_TLS), openssl)
SHA1OBJS += src/crypto/sha1-pbkdf2.c
endif
ifdef NEED_T_PRF
SHA1OBJS += src/crypto/sha1-tprf.c
endif
@ -701,10 +710,17 @@ endif
endif
ifdef NEED_SHA256
L_CFLAGS += -DCONFIG_SHA256
ifneq ($(CONFIG_TLS), openssl)
OBJS += src/crypto/sha256.c
endif
OBJS += src/crypto/sha256-prf.c
ifdef CONFIG_INTERNAL_SHA256
OBJS += src/crypto/sha256-internal.c
endif
ifdef NEED_TLS_PRF_SHA256
OBJS += ../src/crypto/sha256-tlsprf.c
endif
endif
ifdef NEED_DH_GROUPS
@ -793,8 +809,6 @@ else
OBJS_c += src/utils/edit_simple.c
endif
ifeq ($(WPA_BUILD_HOSTAPD),true)
########################
include $(CLEAR_VARS)

View File

@ -1,30 +1,101 @@
ChangeLog for hostapd
2012-11-06 - v1.1
* Fix EAPOL processing when STA switches between multi-BSSes.
* EAP-TLS server: Fix a bug with TLS Message Length validation that
could result in the process terminating.
* Fix memory allocation failure handling in EAP-TTLS/MSCHAPv2 server.
* Fix EAP-FAST with OpenSSL 1.0.1.
* Fix WPA GTK rekeying with multiple VLANs.
* EAP-pwd: Increase maximum number of hunting-and-pecking iterations,
which results in less authentication attempts failing.
* hlr_auc_gw: Use 5 bit IND for SQN updates. The length of IND can be
configured on the command line with the new -i<IND len> parameter.
-i0 would make hlr_auc_gw behave the same as the prev implementation.
* EAP-AKA'
- Update to RFC 5448 in the leading characters used in the username.
This will make EAP-AKA' not interoperate between the earlier draft
version and the new version.
- server: Fix identity for MK derivation, when the EAP client is using
pseudonym.
* WPS:
- Fix nonce comparisons to compare all bytes, not just the first byte.
- Fix NFC password token building with WPS 2.0 to avoid wpabuf
overflow and application abort if NFC out-of-band mechanism is used
with WPS 2.0 enabled.
2013-01-12 - v2.0
* added AP-STA-DISCONNECTED ctrl_iface event
* improved debug logging (human readable event names, interface name
included in more entries)
* added number of small changes to make it easier for static analyzers
to understand the implementation
* added a workaround for Windows 7 Michael MIC failure reporting and
use of the Secure bit in EAPOL-Key msg 3/4
* fixed number of small bugs (see git logs for more details)
* changed OpenSSL to read full certificate chain from server_cert file
* nl80211: number of updates to use new cfg80211/nl80211 functionality
- replace monitor interface with nl80211 commands
- additional information for driver-based AP SME
* EAP-pwd:
- fix KDF for group 21 and zero-padding
- added support for fragmentation
- increased maximum number of hunting-and-pecking iterations
* avoid excessive Probe Response retries for broadcast Probe Request
frames (only with drivers using hostapd SME/MLME)
* added preliminary support for using TLS v1.2 (CONFIG_TLSV12=y)
* fixed WPS operation stopping on dual concurrent AP
* added wps_rf_bands configuration parameter for overriding RF Bands
value for WPS
* added support for getting per-device PSK from RADIUS Tunnel-Password
* added support for libnl 3.2 and newer
* increased initial group key handshake retransmit timeout to 500 ms
* added a workaround for 4-way handshake to update SNonce even after
having sent EAPOL-Key 3/4 to avoid issues with some supplicant
implementations that can change SNonce for each EAP-Key 2/4
* added a workaround for EAPOL-Key 4/4 using incorrect type value in
WPA2 mode (some deployed stations use WPA type in that message)
* added a WPS workaround for mixed mode AP Settings with Windows 7
* changed WPS AP PIN disabling mechanism to disable the PIN after 10
consecutive failures in addition to using the exponential lockout
period
* added support for WFA Hotspot 2.0
- GAS/ANQP advertisement of network information
- disable_dgaf parameter to disable downstream group-addressed
forwarding
* simplified licensing terms by selecting the BSD license as the only
alternative
* EAP-SIM: fixed re-authentication not to update pseudonym
* EAP-SIM: use Notification round before EAP-Failure
* EAP-AKA: added support for AT_COUNTER_TOO_SMALL
* EAP-AKA: skip AKA/Identity exchange if EAP identity is recognized
* EAP-AKA': fixed identity for MK derivation
* EAP-AKA': updated to RFC 5448 (username prefixes changed); note: this
breaks interoperability with older versions
* EAP-SIM/AKA: allow pseudonym to be used after unknown reauth id
* changed ANonce to be a random number instead of Counter-based
* added support for canceling WPS operations with hostapd_cli wps_cancel
* fixed EAP/WPS to PSK transition on reassociation in cases where
deauthentication is missed
* hlr_auc_gw enhancements:
- a new command line parameter -u can be used to enable updating of
SQN in Milenage file
- use 5 bit IND for SQN updates
- SQLite database can now be used to store Milenage information
* EAP-SIM/AKA DB: added optional use of SQLite database for pseudonyms
and reauth data
* added support for Chargeable-User-Identity (RFC 4372)
* added radius_auth_req_attr and radius_acct_req_attr configuration
parameters to allow adding/overriding of RADIUS attributes in
Access-Request and Accounting-Request packets
* added support for RADIUS dynamic authorization server (RFC 5176)
* added initial support for WNM operations
- BSS max idle period
- WNM-Sleep Mode
* added new WPS NFC ctrl_iface mechanism
- removed obsoleted WPS_OOB command (including support for deprecated
UFD config_method)
* added FT support for drivers that implement MLME internally
* added SA Query support for drivers that implement MLME internally
* removed default ACM=1 from AC_VO and AC_VI
* changed VENDOR-TEST EAP method to use proper private enterprise number
(this will not interoperate with older versions)
* added hostapd.conf parameter vendor_elements to allow arbitrary vendor
specific elements to be added to the Beacon and Probe Response frames
* added support for configuring GCMP cipher for IEEE 802.11ad
* added support for 256-bit AES with internal TLS implementation
* changed EAPOL transmission to use AC_VO if WMM is active
* fixed EAP-TLS/PEAP/TTLS/FAST server to validate TLS Message Length
correctly; invalid messages could have caused the hostapd process to
terminate before this fix [CVE-2012-4445]
* limit number of active wildcard PINs for WPS Registrar to one to avoid
confusing behavior with multiple wildcard PINs
* added a workaround for WPS PBC session overlap detection to avoid
interop issues with deployed station implementations that do not
remove active PBC indication from Probe Request frames properly
* added support for using SQLite for the eap_user database
* added Acct-Session-Id attribute into Access-Request messages
* fixed EAPOL frame transmission to non-QoS STAs with nl80211
(do not send QoS frames if the STA did not negotiate use of QoS for
this association)
2012-04-18 - v1.0
2012-05-10 - v1.0
* Add channel selection support in hostapd. See hostapd.conf.
* Add support for IEEE 802.11v Time Advertisement mechanism with UTC
TSF offset. See hostapd.conf for config info.

View File

@ -43,6 +43,7 @@ OBJS += ../src/ap/utils.o
OBJS += ../src/ap/authsrv.o
OBJS += ../src/ap/ieee802_1x.o
OBJS += ../src/ap/ap_config.o
OBJS += ../src/ap/eap_user_db.o
OBJS += ../src/ap/ieee802_11_auth.o
OBJS += ../src/ap/sta_info.o
OBJS += ../src/ap/wpa_auth.o
@ -110,6 +111,7 @@ CONFIG_NO_ACCOUNTING=y
else
OBJS += ../src/radius/radius.o
OBJS += ../src/radius/radius_client.o
OBJS += ../src/radius/radius_das.o
endif
ifdef CONFIG_NO_ACCOUNTING
@ -122,6 +124,12 @@ ifdef CONFIG_NO_VLAN
CFLAGS += -DCONFIG_NO_VLAN
else
OBJS += ../src/ap/vlan_init.o
ifdef CONFIG_VLAN_NETLINK
ifdef CONFIG_FULL_DYNAMIC_VLAN
OBJS += ../src/ap/vlan_util.o
endif
CFLAGS += -DCONFIG_VLAN_NETLINK
endif
endif
ifdef CONFIG_NO_CTRL_IFACE
@ -164,10 +172,23 @@ NEED_AES_OMAC1=y
NEED_AES_UNWRAP=y
endif
ifdef CONFIG_SAE
CFLAGS += -DCONFIG_SAE
endif
ifdef CONFIG_WNM
CFLAGS += -DCONFIG_WNM
OBJS += ../src/ap/wnm_ap.o
endif
ifdef CONFIG_IEEE80211N
CFLAGS += -DCONFIG_IEEE80211N
endif
ifdef CONFIG_IEEE80211AC
CFLAGS += -DCONFIG_IEEE80211AC
endif
include ../src/drivers/drivers.mak
OBJS += $(DRV_AP_OBJS)
CFLAGS += $(DRV_AP_CFLAGS)
@ -203,6 +224,14 @@ OBJS += ../src/eap_server/eap_server_tls.o
TLS_FUNCS=y
endif
ifdef CONFIG_EAP_UNAUTH_TLS
CFLAGS += -DEAP_SERVER_UNAUTH_TLS
ifndef CONFIG_EAP_TLS
OBJS += ../src/eap_server/eap_server_tls.o
TLS_FUNCS=y
endif
endif
ifdef CONFIG_EAP_PEAP
CFLAGS += -DEAP_SERVER_PEAP
OBJS += ../src/eap_server/eap_server_peap.o
@ -329,25 +358,10 @@ NEED_AES_CBC=y
NEED_MODEXP=y
CONFIG_EAP=y
ifdef CONFIG_WPS_UFD
CFLAGS += -DCONFIG_WPS_UFD
OBJS += ../src/wps/wps_ufd.o
NEED_WPS_OOB=y
endif
ifdef CONFIG_WPS_NFC
CFLAGS += -DCONFIG_WPS_NFC
OBJS += ../src/wps/ndef.o
OBJS += ../src/wps/wps_nfc.o
NEED_WPS_OOB=y
ifdef CONFIG_WPS_NFC_PN531
PN531_PATH ?= /usr/local/src/nfc
CFLAGS += -DCONFIG_WPS_NFC_PN531
CFLAGS += -I${PN531_PATH}/inc
OBJS += ../src/wps/wps_nfc_pn531.o
LIBS += ${PN531_PATH}/lib/wpsnfc.dll
LIBS += ${PN531_PATH}/lib/libnfc_mapping_pn53x.dll
endif
endif
ifdef NEED_WPS_OOB
@ -440,6 +454,11 @@ ifdef CONFIG_TLSV11
CFLAGS += -DCONFIG_TLSV11
endif
ifdef CONFIG_TLSV12
CFLAGS += -DCONFIG_TLSV12
NEED_SHA256=y
endif
ifeq ($(CONFIG_TLS), openssl)
ifdef TLS_FUNCS
OBJS += ../src/crypto/tls_openssl.o
@ -519,6 +538,9 @@ OBJS += ../src/tls/pkcs8.o
NEED_SHA256=y
NEED_BASE64=y
NEED_TLS_PRF=y
ifdef CONFIG_TLSV12
NEED_TLS_PRF_SHA256=y
endif
NEED_MODEXP=y
NEED_CIPHER=y
CFLAGS += -DCONFIG_TLS_INTERNAL
@ -632,14 +654,19 @@ OBJS += $(AESOBJS)
endif
ifdef NEED_SHA1
ifneq ($(CONFIG_TLS), openssl)
SHA1OBJS += ../src/crypto/sha1.o
endif
SHA1OBJS += ../src/crypto/sha1-prf.o
ifdef CONFIG_INTERNAL_SHA1
SHA1OBJS += ../src/crypto/sha1-internal.o
ifdef NEED_FIPS186_2_PRF
SHA1OBJS += ../src/crypto/fips_prf_internal.o
endif
endif
ifneq ($(CONFIG_TLS), openssl)
SHA1OBJS += ../src/crypto/sha1-pbkdf2.o
endif
ifdef NEED_T_PRF
SHA1OBJS += ../src/crypto/sha1-tprf.o
endif
@ -678,10 +705,17 @@ endif
endif
ifdef NEED_SHA256
CFLAGS += -DCONFIG_SHA256
ifneq ($(CONFIG_TLS), openssl)
OBJS += ../src/crypto/sha256.o
endif
OBJS += ../src/crypto/sha256-prf.o
ifdef CONFIG_INTERNAL_SHA256
OBJS += ../src/crypto/sha256-internal.o
endif
ifdef NEED_TLS_PRF_SHA256
OBJS += ../src/crypto/sha256-tlsprf.o
endif
endif
ifdef NEED_DH_GROUPS
@ -740,13 +774,25 @@ ifdef CONFIG_IEEE80211N
OBJS += ../src/ap/ieee802_11_ht.o
endif
ifdef CONFIG_IEEE80211AC
OBJS += ../src/ap/ieee802_11_vht.o
endif
ifdef CONFIG_P2P_MANAGER
CFLAGS += -DCONFIG_P2P_MANAGER
OBJS += ../src/ap/p2p_hostapd.o
endif
ifdef CONFIG_HS20
CFLAGS += -DCONFIG_HS20
OBJS += ../src/ap/hs20.o
CONFIG_INTERWORKING=y
endif
ifdef CONFIG_INTERWORKING
CFLAGS += -DCONFIG_INTERWORKING
OBJS += ../src/common/gas.o
OBJS += ../src/ap/gas_serv.o
endif
OBJS += ../src/drivers/driver_common.o
@ -765,6 +811,12 @@ ifdef CONFIG_DEBUG_FILE
CFLAGS += -DCONFIG_DEBUG_FILE
endif
ifdef CONFIG_SQLITE
CFLAGS += -DCONFIG_SQLITE
LIBS += -lsqlite3
LIBS_h += -lsqlite3
endif
ALL=hostapd hostapd_cli
all: verify_config $(ALL)

View File

@ -5,34 +5,19 @@ hostapd - user space IEEE 802.11 AP and IEEE 802.1X/WPA/WPA2/EAP
Copyright (c) 2002-2012, Jouni Malinen <j@w1.fi> and contributors
All Rights Reserved.
This program is dual-licensed under both the GPL version 2 and BSD
license. Either license may be used at your option.
This program is licensed under the BSD license (the one with
advertisement clause removed).
If you are submitting changes to the project, please see CONTRIBUTIONS
file for more instructions.
License
-------
GPL v2:
This program is free software; you can redistribute it and/or modify
it under the terms of the GNU General Public License version 2 as
published by the Free Software Foundation.
This program is distributed in the hope that it will be useful,
but WITHOUT ANY WARRANTY; without even the implied warranty of
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
GNU General Public License for more details.
You should have received a copy of the GNU General Public License
along with this program; if not, write to the Free Software
Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA
(this copy of the license is in COPYING file)
Alternatively, this software may be distributed, used, and modified
under the terms of BSD license:
This software may be distributed, used, and modified under the terms of
BSD license:
Redistribution and use in source and binary forms, with or without
modification, are permitted provided that the following conditions are

View File

@ -66,6 +66,10 @@ CONFIG_WPS=y
CONFIG_WPS2=y
CONFIG_WPS_UPNP=y
Following parameter can be used to enable support for NFC config method:
CONFIG_WPS_NFC=y
Following section shows an example runtime configuration
(hostapd.conf) that enables WPS:
@ -289,3 +293,48 @@ For example:
This can be used to update the externally stored AP configuration and
then update hostapd configuration (followed by restarting of hostapd).
WPS with NFC
------------
WPS can be used with NFC-based configuration method. An NFC tag
containing a password token from the Enrollee can be used to
authenticate the connection instead of the PIN. In addition, an NFC tag
with a configuration token can be used to transfer AP settings without
going through the WPS protocol.
When the AP acts as an Enrollee, a local NFC tag with a password token
can be used by touching the NFC interface of an external Registrar. The
wps_nfc_token command is used to manage use of the NFC password token
from the AP. "wps_nfc_token enable" enables the use of the AP's NFC
password token (in place of AP PIN) and "wps_nfc_token disable" disables
the NFC password token.
The NFC password token that is either pre-configured in the
configuration file (wps_nfc_dev_pw_id, wps_nfc_dh_pubkey,
wps_nfc_dh_privkey, wps_nfc_dev_pw) or generated dynamically with
"wps_nfc_token <WPS|NDEF>" command. The nfc_pw_token tool from
wpa_supplicant can be used to generate NFC password tokens during
manufacturing (each AP needs to have its own random keys).
The "wps_nfc_config_token <WPS/NDEF>" command can be used to build an
NFC configuration token. The output value from this command is a hexdump
of the current AP configuration (WPS parameter requests this to include
only the WPS attributes; NDEF parameter requests additional NDEF
encapsulation to be included). This data needs to be written to an NFC
tag with an external program. Once written, the NFC configuration token
can be used to touch an NFC interface on a station to provision the
credentials needed to access the network.
When the NFC device on the AP reads an NFC tag with a MIME media type
"application/vnd.wfa.wsc", the NDEF message payload (with or without
NDEF encapsulation) can be delivered to hostapd using the
following hostapd_cli command:
wps_nfc_tag_read <hexdump of payload>
If the NFC tag contains a password token, the token is added to the
internal Registrar. This allows station Enrollee from which the password
token was received to run through WPS protocol to provision the
credential.

View File

@ -0,0 +1,190 @@
# Example hostapd build time configuration
#
# This file lists the configuration options that are used when building the
# hostapd binary. All lines starting with # are ignored. Configuration option
# lines must be commented out complete, if they are not to be included, i.e.,
# just setting VARIABLE=n is not disabling that variable.
#
# This file is included in Makefile, so variables like CFLAGS and LIBS can also
# be modified from here. In most cass, these lines should use += in order not
# to override previous values of the variables.
# Driver interface for Host AP driver
#CONFIG_DRIVER_HOSTAP=y
# Driver interface for wired authenticator
#CONFIG_DRIVER_WIRED=y
# Driver interface for madwifi driver
#CONFIG_DRIVER_MADWIFI=y
#CFLAGS += -I../../madwifi # change to the madwifi source directory
# Driver interface for drivers using the nl80211 kernel interface
#CONFIG_DRIVER_NL80211=y
# driver_nl80211.c requires a rather new libnl (version 1.1) which may not be
# shipped with your distribution yet. If that is the case, you need to build
# newer libnl version and point the hostapd build to use it.
#LIBNL=/usr/src/libnl
#CFLAGS += -I$(LIBNL)/include
#LIBS += -L$(LIBNL)/lib
CONFIG_LIBNL20=y
# Driver interface for FreeBSD net80211 layer (e.g., Atheros driver)
#CONFIG_DRIVER_BSD=y
#CFLAGS += -I/usr/local/include
#LIBS += -L/usr/local/lib
#LIBS_p += -L/usr/local/lib
#LIBS_c += -L/usr/local/lib
# Driver interface for no driver (e.g., RADIUS server only)
#CONFIG_DRIVER_NONE=y
# IEEE 802.11F/IAPP
#CONFIG_IAPP=y
# WPA2/IEEE 802.11i RSN pre-authentication
#CONFIG_RSN_PREAUTH=y
# PeerKey handshake for Station to Station Link (IEEE 802.11e DLS)
#CONFIG_PEERKEY=y
# IEEE 802.11w (management frame protection)
# This version is an experimental implementation based on IEEE 802.11w/D1.0
# draft and is subject to change since the standard has not yet been finalized.
# Driver support is also needed for IEEE 802.11w.
#CONFIG_IEEE80211W=y
# Integrated EAP server
#CONFIG_EAP=y
# EAP-MD5 for the integrated EAP server
#CONFIG_EAP_MD5=y
# EAP-TLS for the integrated EAP server
#CONFIG_EAP_TLS=y
# EAP-MSCHAPv2 for the integrated EAP server
#CONFIG_EAP_MSCHAPV2=y
# EAP-PEAP for the integrated EAP server
#CONFIG_EAP_PEAP=y
# EAP-GTC for the integrated EAP server
#CONFIG_EAP_GTC=y
# EAP-TTLS for the integrated EAP server
#CONFIG_EAP_TTLS=y
# EAP-SIM for the integrated EAP server
#CONFIG_EAP_SIM=y
# EAP-AKA for the integrated EAP server
#CONFIG_EAP_AKA=y
# EAP-AKA' for the integrated EAP server
# This requires CONFIG_EAP_AKA to be enabled, too.
#CONFIG_EAP_AKA_PRIME=y
# EAP-PAX for the integrated EAP server
#CONFIG_EAP_PAX=y
# EAP-PSK for the integrated EAP server (this is _not_ needed for WPA-PSK)
#CONFIG_EAP_PSK=y
# EAP-SAKE for the integrated EAP server
#CONFIG_EAP_SAKE=y
# EAP-GPSK for the integrated EAP server
#CONFIG_EAP_GPSK=y
# Include support for optional SHA256 cipher suite in EAP-GPSK
#CONFIG_EAP_GPSK_SHA256=y
# EAP-FAST for the integrated EAP server
# Note: Default OpenSSL package does not include support for all the
# functionality needed for EAP-FAST. If EAP-FAST is enabled with OpenSSL,
# the OpenSSL library must be patched (openssl-0.9.9-session-ticket.patch)
# to add the needed functions.
#CONFIG_EAP_FAST=y
# Wi-Fi Protected Setup (WPS)
CONFIG_WPS=y
# Enable WSC 2.0 support
CONFIG_WPS2=y
# Enable UPnP support for external WPS Registrars
#CONFIG_WPS_UPNP=y
# EAP-IKEv2
#CONFIG_EAP_IKEV2=y
# Trusted Network Connect (EAP-TNC)
#CONFIG_EAP_TNC=y
# PKCS#12 (PFX) support (used to read private key and certificate file from
# a file that usually has extension .p12 or .pfx)
CONFIG_PKCS12=y
# RADIUS authentication server. This provides access to the integrated EAP
# server from external hosts using RADIUS.
#CONFIG_RADIUS_SERVER=y
# Build IPv6 support for RADIUS operations
CONFIG_IPV6=y
# IEEE Std 802.11r-2008 (Fast BSS Transition)
#CONFIG_IEEE80211R=y
# Use the hostapd's IEEE 802.11 authentication (ACL), but without
# the IEEE 802.11 Management capability (e.g., madwifi or FreeBSD/net80211)
#CONFIG_DRIVER_RADIUS_ACL=y
# IEEE 802.11n (High Throughput) support
CONFIG_IEEE80211N=y
# Remove debugging code that is printing out debug messages to stdout.
# This can be used to reduce the size of the hostapd considerably if debugging
# code is not needed.
#CONFIG_NO_STDOUT_DEBUG=y
# Add support for writing debug log to Android logcat instead of standard output
CONFIG_ANDROID_LOG=y
# Remove support for RADIUS accounting
#CONFIG_NO_ACCOUNTING=y
# Remove support for RADIUS
CONFIG_NO_RADIUS=y
# Remove support for VLANs
#CONFIG_NO_VLAN=y
# Remove support for dumping state into a file on SIGUSR1 signal
# This can be used to reduce binary size at the cost of disabling a debugging
# option.
#CONFIG_NO_DUMP_STATE=y
# Select wrapper for operatins system and C library specific functions
# unix = UNIX/POSIX like systems (default)
# win32 = Windows systems
# none = Empty template
CONFIG_OS=unix
# Enable tracing code for developer debugging
# This tracks use of memory allocations and other registrations and reports
# incorrect use with a backtrace of call (or allocation) location.
#CONFIG_WPA_TRACE=y
# For BSD, comment out these.
#LIBS += -lexecinfo
#LIBS_p += -lexecinfo
#LIBS_c += -lexecinfo
# Use libbfd to get more details for developer debugging
# This enables use of libbfd to get more detailed symbols for the backtraces
# generated by CONFIG_WPA_TRACE=y.
#CONFIG_WPA_TRACE_BFD=y
# For BSD, comment out these.
#LIBS += -lbfd -liberty -lz
#LIBS_p += -lbfd -liberty -lz
#LIBS_c += -lbfd -liberty -lz
# Enable AP
CONFIG_AP=y

File diff suppressed because it is too large Load Diff

View File

@ -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 */

View File

@ -1,15 +1,9 @@
/*
* hostapd / UNIX domain socket -based control interface
* Copyright (c) 2004-2010, Jouni Malinen <j@w1.fi>
* Copyright (c) 2004-2012, Jouni Malinen <j@w1.fi>
*
* This program is free software; you can redistribute it and/or modify
* it under the terms of the GNU General Public License version 2 as
* published by the Free Software Foundation.
*
* Alternatively, this software may be distributed under the terms of BSD
* license.
*
* See README and COPYING for more details.
* This software may be distributed under the terms of the BSD license.
* See README for more details.
*/
#include "utils/includes.h"
@ -32,12 +26,12 @@
#include "ap/wpa_auth.h"
#include "ap/ieee802_11.h"
#include "ap/sta_info.h"
#include "ap/accounting.h"
#include "ap/wps_hostapd.h"
#include "ap/ctrl_iface_ap.h"
#include "ap/ap_drv_ops.h"
#include "wps/wps_defs.h"
#include "wps/wps.h"
#include "config_file.h"
#include "ctrl_iface.h"
@ -159,171 +153,6 @@ static int hostapd_ctrl_iface_new_sta(struct hostapd_data *hapd,
}
#ifdef CONFIG_P2P_MANAGER
static int p2p_manager_disconnect(struct hostapd_data *hapd, u16 stype,
u8 minor_reason_code, const u8 *addr)
{
struct ieee80211_mgmt *mgmt;
int ret;
u8 *pos;
if (hapd->driver->send_frame == NULL)
return -1;
mgmt = os_zalloc(sizeof(*mgmt) + 100);
if (mgmt == NULL)
return -1;
wpa_printf(MSG_DEBUG, "P2P: Disconnect STA " MACSTR " with minor "
"reason code %u (stype=%u)",
MAC2STR(addr), minor_reason_code, stype);
mgmt->frame_control = IEEE80211_FC(WLAN_FC_TYPE_MGMT, stype);
os_memcpy(mgmt->da, addr, ETH_ALEN);
os_memcpy(mgmt->sa, hapd->own_addr, ETH_ALEN);
os_memcpy(mgmt->bssid, hapd->own_addr, ETH_ALEN);
if (stype == WLAN_FC_STYPE_DEAUTH) {
mgmt->u.deauth.reason_code =
host_to_le16(WLAN_REASON_PREV_AUTH_NOT_VALID);
pos = (u8 *) (&mgmt->u.deauth.reason_code + 1);
} else {
mgmt->u.disassoc.reason_code =
host_to_le16(WLAN_REASON_PREV_AUTH_NOT_VALID);
pos = (u8 *) (&mgmt->u.disassoc.reason_code + 1);
}
*pos++ = WLAN_EID_VENDOR_SPECIFIC;
*pos++ = 4 + 3 + 1;
WPA_PUT_BE24(pos, OUI_WFA);
pos += 3;
*pos++ = P2P_OUI_TYPE;
*pos++ = P2P_ATTR_MINOR_REASON_CODE;
WPA_PUT_LE16(pos, 1);
pos += 2;
*pos++ = minor_reason_code;
ret = hapd->driver->send_frame(hapd->drv_priv, (u8 *) mgmt,
pos - (u8 *) mgmt, 1);
os_free(mgmt);
return ret < 0 ? -1 : 0;
}
#endif /* CONFIG_P2P_MANAGER */
static int hostapd_ctrl_iface_deauthenticate(struct hostapd_data *hapd,
const char *txtaddr)
{
u8 addr[ETH_ALEN];
struct sta_info *sta;
const char *pos;
wpa_printf(MSG_DEBUG, "CTRL_IFACE DEAUTHENTICATE %s", txtaddr);
if (hwaddr_aton(txtaddr, addr))
return -1;
pos = os_strstr(txtaddr, " test=");
if (pos) {
struct ieee80211_mgmt mgmt;
int encrypt;
if (hapd->driver->send_frame == NULL)
return -1;
pos += 6;
encrypt = atoi(pos);
os_memset(&mgmt, 0, sizeof(mgmt));
mgmt.frame_control = IEEE80211_FC(WLAN_FC_TYPE_MGMT,
WLAN_FC_STYPE_DEAUTH);
os_memcpy(mgmt.da, addr, ETH_ALEN);
os_memcpy(mgmt.sa, hapd->own_addr, ETH_ALEN);
os_memcpy(mgmt.bssid, hapd->own_addr, ETH_ALEN);
mgmt.u.deauth.reason_code =
host_to_le16(WLAN_REASON_PREV_AUTH_NOT_VALID);
if (hapd->driver->send_frame(hapd->drv_priv, (u8 *) &mgmt,
IEEE80211_HDRLEN +
sizeof(mgmt.u.deauth),
encrypt) < 0)
return -1;
return 0;
}
#ifdef CONFIG_P2P_MANAGER
pos = os_strstr(txtaddr, " p2p=");
if (pos) {
return p2p_manager_disconnect(hapd, WLAN_FC_STYPE_DEAUTH,
atoi(pos + 5), addr);
}
#endif /* CONFIG_P2P_MANAGER */
hostapd_drv_sta_deauth(hapd, addr, WLAN_REASON_PREV_AUTH_NOT_VALID);
sta = ap_get_sta(hapd, addr);
if (sta)
ap_sta_deauthenticate(hapd, sta,
WLAN_REASON_PREV_AUTH_NOT_VALID);
else if (addr[0] == 0xff)
hostapd_free_stas(hapd);
return 0;
}
static int hostapd_ctrl_iface_disassociate(struct hostapd_data *hapd,
const char *txtaddr)
{
u8 addr[ETH_ALEN];
struct sta_info *sta;
const char *pos;
wpa_printf(MSG_DEBUG, "CTRL_IFACE DISASSOCIATE %s", txtaddr);
if (hwaddr_aton(txtaddr, addr))
return -1;
pos = os_strstr(txtaddr, " test=");
if (pos) {
struct ieee80211_mgmt mgmt;
int encrypt;
if (hapd->driver->send_frame == NULL)
return -1;
pos += 6;
encrypt = atoi(pos);
os_memset(&mgmt, 0, sizeof(mgmt));
mgmt.frame_control = IEEE80211_FC(WLAN_FC_TYPE_MGMT,
WLAN_FC_STYPE_DISASSOC);
os_memcpy(mgmt.da, addr, ETH_ALEN);
os_memcpy(mgmt.sa, hapd->own_addr, ETH_ALEN);
os_memcpy(mgmt.bssid, hapd->own_addr, ETH_ALEN);
mgmt.u.disassoc.reason_code =
host_to_le16(WLAN_REASON_PREV_AUTH_NOT_VALID);
if (hapd->driver->send_frame(hapd->drv_priv, (u8 *) &mgmt,
IEEE80211_HDRLEN +
sizeof(mgmt.u.deauth),
encrypt) < 0)
return -1;
return 0;
}
#ifdef CONFIG_P2P_MANAGER
pos = os_strstr(txtaddr, " p2p=");
if (pos) {
return p2p_manager_disconnect(hapd, WLAN_FC_STYPE_DISASSOC,
atoi(pos + 5), addr);
}
#endif /* CONFIG_P2P_MANAGER */
hostapd_drv_sta_disassoc(hapd, addr, WLAN_REASON_PREV_AUTH_NOT_VALID);
sta = ap_get_sta(hapd, addr);
if (sta)
ap_sta_disassociate(hapd, sta,
WLAN_REASON_PREV_AUTH_NOT_VALID);
else if (addr[0] == 0xff)
hostapd_free_stas(hapd);
return 0;
}
#ifdef CONFIG_IEEE80211W
#ifdef NEED_AP_MLME
static int hostapd_ctrl_iface_sa_query(struct hostapd_data *hapd,
@ -421,28 +250,109 @@ static int hostapd_ctrl_iface_wps_check_pin(
}
#ifdef CONFIG_WPS_OOB
static int hostapd_ctrl_iface_wps_oob(struct hostapd_data *hapd, char *txt)
#ifdef CONFIG_WPS_NFC
static int hostapd_ctrl_iface_wps_nfc_tag_read(struct hostapd_data *hapd,
char *pos)
{
char *path, *method, *name;
size_t len;
struct wpabuf *buf;
int ret;
path = os_strchr(txt, ' ');
if (path == NULL)
len = os_strlen(pos);
if (len & 0x01)
return -1;
*path++ = '\0';
len /= 2;
method = os_strchr(path, ' ');
if (method == NULL)
buf = wpabuf_alloc(len);
if (buf == NULL)
return -1;
*method++ = '\0';
if (hexstr2bin(pos, wpabuf_put(buf, len), len) < 0) {
wpabuf_free(buf);
return -1;
}
name = os_strchr(method, ' ');
if (name != NULL)
*name++ = '\0';
ret = hostapd_wps_nfc_tag_read(hapd, buf);
wpabuf_free(buf);
return hostapd_wps_start_oob(hapd, txt, path, method, name);
return ret;
}
#endif /* CONFIG_WPS_OOB */
static int hostapd_ctrl_iface_wps_nfc_config_token(struct hostapd_data *hapd,
char *cmd, char *reply,
size_t max_len)
{
int ndef;
struct wpabuf *buf;
int res;
if (os_strcmp(cmd, "WPS") == 0)
ndef = 0;
else if (os_strcmp(cmd, "NDEF") == 0)
ndef = 1;
else
return -1;
buf = hostapd_wps_nfc_config_token(hapd, ndef);
if (buf == NULL)
return -1;
res = wpa_snprintf_hex_uppercase(reply, max_len, wpabuf_head(buf),
wpabuf_len(buf));
reply[res++] = '\n';
reply[res] = '\0';
wpabuf_free(buf);
return res;
}
static int hostapd_ctrl_iface_wps_nfc_token_gen(struct hostapd_data *hapd,
char *reply, size_t max_len,
int ndef)
{
struct wpabuf *buf;
int res;
buf = hostapd_wps_nfc_token_gen(hapd, ndef);
if (buf == NULL)
return -1;
res = wpa_snprintf_hex_uppercase(reply, max_len, wpabuf_head(buf),
wpabuf_len(buf));
reply[res++] = '\n';
reply[res] = '\0';
wpabuf_free(buf);
return res;
}
static int hostapd_ctrl_iface_wps_nfc_token(struct hostapd_data *hapd,
char *cmd, char *reply,
size_t max_len)
{
if (os_strcmp(cmd, "WPS") == 0)
return hostapd_ctrl_iface_wps_nfc_token_gen(hapd, reply,
max_len, 0);
if (os_strcmp(cmd, "NDEF") == 0)
return hostapd_ctrl_iface_wps_nfc_token_gen(hapd, reply,
max_len, 1);
if (os_strcmp(cmd, "enable") == 0)
return hostapd_wps_nfc_token_enable(hapd);
if (os_strcmp(cmd, "disable") == 0) {
hostapd_wps_nfc_token_disable(hapd);
return 0;
}
return -1;
}
#endif /* CONFIG_WPS_NFC */
static int hostapd_ctrl_iface_wps_ap_pin(struct hostapd_data *hapd, char *txt,
@ -526,6 +436,50 @@ static int hostapd_ctrl_iface_wps_config(struct hostapd_data *hapd, char *txt)
#endif /* CONFIG_WPS */
#ifdef CONFIG_WNM
static int hostapd_ctrl_iface_disassoc_imminent(struct hostapd_data *hapd,
const char *cmd)
{
u8 addr[ETH_ALEN];
u8 buf[1000], *pos;
struct ieee80211_mgmt *mgmt;
int disassoc_timer;
if (hwaddr_aton(cmd, addr))
return -1;
if (cmd[17] != ' ')
return -1;
disassoc_timer = atoi(cmd + 17);
os_memset(buf, 0, sizeof(buf));
mgmt = (struct ieee80211_mgmt *) buf;
mgmt->frame_control = IEEE80211_FC(WLAN_FC_TYPE_MGMT,
WLAN_FC_STYPE_ACTION);
os_memcpy(mgmt->da, addr, ETH_ALEN);
os_memcpy(mgmt->sa, hapd->own_addr, ETH_ALEN);
os_memcpy(mgmt->bssid, hapd->own_addr, ETH_ALEN);
mgmt->u.action.category = WLAN_ACTION_WNM;
mgmt->u.action.u.bss_tm_req.action = WNM_BSS_TRANS_MGMT_REQ;
mgmt->u.action.u.bss_tm_req.dialog_token = 1;
mgmt->u.action.u.bss_tm_req.req_mode =
WNM_BSS_TM_REQ_DISASSOC_IMMINENT;
mgmt->u.action.u.bss_tm_req.disassoc_timer =
host_to_le16(disassoc_timer);
mgmt->u.action.u.bss_tm_req.validity_interval = 0;
pos = mgmt->u.action.u.bss_tm_req.variable;
if (hostapd_drv_send_mlme(hapd, buf, pos - buf, 0) < 0) {
wpa_printf(MSG_DEBUG, "Failed to send BSS Transition "
"Management Request frame");
return -1;
}
return 0;
}
static int hostapd_ctrl_iface_ess_disassoc(struct hostapd_data *hapd,
const char *cmd)
{
@ -567,7 +521,7 @@ static int hostapd_ctrl_iface_ess_disassoc(struct hostapd_data *hapd,
os_memcpy(pos, url, url_len);
pos += url_len;
if (hostapd_drv_send_mlme(hapd, buf, pos - buf) < 0) {
if (hostapd_drv_send_mlme(hapd, buf, pos - buf, 0) < 0) {
wpa_printf(MSG_DEBUG, "Failed to send BSS Transition "
"Management Request frame");
return -1;
@ -576,6 +530,8 @@ static int hostapd_ctrl_iface_ess_disassoc(struct hostapd_data *hapd,
return 0;
}
#endif /* CONFIG_WNM */
static int hostapd_ctrl_iface_get_config(struct hostapd_data *hapd,
char *buf, size_t buflen)
@ -589,7 +545,8 @@ static int hostapd_ctrl_iface_get_config(struct hostapd_data *hapd,
ret = os_snprintf(pos, end - pos, "bssid=" MACSTR "\n"
"ssid=%s\n",
MAC2STR(hapd->own_addr),
hapd->conf->ssid.ssid);
wpa_ssid_txt(hapd->conf->ssid.ssid,
hapd->conf->ssid.ssid_len));
if (ret < 0 || ret >= end - pos)
return pos - buf;
pos += ret;
@ -683,6 +640,12 @@ static int hostapd_ctrl_iface_get_config(struct hostapd_data *hapd,
if (ret < 0 || ret >= end - pos)
return pos - buf;
pos += ret;
} else if (hapd->conf->wpa &&
hapd->conf->wpa_group == WPA_CIPHER_GCMP) {
ret = os_snprintf(pos, end - pos, "group_cipher=GCMP\n");
if (ret < 0 || ret >= end - pos)
return pos - buf;
pos += ret;
} else if (hapd->conf->wpa &&
hapd->conf->wpa_group == WPA_CIPHER_TKIP) {
ret = os_snprintf(pos, end - pos, "group_cipher=TKIP\n");
@ -703,6 +666,12 @@ static int hostapd_ctrl_iface_get_config(struct hostapd_data *hapd,
return pos - buf;
pos += ret;
}
if (hapd->conf->rsn_pairwise & WPA_CIPHER_GCMP) {
ret = os_snprintf(pos, end - pos, "GCMP ");
if (ret < 0 || ret >= end - pos)
return pos - buf;
pos += ret;
}
if (hapd->conf->rsn_pairwise & WPA_CIPHER_TKIP) {
ret = os_snprintf(pos, end - pos, "TKIP ");
if (ret < 0 || ret >= end - pos)
@ -728,6 +697,12 @@ static int hostapd_ctrl_iface_get_config(struct hostapd_data *hapd,
return pos - buf;
pos += ret;
}
if (hapd->conf->wpa_pairwise & WPA_CIPHER_GCMP) {
ret = os_snprintf(pos, end - pos, "GCMP ");
if (ret < 0 || ret >= end - pos)
return pos - buf;
pos += ret;
}
if (hapd->conf->wpa_pairwise & WPA_CIPHER_TKIP) {
ret = os_snprintf(pos, end - pos, "TKIP ");
if (ret < 0 || ret >= end - pos)
@ -778,8 +753,16 @@ static int hostapd_ctrl_iface_set(struct hostapd_data *hapd, char *cmd)
wpa_printf(MSG_DEBUG, "WPS: Testing - dummy_cred=%d",
wps_testing_dummy_cred);
#endif /* CONFIG_WPS_TESTING */
#ifdef CONFIG_INTERWORKING
} else if (os_strcasecmp(cmd, "gas_frag_limit") == 0) {
int val = atoi(value);
if (val <= 0)
ret = -1;
else
hapd->gas_frag_limit = val;
#endif /* CONFIG_INTERWORKING */
} else {
ret = -1;
ret = hostapd_set_iface(hapd->iconf, hapd->conf, cmd, value);
}
return ret;
@ -804,6 +787,36 @@ static int hostapd_ctrl_iface_get(struct hostapd_data *hapd, char *cmd,
}
static int hostapd_ctrl_iface_enable(struct hostapd_iface *iface)
{
if (hostapd_enable_iface(iface) < 0) {
wpa_printf(MSG_ERROR, "Enabling of interface failed");
return -1;
}
return 0;
}
static int hostapd_ctrl_iface_reload(struct hostapd_iface *iface)
{
if (hostapd_reload_iface(iface) < 0) {
wpa_printf(MSG_ERROR, "Reloading of interface failed");
return -1;
}
return 0;
}
static int hostapd_ctrl_iface_disable(struct hostapd_iface *iface)
{
if (hostapd_disable_iface(iface) < 0) {
wpa_printf(MSG_ERROR, "Disabling of interface failed");
return -1;
}
return 0;
}
static void hostapd_ctrl_iface_receive(int sock, void *eloop_ctx,
void *sock_ctx)
{
@ -918,21 +931,35 @@ static void hostapd_ctrl_iface_receive(int sock, void *eloop_ctx,
} else if (os_strcmp(buf, "WPS_PBC") == 0) {
if (hostapd_wps_button_pushed(hapd, NULL))
reply_len = -1;
#ifdef CONFIG_WPS_OOB
} else if (os_strncmp(buf, "WPS_OOB ", 8) == 0) {
if (hostapd_ctrl_iface_wps_oob(hapd, buf + 8))
} else if (os_strcmp(buf, "WPS_CANCEL") == 0) {
if (hostapd_wps_cancel(hapd))
reply_len = -1;
#endif /* CONFIG_WPS_OOB */
} else if (os_strncmp(buf, "WPS_AP_PIN ", 11) == 0) {
reply_len = hostapd_ctrl_iface_wps_ap_pin(hapd, buf + 11,
reply, reply_size);
} else if (os_strncmp(buf, "WPS_CONFIG ", 11) == 0) {
if (hostapd_ctrl_iface_wps_config(hapd, buf + 11) < 0)
reply_len = -1;
#ifdef CONFIG_WPS_NFC
} else if (os_strncmp(buf, "WPS_NFC_TAG_READ ", 17) == 0) {
if (hostapd_ctrl_iface_wps_nfc_tag_read(hapd, buf + 17))
reply_len = -1;
} else if (os_strncmp(buf, "WPS_NFC_CONFIG_TOKEN ", 21) == 0) {
reply_len = hostapd_ctrl_iface_wps_nfc_config_token(
hapd, buf + 21, reply, reply_size);
} else if (os_strncmp(buf, "WPS_NFC_TOKEN ", 14) == 0) {
reply_len = hostapd_ctrl_iface_wps_nfc_token(
hapd, buf + 14, reply, reply_size);
#endif /* CONFIG_WPS_NFC */
#endif /* CONFIG_WPS */
#ifdef CONFIG_WNM
} else if (os_strncmp(buf, "DISASSOC_IMMINENT ", 18) == 0) {
if (hostapd_ctrl_iface_disassoc_imminent(hapd, buf + 18))
reply_len = -1;
} else if (os_strncmp(buf, "ESS_DISASSOC ", 13) == 0) {
if (hostapd_ctrl_iface_ess_disassoc(hapd, buf + 13))
reply_len = -1;
#endif /* CONFIG_WNM */
} else if (os_strcmp(buf, "GET_CONFIG") == 0) {
reply_len = hostapd_ctrl_iface_get_config(hapd, reply,
reply_size);
@ -942,6 +969,15 @@ static void hostapd_ctrl_iface_receive(int sock, void *eloop_ctx,
} else if (os_strncmp(buf, "GET ", 4) == 0) {
reply_len = hostapd_ctrl_iface_get(hapd, buf + 4, reply,
reply_size);
} else if (os_strncmp(buf, "ENABLE", 6) == 0) {
if (hostapd_ctrl_iface_enable(hapd->iface))
reply_len = -1;
} else if (os_strncmp(buf, "RELOAD", 6) == 0) {
if (hostapd_ctrl_iface_reload(hapd->iface))
reply_len = -1;
} else if (os_strncmp(buf, "DISABLE", 7) == 0) {
if (hostapd_ctrl_iface_disable(hapd->iface))
reply_len = -1;
} else {
os_memcpy(reply, "UNKNOWN COMMAND\n", 16);
reply_len = 16;
@ -993,7 +1029,10 @@ int hostapd_ctrl_iface_init(struct hostapd_data *hapd)
int s = -1;
char *fname = NULL;
hapd->ctrl_sock = -1;
if (hapd->ctrl_sock > -1) {
wpa_printf(MSG_DEBUG, "ctrl_iface already exists!");
return 0;
}
if (hapd->conf->ctrl_interface == NULL)
return 0;
@ -1009,12 +1048,27 @@ int hostapd_ctrl_iface_init(struct hostapd_data *hapd)
}
if (hapd->conf->ctrl_interface_gid_set &&
chown(hapd->conf->ctrl_interface, 0,
chown(hapd->conf->ctrl_interface, -1,
hapd->conf->ctrl_interface_gid) < 0) {
perror("chown[ctrl_interface]");
return -1;
}
#ifdef ANDROID
/*
* Android is using umask 0077 which would leave the control interface
* directory without group access. This breaks things since Wi-Fi
* framework assumes that this directory can be accessed by other
* applications in the wifi group. Fix this by adding group access even
* if umask value would prevent this.
*/
if (chmod(hapd->conf->ctrl_interface, S_IRWXU | S_IRWXG) < 0) {
wpa_printf(MSG_ERROR, "CTRL: Could not chmod directory: %s",
strerror(errno));
/* Try to continue anyway */
}
#endif /* ANDROID */
if (os_strlen(hapd->conf->ctrl_interface) + 1 +
os_strlen(hapd->conf->iface) >= sizeof(addr.sun_path))
goto fail;
@ -1050,7 +1104,7 @@ int hostapd_ctrl_iface_init(struct hostapd_data *hapd)
}
if (bind(s, (struct sockaddr *) &addr, sizeof(addr)) <
0) {
perror("bind(PF_UNIX)");
perror("hostapd-ctrl-iface: bind(PF_UNIX)");
goto fail;
}
wpa_printf(MSG_DEBUG, "Successfully replaced leftover "
@ -1067,7 +1121,7 @@ int hostapd_ctrl_iface_init(struct hostapd_data *hapd)
}
if (hapd->conf->ctrl_interface_gid_set &&
chown(fname, 0, hapd->conf->ctrl_interface_gid) < 0) {
chown(fname, -1, hapd->conf->ctrl_interface_gid) < 0) {
perror("chown[ctrl_interface/ifname]");
goto fail;
}
@ -1132,6 +1186,220 @@ void hostapd_ctrl_iface_deinit(struct hostapd_data *hapd)
}
static int hostapd_ctrl_iface_add(struct hapd_interfaces *interfaces,
char *buf)
{
if (hostapd_add_iface(interfaces, buf) < 0) {
wpa_printf(MSG_ERROR, "Adding interface %s failed", buf);
return -1;
}
return 0;
}
static int hostapd_ctrl_iface_remove(struct hapd_interfaces *interfaces,
char *buf)
{
if (hostapd_remove_iface(interfaces, buf) < 0) {
wpa_printf(MSG_ERROR, "Removing interface %s failed", buf);
return -1;
}
return 0;
}
static void hostapd_global_ctrl_iface_receive(int sock, void *eloop_ctx,
void *sock_ctx)
{
void *interfaces = eloop_ctx;
char buf[256];
int res;
struct sockaddr_un from;
socklen_t fromlen = sizeof(from);
char reply[24];
int reply_len;
res = recvfrom(sock, buf, sizeof(buf) - 1, 0,
(struct sockaddr *) &from, &fromlen);
if (res < 0) {
perror("recvfrom(ctrl_iface)");
return;
}
buf[res] = '\0';
os_memcpy(reply, "OK\n", 3);
reply_len = 3;
if (os_strcmp(buf, "PING") == 0) {
os_memcpy(reply, "PONG\n", 5);
reply_len = 5;
} else if (os_strncmp(buf, "ADD ", 4) == 0) {
if (hostapd_ctrl_iface_add(interfaces, buf + 4) < 0)
reply_len = -1;
} else if (os_strncmp(buf, "REMOVE ", 7) == 0) {
if (hostapd_ctrl_iface_remove(interfaces, buf + 7) < 0)
reply_len = -1;
} else {
wpa_printf(MSG_DEBUG, "Unrecognized global ctrl_iface command "
"ignored");
reply_len = -1;
}
if (reply_len < 0) {
os_memcpy(reply, "FAIL\n", 5);
reply_len = 5;
}
sendto(sock, reply, reply_len, 0, (struct sockaddr *) &from, fromlen);
}
static char * hostapd_global_ctrl_iface_path(struct hapd_interfaces *interface)
{
char *buf;
size_t len;
if (interface->global_iface_path == NULL)
return NULL;
len = os_strlen(interface->global_iface_path) +
os_strlen(interface->global_iface_name) + 2;
buf = os_malloc(len);
if (buf == NULL)
return NULL;
os_snprintf(buf, len, "%s/%s", interface->global_iface_path,
interface->global_iface_name);
buf[len - 1] = '\0';
return buf;
}
int hostapd_global_ctrl_iface_init(struct hapd_interfaces *interface)
{
struct sockaddr_un addr;
int s = -1;
char *fname = NULL;
if (interface->global_iface_path == NULL) {
wpa_printf(MSG_DEBUG, "ctrl_iface not configured!");
return 0;
}
if (mkdir(interface->global_iface_path, S_IRWXU | S_IRWXG) < 0) {
if (errno == EEXIST) {
wpa_printf(MSG_DEBUG, "Using existing control "
"interface directory.");
} else {
perror("mkdir[ctrl_interface]");
goto fail;
}
}
if (os_strlen(interface->global_iface_path) + 1 +
os_strlen(interface->global_iface_name) >= sizeof(addr.sun_path))
goto fail;
s = socket(PF_UNIX, SOCK_DGRAM, 0);
if (s < 0) {
perror("socket(PF_UNIX)");
goto fail;
}
os_memset(&addr, 0, sizeof(addr));
#ifdef __FreeBSD__
addr.sun_len = sizeof(addr);
#endif /* __FreeBSD__ */
addr.sun_family = AF_UNIX;
fname = hostapd_global_ctrl_iface_path(interface);
if (fname == NULL)
goto fail;
os_strlcpy(addr.sun_path, fname, sizeof(addr.sun_path));
if (bind(s, (struct sockaddr *) &addr, sizeof(addr)) < 0) {
wpa_printf(MSG_DEBUG, "ctrl_iface bind(PF_UNIX) failed: %s",
strerror(errno));
if (connect(s, (struct sockaddr *) &addr, sizeof(addr)) < 0) {
wpa_printf(MSG_DEBUG, "ctrl_iface exists, but does not"
" allow connections - assuming it was left"
"over from forced program termination");
if (unlink(fname) < 0) {
perror("unlink[ctrl_iface]");
wpa_printf(MSG_ERROR, "Could not unlink "
"existing ctrl_iface socket '%s'",
fname);
goto fail;
}
if (bind(s, (struct sockaddr *) &addr, sizeof(addr)) <
0) {
perror("bind(PF_UNIX)");
goto fail;
}
wpa_printf(MSG_DEBUG, "Successfully replaced leftover "
"ctrl_iface socket '%s'", fname);
} else {
wpa_printf(MSG_INFO, "ctrl_iface exists and seems to "
"be in use - cannot override it");
wpa_printf(MSG_INFO, "Delete '%s' manually if it is "
"not used anymore", fname);
os_free(fname);
fname = NULL;
goto fail;
}
}
if (chmod(fname, S_IRWXU | S_IRWXG) < 0) {
perror("chmod[ctrl_interface/ifname]");
goto fail;
}
os_free(fname);
interface->global_ctrl_sock = s;
eloop_register_read_sock(s, hostapd_global_ctrl_iface_receive,
interface, NULL);
return 0;
fail:
if (s >= 0)
close(s);
if (fname) {
unlink(fname);
os_free(fname);
}
return -1;
}
void hostapd_global_ctrl_iface_deinit(struct hapd_interfaces *interfaces)
{
char *fname = NULL;
if (interfaces->global_ctrl_sock > -1) {
eloop_unregister_read_sock(interfaces->global_ctrl_sock);
close(interfaces->global_ctrl_sock);
interfaces->global_ctrl_sock = -1;
fname = hostapd_global_ctrl_iface_path(interfaces);
if (fname) {
unlink(fname);
os_free(fname);
}
if (interfaces->global_iface_path &&
rmdir(interfaces->global_iface_path) < 0) {
if (errno == ENOTEMPTY) {
wpa_printf(MSG_DEBUG, "Control interface "
"directory not empty - leaving it "
"behind");
} else {
perror("rmdir[ctrl_interface]");
}
}
os_free(interfaces->global_iface_path);
interfaces->global_iface_path = NULL;
}
}
static void hostapd_ctrl_iface_send(struct hostapd_data *hapd, int level,
const char *buf, size_t len)
{

View File

@ -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 */

View File

@ -108,6 +108,8 @@ CONFIG_EAP_TTLS=y
#CONFIG_WPS2=y
# Enable UPnP support for external WPS Registrars
#CONFIG_WPS_UPNP=y
# Enable WPS support with NFC config method
#CONFIG_WPS_NFC=y
# EAP-IKEv2
#CONFIG_EAP_IKEV2=y
@ -136,6 +138,13 @@ CONFIG_IPV6=y
# IEEE 802.11n (High Throughput) support
#CONFIG_IEEE80211N=y
# Wireless Network Management (IEEE Std 802.11v-2011)
# Note: This is experimental and not complete implementation.
#CONFIG_WNM=y
# IEEE 802.11ac (Very High Throughput) support
#CONFIG_IEEE80211AC=y
# Remove debugging code that is printing out debug messages to stdout.
# This can be used to reduce the size of the hostapd considerably if debugging
# code is not needed.
@ -158,6 +167,10 @@ CONFIG_IPV6=y
# automatically create bridge and VLAN interfaces if necessary.
#CONFIG_FULL_DYNAMIC_VLAN=y
# Use netlink-based kernel API for VLAN operations instead of ioctl()
# Note: This requires libnl 3.1 or newer.
#CONFIG_VLAN_NETLINK=y
# Remove support for dumping state into a file on SIGUSR1 signal
# This can be used to reduce binary size at the cost of disabling a debugging
# option.
@ -224,6 +237,10 @@ CONFIG_IPV6=y
# are used.
#CONFIG_TLSV11=y
# TLS-based EAP methods require at least TLS v1.0. Newer version of TLS (v1.2)
# can be enabled to enable use of stronger crypto algorithms.
#CONFIG_TLSV12=y
# If CONFIG_TLS=internal is used, additional library and include paths are
# needed for LibTomMath. Alternatively, an integrated, minimal version of
# LibTomMath can be used. See beginning of libtommath.c for details on benefits
@ -244,3 +261,9 @@ CONFIG_IPV6=y
# This can be used to enable functionality to improve interworking with
# external networks.
#CONFIG_INTERWORKING=y
# Hotspot 2.0
#CONFIG_HS20=y
# Enable SQLite database support in hlr_auc_gw, EAP-SIM DB, and eap_user_file
#CONFIG_SQLITE=y

View File

@ -2,14 +2,8 @@
* hostapd / State dump
* Copyright (c) 2002-2009, Jouni Malinen <j@w1.fi>
*
* This program is free software; you can redistribute it and/or modify
* it under the terms of the GNU General Public License version 2 as
* published by the Free Software Foundation.
*
* Alternatively, this software may be distributed under the terms of BSD
* license.
*
* See README and COPYING for more details.
* This software may be distributed under the terms of the BSD license.
* See README for more details.
*/
#include "utils/includes.h"

View File

@ -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

View File

@ -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();

View File

@ -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

View File

@ -1,15 +1,9 @@
/*
* HLR/AuC testing gateway for hostapd EAP-SIM/AKA database/authenticator
* Copyright (c) 2005-2007, Jouni Malinen <j@w1.fi>
* Copyright (c) 2005-2007, 2012, Jouni Malinen <j@w1.fi>
*
* This program is free software; you can redistribute it and/or modify
* it under the terms of the GNU General Public License version 2 as
* published by the Free Software Foundation.
*
* Alternatively, this software may be distributed under the terms of BSD
* license.
*
* See README and COPYING for more details.
* This software may be distributed under the terms of the BSD license.
* See README for more details.
*
* This is an example implementation of the EAP-SIM/AKA database/authentication
* gateway interface to HLR/AuC. It is expected to be replaced with an
@ -49,6 +43,9 @@
#include "includes.h"
#include <sys/un.h>
#ifdef CONFIG_SQLITE
#include <sqlite3.h>
#endif /* CONFIG_SQLITE */
#include "common.h"
#include "crypto/milenage.h"
@ -57,6 +54,9 @@
static const char *default_socket_path = "/tmp/hlr_auc_gw.sock";
static const char *socket_path;
static int serv_sock = -1;
static char *milenage_file = NULL;
static int update_milenage = 0;
static int sqn_changes = 0;
static int ind_len = 5;
/* GSM triplets */
@ -78,6 +78,7 @@ struct milenage_parameters {
u8 opc[16];
u8 amf[2];
u8 sqn[6];
int set;
};
static struct milenage_parameters *milenage_db = NULL;
@ -92,6 +93,144 @@ static struct milenage_parameters *milenage_db = NULL;
#define EAP_AKA_CK_LEN 16
#ifdef CONFIG_SQLITE
static sqlite3 *sqlite_db = NULL;
static struct milenage_parameters db_tmp_milenage;
static int db_table_exists(sqlite3 *db, const char *name)
{
char cmd[128];
os_snprintf(cmd, sizeof(cmd), "SELECT 1 FROM %s;", name);
return sqlite3_exec(db, cmd, NULL, NULL, NULL) == SQLITE_OK;
}
static int db_table_create_milenage(sqlite3 *db)
{
char *err = NULL;
const char *sql =
"CREATE TABLE milenage("
" imsi INTEGER PRIMARY KEY NOT NULL,"
" ki CHAR(32) NOT NULL,"
" opc CHAR(32) NOT NULL,"
" amf CHAR(4) NOT NULL,"
" sqn CHAR(12) NOT NULL"
");";
printf("Adding database table for milenage information\n");
if (sqlite3_exec(db, sql, NULL, NULL, &err) != SQLITE_OK) {
printf("SQLite error: %s\n", err);
sqlite3_free(err);
return -1;
}
return 0;
}
static sqlite3 * db_open(const char *db_file)
{
sqlite3 *db;
if (sqlite3_open(db_file, &db)) {
printf("Failed to open database %s: %s\n",
db_file, sqlite3_errmsg(db));
sqlite3_close(db);
return NULL;
}
if (!db_table_exists(db, "milenage") &&
db_table_create_milenage(db) < 0) {
sqlite3_close(db);
return NULL;
}
return db;
}
static int get_milenage_cb(void *ctx, int argc, char *argv[], char *col[])
{
struct milenage_parameters *m = ctx;
int i;
m->set = 1;
for (i = 0; i < argc; i++) {
if (os_strcmp(col[i], "ki") == 0 && argv[i] &&
hexstr2bin(argv[i], m->ki, sizeof(m->ki))) {
printf("Invalid ki value in database\n");
return -1;
}
if (os_strcmp(col[i], "opc") == 0 && argv[i] &&
hexstr2bin(argv[i], m->opc, sizeof(m->opc))) {
printf("Invalid opcvalue in database\n");
return -1;
}
if (os_strcmp(col[i], "amf") == 0 && argv[i] &&
hexstr2bin(argv[i], m->amf, sizeof(m->amf))) {
printf("Invalid amf value in database\n");
return -1;
}
if (os_strcmp(col[i], "sqn") == 0 && argv[i] &&
hexstr2bin(argv[i], m->sqn, sizeof(m->sqn))) {
printf("Invalid sqn value in database\n");
return -1;
}
}
return 0;
}
static struct milenage_parameters * db_get_milenage(const char *imsi_txt)
{
char cmd[128];
unsigned long long imsi;
os_memset(&db_tmp_milenage, 0, sizeof(db_tmp_milenage));
imsi = atoll(imsi_txt);
os_snprintf(db_tmp_milenage.imsi, sizeof(db_tmp_milenage.imsi),
"%llu", imsi);
os_snprintf(cmd, sizeof(cmd),
"SELECT ki,opc,amf,sqn FROM milenage WHERE imsi=%llu;",
imsi);
if (sqlite3_exec(sqlite_db, cmd, get_milenage_cb, &db_tmp_milenage,
NULL) != SQLITE_OK)
return NULL;
if (!db_tmp_milenage.set)
return NULL;
return &db_tmp_milenage;
}
static int db_update_milenage_sqn(struct milenage_parameters *m)
{
char cmd[128], val[13], *pos;
pos = val;
pos += wpa_snprintf_hex(pos, sizeof(val), m->sqn, 6);
*pos = '\0';
os_snprintf(cmd, sizeof(cmd),
"UPDATE milenage SET sqn='%s' WHERE imsi=%s;",
val, m->imsi);
if (sqlite3_exec(sqlite_db, cmd, NULL, NULL, NULL) != SQLITE_OK) {
printf("Failed to update SQN in database for IMSI %s\n",
m->imsi);
return -1;
}
return 0;
}
#endif /* CONFIG_SQLITE */
static int open_socket(const char *path)
{
struct sockaddr_un addr;
@ -107,7 +246,7 @@ static int open_socket(const char *path)
addr.sun_family = AF_UNIX;
os_strlcpy(addr.sun_path, path, sizeof(addr.sun_path));
if (bind(s, (struct sockaddr *) &addr, sizeof(addr)) < 0) {
perror("bind(PF_UNIX)");
perror("hlr-auc-gw: bind(PF_UNIX)");
close(s);
return -1;
}
@ -221,7 +360,7 @@ static int read_gsm_triplets(const char *fname)
gsm_db = g;
g = NULL;
}
free(g);
os_free(g);
fclose(f);
@ -371,7 +510,7 @@ static int read_milenage(const char *fname)
milenage_db = m;
m = NULL;
}
free(m);
os_free(m);
fclose(f);
@ -379,6 +518,80 @@ static int read_milenage(const char *fname)
}
static void update_milenage_file(const char *fname)
{
FILE *f, *f2;
char buf[500], *pos;
char *end = buf + sizeof(buf);
struct milenage_parameters *m;
size_t imsi_len;
f = fopen(fname, "r");
if (f == NULL) {
printf("Could not open Milenage data file '%s'\n", fname);
return;
}
snprintf(buf, sizeof(buf), "%s.new", fname);
f2 = fopen(buf, "w");
if (f2 == NULL) {
printf("Could not write Milenage data file '%s'\n", buf);
fclose(f);
return;
}
while (fgets(buf, sizeof(buf), f)) {
/* IMSI Ki OPc AMF SQN */
buf[sizeof(buf) - 1] = '\0';
pos = strchr(buf, ' ');
if (buf[0] == '#' || pos == NULL || pos - buf >= 20)
goto no_update;
imsi_len = pos - buf;
for (m = milenage_db; m; m = m->next) {
if (strncmp(buf, m->imsi, imsi_len) == 0 &&
m->imsi[imsi_len] == '\0')
break;
}
if (!m)
goto no_update;
pos = buf;
pos += snprintf(pos, end - pos, "%s ", m->imsi);
pos += wpa_snprintf_hex(pos, end - pos, m->ki, 16);
*pos++ = ' ';
pos += wpa_snprintf_hex(pos, end - pos, m->opc, 16);
*pos++ = ' ';
pos += wpa_snprintf_hex(pos, end - pos, m->amf, 2);
*pos++ = ' ';
pos += wpa_snprintf_hex(pos, end - pos, m->sqn, 6);
*pos++ = '\n';
no_update:
fprintf(f2, "%s", buf);
}
fclose(f2);
fclose(f);
snprintf(buf, sizeof(buf), "%s.bak", fname);
if (rename(fname, buf) < 0) {
perror("rename");
return;
}
snprintf(buf, sizeof(buf), "%s.new", fname);
if (rename(buf, fname) < 0) {
perror("rename");
return;
}
}
static struct milenage_parameters * get_milenage(const char *imsi)
{
struct milenage_parameters *m = milenage_db;
@ -389,6 +602,11 @@ static struct milenage_parameters * get_milenage(const char *imsi)
m = m->next;
}
#ifdef CONFIG_SQLITE
if (!m)
m = db_get_milenage(imsi);
#endif /* CONFIG_SQLITE */
return m;
}
@ -506,6 +724,7 @@ static void aka_req_auth(int s, struct sockaddr_un *from, socklen_t fromlen,
size_t res_len;
int ret;
struct milenage_parameters *m;
int failed = 0;
m = get_milenage(imsi);
if (m) {
@ -513,6 +732,10 @@ static void aka_req_auth(int s, struct sockaddr_un *from, socklen_t fromlen,
return;
res_len = EAP_AKA_RES_MAX_LEN;
inc_sqn(m->sqn);
#ifdef CONFIG_SQLITE
db_update_milenage_sqn(m);
#endif /* CONFIG_SQLITE */
sqn_changes = 1;
printf("AKA: Milenage with SQN=%02x%02x%02x%02x%02x%02x\n",
m->sqn[0], m->sqn[1], m->sqn[2],
m->sqn[3], m->sqn[4], m->sqn[5]);
@ -529,7 +752,7 @@ static void aka_req_auth(int s, struct sockaddr_un *from, socklen_t fromlen,
memset(res, '2', EAP_AKA_RES_MAX_LEN);
res_len = EAP_AKA_RES_MAX_LEN;
#else /* AKA_USE_FIXED_TEST_VALUES */
return;
failed = 1;
#endif /* AKA_USE_FIXED_TEST_VALUES */
}
@ -539,6 +762,13 @@ static void aka_req_auth(int s, struct sockaddr_un *from, socklen_t fromlen,
if (ret < 0 || ret >= end - pos)
return;
pos += ret;
if (failed) {
ret = snprintf(pos, end - pos, "FAILURE");
if (ret < 0 || ret >= end - pos)
return;
pos += ret;
goto done;
}
pos += wpa_snprintf_hex(pos, end - pos, _rand, EAP_AKA_RAND_LEN);
*pos++ = ' ';
pos += wpa_snprintf_hex(pos, end - pos, autn, EAP_AKA_AUTN_LEN);
@ -549,6 +779,7 @@ static void aka_req_auth(int s, struct sockaddr_un *from, socklen_t fromlen,
*pos++ = ' ';
pos += wpa_snprintf_hex(pos, end - pos, res, res_len);
done:
printf("Send: %s\n", reply);
if (sendto(s, reply, pos - reply, 0, (struct sockaddr *) from,
@ -596,6 +827,10 @@ static void aka_auts(int s, struct sockaddr_un *from, socklen_t fromlen,
printf("AKA-AUTS: Re-synchronized: "
"SQN=%02x%02x%02x%02x%02x%02x\n",
sqn[0], sqn[1], sqn[2], sqn[3], sqn[4], sqn[5]);
#ifdef CONFIG_SQLITE
db_update_milenage_sqn(m);
#endif /* CONFIG_SQLITE */
sqn_changes = 1;
}
}
@ -642,22 +877,32 @@ static void cleanup(void)
struct gsm_triplet *g, *gprev;
struct milenage_parameters *m, *prev;
if (update_milenage && milenage_file && sqn_changes)
update_milenage_file(milenage_file);
g = gsm_db;
while (g) {
gprev = g;
g = g->next;
free(gprev);
os_free(gprev);
}
m = milenage_db;
while (m) {
prev = m;
m = m->next;
free(prev);
os_free(prev);
}
close(serv_sock);
unlink(socket_path);
#ifdef CONFIG_SQLITE
if (sqlite_db) {
sqlite3_close(sqlite_db);
sqlite_db = NULL;
}
#endif /* CONFIG_SQLITE */
}
@ -672,19 +917,21 @@ static void usage(void)
{
printf("HLR/AuC testing gateway for hostapd EAP-SIM/AKA "
"database/authenticator\n"
"Copyright (c) 2005-2007, Jouni Malinen <j@w1.fi>\n"
"Copyright (c) 2005-2007, 2012, Jouni Malinen <j@w1.fi>\n"
"\n"
"usage:\n"
"hlr_auc_gw [-h] [-s<socket path>] [-g<triplet file>] "
"hlr_auc_gw [-hu] [-s<socket path>] [-g<triplet file>] "
"[-m<milenage file>] \\\n"
" [-i<IND len in bits>]\n"
" [-D<DB file>] [-i<IND len in bits>]\n"
"\n"
"options:\n"
" -h = show this usage help\n"
" -u = update SQN in Milenage file on exit\n"
" -s<socket path> = path for UNIX domain socket\n"
" (default: %s)\n"
" -g<triplet file> = path for GSM authentication triplets\n"
" -m<milenage file> = path for Milenage keys\n"
" -D<DB file> = path to SQLite database\n"
" -i<IND len in bits> = IND length for SQN (default: 5)\n",
default_socket_path);
}
@ -693,16 +940,27 @@ static void usage(void)
int main(int argc, char *argv[])
{
int c;
char *milenage_file = NULL;
char *gsm_triplet_file = NULL;
char *sqlite_db_file = NULL;
if (os_program_init())
return -1;
socket_path = default_socket_path;
for (;;) {
c = getopt(argc, argv, "g:hi:m:s:");
c = getopt(argc, argv, "D:g:hi:m:s:u");
if (c < 0)
break;
switch (c) {
case 'D':
#ifdef CONFIG_SQLITE
sqlite_db_file = optarg;
break;
#else /* CONFIG_SQLITE */
printf("No SQLite support included in the build\n");
return -1;
#endif /* CONFIG_SQLITE */
case 'g':
gsm_triplet_file = optarg;
break;
@ -722,12 +980,25 @@ int main(int argc, char *argv[])
case 's':
socket_path = optarg;
break;
case 'u':
update_milenage = 1;
break;
default:
usage();
return -1;
}
}
if (!gsm_triplet_file && !milenage_file && !sqlite_db_file) {
usage();
return -1;
}
#ifdef CONFIG_SQLITE
if (sqlite_db_file && (sqlite_db = db_open(sqlite_db_file)) == NULL)
return -1;
#endif /* CONFIG_SQLITE */
if (gsm_triplet_file && read_gsm_triplets(gsm_triplet_file) < 0)
return -1;
@ -747,5 +1018,14 @@ int main(int argc, char *argv[])
for (;;)
process(serv_sock);
#ifdef CONFIG_SQLITE
if (sqlite_db) {
sqlite3_close(sqlite_db);
sqlite_db = NULL;
}
#endif /* CONFIG_SQLITE */
os_program_deinit();
return 0;
}

View 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'

View File

@ -84,6 +84,14 @@ ctrl_interface_group=0
# SSID to be used in IEEE 802.11 management frames
ssid=test
# Alternative formats for configuring SSID
# (double quoted string, hexdump, printf-escaped string)
#ssid2="test"
#ssid2=74657374
#ssid2=P"hello\nthere"
# UTF-8 SSID: Whether the SSID is to be interpreted using UTF-8 encoding
#utf8_ssid=1
# Country code (ISO/IEC 3166-1). Used to set regulatory domain.
# Set as needed to indicate country in which device is operating.
@ -98,6 +106,8 @@ ssid=test
#ieee80211d=1
# Operation mode (a = IEEE 802.11a, b = IEEE 802.11b, g = IEEE 802.11g,
# ad = IEEE 802.11ad (60 GHz); a/g options are used with IEEE 802.11n, too, to
# specify band)
# Default: IEEE 802.11b
hw_mode=g
@ -196,6 +206,13 @@ auth_algs=3
# requests for broadcast SSID
ignore_broadcast_ssid=0
# Additional vendor specfic elements for Beacon and Probe Response frames
# This parameter can be used to add additional vendor specific element(s) into
# the end of the Beacon and Probe Response frames. The format for these
# element(s) is a hexdump of the raw information elements (id+len+payload for
# one or more elements)
#vendor_elements=dd0411223301
# TX queue parameters (EDCF / bursting)
# tx_queue_<queue name>_<param>
# queues: data0, data1, data2, data3, after_beacon, beacon
@ -339,6 +356,12 @@ wmm_ac_vo_acm=0
# the STA with a data frame.
# default: 300 (i.e., 5 minutes)
#ap_max_inactivity=300
#
# The inactivity polling can be disabled to disconnect stations based on
# inactivity timeout so that idle stations are more likely to be disconnected
# even if they are still in range of the AP. This can be done by setting
# skip_inactivity_poll to 1 (default 0).
#skip_inactivity_poll=0
# Disassociate stations based on excessive transmission failures or other
# indications of connection loss. This depends on the driver capabilities and
@ -410,6 +433,157 @@ wmm_ac_vo_acm=0
# Require stations to support HT PHY (reject association if they do not)
#require_ht=1
##### IEEE 802.11ac related configuration #####################################
# ieee80211ac: Whether IEEE 802.11ac (VHT) is enabled
# 0 = disabled (default)
# 1 = enabled
# Note: You will also need to enable WMM for full VHT functionality.
#ieee80211ac=1
# vht_capab: VHT capabilities (list of flags)
#
# vht_max_mpdu_len: [MAX-MPDU-7991] [MAX-MPDU-11454]
# Indicates maximum MPDU length
# 0 = 3895 octets (default)
# 1 = 7991 octets
# 2 = 11454 octets
# 3 = reserved
#
# supported_chan_width: [VHT160] [VHT160-80PLUS80]
# Indicates supported Channel widths
# 0 = 160 MHz & 80+80 channel widths are not supported (default)
# 1 = 160 MHz channel width is supported
# 2 = 160 MHz & 80+80 channel widths are supported
# 3 = reserved
#
# Rx LDPC coding capability: [RXLDPC]
# Indicates support for receiving LDPC coded pkts
# 0 = Not supported (default)
# 1 = Supported
#
# Short GI for 80 MHz: [SHORT-GI-80]
# Indicates short GI support for reception of packets transmitted with TXVECTOR
# params format equal to VHT and CBW = 80Mhz
# 0 = Not supported (default)
# 1 = Supported
#
# Short GI for 160 MHz: [SHORT-GI-160]
# Indicates short GI support for reception of packets transmitted with TXVECTOR
# params format equal to VHT and CBW = 160Mhz
# 0 = Not supported (default)
# 1 = Supported
#
# Tx STBC: [TX-STBC-2BY1]
# Indicates support for the transmission of at least 2x1 STBC
# 0 = Not supported (default)
# 1 = Supported
#
# Rx STBC: [RX-STBC-1] [RX-STBC-12] [RX-STBC-123] [RX-STBC-1234]
# Indicates support for the reception of PPDUs using STBC
# 0 = Not supported (default)
# 1 = support of one spatial stream
# 2 = support of one and two spatial streams
# 3 = support of one, two and three spatial streams
# 4 = support of one, two, three and four spatial streams
# 5,6,7 = reserved
#
# SU Beamformer Capable: [SU-BEAMFORMER]
# Indicates support for operation as a single user beamformer
# 0 = Not supported (default)
# 1 = Supported
#
# SU Beamformee Capable: [SU-BEAMFORMEE]
# Indicates support for operation as a single user beamformee
# 0 = Not supported (default)
# 1 = Supported
#
# Compressed Steering Number of Beamformer Antennas Supported: [BF-ANTENNA-2]
# Beamformee's capability indicating the maximum number of beamformer
# antennas the beamformee can support when sending compressed beamforming
# feedback
# If SU beamformer capable, set to maximum value minus 1
# else reserved (default)
#
# Number of Sounding Dimensions: [SOUNDING-DIMENSION-2]
# Beamformer's capability indicating the maximum value of the NUM_STS parameter
# in the TXVECTOR of a VHT NDP
# If SU beamformer capable, set to maximum value minus 1
# else reserved (default)
#
# MU Beamformer Capable: [MU-BEAMFORMER]
# Indicates support for operation as an MU beamformer
# 0 = Not supported or sent by Non-AP STA (default)
# 1 = Supported
#
# MU Beamformee Capable: [MU-BEAMFORMEE]
# Indicates support for operation as an MU beamformee
# 0 = Not supported or sent by AP (default)
# 1 = Supported
#
# VHT TXOP PS: [VHT-TXOP-PS]
# Indicates whether or not the AP supports VHT TXOP Power Save Mode
# or whether or not the STA is in VHT TXOP Power Save mode
# 0 = VHT AP doesnt support VHT TXOP PS mode (OR) VHT Sta not in VHT TXOP PS
# mode
# 1 = VHT AP supports VHT TXOP PS mode (OR) VHT Sta is in VHT TXOP power save
# mode
#
# +HTC-VHT Capable: [HTC-VHT]
# Indicates whether or not the STA supports receiving a VHT variant HT Control
# field.
# 0 = Not supported (default)
# 1 = supported
#
# Maximum A-MPDU Length Exponent: [MAX-A-MPDU-LEN-EXP0]..[MAX-A-MPDU-LEN-EXP7]
# Indicates the maximum length of A-MPDU pre-EOF padding that the STA can recv
# This field is an integer in the range of 0 to 7.
# The length defined by this field is equal to
# 2 pow(13 + Maximum A-MPDU Length Exponent) -1 octets
#
# VHT Link Adaptation Capable: [VHT-LINK-ADAPT2] [VHT-LINK-ADAPT3]
# Indicates whether or not the STA supports link adaptation using VHT variant
# HT Control field
# If +HTC-VHTcapable is 1
# 0 = (no feedback) if the STA does not provide VHT MFB (default)
# 1 = reserved
# 2 = (Unsolicited) if the STA provides only unsolicited VHT MFB
# 3 = (Both) if the STA can provide VHT MFB in response to VHT MRQ and if the
# STA provides unsolicited VHT MFB
# Reserved if +HTC-VHTcapable is 0
#
# Rx Antenna Pattern Consistency: [RX-ANTENNA-PATTERN]
# Indicates the possibility of Rx antenna pattern change
# 0 = Rx antenna pattern might change during the lifetime of an association
# 1 = Rx antenna pattern does not change during the lifetime of an association
#
# Tx Antenna Pattern Consistency: [TX-ANTENNA-PATTERN]
# Indicates the possibility of Tx antenna pattern change
# 0 = Tx antenna pattern might change during the lifetime of an association
# 1 = Tx antenna pattern does not change during the lifetime of an association
#vht_capab=[SHORT-GI-80][HTC-VHT]
#
# Require stations to support VHT PHY (reject association if they do not)
#require_vht=1
# 0 = 20 or 40 MHz operating Channel width
# 1 = 80 MHz channel width
# 2 = 160 MHz channel width
# 3 = 80+80 MHz channel width
#vht_oper_chwidth=1
#
# center freq = 5 GHz + (5 * index)
# So index 42 gives center freq 5.210 GHz
# which is channel 42 in 5G band
#
#vht_oper_centr_freq_seg0_idx=42
#
# center freq = 5 GHz + (5 * index)
# So index 159 gives center freq 5.795 GHz
# which is channel 159 in 5G band
#
#vht_oper_centr_freq_seg1_idx=159
##### IEEE 802.1X-2004 related configuration ##################################
# Require IEEE 802.1X authorization
@ -466,6 +640,8 @@ eapol_key_index_workaround=0
eap_server=0
# Path for EAP server user database
# If SQLite support is included, this can be set to "sqlite:/path/to/sqlite.db"
# to use SQLite database instead of a text file.
#eap_user_file=/etc/hostapd.eap_user
# CA certificate (PEM or DER file) for EAP-TLS/PEAP/TTLS
@ -510,12 +686,18 @@ eap_server=0
# Fragment size for EAP methods
#fragment_size=1400
# Finite cyclic group for EAP-pwd. Number maps to group of domain parameters
# using the IANA repository for IKE (RFC 2409).
#pwd_group=19
# Configuration data for EAP-SIM database/authentication gateway interface.
# This is a text string in implementation specific format. The example
# implementation in eap_sim_db.c uses this as the UNIX domain socket name for
# the HLR/AuC gateway (e.g., hlr_auc_gw). In this case, the path uses "unix:"
# prefix.
# prefix. If hostapd is built with SQLite support (CONFIG_SQLITE=y in .config),
# database file can be described with an optional db=<path> parameter.
#eap_sim_db=unix:/tmp/hlr_auc_gw.sock
#eap_sim_db=unix:/tmp/hlr_auc_gw.sock db=/tmp/hostapd.db
# Encryption key for EAP-FAST PAC-Opaque values. This key must be a secret,
# random value. It is configured as a 16-octet value in hex format. It can be
@ -622,6 +804,12 @@ own_ip_addr=127.0.0.1
# 60 (1 minute).
#radius_acct_interim_interval=600
# Request Chargeable-User-Identity (RFC 4372)
# This parameter can be used to configure hostapd to request CUI from the
# RADIUS server by including Chargeable-User-Identity attribute into
# Access-Request packets.
#radius_request_cui=1
# Dynamic VLAN mode; allow RADIUS authentication server to decide which VLAN
# is used for the stations. This information is parsed from following RADIUS
# attributes based on RFC 3580 and RFC 2868: Tunnel-Type (value 13 = VLAN),
@ -649,6 +837,61 @@ own_ip_addr=127.0.0.1
# to the bridge.
#vlan_tagged_interface=eth0
# When hostapd creates a VLAN interface on vlan_tagged_interfaces, it needs
# to know how to name it.
# 0 = vlan<XXX>, e.g., vlan1
# 1 = <vlan_tagged_interface>.<XXX>, e.g. eth0.1
#vlan_naming=0
# Arbitrary RADIUS attributes can be added into Access-Request and
# Accounting-Request packets by specifying the contents of the attributes with
# the following configuration parameters. There can be multiple of these to
# add multiple attributes. These parameters can also be used to override some
# of the attributes added automatically by hostapd.
# Format: <attr_id>[:<syntax:value>]
# attr_id: RADIUS attribute type (e.g., 26 = Vendor-Specific)
# syntax: s = string (UTF-8), d = integer, x = octet string
# value: attribute value in format indicated by the syntax
# If syntax and value parts are omitted, a null value (single 0x00 octet) is
# used.
#
# Additional Access-Request attributes
# radius_auth_req_attr=<attr_id>[:<syntax:value>]
# Examples:
# Operator-Name = "Operator"
#radius_auth_req_attr=126:s:Operator
# Service-Type = Framed (2)
#radius_auth_req_attr=6:d:2
# Connect-Info = "testing" (this overrides the automatically generated value)
#radius_auth_req_attr=77:s:testing
# Same Connect-Info value set as a hexdump
#radius_auth_req_attr=77:x:74657374696e67
#
# Additional Accounting-Request attributes
# radius_acct_req_attr=<attr_id>[:<syntax:value>]
# Examples:
# Operator-Name = "Operator"
#radius_acct_req_attr=126:s:Operator
# Dynamic Authorization Extensions (RFC 5176)
# This mechanism can be used to allow dynamic changes to user session based on
# commands from a RADIUS server (or some other disconnect client that has the
# needed session information). For example, Disconnect message can be used to
# request an associated station to be disconnected.
#
# This is disabled by default. Set radius_das_port to non-zero UDP port
# number to enable.
#radius_das_port=3799
#
# DAS client (the host that can send Disconnect/CoA requests) and shared secret
#radius_das_client=192.168.1.123 shared secret here
#
# DAS Event-Timestamp time window in seconds
#radius_das_time_window=300
#
# DAS require Event-Timestamp
#radius_das_require_event_timestamp=1
##### RADIUS authentication server configuration ##############################
@ -672,6 +915,7 @@ own_ip_addr=127.0.0.1
# Enable WPA. Setting this variable configures the AP to require WPA (either
# WPA-PSK or WPA-RADIUS/EAP based on other configuration). For WPA-PSK, either
# wpa_psk or wpa_passphrase must be set and wpa_key_mgmt must include WPA-PSK.
# Instead of wpa_psk / wpa_passphrase, wpa_psk_radius might suffice.
# For WPA-RADIUS/EAP, ieee8021x must be set (but without dynamic WEP keys),
# RADIUS authentication server must be configured, and WPA-EAP must be included
# in wpa_key_mgmt.
@ -696,6 +940,15 @@ own_ip_addr=127.0.0.1
# configuration reloads.
#wpa_psk_file=/etc/hostapd.wpa_psk
# Optionally, WPA passphrase can be received from RADIUS authentication server
# This requires macaddr_acl to be set to 2 (RADIUS)
# 0 = disabled (default)
# 1 = optional; use default passphrase/psk if RADIUS server does not include
# Tunnel-Password
# 2 = required; reject authentication if RADIUS server does not include
# Tunnel-Password
#wpa_psk_radius=0
# Set of accepted key management algorithms (WPA-PSK, WPA-EAP, or both). The
# entries are separated with a space. WPA-PSK-SHA256 and WPA-EAP-SHA256 can be
# added to enable SHA256-based stronger algorithms.
@ -1007,6 +1260,24 @@ own_ip_addr=127.0.0.1
# 12-digit, all-numeric code that identifies the consumer package.
#upc=123456789012
# WPS RF Bands (a = 5G, b = 2.4G, g = 2.4G, ag = dual band)
# This value should be set according to RF band(s) supported by the AP if
# hw_mode is not set. For dual band dual concurrent devices, this needs to be
# set to ag to allow both RF bands to be advertized.
#wps_rf_bands=ag
# NFC password token for WPS
# These parameters can be used to configure a fixed NFC password token for the
# AP. This can be generated, e.g., with nfc_pw_token from wpa_supplicant. When
# these parameters are used, the AP is assumed to be deployed with a NFC tag
# that includes the matching NFC password token (e.g., written based on the
# NDEF record from nfc_pw_token).
#
#wps_nfc_dev_pw_id: Device Password ID (16..65535)
#wps_nfc_dh_pubkey: Hexdump of DH Public Key
#wps_nfc_dh_privkey: Hexdump of DH Private Key
#wps_nfc_dev_pw: Hexdump of Device Password
##### Wi-Fi Direct (P2P) ######################################################
# Enable P2P Device management
@ -1034,6 +1305,16 @@ own_ip_addr=127.0.0.1
# stdoffset[dst[offset][,start[/time],end[/time]]]
#time_zone=EST5
# WNM-Sleep Mode (extended sleep mode for stations)
# 0 = disabled (default)
# 1 = enabled (allow stations to use WNM-Sleep Mode)
#wnm_sleep_mode=1
# BSS Transition Management
# 0 = disabled (default)
# 1 = enabled
#bss_transition=1
##### IEEE 802.11u-2011 #######################################################
# Enable Interworking service
@ -1087,11 +1368,138 @@ own_ip_addr=127.0.0.1
# Arbitrary number of Roaming Consortium OIs can be configured with each line
# adding a new OI to the list. The first three entries are available through
# Beacon and Probe Response frames. Any additional entry will be available only
# through ANQP queries. Each OI is between 3 and 15 octets and is configured a
# through ANQP queries. Each OI is between 3 and 15 octets and is configured as
# a hexstring.
#roaming_consortium=021122
#roaming_consortium=2233445566
# Venue Name information
# This parameter can be used to configure one or more Venue Name Duples for
# Venue Name ANQP information. Each entry has a two or three character language
# code (ISO-639) separated by colon from the venue name string.
# Note that venue_group and venue_type have to be set for Venue Name
# information to be complete.
#venue_name=eng:Example venue
#venue_name=fin:Esimerkkipaikka
# Network Authentication Type
# This parameter indicates what type of network authentication is used in the
# network.
# format: <network auth type indicator (1-octet hex str)> [redirect URL]
# Network Authentication Type Indicator values:
# 00 = Acceptance of terms and conditions
# 01 = On-line enrollment supported
# 02 = http/https redirection
# 03 = DNS redirection
#network_auth_type=00
#network_auth_type=02http://www.example.com/redirect/me/here/
# IP Address Type Availability
# format: <1-octet encoded value as hex str>
# (ipv4_type & 0x3f) << 2 | (ipv6_type & 0x3)
# ipv4_type:
# 0 = Address type not available
# 1 = Public IPv4 address available
# 2 = Port-restricted IPv4 address available
# 3 = Single NATed private IPv4 address available
# 4 = Double NATed private IPv4 address available
# 5 = Port-restricted IPv4 address and single NATed IPv4 address available
# 6 = Port-restricted IPv4 address and double NATed IPv4 address available
# 7 = Availability of the address type is not known
# ipv6_type:
# 0 = Address type not available
# 1 = Address type available
# 2 = Availability of the address type not known
#ipaddr_type_availability=14
# Domain Name
# format: <variable-octet str>[,<variable-octet str>]
#domain_name=example.com,another.example.com,yet-another.example.com
# 3GPP Cellular Network information
# format: <MCC1,MNC1>[;<MCC2,MNC2>][;...]
#anqp_3gpp_cell_net=244,91;310,026;234,56
# NAI Realm information
# One or more realm can be advertised. Each nai_realm line adds a new realm to
# the set. These parameters provide information for stations using Interworking
# network selection to allow automatic connection to a network based on
# credentials.
# format: <encoding>,<NAI Realm(s)>[,<EAP Method 1>][,<EAP Method 2>][,...]
# encoding:
# 0 = Realm formatted in accordance with IETF RFC 4282
# 1 = UTF-8 formatted character string that is not formatted in
# accordance with IETF RFC 4282
# NAI Realm(s): Semi-colon delimited NAI Realm(s)
# EAP Method: <EAP Method>[:<[AuthParam1:Val1]>][<[AuthParam2:Val2]>][...]
# AuthParam (Table 8-188 in IEEE Std 802.11-2012):
# ID 2 = Non-EAP Inner Authentication Type
# 1 = PAP, 2 = CHAP, 3 = MSCHAP, 4 = MSCHAPV2
# ID 3 = Inner authentication EAP Method Type
# ID 5 = Credential Type
# 1 = SIM, 2 = USIM, 3 = NFC Secure Element, 4 = Hardware Token,
# 5 = Softoken, 6 = Certificate, 7 = username/password, 9 = Anonymous,
# 10 = Vendor Specific
#nai_realm=0,example.com;example.net
# EAP methods EAP-TLS with certificate and EAP-TTLS/MSCHAPv2 with
# username/password
#nai_realm=0,example.org,13[5:6],21[2:4][5:7]
##### Hotspot 2.0 #############################################################
# Enable Hotspot 2.0 support
#hs20=1
# Disable Downstream Group-Addressed Forwarding (DGAF)
# This can be used to configure a network where no group-addressed frames are
# allowed. The AP will not forward any group-address frames to the stations and
# random GTKs are issued for each station to prevent associated stations from
# forging such frames to other stations in the BSS.
#disable_dgaf=1
# Operator Friendly Name
# This parameter can be used to configure one or more Operator Friendly Name
# Duples. Each entry has a two or three character language code (ISO-639)
# separated by colon from the operator friendly name string.
#hs20_oper_friendly_name=eng:Example operator
#hs20_oper_friendly_name=fin:Esimerkkioperaattori
# Connection Capability
# This can be used to advertise what type of IP traffic can be sent through the
# hotspot (e.g., due to firewall allowing/blocking protocols/ports).
# format: <IP Protocol>:<Port Number>:<Status>
# IP Protocol: 1 = ICMP, 6 = TCP, 17 = UDP
# Port Number: 0..65535
# Status: 0 = Closed, 1 = Open, 2 = Unknown
# Each hs20_conn_capab line is added to the list of advertised tuples.
#hs20_conn_capab=1:0:2
#hs20_conn_capab=6:22:1
#hs20_conn_capab=17:5060:0
# WAN Metrics
# format: <WAN Info>:<DL Speed>:<UL Speed>:<DL Load>:<UL Load>:<LMD>
# WAN Info: B0-B1: Link Status, B2: Symmetric Link, B3: At Capabity
# (encoded as two hex digits)
# Link Status: 1 = Link up, 2 = Link down, 3 = Link in test state
# Downlink Speed: Estimate of WAN backhaul link current downlink speed in kbps;
# 1..4294967295; 0 = unknown
# Uplink Speed: Estimate of WAN backhaul link current uplink speed in kbps
# 1..4294967295; 0 = unknown
# Downlink Load: Current load of downlink WAN connection (scaled to 255 = 100%)
# Uplink Load: Current load of uplink WAN connection (scaled to 255 = 100%)
# Load Measurement Duration: Duration for measuring downlink/uplink load in
# tenths of a second (1..65535); 0 if load cannot be determined
#hs20_wan_metrics=01:8000:1000:80:240:3000
# Operating Class Indication
# List of operating classes the BSSes in this ESS use. The Global operating
# classes in Table E-4 of IEEE Std 802.11-2012 Annex E define the values that
# can be used in this.
# format: hexdump of operating class octets
# for example, operating classes 81 (2.4 GHz channels 1-13) and 115 (5 GHz
# channels 36-48):
#hs20_operating_class=5173
##### Multiple BSSID support ##################################################
#
# Above configuration is using the default interface (wlan#, or multi-SSID VLAN

View 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');

View File

@ -2,14 +2,8 @@
* hostapd / main()
* Copyright (c) 2002-2011, Jouni Malinen <j@w1.fi>
*
* This program is free software; you can redistribute it and/or modify
* it under the terms of the GNU General Public License version 2 as
* published by the Free Software Foundation.
*
* Alternatively, this software may be distributed under the terms of BSD
* license.
*
* See README and COPYING for more details.
* This software may be distributed under the terms of the BSD license.
* See README for more details.
*/
#include "utils/includes.h"
@ -27,6 +21,7 @@
#include "eap_server/tncs.h"
#include "ap/hostapd.h"
#include "ap/ap_config.h"
#include "ap/ap_drv_ops.h"
#include "config_file.h"
#include "eap_register.h"
#include "dump_state.h"
@ -48,29 +43,6 @@ struct hapd_global {
static struct hapd_global global;
struct hapd_interfaces {
size_t count;
struct hostapd_iface **iface;
};
static int hostapd_for_each_interface(struct hapd_interfaces *interfaces,
int (*cb)(struct hostapd_iface *iface,
void *ctx), void *ctx)
{
size_t i;
int ret;
for (i = 0; i < interfaces->count; i++) {
ret = cb(interfaces->iface[i], ctx);
if (ret)
return ret;
}
return 0;
}
#ifndef CONFIG_NO_HOSTAPD_LOGGER
static void hostapd_logger_cb(void *ctx, const u8 *addr, unsigned int module,
int level, const char *txt, size_t len)
@ -194,14 +166,9 @@ static struct hostapd_iface * hostapd_init(const char *config_file)
if (hapd_iface == NULL)
goto fail;
hapd_iface->reload_config = hostapd_reload_config;
hapd_iface->config_read_cb = hostapd_config_read;
hapd_iface->config_fname = os_strdup(config_file);
if (hapd_iface->config_fname == NULL)
goto fail;
hapd_iface->ctrl_iface_init = hostapd_ctrl_iface_init;
hapd_iface->ctrl_iface_deinit = hostapd_ctrl_iface_deinit;
hapd_iface->for_each_interface = hostapd_for_each_interface;
conf = hostapd_config_read(hapd_iface->config_fname);
if (conf == NULL)
@ -209,7 +176,7 @@ static struct hostapd_iface * hostapd_init(const char *config_file)
hapd_iface->conf = conf;
hapd_iface->num_bss = conf->num_bss;
hapd_iface->bss = os_zalloc(conf->num_bss *
hapd_iface->bss = os_calloc(conf->num_bss,
sizeof(struct hostapd_data *));
if (hapd_iface->bss == NULL)
goto fail;
@ -276,13 +243,13 @@ static int hostapd_driver_init(struct hostapd_iface *iface)
}
params.bssid = b;
params.ifname = hapd->conf->iface;
params.ssid = (const u8 *) hapd->conf->ssid.ssid;
params.ssid = hapd->conf->ssid.ssid;
params.ssid_len = hapd->conf->ssid.ssid_len;
params.test_socket = hapd->conf->test_socket;
params.use_pae_group_addr = hapd->conf->use_pae_group_addr;
params.num_bridge = hapd->iface->num_bss;
params.bridge = os_zalloc(hapd->iface->num_bss * sizeof(char *));
params.bridge = os_calloc(hapd->iface->num_bss, sizeof(char *));
if (params.bridge == NULL)
return -1;
for (i = 0; i < hapd->iface->num_bss; i++) {
@ -303,28 +270,15 @@ static int hostapd_driver_init(struct hostapd_iface *iface)
}
if (hapd->driver->get_capa &&
hapd->driver->get_capa(hapd->drv_priv, &capa) == 0)
hapd->driver->get_capa(hapd->drv_priv, &capa) == 0) {
iface->drv_flags = capa.flags;
iface->probe_resp_offloads = capa.probe_resp_offloads;
}
return 0;
}
static void hostapd_interface_deinit_free(struct hostapd_iface *iface)
{
const struct wpa_driver_ops *driver;
void *drv_priv;
if (iface == NULL)
return;
driver = iface->bss[0]->driver;
drv_priv = iface->bss[0]->drv_priv;
hostapd_interface_deinit(iface);
if (driver && driver->hapd_deinit)
driver->hapd_deinit(drv_priv);
hostapd_interface_free(iface);
}
static struct hostapd_iface *
hostapd_interface_init(struct hapd_interfaces *interfaces,
const char *config_fname, int debug)
@ -343,10 +297,13 @@ hostapd_interface_init(struct hapd_interfaces *interfaces,
iface->bss[0]->conf->logger_stdout_level--;
}
if (hostapd_driver_init(iface) ||
hostapd_setup_interface(iface)) {
hostapd_interface_deinit_free(iface);
return NULL;
if (iface->conf->bss[0].iface[0] != 0 ||
hostapd_drv_none(iface->bss[0])) {
if (hostapd_driver_init(iface) ||
hostapd_setup_interface(iface)) {
hostapd_interface_deinit_free(iface);
return NULL;
}
}
return iface;
@ -434,7 +391,7 @@ static int hostapd_global_init(struct hapd_interfaces *interfaces,
wpa_printf(MSG_ERROR, "No drivers enabled");
return -1;
}
global.drv_priv = os_zalloc(global.drv_count * sizeof(void *));
global.drv_priv = os_calloc(global.drv_count, sizeof(void *));
if (global.drv_priv == NULL)
return -1;
@ -522,13 +479,15 @@ static void usage(void)
fprintf(stderr,
"\n"
"usage: hostapd [-hdBKtv] [-P <PID file>] [-e <entropy file>] "
"<configuration file(s)>\n"
"\\\n"
" [-g <global ctrl_iface>] <configuration file(s)>\n"
"\n"
"options:\n"
" -h show this usage\n"
" -d show more debug messages (-dd for even more)\n"
" -B run daemon in the background\n"
" -e entropy file\n"
" -g global control interface path\n"
" -P PID file\n"
" -K include key data in debug messages\n"
#ifdef CONFIG_DEBUG_FILE
@ -550,6 +509,28 @@ static const char * hostapd_msg_ifname_cb(void *ctx)
}
static int hostapd_get_global_ctrl_iface(struct hapd_interfaces *interfaces,
const char *path)
{
char *pos;
os_free(interfaces->global_iface_path);
interfaces->global_iface_path = os_strdup(path);
if (interfaces->global_iface_path == NULL)
return -1;
pos = os_strrchr(interfaces->global_iface_path, '/');
if (pos == NULL) {
os_free(interfaces->global_iface_path);
interfaces->global_iface_path = NULL;
return -1;
}
*pos = '\0';
interfaces->global_iface_name = pos + 1;
return 0;
}
int main(int argc, char *argv[])
{
struct hapd_interfaces interfaces;
@ -563,8 +544,19 @@ int main(int argc, char *argv[])
if (os_program_init())
return -1;
os_memset(&interfaces, 0, sizeof(interfaces));
interfaces.reload_config = hostapd_reload_config;
interfaces.config_read_cb = hostapd_config_read;
interfaces.for_each_interface = hostapd_for_each_interface;
interfaces.ctrl_iface_init = hostapd_ctrl_iface_init;
interfaces.ctrl_iface_deinit = hostapd_ctrl_iface_deinit;
interfaces.driver_init = hostapd_driver_init;
interfaces.global_iface_path = NULL;
interfaces.global_iface_name = NULL;
interfaces.global_ctrl_sock = -1;
for (;;) {
c = getopt(argc, argv, "Bde:f:hKP:tv");
c = getopt(argc, argv, "Bde:f:hKP:tvg:");
if (c < 0)
break;
switch (c) {
@ -599,6 +591,9 @@ int main(int argc, char *argv[])
show_version();
exit(1);
break;
case 'g':
hostapd_get_global_ctrl_iface(&interfaces, optarg);
break;
default:
usage();
@ -606,7 +601,7 @@ int main(int argc, char *argv[])
}
}
if (optind == argc)
if (optind == argc && interfaces.global_iface_path == NULL)
usage();
wpa_msg_register_ifname_cb(hostapd_msg_ifname_cb);
@ -615,11 +610,13 @@ int main(int argc, char *argv[])
wpa_debug_open_file(log_file);
interfaces.count = argc - optind;
interfaces.iface = os_zalloc(interfaces.count *
sizeof(struct hostapd_iface *));
if (interfaces.iface == NULL) {
wpa_printf(MSG_ERROR, "malloc failed");
return -1;
if (interfaces.count) {
interfaces.iface = os_calloc(interfaces.count,
sizeof(struct hostapd_iface *));
if (interfaces.iface == NULL) {
wpa_printf(MSG_ERROR, "malloc failed");
return -1;
}
}
if (hostapd_global_init(&interfaces, entropy_file))
@ -634,12 +631,15 @@ int main(int argc, char *argv[])
goto out;
}
hostapd_global_ctrl_iface_init(&interfaces);
if (hostapd_global_run(&interfaces, daemonize, pid_file))
goto out;
ret = 0;
out:
hostapd_global_ctrl_iface_deinit(&interfaces);
/* Deinitialize all interfaces */
for (i = 0; i < interfaces.count; i++)
hostapd_interface_deinit_free(interfaces.iface[i]);

View File

@ -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"

View 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

View File

@ -1,15 +1,9 @@
/*
* hostapd / RADIUS Accounting
* Copyright (c) 2002-2009, Jouni Malinen <j@w1.fi>
* Copyright (c) 2002-2009, 2012, Jouni Malinen <j@w1.fi>
*
* This program is free software; you can redistribute it and/or modify
* it under the terms of the GNU General Public License version 2 as
* published by the Free Software Foundation.
*
* Alternatively, this software may be distributed under the terms of BSD
* license.
*
* See README and COPYING for more details.
* This software may be distributed under the terms of the BSD license.
* See README for more details.
*/
#include "utils/includes.h"
@ -32,8 +26,8 @@
* input/output octets and updates Acct-{Input,Output}-Gigawords. */
#define ACCT_DEFAULT_UPDATE_INTERVAL 300
static void accounting_sta_get_id(struct hostapd_data *hapd,
struct sta_info *sta);
static void accounting_sta_interim(struct hostapd_data *hapd,
struct sta_info *sta);
static struct radius_msg * accounting_msg(struct hostapd_data *hapd,
@ -45,6 +39,7 @@ static struct radius_msg * accounting_msg(struct hostapd_data *hapd,
u8 *val;
size_t len;
int i;
struct wpabuf *b;
msg = radius_msg_new(RADIUS_CODE_ACCOUNTING_REQUEST,
radius_client_get_id(hapd->radius));
@ -73,7 +68,9 @@ static struct radius_msg * accounting_msg(struct hostapd_data *hapd,
goto fail;
}
if (!radius_msg_add_attr_int32(msg, RADIUS_ATTR_ACCT_AUTHENTIC,
if (!hostapd_config_get_radius_attr(hapd->conf->radius_acct_req_attr,
RADIUS_ATTR_ACCT_AUTHENTIC) &&
!radius_msg_add_attr_int32(msg, RADIUS_ATTR_ACCT_AUTHENTIC,
hapd->conf->ieee802_1x ?
RADIUS_ACCT_AUTHENTIC_RADIUS :
RADIUS_ACCT_AUTHENTIC_LOCAL)) {
@ -82,7 +79,17 @@ static struct radius_msg * accounting_msg(struct hostapd_data *hapd,
}
if (sta) {
/* Use 802.1X identity if available */
val = ieee802_1x_get_identity(sta->eapol_sm, &len);
/* Use RADIUS ACL identity if 802.1X provides no identity */
if (!val && sta->identity) {
val = (u8 *) sta->identity;
len = os_strlen(sta->identity);
}
/* Use STA MAC if neither 802.1X nor RADIUS ACL provided
* identity */
if (!val) {
os_snprintf(buf, sizeof(buf), RADIUS_ADDR_FORMAT,
MAC2STR(sta->addr));
@ -97,70 +104,11 @@ static struct radius_msg * accounting_msg(struct hostapd_data *hapd,
}
}
if (hapd->conf->own_ip_addr.af == AF_INET &&
!radius_msg_add_attr(msg, RADIUS_ATTR_NAS_IP_ADDRESS,
(u8 *) &hapd->conf->own_ip_addr.u.v4, 4)) {
printf("Could not add NAS-IP-Address\n");
if (add_common_radius_attr(hapd, hapd->conf->radius_acct_req_attr, sta,
msg) < 0)
goto fail;
}
#ifdef CONFIG_IPV6
if (hapd->conf->own_ip_addr.af == AF_INET6 &&
!radius_msg_add_attr(msg, RADIUS_ATTR_NAS_IPV6_ADDRESS,
(u8 *) &hapd->conf->own_ip_addr.u.v6, 16)) {
printf("Could not add NAS-IPv6-Address\n");
goto fail;
}
#endif /* CONFIG_IPV6 */
if (hapd->conf->nas_identifier &&
!radius_msg_add_attr(msg, RADIUS_ATTR_NAS_IDENTIFIER,
(u8 *) hapd->conf->nas_identifier,
os_strlen(hapd->conf->nas_identifier))) {
printf("Could not add NAS-Identifier\n");
goto fail;
}
if (sta &&
!radius_msg_add_attr_int32(msg, RADIUS_ATTR_NAS_PORT, sta->aid)) {
printf("Could not add NAS-Port\n");
goto fail;
}
os_snprintf(buf, sizeof(buf), RADIUS_802_1X_ADDR_FORMAT ":%s",
MAC2STR(hapd->own_addr), hapd->conf->ssid.ssid);
if (!radius_msg_add_attr(msg, RADIUS_ATTR_CALLED_STATION_ID,
(u8 *) buf, os_strlen(buf))) {
printf("Could not add Called-Station-Id\n");
goto fail;
}
if (sta) {
os_snprintf(buf, sizeof(buf), RADIUS_802_1X_ADDR_FORMAT,
MAC2STR(sta->addr));
if (!radius_msg_add_attr(msg, RADIUS_ATTR_CALLING_STATION_ID,
(u8 *) buf, os_strlen(buf))) {
printf("Could not add Calling-Station-Id\n");
goto fail;
}
if (!radius_msg_add_attr_int32(
msg, RADIUS_ATTR_NAS_PORT_TYPE,
RADIUS_NAS_PORT_TYPE_IEEE_802_11)) {
printf("Could not add NAS-Port-Type\n");
goto fail;
}
os_snprintf(buf, sizeof(buf), "CONNECT %d%sMbps %s",
radius_sta_rate(hapd, sta) / 2,
(radius_sta_rate(hapd, sta) & 1) ? ".5" : "",
radius_mode_txt(hapd));
if (!radius_msg_add_attr(msg, RADIUS_ATTR_CONNECT_INFO,
(u8 *) buf, os_strlen(buf))) {
printf("Could not add Connect-Info\n");
goto fail;
}
for (i = 0; ; i++) {
val = ieee802_1x_get_radius_class(sta->eapol_sm, &len,
i);
@ -173,6 +121,24 @@ static struct radius_msg * accounting_msg(struct hostapd_data *hapd,
goto fail;
}
}
b = ieee802_1x_get_radius_cui(sta->eapol_sm);
if (b &&
!radius_msg_add_attr(msg,
RADIUS_ATTR_CHARGEABLE_USER_IDENTITY,
wpabuf_head(b), wpabuf_len(b))) {
wpa_printf(MSG_ERROR, "Could not add CUI");
goto fail;
}
if (!b && sta->radius_cui &&
!radius_msg_add_attr(msg,
RADIUS_ATTR_CHARGEABLE_USER_IDENTITY,
(u8 *) sta->radius_cui,
os_strlen(sta->radius_cui))) {
wpa_printf(MSG_ERROR, "Could not add CUI from ACL");
goto fail;
}
}
return msg;
@ -242,7 +208,6 @@ void accounting_sta_start(struct hostapd_data *hapd, struct sta_info *sta)
if (sta->acct_session_started)
return;
accounting_sta_get_id(hapd, sta);
hostapd_logger(hapd, sta->addr, HOSTAPD_MODULE_RADIUS,
HOSTAPD_LEVEL_INFO,
"starting accounting session %08X-%08X",
@ -381,7 +346,8 @@ static void accounting_sta_report(struct hostapd_data *hapd,
* @hapd: hostapd BSS data
* @sta: The station
*/
void accounting_sta_interim(struct hostapd_data *hapd, struct sta_info *sta)
static void accounting_sta_interim(struct hostapd_data *hapd,
struct sta_info *sta)
{
if (sta->acct_session_started)
accounting_sta_report(hapd, sta, 0);
@ -408,7 +374,7 @@ void accounting_sta_stop(struct hostapd_data *hapd, struct sta_info *sta)
}
static void accounting_sta_get_id(struct hostapd_data *hapd,
void accounting_sta_get_id(struct hostapd_data *hapd,
struct sta_info *sta)
{
sta->acct_session_id_lo = hapd->acct_session_id_lo++;

View File

@ -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);

View File

@ -1,15 +1,9 @@
/*
* hostapd / Configuration helper functions
* Copyright (c) 2003-2009, Jouni Malinen <j@w1.fi>
* Copyright (c) 2003-2012, Jouni Malinen <j@w1.fi>
*
* This program is free software; you can redistribute it and/or modify
* it under the terms of the GNU General Public License version 2 as
* published by the Free Software Foundation.
*
* Alternatively, this software may be distributed under the terms of BSD
* license.
*
* See README and COPYING for more details.
* This software may be distributed under the terms of the BSD license.
* See README for more details.
*/
#include "utils/includes.h"
@ -93,6 +87,8 @@ void hostapd_config_defaults_bss(struct hostapd_bss_config *bss)
#ifdef CONFIG_IEEE80211R
bss->ft_over_ds = 1;
#endif /* CONFIG_IEEE80211R */
bss->radius_das_time_window = 300;
}
@ -108,9 +104,9 @@ struct hostapd_config * hostapd_config_defaults(void)
const struct hostapd_wmm_ac_params ac_be =
{ aCWmin, aCWmax, 3, 0, 0 }; /* best effort traffic */
const struct hostapd_wmm_ac_params ac_vi = /* video traffic */
{ aCWmin - 1, aCWmin, 2, 3000 / 32, 1 };
{ aCWmin - 1, aCWmin, 2, 3000 / 32, 0 };
const struct hostapd_wmm_ac_params ac_vo = /* voice traffic */
{ aCWmin - 2, aCWmin - 1, 2, 1500 / 32, 1 };
{ aCWmin - 2, aCWmin - 1, 2, 1500 / 32, 0 };
const struct hostapd_tx_queue_params txq_bk =
{ 7, ecw2cw(aCWmin), ecw2cw(aCWmax), 0 };
const struct hostapd_tx_queue_params txq_be =
@ -162,6 +158,9 @@ struct hostapd_config * hostapd_config_defaults(void)
conf->ht_capab = HT_CAP_INFO_SMPS_DISABLED;
conf->ap_table_max_size = 255;
conf->ap_table_expiration_time = 60;
return conf;
}
@ -342,6 +341,30 @@ static void hostapd_config_free_radius(struct hostapd_radius_server *servers,
}
struct hostapd_radius_attr *
hostapd_config_get_radius_attr(struct hostapd_radius_attr *attr, u8 type)
{
for (; attr; attr = attr->next) {
if (attr->type == type)
return attr;
}
return NULL;
}
static void hostapd_config_free_radius_attr(struct hostapd_radius_attr *attr)
{
struct hostapd_radius_attr *prev;
while (attr) {
prev = attr;
attr = attr->next;
wpabuf_free(prev->val);
os_free(prev);
}
}
static void hostapd_config_free_eap_user(struct hostapd_eap_user *user)
{
os_free(user->identity);
@ -388,6 +411,7 @@ static void hostapd_config_free_bss(struct hostapd_bss_config *conf)
user = user->next;
hostapd_config_free_eap_user(prev_user);
}
os_free(conf->eap_user_sqlite);
os_free(conf->dump_log_name);
os_free(conf->eap_req_id_text);
@ -398,6 +422,8 @@ static void hostapd_config_free_bss(struct hostapd_bss_config *conf)
conf->radius->num_auth_servers);
hostapd_config_free_radius(conf->radius->acct_servers,
conf->radius->num_acct_servers);
hostapd_config_free_radius_attr(conf->radius_auth_req_attr);
hostapd_config_free_radius_attr(conf->radius_acct_req_attr);
os_free(conf->rsn_preauth_interfaces);
os_free(conf->ctrl_interface);
os_free(conf->ca_cert);
@ -412,6 +438,7 @@ static void hostapd_config_free_bss(struct hostapd_bss_config *conf)
os_free(conf->radius_server_clients);
os_free(conf->test_socket);
os_free(conf->radius);
os_free(conf->radius_das_shared_secret);
hostapd_config_free_vlan(conf);
if (conf->ssid.dyn_vlan_keys) {
struct hostapd_ssid *ssid = &conf->ssid;
@ -468,9 +495,30 @@ static void hostapd_config_free_bss(struct hostapd_bss_config *conf)
os_free(conf->model_description);
os_free(conf->model_url);
os_free(conf->upc);
wpabuf_free(conf->wps_nfc_dh_pubkey);
wpabuf_free(conf->wps_nfc_dh_privkey);
wpabuf_free(conf->wps_nfc_dev_pw);
#endif /* CONFIG_WPS */
os_free(conf->roaming_consortium);
os_free(conf->venue_name);
os_free(conf->nai_realm_data);
os_free(conf->network_auth_type);
os_free(conf->anqp_3gpp_cell_net);
os_free(conf->domain_name);
#ifdef CONFIG_RADIUS_TEST
os_free(conf->dump_msk_file);
#endif /* CONFIG_RADIUS_TEST */
#ifdef CONFIG_HS20
os_free(conf->hs20_oper_friendly_name);
os_free(conf->hs20_wan_metrics);
os_free(conf->hs20_connection_capability);
os_free(conf->hs20_operating_class);
#endif /* CONFIG_HS20 */
wpabuf_free(conf->vendor_elements);
}
@ -575,57 +623,3 @@ const u8 * hostapd_get_psk(const struct hostapd_bss_config *conf,
return NULL;
}
const struct hostapd_eap_user *
hostapd_get_eap_user(const struct hostapd_bss_config *conf, const u8 *identity,
size_t identity_len, int phase2)
{
struct hostapd_eap_user *user = conf->eap_user;
#ifdef CONFIG_WPS
if (conf->wps_state && identity_len == WSC_ID_ENROLLEE_LEN &&
os_memcmp(identity, WSC_ID_ENROLLEE, WSC_ID_ENROLLEE_LEN) == 0) {
static struct hostapd_eap_user wsc_enrollee;
os_memset(&wsc_enrollee, 0, sizeof(wsc_enrollee));
wsc_enrollee.methods[0].method = eap_server_get_type(
"WSC", &wsc_enrollee.methods[0].vendor);
return &wsc_enrollee;
}
if (conf->wps_state && identity_len == WSC_ID_REGISTRAR_LEN &&
os_memcmp(identity, WSC_ID_REGISTRAR, WSC_ID_REGISTRAR_LEN) == 0) {
static struct hostapd_eap_user wsc_registrar;
os_memset(&wsc_registrar, 0, sizeof(wsc_registrar));
wsc_registrar.methods[0].method = eap_server_get_type(
"WSC", &wsc_registrar.methods[0].vendor);
wsc_registrar.password = (u8 *) conf->ap_pin;
wsc_registrar.password_len = conf->ap_pin ?
os_strlen(conf->ap_pin) : 0;
return &wsc_registrar;
}
#endif /* CONFIG_WPS */
while (user) {
if (!phase2 && user->identity == NULL) {
/* Wildcard match */
break;
}
if (user->phase2 == !!phase2 && user->wildcard_prefix &&
identity_len >= user->identity_len &&
os_memcmp(user->identity, identity, user->identity_len) ==
0) {
/* Wildcard prefix match */
break;
}
if (user->phase2 == !!phase2 &&
user->identity_len == identity_len &&
os_memcmp(user->identity, identity, identity_len) == 0)
break;
user = user->next;
}
return user;
}

View File

@ -1,15 +1,9 @@
/*
* hostapd / Configuration definitions and helpers functions
* Copyright (c) 2003-2009, Jouni Malinen <j@w1.fi>
* Copyright (c) 2003-2012, Jouni Malinen <j@w1.fi>
*
* This program is free software; you can redistribute it and/or modify
* it under the terms of the GNU General Public License version 2 as
* published by the Free Software Foundation.
*
* Alternatively, this software may be distributed under the terms of BSD
* license.
*
* See README and COPYING for more details.
* This software may be distributed under the terms of the BSD license.
* See README for more details.
*/
#ifndef HOSTAPD_CONFIG_H
@ -18,6 +12,7 @@
#include "common/defs.h"
#include "ip_addr.h"
#include "common/wpa_common.h"
#include "common/ieee802_11_common.h"
#include "wps/wps.h"
#define MAX_STA_COUNT 2007
@ -54,9 +49,10 @@ typedef enum hostap_security_policy {
} secpolicy;
struct hostapd_ssid {
char ssid[HOSTAPD_MAX_SSID_LEN + 1];
u8 ssid[HOSTAPD_MAX_SSID_LEN];
size_t ssid_len;
int ssid_set;
unsigned int ssid_set:1;
unsigned int utf8_ssid:1;
char vlan[IFNAMSIZ + 1];
secpolicy security_policy;
@ -71,6 +67,10 @@ struct hostapd_ssid {
#define DYNAMIC_VLAN_OPTIONAL 1
#define DYNAMIC_VLAN_REQUIRED 2
int dynamic_vlan;
#define DYNAMIC_VLAN_NAMING_WITHOUT_DEVICE 0
#define DYNAMIC_VLAN_NAMING_WITH_DEVICE 1
#define DYNAMIC_VLAN_NAMING_END 2
int vlan_naming;
#ifdef CONFIG_FULL_DYNAMIC_VLAN
char *vlan_tagged_interface;
#endif /* CONFIG_FULL_DYNAMIC_VLAN */
@ -97,6 +97,11 @@ struct hostapd_vlan {
};
#define PMK_LEN 32
struct hostapd_sta_wpa_psk_short {
struct hostapd_sta_wpa_psk_short *next;
u8 psk[PMK_LEN];
};
struct hostapd_wpa_psk {
struct hostapd_wpa_psk *next;
int group;
@ -104,7 +109,6 @@ struct hostapd_wpa_psk {
u8 addr[ETH_ALEN];
};
#define EAP_USER_MAX_METHODS 8
struct hostapd_eap_user {
struct hostapd_eap_user *next;
u8 *identity;
@ -112,7 +116,7 @@ struct hostapd_eap_user {
struct {
int vendor;
u32 method;
} methods[EAP_USER_MAX_METHODS];
} methods[EAP_MAX_METHODS];
u8 *password;
size_t password_len;
int phase2;
@ -123,6 +127,12 @@ struct hostapd_eap_user {
int ttls_auth; /* EAP_TTLS_AUTH_* bitfield */
};
struct hostapd_radius_attr {
u8 type;
struct wpabuf *val;
struct hostapd_radius_attr *next;
};
#define NUM_TX_QUEUES 4
@ -133,14 +143,6 @@ struct hostapd_tx_queue_params {
int burst; /* maximum burst time in 0.1 ms, i.e., 10 = 1 ms */
};
struct hostapd_wmm_ac_params {
int cwmin;
int cwmax;
int aifs;
int txop_limit; /* in units of 32us */
int admission_control_mandatory;
};
#define MAX_ROAMING_CONSORTIUM_LEN 15
@ -149,6 +151,29 @@ struct hostapd_roaming_consortium {
u8 oi[MAX_ROAMING_CONSORTIUM_LEN];
};
struct hostapd_lang_string {
u8 lang[3];
u8 name_len;
u8 name[252];
};
#define MAX_NAI_REALMS 10
#define MAX_NAI_REALMLEN 255
#define MAX_NAI_EAP_METHODS 5
#define MAX_NAI_AUTH_TYPES 4
struct hostapd_nai_realm_data {
u8 encoding;
char realm_buf[MAX_NAI_REALMLEN + 1];
char *realm[MAX_NAI_REALMS];
u8 eap_method_count;
struct hostapd_nai_realm_eap {
u8 eap_method;
u8 num_auths;
u8 auth_id[MAX_NAI_AUTH_TYPES];
u8 auth_val[MAX_NAI_AUTH_TYPES];
} eap_method[MAX_NAI_EAP_METHODS];
};
/**
* struct hostapd_bss_config - Per-BSS configuration
*/
@ -173,11 +198,21 @@ struct hostapd_bss_config {
int eap_server; /* Use internal EAP server instead of external
* RADIUS server */
struct hostapd_eap_user *eap_user;
char *eap_user_sqlite;
char *eap_sim_db;
struct hostapd_ip_addr own_ip_addr;
char *nas_identifier;
struct hostapd_radius_servers *radius;
int acct_interim_interval;
int radius_request_cui;
struct hostapd_radius_attr *radius_auth_req_attr;
struct hostapd_radius_attr *radius_acct_req_attr;
int radius_das_port;
unsigned int radius_das_time_window;
int radius_das_require_event_timestamp;
struct hostapd_ip_addr radius_das_client_addr;
u8 *radius_das_shared_secret;
size_t radius_das_shared_secret_len;
struct hostapd_ssid ssid;
@ -220,6 +255,11 @@ struct hostapd_bss_config {
/* dot11AssociationSAQueryRetryTimeout (in TUs) */
int assoc_sa_query_retry_timeout;
#endif /* CONFIG_IEEE80211W */
enum {
PSK_RADIUS_IGNORED = 0,
PSK_RADIUS_ACCEPTED = 1,
PSK_RADIUS_REQUIRED = 2
} wpa_psk_radius;
int wpa_pairwise;
int wpa_group;
int wpa_group_rekey;
@ -325,6 +365,10 @@ struct hostapd_bss_config {
char *model_url;
char *upc;
struct wpabuf *wps_vendor_ext[MAX_WPS_VENDOR_EXTENSIONS];
int wps_nfc_dev_pw_id;
struct wpabuf *wps_nfc_dh_pubkey;
struct wpabuf *wps_nfc_dh_privkey;
struct wpabuf *wps_nfc_dev_pw;
#endif /* CONFIG_WPS */
int pbc_in_m1;
@ -336,15 +380,19 @@ struct hostapd_bss_config {
int p2p;
int disassoc_low_ack;
int skip_inactivity_poll;
#define TDLS_PROHIBIT BIT(0)
#define TDLS_PROHIBIT_CHAN_SWITCH BIT(1)
int tdls;
int disable_11n;
int disable_11ac;
/* IEEE 802.11v */
int time_advertisement;
char *time_zone;
int wnm_sleep_mode;
int bss_transition;
/* IEEE 802.11u - Interworking */
int interworking;
@ -361,6 +409,52 @@ struct hostapd_bss_config {
/* IEEE 802.11u - Roaming Consortium list */
unsigned int roaming_consortium_count;
struct hostapd_roaming_consortium *roaming_consortium;
/* IEEE 802.11u - Venue Name duples */
unsigned int venue_name_count;
struct hostapd_lang_string *venue_name;
/* IEEE 802.11u - Network Authentication Type */
u8 *network_auth_type;
size_t network_auth_type_len;
/* IEEE 802.11u - IP Address Type Availability */
u8 ipaddr_type_availability;
u8 ipaddr_type_configured;
/* IEEE 802.11u - 3GPP Cellular Network */
u8 *anqp_3gpp_cell_net;
size_t anqp_3gpp_cell_net_len;
/* IEEE 802.11u - Domain Name */
u8 *domain_name;
size_t domain_name_len;
unsigned int nai_realm_count;
struct hostapd_nai_realm_data *nai_realm_data;
u16 gas_comeback_delay;
int gas_frag_limit;
#ifdef CONFIG_HS20
int hs20;
int disable_dgaf;
unsigned int hs20_oper_friendly_name_count;
struct hostapd_lang_string *hs20_oper_friendly_name;
u8 *hs20_wan_metrics;
u8 *hs20_connection_capability;
size_t hs20_connection_capability_len;
u8 *hs20_operating_class;
u8 hs20_operating_class_len;
#endif /* CONFIG_HS20 */
u8 wps_rf_bands; /* RF bands for WPS (WPS_RF_*) */
#ifdef CONFIG_RADIUS_TEST
char *dump_msk_file;
#endif /* CONFIG_RADIUS_TEST */
struct wpabuf *vendor_elements;
};
@ -415,6 +509,12 @@ struct hostapd_config {
int ieee80211n;
int secondary_channel;
int require_ht;
u32 vht_capab;
int ieee80211ac;
int require_vht;
u8 vht_oper_chwidth;
u8 vht_oper_centr_freq_seg0_idx;
u8 vht_oper_centr_freq_seg1_idx;
};
@ -433,8 +533,7 @@ const u8 * hostapd_get_psk(const struct hostapd_bss_config *conf,
int hostapd_setup_wpa_psk(struct hostapd_bss_config *conf);
const char * hostapd_get_vlan_id_ifname(struct hostapd_vlan *vlan,
int vlan_id);
const struct hostapd_eap_user *
hostapd_get_eap_user(const struct hostapd_bss_config *conf, const u8 *identity,
size_t identity_len, int phase2);
struct hostapd_radius_attr *
hostapd_config_get_radius_attr(struct hostapd_radius_attr *attr, u8 type);
#endif /* HOSTAPD_CONFIG_H */

View File

@ -2,14 +2,8 @@
* hostapd - Driver operations
* Copyright (c) 2009-2010, Jouni Malinen <j@w1.fi>
*
* This program is free software; you can redistribute it and/or modify
* it under the terms of the GNU General Public License version 2 as
* published by the Free Software Foundation.
*
* Alternatively, this software may be distributed under the terms of BSD
* license.
*
* See README and COPYING for more details.
* This software may be distributed under the terms of the BSD license.
* See README for more details.
*/
#include "utils/includes.h"
@ -18,11 +12,13 @@
#include "drivers/driver.h"
#include "common/ieee802_11_defs.h"
#include "wps/wps.h"
#include "p2p/p2p.h"
#include "hostapd.h"
#include "ieee802_11.h"
#include "sta_info.h"
#include "ap_config.h"
#include "p2p_hostapd.h"
#include "hs20.h"
#include "ap_drv_ops.h"
@ -153,6 +149,30 @@ int hostapd_build_ap_extra_ies(struct hostapd_data *hapd,
}
#endif /* CONFIG_P2P_MANAGER */
#ifdef CONFIG_WIFI_DISPLAY
if (hapd->p2p_group) {
struct wpabuf *a;
a = p2p_group_assoc_resp_ie(hapd->p2p_group, P2P_SC_SUCCESS);
if (a && wpabuf_resize(&assocresp, wpabuf_len(a)) == 0)
wpabuf_put_buf(assocresp, a);
wpabuf_free(a);
}
#endif /* CONFIG_WIFI_DISPLAY */
#ifdef CONFIG_HS20
pos = buf;
pos = hostapd_eid_hs20_indication(hapd, pos);
if (pos != buf) {
if (wpabuf_resize(&beacon, pos - buf) != 0)
goto fail;
wpabuf_put_data(beacon, buf, pos - buf);
if (wpabuf_resize(&proberesp, pos - buf) != 0)
goto fail;
wpabuf_put_data(proberesp, buf, pos - buf);
}
#endif /* CONFIG_HS20 */
*beacon_ret = beacon;
*proberesp_ret = proberesp;
*assocresp_ret = assocresp;
@ -318,7 +338,7 @@ int hostapd_sta_add(struct hostapd_data *hapd,
const u8 *supp_rates, size_t supp_rates_len,
u16 listen_interval,
const struct ieee80211_ht_capabilities *ht_capab,
u32 flags)
u32 flags, u8 qosinfo)
{
struct hostapd_sta_add_params params;
@ -336,6 +356,7 @@ int hostapd_sta_add(struct hostapd_data *hapd,
params.listen_interval = listen_interval;
params.ht_capabilities = ht_capab;
params.flags = hostapd_sta_flags_to_drv(flags);
params.qosinfo = qosinfo;
return hapd->driver->sta_add(hapd->drv_priv, &params);
}
@ -475,16 +496,6 @@ int hostapd_sta_set_flags(struct hostapd_data *hapd, u8 *addr,
}
int hostapd_set_rate_sets(struct hostapd_data *hapd, int *supp_rates,
int *basic_rates, int mode)
{
if (hapd->driver == NULL || hapd->driver->set_rate_sets == NULL)
return 0;
return hapd->driver->set_rate_sets(hapd->drv_priv, supp_rates,
basic_rates, mode);
}
int hostapd_set_country(struct hostapd_data *hapd, const char *country)
{
if (hapd->driver == NULL ||
@ -573,11 +584,11 @@ int hostapd_drv_set_key(const char *ifname, struct hostapd_data *hapd,
int hostapd_drv_send_mlme(struct hostapd_data *hapd,
const void *msg, size_t len)
const void *msg, size_t len, int noack)
{
if (hapd->driver == NULL || hapd->driver->send_mlme == NULL)
return 0;
return hapd->driver->send_mlme(hapd->drv_priv, msg, len);
return hapd->driver->send_mlme(hapd->drv_priv, msg, len, noack);
}
@ -599,3 +610,25 @@ int hostapd_drv_sta_disassoc(struct hostapd_data *hapd,
return hapd->driver->sta_disassoc(hapd->drv_priv, hapd->own_addr, addr,
reason);
}
int hostapd_drv_wnm_oper(struct hostapd_data *hapd, enum wnm_oper oper,
const u8 *peer, u8 *buf, u16 *buf_len)
{
if (hapd->driver == NULL || hapd->driver->wnm_oper == NULL)
return 0;
return hapd->driver->wnm_oper(hapd->drv_priv, oper, peer, buf,
buf_len);
}
int hostapd_drv_send_action(struct hostapd_data *hapd, unsigned int freq,
unsigned int wait, const u8 *dst, const u8 *data,
size_t len)
{
if (hapd->driver == NULL || hapd->driver->send_action == NULL)
return 0;
return hapd->driver->send_action(hapd->drv_priv, freq, wait, dst,
hapd->own_addr, hapd->own_addr, data,
len, 0);
}

View File

@ -2,14 +2,8 @@
* hostapd - Driver operations
* Copyright (c) 2009, Jouni Malinen <j@w1.fi>
*
* This program is free software; you can redistribute it and/or modify
* it under the terms of the GNU General Public License version 2 as
* published by the Free Software Foundation.
*
* Alternatively, this software may be distributed under the terms of BSD
* license.
*
* See README and COPYING for more details.
* This software may be distributed under the terms of the BSD license.
* See README for more details.
*/
#ifndef AP_DRV_OPS
@ -43,7 +37,7 @@ int hostapd_sta_add(struct hostapd_data *hapd,
const u8 *supp_rates, size_t supp_rates_len,
u16 listen_interval,
const struct ieee80211_ht_capabilities *ht_capab,
u32 flags);
u32 flags, u8 qosinfo);
int hostapd_set_privacy(struct hostapd_data *hapd, int enabled);
int hostapd_set_generic_elem(struct hostapd_data *hapd, const u8 *elem,
size_t elem_len);
@ -66,8 +60,6 @@ int hostapd_set_rts(struct hostapd_data *hapd, int rts);
int hostapd_set_frag(struct hostapd_data *hapd, int frag);
int hostapd_sta_set_flags(struct hostapd_data *hapd, u8 *addr,
int total_flags, int flags_or, int flags_and);
int hostapd_set_rate_sets(struct hostapd_data *hapd, int *supp_rates,
int *basic_rates, int mode);
int hostapd_set_country(struct hostapd_data *hapd, const char *country);
int hostapd_set_tx_queue_params(struct hostapd_data *hapd, int queue, int aifs,
int cw_min, int cw_max, int burst_time);
@ -89,11 +81,14 @@ int hostapd_drv_set_key(const char *ifname,
const u8 *seq, size_t seq_len,
const u8 *key, size_t key_len);
int hostapd_drv_send_mlme(struct hostapd_data *hapd,
const void *msg, size_t len);
const void *msg, size_t len, int noack);
int hostapd_drv_sta_deauth(struct hostapd_data *hapd,
const u8 *addr, int reason);
int hostapd_drv_sta_disassoc(struct hostapd_data *hapd,
const u8 *addr, int reason);
int hostapd_drv_send_action(struct hostapd_data *hapd, unsigned int freq,
unsigned int wait, const u8 *dst, const u8 *data,
size_t len);
int hostapd_add_sta_node(struct hostapd_data *hapd, const u8 *addr,
u16 auth_alg);
int hostapd_sta_auth(struct hostapd_data *hapd, const u8 *addr,
@ -106,6 +101,10 @@ int hostapd_add_tspec(struct hostapd_data *hapd, const u8 *addr,
#include "drivers/driver.h"
int hostapd_drv_wnm_oper(struct hostapd_data *hapd,
enum wnm_oper oper, const u8 *peer,
u8 *buf, u16 *buf_len);
static inline int hostapd_drv_set_countermeasures(struct hostapd_data *hapd,
int enabled)
{

View File

@ -4,14 +4,8 @@
* Copyright (c) 2003-2004, Instant802 Networks, Inc.
* Copyright (c) 2006, Devicescape Software, Inc.
*
* This program is free software; you can redistribute it and/or modify
* it under the terms of the GNU General Public License version 2 as
* published by the Free Software Foundation.
*
* Alternatively, this software may be distributed under the terms of BSD
* license.
*
* See README and COPYING for more details.
* This software may be distributed under the terms of the BSD license.
* See README for more details.
*/
#include "utils/includes.h"
@ -257,23 +251,9 @@ void ap_list_process_beacon(struct hostapd_iface *iface,
ap->ssid_len = len;
}
os_memset(ap->supported_rates, 0, WLAN_SUPP_RATES_MAX);
len = 0;
if (elems->supp_rates) {
len = elems->supp_rates_len;
if (len > WLAN_SUPP_RATES_MAX)
len = WLAN_SUPP_RATES_MAX;
os_memcpy(ap->supported_rates, elems->supp_rates, len);
}
if (elems->ext_supp_rates) {
int len2;
if (len + elems->ext_supp_rates_len > WLAN_SUPP_RATES_MAX)
len2 = WLAN_SUPP_RATES_MAX - len;
else
len2 = elems->ext_supp_rates_len;
os_memcpy(ap->supported_rates + len, elems->ext_supp_rates,
len2);
}
merge_byte_arrays(ap->supported_rates, WLAN_SUPP_RATES_MAX,
elems->supp_rates, elems->supp_rates_len,
elems->ext_supp_rates, elems->ext_supp_rates_len);
ap->wpa = elems->wpa_ie != NULL;
@ -295,10 +275,8 @@ void ap_list_process_beacon(struct hostapd_iface *iface,
ap->num_beacons++;
os_get_time(&now);
ap->last_beacon = now.sec;
if (fi) {
ap->ssi_signal = fi->ssi_signal;
if (fi)
ap->datarate = fi->datarate;
}
if (!new_ap && ap != iface->ap_list) {
/* move AP entry into the beginning of the list so that the
@ -326,7 +304,7 @@ void ap_list_process_beacon(struct hostapd_iface *iface,
#endif /* CONFIG_IEEE80211N */
if (set_beacon)
ieee802_11_set_beacons(iface);
ieee802_11_update_beacons(iface);
}
@ -381,7 +359,7 @@ static void ap_list_timer(void *eloop_ctx, void *timeout_ctx)
}
if (set_beacon)
ieee802_11_set_beacons(iface);
ieee802_11_update_beacons(iface);
}

View File

@ -4,14 +4,8 @@
* Copyright (c) 2003-2004, Instant802 Networks, Inc.
* Copyright (c) 2006, Devicescape Software, Inc.
*
* This program is free software; you can redistribute it and/or modify
* it under the terms of the GNU General Public License version 2 as
* published by the Free Software Foundation.
*
* Alternatively, this software may be distributed under the terms of BSD
* license.
*
* See README and COPYING for more details.
* This software may be distributed under the terms of the BSD license.
* See README for more details.
*/
#ifndef AP_LIST_H
@ -40,7 +34,6 @@ struct ap_info {
int channel;
int datarate; /* in 100 kbps */
int ssi_signal;
int ht_support;

View File

@ -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"

View File

@ -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

View File

@ -2,14 +2,8 @@
* Authentication server setup
* Copyright (c) 2002-2009, Jouni Malinen <j@w1.fi>
*
* This program is free software; you can redistribute it and/or modify
* it under the terms of the GNU General Public License version 2 as
* published by the Free Software Foundation.
*
* Alternatively, this software may be distributed under the terms of BSD
* license.
*
* See README and COPYING for more details.
* This software may be distributed under the terms of the BSD license.
* See README for more details.
*/
#include "utils/includes.h"
@ -60,7 +54,7 @@ static int hostapd_radius_get_eap_user(void *ctx, const u8 *identity,
struct eap_user *user)
{
const struct hostapd_eap_user *eap_user;
int i, count;
int i;
eap_user = hostapd_get_eap_user(ctx, identity, identity_len, phase2);
if (eap_user == NULL)
@ -70,10 +64,7 @@ static int hostapd_radius_get_eap_user(void *ctx, const u8 *identity,
return 0;
os_memset(user, 0, sizeof(*user));
count = EAP_USER_MAX_METHODS;
if (count > EAP_MAX_METHODS)
count = EAP_MAX_METHODS;
for (i = 0; i < count; i++) {
for (i = 0; i < EAP_MAX_METHODS; i++) {
user->methods[i].vendor = eap_user->methods[i].vendor;
user->methods[i].method = eap_user->methods[i].method;
}
@ -101,7 +92,7 @@ static int hostapd_setup_radius_srv(struct hostapd_data *hapd)
os_memset(&srv, 0, sizeof(srv));
srv.client_file = conf->radius_server_clients;
srv.auth_port = conf->radius_server_auth_port;
srv.conf_ctx = conf;
srv.conf_ctx = hapd;
srv.eap_sim_db_priv = hapd->eap_sim_db_priv;
srv.ssl_ctx = hapd->ssl_ctx;
srv.msg_ctx = hapd->msg_ctx;
@ -120,6 +111,9 @@ static int hostapd_setup_radius_srv(struct hostapd_data *hapd)
srv.eap_req_id_text = conf->eap_req_id_text;
srv.eap_req_id_text_len = conf->eap_req_id_text_len;
srv.pwd_group = conf->pwd_group;
#ifdef CONFIG_RADIUS_TEST
srv.dump_msk_file = conf->dump_msk_file;
#endif /* CONFIG_RADIUS_TEST */
hapd->radius_srv = radius_server_init(&srv);
if (hapd->radius_srv == NULL) {

View File

@ -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

View File

@ -2,7 +2,7 @@
* hostapd / IEEE 802.11 Management: Beacon and Probe Request/Response
* Copyright (c) 2002-2004, Instant802 Networks, Inc.
* Copyright (c) 2005-2006, Devicescape Software, Inc.
* Copyright (c) 2008-2009, Jouni Malinen <j@w1.fi>
* Copyright (c) 2008-2012, Jouni Malinen <j@w1.fi>
*
* This program is free software; you can redistribute it and/or modify
* it under the terms of the GNU General Public License version 2 as
@ -33,6 +33,7 @@
#include "p2p_hostapd.h"
#include "ap_drv_ops.h"
#include "beacon.h"
#include "hs20.h"
#ifdef NEED_AP_MLME
@ -186,18 +187,181 @@ static u8 * hostapd_eid_wpa(struct hostapd_data *hapd, u8 *eid, size_t len)
}
void handle_probe_req(struct hostapd_data *hapd,
const struct ieee80211_mgmt *mgmt, size_t len)
static u8 * hostapd_gen_probe_resp(struct hostapd_data *hapd,
struct sta_info *sta,
const struct ieee80211_mgmt *req,
int is_p2p, size_t *resp_len)
{
struct ieee80211_mgmt *resp;
struct ieee802_11_elems elems;
char *ssid;
u8 *pos, *epos;
const u8 *ie;
size_t ssid_len, ie_len;
struct sta_info *sta = NULL;
size_t buflen;
size_t i;
#define MAX_PROBERESP_LEN 768
buflen = MAX_PROBERESP_LEN;
#ifdef CONFIG_WPS
if (hapd->wps_probe_resp_ie)
buflen += wpabuf_len(hapd->wps_probe_resp_ie);
#endif /* CONFIG_WPS */
#ifdef CONFIG_P2P
if (hapd->p2p_probe_resp_ie)
buflen += wpabuf_len(hapd->p2p_probe_resp_ie);
#endif /* CONFIG_P2P */
if (hapd->conf->vendor_elements)
buflen += wpabuf_len(hapd->conf->vendor_elements);
resp = os_zalloc(buflen);
if (resp == NULL)
return NULL;
epos = ((u8 *) resp) + MAX_PROBERESP_LEN;
resp->frame_control = IEEE80211_FC(WLAN_FC_TYPE_MGMT,
WLAN_FC_STYPE_PROBE_RESP);
if (req)
os_memcpy(resp->da, req->sa, ETH_ALEN);
os_memcpy(resp->sa, hapd->own_addr, ETH_ALEN);
os_memcpy(resp->bssid, hapd->own_addr, ETH_ALEN);
resp->u.probe_resp.beacon_int =
host_to_le16(hapd->iconf->beacon_int);
/* hardware or low-level driver will setup seq_ctrl and timestamp */
resp->u.probe_resp.capab_info =
host_to_le16(hostapd_own_capab_info(hapd, sta, 1));
pos = resp->u.probe_resp.variable;
*pos++ = WLAN_EID_SSID;
*pos++ = hapd->conf->ssid.ssid_len;
os_memcpy(pos, hapd->conf->ssid.ssid, hapd->conf->ssid.ssid_len);
pos += hapd->conf->ssid.ssid_len;
/* Supported rates */
pos = hostapd_eid_supp_rates(hapd, pos);
/* DS Params */
pos = hostapd_eid_ds_params(hapd, pos);
pos = hostapd_eid_country(hapd, pos, epos - pos);
/* ERP Information element */
pos = hostapd_eid_erp_info(hapd, pos);
/* Extended supported rates */
pos = hostapd_eid_ext_supp_rates(hapd, pos);
/* RSN, MDIE, WPA */
pos = hostapd_eid_wpa(hapd, pos, epos - pos);
#ifdef CONFIG_IEEE80211N
pos = hostapd_eid_ht_capabilities(hapd, pos);
pos = hostapd_eid_ht_operation(hapd, pos);
#endif /* CONFIG_IEEE80211N */
pos = hostapd_eid_ext_capab(hapd, pos);
pos = hostapd_eid_time_adv(hapd, pos);
pos = hostapd_eid_time_zone(hapd, pos);
pos = hostapd_eid_interworking(hapd, pos);
pos = hostapd_eid_adv_proto(hapd, pos);
pos = hostapd_eid_roaming_consortium(hapd, pos);
#ifdef CONFIG_IEEE80211AC
pos = hostapd_eid_vht_capabilities(hapd, pos);
pos = hostapd_eid_vht_operation(hapd, pos);
#endif /* CONFIG_IEEE80211AC */
/* Wi-Fi Alliance WMM */
pos = hostapd_eid_wmm(hapd, pos);
#ifdef CONFIG_WPS
if (hapd->conf->wps_state && hapd->wps_probe_resp_ie) {
os_memcpy(pos, wpabuf_head(hapd->wps_probe_resp_ie),
wpabuf_len(hapd->wps_probe_resp_ie));
pos += wpabuf_len(hapd->wps_probe_resp_ie);
}
#endif /* CONFIG_WPS */
#ifdef CONFIG_P2P
if ((hapd->conf->p2p & P2P_ENABLED) && is_p2p &&
hapd->p2p_probe_resp_ie) {
os_memcpy(pos, wpabuf_head(hapd->p2p_probe_resp_ie),
wpabuf_len(hapd->p2p_probe_resp_ie));
pos += wpabuf_len(hapd->p2p_probe_resp_ie);
}
#endif /* CONFIG_P2P */
#ifdef CONFIG_P2P_MANAGER
if ((hapd->conf->p2p & (P2P_MANAGE | P2P_ENABLED | P2P_GROUP_OWNER)) ==
P2P_MANAGE)
pos = hostapd_eid_p2p_manage(hapd, pos);
#endif /* CONFIG_P2P_MANAGER */
#ifdef CONFIG_HS20
pos = hostapd_eid_hs20_indication(hapd, pos);
#endif /* CONFIG_HS20 */
if (hapd->conf->vendor_elements) {
os_memcpy(pos, wpabuf_head(hapd->conf->vendor_elements),
wpabuf_len(hapd->conf->vendor_elements));
pos += wpabuf_len(hapd->conf->vendor_elements);
}
*resp_len = pos - (u8 *) resp;
return (u8 *) resp;
}
enum ssid_match_result {
NO_SSID_MATCH,
EXACT_SSID_MATCH,
WILDCARD_SSID_MATCH
};
static enum ssid_match_result ssid_match(struct hostapd_data *hapd,
const u8 *ssid, size_t ssid_len,
const u8 *ssid_list,
size_t ssid_list_len)
{
const u8 *pos, *end;
int wildcard = 0;
if (ssid_len == 0)
wildcard = 1;
if (ssid_len == hapd->conf->ssid.ssid_len &&
os_memcmp(ssid, hapd->conf->ssid.ssid, ssid_len) == 0)
return EXACT_SSID_MATCH;
if (ssid_list == NULL)
return wildcard ? WILDCARD_SSID_MATCH : NO_SSID_MATCH;
pos = ssid_list;
end = ssid_list + ssid_list_len;
while (pos + 1 <= end) {
if (pos + 2 + pos[1] > end)
break;
if (pos[1] == 0)
wildcard = 1;
if (pos[1] == hapd->conf->ssid.ssid_len &&
os_memcmp(pos + 2, hapd->conf->ssid.ssid, pos[1]) == 0)
return EXACT_SSID_MATCH;
pos += 2 + pos[1];
}
return wildcard ? WILDCARD_SSID_MATCH : NO_SSID_MATCH;
}
void handle_probe_req(struct hostapd_data *hapd,
const struct ieee80211_mgmt *mgmt, size_t len,
int ssi_signal)
{
u8 *resp;
struct ieee802_11_elems elems;
const u8 *ie;
size_t ie_len;
struct sta_info *sta = NULL;
size_t i, resp_len;
int noack;
enum ssid_match_result res;
ie = mgmt->u.probe_req.variable;
if (len < IEEE80211_HDRLEN + sizeof(mgmt->u.probe_req))
@ -207,7 +371,7 @@ void handle_probe_req(struct hostapd_data *hapd,
for (i = 0; hapd->probereq_cb && i < hapd->num_probereq_cb; i++)
if (hapd->probereq_cb[i].cb(hapd->probereq_cb[i].ctx,
mgmt->sa, mgmt->da, mgmt->bssid,
ie, ie_len) > 0)
ie, ie_len, ssi_signal) > 0)
return;
if (!hapd->iconf->send_probe_response)
@ -219,9 +383,6 @@ void handle_probe_req(struct hostapd_data *hapd,
return;
}
ssid = NULL;
ssid_len = 0;
if ((!elems.ssid || !elems.supp_rates)) {
wpa_printf(MSG_DEBUG, "STA " MACSTR " sent probe request "
"without SSID or supported rates element",
@ -256,7 +417,8 @@ void handle_probe_req(struct hostapd_data *hapd,
}
#endif /* CONFIG_P2P */
if (hapd->conf->ignore_broadcast_ssid && elems.ssid_len == 0) {
if (hapd->conf->ignore_broadcast_ssid && elems.ssid_len == 0 &&
elems.ssid_list_len == 0) {
wpa_printf(MSG_MSGDUMP, "Probe Request from " MACSTR " for "
"broadcast SSID ignored", MAC2STR(mgmt->sa));
return;
@ -274,25 +436,21 @@ void handle_probe_req(struct hostapd_data *hapd,
}
#endif /* CONFIG_P2P */
if (elems.ssid_len == 0 ||
(elems.ssid_len == hapd->conf->ssid.ssid_len &&
os_memcmp(elems.ssid, hapd->conf->ssid.ssid, elems.ssid_len) ==
0)) {
ssid = hapd->conf->ssid.ssid;
ssid_len = hapd->conf->ssid.ssid_len;
res = ssid_match(hapd, elems.ssid, elems.ssid_len,
elems.ssid_list, elems.ssid_list_len);
if (res != NO_SSID_MATCH) {
if (sta)
sta->ssid_probe = &hapd->conf->ssid;
}
if (!ssid) {
} else {
if (!(mgmt->da[0] & 0x01)) {
char ssid_txt[33];
ieee802_11_print_ssid(ssid_txt, elems.ssid,
elems.ssid_len);
wpa_printf(MSG_MSGDUMP, "Probe Request from " MACSTR
" for foreign SSID '%s' (DA " MACSTR ")",
" for foreign SSID '%s' (DA " MACSTR ")%s",
MAC2STR(mgmt->sa), ssid_txt,
MAC2STR(mgmt->da));
MAC2STR(mgmt->da),
elems.ssid_list ? " (SSID list)" : "");
}
return;
}
@ -329,97 +487,20 @@ void handle_probe_req(struct hostapd_data *hapd,
/* TODO: verify that supp_rates contains at least one matching rate
* with AP configuration */
#define MAX_PROBERESP_LEN 768
buflen = MAX_PROBERESP_LEN;
#ifdef CONFIG_WPS
if (hapd->wps_probe_resp_ie)
buflen += wpabuf_len(hapd->wps_probe_resp_ie);
#endif /* CONFIG_WPS */
#ifdef CONFIG_P2P
if (hapd->p2p_probe_resp_ie)
buflen += wpabuf_len(hapd->p2p_probe_resp_ie);
#endif /* CONFIG_P2P */
resp = os_zalloc(buflen);
resp = hostapd_gen_probe_resp(hapd, sta, mgmt, elems.p2p != NULL,
&resp_len);
if (resp == NULL)
return;
epos = ((u8 *) resp) + MAX_PROBERESP_LEN;
resp->frame_control = IEEE80211_FC(WLAN_FC_TYPE_MGMT,
WLAN_FC_STYPE_PROBE_RESP);
os_memcpy(resp->da, mgmt->sa, ETH_ALEN);
os_memcpy(resp->sa, hapd->own_addr, ETH_ALEN);
/*
* If this is a broadcast probe request, apply no ack policy to avoid
* excessive retries.
*/
noack = !!(res == WILDCARD_SSID_MATCH &&
is_broadcast_ether_addr(mgmt->da));
os_memcpy(resp->bssid, hapd->own_addr, ETH_ALEN);
resp->u.probe_resp.beacon_int =
host_to_le16(hapd->iconf->beacon_int);
/* hardware or low-level driver will setup seq_ctrl and timestamp */
resp->u.probe_resp.capab_info =
host_to_le16(hostapd_own_capab_info(hapd, sta, 1));
pos = resp->u.probe_resp.variable;
*pos++ = WLAN_EID_SSID;
*pos++ = ssid_len;
os_memcpy(pos, ssid, ssid_len);
pos += ssid_len;
/* Supported rates */
pos = hostapd_eid_supp_rates(hapd, pos);
/* DS Params */
pos = hostapd_eid_ds_params(hapd, pos);
pos = hostapd_eid_country(hapd, pos, epos - pos);
/* ERP Information element */
pos = hostapd_eid_erp_info(hapd, pos);
/* Extended supported rates */
pos = hostapd_eid_ext_supp_rates(hapd, pos);
/* RSN, MDIE, WPA */
pos = hostapd_eid_wpa(hapd, pos, epos - pos);
#ifdef CONFIG_IEEE80211N
pos = hostapd_eid_ht_capabilities(hapd, pos);
pos = hostapd_eid_ht_operation(hapd, pos);
#endif /* CONFIG_IEEE80211N */
pos = hostapd_eid_ext_capab(hapd, pos);
pos = hostapd_eid_time_adv(hapd, pos);
pos = hostapd_eid_time_zone(hapd, pos);
pos = hostapd_eid_interworking(hapd, pos);
pos = hostapd_eid_adv_proto(hapd, pos);
pos = hostapd_eid_roaming_consortium(hapd, pos);
/* Wi-Fi Alliance WMM */
pos = hostapd_eid_wmm(hapd, pos);
#ifdef CONFIG_WPS
if (hapd->conf->wps_state && hapd->wps_probe_resp_ie) {
os_memcpy(pos, wpabuf_head(hapd->wps_probe_resp_ie),
wpabuf_len(hapd->wps_probe_resp_ie));
pos += wpabuf_len(hapd->wps_probe_resp_ie);
}
#endif /* CONFIG_WPS */
#ifdef CONFIG_P2P
if ((hapd->conf->p2p & P2P_ENABLED) && elems.p2p &&
hapd->p2p_probe_resp_ie) {
os_memcpy(pos, wpabuf_head(hapd->p2p_probe_resp_ie),
wpabuf_len(hapd->p2p_probe_resp_ie));
pos += wpabuf_len(hapd->p2p_probe_resp_ie);
}
#endif /* CONFIG_P2P */
#ifdef CONFIG_P2P_MANAGER
if ((hapd->conf->p2p & (P2P_MANAGE | P2P_ENABLED | P2P_GROUP_OWNER)) ==
P2P_MANAGE)
pos = hostapd_eid_p2p_manage(hapd, pos);
#endif /* CONFIG_P2P_MANAGER */
if (hostapd_drv_send_mlme(hapd, resp, pos - (u8 *) resp) < 0)
if (hostapd_drv_send_mlme(hapd, resp, resp_len, noack) < 0)
perror("handle_probe_req: send");
os_free(resp);
@ -429,6 +510,42 @@ void handle_probe_req(struct hostapd_data *hapd,
elems.ssid_len == 0 ? "broadcast" : "our");
}
static u8 * hostapd_probe_resp_offloads(struct hostapd_data *hapd,
size_t *resp_len)
{
/* check probe response offloading caps and print warnings */
if (!(hapd->iface->drv_flags & WPA_DRIVER_FLAGS_PROBE_RESP_OFFLOAD))
return NULL;
#ifdef CONFIG_WPS
if (hapd->conf->wps_state && hapd->wps_probe_resp_ie &&
(!(hapd->iface->probe_resp_offloads &
(WPA_DRIVER_PROBE_RESP_OFFLOAD_WPS |
WPA_DRIVER_PROBE_RESP_OFFLOAD_WPS2))))
wpa_printf(MSG_WARNING, "Device is trying to offload WPS "
"Probe Response while not supporting this");
#endif /* CONFIG_WPS */
#ifdef CONFIG_P2P
if ((hapd->conf->p2p & P2P_ENABLED) && hapd->p2p_probe_resp_ie &&
!(hapd->iface->probe_resp_offloads &
WPA_DRIVER_PROBE_RESP_OFFLOAD_P2P))
wpa_printf(MSG_WARNING, "Device is trying to offload P2P "
"Probe Response while not supporting this");
#endif /* CONFIG_P2P */
if (hapd->conf->interworking &&
!(hapd->iface->probe_resp_offloads &
WPA_DRIVER_PROBE_RESP_OFFLOAD_INTERWORKING))
wpa_printf(MSG_WARNING, "Device is trying to offload "
"Interworking Probe Response while not supporting "
"this");
/* Generate a Probe Response template for the non-P2P case */
return hostapd_gen_probe_resp(hapd, NULL, NULL, 0, resp_len);
}
#endif /* NEED_AP_MLME */
@ -437,6 +554,8 @@ void ieee802_11_set_beacon(struct hostapd_data *hapd)
struct ieee80211_mgmt *head = NULL;
u8 *tail = NULL;
size_t head_len = 0, tail_len = 0;
u8 *resp = NULL;
size_t resp_len = 0;
struct wpa_driver_ap_params params;
struct wpabuf *beacon, *proberesp, *assocresp;
#ifdef NEED_AP_MLME
@ -460,6 +579,8 @@ void ieee802_11_set_beacon(struct hostapd_data *hapd)
if (hapd->p2p_beacon_ie)
tail_len += wpabuf_len(hapd->p2p_beacon_ie);
#endif /* CONFIG_P2P */
if (hapd->conf->vendor_elements)
tail_len += wpabuf_len(hapd->conf->vendor_elements);
tailpos = tail = os_malloc(tail_len);
if (head == NULL || tail == NULL) {
wpa_printf(MSG_ERROR, "Failed to set beacon data");
@ -537,6 +658,11 @@ void ieee802_11_set_beacon(struct hostapd_data *hapd)
tailpos = hostapd_eid_adv_proto(hapd, tailpos);
tailpos = hostapd_eid_roaming_consortium(hapd, tailpos);
#ifdef CONFIG_IEEE80211AC
tailpos = hostapd_eid_vht_capabilities(hapd, tailpos);
tailpos = hostapd_eid_vht_operation(hapd, tailpos);
#endif /* CONFIG_IEEE80211AC */
/* Wi-Fi Alliance WMM */
tailpos = hostapd_eid_wmm(hapd, tailpos);
@ -561,8 +687,19 @@ void ieee802_11_set_beacon(struct hostapd_data *hapd)
tailpos = hostapd_eid_p2p_manage(hapd, tailpos);
#endif /* CONFIG_P2P_MANAGER */
#ifdef CONFIG_HS20
tailpos = hostapd_eid_hs20_indication(hapd, tailpos);
#endif /* CONFIG_HS20 */
if (hapd->conf->vendor_elements) {
os_memcpy(tailpos, wpabuf_head(hapd->conf->vendor_elements),
wpabuf_len(hapd->conf->vendor_elements));
tailpos += wpabuf_len(hapd->conf->vendor_elements);
}
tail_len = tailpos > tail ? tailpos - tail : 0;
resp = hostapd_probe_resp_offloads(hapd, &resp_len);
#endif /* NEED_AP_MLME */
os_memset(&params, 0, sizeof(params));
@ -570,9 +707,12 @@ void ieee802_11_set_beacon(struct hostapd_data *hapd)
params.head_len = head_len;
params.tail = tail;
params.tail_len = tail_len;
params.proberesp = resp;
params.proberesp_len = resp_len;
params.dtim_period = hapd->conf->dtim_period;
params.beacon_int = hapd->iconf->beacon_int;
params.ssid = (u8 *) hapd->conf->ssid.ssid;
params.basic_rates = hapd->iface->basic_rates;
params.ssid = hapd->conf->ssid.ssid;
params.ssid_len = hapd->conf->ssid.ssid_len;
params.pairwise_ciphers = hapd->conf->rsn_pairwise ?
hapd->conf->rsn_pairwise : hapd->conf->wpa_pairwise;
@ -621,12 +761,17 @@ void ieee802_11_set_beacon(struct hostapd_data *hapd)
!is_zero_ether_addr(hapd->conf->hessid))
params.hessid = hapd->conf->hessid;
params.access_network_type = hapd->conf->access_network_type;
params.ap_max_inactivity = hapd->conf->ap_max_inactivity;
#ifdef CONFIG_HS20
params.disable_dgaf = hapd->conf->disable_dgaf;
#endif /* CONFIG_HS20 */
if (hostapd_drv_set_ap(hapd, &params))
wpa_printf(MSG_ERROR, "Failed to set beacon parameters");
hostapd_free_ap_extra_ies(hapd, beacon, proberesp, assocresp);
os_free(tail);
os_free(head);
os_free(resp);
}
@ -637,4 +782,14 @@ void ieee802_11_set_beacons(struct hostapd_iface *iface)
ieee802_11_set_beacon(iface->bss[i]);
}
/* only update beacons if started */
void ieee802_11_update_beacons(struct hostapd_iface *iface)
{
size_t i;
for (i = 0; i < iface->num_bss; i++)
if (iface->bss[i]->beacon_set_done)
ieee802_11_set_beacon(iface->bss[i]);
}
#endif /* CONFIG_NATIVE_WINDOWS */

View File

@ -19,8 +19,10 @@
struct ieee80211_mgmt;
void handle_probe_req(struct hostapd_data *hapd,
const struct ieee80211_mgmt *mgmt, size_t len);
const struct ieee80211_mgmt *mgmt, size_t len,
int ssi_signal);
void ieee802_11_set_beacon(struct hostapd_data *hapd);
void ieee802_11_set_beacons(struct hostapd_iface *iface);
void ieee802_11_update_beacons(struct hostapd_iface *iface);
#endif /* BEACON_H */

View File

@ -2,19 +2,14 @@
* Control interface for shared AP commands
* Copyright (c) 2004-2009, Jouni Malinen <j@w1.fi>
*
* This program is free software; you can redistribute it and/or modify
* it under the terms of the GNU General Public License version 2 as
* published by the Free Software Foundation.
*
* Alternatively, this software may be distributed under the terms of BSD
* license.
*
* See README and COPYING for more details.
* This software may be distributed under the terms of the BSD license.
* See README for more details.
*/
#include "utils/includes.h"
#include "utils/common.h"
#include "common/ieee802_11_defs.h"
#include "hostapd.h"
#include "ieee802_1x.h"
#include "wpa_auth.h"
@ -23,6 +18,29 @@
#include "wps_hostapd.h"
#include "p2p_hostapd.h"
#include "ctrl_iface_ap.h"
#include "ap_drv_ops.h"
static int hostapd_get_sta_conn_time(struct sta_info *sta,
char *buf, size_t buflen)
{
struct os_time now, age;
int len = 0, ret;
if (!sta->connected_time.sec)
return 0;
os_get_time(&now);
os_time_sub(&now, &sta->connected_time, &age);
ret = os_snprintf(buf + len, buflen - len, "connected_time=%u\n",
(unsigned int) age.sec);
if (ret < 0 || (size_t) ret >= buflen - len)
return len;
len += ret;
return len;
}
static int hostapd_ctrl_iface_sta_mib(struct hostapd_data *hapd,
@ -62,6 +80,10 @@ static int hostapd_ctrl_iface_sta_mib(struct hostapd_data *hapd,
if (res >= 0)
len += res;
res = hostapd_get_sta_conn_time(sta, buf + len, buflen - len);
if (res >= 0)
len += res;
return len;
}
@ -106,3 +128,170 @@ int hostapd_ctrl_iface_sta_next(struct hostapd_data *hapd, const char *txtaddr,
}
return hostapd_ctrl_iface_sta_mib(hapd, sta->next, buf, buflen);
}
#ifdef CONFIG_P2P_MANAGER
static int p2p_manager_disconnect(struct hostapd_data *hapd, u16 stype,
u8 minor_reason_code, const u8 *addr)
{
struct ieee80211_mgmt *mgmt;
int ret;
u8 *pos;
if (hapd->driver->send_frame == NULL)
return -1;
mgmt = os_zalloc(sizeof(*mgmt) + 100);
if (mgmt == NULL)
return -1;
wpa_dbg(hapd->msg_ctx, MSG_DEBUG, "P2P: Disconnect STA " MACSTR
" with minor reason code %u (stype=%u)",
MAC2STR(addr), minor_reason_code, stype);
mgmt->frame_control = IEEE80211_FC(WLAN_FC_TYPE_MGMT, stype);
os_memcpy(mgmt->da, addr, ETH_ALEN);
os_memcpy(mgmt->sa, hapd->own_addr, ETH_ALEN);
os_memcpy(mgmt->bssid, hapd->own_addr, ETH_ALEN);
if (stype == WLAN_FC_STYPE_DEAUTH) {
mgmt->u.deauth.reason_code =
host_to_le16(WLAN_REASON_PREV_AUTH_NOT_VALID);
pos = (u8 *) (&mgmt->u.deauth.reason_code + 1);
} else {
mgmt->u.disassoc.reason_code =
host_to_le16(WLAN_REASON_PREV_AUTH_NOT_VALID);
pos = (u8 *) (&mgmt->u.disassoc.reason_code + 1);
}
*pos++ = WLAN_EID_VENDOR_SPECIFIC;
*pos++ = 4 + 3 + 1;
WPA_PUT_BE24(pos, OUI_WFA);
pos += 3;
*pos++ = P2P_OUI_TYPE;
*pos++ = P2P_ATTR_MINOR_REASON_CODE;
WPA_PUT_LE16(pos, 1);
pos += 2;
*pos++ = minor_reason_code;
ret = hapd->driver->send_frame(hapd->drv_priv, (u8 *) mgmt,
pos - (u8 *) mgmt, 1);
os_free(mgmt);
return ret < 0 ? -1 : 0;
}
#endif /* CONFIG_P2P_MANAGER */
int hostapd_ctrl_iface_deauthenticate(struct hostapd_data *hapd,
const char *txtaddr)
{
u8 addr[ETH_ALEN];
struct sta_info *sta;
const char *pos;
wpa_dbg(hapd->msg_ctx, MSG_DEBUG, "CTRL_IFACE DEAUTHENTICATE %s",
txtaddr);
if (hwaddr_aton(txtaddr, addr))
return -1;
pos = os_strstr(txtaddr, " test=");
if (pos) {
struct ieee80211_mgmt mgmt;
int encrypt;
if (hapd->driver->send_frame == NULL)
return -1;
pos += 6;
encrypt = atoi(pos);
os_memset(&mgmt, 0, sizeof(mgmt));
mgmt.frame_control = IEEE80211_FC(WLAN_FC_TYPE_MGMT,
WLAN_FC_STYPE_DEAUTH);
os_memcpy(mgmt.da, addr, ETH_ALEN);
os_memcpy(mgmt.sa, hapd->own_addr, ETH_ALEN);
os_memcpy(mgmt.bssid, hapd->own_addr, ETH_ALEN);
mgmt.u.deauth.reason_code =
host_to_le16(WLAN_REASON_PREV_AUTH_NOT_VALID);
if (hapd->driver->send_frame(hapd->drv_priv, (u8 *) &mgmt,
IEEE80211_HDRLEN +
sizeof(mgmt.u.deauth),
encrypt) < 0)
return -1;
return 0;
}
#ifdef CONFIG_P2P_MANAGER
pos = os_strstr(txtaddr, " p2p=");
if (pos) {
return p2p_manager_disconnect(hapd, WLAN_FC_STYPE_DEAUTH,
atoi(pos + 5), addr);
}
#endif /* CONFIG_P2P_MANAGER */
hostapd_drv_sta_deauth(hapd, addr, WLAN_REASON_PREV_AUTH_NOT_VALID);
sta = ap_get_sta(hapd, addr);
if (sta)
ap_sta_deauthenticate(hapd, sta,
WLAN_REASON_PREV_AUTH_NOT_VALID);
else if (addr[0] == 0xff)
hostapd_free_stas(hapd);
return 0;
}
int hostapd_ctrl_iface_disassociate(struct hostapd_data *hapd,
const char *txtaddr)
{
u8 addr[ETH_ALEN];
struct sta_info *sta;
const char *pos;
wpa_dbg(hapd->msg_ctx, MSG_DEBUG, "CTRL_IFACE DISASSOCIATE %s",
txtaddr);
if (hwaddr_aton(txtaddr, addr))
return -1;
pos = os_strstr(txtaddr, " test=");
if (pos) {
struct ieee80211_mgmt mgmt;
int encrypt;
if (hapd->driver->send_frame == NULL)
return -1;
pos += 6;
encrypt = atoi(pos);
os_memset(&mgmt, 0, sizeof(mgmt));
mgmt.frame_control = IEEE80211_FC(WLAN_FC_TYPE_MGMT,
WLAN_FC_STYPE_DISASSOC);
os_memcpy(mgmt.da, addr, ETH_ALEN);
os_memcpy(mgmt.sa, hapd->own_addr, ETH_ALEN);
os_memcpy(mgmt.bssid, hapd->own_addr, ETH_ALEN);
mgmt.u.disassoc.reason_code =
host_to_le16(WLAN_REASON_PREV_AUTH_NOT_VALID);
if (hapd->driver->send_frame(hapd->drv_priv, (u8 *) &mgmt,
IEEE80211_HDRLEN +
sizeof(mgmt.u.deauth),
encrypt) < 0)
return -1;
return 0;
}
#ifdef CONFIG_P2P_MANAGER
pos = os_strstr(txtaddr, " p2p=");
if (pos) {
return p2p_manager_disconnect(hapd, WLAN_FC_STYPE_DISASSOC,
atoi(pos + 5), addr);
}
#endif /* CONFIG_P2P_MANAGER */
hostapd_drv_sta_disassoc(hapd, addr, WLAN_REASON_PREV_AUTH_NOT_VALID);
sta = ap_get_sta(hapd, addr);
if (sta)
ap_sta_disassociate(hapd, sta,
WLAN_REASON_PREV_AUTH_NOT_VALID);
else if (addr[0] == 0xff)
hostapd_free_stas(hapd);
return 0;
}

View File

@ -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 */

View File

@ -2,14 +2,8 @@
* hostapd / Callback functions for driver wrappers
* Copyright (c) 2002-2009, Jouni Malinen <j@w1.fi>
*
* This program is free software; you can redistribute it and/or modify
* it under the terms of the GNU General Public License version 2 as
* published by the Free Software Foundation.
*
* Alternatively, this software may be distributed under the terms of BSD
* license.
*
* See README and COPYING for more details.
* This software may be distributed under the terms of the BSD license.
* See README for more details.
*/
#include "utils/includes.h"
@ -19,22 +13,21 @@
#include "drivers/driver.h"
#include "common/ieee802_11_defs.h"
#include "common/ieee802_11_common.h"
#include "common/wpa_ctrl.h"
#include "crypto/random.h"
#include "p2p/p2p.h"
#include "wps/wps.h"
#include "wnm_ap.h"
#include "hostapd.h"
#include "ieee802_11.h"
#include "sta_info.h"
#include "accounting.h"
#include "tkip_countermeasures.h"
#include "iapp.h"
#include "ieee802_1x.h"
#include "wpa_auth.h"
#include "wmm.h"
#include "wps_hostapd.h"
#include "ap_drv_ops.h"
#include "ap_config.h"
#include "hw_features.h"
int hostapd_notif_assoc(struct hostapd_data *hapd, const u8 *addr,
@ -45,7 +38,12 @@ int hostapd_notif_assoc(struct hostapd_data *hapd, const u8 *addr,
struct ieee802_11_elems elems;
const u8 *ie;
size_t ielen;
#ifdef CONFIG_IEEE80211R
u8 buf[sizeof(struct ieee80211_mgmt) + 1024];
u8 *p = buf;
#endif /* CONFIG_IEEE80211R */
u16 reason = WLAN_REASON_UNSPECIFIED;
u16 status = WLAN_STATUS_SUCCESS;
if (addr == NULL) {
/*
@ -95,8 +93,11 @@ int hostapd_notif_assoc(struct hostapd_data *hapd, const u8 *addr,
sta->timeout_next = STA_NULLFUNC;
} else {
sta = ap_sta_add(hapd, addr);
if (sta == NULL)
if (sta == NULL) {
hostapd_drv_sta_disassoc(hapd, addr,
WLAN_REASON_DISASSOC_AP_BUSY);
return -1;
}
}
sta->flags &= ~(WLAN_STA_WPS | WLAN_STA_MAYBE_WPS | WLAN_STA_WPS2);
@ -108,6 +109,15 @@ int hostapd_notif_assoc(struct hostapd_data *hapd, const u8 *addr,
}
#endif /* CONFIG_P2P */
#ifdef CONFIG_HS20
wpabuf_free(sta->hs20_ie);
if (elems.hs20 && elems.hs20_len > 4) {
sta->hs20_ie = wpabuf_alloc_copy(elems.hs20 + 4,
elems.hs20_len - 4);
} else
sta->hs20_ie = NULL;
#endif /* CONFIG_HS20 */
if (hapd->conf->wpa) {
if (ie == NULL || ielen == 0) {
#ifdef CONFIG_WPS
@ -151,27 +161,85 @@ int hostapd_notif_assoc(struct hostapd_data *hapd, const u8 *addr,
return -1;
}
res = wpa_validate_wpa_ie(hapd->wpa_auth, sta->wpa_sm,
ie, ielen, NULL, 0);
ie, ielen,
elems.mdie, elems.mdie_len);
if (res != WPA_IE_OK) {
wpa_printf(MSG_DEBUG, "WPA/RSN information element "
"rejected? (res %u)", res);
wpa_hexdump(MSG_DEBUG, "IE", ie, ielen);
if (res == WPA_INVALID_GROUP)
if (res == WPA_INVALID_GROUP) {
reason = WLAN_REASON_GROUP_CIPHER_NOT_VALID;
else if (res == WPA_INVALID_PAIRWISE)
status = WLAN_STATUS_GROUP_CIPHER_NOT_VALID;
} else if (res == WPA_INVALID_PAIRWISE) {
reason = WLAN_REASON_PAIRWISE_CIPHER_NOT_VALID;
else if (res == WPA_INVALID_AKMP)
status = WLAN_STATUS_PAIRWISE_CIPHER_NOT_VALID;
} else if (res == WPA_INVALID_AKMP) {
reason = WLAN_REASON_AKMP_NOT_VALID;
status = WLAN_STATUS_AKMP_NOT_VALID;
}
#ifdef CONFIG_IEEE80211W
else if (res == WPA_MGMT_FRAME_PROTECTION_VIOLATION)
else if (res == WPA_MGMT_FRAME_PROTECTION_VIOLATION) {
reason = WLAN_REASON_INVALID_IE;
else if (res == WPA_INVALID_MGMT_GROUP_CIPHER)
status = WLAN_STATUS_INVALID_IE;
} else if (res == WPA_INVALID_MGMT_GROUP_CIPHER) {
reason = WLAN_REASON_GROUP_CIPHER_NOT_VALID;
status = WLAN_STATUS_GROUP_CIPHER_NOT_VALID;
}
#endif /* CONFIG_IEEE80211W */
else
else {
reason = WLAN_REASON_INVALID_IE;
status = WLAN_STATUS_INVALID_IE;
}
goto fail;
}
#ifdef CONFIG_IEEE80211W
if ((sta->flags & WLAN_STA_MFP) && !sta->sa_query_timed_out &&
sta->sa_query_count > 0)
ap_check_sa_query_timeout(hapd, sta);
if ((sta->flags & WLAN_STA_MFP) && !sta->sa_query_timed_out &&
(sta->auth_alg != WLAN_AUTH_FT)) {
/*
* STA has already been associated with MFP and SA
* Query timeout has not been reached. Reject the
* association attempt temporarily and start SA Query,
* if one is not pending.
*/
if (sta->sa_query_count == 0)
ap_sta_start_sa_query(hapd, sta);
#ifdef CONFIG_IEEE80211R
status = WLAN_STATUS_ASSOC_REJECTED_TEMPORARILY;
p = hostapd_eid_assoc_comeback_time(hapd, sta, p);
hostapd_sta_assoc(hapd, addr, reassoc, status, buf,
p - buf);
#endif /* CONFIG_IEEE80211R */
return 0;
}
if (wpa_auth_uses_mfp(sta->wpa_sm))
sta->flags |= WLAN_STA_MFP;
else
sta->flags &= ~WLAN_STA_MFP;
#endif /* CONFIG_IEEE80211W */
#ifdef CONFIG_IEEE80211R
if (sta->auth_alg == WLAN_AUTH_FT) {
status = wpa_ft_validate_reassoc(sta->wpa_sm, req_ies,
req_ies_len);
if (status != WLAN_STATUS_SUCCESS) {
if (status == WLAN_STATUS_INVALID_PMKID)
reason = WLAN_REASON_INVALID_IE;
if (status == WLAN_STATUS_INVALID_MDIE)
reason = WLAN_REASON_INVALID_IE;
if (status == WLAN_STATUS_INVALID_FTIE)
reason = WLAN_REASON_INVALID_IE;
goto fail;
}
}
#endif /* CONFIG_IEEE80211R */
} else if (hapd->conf->wps_state) {
#ifdef CONFIG_WPS
struct wpabuf *wps;
@ -183,6 +251,7 @@ int hostapd_notif_assoc(struct hostapd_data *hapd, const u8 *addr,
#ifdef CONFIG_WPS_STRICT
if (wps && wps_validate_assoc_req(wps) < 0) {
reason = WLAN_REASON_INVALID_IE;
status = WLAN_STATUS_INVALID_IE;
wpabuf_free(wps);
goto fail;
}
@ -203,9 +272,24 @@ int hostapd_notif_assoc(struct hostapd_data *hapd, const u8 *addr,
skip_wpa_check:
#endif /* CONFIG_WPS */
#ifdef CONFIG_IEEE80211R
p = wpa_sm_write_assoc_resp_ies(sta->wpa_sm, buf, sizeof(buf),
sta->auth_alg, req_ies, req_ies_len);
hostapd_sta_assoc(hapd, addr, reassoc, status, buf, p - buf);
#else /* CONFIG_IEEE80211R */
/* Keep compiler silent about unused variables */
if (status) {
}
#endif /* CONFIG_IEEE80211R */
new_assoc = (sta->flags & WLAN_STA_ASSOC) == 0;
sta->flags |= WLAN_STA_AUTH | WLAN_STA_ASSOC;
wpa_auth_sm_event(sta->wpa_sm, WPA_ASSOC);
if (reassoc && (sta->auth_alg == WLAN_AUTH_FT))
wpa_auth_sm_event(sta->wpa_sm, WPA_ASSOC_FT);
else
wpa_auth_sm_event(sta->wpa_sm, WPA_ASSOC);
hostapd_new_assoc_sta(hapd, sta, !new_assoc);
@ -221,6 +305,9 @@ skip_wpa_check:
return 0;
fail:
#ifdef CONFIG_IEEE80211R
hostapd_sta_assoc(hapd, addr, reassoc, status, buf, p - buf);
#endif /* CONFIG_IEEE80211R */
hostapd_drv_sta_disassoc(hapd, sta->addr, reason);
ap_free_sta(hapd, sta);
return -1;
@ -279,8 +366,36 @@ void hostapd_event_sta_low_ack(struct hostapd_data *hapd, const u8 *addr)
}
void hostapd_event_ch_switch(struct hostapd_data *hapd, int freq, int ht,
int offset)
{
#ifdef NEED_AP_MLME
int channel;
hostapd_logger(hapd, NULL, HOSTAPD_MODULE_IEEE80211,
HOSTAPD_LEVEL_INFO, "driver had channel switch: "
"freq=%d, ht=%d, offset=%d", freq, ht, offset);
hapd->iface->freq = freq;
channel = hostapd_hw_get_channel(hapd, freq);
if (!channel) {
hostapd_logger(hapd, NULL, HOSTAPD_MODULE_IEEE80211,
HOSTAPD_LEVEL_WARNING, "driver switched to "
"bad channel!");
return;
}
hapd->iconf->channel = channel;
hapd->iconf->ieee80211n = ht;
hapd->iconf->secondary_channel = offset;
#endif /* NEED_AP_MLME */
}
int hostapd_probe_req_rx(struct hostapd_data *hapd, const u8 *sa, const u8 *da,
const u8 *bssid, const u8 *ie, size_t ie_len)
const u8 *bssid, const u8 *ie, size_t ie_len,
int ssi_signal)
{
size_t i;
int ret = 0;
@ -291,7 +406,8 @@ int hostapd_probe_req_rx(struct hostapd_data *hapd, const u8 *sa, const u8 *da,
random_add_randomness(sa, ETH_ALEN);
for (i = 0; hapd->probereq_cb && i < hapd->num_probereq_cb; i++) {
if (hapd->probereq_cb[i].cb(hapd->probereq_cb[i].ctx,
sa, da, bssid, ie, ie_len) > 0) {
sa, da, bssid, ie, ie_len,
ssi_signal) > 0) {
ret = 1;
break;
}
@ -302,6 +418,110 @@ int hostapd_probe_req_rx(struct hostapd_data *hapd, const u8 *sa, const u8 *da,
#ifdef HOSTAPD
#ifdef CONFIG_IEEE80211R
static void hostapd_notify_auth_ft_finish(void *ctx, const u8 *dst,
const u8 *bssid,
u16 auth_transaction, u16 status,
const u8 *ies, size_t ies_len)
{
struct hostapd_data *hapd = ctx;
struct sta_info *sta;
sta = ap_get_sta(hapd, dst);
if (sta == NULL)
return;
hostapd_logger(hapd, dst, HOSTAPD_MODULE_IEEE80211,
HOSTAPD_LEVEL_DEBUG, "authentication OK (FT)");
sta->flags |= WLAN_STA_AUTH;
hostapd_sta_auth(hapd, dst, auth_transaction, status, ies, ies_len);
}
#endif /* CONFIG_IEEE80211R */
static void hostapd_notif_auth(struct hostapd_data *hapd,
struct auth_info *rx_auth)
{
struct sta_info *sta;
u16 status = WLAN_STATUS_SUCCESS;
u8 resp_ies[2 + WLAN_AUTH_CHALLENGE_LEN];
size_t resp_ies_len = 0;
sta = ap_get_sta(hapd, rx_auth->peer);
if (!sta) {
sta = ap_sta_add(hapd, rx_auth->peer);
if (sta == NULL) {
status = WLAN_STATUS_UNSPECIFIED_FAILURE;
goto fail;
}
}
sta->flags &= ~WLAN_STA_PREAUTH;
ieee802_1x_notify_pre_auth(sta->eapol_sm, 0);
#ifdef CONFIG_IEEE80211R
if (rx_auth->auth_type == WLAN_AUTH_FT && hapd->wpa_auth) {
sta->auth_alg = WLAN_AUTH_FT;
if (sta->wpa_sm == NULL)
sta->wpa_sm = wpa_auth_sta_init(hapd->wpa_auth,
sta->addr);
if (sta->wpa_sm == NULL) {
wpa_printf(MSG_DEBUG, "FT: Failed to initialize WPA "
"state machine");
status = WLAN_STATUS_UNSPECIFIED_FAILURE;
goto fail;
}
wpa_ft_process_auth(sta->wpa_sm, rx_auth->bssid,
rx_auth->auth_transaction, rx_auth->ies,
rx_auth->ies_len,
hostapd_notify_auth_ft_finish, hapd);
return;
}
#endif /* CONFIG_IEEE80211R */
fail:
hostapd_sta_auth(hapd, rx_auth->peer, rx_auth->auth_transaction + 1,
status, resp_ies, resp_ies_len);
}
static void hostapd_action_rx(struct hostapd_data *hapd,
struct rx_action *action)
{
struct sta_info *sta;
wpa_printf(MSG_DEBUG, "RX_ACTION cat %d action plen %d",
action->category, (int) action->len);
sta = ap_get_sta(hapd, action->sa);
if (sta == NULL) {
wpa_printf(MSG_DEBUG, "%s: station not found", __func__);
return;
}
#ifdef CONFIG_IEEE80211R
if (action->category == WLAN_ACTION_FT) {
wpa_printf(MSG_DEBUG, "%s: FT_ACTION length %d",
__func__, (int) action->len);
wpa_ft_action_rx(sta->wpa_sm, action->data, action->len);
}
#endif /* CONFIG_IEEE80211R */
#ifdef CONFIG_IEEE80211W
if (action->category == WLAN_ACTION_SA_QUERY && action->len >= 4) {
wpa_printf(MSG_DEBUG, "%s: SA_QUERY_ACTION length %d",
__func__, (int) action->len);
ieee802_11_sa_query_action(hapd, action->sa,
*(action->data + 1),
action->data + 2);
}
#endif /* CONFIG_IEEE80211W */
#ifdef CONFIG_WNM
if (action->category == WLAN_ACTION_WNM) {
wpa_printf(MSG_DEBUG, "%s: WNM_ACTION length %d",
__func__, (int) action->len);
ieee802_11_rx_wnm_action_ap(hapd, action);
}
#endif /* CONFIG_WNM */
}
#ifdef NEED_AP_MLME
#define HAPD_BROADCAST ((struct hostapd_data *) -1)
@ -481,6 +701,23 @@ void wpa_supplicant_event(void *ctx, enum wpa_event_type event,
union wpa_event_data *data)
{
struct hostapd_data *hapd = ctx;
#ifndef CONFIG_NO_STDOUT_DEBUG
int level = MSG_DEBUG;
if (event == EVENT_RX_MGMT && data->rx_mgmt.frame &&
data->rx_mgmt.frame_len >= 24) {
const struct ieee80211_hdr *hdr;
u16 fc;
hdr = (const struct ieee80211_hdr *) data->rx_mgmt.frame;
fc = le_to_host16(hdr->frame_control);
if (WLAN_FC_GET_TYPE(fc) == WLAN_FC_TYPE_MGMT &&
WLAN_FC_GET_STYPE(fc) == WLAN_FC_STYPE_BEACON)
level = MSG_EXCESSIVE;
}
wpa_dbg(hapd->msg_ctx, level, "Event %s (%d) received",
event_to_string(event), event);
#endif /* CONFIG_NO_STDOUT_DEBUG */
switch (event) {
case EVENT_MICHAEL_MIC_FAILURE:
@ -516,6 +753,12 @@ void wpa_supplicant_event(void *ctx, enum wpa_event_type event,
break;
}
break;
case EVENT_EAPOL_TX_STATUS:
hostapd_eapol_tx_status(hapd, data->eapol_tx_status.dst,
data->eapol_tx_status.data,
data->eapol_tx_status.data_len,
data->eapol_tx_status.ack);
break;
case EVENT_DRIVER_CLIENT_POLL_OK:
hostapd_client_poll_ok(hapd, data->client_poll.addr);
break;
@ -536,7 +779,8 @@ void wpa_supplicant_event(void *ctx, enum wpa_event_type event,
data->rx_probe_req.da,
data->rx_probe_req.bssid,
data->rx_probe_req.ie,
data->rx_probe_req.ie_len);
data->rx_probe_req.ie_len,
data->rx_probe_req.ssi_signal);
break;
case EVENT_NEW_STA:
hostapd_event_new_sta(hapd, data->new_sta.addr);
@ -565,14 +809,25 @@ void wpa_supplicant_event(void *ctx, enum wpa_event_type event,
break;
hostapd_event_sta_low_ack(hapd, data->low_ack.addr);
break;
#ifdef NEED_AP_MLME
case EVENT_RX_ACTION:
if (data->rx_action.da == NULL || data->rx_action.sa == NULL ||
data->rx_action.bssid == NULL)
break;
#ifdef NEED_AP_MLME
hostapd_rx_action(hapd, &data->rx_action);
break;
#endif /* NEED_AP_MLME */
hostapd_action_rx(hapd, &data->rx_action);
break;
case EVENT_AUTH:
hostapd_notif_auth(hapd, &data->auth);
break;
case EVENT_CH_SWITCH:
if (!data)
break;
hostapd_event_ch_switch(hapd, data->ch_switch.freq,
data->ch_switch.ht_enabled,
data->ch_switch.ch_offset);
break;
default:
wpa_printf(MSG_DEBUG, "Unknown event %d", event);
break;

View 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
external/bsd/wpa/dist/src/ap/gas_serv.c vendored Normal file

File diff suppressed because it is too large Load Diff

71
external/bsd/wpa/dist/src/ap/gas_serv.h vendored Normal file
View 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 */

View File

@ -1,15 +1,9 @@
/*
* hostapd / Initialization and configuration
* Copyright (c) 2002-2009, Jouni Malinen <j@w1.fi>
* Copyright (c) 2002-2012, Jouni Malinen <j@w1.fi>
*
* This program is free software; you can redistribute it and/or modify
* it under the terms of the GNU General Public License version 2 as
* published by the Free Software Foundation.
*
* Alternatively, this software may be distributed under the terms of BSD
* license.
*
* See README and COPYING for more details.
* This software may be distributed under the terms of the BSD license.
* See README for more details.
*/
#include "utils/includes.h"
@ -18,6 +12,7 @@
#include "utils/eloop.h"
#include "common/ieee802_11_defs.h"
#include "radius/radius_client.h"
#include "radius/radius_das.h"
#include "drivers/driver.h"
#include "hostapd.h"
#include "authsrv.h"
@ -36,6 +31,7 @@
#include "ap_drv_ops.h"
#include "ap_config.h"
#include "p2p_hostapd.h"
#include "gas_serv.h"
static int hostapd_flush_old_stations(struct hostapd_data *hapd, u16 reason);
@ -43,6 +39,24 @@ static int hostapd_setup_encryption(char *iface, struct hostapd_data *hapd);
static int hostapd_broadcast_wep_clear(struct hostapd_data *hapd);
extern int wpa_debug_level;
extern struct wpa_driver_ops *wpa_drivers[];
int hostapd_for_each_interface(struct hapd_interfaces *interfaces,
int (*cb)(struct hostapd_iface *iface,
void *ctx), void *ctx)
{
size_t i;
int ret;
for (i = 0; i < interfaces->count; i++) {
ret = cb(interfaces->iface[i], ctx);
if (ret)
return ret;
}
return 0;
}
static void hostapd_reload_bss(struct hostapd_data *hapd)
@ -85,7 +99,7 @@ static void hostapd_reload_bss(struct hostapd_data *hapd)
hostapd_update_wps(hapd);
if (hapd->conf->ssid.ssid_set &&
hostapd_set_ssid(hapd, (u8 *) hapd->conf->ssid.ssid,
hostapd_set_ssid(hapd, hapd->conf->ssid.ssid,
hapd->conf->ssid.ssid_len)) {
wpa_printf(MSG_ERROR, "Could not set SSID for kernel driver");
/* try to continue */
@ -100,9 +114,10 @@ int hostapd_reload_config(struct hostapd_iface *iface)
struct hostapd_config *newconf, *oldconf;
size_t j;
if (iface->config_read_cb == NULL)
if (iface->interfaces == NULL ||
iface->interfaces->config_read_cb == NULL)
return -1;
newconf = iface->config_read_cb(iface->config_fname);
newconf = iface->interfaces->config_read_cb(iface->config_fname);
if (newconf == NULL)
return -1;
@ -217,21 +232,9 @@ static int hostapd_broadcast_wep_set(struct hostapd_data *hapd)
return errors;
}
/**
* hostapd_cleanup - Per-BSS cleanup (deinitialization)
* @hapd: Pointer to BSS data
*
* This function is used to free all per-BSS data structures and resources.
* This gets called in a loop for each BSS between calls to
* hostapd_cleanup_iface_pre() and hostapd_cleanup_iface() when an interface
* is deinitialized. Most of the modules that are initialized in
* hostapd_setup_bss() are deinitialized here.
*/
static void hostapd_cleanup(struct hostapd_data *hapd)
{
if (hapd->iface->ctrl_iface_deinit)
hapd->iface->ctrl_iface_deinit(hapd);
static void hostapd_free_hapd_data(struct hostapd_data *hapd)
{
iapp_deinit(hapd->iapp);
hapd->iapp = NULL;
accounting_deinit(hapd);
@ -241,6 +244,8 @@ static void hostapd_cleanup(struct hostapd_data *hapd)
#ifndef CONFIG_NO_RADIUS
radius_client_deinit(hapd->radius);
hapd->radius = NULL;
radius_das_deinit(hapd->radius_das);
hapd->radius_das = NULL;
#endif /* CONFIG_NO_RADIUS */
hostapd_deinit_wps(hapd);
@ -264,6 +269,34 @@ static void hostapd_cleanup(struct hostapd_data *hapd)
#endif /* CONFIG_P2P */
wpabuf_free(hapd->time_adv);
#ifdef CONFIG_INTERWORKING
gas_serv_deinit(hapd);
#endif /* CONFIG_INTERWORKING */
#ifdef CONFIG_SQLITE
os_free(hapd->tmp_eap_user.identity);
os_free(hapd->tmp_eap_user.password);
#endif /* CONFIG_SQLITE */
}
/**
* hostapd_cleanup - Per-BSS cleanup (deinitialization)
* @hapd: Pointer to BSS data
*
* This function is used to free all per-BSS data structures and resources.
* This gets called in a loop for each BSS between calls to
* hostapd_cleanup_iface_pre() and hostapd_cleanup_iface() when an interface
* is deinitialized. Most of the modules that are initialized in
* hostapd_setup_bss() are deinitialized here.
*/
static void hostapd_cleanup(struct hostapd_data *hapd)
{
if (hapd->iface->interfaces &&
hapd->iface->interfaces->ctrl_iface_deinit)
hapd->iface->interfaces->ctrl_iface_deinit(hapd);
hostapd_free_hapd_data(hapd);
}
@ -279,6 +312,18 @@ static void hostapd_cleanup_iface_pre(struct hostapd_iface *iface)
}
static void hostapd_cleanup_iface_partial(struct hostapd_iface *iface)
{
hostapd_free_hw_features(iface->hw_features, iface->num_hw_features);
iface->hw_features = NULL;
os_free(iface->current_rates);
iface->current_rates = NULL;
os_free(iface->basic_rates);
iface->basic_rates = NULL;
ap_list_deinit(iface);
}
/**
* hostapd_cleanup_iface - Complete per-interface cleanup
* @iface: Pointer to interface data
@ -288,11 +333,7 @@ static void hostapd_cleanup_iface_pre(struct hostapd_iface *iface)
*/
static void hostapd_cleanup_iface(struct hostapd_iface *iface)
{
hostapd_free_hw_features(iface->hw_features, iface->num_hw_features);
iface->hw_features = NULL;
os_free(iface->current_rates);
iface->current_rates = NULL;
ap_list_deinit(iface);
hostapd_cleanup_iface_partial(iface);
hostapd_config_free(iface->conf);
iface->conf = NULL;
@ -302,6 +343,15 @@ static void hostapd_cleanup_iface(struct hostapd_iface *iface)
}
static void hostapd_clear_wep(struct hostapd_data *hapd)
{
if (hapd->drv_priv) {
hostapd_set_privacy(hapd, 0);
hostapd_broadcast_wep_clear(hapd);
}
}
static int hostapd_setup_encryption(char *iface, struct hostapd_data *hapd)
{
int i;
@ -346,12 +396,13 @@ static int hostapd_flush_old_stations(struct hostapd_data *hapd, u16 reason)
if (hostapd_drv_none(hapd) || hapd->drv_priv == NULL)
return 0;
wpa_printf(MSG_DEBUG, "Flushing old station entries");
wpa_dbg(hapd->msg_ctx, MSG_DEBUG, "Flushing old station entries");
if (hostapd_flush(hapd)) {
wpa_printf(MSG_WARNING, "Could not connect to kernel driver.");
wpa_msg(hapd->msg_ctx, MSG_WARNING, "Could not connect to "
"kernel driver");
ret = -1;
}
wpa_printf(MSG_DEBUG, "Deauthenticate all stations");
wpa_dbg(hapd->msg_ctx, MSG_DEBUG, "Deauthenticate all stations");
os_memset(addr, 0xff, ETH_ALEN);
hostapd_drv_sta_deauth(hapd, addr, reason);
hostapd_free_stas(hapd);
@ -468,6 +519,86 @@ static int mac_in_conf(struct hostapd_config *conf, const void *a)
}
#ifndef CONFIG_NO_RADIUS
static int hostapd_das_nas_mismatch(struct hostapd_data *hapd,
struct radius_das_attrs *attr)
{
/* TODO */
return 0;
}
static struct sta_info * hostapd_das_find_sta(struct hostapd_data *hapd,
struct radius_das_attrs *attr)
{
struct sta_info *sta = NULL;
char buf[128];
if (attr->sta_addr)
sta = ap_get_sta(hapd, attr->sta_addr);
if (sta == NULL && attr->acct_session_id &&
attr->acct_session_id_len == 17) {
for (sta = hapd->sta_list; sta; sta = sta->next) {
os_snprintf(buf, sizeof(buf), "%08X-%08X",
sta->acct_session_id_hi,
sta->acct_session_id_lo);
if (os_memcmp(attr->acct_session_id, buf, 17) == 0)
break;
}
}
if (sta == NULL && attr->cui) {
for (sta = hapd->sta_list; sta; sta = sta->next) {
struct wpabuf *cui;
cui = ieee802_1x_get_radius_cui(sta->eapol_sm);
if (cui && wpabuf_len(cui) == attr->cui_len &&
os_memcmp(wpabuf_head(cui), attr->cui,
attr->cui_len) == 0)
break;
}
}
if (sta == NULL && attr->user_name) {
for (sta = hapd->sta_list; sta; sta = sta->next) {
u8 *identity;
size_t identity_len;
identity = ieee802_1x_get_identity(sta->eapol_sm,
&identity_len);
if (identity &&
identity_len == attr->user_name_len &&
os_memcmp(identity, attr->user_name, identity_len)
== 0)
break;
}
}
return sta;
}
static enum radius_das_res
hostapd_das_disconnect(void *ctx, struct radius_das_attrs *attr)
{
struct hostapd_data *hapd = ctx;
struct sta_info *sta;
if (hostapd_das_nas_mismatch(hapd, attr))
return RADIUS_DAS_NAS_MISMATCH;
sta = hostapd_das_find_sta(hapd, attr);
if (sta == NULL)
return RADIUS_DAS_SESSION_NOT_FOUND;
hostapd_drv_sta_deauth(hapd, sta->addr,
WLAN_REASON_PREV_AUTH_NOT_VALID);
ap_sta_deauthenticate(hapd, sta, WLAN_REASON_PREV_AUTH_NOT_VALID);
return RADIUS_DAS_SUCCESS;
}
#endif /* CONFIG_NO_RADIUS */
/**
@ -556,14 +687,14 @@ static int hostapd_setup_bss(struct hostapd_data *hapd, int first)
set_ssid = 0;
conf->ssid.ssid_len = ssid_len;
os_memcpy(conf->ssid.ssid, ssid, conf->ssid.ssid_len);
conf->ssid.ssid[conf->ssid.ssid_len] = '\0';
}
if (!hostapd_drv_none(hapd)) {
wpa_printf(MSG_ERROR, "Using interface %s with hwaddr " MACSTR
" and ssid '%s'",
" and ssid \"%s\"",
hapd->conf->iface, MAC2STR(hapd->own_addr),
hapd->conf->ssid.ssid);
wpa_ssid_txt(hapd->conf->ssid.ssid,
hapd->conf->ssid.ssid_len));
}
if (hostapd_setup_wpa_psk(conf)) {
@ -573,7 +704,7 @@ static int hostapd_setup_bss(struct hostapd_data *hapd, int first)
/* Set SSID for the kernel driver (to be used in beacon and probe
* response frames) */
if (set_ssid && hostapd_set_ssid(hapd, (u8 *) conf->ssid.ssid,
if (set_ssid && hostapd_set_ssid(hapd, conf->ssid.ssid,
conf->ssid.ssid_len)) {
wpa_printf(MSG_ERROR, "Could not set SSID for kernel driver");
return -1;
@ -587,6 +718,27 @@ static int hostapd_setup_bss(struct hostapd_data *hapd, int first)
wpa_printf(MSG_ERROR, "RADIUS client initialization failed.");
return -1;
}
if (hapd->conf->radius_das_port) {
struct radius_das_conf das_conf;
os_memset(&das_conf, 0, sizeof(das_conf));
das_conf.port = hapd->conf->radius_das_port;
das_conf.shared_secret = hapd->conf->radius_das_shared_secret;
das_conf.shared_secret_len =
hapd->conf->radius_das_shared_secret_len;
das_conf.client_addr = &hapd->conf->radius_das_client_addr;
das_conf.time_window = hapd->conf->radius_das_time_window;
das_conf.require_event_timestamp =
hapd->conf->radius_das_require_event_timestamp;
das_conf.ctx = hapd;
das_conf.disconnect = hostapd_das_disconnect;
hapd->radius_das = radius_das_init(&das_conf);
if (hapd->radius_das == NULL) {
wpa_printf(MSG_ERROR, "RADIUS DAS initialization "
"failed.");
return -1;
}
}
#endif /* CONFIG_NO_RADIUS */
if (hostapd_acl_init(hapd)) {
@ -619,8 +771,16 @@ static int hostapd_setup_bss(struct hostapd_data *hapd, int first)
return -1;
}
if (hapd->iface->ctrl_iface_init &&
hapd->iface->ctrl_iface_init(hapd)) {
#ifdef CONFIG_INTERWORKING
if (gas_serv_init(hapd)) {
wpa_printf(MSG_ERROR, "GAS server initialization failed");
return -1;
}
#endif /* CONFIG_INTERWORKING */
if (hapd->iface->interfaces &&
hapd->iface->interfaces->ctrl_iface_init &&
hapd->iface->interfaces->ctrl_iface_init(hapd)) {
wpa_printf(MSG_ERROR, "Failed to setup control interface");
return -1;
}
@ -742,7 +902,7 @@ int hostapd_setup_interface_complete(struct hostapd_iface *iface, int err)
}
if (iface->current_mode) {
if (hostapd_prepare_rates(hapd, iface->current_mode)) {
if (hostapd_prepare_rates(iface, iface->current_mode)) {
wpa_printf(MSG_ERROR, "Failed to prepare rates "
"table.");
hostapd_logger(hapd, NULL, HOSTAPD_MODULE_IEEE80211,
@ -861,6 +1021,7 @@ hostapd_alloc_bss_data(struct hostapd_iface *hapd_iface,
hapd->conf = bss;
hapd->iface = hapd_iface;
hapd->driver = hapd->iconf->driver;
hapd->ctrl_sock = -1;
return hapd;
}
@ -878,6 +1039,7 @@ void hostapd_interface_deinit(struct hostapd_iface *iface)
struct hostapd_data *hapd = iface->bss[j];
hostapd_free_stas(hapd);
hostapd_flush_old_stations(hapd, WLAN_REASON_DEAUTH_LEAVING);
hostapd_clear_wep(hapd);
hostapd_cleanup(hapd);
}
}
@ -892,6 +1054,293 @@ void hostapd_interface_free(struct hostapd_iface *iface)
}
#ifdef HOSTAPD
void hostapd_interface_deinit_free(struct hostapd_iface *iface)
{
const struct wpa_driver_ops *driver;
void *drv_priv;
if (iface == NULL)
return;
driver = iface->bss[0]->driver;
drv_priv = iface->bss[0]->drv_priv;
hostapd_interface_deinit(iface);
if (driver && driver->hapd_deinit && drv_priv)
driver->hapd_deinit(drv_priv);
hostapd_interface_free(iface);
}
int hostapd_enable_iface(struct hostapd_iface *hapd_iface)
{
if (hapd_iface->bss[0]->drv_priv != NULL) {
wpa_printf(MSG_ERROR, "Interface %s already enabled",
hapd_iface->conf->bss[0].iface);
return -1;
}
wpa_printf(MSG_DEBUG, "Enable interface %s",
hapd_iface->conf->bss[0].iface);
if (hapd_iface->interfaces == NULL ||
hapd_iface->interfaces->driver_init == NULL ||
hapd_iface->interfaces->driver_init(hapd_iface) ||
hostapd_setup_interface(hapd_iface)) {
hostapd_interface_deinit_free(hapd_iface);
return -1;
}
return 0;
}
int hostapd_reload_iface(struct hostapd_iface *hapd_iface)
{
size_t j;
wpa_printf(MSG_DEBUG, "Reload interface %s",
hapd_iface->conf->bss[0].iface);
for (j = 0; j < hapd_iface->num_bss; j++) {
hostapd_flush_old_stations(hapd_iface->bss[j],
WLAN_REASON_PREV_AUTH_NOT_VALID);
#ifndef CONFIG_NO_RADIUS
/* TODO: update dynamic data based on changed configuration
* items (e.g., open/close sockets, etc.) */
radius_client_flush(hapd_iface->bss[j]->radius, 0);
#endif /* CONFIG_NO_RADIUS */
hostapd_reload_bss(hapd_iface->bss[j]);
}
return 0;
}
int hostapd_disable_iface(struct hostapd_iface *hapd_iface)
{
size_t j;
struct hostapd_bss_config *bss;
const struct wpa_driver_ops *driver;
void *drv_priv;
if (hapd_iface == NULL)
return -1;
bss = hapd_iface->bss[0]->conf;
driver = hapd_iface->bss[0]->driver;
drv_priv = hapd_iface->bss[0]->drv_priv;
/* whatever hostapd_interface_deinit does */
for (j = 0; j < hapd_iface->num_bss; j++) {
struct hostapd_data *hapd = hapd_iface->bss[j];
hostapd_free_stas(hapd);
hostapd_flush_old_stations(hapd, WLAN_REASON_DEAUTH_LEAVING);
hostapd_clear_wep(hapd);
hostapd_free_hapd_data(hapd);
}
if (driver && driver->hapd_deinit && drv_priv) {
driver->hapd_deinit(drv_priv);
hapd_iface->bss[0]->drv_priv = NULL;
}
/* From hostapd_cleanup_iface: These were initialized in
* hostapd_setup_interface and hostapd_setup_interface_complete
*/
hostapd_cleanup_iface_partial(hapd_iface);
bss->wpa = 0;
bss->wpa_key_mgmt = -1;
bss->wpa_pairwise = -1;
wpa_printf(MSG_DEBUG, "Interface %s disabled", bss->iface);
return 0;
}
static struct hostapd_iface *
hostapd_iface_alloc(struct hapd_interfaces *interfaces)
{
struct hostapd_iface **iface, *hapd_iface;
iface = os_realloc_array(interfaces->iface, interfaces->count + 1,
sizeof(struct hostapd_iface *));
if (iface == NULL)
return NULL;
interfaces->iface = iface;
hapd_iface = interfaces->iface[interfaces->count] =
os_zalloc(sizeof(*hapd_iface));
if (hapd_iface == NULL) {
wpa_printf(MSG_ERROR, "%s: Failed to allocate memory for "
"the interface", __func__);
return NULL;
}
interfaces->count++;
hapd_iface->interfaces = interfaces;
return hapd_iface;
}
static struct hostapd_config *
hostapd_config_alloc(struct hapd_interfaces *interfaces, const char *ifname,
const char *ctrl_iface)
{
struct hostapd_bss_config *bss;
struct hostapd_config *conf;
/* Allocates memory for bss and conf */
conf = hostapd_config_defaults();
if (conf == NULL) {
wpa_printf(MSG_ERROR, "%s: Failed to allocate memory for "
"configuration", __func__);
return NULL;
}
conf->driver = wpa_drivers[0];
if (conf->driver == NULL) {
wpa_printf(MSG_ERROR, "No driver wrappers registered!");
hostapd_config_free(conf);
return NULL;
}
bss = conf->last_bss = conf->bss;
os_strlcpy(bss->iface, ifname, sizeof(bss->iface));
bss->ctrl_interface = os_strdup(ctrl_iface);
if (bss->ctrl_interface == NULL) {
hostapd_config_free(conf);
return NULL;
}
/* Reading configuration file skipped, will be done in SET!
* From reading the configuration till the end has to be done in
* SET
*/
return conf;
}
static struct hostapd_iface * hostapd_data_alloc(
struct hapd_interfaces *interfaces, struct hostapd_config *conf)
{
size_t i;
struct hostapd_iface *hapd_iface =
interfaces->iface[interfaces->count - 1];
struct hostapd_data *hapd;
hapd_iface->conf = conf;
hapd_iface->num_bss = conf->num_bss;
hapd_iface->bss = os_zalloc(conf->num_bss *
sizeof(struct hostapd_data *));
if (hapd_iface->bss == NULL)
return NULL;
for (i = 0; i < conf->num_bss; i++) {
hapd = hapd_iface->bss[i] =
hostapd_alloc_bss_data(hapd_iface, conf,
&conf->bss[i]);
if (hapd == NULL)
return NULL;
hapd->msg_ctx = hapd;
}
hapd_iface->interfaces = interfaces;
return hapd_iface;
}
int hostapd_add_iface(struct hapd_interfaces *interfaces, char *buf)
{
struct hostapd_config *conf = NULL;
struct hostapd_iface *hapd_iface = NULL;
char *ptr;
size_t i;
ptr = os_strchr(buf, ' ');
if (ptr == NULL)
return -1;
*ptr++ = '\0';
for (i = 0; i < interfaces->count; i++) {
if (!os_strcmp(interfaces->iface[i]->conf->bss[0].iface,
buf)) {
wpa_printf(MSG_INFO, "Cannot add interface - it "
"already exists");
return -1;
}
}
hapd_iface = hostapd_iface_alloc(interfaces);
if (hapd_iface == NULL) {
wpa_printf(MSG_ERROR, "%s: Failed to allocate memory "
"for interface", __func__);
goto fail;
}
conf = hostapd_config_alloc(interfaces, buf, ptr);
if (conf == NULL) {
wpa_printf(MSG_ERROR, "%s: Failed to allocate memory "
"for configuration", __func__);
goto fail;
}
hapd_iface = hostapd_data_alloc(interfaces, conf);
if (hapd_iface == NULL) {
wpa_printf(MSG_ERROR, "%s: Failed to allocate memory "
"for hostapd", __func__);
goto fail;
}
if (hapd_iface->interfaces &&
hapd_iface->interfaces->ctrl_iface_init &&
hapd_iface->interfaces->ctrl_iface_init(hapd_iface->bss[0])) {
wpa_printf(MSG_ERROR, "%s: Failed to setup control "
"interface", __func__);
goto fail;
}
wpa_printf(MSG_INFO, "Add interface '%s'", conf->bss[0].iface);
return 0;
fail:
if (conf)
hostapd_config_free(conf);
if (hapd_iface) {
os_free(hapd_iface->bss[interfaces->count]);
os_free(hapd_iface);
}
return -1;
}
int hostapd_remove_iface(struct hapd_interfaces *interfaces, char *buf)
{
struct hostapd_iface *hapd_iface;
size_t i, k = 0;
for (i = 0; i < interfaces->count; i++) {
hapd_iface = interfaces->iface[i];
if (hapd_iface == NULL)
return -1;
if (!os_strcmp(hapd_iface->conf->bss[0].iface, buf)) {
wpa_printf(MSG_INFO, "Remove interface '%s'", buf);
hostapd_interface_deinit_free(hapd_iface);
k = i;
while (k < (interfaces->count - 1)) {
interfaces->iface[k] =
interfaces->iface[k + 1];
k++;
}
interfaces->count--;
return 0;
}
}
return -1;
}
#endif /* HOSTAPD */
/**
* hostapd_new_assoc_sta - Notify that a new station associated with the AP
* @hapd: Pointer to BSS data
@ -930,8 +1379,10 @@ void hostapd_new_assoc_sta(struct hostapd_data *hapd, struct sta_info *sta,
/* Start accounting here, if IEEE 802.1X and WPA are not used.
* IEEE 802.1X/WPA code will start accounting after the station has
* been authorized. */
if (!hapd->conf->ieee802_1x && !hapd->conf->wpa)
if (!hapd->conf->ieee802_1x && !hapd->conf->wpa) {
os_get_time(&sta->connected_time);
accounting_sta_start(hapd, sta);
}
/* Start IEEE 802.1X authentication process for new stations */
ieee802_1x_new_station(hapd, sta);
@ -941,4 +1392,12 @@ void hostapd_new_assoc_sta(struct hostapd_data *hapd, struct sta_info *sta,
wpa_auth_sm_event(sta->wpa_sm, WPA_REAUTH);
} else
wpa_auth_sta_associated(hapd->wpa_auth, sta->wpa_sm);
wpa_printf(MSG_DEBUG, "%s: reschedule ap_handle_timer timeout "
"for " MACSTR " (%d seconds - ap_max_inactivity)",
__func__, MAC2STR(sta->addr),
hapd->conf->ap_max_inactivity);
eloop_cancel_timeout(ap_handle_timer, hapd, sta);
eloop_register_timeout(hapd->conf->ap_max_inactivity, 0,
ap_handle_timer, hapd, sta);
}

View File

@ -2,26 +2,20 @@
* hostapd / Initialization and configuration
* Copyright (c) 2002-2009, Jouni Malinen <j@w1.fi>
*
* This program is free software; you can redistribute it and/or modify
* it under the terms of the GNU General Public License version 2 as
* published by the Free Software Foundation.
*
* Alternatively, this software may be distributed under the terms of BSD
* license.
*
* See README and COPYING for more details.
* This software may be distributed under the terms of the BSD license.
* See README for more details.
*/
#ifndef HOSTAPD_H
#define HOSTAPD_H
#include "common/defs.h"
#include "ap_config.h"
struct wpa_driver_ops;
struct wpa_ctrl_dst;
struct radius_server_data;
struct upnp_wps_device_sm;
struct hapd_interfaces;
struct hostapd_data;
struct sta_info;
struct hostap_sta_driver_data;
@ -30,9 +24,29 @@ struct full_dynamic_vlan;
enum wps_event;
union wps_event_data;
struct hostapd_iface;
struct hapd_interfaces {
int (*reload_config)(struct hostapd_iface *iface);
struct hostapd_config * (*config_read_cb)(const char *config_fname);
int (*ctrl_iface_init)(struct hostapd_data *hapd);
void (*ctrl_iface_deinit)(struct hostapd_data *hapd);
int (*for_each_interface)(struct hapd_interfaces *interfaces,
int (*cb)(struct hostapd_iface *iface,
void *ctx), void *ctx);
int (*driver_init)(struct hostapd_iface *iface);
size_t count;
int global_ctrl_sock;
char *global_iface_path;
char *global_iface_name;
struct hostapd_iface **iface;
};
struct hostapd_probereq_cb {
int (*cb)(void *ctx, const u8 *sa, const u8 *da, const u8 *bssid,
const u8 *ie, size_t ie_len);
const u8 *ie, size_t ie_len, int ssi_signal);
void *ctx;
};
@ -46,7 +60,7 @@ struct hostapd_rate_data {
struct hostapd_frame_info {
u32 channel;
u32 datarate;
u32 ssi_signal;
int ssi_signal; /* dBm */
};
@ -86,6 +100,7 @@ struct hostapd_data {
struct radius_client_data *radius;
u32 acct_session_id_hi, acct_session_id_lo;
struct radius_das_data *radius_das;
struct iapp_data *iapp;
@ -170,6 +185,13 @@ struct hostapd_data {
int noa_start;
int noa_duration;
#endif /* CONFIG_P2P */
#ifdef CONFIG_INTERWORKING
size_t gas_frag_limit;
#endif /* CONFIG_INTERWORKING */
#ifdef CONFIG_SQLITE
struct hostapd_eap_user tmp_eap_user;
#endif /* CONFIG_SQLITE */
};
@ -179,8 +201,6 @@ struct hostapd_data {
struct hostapd_iface {
struct hapd_interfaces *interfaces;
void *owner;
int (*reload_config)(struct hostapd_iface *iface);
struct hostapd_config * (*config_read_cb)(const char *config_fname);
char *config_fname;
struct hostapd_config *conf;
@ -193,6 +213,13 @@ struct hostapd_iface {
struct ap_info *ap_iter_list;
unsigned int drv_flags;
/*
* A bitmap of supported protocols for probe response offload. See
* struct wpa_driver_capa in driver.h
*/
unsigned int probe_resp_offloads;
struct hostapd_hw_modes *hw_features;
int num_hw_features;
struct hostapd_hw_modes *current_mode;
@ -200,6 +227,7 @@ struct hostapd_iface {
* current_mode->channels */
int num_rates;
struct hostapd_rate_data *current_rates;
int *basic_rates;
int freq;
u16 hw_flags;
@ -230,16 +258,12 @@ struct hostapd_iface {
u16 ht_op_mode;
void (*scan_cb)(struct hostapd_iface *iface);
int (*ctrl_iface_init)(struct hostapd_data *hapd);
void (*ctrl_iface_deinit)(struct hostapd_data *hapd);
int (*for_each_interface)(struct hapd_interfaces *interfaces,
int (*cb)(struct hostapd_iface *iface,
void *ctx), void *ctx);
};
/* hostapd.c */
int hostapd_for_each_interface(struct hapd_interfaces *interfaces,
int (*cb)(struct hostapd_iface *iface,
void *ctx), void *ctx);
int hostapd_reload_config(struct hostapd_iface *iface);
struct hostapd_data *
hostapd_alloc_bss_data(struct hostapd_iface *hapd_iface,
@ -251,12 +275,19 @@ void hostapd_interface_deinit(struct hostapd_iface *iface);
void hostapd_interface_free(struct hostapd_iface *iface);
void hostapd_new_assoc_sta(struct hostapd_data *hapd, struct sta_info *sta,
int reassoc);
void hostapd_interface_deinit_free(struct hostapd_iface *iface);
int hostapd_enable_iface(struct hostapd_iface *hapd_iface);
int hostapd_reload_iface(struct hostapd_iface *hapd_iface);
int hostapd_disable_iface(struct hostapd_iface *hapd_iface);
int hostapd_add_iface(struct hapd_interfaces *ifaces, char *buf);
int hostapd_remove_iface(struct hapd_interfaces *ifaces, char *buf);
/* utils.c */
int hostapd_register_probereq_cb(struct hostapd_data *hapd,
int (*cb)(void *ctx, const u8 *sa,
const u8 *da, const u8 *bssid,
const u8 *ie, size_t ie_len),
const u8 *ie, size_t ie_len,
int ssi_signal),
void *ctx);
void hostapd_prune_associations(struct hostapd_data *hapd, const u8 *addr);
@ -266,6 +297,13 @@ int hostapd_notif_assoc(struct hostapd_data *hapd, const u8 *addr,
void hostapd_notif_disassoc(struct hostapd_data *hapd, const u8 *addr);
void hostapd_event_sta_low_ack(struct hostapd_data *hapd, const u8 *addr);
int hostapd_probe_req_rx(struct hostapd_data *hapd, const u8 *sa, const u8 *da,
const u8 *bssid, const u8 *ie, size_t ie_len);
const u8 *bssid, const u8 *ie, size_t ie_len,
int ssi_signal);
void hostapd_event_ch_switch(struct hostapd_data *hapd, int freq, int ht,
int offset);
const struct hostapd_eap_user *
hostapd_get_eap_user(struct hostapd_data *hapd, const u8 *identity,
size_t identity_len, int phase2);
#endif /* HOSTAPD_H */

31
external/bsd/wpa/dist/src/ap/hs20.c vendored Normal file
View 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
external/bsd/wpa/dist/src/ap/hs20.h vendored Normal file
View 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 */

View File

@ -2,7 +2,7 @@
* hostapd / Hardware feature query and different modes
* Copyright 2002-2003, Instant802 Networks, Inc.
* Copyright 2005-2006, Devicescape Software, Inc.
* Copyright (c) 2008-2009, Jouni Malinen <j@w1.fi>
* Copyright (c) 2008-2012, Jouni Malinen <j@w1.fi>
*
* This program is free software; you can redistribute it and/or modify
* it under the terms of the GNU General Public License version 2 as
@ -101,7 +101,7 @@ int hostapd_get_hw_features(struct hostapd_iface *iface)
}
int hostapd_prepare_rates(struct hostapd_data *hapd,
int hostapd_prepare_rates(struct hostapd_iface *iface,
struct hostapd_hw_modes *mode)
{
int i, num_basic_rates = 0;
@ -110,8 +110,8 @@ int hostapd_prepare_rates(struct hostapd_data *hapd,
int basic_rates_g[] = { 10, 20, 55, 110, -1 };
int *basic_rates;
if (hapd->iconf->basic_rates)
basic_rates = hapd->iconf->basic_rates;
if (iface->conf->basic_rates)
basic_rates = iface->conf->basic_rates;
else switch (mode->mode) {
case HOSTAPD_MODE_IEEE80211A:
basic_rates = basic_rates_a;
@ -122,22 +122,28 @@ int hostapd_prepare_rates(struct hostapd_data *hapd,
case HOSTAPD_MODE_IEEE80211G:
basic_rates = basic_rates_g;
break;
case HOSTAPD_MODE_IEEE80211AD:
return 0; /* No basic rates for 11ad */
default:
return -1;
}
if (hostapd_set_rate_sets(hapd, hapd->iconf->supported_rates,
basic_rates, mode->mode)) {
wpa_printf(MSG_ERROR, "Failed to update rate sets in kernel "
"module");
}
i = 0;
while (basic_rates[i] >= 0)
i++;
if (i)
i++; /* -1 termination */
os_free(iface->basic_rates);
iface->basic_rates = os_malloc(i * sizeof(int));
if (iface->basic_rates)
os_memcpy(iface->basic_rates, basic_rates, i * sizeof(int));
os_free(hapd->iface->current_rates);
hapd->iface->num_rates = 0;
os_free(iface->current_rates);
iface->num_rates = 0;
hapd->iface->current_rates =
os_zalloc(mode->num_rates * sizeof(struct hostapd_rate_data));
if (!hapd->iface->current_rates) {
iface->current_rates =
os_calloc(mode->num_rates, sizeof(struct hostapd_rate_data));
if (!iface->current_rates) {
wpa_printf(MSG_ERROR, "Failed to allocate memory for rate "
"table.");
return -1;
@ -146,27 +152,27 @@ int hostapd_prepare_rates(struct hostapd_data *hapd,
for (i = 0; i < mode->num_rates; i++) {
struct hostapd_rate_data *rate;
if (hapd->iconf->supported_rates &&
!hostapd_rate_found(hapd->iconf->supported_rates,
if (iface->conf->supported_rates &&
!hostapd_rate_found(iface->conf->supported_rates,
mode->rates[i]))
continue;
rate = &hapd->iface->current_rates[hapd->iface->num_rates];
rate = &iface->current_rates[iface->num_rates];
rate->rate = mode->rates[i];
if (hostapd_rate_found(basic_rates, rate->rate)) {
rate->flags |= HOSTAPD_RATE_BASIC;
num_basic_rates++;
}
wpa_printf(MSG_DEBUG, "RATE[%d] rate=%d flags=0x%x",
hapd->iface->num_rates, rate->rate, rate->flags);
hapd->iface->num_rates++;
iface->num_rates, rate->rate, rate->flags);
iface->num_rates++;
}
if ((hapd->iface->num_rates == 0 || num_basic_rates == 0) &&
(!hapd->iconf->ieee80211n || !hapd->iconf->require_ht)) {
if ((iface->num_rates == 0 || num_basic_rates == 0) &&
(!iface->conf->ieee80211n || !iface->conf->require_ht)) {
wpa_printf(MSG_ERROR, "No rates remaining in supported/basic "
"rate sets (%d,%d).",
hapd->iface->num_rates, num_basic_rates);
iface->num_rates, num_basic_rates);
return -1;
}
@ -414,7 +420,7 @@ static void ieee80211n_check_scan(struct hostapd_iface *iface)
int res;
/* Check list of neighboring BSSes (from scan) to see whether 40 MHz is
* allowed per IEEE 802.11n/D7.0, 11.14.3.2 */
* allowed per IEEE Std 802.11-2012, 10.15.3.2 */
iface->scan_cb = NULL;
@ -445,6 +451,46 @@ static void ieee80211n_check_scan(struct hostapd_iface *iface)
}
static void ieee80211n_scan_channels_2g4(struct hostapd_iface *iface,
struct wpa_driver_scan_params *params)
{
/* Scan only the affected frequency range */
int pri_freq, sec_freq;
int affected_start, affected_end;
int i, pos;
struct hostapd_hw_modes *mode;
if (iface->current_mode == NULL)
return;
pri_freq = hostapd_hw_get_freq(iface->bss[0], iface->conf->channel);
if (iface->conf->secondary_channel > 0)
sec_freq = pri_freq + 20;
else
sec_freq = pri_freq - 20;
affected_start = (pri_freq + sec_freq) / 2 - 25;
affected_end = (pri_freq + sec_freq) / 2 + 25;
wpa_printf(MSG_DEBUG, "40 MHz affected channel range: [%d,%d] MHz",
affected_start, affected_end);
mode = iface->current_mode;
params->freqs = os_calloc(mode->num_channels + 1, sizeof(int));
if (params->freqs == NULL)
return;
pos = 0;
for (i = 0; i < mode->num_channels; i++) {
struct hostapd_channel_data *chan = &mode->channels[i];
if (chan->flag & HOSTAPD_CHAN_DISABLED)
continue;
if (chan->freq < affected_start ||
chan->freq > affected_end)
continue;
params->freqs[pos++] = chan->freq;
}
}
static int ieee80211n_check_40mhz(struct hostapd_iface *iface)
{
struct wpa_driver_scan_params params;
@ -455,12 +501,15 @@ static int ieee80211n_check_40mhz(struct hostapd_iface *iface)
wpa_printf(MSG_DEBUG, "Scan for neighboring BSSes prior to enabling "
"40 MHz channel");
os_memset(&params, 0, sizeof(params));
/* TODO: scan only the needed frequency */
if (iface->current_mode->mode == HOSTAPD_MODE_IEEE80211G)
ieee80211n_scan_channels_2g4(iface, &params);
if (hostapd_driver_scan(iface->bss[0], &params) < 0) {
wpa_printf(MSG_ERROR, "Failed to request a scan of "
"neighboring BSSes");
os_free(params.freqs);
return -1;
}
os_free(params.freqs);
iface->scan_cb = ieee80211n_check_scan;
return 1;
@ -629,8 +678,15 @@ int hostapd_select_hw_mode(struct hostapd_iface *iface)
if (chan->flag & HOSTAPD_CHAN_DISABLED) {
wpa_printf(MSG_ERROR,
"channel [%i] (%i) is disabled for "
"use in AP mode, flags: 0x%x",
j, chan->chan, chan->flag);
"use in AP mode, flags: 0x%x%s%s%s",
j, chan->chan, chan->flag,
chan->flag & HOSTAPD_CHAN_NO_IBSS ?
" NO-IBSS" : "",
chan->flag &
HOSTAPD_CHAN_PASSIVE_SCAN ?
" PASSIVE-SCAN" : "",
chan->flag & HOSTAPD_CHAN_RADAR ?
" RADAR" : "");
} else {
ok = 1;
break;
@ -702,6 +758,8 @@ const char * hostapd_hw_mode_txt(int mode)
return "IEEE 802.11b";
case HOSTAPD_MODE_IEEE80211G:
return "IEEE 802.11g";
case HOSTAPD_MODE_IEEE80211AD:
return "IEEE 802.11ad";
default:
return "UNKNOWN";
}

View File

@ -2,6 +2,7 @@
* hostapd / Hardware feature query and different modes
* Copyright 2002-2003, Instant802 Networks, Inc.
* Copyright 2005-2006, Devicescape Software, Inc.
* Copyright (c) 2008-2011, Jouni Malinen <j@w1.fi>
*
* This program is free software; you can redistribute it and/or modify
* it under the terms of the GNU General Public License version 2 as
@ -25,7 +26,7 @@ const char * hostapd_hw_mode_txt(int mode);
int hostapd_hw_get_freq(struct hostapd_data *hapd, int chan);
int hostapd_hw_get_channel(struct hostapd_data *hapd, int freq);
int hostapd_check_ht_capab(struct hostapd_iface *iface);
int hostapd_prepare_rates(struct hostapd_data *hapd,
int hostapd_prepare_rates(struct hostapd_iface *iface,
struct hostapd_hw_modes *mode);
#else /* NEED_AP_MLME */
static inline void
@ -59,7 +60,7 @@ static inline int hostapd_check_ht_capab(struct hostapd_iface *iface)
return 0;
}
static inline int hostapd_prepare_rates(struct hostapd_data *hapd,
static inline int hostapd_prepare_rates(struct hostapd_iface *iface,
struct hostapd_hw_modes *mode)
{
return 0;

View File

@ -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

View File

@ -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

View File

@ -1,15 +1,9 @@
/*
* hostapd / IEEE 802.11 Management
* Copyright (c) 2002-2011, Jouni Malinen <j@w1.fi>
* Copyright (c) 2002-2012, Jouni Malinen <j@w1.fi>
*
* This program is free software; you can redistribute it and/or modify
* it under the terms of the GNU General Public License version 2 as
* published by the Free Software Foundation.
*
* Alternatively, this software may be distributed under the terms of BSD
* license.
*
* See README and COPYING for more details.
* This software may be distributed under the terms of the BSD license.
* See README for more details.
*/
#include "utils/includes.h"
@ -40,6 +34,7 @@
#include "ap_mlme.h"
#include "p2p_hostapd.h"
#include "ap_drv_ops.h"
#include "wnm_ap.h"
#include "ieee802_11.h"
@ -55,6 +50,8 @@ u8 * hostapd_eid_supp_rates(struct hostapd_data *hapd, u8 *eid)
num = hapd->iface->num_rates;
if (hapd->iconf->ieee80211n && hapd->iconf->require_ht)
num++;
if (hapd->iconf->ieee80211ac && hapd->iconf->require_vht)
num++;
if (num > 8) {
/* rest of the rates are encoded in Extended supported
* rates element */
@ -72,9 +69,15 @@ u8 * hostapd_eid_supp_rates(struct hostapd_data *hapd, u8 *eid)
pos++;
}
if (hapd->iconf->ieee80211n && hapd->iconf->require_ht &&
hapd->iface->num_rates < 8)
if (hapd->iconf->ieee80211n && hapd->iconf->require_ht && count < 8) {
count++;
*pos++ = 0x80 | BSS_MEMBERSHIP_SELECTOR_HT_PHY;
}
if (hapd->iconf->ieee80211ac && hapd->iconf->require_vht && count < 8) {
count++;
*pos++ = 0x80 | BSS_MEMBERSHIP_SELECTOR_VHT_PHY;
}
return pos;
}
@ -91,6 +94,8 @@ u8 * hostapd_eid_ext_supp_rates(struct hostapd_data *hapd, u8 *eid)
num = hapd->iface->num_rates;
if (hapd->iconf->ieee80211n && hapd->iconf->require_ht)
num++;
if (hapd->iconf->ieee80211ac && hapd->iconf->require_vht)
num++;
if (num <= 8)
return eid;
num -= 8;
@ -109,9 +114,17 @@ u8 * hostapd_eid_ext_supp_rates(struct hostapd_data *hapd, u8 *eid)
pos++;
}
if (hapd->iconf->ieee80211n && hapd->iconf->require_ht &&
hapd->iface->num_rates >= 8)
*pos++ = 0x80 | BSS_MEMBERSHIP_SELECTOR_HT_PHY;
if (hapd->iconf->ieee80211n && hapd->iconf->require_ht) {
count++;
if (count > 8)
*pos++ = 0x80 | BSS_MEMBERSHIP_SELECTOR_HT_PHY;
}
if (hapd->iconf->ieee80211ac && hapd->iconf->require_vht) {
count++;
if (count > 8)
*pos++ = 0x80 | BSS_MEMBERSHIP_SELECTOR_VHT_PHY;
}
return pos;
}
@ -269,7 +282,7 @@ static void send_auth_reply(struct hostapd_data *hapd,
" auth_alg=%d auth_transaction=%d resp=%d (IE len=%lu)",
MAC2STR(dst), auth_alg, auth_transaction,
resp, (unsigned long) ies_len);
if (hostapd_drv_send_mlme(hapd, reply, rlen) < 0)
if (hostapd_drv_send_mlme(hapd, reply, rlen, 0) < 0)
perror("send_auth_reply: send");
os_free(buf);
@ -302,6 +315,142 @@ static void handle_auth_ft_finish(void *ctx, const u8 *dst, const u8 *bssid,
#endif /* CONFIG_IEEE80211R */
#ifdef CONFIG_SAE
static struct wpabuf * auth_build_sae_commit(struct hostapd_data *hapd,
struct sta_info *sta)
{
struct wpabuf *buf;
buf = wpabuf_alloc(2);
if (buf == NULL)
return NULL;
wpabuf_put_le16(buf, 19); /* Finite Cyclic Group */
/* TODO: Anti-Clogging Token (if requested) */
/* TODO: Scalar */
/* TODO: Element */
return buf;
}
static struct wpabuf * auth_build_sae_confirm(struct hostapd_data *hapd,
struct sta_info *sta)
{
struct wpabuf *buf;
buf = wpabuf_alloc(2);
if (buf == NULL)
return NULL;
wpabuf_put_le16(buf, sta->sae_send_confirm);
sta->sae_send_confirm++;
/* TODO: Confirm */
return buf;
}
static u16 handle_sae_commit(struct hostapd_data *hapd, struct sta_info *sta,
const u8 *data, size_t len)
{
wpa_hexdump(MSG_DEBUG, "SAE commit fields", data, len);
/* Check Finite Cyclic Group */
if (len < 2)
return WLAN_STATUS_UNSPECIFIED_FAILURE;
if (WPA_GET_LE16(data) != 19) {
wpa_printf(MSG_DEBUG, "SAE: Unsupported Finite Cyclic Group %u",
WPA_GET_LE16(data));
return WLAN_STATUS_FINITE_CYCLIC_GROUP_NOT_SUPPORTED;
}
return WLAN_STATUS_SUCCESS;
}
static u16 handle_sae_confirm(struct hostapd_data *hapd, struct sta_info *sta,
const u8 *data, size_t len)
{
u16 rc;
wpa_hexdump(MSG_DEBUG, "SAE confirm fields", data, len);
if (len < 2)
return WLAN_STATUS_UNSPECIFIED_FAILURE;
rc = WPA_GET_LE16(data);
wpa_printf(MSG_DEBUG, "SAE: peer-send-confirm %u", rc);
return WLAN_STATUS_SUCCESS;
}
static void handle_auth_sae(struct hostapd_data *hapd, struct sta_info *sta,
const struct ieee80211_mgmt *mgmt, size_t len,
u8 auth_transaction)
{
u16 resp = WLAN_STATUS_SUCCESS;
struct wpabuf *data;
if (auth_transaction == 1) {
hostapd_logger(hapd, sta->addr, HOSTAPD_MODULE_IEEE80211,
HOSTAPD_LEVEL_DEBUG,
"start SAE authentication (RX commit)");
resp = handle_sae_commit(hapd, sta, mgmt->u.auth.variable,
((u8 *) mgmt) + len -
mgmt->u.auth.variable);
if (resp == WLAN_STATUS_SUCCESS)
sta->sae_state = SAE_COMMIT;
} else if (auth_transaction == 2) {
if (sta->sae_state != SAE_COMMIT) {
hostapd_logger(hapd, sta->addr,
HOSTAPD_MODULE_IEEE80211,
HOSTAPD_LEVEL_DEBUG,
"SAE confirm before commit");
resp = WLAN_STATUS_UNKNOWN_AUTH_TRANSACTION;
}
hostapd_logger(hapd, sta->addr, HOSTAPD_MODULE_IEEE80211,
HOSTAPD_LEVEL_DEBUG,
"SAE authentication (RX confirm)");
resp = handle_sae_confirm(hapd, sta, mgmt->u.auth.variable,
((u8 *) mgmt) + len -
mgmt->u.auth.variable);
if (resp == WLAN_STATUS_SUCCESS) {
sta->flags |= WLAN_STA_AUTH;
wpa_auth_sm_event(sta->wpa_sm, WPA_AUTH);
sta->auth_alg = WLAN_AUTH_SAE;
mlme_authenticate_indication(hapd, sta);
}
} else {
hostapd_logger(hapd, sta->addr, HOSTAPD_MODULE_IEEE80211,
HOSTAPD_LEVEL_DEBUG,
"unexpected SAE authentication transaction %u",
auth_transaction);
resp = WLAN_STATUS_UNKNOWN_AUTH_TRANSACTION;
}
sta->auth_alg = WLAN_AUTH_SAE;
if (resp == WLAN_STATUS_SUCCESS) {
if (auth_transaction == 1)
data = auth_build_sae_commit(hapd, sta);
else
data = auth_build_sae_confirm(hapd, sta);
if (data == NULL)
resp = WLAN_STATUS_UNSPECIFIED_FAILURE;
} else
data = NULL;
send_auth_reply(hapd, mgmt->sa, mgmt->bssid, WLAN_AUTH_SAE,
auth_transaction, resp,
data ? wpabuf_head(data) : (u8 *) "",
data ? wpabuf_len(data) : 0);
wpabuf_free(data);
}
#endif /* CONFIG_SAE */
static void handle_auth(struct hostapd_data *hapd,
const struct ieee80211_mgmt *mgmt, size_t len)
{
@ -313,8 +462,11 @@ static void handle_auth(struct hostapd_data *hapd,
const u8 *challenge = NULL;
u32 session_timeout, acct_interim_interval;
int vlan_id = 0;
struct hostapd_sta_wpa_psk_short *psk = NULL;
u8 resp_ies[2 + WLAN_AUTH_CHALLENGE_LEN];
size_t resp_ies_len = 0;
char *identity = NULL;
char *radius_cui = NULL;
if (len < IEEE80211_HDRLEN + sizeof(mgmt->u.auth)) {
printf("handle_auth - too short payload (len=%lu)\n",
@ -347,11 +499,13 @@ static void handle_auth(struct hostapd_data *hapd,
if (!(((hapd->conf->auth_algs & WPA_AUTH_ALG_OPEN) &&
auth_alg == WLAN_AUTH_OPEN) ||
#ifdef CONFIG_IEEE80211R
(hapd->conf->wpa &&
(hapd->conf->wpa_key_mgmt &
(WPA_KEY_MGMT_FT_IEEE8021X | WPA_KEY_MGMT_FT_PSK)) &&
(hapd->conf->wpa && wpa_key_mgmt_ft(hapd->conf->wpa_key_mgmt) &&
auth_alg == WLAN_AUTH_FT) ||
#endif /* CONFIG_IEEE80211R */
#ifdef CONFIG_SAE
(hapd->conf->wpa && wpa_key_mgmt_sae(hapd->conf->wpa_key_mgmt) &&
auth_alg == WLAN_AUTH_SAE) ||
#endif /* CONFIG_SAE */
((hapd->conf->auth_algs & WPA_AUTH_ALG_SHARED) &&
auth_alg == WLAN_AUTH_SHARED_KEY))) {
printf("Unsupported authentication algorithm (%d)\n",
@ -360,7 +514,7 @@ static void handle_auth(struct hostapd_data *hapd,
goto fail;
}
if (!(auth_transaction == 1 ||
if (!(auth_transaction == 1 || auth_alg == WLAN_AUTH_SAE ||
(auth_alg == WLAN_AUTH_SHARED_KEY && auth_transaction == 3))) {
printf("Unknown authentication transaction number (%d)\n",
auth_transaction);
@ -377,7 +531,9 @@ static void handle_auth(struct hostapd_data *hapd,
res = hostapd_allowed_address(hapd, mgmt->sa, (u8 *) mgmt, len,
&session_timeout,
&acct_interim_interval, &vlan_id);
&acct_interim_interval, &vlan_id,
&psk, &identity, &radius_cui);
if (res == HOSTAPD_ACL_REJECT) {
printf("Station " MACSTR " not allowed to authenticate.\n",
MAC2STR(mgmt->sa));
@ -415,6 +571,19 @@ static void handle_auth(struct hostapd_data *hapd,
HOSTAPD_LEVEL_INFO, "VLAN ID %d", sta->vlan_id);
}
hostapd_free_psk_list(sta->psk);
if (hapd->conf->wpa_psk_radius != PSK_RADIUS_IGNORED) {
sta->psk = psk;
psk = NULL;
} else {
sta->psk = NULL;
}
sta->identity = identity;
identity = NULL;
sta->radius_cui = radius_cui;
radius_cui = NULL;
sta->flags &= ~WLAN_STA_PREAUTH;
ieee802_1x_notify_pre_auth(sta->eapol_sm, 0);
@ -473,9 +642,18 @@ static void handle_auth(struct hostapd_data *hapd,
/* handle_auth_ft_finish() callback will complete auth. */
return;
#endif /* CONFIG_IEEE80211R */
#ifdef CONFIG_SAE
case WLAN_AUTH_SAE:
handle_auth_sae(hapd, sta, mgmt, len, auth_transaction);
return;
#endif /* CONFIG_SAE */
}
fail:
os_free(identity);
os_free(radius_cui);
hostapd_free_psk_list(psk);
send_auth_reply(hapd, mgmt->sa, mgmt->bssid, auth_alg,
auth_transaction + 1, resp, resp_ies, resp_ies_len);
}
@ -539,15 +717,22 @@ static u16 check_wmm(struct hostapd_data *hapd, struct sta_info *sta,
const u8 *wmm_ie, size_t wmm_ie_len)
{
sta->flags &= ~WLAN_STA_WMM;
sta->qosinfo = 0;
if (wmm_ie && hapd->conf->wmm_enabled) {
if (!hostapd_eid_wmm_valid(hapd, wmm_ie, wmm_ie_len))
struct wmm_information_element *wmm;
if (!hostapd_eid_wmm_valid(hapd, wmm_ie, wmm_ie_len)) {
hostapd_logger(hapd, sta->addr,
HOSTAPD_MODULE_WPA,
HOSTAPD_LEVEL_DEBUG,
"invalid WMM element in association "
"request");
else
sta->flags |= WLAN_STA_WMM;
return WLAN_STATUS_UNSPECIFIED_FAILURE;
}
sta->flags |= WLAN_STA_WMM;
wmm = (struct wmm_information_element *) wmm_ie;
sta->qosinfo = wmm->qos_info;
}
return WLAN_STATUS_SUCCESS;
}
@ -563,35 +748,20 @@ static u16 copy_supp_rates(struct hostapd_data *hapd, struct sta_info *sta,
return WLAN_STATUS_UNSPECIFIED_FAILURE;
}
if (elems->supp_rates_len > sizeof(sta->supported_rates)) {
if (elems->supp_rates_len + elems->ext_supp_rates_len >
sizeof(sta->supported_rates)) {
hostapd_logger(hapd, sta->addr, HOSTAPD_MODULE_IEEE80211,
HOSTAPD_LEVEL_DEBUG,
"Invalid supported rates element length %d",
elems->supp_rates_len);
"Invalid supported rates element length %d+%d",
elems->supp_rates_len,
elems->ext_supp_rates_len);
return WLAN_STATUS_UNSPECIFIED_FAILURE;
}
os_memset(sta->supported_rates, 0, sizeof(sta->supported_rates));
os_memcpy(sta->supported_rates, elems->supp_rates,
elems->supp_rates_len);
sta->supported_rates_len = elems->supp_rates_len;
if (elems->ext_supp_rates) {
if (elems->supp_rates_len + elems->ext_supp_rates_len >
sizeof(sta->supported_rates)) {
hostapd_logger(hapd, sta->addr,
HOSTAPD_MODULE_IEEE80211,
HOSTAPD_LEVEL_DEBUG,
"Invalid supported rates element length"
" %d+%d", elems->supp_rates_len,
elems->ext_supp_rates_len);
return WLAN_STATUS_UNSPECIFIED_FAILURE;
}
os_memcpy(sta->supported_rates + elems->supp_rates_len,
elems->ext_supp_rates, elems->ext_supp_rates_len);
sta->supported_rates_len += elems->ext_supp_rates_len;
}
sta->supported_rates_len = merge_byte_arrays(
sta->supported_rates, sizeof(sta->supported_rates),
elems->supp_rates, elems->supp_rates_len,
elems->ext_supp_rates, elems->ext_supp_rates_len);
return WLAN_STATUS_SUCCESS;
}
@ -635,6 +805,20 @@ static u16 check_assoc_ies(struct hostapd_data *hapd, struct sta_info *sta,
}
#endif /* CONFIG_IEEE80211N */
#ifdef CONFIG_IEEE80211AC
resp = copy_sta_vht_capab(hapd, sta, elems.vht_capabilities,
elems.vht_capabilities_len);
if (resp != WLAN_STATUS_SUCCESS)
return resp;
if (hapd->iconf->ieee80211ac && hapd->iconf->require_vht &&
!(sta->flags & WLAN_STA_VHT)) {
hostapd_logger(hapd, sta->addr, HOSTAPD_MODULE_IEEE80211,
HOSTAPD_LEVEL_INFO, "Station does not support "
"mandatory VHT PHY - reject association");
return WLAN_STATUS_UNSPECIFIED_FAILURE;
}
#endif /* CONFIG_IEEE80211AC */
if ((hapd->conf->wpa & WPA_PROTO_RSN) && elems.rsn_ie) {
wpa_ie = elems.rsn_ie;
wpa_ie_len = elems.rsn_ie_len;
@ -757,8 +941,18 @@ static u16 check_assoc_ies(struct hostapd_data *hapd, struct sta_info *sta,
}
#endif /* CONFIG_IEEE80211R */
#ifdef CONFIG_SAE
if (wpa_auth_uses_sae(sta->wpa_sm) &&
sta->auth_alg != WLAN_AUTH_SAE) {
wpa_printf(MSG_DEBUG, "SAE: " MACSTR " tried to use "
"SAE AKM after non-SAE auth_alg %u",
MAC2STR(sta->addr), sta->auth_alg);
return WLAN_STATUS_NOT_SUPPORTED_AUTH_ALG;
}
#endif /* CONFIG_SAE */
#ifdef CONFIG_IEEE80211N
if ((sta->flags & WLAN_STA_HT) &&
if ((sta->flags & (WLAN_STA_HT | WLAN_STA_VHT)) &&
wpa_auth_get_pairwise(sta->wpa_sm) == WPA_CIPHER_TKIP) {
hostapd_logger(hapd, sta->addr,
HOSTAPD_MODULE_IEEE80211,
@ -785,6 +979,15 @@ static u16 check_assoc_ies(struct hostapd_data *hapd, struct sta_info *sta,
p2p_group_notif_assoc(hapd->p2p_group, sta->addr, ies, ies_len);
#endif /* CONFIG_P2P */
#ifdef CONFIG_HS20
wpabuf_free(sta->hs20_ie);
if (elems.hs20 && elems.hs20_len > 4) {
sta->hs20_ie = wpabuf_alloc_copy(elems.hs20 + 4,
elems.hs20_len - 4);
} else
sta->hs20_ie = NULL;
#endif /* CONFIG_HS20 */
return WLAN_STATUS_SUCCESS;
}
@ -805,7 +1008,7 @@ static void send_deauth(struct hostapd_data *hapd, const u8 *addr,
send_len = IEEE80211_HDRLEN + sizeof(reply.u.deauth);
reply.u.deauth.reason_code = host_to_le16(reason_code);
if (hostapd_drv_send_mlme(hapd, &reply, send_len) < 0)
if (hostapd_drv_send_mlme(hapd, &reply, send_len, 0) < 0)
wpa_printf(MSG_INFO, "Failed to send deauth: %s",
strerror(errno));
}
@ -862,7 +1065,13 @@ static void send_assoc_resp(struct hostapd_data *hapd, struct sta_info *sta,
p = hostapd_eid_ht_operation(hapd, p);
#endif /* CONFIG_IEEE80211N */
#ifdef CONFIG_IEEE80211AC
p = hostapd_eid_vht_capabilities(hapd, p);
p = hostapd_eid_vht_operation(hapd, p);
#endif /* CONFIG_IEEE80211AC */
p = hostapd_eid_ext_capab(hapd, p);
p = hostapd_eid_bss_max_idle_period(hapd, p);
if (sta->flags & WLAN_STA_WMM)
p = hostapd_eid_wmm(hapd, p);
@ -911,7 +1120,7 @@ static void send_assoc_resp(struct hostapd_data *hapd, struct sta_info *sta,
send_len += p - reply->u.assoc_resp.variable;
if (hostapd_drv_send_mlme(hapd, reply, send_len) < 0)
if (hostapd_drv_send_mlme(hapd, reply, send_len, 0) < 0)
wpa_printf(MSG_INFO, "Failed to send assoc resp: %s",
strerror(errno));
}
@ -1226,13 +1435,32 @@ static int robust_action_frame(u8 category)
#endif /* CONFIG_IEEE80211W */
#ifdef CONFIG_WNM
static void hostapd_wnm_action(struct hostapd_data *hapd, struct sta_info *sta,
const struct ieee80211_mgmt *mgmt,
size_t len)
{
struct rx_action action;
if (len < IEEE80211_HDRLEN + 2)
return;
os_memset(&action, 0, sizeof(action));
action.da = mgmt->da;
action.sa = mgmt->sa;
action.bssid = mgmt->bssid;
action.category = mgmt->u.action.category;
action.data = (const u8 *) &mgmt->u.action.u.wnm_sleep_req.action;
action.len = len - IEEE80211_HDRLEN - 1;
action.freq = hapd->iface->freq;
ieee802_11_rx_wnm_action_ap(hapd, &action);
}
#endif /* CONFIG_WNM */
static void handle_action(struct hostapd_data *hapd,
const struct ieee80211_mgmt *mgmt, size_t len)
{
#if defined(CONFIG_IEEE80211W) || defined(CONFIG_IEEE80211R)
struct sta_info *sta;
sta = ap_get_sta(hapd, mgmt->sa);
#endif /* CONFIG_IEEE80211W || CONFIG_IEEE80211R */
if (len < IEEE80211_HDRLEN + 1) {
hostapd_logger(hapd, mgmt->sa, HOSTAPD_MODULE_IEEE80211,
@ -1242,6 +1470,14 @@ static void handle_action(struct hostapd_data *hapd,
return;
}
if (mgmt->u.action.category != WLAN_ACTION_PUBLIC &&
(sta == NULL || !(sta->flags & WLAN_STA_ASSOC))) {
wpa_printf(MSG_DEBUG, "IEEE 802.11: Ignored Action "
"frame (category=%u) from unassociated STA " MACSTR,
MAC2STR(mgmt->sa), mgmt->u.action.category);
return;
}
#ifdef CONFIG_IEEE80211W
if (sta && (sta->flags & WLAN_STA_MFP) &&
!(mgmt->frame_control & host_to_le16(WLAN_FC_ISWEP) &&
@ -1257,20 +1493,10 @@ static void handle_action(struct hostapd_data *hapd,
switch (mgmt->u.action.category) {
#ifdef CONFIG_IEEE80211R
case WLAN_ACTION_FT:
{
if (sta == NULL || !(sta->flags & WLAN_STA_ASSOC)) {
wpa_printf(MSG_DEBUG, "IEEE 802.11: Ignored FT Action "
"frame from unassociated STA " MACSTR,
MAC2STR(mgmt->sa));
return;
}
if (wpa_ft_action_rx(sta->wpa_sm, (u8 *) &mgmt->u.action,
len - IEEE80211_HDRLEN))
break;
return;
}
#endif /* CONFIG_IEEE80211R */
case WLAN_ACTION_WMM:
hostapd_wmm_action(hapd, mgmt, len);
@ -1280,6 +1506,11 @@ static void handle_action(struct hostapd_data *hapd,
hostapd_sa_query_action(hapd, mgmt, len);
return;
#endif /* CONFIG_IEEE80211W */
#ifdef CONFIG_WNM
case WLAN_ACTION_WNM:
hostapd_wnm_action(hapd, sta, mgmt, len);
return;
#endif /* CONFIG_WNM */
case WLAN_ACTION_PUBLIC:
if (hapd->public_action_cb) {
hapd->public_action_cb(hapd->public_action_cb_ctx,
@ -1323,7 +1554,10 @@ static void handle_action(struct hostapd_data *hapd,
os_memcpy(resp->bssid, hapd->own_addr, ETH_ALEN);
resp->u.action.category |= 0x80;
hostapd_drv_send_mlme(hapd, resp, len);
if (hostapd_drv_send_mlme(hapd, resp, len, 0) < 0) {
wpa_printf(MSG_ERROR, "IEEE 802.11: Failed to send "
"Action frame");
}
os_free(resp);
}
}
@ -1379,7 +1613,7 @@ void ieee802_11_mgmt(struct hostapd_data *hapd, const u8 *buf, size_t len,
if (stype == WLAN_FC_STYPE_PROBE_REQ) {
handle_probe_req(hapd, mgmt, len);
handle_probe_req(hapd, mgmt, len, fi->ssi_signal);
return;
}
@ -1475,13 +1709,6 @@ static void handle_assoc_cb(struct hostapd_data *hapd,
int new_assoc = 1;
struct ieee80211_ht_capabilities ht_cap;
if (!ok) {
hostapd_logger(hapd, mgmt->da, HOSTAPD_MODULE_IEEE80211,
HOSTAPD_LEVEL_DEBUG,
"did not acknowledge association response");
return;
}
if (len < IEEE80211_HDRLEN + (reassoc ? sizeof(mgmt->u.reassoc_resp) :
sizeof(mgmt->u.assoc_resp))) {
printf("handle_assoc_cb(reassoc=%d) - too short payload "
@ -1489,11 +1716,6 @@ static void handle_assoc_cb(struct hostapd_data *hapd,
return;
}
if (reassoc)
status = le_to_host16(mgmt->u.reassoc_resp.status_code);
else
status = le_to_host16(mgmt->u.assoc_resp.status_code);
sta = ap_get_sta(hapd, mgmt->da);
if (!sta) {
printf("handle_assoc_cb: STA " MACSTR " not found\n",
@ -1501,6 +1723,19 @@ static void handle_assoc_cb(struct hostapd_data *hapd,
return;
}
if (!ok) {
hostapd_logger(hapd, mgmt->da, HOSTAPD_MODULE_IEEE80211,
HOSTAPD_LEVEL_DEBUG,
"did not acknowledge association response");
sta->flags &= ~WLAN_STA_ASSOC_REQ_OK;
return;
}
if (reassoc)
status = le_to_host16(mgmt->u.reassoc_resp.status_code);
else
status = le_to_host16(mgmt->u.assoc_resp.status_code);
if (status != WLAN_STATUS_SUCCESS)
goto fail;
@ -1550,7 +1785,7 @@ static void handle_assoc_cb(struct hostapd_data *hapd,
sta->supported_rates, sta->supported_rates_len,
sta->listen_interval,
sta->flags & WLAN_STA_HT ? &ht_cap : NULL,
sta->flags)) {
sta->flags, sta->qosinfo)) {
hostapd_logger(hapd, sta->addr, HOSTAPD_MODULE_IEEE80211,
HOSTAPD_LEVEL_NOTICE,
"Could not add STA to kernel driver");
@ -1739,6 +1974,33 @@ void hostapd_tx_status(struct hostapd_data *hapd, const u8 *addr,
}
void hostapd_eapol_tx_status(struct hostapd_data *hapd, const u8 *dst,
const u8 *data, size_t len, int ack)
{
struct sta_info *sta;
struct hostapd_iface *iface = hapd->iface;
sta = ap_get_sta(hapd, dst);
if (sta == NULL && iface->num_bss > 1) {
size_t j;
for (j = 0; j < iface->num_bss; j++) {
hapd = iface->bss[j];
sta = ap_get_sta(hapd, dst);
if (sta)
break;
}
}
if (sta == NULL || !(sta->flags & WLAN_STA_ASSOC)) {
wpa_printf(MSG_DEBUG, "Ignore TX status for Data frame to STA "
MACSTR " that is not currently associated",
MAC2STR(dst));
return;
}
ieee802_1x_eapol_tx_status(hapd, sta, data, len, ack);
}
void hostapd_client_poll_ok(struct hostapd_data *hapd, const u8 *addr)
{
struct sta_info *sta;
@ -1772,6 +2034,9 @@ void ieee802_11_rx_from_unknown(struct hostapd_data *hapd, const u8 *src,
sta = ap_get_sta(hapd, src);
if (sta && (sta->flags & WLAN_STA_ASSOC)) {
if (!hapd->conf->wds_sta)
return;
if (wds && !(sta->flags & WLAN_STA_WDS)) {
wpa_printf(MSG_DEBUG, "Enable 4-address WDS mode for "
"STA " MACSTR " (aid %u)",

View File

@ -2,14 +2,8 @@
* hostapd / IEEE 802.11 Management
* Copyright (c) 2002-2009, Jouni Malinen <j@w1.fi>
*
* This program is free software; you can redistribute it and/or modify
* it under the terms of the GNU General Public License version 2 as
* published by the Free Software Foundation.
*
* Alternatively, this software may be distributed under the terms of BSD
* license.
*
* See README and COPYING for more details.
* This software may be distributed under the terms of the BSD license.
* See README for more details.
*/
#ifndef IEEE802_11_H
@ -51,6 +45,8 @@ u8 * hostapd_eid_supp_rates(struct hostapd_data *hapd, u8 *eid);
u8 * hostapd_eid_ext_supp_rates(struct hostapd_data *hapd, u8 *eid);
u8 * hostapd_eid_ht_capabilities(struct hostapd_data *hapd, u8 *eid);
u8 * hostapd_eid_ht_operation(struct hostapd_data *hapd, u8 *eid);
u8 * hostapd_eid_vht_capabilities(struct hostapd_data *hapd, u8 *eid);
u8 * hostapd_eid_vht_operation(struct hostapd_data *hapd, u8 *eid);
int hostapd_ht_operation_update(struct hostapd_iface *iface);
void ieee802_11_send_sa_query_req(struct hostapd_data *hapd,
const u8 *addr, const u8 *trans_id);
@ -60,8 +56,12 @@ void hostapd_get_ht_capab(struct hostapd_data *hapd,
u16 copy_sta_ht_capab(struct hostapd_data *hapd, struct sta_info *sta,
const u8 *ht_capab, size_t ht_capab_len);
void update_ht_state(struct hostapd_data *hapd, struct sta_info *sta);
u16 copy_sta_vht_capab(struct hostapd_data *hapd, struct sta_info *sta,
const u8 *vht_capab, size_t vht_capab_len);
void hostapd_tx_status(struct hostapd_data *hapd, const u8 *addr,
const u8 *buf, size_t len, int ack);
void hostapd_eapol_tx_status(struct hostapd_data *hapd, const u8 *dst,
const u8 *data, size_t len, int ack);
void ieee802_11_rx_from_unknown(struct hostapd_data *hapd, const u8 *src,
int wds);
u8 * hostapd_eid_assoc_comeback_time(struct hostapd_data *hapd,
@ -76,5 +76,6 @@ u8 * hostapd_eid_time_adv(struct hostapd_data *hapd, u8 *eid);
u8 * hostapd_eid_time_zone(struct hostapd_data *hapd, u8 *eid);
int hostapd_update_time_adv(struct hostapd_data *hapd);
void hostapd_client_poll_ok(struct hostapd_data *hapd, const u8 *addr);
u8 * hostapd_eid_bss_max_idle_period(struct hostapd_data *hapd, u8 *eid);
#endif /* IEEE802_11_H */

View File

@ -1,15 +1,9 @@
/*
* hostapd / IEEE 802.11 authentication (ACL)
* Copyright (c) 2003-2009, Jouni Malinen <j@w1.fi>
* Copyright (c) 2003-2012, Jouni Malinen <j@w1.fi>
*
* This program is free software; you can redistribute it and/or modify
* it under the terms of the GNU General Public License version 2 as
* published by the Free Software Foundation.
*
* Alternatively, this software may be distributed under the terms of BSD
* license.
*
* See README and COPYING for more details.
* This software may be distributed under the terms of the BSD license.
* See README for more details.
*
* Access control list for IEEE 802.11 authentication can uses statically
* configured ACL from configuration files or an external RADIUS server.
@ -21,12 +15,14 @@
#include "utils/common.h"
#include "utils/eloop.h"
#include "crypto/sha1.h"
#include "radius/radius.h"
#include "radius/radius_client.h"
#include "hostapd.h"
#include "ap_config.h"
#include "ap_drv_ops.h"
#include "ieee802_11.h"
#include "ieee802_1x.h"
#include "ieee802_11_auth.h"
#define RADIUS_ACL_TIMEOUT 30
@ -40,6 +36,9 @@ struct hostapd_cached_radius_acl {
u32 session_timeout;
u32 acct_interim_interval;
int vlan_id;
struct hostapd_sta_wpa_psk_short *psk;
char *identity;
char *radius_cui;
};
@ -54,6 +53,15 @@ struct hostapd_acl_query_data {
#ifndef CONFIG_NO_RADIUS
static void hostapd_acl_cache_free_entry(struct hostapd_cached_radius_acl *e)
{
os_free(e->identity);
os_free(e->radius_cui);
hostapd_free_psk_list(e->psk);
os_free(e);
}
static void hostapd_acl_cache_free(struct hostapd_cached_radius_acl *acl_cache)
{
struct hostapd_cached_radius_acl *prev;
@ -61,38 +69,73 @@ static void hostapd_acl_cache_free(struct hostapd_cached_radius_acl *acl_cache)
while (acl_cache) {
prev = acl_cache;
acl_cache = acl_cache->next;
os_free(prev);
hostapd_acl_cache_free_entry(prev);
}
}
static void copy_psk_list(struct hostapd_sta_wpa_psk_short **psk,
struct hostapd_sta_wpa_psk_short *src)
{
struct hostapd_sta_wpa_psk_short **copy_to;
struct hostapd_sta_wpa_psk_short *copy_from;
/* Copy PSK linked list */
copy_to = psk;
copy_from = src;
while (copy_from && copy_to) {
*copy_to = os_zalloc(sizeof(struct hostapd_sta_wpa_psk_short));
if (*copy_to == NULL)
break;
os_memcpy(*copy_to, copy_from,
sizeof(struct hostapd_sta_wpa_psk_short));
copy_from = copy_from->next;
copy_to = &((*copy_to)->next);
}
if (copy_to)
*copy_to = NULL;
}
static int hostapd_acl_cache_get(struct hostapd_data *hapd, const u8 *addr,
u32 *session_timeout,
u32 *acct_interim_interval, int *vlan_id)
u32 *acct_interim_interval, int *vlan_id,
struct hostapd_sta_wpa_psk_short **psk,
char **identity, char **radius_cui)
{
struct hostapd_cached_radius_acl *entry;
struct os_time now;
os_get_time(&now);
entry = hapd->acl_cache;
while (entry) {
if (os_memcmp(entry->addr, addr, ETH_ALEN) == 0) {
if (now.sec - entry->timestamp > RADIUS_ACL_TIMEOUT)
return -1; /* entry has expired */
if (entry->accepted == HOSTAPD_ACL_ACCEPT_TIMEOUT)
if (session_timeout)
*session_timeout =
entry->session_timeout;
if (acct_interim_interval)
*acct_interim_interval =
entry->acct_interim_interval;
if (vlan_id)
*vlan_id = entry->vlan_id;
return entry->accepted;
for (entry = hapd->acl_cache; entry; entry = entry->next) {
if (os_memcmp(entry->addr, addr, ETH_ALEN) != 0)
continue;
if (now.sec - entry->timestamp > RADIUS_ACL_TIMEOUT)
return -1; /* entry has expired */
if (entry->accepted == HOSTAPD_ACL_ACCEPT_TIMEOUT)
if (session_timeout)
*session_timeout = entry->session_timeout;
if (acct_interim_interval)
*acct_interim_interval =
entry->acct_interim_interval;
if (vlan_id)
*vlan_id = entry->vlan_id;
copy_psk_list(psk, entry->psk);
if (identity) {
if (entry->identity)
*identity = os_strdup(entry->identity);
else
*identity = NULL;
}
entry = entry->next;
if (radius_cui) {
if (entry->radius_cui)
*radius_cui = os_strdup(entry->radius_cui);
else
*radius_cui = NULL;
}
return entry->accepted;
}
return -1;
@ -138,37 +181,9 @@ static int hostapd_radius_acl_query(struct hostapd_data *hapd, const u8 *addr,
goto fail;
}
if (hapd->conf->own_ip_addr.af == AF_INET &&
!radius_msg_add_attr(msg, RADIUS_ATTR_NAS_IP_ADDRESS,
(u8 *) &hapd->conf->own_ip_addr.u.v4, 4)) {
wpa_printf(MSG_DEBUG, "Could not add NAS-IP-Address");
if (add_common_radius_attr(hapd, hapd->conf->radius_auth_req_attr,
NULL, msg) < 0)
goto fail;
}
#ifdef CONFIG_IPV6
if (hapd->conf->own_ip_addr.af == AF_INET6 &&
!radius_msg_add_attr(msg, RADIUS_ATTR_NAS_IPV6_ADDRESS,
(u8 *) &hapd->conf->own_ip_addr.u.v6, 16)) {
wpa_printf(MSG_DEBUG, "Could not add NAS-IPv6-Address");
goto fail;
}
#endif /* CONFIG_IPV6 */
if (hapd->conf->nas_identifier &&
!radius_msg_add_attr(msg, RADIUS_ATTR_NAS_IDENTIFIER,
(u8 *) hapd->conf->nas_identifier,
os_strlen(hapd->conf->nas_identifier))) {
wpa_printf(MSG_DEBUG, "Could not add NAS-Identifier");
goto fail;
}
os_snprintf(buf, sizeof(buf), RADIUS_802_1X_ADDR_FORMAT ":%s",
MAC2STR(hapd->own_addr), hapd->conf->ssid.ssid);
if (!radius_msg_add_attr(msg, RADIUS_ATTR_CALLED_STATION_ID,
(u8 *) buf, os_strlen(buf))) {
wpa_printf(MSG_DEBUG, "Could not add Called-Station-Id");
goto fail;
}
os_snprintf(buf, sizeof(buf), RADIUS_802_1X_ADDR_FORMAT,
MAC2STR(addr));
@ -178,12 +193,6 @@ static int hostapd_radius_acl_query(struct hostapd_data *hapd, const u8 *addr,
goto fail;
}
if (!radius_msg_add_attr_int32(msg, RADIUS_ATTR_NAS_PORT_TYPE,
RADIUS_NAS_PORT_TYPE_IEEE_802_11)) {
wpa_printf(MSG_DEBUG, "Could not add NAS-Port-Type");
goto fail;
}
os_snprintf(buf, sizeof(buf), "CONNECT 11Mbps 802.11b");
if (!radius_msg_add_attr(msg, RADIUS_ATTR_CONNECT_INFO,
(u8 *) buf, os_strlen(buf))) {
@ -211,11 +220,19 @@ static int hostapd_radius_acl_query(struct hostapd_data *hapd, const u8 *addr,
* @session_timeout: Buffer for returning session timeout (from RADIUS)
* @acct_interim_interval: Buffer for returning account interval (from RADIUS)
* @vlan_id: Buffer for returning VLAN ID
* @psk: Linked list buffer for returning WPA PSK
* @identity: Buffer for returning identity (from RADIUS)
* @radius_cui: Buffer for returning CUI (from RADIUS)
* Returns: HOSTAPD_ACL_ACCEPT, HOSTAPD_ACL_REJECT, or HOSTAPD_ACL_PENDING
*
* The caller is responsible for freeing the returned *identity and *radius_cui
* values with os_free().
*/
int hostapd_allowed_address(struct hostapd_data *hapd, const u8 *addr,
const u8 *msg, size_t len, u32 *session_timeout,
u32 *acct_interim_interval, int *vlan_id)
u32 *acct_interim_interval, int *vlan_id,
struct hostapd_sta_wpa_psk_short **psk,
char **identity, char **radius_cui)
{
if (session_timeout)
*session_timeout = 0;
@ -223,6 +240,12 @@ int hostapd_allowed_address(struct hostapd_data *hapd, const u8 *addr,
*acct_interim_interval = 0;
if (vlan_id)
*vlan_id = 0;
if (psk)
*psk = NULL;
if (identity)
*identity = NULL;
if (radius_cui)
*radius_cui = NULL;
if (hostapd_maclist_found(hapd->conf->accept_mac,
hapd->conf->num_accept_mac, addr, vlan_id))
@ -247,7 +270,8 @@ int hostapd_allowed_address(struct hostapd_data *hapd, const u8 *addr,
/* Check whether ACL cache has an entry for this station */
int res = hostapd_acl_cache_get(hapd, addr, session_timeout,
acct_interim_interval,
vlan_id);
vlan_id, psk,
identity, radius_cui);
if (res == HOSTAPD_ACL_ACCEPT ||
res == HOSTAPD_ACL_ACCEPT_TIMEOUT)
return res;
@ -259,6 +283,14 @@ int hostapd_allowed_address(struct hostapd_data *hapd, const u8 *addr,
if (os_memcmp(query->addr, addr, ETH_ALEN) == 0) {
/* pending query in RADIUS retransmit queue;
* do not generate a new one */
if (identity) {
os_free(*identity);
*identity = NULL;
}
if (radius_cui) {
os_free(*radius_cui);
*radius_cui = NULL;
}
return HOSTAPD_ACL_PENDING;
}
query = query->next;
@ -324,7 +356,7 @@ static void hostapd_acl_expire_cache(struct hostapd_data *hapd, os_time_t now)
hostapd_drv_set_radius_acl_expire(hapd, entry->addr);
tmp = entry;
entry = entry->next;
os_free(tmp);
hostapd_acl_cache_free_entry(tmp);
continue;
}
@ -381,6 +413,54 @@ static void hostapd_acl_expire(void *eloop_ctx, void *timeout_ctx)
}
static void decode_tunnel_passwords(struct hostapd_data *hapd,
const u8 *shared_secret,
size_t shared_secret_len,
struct radius_msg *msg,
struct radius_msg *req,
struct hostapd_cached_radius_acl *cache)
{
int passphraselen;
char *passphrase, *strpassphrase;
size_t i;
struct hostapd_sta_wpa_psk_short *psk;
/*
* Decode all tunnel passwords as PSK and save them into a linked list.
*/
for (i = 0; ; i++) {
passphrase = radius_msg_get_tunnel_password(
msg, &passphraselen, shared_secret, shared_secret_len,
req, i);
/*
* Passphrase is NULL iff there is no i-th Tunnel-Password
* attribute in msg.
*/
if (passphrase == NULL)
break;
/*
* passphrase does not contain the NULL termination.
* Add it here as pbkdf2_sha1() requires it.
*/
strpassphrase = os_zalloc(passphraselen + 1);
psk = os_zalloc(sizeof(struct hostapd_sta_wpa_psk_short));
if (strpassphrase && psk) {
os_memcpy(strpassphrase, passphrase, passphraselen);
pbkdf2_sha1(strpassphrase,
hapd->conf->ssid.ssid,
hapd->conf->ssid.ssid_len, 4096,
psk->psk, PMK_LEN);
psk->next = cache->psk;
cache->psk = psk;
psk = NULL;
}
os_free(strpassphrase);
os_free(psk);
os_free(passphrase);
}
}
/**
* hostapd_acl_recv_radius - Process incoming RADIUS Authentication messages
* @msg: RADIUS response message
@ -439,6 +519,9 @@ hostapd_acl_recv_radius(struct radius_msg *msg, struct radius_msg *req,
cache->timestamp = t.sec;
os_memcpy(cache->addr, query->addr, sizeof(cache->addr));
if (hdr->code == RADIUS_CODE_ACCESS_ACCEPT) {
u8 *buf;
size_t len;
if (radius_msg_get_attr_int32(msg, RADIUS_ATTR_SESSION_TIMEOUT,
&cache->session_timeout) == 0)
cache->accepted = HOSTAPD_ACL_ACCEPT_TIMEOUT;
@ -457,6 +540,27 @@ hostapd_acl_recv_radius(struct radius_msg *msg, struct radius_msg *req,
}
cache->vlan_id = radius_msg_get_vlanid(msg);
decode_tunnel_passwords(hapd, shared_secret, shared_secret_len,
msg, req, cache);
if (radius_msg_get_attr_ptr(msg, RADIUS_ATTR_USER_NAME,
&buf, &len, NULL) == 0) {
cache->identity = os_zalloc(len + 1);
if (cache->identity)
os_memcpy(cache->identity, buf, len);
}
if (radius_msg_get_attr_ptr(
msg, RADIUS_ATTR_CHARGEABLE_USER_IDENTITY,
&buf, &len, NULL) == 0) {
cache->radius_cui = os_zalloc(len + 1);
if (cache->radius_cui)
os_memcpy(cache->radius_cui, buf, len);
}
if (hapd->conf->wpa_psk_radius == PSK_RADIUS_REQUIRED &&
!cache->psk)
cache->accepted = HOSTAPD_ACL_REJECT;
} else
cache->accepted = HOSTAPD_ACL_REJECT;
cache->next = hapd->acl_cache;
@ -527,3 +631,13 @@ void hostapd_acl_deinit(struct hostapd_data *hapd)
hostapd_acl_query_free(prev);
}
}
void hostapd_free_psk_list(struct hostapd_sta_wpa_psk_short *psk)
{
while (psk) {
struct hostapd_sta_wpa_psk_short *prev = psk;
psk = psk->next;
os_free(prev);
}
}

View File

@ -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 */

View File

@ -1,15 +1,9 @@
/*
* hostapd / IEEE 802.11 Management
* Copyright (c) 2002-2010, Jouni Malinen <j@w1.fi>
* Copyright (c) 2002-2012, Jouni Malinen <j@w1.fi>
*
* This program is free software; you can redistribute it and/or modify
* it under the terms of the GNU General Public License version 2 as
* published by the Free Software Foundation.
*
* Alternatively, this software may be distributed under the terms of BSD
* license.
*
* See README and COPYING for more details.
* This software may be distributed under the terms of the BSD license.
* See README for more details.
*/
#include "utils/includes.h"
@ -74,13 +68,13 @@ void ieee802_11_send_sa_query_req(struct hostapd_data *hapd,
os_memcpy(mgmt.u.action.u.sa_query_req.trans_id, trans_id,
WLAN_SA_QUERY_TR_ID_LEN);
end = mgmt.u.action.u.sa_query_req.trans_id + WLAN_SA_QUERY_TR_ID_LEN;
if (hostapd_drv_send_mlme(hapd, &mgmt, end - (u8 *) &mgmt) < 0)
if (hostapd_drv_send_mlme(hapd, &mgmt, end - (u8 *) &mgmt, 0) < 0)
perror("ieee802_11_send_sa_query_req: send");
}
void ieee802_11_send_sa_query_resp(struct hostapd_data *hapd,
const u8 *sa, const u8 *trans_id)
static void ieee802_11_send_sa_query_resp(struct hostapd_data *hapd,
const u8 *sa, const u8 *trans_id)
{
struct sta_info *sta;
struct ieee80211_mgmt resp;
@ -112,7 +106,7 @@ void ieee802_11_send_sa_query_resp(struct hostapd_data *hapd,
os_memcpy(resp.u.action.u.sa_query_req.trans_id, trans_id,
WLAN_SA_QUERY_TR_ID_LEN);
end = resp.u.action.u.sa_query_req.trans_id + WLAN_SA_QUERY_TR_ID_LEN;
if (hostapd_drv_send_mlme(hapd, &resp, end - (u8 *) &resp) < 0)
if (hostapd_drv_send_mlme(hapd, &resp, end - (u8 *) &resp, 0) < 0)
perror("ieee80211_mgmt_sa_query_request: send");
}
@ -179,6 +173,14 @@ u8 * hostapd_eid_ext_capab(struct hostapd_data *hapd, u8 *eid)
len = 5;
if (len < 4 && hapd->conf->interworking)
len = 4;
if (len < 3 && hapd->conf->wnm_sleep_mode)
len = 3;
if (len < 7 && hapd->conf->ssid.utf8_ssid)
len = 7;
#ifdef CONFIG_WNM
if (len < 4)
len = 4;
#endif /* CONFIG_WNM */
if (len == 0)
return eid;
@ -186,9 +188,20 @@ u8 * hostapd_eid_ext_capab(struct hostapd_data *hapd, u8 *eid)
*pos++ = len;
*pos++ = 0x00;
*pos++ = 0x00;
*pos++ = 0x00;
*pos = 0x00;
if (hapd->conf->wnm_sleep_mode)
*pos |= 0x02; /* Bit 17 - WNM-Sleep Mode */
if (hapd->conf->bss_transition)
*pos |= 0x08; /* Bit 19 - BSS Transition */
pos++;
if (len < 4)
return pos;
*pos = 0x00;
#ifdef CONFIG_WNM
*pos |= 0x02; /* Bit 25 - SSID List */
#endif /* CONFIG_WNM */
if (hapd->conf->time_advertisement == 2)
*pos |= 0x08; /* Bit 27 - UTC TSF Offset */
if (hapd->conf->interworking)
@ -204,6 +217,18 @@ u8 * hostapd_eid_ext_capab(struct hostapd_data *hapd, u8 *eid)
*pos |= 0x80; /* Bit 39 - TDLS Channel Switching Prohibited */
pos++;
if (len < 6)
return pos;
*pos = 0x00;
pos++;
if (len < 7)
return pos;
*pos = 0x00;
if (hapd->conf->ssid.utf8_ssid)
*pos |= 0x01; /* Bit 48 - UTF-8 SSID */
pos++;
return pos;
}
@ -403,3 +428,31 @@ int hostapd_update_time_adv(struct hostapd_data *hapd)
return 0;
}
u8 * hostapd_eid_bss_max_idle_period(struct hostapd_data *hapd, u8 *eid)
{
u8 *pos = eid;
#ifdef CONFIG_WNM
if (hapd->conf->ap_max_inactivity > 0) {
unsigned int val;
*pos++ = WLAN_EID_BSS_MAX_IDLE_PERIOD;
*pos++ = 3;
val = hapd->conf->ap_max_inactivity;
if (val > 68000)
val = 68000;
val *= 1000;
val /= 1024;
if (val == 0)
val = 1;
if (val > 65535)
val = 65535;
WPA_PUT_LE16(pos, val);
pos += 2;
*pos++ = 0x00; /* TODO: Protected Keep-Alive Required */
}
#endif /* CONFIG_WNM */
return pos;
}

View 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;
}

View File

@ -2,14 +2,8 @@
* hostapd / IEEE 802.1X-2004 Authenticator
* Copyright (c) 2002-2012, Jouni Malinen <j@w1.fi>
*
* This program is free software; you can redistribute it and/or modify
* it under the terms of the GNU General Public License version 2 as
* published by the Free Software Foundation.
*
* Alternatively, this software may be distributed under the terms of BSD
* license.
*
* See README and COPYING for more details.
* This software may be distributed under the terms of the BSD license.
* See README for more details.
*/
#include "utils/includes.h"
@ -20,7 +14,6 @@
#include "crypto/crypto.h"
#include "crypto/random.h"
#include "common/ieee802_11_defs.h"
#include "common/wpa_ctrl.h"
#include "radius/radius.h"
#include "radius/radius_client.h"
#include "eap_server/eap.h"
@ -73,8 +66,9 @@ static void ieee802_1x_send(struct hostapd_data *hapd, struct sta_info *sta,
if (sta->flags & WLAN_STA_PREAUTH) {
rsn_preauth_send(hapd, sta, buf, len);
} else {
hostapd_drv_hapd_send_eapol(hapd, sta->addr, buf, len,
encrypt, sta->flags);
hostapd_drv_hapd_send_eapol(
hapd, sta->addr, buf, len,
encrypt, hostapd_sta_flags_to_drv(sta->flags));
}
os_free(buf);
@ -106,8 +100,10 @@ void ieee802_1x_set_sta_authorized(struct hostapd_data *hapd,
"driver (errno=%d).\n", MAC2STR(sta->addr), errno);
}
if (authorized)
if (authorized) {
os_get_time(&sta->connected_time);
accounting_sta_start(hapd, sta);
}
}
@ -133,7 +129,7 @@ static void ieee802_1x_tx_key_one(struct hostapd_data *hapd,
hdr = (struct ieee802_1x_hdr *) buf;
key = (struct ieee802_1x_eapol_key *) (hdr + 1);
key->type = EAPOL_KEY_TYPE_RC4;
key->key_length = htons(key_len);
WPA_PUT_BE16(key->key_length, key_len);
wpa_get_ntp_timestamp(key->replay_counter);
if (random_get_bytes(key->key_iv, sizeof(key->key_iv))) {
@ -359,6 +355,8 @@ void ieee802_1x_tx_key(struct hostapd_data *hapd, struct sta_info *sta)
const char *radius_mode_txt(struct hostapd_data *hapd)
{
switch (hapd->iface->conf->hw_mode) {
case HOSTAPD_MODE_IEEE80211AD:
return "802.11ad";
case HOSTAPD_MODE_IEEE80211A:
return "802.11a";
case HOSTAPD_MODE_IEEE80211G:
@ -416,12 +414,142 @@ static void ieee802_1x_learn_identity(struct hostapd_data *hapd,
}
static int add_common_radius_sta_attr(struct hostapd_data *hapd,
struct hostapd_radius_attr *req_attr,
struct sta_info *sta,
struct radius_msg *msg)
{
char buf[128];
if (!hostapd_config_get_radius_attr(req_attr,
RADIUS_ATTR_NAS_PORT) &&
!radius_msg_add_attr_int32(msg, RADIUS_ATTR_NAS_PORT, sta->aid)) {
wpa_printf(MSG_ERROR, "Could not add NAS-Port");
return -1;
}
os_snprintf(buf, sizeof(buf), RADIUS_802_1X_ADDR_FORMAT,
MAC2STR(sta->addr));
buf[sizeof(buf) - 1] = '\0';
if (!radius_msg_add_attr(msg, RADIUS_ATTR_CALLING_STATION_ID,
(u8 *) buf, os_strlen(buf))) {
wpa_printf(MSG_ERROR, "Could not add Calling-Station-Id");
return -1;
}
if (sta->flags & WLAN_STA_PREAUTH) {
os_strlcpy(buf, "IEEE 802.11i Pre-Authentication",
sizeof(buf));
} else {
os_snprintf(buf, sizeof(buf), "CONNECT %d%sMbps %s",
radius_sta_rate(hapd, sta) / 2,
(radius_sta_rate(hapd, sta) & 1) ? ".5" : "",
radius_mode_txt(hapd));
buf[sizeof(buf) - 1] = '\0';
}
if (!hostapd_config_get_radius_attr(req_attr,
RADIUS_ATTR_CONNECT_INFO) &&
!radius_msg_add_attr(msg, RADIUS_ATTR_CONNECT_INFO,
(u8 *) buf, os_strlen(buf))) {
wpa_printf(MSG_ERROR, "Could not add Connect-Info");
return -1;
}
if (sta->acct_session_id_hi || sta->acct_session_id_lo) {
os_snprintf(buf, sizeof(buf), "%08X-%08X",
sta->acct_session_id_hi, sta->acct_session_id_lo);
if (!radius_msg_add_attr(msg, RADIUS_ATTR_ACCT_SESSION_ID,
(u8 *) buf, os_strlen(buf))) {
wpa_printf(MSG_ERROR, "Could not add Acct-Session-Id");
return -1;
}
}
return 0;
}
int add_common_radius_attr(struct hostapd_data *hapd,
struct hostapd_radius_attr *req_attr,
struct sta_info *sta,
struct radius_msg *msg)
{
char buf[128];
struct hostapd_radius_attr *attr;
if (!hostapd_config_get_radius_attr(req_attr,
RADIUS_ATTR_NAS_IP_ADDRESS) &&
hapd->conf->own_ip_addr.af == AF_INET &&
!radius_msg_add_attr(msg, RADIUS_ATTR_NAS_IP_ADDRESS,
(u8 *) &hapd->conf->own_ip_addr.u.v4, 4)) {
wpa_printf(MSG_ERROR, "Could not add NAS-IP-Address");
return -1;
}
#ifdef CONFIG_IPV6
if (!hostapd_config_get_radius_attr(req_attr,
RADIUS_ATTR_NAS_IPV6_ADDRESS) &&
hapd->conf->own_ip_addr.af == AF_INET6 &&
!radius_msg_add_attr(msg, RADIUS_ATTR_NAS_IPV6_ADDRESS,
(u8 *) &hapd->conf->own_ip_addr.u.v6, 16)) {
wpa_printf(MSG_ERROR, "Could not add NAS-IPv6-Address");
return -1;
}
#endif /* CONFIG_IPV6 */
if (!hostapd_config_get_radius_attr(req_attr,
RADIUS_ATTR_NAS_IDENTIFIER) &&
hapd->conf->nas_identifier &&
!radius_msg_add_attr(msg, RADIUS_ATTR_NAS_IDENTIFIER,
(u8 *) hapd->conf->nas_identifier,
os_strlen(hapd->conf->nas_identifier))) {
wpa_printf(MSG_ERROR, "Could not add NAS-Identifier");
return -1;
}
os_snprintf(buf, sizeof(buf), RADIUS_802_1X_ADDR_FORMAT ":%s",
MAC2STR(hapd->own_addr),
wpa_ssid_txt(hapd->conf->ssid.ssid,
hapd->conf->ssid.ssid_len));
buf[sizeof(buf) - 1] = '\0';
if (!hostapd_config_get_radius_attr(req_attr,
RADIUS_ATTR_CALLED_STATION_ID) &&
!radius_msg_add_attr(msg, RADIUS_ATTR_CALLED_STATION_ID,
(u8 *) buf, os_strlen(buf))) {
wpa_printf(MSG_ERROR, "Could not add Called-Station-Id");
return -1;
}
if (!hostapd_config_get_radius_attr(req_attr,
RADIUS_ATTR_NAS_PORT_TYPE) &&
!radius_msg_add_attr_int32(msg, RADIUS_ATTR_NAS_PORT_TYPE,
RADIUS_NAS_PORT_TYPE_IEEE_802_11)) {
wpa_printf(MSG_ERROR, "Could not add NAS-Port-Type");
return -1;
}
if (sta && add_common_radius_sta_attr(hapd, req_attr, sta, msg) < 0)
return -1;
for (attr = req_attr; attr; attr = attr->next) {
if (!radius_msg_add_attr(msg, attr->type,
wpabuf_head(attr->val),
wpabuf_len(attr->val))) {
wpa_printf(MSG_ERROR, "Could not add RADIUS "
"attribute");
return -1;
}
}
return 0;
}
static void ieee802_1x_encapsulate_radius(struct hostapd_data *hapd,
struct sta_info *sta,
const u8 *eap, size_t len)
{
struct radius_msg *msg;
char buf[128];
struct eapol_state_machine *sm = sta->eapol_sm;
if (sm == NULL)
@ -449,83 +577,20 @@ static void ieee802_1x_encapsulate_radius(struct hostapd_data *hapd,
goto fail;
}
if (hapd->conf->own_ip_addr.af == AF_INET &&
!radius_msg_add_attr(msg, RADIUS_ATTR_NAS_IP_ADDRESS,
(u8 *) &hapd->conf->own_ip_addr.u.v4, 4)) {
printf("Could not add NAS-IP-Address\n");
if (add_common_radius_attr(hapd, hapd->conf->radius_auth_req_attr, sta,
msg) < 0)
goto fail;
}
#ifdef CONFIG_IPV6
if (hapd->conf->own_ip_addr.af == AF_INET6 &&
!radius_msg_add_attr(msg, RADIUS_ATTR_NAS_IPV6_ADDRESS,
(u8 *) &hapd->conf->own_ip_addr.u.v6, 16)) {
printf("Could not add NAS-IPv6-Address\n");
goto fail;
}
#endif /* CONFIG_IPV6 */
if (hapd->conf->nas_identifier &&
!radius_msg_add_attr(msg, RADIUS_ATTR_NAS_IDENTIFIER,
(u8 *) hapd->conf->nas_identifier,
os_strlen(hapd->conf->nas_identifier))) {
printf("Could not add NAS-Identifier\n");
goto fail;
}
if (!radius_msg_add_attr_int32(msg, RADIUS_ATTR_NAS_PORT, sta->aid)) {
printf("Could not add NAS-Port\n");
goto fail;
}
os_snprintf(buf, sizeof(buf), RADIUS_802_1X_ADDR_FORMAT ":%s",
MAC2STR(hapd->own_addr), hapd->conf->ssid.ssid);
buf[sizeof(buf) - 1] = '\0';
if (!radius_msg_add_attr(msg, RADIUS_ATTR_CALLED_STATION_ID,
(u8 *) buf, os_strlen(buf))) {
printf("Could not add Called-Station-Id\n");
goto fail;
}
os_snprintf(buf, sizeof(buf), RADIUS_802_1X_ADDR_FORMAT,
MAC2STR(sta->addr));
buf[sizeof(buf) - 1] = '\0';
if (!radius_msg_add_attr(msg, RADIUS_ATTR_CALLING_STATION_ID,
(u8 *) buf, os_strlen(buf))) {
printf("Could not add Calling-Station-Id\n");
goto fail;
}
/* TODO: should probably check MTU from driver config; 2304 is max for
* IEEE 802.11, but use 1400 to avoid problems with too large packets
*/
if (!radius_msg_add_attr_int32(msg, RADIUS_ATTR_FRAMED_MTU, 1400)) {
if (!hostapd_config_get_radius_attr(hapd->conf->radius_auth_req_attr,
RADIUS_ATTR_FRAMED_MTU) &&
!radius_msg_add_attr_int32(msg, RADIUS_ATTR_FRAMED_MTU, 1400)) {
printf("Could not add Framed-MTU\n");
goto fail;
}
if (!radius_msg_add_attr_int32(msg, RADIUS_ATTR_NAS_PORT_TYPE,
RADIUS_NAS_PORT_TYPE_IEEE_802_11)) {
printf("Could not add NAS-Port-Type\n");
goto fail;
}
if (sta->flags & WLAN_STA_PREAUTH) {
os_strlcpy(buf, "IEEE 802.11i Pre-Authentication",
sizeof(buf));
} else {
os_snprintf(buf, sizeof(buf), "CONNECT %d%sMbps %s",
radius_sta_rate(hapd, sta) / 2,
(radius_sta_rate(hapd, sta) & 1) ? ".5" : "",
radius_mode_txt(hapd));
buf[sizeof(buf) - 1] = '\0';
}
if (!radius_msg_add_attr(msg, RADIUS_ATTR_CONNECT_INFO,
(u8 *) buf, os_strlen(buf))) {
printf("Could not add Connect-Info\n");
goto fail;
}
if (eap && !radius_msg_add_eap(msg, eap, len)) {
printf("Could not add EAP-Message\n");
goto fail;
@ -548,6 +613,25 @@ static void ieee802_1x_encapsulate_radius(struct hostapd_data *hapd,
}
}
if (hapd->conf->radius_request_cui) {
const u8 *cui;
size_t cui_len;
/* Add previously learned CUI or nul CUI to request CUI */
if (sm->radius_cui) {
cui = wpabuf_head(sm->radius_cui);
cui_len = wpabuf_len(sm->radius_cui);
} else {
cui = (const u8 *) "\0";
cui_len = 1;
}
if (!radius_msg_add_attr(msg,
RADIUS_ATTR_CHARGEABLE_USER_IDENTITY,
cui, cui_len)) {
wpa_printf(MSG_ERROR, "Could not add CUI");
goto fail;
}
}
if (radius_client_send(hapd->radius, msg, RADIUS_AUTH, sta->addr) < 0)
goto fail;
@ -653,7 +737,8 @@ ieee802_1x_alloc_eapol_sm(struct hostapd_data *hapd, struct sta_info *sta)
flags |= EAPOL_SM_FROM_PMKSA_CACHE;
}
return eapol_auth_alloc(hapd->eapol_auth, sta->addr, flags,
sta->wps_ie, sta->p2p_ie, sta);
sta->wps_ie, sta->p2p_ie, sta,
sta->identity, sta->radius_cui);
}
@ -985,6 +1070,7 @@ void ieee802_1x_free_station(struct sta_info *sta)
#ifndef CONFIG_NO_RADIUS
radius_msg_free(sm->last_recv_radius);
radius_free_class(&sm->radius_class);
wpabuf_free(sm->radius_cui);
#endif /* CONFIG_NO_RADIUS */
os_free(sm->identity);
@ -996,9 +1082,8 @@ void ieee802_1x_free_station(struct sta_info *sta)
static void ieee802_1x_decapsulate_radius(struct hostapd_data *hapd,
struct sta_info *sta)
{
u8 *eap;
size_t len;
struct eap_hdr *hdr;
struct wpabuf *eap;
const struct eap_hdr *hdr;
int eap_type = -1;
char buf[64];
struct radius_msg *msg;
@ -1012,7 +1097,7 @@ static void ieee802_1x_decapsulate_radius(struct hostapd_data *hapd,
msg = sm->last_recv_radius;
eap = radius_msg_get_eap(msg, &len);
eap = radius_msg_get_eap(msg);
if (eap == NULL) {
/* RFC 3579, Chap. 2.6.3:
* RADIUS server SHOULD NOT send Access-Reject/no EAP-Message
@ -1024,19 +1109,19 @@ static void ieee802_1x_decapsulate_radius(struct hostapd_data *hapd,
return;
}
if (len < sizeof(*hdr)) {
if (wpabuf_len(eap) < sizeof(*hdr)) {
hostapd_logger(hapd, sta->addr, HOSTAPD_MODULE_IEEE8021X,
HOSTAPD_LEVEL_WARNING, "too short EAP packet "
"received from authentication server");
os_free(eap);
wpabuf_free(eap);
sm->eap_if->aaaEapNoReq = TRUE;
return;
}
if (len > sizeof(*hdr))
eap_type = eap[sizeof(*hdr)];
if (wpabuf_len(eap) > sizeof(*hdr))
eap_type = (wpabuf_head_u8(eap))[sizeof(*hdr)];
hdr = (struct eap_hdr *) eap;
hdr = wpabuf_head(eap);
switch (hdr->code) {
case EAP_CODE_REQUEST:
if (eap_type >= 0)
@ -1071,7 +1156,7 @@ static void ieee802_1x_decapsulate_radius(struct hostapd_data *hapd,
sm->eap_if->aaaEapReq = TRUE;
wpabuf_free(sm->eap_if->aaaEapReqData);
sm->eap_if->aaaEapReqData = wpabuf_alloc_ext_data(eap, len);
sm->eap_if->aaaEapReqData = eap;
}
@ -1136,7 +1221,7 @@ static void ieee802_1x_store_radius_class(struct hostapd_data *hapd,
if (count <= 0)
return;
nclass = os_zalloc(count * sizeof(struct radius_attr_data));
nclass = os_calloc(count, sizeof(struct radius_attr_data));
if (nclass == NULL)
return;
@ -1206,6 +1291,32 @@ static void ieee802_1x_update_sta_identity(struct hostapd_data *hapd,
}
/* Update CUI based on Chargeable-User-Identity attribute in Access-Accept */
static void ieee802_1x_update_sta_cui(struct hostapd_data *hapd,
struct sta_info *sta,
struct radius_msg *msg)
{
struct eapol_state_machine *sm = sta->eapol_sm;
struct wpabuf *cui;
u8 *buf;
size_t len;
if (sm == NULL)
return;
if (radius_msg_get_attr_ptr(msg, RADIUS_ATTR_CHARGEABLE_USER_IDENTITY,
&buf, &len, NULL) < 0)
return;
cui = wpabuf_alloc_copy(buf, len);
if (cui == NULL)
return;
wpabuf_free(sm->radius_cui);
sm->radius_cui = cui;
}
struct sta_id_search {
u8 identifier;
struct eapol_state_machine *sm;
@ -1365,6 +1476,7 @@ ieee802_1x_receive_auth(struct radius_msg *msg, struct radius_msg *req,
shared_secret_len);
ieee802_1x_store_radius_class(hapd, sta, msg);
ieee802_1x_update_sta_identity(hapd, sta, msg);
ieee802_1x_update_sta_cui(hapd, sta, msg);
if (sm->eap_if->eapKeyAvailable &&
wpa_auth_pmksa_add(sta->wpa_sm, sm->eapol_key_crypt,
session_timeout_set ?
@ -1430,6 +1542,9 @@ void ieee802_1x_abort_auth(struct hostapd_data *hapd, struct sta_info *sta)
* request and we cannot continue EAP processing (EAP-Failure
* could only be sent if the EAP peer actually replied).
*/
wpa_dbg(hapd->msg_ctx, MSG_DEBUG, "EAP Timeout, STA " MACSTR,
MAC2STR(sta->addr));
sm->eap_if->portEnabled = FALSE;
ap_sta_disconnect(hapd, sta, sta->addr,
WLAN_REASON_PREV_AUTH_NOT_VALID);
@ -1582,19 +1697,15 @@ static int ieee802_1x_get_eap_user(void *ctx, const u8 *identity,
{
struct hostapd_data *hapd = ctx;
const struct hostapd_eap_user *eap_user;
int i, count;
int i;
eap_user = hostapd_get_eap_user(hapd->conf, identity,
identity_len, phase2);
eap_user = hostapd_get_eap_user(hapd, identity, identity_len, phase2);
if (eap_user == NULL)
return -1;
os_memset(user, 0, sizeof(*user));
user->phase2 = phase2;
count = EAP_USER_MAX_METHODS;
if (count > EAP_MAX_METHODS)
count = EAP_MAX_METHODS;
for (i = 0; i < count; i++) {
for (i = 0; i < EAP_MAX_METHODS; i++) {
user->methods[i].vendor = eap_user->methods[i].vendor;
user->methods[i].method = eap_user->methods[i].method;
}
@ -1783,15 +1894,13 @@ int ieee802_1x_tx_status(struct hostapd_data *hapd, struct sta_info *sta,
const u8 *buf, size_t len, int ack)
{
struct ieee80211_hdr *hdr;
struct ieee802_1x_hdr *xhdr;
struct ieee802_1x_eapol_key *key;
u8 *pos;
const unsigned char rfc1042_hdr[ETH_ALEN] =
{ 0xaa, 0xaa, 0x03, 0x00, 0x00, 0x00 };
if (sta == NULL)
return -1;
if (len < sizeof(*hdr) + sizeof(rfc1042_hdr) + 2 + sizeof(*xhdr))
if (len < sizeof(*hdr) + sizeof(rfc1042_hdr) + 2)
return 0;
hdr = (struct ieee80211_hdr *) buf;
@ -1803,16 +1912,30 @@ int ieee802_1x_tx_status(struct hostapd_data *hapd, struct sta_info *sta,
return 0;
pos += 2;
xhdr = (struct ieee802_1x_hdr *) pos;
pos += sizeof(*xhdr);
return ieee802_1x_eapol_tx_status(hapd, sta, pos, buf + len - pos,
ack);
}
int ieee802_1x_eapol_tx_status(struct hostapd_data *hapd, struct sta_info *sta,
const u8 *buf, int len, int ack)
{
const struct ieee802_1x_hdr *xhdr =
(const struct ieee802_1x_hdr *) buf;
const u8 *pos = buf + sizeof(*xhdr);
struct ieee802_1x_eapol_key *key;
if (len < (int) sizeof(*xhdr))
return 0;
wpa_printf(MSG_DEBUG, "IEEE 802.1X: " MACSTR " TX status - version=%d "
"type=%d length=%d - ack=%d",
MAC2STR(sta->addr), xhdr->version, xhdr->type,
be_to_host16(xhdr->length), ack);
if (xhdr->type == IEEE802_1X_TYPE_EAPOL_KEY &&
pos + sizeof(struct wpa_eapol_key) <= buf + len) {
if (xhdr->type != IEEE802_1X_TYPE_EAPOL_KEY)
return 0;
if (pos + sizeof(struct wpa_eapol_key) <= buf + len) {
const struct wpa_eapol_key *wpa;
wpa = (const struct wpa_eapol_key *) pos;
if (wpa->type == EAPOL_KEY_TYPE_RSN ||
@ -1826,8 +1949,7 @@ int ieee802_1x_tx_status(struct hostapd_data *hapd, struct sta_info *sta,
* retransmitted in case of failure. Try to re-send failed EAPOL-Key
* packets couple of times because otherwise STA keys become
* unsynchronized with AP. */
if (xhdr->type == IEEE802_1X_TYPE_EAPOL_KEY && !ack &&
pos + sizeof(*key) <= buf + len) {
if (!ack && pos + sizeof(*key) <= buf + len) {
key = (struct ieee802_1x_eapol_key *) pos;
hostapd_logger(hapd, sta->addr, HOSTAPD_MODULE_IEEE8021X,
HOSTAPD_LEVEL_DEBUG, "did not Ack EAPOL-Key "
@ -1871,6 +1993,14 @@ u8 * ieee802_1x_get_radius_class(struct eapol_state_machine *sm, size_t *len,
}
struct wpabuf * ieee802_1x_get_radius_cui(struct eapol_state_machine *sm)
{
if (sm == NULL)
return NULL;
return sm->radius_cui;
}
const u8 * ieee802_1x_get_key(struct eapol_state_machine *sm, size_t *len)
{
*len = 0;
@ -2099,8 +2229,8 @@ static void ieee802_1x_finished(struct hostapd_data *hapd,
* EAP-FAST with anonymous provisioning, may require another
* EAPOL authentication to be started to complete connection.
*/
wpa_printf(MSG_DEBUG, "IEEE 802.1X: Force disconnection after "
"EAP-Failure");
wpa_dbg(hapd->msg_ctx, MSG_DEBUG, "IEEE 802.1X: Force "
"disconnection after EAP-Failure");
/* Add a small sleep to increase likelihood of previously
* requested EAP-Failure TX getting out before this should the
* driver reorder operations.

View File

@ -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 */

View File

@ -2,14 +2,8 @@
* hostapd / P2P integration
* Copyright (c) 2009-2010, Atheros Communications
*
* This program is free software; you can redistribute it and/or modify
* it under the terms of the GNU General Public License version 2 as
* published by the Free Software Foundation.
*
* Alternatively, this software may be distributed under the terms of BSD
* license.
*
* See README and COPYING for more details.
* This software may be distributed under the terms of the BSD license.
* See README for more details.
*/
#include "utils/includes.h"

View File

@ -2,14 +2,8 @@
* hostapd / P2P integration
* Copyright (c) 2009-2010, Atheros Communications
*
* This program is free software; you can redistribute it and/or modify
* it under the terms of the GNU General Public License version 2 as
* published by the Free Software Foundation.
*
* Alternatively, this software may be distributed under the terms of BSD
* license.
*
* See README and COPYING for more details.
* This software may be distributed under the terms of the BSD license.
* See README for more details.
*/
#ifndef P2P_HOSTAPD_H

View File

@ -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"

View File

@ -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 */

View File

@ -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;

View File

@ -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"

View File

@ -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

View File

@ -2,14 +2,8 @@
* hostapd / Station table
* Copyright (c) 2002-2011, Jouni Malinen <j@w1.fi>
*
* This program is free software; you can redistribute it and/or modify
* it under the terms of the GNU General Public License version 2 as
* published by the Free Software Foundation.
*
* Alternatively, this software may be distributed under the terms of BSD
* license.
*
* See README and COPYING for more details.
* This software may be distributed under the terms of the BSD license.
* See README for more details.
*/
#include "utils/includes.h"
@ -26,6 +20,7 @@
#include "accounting.h"
#include "ieee802_1x.h"
#include "ieee802_11.h"
#include "ieee802_11_auth.h"
#include "wpa_auth.h"
#include "preauth_auth.h"
#include "ap_config.h"
@ -34,6 +29,7 @@
#include "vlan_init.h"
#include "p2p_hostapd.h"
#include "ap_drv_ops.h"
#include "gas_serv.h"
#include "sta_info.h"
static void ap_sta_remove_in_other_bss(struct hostapd_data *hapd,
@ -200,6 +196,8 @@ void ap_free_sta(struct hostapd_data *hapd, struct sta_info *sta)
if (set_beacon)
ieee802_11_set_beacons(hapd->iface);
wpa_printf(MSG_DEBUG, "%s: cancel ap_handle_timer for " MACSTR,
__func__, MAC2STR(sta->addr));
eloop_cancel_timeout(ap_handle_timer, hapd, sta);
eloop_cancel_timeout(ap_handle_session_timer, hapd, sta);
eloop_cancel_timeout(ap_sta_deauth_cb_timeout, hapd, sta);
@ -224,10 +222,23 @@ void ap_free_sta(struct hostapd_data *hapd, struct sta_info *sta)
p2p_group_notif_disassoc(hapd->p2p_group, sta->addr);
#endif /* CONFIG_P2P */
#ifdef CONFIG_INTERWORKING
if (sta->gas_dialog) {
int i;
for (i = 0; i < GAS_DIALOG_MAX; i++)
gas_serv_dialog_clear(&sta->gas_dialog[i]);
os_free(sta->gas_dialog);
}
#endif /* CONFIG_INTERWORKING */
wpabuf_free(sta->wps_ie);
wpabuf_free(sta->p2p_ie);
wpabuf_free(sta->hs20_ie);
os_free(sta->ht_capabilities);
hostapd_free_psk_list(sta->psk);
os_free(sta->identity);
os_free(sta->radius_cui);
os_free(sta);
}
@ -267,6 +278,9 @@ void ap_handle_timer(void *eloop_ctx, void *timeout_ctx)
struct sta_info *sta = timeout_ctx;
unsigned long next_time = 0;
wpa_printf(MSG_DEBUG, "%s: " MACSTR " flags=0x%x timeout_next=%d",
__func__, MAC2STR(sta->addr), sta->flags,
sta->timeout_next);
if (sta->timeout_next == STA_REMOVE) {
hostapd_logger(hapd, sta->addr, HOSTAPD_MODULE_IEEE80211,
HOSTAPD_LEVEL_INFO, "deauthenticated due to "
@ -279,6 +293,12 @@ void ap_handle_timer(void *eloop_ctx, void *timeout_ctx)
(sta->timeout_next == STA_NULLFUNC ||
sta->timeout_next == STA_DISASSOC)) {
int inactive_sec;
/*
* Add random value to timeout so that we don't end up bouncing
* all stations at the same time if we have lots of associated
* stations that are idle (but keep re-associating).
*/
int fuzz = os_random() % 20;
inactive_sec = hostapd_drv_get_inact_sec(hapd, sta->addr);
if (inactive_sec == -1) {
wpa_msg(hapd->msg_ctx, MSG_DEBUG,
@ -290,7 +310,7 @@ void ap_handle_timer(void *eloop_ctx, void *timeout_ctx)
* Anyway, try again after the next inactivity timeout,
* but do not disconnect the station now.
*/
next_time = hapd->conf->ap_max_inactivity;
next_time = hapd->conf->ap_max_inactivity + fuzz;
} else if (inactive_sec < hapd->conf->ap_max_inactivity &&
sta->flags & WLAN_STA_ASSOC) {
/* station activity detected; reset timeout state */
@ -298,7 +318,7 @@ void ap_handle_timer(void *eloop_ctx, void *timeout_ctx)
"Station " MACSTR " has been active %is ago",
MAC2STR(sta->addr), inactive_sec);
sta->timeout_next = STA_NULLFUNC;
next_time = hapd->conf->ap_max_inactivity -
next_time = hapd->conf->ap_max_inactivity + fuzz -
inactive_sec;
} else {
wpa_msg(hapd->msg_ctx, MSG_DEBUG,
@ -306,12 +326,16 @@ void ap_handle_timer(void *eloop_ctx, void *timeout_ctx)
"inactive too long: %d sec, max allowed: %d",
MAC2STR(sta->addr), inactive_sec,
hapd->conf->ap_max_inactivity);
if (hapd->conf->skip_inactivity_poll)
sta->timeout_next = STA_DISASSOC;
}
}
if ((sta->flags & WLAN_STA_ASSOC) &&
sta->timeout_next == STA_DISASSOC &&
!(sta->flags & WLAN_STA_PENDING_POLL)) {
!(sta->flags & WLAN_STA_PENDING_POLL) &&
!hapd->conf->skip_inactivity_poll) {
wpa_msg(hapd->msg_ctx, MSG_DEBUG, "Station " MACSTR
" has ACKed data poll", MAC2STR(sta->addr));
/* data nullfunc frame poll did not produce TX errors; assume
@ -321,6 +345,9 @@ void ap_handle_timer(void *eloop_ctx, void *timeout_ctx)
}
if (next_time) {
wpa_printf(MSG_DEBUG, "%s: register ap_handle_timer timeout "
"for " MACSTR " (%lu seconds)",
__func__, MAC2STR(sta->addr), next_time);
eloop_register_timeout(next_time, 0, ap_handle_timer, hapd,
sta);
return;
@ -335,9 +362,10 @@ void ap_handle_timer(void *eloop_ctx, void *timeout_ctx)
} else if (sta->timeout_next != STA_REMOVE) {
int deauth = sta->timeout_next == STA_DEAUTH;
wpa_printf(MSG_DEBUG, "Sending %s info to STA " MACSTR,
deauth ? "deauthentication" : "disassociation",
MAC2STR(sta->addr));
wpa_dbg(hapd->msg_ctx, MSG_DEBUG,
"Timeout, sending %s info to STA " MACSTR,
deauth ? "deauthentication" : "disassociation",
MAC2STR(sta->addr));
if (deauth) {
hostapd_drv_sta_deauth(
@ -353,6 +381,9 @@ void ap_handle_timer(void *eloop_ctx, void *timeout_ctx)
switch (sta->timeout_next) {
case STA_NULLFUNC:
sta->timeout_next = STA_DISASSOC;
wpa_printf(MSG_DEBUG, "%s: register ap_handle_timer timeout "
"for " MACSTR " (%d seconds - AP_DISASSOC_DELAY)",
__func__, MAC2STR(sta->addr), AP_DISASSOC_DELAY);
eloop_register_timeout(AP_DISASSOC_DELAY, 0, ap_handle_timer,
hapd, sta);
break;
@ -369,6 +400,9 @@ void ap_handle_timer(void *eloop_ctx, void *timeout_ctx)
HOSTAPD_LEVEL_INFO, "disassociated due to "
"inactivity");
sta->timeout_next = STA_DEAUTH;
wpa_printf(MSG_DEBUG, "%s: register ap_handle_timer timeout "
"for " MACSTR " (%d seconds - AP_DEAUTH_DELAY)",
__func__, MAC2STR(sta->addr), AP_DEAUTH_DELAY);
eloop_register_timeout(AP_DEAUTH_DELAY, 0, ap_handle_timer,
hapd, sta);
mlme_disassociate_indication(
@ -378,7 +412,7 @@ void ap_handle_timer(void *eloop_ctx, void *timeout_ctx)
case STA_REMOVE:
hostapd_logger(hapd, sta->addr, HOSTAPD_MODULE_IEEE80211,
HOSTAPD_LEVEL_INFO, "deauthenticated due to "
"inactivity");
"inactivity (timer DEAUTH/REMOVE)");
if (!sta->acct_terminate_cause)
sta->acct_terminate_cause =
RADIUS_ACCT_TERMINATE_CAUSE_IDLE_TIMEOUT;
@ -397,8 +431,14 @@ static void ap_handle_session_timer(void *eloop_ctx, void *timeout_ctx)
struct sta_info *sta = timeout_ctx;
u8 addr[ETH_ALEN];
if (!(sta->flags & WLAN_STA_AUTH))
if (!(sta->flags & WLAN_STA_AUTH)) {
if (sta->flags & WLAN_STA_GAS) {
wpa_printf(MSG_DEBUG, "GAS: Remove temporary STA "
"entry " MACSTR, MAC2STR(sta->addr));
ap_free_sta(hapd, sta);
}
return;
}
mlme_deauthenticate_indication(hapd, sta,
WLAN_REASON_PREV_AUTH_NOT_VALID);
@ -453,8 +493,13 @@ struct sta_info * ap_sta_add(struct hostapd_data *hapd, const u8 *addr)
return NULL;
}
sta->acct_interim_interval = hapd->conf->acct_interim_interval;
accounting_sta_get_id(hapd, sta);
/* initialize STA info data */
wpa_printf(MSG_DEBUG, "%s: register ap_handle_timer timeout "
"for " MACSTR " (%d seconds - ap_max_inactivity)",
__func__, MAC2STR(addr),
hapd->conf->ap_max_inactivity);
eloop_register_timeout(hapd->conf->ap_max_inactivity, 0,
ap_handle_timer, hapd, sta);
os_memcpy(sta->addr, addr, ETH_ALEN);
@ -528,6 +573,11 @@ void ap_sta_disassociate(struct hostapd_data *hapd, struct sta_info *sta,
sta->flags &= ~WLAN_STA_ASSOC;
ap_sta_set_authorized(hapd, sta, 0);
sta->timeout_next = STA_DEAUTH;
wpa_printf(MSG_DEBUG, "%s: reschedule ap_handle_timer timeout "
"for " MACSTR " (%d seconds - "
"AP_MAX_INACTIVITY_AFTER_DISASSOC)",
__func__, MAC2STR(sta->addr),
AP_MAX_INACTIVITY_AFTER_DISASSOC);
eloop_cancel_timeout(ap_handle_timer, hapd, sta);
eloop_register_timeout(AP_MAX_INACTIVITY_AFTER_DISASSOC, 0,
ap_handle_timer, hapd, sta);
@ -561,6 +611,11 @@ void ap_sta_deauthenticate(struct hostapd_data *hapd, struct sta_info *sta,
sta->flags &= ~(WLAN_STA_AUTH | WLAN_STA_ASSOC);
ap_sta_set_authorized(hapd, sta, 0);
sta->timeout_next = STA_REMOVE;
wpa_printf(MSG_DEBUG, "%s: reschedule ap_handle_timer timeout "
"for " MACSTR " (%d seconds - "
"AP_MAX_INACTIVITY_AFTER_DEAUTH)",
__func__, MAC2STR(sta->addr),
AP_MAX_INACTIVITY_AFTER_DEAUTH);
eloop_cancel_timeout(ap_handle_timer, hapd, sta);
eloop_register_timeout(AP_MAX_INACTIVITY_AFTER_DEAUTH, 0,
ap_handle_timer, hapd, sta);
@ -576,6 +631,23 @@ void ap_sta_deauthenticate(struct hostapd_data *hapd, struct sta_info *sta,
}
#ifdef CONFIG_WPS
int ap_sta_wps_cancel(struct hostapd_data *hapd,
struct sta_info *sta, void *ctx)
{
if (sta && (sta->flags & WLAN_STA_WPS)) {
ap_sta_deauthenticate(hapd, sta,
WLAN_REASON_PREV_AUTH_NOT_VALID);
wpa_printf(MSG_DEBUG, "WPS: %s: Deauth sta=" MACSTR,
__func__, MAC2STR(sta->addr));
return 1;
}
return 0;
}
#endif /* CONFIG_WPS */
int ap_sta_bind_vlan(struct hostapd_data *hapd, struct sta_info *sta,
int old_vlanid)
{
@ -728,8 +800,9 @@ static void ap_sa_query_timer(void *eloop_ctx, void *timeout_ctx)
ap_check_sa_query_timeout(hapd, sta))
return;
nbuf = os_realloc(sta->sa_query_trans_id,
(sta->sa_query_count + 1) * WLAN_SA_QUERY_TR_ID_LEN);
nbuf = os_realloc_array(sta->sa_query_trans_id,
sta->sa_query_count + 1,
WLAN_SA_QUERY_TR_ID_LEN);
if (nbuf == NULL)
return;
if (sta->sa_query_count == 0) {
@ -751,9 +824,7 @@ static void ap_sa_query_timer(void *eloop_ctx, void *timeout_ctx)
HOSTAPD_LEVEL_DEBUG,
"association SA Query attempt %d", sta->sa_query_count);
#ifdef NEED_AP_MLME
ieee802_11_send_sa_query_req(hapd, sta->addr, trans_id);
#endif /* NEED_AP_MLME */
}
@ -778,11 +849,20 @@ void ap_sta_set_authorized(struct hostapd_data *hapd, struct sta_info *sta,
int authorized)
{
const u8 *dev_addr = NULL;
#ifdef CONFIG_P2P
u8 addr[ETH_ALEN];
#endif /* CONFIG_P2P */
if (!!authorized == !!(sta->flags & WLAN_STA_AUTHORIZED))
return;
#ifdef CONFIG_P2P
dev_addr = p2p_group_get_dev_addr(hapd->p2p_group, sta->addr);
if (hapd->p2p_group == NULL) {
if (sta->p2p_ie != NULL &&
p2p_parse_dev_addr_in_p2p_ie(sta->p2p_ie, addr) == 0)
dev_addr = addr;
} else
dev_addr = p2p_group_get_dev_addr(hapd->p2p_group, sta->addr);
#endif /* CONFIG_P2P */
if (authorized) {
@ -848,6 +928,11 @@ void ap_sta_disconnect(struct hostapd_data *hapd, struct sta_info *sta,
wpa_auth_sm_event(sta->wpa_sm, WPA_DEAUTH);
ieee802_1x_notify_port_enabled(sta->eapol_sm, 0);
sta->flags &= ~(WLAN_STA_AUTH | WLAN_STA_ASSOC);
wpa_printf(MSG_DEBUG, "%s: reschedule ap_handle_timer timeout "
"for " MACSTR " (%d seconds - "
"AP_MAX_INACTIVITY_AFTER_DEAUTH)",
__func__, MAC2STR(sta->addr),
AP_MAX_INACTIVITY_AFTER_DEAUTH);
eloop_cancel_timeout(ap_handle_timer, hapd, sta);
eloop_register_timeout(AP_MAX_INACTIVITY_AFTER_DEAUTH, 0,
ap_handle_timer, hapd, sta);

View File

@ -2,14 +2,8 @@
* hostapd / Station table
* Copyright (c) 2002-2011, Jouni Malinen <j@w1.fi>
*
* This program is free software; you can redistribute it and/or modify
* it under the terms of the GNU General Public License version 2 as
* published by the Free Software Foundation.
*
* Alternatively, this software may be distributed under the terms of BSD
* license.
*
* See README and COPYING for more details.
* This software may be distributed under the terms of the BSD license.
* See README for more details.
*/
#ifndef STA_INFO_H
@ -33,6 +27,8 @@
#define WLAN_STA_WDS BIT(14)
#define WLAN_STA_ASSOC_REQ_OK BIT(15)
#define WLAN_STA_WPS2 BIT(16)
#define WLAN_STA_GAS BIT(17)
#define WLAN_STA_VHT BIT(18)
#define WLAN_STA_PENDING_DISASSOC_CB BIT(29)
#define WLAN_STA_PENDING_DEAUTH_CB BIT(30)
#define WLAN_STA_NONERP BIT(31)
@ -52,6 +48,7 @@ struct sta_info {
u16 listen_interval; /* or beacon_int for APs */
u8 supported_rates[WLAN_SUPP_RATES_MAX];
int supported_rates_len;
u8 qosinfo; /* Valid when WLAN_STA_WMM is set */
unsigned int nonerp_set:1;
unsigned int no_short_slot_time_set:1;
@ -98,8 +95,14 @@ struct sta_info {
struct hostapd_ssid *ssid_probe; /* SSID selection based on ProbeReq */
int vlan_id;
/* PSKs from RADIUS authentication server */
struct hostapd_sta_wpa_psk_short *psk;
char *identity; /* User-Name from RADIUS */
char *radius_cui; /* Chargeable-User-Identity from RADIUS */
struct ieee80211_ht_capabilities *ht_capabilities;
struct ieee80211_vht_capabilities *vht_capabilities;
#ifdef CONFIG_IEEE80211W
int sa_query_count; /* number of pending SA Query requests;
@ -111,8 +114,22 @@ struct sta_info {
struct os_time sa_query_start;
#endif /* CONFIG_IEEE80211W */
#ifdef CONFIG_INTERWORKING
#define GAS_DIALOG_MAX 8 /* Max concurrent dialog number */
struct gas_dialog_info *gas_dialog;
u8 gas_dialog_next;
#endif /* CONFIG_INTERWORKING */
struct wpabuf *wps_ie; /* WPS IE from (Re)Association Request */
struct wpabuf *p2p_ie; /* P2P IE from (Re)Association Request */
struct wpabuf *hs20_ie; /* HS 2.0 IE from (Re)Association Request */
struct os_time connected_time;
#ifdef CONFIG_SAE
enum { SAE_INIT, SAE_COMMIT, SAE_CONFIRM } sae_state;
u16 sae_send_confirm;
#endif /* CONFIG_SAE */
};
@ -141,7 +158,6 @@ int ap_for_each_sta(struct hostapd_data *hapd,
struct sta_info * ap_get_sta(struct hostapd_data *hapd, const u8 *sta);
void ap_sta_hash_add(struct hostapd_data *hapd, struct sta_info *sta);
void ap_free_sta(struct hostapd_data *hapd, struct sta_info *sta);
void ap_free_sta(struct hostapd_data *hapd, struct sta_info *sta);
void hostapd_free_stas(struct hostapd_data *hapd);
void ap_handle_timer(void *eloop_ctx, void *timeout_ctx);
void ap_sta_session_timeout(struct hostapd_data *hapd, struct sta_info *sta,
@ -153,6 +169,10 @@ void ap_sta_disassociate(struct hostapd_data *hapd, struct sta_info *sta,
u16 reason);
void ap_sta_deauthenticate(struct hostapd_data *hapd, struct sta_info *sta,
u16 reason);
#ifdef CONFIG_WPS
int ap_sta_wps_cancel(struct hostapd_data *hapd,
struct sta_info *sta, void *ctx);
#endif /* CONFIG_WPS */
int ap_sta_bind_vlan(struct hostapd_data *hapd, struct sta_info *sta,
int old_vlanid);
void ap_sta_start_sa_query(struct hostapd_data *hapd, struct sta_info *sta);

View File

@ -1,15 +1,9 @@
/*
* hostapd / TKIP countermeasures
* Copyright (c) 2002-2011, Jouni Malinen <j@w1.fi>
* Copyright (c) 2002-2012, Jouni Malinen <j@w1.fi>
*
* This program is free software; you can redistribute it and/or modify
* it under the terms of the GNU General Public License version 2 as
* published by the Free Software Foundation.
*
* Alternatively, this software may be distributed under the terms of BSD
* license.
*
* See README and COPYING for more details.
* This software may be distributed under the terms of the BSD license.
* See README for more details.
*/
#include "utils/includes.h"
@ -17,6 +11,7 @@
#include "utils/common.h"
#include "utils/eloop.h"
#include "common/ieee802_11_defs.h"
#include "radius/radius.h"
#include "hostapd.h"
#include "sta_info.h"
#include "ap_mlme.h"
@ -50,12 +45,17 @@ static void ieee80211_tkip_countermeasures_start(struct hostapd_data *hapd)
eloop_cancel_timeout(ieee80211_tkip_countermeasures_stop, hapd, NULL);
eloop_register_timeout(60, 0, ieee80211_tkip_countermeasures_stop,
hapd, NULL);
for (sta = hapd->sta_list; sta != NULL; sta = sta->next) {
while ((sta = hapd->sta_list)) {
sta->acct_terminate_cause =
RADIUS_ACCT_TERMINATE_CAUSE_ADMIN_RESET;
if (sta->flags & WLAN_STA_AUTH) {
mlme_deauthenticate_indication(
hapd, sta,
WLAN_REASON_MICHAEL_MIC_FAILURE);
}
hostapd_drv_sta_deauth(hapd, sta->addr,
WLAN_REASON_MICHAEL_MIC_FAILURE);
ap_sta_set_authorized(hapd, sta, 0);
sta->flags &= ~(WLAN_STA_AUTH | WLAN_STA_ASSOC);
hostapd_drv_sta_remove(hapd, sta->addr);
ap_free_sta(hapd, sta);
}
}
@ -66,9 +66,10 @@ void ieee80211_tkip_countermeasures_deinit(struct hostapd_data *hapd)
}
void michael_mic_failure(struct hostapd_data *hapd, const u8 *addr, int local)
int michael_mic_failure(struct hostapd_data *hapd, const u8 *addr, int local)
{
struct os_time now;
int ret = 0;
if (addr && local) {
struct sta_info *sta = ap_get_sta(hapd, addr);
@ -84,7 +85,7 @@ void michael_mic_failure(struct hostapd_data *hapd, const u8 *addr, int local)
"MLME-MICHAELMICFAILURE.indication "
"for not associated STA (" MACSTR
") ignored", MAC2STR(addr));
return;
return ret;
}
}
@ -93,8 +94,12 @@ void michael_mic_failure(struct hostapd_data *hapd, const u8 *addr, int local)
hapd->michael_mic_failures = 1;
} else {
hapd->michael_mic_failures++;
if (hapd->michael_mic_failures > 1)
if (hapd->michael_mic_failures > 1) {
ieee80211_tkip_countermeasures_start(hapd);
ret = 1;
}
}
hapd->michael_mic_failure = now.sec;
return ret;
}

View File

@ -1,21 +1,15 @@
/*
* hostapd / TKIP countermeasures
* Copyright (c) 2002-2011, Jouni Malinen <j@w1.fi>
* Copyright (c) 2002-2012, Jouni Malinen <j@w1.fi>
*
* This program is free software; you can redistribute it and/or modify
* it under the terms of the GNU General Public License version 2 as
* published by the Free Software Foundation.
*
* Alternatively, this software may be distributed under the terms of BSD
* license.
*
* See README and COPYING for more details.
* This software may be distributed under the terms of the BSD license.
* See README for more details.
*/
#ifndef TKIP_COUNTERMEASURES_H
#define TKIP_COUNTERMEASURES_H
void michael_mic_failure(struct hostapd_data *hapd, const u8 *addr, int local);
int michael_mic_failure(struct hostapd_data *hapd, const u8 *addr, int local);
void ieee80211_tkip_countermeasures_deinit(struct hostapd_data *hapd);
#endif /* TKIP_COUNTERMEASURES_H */

View File

@ -2,14 +2,8 @@
* AP mode helper functions
* Copyright (c) 2009, Jouni Malinen <j@w1.fi>
*
* This program is free software; you can redistribute it and/or modify
* it under the terms of the GNU General Public License version 2 as
* published by the Free Software Foundation.
*
* Alternatively, this software may be distributed under the terms of BSD
* license.
*
* See README and COPYING for more details.
* This software may be distributed under the terms of the BSD license.
* See README for more details.
*/
#include "includes.h"
@ -23,13 +17,14 @@
int hostapd_register_probereq_cb(struct hostapd_data *hapd,
int (*cb)(void *ctx, const u8 *sa,
const u8 *da, const u8 *bssid,
const u8 *ie, size_t ie_len),
const u8 *ie, size_t ie_len,
int ssi_signal),
void *ctx)
{
struct hostapd_probereq_cb *n;
n = os_realloc(hapd->probereq_cb, (hapd->num_probereq_cb + 1) *
sizeof(struct hostapd_probereq_cb));
n = os_realloc_array(hapd->probereq_cb, hapd->num_probereq_cb + 1,
sizeof(struct hostapd_probereq_cb));
if (n == NULL)
return -1;
@ -83,7 +78,8 @@ void hostapd_prune_associations(struct hostapd_data *hapd, const u8 *addr)
struct prune_data data;
data.hapd = hapd;
data.addr = addr;
if (hapd->iface->for_each_interface)
hapd->iface->for_each_interface(hapd->iface->interfaces,
prune_associations, &data);
if (hapd->iface->interfaces &&
hapd->iface->interfaces->for_each_interface)
hapd->iface->interfaces->for_each_interface(
hapd->iface->interfaces, prune_associations, &data);
}

View File

@ -21,6 +21,7 @@
#include "ap_config.h"
#include "ap_drv_ops.h"
#include "vlan_init.h"
#include "vlan_util.h"
#ifdef CONFIG_FULL_DYNAMIC_VLAN
@ -335,7 +336,9 @@ static int br_getnumports(const char *br_name)
}
static int vlan_rem(const char *if_name)
#ifndef CONFIG_VLAN_NETLINK
int vlan_rem(const char *if_name)
{
int fd;
struct vlan_ioctl_args if_request;
@ -378,7 +381,7 @@ static int vlan_rem(const char *if_name)
returns 1 if the interface already exists
returns 0 otherwise
*/
static int vlan_add(const char *if_name, int vid)
int vlan_add(const char *if_name, int vid, const char *vlan_if_name)
{
int fd;
struct vlan_ioctl_args if_request;
@ -474,6 +477,8 @@ static int vlan_set_name_type(unsigned int name_type)
return 0;
}
#endif /* CONFIG_VLAN_NETLINK */
static void vlan_newlink(char *ifname, struct hostapd_data *hapd)
{
@ -481,6 +486,7 @@ static void vlan_newlink(char *ifname, struct hostapd_data *hapd)
char br_name[IFNAMSIZ];
struct hostapd_vlan *vlan = hapd->conf->vlan;
char *tagged_interface = hapd->conf->ssid.vlan_tagged_interface;
int vlan_naming = hapd->conf->ssid.vlan_naming;
wpa_printf(MSG_DEBUG, "VLAN: vlan_newlink(%s)", ifname);
@ -496,13 +502,22 @@ static void vlan_newlink(char *ifname, struct hostapd_data *hapd)
ifconfig_up(br_name);
if (tagged_interface) {
if (vlan_naming ==
DYNAMIC_VLAN_NAMING_WITH_DEVICE)
os_snprintf(vlan_ifname,
sizeof(vlan_ifname),
"%s.%d", tagged_interface,
vlan->vlan_id);
else
os_snprintf(vlan_ifname,
sizeof(vlan_ifname),
"vlan%d", vlan->vlan_id);
if (!vlan_add(tagged_interface, vlan->vlan_id))
ifconfig_up(tagged_interface);
if (!vlan_add(tagged_interface, vlan->vlan_id,
vlan_ifname))
vlan->clean |= DVLAN_CLEAN_VLAN;
os_snprintf(vlan_ifname, sizeof(vlan_ifname),
"vlan%d", vlan->vlan_id);
if (!br_addif(br_name, vlan_ifname))
vlan->clean |= DVLAN_CLEAN_VLAN_PORT;
@ -527,6 +542,7 @@ static void vlan_dellink(char *ifname, struct hostapd_data *hapd)
char br_name[IFNAMSIZ];
struct hostapd_vlan *first, *prev, *vlan = hapd->conf->vlan;
char *tagged_interface = hapd->conf->ssid.vlan_tagged_interface;
int vlan_naming = hapd->conf->ssid.vlan_naming;
wpa_printf(MSG_DEBUG, "VLAN: vlan_dellink(%s)", ifname);
@ -541,8 +557,16 @@ static void vlan_dellink(char *ifname, struct hostapd_data *hapd)
br_delif(br_name, vlan->ifname);
if (tagged_interface) {
os_snprintf(vlan_ifname, sizeof(vlan_ifname),
"vlan%d", vlan->vlan_id);
if (vlan_naming ==
DYNAMIC_VLAN_NAMING_WITH_DEVICE)
os_snprintf(vlan_ifname,
sizeof(vlan_ifname),
"%s.%d", tagged_interface,
vlan->vlan_id);
else
os_snprintf(vlan_ifname,
sizeof(vlan_ifname),
"vlan%d", vlan->vlan_id);
if (vlan->clean & DVLAN_CLEAN_VLAN_PORT)
br_delif(br_name, vlan_ifname);
ifconfig_down(vlan_ifname);
@ -682,7 +706,12 @@ full_dynamic_vlan_init(struct hostapd_data *hapd)
if (priv == NULL)
return NULL;
vlan_set_name_type(VLAN_NAME_TYPE_PLUS_VID_NO_PAD);
#ifndef CONFIG_VLAN_NETLINK
vlan_set_name_type(hapd->conf->ssid.vlan_naming ==
DYNAMIC_VLAN_NAMING_WITH_DEVICE ?
VLAN_NAME_TYPE_RAW_PLUS_VID_NO_PAD :
VLAN_NAME_TYPE_PLUS_VID_NO_PAD);
#endif /* CONFIG_VLAN_NETLINK */
priv->s = socket(PF_NETLINK, SOCK_RAW, NETLINK_ROUTE);
if (priv->s < 0) {

177
external/bsd/wpa/dist/src/ap/vlan_util.c vendored Normal file
View 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;
}

View 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 */

View File

@ -72,7 +72,8 @@ u8 * hostapd_eid_wmm(struct hostapd_data *hapd, u8 *eid)
wmm->version = WMM_VERSION;
wmm->qos_info = hapd->parameter_set_count & 0xf;
if (hapd->conf->wmm_uapsd)
if (hapd->conf->wmm_uapsd &&
(hapd->iface->drv_flags & WPA_DRIVER_FLAGS_AP_UAPSD))
wmm->qos_info |= 0x80;
wmm->reserved = 0;
@ -155,7 +156,7 @@ static void wmm_send_action(struct hostapd_data *hapd, const u8 *addr,
os_memcpy(t, tspec, sizeof(struct wmm_tspec_element));
len = ((u8 *) (t + 1)) - buf;
if (hostapd_drv_send_mlme(hapd, m, len) < 0)
if (hostapd_drv_send_mlme(hapd, m, len, 0) < 0)
perror("wmm_send_action: send");
}

271
external/bsd/wpa/dist/src/ap/wnm_ap.c vendored Normal file
View 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
external/bsd/wpa/dist/src/ap/wnm_ap.h vendored Normal file
View 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 */

View File

@ -2,14 +2,8 @@
* hostapd - IEEE 802.11i-2004 / WPA Authenticator
* Copyright (c) 2004-2007, Jouni Malinen <j@w1.fi>
*
* This program is free software; you can redistribute it and/or modify
* it under the terms of the GNU General Public License version 2 as
* published by the Free Software Foundation.
*
* Alternatively, this software may be distributed under the terms of BSD
* license.
*
* See README and COPYING for more details.
* This software may be distributed under the terms of the BSD license.
* See README for more details.
*/
#ifndef WPA_AUTH_H
@ -164,6 +158,8 @@ struct wpa_auth_config {
int pmk_r1_push;
int ft_over_ds;
#endif /* CONFIG_IEEE80211R */
int disable_gtk;
int ap_mlme;
};
typedef enum {
@ -181,7 +177,7 @@ struct wpa_auth_callbacks {
void (*logger)(void *ctx, const u8 *addr, logger_level level,
const char *txt);
void (*disconnect)(void *ctx, const u8 *addr, u16 reason);
void (*mic_failure_report)(void *ctx, const u8 *addr);
int (*mic_failure_report)(void *ctx, const u8 *addr);
void (*set_eapol)(void *ctx, const u8 *addr, wpa_eapol_variable var,
int value);
int (*get_eapol)(void *ctx, const u8 *addr, wpa_eapol_variable var);
@ -202,6 +198,8 @@ struct wpa_auth_callbacks {
struct wpa_state_machine * (*add_sta)(void *ctx, const u8 *sta_addr);
int (*send_ft_action)(void *ctx, const u8 *dst,
const u8 *data, size_t data_len);
int (*add_tspec)(void *ctx, const u8 *sta_addr, u8 *tspec_ie,
size_t tspec_ielen);
#endif /* CONFIG_IEEE80211R */
};
@ -284,4 +282,11 @@ int wpa_ft_rrb_rx(struct wpa_authenticator *wpa_auth, const u8 *src_addr,
void wpa_ft_push_pmk_r1(struct wpa_authenticator *wpa_auth, const u8 *addr);
#endif /* CONFIG_IEEE80211R */
void wpa_wnmsleep_rekey_gtk(struct wpa_state_machine *sm);
void wpa_set_wnmsleep(struct wpa_state_machine *sm, int flag);
int wpa_wnmsleep_gtk_subelem(struct wpa_state_machine *sm, u8 *pos);
int wpa_wnmsleep_igtk_subelem(struct wpa_state_machine *sm, u8 *pos);
int wpa_auth_uses_sae(struct wpa_state_machine *sm);
#endif /* WPA_AUTH_H */

View File

@ -2,14 +2,8 @@
* hostapd - IEEE 802.11r - Fast BSS Transition
* Copyright (c) 2004-2009, Jouni Malinen <j@w1.fi>
*
* This program is free software; you can redistribute it and/or modify
* it under the terms of the GNU General Public License version 2 as
* published by the Free Software Foundation.
*
* Alternatively, this software may be distributed under the terms of BSD
* license.
*
* See README and COPYING for more details.
* This software may be distributed under the terms of the BSD license.
* See README for more details.
*/
#include "utils/includes.h"
@ -24,7 +18,6 @@
#include "wmm.h"
#include "wpa_auth.h"
#include "wpa_auth_i.h"
#include "wpa_auth_ie.h"
#ifdef CONFIG_IEEE80211R
@ -59,6 +52,19 @@ wpa_ft_add_sta(struct wpa_authenticator *wpa_auth, const u8 *sta_addr)
}
static int wpa_ft_add_tspec(struct wpa_authenticator *wpa_auth,
const u8 *sta_addr,
u8 *tspec_ie, size_t tspec_ielen)
{
if (wpa_auth->cb.add_tspec == NULL) {
wpa_printf(MSG_DEBUG, "FT: add_tspec is not initialized");
return -1;
}
return wpa_auth->cb.add_tspec(wpa_auth->cb.ctx, sta_addr, tspec_ie,
tspec_ielen);
}
int wpa_write_mdie(struct wpa_auth_config *conf, u8 *buf, size_t len)
{
u8 *pos = buf;
@ -478,7 +484,8 @@ static u8 * wpa_ft_igtk_subelem(struct wpa_state_machine *sm, size_t *len)
#endif /* CONFIG_IEEE80211W */
static u8 * wpa_ft_process_rdie(u8 *pos, u8 *end, u8 id, u8 descr_count,
static u8 * wpa_ft_process_rdie(struct wpa_state_machine *sm,
u8 *pos, u8 *end, u8 id, u8 descr_count,
const u8 *ies, size_t ies_len)
{
struct ieee802_11_elems parse;
@ -511,7 +518,7 @@ static u8 * wpa_ft_process_rdie(u8 *pos, u8 *end, u8 id, u8 descr_count,
}
#ifdef NEED_AP_MLME
if (parse.wmm_tspec) {
if (parse.wmm_tspec && sm->wpa_auth->conf.ap_mlme) {
struct wmm_tspec_element *tspec;
int res;
@ -548,13 +555,35 @@ static u8 * wpa_ft_process_rdie(u8 *pos, u8 *end, u8 id, u8 descr_count,
}
#endif /* NEED_AP_MLME */
if (parse.wmm_tspec && !sm->wpa_auth->conf.ap_mlme) {
struct wmm_tspec_element *tspec;
int res;
tspec = (struct wmm_tspec_element *) pos;
os_memcpy(tspec, parse.wmm_tspec - 2, sizeof(*tspec));
res = wpa_ft_add_tspec(sm->wpa_auth, sm->addr, pos,
sizeof(*tspec));
if (res >= 0) {
if (res)
rdie->status_code = host_to_le16(res);
else {
/* TSPEC accepted; include updated TSPEC in
* response */
rdie->descr_count = 1;
pos += sizeof(*tspec);
}
return pos;
}
}
wpa_printf(MSG_DEBUG, "FT: No supported resource requested");
rdie->status_code = host_to_le16(WLAN_STATUS_UNSPECIFIED_FAILURE);
return pos;
}
static u8 * wpa_ft_process_ric(u8 *pos, u8 *end, const u8 *ric, size_t ric_len)
static u8 * wpa_ft_process_ric(struct wpa_state_machine *sm, u8 *pos, u8 *end,
const u8 *ric, size_t ric_len)
{
const u8 *rpos, *start;
const struct rsn_rdie *rdie;
@ -576,7 +605,7 @@ static u8 * wpa_ft_process_ric(u8 *pos, u8 *end, const u8 *ric, size_t ric_len)
break;
rpos += 2 + rpos[1];
}
pos = wpa_ft_process_rdie(pos, end, rdie->id,
pos = wpa_ft_process_rdie(sm, pos, end, rdie->id,
rdie->descr_count,
start, rpos - start);
}
@ -685,7 +714,8 @@ u8 * wpa_sm_write_assoc_resp_ies(struct wpa_state_machine *sm, u8 *pos,
ric_start = pos;
if (wpa_ft_parse_ies(req_ies, req_ies_len, &parse) == 0 && parse.ric) {
pos = wpa_ft_process_ric(pos, end, parse.ric, parse.ric_len);
pos = wpa_ft_process_ric(sm, pos, end, parse.ric,
parse.ric_len);
if (auth_alg == WLAN_AUTH_FT)
_ftie->mic_control[1] +=
ieee802_11_ie_count(ric_start,
@ -724,13 +754,9 @@ void wpa_ft_install_ptk(struct wpa_state_machine *sm)
int klen;
/* MLME-SETKEYS.request(PTK) */
if (sm->pairwise == WPA_CIPHER_TKIP) {
alg = WPA_ALG_TKIP;
klen = 32;
} else if (sm->pairwise == WPA_CIPHER_CCMP) {
alg = WPA_ALG_CCMP;
klen = 16;
} else {
alg = wpa_cipher_to_alg(sm->pairwise);
klen = wpa_cipher_key_len(sm->pairwise);
if (!wpa_cipher_valid_pairwise(sm->pairwise)) {
wpa_printf(MSG_DEBUG, "FT: Unknown pairwise alg 0x%x - skip "
"PTK configuration", sm->pairwise);
return;
@ -852,7 +878,7 @@ static u16 wpa_ft_process_auth_req(struct wpa_state_machine *sm,
wpa_hexdump(MSG_DEBUG, "FT: Generated ANonce",
sm->ANonce, WPA_NONCE_LEN);
ptk_len = pairwise != WPA_CIPHER_CCMP ? 64 : 48;
ptk_len = pairwise == WPA_CIPHER_TKIP ? 64 : 48;
wpa_pmk_r1_to_ptk(pmk_r1, sm->SNonce, sm->ANonce, sm->addr,
sm->wpa_auth->addr, pmk_r1_name,
(u8 *) &sm->PTK, ptk_len, ptk_name);
@ -1068,8 +1094,16 @@ u16 wpa_ft_validate_reassoc(struct wpa_state_machine *sm, const u8 *ies,
if (os_memcmp(mic, ftie->mic, 16) != 0) {
wpa_printf(MSG_DEBUG, "FT: Invalid MIC in FTIE");
wpa_printf(MSG_DEBUG, "FT: addr=" MACSTR " auth_addr=" MACSTR,
MAC2STR(sm->addr), MAC2STR(sm->wpa_auth->addr));
wpa_hexdump(MSG_MSGDUMP, "FT: Received MIC", ftie->mic, 16);
wpa_hexdump(MSG_MSGDUMP, "FT: Calculated MIC", mic, 16);
wpa_hexdump(MSG_MSGDUMP, "FT: MDIE",
parse.mdie - 2, parse.mdie_len + 2);
wpa_hexdump(MSG_MSGDUMP, "FT: FTIE",
parse.ftie - 2, parse.ftie_len + 2);
wpa_hexdump(MSG_MSGDUMP, "FT: RSN",
parse.rsn - 2, parse.rsn_len + 2);
return WLAN_STATUS_INVALID_FTIE;
}

View File

@ -2,14 +2,8 @@
* hostapd / WPA authenticator glue code
* Copyright (c) 2002-2011, Jouni Malinen <j@w1.fi>
*
* This program is free software; you can redistribute it and/or modify
* it under the terms of the GNU General Public License version 2 as
* published by the Free Software Foundation.
*
* Alternatively, this software may be distributed under the terms of BSD
* license.
*
* See README and COPYING for more details.
* This software may be distributed under the terms of the BSD license.
* See README for more details.
*/
#include "utils/includes.h"
@ -29,6 +23,7 @@
#include "ap_drv_ops.h"
#include "ap_config.h"
#include "wpa_auth.h"
#include "wpa_auth_glue.h"
static void hostapd_wpa_auth_conf(struct hostapd_bss_config *conf,
@ -75,6 +70,9 @@ static void hostapd_wpa_auth_conf(struct hostapd_bss_config *conf,
wconf->pmk_r1_push = conf->pmk_r1_push;
wconf->ft_over_ds = conf->ft_over_ds;
#endif /* CONFIG_IEEE80211R */
#ifdef CONFIG_HS20
wconf->disable_gtk = conf->disable_dgaf;
#endif /* CONFIG_HS20 */
}
@ -114,10 +112,10 @@ static void hostapd_wpa_auth_disconnect(void *ctx, const u8 *addr,
}
static void hostapd_wpa_auth_mic_failure_report(void *ctx, const u8 *addr)
static int hostapd_wpa_auth_mic_failure_report(void *ctx, const u8 *addr)
{
struct hostapd_data *hapd = ctx;
michael_mic_failure(hapd, addr, 0);
return michael_mic_failure(hapd, addr, 0);
}
@ -185,7 +183,24 @@ static const u8 * hostapd_wpa_auth_get_psk(void *ctx, const u8 *addr,
const u8 *prev_psk)
{
struct hostapd_data *hapd = ctx;
return hostapd_get_psk(hapd->conf, addr, prev_psk);
struct sta_info *sta = ap_get_sta(hapd, addr);
const u8 *psk = hostapd_get_psk(hapd->conf, addr, prev_psk);
/*
* This is about to iterate over all psks, prev_psk gives the last
* returned psk which should not be returned again.
* logic list (all hostapd_get_psk; all sta->psk)
*/
if (sta && sta->psk && !psk) {
struct hostapd_sta_wpa_psk_short *pos;
psk = sta->psk->psk;
for (pos = sta->psk; pos; pos = pos->next) {
if (pos->psk == prev_psk) {
psk = pos->next ? pos->next->psk : NULL;
break;
}
}
}
return psk;
}
@ -296,12 +311,13 @@ static int hostapd_wpa_auth_for_each_auth(
{
struct hostapd_data *hapd = ctx;
struct wpa_auth_iface_iter_data data;
if (hapd->iface->for_each_interface == NULL)
if (hapd->iface->interfaces == NULL ||
hapd->iface->interfaces->for_each_interface == NULL)
return -1;
data.cb = cb;
data.cb_ctx = cb_ctx;
return hapd->iface->for_each_interface(hapd->iface->interfaces,
wpa_auth_iface_iter, &data);
return hapd->iface->interfaces->for_each_interface(
hapd->iface->interfaces, wpa_auth_iface_iter, &data);
}
@ -353,16 +369,17 @@ static int hostapd_wpa_auth_send_ether(void *ctx, const u8 *dst, u16 proto,
int ret;
#ifdef CONFIG_IEEE80211R
if (proto == ETH_P_RRB && hapd->iface->for_each_interface) {
if (proto == ETH_P_RRB && hapd->iface->interfaces &&
hapd->iface->interfaces->for_each_interface) {
int res;
struct wpa_auth_ft_iface_iter_data idata;
idata.src_hapd = hapd;
idata.dst = dst;
idata.data = data;
idata.data_len = data_len;
res = hapd->iface->for_each_interface(hapd->iface->interfaces,
hostapd_wpa_auth_ft_iter,
&idata);
res = hapd->iface->interfaces->for_each_interface(
hapd->iface->interfaces, hostapd_wpa_auth_ft_iter,
&idata);
if (res == 1)
return data_len;
}
@ -415,7 +432,7 @@ static int hostapd_wpa_auth_send_ft_action(void *ctx, const u8 *dst,
os_memcpy(m->bssid, hapd->own_addr, ETH_ALEN);
os_memcpy(&m->u, data, data_len);
res = hostapd_drv_send_mlme(hapd, (u8 *) m, mlen);
res = hostapd_drv_send_mlme(hapd, (u8 *) m, mlen, 0);
os_free(m);
return res;
}
@ -427,6 +444,9 @@ hostapd_wpa_auth_add_sta(void *ctx, const u8 *sta_addr)
struct hostapd_data *hapd = ctx;
struct sta_info *sta;
if (hostapd_add_sta_node(hapd, sta_addr, WLAN_AUTH_FT) < 0)
return NULL;
sta = ap_sta_add(hapd, sta_addr);
if (sta == NULL)
return NULL;
@ -460,6 +480,14 @@ static void hostapd_rrb_receive(void *ctx, const u8 *src_addr, const u8 *buf,
len - sizeof(*ethhdr));
}
static int hostapd_wpa_auth_add_tspec(void *ctx, const u8 *sta_addr,
u8 *tspec_ie, size_t tspec_ielen)
{
struct hostapd_data *hapd = ctx;
return hostapd_add_tspec(hapd, sta_addr, tspec_ie, tspec_ielen);
}
#endif /* CONFIG_IEEE80211R */
@ -473,6 +501,8 @@ int hostapd_setup_wpa(struct hostapd_data *hapd)
hostapd_wpa_auth_conf(hapd->conf, &_conf);
if (hapd->iface->drv_flags & WPA_DRIVER_FLAGS_EAPOL_TX_STATUS)
_conf.tx_status = 1;
if (hapd->iface->drv_flags & WPA_DRIVER_FLAGS_AP_MLME)
_conf.ap_mlme = 1;
os_memset(&cb, 0, sizeof(cb));
cb.ctx = hapd;
cb.logger = hostapd_wpa_auth_logger;
@ -491,6 +521,7 @@ int hostapd_setup_wpa(struct hostapd_data *hapd)
#ifdef CONFIG_IEEE80211R
cb.send_ft_action = hostapd_wpa_auth_send_ft_action;
cb.add_sta = hostapd_wpa_auth_add_sta;
cb.add_tspec = hostapd_wpa_auth_add_tspec;
#endif /* CONFIG_IEEE80211R */
hapd->wpa_auth = wpa_init(hapd->own_addr, &_conf, &cb);
if (hapd->wpa_auth == NULL) {

View File

@ -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

View File

@ -2,14 +2,8 @@
* hostapd - IEEE 802.11i-2004 / WPA Authenticator: Internal definitions
* Copyright (c) 2004-2007, Jouni Malinen <j@w1.fi>
*
* This program is free software; you can redistribute it and/or modify
* it under the terms of the GNU General Public License version 2 as
* published by the Free Software Foundation.
*
* Alternatively, this software may be distributed under the terms of BSD
* license.
*
* See README and COPYING for more details.
* This software may be distributed under the terms of the BSD license.
* See README for more details.
*/
#ifndef WPA_AUTH_I_H
@ -69,10 +63,11 @@ struct wpa_state_machine {
Boolean pairwise_set;
int keycount;
Boolean Pair;
struct {
struct wpa_key_replay_counter {
u8 counter[WPA_REPLAY_COUNTER_LEN];
Boolean valid;
} key_replay[RSNA_MAX_EAPOL_RETRIES];
} key_replay[RSNA_MAX_EAPOL_RETRIES],
prev_key_replay[RSNA_MAX_EAPOL_RETRIES];
Boolean PInitAKeys; /* WPA only, not in IEEE 802.11i */
Boolean PTKRequest; /* not in IEEE 802.11i state machine */
Boolean has_GTK;
@ -87,10 +82,12 @@ struct wpa_state_machine {
unsigned int started:1;
unsigned int mgmt_frame_prot:1;
unsigned int rx_eapol_key_secure:1;
unsigned int update_snonce:1;
#ifdef CONFIG_IEEE80211R
unsigned int ft_completed:1;
unsigned int pmk_r1_name_valid:1;
#endif /* CONFIG_IEEE80211R */
unsigned int is_wnmsleep:1;
u8 req_replay_counter[WPA_REPLAY_COUNTER_LEN];
int req_replay_counter_used;

View File

@ -2,14 +2,8 @@
* hostapd - WPA/RSN IE and KDE definitions
* Copyright (c) 2004-2008, Jouni Malinen <j@w1.fi>
*
* This program is free software; you can redistribute it and/or modify
* it under the terms of the GNU General Public License version 2 as
* published by the Free Software Foundation.
*
* Alternatively, this software may be distributed under the terms of BSD
* license.
*
* See README and COPYING for more details.
* This software may be distributed under the terms of the BSD license.
* See README for more details.
*/
#include "utils/includes.h"
@ -35,6 +29,7 @@ static int wpa_write_wpa_ie(struct wpa_auth_config *conf, u8 *buf, size_t len)
struct wpa_ie_hdr *hdr;
int num_suites;
u8 *pos, *count;
u32 suite;
hdr = (struct wpa_ie_hdr *) buf;
hdr->elem_id = WLAN_EID_VENDOR_SPECIFIC;
@ -42,46 +37,25 @@ static int wpa_write_wpa_ie(struct wpa_auth_config *conf, u8 *buf, size_t len)
WPA_PUT_LE16(hdr->version, WPA_VERSION);
pos = (u8 *) (hdr + 1);
if (conf->wpa_group == WPA_CIPHER_CCMP) {
RSN_SELECTOR_PUT(pos, WPA_CIPHER_SUITE_CCMP);
} else if (conf->wpa_group == WPA_CIPHER_TKIP) {
RSN_SELECTOR_PUT(pos, WPA_CIPHER_SUITE_TKIP);
} else if (conf->wpa_group == WPA_CIPHER_WEP104) {
RSN_SELECTOR_PUT(pos, WPA_CIPHER_SUITE_WEP104);
} else if (conf->wpa_group == WPA_CIPHER_WEP40) {
RSN_SELECTOR_PUT(pos, WPA_CIPHER_SUITE_WEP40);
} else {
suite = wpa_cipher_to_suite(WPA_PROTO_WPA, conf->wpa_group);
if (suite == 0) {
wpa_printf(MSG_DEBUG, "Invalid group cipher (%d).",
conf->wpa_group);
return -1;
}
RSN_SELECTOR_PUT(pos, suite);
pos += WPA_SELECTOR_LEN;
num_suites = 0;
count = pos;
pos += 2;
if (conf->wpa_pairwise & WPA_CIPHER_CCMP) {
RSN_SELECTOR_PUT(pos, WPA_CIPHER_SUITE_CCMP);
pos += WPA_SELECTOR_LEN;
num_suites++;
}
if (conf->wpa_pairwise & WPA_CIPHER_TKIP) {
RSN_SELECTOR_PUT(pos, WPA_CIPHER_SUITE_TKIP);
pos += WPA_SELECTOR_LEN;
num_suites++;
}
if (conf->wpa_pairwise & WPA_CIPHER_NONE) {
RSN_SELECTOR_PUT(pos, WPA_CIPHER_SUITE_NONE);
pos += WPA_SELECTOR_LEN;
num_suites++;
}
num_suites = wpa_cipher_put_suites(pos, conf->wpa_pairwise);
if (num_suites == 0) {
wpa_printf(MSG_DEBUG, "Invalid pairwise cipher (%d).",
conf->wpa_pairwise);
return -1;
}
pos += num_suites * WPA_SELECTOR_LEN;
WPA_PUT_LE16(count, num_suites);
num_suites = 0;
@ -118,28 +92,23 @@ int wpa_write_rsn_ie(struct wpa_auth_config *conf, u8 *buf, size_t len,
const u8 *pmkid)
{
struct rsn_ie_hdr *hdr;
int num_suites;
int num_suites, res;
u8 *pos, *count;
u16 capab;
u32 suite;
hdr = (struct rsn_ie_hdr *) buf;
hdr->elem_id = WLAN_EID_RSN;
WPA_PUT_LE16(hdr->version, RSN_VERSION);
pos = (u8 *) (hdr + 1);
if (conf->wpa_group == WPA_CIPHER_CCMP) {
RSN_SELECTOR_PUT(pos, RSN_CIPHER_SUITE_CCMP);
} else if (conf->wpa_group == WPA_CIPHER_TKIP) {
RSN_SELECTOR_PUT(pos, RSN_CIPHER_SUITE_TKIP);
} else if (conf->wpa_group == WPA_CIPHER_WEP104) {
RSN_SELECTOR_PUT(pos, RSN_CIPHER_SUITE_WEP104);
} else if (conf->wpa_group == WPA_CIPHER_WEP40) {
RSN_SELECTOR_PUT(pos, RSN_CIPHER_SUITE_WEP40);
} else {
suite = wpa_cipher_to_suite(WPA_PROTO_RSN, conf->wpa_group);
if (suite == 0) {
wpa_printf(MSG_DEBUG, "Invalid group cipher (%d).",
conf->wpa_group);
return -1;
}
RSN_SELECTOR_PUT(pos, suite);
pos += RSN_SELECTOR_LEN;
num_suites = 0;
@ -154,21 +123,9 @@ int wpa_write_rsn_ie(struct wpa_auth_config *conf, u8 *buf, size_t len,
}
#endif /* CONFIG_RSN_TESTING */
if (conf->rsn_pairwise & WPA_CIPHER_CCMP) {
RSN_SELECTOR_PUT(pos, RSN_CIPHER_SUITE_CCMP);
pos += RSN_SELECTOR_LEN;
num_suites++;
}
if (conf->rsn_pairwise & WPA_CIPHER_TKIP) {
RSN_SELECTOR_PUT(pos, RSN_CIPHER_SUITE_TKIP);
pos += RSN_SELECTOR_LEN;
num_suites++;
}
if (conf->rsn_pairwise & WPA_CIPHER_NONE) {
RSN_SELECTOR_PUT(pos, RSN_CIPHER_SUITE_NONE);
pos += RSN_SELECTOR_LEN;
num_suites++;
}
res = rsn_cipher_put_suites(pos, conf->rsn_pairwise);
num_suites += res;
pos += res * RSN_SELECTOR_LEN;
#ifdef CONFIG_RSN_TESTING
if (rsn_testing) {
@ -231,6 +188,18 @@ int wpa_write_rsn_ie(struct wpa_auth_config *conf, u8 *buf, size_t len,
num_suites++;
}
#endif /* CONFIG_IEEE80211W */
#ifdef CONFIG_SAE
if (conf->wpa_key_mgmt & WPA_KEY_MGMT_SAE) {
RSN_SELECTOR_PUT(pos, RSN_AUTH_KEY_MGMT_SAE);
pos += RSN_SELECTOR_LEN;
num_suites++;
}
if (conf->wpa_key_mgmt & WPA_KEY_MGMT_FT_SAE) {
RSN_SELECTOR_PUT(pos, RSN_AUTH_KEY_MGMT_FT_SAE);
pos += RSN_SELECTOR_LEN;
num_suites++;
}
#endif /* CONFIG_SAE */
#ifdef CONFIG_RSN_TESTING
if (rsn_testing) {
@ -341,8 +310,7 @@ int wpa_auth_gen_wpa_ie(struct wpa_authenticator *wpa_auth)
pos += res;
}
#ifdef CONFIG_IEEE80211R
if (wpa_auth->conf.wpa_key_mgmt &
(WPA_KEY_MGMT_FT_IEEE8021X | WPA_KEY_MGMT_FT_PSK)) {
if (wpa_key_mgmt_ft(wpa_auth->conf.wpa_key_mgmt)) {
res = wpa_write_mdie(&wpa_auth->conf, pos,
buf + sizeof(buf) - pos);
if (res < 0)
@ -451,36 +419,28 @@ int wpa_validate_wpa_ie(struct wpa_authenticator *wpa_auth,
else if (data.key_mgmt & WPA_KEY_MGMT_PSK_SHA256)
selector = RSN_AUTH_KEY_MGMT_PSK_SHA256;
#endif /* CONFIG_IEEE80211W */
#ifdef CONFIG_SAE
else if (data.key_mgmt & WPA_KEY_MGMT_SAE)
selector = RSN_AUTH_KEY_MGMT_SAE;
else if (data.key_mgmt & WPA_KEY_MGMT_FT_SAE)
selector = RSN_AUTH_KEY_MGMT_FT_SAE;
#endif /* CONFIG_SAE */
else if (data.key_mgmt & WPA_KEY_MGMT_IEEE8021X)
selector = RSN_AUTH_KEY_MGMT_UNSPEC_802_1X;
else if (data.key_mgmt & WPA_KEY_MGMT_PSK)
selector = RSN_AUTH_KEY_MGMT_PSK_OVER_802_1X;
wpa_auth->dot11RSNAAuthenticationSuiteSelected = selector;
selector = RSN_CIPHER_SUITE_CCMP;
if (data.pairwise_cipher & WPA_CIPHER_CCMP)
selector = wpa_cipher_to_suite(WPA_PROTO_RSN,
data.pairwise_cipher);
if (!selector)
selector = RSN_CIPHER_SUITE_CCMP;
else if (data.pairwise_cipher & WPA_CIPHER_TKIP)
selector = RSN_CIPHER_SUITE_TKIP;
else if (data.pairwise_cipher & WPA_CIPHER_WEP104)
selector = RSN_CIPHER_SUITE_WEP104;
else if (data.pairwise_cipher & WPA_CIPHER_WEP40)
selector = RSN_CIPHER_SUITE_WEP40;
else if (data.pairwise_cipher & WPA_CIPHER_NONE)
selector = RSN_CIPHER_SUITE_NONE;
wpa_auth->dot11RSNAPairwiseCipherSelected = selector;
selector = RSN_CIPHER_SUITE_CCMP;
if (data.group_cipher & WPA_CIPHER_CCMP)
selector = wpa_cipher_to_suite(WPA_PROTO_RSN,
data.group_cipher);
if (!selector)
selector = RSN_CIPHER_SUITE_CCMP;
else if (data.group_cipher & WPA_CIPHER_TKIP)
selector = RSN_CIPHER_SUITE_TKIP;
else if (data.group_cipher & WPA_CIPHER_WEP104)
selector = RSN_CIPHER_SUITE_WEP104;
else if (data.group_cipher & WPA_CIPHER_WEP40)
selector = RSN_CIPHER_SUITE_WEP40;
else if (data.group_cipher & WPA_CIPHER_NONE)
selector = RSN_CIPHER_SUITE_NONE;
wpa_auth->dot11RSNAGroupCipherSelected = selector;
} else {
res = wpa_parse_wpa_ie_wpa(wpa_ie, wpa_ie_len, &data);
@ -492,30 +452,16 @@ int wpa_validate_wpa_ie(struct wpa_authenticator *wpa_auth,
selector = WPA_AUTH_KEY_MGMT_PSK_OVER_802_1X;
wpa_auth->dot11RSNAAuthenticationSuiteSelected = selector;
selector = WPA_CIPHER_SUITE_TKIP;
if (data.pairwise_cipher & WPA_CIPHER_CCMP)
selector = WPA_CIPHER_SUITE_CCMP;
else if (data.pairwise_cipher & WPA_CIPHER_TKIP)
selector = WPA_CIPHER_SUITE_TKIP;
else if (data.pairwise_cipher & WPA_CIPHER_WEP104)
selector = WPA_CIPHER_SUITE_WEP104;
else if (data.pairwise_cipher & WPA_CIPHER_WEP40)
selector = WPA_CIPHER_SUITE_WEP40;
else if (data.pairwise_cipher & WPA_CIPHER_NONE)
selector = WPA_CIPHER_SUITE_NONE;
selector = wpa_cipher_to_suite(WPA_PROTO_WPA,
data.pairwise_cipher);
if (!selector)
selector = RSN_CIPHER_SUITE_TKIP;
wpa_auth->dot11RSNAPairwiseCipherSelected = selector;
selector = WPA_CIPHER_SUITE_TKIP;
if (data.group_cipher & WPA_CIPHER_CCMP)
selector = WPA_CIPHER_SUITE_CCMP;
else if (data.group_cipher & WPA_CIPHER_TKIP)
selector = wpa_cipher_to_suite(WPA_PROTO_WPA,
data.group_cipher);
if (!selector)
selector = WPA_CIPHER_SUITE_TKIP;
else if (data.group_cipher & WPA_CIPHER_WEP104)
selector = WPA_CIPHER_SUITE_WEP104;
else if (data.group_cipher & WPA_CIPHER_WEP40)
selector = WPA_CIPHER_SUITE_WEP40;
else if (data.group_cipher & WPA_CIPHER_NONE)
selector = WPA_CIPHER_SUITE_NONE;
wpa_auth->dot11RSNAGroupCipherSelected = selector;
}
if (res) {
@ -551,6 +497,12 @@ int wpa_validate_wpa_ie(struct wpa_authenticator *wpa_auth,
else if (key_mgmt & WPA_KEY_MGMT_PSK_SHA256)
sm->wpa_key_mgmt = WPA_KEY_MGMT_PSK_SHA256;
#endif /* CONFIG_IEEE80211W */
#ifdef CONFIG_SAE
else if (key_mgmt & WPA_KEY_MGMT_SAE)
sm->wpa_key_mgmt = WPA_KEY_MGMT_SAE;
else if (key_mgmt & WPA_KEY_MGMT_FT_SAE)
sm->wpa_key_mgmt = WPA_KEY_MGMT_FT_SAE;
#endif /* CONFIG_SAE */
else if (key_mgmt & WPA_KEY_MGMT_IEEE8021X)
sm->wpa_key_mgmt = WPA_KEY_MGMT_IEEE8021X;
else
@ -614,6 +566,8 @@ int wpa_validate_wpa_ie(struct wpa_authenticator *wpa_auth,
if (ciphers & WPA_CIPHER_CCMP)
sm->pairwise = WPA_CIPHER_CCMP;
else if (ciphers & WPA_CIPHER_GCMP)
sm->pairwise = WPA_CIPHER_GCMP;
else
sm->pairwise = WPA_CIPHER_TKIP;

View File

@ -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

View File

@ -1,15 +1,9 @@
/*
* hostapd / WPS integration
* Copyright (c) 2008-2010, Jouni Malinen <j@w1.fi>
* Copyright (c) 2008-2012, Jouni Malinen <j@w1.fi>
*
* This program is free software; you can redistribute it and/or modify
* it under the terms of the GNU General Public License version 2 as
* published by the Free Software Foundation.
*
* Alternatively, this software may be distributed under the terms of BSD
* license.
*
* See README and COPYING for more details.
* This software may be distributed under the terms of the BSD license.
* See README for more details.
*/
#include "utils/includes.h"
@ -17,7 +11,6 @@
#include "utils/common.h"
#include "utils/eloop.h"
#include "utils/uuid.h"
#include "crypto/dh_groups.h"
#include "common/wpa_ctrl.h"
#include "common/ieee802_11_defs.h"
#include "common/ieee802_11_common.h"
@ -26,6 +19,7 @@
#include "wps/wps.h"
#include "wps/wps_defs.h"
#include "wps/wps_dev_attr.h"
#include "wps/wps_attr_parse.h"
#include "hostapd.h"
#include "ap_config.h"
#include "ap_drv_ops.h"
@ -43,7 +37,8 @@ static void hostapd_wps_upnp_deinit(struct hostapd_data *hapd);
static int hostapd_wps_probe_req_rx(void *ctx, const u8 *addr, const u8 *da,
const u8 *bssid,
const u8 *ie, size_t ie_len);
const u8 *ie, size_t ie_len,
int ssi_signal);
static void hostapd_wps_ap_pin_timeout(void *eloop_data, void *user_ctx);
@ -79,10 +74,11 @@ static int hostapd_wps_for_each(struct hostapd_data *hapd,
struct wps_for_each_data data;
data.func = func;
data.ctx = ctx;
if (iface->for_each_interface == NULL)
if (iface->interfaces == NULL ||
iface->interfaces->for_each_interface == NULL)
return wps_for_each(iface, &data);
return iface->for_each_interface(iface->interfaces, wps_for_each,
&data);
return iface->interfaces->for_each_interface(iface->interfaces,
wps_for_each, &data);
}
@ -189,19 +185,23 @@ static void hostapd_wps_pin_needed_cb(void *ctx, const u8 *uuid_e,
struct wps_stop_reg_data {
struct hostapd_data *current_hapd;
const u8 *uuid_e;
const u8 *dev_pw;
size_t dev_pw_len;
};
static int wps_stop_registrar(struct hostapd_data *hapd, void *ctx)
{
struct wps_stop_reg_data *data = ctx;
if (hapd != data->current_hapd && hapd->wps != NULL)
wps_registrar_complete(hapd->wps->registrar, data->uuid_e);
wps_registrar_complete(hapd->wps->registrar, data->uuid_e,
data->dev_pw, data->dev_pw_len);
return 0;
}
static void hostapd_wps_reg_success_cb(void *ctx, const u8 *mac_addr,
const u8 *uuid_e)
const u8 *uuid_e, const u8 *dev_pw,
size_t dev_pw_len)
{
struct hostapd_data *hapd = ctx;
char uuid[40];
@ -215,6 +215,8 @@ static void hostapd_wps_reg_success_cb(void *ctx, const u8 *mac_addr,
mac_addr, uuid_e);
data.current_hapd = hapd;
data.uuid_e = uuid_e;
data.dev_pw = dev_pw;
data.dev_pw_len = dev_pw_len;
hostapd_wps_for_each(hapd, wps_stop_registrar, &data);
}
@ -253,7 +255,8 @@ static void wps_reload_config(void *eloop_data, void *user_ctx)
struct hostapd_iface *iface = eloop_data;
wpa_printf(MSG_DEBUG, "WPS: Reload configuration data");
if (iface->reload_config(iface) < 0) {
if (iface->interfaces == NULL ||
iface->interfaces->reload_config(iface) < 0) {
wpa_printf(MSG_WARNING, "WPS: Failed to reload the updated "
"configuration");
}
@ -340,6 +343,8 @@ static int hapd_wps_cred_cb(struct hostapd_data *hapd, void *ctx)
}
hapd->wps->wps_state = WPS_STATE_CONFIGURED;
if (hapd->iface->config_fname == NULL)
return 0;
len = os_strlen(hapd->iface->config_fname) + 5;
tmp_fname = os_malloc(len);
if (tmp_fname == NULL)
@ -367,10 +372,17 @@ static int hapd_wps_cred_cb(struct hostapd_data *hapd, void *ctx)
fprintf(nconf, "wps_state=2\n");
fprintf(nconf, "ssid=");
for (i = 0; i < cred->ssid_len; i++)
fputc(cred->ssid[i], nconf);
fprintf(nconf, "\n");
if (is_hex(cred->ssid, cred->ssid_len)) {
fprintf(nconf, "ssid2=");
for (i = 0; i < cred->ssid_len; i++)
fprintf(nconf, "%02x", cred->ssid[i]);
fprintf(nconf, "\n");
} else {
fprintf(nconf, "ssid=");
for (i = 0; i < cred->ssid_len; i++)
fputc(cred->ssid[i], nconf);
fprintf(nconf, "\n");
}
if ((cred->auth_type & (WPS_AUTH_WPA2 | WPS_AUTH_WPA2PSK)) &&
(cred->auth_type & (WPS_AUTH_WPA | WPS_AUTH_WPAPSK)))
@ -460,6 +472,7 @@ static int hapd_wps_cred_cb(struct hostapd_data *hapd, void *ctx)
multi_bss = 1;
if (!multi_bss &&
(str_starts(buf, "ssid=") ||
str_starts(buf, "ssid2=") ||
str_starts(buf, "auth_algs=") ||
str_starts(buf, "wep_default_key=") ||
str_starts(buf, "wep_key") ||
@ -706,10 +719,12 @@ static int get_uuid_cb(struct hostapd_iface *iface, void *ctx)
static const u8 * get_own_uuid(struct hostapd_iface *iface)
{
const u8 *uuid;
if (iface->for_each_interface == NULL)
if (iface->interfaces == NULL ||
iface->interfaces->for_each_interface == NULL)
return NULL;
uuid = NULL;
iface->for_each_interface(iface->interfaces, get_uuid_cb, &uuid);
iface->interfaces->for_each_interface(iface->interfaces, get_uuid_cb,
&uuid);
return uuid;
}
@ -725,10 +740,11 @@ static int count_interface_cb(struct hostapd_iface *iface, void *ctx)
static int interface_count(struct hostapd_iface *iface)
{
int count = 0;
if (iface->for_each_interface == NULL)
if (iface->interfaces == NULL ||
iface->interfaces->for_each_interface == NULL)
return 0;
iface->for_each_interface(iface->interfaces, count_interface_cb,
&count);
iface->interfaces->for_each_interface(iface->interfaces,
count_interface_cb, &count);
return count;
}
@ -838,8 +854,14 @@ int hostapd_init_wps(struct hostapd_data *hapd,
}
wps->dev.os_version = WPA_GET_BE32(hapd->conf->os_version);
wps->dev.rf_bands = hapd->iconf->hw_mode == HOSTAPD_MODE_IEEE80211A ?
WPS_RF_50GHZ : WPS_RF_24GHZ; /* FIX: dualband AP */
if (conf->wps_rf_bands) {
wps->dev.rf_bands = conf->wps_rf_bands;
} else {
wps->dev.rf_bands =
hapd->iconf->hw_mode == HOSTAPD_MODE_IEEE80211A ?
WPS_RF_50GHZ : WPS_RF_24GHZ; /* FIX: dualband AP */
}
if (conf->wpa & WPA_PROTO_RSN) {
if (conf->wpa_key_mgmt & WPA_KEY_MGMT_PSK)
@ -935,6 +957,9 @@ int hostapd_init_wps(struct hostapd_data *hapd,
if (conf->ssid.security_policy == SECURITY_STATIC_WEP)
cfg.static_wep_only = 1;
cfg.dualband = interface_count(hapd->iface) > 1;
if ((wps->dev.rf_bands & (WPS_RF_50GHZ | WPS_RF_24GHZ)) ==
(WPS_RF_50GHZ | WPS_RF_24GHZ))
cfg.dualband = 1;
if (cfg.dualband)
wpa_printf(MSG_DEBUG, "WPS: Dualband AP");
@ -984,6 +1009,20 @@ int hostapd_init_wps_complete(struct hostapd_data *hapd)
}
static void hostapd_wps_nfc_clear(struct wps_context *wps)
{
#ifdef CONFIG_WPS_NFC
wps->ap_nfc_dev_pw_id = 0;
wpabuf_free(wps->ap_nfc_dh_pubkey);
wps->ap_nfc_dh_pubkey = NULL;
wpabuf_free(wps->ap_nfc_dh_privkey);
wps->ap_nfc_dh_privkey = NULL;
wpabuf_free(wps->ap_nfc_dev_pw);
wps->ap_nfc_dev_pw = NULL;
#endif /* CONFIG_WPS_NFC */
}
void hostapd_deinit_wps(struct hostapd_data *hapd)
{
eloop_cancel_timeout(hostapd_wps_reenable_ap_pin, hapd, NULL);
@ -998,9 +1037,8 @@ void hostapd_deinit_wps(struct hostapd_data *hapd)
wps_device_data_free(&hapd->wps->dev);
wpabuf_free(hapd->wps->dh_pubkey);
wpabuf_free(hapd->wps->dh_privkey);
wpabuf_free(hapd->wps->oob_conf.pubkey_hash);
wpabuf_free(hapd->wps->oob_conf.dev_password);
wps_free_pending_msgs(hapd->wps->upnp_msgs);
hostapd_wps_nfc_clear(hapd->wps);
os_free(hapd->wps);
hapd->wps = NULL;
hostapd_wps_clear_ies(hapd);
@ -1098,63 +1136,28 @@ int hostapd_wps_button_pushed(struct hostapd_data *hapd,
}
#ifdef CONFIG_WPS_OOB
int hostapd_wps_start_oob(struct hostapd_data *hapd, char *device_type,
char *path, char *method, char *name)
static int wps_cancel(struct hostapd_data *hapd, void *ctx)
{
struct wps_context *wps = hapd->wps;
struct oob_device_data *oob_dev;
if (hapd->wps == NULL)
return 0;
oob_dev = wps_get_oob_device(device_type);
if (oob_dev == NULL)
return -1;
oob_dev->device_path = path;
oob_dev->device_name = name;
wps->oob_conf.oob_method = wps_get_oob_method(method);
if (wps->oob_conf.oob_method == OOB_METHOD_DEV_PWD_R) {
/*
* Use pre-configured DH keys in order to be able to write the
* key hash into the OOB file.
*/
wpabuf_free(wps->dh_pubkey);
wpabuf_free(wps->dh_privkey);
wps->dh_privkey = NULL;
wps->dh_pubkey = dh_init(dh_groups_get(WPS_DH_GROUP),
&wps->dh_privkey);
wps->dh_pubkey = wpabuf_zeropad(wps->dh_pubkey, 192);
if (wps->dh_pubkey == NULL) {
wpa_printf(MSG_ERROR, "WPS: Failed to initialize "
"Diffie-Hellman handshake");
return -1;
}
}
if (wps_process_oob(wps, oob_dev, 1) < 0)
goto error;
if ((wps->oob_conf.oob_method == OOB_METHOD_DEV_PWD_E ||
wps->oob_conf.oob_method == OOB_METHOD_DEV_PWD_R) &&
hostapd_wps_add_pin(hapd, NULL, "any",
wpabuf_head(wps->oob_conf.dev_password), 0) <
0)
goto error;
wps_registrar_wps_cancel(hapd->wps->registrar);
ap_for_each_sta(hapd, ap_sta_wps_cancel, NULL);
return 0;
error:
wpabuf_free(wps->dh_pubkey);
wps->dh_pubkey = NULL;
wpabuf_free(wps->dh_privkey);
wps->dh_privkey = NULL;
return -1;
}
#endif /* CONFIG_WPS_OOB */
int hostapd_wps_cancel(struct hostapd_data *hapd)
{
return hostapd_wps_for_each(hapd, wps_cancel, NULL);
}
static int hostapd_wps_probe_req_rx(void *ctx, const u8 *addr, const u8 *da,
const u8 *bssid,
const u8 *ie, size_t ie_len)
const u8 *ie, size_t ie_len,
int ssi_signal)
{
struct hostapd_data *hapd = ctx;
struct wpabuf *wps_ie;
@ -1471,3 +1474,156 @@ int hostapd_wps_config_ap(struct hostapd_data *hapd, const char *ssid,
return wps_registrar_config_ap(hapd->wps->registrar, &cred);
}
#ifdef CONFIG_WPS_NFC
struct wps_nfc_password_token_data {
const u8 *oob_dev_pw;
size_t oob_dev_pw_len;
int added;
};
static int wps_add_nfc_password_token(struct hostapd_data *hapd, void *ctx)
{
struct wps_nfc_password_token_data *data = ctx;
int ret;
if (hapd->wps == NULL)
return 0;
ret = wps_registrar_add_nfc_password_token(hapd->wps->registrar,
data->oob_dev_pw,
data->oob_dev_pw_len);
if (ret == 0)
data->added++;
return ret;
}
static int hostapd_wps_add_nfc_password_token(struct hostapd_data *hapd,
struct wps_parse_attr *attr)
{
struct wps_nfc_password_token_data data;
data.oob_dev_pw = attr->oob_dev_password;
data.oob_dev_pw_len = attr->oob_dev_password_len;
data.added = 0;
if (hostapd_wps_for_each(hapd, wps_add_nfc_password_token, &data) < 0)
return -1;
return data.added ? 0 : -1;
}
static int hostapd_wps_nfc_tag_process(struct hostapd_data *hapd,
const struct wpabuf *wps)
{
struct wps_parse_attr attr;
wpa_hexdump_buf(MSG_DEBUG, "WPS: Received NFC tag payload", wps);
if (wps_parse_msg(wps, &attr)) {
wpa_printf(MSG_DEBUG, "WPS: Ignore invalid data from NFC tag");
return -1;
}
if (attr.oob_dev_password)
return hostapd_wps_add_nfc_password_token(hapd, &attr);
wpa_printf(MSG_DEBUG, "WPS: Ignore unrecognized NFC tag");
return -1;
}
int hostapd_wps_nfc_tag_read(struct hostapd_data *hapd,
const struct wpabuf *data)
{
const struct wpabuf *wps = data;
struct wpabuf *tmp = NULL;
int ret;
if (wpabuf_len(data) < 4)
return -1;
if (*wpabuf_head_u8(data) != 0x10) {
/* Assume this contains full NDEF record */
tmp = ndef_parse_wifi(data);
if (tmp == NULL) {
wpa_printf(MSG_DEBUG, "WPS: Could not parse NDEF");
return -1;
}
wps = tmp;
}
ret = hostapd_wps_nfc_tag_process(hapd, wps);
wpabuf_free(tmp);
return ret;
}
struct wpabuf * hostapd_wps_nfc_config_token(struct hostapd_data *hapd,
int ndef)
{
struct wpabuf *ret;
if (hapd->wps == NULL)
return NULL;
ret = wps_get_oob_cred(hapd->wps);
if (ndef && ret) {
struct wpabuf *tmp;
tmp = ndef_build_wifi(ret);
wpabuf_free(ret);
if (tmp == NULL)
return NULL;
ret = tmp;
}
return ret;
}
struct wpabuf * hostapd_wps_nfc_token_gen(struct hostapd_data *hapd, int ndef)
{
return wps_nfc_token_gen(ndef, &hapd->conf->wps_nfc_dev_pw_id,
&hapd->conf->wps_nfc_dh_pubkey,
&hapd->conf->wps_nfc_dh_privkey,
&hapd->conf->wps_nfc_dev_pw);
}
int hostapd_wps_nfc_token_enable(struct hostapd_data *hapd)
{
struct wps_context *wps = hapd->wps;
if (wps == NULL)
return -1;
if (!hapd->conf->wps_nfc_dh_pubkey ||
!hapd->conf->wps_nfc_dh_privkey ||
!hapd->conf->wps_nfc_dev_pw ||
!hapd->conf->wps_nfc_dev_pw_id)
return -1;
hostapd_wps_nfc_clear(wps);
wps->ap_nfc_dev_pw_id = hapd->conf->wps_nfc_dev_pw_id;
wps->ap_nfc_dh_pubkey = wpabuf_dup(hapd->conf->wps_nfc_dh_pubkey);
wps->ap_nfc_dh_privkey = wpabuf_dup(hapd->conf->wps_nfc_dh_privkey);
wps->ap_nfc_dev_pw = wpabuf_dup(hapd->conf->wps_nfc_dev_pw);
if (!wps->ap_nfc_dh_pubkey || !wps->ap_nfc_dh_privkey ||
!wps->ap_nfc_dev_pw) {
hostapd_wps_nfc_clear(wps);
return -1;
}
return 0;
}
void hostapd_wps_nfc_token_disable(struct hostapd_data *hapd)
{
hostapd_wps_nfc_clear(hapd->wps);
}
#endif /* CONFIG_WPS_NFC */

View File

@ -1,15 +1,9 @@
/*
* hostapd / WPS integration
* Copyright (c) 2008-2010, Jouni Malinen <j@w1.fi>
* Copyright (c) 2008-2012, Jouni Malinen <j@w1.fi>
*
* This program is free software; you can redistribute it and/or modify
* it under the terms of the GNU General Public License version 2 as
* published by the Free Software Foundation.
*
* Alternatively, this software may be distributed under the terms of BSD
* license.
*
* See README and COPYING for more details.
* This software may be distributed under the terms of the BSD license.
* See README for more details.
*/
#ifndef WPS_HOSTAPD_H
@ -26,8 +20,7 @@ int hostapd_wps_add_pin(struct hostapd_data *hapd, const u8 *addr,
const char *uuid, const char *pin, int timeout);
int hostapd_wps_button_pushed(struct hostapd_data *hapd,
const u8 *p2p_dev_addr);
int hostapd_wps_start_oob(struct hostapd_data *hapd, char *device_type,
char *path, char *method, char *name);
int hostapd_wps_cancel(struct hostapd_data *hapd);
int hostapd_wps_get_mib_sta(struct hostapd_data *hapd, const u8 *addr,
char *buf, size_t buflen);
void hostapd_wps_ap_pin_disable(struct hostapd_data *hapd);
@ -38,6 +31,13 @@ int hostapd_wps_ap_pin_set(struct hostapd_data *hapd, const char *pin,
void hostapd_wps_update_ie(struct hostapd_data *hapd);
int hostapd_wps_config_ap(struct hostapd_data *hapd, const char *ssid,
const char *auth, const char *encr, const char *key);
int hostapd_wps_nfc_tag_read(struct hostapd_data *hapd,
const struct wpabuf *data);
struct wpabuf * hostapd_wps_nfc_config_token(struct hostapd_data *hapd,
int ndef);
struct wpabuf * hostapd_wps_nfc_token_gen(struct hostapd_data *hapd, int ndef);
int hostapd_wps_nfc_token_enable(struct hostapd_data *hapd);
void hostapd_wps_nfc_token_disable(struct hostapd_data *hapd);
#else /* CONFIG_WPS */
@ -73,6 +73,11 @@ static inline int hostapd_wps_button_pushed(struct hostapd_data *hapd,
return 0;
}
static inline int hostapd_wps_cancel(struct hostapd_data *hapd)
{
return 0;
}
#endif /* CONFIG_WPS */
#endif /* WPS_HOSTAPD_H */

View File

@ -2,14 +2,8 @@
* WPA Supplicant - Common definitions
* Copyright (c) 2004-2008, Jouni Malinen <j@w1.fi>
*
* This program is free software; you can redistribute it and/or modify
* it under the terms of the GNU General Public License version 2 as
* published by the Free Software Foundation.
*
* Alternatively, this software may be distributed under the terms of BSD
* license.
*
* See README and COPYING for more details.
* This software may be distributed under the terms of the BSD license.
* See README for more details.
*/
#ifndef DEFS_H
@ -32,6 +26,8 @@ typedef enum { FALSE = 0, TRUE = 1 } Boolean;
#ifdef CONFIG_IEEE80211W
#define WPA_CIPHER_AES_128_CMAC BIT(5)
#endif /* CONFIG_IEEE80211W */
#define WPA_CIPHER_GCMP BIT(6)
#define WPA_CIPHER_SMS4 BIT(7)
#define WPA_KEY_MGMT_IEEE8021X BIT(0)
#define WPA_KEY_MGMT_PSK BIT(1)
@ -43,11 +39,17 @@ typedef enum { FALSE = 0, TRUE = 1 } Boolean;
#define WPA_KEY_MGMT_IEEE8021X_SHA256 BIT(7)
#define WPA_KEY_MGMT_PSK_SHA256 BIT(8)
#define WPA_KEY_MGMT_WPS BIT(9)
#define WPA_KEY_MGMT_SAE BIT(10)
#define WPA_KEY_MGMT_FT_SAE BIT(11)
#define WPA_KEY_MGMT_WAPI_PSK BIT(12)
#define WPA_KEY_MGMT_WAPI_CERT BIT(13)
#define WPA_KEY_MGMT_CCKM BIT(14)
static inline int wpa_key_mgmt_wpa_ieee8021x(int akm)
{
return !!(akm & (WPA_KEY_MGMT_IEEE8021X |
WPA_KEY_MGMT_FT_IEEE8021X |
WPA_KEY_MGMT_CCKM |
WPA_KEY_MGMT_IEEE8021X_SHA256));
}
@ -55,13 +57,21 @@ static inline int wpa_key_mgmt_wpa_psk(int akm)
{
return !!(akm & (WPA_KEY_MGMT_PSK |
WPA_KEY_MGMT_FT_PSK |
WPA_KEY_MGMT_PSK_SHA256));
WPA_KEY_MGMT_PSK_SHA256 |
WPA_KEY_MGMT_SAE));
}
static inline int wpa_key_mgmt_ft(int akm)
{
return !!(akm & (WPA_KEY_MGMT_FT_PSK |
WPA_KEY_MGMT_FT_IEEE8021X));
WPA_KEY_MGMT_FT_IEEE8021X |
WPA_KEY_MGMT_FT_SAE));
}
static inline int wpa_key_mgmt_sae(int akm)
{
return !!(akm & (WPA_KEY_MGMT_SAE |
WPA_KEY_MGMT_FT_SAE));
}
static inline int wpa_key_mgmt_sha256(int akm)
@ -76,14 +86,26 @@ static inline int wpa_key_mgmt_wpa(int akm)
wpa_key_mgmt_wpa_psk(akm);
}
static inline int wpa_key_mgmt_wpa_any(int akm)
{
return wpa_key_mgmt_wpa(akm) || (akm & WPA_KEY_MGMT_WPA_NONE);
}
static inline int wpa_key_mgmt_cckm(int akm)
{
return akm == WPA_KEY_MGMT_CCKM;
}
#define WPA_PROTO_WPA BIT(0)
#define WPA_PROTO_RSN BIT(1)
#define WPA_PROTO_WAPI BIT(2)
#define WPA_AUTH_ALG_OPEN BIT(0)
#define WPA_AUTH_ALG_SHARED BIT(1)
#define WPA_AUTH_ALG_LEAP BIT(2)
#define WPA_AUTH_ALG_FT BIT(3)
#define WPA_AUTH_ALG_SAE BIT(4)
enum wpa_alg {
@ -92,7 +114,10 @@ enum wpa_alg {
WPA_ALG_TKIP,
WPA_ALG_CCMP,
WPA_ALG_IGTK,
WPA_ALG_PMK
WPA_ALG_PMK,
WPA_ALG_GCMP,
WPA_ALG_SMS4,
WPA_ALG_KRK
};
/**
@ -103,7 +128,9 @@ enum wpa_cipher {
CIPHER_WEP40,
CIPHER_TKIP,
CIPHER_CCMP,
CIPHER_WEP104
CIPHER_WEP104,
CIPHER_GCMP,
CIPHER_SMS4
};
/**
@ -119,7 +146,12 @@ enum wpa_key_mgmt {
KEY_MGMT_FT_PSK,
KEY_MGMT_802_1X_SHA256,
KEY_MGMT_PSK_SHA256,
KEY_MGMT_WPS
KEY_MGMT_WPS,
KEY_MGMT_SAE,
KEY_MGMT_FT_SAE,
KEY_MGMT_WAPI_PSK,
KEY_MGMT_WAPI_CERT,
KEY_MGMT_CCKM
};
/**
@ -254,8 +286,9 @@ enum wpa_states {
enum mfp_options {
NO_MGMT_FRAME_PROTECTION = 0,
MGMT_FRAME_PROTECTION_OPTIONAL = 1,
MGMT_FRAME_PROTECTION_REQUIRED = 2
MGMT_FRAME_PROTECTION_REQUIRED = 2,
};
#define MGMT_FRAME_PROTECTION_DEFAULT 3
/**
* enum hostapd_hw_mode - Hardware mode
@ -264,6 +297,7 @@ enum hostapd_hw_mode {
HOSTAPD_MODE_IEEE80211B,
HOSTAPD_MODE_IEEE80211G,
HOSTAPD_MODE_IEEE80211A,
HOSTAPD_MODE_IEEE80211AD,
NUM_HOSTAPD_MODES
};
@ -281,4 +315,7 @@ enum wpa_ctrl_req_type {
NUM_WPA_CTRL_REQS
};
/* Maximum number of EAP methods to store for EAP server user information */
#define EAP_MAX_METHODS 8
#endif /* DEFS_H */

View File

@ -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 */

View File

@ -1,16 +1,10 @@
/*
* Generic advertisement service (GAS) (IEEE 802.11u)
* Copyright (c) 2009, Atheros Communications
* Copyright (c) 2011, Qualcomm Atheros
* Copyright (c) 2011-2012, Qualcomm Atheros
*
* This program is free software; you can redistribute it and/or modify
* it under the terms of the GNU General Public License version 2 as
* published by the Free Software Foundation.
*
* Alternatively, this software may be distributed under the terms of BSD
* license.
*
* See README and COPYING for more details.
* This software may be distributed under the terms of the BSD license.
* See README for more details.
*/
#include "includes.h"
@ -37,7 +31,7 @@ gas_build_req(u8 action, u8 dialog_token, size_t size)
}
static struct wpabuf * gas_build_initial_req(u8 dialog_token, size_t size)
struct wpabuf * gas_build_initial_req(u8 dialog_token, size_t size)
{
return gas_build_req(WLAN_PA_GAS_INITIAL_REQ, dialog_token,
size);

View File

@ -1,21 +1,16 @@
/*
* Generic advertisement service (GAS) (IEEE 802.11u)
* Copyright (c) 2009, Atheros Communications
* Copyright (c) 2011, Qualcomm Atheros
* Copyright (c) 2011-2012, Qualcomm Atheros
*
* This program is free software; you can redistribute it and/or modify
* it under the terms of the GNU General Public License version 2 as
* published by the Free Software Foundation.
*
* Alternatively, this software may be distributed under the terms of BSD
* license.
*
* See README and COPYING for more details.
* This software may be distributed under the terms of the BSD license.
* See README for more details.
*/
#ifndef GAS_H
#define GAS_H
struct wpabuf * gas_build_initial_req(u8 dialog_token, size_t size);
struct wpabuf * gas_build_comeback_req(u8 dialog_token);
struct wpabuf * gas_build_initial_resp(u8 dialog_token, u16 status_code,
u16 comeback_delay, size_t size);

View File

@ -1,15 +1,9 @@
/*
* IEEE 802.11 Common routines
* Copyright (c) 2002-2009, Jouni Malinen <j@w1.fi>
* Copyright (c) 2002-2012, Jouni Malinen <j@w1.fi>
*
* This program is free software; you can redistribute it and/or modify
* it under the terms of the GNU General Public License version 2 as
* published by the Free Software Foundation.
*
* Alternatively, this software may be distributed under the terms of BSD
* license.
*
* See README and COPYING for more details.
* This software may be distributed under the terms of the BSD license.
* See README for more details.
*/
#include "includes.h"
@ -103,6 +97,16 @@ static int ieee802_11_parse_vendor_specific(const u8 *pos, size_t elen,
elems->p2p = pos;
elems->p2p_len = elen;
break;
case WFD_OUI_TYPE:
/* Wi-Fi Alliance - WFD IE */
elems->wfd = pos;
elems->wfd_len = elen;
break;
case HS20_INDICATION_OUI_TYPE:
/* Hotspot 2.0 */
elems->hs20 = pos;
elems->hs20_len = elen;
break;
default:
wpa_printf(MSG_MSGDUMP, "Unknown WFA "
"information element ignored "
@ -254,6 +258,14 @@ ParseRes ieee802_11_parse_elems(const u8 *start, size_t len,
elems->ht_operation = pos;
elems->ht_operation_len = elen;
break;
case WLAN_EID_VHT_CAP:
elems->vht_capabilities = pos;
elems->vht_capabilities_len = elen;
break;
case WLAN_EID_VHT_OPERATION:
elems->vht_operation = pos;
elems->vht_operation_len = elen;
break;
case WLAN_EID_LINK_ID:
if (elen < 18)
break;
@ -263,6 +275,19 @@ ParseRes ieee802_11_parse_elems(const u8 *start, size_t len,
elems->interworking = pos;
elems->interworking_len = elen;
break;
case WLAN_EID_EXT_CAPAB:
elems->ext_capab = pos;
elems->ext_capab_len = elen;
break;
case WLAN_EID_BSS_MAX_IDLE_PERIOD:
if (elen < 3)
break;
elems->bss_max_idle_period = pos;
break;
case WLAN_EID_SSID_LIST:
elems->ssid_list = pos;
elems->ssid_list_len = elen;
break;
default:
unknown++;
if (!show_errors)
@ -389,3 +414,75 @@ const u8 * get_hdr_bssid(const struct ieee80211_hdr *hdr, size_t len)
return NULL;
}
}
int hostapd_config_wmm_ac(struct hostapd_wmm_ac_params wmm_ac_params[],
const char *name, const char *val)
{
int num, v;
const char *pos;
struct hostapd_wmm_ac_params *ac;
/* skip 'wme_ac_' or 'wmm_ac_' prefix */
pos = name + 7;
if (os_strncmp(pos, "be_", 3) == 0) {
num = 0;
pos += 3;
} else if (os_strncmp(pos, "bk_", 3) == 0) {
num = 1;
pos += 3;
} else if (os_strncmp(pos, "vi_", 3) == 0) {
num = 2;
pos += 3;
} else if (os_strncmp(pos, "vo_", 3) == 0) {
num = 3;
pos += 3;
} else {
wpa_printf(MSG_ERROR, "Unknown WMM name '%s'", pos);
return -1;
}
ac = &wmm_ac_params[num];
if (os_strcmp(pos, "aifs") == 0) {
v = atoi(val);
if (v < 1 || v > 255) {
wpa_printf(MSG_ERROR, "Invalid AIFS value %d", v);
return -1;
}
ac->aifs = v;
} else if (os_strcmp(pos, "cwmin") == 0) {
v = atoi(val);
if (v < 0 || v > 12) {
wpa_printf(MSG_ERROR, "Invalid cwMin value %d", v);
return -1;
}
ac->cwmin = v;
} else if (os_strcmp(pos, "cwmax") == 0) {
v = atoi(val);
if (v < 0 || v > 12) {
wpa_printf(MSG_ERROR, "Invalid cwMax value %d", v);
return -1;
}
ac->cwmax = v;
} else if (os_strcmp(pos, "txop_limit") == 0) {
v = atoi(val);
if (v < 0 || v > 0xffff) {
wpa_printf(MSG_ERROR, "Invalid txop value %d", v);
return -1;
}
ac->txop_limit = v;
} else if (os_strcmp(pos, "acm") == 0) {
v = atoi(val);
if (v < 0 || v > 1) {
wpa_printf(MSG_ERROR, "Invalid acm value %d", v);
return -1;
}
ac->admission_control_mandatory = v;
} else {
wpa_printf(MSG_ERROR, "Unknown wmm_ac_ field '%s'", pos);
return -1;
}
return 0;
}

View File

@ -1,15 +1,9 @@
/*
* IEEE 802.11 Common routines
* Copyright (c) 2002-2009, Jouni Malinen <j@w1.fi>
* Copyright (c) 2002-2012, Jouni Malinen <j@w1.fi>
*
* This program is free software; you can redistribute it and/or modify
* it under the terms of the GNU General Public License version 2 as
* published by the Free Software Foundation.
*
* Alternatively, this software may be distributed under the terms of BSD
* license.
*
* See README and COPYING for more details.
* This software may be distributed under the terms of the BSD license.
* See README for more details.
*/
#ifndef IEEE802_11_COMMON_H
@ -39,10 +33,17 @@ struct ieee802_11_elems {
const u8 *timeout_int;
const u8 *ht_capabilities;
const u8 *ht_operation;
const u8 *vht_capabilities;
const u8 *vht_operation;
const u8 *vendor_ht_cap;
const u8 *p2p;
const u8 *wfd;
const u8 *link_id;
const u8 *interworking;
const u8 *hs20;
const u8 *ext_capab;
const u8 *bss_max_idle_period;
const u8 *ssid_list;
u8 ssid_len;
u8 supp_rates_len;
@ -66,9 +67,15 @@ struct ieee802_11_elems {
u8 timeout_int_len;
u8 ht_capabilities_len;
u8 ht_operation_len;
u8 vht_capabilities_len;
u8 vht_operation_len;
u8 vendor_ht_cap_len;
u8 p2p_len;
u8 wfd_len;
u8 interworking_len;
u8 hs20_len;
u8 ext_capab_len;
u8 ssid_list_len;
};
typedef enum { ParseOK = 0, ParseUnknown = 1, ParseFailed = -1 } ParseRes;
@ -82,4 +89,15 @@ struct wpabuf * ieee802_11_vendor_ie_concat(const u8 *ies, size_t ies_len,
struct ieee80211_hdr;
const u8 * get_hdr_bssid(const struct ieee80211_hdr *hdr, size_t len);
struct hostapd_wmm_ac_params {
int cwmin;
int cwmax;
int aifs;
int txop_limit; /* in units of 32us */
int admission_control_mandatory;
};
int hostapd_config_wmm_ac(struct hostapd_wmm_ac_params wmm_ac_params[],
const char *name, const char *val);
#endif /* IEEE802_11_COMMON_H */

View File

@ -3,14 +3,8 @@
* Copyright (c) 2002-2009, Jouni Malinen <j@w1.fi>
* Copyright (c) 2007-2008 Intel Corporation
*
* This program is free software; you can redistribute it and/or modify
* it under the terms of the GNU General Public License version 2 as
* published by the Free Software Foundation.
*
* Alternatively, this software may be distributed under the terms of BSD
* license.
*
* See README and COPYING for more details.
* This software may be distributed under the terms of the BSD license.
* See README for more details.
*/
#ifndef IEEE802_11_DEFS_H
@ -82,6 +76,7 @@
#define WLAN_AUTH_OPEN 0
#define WLAN_AUTH_SHARED_KEY 1
#define WLAN_AUTH_FT 2
#define WLAN_AUTH_SAE 3
#define WLAN_AUTH_LEAP 128
#define WLAN_AUTH_CHALLENGE_LEN 128
@ -163,6 +158,8 @@
#define WLAN_STATUS_REQ_REFUSED_SSPN 67
#define WLAN_STATUS_REQ_REFUSED_UNAUTH_ACCESS 68
#define WLAN_STATUS_INVALID_RSNIE 72
#define WLAN_STATUS_ANTI_CLOGGING_TOKEN_REQ 76
#define WLAN_STATUS_FINITE_CYCLIC_GROUP_NOT_SUPPORTED 77
#define WLAN_STATUS_TRANSMISSION_FAILURE 79
/* Reason codes (IEEE 802.11-2007, 7.3.1.7, Table 7-22) */
@ -229,17 +226,33 @@
#define WLAN_EID_RIC_DATA 57
#define WLAN_EID_HT_OPERATION 61
#define WLAN_EID_SECONDARY_CHANNEL_OFFSET 62
#define WLAN_EID_WAPI 68
#define WLAN_EID_TIME_ADVERTISEMENT 69
#define WLAN_EID_20_40_BSS_COEXISTENCE 72
#define WLAN_EID_20_40_BSS_INTOLERANT 73
#define WLAN_EID_OVERLAPPING_BSS_SCAN_PARAMS 74
#define WLAN_EID_MMIE 76
#define WLAN_EID_SSID_LIST 84
#define WLAN_EID_BSS_MAX_IDLE_PERIOD 90
#define WLAN_EID_TFS_REQ 91
#define WLAN_EID_TFS_RESP 92
#define WLAN_EID_WNMSLEEP 93
#define WLAN_EID_TIME_ZONE 98
#define WLAN_EID_LINK_ID 101
#define WLAN_EID_INTERWORKING 107
#define WLAN_EID_ADV_PROTO 108
#define WLAN_EID_ROAMING_CONSORTIUM 111
#define WLAN_EID_EXT_CAPAB 127
#define WLAN_EID_CCKM 156
#define WLAN_EID_VHT_CAP 191
#define WLAN_EID_VHT_OPERATION 192
#define WLAN_EID_VHT_EXTENDED_BSS_LOAD 193
#define WLAN_EID_VHT_WIDE_BW_CHSWITCH 194
#define WLAN_EID_VHT_TRANSMIT_POWER_ENVELOPE 195
#define WLAN_EID_VHT_CHANNEL_SWITCH_WRAPPER 196
#define WLAN_EID_VHT_AID 197
#define WLAN_EID_VHT_QUIET_CHANNEL 198
#define WLAN_EID_VHT_OPERATING_MODE_NOTIFICATION 199
#define WLAN_EID_VENDOR_SPECIFIC 221
@ -260,6 +273,7 @@
#define WLAN_ACTION_VENDOR_SPECIFIC 127
/* Public action codes */
#define WLAN_PA_20_40_BSS_COEX 0
#define WLAN_PA_VENDOR_SPECIFIC 9
#define WLAN_PA_GAS_INITIAL_REQ 10
#define WLAN_PA_GAS_INITIAL_RESP 11
@ -491,6 +505,17 @@ struct ieee80211_mgmt {
u8 action; /* */
u8 trans_id[WLAN_SA_QUERY_TR_ID_LEN];
} STRUCT_PACKED sa_query_resp;
struct {
u8 action;
u8 dialogtoken;
u8 variable[0];
} STRUCT_PACKED wnm_sleep_req;
struct {
u8 action;
u8 dialogtoken;
le16 keydata_len;
u8 variable[0];
} STRUCT_PACKED wnm_sleep_resp;
struct {
u8 action;
u8 variable[0];
@ -513,12 +538,25 @@ struct ieee80211_mgmt {
* Entries */
u8 variable[0];
} STRUCT_PACKED bss_tm_req;
struct {
u8 action; /* 8 */
u8 dialog_token;
u8 status_code;
u8 bss_termination_delay;
/* Target BSSID (optional),
* BSS Transition Candidate List
* Entries (optional) */
u8 variable[0];
} STRUCT_PACKED bss_tm_resp;
} u;
} STRUCT_PACKED action;
} u;
} STRUCT_PACKED;
/* Rx MCS bitmask is in the first 77 bits of supported_mcs_set */
#define IEEE80211_HT_MCS_MASK_LEN 10
struct ieee80211_ht_capabilities {
le16 ht_capabilities_info;
u8 a_mpdu_params;
@ -537,6 +575,19 @@ struct ieee80211_ht_operation {
u8 basic_set[16];
} STRUCT_PACKED;
struct ieee80211_vht_capabilities {
le32 vht_capabilities_info;
u8 vht_supported_mcs_set[8];
} STRUCT_PACKED;
struct ieee80211_vht_operation {
u8 vht_op_info_chwidth;
u8 vht_op_info_chan_center_freq_seg0_idx;
u8 vht_op_info_chan_center_freq_seg1_idx;
le16 vht_basic_mcs_set;
} STRUCT_PACKED;
#ifdef _MSC_VER
#pragma pack(pop)
#endif /* _MSC_VER */
@ -618,7 +669,7 @@ struct ieee80211_ht_operation {
#define OP_MODE_MIXED 3
#define HT_INFO_OPERATION_MODE_OP_MODE_MASK \
((le16) (0x0001 | 0x0002))
(0x0001 | 0x0002)
#define HT_INFO_OPERATION_MODE_OP_MODE_OFFSET 0
#define HT_INFO_OPERATION_MODE_NON_GF_DEVS_PRESENT ((u8) BIT(2))
#define HT_INFO_OPERATION_MODE_TRANSMIT_BURST_LIMIT ((u8) BIT(3))
@ -631,14 +682,45 @@ struct ieee80211_ht_operation {
#define HT_INFO_STBC_PARAM_PCO_ACTIVE ((u16) BIT(10))
#define HT_INFO_STBC_PARAM_PCO_PHASE ((u16) BIT(11))
#define BSS_MEMBERSHIP_SELECTOR_VHT_PHY 126
#define BSS_MEMBERSHIP_SELECTOR_HT_PHY 127
/* VHT Defines */
#define VHT_CAP_MAX_MPDU_LENGTH_7991 ((u32) BIT(0))
#define VHT_CAP_MAX_MPDU_LENGTH_11454 ((u32) BIT(1))
#define VHT_CAP_SUPP_CHAN_WIDTH_160MHZ ((u32) BIT(2))
#define VHT_CAP_SUPP_CHAN_WIDTH_160_80PLUS80MHZ ((u32) BIT(3))
#define VHT_CAP_RXLDPC ((u32) BIT(4))
#define VHT_CAP_SHORT_GI_80 ((u32) BIT(5))
#define VHT_CAP_SHORT_GI_160 ((u32) BIT(6))
#define VHT_CAP_TXSTBC ((u32) BIT(7))
#define VHT_CAP_RXSTBC_1 ((u32) BIT(8))
#define VHT_CAP_RXSTBC_2 ((u32) BIT(9))
#define VHT_CAP_RXSTBC_3 ((u32) BIT(8) | BIT(9))
#define VHT_CAP_RXSTBC_4 ((u32) BIT(10))
#define VHT_CAP_SU_BEAMFORMER_CAPABLE ((u32) BIT(11))
#define VHT_CAP_SU_BEAMFORMEE_CAPABLE ((u32) BIT(12))
#define VHT_CAP_BEAMFORMER_ANTENNAS_MAX ((u32) BIT(13) | BIT(14))
#define VHT_CAP_SOUNDING_DIMENTION_MAX ((u32) BIT(16) | BIT(17))
#define VHT_CAP_MU_BEAMFORMER_CAPABLE ((u32) BIT(19))
#define VHT_CAP_MU_BEAMFORMEE_CAPABLE ((u32) BIT(20))
#define VHT_CAP_VHT_TXOP_PS ((u32) BIT(21))
#define VHT_CAP_HTC_VHT ((u32) BIT(22))
#define VHT_CAP_MAX_A_MPDU_LENGTH_EXPONENT ((u32) BIT(23))
#define VHT_CAP_VHT_LINK_ADAPTATION_VHT_UNSOL_MFB ((u32) BIT(27))
#define VHT_CAP_VHT_LINK_ADAPTATION_VHT_MRQ_MFB ((u32) BIT(26) | BIT(27))
#define VHT_CAP_RX_ANTENNA_PATTERN ((u32) BIT(28))
#define VHT_CAP_TX_ANTENNA_PATTERN ((u32) BIT(29))
#define OUI_MICROSOFT 0x0050f2 /* Microsoft (also used in Wi-Fi specs)
* 00:50:F2 */
#define WPA_IE_VENDOR_TYPE 0x0050f201
#define WPS_IE_VENDOR_TYPE 0x0050f204
#define OUI_WFA 0x506f9a
#define P2P_IE_VENDOR_TYPE 0x506f9a09
#define WFD_IE_VENDOR_TYPE 0x506f9a0a
#define WFD_OUI_TYPE 10
#define HS20_IE_VENDOR_TYPE 0x506f9a10
#define WMM_OUI_TYPE 2
#define WMM_OUI_SUBTYPE_INFORMATION_ELEMENT 0
@ -677,6 +759,10 @@ struct wmm_information_element {
} STRUCT_PACKED;
#define WMM_QOSINFO_STA_AC_MASK 0x0f
#define WMM_QOSINFO_STA_SP_MASK 0x03
#define WMM_QOSINFO_STA_SP_SHIFT 5
#define WMM_AC_AIFSN_MASK 0x0f
#define WMM_AC_AIFNS_SHIFT 0
#define WMM_AC_ACM 0x10
@ -748,6 +834,16 @@ enum {
};
#define HS20_INDICATION_OUI_TYPE 16
#define HS20_ANQP_OUI_TYPE 17
#define HS20_STYPE_QUERY_LIST 1
#define HS20_STYPE_CAPABILITY_LIST 2
#define HS20_STYPE_OPERATOR_FRIENDLY_NAME 3
#define HS20_STYPE_WAN_METRICS 4
#define HS20_STYPE_CONNECTION_CAPABILITY 5
#define HS20_STYPE_NAI_HOME_REALM_QUERY 6
#define HS20_STYPE_OPERATING_CLASS 7
/* Wi-Fi Direct (P2P) */
#define P2P_OUI_TYPE 9
@ -846,6 +942,7 @@ enum p2p_service_protocol_type {
P2P_SERV_BONJOUR = 1,
P2P_SERV_UPNP = 2,
P2P_SERV_WS_DISCOVERY = 3,
P2P_SERV_WIFI_DISPLAY = 4,
P2P_SERV_VENDOR_SPECIFIC = 255
};
@ -857,6 +954,20 @@ enum p2p_sd_status {
};
enum wifi_display_subelem {
WFD_SUBELEM_DEVICE_INFO = 0,
WFD_SUBELEM_ASSOCIATED_BSSID = 1,
WFD_SUBELEM_AUDIO_FORMATS = 2,
WFD_SUBELEM_VIDEO_FORMATS = 3,
WFD_SUBELEM_3D_VIDEO_FORMATS = 4,
WFD_SUBELEM_CONTENT_PROTECTION = 5,
WFD_SUBELEM_COUPLED_SINK = 6,
WFD_SUBELEM_EXT_CAPAB = 7,
WFD_SUBELEM_LOCAL_IP_ADDRESS = 8,
WFD_SUBELEM_SESSION_INFO = 9
};
#define OUI_BROADCOM 0x00904c /* Broadcom (Epigram) */
#define VENDOR_HT_CAPAB_OUI_TYPE 0x33 /* 00-90-4c:0x33 */
@ -869,10 +980,20 @@ enum p2p_sd_status {
#define WLAN_CIPHER_SUITE_CCMP 0x000FAC04
#define WLAN_CIPHER_SUITE_WEP104 0x000FAC05
#define WLAN_CIPHER_SUITE_AES_CMAC 0x000FAC06
#define WLAN_CIPHER_SUITE_NO_GROUP_ADDR 0x000FAC07
#define WLAN_CIPHER_SUITE_GCMP 0x000FAC08
#define WLAN_CIPHER_SUITE_SMS4 0x00147201
#define WLAN_CIPHER_SUITE_CKIP 0x00409600
#define WLAN_CIPHER_SUITE_CKIP_CMIC 0x00409601
#define WLAN_CIPHER_SUITE_CMIC 0x00409602
#define WLAN_CIPHER_SUITE_KRK 0x004096FF /* for nl80211 use only */
/* AKM suite selectors */
#define WLAN_AKM_SUITE_8021X 0x000FAC01
#define WLAN_AKM_SUITE_PSK 0x000FAC02
#define WLAN_AKM_SUITE_CCKM 0x00409600
/* IEEE 802.11v - WNM Action field values */
@ -914,4 +1035,51 @@ enum wnm_action {
#define WNM_BSS_TM_REQ_BSS_TERMINATION_INCLUDED BIT(3)
#define WNM_BSS_TM_REQ_ESS_DISASSOC_IMMINENT BIT(4)
/* IEEE Std 802.11-2012, 8.4.2.62 20/40 BSS Coexistence element */
#define WLAN_20_40_BSS_COEX_INFO_REQ BIT(0)
#define WLAN_20_40_BSS_COEX_40MHZ_INTOL BIT(1)
#define WLAN_20_40_BSS_COEX_20MHZ_WIDTH_REQ BIT(2)
#define WLAN_20_40_BSS_COEX_OBSS_EXEMPT_REQ BIT(3)
#define WLAN_20_40_BSS_COEX_OBSS_EXEMPT_GRNT BIT(4)
struct ieee80211_2040_bss_coex_ie {
u8 element_id;
u8 length;
u8 coex_param;
} STRUCT_PACKED;
struct ieee80211_2040_intol_chan_report {
u8 element_id;
u8 length;
u8 op_class;
u8 variable[0]; /* Channel List */
} STRUCT_PACKED;
/* IEEE 802.11v - WNM-Sleep Mode element */
struct wnm_sleep_element {
u8 eid; /* WLAN_EID_WNMSLEEP */
u8 len;
u8 action_type; /* WNM_SLEEP_ENTER/WNM_SLEEP_MODE_EXIT */
u8 status;
le16 intval;
} STRUCT_PACKED;
#define WNM_SLEEP_MODE_ENTER 0
#define WNM_SLEEP_MODE_EXIT 1
enum wnm_sleep_mode_response_status {
WNM_STATUS_SLEEP_ACCEPT = 0,
WNM_STATUS_SLEEP_EXIT_ACCEPT_GTK_UPDATE = 1,
WNM_STATUS_DENIED_ACTION = 2,
WNM_STATUS_DENIED_TMP = 3,
WNM_STATUS_DENIED_KEY = 4,
WNM_STATUS_DENIED_OTHER_WNM_SERVICE = 5
};
/* WNM-Sleep Mode subelement IDs */
enum wnm_sleep_mode_subelement_id {
WNM_SLEEP_SUBELEM_GTK = 0,
WNM_SLEEP_SUBELEM_IGTK = 1
};
#endif /* IEEE802_11_DEFS_H */

View File

@ -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

View File

@ -5,6 +5,6 @@
#define VERSION_STR_POSTFIX ""
#endif /* VERSION_STR_POSTFIX */
#define VERSION_STR "1.1" VERSION_STR_POSTFIX
#define VERSION_STR "2.0" VERSION_STR_POSTFIX
#endif /* VERSION_H */

View File

@ -2,14 +2,8 @@
* WPA/RSN - Shared functions for supplicant and authenticator
* Copyright (c) 2002-2008, Jouni Malinen <j@w1.fi>
*
* This program is free software; you can redistribute it and/or modify
* it under the terms of the GNU General Public License version 2 as
* published by the Free Software Foundation.
*
* Alternatively, this software may be distributed under the terms of BSD
* license.
*
* See README and COPYING for more details.
* This software may be distributed under the terms of the BSD license.
* See README for more details.
*/
#include "includes.h"
@ -49,8 +43,10 @@ int wpa_eapol_key_mic(const u8 *key, int ver, const u8 *buf, size_t len,
u8 hash[SHA1_MAC_LEN];
switch (ver) {
#ifndef CONFIG_FIPS
case WPA_KEY_INFO_TYPE_HMAC_MD5_RC4:
return hmac_md5(key, 16, buf, len, mic);
#endif /* CONFIG_FIPS */
case WPA_KEY_INFO_TYPE_HMAC_SHA1_AES:
if (hmac_sha1(key, 16, buf, len, hash))
return -1;
@ -356,6 +352,8 @@ static int rsn_selector_to_bitfield(const u8 *s)
if (RSN_SELECTOR_GET(s) == RSN_CIPHER_SUITE_AES_128_CMAC)
return WPA_CIPHER_AES_128_CMAC;
#endif /* CONFIG_IEEE80211W */
if (RSN_SELECTOR_GET(s) == RSN_CIPHER_SUITE_GCMP)
return WPA_CIPHER_GCMP;
return 0;
}
@ -378,6 +376,12 @@ static int rsn_key_mgmt_to_bitfield(const u8 *s)
if (RSN_SELECTOR_GET(s) == RSN_AUTH_KEY_MGMT_PSK_SHA256)
return WPA_KEY_MGMT_PSK_SHA256;
#endif /* CONFIG_IEEE80211W */
#ifdef CONFIG_SAE
if (RSN_SELECTOR_GET(s) == RSN_AUTH_KEY_MGMT_SAE)
return WPA_KEY_MGMT_SAE;
if (RSN_SELECTOR_GET(s) == RSN_AUTH_KEY_MGMT_FT_SAE)
return WPA_KEY_MGMT_FT_SAE;
#endif /* CONFIG_SAE */
return 0;
}
#endif /* CONFIG_NO_WPA2 */
@ -912,6 +916,8 @@ const char * wpa_cipher_txt(int cipher)
return "CCMP";
case WPA_CIPHER_CCMP | WPA_CIPHER_TKIP:
return "CCMP+TKIP";
case WPA_CIPHER_GCMP:
return "GCMP";
default:
return "UNKNOWN";
}
@ -1073,3 +1079,138 @@ int wpa_insert_pmkid(u8 *ies, size_t ies_len, const u8 *pmkid)
return added;
}
#endif /* CONFIG_IEEE80211R */
int wpa_cipher_key_len(int cipher)
{
switch (cipher) {
case WPA_CIPHER_CCMP:
case WPA_CIPHER_GCMP:
return 16;
case WPA_CIPHER_TKIP:
return 32;
case WPA_CIPHER_WEP104:
return 13;
case WPA_CIPHER_WEP40:
return 5;
}
return 0;
}
int wpa_cipher_rsc_len(int cipher)
{
switch (cipher) {
case WPA_CIPHER_CCMP:
case WPA_CIPHER_GCMP:
case WPA_CIPHER_TKIP:
return 6;
case WPA_CIPHER_WEP104:
case WPA_CIPHER_WEP40:
return 0;
}
return 0;
}
int wpa_cipher_to_alg(int cipher)
{
switch (cipher) {
case WPA_CIPHER_CCMP:
return WPA_ALG_CCMP;
case WPA_CIPHER_GCMP:
return WPA_ALG_GCMP;
case WPA_CIPHER_TKIP:
return WPA_ALG_TKIP;
case WPA_CIPHER_WEP104:
case WPA_CIPHER_WEP40:
return WPA_ALG_WEP;
}
return WPA_ALG_NONE;
}
int wpa_cipher_valid_pairwise(int cipher)
{
return cipher == WPA_CIPHER_CCMP ||
cipher == WPA_CIPHER_GCMP ||
cipher == WPA_CIPHER_TKIP;
}
u32 wpa_cipher_to_suite(int proto, int cipher)
{
if (cipher & WPA_CIPHER_CCMP)
return (proto == WPA_PROTO_RSN ?
RSN_CIPHER_SUITE_CCMP : WPA_CIPHER_SUITE_CCMP);
if (cipher & WPA_CIPHER_GCMP)
return RSN_CIPHER_SUITE_GCMP;
if (cipher & WPA_CIPHER_TKIP)
return (proto == WPA_PROTO_RSN ?
RSN_CIPHER_SUITE_TKIP : WPA_CIPHER_SUITE_TKIP);
if (cipher & WPA_CIPHER_WEP104)
return (proto == WPA_PROTO_RSN ?
RSN_CIPHER_SUITE_WEP104 : WPA_CIPHER_SUITE_WEP104);
if (cipher & WPA_CIPHER_WEP40)
return (proto == WPA_PROTO_RSN ?
RSN_CIPHER_SUITE_WEP40 : WPA_CIPHER_SUITE_WEP40);
if (cipher & WPA_CIPHER_NONE)
return (proto == WPA_PROTO_RSN ?
RSN_CIPHER_SUITE_NONE : WPA_CIPHER_SUITE_NONE);
return 0;
}
int rsn_cipher_put_suites(u8 *pos, int ciphers)
{
int num_suites = 0;
if (ciphers & WPA_CIPHER_CCMP) {
RSN_SELECTOR_PUT(pos, RSN_CIPHER_SUITE_CCMP);
pos += RSN_SELECTOR_LEN;
num_suites++;
}
if (ciphers & WPA_CIPHER_GCMP) {
RSN_SELECTOR_PUT(pos, RSN_CIPHER_SUITE_GCMP);
pos += RSN_SELECTOR_LEN;
num_suites++;
}
if (ciphers & WPA_CIPHER_TKIP) {
RSN_SELECTOR_PUT(pos, RSN_CIPHER_SUITE_TKIP);
pos += RSN_SELECTOR_LEN;
num_suites++;
}
if (ciphers & WPA_CIPHER_NONE) {
RSN_SELECTOR_PUT(pos, RSN_CIPHER_SUITE_NONE);
pos += RSN_SELECTOR_LEN;
num_suites++;
}
return num_suites;
}
int wpa_cipher_put_suites(u8 *pos, int ciphers)
{
int num_suites = 0;
if (ciphers & WPA_CIPHER_CCMP) {
RSN_SELECTOR_PUT(pos, WPA_CIPHER_SUITE_CCMP);
pos += WPA_SELECTOR_LEN;
num_suites++;
}
if (ciphers & WPA_CIPHER_TKIP) {
RSN_SELECTOR_PUT(pos, WPA_CIPHER_SUITE_TKIP);
pos += WPA_SELECTOR_LEN;
num_suites++;
}
if (ciphers & WPA_CIPHER_NONE) {
RSN_SELECTOR_PUT(pos, WPA_CIPHER_SUITE_NONE);
pos += WPA_SELECTOR_LEN;
num_suites++;
}
return num_suites;
}

View File

@ -2,14 +2,8 @@
* WPA definitions shared between hostapd and wpa_supplicant
* Copyright (c) 2002-2008, Jouni Malinen <j@w1.fi>
*
* This program is free software; you can redistribute it and/or modify
* it under the terms of the GNU General Public License version 2 as
* published by the Free Software Foundation.
*
* Alternatively, this software may be distributed under the terms of BSD
* license.
*
* See README and COPYING for more details.
* This software may be distributed under the terms of the BSD license.
* See README for more details.
*/
#ifndef WPA_COMMON_H
@ -38,6 +32,7 @@
#define WPA_AUTH_KEY_MGMT_NONE RSN_SELECTOR(0x00, 0x50, 0xf2, 0)
#define WPA_AUTH_KEY_MGMT_UNSPEC_802_1X RSN_SELECTOR(0x00, 0x50, 0xf2, 1)
#define WPA_AUTH_KEY_MGMT_PSK_OVER_802_1X RSN_SELECTOR(0x00, 0x50, 0xf2, 2)
#define WPA_AUTH_KEY_MGMT_CCKM RSN_SELECTOR(0x00, 0x40, 0x96, 0)
#define WPA_CIPHER_SUITE_NONE RSN_SELECTOR(0x00, 0x50, 0xf2, 0)
#define WPA_CIPHER_SUITE_WEP40 RSN_SELECTOR(0x00, 0x50, 0xf2, 1)
#define WPA_CIPHER_SUITE_TKIP RSN_SELECTOR(0x00, 0x50, 0xf2, 2)
@ -57,6 +52,9 @@
#define RSN_AUTH_KEY_MGMT_802_1X_SHA256 RSN_SELECTOR(0x00, 0x0f, 0xac, 5)
#define RSN_AUTH_KEY_MGMT_PSK_SHA256 RSN_SELECTOR(0x00, 0x0f, 0xac, 6)
#define RSN_AUTH_KEY_MGMT_TPK_HANDSHAKE RSN_SELECTOR(0x00, 0x0f, 0xac, 7)
#define RSN_AUTH_KEY_MGMT_SAE RSN_SELECTOR(0x00, 0x0f, 0xac, 8)
#define RSN_AUTH_KEY_MGMT_FT_SAE RSN_SELECTOR(0x00, 0x0f, 0xac, 9)
#define RSN_AUTH_KEY_MGMT_CCKM RSN_SELECTOR(0x00, 0x40, 0x96, 0x00)
#define RSN_CIPHER_SUITE_NONE RSN_SELECTOR(0x00, 0x0f, 0xac, 0)
#define RSN_CIPHER_SUITE_WEP40 RSN_SELECTOR(0x00, 0x0f, 0xac, 1)
@ -70,6 +68,7 @@
#define RSN_CIPHER_SUITE_AES_128_CMAC RSN_SELECTOR(0x00, 0x0f, 0xac, 6)
#endif /* CONFIG_IEEE80211W */
#define RSN_CIPHER_SUITE_NO_GROUP_ADDRESSED RSN_SELECTOR(0x00, 0x0f, 0xac, 7)
#define RSN_CIPHER_SUITE_GCMP RSN_SELECTOR(0x00, 0x0f, 0xac, 8)
/* EAPOL-Key Key Data Encapsulation
* GroupKey and PeerKey require encryption, otherwise, encryption is optional.
@ -89,6 +88,9 @@
#ifdef CONFIG_IEEE80211W
#define RSN_KEY_DATA_IGTK RSN_SELECTOR(0x00, 0x0f, 0xac, 9)
#endif /* CONFIG_IEEE80211W */
#define RSN_KEY_DATA_KEYID RSN_SELECTOR(0x00, 0x0f, 0xac, 10)
#define RSN_KEY_DATA_MULTIBAND_GTK RSN_SELECTOR(0x00, 0x0f, 0xac, 11)
#define RSN_KEY_DATA_MULTIBAND_KEYID RSN_SELECTOR(0x00, 0x0f, 0xac, 12)
#define WPA_OUI_TYPE RSN_SELECTOR(0x00, 0x50, 0xf2, 1)
@ -381,4 +383,12 @@ struct wpa_ft_ies {
int wpa_ft_parse_ies(const u8 *ies, size_t ies_len, struct wpa_ft_ies *parse);
int wpa_cipher_key_len(int cipher);
int wpa_cipher_rsc_len(int cipher);
int wpa_cipher_to_alg(int cipher);
int wpa_cipher_valid_pairwise(int cipher);
u32 wpa_cipher_to_suite(int proto, int cipher);
int rsn_cipher_put_suites(u8 *pos, int ciphers);
int wpa_cipher_put_suites(u8 *pos, int ciphers);
#endif /* WPA_COMMON_H */

View File

@ -2,14 +2,8 @@
* wpa_supplicant/hostapd control interface library
* Copyright (c) 2004-2007, Jouni Malinen <j@w1.fi>
*
* This program is free software; you can redistribute it and/or modify
* it under the terms of the GNU General Public License version 2 as
* published by the Free Software Foundation.
*
* Alternatively, this software may be distributed under the terms of BSD
* license.
*
* See README and COPYING for more details.
* This software may be distributed under the terms of the BSD license.
* See README for more details.
*/
#include "includes.h"
@ -18,7 +12,12 @@
#ifdef CONFIG_CTRL_IFACE_UNIX
#include <sys/un.h>
#include <unistd.h>
#include <fcntl.h>
#endif /* CONFIG_CTRL_IFACE_UNIX */
#ifdef CONFIG_CTRL_IFACE_UDP_REMOTE
#include <netdb.h>
#endif /* CONFIG_CTRL_IFACE_UDP_REMOTE */
#ifdef ANDROID
#include <dirent.h>
@ -50,6 +49,8 @@ struct wpa_ctrl {
struct sockaddr_in local;
struct sockaddr_in dest;
char *cookie;
char *remote_ifname;
char *remote_ip;
#endif /* CONFIG_CTRL_IFACE_UDP */
#ifdef CONFIG_CTRL_IFACE_UNIX
int s;
@ -79,6 +80,7 @@ struct wpa_ctrl * wpa_ctrl_open(const char *ctrl_path)
int ret;
size_t res;
int tries = 0;
int flags;
ctrl = os_malloc(sizeof(*ctrl));
if (ctrl == NULL)
@ -162,6 +164,19 @@ try_again:
return NULL;
}
/*
* Make socket non-blocking so that we don't hang forever if
* target dies unexpectedly.
*/
flags = fcntl(ctrl->s, F_GETFL);
if (flags >= 0) {
flags |= O_NONBLOCK;
if (fcntl(ctrl->s, F_SETFL, flags) < 0) {
perror("fcntl(ctrl->s, O_NONBLOCK)");
/* Not fatal, continue on.*/
}
}
return ctrl;
}
@ -236,6 +251,9 @@ struct wpa_ctrl * wpa_ctrl_open(const char *ctrl_path)
struct wpa_ctrl *ctrl;
char buf[128];
size_t len;
#ifdef CONFIG_CTRL_IFACE_UDP_REMOTE
struct hostent *h;
#endif /* CONFIG_CTRL_IFACE_UDP_REMOTE */
ctrl = os_malloc(sizeof(*ctrl));
if (ctrl == NULL)
@ -250,7 +268,11 @@ struct wpa_ctrl * wpa_ctrl_open(const char *ctrl_path)
}
ctrl->local.sin_family = AF_INET;
#ifdef CONFIG_CTRL_IFACE_UDP_REMOTE
ctrl->local.sin_addr.s_addr = INADDR_ANY;
#else /* CONFIG_CTRL_IFACE_UDP_REMOTE */
ctrl->local.sin_addr.s_addr = htonl((127 << 24) | 1);
#endif /* CONFIG_CTRL_IFACE_UDP_REMOTE */
if (bind(ctrl->s, (struct sockaddr *) &ctrl->local,
sizeof(ctrl->local)) < 0) {
close(ctrl->s);
@ -261,10 +283,48 @@ struct wpa_ctrl * wpa_ctrl_open(const char *ctrl_path)
ctrl->dest.sin_family = AF_INET;
ctrl->dest.sin_addr.s_addr = htonl((127 << 24) | 1);
ctrl->dest.sin_port = htons(WPA_CTRL_IFACE_PORT);
#ifdef CONFIG_CTRL_IFACE_UDP_REMOTE
if (ctrl_path) {
char *port, *name;
int port_id;
name = os_strdup(ctrl_path);
if (name == NULL) {
close(ctrl->s);
os_free(ctrl);
return NULL;
}
port = os_strchr(name, ':');
if (port) {
port_id = atoi(&port[1]);
port[0] = '\0';
} else
port_id = WPA_CTRL_IFACE_PORT;
h = gethostbyname(name);
ctrl->remote_ip = os_strdup(name);
os_free(name);
if (h == NULL) {
perror("gethostbyname");
close(ctrl->s);
os_free(ctrl->remote_ip);
os_free(ctrl);
return NULL;
}
ctrl->dest.sin_port = htons(port_id);
os_memcpy(h->h_addr, (char *) &ctrl->dest.sin_addr.s_addr,
h->h_length);
} else
ctrl->remote_ip = os_strdup("localhost");
#endif /* CONFIG_CTRL_IFACE_UDP_REMOTE */
if (connect(ctrl->s, (struct sockaddr *) &ctrl->dest,
sizeof(ctrl->dest)) < 0) {
perror("connect");
close(ctrl->s);
os_free(ctrl->remote_ip);
os_free(ctrl);
return NULL;
}
@ -275,14 +335,31 @@ struct wpa_ctrl * wpa_ctrl_open(const char *ctrl_path)
ctrl->cookie = os_strdup(buf);
}
if (wpa_ctrl_request(ctrl, "IFNAME", 6, buf, &len, NULL) == 0) {
buf[len] = '\0';
ctrl->remote_ifname = os_strdup(buf);
}
return ctrl;
}
char * wpa_ctrl_get_remote_ifname(struct wpa_ctrl *ctrl)
{
#define WPA_CTRL_MAX_PS_NAME 100
static char ps[WPA_CTRL_MAX_PS_NAME] = {};
os_snprintf(ps, WPA_CTRL_MAX_PS_NAME, "%s/%s",
ctrl->remote_ip, ctrl->remote_ifname);
return ps;
}
void wpa_ctrl_close(struct wpa_ctrl *ctrl)
{
close(ctrl->s);
os_free(ctrl->cookie);
os_free(ctrl->remote_ifname);
os_free(ctrl->remote_ip);
os_free(ctrl);
}
@ -295,6 +372,7 @@ int wpa_ctrl_request(struct wpa_ctrl *ctrl, const char *cmd, size_t cmd_len,
void (*msg_cb)(char *msg, size_t len))
{
struct timeval tv;
struct os_time started_at;
int res;
fd_set rfds;
const char *_cmd;
@ -321,7 +399,30 @@ int wpa_ctrl_request(struct wpa_ctrl *ctrl, const char *cmd, size_t cmd_len,
_cmd_len = cmd_len;
}
errno = 0;
started_at.sec = 0;
started_at.usec = 0;
retry_send:
if (send(ctrl->s, _cmd, _cmd_len, 0) < 0) {
if (errno == EAGAIN || errno == EBUSY || errno == EWOULDBLOCK)
{
/*
* Must be a non-blocking socket... Try for a bit
* longer before giving up.
*/
if (started_at.sec == 0)
os_get_time(&started_at);
else {
struct os_time n;
os_get_time(&n);
/* Try for a few seconds. */
if (n.sec > started_at.sec + 5)
goto send_err;
}
os_sleep(1, 0);
goto retry_send;
}
send_err:
os_free(cmd_buf);
return -1;
}

View File

@ -2,14 +2,8 @@
* wpa_supplicant/hostapd control interface library
* Copyright (c) 2004-2006, Jouni Malinen <j@w1.fi>
*
* This program is free software; you can redistribute it and/or modify
* it under the terms of the GNU General Public License version 2 as
* published by the Free Software Foundation.
*
* Alternatively, this software may be distributed under the terms of BSD
* license.
*
* See README and COPYING for more details.
* This software may be distributed under the terms of the BSD license.
* See README for more details.
*/
#ifndef WPA_CTRL_H
@ -54,6 +48,10 @@ extern "C" {
#define WPA_EVENT_EAP_SUCCESS "CTRL-EVENT-EAP-SUCCESS "
/** EAP authentication failed (EAP-Failure received) */
#define WPA_EVENT_EAP_FAILURE "CTRL-EVENT-EAP-FAILURE "
/** Network block temporarily disabled (e.g., due to authentication failure) */
#define WPA_EVENT_TEMP_DISABLED "CTRL-EVENT-SSID-TEMP-DISABLED "
/** Temporarily disabled network block re-enabled */
#define WPA_EVENT_REENABLED "CTRL-EVENT-SSID-REENABLED "
/** New scan results available */
#define WPA_EVENT_SCAN_RESULTS "CTRL-EVENT-SCAN-RESULTS "
/** wpa_supplicant state change */
@ -122,6 +120,8 @@ extern "C" {
#define P2P_EVENT_PROV_DISC_PBC_REQ "P2P-PROV-DISC-PBC-REQ "
/* parameters: <peer address> */
#define P2P_EVENT_PROV_DISC_PBC_RESP "P2P-PROV-DISC-PBC-RESP "
/* parameters: <peer address> <status> */
#define P2P_EVENT_PROV_DISC_FAILURE "P2P-PROV-DISC-FAILURE"
/* parameters: <freq> <src addr> <dialog token> <update indicator> <TLVs> */
#define P2P_EVENT_SERV_DISC_REQ "P2P-SERV-DISC-REQ "
/* parameters: <src addr> <update indicator> <TLVs> */
@ -133,6 +133,8 @@ extern "C" {
#define INTERWORKING_AP "INTERWORKING-AP "
#define INTERWORKING_NO_MATCH "INTERWORKING-NO-MATCH "
#define GAS_RESPONSE_INFO "GAS-RESPONSE-INFO "
/* hostapd control interface - fixed message prefixes */
#define WPS_EVENT_PIN_NEEDED "WPS-PIN-NEEDED "
#define WPS_EVENT_NEW_AP_SETTINGS "WPS-NEW-AP-SETTINGS "
@ -145,6 +147,28 @@ extern "C" {
#define AP_STA_DISCONNECTED "AP-STA-DISCONNECTED "
/* BSS command information masks */
#define WPA_BSS_MASK_ALL 0xFFFFFFFF
#define WPA_BSS_MASK_ID BIT(0)
#define WPA_BSS_MASK_BSSID BIT(1)
#define WPA_BSS_MASK_FREQ BIT(2)
#define WPA_BSS_MASK_BEACON_INT BIT(3)
#define WPA_BSS_MASK_CAPABILITIES BIT(4)
#define WPA_BSS_MASK_QUAL BIT(5)
#define WPA_BSS_MASK_NOISE BIT(6)
#define WPA_BSS_MASK_LEVEL BIT(7)
#define WPA_BSS_MASK_TSF BIT(8)
#define WPA_BSS_MASK_AGE BIT(9)
#define WPA_BSS_MASK_IE BIT(10)
#define WPA_BSS_MASK_FLAGS BIT(11)
#define WPA_BSS_MASK_SSID BIT(12)
#define WPA_BSS_MASK_WPS_SCAN BIT(13)
#define WPA_BSS_MASK_P2P_SCAN BIT(14)
#define WPA_BSS_MASK_INTERNETW BIT(15)
#define WPA_BSS_MASK_WIFI_DISPLAY BIT(16)
/* wpa_supplicant/hostapd control interface access */
/**
@ -269,6 +293,8 @@ int wpa_ctrl_pending(struct wpa_ctrl *ctrl);
*/
int wpa_ctrl_get_fd(struct wpa_ctrl *ctrl);
char * wpa_ctrl_get_remote_ifname(struct wpa_ctrl *ctrl);
#ifdef ANDROID
/**
* wpa_ctrl_cleanup() - Delete any local UNIX domain socket files that
@ -281,8 +307,11 @@ void wpa_ctrl_cleanup(void);
#endif /* ANDROID */
#ifdef CONFIG_CTRL_IFACE_UDP
/* Port range for multiple wpa_supplicant instances and multiple VIFs */
#define WPA_CTRL_IFACE_PORT 9877
#define WPA_CTRL_IFACE_PORT_LIMIT 50 /* decremented from start */
#define WPA_GLOBAL_CTRL_IFACE_PORT 9878
#define WPA_GLOBAL_CTRL_IFACE_PORT_LIMIT 20 /* incremented from start */
#endif /* CONFIG_CTRL_IFACE_UDP */

Some files were not shown because too many files have changed in this diff Show More