mirror of
https://github.com/lwfinger/rtl8188eu.git
synced 2024-11-22 04:23:39 +00:00
rtl8188eu: Add hostapd and configurationb file
Signed-off-by: Larry Finger <Larry.Finger@lwfinger.net>
This commit is contained in:
parent
7638be5ee7
commit
e275d5ba1f
477 changed files with 220879 additions and 0 deletions
340
hostapd-0.8/COPYING
Normal file
340
hostapd-0.8/COPYING
Normal file
|
@ -0,0 +1,340 @@
|
|||
GNU GENERAL PUBLIC LICENSE
|
||||
Version 2, June 1991
|
||||
|
||||
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
|
||||
|
||||
|
||||
Also add information on how to contact you by electronic and paper mail.
|
||||
|
||||
If the program is interactive, make it output a short notice like this
|
||||
when it starts in an interactive mode:
|
||||
|
||||
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.
|
72
hostapd-0.8/README
Normal file
72
hostapd-0.8/README
Normal file
|
@ -0,0 +1,72 @@
|
|||
wpa_supplicant and hostapd
|
||||
--------------------------
|
||||
|
||||
Copyright (c) 2002-2011, 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.
|
||||
|
||||
|
||||
This package may include either wpa_supplicant, hostapd, or both. See
|
||||
README file respective subdirectories (wpa_supplicant/README or
|
||||
hostapd/README) for more details.
|
||||
|
||||
Source code files were moved around in v0.6.x releases and compared to
|
||||
earlier releases, the programs are now built by first going to a
|
||||
subdirectory (wpa_supplicant or hostapd) and creating build
|
||||
configuration (.config) and running 'make' there (for Linux/BSD/cygwin
|
||||
builds).
|
||||
|
||||
|
||||
License
|
||||
-------
|
||||
|
||||
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:
|
||||
|
||||
Redistribution and use in source and binary forms, with or without
|
||||
modification, are permitted provided that the following conditions are
|
||||
met:
|
||||
|
||||
1. Redistributions of source code must retain the above copyright
|
||||
notice, this list of conditions and the following disclaimer.
|
||||
|
||||
2. Redistributions in binary form must reproduce the above copyright
|
||||
notice, this list of conditions and the following disclaimer in the
|
||||
documentation and/or other materials provided with the distribution.
|
||||
|
||||
3. Neither the name(s) of the above-listed copyright holder(s) nor the
|
||||
names of its contributors may be used to endorse or promote products
|
||||
derived from this software without specific prior written permission.
|
||||
|
||||
THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
|
||||
"AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
|
||||
LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
|
||||
A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
|
||||
OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
|
||||
SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
|
||||
LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
|
||||
DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
|
||||
THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
|
||||
(INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
|
||||
OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
|
816
hostapd-0.8/hostapd/Android.mk
Normal file
816
hostapd-0.8/hostapd/Android.mk
Normal file
|
@ -0,0 +1,816 @@
|
|||
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
|
||||
endif
|
||||
|
||||
include $(LOCAL_PATH)/.config
|
||||
|
||||
# To ignore possible wrong network configurations
|
||||
L_CFLAGS = -DWPA_IGNORE_CONFIG_ERRORS
|
||||
|
||||
# To force sizeof(enum) = 4
|
||||
ifeq ($(TARGET_ARCH),arm)
|
||||
L_CFLAGS += -mabi=aapcs-linux
|
||||
endif
|
||||
|
||||
# To allow non-ASCII characters in SSID
|
||||
L_CFLAGS += -DWPA_UNICODE_SSID
|
||||
|
||||
# OpenSSL is configured without engines on Android
|
||||
L_CFLAGS += -DOPENSSL_NO_ENGINE
|
||||
|
||||
INCLUDES = $(LOCAL_PATH)
|
||||
INCLUDES += $(LOCAL_PATH)/src
|
||||
INCLUDES += $(LOCAL_PATH)/src/utils
|
||||
INCLUDES += external/openssl/include
|
||||
INCLUDES += frameworks/base/cmds/keystore
|
||||
ifdef CONFIG_DRIVER_NL80211
|
||||
INCLUDES += external/libnl_2/include
|
||||
endif
|
||||
|
||||
|
||||
ifndef CONFIG_OS
|
||||
ifdef CONFIG_NATIVE_WINDOWS
|
||||
CONFIG_OS=win32
|
||||
else
|
||||
CONFIG_OS=unix
|
||||
endif
|
||||
endif
|
||||
|
||||
ifeq ($(CONFIG_OS), internal)
|
||||
L_CFLAGS += -DOS_NO_C_LIB_DEFINES
|
||||
endif
|
||||
|
||||
ifdef CONFIG_NATIVE_WINDOWS
|
||||
L_CFLAGS += -DCONFIG_NATIVE_WINDOWS
|
||||
LIBS += -lws2_32
|
||||
endif
|
||||
|
||||
OBJS = main.c
|
||||
OBJS += config_file.c
|
||||
|
||||
OBJS += src/ap/hostapd.c
|
||||
OBJS += src/ap/wpa_auth_glue.c
|
||||
OBJS += src/ap/drv_callbacks.c
|
||||
OBJS += src/ap/ap_drv_ops.c
|
||||
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/ieee802_11_auth.c
|
||||
OBJS += src/ap/sta_info.c
|
||||
OBJS += src/ap/wpa_auth.c
|
||||
OBJS += src/ap/tkip_countermeasures.c
|
||||
OBJS += src/ap/ap_mlme.c
|
||||
OBJS += src/ap/wpa_auth_ie.c
|
||||
OBJS += src/ap/preauth_auth.c
|
||||
OBJS += src/ap/pmksa_cache_auth.c
|
||||
OBJS_d =
|
||||
OBJS_p =
|
||||
LIBS =
|
||||
LIBS_c =
|
||||
HOBJS =
|
||||
LIBS_h =
|
||||
|
||||
NEED_RC4=y
|
||||
NEED_AES=y
|
||||
NEED_MD5=y
|
||||
NEED_SHA1=y
|
||||
|
||||
OBJS += src/drivers/drivers.c
|
||||
L_CFLAGS += -DHOSTAPD
|
||||
|
||||
ifdef CONFIG_WPA_TRACE
|
||||
L_CFLAGS += -DWPA_TRACE
|
||||
OBJS += src/utils/trace.c
|
||||
HOBJS += src/utils/trace.c
|
||||
LDFLAGS += -rdynamic
|
||||
L_CFLAGS += -funwind-tables
|
||||
ifdef CONFIG_WPA_TRACE_BFD
|
||||
L_CFLAGS += -DWPA_TRACE_BFD
|
||||
LIBS += -lbfd
|
||||
LIBS_c += -lbfd
|
||||
LIBS_h += -lbfd
|
||||
endif
|
||||
endif
|
||||
|
||||
OBJS += src/utils/eloop.c
|
||||
OBJS += src/utils/common.c
|
||||
OBJS += src/utils/wpa_debug.c
|
||||
OBJS += src/utils/wpabuf.c
|
||||
OBJS += src/utils/os_$(CONFIG_OS).c
|
||||
OBJS += src/utils/ip_addr.c
|
||||
|
||||
OBJS += src/common/ieee802_11_common.c
|
||||
OBJS += src/common/wpa_common.c
|
||||
|
||||
OBJS += src/eapol_auth/eapol_auth_sm.c
|
||||
|
||||
|
||||
ifndef CONFIG_NO_DUMP_STATE
|
||||
# define HOSTAPD_DUMP_STATE to include SIGUSR1 handler for dumping state to
|
||||
# a file (undefine it, if you want to save in binary size)
|
||||
L_CFLAGS += -DHOSTAPD_DUMP_STATE
|
||||
OBJS += dump_state.c
|
||||
OBJS += src/eapol_auth/eapol_auth_dump.c
|
||||
endif
|
||||
|
||||
ifdef CONFIG_NO_RADIUS
|
||||
L_CFLAGS += -DCONFIG_NO_RADIUS
|
||||
CONFIG_NO_ACCOUNTING=y
|
||||
else
|
||||
OBJS += src/radius/radius.c
|
||||
OBJS += src/radius/radius_client.c
|
||||
endif
|
||||
|
||||
ifdef CONFIG_NO_ACCOUNTING
|
||||
L_CFLAGS += -DCONFIG_NO_ACCOUNTING
|
||||
else
|
||||
OBJS += src/ap/accounting.c
|
||||
endif
|
||||
|
||||
ifdef CONFIG_NO_VLAN
|
||||
L_CFLAGS += -DCONFIG_NO_VLAN
|
||||
else
|
||||
OBJS += src/ap/vlan_init.c
|
||||
endif
|
||||
|
||||
ifdef CONFIG_NO_CTRL_IFACE
|
||||
L_CFLAGS += -DCONFIG_NO_CTRL_IFACE
|
||||
else
|
||||
OBJS += ctrl_iface.c
|
||||
OBJS += src/ap/ctrl_iface_ap.c
|
||||
endif
|
||||
|
||||
OBJS += src/crypto/md5.c
|
||||
|
||||
L_CFLAGS += -DCONFIG_CTRL_IFACE -DCONFIG_CTRL_IFACE_UNIX
|
||||
|
||||
ifdef CONFIG_IAPP
|
||||
L_CFLAGS += -DCONFIG_IAPP
|
||||
OBJS += src/ap/iapp.c
|
||||
endif
|
||||
|
||||
ifdef CONFIG_RSN_PREAUTH
|
||||
L_CFLAGS += -DCONFIG_RSN_PREAUTH
|
||||
CONFIG_L2_PACKET=y
|
||||
endif
|
||||
|
||||
ifdef CONFIG_PEERKEY
|
||||
L_CFLAGS += -DCONFIG_PEERKEY
|
||||
OBJS += src/ap/peerkey_auth.c
|
||||
endif
|
||||
|
||||
ifdef CONFIG_IEEE80211W
|
||||
L_CFLAGS += -DCONFIG_IEEE80211W
|
||||
NEED_SHA256=y
|
||||
NEED_AES_OMAC1=y
|
||||
endif
|
||||
|
||||
ifdef CONFIG_IEEE80211R
|
||||
L_CFLAGS += -DCONFIG_IEEE80211R
|
||||
OBJS += src/ap/wpa_auth_ft.c
|
||||
NEED_SHA256=y
|
||||
NEED_AES_OMAC1=y
|
||||
NEED_AES_UNWRAP=y
|
||||
endif
|
||||
|
||||
ifdef CONFIG_IEEE80211N
|
||||
L_CFLAGS += -DCONFIG_IEEE80211N
|
||||
endif
|
||||
|
||||
include $(LOCAL_PATH)/src/drivers/drivers.mk
|
||||
|
||||
OBJS += $(DRV_AP_OBJS)
|
||||
L_CFLAGS += $(DRV_AP_CFLAGS)
|
||||
LDFLAGS += $(DRV_AP_LDFLAGS)
|
||||
LIBS += $(DRV_AP_LIBS)
|
||||
|
||||
ifdef CONFIG_L2_PACKET
|
||||
ifdef CONFIG_DNET_PCAP
|
||||
ifdef CONFIG_L2_FREEBSD
|
||||
LIBS += -lpcap
|
||||
OBJS += src/l2_packet/l2_packet_freebsd.c
|
||||
else
|
||||
LIBS += -ldnet -lpcap
|
||||
OBJS += src/l2_packet/l2_packet_pcap.c
|
||||
endif
|
||||
else
|
||||
OBJS += src/l2_packet/l2_packet_linux.c
|
||||
endif
|
||||
else
|
||||
OBJS += src/l2_packet/l2_packet_none.c
|
||||
endif
|
||||
|
||||
|
||||
ifdef CONFIG_EAP_MD5
|
||||
L_CFLAGS += -DEAP_SERVER_MD5
|
||||
OBJS += src/eap_server/eap_server_md5.c
|
||||
CHAP=y
|
||||
endif
|
||||
|
||||
ifdef CONFIG_EAP_TLS
|
||||
L_CFLAGS += -DEAP_SERVER_TLS
|
||||
OBJS += src/eap_server/eap_server_tls.c
|
||||
TLS_FUNCS=y
|
||||
endif
|
||||
|
||||
ifdef CONFIG_EAP_PEAP
|
||||
L_CFLAGS += -DEAP_SERVER_PEAP
|
||||
OBJS += src/eap_server/eap_server_peap.c
|
||||
OBJS += src/eap_common/eap_peap_common.c
|
||||
TLS_FUNCS=y
|
||||
CONFIG_EAP_MSCHAPV2=y
|
||||
endif
|
||||
|
||||
ifdef CONFIG_EAP_TTLS
|
||||
L_CFLAGS += -DEAP_SERVER_TTLS
|
||||
OBJS += src/eap_server/eap_server_ttls.c
|
||||
TLS_FUNCS=y
|
||||
CHAP=y
|
||||
endif
|
||||
|
||||
ifdef CONFIG_EAP_MSCHAPV2
|
||||
L_CFLAGS += -DEAP_SERVER_MSCHAPV2
|
||||
OBJS += src/eap_server/eap_server_mschapv2.c
|
||||
MS_FUNCS=y
|
||||
endif
|
||||
|
||||
ifdef CONFIG_EAP_GTC
|
||||
L_CFLAGS += -DEAP_SERVER_GTC
|
||||
OBJS += src/eap_server/eap_server_gtc.c
|
||||
endif
|
||||
|
||||
ifdef CONFIG_EAP_SIM
|
||||
L_CFLAGS += -DEAP_SERVER_SIM
|
||||
OBJS += src/eap_server/eap_server_sim.c
|
||||
CONFIG_EAP_SIM_COMMON=y
|
||||
NEED_AES_CBC=y
|
||||
endif
|
||||
|
||||
ifdef CONFIG_EAP_AKA
|
||||
L_CFLAGS += -DEAP_SERVER_AKA
|
||||
OBJS += src/eap_server/eap_server_aka.c
|
||||
CONFIG_EAP_SIM_COMMON=y
|
||||
NEED_SHA256=y
|
||||
NEED_AES_CBC=y
|
||||
endif
|
||||
|
||||
ifdef CONFIG_EAP_AKA_PRIME
|
||||
L_CFLAGS += -DEAP_SERVER_AKA_PRIME
|
||||
endif
|
||||
|
||||
ifdef CONFIG_EAP_SIM_COMMON
|
||||
OBJS += src/eap_common/eap_sim_common.c
|
||||
# Example EAP-SIM/AKA interface for GSM/UMTS authentication. This can be
|
||||
# replaced with another file implementating the interface specified in
|
||||
# eap_sim_db.h.
|
||||
OBJS += src/eap_server/eap_sim_db.c
|
||||
NEED_FIPS186_2_PRF=y
|
||||
endif
|
||||
|
||||
ifdef CONFIG_EAP_PAX
|
||||
L_CFLAGS += -DEAP_SERVER_PAX
|
||||
OBJS += src/eap_server/eap_server_pax.c src/eap_common/eap_pax_common.c
|
||||
endif
|
||||
|
||||
ifdef CONFIG_EAP_PSK
|
||||
L_CFLAGS += -DEAP_SERVER_PSK
|
||||
OBJS += src/eap_server/eap_server_psk.c src/eap_common/eap_psk_common.c
|
||||
NEED_AES_OMAC1=y
|
||||
NEED_AES_ENCBLOCK=y
|
||||
NEED_AES_EAX=y
|
||||
endif
|
||||
|
||||
ifdef CONFIG_EAP_SAKE
|
||||
L_CFLAGS += -DEAP_SERVER_SAKE
|
||||
OBJS += src/eap_server/eap_server_sake.c src/eap_common/eap_sake_common.c
|
||||
endif
|
||||
|
||||
ifdef CONFIG_EAP_GPSK
|
||||
L_CFLAGS += -DEAP_SERVER_GPSK
|
||||
OBJS += src/eap_server/eap_server_gpsk.c src/eap_common/eap_gpsk_common.c
|
||||
ifdef CONFIG_EAP_GPSK_SHA256
|
||||
L_CFLAGS += -DEAP_SERVER_GPSK_SHA256
|
||||
endif
|
||||
NEED_SHA256=y
|
||||
NEED_AES_OMAC1=y
|
||||
endif
|
||||
|
||||
ifdef CONFIG_EAP_PWD
|
||||
L_CFLAGS += -DEAP_SERVER_PWD
|
||||
OBJS += src/eap_server/eap_server_pwd.c src/eap_common/eap_pwd_common.c
|
||||
NEED_SHA256=y
|
||||
endif
|
||||
|
||||
ifdef CONFIG_EAP_VENDOR_TEST
|
||||
L_CFLAGS += -DEAP_SERVER_VENDOR_TEST
|
||||
OBJS += src/eap_server/eap_server_vendor_test.c
|
||||
endif
|
||||
|
||||
ifdef CONFIG_EAP_FAST
|
||||
L_CFLAGS += -DEAP_SERVER_FAST
|
||||
OBJS += src/eap_server/eap_server_fast.c
|
||||
OBJS += src/eap_common/eap_fast_common.c
|
||||
TLS_FUNCS=y
|
||||
NEED_T_PRF=y
|
||||
NEED_AES_UNWRAP=y
|
||||
endif
|
||||
|
||||
ifdef CONFIG_WPS
|
||||
ifdef CONFIG_WPS2
|
||||
L_CFLAGS += -DCONFIG_WPS2
|
||||
endif
|
||||
|
||||
L_CFLAGS += -DCONFIG_WPS -DEAP_SERVER_WSC
|
||||
OBJS += src/utils/uuid.c
|
||||
OBJS += src/ap/wps_hostapd.c
|
||||
OBJS += src/eap_server/eap_server_wsc.c src/eap_common/eap_wsc_common.c
|
||||
OBJS += src/wps/wps.c
|
||||
OBJS += src/wps/wps_common.c
|
||||
OBJS += src/wps/wps_attr_parse.c
|
||||
OBJS += src/wps/wps_attr_build.c
|
||||
OBJS += src/wps/wps_attr_process.c
|
||||
OBJS += src/wps/wps_dev_attr.c
|
||||
OBJS += src/wps/wps_enrollee.c
|
||||
OBJS += src/wps/wps_registrar.c
|
||||
NEED_DH_GROUPS=y
|
||||
NEED_SHA256=y
|
||||
NEED_BASE64=y
|
||||
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
|
||||
L_CFLAGS += -DCONFIG_WPS_OOB
|
||||
endif
|
||||
|
||||
ifdef CONFIG_WPS_UPNP
|
||||
L_CFLAGS += -DCONFIG_WPS_UPNP
|
||||
OBJS += src/wps/wps_upnp.c
|
||||
OBJS += src/wps/wps_upnp_ssdp.c
|
||||
OBJS += src/wps/wps_upnp_web.c
|
||||
OBJS += src/wps/wps_upnp_event.c
|
||||
OBJS += src/wps/wps_upnp_ap.c
|
||||
OBJS += src/wps/upnp_xml.c
|
||||
OBJS += src/wps/httpread.c
|
||||
OBJS += src/wps/http_client.c
|
||||
OBJS += src/wps/http_server.c
|
||||
endif
|
||||
|
||||
ifdef CONFIG_WPS_STRICT
|
||||
L_CFLAGS += -DCONFIG_WPS_STRICT
|
||||
OBJS += src/wps/wps_validate.c
|
||||
endif
|
||||
|
||||
ifdef CONFIG_WPS_TESTING
|
||||
L_CFLAGS += -DCONFIG_WPS_TESTING
|
||||
endif
|
||||
|
||||
endif
|
||||
|
||||
ifdef CONFIG_EAP_IKEV2
|
||||
L_CFLAGS += -DEAP_SERVER_IKEV2
|
||||
OBJS += src/eap_server/eap_server_ikev2.c src/eap_server/ikev2.c
|
||||
OBJS += src/eap_common/eap_ikev2_common.c src/eap_common/ikev2_common.c
|
||||
NEED_DH_GROUPS=y
|
||||
NEED_DH_GROUPS_ALL=y
|
||||
NEED_MODEXP=y
|
||||
NEED_CIPHER=y
|
||||
endif
|
||||
|
||||
ifdef CONFIG_EAP_TNC
|
||||
L_CFLAGS += -DEAP_SERVER_TNC
|
||||
OBJS += src/eap_server/eap_server_tnc.c
|
||||
OBJS += src/eap_server/tncs.c
|
||||
NEED_BASE64=y
|
||||
ifndef CONFIG_DRIVER_BSD
|
||||
LIBS += -ldl
|
||||
endif
|
||||
endif
|
||||
|
||||
# Basic EAP functionality is needed for EAPOL
|
||||
OBJS += eap_register.c
|
||||
OBJS += src/eap_server/eap_server.c
|
||||
OBJS += src/eap_common/eap_common.c
|
||||
OBJS += src/eap_server/eap_server_methods.c
|
||||
OBJS += src/eap_server/eap_server_identity.c
|
||||
L_CFLAGS += -DEAP_SERVER_IDENTITY
|
||||
|
||||
ifdef CONFIG_EAP
|
||||
L_CFLAGS += -DEAP_SERVER
|
||||
endif
|
||||
|
||||
ifdef CONFIG_PKCS12
|
||||
L_CFLAGS += -DPKCS12_FUNCS
|
||||
endif
|
||||
|
||||
ifdef MS_FUNCS
|
||||
OBJS += src/crypto/ms_funcs.c
|
||||
NEED_DES=y
|
||||
NEED_MD4=y
|
||||
endif
|
||||
|
||||
ifdef CHAP
|
||||
OBJS += src/eap_common/chap.c
|
||||
endif
|
||||
|
||||
ifdef TLS_FUNCS
|
||||
NEED_DES=y
|
||||
# Shared TLS functions (needed for EAP_TLS, EAP_PEAP, and EAP_TTLS)
|
||||
L_CFLAGS += -DEAP_TLS_FUNCS
|
||||
OBJS += src/eap_server/eap_server_tls_common.c
|
||||
NEED_TLS_PRF=y
|
||||
endif
|
||||
|
||||
ifndef CONFIG_TLS
|
||||
CONFIG_TLS=openssl
|
||||
endif
|
||||
|
||||
ifeq ($(CONFIG_TLS), openssl)
|
||||
ifdef TLS_FUNCS
|
||||
OBJS += src/crypto/tls_openssl.c
|
||||
LIBS += -lssl
|
||||
endif
|
||||
OBJS += src/crypto/crypto_openssl.c
|
||||
HOBJS += src/crypto/crypto_openssl.c
|
||||
ifdef NEED_FIPS186_2_PRF
|
||||
OBJS += src/crypto/fips_prf_openssl.c
|
||||
endif
|
||||
LIBS += -lcrypto
|
||||
LIBS_h += -lcrypto
|
||||
endif
|
||||
|
||||
ifeq ($(CONFIG_TLS), gnutls)
|
||||
ifdef TLS_FUNCS
|
||||
OBJS += src/crypto/tls_gnutls.c
|
||||
LIBS += -lgnutls -lgpg-error
|
||||
ifdef CONFIG_GNUTLS_EXTRA
|
||||
L_CFLAGS += -DCONFIG_GNUTLS_EXTRA
|
||||
LIBS += -lgnutls-extra
|
||||
endif
|
||||
endif
|
||||
OBJS += src/crypto/crypto_gnutls.c
|
||||
HOBJS += src/crypto/crypto_gnutls.c
|
||||
ifdef NEED_FIPS186_2_PRF
|
||||
OBJS += src/crypto/fips_prf_gnutls.c
|
||||
endif
|
||||
LIBS += -lgcrypt
|
||||
LIBS_h += -lgcrypt
|
||||
CONFIG_INTERNAL_SHA256=y
|
||||
CONFIG_INTERNAL_RC4=y
|
||||
CONFIG_INTERNAL_DH_GROUP5=y
|
||||
endif
|
||||
|
||||
ifeq ($(CONFIG_TLS), schannel)
|
||||
ifdef TLS_FUNCS
|
||||
OBJS += src/crypto/tls_schannel.c
|
||||
endif
|
||||
OBJS += src/crypto/crypto_cryptoapi.c
|
||||
OBJS_p += src/crypto/crypto_cryptoapi.c
|
||||
CONFIG_INTERNAL_SHA256=y
|
||||
CONFIG_INTERNAL_RC4=y
|
||||
CONFIG_INTERNAL_DH_GROUP5=y
|
||||
endif
|
||||
|
||||
ifeq ($(CONFIG_TLS), nss)
|
||||
ifdef TLS_FUNCS
|
||||
OBJS += src/crypto/tls_nss.c
|
||||
LIBS += -lssl3
|
||||
endif
|
||||
OBJS += src/crypto/crypto_nss.c
|
||||
ifdef NEED_FIPS186_2_PRF
|
||||
OBJS += src/crypto/fips_prf_nss.c
|
||||
endif
|
||||
LIBS += -lnss3
|
||||
LIBS_h += -lnss3
|
||||
CONFIG_INTERNAL_MD4=y
|
||||
CONFIG_INTERNAL_DH_GROUP5=y
|
||||
endif
|
||||
|
||||
ifeq ($(CONFIG_TLS), internal)
|
||||
ifndef CONFIG_CRYPTO
|
||||
CONFIG_CRYPTO=internal
|
||||
endif
|
||||
ifdef TLS_FUNCS
|
||||
OBJS += src/crypto/crypto_internal-rsa.c
|
||||
OBJS += src/crypto/tls_internal.c
|
||||
OBJS += src/tls/tlsv1_common.c
|
||||
OBJS += src/tls/tlsv1_record.c
|
||||
OBJS += src/tls/tlsv1_cred.c
|
||||
OBJS += src/tls/tlsv1_server.c
|
||||
OBJS += src/tls/tlsv1_server_write.c
|
||||
OBJS += src/tls/tlsv1_server_read.c
|
||||
OBJS += src/tls/asn1.c
|
||||
OBJS += src/tls/rsa.c
|
||||
OBJS += src/tls/x509v3.c
|
||||
OBJS += src/tls/pkcs1.c
|
||||
OBJS += src/tls/pkcs5.c
|
||||
OBJS += src/tls/pkcs8.c
|
||||
NEED_SHA256=y
|
||||
NEED_BASE64=y
|
||||
NEED_TLS_PRF=y
|
||||
NEED_MODEXP=y
|
||||
NEED_CIPHER=y
|
||||
L_CFLAGS += -DCONFIG_TLS_INTERNAL
|
||||
L_CFLAGS += -DCONFIG_TLS_INTERNAL_SERVER
|
||||
endif
|
||||
ifdef NEED_CIPHER
|
||||
NEED_DES=y
|
||||
OBJS += src/crypto/crypto_internal-cipher.c
|
||||
endif
|
||||
ifdef NEED_MODEXP
|
||||
OBJS += src/crypto/crypto_internal-modexp.c
|
||||
OBJS += src/tls/bignum.c
|
||||
endif
|
||||
ifeq ($(CONFIG_CRYPTO), libtomcrypt)
|
||||
OBJS += src/crypto/crypto_libtomcrypt.c
|
||||
LIBS += -ltomcrypt -ltfm
|
||||
LIBS_h += -ltomcrypt -ltfm
|
||||
CONFIG_INTERNAL_SHA256=y
|
||||
CONFIG_INTERNAL_RC4=y
|
||||
CONFIG_INTERNAL_DH_GROUP5=y
|
||||
endif
|
||||
ifeq ($(CONFIG_CRYPTO), internal)
|
||||
OBJS += src/crypto/crypto_internal.c
|
||||
NEED_AES_DEC=y
|
||||
L_CFLAGS += -DCONFIG_CRYPTO_INTERNAL
|
||||
ifdef CONFIG_INTERNAL_LIBTOMMATH
|
||||
L_CFLAGS += -DCONFIG_INTERNAL_LIBTOMMATH
|
||||
ifdef CONFIG_INTERNAL_LIBTOMMATH_FAST
|
||||
L_CFLAGS += -DLTM_FAST
|
||||
endif
|
||||
else
|
||||
LIBS += -ltommath
|
||||
LIBS_h += -ltommath
|
||||
endif
|
||||
CONFIG_INTERNAL_AES=y
|
||||
CONFIG_INTERNAL_DES=y
|
||||
CONFIG_INTERNAL_SHA1=y
|
||||
CONFIG_INTERNAL_MD4=y
|
||||
CONFIG_INTERNAL_MD5=y
|
||||
CONFIG_INTERNAL_SHA256=y
|
||||
CONFIG_INTERNAL_RC4=y
|
||||
CONFIG_INTERNAL_DH_GROUP5=y
|
||||
endif
|
||||
ifeq ($(CONFIG_CRYPTO), cryptoapi)
|
||||
OBJS += src/crypto/crypto_cryptoapi.c
|
||||
OBJS_p += src/crypto/crypto_cryptoapi.c
|
||||
L_CFLAGS += -DCONFIG_CRYPTO_CRYPTOAPI
|
||||
CONFIG_INTERNAL_SHA256=y
|
||||
CONFIG_INTERNAL_RC4=y
|
||||
endif
|
||||
endif
|
||||
|
||||
ifeq ($(CONFIG_TLS), none)
|
||||
ifdef TLS_FUNCS
|
||||
OBJS += src/crypto/tls_none.c
|
||||
L_CFLAGS += -DEAP_TLS_NONE
|
||||
CONFIG_INTERNAL_AES=y
|
||||
CONFIG_INTERNAL_SHA1=y
|
||||
CONFIG_INTERNAL_MD5=y
|
||||
endif
|
||||
OBJS += src/crypto/crypto_none.c
|
||||
OBJS_p += src/crypto/crypto_none.c
|
||||
CONFIG_INTERNAL_SHA256=y
|
||||
CONFIG_INTERNAL_RC4=y
|
||||
endif
|
||||
|
||||
ifndef TLS_FUNCS
|
||||
OBJS += src/crypto/tls_none.c
|
||||
ifeq ($(CONFIG_TLS), internal)
|
||||
CONFIG_INTERNAL_AES=y
|
||||
CONFIG_INTERNAL_SHA1=y
|
||||
CONFIG_INTERNAL_MD5=y
|
||||
CONFIG_INTERNAL_RC4=y
|
||||
endif
|
||||
endif
|
||||
|
||||
AESOBJS = # none so far
|
||||
ifdef CONFIG_INTERNAL_AES
|
||||
AESOBJS += src/crypto/aes-internal.c src/crypto/aes-internal-enc.c
|
||||
endif
|
||||
|
||||
AESOBJS += src/crypto/aes-wrap.c
|
||||
ifdef NEED_AES_EAX
|
||||
AESOBJS += src/crypto/aes-eax.c
|
||||
NEED_AES_CTR=y
|
||||
endif
|
||||
ifdef NEED_AES_CTR
|
||||
AESOBJS += src/crypto/aes-ctr.c
|
||||
endif
|
||||
ifdef NEED_AES_ENCBLOCK
|
||||
AESOBJS += src/crypto/aes-encblock.c
|
||||
endif
|
||||
ifdef NEED_AES_OMAC1
|
||||
AESOBJS += src/crypto/aes-omac1.c
|
||||
endif
|
||||
ifdef NEED_AES_UNWRAP
|
||||
NEED_AES_DEC=y
|
||||
AESOBJS += src/crypto/aes-unwrap.c
|
||||
endif
|
||||
ifdef NEED_AES_CBC
|
||||
NEED_AES_DEC=y
|
||||
AESOBJS += src/crypto/aes-cbc.c
|
||||
endif
|
||||
ifdef NEED_AES_DEC
|
||||
ifdef CONFIG_INTERNAL_AES
|
||||
AESOBJS += src/crypto/aes-internal-dec.c
|
||||
endif
|
||||
endif
|
||||
ifdef NEED_AES
|
||||
OBJS += $(AESOBJS)
|
||||
endif
|
||||
|
||||
SHA1OBJS =
|
||||
ifdef NEED_SHA1
|
||||
SHA1OBJS += src/crypto/sha1.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
|
||||
SHA1OBJS += src/crypto/sha1-pbkdf2.c
|
||||
ifdef NEED_T_PRF
|
||||
SHA1OBJS += src/crypto/sha1-tprf.c
|
||||
endif
|
||||
ifdef NEED_TLS_PRF
|
||||
SHA1OBJS += src/crypto/sha1-tlsprf.c
|
||||
endif
|
||||
endif
|
||||
|
||||
ifdef NEED_SHA1
|
||||
OBJS += $(SHA1OBJS)
|
||||
endif
|
||||
|
||||
ifdef NEED_MD5
|
||||
ifdef CONFIG_INTERNAL_MD5
|
||||
OBJS += src/crypto/md5-internal.c
|
||||
HOBJS += src/crypto/md5-internal.c
|
||||
endif
|
||||
endif
|
||||
|
||||
ifdef NEED_MD4
|
||||
ifdef CONFIG_INTERNAL_MD4
|
||||
OBJS += src/crypto/md4-internal.c
|
||||
endif
|
||||
endif
|
||||
|
||||
ifdef NEED_DES
|
||||
ifdef CONFIG_INTERNAL_DES
|
||||
OBJS += src/crypto/des-internal.c
|
||||
endif
|
||||
endif
|
||||
|
||||
ifdef NEED_RC4
|
||||
ifdef CONFIG_INTERNAL_RC4
|
||||
OBJS += src/crypto/rc4.c
|
||||
endif
|
||||
endif
|
||||
|
||||
ifdef NEED_SHA256
|
||||
OBJS += src/crypto/sha256.c
|
||||
ifdef CONFIG_INTERNAL_SHA256
|
||||
OBJS += src/crypto/sha256-internal.c
|
||||
endif
|
||||
endif
|
||||
|
||||
ifdef NEED_DH_GROUPS
|
||||
OBJS += src/crypto/dh_groups.c
|
||||
endif
|
||||
ifdef NEED_DH_GROUPS_ALL
|
||||
L_CFLAGS += -DALL_DH_GROUPS
|
||||
endif
|
||||
ifdef CONFIG_INTERNAL_DH_GROUP5
|
||||
ifdef NEED_DH_GROUPS
|
||||
OBJS += src/crypto/dh_group5.c
|
||||
endif
|
||||
endif
|
||||
|
||||
ifdef CONFIG_NO_RANDOM_POOL
|
||||
L_CFLAGS += -DCONFIG_NO_RANDOM_POOL
|
||||
else
|
||||
OBJS += src/crypto/random.c
|
||||
HOBJS += src/crypto/random.c
|
||||
HOBJS += $(SHA1OBJS)
|
||||
HOBJS += src/crypto/md5.c
|
||||
endif
|
||||
|
||||
ifdef CONFIG_RADIUS_SERVER
|
||||
L_CFLAGS += -DRADIUS_SERVER
|
||||
OBJS += src/radius/radius_server.c
|
||||
endif
|
||||
|
||||
ifdef CONFIG_IPV6
|
||||
L_CFLAGS += -DCONFIG_IPV6
|
||||
endif
|
||||
|
||||
ifdef CONFIG_DRIVER_RADIUS_ACL
|
||||
L_CFLAGS += -DCONFIG_DRIVER_RADIUS_ACL
|
||||
endif
|
||||
|
||||
ifdef CONFIG_FULL_DYNAMIC_VLAN
|
||||
# define CONFIG_FULL_DYNAMIC_VLAN to have hostapd manipulate bridges
|
||||
# and vlan interfaces for the vlan feature.
|
||||
L_CFLAGS += -DCONFIG_FULL_DYNAMIC_VLAN
|
||||
endif
|
||||
|
||||
ifdef NEED_BASE64
|
||||
OBJS += src/utils/base64.c
|
||||
endif
|
||||
|
||||
ifdef NEED_AP_MLME
|
||||
OBJS += src/ap/beacon.c
|
||||
OBJS += src/ap/wmm.c
|
||||
OBJS += src/ap/ap_list.c
|
||||
OBJS += src/ap/ieee802_11.c
|
||||
OBJS += src/ap/hw_features.c
|
||||
L_CFLAGS += -DNEED_AP_MLME
|
||||
endif
|
||||
ifdef CONFIG_IEEE80211N
|
||||
OBJS += src/ap/ieee802_11_ht.c
|
||||
endif
|
||||
|
||||
ifdef CONFIG_P2P_MANAGER
|
||||
L_CFLAGS += -DCONFIG_P2P_MANAGER
|
||||
OBJS += src/ap/p2p_hostapd.c
|
||||
endif
|
||||
|
||||
ifdef CONFIG_NO_STDOUT_DEBUG
|
||||
L_CFLAGS += -DCONFIG_NO_STDOUT_DEBUG
|
||||
endif
|
||||
|
||||
ifdef CONFIG_DEBUG_FILE
|
||||
L_CFLAGS += -DCONFIG_DEBUG_FILE
|
||||
endif
|
||||
|
||||
ifdef CONFIG_ANDROID_LOG
|
||||
L_CFLAGS += -DCONFIG_ANDROID_LOG
|
||||
endif
|
||||
|
||||
OBJS_c = hostapd_cli.c src/common/wpa_ctrl.c src/utils/os_$(CONFIG_OS).c
|
||||
ifdef CONFIG_WPA_TRACE
|
||||
OBJS_c += src/utils/trace.c
|
||||
OBJS_c += src/utils/wpa_debug.c
|
||||
endif
|
||||
|
||||
ifeq ($(WPA_BUILD_HOSTAPD),true)
|
||||
|
||||
########################
|
||||
|
||||
include $(CLEAR_VARS)
|
||||
LOCAL_MODULE := hostapd_cli
|
||||
LOCAL_MODULE_TAGS := debug
|
||||
LOCAL_SHARED_LIBRARIES := libc libcutils
|
||||
LOCAL_CFLAGS := $(L_CFLAGS)
|
||||
LOCAL_SRC_FILES := $(OBJS_c)
|
||||
LOCAL_C_INCLUDES := $(INCLUDES)
|
||||
include $(BUILD_EXECUTABLE)
|
||||
|
||||
########################
|
||||
include $(CLEAR_VARS)
|
||||
LOCAL_MODULE := hostapd
|
||||
LOCAL_MODULE_TAGS := optional
|
||||
ifdef CONFIG_DRIVER_CUSTOM
|
||||
LOCAL_STATIC_LIBRARIES := libCustomWifi
|
||||
endif
|
||||
ifneq ($(BOARD_HOSTAPD_PRIVATE_LIB),)
|
||||
LOCAL_STATIC_LIBRARIES += $(BOARD_HOSTAPD_PRIVATE_LIB)
|
||||
endif
|
||||
LOCAL_SHARED_LIBRARIES := libc libcutils libcrypto libssl
|
||||
ifdef CONFIG_DRIVER_NL80211
|
||||
LOCAL_SHARED_LIBRARIES += libnl_2
|
||||
endif
|
||||
LOCAL_CFLAGS := $(L_CFLAGS)
|
||||
LOCAL_SRC_FILES := $(OBJS)
|
||||
LOCAL_C_INCLUDES := $(INCLUDES)
|
||||
include $(BUILD_EXECUTABLE)
|
||||
|
||||
endif # ifeq ($(WPA_BUILD_HOSTAPD),true)
|
647
hostapd-0.8/hostapd/ChangeLog
Normal file
647
hostapd-0.8/hostapd/ChangeLog
Normal file
|
@ -0,0 +1,647 @@
|
|||
ChangeLog for hostapd
|
||||
|
||||
2010-04-18 - v0.7.2
|
||||
* fix WPS internal Registrar use when an external Registrar is also
|
||||
active
|
||||
* bsd: Cleaned up driver wrapper and added various low-level
|
||||
configuration options
|
||||
* TNC: fixed issues with fragmentation
|
||||
* EAP-TNC: add Flags field into fragment acknowledgement (needed to
|
||||
interoperate with other implementations; may potentially breaks
|
||||
compatibility with older wpa_supplicant/hostapd versions)
|
||||
* cleaned up driver wrapper API for multi-BSS operations
|
||||
* nl80211: fix multi-BSS and VLAN operations
|
||||
* fix number of issues with IEEE 802.11r/FT; this version is not
|
||||
backwards compatible with old versions
|
||||
* add SA Query Request processing in AP mode (IEEE 802.11w)
|
||||
* fix IGTK PN in group rekeying (IEEE 802.11w)
|
||||
* fix WPS PBC session overlap detection to use correct attribute
|
||||
* hostapd_notif_Assoc() can now be called with all IEs to simplify
|
||||
driver wrappers
|
||||
* work around interoperability issue with some WPS External Registrar
|
||||
implementations
|
||||
* nl80211: fix WPS IE update
|
||||
* hostapd_cli: add support for action script operations (run a script
|
||||
on hostapd events)
|
||||
* fix DH padding with internal crypto code (mainly, for WPS)
|
||||
* fix WPS association with both WPS IE and WPA/RSN IE present with
|
||||
driver wrappers that use hostapd MLME (e.g., nl80211)
|
||||
|
||||
2010-01-16 - v0.7.1
|
||||
* cleaned up driver wrapper API (struct wpa_driver_ops); the new API
|
||||
is not fully backwards compatible, so out-of-tree driver wrappers
|
||||
will need modifications
|
||||
* cleaned up various module interfaces
|
||||
* merge hostapd and wpa_supplicant developers' documentation into a
|
||||
single document
|
||||
* fixed HT Capabilities IE with nl80211 drivers
|
||||
* moved generic AP functionality code into src/ap
|
||||
* WPS: handle Selected Registrar as union of info from all Registrars
|
||||
* remove obsolte Prism54.org driver wrapper
|
||||
* added internal debugging mechanism with backtrace support and memory
|
||||
allocation/freeing validation, etc. tests (CONFIG_WPA_TRACE=y)
|
||||
* EAP-FAST server: piggyback Phase 2 start with the end of Phase 1
|
||||
* WPS: add support for dynamically selecting whether to provision the
|
||||
PSK as an ASCII passphrase or PSK
|
||||
* added support for WDS (4-address frame) mode with per-station virtual
|
||||
interfaces (wds_sta=1 in config file; only supported with
|
||||
driver=nl80211 for now)
|
||||
* fixed WPS Probe Request processing to handle missing required
|
||||
attribute
|
||||
* fixed PKCS#12 use with OpenSSL 1.0.0
|
||||
* detect bridge interface automatically so that bridge parameter in
|
||||
hostapd.conf becomes optional (though, it may now be used to
|
||||
automatically add then WLAN interface into a bridge with
|
||||
driver=nl80211)
|
||||
|
||||
2009-11-21 - v0.7.0
|
||||
* increased hostapd_cli ping interval to 5 seconds and made this
|
||||
configurable with a new command line options (-G<seconds>)
|
||||
* driver_nl80211: use Linux socket filter to improve performance
|
||||
* added support for external Registrars with WPS (UPnP transport)
|
||||
* 802.11n: scan for overlapping BSSes before starting 20/40 MHz channel
|
||||
* driver_nl80211: fixed STA accounting data collection (TX/RX bytes
|
||||
reported correctly; TX/RX packets not yet available from kernel)
|
||||
* added support for WPS USBA out-of-band mechanism with USB Flash
|
||||
Drives (UFD) (CONFIG_WPS_UFD=y)
|
||||
* fixed EAPOL/EAP reauthentication when using an external RADIUS
|
||||
authentication server
|
||||
* fixed TNC with EAP-TTLS
|
||||
* fixed IEEE 802.11r key derivation function to match with the standard
|
||||
(note: this breaks interoperability with previous version) [Bug 303]
|
||||
* fixed SHA-256 based key derivation function to match with the
|
||||
standard when using CCMP (for IEEE 802.11r and IEEE 802.11w)
|
||||
(note: this breaks interoperability with previous version) [Bug 307]
|
||||
* added number of code size optimizations to remove unnecessary
|
||||
functionality from the program binary based on build configuration
|
||||
(part of this automatic; part configurable with CONFIG_NO_* build
|
||||
options)
|
||||
* use shared driver wrapper files with wpa_supplicant
|
||||
* driver_nl80211: multiple updates to provide support for new Linux
|
||||
nl80211/mac80211 functionality
|
||||
* updated management frame protection to use IEEE Std 802.11w-2009
|
||||
* fixed number of small WPS issues and added workarounds to
|
||||
interoperate with common deployed broken implementations
|
||||
* added some IEEE 802.11n co-existance rules to disable 40 MHz channels
|
||||
or modify primary/secondary channels if needed based on neighboring
|
||||
networks
|
||||
* added support for NFC out-of-band mechanism with WPS
|
||||
* added preliminary support for IEEE 802.11r RIC processing
|
||||
|
||||
2009-01-06 - v0.6.7
|
||||
* added support for Wi-Fi Protected Setup (WPS)
|
||||
(hostapd can now be configured to act as an integrated WPS Registrar
|
||||
and provision credentials for WPS Enrollees using PIN and PBC
|
||||
methods; external wireless Registrar can configure the AP, but
|
||||
external WLAN Manager Registrars are not supported); WPS support can
|
||||
be enabled by adding CONFIG_WPS=y into .config and setting the
|
||||
runtime configuration variables in hostapd.conf (see WPS section in
|
||||
the example configuration file); new hostapd_cli commands wps_pin and
|
||||
wps_pbc are used to configure WPS negotiation; see README-WPS for
|
||||
more details
|
||||
* added IEEE 802.11n HT capability configuration (ht_capab)
|
||||
* added support for generating Country IE based on nl80211 regulatory
|
||||
information (added if ieee80211d=1 in configuration)
|
||||
* fixed WEP authentication (both Open System and Shared Key) with
|
||||
mac80211
|
||||
* added support for EAP-AKA' (draft-arkko-eap-aka-kdf)
|
||||
* added support for using driver_test over UDP socket
|
||||
* changed EAP-GPSK to use the IANA assigned EAP method type 51
|
||||
* updated management frame protection to use IEEE 802.11w/D7.0
|
||||
* fixed retransmission of EAP requests if no response is received
|
||||
|
||||
2008-11-23 - v0.6.6
|
||||
* added a new configuration option, wpa_ptk_rekey, that can be used to
|
||||
enforce frequent PTK rekeying, e.g., to mitigate some attacks against
|
||||
TKIP deficiencies
|
||||
* updated OpenSSL code for EAP-FAST to use an updated version of the
|
||||
session ticket overriding API that was included into the upstream
|
||||
OpenSSL 0.9.9 tree on 2008-11-15 (no additional OpenSSL patch is
|
||||
needed with that version anymore)
|
||||
* changed channel flags configuration to read the information from
|
||||
the driver (e.g., via driver_nl80211 when using mac80211) instead of
|
||||
using hostapd as the source of the regulatory information (i.e.,
|
||||
information from CRDA is now used with mac80211); this allows 5 GHz
|
||||
channels to be used with hostapd (if allowed in the current
|
||||
regulatory domain)
|
||||
* fixed EAP-TLS message processing for the last TLS message if it is
|
||||
large enough to require fragmentation (e.g., if a large Session
|
||||
Ticket data is included)
|
||||
* fixed listen interval configuration for nl80211 drivers
|
||||
|
||||
2008-11-01 - v0.6.5
|
||||
* added support for SHA-256 as X.509 certificate digest when using the
|
||||
internal X.509/TLSv1 implementation
|
||||
* fixed EAP-FAST PAC-Opaque padding (0.6.4 broke this for some peer
|
||||
identity lengths)
|
||||
* fixed internal TLSv1 implementation for abbreviated handshake (used
|
||||
by EAP-FAST server)
|
||||
* added support for setting VLAN ID for STAs based on local MAC ACL
|
||||
(accept_mac_file) as an alternative for RADIUS server-based
|
||||
configuration
|
||||
* updated management frame protection to use IEEE 802.11w/D6.0
|
||||
(adds a new association ping to protect against unauthenticated
|
||||
authenticate or (re)associate request frames dropping association)
|
||||
* added support for using SHA256-based stronger key derivation for WPA2
|
||||
(IEEE 802.11w)
|
||||
* added new "driver wrapper" for RADIUS-only configuration
|
||||
(driver=none in hostapd.conf; CONFIG_DRIVER_NONE=y in .config)
|
||||
* fixed WPA/RSN IE validation to verify that the proto (WPA vs. WPA2)
|
||||
is enabled in configuration
|
||||
* changed EAP-FAST configuration to use separate fields for A-ID and
|
||||
A-ID-Info (eap_fast_a_id_info) to allow A-ID to be set to a fixed
|
||||
16-octet len binary value for better interoperability with some peer
|
||||
implementations; eap_fast_a_id is now configured as a hex string
|
||||
* driver_nl80211: Updated to match the current Linux mac80211 AP mode
|
||||
configuration (wireless-testing.git and Linux kernel releases
|
||||
starting from 2.6.29)
|
||||
|
||||
2008-08-10 - v0.6.4
|
||||
* added peer identity into EAP-FAST PAC-Opaque and skip Phase 2
|
||||
Identity Request if identity is already known
|
||||
* added support for EAP Sequences in EAP-FAST Phase 2
|
||||
* added support for EAP-TNC (Trusted Network Connect)
|
||||
(this version implements the EAP-TNC method and EAP-TTLS/EAP-FAST
|
||||
changes needed to run two methods in sequence (IF-T) and the IF-IMV
|
||||
and IF-TNCCS interfaces from TNCS)
|
||||
* added support for optional cryptobinding with PEAPv0
|
||||
* added fragmentation support for EAP-TNC
|
||||
* added support for fragmenting EAP-TTLS/PEAP/FAST Phase 2 (tunneled)
|
||||
data
|
||||
* added support for opportunistic key caching (OKC)
|
||||
|
||||
2008-02-22 - v0.6.3
|
||||
* fixed Reassociation Response callback processing when using internal
|
||||
MLME (driver_{hostap,nl80211,test}.c)
|
||||
* updated FT support to use the latest draft, IEEE 802.11r/D9.0
|
||||
* copy optional Proxy-State attributes into RADIUS response when acting
|
||||
as a RADIUS authentication server
|
||||
* fixed EAPOL state machine to handle a case in which no response is
|
||||
received from the RADIUS authentication server; previous version
|
||||
could have triggered a crash in some cases after a timeout
|
||||
* fixed EAP-SIM/AKA realm processing to allow decorated usernames to
|
||||
be used
|
||||
* added a workaround for EAP-SIM/AKA peers that include incorrect null
|
||||
termination in the username
|
||||
* fixed EAP-SIM/AKA protected result indication to include AT_COUNTER
|
||||
attribute in notification messages only when using fast
|
||||
reauthentication
|
||||
* fixed EAP-SIM Start response processing for fast reauthentication
|
||||
case
|
||||
* added support for pending EAP processing in EAP-{PEAP,TTLS,FAST}
|
||||
phase 2 to allow EAP-SIM and EAP-AKA to be used as the Phase 2 method
|
||||
|
||||
2008-01-01 - v0.6.2
|
||||
* fixed EAP-SIM and EAP-AKA message parser to validate attribute
|
||||
lengths properly to avoid potential crash caused by invalid messages
|
||||
* added data structure for storing allocated buffers (struct wpabuf);
|
||||
this does not affect hostapd usage, but many of the APIs changed
|
||||
and various interfaces (e.g., EAP) is not compatible with old
|
||||
versions
|
||||
* added support for protecting EAP-AKA/Identity messages with
|
||||
AT_CHECKCODE (optional feature in RFC 4187)
|
||||
* added support for protected result indication with AT_RESULT_IND for
|
||||
EAP-SIM and EAP-AKA (eap_sim_aka_result_ind=1)
|
||||
* added support for configuring EAP-TTLS phase 2 non-EAP methods in
|
||||
EAP server configuration; previously all four were enabled for every
|
||||
phase 2 user, now all four are disabled by default and need to be
|
||||
enabled with new method names TTLS-PAP, TTLS-CHAP, TTLS-MSCHAP,
|
||||
TTLS-MSCHAPV2
|
||||
* removed old debug printing mechanism and the related 'debug'
|
||||
parameter in the configuration file; debug verbosity is now set with
|
||||
-d (or -dd) command line arguments
|
||||
* added support for EAP-IKEv2 (draft-tschofenig-eap-ikev2-15.txt);
|
||||
only shared key/password authentication is supported in this version
|
||||
|
||||
2007-11-24 - v0.6.1
|
||||
* added experimental, integrated TLSv1 server implementation with the
|
||||
needed X.509/ASN.1/RSA/bignum processing (this can be enabled by
|
||||
setting CONFIG_TLS=internal and CONFIG_INTERNAL_LIBTOMMATH=y in
|
||||
.config); this can be useful, e.g., if the target system does not
|
||||
have a suitable TLS library and a minimal code size is required
|
||||
* added support for EAP-FAST server method to the integrated EAP
|
||||
server
|
||||
* updated EAP Generalized Pre-Shared Key (EAP-GPSK) to use the latest
|
||||
draft (draft-ietf-emu-eap-gpsk-07.txt)
|
||||
* added a new configuration parameter, rsn_pairwise, to allow different
|
||||
pairwise cipher suites to be enabled for WPA and RSN/WPA2
|
||||
(note: if wpa_pairwise differs from rsn_pairwise, the driver will
|
||||
either need to support this or will have to use the WPA/RSN IEs from
|
||||
hostapd; currently, the included madwifi and bsd driver interfaces do
|
||||
not have support for this)
|
||||
* updated FT support to use the latest draft, IEEE 802.11r/D8.0
|
||||
|
||||
2007-05-28 - v0.6.0
|
||||
* added experimental IEEE 802.11r/D6.0 support
|
||||
* updated EAP-SAKE to RFC 4763 and the IANA-allocated EAP type 48
|
||||
* updated EAP-PSK to use the IANA-allocated EAP type 47
|
||||
* fixed EAP-PSK bit ordering of the Flags field
|
||||
* fixed configuration reloading (SIGHUP) to re-initialize WPA PSKs
|
||||
by reading wpa_psk_file [Bug 181]
|
||||
* fixed EAP-TTLS AVP parser processing for too short AVP lengths
|
||||
* fixed IPv6 connection to RADIUS accounting server
|
||||
* updated EAP Generalized Pre-Shared Key (EAP-GPSK) to use the latest
|
||||
draft (draft-ietf-emu-eap-gpsk-04.txt)
|
||||
* hlr_auc_gw: read GSM triplet file into memory and rotate through the
|
||||
entries instead of only using the same three triplets every time
|
||||
(this does not work properly with tests using multiple clients, but
|
||||
provides bit better triplet data for testing a single client; anyway,
|
||||
if a better quality triplets are needed, GSM-Milenage should be used
|
||||
instead of hardcoded triplet file)
|
||||
* fixed EAP-MSCHAPv2 server to use a space between S and M parameters
|
||||
in Success Request [Bug 203]
|
||||
* added support for sending EAP-AKA Notifications in error cases
|
||||
* updated to use IEEE 802.11w/D2.0 for management frame protection
|
||||
(still experimental)
|
||||
* RADIUS server: added support for processing duplicate messages
|
||||
(retransmissions from RADIUS client) by replying with the previous
|
||||
reply
|
||||
|
||||
2006-11-24 - v0.5.6
|
||||
* added support for configuring and controlling multiple BSSes per
|
||||
radio interface (bss=<ifname> in hostapd.conf); this is only
|
||||
available with Devicescape and test driver interfaces
|
||||
* fixed PMKSA cache update in the end of successful RSN
|
||||
pre-authentication
|
||||
* added support for dynamic VLAN configuration (i.e., selecting VLAN-ID
|
||||
for each STA based on RADIUS Access-Accept attributes); this requires
|
||||
VLAN support from the kernel driver/802.11 stack and this is
|
||||
currently only available with Devicescape and test driver interfaces
|
||||
* driver_madwifi: fixed configuration of unencrypted modes (plaintext
|
||||
and IEEE 802.1X without WEP)
|
||||
* removed STAKey handshake since PeerKey handshake has replaced it in
|
||||
IEEE 802.11ma and there are no known deployments of STAKey
|
||||
* updated EAP Generalized Pre-Shared Key (EAP-GPSK) to use the latest
|
||||
draft (draft-ietf-emu-eap-gpsk-01.txt)
|
||||
* added preliminary implementation of IEEE 802.11w/D1.0 (management
|
||||
frame protection)
|
||||
(Note: this requires driver support to work properly.)
|
||||
(Note2: IEEE 802.11w is an unapproved draft and subject to change.)
|
||||
* hlr_auc_gw: added support for GSM-Milenage (for EAP-SIM)
|
||||
* hlr_auc_gw: added support for reading per-IMSI Milenage keys and
|
||||
parameters from a text file to make it possible to implement proper
|
||||
GSM/UMTS authentication server for multiple SIM/USIM cards using
|
||||
EAP-SIM/EAP-AKA
|
||||
* fixed session timeout processing with drivers that do not use
|
||||
ieee802_11.c (e.g., madwifi)
|
||||
|
||||
2006-08-27 - v0.5.5
|
||||
* added 'hostapd_cli new_sta <addr>' command for adding a new STA into
|
||||
hostapd (e.g., to initialize wired network authentication based on an
|
||||
external signal)
|
||||
* fixed hostapd to add PMKID KDE into 4-Way Handshake Message 1 when
|
||||
using WPA2 even if PMKSA caching is not used
|
||||
* added -P<pid file> argument for hostapd to write the current process
|
||||
id into a file
|
||||
* added support for RADIUS Authentication Server MIB (RFC 2619)
|
||||
|
||||
2006-06-20 - v0.5.4
|
||||
* fixed nt_password_hash build [Bug 144]
|
||||
* added PeerKey handshake implementation for IEEE 802.11e
|
||||
direct link setup (DLS) to replace STAKey handshake
|
||||
* added support for EAP Generalized Pre-Shared Key (EAP-GPSK,
|
||||
draft-clancy-emu-eap-shared-secret-00.txt)
|
||||
* fixed a segmentation fault when RSN pre-authentication was completed
|
||||
successfully [Bug 152]
|
||||
|
||||
2006-04-27 - v0.5.3
|
||||
* do not build nt_password_hash and hlr_auc_gw by default to avoid
|
||||
requiring a TLS library for a successful build; these programs can be
|
||||
build with 'make nt_password_hash' and 'make hlr_auc_gw'
|
||||
* added a new configuration option, eapol_version, that can be used to
|
||||
set EAPOL version to 1 (default is 2) to work around broken client
|
||||
implementations that drop EAPOL frames which use version number 2
|
||||
[Bug 89]
|
||||
* added support for EAP-SAKE (no EAP method number allocated yet, so
|
||||
this is using the same experimental type 255 as EAP-PSK)
|
||||
* fixed EAP-MSCHAPv2 message length validation
|
||||
|
||||
2006-03-19 - v0.5.2
|
||||
* fixed stdarg use in hostapd_logger(): if both stdout and syslog
|
||||
logging was enabled, hostapd could trigger a segmentation fault in
|
||||
vsyslog on some CPU -- C library combinations
|
||||
* moved HLR/AuC gateway implementation for EAP-SIM/AKA into an external
|
||||
program to make it easier to use for implementing real SS7 gateway;
|
||||
eap_sim_db is not anymore used as a file name for GSM authentication
|
||||
triplets; instead, it is path to UNIX domain socket that will be used
|
||||
to communicate with the external gateway program (e.g., hlr_auc_gw)
|
||||
* added example HLR/AuC gateway implementation, hlr_auc_gw, that uses
|
||||
local information (GSM authentication triplets from a text file and
|
||||
hardcoded AKA authentication data); this can be used to test EAP-SIM
|
||||
and EAP-AKA
|
||||
* added Milenage algorithm (example 3GPP AKA algorithm) to hlr_auc_gw
|
||||
to make it possible to test EAP-AKA with real USIM cards (this is
|
||||
disabled by default; define AKA_USE_MILENAGE when building hlr_auc_gw
|
||||
to enable this)
|
||||
* driver_madwifi: added support for getting station RSN IE from
|
||||
madwifi-ng svn r1453 and newer; this fixes RSN that was apparently
|
||||
broken with earlier change (r1357) in the driver
|
||||
* changed EAP method registration to use a dynamic list of methods
|
||||
instead of a static list generated at build time
|
||||
* fixed WPA message 3/4 not to encrypt Key Data field (WPA IE)
|
||||
[Bug 125]
|
||||
* added ap_max_inactivity configuration parameter
|
||||
|
||||
2006-01-29 - v0.5.1
|
||||
* driver_test: added better support for multiple APs and STAs by using
|
||||
a directory with sockets that include MAC address for each device in
|
||||
the name (test_socket=DIR:/tmp/test)
|
||||
* added support for EAP expanded type (vendor specific EAP methods)
|
||||
|
||||
2005-12-18 - v0.5.0 (beginning of 0.5.x development releases)
|
||||
* added experimental STAKey handshake implementation for IEEE 802.11e
|
||||
direct link setup (DLS); note: this is disabled by default in both
|
||||
build and runtime configuration (can be enabled with CONFIG_STAKEY=y
|
||||
and stakey=1)
|
||||
* added support for EAP methods to use callbacks to external programs
|
||||
by buffering a pending request and processing it after the EAP method
|
||||
is ready to continue
|
||||
* improved EAP-SIM database interface to allow external request to GSM
|
||||
HLR/AuC without blocking hostapd process
|
||||
* added support for using EAP-SIM pseudonyms and fast re-authentication
|
||||
* added support for EAP-AKA in the integrated EAP authenticator
|
||||
* added support for matching EAP identity prefixes (e.g., "1"*) in EAP
|
||||
user database to allow EAP-SIM/AKA selection without extra roundtrip
|
||||
for EAP-Nak negotiation
|
||||
* added support for storing EAP user password as NtPasswordHash instead
|
||||
of plaintext password when using MSCHAP or MSCHAPv2 for
|
||||
authentication (hash:<16-octet hex value>); added nt_password_hash
|
||||
tool for hashing password to generate NtPasswordHash
|
||||
|
||||
2005-11-20 - v0.4.7 (beginning of 0.4.x stable releases)
|
||||
* driver_wired: fixed EAPOL sending to optionally use PAE group address
|
||||
as the destination instead of supplicant MAC address; this is
|
||||
disabled by default, but should be enabled with use_pae_group_addr=1
|
||||
in configuration file if the wired interface is used by only one
|
||||
device at the time (common switch configuration)
|
||||
* driver_madwifi: configure driver to use TKIP countermeasures in order
|
||||
to get correct behavior (IEEE 802.11 association failing; previously,
|
||||
association succeeded, but hostpad forced disassociation immediately)
|
||||
* driver_madwifi: added support for madwifi-ng
|
||||
|
||||
2005-10-27 - v0.4.6
|
||||
* added support for replacing user identity from EAP with RADIUS
|
||||
User-Name attribute from Access-Accept message, if that is included,
|
||||
for the RADIUS accounting messages (e.g., for EAP-PEAP/TTLS to get
|
||||
tunneled identity into accounting messages when the RADIUS server
|
||||
does not support better way of doing this with Class attribute)
|
||||
* driver_madwifi: fixed EAPOL packet receive for configuration where
|
||||
ath# is part of a bridge interface
|
||||
* added a configuration file and log analyzer script for logwatch
|
||||
* fixed EAPOL state machine step function to process all state
|
||||
transitions before processing new events; this resolves a race
|
||||
condition in which EAPOL-Start message could trigger hostapd to send
|
||||
two EAP-Response/Identity frames to the authentication server
|
||||
|
||||
2005-09-25 - v0.4.5
|
||||
* added client CA list to the TLS certificate request in order to make
|
||||
it easier for the client to select which certificate to use
|
||||
* added experimental support for EAP-PSK
|
||||
* added support for WE-19 (hostap, madwifi)
|
||||
|
||||
2005-08-21 - v0.4.4
|
||||
* fixed build without CONFIG_RSN_PREAUTH
|
||||
* fixed FreeBSD build
|
||||
|
||||
2005-06-26 - v0.4.3
|
||||
* fixed PMKSA caching to copy User-Name and Class attributes so that
|
||||
RADIUS accounting gets correct information
|
||||
* start RADIUS accounting only after successful completion of WPA
|
||||
4-Way Handshake if WPA-PSK is used
|
||||
* fixed PMKSA caching for the case where STA (re)associates without
|
||||
first disassociating
|
||||
|
||||
2005-06-12 - v0.4.2
|
||||
* EAP-PAX is now registered as EAP type 46
|
||||
* fixed EAP-PAX MAC calculation
|
||||
* fixed EAP-PAX CK and ICK key derivation
|
||||
* renamed eap_authenticator configuration variable to eap_server to
|
||||
better match with RFC 3748 (EAP) terminology
|
||||
* driver_test: added support for testing hostapd with wpa_supplicant
|
||||
by using test driver interface without any kernel drivers or network
|
||||
cards
|
||||
|
||||
2005-05-22 - v0.4.1
|
||||
* fixed RADIUS server initialization when only auth or acct server
|
||||
is configured and the other one is left empty
|
||||
* driver_madwifi: added support for RADIUS accounting
|
||||
* driver_madwifi: added preliminary support for compiling against 'BSD'
|
||||
branch of madwifi CVS tree
|
||||
* driver_madwifi: fixed pairwise key removal to allow WPA reauth
|
||||
without disassociation
|
||||
* added support for reading additional certificates from PKCS#12 files
|
||||
and adding them to the certificate chain
|
||||
* fixed RADIUS Class attribute processing to only use Access-Accept
|
||||
packets to update Class; previously, other RADIUS authentication
|
||||
packets could have cleared Class attribute
|
||||
* added support for more than one Class attribute in RADIUS packets
|
||||
* added support for verifying certificate revocation list (CRL) when
|
||||
using integrated EAP authenticator for EAP-TLS; new hostapd.conf
|
||||
options 'check_crl'; CRL must be included in the ca_cert file for now
|
||||
|
||||
2005-04-25 - v0.4.0 (beginning of 0.4.x development releases)
|
||||
* added support for including network information into
|
||||
EAP-Request/Identity message (ASCII-0 (nul) in eap_message)
|
||||
(e.g., to implement draft-adrange-eap-network-discovery-07.txt)
|
||||
* fixed a bug which caused some RSN pre-authentication cases to use
|
||||
freed memory and potentially crash hostapd
|
||||
* fixed private key loading for cases where passphrase is not set
|
||||
* added support for sending TLS alerts and aborting authentication
|
||||
when receiving a TLS alert
|
||||
* fixed WPA2 to add PMKSA cache entry when using integrated EAP
|
||||
authenticator
|
||||
* fixed PMKSA caching (EAP authentication was not skipped correctly
|
||||
with the new state machine changes from IEEE 802.1X draft)
|
||||
* added support for RADIUS over IPv6; own_ip_addr, auth_server_addr,
|
||||
and acct_server_addr can now be IPv6 addresses (CONFIG_IPV6=y needs
|
||||
to be added to .config to include IPv6 support); for RADIUS server,
|
||||
radius_server_ipv6=1 needs to be set in hostapd.conf and addresses
|
||||
in RADIUS clients file can then use IPv6 format
|
||||
* added experimental support for EAP-PAX
|
||||
* replaced hostapd control interface library (hostapd_ctrl.[ch]) with
|
||||
the same implementation that wpa_supplicant is using (wpa_ctrl.[ch])
|
||||
|
||||
2005-02-12 - v0.3.7 (beginning of 0.3.x stable releases)
|
||||
|
||||
2005-01-23 - v0.3.5
|
||||
* added support for configuring a forced PEAP version based on the
|
||||
Phase 1 identity
|
||||
* fixed PEAPv1 to use tunneled EAP-Success/Failure instead of EAP-TLV
|
||||
to terminate authentication
|
||||
* fixed EAP identifier duplicate processing with the new IEEE 802.1X
|
||||
draft
|
||||
* clear accounting data in the driver when starting a new accounting
|
||||
session
|
||||
* driver_madwifi: filter wireless events based on ifindex to allow more
|
||||
than one network interface to be used
|
||||
* fixed WPA message 2/4 processing not to cancel timeout for TimeoutEvt
|
||||
setting if the packet does not pass MIC verification (e.g., due to
|
||||
incorrect PSK); previously, message 1/4 was not tried again if an
|
||||
invalid message 2/4 was received
|
||||
* fixed reconfiguration of RADIUS client retransmission timer when
|
||||
adding a new message to the pending list; previously, timer was not
|
||||
updated at this point and if there was a pending message with long
|
||||
time for the next retry, the new message needed to wait that long for
|
||||
its first retry, too
|
||||
|
||||
2005-01-09 - v0.3.4
|
||||
* added support for configuring multiple allowed EAP types for Phase 2
|
||||
authentication (EAP-PEAP, EAP-TTLS)
|
||||
* fixed EAPOL-Start processing to trigger WPA reauthentication
|
||||
(previously, only EAPOL authentication was done)
|
||||
|
||||
2005-01-02 - v0.3.3
|
||||
* added support for EAP-PEAP in the integrated EAP authenticator
|
||||
* added support for EAP-GTC in the integrated EAP authenticator
|
||||
* added support for configuring list of EAP methods for Phase 1 so that
|
||||
the integrated EAP authenticator can, e.g., use the wildcard entry
|
||||
for EAP-TLS and EAP-PEAP
|
||||
* added support for EAP-TTLS in the integrated EAP authenticator
|
||||
* added support for EAP-SIM in the integrated EAP authenticator
|
||||
* added support for using hostapd as a RADIUS authentication server
|
||||
with the integrated EAP authenticator taking care of EAP
|
||||
authentication (new hostapd.conf options: radius_server_clients and
|
||||
radius_server_auth_port); this is not included in default build; use
|
||||
CONFIG_RADIUS_SERVER=y in .config to include
|
||||
|
||||
2004-12-19 - v0.3.2
|
||||
* removed 'daemonize' configuration file option since it has not really
|
||||
been used at all for more than year
|
||||
* driver_madwifi: fixed group key setup and added get_ssid method
|
||||
* added support for EAP-MSCHAPv2 in the integrated EAP authenticator
|
||||
|
||||
2004-12-12 - v0.3.1
|
||||
* added support for integrated EAP-TLS authentication (new hostapd.conf
|
||||
variables: ca_cert, server_cert, private_key, private_key_passwd);
|
||||
this enabled dynamic keying (WPA2/WPA/IEEE 802.1X/WEP) without
|
||||
external RADIUS server
|
||||
* added support for reading PKCS#12 (PFX) files (as a replacement for
|
||||
PEM/DER) to get certificate and private key (CONFIG_PKCS12)
|
||||
|
||||
2004-12-05 - v0.3.0 (beginning of 0.3.x development releases)
|
||||
* added support for Acct-{Input,Output}-Gigawords
|
||||
* added support for Event-Timestamp (in RADIUS Accounting-Requests)
|
||||
* added support for RADIUS Authentication Client MIB (RFC2618)
|
||||
* added support for RADIUS Accounting Client MIB (RFC2620)
|
||||
* made EAP re-authentication period configurable (eap_reauth_period)
|
||||
* fixed EAPOL reauthentication to trigger WPA/WPA2 reauthentication
|
||||
* fixed EAPOL state machine to stop if STA is removed during
|
||||
eapol_sm_step(); this fixes at least one segfault triggering bug with
|
||||
IEEE 802.11i pre-authentication
|
||||
* added support for multiple WPA pre-shared keys (e.g., one for each
|
||||
client MAC address or keys shared by a group of clients);
|
||||
new hostapd.conf field wpa_psk_file for setting path to a text file
|
||||
containing PSKs, see hostapd.wpa_psk for an example
|
||||
* added support for multiple driver interfaces to allow hostapd to be
|
||||
used with other drivers
|
||||
* added wired authenticator driver interface (driver=wired in
|
||||
hostapd.conf, see wired.conf for example configuration)
|
||||
* added madwifi driver interface (driver=madwifi in hostapd.conf, see
|
||||
madwifi.conf for example configuration; Note: include files from
|
||||
madwifi project is needed for building and a configuration file,
|
||||
.config, needs to be created in hostapd directory with
|
||||
CONFIG_DRIVER_MADWIFI=y to include this driver interface in hostapd
|
||||
build)
|
||||
* fixed an alignment issue that could cause SHA-1 to fail on some
|
||||
platforms (e.g., Intel ixp425 with a compiler that does not 32-bit
|
||||
align variables)
|
||||
* fixed RADIUS reconnection after an error in sending interim
|
||||
accounting packets
|
||||
* added hostapd control interface for external programs and an example
|
||||
CLI, hostapd_cli (like wpa_cli for wpa_supplicant)
|
||||
* started adding dot11, dot1x, radius MIBs ('hostapd_cli mib',
|
||||
'hostapd_cli sta <addr>')
|
||||
* finished update from IEEE 802.1X-2001 to IEEE 802.1X-REV (now d11)
|
||||
* added support for strict GTK rekeying (wpa_strict_rekey in
|
||||
hostapd.conf)
|
||||
* updated IAPP to use UDP port 3517 and multicast address 224.0.1.178
|
||||
(instead of broadcast) for IAPP ADD-notify (moved from draft 3 to
|
||||
IEEE 802.11F-2003)
|
||||
* added Prism54 driver interface (driver=prism54 in hostapd.conf;
|
||||
note: .config needs to be created in hostapd directory with
|
||||
CONFIG_DRIVER_PRISM54=y to include this driver interface in hostapd
|
||||
build)
|
||||
* dual-licensed hostapd (GPLv2 and BSD licenses)
|
||||
* fixed RADIUS accounting to generate a new session id for cases where
|
||||
a station reassociates without first being complete deauthenticated
|
||||
* fixed STA disassociation handler to mark next timeout state to
|
||||
deauthenticate the station, i.e., skip long wait for inactivity poll
|
||||
and extra disassociation, if the STA disassociates without
|
||||
deauthenticating
|
||||
* added integrated EAP authenticator that can be used instead of
|
||||
external RADIUS authentication server; currently, only EAP-MD5 is
|
||||
supported, so this cannot yet be used for key distribution; the EAP
|
||||
method interface is generic, though, so adding new EAP methods should
|
||||
be straightforward; new hostapd.conf variables: 'eap_authenticator'
|
||||
and 'eap_user_file'; this obsoletes "minimal authentication server"
|
||||
('minimal_eap' in hostapd.conf) which is now removed
|
||||
* added support for FreeBSD and driver interface for the BSD net80211
|
||||
layer (driver=bsd in hostapd.conf and CONFIG_DRIVER_BSD=y in
|
||||
.config); please note that some of the required kernel mods have not
|
||||
yet been committed
|
||||
|
||||
2004-07-17 - v0.2.4 (beginning of 0.2.x stable releases)
|
||||
* fixed some accounting cases where Accounting-Start was sent when
|
||||
IEEE 802.1X port was being deauthorized
|
||||
|
||||
2004-06-20 - v0.2.3
|
||||
* modified RADIUS client to re-connect the socket in case of certain
|
||||
error codes that are generated when a network interface state is
|
||||
changes (e.g., when IP address changes or the interface is set UP)
|
||||
* fixed couple of cases where EAPOL state for a station was freed
|
||||
twice causing a segfault for hostapd
|
||||
* fixed couple of bugs in processing WPA deauthentication (freed data
|
||||
was used)
|
||||
|
||||
2004-05-31 - v0.2.2
|
||||
* fixed WPA/WPA2 group rekeying to use key index correctly (GN/GM)
|
||||
* fixed group rekeying to send zero TSC in EAPOL-Key messages to fix
|
||||
cases where STAs dropped multicast frames as replay attacks
|
||||
* added support for copying RADIUS Attribute 'Class' from
|
||||
authentication messages into accounting messages
|
||||
* send canned EAP failure if RADIUS server sends Access-Reject without
|
||||
EAP message (previously, Supplicant was not notified in this case)
|
||||
* fixed mixed WPA-PSK and WPA-EAP mode to work with WPA-PSK (i.e., do
|
||||
not start EAPOL state machines if the STA selected to use WPA-PSK)
|
||||
|
||||
2004-05-06 - v0.2.1
|
||||
* added WPA and IEEE 802.11i/RSN (WPA2) Authenticator functionality
|
||||
- based on IEEE 802.11i/D10.0 but modified to interoperate with WPA
|
||||
(i.e., IEEE 802.11i/D3.0)
|
||||
- supports WPA-only, RSN-only, and mixed WPA/RSN mode
|
||||
- both WPA-PSK and WPA-RADIUS/EAP are supported
|
||||
- PMKSA caching and pre-authentication
|
||||
- new hostapd.conf variables: wpa, wpa_psk, wpa_passphrase,
|
||||
wpa_key_mgmt, wpa_pairwise, wpa_group_rekey, wpa_gmk_rekey,
|
||||
rsn_preauth, rsn_preauth_interfaces
|
||||
* fixed interim accounting to remove any pending accounting messages
|
||||
to the STA before sending a new one
|
||||
|
||||
2004-02-15 - v0.2.0
|
||||
* added support for Acct-Interim-Interval:
|
||||
- draft-ietf-radius-acct-interim-01.txt
|
||||
- use Acct-Interim-Interval attribute from Access-Accept if local
|
||||
'radius_acct_interim_interval' is not set
|
||||
- allow different update intervals for each STA
|
||||
* fixed event loop to call signal handlers only after returning from
|
||||
the real signal handler
|
||||
* reset sta->timeout_next after successful association to make sure
|
||||
that the previously registered inactivity timer will not remove the
|
||||
STA immediately (e.g., if STA deauthenticates and re-associates
|
||||
before the timer is triggered).
|
||||
* added new hostapd.conf variable, nas_identifier, that can be used to
|
||||
add an optional RADIUS Attribute, NAS-Identifier, into authentication
|
||||
and accounting messages
|
||||
* added support for Accounting-On and Accounting-Off messages
|
||||
* fixed accounting session handling to send Accounting-Start only once
|
||||
per session and not to send Accounting-Stop if the session was not
|
||||
initialized properly
|
||||
* fixed Accounting-Stop statistics in cases where the message was
|
||||
previously sent after the kernel entry for the STA (and/or IEEE
|
||||
802.1X data) was removed
|
||||
|
||||
|
||||
Note:
|
||||
|
||||
Older changes up to and including v0.1.0 are included in the ChangeLog
|
||||
of the Host AP driver.
|
836
hostapd-0.8/hostapd/Makefile
Normal file
836
hostapd-0.8/hostapd/Makefile
Normal file
|
@ -0,0 +1,836 @@
|
|||
ifndef CC
|
||||
CC=gcc
|
||||
endif
|
||||
|
||||
ifndef CFLAGS
|
||||
CFLAGS = -MMD -O2 -Wall -g
|
||||
endif
|
||||
|
||||
CFLAGS += -I../src
|
||||
CFLAGS += -I../src/utils
|
||||
|
||||
# Uncomment following line and set the path to your kernel tree include
|
||||
# directory if your C library does not include all header files.
|
||||
# CFLAGS += -DUSE_KERNEL_HEADERS -I/usr/src/linux/include
|
||||
|
||||
-include .config
|
||||
|
||||
ifndef CONFIG_OS
|
||||
ifdef CONFIG_NATIVE_WINDOWS
|
||||
CONFIG_OS=win32
|
||||
else
|
||||
CONFIG_OS=unix
|
||||
endif
|
||||
endif
|
||||
|
||||
ifeq ($(CONFIG_OS), internal)
|
||||
CFLAGS += -DOS_NO_C_LIB_DEFINES
|
||||
endif
|
||||
|
||||
ifdef CONFIG_NATIVE_WINDOWS
|
||||
CFLAGS += -DCONFIG_NATIVE_WINDOWS
|
||||
LIBS += -lws2_32
|
||||
endif
|
||||
|
||||
OBJS += main.o
|
||||
OBJS += config_file.o
|
||||
|
||||
OBJS += ../src/ap/hostapd.o
|
||||
OBJS += ../src/ap/wpa_auth_glue.o
|
||||
OBJS += ../src/ap/drv_callbacks.o
|
||||
OBJS += ../src/ap/ap_drv_ops.o
|
||||
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/ieee802_11_auth.o
|
||||
OBJS += ../src/ap/sta_info.o
|
||||
OBJS += ../src/ap/wpa_auth.o
|
||||
OBJS += ../src/ap/tkip_countermeasures.o
|
||||
OBJS += ../src/ap/ap_mlme.o
|
||||
OBJS += ../src/ap/wpa_auth_ie.o
|
||||
OBJS += ../src/ap/preauth_auth.o
|
||||
OBJS += ../src/ap/pmksa_cache_auth.o
|
||||
|
||||
NEED_RC4=y
|
||||
NEED_AES=y
|
||||
NEED_MD5=y
|
||||
NEED_SHA1=y
|
||||
|
||||
OBJS += ../src/drivers/drivers.o
|
||||
CFLAGS += -DHOSTAPD
|
||||
|
||||
ifdef CONFIG_WPA_TRACE
|
||||
CFLAGS += -DWPA_TRACE
|
||||
OBJS += ../src/utils/trace.o
|
||||
HOBJS += ../src/utils/trace.o
|
||||
LDFLAGS += -rdynamic
|
||||
CFLAGS += -funwind-tables
|
||||
ifdef CONFIG_WPA_TRACE_BFD
|
||||
CFLAGS += -DWPA_TRACE_BFD
|
||||
LIBS += -lbfd
|
||||
LIBS_c += -lbfd
|
||||
LIBS_h += -lbfd
|
||||
endif
|
||||
endif
|
||||
|
||||
OBJS += ../src/utils/eloop.o
|
||||
OBJS += ../src/utils/common.o
|
||||
OBJS += ../src/utils/wpa_debug.o
|
||||
OBJS += ../src/utils/wpabuf.o
|
||||
OBJS += ../src/utils/os_$(CONFIG_OS).o
|
||||
OBJS += ../src/utils/ip_addr.o
|
||||
|
||||
OBJS += ../src/common/ieee802_11_common.o
|
||||
OBJS += ../src/common/wpa_common.o
|
||||
|
||||
OBJS += ../src/eapol_auth/eapol_auth_sm.o
|
||||
|
||||
|
||||
ifndef CONFIG_NO_DUMP_STATE
|
||||
# define HOSTAPD_DUMP_STATE to include SIGUSR1 handler for dumping state to
|
||||
# a file (undefine it, if you want to save in binary size)
|
||||
CFLAGS += -DHOSTAPD_DUMP_STATE
|
||||
OBJS += dump_state.o
|
||||
OBJS += ../src/eapol_auth/eapol_auth_dump.o
|
||||
endif
|
||||
|
||||
ifdef CONFIG_NO_RADIUS
|
||||
CFLAGS += -DCONFIG_NO_RADIUS
|
||||
CONFIG_NO_ACCOUNTING=y
|
||||
else
|
||||
OBJS += ../src/radius/radius.o
|
||||
OBJS += ../src/radius/radius_client.o
|
||||
endif
|
||||
|
||||
ifdef CONFIG_NO_ACCOUNTING
|
||||
CFLAGS += -DCONFIG_NO_ACCOUNTING
|
||||
else
|
||||
OBJS += ../src/ap/accounting.o
|
||||
endif
|
||||
|
||||
ifdef CONFIG_NO_VLAN
|
||||
CFLAGS += -DCONFIG_NO_VLAN
|
||||
else
|
||||
OBJS += ../src/ap/vlan_init.o
|
||||
endif
|
||||
|
||||
ifdef CONFIG_NO_CTRL_IFACE
|
||||
CFLAGS += -DCONFIG_NO_CTRL_IFACE
|
||||
else
|
||||
OBJS += ctrl_iface.o
|
||||
OBJS += ../src/ap/ctrl_iface_ap.o
|
||||
endif
|
||||
|
||||
OBJS += ../src/crypto/md5.o
|
||||
|
||||
CFLAGS += -DCONFIG_CTRL_IFACE -DCONFIG_CTRL_IFACE_UNIX
|
||||
|
||||
ifdef CONFIG_IAPP
|
||||
CFLAGS += -DCONFIG_IAPP
|
||||
OBJS += ../src/ap/iapp.o
|
||||
endif
|
||||
|
||||
ifdef CONFIG_RSN_PREAUTH
|
||||
CFLAGS += -DCONFIG_RSN_PREAUTH
|
||||
CONFIG_L2_PACKET=y
|
||||
endif
|
||||
|
||||
ifdef CONFIG_PEERKEY
|
||||
CFLAGS += -DCONFIG_PEERKEY
|
||||
OBJS += ../src/ap/peerkey_auth.o
|
||||
endif
|
||||
|
||||
ifdef CONFIG_IEEE80211W
|
||||
CFLAGS += -DCONFIG_IEEE80211W
|
||||
NEED_SHA256=y
|
||||
NEED_AES_OMAC1=y
|
||||
endif
|
||||
|
||||
ifdef CONFIG_IEEE80211R
|
||||
CFLAGS += -DCONFIG_IEEE80211R
|
||||
OBJS += ../src/ap/wpa_auth_ft.o
|
||||
NEED_SHA256=y
|
||||
NEED_AES_OMAC1=y
|
||||
NEED_AES_UNWRAP=y
|
||||
endif
|
||||
|
||||
ifdef CONFIG_IEEE80211N
|
||||
CFLAGS += -DCONFIG_IEEE80211N
|
||||
endif
|
||||
|
||||
include ../src/drivers/drivers.mak
|
||||
OBJS += $(DRV_AP_OBJS)
|
||||
CFLAGS += $(DRV_AP_CFLAGS)
|
||||
LDFLAGS += $(DRV_AP_LDFLAGS)
|
||||
LIBS += $(DRV_AP_LIBS)
|
||||
|
||||
ifdef CONFIG_L2_PACKET
|
||||
ifdef CONFIG_DNET_PCAP
|
||||
ifdef CONFIG_L2_FREEBSD
|
||||
LIBS += -lpcap
|
||||
OBJS += ../src/l2_packet/l2_packet_freebsd.o
|
||||
else
|
||||
LIBS += -ldnet -lpcap
|
||||
OBJS += ../src/l2_packet/l2_packet_pcap.o
|
||||
endif
|
||||
else
|
||||
OBJS += ../src/l2_packet/l2_packet_linux.o
|
||||
endif
|
||||
else
|
||||
OBJS += ../src/l2_packet/l2_packet_none.o
|
||||
endif
|
||||
|
||||
|
||||
ifdef CONFIG_EAP_MD5
|
||||
CFLAGS += -DEAP_SERVER_MD5
|
||||
OBJS += ../src/eap_server/eap_server_md5.o
|
||||
CHAP=y
|
||||
endif
|
||||
|
||||
ifdef CONFIG_EAP_TLS
|
||||
CFLAGS += -DEAP_SERVER_TLS
|
||||
OBJS += ../src/eap_server/eap_server_tls.o
|
||||
TLS_FUNCS=y
|
||||
endif
|
||||
|
||||
ifdef CONFIG_EAP_PEAP
|
||||
CFLAGS += -DEAP_SERVER_PEAP
|
||||
OBJS += ../src/eap_server/eap_server_peap.o
|
||||
OBJS += ../src/eap_common/eap_peap_common.o
|
||||
TLS_FUNCS=y
|
||||
CONFIG_EAP_MSCHAPV2=y
|
||||
endif
|
||||
|
||||
ifdef CONFIG_EAP_TTLS
|
||||
CFLAGS += -DEAP_SERVER_TTLS
|
||||
OBJS += ../src/eap_server/eap_server_ttls.o
|
||||
TLS_FUNCS=y
|
||||
CHAP=y
|
||||
endif
|
||||
|
||||
ifdef CONFIG_EAP_MSCHAPV2
|
||||
CFLAGS += -DEAP_SERVER_MSCHAPV2
|
||||
OBJS += ../src/eap_server/eap_server_mschapv2.o
|
||||
MS_FUNCS=y
|
||||
endif
|
||||
|
||||
ifdef CONFIG_EAP_GTC
|
||||
CFLAGS += -DEAP_SERVER_GTC
|
||||
OBJS += ../src/eap_server/eap_server_gtc.o
|
||||
endif
|
||||
|
||||
ifdef CONFIG_EAP_SIM
|
||||
CFLAGS += -DEAP_SERVER_SIM
|
||||
OBJS += ../src/eap_server/eap_server_sim.o
|
||||
CONFIG_EAP_SIM_COMMON=y
|
||||
NEED_AES_CBC=y
|
||||
endif
|
||||
|
||||
ifdef CONFIG_EAP_AKA
|
||||
CFLAGS += -DEAP_SERVER_AKA
|
||||
OBJS += ../src/eap_server/eap_server_aka.o
|
||||
CONFIG_EAP_SIM_COMMON=y
|
||||
NEED_SHA256=y
|
||||
NEED_AES_CBC=y
|
||||
endif
|
||||
|
||||
ifdef CONFIG_EAP_AKA_PRIME
|
||||
CFLAGS += -DEAP_SERVER_AKA_PRIME
|
||||
endif
|
||||
|
||||
ifdef CONFIG_EAP_SIM_COMMON
|
||||
OBJS += ../src/eap_common/eap_sim_common.o
|
||||
# Example EAP-SIM/AKA interface for GSM/UMTS authentication. This can be
|
||||
# replaced with another file implementating the interface specified in
|
||||
# eap_sim_db.h.
|
||||
OBJS += ../src/eap_server/eap_sim_db.o
|
||||
NEED_FIPS186_2_PRF=y
|
||||
endif
|
||||
|
||||
ifdef CONFIG_EAP_PAX
|
||||
CFLAGS += -DEAP_SERVER_PAX
|
||||
OBJS += ../src/eap_server/eap_server_pax.o ../src/eap_common/eap_pax_common.o
|
||||
endif
|
||||
|
||||
ifdef CONFIG_EAP_PSK
|
||||
CFLAGS += -DEAP_SERVER_PSK
|
||||
OBJS += ../src/eap_server/eap_server_psk.o ../src/eap_common/eap_psk_common.o
|
||||
NEED_AES_OMAC1=y
|
||||
NEED_AES_ENCBLOCK=y
|
||||
NEED_AES_EAX=y
|
||||
endif
|
||||
|
||||
ifdef CONFIG_EAP_SAKE
|
||||
CFLAGS += -DEAP_SERVER_SAKE
|
||||
OBJS += ../src/eap_server/eap_server_sake.o ../src/eap_common/eap_sake_common.o
|
||||
endif
|
||||
|
||||
ifdef CONFIG_EAP_GPSK
|
||||
CFLAGS += -DEAP_SERVER_GPSK
|
||||
OBJS += ../src/eap_server/eap_server_gpsk.o ../src/eap_common/eap_gpsk_common.o
|
||||
ifdef CONFIG_EAP_GPSK_SHA256
|
||||
CFLAGS += -DEAP_SERVER_GPSK_SHA256
|
||||
endif
|
||||
NEED_SHA256=y
|
||||
NEED_AES_OMAC1=y
|
||||
endif
|
||||
|
||||
ifdef CONFIG_EAP_PWD
|
||||
CFLAGS += -DEAP_SERVER_PWD
|
||||
OBJS += ../src/eap_server/eap_server_pwd.o ../src/eap_common/eap_pwd_common.o
|
||||
NEED_SHA256=y
|
||||
endif
|
||||
|
||||
ifdef CONFIG_EAP_VENDOR_TEST
|
||||
CFLAGS += -DEAP_SERVER_VENDOR_TEST
|
||||
OBJS += ../src/eap_server/eap_server_vendor_test.o
|
||||
endif
|
||||
|
||||
ifdef CONFIG_EAP_FAST
|
||||
CFLAGS += -DEAP_SERVER_FAST
|
||||
OBJS += ../src/eap_server/eap_server_fast.o
|
||||
OBJS += ../src/eap_common/eap_fast_common.o
|
||||
TLS_FUNCS=y
|
||||
NEED_T_PRF=y
|
||||
NEED_AES_UNWRAP=y
|
||||
endif
|
||||
|
||||
ifdef CONFIG_WPS
|
||||
ifdef CONFIG_WPS2
|
||||
CFLAGS += -DCONFIG_WPS2
|
||||
endif
|
||||
|
||||
CFLAGS += -DCONFIG_WPS -DEAP_SERVER_WSC
|
||||
OBJS += ../src/utils/uuid.o
|
||||
OBJS += ../src/ap/wps_hostapd.o
|
||||
OBJS += ../src/eap_server/eap_server_wsc.o ../src/eap_common/eap_wsc_common.o
|
||||
OBJS += ../src/wps/wps.o
|
||||
OBJS += ../src/wps/wps_common.o
|
||||
OBJS += ../src/wps/wps_attr_parse.o
|
||||
OBJS += ../src/wps/wps_attr_build.o
|
||||
OBJS += ../src/wps/wps_attr_process.o
|
||||
OBJS += ../src/wps/wps_dev_attr.o
|
||||
OBJS += ../src/wps/wps_enrollee.o
|
||||
OBJS += ../src/wps/wps_registrar.o
|
||||
NEED_DH_GROUPS=y
|
||||
NEED_SHA256=y
|
||||
NEED_BASE64=y
|
||||
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
|
||||
CFLAGS += -DCONFIG_WPS_OOB
|
||||
endif
|
||||
|
||||
ifdef CONFIG_WPS_UPNP
|
||||
CFLAGS += -DCONFIG_WPS_UPNP
|
||||
OBJS += ../src/wps/wps_upnp.o
|
||||
OBJS += ../src/wps/wps_upnp_ssdp.o
|
||||
OBJS += ../src/wps/wps_upnp_web.o
|
||||
OBJS += ../src/wps/wps_upnp_event.o
|
||||
OBJS += ../src/wps/wps_upnp_ap.o
|
||||
OBJS += ../src/wps/upnp_xml.o
|
||||
OBJS += ../src/wps/httpread.o
|
||||
OBJS += ../src/wps/http_client.o
|
||||
OBJS += ../src/wps/http_server.o
|
||||
endif
|
||||
|
||||
ifdef CONFIG_WPS_STRICT
|
||||
CFLAGS += -DCONFIG_WPS_STRICT
|
||||
OBJS += ../src/wps/wps_validate.o
|
||||
endif
|
||||
|
||||
ifdef CONFIG_WPS_TESTING
|
||||
CFLAGS += -DCONFIG_WPS_TESTING
|
||||
endif
|
||||
|
||||
endif
|
||||
|
||||
ifdef CONFIG_EAP_IKEV2
|
||||
CFLAGS += -DEAP_SERVER_IKEV2
|
||||
OBJS += ../src/eap_server/eap_server_ikev2.o ../src/eap_server/ikev2.o
|
||||
OBJS += ../src/eap_common/eap_ikev2_common.o ../src/eap_common/ikev2_common.o
|
||||
NEED_DH_GROUPS=y
|
||||
NEED_DH_GROUPS_ALL=y
|
||||
NEED_MODEXP=y
|
||||
NEED_CIPHER=y
|
||||
endif
|
||||
|
||||
ifdef CONFIG_EAP_TNC
|
||||
CFLAGS += -DEAP_SERVER_TNC
|
||||
OBJS += ../src/eap_server/eap_server_tnc.o
|
||||
OBJS += ../src/eap_server/tncs.o
|
||||
NEED_BASE64=y
|
||||
ifndef CONFIG_DRIVER_BSD
|
||||
LIBS += -ldl
|
||||
endif
|
||||
endif
|
||||
|
||||
# Basic EAP functionality is needed for EAPOL
|
||||
OBJS += eap_register.o
|
||||
OBJS += ../src/eap_server/eap_server.o
|
||||
OBJS += ../src/eap_common/eap_common.o
|
||||
OBJS += ../src/eap_server/eap_server_methods.o
|
||||
OBJS += ../src/eap_server/eap_server_identity.o
|
||||
CFLAGS += -DEAP_SERVER_IDENTITY
|
||||
|
||||
ifdef CONFIG_EAP
|
||||
CFLAGS += -DEAP_SERVER
|
||||
endif
|
||||
|
||||
ifdef CONFIG_PKCS12
|
||||
CFLAGS += -DPKCS12_FUNCS
|
||||
endif
|
||||
|
||||
ifdef MS_FUNCS
|
||||
OBJS += ../src/crypto/ms_funcs.o
|
||||
NEED_DES=y
|
||||
NEED_MD4=y
|
||||
endif
|
||||
|
||||
ifdef CHAP
|
||||
OBJS += ../src/eap_common/chap.o
|
||||
endif
|
||||
|
||||
ifdef TLS_FUNCS
|
||||
NEED_DES=y
|
||||
# Shared TLS functions (needed for EAP_TLS, EAP_PEAP, and EAP_TTLS)
|
||||
CFLAGS += -DEAP_TLS_FUNCS
|
||||
OBJS += ../src/eap_server/eap_server_tls_common.o
|
||||
NEED_TLS_PRF=y
|
||||
endif
|
||||
|
||||
ifndef CONFIG_TLS
|
||||
CONFIG_TLS=openssl
|
||||
endif
|
||||
|
||||
ifeq ($(CONFIG_TLS), openssl)
|
||||
ifdef TLS_FUNCS
|
||||
OBJS += ../src/crypto/tls_openssl.o
|
||||
LIBS += -lssl
|
||||
endif
|
||||
OBJS += ../src/crypto/crypto_openssl.o
|
||||
HOBJS += ../src/crypto/crypto_openssl.o
|
||||
ifdef NEED_FIPS186_2_PRF
|
||||
OBJS += ../src/crypto/fips_prf_openssl.o
|
||||
endif
|
||||
LIBS += -lcrypto
|
||||
LIBS_h += -lcrypto
|
||||
endif
|
||||
|
||||
ifeq ($(CONFIG_TLS), gnutls)
|
||||
ifdef TLS_FUNCS
|
||||
OBJS += ../src/crypto/tls_gnutls.o
|
||||
LIBS += -lgnutls -lgpg-error
|
||||
ifdef CONFIG_GNUTLS_EXTRA
|
||||
CFLAGS += -DCONFIG_GNUTLS_EXTRA
|
||||
LIBS += -lgnutls-extra
|
||||
endif
|
||||
endif
|
||||
OBJS += ../src/crypto/crypto_gnutls.o
|
||||
HOBJS += ../src/crypto/crypto_gnutls.o
|
||||
ifdef NEED_FIPS186_2_PRF
|
||||
OBJS += ../src/crypto/fips_prf_gnutls.o
|
||||
endif
|
||||
LIBS += -lgcrypt
|
||||
LIBS_h += -lgcrypt
|
||||
CONFIG_INTERNAL_SHA256=y
|
||||
CONFIG_INTERNAL_RC4=y
|
||||
CONFIG_INTERNAL_DH_GROUP5=y
|
||||
endif
|
||||
|
||||
ifeq ($(CONFIG_TLS), schannel)
|
||||
ifdef TLS_FUNCS
|
||||
OBJS += ../src/crypto/tls_schannel.o
|
||||
endif
|
||||
OBJS += ../src/crypto/crypto_cryptoapi.o
|
||||
OBJS_p += ../src/crypto/crypto_cryptoapi.o
|
||||
CONFIG_INTERNAL_SHA256=y
|
||||
CONFIG_INTERNAL_RC4=y
|
||||
CONFIG_INTERNAL_DH_GROUP5=y
|
||||
endif
|
||||
|
||||
ifeq ($(CONFIG_TLS), nss)
|
||||
ifdef TLS_FUNCS
|
||||
OBJS += ../src/crypto/tls_nss.o
|
||||
LIBS += -lssl3
|
||||
endif
|
||||
OBJS += ../src/crypto/crypto_nss.o
|
||||
ifdef NEED_FIPS186_2_PRF
|
||||
OBJS += ../src/crypto/fips_prf_nss.o
|
||||
endif
|
||||
LIBS += -lnss3
|
||||
LIBS_h += -lnss3
|
||||
CONFIG_INTERNAL_MD4=y
|
||||
CONFIG_INTERNAL_DH_GROUP5=y
|
||||
endif
|
||||
|
||||
ifeq ($(CONFIG_TLS), internal)
|
||||
ifndef CONFIG_CRYPTO
|
||||
CONFIG_CRYPTO=internal
|
||||
endif
|
||||
ifdef TLS_FUNCS
|
||||
OBJS += ../src/crypto/crypto_internal-rsa.o
|
||||
OBJS += ../src/crypto/tls_internal.o
|
||||
OBJS += ../src/tls/tlsv1_common.o
|
||||
OBJS += ../src/tls/tlsv1_record.o
|
||||
OBJS += ../src/tls/tlsv1_cred.o
|
||||
OBJS += ../src/tls/tlsv1_server.o
|
||||
OBJS += ../src/tls/tlsv1_server_write.o
|
||||
OBJS += ../src/tls/tlsv1_server_read.o
|
||||
OBJS += ../src/tls/asn1.o
|
||||
OBJS += ../src/tls/rsa.o
|
||||
OBJS += ../src/tls/x509v3.o
|
||||
OBJS += ../src/tls/pkcs1.o
|
||||
OBJS += ../src/tls/pkcs5.o
|
||||
OBJS += ../src/tls/pkcs8.o
|
||||
NEED_SHA256=y
|
||||
NEED_BASE64=y
|
||||
NEED_TLS_PRF=y
|
||||
NEED_MODEXP=y
|
||||
NEED_CIPHER=y
|
||||
CFLAGS += -DCONFIG_TLS_INTERNAL
|
||||
CFLAGS += -DCONFIG_TLS_INTERNAL_SERVER
|
||||
endif
|
||||
ifdef NEED_CIPHER
|
||||
NEED_DES=y
|
||||
OBJS += ../src/crypto/crypto_internal-cipher.o
|
||||
endif
|
||||
ifdef NEED_MODEXP
|
||||
OBJS += ../src/crypto/crypto_internal-modexp.o
|
||||
OBJS += ../src/tls/bignum.o
|
||||
endif
|
||||
ifeq ($(CONFIG_CRYPTO), libtomcrypt)
|
||||
OBJS += ../src/crypto/crypto_libtomcrypt.o
|
||||
LIBS += -ltomcrypt -ltfm
|
||||
LIBS_h += -ltomcrypt -ltfm
|
||||
CONFIG_INTERNAL_SHA256=y
|
||||
CONFIG_INTERNAL_RC4=y
|
||||
CONFIG_INTERNAL_DH_GROUP5=y
|
||||
endif
|
||||
ifeq ($(CONFIG_CRYPTO), internal)
|
||||
OBJS += ../src/crypto/crypto_internal.o
|
||||
NEED_AES_DEC=y
|
||||
CFLAGS += -DCONFIG_CRYPTO_INTERNAL
|
||||
ifdef CONFIG_INTERNAL_LIBTOMMATH
|
||||
CFLAGS += -DCONFIG_INTERNAL_LIBTOMMATH
|
||||
ifdef CONFIG_INTERNAL_LIBTOMMATH_FAST
|
||||
CFLAGS += -DLTM_FAST
|
||||
endif
|
||||
else
|
||||
LIBS += -ltommath
|
||||
LIBS_h += -ltommath
|
||||
endif
|
||||
CONFIG_INTERNAL_AES=y
|
||||
CONFIG_INTERNAL_DES=y
|
||||
CONFIG_INTERNAL_SHA1=y
|
||||
CONFIG_INTERNAL_MD4=y
|
||||
CONFIG_INTERNAL_MD5=y
|
||||
CONFIG_INTERNAL_SHA256=y
|
||||
CONFIG_INTERNAL_RC4=y
|
||||
CONFIG_INTERNAL_DH_GROUP5=y
|
||||
endif
|
||||
ifeq ($(CONFIG_CRYPTO), cryptoapi)
|
||||
OBJS += ../src/crypto/crypto_cryptoapi.o
|
||||
OBJS_p += ../src/crypto/crypto_cryptoapi.o
|
||||
CFLAGS += -DCONFIG_CRYPTO_CRYPTOAPI
|
||||
CONFIG_INTERNAL_SHA256=y
|
||||
CONFIG_INTERNAL_RC4=y
|
||||
endif
|
||||
endif
|
||||
|
||||
ifeq ($(CONFIG_TLS), none)
|
||||
ifdef TLS_FUNCS
|
||||
OBJS += ../src/crypto/tls_none.o
|
||||
CFLAGS += -DEAP_TLS_NONE
|
||||
CONFIG_INTERNAL_AES=y
|
||||
CONFIG_INTERNAL_SHA1=y
|
||||
CONFIG_INTERNAL_MD5=y
|
||||
endif
|
||||
OBJS += ../src/crypto/crypto_none.o
|
||||
OBJS_p += ../src/crypto/crypto_none.o
|
||||
CONFIG_INTERNAL_SHA256=y
|
||||
CONFIG_INTERNAL_RC4=y
|
||||
endif
|
||||
|
||||
ifndef TLS_FUNCS
|
||||
OBJS += ../src/crypto/tls_none.o
|
||||
ifeq ($(CONFIG_TLS), internal)
|
||||
CONFIG_INTERNAL_AES=y
|
||||
CONFIG_INTERNAL_SHA1=y
|
||||
CONFIG_INTERNAL_MD5=y
|
||||
CONFIG_INTERNAL_RC4=y
|
||||
endif
|
||||
endif
|
||||
|
||||
AESOBJS = # none so far
|
||||
ifdef CONFIG_INTERNAL_AES
|
||||
AESOBJS += ../src/crypto/aes-internal.o ../src/crypto/aes-internal-enc.o
|
||||
endif
|
||||
|
||||
AESOBJS += ../src/crypto/aes-wrap.o
|
||||
ifdef NEED_AES_EAX
|
||||
AESOBJS += ../src/crypto/aes-eax.o
|
||||
NEED_AES_CTR=y
|
||||
endif
|
||||
ifdef NEED_AES_CTR
|
||||
AESOBJS += ../src/crypto/aes-ctr.o
|
||||
endif
|
||||
ifdef NEED_AES_ENCBLOCK
|
||||
AESOBJS += ../src/crypto/aes-encblock.o
|
||||
endif
|
||||
ifdef NEED_AES_OMAC1
|
||||
AESOBJS += ../src/crypto/aes-omac1.o
|
||||
endif
|
||||
ifdef NEED_AES_UNWRAP
|
||||
NEED_AES_DEC=y
|
||||
AESOBJS += ../src/crypto/aes-unwrap.o
|
||||
endif
|
||||
ifdef NEED_AES_CBC
|
||||
NEED_AES_DEC=y
|
||||
AESOBJS += ../src/crypto/aes-cbc.o
|
||||
endif
|
||||
ifdef NEED_AES_DEC
|
||||
ifdef CONFIG_INTERNAL_AES
|
||||
AESOBJS += ../src/crypto/aes-internal-dec.o
|
||||
endif
|
||||
endif
|
||||
ifdef NEED_AES
|
||||
OBJS += $(AESOBJS)
|
||||
endif
|
||||
|
||||
ifdef NEED_SHA1
|
||||
SHA1OBJS += ../src/crypto/sha1.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
|
||||
SHA1OBJS += ../src/crypto/sha1-pbkdf2.o
|
||||
ifdef NEED_T_PRF
|
||||
SHA1OBJS += ../src/crypto/sha1-tprf.o
|
||||
endif
|
||||
ifdef NEED_TLS_PRF
|
||||
SHA1OBJS += ../src/crypto/sha1-tlsprf.o
|
||||
endif
|
||||
endif
|
||||
|
||||
ifdef NEED_SHA1
|
||||
OBJS += $(SHA1OBJS)
|
||||
endif
|
||||
|
||||
ifdef NEED_MD5
|
||||
ifdef CONFIG_INTERNAL_MD5
|
||||
OBJS += ../src/crypto/md5-internal.o
|
||||
HOBJS += ../src/crypto/md5-internal.o
|
||||
endif
|
||||
endif
|
||||
|
||||
ifdef NEED_MD4
|
||||
ifdef CONFIG_INTERNAL_MD4
|
||||
OBJS += ../src/crypto/md4-internal.o
|
||||
endif
|
||||
endif
|
||||
|
||||
ifdef NEED_DES
|
||||
ifdef CONFIG_INTERNAL_DES
|
||||
OBJS += ../src/crypto/des-internal.o
|
||||
endif
|
||||
endif
|
||||
|
||||
ifdef NEED_RC4
|
||||
ifdef CONFIG_INTERNAL_RC4
|
||||
OBJS += ../src/crypto/rc4.o
|
||||
endif
|
||||
endif
|
||||
|
||||
ifdef NEED_SHA256
|
||||
OBJS += ../src/crypto/sha256.o
|
||||
ifdef CONFIG_INTERNAL_SHA256
|
||||
OBJS += ../src/crypto/sha256-internal.o
|
||||
endif
|
||||
endif
|
||||
|
||||
ifdef NEED_DH_GROUPS
|
||||
OBJS += ../src/crypto/dh_groups.o
|
||||
endif
|
||||
ifdef NEED_DH_GROUPS_ALL
|
||||
CFLAGS += -DALL_DH_GROUPS
|
||||
endif
|
||||
ifdef CONFIG_INTERNAL_DH_GROUP5
|
||||
ifdef NEED_DH_GROUPS
|
||||
OBJS += ../src/crypto/dh_group5.o
|
||||
endif
|
||||
endif
|
||||
|
||||
ifdef CONFIG_NO_RANDOM_POOL
|
||||
CFLAGS += -DCONFIG_NO_RANDOM_POOL
|
||||
else
|
||||
OBJS += ../src/crypto/random.o
|
||||
HOBJS += ../src/crypto/random.o
|
||||
HOBJS += $(SHA1OBJS)
|
||||
HOBJS += ../src/crypto/md5.o
|
||||
endif
|
||||
|
||||
ifdef CONFIG_RADIUS_SERVER
|
||||
CFLAGS += -DRADIUS_SERVER
|
||||
OBJS += ../src/radius/radius_server.o
|
||||
endif
|
||||
|
||||
ifdef CONFIG_IPV6
|
||||
CFLAGS += -DCONFIG_IPV6
|
||||
endif
|
||||
|
||||
ifdef CONFIG_DRIVER_RADIUS_ACL
|
||||
CFLAGS += -DCONFIG_DRIVER_RADIUS_ACL
|
||||
endif
|
||||
|
||||
ifdef CONFIG_FULL_DYNAMIC_VLAN
|
||||
# define CONFIG_FULL_DYNAMIC_VLAN to have hostapd manipulate bridges
|
||||
# and vlan interfaces for the vlan feature.
|
||||
CFLAGS += -DCONFIG_FULL_DYNAMIC_VLAN
|
||||
endif
|
||||
|
||||
ifdef NEED_BASE64
|
||||
OBJS += ../src/utils/base64.o
|
||||
endif
|
||||
|
||||
ifdef NEED_AP_MLME
|
||||
OBJS += ../src/ap/beacon.o
|
||||
OBJS += ../src/ap/wmm.o
|
||||
OBJS += ../src/ap/ap_list.o
|
||||
OBJS += ../src/ap/ieee802_11.o
|
||||
OBJS += ../src/ap/hw_features.o
|
||||
CFLAGS += -DNEED_AP_MLME
|
||||
endif
|
||||
ifdef CONFIG_IEEE80211N
|
||||
OBJS += ../src/ap/ieee802_11_ht.o
|
||||
endif
|
||||
|
||||
ifdef CONFIG_P2P_MANAGER
|
||||
CFLAGS += -DCONFIG_P2P_MANAGER
|
||||
OBJS += ../src/ap/p2p_hostapd.o
|
||||
endif
|
||||
|
||||
ifdef CONFIG_NO_STDOUT_DEBUG
|
||||
CFLAGS += -DCONFIG_NO_STDOUT_DEBUG
|
||||
endif
|
||||
|
||||
ifdef CONFIG_DEBUG_FILE
|
||||
CFLAGS += -DCONFIG_DEBUG_FILE
|
||||
endif
|
||||
|
||||
ALL=hostapd hostapd_cli
|
||||
|
||||
all: verify_config $(ALL)
|
||||
|
||||
Q=@
|
||||
E=echo
|
||||
ifeq ($(V), 1)
|
||||
Q=
|
||||
E=true
|
||||
endif
|
||||
|
||||
%.o: %.c
|
||||
$(Q)$(CC) -c -o $@ $(CFLAGS) $<
|
||||
@$(E) " CC " $<
|
||||
|
||||
verify_config:
|
||||
@if [ ! -r .config ]; then \
|
||||
echo 'Building hostapd requires a configuration file'; \
|
||||
echo '(.config). See README for more instructions. You can'; \
|
||||
echo 'run "cp defconfig .config" to create an example'; \
|
||||
echo 'configuration.'; \
|
||||
exit 1; \
|
||||
fi
|
||||
|
||||
install: all
|
||||
mkdir -p $(DESTDIR)/usr/local/bin
|
||||
for i in $(ALL); do cp -f $$i $(DESTDIR)/usr/local/bin/$$i; done
|
||||
|
||||
../src/drivers/build.hostapd:
|
||||
@if [ -f ../src/drivers/build.wpa_supplicant ]; then \
|
||||
$(MAKE) -C ../src/drivers clean; \
|
||||
fi
|
||||
@touch ../src/drivers/build.hostapd
|
||||
|
||||
BCHECK=../src/drivers/build.hostapd
|
||||
|
||||
hostapd: $(BCHECK) $(OBJS)
|
||||
$(Q)$(CC) $(LDFLAGS) -o hostapd $(OBJS) $(LIBS)
|
||||
@$(E) " LD " $@
|
||||
|
||||
OBJS_c = hostapd_cli.o ../src/common/wpa_ctrl.o ../src/utils/os_$(CONFIG_OS).o
|
||||
ifdef CONFIG_WPA_TRACE
|
||||
OBJS_c += ../src/utils/trace.o
|
||||
OBJS_c += ../src/utils/wpa_debug.o
|
||||
endif
|
||||
hostapd_cli: $(OBJS_c)
|
||||
$(Q)$(CC) $(LDFLAGS) -o hostapd_cli $(OBJS_c) $(LIBS_c)
|
||||
@$(E) " LD " $@
|
||||
|
||||
NOBJS = nt_password_hash.o ../src/crypto/ms_funcs.o $(SHA1OBJS) ../src/crypto/md5.o
|
||||
ifdef NEED_RC4
|
||||
ifdef CONFIG_INTERNAL_RC4
|
||||
NOBJS += ../src/crypto/rc4.o
|
||||
endif
|
||||
endif
|
||||
ifdef CONFIG_INTERNAL_MD5
|
||||
NOBJS += ../src/crypto/md5-internal.o
|
||||
endif
|
||||
NOBJS += ../src/crypto/crypto_openssl.o ../src/utils/os_$(CONFIG_OS).o
|
||||
NOBJS += ../src/utils/wpa_debug.o
|
||||
NOBJS += ../src/utils/wpabuf.o
|
||||
ifdef CONFIG_WPA_TRACE
|
||||
NOBJS += ../src/utils/trace.o
|
||||
LIBS_n += -lbfd
|
||||
endif
|
||||
ifdef TLS_FUNCS
|
||||
LIBS_n += -lcrypto
|
||||
endif
|
||||
|
||||
HOBJS += hlr_auc_gw.o ../src/utils/common.o ../src/utils/wpa_debug.o ../src/utils/os_$(CONFIG_OS).o ../src/utils/wpabuf.o ../src/crypto/milenage.o
|
||||
HOBJS += ../src/crypto/aes-encblock.o
|
||||
ifdef CONFIG_INTERNAL_AES
|
||||
HOBJS += ../src/crypto/aes-internal.o
|
||||
HOBJS += ../src/crypto/aes-internal-enc.o
|
||||
endif
|
||||
|
||||
nt_password_hash: $(NOBJS)
|
||||
$(Q)$(CC) $(LDFLAGS) -o nt_password_hash $(NOBJS) $(LIBS_n)
|
||||
@$(E) " LD " $@
|
||||
|
||||
hlr_auc_gw: $(HOBJS)
|
||||
$(Q)$(CC) $(LDFLAGS) -o hlr_auc_gw $(HOBJS) $(LIBS_h)
|
||||
@$(E) " LD " $@
|
||||
|
||||
clean:
|
||||
$(MAKE) -C ../src clean
|
||||
rm -f core *~ *.o hostapd hostapd_cli nt_password_hash hlr_auc_gw
|
||||
rm -f *.d
|
||||
|
||||
-include $(OBJS:%.o=%.d)
|
387
hostapd-0.8/hostapd/README
Normal file
387
hostapd-0.8/hostapd/README
Normal file
|
@ -0,0 +1,387 @@
|
|||
hostapd - user space IEEE 802.11 AP and IEEE 802.1X/WPA/WPA2/EAP
|
||||
Authenticator and RADIUS authentication server
|
||||
================================================================
|
||||
|
||||
Copyright (c) 2002-2011, 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.
|
||||
|
||||
|
||||
|
||||
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:
|
||||
|
||||
Redistribution and use in source and binary forms, with or without
|
||||
modification, are permitted provided that the following conditions are
|
||||
met:
|
||||
|
||||
1. Redistributions of source code must retain the above copyright
|
||||
notice, this list of conditions and the following disclaimer.
|
||||
|
||||
2. Redistributions in binary form must reproduce the above copyright
|
||||
notice, this list of conditions and the following disclaimer in the
|
||||
documentation and/or other materials provided with the distribution.
|
||||
|
||||
3. Neither the name(s) of the above-listed copyright holder(s) nor the
|
||||
names of its contributors may be used to endorse or promote products
|
||||
derived from this software without specific prior written permission.
|
||||
|
||||
THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
|
||||
"AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
|
||||
LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
|
||||
A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
|
||||
OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
|
||||
SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
|
||||
LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
|
||||
DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
|
||||
THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
|
||||
(INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
|
||||
OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
|
||||
|
||||
|
||||
|
||||
Introduction
|
||||
============
|
||||
|
||||
Originally, hostapd was an optional user space component for Host AP
|
||||
driver. It adds more features to the basic IEEE 802.11 management
|
||||
included in the kernel driver: using external RADIUS authentication
|
||||
server for MAC address based access control, IEEE 802.1X Authenticator
|
||||
and dynamic WEP keying, RADIUS accounting, WPA/WPA2 (IEEE 802.11i/RSN)
|
||||
Authenticator and dynamic TKIP/CCMP keying.
|
||||
|
||||
The current version includes support for other drivers, an integrated
|
||||
EAP server (i.e., allow full authentication without requiring
|
||||
an external RADIUS authentication server), and RADIUS authentication
|
||||
server for EAP authentication.
|
||||
|
||||
|
||||
Requirements
|
||||
------------
|
||||
|
||||
Current hardware/software requirements:
|
||||
- drivers:
|
||||
Host AP driver for Prism2/2.5/3.
|
||||
(http://hostap.epitest.fi/)
|
||||
Please note that station firmware version needs to be 1.7.0 or newer
|
||||
to work in WPA mode.
|
||||
|
||||
madwifi driver for cards based on Atheros chip set (ar521x)
|
||||
(http://sourceforge.net/projects/madwifi/)
|
||||
Please note that you will need to add the correct path for
|
||||
madwifi driver root directory in .config (see defconfig file for
|
||||
an example: CFLAGS += -I<path>)
|
||||
|
||||
mac80211-based drivers that support AP mode (with driver=nl80211).
|
||||
This includes drivers for Atheros (ath9k) and Broadcom (b43)
|
||||
chipsets.
|
||||
|
||||
Any wired Ethernet driver for wired IEEE 802.1X authentication
|
||||
(experimental code)
|
||||
|
||||
FreeBSD -current (with some kernel mods that have not yet been
|
||||
committed when hostapd v0.3.0 was released)
|
||||
BSD net80211 layer (e.g., Atheros driver)
|
||||
|
||||
|
||||
Build configuration
|
||||
-------------------
|
||||
|
||||
In order to be able to build hostapd, you will need to create a build
|
||||
time configuration file, .config that selects which optional
|
||||
components are included. See defconfig file for example configuration
|
||||
and list of available options.
|
||||
|
||||
|
||||
|
||||
IEEE 802.1X
|
||||
===========
|
||||
|
||||
IEEE Std 802.1X-2001 is a standard for port-based network access
|
||||
control. In case of IEEE 802.11 networks, a "virtual port" is used
|
||||
between each associated station and the AP. IEEE 802.11 specifies
|
||||
minimal authentication mechanism for stations, whereas IEEE 802.1X
|
||||
introduces a extensible mechanism for authenticating and authorizing
|
||||
users.
|
||||
|
||||
IEEE 802.1X uses elements called Supplicant, Authenticator, Port
|
||||
Access Entity, and Authentication Server. Supplicant is a component in
|
||||
a station and it performs the authentication with the Authentication
|
||||
Server. An access point includes an Authenticator that relays the packets
|
||||
between a Supplicant and an Authentication Server. In addition, it has a
|
||||
Port Access Entity (PAE) with Authenticator functionality for
|
||||
controlling the virtual port authorization, i.e., whether to accept
|
||||
packets from or to the station.
|
||||
|
||||
IEEE 802.1X uses Extensible Authentication Protocol (EAP). The frames
|
||||
between a Supplicant and an Authenticator are sent using EAP over LAN
|
||||
(EAPOL) and the Authenticator relays these frames to the Authentication
|
||||
Server (and similarly, relays the messages from the Authentication
|
||||
Server to the Supplicant). The Authentication Server can be colocated with the
|
||||
Authenticator, in which case there is no need for additional protocol
|
||||
for EAP frame transmission. However, a more common configuration is to
|
||||
use an external Authentication Server and encapsulate EAP frame in the
|
||||
frames used by that server. RADIUS is suitable for this, but IEEE
|
||||
802.1X would also allow other mechanisms.
|
||||
|
||||
Host AP driver includes PAE functionality in the kernel driver. It
|
||||
is a relatively simple mechanism for denying normal frames going to
|
||||
or coming from an unauthorized port. PAE allows IEEE 802.1X related
|
||||
frames to be passed between the Supplicant and the Authenticator even
|
||||
on an unauthorized port.
|
||||
|
||||
User space daemon, hostapd, includes Authenticator functionality. It
|
||||
receives 802.1X (EAPOL) frames from the Supplicant using the wlan#ap
|
||||
device that is also used with IEEE 802.11 management frames. The
|
||||
frames to the Supplicant are sent using the same device.
|
||||
|
||||
The normal configuration of the Authenticator would use an external
|
||||
Authentication Server. hostapd supports RADIUS encapsulation of EAP
|
||||
packets, so the Authentication Server should be a RADIUS server, like
|
||||
FreeRADIUS (http://www.freeradius.org/). The Authenticator in hostapd
|
||||
relays the frames between the Supplicant and the Authentication
|
||||
Server. It also controls the PAE functionality in the kernel driver by
|
||||
controlling virtual port authorization, i.e., station-AP
|
||||
connection, based on the IEEE 802.1X state.
|
||||
|
||||
When a station would like to use the services of an access point, it
|
||||
will first perform IEEE 802.11 authentication. This is normally done
|
||||
with open systems authentication, so there is no security. After
|
||||
this, IEEE 802.11 association is performed. If IEEE 802.1X is
|
||||
configured to be used, the virtual port for the station is set in
|
||||
Unauthorized state and only IEEE 802.1X frames are accepted at this
|
||||
point. The Authenticator will then ask the Supplicant to authenticate
|
||||
with the Authentication Server. After this is completed successfully,
|
||||
the virtual port is set to Authorized state and frames from and to the
|
||||
station are accepted.
|
||||
|
||||
Host AP configuration for IEEE 802.1X
|
||||
-------------------------------------
|
||||
|
||||
The user space daemon has its own configuration file that can be used to
|
||||
define AP options. Distribution package contains an example
|
||||
configuration file (hostapd/hostapd.conf) that can be used as a basis
|
||||
for configuration. It includes examples of all supported configuration
|
||||
options and short description of each option. hostapd should be started
|
||||
with full path to the configuration file as the command line argument,
|
||||
e.g., './hostapd /etc/hostapd.conf'. If you have more that one wireless
|
||||
LAN card, you can use one hostapd process for multiple interfaces by
|
||||
giving a list of configuration files (one per interface) in the command
|
||||
line.
|
||||
|
||||
hostapd includes a minimal co-located IEEE 802.1X server which can be
|
||||
used to test IEEE 802.1X authentication. However, it should not be
|
||||
used in normal use since it does not provide any security. This can be
|
||||
configured by setting ieee8021x and minimal_eap options in the
|
||||
configuration file.
|
||||
|
||||
An external Authentication Server (RADIUS) is configured with
|
||||
auth_server_{addr,port,shared_secret} options. In addition,
|
||||
ieee8021x and own_ip_addr must be set for this mode. With such
|
||||
configuration, the co-located Authentication Server is not used and EAP
|
||||
frames will be relayed using EAPOL between the Supplicant and the
|
||||
Authenticator and RADIUS encapsulation between the Authenticator and
|
||||
the Authentication Server. Other than this, the functionality is similar
|
||||
to the case with the co-located Authentication Server.
|
||||
|
||||
Authentication Server and Supplicant
|
||||
------------------------------------
|
||||
|
||||
Any RADIUS server supporting EAP should be usable as an IEEE 802.1X
|
||||
Authentication Server with hostapd Authenticator. FreeRADIUS
|
||||
(http://www.freeradius.org/) has been successfully tested with hostapd
|
||||
Authenticator and both Xsupplicant (http://www.open1x.org) and Windows
|
||||
XP Supplicants. EAP/TLS was used with Xsupplicant and
|
||||
EAP/MD5-Challenge with Windows XP.
|
||||
|
||||
http://www.missl.cs.umd.edu/wireless/eaptls/ has useful information
|
||||
about using EAP/TLS with FreeRADIUS and Xsupplicant (just replace
|
||||
Cisco access point with Host AP driver, hostapd daemon, and a Prism2
|
||||
card ;-). http://www.freeradius.org/doc/EAP-MD5.html has information
|
||||
about using EAP/MD5 with FreeRADIUS, including instructions for WinXP
|
||||
configuration. http://www.denobula.com/EAPTLS.pdf has a HOWTO on
|
||||
EAP/TLS use with WinXP Supplicant.
|
||||
|
||||
Automatic WEP key configuration
|
||||
-------------------------------
|
||||
|
||||
EAP/TLS generates a session key that can be used to send WEP keys from
|
||||
an AP to authenticated stations. The Authenticator in hostapd can be
|
||||
configured to automatically select a random default/broadcast key
|
||||
(shared by all authenticated stations) with wep_key_len_broadcast
|
||||
option (5 for 40-bit WEP or 13 for 104-bit WEP). In addition,
|
||||
wep_key_len_unicast option can be used to configure individual unicast
|
||||
keys for stations. This requires support for individual keys in the
|
||||
station driver.
|
||||
|
||||
WEP keys can be automatically updated by configuring rekeying. This
|
||||
will improve security of the network since same WEP key will only be
|
||||
used for a limited period of time. wep_rekey_period option sets the
|
||||
interval for rekeying in seconds.
|
||||
|
||||
|
||||
WPA/WPA2
|
||||
========
|
||||
|
||||
Features
|
||||
--------
|
||||
|
||||
Supported WPA/IEEE 802.11i features:
|
||||
- WPA-PSK ("WPA-Personal")
|
||||
- WPA with EAP (e.g., with RADIUS authentication server) ("WPA-Enterprise")
|
||||
- key management for CCMP, TKIP, WEP104, WEP40
|
||||
- RSN/WPA2 (IEEE 802.11i), including PMKSA caching and pre-authentication
|
||||
|
||||
WPA
|
||||
---
|
||||
|
||||
The original security mechanism of IEEE 802.11 standard was not
|
||||
designed to be strong and has proved to be insufficient for most
|
||||
networks that require some kind of security. Task group I (Security)
|
||||
of IEEE 802.11 working group (http://www.ieee802.org/11/) has worked
|
||||
to address the flaws of the base standard and has in practice
|
||||
completed its work in May 2004. The IEEE 802.11i amendment to the IEEE
|
||||
802.11 standard was approved in June 2004 and this amendment is likely
|
||||
to be published in July 2004.
|
||||
|
||||
Wi-Fi Alliance (http://www.wi-fi.org/) used a draft version of the
|
||||
IEEE 802.11i work (draft 3.0) to define a subset of the security
|
||||
enhancements that can be implemented with existing wlan hardware. This
|
||||
is called Wi-Fi Protected Access<TM> (WPA). This has now become a
|
||||
mandatory component of interoperability testing and certification done
|
||||
by Wi-Fi Alliance. Wi-Fi provides information about WPA at its web
|
||||
site (http://www.wi-fi.org/OpenSection/protected_access.asp).
|
||||
|
||||
IEEE 802.11 standard defined wired equivalent privacy (WEP) algorithm
|
||||
for protecting wireless networks. WEP uses RC4 with 40-bit keys,
|
||||
24-bit initialization vector (IV), and CRC32 to protect against packet
|
||||
forgery. All these choices have proven to be insufficient: key space is
|
||||
too small against current attacks, RC4 key scheduling is insufficient
|
||||
(beginning of the pseudorandom stream should be skipped), IV space is
|
||||
too small and IV reuse makes attacks easier, there is no replay
|
||||
protection, and non-keyed authentication does not protect against bit
|
||||
flipping packet data.
|
||||
|
||||
WPA is an intermediate solution for the security issues. It uses
|
||||
Temporal Key Integrity Protocol (TKIP) to replace WEP. TKIP is a
|
||||
compromise on strong security and possibility to use existing
|
||||
hardware. It still uses RC4 for the encryption like WEP, but with
|
||||
per-packet RC4 keys. In addition, it implements replay protection,
|
||||
keyed packet authentication mechanism (Michael MIC).
|
||||
|
||||
Keys can be managed using two different mechanisms. WPA can either use
|
||||
an external authentication server (e.g., RADIUS) and EAP just like
|
||||
IEEE 802.1X is using or pre-shared keys without need for additional
|
||||
servers. Wi-Fi calls these "WPA-Enterprise" and "WPA-Personal",
|
||||
respectively. Both mechanisms will generate a master session key for
|
||||
the Authenticator (AP) and Supplicant (client station).
|
||||
|
||||
WPA implements a new key handshake (4-Way Handshake and Group Key
|
||||
Handshake) for generating and exchanging data encryption keys between
|
||||
the Authenticator and Supplicant. This handshake is also used to
|
||||
verify that both Authenticator and Supplicant know the master session
|
||||
key. These handshakes are identical regardless of the selected key
|
||||
management mechanism (only the method for generating master session
|
||||
key changes).
|
||||
|
||||
|
||||
IEEE 802.11i / WPA2
|
||||
-------------------
|
||||
|
||||
The design for parts of IEEE 802.11i that were not included in WPA has
|
||||
finished (May 2004) and this amendment to IEEE 802.11 was approved in
|
||||
June 2004. Wi-Fi Alliance is using the final IEEE 802.11i as a new
|
||||
version of WPA called WPA2. This includes, e.g., support for more
|
||||
robust encryption algorithm (CCMP: AES in Counter mode with CBC-MAC)
|
||||
to replace TKIP and optimizations for handoff (reduced number of
|
||||
messages in initial key handshake, pre-authentication, and PMKSA caching).
|
||||
|
||||
Some wireless LAN vendors are already providing support for CCMP in
|
||||
their WPA products. There is no "official" interoperability
|
||||
certification for CCMP and/or mixed modes using both TKIP and CCMP, so
|
||||
some interoperability issues can be expected even though many
|
||||
combinations seem to be working with equipment from different vendors.
|
||||
Testing for WPA2 is likely to start during the second half of 2004.
|
||||
|
||||
hostapd configuration for WPA/WPA2
|
||||
----------------------------------
|
||||
|
||||
TODO
|
||||
|
||||
# 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.
|
||||
# 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.
|
||||
# This field is a bit field that can be used to enable WPA (IEEE 802.11i/D3.0)
|
||||
# and/or WPA2 (full IEEE 802.11i/RSN):
|
||||
# bit0 = WPA
|
||||
# bit1 = IEEE 802.11i/RSN (WPA2)
|
||||
#wpa=1
|
||||
|
||||
# WPA pre-shared keys for WPA-PSK. This can be either entered as a 256-bit
|
||||
# secret in hex format (64 hex digits), wpa_psk, or as an ASCII passphrase
|
||||
# (8..63 characters) that will be converted to PSK. This conversion uses SSID
|
||||
# so the PSK changes when ASCII passphrase is used and the SSID is changed.
|
||||
#wpa_psk=0123456789abcdef0123456789abcdef0123456789abcdef0123456789abcdef
|
||||
#wpa_passphrase=secret passphrase
|
||||
|
||||
# Set of accepted key management algorithms (WPA-PSK, WPA-EAP, or both). The
|
||||
# entries are separated with a space.
|
||||
#wpa_key_mgmt=WPA-PSK WPA-EAP
|
||||
|
||||
# Set of accepted cipher suites (encryption algorithms) for pairwise keys
|
||||
# (unicast packets). This is a space separated list of algorithms:
|
||||
# CCMP = AES in Counter mode with CBC-MAC [RFC 3610, IEEE 802.11i]
|
||||
# TKIP = Temporal Key Integrity Protocol [IEEE 802.11i]
|
||||
# Group cipher suite (encryption algorithm for broadcast and multicast frames)
|
||||
# is automatically selected based on this configuration. If only CCMP is
|
||||
# allowed as the pairwise cipher, group cipher will also be CCMP. Otherwise,
|
||||
# TKIP will be used as the group cipher.
|
||||
#wpa_pairwise=TKIP CCMP
|
||||
|
||||
# Time interval for rekeying GTK (broadcast/multicast encryption keys) in
|
||||
# seconds.
|
||||
#wpa_group_rekey=600
|
||||
|
||||
# Time interval for rekeying GMK (master key used internally to generate GTKs
|
||||
# (in seconds).
|
||||
#wpa_gmk_rekey=86400
|
||||
|
||||
# Enable IEEE 802.11i/RSN/WPA2 pre-authentication. This is used to speed up
|
||||
# roaming be pre-authenticating IEEE 802.1X/EAP part of the full RSN
|
||||
# authentication and key handshake before actually associating with a new AP.
|
||||
#rsn_preauth=1
|
||||
#
|
||||
# Space separated list of interfaces from which pre-authentication frames are
|
||||
# accepted (e.g., 'eth0' or 'eth0 wlan0wds0'. This list should include all
|
||||
# interface that are used for connections to other APs. This could include
|
||||
# wired interfaces and WDS links. The normal wireless data interface towards
|
||||
# associated stations (e.g., wlan0) should not be added, since
|
||||
# pre-authentication is only used with APs other than the currently associated
|
||||
# one.
|
||||
#rsn_preauth_interfaces=eth0
|
291
hostapd-0.8/hostapd/README-WPS
Normal file
291
hostapd-0.8/hostapd/README-WPS
Normal file
|
@ -0,0 +1,291 @@
|
|||
hostapd and Wi-Fi Protected Setup (WPS)
|
||||
=======================================
|
||||
|
||||
This document describes how the WPS implementation in hostapd can be
|
||||
configured and how an external component on an AP (e.g., web UI) is
|
||||
used to enable enrollment of client devices.
|
||||
|
||||
|
||||
Introduction to WPS
|
||||
-------------------
|
||||
|
||||
Wi-Fi Protected Setup (WPS) is a mechanism for easy configuration of a
|
||||
wireless network. It allows automated generation of random keys (WPA
|
||||
passphrase/PSK) and configuration of an access point and client
|
||||
devices. WPS includes number of methods for setting up connections
|
||||
with PIN method and push-button configuration (PBC) being the most
|
||||
commonly deployed options.
|
||||
|
||||
While WPS can enable more home networks to use encryption in the
|
||||
wireless network, it should be noted that the use of the PIN and
|
||||
especially PBC mechanisms for authenticating the initial key setup is
|
||||
not very secure. As such, use of WPS may not be suitable for
|
||||
environments that require secure network access without chance for
|
||||
allowing outsiders to gain access during the setup phase.
|
||||
|
||||
WPS uses following terms to describe the entities participating in the
|
||||
network setup:
|
||||
- access point: the WLAN access point
|
||||
- Registrar: a device that control a network and can authorize
|
||||
addition of new devices); this may be either in the AP ("internal
|
||||
Registrar") or in an external device, e.g., a laptop, ("external
|
||||
Registrar")
|
||||
- Enrollee: a device that is being authorized to use the network
|
||||
|
||||
It should also be noted that the AP and a client device may change
|
||||
roles (i.e., AP acts as an Enrollee and client device as a Registrar)
|
||||
when WPS is used to configure the access point.
|
||||
|
||||
|
||||
More information about WPS is available from Wi-Fi Alliance:
|
||||
http://www.wi-fi.org/wifi-protected-setup
|
||||
|
||||
|
||||
hostapd implementation
|
||||
----------------------
|
||||
|
||||
hostapd includes an optional WPS component that can be used as an
|
||||
internal WPS Registrar to manage addition of new WPS enabled clients
|
||||
to the network. In addition, WPS Enrollee functionality in hostapd can
|
||||
be used to allow external WPS Registrars to configure the access
|
||||
point, e.g., for initial network setup. In addition, hostapd can proxy a
|
||||
WPS registration between a wireless Enrollee and an external Registrar
|
||||
(e.g., Microsoft Vista or Atheros JumpStart) with UPnP.
|
||||
|
||||
|
||||
hostapd configuration
|
||||
---------------------
|
||||
|
||||
WPS is an optional component that needs to be enabled in hostapd build
|
||||
configuration (.config). Here is an example configuration that
|
||||
includes WPS support and uses madwifi driver interface:
|
||||
|
||||
CONFIG_DRIVER_MADWIFI=y
|
||||
CFLAGS += -I/usr/src/madwifi-0.9.3
|
||||
CONFIG_WPS=y
|
||||
CONFIG_WPS2=y
|
||||
CONFIG_WPS_UPNP=y
|
||||
|
||||
|
||||
Following section shows an example runtime configuration
|
||||
(hostapd.conf) that enables WPS:
|
||||
|
||||
# Configure the driver and network interface
|
||||
driver=madwifi
|
||||
interface=ath0
|
||||
|
||||
# WPA2-Personal configuration for the AP
|
||||
ssid=wps-test
|
||||
wpa=2
|
||||
wpa_key_mgmt=WPA-PSK
|
||||
wpa_pairwise=CCMP
|
||||
# Default WPA passphrase for legacy (non-WPS) clients
|
||||
wpa_passphrase=12345678
|
||||
# Enable random per-device PSK generation for WPS clients
|
||||
# Please note that the file has to exists for hostapd to start (i.e., create an
|
||||
# empty file as a starting point).
|
||||
wpa_psk_file=/etc/hostapd.psk
|
||||
|
||||
# Enable control interface for PBC/PIN entry
|
||||
ctrl_interface=/var/run/hostapd
|
||||
|
||||
# Enable internal EAP server for EAP-WSC (part of Wi-Fi Protected Setup)
|
||||
eap_server=1
|
||||
|
||||
# WPS configuration (AP configured, do not allow external WPS Registrars)
|
||||
wps_state=2
|
||||
ap_setup_locked=1
|
||||
# If UUID is not configured, it will be generated based on local MAC address.
|
||||
uuid=87654321-9abc-def0-1234-56789abc0000
|
||||
wps_pin_requests=/var/run/hostapd.pin-req
|
||||
device_name=Wireless AP
|
||||
manufacturer=Company
|
||||
model_name=WAP
|
||||
model_number=123
|
||||
serial_number=12345
|
||||
device_type=6-0050F204-1
|
||||
os_version=01020300
|
||||
config_methods=label display push_button keypad
|
||||
|
||||
# if external Registrars are allowed, UPnP support could be added:
|
||||
#upnp_iface=br0
|
||||
#friendly_name=WPS Access Point
|
||||
|
||||
|
||||
External operations
|
||||
-------------------
|
||||
|
||||
WPS requires either a device PIN code (usually, 8-digit number) or a
|
||||
pushbutton event (for PBC) to allow a new WPS Enrollee to join the
|
||||
network. hostapd uses the control interface as an input channel for
|
||||
these events.
|
||||
|
||||
The PIN value used in the commands must be processed by an UI to
|
||||
remove non-digit characters and potentially, to verify the checksum
|
||||
digit. "hostapd_cli wps_check_pin <PIN>" can be used to do such
|
||||
processing. It returns FAIL if the PIN is invalid, or FAIL-CHECKSUM if
|
||||
the checksum digit is incorrect, or the processed PIN (non-digit
|
||||
characters removed) if the PIN is valid.
|
||||
|
||||
When a client device (WPS Enrollee) connects to hostapd (WPS
|
||||
Registrar) in order to start PIN mode negotiation for WPS, an
|
||||
identifier (Enrollee UUID) is sent. hostapd will need to be configured
|
||||
with a device password (PIN) for this Enrollee. This is an operation
|
||||
that requires user interaction (assuming there are no pre-configured
|
||||
PINs on the AP for a set of Enrollee).
|
||||
|
||||
The PIN request with information about the device is appended to the
|
||||
wps_pin_requests file (/var/run/hostapd.pin-req in this example). In
|
||||
addition, hostapd control interface event is sent as a notification of
|
||||
a new device. The AP could use, e.g., a web UI for showing active
|
||||
Enrollees to the user and request a PIN for an Enrollee.
|
||||
|
||||
The PIN request file has one line for every Enrollee that connected to
|
||||
the AP, but for which there was no PIN. Following information is
|
||||
provided for each Enrollee (separated with tabulators):
|
||||
- timestamp (seconds from 1970-01-01)
|
||||
- Enrollee UUID
|
||||
- MAC address
|
||||
- Device name
|
||||
- Manufacturer
|
||||
- Model Name
|
||||
- Model Number
|
||||
- Serial Number
|
||||
- Device category
|
||||
|
||||
Example line in the /var/run/hostapd.pin-req file:
|
||||
1200188391 53b63a98-d29e-4457-a2ed-094d7e6a669c Intel(R) Centrino(R) Intel Corporation Intel(R) Centrino(R) - - 1-0050F204-1
|
||||
|
||||
Control interface data:
|
||||
WPS-PIN-NEEDED [UUID-E|MAC Address|Device Name|Manufacturer|Model Name|Model Number|Serial Number|Device Category]
|
||||
For example:
|
||||
<2>WPS-PIN-NEEDED [53b63a98-d29e-4457-a2ed-094d7e6a669c|02:12:34:56:78:9a|Device|Manuf|Model|Model Number|Serial Number|1-0050F204-1]
|
||||
|
||||
When the user enters a PIN for a pending Enrollee, e.g., on the web
|
||||
UI), hostapd needs to be notified of the new PIN over the control
|
||||
interface. This can be done either by using the UNIX domain socket
|
||||
-based control interface directly (src/common/wpa_ctrl.c provides
|
||||
helper functions for using the interface) or by calling hostapd_cli.
|
||||
|
||||
Example command to add a PIN (12345670) for an Enrollee:
|
||||
|
||||
hostapd_cli wps_pin 53b63a98-d29e-4457-a2ed-094d7e6a669c 12345670
|
||||
|
||||
If the UUID-E is not available (e.g., Enrollee waits for the Registrar
|
||||
to be selected before connecting), wildcard UUID may be used to allow
|
||||
the PIN to be used once with any UUID:
|
||||
|
||||
hostapd_cli wps_pin any 12345670
|
||||
|
||||
To reduce likelihood of PIN being used with other devices or of
|
||||
forgetting an active PIN available for potential attackers, expiration
|
||||
time in seconds can be set for the new PIN (value 0 indicates no
|
||||
expiration):
|
||||
|
||||
hostapd_cli wps_pin any 12345670 300
|
||||
|
||||
If the MAC address of the enrollee is known, it should be configured
|
||||
to allow the AP to advertise list of authorized enrollees:
|
||||
|
||||
hostapd_cli wps_pin 53b63a98-d29e-4457-a2ed-094d7e6a669c \
|
||||
12345670 300 00:11:22:33:44:55
|
||||
|
||||
|
||||
After this, the Enrollee can connect to the AP again and complete WPS
|
||||
negotiation. At that point, a new, random WPA PSK is generated for the
|
||||
client device and the client can then use that key to connect to the
|
||||
AP to access the network.
|
||||
|
||||
|
||||
If the AP includes a pushbutton, WPS PBC mode can be used. It is
|
||||
enabled by pushing a button on both the AP and the client at about the
|
||||
same time (2 minute window). hostapd needs to be notified about the AP
|
||||
button pushed event over the control interface, e.g., by calling
|
||||
hostapd_cli:
|
||||
|
||||
hostapd_cli wps_pbc
|
||||
|
||||
At this point, the client has two minutes to complete WPS negotiation
|
||||
which will generate a new WPA PSK in the same way as the PIN method
|
||||
described above.
|
||||
|
||||
|
||||
When an external Registrar is used, the AP can act as an Enrollee and
|
||||
use its AP PIN. A static AP PIN (e.g., one one a label in the AP
|
||||
device) can be configured in hostapd.conf (ap_pin parameter). A more
|
||||
secure option is to use hostapd_cli wps_ap_pin command to enable the
|
||||
AP PIN only based on user action (and even better security by using a
|
||||
random AP PIN for each session, i.e., by using "wps_ap_pin random"
|
||||
command with a timeout value). Following commands are available for
|
||||
managing the dynamic AP PIN operations:
|
||||
|
||||
hostapd_cli wps_ap_pin disable
|
||||
- disable AP PIN (i.e., do not allow external Registrars to use it to
|
||||
learn the current AP settings or to reconfigure the AP)
|
||||
|
||||
hostapd_cli wps_ap_pin random [timeout]
|
||||
- generate a random AP PIN and enable it
|
||||
- if the optional timeout parameter is given, the AP PIN will be enabled
|
||||
for the specified number of seconds
|
||||
|
||||
hostapd_cli wps_ap_pin get
|
||||
- fetch the current AP PIN
|
||||
|
||||
hostapd_cli wps_ap_pin set <PIN> [timeout]
|
||||
- set the AP PIN and enable it
|
||||
- if the optional timeout parameter is given, the AP PIN will be enabled
|
||||
for the specified number of seconds
|
||||
|
||||
hostapd_cli get_config
|
||||
- display the current configuration
|
||||
|
||||
hostapd_cli wps_config <new SSID> <auth> <encr> <new key>
|
||||
examples:
|
||||
hostapd_cli wps_config testing WPA2PSK CCMP 12345678
|
||||
hostapd_cli wps_config "no security" OPEN NONE ""
|
||||
|
||||
<auth> must be one of the following: OPEN WPAPSK WPA2PSK
|
||||
<encr> must be one of the following: NONE WEP TKIP CCMP
|
||||
|
||||
|
||||
Credential generation and configuration changes
|
||||
-----------------------------------------------
|
||||
|
||||
By default, hostapd generates credentials for Enrollees and processing
|
||||
AP configuration updates internally. However, it is possible to
|
||||
control these operations from external programs, if desired.
|
||||
|
||||
The internal credential generation can be disabled with
|
||||
skip_cred_build=1 option in the configuration. extra_cred option will
|
||||
then need to be used to provide pre-configured Credential attribute(s)
|
||||
for hostapd to use. The exact data from this binary file will be sent,
|
||||
i.e., it will have to include valid WPS attributes. extra_cred can
|
||||
also be used to add additional networks if the Registrar is used to
|
||||
configure credentials for multiple networks.
|
||||
|
||||
Processing of received configuration updates can be disabled with
|
||||
wps_cred_processing=1 option. When this is used, an external program
|
||||
is responsible for creating hostapd configuration files and processing
|
||||
configuration updates based on messages received from hostapd over
|
||||
control interface. This will also include the initial configuration on
|
||||
first successful registration if the AP is initially set in
|
||||
unconfigured state.
|
||||
|
||||
Following control interface messages are sent out for external programs:
|
||||
|
||||
WPS-REG-SUCCESS <Enrollee MAC address <UUID-E>
|
||||
For example:
|
||||
<2>WPS-REG-SUCCESS 02:66:a0:ee:17:27 2b7093f1-d6fb-5108-adbb-bea66bb87333
|
||||
|
||||
This can be used to trigger change from unconfigured to configured
|
||||
state (random configuration based on the first successful WPS
|
||||
registration). In addition, this can be used to update AP UI about the
|
||||
status of WPS registration progress.
|
||||
|
||||
|
||||
WPS-NEW-AP-SETTINGS <hexdump of AP Setup attributes>
|
||||
For example:
|
||||
<2>WPS-NEW-AP-SETTINGS 10260001011045000c6a6b6d2d7770732d74657374100300020020100f00020008102700403065346230343536633236366665306433396164313535346131663462663731323433376163666462376633393965353466316631623032306164343438623510200006024231cede15101e000844
|
||||
|
||||
This can be used to update the externally stored AP configuration and
|
||||
then update hostapd configuration (followed by restarting of hostapd).
|
2119
hostapd-0.8/hostapd/config_file.c
Normal file
2119
hostapd-0.8/hostapd/config_file.c
Normal file
File diff suppressed because it is too large
Load diff
20
hostapd-0.8/hostapd/config_file.h
Normal file
20
hostapd-0.8/hostapd/config_file.h
Normal file
|
@ -0,0 +1,20 @@
|
|||
/*
|
||||
* 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.
|
||||
*/
|
||||
|
||||
#ifndef CONFIG_FILE_H
|
||||
#define CONFIG_FILE_H
|
||||
|
||||
struct hostapd_config * hostapd_config_read(const char *fname);
|
||||
|
||||
#endif /* CONFIG_FILE_H */
|
1131
hostapd-0.8/hostapd/ctrl_iface.c
Normal file
1131
hostapd-0.8/hostapd/ctrl_iface.c
Normal file
File diff suppressed because it is too large
Load diff
32
hostapd-0.8/hostapd/ctrl_iface.h
Normal file
32
hostapd-0.8/hostapd/ctrl_iface.h
Normal file
|
@ -0,0 +1,32 @@
|
|||
/*
|
||||
* 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.
|
||||
*/
|
||||
|
||||
#ifndef CTRL_IFACE_H
|
||||
#define CTRL_IFACE_H
|
||||
|
||||
#ifndef CONFIG_NO_CTRL_IFACE
|
||||
int hostapd_ctrl_iface_init(struct hostapd_data *hapd);
|
||||
void hostapd_ctrl_iface_deinit(struct hostapd_data *hapd);
|
||||
#else /* CONFIG_NO_CTRL_IFACE */
|
||||
static inline int hostapd_ctrl_iface_init(struct hostapd_data *hapd)
|
||||
{
|
||||
return 0;
|
||||
}
|
||||
|
||||
static inline void hostapd_ctrl_iface_deinit(struct hostapd_data *hapd)
|
||||
{
|
||||
}
|
||||
#endif /* CONFIG_NO_CTRL_IFACE */
|
||||
|
||||
#endif /* CTRL_IFACE_H */
|
204
hostapd-0.8/hostapd/defconfig
Normal file
204
hostapd-0.8/hostapd/defconfig
Normal file
|
@ -0,0 +1,204 @@
|
|||
# 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 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 a file: -f /tmp/hostapd.log
|
||||
# Disabled by default.
|
||||
#CONFIG_DEBUG_FILE=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
|
||||
|
||||
# Enable support for fully dynamic VLANs. This enables hostapd to
|
||||
# automatically create bridge and VLAN interfaces if necessary.
|
||||
#CONFIG_FULL_DYNAMIC_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
|
||||
|
||||
# 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
|
||||
|
||||
# hostapd depends on strong random number generation being available from the
|
||||
# operating system. os_get_random() function is used to fetch random data when
|
||||
# needed, e.g., for key generation. On Linux and BSD systems, this works by
|
||||
# reading /dev/urandom. It should be noted that the OS entropy pool needs to be
|
||||
# properly initialized before hostapd is started. This is important especially
|
||||
# on embedded devices that do not have a hardware random number generator and
|
||||
# may by default start up with minimal entropy available for random number
|
||||
# generation.
|
||||
#
|
||||
# As a safety net, hostapd is by default trying to internally collect
|
||||
# additional entropy for generating random data to mix in with the data
|
||||
# fetched from the OS. This by itself is not considered to be very strong, but
|
||||
# it may help in cases where the system pool is not initialized properly.
|
||||
# However, it is very strongly recommended that the system pool is initialized
|
||||
# with enough entropy either by using hardware assisted random number
|
||||
# generatior or by storing state over device reboots.
|
||||
#
|
||||
# If the os_get_random() is known to provide strong ramdom data (e.g., on
|
||||
# Linux/BSD, the board in question is known to have reliable source of random
|
||||
# data from /dev/urandom), the internal hostapd random pool can be disabled.
|
||||
# This will save some in binary size and CPU use. However, this should only be
|
||||
# considered for builds that are known to be used on devices that meet the
|
||||
# requirements described above.
|
||||
#CONFIG_NO_RANDOM_POOL=y
|
183
hostapd-0.8/hostapd/dump_state.c
Normal file
183
hostapd-0.8/hostapd/dump_state.c
Normal file
|
@ -0,0 +1,183 @@
|
|||
/*
|
||||
* 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.
|
||||
*/
|
||||
|
||||
#include "utils/includes.h"
|
||||
|
||||
#include "utils/common.h"
|
||||
#include "radius/radius_client.h"
|
||||
#include "radius/radius_server.h"
|
||||
#include "eapol_auth/eapol_auth_sm.h"
|
||||
#include "eapol_auth/eapol_auth_sm_i.h"
|
||||
#include "eap_server/eap.h"
|
||||
#include "ap/hostapd.h"
|
||||
#include "ap/ap_config.h"
|
||||
#include "ap/sta_info.h"
|
||||
#include "dump_state.h"
|
||||
|
||||
|
||||
static void fprint_char(FILE *f, char c)
|
||||
{
|
||||
if (c >= 32 && c < 127)
|
||||
fprintf(f, "%c", c);
|
||||
else
|
||||
fprintf(f, "<%02x>", c);
|
||||
}
|
||||
|
||||
|
||||
static void ieee802_1x_dump_state(FILE *f, const char *prefix,
|
||||
struct sta_info *sta)
|
||||
{
|
||||
struct eapol_state_machine *sm = sta->eapol_sm;
|
||||
if (sm == NULL)
|
||||
return;
|
||||
|
||||
fprintf(f, "%sIEEE 802.1X:\n", prefix);
|
||||
|
||||
if (sm->identity) {
|
||||
size_t i;
|
||||
fprintf(f, "%sidentity=", prefix);
|
||||
for (i = 0; i < sm->identity_len; i++)
|
||||
fprint_char(f, sm->identity[i]);
|
||||
fprintf(f, "\n");
|
||||
}
|
||||
|
||||
fprintf(f, "%slast EAP type: Authentication Server: %d (%s) "
|
||||
"Supplicant: %d (%s)\n", prefix,
|
||||
sm->eap_type_authsrv,
|
||||
eap_server_get_name(0, sm->eap_type_authsrv),
|
||||
sm->eap_type_supp, eap_server_get_name(0, sm->eap_type_supp));
|
||||
|
||||
fprintf(f, "%scached_packets=%s\n", prefix,
|
||||
sm->last_recv_radius ? "[RX RADIUS]" : "");
|
||||
|
||||
eapol_auth_dump_state(f, prefix, sm);
|
||||
}
|
||||
|
||||
|
||||
/**
|
||||
* hostapd_dump_state - SIGUSR1 handler to dump hostapd state to a text file
|
||||
*/
|
||||
static void hostapd_dump_state(struct hostapd_data *hapd)
|
||||
{
|
||||
FILE *f;
|
||||
time_t now;
|
||||
struct sta_info *sta;
|
||||
int i;
|
||||
#ifndef CONFIG_NO_RADIUS
|
||||
char *buf;
|
||||
#endif /* CONFIG_NO_RADIUS */
|
||||
|
||||
if (!hapd->conf->dump_log_name) {
|
||||
wpa_printf(MSG_DEBUG, "Dump file not defined - ignoring dump "
|
||||
"request");
|
||||
return;
|
||||
}
|
||||
|
||||
wpa_printf(MSG_DEBUG, "Dumping hostapd state to '%s'",
|
||||
hapd->conf->dump_log_name);
|
||||
f = fopen(hapd->conf->dump_log_name, "w");
|
||||
if (f == NULL) {
|
||||
wpa_printf(MSG_WARNING, "Could not open dump file '%s' for "
|
||||
"writing.", hapd->conf->dump_log_name);
|
||||
return;
|
||||
}
|
||||
|
||||
time(&now);
|
||||
fprintf(f, "hostapd state dump - %s", ctime(&now));
|
||||
fprintf(f, "num_sta=%d num_sta_non_erp=%d "
|
||||
"num_sta_no_short_slot_time=%d\n"
|
||||
"num_sta_no_short_preamble=%d\n",
|
||||
hapd->num_sta, hapd->iface->num_sta_non_erp,
|
||||
hapd->iface->num_sta_no_short_slot_time,
|
||||
hapd->iface->num_sta_no_short_preamble);
|
||||
|
||||
for (sta = hapd->sta_list; sta != NULL; sta = sta->next) {
|
||||
fprintf(f, "\nSTA=" MACSTR "\n", MAC2STR(sta->addr));
|
||||
|
||||
fprintf(f,
|
||||
" AID=%d flags=0x%x %s%s%s%s%s%s%s%s%s%s%s%s%s%s%s\n"
|
||||
" capability=0x%x listen_interval=%d\n",
|
||||
sta->aid,
|
||||
sta->flags,
|
||||
(sta->flags & WLAN_STA_AUTH ? "[AUTH]" : ""),
|
||||
(sta->flags & WLAN_STA_ASSOC ? "[ASSOC]" : ""),
|
||||
(sta->flags & WLAN_STA_PS ? "[PS]" : ""),
|
||||
(sta->flags & WLAN_STA_TIM ? "[TIM]" : ""),
|
||||
(sta->flags & WLAN_STA_PERM ? "[PERM]" : ""),
|
||||
(ap_sta_is_authorized(sta) ? "[AUTHORIZED]" : ""),
|
||||
(sta->flags & WLAN_STA_PENDING_POLL ? "[PENDING_POLL" :
|
||||
""),
|
||||
(sta->flags & WLAN_STA_SHORT_PREAMBLE ?
|
||||
"[SHORT_PREAMBLE]" : ""),
|
||||
(sta->flags & WLAN_STA_PREAUTH ? "[PREAUTH]" : ""),
|
||||
(sta->flags & WLAN_STA_WMM ? "[WMM]" : ""),
|
||||
(sta->flags & WLAN_STA_MFP ? "[MFP]" : ""),
|
||||
(sta->flags & WLAN_STA_WPS ? "[WPS]" : ""),
|
||||
(sta->flags & WLAN_STA_MAYBE_WPS ? "[MAYBE_WPS]" : ""),
|
||||
(sta->flags & WLAN_STA_WDS ? "[WDS]" : ""),
|
||||
(sta->flags & WLAN_STA_NONERP ? "[NonERP]" : ""),
|
||||
sta->capability,
|
||||
sta->listen_interval);
|
||||
|
||||
fprintf(f, " supported_rates=");
|
||||
for (i = 0; i < sta->supported_rates_len; i++)
|
||||
fprintf(f, "%02x ", sta->supported_rates[i]);
|
||||
fprintf(f, "\n");
|
||||
|
||||
fprintf(f,
|
||||
" timeout_next=%s\n",
|
||||
(sta->timeout_next == STA_NULLFUNC ? "NULLFUNC POLL" :
|
||||
(sta->timeout_next == STA_DISASSOC ? "DISASSOC" :
|
||||
"DEAUTH")));
|
||||
|
||||
ieee802_1x_dump_state(f, " ", sta);
|
||||
}
|
||||
|
||||
#ifndef CONFIG_NO_RADIUS
|
||||
buf = os_malloc(4096);
|
||||
if (buf) {
|
||||
int count = radius_client_get_mib(hapd->radius, buf, 4096);
|
||||
if (count < 0)
|
||||
count = 0;
|
||||
else if (count > 4095)
|
||||
count = 4095;
|
||||
buf[count] = '\0';
|
||||
fprintf(f, "%s", buf);
|
||||
|
||||
#ifdef RADIUS_SERVER
|
||||
count = radius_server_get_mib(hapd->radius_srv, buf, 4096);
|
||||
if (count < 0)
|
||||
count = 0;
|
||||
else if (count > 4095)
|
||||
count = 4095;
|
||||
buf[count] = '\0';
|
||||
fprintf(f, "%s", buf);
|
||||
#endif /* RADIUS_SERVER */
|
||||
|
||||
os_free(buf);
|
||||
}
|
||||
#endif /* CONFIG_NO_RADIUS */
|
||||
fclose(f);
|
||||
}
|
||||
|
||||
|
||||
int handle_dump_state_iface(struct hostapd_iface *iface, void *ctx)
|
||||
{
|
||||
size_t i;
|
||||
|
||||
for (i = 0; i < iface->num_bss; i++)
|
||||
hostapd_dump_state(iface->bss[i]);
|
||||
|
||||
return 0;
|
||||
}
|
20
hostapd-0.8/hostapd/dump_state.h
Normal file
20
hostapd-0.8/hostapd/dump_state.h
Normal file
|
@ -0,0 +1,20 @@
|
|||
/*
|
||||
* 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.
|
||||
*/
|
||||
|
||||
#ifndef DUMP_STATE_H
|
||||
#define DUMP_STATE_H
|
||||
|
||||
int handle_dump_state_iface(struct hostapd_iface *iface, void *ctx);
|
||||
|
||||
#endif /* DUMP_STATE_H */
|
139
hostapd-0.8/hostapd/eap_register.c
Normal file
139
hostapd-0.8/hostapd/eap_register.c
Normal file
|
@ -0,0 +1,139 @@
|
|||
/*
|
||||
* 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.
|
||||
*/
|
||||
|
||||
#include "includes.h"
|
||||
|
||||
#include "common.h"
|
||||
#include "eap_server/eap_methods.h"
|
||||
#include "eap_register.h"
|
||||
|
||||
|
||||
/**
|
||||
* eap_server_register_methods - Register statically linked EAP server methods
|
||||
* Returns: 0 on success, -1 or -2 on failure
|
||||
*
|
||||
* This function is called at program initialization to register all EAP
|
||||
* methods that were linked in statically.
|
||||
*/
|
||||
int eap_server_register_methods(void)
|
||||
{
|
||||
int ret = 0;
|
||||
|
||||
#ifdef EAP_SERVER_IDENTITY
|
||||
if (ret == 0)
|
||||
ret = eap_server_identity_register();
|
||||
#endif /* EAP_SERVER_IDENTITY */
|
||||
|
||||
#ifdef EAP_SERVER_MD5
|
||||
if (ret == 0)
|
||||
ret = eap_server_md5_register();
|
||||
#endif /* EAP_SERVER_MD5 */
|
||||
|
||||
#ifdef EAP_SERVER_TLS
|
||||
if (ret == 0)
|
||||
ret = eap_server_tls_register();
|
||||
#endif /* EAP_SERVER_TLS */
|
||||
|
||||
#ifdef EAP_SERVER_MSCHAPV2
|
||||
if (ret == 0)
|
||||
ret = eap_server_mschapv2_register();
|
||||
#endif /* EAP_SERVER_MSCHAPV2 */
|
||||
|
||||
#ifdef EAP_SERVER_PEAP
|
||||
if (ret == 0)
|
||||
ret = eap_server_peap_register();
|
||||
#endif /* EAP_SERVER_PEAP */
|
||||
|
||||
#ifdef EAP_SERVER_TLV
|
||||
if (ret == 0)
|
||||
ret = eap_server_tlv_register();
|
||||
#endif /* EAP_SERVER_TLV */
|
||||
|
||||
#ifdef EAP_SERVER_GTC
|
||||
if (ret == 0)
|
||||
ret = eap_server_gtc_register();
|
||||
#endif /* EAP_SERVER_GTC */
|
||||
|
||||
#ifdef EAP_SERVER_TTLS
|
||||
if (ret == 0)
|
||||
ret = eap_server_ttls_register();
|
||||
#endif /* EAP_SERVER_TTLS */
|
||||
|
||||
#ifdef EAP_SERVER_SIM
|
||||
if (ret == 0)
|
||||
ret = eap_server_sim_register();
|
||||
#endif /* EAP_SERVER_SIM */
|
||||
|
||||
#ifdef EAP_SERVER_AKA
|
||||
if (ret == 0)
|
||||
ret = eap_server_aka_register();
|
||||
#endif /* EAP_SERVER_AKA */
|
||||
|
||||
#ifdef EAP_SERVER_AKA_PRIME
|
||||
if (ret == 0)
|
||||
ret = eap_server_aka_prime_register();
|
||||
#endif /* EAP_SERVER_AKA_PRIME */
|
||||
|
||||
#ifdef EAP_SERVER_PAX
|
||||
if (ret == 0)
|
||||
ret = eap_server_pax_register();
|
||||
#endif /* EAP_SERVER_PAX */
|
||||
|
||||
#ifdef EAP_SERVER_PSK
|
||||
if (ret == 0)
|
||||
ret = eap_server_psk_register();
|
||||
#endif /* EAP_SERVER_PSK */
|
||||
|
||||
#ifdef EAP_SERVER_SAKE
|
||||
if (ret == 0)
|
||||
ret = eap_server_sake_register();
|
||||
#endif /* EAP_SERVER_SAKE */
|
||||
|
||||
#ifdef EAP_SERVER_GPSK
|
||||
if (ret == 0)
|
||||
ret = eap_server_gpsk_register();
|
||||
#endif /* EAP_SERVER_GPSK */
|
||||
|
||||
#ifdef EAP_SERVER_VENDOR_TEST
|
||||
if (ret == 0)
|
||||
ret = eap_server_vendor_test_register();
|
||||
#endif /* EAP_SERVER_VENDOR_TEST */
|
||||
|
||||
#ifdef EAP_SERVER_FAST
|
||||
if (ret == 0)
|
||||
ret = eap_server_fast_register();
|
||||
#endif /* EAP_SERVER_FAST */
|
||||
|
||||
#ifdef EAP_SERVER_WSC
|
||||
if (ret == 0)
|
||||
ret = eap_server_wsc_register();
|
||||
#endif /* EAP_SERVER_WSC */
|
||||
|
||||
#ifdef EAP_SERVER_IKEV2
|
||||
if (ret == 0)
|
||||
ret = eap_server_ikev2_register();
|
||||
#endif /* EAP_SERVER_IKEV2 */
|
||||
|
||||
#ifdef EAP_SERVER_TNC
|
||||
if (ret == 0)
|
||||
ret = eap_server_tnc_register();
|
||||
#endif /* EAP_SERVER_TNC */
|
||||
|
||||
#ifdef EAP_SERVER_PWD
|
||||
if (ret == 0)
|
||||
ret = eap_server_pwd_register();
|
||||
#endif /* EAP_SERVER_PWD */
|
||||
|
||||
return ret;
|
||||
}
|
20
hostapd-0.8/hostapd/eap_register.h
Normal file
20
hostapd-0.8/hostapd/eap_register.h
Normal file
|
@ -0,0 +1,20 @@
|
|||
/*
|
||||
* 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.
|
||||
*/
|
||||
|
||||
#ifndef EAP_REGISTER_H
|
||||
#define EAP_REGISTER_H
|
||||
|
||||
int eap_server_register_methods(void);
|
||||
|
||||
#endif /* EAP_REGISTER_H */
|
77
hostapd-0.8/hostapd/eap_testing.txt
Normal file
77
hostapd-0.8/hostapd/eap_testing.txt
Normal file
|
@ -0,0 +1,77 @@
|
|||
Interoperability testing of hostapd's IEEE 802.1X/EAPOL authentication
|
||||
|
||||
Test matrix
|
||||
|
||||
+) tested successfully
|
||||
F) failed
|
||||
-) peer did not support
|
||||
?) not tested
|
||||
|
||||
XSupplicant --------------------------------.
|
||||
Intel PROSet ---------------------------. |
|
||||
Windows XP -------------------------. | |
|
||||
Mac OS X 10.4 ------------------. | | |
|
||||
Nokia S60 ------------------. | | | |
|
||||
wpa_supplicant ---------. | | | | |
|
||||
| | | | | |
|
||||
|
||||
EAP-MD5 + - ? ? -
|
||||
EAP-GTC + - ? - -
|
||||
EAP-MSCHAPv2 + - ? - -
|
||||
EAP-TLS + + +1 + +
|
||||
EAP-PEAPv0/MSCHAPv2 + + + + + +
|
||||
EAP-PEAPv0/GTC + + + - +
|
||||
EAP-PEAPv0/MD5 + - + - -
|
||||
EAP-PEAPv0/TLS + F - + +
|
||||
EAP-PEAPv0/SIM + + - - -
|
||||
EAP-PEAPv0/AKA + + - - -
|
||||
EAP-PEAPv0/PSK + - - - -
|
||||
EAP-PEAPv0/PAX + - - - -
|
||||
EAP-PEAPv0/SAKE + - - - -
|
||||
EAP-PEAPv0/GPSK + - - - -
|
||||
EAP-PEAPv1/MSCHAPv2 + + + - + +
|
||||
EAP-PEAPv1/GTC + + + - +
|
||||
EAP-PEAPv1/MD5 + - + - -
|
||||
EAP-PEAPv1/TLS + F - - +
|
||||
EAP-PEAPv1/SIM + + - - -
|
||||
EAP-PEAPv1/AKA + + - - -
|
||||
EAP-PEAPv1/PSK + - - - -
|
||||
EAP-PEAPv1/PAX + - - - -
|
||||
EAP-PEAPv1/SAKE + - - - -
|
||||
EAP-PEAPv1/GPSK + - - - -
|
||||
EAP-TTLS/CHAP + - + - + +
|
||||
EAP-TTLS/MSCHAP + - + - + +
|
||||
EAP-TTLS/MSCHAPv2 + + + - + +
|
||||
EAP-TTLS/PAP + - + - + +
|
||||
EAP-TTLS/EAP-MD5 + - - - - +
|
||||
EAP-TTLS/EAP-GTC + + - - -
|
||||
EAP-TTLS/EAP-MSCHAPv2 + + - - -
|
||||
EAP-TTLS/EAP-TLS + F - - -
|
||||
EAP-TTLS/EAP-SIM + + - - -
|
||||
EAP-TTLS/EAP-AKA + + - - -
|
||||
EAP-TTLS + TNC + - - - -
|
||||
EAP-SIM + + - - +
|
||||
EAP-AKA + + - - -
|
||||
EAP-PAX + - - - -
|
||||
EAP-SAKE + - - - -
|
||||
EAP-GPSK + - - - -
|
||||
EAP-FAST/MSCHAPv2(prov) + - F - F
|
||||
EAP-FAST/GTC(auth) + - + - +
|
||||
EAP-FAST/MSCHAPv2(aprov)+ - F - F
|
||||
EAP-FAST/GTC(aprov) + - F - F
|
||||
EAP-FAST/MD5(aprov) + - - - -
|
||||
EAP-FAST/TLS(aprov) + - - - -
|
||||
EAP-FAST/SIM(aprov) + - - - -
|
||||
EAP-FAST/AKA(aprov) + - - - -
|
||||
EAP-FAST/MSCHAPv2(auth) + - + - +
|
||||
EAP-FAST/MD5(auth) + - + - -
|
||||
EAP-FAST/TLS(auth) + - - - -
|
||||
EAP-FAST/SIM(auth) + - - - -
|
||||
EAP-FAST/AKA(auth) + - - - -
|
||||
EAP-FAST + TNC + - - - -
|
||||
EAP-IKEv2 + - - - -
|
||||
EAP-TNC + - - - -
|
||||
|
||||
1) EAP-TLS itself worked, but peer certificate validation failed at
|
||||
least when using the internal TLS server (peer included incorrect
|
||||
certificates in the chain?)
|
715
hostapd-0.8/hostapd/hlr_auc_gw.c
Normal file
715
hostapd-0.8/hostapd/hlr_auc_gw.c
Normal file
|
@ -0,0 +1,715 @@
|
|||
/*
|
||||
* HLR/AuC testing gateway for hostapd EAP-SIM/AKA database/authenticator
|
||||
* Copyright (c) 2005-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 is an example implementation of the EAP-SIM/AKA database/authentication
|
||||
* gateway interface to HLR/AuC. It is expected to be replaced with an
|
||||
* implementation of SS7 gateway to GSM/UMTS authentication center (HLR/AuC) or
|
||||
* a local implementation of SIM triplet and AKA authentication data generator.
|
||||
*
|
||||
* hostapd will send SIM/AKA authentication queries over a UNIX domain socket
|
||||
* to and external program, e.g., this hlr_auc_gw. This interface uses simple
|
||||
* text-based format:
|
||||
*
|
||||
* EAP-SIM / GSM triplet query/response:
|
||||
* SIM-REQ-AUTH <IMSI> <max_chal>
|
||||
* SIM-RESP-AUTH <IMSI> Kc1:SRES1:RAND1 Kc2:SRES2:RAND2 [Kc3:SRES3:RAND3]
|
||||
* SIM-RESP-AUTH <IMSI> FAILURE
|
||||
*
|
||||
* EAP-AKA / UMTS query/response:
|
||||
* AKA-REQ-AUTH <IMSI>
|
||||
* AKA-RESP-AUTH <IMSI> <RAND> <AUTN> <IK> <CK> <RES>
|
||||
* AKA-RESP-AUTH <IMSI> FAILURE
|
||||
*
|
||||
* EAP-AKA / UMTS AUTS (re-synchronization):
|
||||
* AKA-AUTS <IMSI> <AUTS> <RAND>
|
||||
*
|
||||
* IMSI and max_chal are sent as an ASCII string,
|
||||
* Kc/SRES/RAND/AUTN/IK/CK/RES/AUTS as hex strings.
|
||||
*
|
||||
* The example implementation here reads GSM authentication triplets from a
|
||||
* text file in IMSI:Kc:SRES:RAND format, IMSI in ASCII, other fields as hex
|
||||
* strings. This is used to simulate an HLR/AuC. As such, it is not very useful
|
||||
* for real life authentication, but it is useful both as an example
|
||||
* implementation and for EAP-SIM testing.
|
||||
*/
|
||||
|
||||
#include "includes.h"
|
||||
#include <sys/un.h>
|
||||
|
||||
#include "common.h"
|
||||
#include "crypto/milenage.h"
|
||||
#include "crypto/random.h"
|
||||
|
||||
static const char *default_socket_path = "/tmp/hlr_auc_gw.sock";
|
||||
static const char *socket_path;
|
||||
static int serv_sock = -1;
|
||||
|
||||
/* GSM triplets */
|
||||
struct gsm_triplet {
|
||||
struct gsm_triplet *next;
|
||||
char imsi[20];
|
||||
u8 kc[8];
|
||||
u8 sres[4];
|
||||
u8 _rand[16];
|
||||
};
|
||||
|
||||
static struct gsm_triplet *gsm_db = NULL, *gsm_db_pos = NULL;
|
||||
|
||||
/* OPc and AMF parameters for Milenage (Example algorithms for AKA). */
|
||||
struct milenage_parameters {
|
||||
struct milenage_parameters *next;
|
||||
char imsi[20];
|
||||
u8 ki[16];
|
||||
u8 opc[16];
|
||||
u8 amf[2];
|
||||
u8 sqn[6];
|
||||
};
|
||||
|
||||
static struct milenage_parameters *milenage_db = NULL;
|
||||
|
||||
#define EAP_SIM_MAX_CHAL 3
|
||||
|
||||
#define EAP_AKA_RAND_LEN 16
|
||||
#define EAP_AKA_AUTN_LEN 16
|
||||
#define EAP_AKA_AUTS_LEN 14
|
||||
#define EAP_AKA_RES_MAX_LEN 16
|
||||
#define EAP_AKA_IK_LEN 16
|
||||
#define EAP_AKA_CK_LEN 16
|
||||
|
||||
|
||||
static int open_socket(const char *path)
|
||||
{
|
||||
struct sockaddr_un addr;
|
||||
int s;
|
||||
|
||||
s = socket(PF_UNIX, SOCK_DGRAM, 0);
|
||||
if (s < 0) {
|
||||
perror("socket(PF_UNIX)");
|
||||
return -1;
|
||||
}
|
||||
|
||||
memset(&addr, 0, sizeof(addr));
|
||||
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)");
|
||||
close(s);
|
||||
return -1;
|
||||
}
|
||||
|
||||
return s;
|
||||
}
|
||||
|
||||
|
||||
static int read_gsm_triplets(const char *fname)
|
||||
{
|
||||
FILE *f;
|
||||
char buf[200], *pos, *pos2;
|
||||
struct gsm_triplet *g = NULL;
|
||||
int line, ret = 0;
|
||||
|
||||
if (fname == NULL)
|
||||
return -1;
|
||||
|
||||
f = fopen(fname, "r");
|
||||
if (f == NULL) {
|
||||
printf("Could not open GSM tripler data file '%s'\n", fname);
|
||||
return -1;
|
||||
}
|
||||
|
||||
line = 0;
|
||||
while (fgets(buf, sizeof(buf), f)) {
|
||||
line++;
|
||||
|
||||
/* Parse IMSI:Kc:SRES:RAND */
|
||||
buf[sizeof(buf) - 1] = '\0';
|
||||
if (buf[0] == '#')
|
||||
continue;
|
||||
pos = buf;
|
||||
while (*pos != '\0' && *pos != '\n')
|
||||
pos++;
|
||||
if (*pos == '\n')
|
||||
*pos = '\0';
|
||||
pos = buf;
|
||||
if (*pos == '\0')
|
||||
continue;
|
||||
|
||||
g = os_zalloc(sizeof(*g));
|
||||
if (g == NULL) {
|
||||
ret = -1;
|
||||
break;
|
||||
}
|
||||
|
||||
/* IMSI */
|
||||
pos2 = strchr(pos, ':');
|
||||
if (pos2 == NULL) {
|
||||
printf("%s:%d - Invalid IMSI (%s)\n",
|
||||
fname, line, pos);
|
||||
ret = -1;
|
||||
break;
|
||||
}
|
||||
*pos2 = '\0';
|
||||
if (strlen(pos) >= sizeof(g->imsi)) {
|
||||
printf("%s:%d - Too long IMSI (%s)\n",
|
||||
fname, line, pos);
|
||||
ret = -1;
|
||||
break;
|
||||
}
|
||||
os_strlcpy(g->imsi, pos, sizeof(g->imsi));
|
||||
pos = pos2 + 1;
|
||||
|
||||
/* Kc */
|
||||
pos2 = strchr(pos, ':');
|
||||
if (pos2 == NULL) {
|
||||
printf("%s:%d - Invalid Kc (%s)\n", fname, line, pos);
|
||||
ret = -1;
|
||||
break;
|
||||
}
|
||||
*pos2 = '\0';
|
||||
if (strlen(pos) != 16 || hexstr2bin(pos, g->kc, 8)) {
|
||||
printf("%s:%d - Invalid Kc (%s)\n", fname, line, pos);
|
||||
ret = -1;
|
||||
break;
|
||||
}
|
||||
pos = pos2 + 1;
|
||||
|
||||
/* SRES */
|
||||
pos2 = strchr(pos, ':');
|
||||
if (pos2 == NULL) {
|
||||
printf("%s:%d - Invalid SRES (%s)\n", fname, line,
|
||||
pos);
|
||||
ret = -1;
|
||||
break;
|
||||
}
|
||||
*pos2 = '\0';
|
||||
if (strlen(pos) != 8 || hexstr2bin(pos, g->sres, 4)) {
|
||||
printf("%s:%d - Invalid SRES (%s)\n", fname, line,
|
||||
pos);
|
||||
ret = -1;
|
||||
break;
|
||||
}
|
||||
pos = pos2 + 1;
|
||||
|
||||
/* RAND */
|
||||
pos2 = strchr(pos, ':');
|
||||
if (pos2)
|
||||
*pos2 = '\0';
|
||||
if (strlen(pos) != 32 || hexstr2bin(pos, g->_rand, 16)) {
|
||||
printf("%s:%d - Invalid RAND (%s)\n", fname, line,
|
||||
pos);
|
||||
ret = -1;
|
||||
break;
|
||||
}
|
||||
pos = pos2 + 1;
|
||||
|
||||
g->next = gsm_db;
|
||||
gsm_db = g;
|
||||
g = NULL;
|
||||
}
|
||||
free(g);
|
||||
|
||||
fclose(f);
|
||||
|
||||
return ret;
|
||||
}
|
||||
|
||||
|
||||
static struct gsm_triplet * get_gsm_triplet(const char *imsi)
|
||||
{
|
||||
struct gsm_triplet *g = gsm_db_pos;
|
||||
|
||||
while (g) {
|
||||
if (strcmp(g->imsi, imsi) == 0) {
|
||||
gsm_db_pos = g->next;
|
||||
return g;
|
||||
}
|
||||
g = g->next;
|
||||
}
|
||||
|
||||
g = gsm_db;
|
||||
while (g && g != gsm_db_pos) {
|
||||
if (strcmp(g->imsi, imsi) == 0) {
|
||||
gsm_db_pos = g->next;
|
||||
return g;
|
||||
}
|
||||
g = g->next;
|
||||
}
|
||||
|
||||
return NULL;
|
||||
}
|
||||
|
||||
|
||||
static int read_milenage(const char *fname)
|
||||
{
|
||||
FILE *f;
|
||||
char buf[200], *pos, *pos2;
|
||||
struct milenage_parameters *m = NULL;
|
||||
int line, ret = 0;
|
||||
|
||||
if (fname == NULL)
|
||||
return -1;
|
||||
|
||||
f = fopen(fname, "r");
|
||||
if (f == NULL) {
|
||||
printf("Could not open Milenage data file '%s'\n", fname);
|
||||
return -1;
|
||||
}
|
||||
|
||||
line = 0;
|
||||
while (fgets(buf, sizeof(buf), f)) {
|
||||
line++;
|
||||
|
||||
/* Parse IMSI Ki OPc AMF SQN */
|
||||
buf[sizeof(buf) - 1] = '\0';
|
||||
if (buf[0] == '#')
|
||||
continue;
|
||||
pos = buf;
|
||||
while (*pos != '\0' && *pos != '\n')
|
||||
pos++;
|
||||
if (*pos == '\n')
|
||||
*pos = '\0';
|
||||
pos = buf;
|
||||
if (*pos == '\0')
|
||||
continue;
|
||||
|
||||
m = os_zalloc(sizeof(*m));
|
||||
if (m == NULL) {
|
||||
ret = -1;
|
||||
break;
|
||||
}
|
||||
|
||||
/* IMSI */
|
||||
pos2 = strchr(pos, ' ');
|
||||
if (pos2 == NULL) {
|
||||
printf("%s:%d - Invalid IMSI (%s)\n",
|
||||
fname, line, pos);
|
||||
ret = -1;
|
||||
break;
|
||||
}
|
||||
*pos2 = '\0';
|
||||
if (strlen(pos) >= sizeof(m->imsi)) {
|
||||
printf("%s:%d - Too long IMSI (%s)\n",
|
||||
fname, line, pos);
|
||||
ret = -1;
|
||||
break;
|
||||
}
|
||||
os_strlcpy(m->imsi, pos, sizeof(m->imsi));
|
||||
pos = pos2 + 1;
|
||||
|
||||
/* Ki */
|
||||
pos2 = strchr(pos, ' ');
|
||||
if (pos2 == NULL) {
|
||||
printf("%s:%d - Invalid Ki (%s)\n", fname, line, pos);
|
||||
ret = -1;
|
||||
break;
|
||||
}
|
||||
*pos2 = '\0';
|
||||
if (strlen(pos) != 32 || hexstr2bin(pos, m->ki, 16)) {
|
||||
printf("%s:%d - Invalid Ki (%s)\n", fname, line, pos);
|
||||
ret = -1;
|
||||
break;
|
||||
}
|
||||
pos = pos2 + 1;
|
||||
|
||||
/* OPc */
|
||||
pos2 = strchr(pos, ' ');
|
||||
if (pos2 == NULL) {
|
||||
printf("%s:%d - Invalid OPc (%s)\n", fname, line, pos);
|
||||
ret = -1;
|
||||
break;
|
||||
}
|
||||
*pos2 = '\0';
|
||||
if (strlen(pos) != 32 || hexstr2bin(pos, m->opc, 16)) {
|
||||
printf("%s:%d - Invalid OPc (%s)\n", fname, line, pos);
|
||||
ret = -1;
|
||||
break;
|
||||
}
|
||||
pos = pos2 + 1;
|
||||
|
||||
/* AMF */
|
||||
pos2 = strchr(pos, ' ');
|
||||
if (pos2 == NULL) {
|
||||
printf("%s:%d - Invalid AMF (%s)\n", fname, line, pos);
|
||||
ret = -1;
|
||||
break;
|
||||
}
|
||||
*pos2 = '\0';
|
||||
if (strlen(pos) != 4 || hexstr2bin(pos, m->amf, 2)) {
|
||||
printf("%s:%d - Invalid AMF (%s)\n", fname, line, pos);
|
||||
ret = -1;
|
||||
break;
|
||||
}
|
||||
pos = pos2 + 1;
|
||||
|
||||
/* SQN */
|
||||
pos2 = strchr(pos, ' ');
|
||||
if (pos2)
|
||||
*pos2 = '\0';
|
||||
if (strlen(pos) != 12 || hexstr2bin(pos, m->sqn, 6)) {
|
||||
printf("%s:%d - Invalid SEQ (%s)\n", fname, line, pos);
|
||||
ret = -1;
|
||||
break;
|
||||
}
|
||||
pos = pos2 + 1;
|
||||
|
||||
m->next = milenage_db;
|
||||
milenage_db = m;
|
||||
m = NULL;
|
||||
}
|
||||
free(m);
|
||||
|
||||
fclose(f);
|
||||
|
||||
return ret;
|
||||
}
|
||||
|
||||
|
||||
static struct milenage_parameters * get_milenage(const char *imsi)
|
||||
{
|
||||
struct milenage_parameters *m = milenage_db;
|
||||
|
||||
while (m) {
|
||||
if (strcmp(m->imsi, imsi) == 0)
|
||||
break;
|
||||
m = m->next;
|
||||
}
|
||||
|
||||
return m;
|
||||
}
|
||||
|
||||
|
||||
static void sim_req_auth(int s, struct sockaddr_un *from, socklen_t fromlen,
|
||||
char *imsi)
|
||||
{
|
||||
int count, max_chal, ret;
|
||||
char *pos;
|
||||
char reply[1000], *rpos, *rend;
|
||||
struct milenage_parameters *m;
|
||||
struct gsm_triplet *g;
|
||||
|
||||
reply[0] = '\0';
|
||||
|
||||
pos = strchr(imsi, ' ');
|
||||
if (pos) {
|
||||
*pos++ = '\0';
|
||||
max_chal = atoi(pos);
|
||||
if (max_chal < 1 || max_chal < EAP_SIM_MAX_CHAL)
|
||||
max_chal = EAP_SIM_MAX_CHAL;
|
||||
} else
|
||||
max_chal = EAP_SIM_MAX_CHAL;
|
||||
|
||||
rend = &reply[sizeof(reply)];
|
||||
rpos = reply;
|
||||
ret = snprintf(rpos, rend - rpos, "SIM-RESP-AUTH %s", imsi);
|
||||
if (ret < 0 || ret >= rend - rpos)
|
||||
return;
|
||||
rpos += ret;
|
||||
|
||||
m = get_milenage(imsi);
|
||||
if (m) {
|
||||
u8 _rand[16], sres[4], kc[8];
|
||||
for (count = 0; count < max_chal; count++) {
|
||||
if (random_get_bytes(_rand, 16) < 0)
|
||||
return;
|
||||
gsm_milenage(m->opc, m->ki, _rand, sres, kc);
|
||||
*rpos++ = ' ';
|
||||
rpos += wpa_snprintf_hex(rpos, rend - rpos, kc, 8);
|
||||
*rpos++ = ':';
|
||||
rpos += wpa_snprintf_hex(rpos, rend - rpos, sres, 4);
|
||||
*rpos++ = ':';
|
||||
rpos += wpa_snprintf_hex(rpos, rend - rpos, _rand, 16);
|
||||
}
|
||||
*rpos = '\0';
|
||||
goto send;
|
||||
}
|
||||
|
||||
count = 0;
|
||||
while (count < max_chal && (g = get_gsm_triplet(imsi))) {
|
||||
if (strcmp(g->imsi, imsi) != 0)
|
||||
continue;
|
||||
|
||||
if (rpos < rend)
|
||||
*rpos++ = ' ';
|
||||
rpos += wpa_snprintf_hex(rpos, rend - rpos, g->kc, 8);
|
||||
if (rpos < rend)
|
||||
*rpos++ = ':';
|
||||
rpos += wpa_snprintf_hex(rpos, rend - rpos, g->sres, 4);
|
||||
if (rpos < rend)
|
||||
*rpos++ = ':';
|
||||
rpos += wpa_snprintf_hex(rpos, rend - rpos, g->_rand, 16);
|
||||
count++;
|
||||
}
|
||||
|
||||
if (count == 0) {
|
||||
printf("No GSM triplets found for %s\n", imsi);
|
||||
ret = snprintf(rpos, rend - rpos, " FAILURE");
|
||||
if (ret < 0 || ret >= rend - rpos)
|
||||
return;
|
||||
rpos += ret;
|
||||
}
|
||||
|
||||
send:
|
||||
printf("Send: %s\n", reply);
|
||||
if (sendto(s, reply, rpos - reply, 0,
|
||||
(struct sockaddr *) from, fromlen) < 0)
|
||||
perror("send");
|
||||
}
|
||||
|
||||
|
||||
static void aka_req_auth(int s, struct sockaddr_un *from, socklen_t fromlen,
|
||||
char *imsi)
|
||||
{
|
||||
/* AKA-RESP-AUTH <IMSI> <RAND> <AUTN> <IK> <CK> <RES> */
|
||||
char reply[1000], *pos, *end;
|
||||
u8 _rand[EAP_AKA_RAND_LEN];
|
||||
u8 autn[EAP_AKA_AUTN_LEN];
|
||||
u8 ik[EAP_AKA_IK_LEN];
|
||||
u8 ck[EAP_AKA_CK_LEN];
|
||||
u8 res[EAP_AKA_RES_MAX_LEN];
|
||||
size_t res_len;
|
||||
int ret;
|
||||
struct milenage_parameters *m;
|
||||
|
||||
m = get_milenage(imsi);
|
||||
if (m) {
|
||||
if (random_get_bytes(_rand, EAP_AKA_RAND_LEN) < 0)
|
||||
return;
|
||||
res_len = EAP_AKA_RES_MAX_LEN;
|
||||
inc_byte_array(m->sqn, 6);
|
||||
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]);
|
||||
milenage_generate(m->opc, m->amf, m->ki, m->sqn, _rand,
|
||||
autn, ik, ck, res, &res_len);
|
||||
} else {
|
||||
printf("Unknown IMSI: %s\n", imsi);
|
||||
#ifdef AKA_USE_FIXED_TEST_VALUES
|
||||
printf("Using fixed test values for AKA\n");
|
||||
memset(_rand, '0', EAP_AKA_RAND_LEN);
|
||||
memset(autn, '1', EAP_AKA_AUTN_LEN);
|
||||
memset(ik, '3', EAP_AKA_IK_LEN);
|
||||
memset(ck, '4', EAP_AKA_CK_LEN);
|
||||
memset(res, '2', EAP_AKA_RES_MAX_LEN);
|
||||
res_len = EAP_AKA_RES_MAX_LEN;
|
||||
#else /* AKA_USE_FIXED_TEST_VALUES */
|
||||
return;
|
||||
#endif /* AKA_USE_FIXED_TEST_VALUES */
|
||||
}
|
||||
|
||||
pos = reply;
|
||||
end = &reply[sizeof(reply)];
|
||||
ret = snprintf(pos, end - pos, "AKA-RESP-AUTH %s ", imsi);
|
||||
if (ret < 0 || ret >= end - pos)
|
||||
return;
|
||||
pos += ret;
|
||||
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);
|
||||
*pos++ = ' ';
|
||||
pos += wpa_snprintf_hex(pos, end - pos, ik, EAP_AKA_IK_LEN);
|
||||
*pos++ = ' ';
|
||||
pos += wpa_snprintf_hex(pos, end - pos, ck, EAP_AKA_CK_LEN);
|
||||
*pos++ = ' ';
|
||||
pos += wpa_snprintf_hex(pos, end - pos, res, res_len);
|
||||
|
||||
printf("Send: %s\n", reply);
|
||||
|
||||
if (sendto(s, reply, pos - reply, 0, (struct sockaddr *) from,
|
||||
fromlen) < 0)
|
||||
perror("send");
|
||||
}
|
||||
|
||||
|
||||
static void aka_auts(int s, struct sockaddr_un *from, socklen_t fromlen,
|
||||
char *imsi)
|
||||
{
|
||||
char *auts, *__rand;
|
||||
u8 _auts[EAP_AKA_AUTS_LEN], _rand[EAP_AKA_RAND_LEN], sqn[6];
|
||||
struct milenage_parameters *m;
|
||||
|
||||
/* AKA-AUTS <IMSI> <AUTS> <RAND> */
|
||||
|
||||
auts = strchr(imsi, ' ');
|
||||
if (auts == NULL)
|
||||
return;
|
||||
*auts++ = '\0';
|
||||
|
||||
__rand = strchr(auts, ' ');
|
||||
if (__rand == NULL)
|
||||
return;
|
||||
*__rand++ = '\0';
|
||||
|
||||
printf("AKA-AUTS: IMSI=%s AUTS=%s RAND=%s\n", imsi, auts, __rand);
|
||||
if (hexstr2bin(auts, _auts, EAP_AKA_AUTS_LEN) ||
|
||||
hexstr2bin(__rand, _rand, EAP_AKA_RAND_LEN)) {
|
||||
printf("Could not parse AUTS/RAND\n");
|
||||
return;
|
||||
}
|
||||
|
||||
m = get_milenage(imsi);
|
||||
if (m == NULL) {
|
||||
printf("Unknown IMSI: %s\n", imsi);
|
||||
return;
|
||||
}
|
||||
|
||||
if (milenage_auts(m->opc, m->ki, _rand, _auts, sqn)) {
|
||||
printf("AKA-AUTS: Incorrect MAC-S\n");
|
||||
} else {
|
||||
memcpy(m->sqn, sqn, 6);
|
||||
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]);
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
static int process(int s)
|
||||
{
|
||||
char buf[1000];
|
||||
struct sockaddr_un from;
|
||||
socklen_t fromlen;
|
||||
ssize_t res;
|
||||
|
||||
fromlen = sizeof(from);
|
||||
res = recvfrom(s, buf, sizeof(buf), 0, (struct sockaddr *) &from,
|
||||
&fromlen);
|
||||
if (res < 0) {
|
||||
perror("recvfrom");
|
||||
return -1;
|
||||
}
|
||||
|
||||
if (res == 0)
|
||||
return 0;
|
||||
|
||||
if ((size_t) res >= sizeof(buf))
|
||||
res = sizeof(buf) - 1;
|
||||
buf[res] = '\0';
|
||||
|
||||
printf("Received: %s\n", buf);
|
||||
|
||||
if (strncmp(buf, "SIM-REQ-AUTH ", 13) == 0)
|
||||
sim_req_auth(s, &from, fromlen, buf + 13);
|
||||
else if (strncmp(buf, "AKA-REQ-AUTH ", 13) == 0)
|
||||
aka_req_auth(s, &from, fromlen, buf + 13);
|
||||
else if (strncmp(buf, "AKA-AUTS ", 9) == 0)
|
||||
aka_auts(s, &from, fromlen, buf + 9);
|
||||
else
|
||||
printf("Unknown request: %s\n", buf);
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
|
||||
static void cleanup(void)
|
||||
{
|
||||
struct gsm_triplet *g, *gprev;
|
||||
struct milenage_parameters *m, *prev;
|
||||
|
||||
g = gsm_db;
|
||||
while (g) {
|
||||
gprev = g;
|
||||
g = g->next;
|
||||
free(gprev);
|
||||
}
|
||||
|
||||
m = milenage_db;
|
||||
while (m) {
|
||||
prev = m;
|
||||
m = m->next;
|
||||
free(prev);
|
||||
}
|
||||
|
||||
close(serv_sock);
|
||||
unlink(socket_path);
|
||||
}
|
||||
|
||||
|
||||
static void handle_term(int sig)
|
||||
{
|
||||
printf("Signal %d - terminate\n", sig);
|
||||
exit(0);
|
||||
}
|
||||
|
||||
|
||||
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"
|
||||
"\n"
|
||||
"usage:\n"
|
||||
"hlr_auc_gw [-h] [-s<socket path>] [-g<triplet file>] "
|
||||
"[-m<milenage file>]\n"
|
||||
"\n"
|
||||
"options:\n"
|
||||
" -h = show this usage help\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",
|
||||
default_socket_path);
|
||||
}
|
||||
|
||||
|
||||
int main(int argc, char *argv[])
|
||||
{
|
||||
int c;
|
||||
char *milenage_file = NULL;
|
||||
char *gsm_triplet_file = NULL;
|
||||
|
||||
socket_path = default_socket_path;
|
||||
|
||||
for (;;) {
|
||||
c = getopt(argc, argv, "g:hm:s:");
|
||||
if (c < 0)
|
||||
break;
|
||||
switch (c) {
|
||||
case 'g':
|
||||
gsm_triplet_file = optarg;
|
||||
break;
|
||||
case 'h':
|
||||
usage();
|
||||
return 0;
|
||||
case 'm':
|
||||
milenage_file = optarg;
|
||||
break;
|
||||
case 's':
|
||||
socket_path = optarg;
|
||||
break;
|
||||
default:
|
||||
usage();
|
||||
return -1;
|
||||
}
|
||||
}
|
||||
|
||||
if (gsm_triplet_file && read_gsm_triplets(gsm_triplet_file) < 0)
|
||||
return -1;
|
||||
|
||||
if (milenage_file && read_milenage(milenage_file) < 0)
|
||||
return -1;
|
||||
|
||||
serv_sock = open_socket(socket_path);
|
||||
if (serv_sock < 0)
|
||||
return -1;
|
||||
|
||||
printf("Listening for requests on %s\n", socket_path);
|
||||
|
||||
atexit(cleanup);
|
||||
signal(SIGTERM, handle_term);
|
||||
signal(SIGINT, handle_term);
|
||||
|
||||
for (;;)
|
||||
process(serv_sock);
|
||||
|
||||
return 0;
|
||||
}
|
13
hostapd-0.8/hostapd/hlr_auc_gw.milenage_db
Normal file
13
hostapd-0.8/hostapd/hlr_auc_gw.milenage_db
Normal file
|
@ -0,0 +1,13 @@
|
|||
# Parameters for Milenage (Example algorithms for AKA).
|
||||
# The example Ki, OPc, and AMF values here are from 3GPP TS 35.208 v6.0.0
|
||||
# 4.3.20 Test Set 20. SQN is the last used SQN value.
|
||||
# These values can be used for both UMTS (EAP-AKA) and GSM (EAP-SIM)
|
||||
# authentication. In case of GSM/EAP-SIM, AMF and SQN values are not used, but
|
||||
# dummy values will need to be included in this file.
|
||||
|
||||
# IMSI Ki OPc AMF SQN
|
||||
232010000000000 90dca4eda45b53cf0f12d7c9c3bc6a89 cb9cccc4b9258e6dca4760379fb82581 61df 000000000000
|
||||
|
||||
# These values are from Test Set 19 which has the AMF separation bit set to 1
|
||||
# and as such, is suitable for EAP-AKA' test.
|
||||
555444333222111 5122250214c33e723a5dd523fc145fc0 981d464c7c52eb6e5036234984ad0bcf c3ab 16f3b3f70fc1
|
59
hostapd-0.8/hostapd/hostapd.8
Normal file
59
hostapd-0.8/hostapd/hostapd.8
Normal file
|
@ -0,0 +1,59 @@
|
|||
.TH HOSTAPD 8 "April 7, 2005" hostapd hostapd
|
||||
.SH NAME
|
||||
hostapd \- IEEE 802.11 AP, IEEE 802.1X/WPA/WPA2/EAP/RADIUS Authenticator
|
||||
.SH SYNOPSIS
|
||||
.B hostapd
|
||||
[\-hdBKtv] [\-P <PID file>] <configuration file(s)>
|
||||
.SH DESCRIPTION
|
||||
This manual page documents briefly the
|
||||
.B hostapd
|
||||
daemon.
|
||||
.PP
|
||||
.B hostapd
|
||||
is a user space daemon for access point and authentication servers.
|
||||
It implements IEEE 802.11 access point management, IEEE 802.1X/WPA/WPA2/EAP Authenticators and RADIUS authentication server.
|
||||
The current version supports Linux (Host AP, madwifi, mac80211-based drivers) and FreeBSD (net80211).
|
||||
|
||||
.B hostapd
|
||||
is designed to be a "daemon" program that runs in the background and acts as the backend component controlling authentication.
|
||||
.B hostapd
|
||||
supports separate frontend programs and an example text-based frontend,
|
||||
.BR hostapd_cli ,
|
||||
is included with
|
||||
.BR hostapd .
|
||||
.SH OPTIONS
|
||||
A summary of options is included below.
|
||||
For a complete description, run
|
||||
.BR hostapd
|
||||
from the command line.
|
||||
.TP
|
||||
.B \-h
|
||||
Show usage.
|
||||
.TP
|
||||
.B \-d
|
||||
Show more debug messages.
|
||||
.TP
|
||||
.B \-dd
|
||||
Show even more debug messages.
|
||||
.TP
|
||||
.B \-B
|
||||
Run daemon in the background.
|
||||
.TP
|
||||
.B \-P <PID file>
|
||||
Path to PID file.
|
||||
.TP
|
||||
.B \-K
|
||||
Include key data in debug messages.
|
||||
.TP
|
||||
.B \-t
|
||||
Include timestamps in some debug messages.
|
||||
.TP
|
||||
.B \-v
|
||||
Show hostapd version.
|
||||
.SH SEE ALSO
|
||||
.BR hostapd_cli (1).
|
||||
.SH AUTHOR
|
||||
hostapd was written by Jouni Malinen <j@w1.fi>.
|
||||
.PP
|
||||
This manual page was written by Faidon Liambotis <faidon@cube.gr>,
|
||||
for the Debian project (but may be used by others).
|
6
hostapd-0.8/hostapd/hostapd.accept
Normal file
6
hostapd-0.8/hostapd/hostapd.accept
Normal file
|
@ -0,0 +1,6 @@
|
|||
# List of MAC addresses that are allowed to authenticate (IEEE 802.11)
|
||||
# with the AP. Optional VLAN ID can be assigned for clients based on the
|
||||
# MAC address if dynamic VLANs (hostapd.conf dynamic_vlan option) are used.
|
||||
00:11:22:33:44:55
|
||||
00:66:77:88:99:aa
|
||||
00:00:22:33:44:55 1
|
1040
hostapd-0.8/hostapd/hostapd.conf
Normal file
1040
hostapd-0.8/hostapd/hostapd.conf
Normal file
File diff suppressed because it is too large
Load diff
5
hostapd-0.8/hostapd/hostapd.deny
Normal file
5
hostapd-0.8/hostapd/hostapd.deny
Normal file
|
@ -0,0 +1,5 @@
|
|||
# List of MAC addresses that are not allowed to authenticate (IEEE 802.11)
|
||||
# with the AP.
|
||||
00:20:30:40:50:60
|
||||
00:ab:cd:ef:12:34
|
||||
00:00:30:40:50:60
|
91
hostapd-0.8/hostapd/hostapd.eap_user
Normal file
91
hostapd-0.8/hostapd/hostapd.eap_user
Normal file
|
@ -0,0 +1,91 @@
|
|||
# hostapd user database for integrated EAP server
|
||||
|
||||
# Each line must contain an identity, EAP method(s), and an optional password
|
||||
# separated with whitespace (space or tab). The identity and password must be
|
||||
# double quoted ("user"). Password can alternatively be stored as
|
||||
# NtPasswordHash (16-byte MD4 hash of the unicode presentation of the password
|
||||
# in unicode) if it is used for MSCHAP or MSCHAPv2 authentication. This means
|
||||
# that the plaintext password does not need to be included in the user file.
|
||||
# Password hash is stored as hash:<16-octets of hex data> without quotation
|
||||
# marks.
|
||||
|
||||
# [2] flag in the end of the line can be used to mark users for tunneled phase
|
||||
# 2 authentication (e.g., within EAP-PEAP). In these cases, an anonymous
|
||||
# identity can be used in the unencrypted phase 1 and the real user identity
|
||||
# is transmitted only within the encrypted tunnel in phase 2. If non-anonymous
|
||||
# access is needed, two user entries is needed, one for phase 1 and another
|
||||
# with the same username for phase 2.
|
||||
#
|
||||
# EAP-TLS, EAP-PEAP, EAP-TTLS, EAP-FAST, EAP-SIM, and EAP-AKA do not use
|
||||
# password option.
|
||||
# EAP-MD5, EAP-MSCHAPV2, EAP-GTC, EAP-PAX, EAP-PSK, and EAP-SAKE require a
|
||||
# password.
|
||||
# EAP-PEAP, EAP-TTLS, and EAP-FAST require Phase 2 configuration.
|
||||
#
|
||||
# * can be used as a wildcard to match any user identity. The main purposes for
|
||||
# this are to set anonymous phase 1 identity for EAP-PEAP and EAP-TTLS and to
|
||||
# avoid having to configure every certificate for EAP-TLS authentication. The
|
||||
# first matching entry is selected, so * should be used as the last phase 1
|
||||
# user entry.
|
||||
#
|
||||
# "prefix"* can be used to match the given prefix and anything after this. The
|
||||
# main purpose for this is to be able to avoid EAP method negotiation when the
|
||||
# method is using known prefix in identities (e.g., EAP-SIM and EAP-AKA). This
|
||||
# is only allowed for phase 1 identities.
|
||||
#
|
||||
# Multiple methods can be configured to make the authenticator try them one by
|
||||
# one until the peer accepts one. The method names are separated with a
|
||||
# comma (,).
|
||||
#
|
||||
# [ver=0] and [ver=1] flags after EAP type PEAP can be used to force PEAP
|
||||
# version based on the Phase 1 identity. Without this flag, the EAP
|
||||
# authenticator advertises the highest supported version and select the version
|
||||
# based on the first PEAP packet from the supplicant.
|
||||
#
|
||||
# EAP-TTLS supports both EAP and non-EAP authentication inside the tunnel.
|
||||
# Tunneled EAP methods are configured with standard EAP method name and [2]
|
||||
# flag. Non-EAP methods can be enabled by following method names: TTLS-PAP,
|
||||
# TTLS-CHAP, TTLS-MSCHAP, TTLS-MSCHAPV2. TTLS-PAP and TTLS-CHAP require a
|
||||
# plaintext password while TTLS-MSCHAP and TTLS-MSCHAPV2 can use NT password
|
||||
# hash.
|
||||
|
||||
# Phase 1 users
|
||||
"user" MD5 "password"
|
||||
"test user" MD5 "secret"
|
||||
"example user" TLS
|
||||
"DOMAIN\user" MSCHAPV2 "password"
|
||||
"gtc user" GTC "password"
|
||||
"pax user" PAX "unknown"
|
||||
"pax.user@example.com" PAX 0123456789abcdef0123456789abcdef
|
||||
"psk user" PSK "unknown"
|
||||
"psk.user@example.com" PSK 0123456789abcdef0123456789abcdef
|
||||
"sake.user@example.com" SAKE 0123456789abcdef0123456789abcdef0123456789abcdef0123456789abcdef
|
||||
"ttls" TTLS
|
||||
"not anonymous" PEAP
|
||||
# Default to EAP-SIM and EAP-AKA based on fixed identity prefixes
|
||||
"0"* AKA,TTLS,TLS,PEAP,SIM
|
||||
"1"* SIM,TTLS,TLS,PEAP,AKA
|
||||
"2"* AKA,TTLS,TLS,PEAP,SIM
|
||||
"3"* SIM,TTLS,TLS,PEAP,AKA
|
||||
"4"* AKA,TTLS,TLS,PEAP,SIM
|
||||
"5"* SIM,TTLS,TLS,PEAP,AKA
|
||||
|
||||
# Wildcard for all other identities
|
||||
* PEAP,TTLS,TLS,SIM,AKA
|
||||
|
||||
# Phase 2 (tunnelled within EAP-PEAP or EAP-TTLS) users
|
||||
"t-md5" MD5 "password" [2]
|
||||
"DOMAIN\t-mschapv2" MSCHAPV2 "password" [2]
|
||||
"t-gtc" GTC "password" [2]
|
||||
"not anonymous" MSCHAPV2 "password" [2]
|
||||
"user" MD5,GTC,MSCHAPV2 "password" [2]
|
||||
"test user" MSCHAPV2 hash:000102030405060708090a0b0c0d0e0f [2]
|
||||
"ttls-user" TTLS-PAP,TTLS-CHAP,TTLS-MSCHAP,TTLS-MSCHAPV2 "password" [2]
|
||||
|
||||
# Default to EAP-SIM and EAP-AKA based on fixed identity prefixes in phase 2
|
||||
"0"* AKA [2]
|
||||
"1"* SIM [2]
|
||||
"2"* AKA [2]
|
||||
"3"* SIM [2]
|
||||
"4"* AKA [2]
|
||||
"5"* SIM [2]
|
4
hostapd-0.8/hostapd/hostapd.radius_clients
Normal file
4
hostapd-0.8/hostapd/hostapd.radius_clients
Normal file
|
@ -0,0 +1,4 @@
|
|||
# RADIUS client configuration for the RADIUS server
|
||||
10.1.2.3 secret passphrase
|
||||
192.168.1.0/24 another very secret passphrase
|
||||
0.0.0.0/0 radius
|
9
hostapd-0.8/hostapd/hostapd.sim_db
Normal file
9
hostapd-0.8/hostapd/hostapd.sim_db
Normal file
|
@ -0,0 +1,9 @@
|
|||
# Example GSM authentication triplet file for EAP-SIM authenticator
|
||||
# IMSI:Kc:SRES:RAND
|
||||
# IMSI: ASCII string (numbers)
|
||||
# Kc: hex, 8 octets
|
||||
# SRES: hex, 4 octets
|
||||
# RAND: hex, 16 octets
|
||||
234567898765432:A0A1A2A3A4A5A6A7:D1D2D3D4:AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
|
||||
234567898765432:B0B1B2B3B4B5B6B7:E1E2E3E4:BBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBB
|
||||
234567898765432:C0C1C2C3C4C5C6C7:F1F2F3F4:CCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCC
|
9
hostapd-0.8/hostapd/hostapd.vlan
Normal file
9
hostapd-0.8/hostapd/hostapd.vlan
Normal file
|
@ -0,0 +1,9 @@
|
|||
# VLAN ID to network interface mapping
|
||||
1 vlan1
|
||||
2 vlan2
|
||||
3 vlan3
|
||||
100 guest
|
||||
# Optional wildcard entry matching all VLAN IDs. The first # in the interface
|
||||
# name will be replaced with the VLAN ID. The network interfaces are created
|
||||
# (and removed) dynamically based on the use.
|
||||
* vlan#
|
9
hostapd-0.8/hostapd/hostapd.wpa_psk
Normal file
9
hostapd-0.8/hostapd/hostapd.wpa_psk
Normal file
|
@ -0,0 +1,9 @@
|
|||
# List of WPA PSKs. Each line, except for empty lines and lines starting
|
||||
# with #, must contain a MAC address and PSK separated with a space.
|
||||
# Special MAC address 00:00:00:00:00:00 can be used to configure PSKs that
|
||||
# anyone can use. PSK can be configured as an ASCII passphrase of 8..63
|
||||
# characters or as a 256-bit hex PSK (64 hex digits).
|
||||
00:00:00:00:00:00 secret passphrase
|
||||
00:11:22:33:44:55 another passphrase
|
||||
00:22:33:44:55:66 0123456789abcdef0123456789abcdef0123456789abcdef0123456789abcdef
|
||||
00:00:00:00:00:00 another passphrase for all STAs
|
89
hostapd-0.8/hostapd/hostapd_cli.1
Normal file
89
hostapd-0.8/hostapd/hostapd_cli.1
Normal file
|
@ -0,0 +1,89 @@
|
|||
.TH HOSTAPD_CLI 1 "April 7, 2005" hostapd_cli "hostapd command-line interface"
|
||||
.SH NAME
|
||||
hostapd_cli \- hostapd command-line interface
|
||||
.SH SYNOPSIS
|
||||
.B hostapd_cli
|
||||
[\-p<path>] [\-i<ifname>] [\-a<path>] [\-hvB] [command..]
|
||||
.SH DESCRIPTION
|
||||
This manual page documents briefly the
|
||||
.B hostapd_cli
|
||||
utility.
|
||||
.PP
|
||||
.B hostapd_cli
|
||||
is a command-line interface for the
|
||||
.B hostapd
|
||||
daemon.
|
||||
|
||||
.B hostapd
|
||||
is a user space daemon for access point and authentication servers.
|
||||
It implements IEEE 802.11 access point management, IEEE 802.1X/WPA/WPA2/EAP Authenticators and RADIUS authentication server.
|
||||
For more information about
|
||||
.B hostapd
|
||||
refer to the
|
||||
.BR hostapd (8)
|
||||
man page.
|
||||
.SH OPTIONS
|
||||
A summary of options is included below.
|
||||
For a complete description, run
|
||||
.BR hostapd_cli
|
||||
from the command line.
|
||||
.TP
|
||||
.B \-p<path>
|
||||
Path to find control sockets.
|
||||
|
||||
Default: /var/run/hostapd
|
||||
.TP
|
||||
.B \-i<ifname>
|
||||
Interface to listen on.
|
||||
|
||||
Default: first interface found in socket path.
|
||||
.TP
|
||||
.B \-a<path>
|
||||
Run in daemon mode executing the action file based on events from hostapd.
|
||||
.TP
|
||||
.B \-B
|
||||
Run a daemon in the background.
|
||||
.TP
|
||||
.B \-h
|
||||
Show usage.
|
||||
.TP
|
||||
.B \-v
|
||||
Show hostapd_cli version.
|
||||
.SH COMMANDS
|
||||
A summary of commands is included below.
|
||||
For a complete description, run
|
||||
.BR hostapd_cli
|
||||
from the command line.
|
||||
.TP
|
||||
.B mib
|
||||
Get MIB variables (dot1x, dot11, radius).
|
||||
.TP
|
||||
.B sta <addr>
|
||||
Get MIB variables for one station.
|
||||
.TP
|
||||
.B all_sta
|
||||
Get MIB variables for all stations.
|
||||
.TP
|
||||
.B help
|
||||
Get usage help.
|
||||
.TP
|
||||
.B interface [ifname]
|
||||
Show interfaces/select interface.
|
||||
.TP
|
||||
.B level <debug level>
|
||||
Change debug level.
|
||||
.TP
|
||||
.B license
|
||||
Show full
|
||||
.B hostapd_cli
|
||||
license.
|
||||
.TP
|
||||
.B quit
|
||||
Exit hostapd_cli.
|
||||
.SH SEE ALSO
|
||||
.BR hostapd (8).
|
||||
.SH AUTHOR
|
||||
hostapd_cli was written by Jouni Malinen <j@w1.fi>.
|
||||
.PP
|
||||
This manual page was written by Faidon Liambotis <faidon@cube.gr>,
|
||||
for the Debian project (but may be used by others).
|
1044
hostapd-0.8/hostapd/hostapd_cli.c
Normal file
1044
hostapd-0.8/hostapd/hostapd_cli.c
Normal file
File diff suppressed because it is too large
Load diff
9
hostapd-0.8/hostapd/logwatch/README
Normal file
9
hostapd-0.8/hostapd/logwatch/README
Normal file
|
@ -0,0 +1,9 @@
|
|||
Logwatch is a utility for analyzing system logs and provide a human
|
||||
readable summary. This directory has a configuration file and a log
|
||||
analyzer script for parsing hostapd system log entries for logwatch.
|
||||
These files can be installed by copying them to following locations:
|
||||
|
||||
/etc/log.d/conf/services/hostapd.conf
|
||||
/etc/log.d/scripts/services/hostapd
|
||||
|
||||
More information about logwatch is available from http://www.logwatch.org/
|
65
hostapd-0.8/hostapd/logwatch/hostapd
Normal file
65
hostapd-0.8/hostapd/logwatch/hostapd
Normal file
|
@ -0,0 +1,65 @@
|
|||
#!/usr/bin/perl -w
|
||||
#
|
||||
# Logwatch script for hostapd
|
||||
#
|
||||
# Copyright 2005 Henrik Brix Andersen <brix@gentoo.org>
|
||||
# Distributed under the terms of the GNU General Public License v2
|
||||
# Alternatively, this file may be distributed under the terms of the BSD License
|
||||
|
||||
use strict;
|
||||
|
||||
my $debug = $ENV{'LOGWATCH_DEBUG'} || 0;
|
||||
my $detail = $ENV{'LOGWATCH_DETAIL_LEVEL'} || 0;
|
||||
my $debugcounter = 1;
|
||||
|
||||
my %hostapd;
|
||||
my @unmatched;
|
||||
|
||||
if ($debug >= 5) {
|
||||
print STDERR "\n\nDEBUG: Inside HOSTAPD Filter\n\n";
|
||||
}
|
||||
|
||||
while (defined(my $line = <STDIN>)) {
|
||||
if ($debug >= 5) {
|
||||
print STDERR "DEBUG($debugcounter): $line";
|
||||
$debugcounter++;
|
||||
}
|
||||
chomp($line);
|
||||
|
||||
if (my ($iface,$mac,$layer,$details) = ($line =~ /(.*?): STA (.*?) (.*?): (.*?)$/i)) {
|
||||
unless ($detail == 10) {
|
||||
# collapse association events
|
||||
$details =~ s/^(associated) .*$/$1/i;
|
||||
}
|
||||
$hostapd{$iface}->{$mac}->{$layer}->{$details}++;
|
||||
} else {
|
||||
push @unmatched, "$line\n";
|
||||
}
|
||||
}
|
||||
|
||||
if (keys %hostapd) {
|
||||
foreach my $iface (sort keys %hostapd) {
|
||||
print "Interface $iface:\n";
|
||||
foreach my $mac (sort keys %{$hostapd{$iface}}) {
|
||||
print " Client MAC Address $mac:\n";
|
||||
foreach my $layer (sort keys %{$hostapd{$iface}->{$mac}}) {
|
||||
print " $layer:\n";
|
||||
foreach my $details (sort keys %{$hostapd{$iface}->{$mac}->{$layer}}) {
|
||||
print " $details";
|
||||
my $count = $hostapd{$iface}->{$mac}->{$layer}->{$details};
|
||||
if ($count > 1) {
|
||||
print ": " . $count . " Times";
|
||||
}
|
||||
print "\n";
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
if ($#unmatched >= 0) {
|
||||
print "\n**Unmatched Entries**\n";
|
||||
print @unmatched;
|
||||
}
|
||||
|
||||
exit(0);
|
10
hostapd-0.8/hostapd/logwatch/hostapd.conf
Normal file
10
hostapd-0.8/hostapd/logwatch/hostapd.conf
Normal file
|
@ -0,0 +1,10 @@
|
|||
# Logwatch configuration for hostapd
|
||||
#
|
||||
# Copyright 2005 Henrik Brix Andersen <brix@gentoo.org>
|
||||
# Distributed under the terms of the GNU General Public License v2
|
||||
# Alternatively, this file may be distributed under the terms of the BSD License
|
||||
|
||||
Title = "hostapd"
|
||||
LogFile = messages
|
||||
*OnlyService = hostapd
|
||||
*RemoveHeaders
|
599
hostapd-0.8/hostapd/main.c
Normal file
599
hostapd-0.8/hostapd/main.c
Normal file
|
@ -0,0 +1,599 @@
|
|||
/*
|
||||
* 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.
|
||||
*/
|
||||
|
||||
#include "utils/includes.h"
|
||||
#ifndef CONFIG_NATIVE_WINDOWS
|
||||
#include <syslog.h>
|
||||
#endif /* CONFIG_NATIVE_WINDOWS */
|
||||
|
||||
#include "utils/common.h"
|
||||
#include "utils/eloop.h"
|
||||
#include "crypto/random.h"
|
||||
#include "crypto/tls.h"
|
||||
#include "common/version.h"
|
||||
#include "drivers/driver.h"
|
||||
#include "eap_server/eap.h"
|
||||
#include "eap_server/tncs.h"
|
||||
#include "ap/hostapd.h"
|
||||
#include "ap/ap_config.h"
|
||||
#include "config_file.h"
|
||||
#include "eap_register.h"
|
||||
#include "dump_state.h"
|
||||
#include "ctrl_iface.h"
|
||||
|
||||
|
||||
extern int wpa_debug_level;
|
||||
extern int wpa_debug_show_keys;
|
||||
extern int wpa_debug_timestamp;
|
||||
|
||||
|
||||
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)
|
||||
{
|
||||
struct hostapd_data *hapd = ctx;
|
||||
char *format, *module_str;
|
||||
int maxlen;
|
||||
int conf_syslog_level, conf_stdout_level;
|
||||
unsigned int conf_syslog, conf_stdout;
|
||||
|
||||
maxlen = len + 100;
|
||||
format = os_malloc(maxlen);
|
||||
if (!format)
|
||||
return;
|
||||
|
||||
if (hapd && hapd->conf) {
|
||||
conf_syslog_level = hapd->conf->logger_syslog_level;
|
||||
conf_stdout_level = hapd->conf->logger_stdout_level;
|
||||
conf_syslog = hapd->conf->logger_syslog;
|
||||
conf_stdout = hapd->conf->logger_stdout;
|
||||
} else {
|
||||
conf_syslog_level = conf_stdout_level = 0;
|
||||
conf_syslog = conf_stdout = (unsigned int) -1;
|
||||
}
|
||||
|
||||
switch (module) {
|
||||
case HOSTAPD_MODULE_IEEE80211:
|
||||
module_str = "IEEE 802.11";
|
||||
break;
|
||||
case HOSTAPD_MODULE_IEEE8021X:
|
||||
module_str = "IEEE 802.1X";
|
||||
break;
|
||||
case HOSTAPD_MODULE_RADIUS:
|
||||
module_str = "RADIUS";
|
||||
break;
|
||||
case HOSTAPD_MODULE_WPA:
|
||||
module_str = "WPA";
|
||||
break;
|
||||
case HOSTAPD_MODULE_DRIVER:
|
||||
module_str = "DRIVER";
|
||||
break;
|
||||
case HOSTAPD_MODULE_IAPP:
|
||||
module_str = "IAPP";
|
||||
break;
|
||||
case HOSTAPD_MODULE_MLME:
|
||||
module_str = "MLME";
|
||||
break;
|
||||
default:
|
||||
module_str = NULL;
|
||||
break;
|
||||
}
|
||||
|
||||
if (hapd && hapd->conf && addr)
|
||||
os_snprintf(format, maxlen, "%s: STA " MACSTR "%s%s: %s",
|
||||
hapd->conf->iface, MAC2STR(addr),
|
||||
module_str ? " " : "", module_str, txt);
|
||||
else if (hapd && hapd->conf)
|
||||
os_snprintf(format, maxlen, "%s:%s%s %s",
|
||||
hapd->conf->iface, module_str ? " " : "",
|
||||
module_str, txt);
|
||||
else if (addr)
|
||||
os_snprintf(format, maxlen, "STA " MACSTR "%s%s: %s",
|
||||
MAC2STR(addr), module_str ? " " : "",
|
||||
module_str, txt);
|
||||
else
|
||||
os_snprintf(format, maxlen, "%s%s%s",
|
||||
module_str, module_str ? ": " : "", txt);
|
||||
|
||||
if ((conf_stdout & module) && level >= conf_stdout_level) {
|
||||
wpa_debug_print_timestamp();
|
||||
printf("%s\n", format);
|
||||
}
|
||||
|
||||
#ifndef CONFIG_NATIVE_WINDOWS
|
||||
if ((conf_syslog & module) && level >= conf_syslog_level) {
|
||||
int priority;
|
||||
switch (level) {
|
||||
case HOSTAPD_LEVEL_DEBUG_VERBOSE:
|
||||
case HOSTAPD_LEVEL_DEBUG:
|
||||
priority = LOG_DEBUG;
|
||||
break;
|
||||
case HOSTAPD_LEVEL_INFO:
|
||||
priority = LOG_INFO;
|
||||
break;
|
||||
case HOSTAPD_LEVEL_NOTICE:
|
||||
priority = LOG_NOTICE;
|
||||
break;
|
||||
case HOSTAPD_LEVEL_WARNING:
|
||||
priority = LOG_WARNING;
|
||||
break;
|
||||
default:
|
||||
priority = LOG_INFO;
|
||||
break;
|
||||
}
|
||||
syslog(priority, "%s", format);
|
||||
}
|
||||
#endif /* CONFIG_NATIVE_WINDOWS */
|
||||
|
||||
os_free(format);
|
||||
}
|
||||
#endif /* CONFIG_NO_HOSTAPD_LOGGER */
|
||||
|
||||
|
||||
/**
|
||||
* hostapd_init - Allocate and initialize per-interface data
|
||||
* @config_file: Path to the configuration file
|
||||
* Returns: Pointer to the allocated interface data or %NULL on failure
|
||||
*
|
||||
* This function is used to allocate main data structures for per-interface
|
||||
* data. The allocated data buffer will be freed by calling
|
||||
* hostapd_cleanup_iface().
|
||||
*/
|
||||
static struct hostapd_iface * hostapd_init(const char *config_file)
|
||||
{
|
||||
struct hostapd_iface *hapd_iface = NULL;
|
||||
struct hostapd_config *conf = NULL;
|
||||
struct hostapd_data *hapd;
|
||||
size_t i;
|
||||
|
||||
hapd_iface = os_zalloc(sizeof(*hapd_iface));
|
||||
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)
|
||||
goto fail;
|
||||
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)
|
||||
goto fail;
|
||||
|
||||
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)
|
||||
goto fail;
|
||||
hapd->msg_ctx = hapd;
|
||||
}
|
||||
|
||||
return hapd_iface;
|
||||
|
||||
fail:
|
||||
if (conf)
|
||||
hostapd_config_free(conf);
|
||||
if (hapd_iface) {
|
||||
os_free(hapd_iface->config_fname);
|
||||
os_free(hapd_iface->bss);
|
||||
os_free(hapd_iface);
|
||||
}
|
||||
return NULL;
|
||||
}
|
||||
|
||||
|
||||
static int hostapd_driver_init(struct hostapd_iface *iface)
|
||||
{
|
||||
struct wpa_init_params params;
|
||||
size_t i;
|
||||
struct hostapd_data *hapd = iface->bss[0];
|
||||
struct hostapd_bss_config *conf = hapd->conf;
|
||||
u8 *b = conf->bssid;
|
||||
struct wpa_driver_capa capa;
|
||||
|
||||
if (hapd->driver == NULL || hapd->driver->hapd_init == NULL) {
|
||||
wpa_printf(MSG_ERROR, "No hostapd driver wrapper available");
|
||||
return -1;
|
||||
}
|
||||
|
||||
/* Initialize the driver interface */
|
||||
if (!(b[0] | b[1] | b[2] | b[3] | b[4] | b[5]))
|
||||
b = NULL;
|
||||
|
||||
os_memset(¶ms, 0, sizeof(params));
|
||||
params.bssid = b;
|
||||
params.ifname = hapd->conf->iface;
|
||||
params.ssid = (const u8 *) 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 *));
|
||||
if (params.bridge == NULL)
|
||||
return -1;
|
||||
for (i = 0; i < hapd->iface->num_bss; i++) {
|
||||
struct hostapd_data *bss = hapd->iface->bss[i];
|
||||
if (bss->conf->bridge[0])
|
||||
params.bridge[i] = bss->conf->bridge;
|
||||
}
|
||||
|
||||
params.own_addr = hapd->own_addr;
|
||||
|
||||
hapd->drv_priv = hapd->driver->hapd_init(hapd, ¶ms);
|
||||
os_free(params.bridge);
|
||||
if (hapd->drv_priv == NULL) {
|
||||
wpa_printf(MSG_ERROR, "%s driver initialization failed.",
|
||||
hapd->driver->name);
|
||||
hapd->driver = NULL;
|
||||
return -1;
|
||||
}
|
||||
|
||||
if (hapd->driver->get_capa &&
|
||||
hapd->driver->get_capa(hapd->drv_priv, &capa) == 0)
|
||||
iface->drv_flags = capa.flags;
|
||||
|
||||
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)
|
||||
{
|
||||
struct hostapd_iface *iface;
|
||||
int k;
|
||||
|
||||
wpa_printf(MSG_ERROR, "Configuration file: %s", config_fname);
|
||||
iface = hostapd_init(config_fname);
|
||||
if (!iface)
|
||||
return NULL;
|
||||
iface->interfaces = interfaces;
|
||||
|
||||
for (k = 0; k < debug; k++) {
|
||||
if (iface->bss[0]->conf->logger_stdout_level > 0)
|
||||
iface->bss[0]->conf->logger_stdout_level--;
|
||||
}
|
||||
|
||||
if (hostapd_driver_init(iface) ||
|
||||
hostapd_setup_interface(iface)) {
|
||||
hostapd_interface_deinit_free(iface);
|
||||
return NULL;
|
||||
}
|
||||
|
||||
return iface;
|
||||
}
|
||||
|
||||
|
||||
/**
|
||||
* handle_term - SIGINT and SIGTERM handler to terminate hostapd process
|
||||
*/
|
||||
static void handle_term(int sig, void *signal_ctx)
|
||||
{
|
||||
wpa_printf(MSG_DEBUG, "Signal %d received - terminating", sig);
|
||||
eloop_terminate();
|
||||
}
|
||||
|
||||
|
||||
#ifndef CONFIG_NATIVE_WINDOWS
|
||||
|
||||
static int handle_reload_iface(struct hostapd_iface *iface, void *ctx)
|
||||
{
|
||||
if (hostapd_reload_config(iface) < 0) {
|
||||
wpa_printf(MSG_WARNING, "Failed to read new configuration "
|
||||
"file - continuing with old.");
|
||||
}
|
||||
return 0;
|
||||
}
|
||||
|
||||
|
||||
/**
|
||||
* handle_reload - SIGHUP handler to reload configuration
|
||||
*/
|
||||
static void handle_reload(int sig, void *signal_ctx)
|
||||
{
|
||||
struct hapd_interfaces *interfaces = signal_ctx;
|
||||
wpa_printf(MSG_DEBUG, "Signal %d received - reloading configuration",
|
||||
sig);
|
||||
hostapd_for_each_interface(interfaces, handle_reload_iface, NULL);
|
||||
}
|
||||
|
||||
|
||||
static void handle_dump_state(int sig, void *signal_ctx)
|
||||
{
|
||||
#ifdef HOSTAPD_DUMP_STATE
|
||||
struct hapd_interfaces *interfaces = signal_ctx;
|
||||
hostapd_for_each_interface(interfaces, handle_dump_state_iface, NULL);
|
||||
#endif /* HOSTAPD_DUMP_STATE */
|
||||
}
|
||||
#endif /* CONFIG_NATIVE_WINDOWS */
|
||||
|
||||
|
||||
static int hostapd_global_init(struct hapd_interfaces *interfaces)
|
||||
{
|
||||
hostapd_logger_register_cb(hostapd_logger_cb);
|
||||
|
||||
if (eap_server_register_methods()) {
|
||||
wpa_printf(MSG_ERROR, "Failed to register EAP methods");
|
||||
return -1;
|
||||
}
|
||||
|
||||
if (eloop_init()) {
|
||||
wpa_printf(MSG_ERROR, "Failed to initialize event loop");
|
||||
return -1;
|
||||
}
|
||||
|
||||
random_init();
|
||||
|
||||
#ifndef CONFIG_NATIVE_WINDOWS
|
||||
eloop_register_signal(SIGHUP, handle_reload, interfaces);
|
||||
eloop_register_signal(SIGUSR1, handle_dump_state, interfaces);
|
||||
#endif /* CONFIG_NATIVE_WINDOWS */
|
||||
eloop_register_signal_terminate(handle_term, interfaces);
|
||||
|
||||
#ifndef CONFIG_NATIVE_WINDOWS
|
||||
openlog("hostapd", 0, LOG_DAEMON);
|
||||
#endif /* CONFIG_NATIVE_WINDOWS */
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
|
||||
static void hostapd_global_deinit(const char *pid_file)
|
||||
{
|
||||
#ifdef EAP_SERVER_TNC
|
||||
tncs_global_deinit();
|
||||
#endif /* EAP_SERVER_TNC */
|
||||
|
||||
random_deinit();
|
||||
|
||||
eloop_destroy();
|
||||
|
||||
#ifndef CONFIG_NATIVE_WINDOWS
|
||||
closelog();
|
||||
#endif /* CONFIG_NATIVE_WINDOWS */
|
||||
|
||||
eap_server_unregister_methods();
|
||||
|
||||
os_daemonize_terminate(pid_file);
|
||||
}
|
||||
|
||||
|
||||
static int hostapd_global_run(struct hapd_interfaces *ifaces, int daemonize,
|
||||
const char *pid_file)
|
||||
{
|
||||
#ifdef EAP_SERVER_TNC
|
||||
int tnc = 0;
|
||||
size_t i, k;
|
||||
|
||||
for (i = 0; !tnc && i < ifaces->count; i++) {
|
||||
for (k = 0; k < ifaces->iface[i]->num_bss; k++) {
|
||||
if (ifaces->iface[i]->bss[0]->conf->tnc) {
|
||||
tnc++;
|
||||
break;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
if (tnc && tncs_global_init() < 0) {
|
||||
wpa_printf(MSG_ERROR, "Failed to initialize TNCS");
|
||||
return -1;
|
||||
}
|
||||
#endif /* EAP_SERVER_TNC */
|
||||
|
||||
if (daemonize && os_daemonize(pid_file)) {
|
||||
perror("daemon");
|
||||
return -1;
|
||||
}
|
||||
|
||||
eloop_run();
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
|
||||
static void show_version(void)
|
||||
{
|
||||
fprintf(stderr,
|
||||
"hostapd v" VERSION_STR "\n"
|
||||
"User space daemon for IEEE 802.11 AP management,\n"
|
||||
"IEEE 802.1X/WPA/WPA2/EAP/RADIUS Authenticator\n"
|
||||
"Copyright (c) 2002-2011, Jouni Malinen <j@w1.fi> "
|
||||
"and contributors\n");
|
||||
}
|
||||
|
||||
|
||||
static void usage(void)
|
||||
{
|
||||
show_version();
|
||||
fprintf(stderr,
|
||||
"\n"
|
||||
"usage: hostapd [-hdBKtv] [-P <PID file>] "
|
||||
"<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"
|
||||
" -P PID file\n"
|
||||
" -K include key data in debug messages\n"
|
||||
#ifdef CONFIG_DEBUG_FILE
|
||||
" -f log output to debug file instead of stdout\n"
|
||||
#endif /* CONFIG_DEBUG_FILE */
|
||||
" -t include timestamps in some debug messages\n"
|
||||
" -v show hostapd version\n");
|
||||
|
||||
exit(1);
|
||||
}
|
||||
|
||||
|
||||
static const char * hostapd_msg_ifname_cb(void *ctx)
|
||||
{
|
||||
struct hostapd_data *hapd = ctx;
|
||||
if (hapd && hapd->iconf && hapd->iconf->bss)
|
||||
return hapd->iconf->bss->iface;
|
||||
return NULL;
|
||||
}
|
||||
|
||||
|
||||
int main(int argc, char *argv[])
|
||||
{
|
||||
struct hapd_interfaces interfaces;
|
||||
int ret = 1;
|
||||
size_t i;
|
||||
int c, debug = 0, daemonize = 0;
|
||||
char *pid_file = NULL;
|
||||
const char *log_file = NULL;
|
||||
|
||||
if (os_program_init())
|
||||
return -1;
|
||||
|
||||
for (;;) {
|
||||
c = getopt(argc, argv, "Bdf:hKP:tv");
|
||||
if (c < 0)
|
||||
break;
|
||||
switch (c) {
|
||||
case 'h':
|
||||
usage();
|
||||
break;
|
||||
case 'd':
|
||||
debug++;
|
||||
if (wpa_debug_level > 0)
|
||||
wpa_debug_level--;
|
||||
break;
|
||||
case 'B':
|
||||
daemonize++;
|
||||
break;
|
||||
case 'f':
|
||||
log_file = optarg;
|
||||
break;
|
||||
case 'K':
|
||||
wpa_debug_show_keys++;
|
||||
break;
|
||||
case 'P':
|
||||
os_free(pid_file);
|
||||
pid_file = os_rel2abs_path(optarg);
|
||||
break;
|
||||
case 't':
|
||||
wpa_debug_timestamp++;
|
||||
break;
|
||||
case 'v':
|
||||
show_version();
|
||||
exit(1);
|
||||
break;
|
||||
|
||||
default:
|
||||
usage();
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
if (optind == argc)
|
||||
usage();
|
||||
|
||||
wpa_msg_register_ifname_cb(hostapd_msg_ifname_cb);
|
||||
|
||||
if (log_file)
|
||||
wpa_debug_open_file(log_file);
|
||||
|
||||
interfaces.count = argc - optind;
|
||||
interfaces.iface = os_zalloc(interfaces.count *
|
||||
sizeof(struct hostapd_iface *));
|
||||
if (interfaces.iface == NULL) {
|
||||
wpa_printf(MSG_ERROR, "malloc failed");
|
||||
return -1;
|
||||
}
|
||||
|
||||
if (hostapd_global_init(&interfaces))
|
||||
return -1;
|
||||
|
||||
/* Initialize interfaces */
|
||||
for (i = 0; i < interfaces.count; i++) {
|
||||
interfaces.iface[i] = hostapd_interface_init(&interfaces,
|
||||
argv[optind + i],
|
||||
debug);
|
||||
if (!interfaces.iface[i])
|
||||
goto out;
|
||||
}
|
||||
|
||||
if (hostapd_global_run(&interfaces, daemonize, pid_file))
|
||||
goto out;
|
||||
|
||||
ret = 0;
|
||||
|
||||
out:
|
||||
/* Deinitialize all interfaces */
|
||||
for (i = 0; i < interfaces.count; i++)
|
||||
hostapd_interface_deinit_free(interfaces.iface[i]);
|
||||
os_free(interfaces.iface);
|
||||
|
||||
hostapd_global_deinit(pid_file);
|
||||
os_free(pid_file);
|
||||
|
||||
if (log_file)
|
||||
wpa_debug_close_file();
|
||||
|
||||
os_program_deinit();
|
||||
|
||||
return ret;
|
||||
}
|
53
hostapd-0.8/hostapd/nt_password_hash.c
Normal file
53
hostapd-0.8/hostapd/nt_password_hash.c
Normal file
|
@ -0,0 +1,53 @@
|
|||
/*
|
||||
* 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.
|
||||
*/
|
||||
|
||||
#include "includes.h"
|
||||
|
||||
#include "common.h"
|
||||
#include "crypto/ms_funcs.h"
|
||||
|
||||
|
||||
int main(int argc, char *argv[])
|
||||
{
|
||||
unsigned char password_hash[16];
|
||||
size_t i;
|
||||
char *password, buf[64], *pos;
|
||||
|
||||
if (argc > 1)
|
||||
password = argv[1];
|
||||
else {
|
||||
if (fgets(buf, sizeof(buf), stdin) == NULL) {
|
||||
printf("Failed to read password\n");
|
||||
return 1;
|
||||
}
|
||||
buf[sizeof(buf) - 1] = '\0';
|
||||
pos = buf;
|
||||
while (*pos != '\0') {
|
||||
if (*pos == '\r' || *pos == '\n') {
|
||||
*pos = '\0';
|
||||
break;
|
||||
}
|
||||
pos++;
|
||||
}
|
||||
password = buf;
|
||||
}
|
||||
|
||||
if (nt_password_hash((u8 *) password, strlen(password), password_hash))
|
||||
return -1;
|
||||
for (i = 0; i < sizeof(password_hash); i++)
|
||||
printf("%02x", password_hash[i]);
|
||||
printf("\n");
|
||||
|
||||
return 0;
|
||||
}
|
40
hostapd-0.8/hostapd/wired.conf
Normal file
40
hostapd-0.8/hostapd/wired.conf
Normal file
|
@ -0,0 +1,40 @@
|
|||
##### hostapd configuration file ##############################################
|
||||
# Empty lines and lines starting with # are ignored
|
||||
|
||||
# Example configuration file for wired authenticator. See hostapd.conf for
|
||||
# more details.
|
||||
|
||||
interface=eth0
|
||||
driver=wired
|
||||
logger_stdout=-1
|
||||
logger_stdout_level=1
|
||||
debug=2
|
||||
dump_file=/tmp/hostapd.dump
|
||||
|
||||
ieee8021x=1
|
||||
eap_reauth_period=3600
|
||||
|
||||
use_pae_group_addr=1
|
||||
|
||||
|
||||
##### RADIUS configuration ####################################################
|
||||
# for IEEE 802.1X with external Authentication Server, IEEE 802.11
|
||||
# authentication with external ACL for MAC addresses, and accounting
|
||||
|
||||
# The own IP address of the access point (used as NAS-IP-Address)
|
||||
own_ip_addr=127.0.0.1
|
||||
|
||||
# Optional NAS-Identifier string for RADIUS messages. When used, this should be
|
||||
# a unique to the NAS within the scope of the RADIUS server. For example, a
|
||||
# fully qualified domain name can be used here.
|
||||
nas_identifier=ap.example.com
|
||||
|
||||
# RADIUS authentication server
|
||||
auth_server_addr=127.0.0.1
|
||||
auth_server_port=1812
|
||||
auth_server_shared_secret=radius
|
||||
|
||||
# RADIUS accounting server
|
||||
acct_server_addr=127.0.0.1
|
||||
acct_server_port=1813
|
||||
acct_server_shared_secret=radius
|
11
hostapd-0.8/src/Makefile
Normal file
11
hostapd-0.8/src/Makefile
Normal file
|
@ -0,0 +1,11 @@
|
|||
SUBDIRS=ap common crypto drivers eapol_auth eapol_supp eap_common eap_peer eap_server l2_packet p2p radius rsn_supp tls utils wps
|
||||
|
||||
all:
|
||||
for d in $(SUBDIRS); do [ -d $$d ] && $(MAKE) -C $$d; done
|
||||
|
||||
clean:
|
||||
for d in $(SUBDIRS); do [ -d $$d ] && $(MAKE) -C $$d clean; done
|
||||
rm -f *~
|
||||
|
||||
install:
|
||||
for d in $(SUBDIRS); do [ -d $$d ] && $(MAKE) -C $$d install; done
|
8
hostapd-0.8/src/ap/Makefile
Normal file
8
hostapd-0.8/src/ap/Makefile
Normal file
|
@ -0,0 +1,8 @@
|
|||
all:
|
||||
@echo Nothing to be made.
|
||||
|
||||
clean:
|
||||
rm -f *~ *.o *.d
|
||||
|
||||
install:
|
||||
@echo Nothing to be made.
|
505
hostapd-0.8/src/ap/accounting.c
Normal file
505
hostapd-0.8/src/ap/accounting.c
Normal file
|
@ -0,0 +1,505 @@
|
|||
/*
|
||||
* hostapd / RADIUS Accounting
|
||||
* 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.
|
||||
*/
|
||||
|
||||
#include "utils/includes.h"
|
||||
|
||||
#include "utils/common.h"
|
||||
#include "utils/eloop.h"
|
||||
#include "drivers/driver.h"
|
||||
#include "radius/radius.h"
|
||||
#include "radius/radius_client.h"
|
||||
#include "hostapd.h"
|
||||
#include "ieee802_1x.h"
|
||||
#include "ap_config.h"
|
||||
#include "sta_info.h"
|
||||
#include "ap_drv_ops.h"
|
||||
#include "accounting.h"
|
||||
|
||||
|
||||
/* Default interval in seconds for polling TX/RX octets from the driver if
|
||||
* STA is not using interim accounting. This detects wrap arounds for
|
||||
* 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 struct radius_msg * accounting_msg(struct hostapd_data *hapd,
|
||||
struct sta_info *sta,
|
||||
int status_type)
|
||||
{
|
||||
struct radius_msg *msg;
|
||||
char buf[128];
|
||||
u8 *val;
|
||||
size_t len;
|
||||
int i;
|
||||
|
||||
msg = radius_msg_new(RADIUS_CODE_ACCOUNTING_REQUEST,
|
||||
radius_client_get_id(hapd->radius));
|
||||
if (msg == NULL) {
|
||||
printf("Could not create net RADIUS packet\n");
|
||||
return NULL;
|
||||
}
|
||||
|
||||
if (sta) {
|
||||
radius_msg_make_authenticator(msg, (u8 *) sta, sizeof(*sta));
|
||||
|
||||
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))) {
|
||||
printf("Could not add Acct-Session-Id\n");
|
||||
goto fail;
|
||||
}
|
||||
} else {
|
||||
radius_msg_make_authenticator(msg, (u8 *) hapd, sizeof(*hapd));
|
||||
}
|
||||
|
||||
if (!radius_msg_add_attr_int32(msg, RADIUS_ATTR_ACCT_STATUS_TYPE,
|
||||
status_type)) {
|
||||
printf("Could not add Acct-Status-Type\n");
|
||||
goto fail;
|
||||
}
|
||||
|
||||
if (!radius_msg_add_attr_int32(msg, RADIUS_ATTR_ACCT_AUTHENTIC,
|
||||
hapd->conf->ieee802_1x ?
|
||||
RADIUS_ACCT_AUTHENTIC_RADIUS :
|
||||
RADIUS_ACCT_AUTHENTIC_LOCAL)) {
|
||||
printf("Could not add Acct-Authentic\n");
|
||||
goto fail;
|
||||
}
|
||||
|
||||
if (sta) {
|
||||
val = ieee802_1x_get_identity(sta->eapol_sm, &len);
|
||||
if (!val) {
|
||||
os_snprintf(buf, sizeof(buf), RADIUS_ADDR_FORMAT,
|
||||
MAC2STR(sta->addr));
|
||||
val = (u8 *) buf;
|
||||
len = os_strlen(buf);
|
||||
}
|
||||
|
||||
if (!radius_msg_add_attr(msg, RADIUS_ATTR_USER_NAME, val,
|
||||
len)) {
|
||||
printf("Could not add User-Name\n");
|
||||
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");
|
||||
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);
|
||||
if (val == NULL)
|
||||
break;
|
||||
|
||||
if (!radius_msg_add_attr(msg, RADIUS_ATTR_CLASS,
|
||||
val, len)) {
|
||||
printf("Could not add Class\n");
|
||||
goto fail;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
return msg;
|
||||
|
||||
fail:
|
||||
radius_msg_free(msg);
|
||||
return NULL;
|
||||
}
|
||||
|
||||
|
||||
static int accounting_sta_update_stats(struct hostapd_data *hapd,
|
||||
struct sta_info *sta,
|
||||
struct hostap_sta_driver_data *data)
|
||||
{
|
||||
if (hostapd_drv_read_sta_data(hapd, data, sta->addr))
|
||||
return -1;
|
||||
|
||||
if (sta->last_rx_bytes > data->rx_bytes)
|
||||
sta->acct_input_gigawords++;
|
||||
if (sta->last_tx_bytes > data->tx_bytes)
|
||||
sta->acct_output_gigawords++;
|
||||
sta->last_rx_bytes = data->rx_bytes;
|
||||
sta->last_tx_bytes = data->tx_bytes;
|
||||
|
||||
hostapd_logger(hapd, sta->addr, HOSTAPD_MODULE_RADIUS,
|
||||
HOSTAPD_LEVEL_DEBUG, "updated TX/RX stats: "
|
||||
"Acct-Input-Octets=%lu Acct-Input-Gigawords=%u "
|
||||
"Acct-Output-Octets=%lu Acct-Output-Gigawords=%u",
|
||||
sta->last_rx_bytes, sta->acct_input_gigawords,
|
||||
sta->last_tx_bytes, sta->acct_output_gigawords);
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
|
||||
static void accounting_interim_update(void *eloop_ctx, void *timeout_ctx)
|
||||
{
|
||||
struct hostapd_data *hapd = eloop_ctx;
|
||||
struct sta_info *sta = timeout_ctx;
|
||||
int interval;
|
||||
|
||||
if (sta->acct_interim_interval) {
|
||||
accounting_sta_interim(hapd, sta);
|
||||
interval = sta->acct_interim_interval;
|
||||
} else {
|
||||
struct hostap_sta_driver_data data;
|
||||
accounting_sta_update_stats(hapd, sta, &data);
|
||||
interval = ACCT_DEFAULT_UPDATE_INTERVAL;
|
||||
}
|
||||
|
||||
eloop_register_timeout(interval, 0, accounting_interim_update,
|
||||
hapd, sta);
|
||||
}
|
||||
|
||||
|
||||
/**
|
||||
* accounting_sta_start - Start STA accounting
|
||||
* @hapd: hostapd BSS data
|
||||
* @sta: The station
|
||||
*/
|
||||
void accounting_sta_start(struct hostapd_data *hapd, struct sta_info *sta)
|
||||
{
|
||||
struct radius_msg *msg;
|
||||
int interval;
|
||||
|
||||
if (sta->acct_session_started)
|
||||
return;
|
||||
|
||||
accounting_sta_get_id(hapd, sta);
|
||||
hostapd_logger(hapd, sta->addr, HOSTAPD_MODULE_RADIUS,
|
||||
HOSTAPD_LEVEL_INFO,
|
||||
"starting accounting session %08X-%08X",
|
||||
sta->acct_session_id_hi, sta->acct_session_id_lo);
|
||||
|
||||
time(&sta->acct_session_start);
|
||||
sta->last_rx_bytes = sta->last_tx_bytes = 0;
|
||||
sta->acct_input_gigawords = sta->acct_output_gigawords = 0;
|
||||
hostapd_drv_sta_clear_stats(hapd, sta->addr);
|
||||
|
||||
if (!hapd->conf->radius->acct_server)
|
||||
return;
|
||||
|
||||
if (sta->acct_interim_interval)
|
||||
interval = sta->acct_interim_interval;
|
||||
else
|
||||
interval = ACCT_DEFAULT_UPDATE_INTERVAL;
|
||||
eloop_register_timeout(interval, 0, accounting_interim_update,
|
||||
hapd, sta);
|
||||
|
||||
msg = accounting_msg(hapd, sta, RADIUS_ACCT_STATUS_TYPE_START);
|
||||
if (msg)
|
||||
radius_client_send(hapd->radius, msg, RADIUS_ACCT, sta->addr);
|
||||
|
||||
sta->acct_session_started = 1;
|
||||
}
|
||||
|
||||
|
||||
static void accounting_sta_report(struct hostapd_data *hapd,
|
||||
struct sta_info *sta, int stop)
|
||||
{
|
||||
struct radius_msg *msg;
|
||||
int cause = sta->acct_terminate_cause;
|
||||
struct hostap_sta_driver_data data;
|
||||
struct os_time now;
|
||||
u32 gigawords;
|
||||
|
||||
if (!hapd->conf->radius->acct_server)
|
||||
return;
|
||||
|
||||
msg = accounting_msg(hapd, sta,
|
||||
stop ? RADIUS_ACCT_STATUS_TYPE_STOP :
|
||||
RADIUS_ACCT_STATUS_TYPE_INTERIM_UPDATE);
|
||||
if (!msg) {
|
||||
printf("Could not create RADIUS Accounting message\n");
|
||||
return;
|
||||
}
|
||||
|
||||
os_get_time(&now);
|
||||
if (!radius_msg_add_attr_int32(msg, RADIUS_ATTR_ACCT_SESSION_TIME,
|
||||
now.sec - sta->acct_session_start)) {
|
||||
printf("Could not add Acct-Session-Time\n");
|
||||
goto fail;
|
||||
}
|
||||
|
||||
if (accounting_sta_update_stats(hapd, sta, &data) == 0) {
|
||||
if (!radius_msg_add_attr_int32(msg,
|
||||
RADIUS_ATTR_ACCT_INPUT_PACKETS,
|
||||
data.rx_packets)) {
|
||||
printf("Could not add Acct-Input-Packets\n");
|
||||
goto fail;
|
||||
}
|
||||
if (!radius_msg_add_attr_int32(msg,
|
||||
RADIUS_ATTR_ACCT_OUTPUT_PACKETS,
|
||||
data.tx_packets)) {
|
||||
printf("Could not add Acct-Output-Packets\n");
|
||||
goto fail;
|
||||
}
|
||||
if (!radius_msg_add_attr_int32(msg,
|
||||
RADIUS_ATTR_ACCT_INPUT_OCTETS,
|
||||
data.rx_bytes)) {
|
||||
printf("Could not add Acct-Input-Octets\n");
|
||||
goto fail;
|
||||
}
|
||||
gigawords = sta->acct_input_gigawords;
|
||||
#if __WORDSIZE == 64
|
||||
gigawords += data.rx_bytes >> 32;
|
||||
#endif
|
||||
if (gigawords &&
|
||||
!radius_msg_add_attr_int32(
|
||||
msg, RADIUS_ATTR_ACCT_INPUT_GIGAWORDS,
|
||||
gigawords)) {
|
||||
printf("Could not add Acct-Input-Gigawords\n");
|
||||
goto fail;
|
||||
}
|
||||
if (!radius_msg_add_attr_int32(msg,
|
||||
RADIUS_ATTR_ACCT_OUTPUT_OCTETS,
|
||||
data.tx_bytes)) {
|
||||
printf("Could not add Acct-Output-Octets\n");
|
||||
goto fail;
|
||||
}
|
||||
gigawords = sta->acct_output_gigawords;
|
||||
#if __WORDSIZE == 64
|
||||
gigawords += data.tx_bytes >> 32;
|
||||
#endif
|
||||
if (gigawords &&
|
||||
!radius_msg_add_attr_int32(
|
||||
msg, RADIUS_ATTR_ACCT_OUTPUT_GIGAWORDS,
|
||||
gigawords)) {
|
||||
printf("Could not add Acct-Output-Gigawords\n");
|
||||
goto fail;
|
||||
}
|
||||
}
|
||||
|
||||
if (!radius_msg_add_attr_int32(msg, RADIUS_ATTR_EVENT_TIMESTAMP,
|
||||
now.sec)) {
|
||||
printf("Could not add Event-Timestamp\n");
|
||||
goto fail;
|
||||
}
|
||||
|
||||
if (eloop_terminated())
|
||||
cause = RADIUS_ACCT_TERMINATE_CAUSE_ADMIN_REBOOT;
|
||||
|
||||
if (stop && cause &&
|
||||
!radius_msg_add_attr_int32(msg, RADIUS_ATTR_ACCT_TERMINATE_CAUSE,
|
||||
cause)) {
|
||||
printf("Could not add Acct-Terminate-Cause\n");
|
||||
goto fail;
|
||||
}
|
||||
|
||||
radius_client_send(hapd->radius, msg,
|
||||
stop ? RADIUS_ACCT : RADIUS_ACCT_INTERIM,
|
||||
sta->addr);
|
||||
return;
|
||||
|
||||
fail:
|
||||
radius_msg_free(msg);
|
||||
}
|
||||
|
||||
|
||||
/**
|
||||
* accounting_sta_interim - Send a interim STA accounting report
|
||||
* @hapd: hostapd BSS data
|
||||
* @sta: The station
|
||||
*/
|
||||
void accounting_sta_interim(struct hostapd_data *hapd, struct sta_info *sta)
|
||||
{
|
||||
if (sta->acct_session_started)
|
||||
accounting_sta_report(hapd, sta, 0);
|
||||
}
|
||||
|
||||
|
||||
/**
|
||||
* accounting_sta_stop - Stop STA accounting
|
||||
* @hapd: hostapd BSS data
|
||||
* @sta: The station
|
||||
*/
|
||||
void accounting_sta_stop(struct hostapd_data *hapd, struct sta_info *sta)
|
||||
{
|
||||
if (sta->acct_session_started) {
|
||||
accounting_sta_report(hapd, sta, 1);
|
||||
eloop_cancel_timeout(accounting_interim_update, hapd, sta);
|
||||
hostapd_logger(hapd, sta->addr, HOSTAPD_MODULE_RADIUS,
|
||||
HOSTAPD_LEVEL_INFO,
|
||||
"stopped accounting session %08X-%08X",
|
||||
sta->acct_session_id_hi,
|
||||
sta->acct_session_id_lo);
|
||||
sta->acct_session_started = 0;
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
static void accounting_sta_get_id(struct hostapd_data *hapd,
|
||||
struct sta_info *sta)
|
||||
{
|
||||
sta->acct_session_id_lo = hapd->acct_session_id_lo++;
|
||||
if (hapd->acct_session_id_lo == 0) {
|
||||
hapd->acct_session_id_hi++;
|
||||
}
|
||||
sta->acct_session_id_hi = hapd->acct_session_id_hi;
|
||||
}
|
||||
|
||||
|
||||
/**
|
||||
* accounting_receive - Process the RADIUS frames from Accounting Server
|
||||
* @msg: RADIUS response message
|
||||
* @req: RADIUS request message
|
||||
* @shared_secret: RADIUS shared secret
|
||||
* @shared_secret_len: Length of shared_secret in octets
|
||||
* @data: Context data (struct hostapd_data *)
|
||||
* Returns: Processing status
|
||||
*/
|
||||
static RadiusRxResult
|
||||
accounting_receive(struct radius_msg *msg, struct radius_msg *req,
|
||||
const u8 *shared_secret, size_t shared_secret_len,
|
||||
void *data)
|
||||
{
|
||||
if (radius_msg_get_hdr(msg)->code != RADIUS_CODE_ACCOUNTING_RESPONSE) {
|
||||
printf("Unknown RADIUS message code\n");
|
||||
return RADIUS_RX_UNKNOWN;
|
||||
}
|
||||
|
||||
if (radius_msg_verify(msg, shared_secret, shared_secret_len, req, 0)) {
|
||||
printf("Incoming RADIUS packet did not have correct "
|
||||
"Authenticator - dropped\n");
|
||||
return RADIUS_RX_INVALID_AUTHENTICATOR;
|
||||
}
|
||||
|
||||
return RADIUS_RX_PROCESSED;
|
||||
}
|
||||
|
||||
|
||||
static void accounting_report_state(struct hostapd_data *hapd, int on)
|
||||
{
|
||||
struct radius_msg *msg;
|
||||
|
||||
if (!hapd->conf->radius->acct_server || hapd->radius == NULL)
|
||||
return;
|
||||
|
||||
/* Inform RADIUS server that accounting will start/stop so that the
|
||||
* server can close old accounting sessions. */
|
||||
msg = accounting_msg(hapd, NULL,
|
||||
on ? RADIUS_ACCT_STATUS_TYPE_ACCOUNTING_ON :
|
||||
RADIUS_ACCT_STATUS_TYPE_ACCOUNTING_OFF);
|
||||
if (!msg)
|
||||
return;
|
||||
|
||||
if (!radius_msg_add_attr_int32(msg, RADIUS_ATTR_ACCT_TERMINATE_CAUSE,
|
||||
RADIUS_ACCT_TERMINATE_CAUSE_NAS_REBOOT))
|
||||
{
|
||||
printf("Could not add Acct-Terminate-Cause\n");
|
||||
radius_msg_free(msg);
|
||||
return;
|
||||
}
|
||||
|
||||
radius_client_send(hapd->radius, msg, RADIUS_ACCT, NULL);
|
||||
}
|
||||
|
||||
|
||||
/**
|
||||
* accounting_init: Initialize accounting
|
||||
* @hapd: hostapd BSS data
|
||||
* Returns: 0 on success, -1 on failure
|
||||
*/
|
||||
int accounting_init(struct hostapd_data *hapd)
|
||||
{
|
||||
struct os_time now;
|
||||
|
||||
/* Acct-Session-Id should be unique over reboots. If reliable clock is
|
||||
* not available, this could be replaced with reboot counter, etc. */
|
||||
os_get_time(&now);
|
||||
hapd->acct_session_id_hi = now.sec;
|
||||
|
||||
if (radius_client_register(hapd->radius, RADIUS_ACCT,
|
||||
accounting_receive, hapd))
|
||||
return -1;
|
||||
|
||||
accounting_report_state(hapd, 1);
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
|
||||
/**
|
||||
* accounting_deinit: Deinitilize accounting
|
||||
* @hapd: hostapd BSS data
|
||||
*/
|
||||
void accounting_deinit(struct hostapd_data *hapd)
|
||||
{
|
||||
accounting_report_state(hapd, 0);
|
||||
}
|
45
hostapd-0.8/src/ap/accounting.h
Normal file
45
hostapd-0.8/src/ap/accounting.h
Normal file
|
@ -0,0 +1,45 @@
|
|||
/*
|
||||
* 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.
|
||||
*/
|
||||
|
||||
#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_start(struct hostapd_data *hapd,
|
||||
struct sta_info *sta)
|
||||
{
|
||||
}
|
||||
|
||||
static inline void accounting_sta_stop(struct hostapd_data *hapd,
|
||||
struct sta_info *sta)
|
||||
{
|
||||
}
|
||||
|
||||
static inline int accounting_init(struct hostapd_data *hapd)
|
||||
{
|
||||
return 0;
|
||||
}
|
||||
|
||||
static inline void accounting_deinit(struct hostapd_data *hapd)
|
||||
{
|
||||
}
|
||||
#else /* CONFIG_NO_ACCOUNTING */
|
||||
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);
|
||||
void accounting_deinit(struct hostapd_data *hapd);
|
||||
#endif /* CONFIG_NO_ACCOUNTING */
|
||||
|
||||
#endif /* ACCOUNTING_H */
|
627
hostapd-0.8/src/ap/ap_config.c
Normal file
627
hostapd-0.8/src/ap/ap_config.c
Normal file
|
@ -0,0 +1,627 @@
|
|||
/*
|
||||
* hostapd / Configuration helper functions
|
||||
* 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.
|
||||
*/
|
||||
|
||||
#include "utils/includes.h"
|
||||
|
||||
#include "utils/common.h"
|
||||
#include "crypto/sha1.h"
|
||||
#include "radius/radius_client.h"
|
||||
#include "common/ieee802_11_defs.h"
|
||||
#include "common/eapol_common.h"
|
||||
#include "eap_common/eap_wsc_common.h"
|
||||
#include "eap_server/eap.h"
|
||||
#include "wpa_auth.h"
|
||||
#include "sta_info.h"
|
||||
#include "ap_config.h"
|
||||
|
||||
|
||||
static void hostapd_config_free_vlan(struct hostapd_bss_config *bss)
|
||||
{
|
||||
struct hostapd_vlan *vlan, *prev;
|
||||
|
||||
vlan = bss->vlan;
|
||||
prev = NULL;
|
||||
while (vlan) {
|
||||
prev = vlan;
|
||||
vlan = vlan->next;
|
||||
os_free(prev);
|
||||
}
|
||||
|
||||
bss->vlan = NULL;
|
||||
}
|
||||
|
||||
|
||||
void hostapd_config_defaults_bss(struct hostapd_bss_config *bss)
|
||||
{
|
||||
bss->logger_syslog_level = HOSTAPD_LEVEL_INFO;
|
||||
bss->logger_stdout_level = HOSTAPD_LEVEL_INFO;
|
||||
bss->logger_syslog = (unsigned int) -1;
|
||||
bss->logger_stdout = (unsigned int) -1;
|
||||
|
||||
bss->auth_algs = WPA_AUTH_ALG_OPEN | WPA_AUTH_ALG_SHARED;
|
||||
|
||||
bss->wep_rekeying_period = 300;
|
||||
/* use key0 in individual key and key1 in broadcast key */
|
||||
bss->broadcast_key_idx_min = 1;
|
||||
bss->broadcast_key_idx_max = 2;
|
||||
bss->eap_reauth_period = 3600;
|
||||
|
||||
bss->wpa_group_rekey = 600;
|
||||
bss->wpa_gmk_rekey = 86400;
|
||||
bss->wpa_key_mgmt = WPA_KEY_MGMT_PSK;
|
||||
bss->wpa_pairwise = WPA_CIPHER_TKIP;
|
||||
bss->wpa_group = WPA_CIPHER_TKIP;
|
||||
bss->rsn_pairwise = 0;
|
||||
|
||||
bss->max_num_sta = MAX_STA_COUNT;
|
||||
|
||||
bss->dtim_period = 2;
|
||||
|
||||
bss->radius_server_auth_port = 1812;
|
||||
bss->ap_max_inactivity = AP_MAX_INACTIVITY;
|
||||
bss->eapol_version = EAPOL_VERSION;
|
||||
|
||||
bss->max_listen_interval = 65535;
|
||||
|
||||
bss->pwd_group = 19; /* ECC: GF(p=256) */
|
||||
|
||||
#ifdef CONFIG_IEEE80211W
|
||||
bss->assoc_sa_query_max_timeout = 1000;
|
||||
bss->assoc_sa_query_retry_timeout = 201;
|
||||
#endif /* CONFIG_IEEE80211W */
|
||||
#ifdef EAP_SERVER_FAST
|
||||
/* both anonymous and authenticated provisioning */
|
||||
bss->eap_fast_prov = 3;
|
||||
bss->pac_key_lifetime = 7 * 24 * 60 * 60;
|
||||
bss->pac_key_refresh_time = 1 * 24 * 60 * 60;
|
||||
#endif /* EAP_SERVER_FAST */
|
||||
|
||||
/* Set to -1 as defaults depends on HT in setup */
|
||||
bss->wmm_enabled = -1;
|
||||
|
||||
#ifdef CONFIG_IEEE80211R
|
||||
bss->ft_over_ds = 1;
|
||||
#endif /* CONFIG_IEEE80211R */
|
||||
}
|
||||
|
||||
|
||||
struct hostapd_config * hostapd_config_defaults(void)
|
||||
{
|
||||
#define ecw2cw(ecw) ((1 << (ecw)) - 1)
|
||||
|
||||
struct hostapd_config *conf;
|
||||
struct hostapd_bss_config *bss;
|
||||
const int aCWmin = 4, aCWmax = 10;
|
||||
const struct hostapd_wmm_ac_params ac_bk =
|
||||
{ aCWmin, aCWmax, 7, 0, 0 }; /* background traffic */
|
||||
const struct hostapd_wmm_ac_params ac_be =
|
||||
{ aCWmin, aCWmax, 3, 0, 0 }; /* best effort traffic */
|
||||
const struct hostapd_wmm_ac_params ac_vi = /* video traffic */
|
||||
{ aCWmin - 1, aCWmin, 2, 3000 / 32, 1 };
|
||||
const struct hostapd_wmm_ac_params ac_vo = /* voice traffic */
|
||||
{ aCWmin - 2, aCWmin - 1, 2, 1500 / 32, 1 };
|
||||
const struct hostapd_tx_queue_params txq_bk =
|
||||
{ 7, ecw2cw(aCWmin), ecw2cw(aCWmax), 0 };
|
||||
const struct hostapd_tx_queue_params txq_be =
|
||||
{ 3, ecw2cw(aCWmin), 4 * (ecw2cw(aCWmin) + 1) - 1, 0};
|
||||
const struct hostapd_tx_queue_params txq_vi =
|
||||
{ 1, (ecw2cw(aCWmin) + 1) / 2 - 1, ecw2cw(aCWmin), 30};
|
||||
const struct hostapd_tx_queue_params txq_vo =
|
||||
{ 1, (ecw2cw(aCWmin) + 1) / 4 - 1,
|
||||
(ecw2cw(aCWmin) + 1) / 2 - 1, 15};
|
||||
|
||||
#undef ecw2cw
|
||||
|
||||
conf = os_zalloc(sizeof(*conf));
|
||||
bss = os_zalloc(sizeof(*bss));
|
||||
if (conf == NULL || bss == NULL) {
|
||||
wpa_printf(MSG_ERROR, "Failed to allocate memory for "
|
||||
"configuration data.");
|
||||
os_free(conf);
|
||||
os_free(bss);
|
||||
return NULL;
|
||||
}
|
||||
|
||||
bss->radius = os_zalloc(sizeof(*bss->radius));
|
||||
if (bss->radius == NULL) {
|
||||
os_free(conf);
|
||||
os_free(bss);
|
||||
return NULL;
|
||||
}
|
||||
|
||||
hostapd_config_defaults_bss(bss);
|
||||
|
||||
conf->num_bss = 1;
|
||||
conf->bss = bss;
|
||||
|
||||
conf->beacon_int = 100;
|
||||
conf->rts_threshold = -1; /* use driver default: 2347 */
|
||||
conf->fragm_threshold = -1; /* user driver default: 2346 */
|
||||
conf->send_probe_response = 1;
|
||||
|
||||
conf->wmm_ac_params[0] = ac_be;
|
||||
conf->wmm_ac_params[1] = ac_bk;
|
||||
conf->wmm_ac_params[2] = ac_vi;
|
||||
conf->wmm_ac_params[3] = ac_vo;
|
||||
|
||||
conf->tx_queue[0] = txq_vo;
|
||||
conf->tx_queue[1] = txq_vi;
|
||||
conf->tx_queue[2] = txq_be;
|
||||
conf->tx_queue[3] = txq_bk;
|
||||
|
||||
conf->ht_capab = HT_CAP_INFO_SMPS_DISABLED;
|
||||
|
||||
return conf;
|
||||
}
|
||||
|
||||
|
||||
int hostapd_mac_comp(const void *a, const void *b)
|
||||
{
|
||||
return os_memcmp(a, b, sizeof(macaddr));
|
||||
}
|
||||
|
||||
|
||||
int hostapd_mac_comp_empty(const void *a)
|
||||
{
|
||||
macaddr empty = { 0 };
|
||||
return os_memcmp(a, empty, sizeof(macaddr));
|
||||
}
|
||||
|
||||
|
||||
static int hostapd_config_read_wpa_psk(const char *fname,
|
||||
struct hostapd_ssid *ssid)
|
||||
{
|
||||
FILE *f;
|
||||
char buf[128], *pos;
|
||||
int line = 0, ret = 0, len, ok;
|
||||
u8 addr[ETH_ALEN];
|
||||
struct hostapd_wpa_psk *psk;
|
||||
|
||||
if (!fname)
|
||||
return 0;
|
||||
|
||||
f = fopen(fname, "r");
|
||||
if (!f) {
|
||||
wpa_printf(MSG_ERROR, "WPA PSK file '%s' not found.", fname);
|
||||
return -1;
|
||||
}
|
||||
|
||||
while (fgets(buf, sizeof(buf), f)) {
|
||||
line++;
|
||||
|
||||
if (buf[0] == '#')
|
||||
continue;
|
||||
pos = buf;
|
||||
while (*pos != '\0') {
|
||||
if (*pos == '\n') {
|
||||
*pos = '\0';
|
||||
break;
|
||||
}
|
||||
pos++;
|
||||
}
|
||||
if (buf[0] == '\0')
|
||||
continue;
|
||||
|
||||
if (hwaddr_aton(buf, addr)) {
|
||||
wpa_printf(MSG_ERROR, "Invalid MAC address '%s' on "
|
||||
"line %d in '%s'", buf, line, fname);
|
||||
ret = -1;
|
||||
break;
|
||||
}
|
||||
|
||||
psk = os_zalloc(sizeof(*psk));
|
||||
if (psk == NULL) {
|
||||
wpa_printf(MSG_ERROR, "WPA PSK allocation failed");
|
||||
ret = -1;
|
||||
break;
|
||||
}
|
||||
if (is_zero_ether_addr(addr))
|
||||
psk->group = 1;
|
||||
else
|
||||
os_memcpy(psk->addr, addr, ETH_ALEN);
|
||||
|
||||
pos = buf + 17;
|
||||
if (*pos == '\0') {
|
||||
wpa_printf(MSG_ERROR, "No PSK on line %d in '%s'",
|
||||
line, fname);
|
||||
os_free(psk);
|
||||
ret = -1;
|
||||
break;
|
||||
}
|
||||
pos++;
|
||||
|
||||
ok = 0;
|
||||
len = os_strlen(pos);
|
||||
if (len == 64 && hexstr2bin(pos, psk->psk, PMK_LEN) == 0)
|
||||
ok = 1;
|
||||
else if (len >= 8 && len < 64) {
|
||||
pbkdf2_sha1(pos, ssid->ssid, ssid->ssid_len,
|
||||
4096, psk->psk, PMK_LEN);
|
||||
ok = 1;
|
||||
}
|
||||
if (!ok) {
|
||||
wpa_printf(MSG_ERROR, "Invalid PSK '%s' on line %d in "
|
||||
"'%s'", pos, line, fname);
|
||||
os_free(psk);
|
||||
ret = -1;
|
||||
break;
|
||||
}
|
||||
|
||||
psk->next = ssid->wpa_psk;
|
||||
ssid->wpa_psk = psk;
|
||||
}
|
||||
|
||||
fclose(f);
|
||||
|
||||
return ret;
|
||||
}
|
||||
|
||||
|
||||
static int hostapd_derive_psk(struct hostapd_ssid *ssid)
|
||||
{
|
||||
ssid->wpa_psk = os_zalloc(sizeof(struct hostapd_wpa_psk));
|
||||
if (ssid->wpa_psk == NULL) {
|
||||
wpa_printf(MSG_ERROR, "Unable to alloc space for PSK");
|
||||
return -1;
|
||||
}
|
||||
wpa_hexdump_ascii(MSG_DEBUG, "SSID",
|
||||
(u8 *) ssid->ssid, ssid->ssid_len);
|
||||
wpa_hexdump_ascii_key(MSG_DEBUG, "PSK (ASCII passphrase)",
|
||||
(u8 *) ssid->wpa_passphrase,
|
||||
os_strlen(ssid->wpa_passphrase));
|
||||
pbkdf2_sha1(ssid->wpa_passphrase,
|
||||
ssid->ssid, ssid->ssid_len,
|
||||
4096, ssid->wpa_psk->psk, PMK_LEN);
|
||||
wpa_hexdump_key(MSG_DEBUG, "PSK (from passphrase)",
|
||||
ssid->wpa_psk->psk, PMK_LEN);
|
||||
return 0;
|
||||
}
|
||||
|
||||
|
||||
int hostapd_setup_wpa_psk(struct hostapd_bss_config *conf)
|
||||
{
|
||||
struct hostapd_ssid *ssid = &conf->ssid;
|
||||
|
||||
if (ssid->wpa_passphrase != NULL) {
|
||||
if (ssid->wpa_psk != NULL) {
|
||||
wpa_printf(MSG_DEBUG, "Using pre-configured WPA PSK "
|
||||
"instead of passphrase");
|
||||
} else {
|
||||
wpa_printf(MSG_DEBUG, "Deriving WPA PSK based on "
|
||||
"passphrase");
|
||||
if (hostapd_derive_psk(ssid) < 0)
|
||||
return -1;
|
||||
}
|
||||
ssid->wpa_psk->group = 1;
|
||||
}
|
||||
|
||||
if (ssid->wpa_psk_file) {
|
||||
if (hostapd_config_read_wpa_psk(ssid->wpa_psk_file,
|
||||
&conf->ssid))
|
||||
return -1;
|
||||
}
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
|
||||
int hostapd_wep_key_cmp(struct hostapd_wep_keys *a, struct hostapd_wep_keys *b)
|
||||
{
|
||||
int i;
|
||||
|
||||
if (a->idx != b->idx || a->default_len != b->default_len)
|
||||
return 1;
|
||||
for (i = 0; i < NUM_WEP_KEYS; i++)
|
||||
if (a->len[i] != b->len[i] ||
|
||||
os_memcmp(a->key[i], b->key[i], a->len[i]) != 0)
|
||||
return 1;
|
||||
return 0;
|
||||
}
|
||||
|
||||
|
||||
static void hostapd_config_free_radius(struct hostapd_radius_server *servers,
|
||||
int num_servers)
|
||||
{
|
||||
int i;
|
||||
|
||||
for (i = 0; i < num_servers; i++) {
|
||||
os_free(servers[i].shared_secret);
|
||||
}
|
||||
os_free(servers);
|
||||
}
|
||||
|
||||
|
||||
static void hostapd_config_free_eap_user(struct hostapd_eap_user *user)
|
||||
{
|
||||
os_free(user->identity);
|
||||
os_free(user->password);
|
||||
os_free(user);
|
||||
}
|
||||
|
||||
|
||||
static void hostapd_config_free_wep(struct hostapd_wep_keys *keys)
|
||||
{
|
||||
int i;
|
||||
for (i = 0; i < NUM_WEP_KEYS; i++) {
|
||||
os_free(keys->key[i]);
|
||||
keys->key[i] = NULL;
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
static void hostapd_config_free_bss(struct hostapd_bss_config *conf)
|
||||
{
|
||||
struct hostapd_wpa_psk *psk, *prev;
|
||||
struct hostapd_eap_user *user, *prev_user;
|
||||
|
||||
if (conf == NULL)
|
||||
return;
|
||||
|
||||
psk = conf->ssid.wpa_psk;
|
||||
while (psk) {
|
||||
prev = psk;
|
||||
psk = psk->next;
|
||||
os_free(prev);
|
||||
}
|
||||
|
||||
os_free(conf->ssid.wpa_passphrase);
|
||||
os_free(conf->ssid.wpa_psk_file);
|
||||
hostapd_config_free_wep(&conf->ssid.wep);
|
||||
#ifdef CONFIG_FULL_DYNAMIC_VLAN
|
||||
os_free(conf->ssid.vlan_tagged_interface);
|
||||
#endif /* CONFIG_FULL_DYNAMIC_VLAN */
|
||||
|
||||
user = conf->eap_user;
|
||||
while (user) {
|
||||
prev_user = user;
|
||||
user = user->next;
|
||||
hostapd_config_free_eap_user(prev_user);
|
||||
}
|
||||
|
||||
os_free(conf->dump_log_name);
|
||||
os_free(conf->eap_req_id_text);
|
||||
os_free(conf->accept_mac);
|
||||
os_free(conf->deny_mac);
|
||||
os_free(conf->nas_identifier);
|
||||
hostapd_config_free_radius(conf->radius->auth_servers,
|
||||
conf->radius->num_auth_servers);
|
||||
hostapd_config_free_radius(conf->radius->acct_servers,
|
||||
conf->radius->num_acct_servers);
|
||||
os_free(conf->rsn_preauth_interfaces);
|
||||
os_free(conf->ctrl_interface);
|
||||
os_free(conf->ca_cert);
|
||||
os_free(conf->server_cert);
|
||||
os_free(conf->private_key);
|
||||
os_free(conf->private_key_passwd);
|
||||
os_free(conf->dh_file);
|
||||
os_free(conf->pac_opaque_encr_key);
|
||||
os_free(conf->eap_fast_a_id);
|
||||
os_free(conf->eap_fast_a_id_info);
|
||||
os_free(conf->eap_sim_db);
|
||||
os_free(conf->radius_server_clients);
|
||||
os_free(conf->test_socket);
|
||||
os_free(conf->radius);
|
||||
hostapd_config_free_vlan(conf);
|
||||
if (conf->ssid.dyn_vlan_keys) {
|
||||
struct hostapd_ssid *ssid = &conf->ssid;
|
||||
size_t i;
|
||||
for (i = 0; i <= ssid->max_dyn_vlan_keys; i++) {
|
||||
if (ssid->dyn_vlan_keys[i] == NULL)
|
||||
continue;
|
||||
hostapd_config_free_wep(ssid->dyn_vlan_keys[i]);
|
||||
os_free(ssid->dyn_vlan_keys[i]);
|
||||
}
|
||||
os_free(ssid->dyn_vlan_keys);
|
||||
ssid->dyn_vlan_keys = NULL;
|
||||
}
|
||||
|
||||
#ifdef CONFIG_IEEE80211R
|
||||
{
|
||||
struct ft_remote_r0kh *r0kh, *r0kh_prev;
|
||||
struct ft_remote_r1kh *r1kh, *r1kh_prev;
|
||||
|
||||
r0kh = conf->r0kh_list;
|
||||
conf->r0kh_list = NULL;
|
||||
while (r0kh) {
|
||||
r0kh_prev = r0kh;
|
||||
r0kh = r0kh->next;
|
||||
os_free(r0kh_prev);
|
||||
}
|
||||
|
||||
r1kh = conf->r1kh_list;
|
||||
conf->r1kh_list = NULL;
|
||||
while (r1kh) {
|
||||
r1kh_prev = r1kh;
|
||||
r1kh = r1kh->next;
|
||||
os_free(r1kh_prev);
|
||||
}
|
||||
}
|
||||
#endif /* CONFIG_IEEE80211R */
|
||||
|
||||
#ifdef CONFIG_WPS
|
||||
os_free(conf->wps_pin_requests);
|
||||
os_free(conf->device_name);
|
||||
os_free(conf->manufacturer);
|
||||
os_free(conf->model_name);
|
||||
os_free(conf->model_number);
|
||||
os_free(conf->serial_number);
|
||||
os_free(conf->config_methods);
|
||||
os_free(conf->ap_pin);
|
||||
os_free(conf->extra_cred);
|
||||
os_free(conf->ap_settings);
|
||||
os_free(conf->upnp_iface);
|
||||
os_free(conf->friendly_name);
|
||||
os_free(conf->manufacturer_url);
|
||||
os_free(conf->model_description);
|
||||
os_free(conf->model_url);
|
||||
os_free(conf->upc);
|
||||
#endif /* CONFIG_WPS */
|
||||
}
|
||||
|
||||
|
||||
/**
|
||||
* hostapd_config_free - Free hostapd configuration
|
||||
* @conf: Configuration data from hostapd_config_read().
|
||||
*/
|
||||
void hostapd_config_free(struct hostapd_config *conf)
|
||||
{
|
||||
size_t i;
|
||||
|
||||
if (conf == NULL)
|
||||
return;
|
||||
|
||||
for (i = 0; i < conf->num_bss; i++)
|
||||
hostapd_config_free_bss(&conf->bss[i]);
|
||||
os_free(conf->bss);
|
||||
os_free(conf->supported_rates);
|
||||
os_free(conf->basic_rates);
|
||||
|
||||
os_free(conf);
|
||||
}
|
||||
|
||||
|
||||
/**
|
||||
* hostapd_maclist_found - Find a MAC address from a list
|
||||
* @list: MAC address list
|
||||
* @num_entries: Number of addresses in the list
|
||||
* @addr: Address to search for
|
||||
* @vlan_id: Buffer for returning VLAN ID or %NULL if not needed
|
||||
* Returns: 1 if address is in the list or 0 if not.
|
||||
*
|
||||
* Perform a binary search for given MAC address from a pre-sorted list.
|
||||
*/
|
||||
int hostapd_maclist_found(struct mac_acl_entry *list, int num_entries,
|
||||
const u8 *addr, int *vlan_id)
|
||||
{
|
||||
int start, end, middle, res;
|
||||
|
||||
start = 0;
|
||||
end = num_entries - 1;
|
||||
|
||||
while (start <= end) {
|
||||
middle = (start + end) / 2;
|
||||
res = os_memcmp(list[middle].addr, addr, ETH_ALEN);
|
||||
if (res == 0) {
|
||||
if (vlan_id)
|
||||
*vlan_id = list[middle].vlan_id;
|
||||
return 1;
|
||||
}
|
||||
if (res < 0)
|
||||
start = middle + 1;
|
||||
else
|
||||
end = middle - 1;
|
||||
}
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
|
||||
int hostapd_rate_found(int *list, int rate)
|
||||
{
|
||||
int i;
|
||||
|
||||
if (list == NULL)
|
||||
return 0;
|
||||
|
||||
for (i = 0; list[i] >= 0; i++)
|
||||
if (list[i] == rate)
|
||||
return 1;
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
|
||||
const char * hostapd_get_vlan_id_ifname(struct hostapd_vlan *vlan, int vlan_id)
|
||||
{
|
||||
struct hostapd_vlan *v = vlan;
|
||||
while (v) {
|
||||
if (v->vlan_id == vlan_id || v->vlan_id == VLAN_ID_WILDCARD)
|
||||
return v->ifname;
|
||||
v = v->next;
|
||||
}
|
||||
return NULL;
|
||||
}
|
||||
|
||||
|
||||
const u8 * hostapd_get_psk(const struct hostapd_bss_config *conf,
|
||||
const u8 *addr, const u8 *prev_psk)
|
||||
{
|
||||
struct hostapd_wpa_psk *psk;
|
||||
int next_ok = prev_psk == NULL;
|
||||
|
||||
for (psk = conf->ssid.wpa_psk; psk != NULL; psk = psk->next) {
|
||||
if (next_ok &&
|
||||
(psk->group || os_memcmp(psk->addr, addr, ETH_ALEN) == 0))
|
||||
return psk->psk;
|
||||
|
||||
if (psk->psk == prev_psk)
|
||||
next_ok = 1;
|
||||
}
|
||||
|
||||
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;
|
||||
}
|
417
hostapd-0.8/src/ap/ap_config.h
Normal file
417
hostapd-0.8/src/ap/ap_config.h
Normal file
|
@ -0,0 +1,417 @@
|
|||
/*
|
||||
* hostapd / Configuration definitions and helpers functions
|
||||
* 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.
|
||||
*/
|
||||
|
||||
#ifndef HOSTAPD_CONFIG_H
|
||||
#define HOSTAPD_CONFIG_H
|
||||
|
||||
#include "common/defs.h"
|
||||
#include "ip_addr.h"
|
||||
#include "common/wpa_common.h"
|
||||
#include "wps/wps.h"
|
||||
|
||||
#define MAX_STA_COUNT 2007
|
||||
#define MAX_VLAN_ID 4094
|
||||
|
||||
typedef u8 macaddr[ETH_ALEN];
|
||||
|
||||
struct mac_acl_entry {
|
||||
macaddr addr;
|
||||
int vlan_id;
|
||||
};
|
||||
|
||||
struct hostapd_radius_servers;
|
||||
struct ft_remote_r0kh;
|
||||
struct ft_remote_r1kh;
|
||||
|
||||
#define HOSTAPD_MAX_SSID_LEN 32
|
||||
|
||||
#define NUM_WEP_KEYS 4
|
||||
struct hostapd_wep_keys {
|
||||
u8 idx;
|
||||
u8 *key[NUM_WEP_KEYS];
|
||||
size_t len[NUM_WEP_KEYS];
|
||||
int keys_set;
|
||||
size_t default_len; /* key length used for dynamic key generation */
|
||||
};
|
||||
|
||||
typedef enum hostap_security_policy {
|
||||
SECURITY_PLAINTEXT = 0,
|
||||
SECURITY_STATIC_WEP = 1,
|
||||
SECURITY_IEEE_802_1X = 2,
|
||||
SECURITY_WPA_PSK = 3,
|
||||
SECURITY_WPA = 4
|
||||
} secpolicy;
|
||||
|
||||
struct hostapd_ssid {
|
||||
char ssid[HOSTAPD_MAX_SSID_LEN + 1];
|
||||
size_t ssid_len;
|
||||
int ssid_set;
|
||||
|
||||
char vlan[IFNAMSIZ + 1];
|
||||
secpolicy security_policy;
|
||||
|
||||
struct hostapd_wpa_psk *wpa_psk;
|
||||
char *wpa_passphrase;
|
||||
char *wpa_psk_file;
|
||||
|
||||
struct hostapd_wep_keys wep;
|
||||
|
||||
#define DYNAMIC_VLAN_DISABLED 0
|
||||
#define DYNAMIC_VLAN_OPTIONAL 1
|
||||
#define DYNAMIC_VLAN_REQUIRED 2
|
||||
int dynamic_vlan;
|
||||
#ifdef CONFIG_FULL_DYNAMIC_VLAN
|
||||
char *vlan_tagged_interface;
|
||||
#endif /* CONFIG_FULL_DYNAMIC_VLAN */
|
||||
struct hostapd_wep_keys **dyn_vlan_keys;
|
||||
size_t max_dyn_vlan_keys;
|
||||
};
|
||||
|
||||
|
||||
#define VLAN_ID_WILDCARD -1
|
||||
|
||||
struct hostapd_vlan {
|
||||
struct hostapd_vlan *next;
|
||||
int vlan_id; /* VLAN ID or -1 (VLAN_ID_WILDCARD) for wildcard entry */
|
||||
char ifname[IFNAMSIZ + 1];
|
||||
int dynamic_vlan;
|
||||
#ifdef CONFIG_FULL_DYNAMIC_VLAN
|
||||
|
||||
#define DVLAN_CLEAN_BR 0x1
|
||||
#define DVLAN_CLEAN_VLAN 0x2
|
||||
#define DVLAN_CLEAN_VLAN_PORT 0x4
|
||||
#define DVLAN_CLEAN_WLAN_PORT 0x8
|
||||
int clean;
|
||||
#endif /* CONFIG_FULL_DYNAMIC_VLAN */
|
||||
};
|
||||
|
||||
#define PMK_LEN 32
|
||||
struct hostapd_wpa_psk {
|
||||
struct hostapd_wpa_psk *next;
|
||||
int group;
|
||||
u8 psk[PMK_LEN];
|
||||
u8 addr[ETH_ALEN];
|
||||
};
|
||||
|
||||
#define EAP_USER_MAX_METHODS 8
|
||||
struct hostapd_eap_user {
|
||||
struct hostapd_eap_user *next;
|
||||
u8 *identity;
|
||||
size_t identity_len;
|
||||
struct {
|
||||
int vendor;
|
||||
u32 method;
|
||||
} methods[EAP_USER_MAX_METHODS];
|
||||
u8 *password;
|
||||
size_t password_len;
|
||||
int phase2;
|
||||
int force_version;
|
||||
unsigned int wildcard_prefix:1;
|
||||
unsigned int password_hash:1; /* whether password is hashed with
|
||||
* nt_password_hash() */
|
||||
int ttls_auth; /* EAP_TTLS_AUTH_* bitfield */
|
||||
};
|
||||
|
||||
|
||||
#define NUM_TX_QUEUES 4
|
||||
|
||||
struct hostapd_tx_queue_params {
|
||||
int aifs;
|
||||
int cwmin;
|
||||
int cwmax;
|
||||
int burst; /* maximum burst time in 0.1 ms, i.e., 10 = 1 ms */
|
||||
};
|
||||
|
||||
struct hostapd_wmm_ac_params {
|
||||
int cwmin;
|
||||
int cwmax;
|
||||
int aifs;
|
||||
int txop_limit; /* in units of 32us */
|
||||
int admission_control_mandatory;
|
||||
};
|
||||
|
||||
|
||||
/**
|
||||
* struct hostapd_bss_config - Per-BSS configuration
|
||||
*/
|
||||
struct hostapd_bss_config {
|
||||
char iface[IFNAMSIZ + 1];
|
||||
char bridge[IFNAMSIZ + 1];
|
||||
char wds_bridge[IFNAMSIZ + 1];
|
||||
|
||||
enum hostapd_logger_level logger_syslog_level, logger_stdout_level;
|
||||
|
||||
unsigned int logger_syslog; /* module bitfield */
|
||||
unsigned int logger_stdout; /* module bitfield */
|
||||
|
||||
char *dump_log_name; /* file name for state dump (SIGUSR1) */
|
||||
|
||||
int max_num_sta; /* maximum number of STAs in station table */
|
||||
|
||||
int dtim_period;
|
||||
|
||||
int ieee802_1x; /* use IEEE 802.1X */
|
||||
int eapol_version;
|
||||
int eap_server; /* Use internal EAP server instead of external
|
||||
* RADIUS server */
|
||||
struct hostapd_eap_user *eap_user;
|
||||
char *eap_sim_db;
|
||||
struct hostapd_ip_addr own_ip_addr;
|
||||
char *nas_identifier;
|
||||
struct hostapd_radius_servers *radius;
|
||||
int acct_interim_interval;
|
||||
|
||||
struct hostapd_ssid ssid;
|
||||
|
||||
char *eap_req_id_text; /* optional displayable message sent with
|
||||
* EAP Request-Identity */
|
||||
size_t eap_req_id_text_len;
|
||||
int eapol_key_index_workaround;
|
||||
|
||||
size_t default_wep_key_len;
|
||||
int individual_wep_key_len;
|
||||
int wep_rekeying_period;
|
||||
int broadcast_key_idx_min, broadcast_key_idx_max;
|
||||
int eap_reauth_period;
|
||||
|
||||
int ieee802_11f; /* use IEEE 802.11f (IAPP) */
|
||||
char iapp_iface[IFNAMSIZ + 1]; /* interface used with IAPP broadcast
|
||||
* frames */
|
||||
|
||||
enum {
|
||||
ACCEPT_UNLESS_DENIED = 0,
|
||||
DENY_UNLESS_ACCEPTED = 1,
|
||||
USE_EXTERNAL_RADIUS_AUTH = 2
|
||||
} macaddr_acl;
|
||||
struct mac_acl_entry *accept_mac;
|
||||
int num_accept_mac;
|
||||
struct mac_acl_entry *deny_mac;
|
||||
int num_deny_mac;
|
||||
int wds_sta;
|
||||
int isolate;
|
||||
|
||||
int auth_algs; /* bitfield of allowed IEEE 802.11 authentication
|
||||
* algorithms, WPA_AUTH_ALG_{OPEN,SHARED,LEAP} */
|
||||
|
||||
int wpa; /* bitfield of WPA_PROTO_WPA, WPA_PROTO_RSN */
|
||||
int wpa_key_mgmt;
|
||||
#ifdef CONFIG_IEEE80211W
|
||||
enum mfp_options ieee80211w;
|
||||
/* dot11AssociationSAQueryMaximumTimeout (in TUs) */
|
||||
unsigned int assoc_sa_query_max_timeout;
|
||||
/* dot11AssociationSAQueryRetryTimeout (in TUs) */
|
||||
int assoc_sa_query_retry_timeout;
|
||||
#endif /* CONFIG_IEEE80211W */
|
||||
int wpa_pairwise;
|
||||
int wpa_group;
|
||||
int wpa_group_rekey;
|
||||
int wpa_strict_rekey;
|
||||
int wpa_gmk_rekey;
|
||||
int wpa_ptk_rekey;
|
||||
int rsn_pairwise;
|
||||
int rsn_preauth;
|
||||
char *rsn_preauth_interfaces;
|
||||
int peerkey;
|
||||
|
||||
#ifdef CONFIG_IEEE80211R
|
||||
/* IEEE 802.11r - Fast BSS Transition */
|
||||
u8 mobility_domain[MOBILITY_DOMAIN_ID_LEN];
|
||||
u8 r1_key_holder[FT_R1KH_ID_LEN];
|
||||
u32 r0_key_lifetime;
|
||||
u32 reassociation_deadline;
|
||||
struct ft_remote_r0kh *r0kh_list;
|
||||
struct ft_remote_r1kh *r1kh_list;
|
||||
int pmk_r1_push;
|
||||
int ft_over_ds;
|
||||
#endif /* CONFIG_IEEE80211R */
|
||||
|
||||
char *ctrl_interface; /* directory for UNIX domain sockets */
|
||||
#ifndef CONFIG_NATIVE_WINDOWS
|
||||
gid_t ctrl_interface_gid;
|
||||
#endif /* CONFIG_NATIVE_WINDOWS */
|
||||
int ctrl_interface_gid_set;
|
||||
|
||||
char *ca_cert;
|
||||
char *server_cert;
|
||||
char *private_key;
|
||||
char *private_key_passwd;
|
||||
int check_crl;
|
||||
char *dh_file;
|
||||
u8 *pac_opaque_encr_key;
|
||||
u8 *eap_fast_a_id;
|
||||
size_t eap_fast_a_id_len;
|
||||
char *eap_fast_a_id_info;
|
||||
int eap_fast_prov;
|
||||
int pac_key_lifetime;
|
||||
int pac_key_refresh_time;
|
||||
int eap_sim_aka_result_ind;
|
||||
int tnc;
|
||||
int fragment_size;
|
||||
u16 pwd_group;
|
||||
|
||||
char *radius_server_clients;
|
||||
int radius_server_auth_port;
|
||||
int radius_server_ipv6;
|
||||
|
||||
char *test_socket; /* UNIX domain socket path for driver_test */
|
||||
|
||||
int use_pae_group_addr; /* Whether to send EAPOL frames to PAE group
|
||||
* address instead of individual address
|
||||
* (for driver_wired.c).
|
||||
*/
|
||||
|
||||
int ap_max_inactivity;
|
||||
int ignore_broadcast_ssid;
|
||||
|
||||
int wmm_enabled;
|
||||
int wmm_uapsd;
|
||||
|
||||
struct hostapd_vlan *vlan, *vlan_tail;
|
||||
|
||||
macaddr bssid;
|
||||
|
||||
/*
|
||||
* Maximum listen interval that STAs can use when associating with this
|
||||
* BSS. If a STA tries to use larger value, the association will be
|
||||
* denied with status code 51.
|
||||
*/
|
||||
u16 max_listen_interval;
|
||||
|
||||
int okc; /* Opportunistic Key Caching */
|
||||
|
||||
int wps_state;
|
||||
#ifdef CONFIG_WPS
|
||||
int ap_setup_locked;
|
||||
u8 uuid[16];
|
||||
char *wps_pin_requests;
|
||||
char *device_name;
|
||||
char *manufacturer;
|
||||
char *model_name;
|
||||
char *model_number;
|
||||
char *serial_number;
|
||||
u8 device_type[WPS_DEV_TYPE_LEN];
|
||||
char *config_methods;
|
||||
u8 os_version[4];
|
||||
char *ap_pin;
|
||||
int skip_cred_build;
|
||||
u8 *extra_cred;
|
||||
size_t extra_cred_len;
|
||||
int wps_cred_processing;
|
||||
u8 *ap_settings;
|
||||
size_t ap_settings_len;
|
||||
char *upnp_iface;
|
||||
char *friendly_name;
|
||||
char *manufacturer_url;
|
||||
char *model_description;
|
||||
char *model_url;
|
||||
char *upc;
|
||||
struct wpabuf *wps_vendor_ext[MAX_WPS_VENDOR_EXTENSIONS];
|
||||
#endif /* CONFIG_WPS */
|
||||
|
||||
#define P2P_ENABLED BIT(0)
|
||||
#define P2P_GROUP_OWNER BIT(1)
|
||||
#define P2P_GROUP_FORMATION BIT(2)
|
||||
#define P2P_MANAGE BIT(3)
|
||||
#define P2P_ALLOW_CROSS_CONNECTION BIT(4)
|
||||
int p2p;
|
||||
|
||||
int disassoc_low_ack;
|
||||
|
||||
#define TDLS_PROHIBIT BIT(0)
|
||||
#define TDLS_PROHIBIT_CHAN_SWITCH BIT(1)
|
||||
int tdls;
|
||||
int disable_11n;
|
||||
};
|
||||
|
||||
|
||||
/**
|
||||
* struct hostapd_config - Per-radio interface configuration
|
||||
*/
|
||||
struct hostapd_config {
|
||||
struct hostapd_bss_config *bss, *last_bss;
|
||||
size_t num_bss;
|
||||
|
||||
u16 beacon_int;
|
||||
int rts_threshold;
|
||||
int fragm_threshold;
|
||||
u8 send_probe_response;
|
||||
u8 channel;
|
||||
enum hostapd_hw_mode hw_mode; /* HOSTAPD_MODE_IEEE80211A, .. */
|
||||
enum {
|
||||
LONG_PREAMBLE = 0,
|
||||
SHORT_PREAMBLE = 1
|
||||
} preamble;
|
||||
enum {
|
||||
CTS_PROTECTION_AUTOMATIC = 0,
|
||||
CTS_PROTECTION_FORCE_ENABLED = 1,
|
||||
CTS_PROTECTION_FORCE_DISABLED = 2,
|
||||
CTS_PROTECTION_AUTOMATIC_NO_OLBC = 3,
|
||||
} cts_protection_type;
|
||||
|
||||
int *supported_rates;
|
||||
int *basic_rates;
|
||||
|
||||
const struct wpa_driver_ops *driver;
|
||||
|
||||
int ap_table_max_size;
|
||||
int ap_table_expiration_time;
|
||||
|
||||
char country[3]; /* first two octets: country code as described in
|
||||
* ISO/IEC 3166-1. Third octet:
|
||||
* ' ' (ascii 32): all environments
|
||||
* 'O': Outdoor environemnt only
|
||||
* 'I': Indoor environment only
|
||||
*/
|
||||
|
||||
int ieee80211d;
|
||||
|
||||
struct hostapd_tx_queue_params tx_queue[NUM_TX_QUEUES];
|
||||
|
||||
/*
|
||||
* WMM AC parameters, in same order as 802.1D, i.e.
|
||||
* 0 = BE (best effort)
|
||||
* 1 = BK (background)
|
||||
* 2 = VI (video)
|
||||
* 3 = VO (voice)
|
||||
*/
|
||||
struct hostapd_wmm_ac_params wmm_ac_params[4];
|
||||
|
||||
int ht_op_mode_fixed;
|
||||
u16 ht_capab;
|
||||
int ieee80211n;
|
||||
int secondary_channel;
|
||||
int require_ht;
|
||||
};
|
||||
|
||||
|
||||
int hostapd_mac_comp(const void *a, const void *b);
|
||||
int hostapd_mac_comp_empty(const void *a);
|
||||
struct hostapd_config * hostapd_config_defaults(void);
|
||||
void hostapd_config_defaults_bss(struct hostapd_bss_config *bss);
|
||||
void hostapd_config_free(struct hostapd_config *conf);
|
||||
int hostapd_maclist_found(struct mac_acl_entry *list, int num_entries,
|
||||
const u8 *addr, int *vlan_id);
|
||||
int hostapd_rate_found(int *list, int rate);
|
||||
int hostapd_wep_key_cmp(struct hostapd_wep_keys *a,
|
||||
struct hostapd_wep_keys *b);
|
||||
const u8 * hostapd_get_psk(const struct hostapd_bss_config *conf,
|
||||
const u8 *addr, const u8 *prev_psk);
|
||||
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);
|
||||
|
||||
#endif /* HOSTAPD_CONFIG_H */
|
632
hostapd-0.8/src/ap/ap_drv_ops.c
Normal file
632
hostapd-0.8/src/ap/ap_drv_ops.c
Normal file
|
@ -0,0 +1,632 @@
|
|||
/*
|
||||
* 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.
|
||||
*/
|
||||
|
||||
#include "utils/includes.h"
|
||||
|
||||
#include "utils/common.h"
|
||||
#include "drivers/driver.h"
|
||||
#include "common/ieee802_11_defs.h"
|
||||
#include "wps/wps.h"
|
||||
#include "hostapd.h"
|
||||
#include "ieee802_11.h"
|
||||
#include "sta_info.h"
|
||||
#include "ap_config.h"
|
||||
#include "p2p_hostapd.h"
|
||||
#include "ap_drv_ops.h"
|
||||
|
||||
|
||||
u32 hostapd_sta_flags_to_drv(u32 flags)
|
||||
{
|
||||
int res = 0;
|
||||
if (flags & WLAN_STA_AUTHORIZED)
|
||||
res |= WPA_STA_AUTHORIZED;
|
||||
if (flags & WLAN_STA_WMM)
|
||||
res |= WPA_STA_WMM;
|
||||
if (flags & WLAN_STA_SHORT_PREAMBLE)
|
||||
res |= WPA_STA_SHORT_PREAMBLE;
|
||||
if (flags & WLAN_STA_MFP)
|
||||
res |= WPA_STA_MFP;
|
||||
return res;
|
||||
}
|
||||
|
||||
|
||||
int hostapd_set_ap_wps_ie(struct hostapd_data *hapd)
|
||||
{
|
||||
struct wpabuf *beacon, *proberesp, *assocresp = NULL;
|
||||
int ret;
|
||||
|
||||
if (hapd->driver == NULL || hapd->driver->set_ap_wps_ie == NULL)
|
||||
return 0;
|
||||
|
||||
beacon = hapd->wps_beacon_ie;
|
||||
proberesp = hapd->wps_probe_resp_ie;
|
||||
|
||||
#ifdef CONFIG_P2P
|
||||
if (hapd->wps_beacon_ie == NULL && hapd->p2p_beacon_ie == NULL)
|
||||
beacon = NULL;
|
||||
else {
|
||||
beacon = wpabuf_alloc((hapd->wps_beacon_ie ?
|
||||
wpabuf_len(hapd->wps_beacon_ie) : 0) +
|
||||
(hapd->p2p_beacon_ie ?
|
||||
wpabuf_len(hapd->p2p_beacon_ie) : 0));
|
||||
if (beacon == NULL)
|
||||
return -1;
|
||||
if (hapd->wps_beacon_ie)
|
||||
wpabuf_put_buf(beacon, hapd->wps_beacon_ie);
|
||||
if (hapd->p2p_beacon_ie)
|
||||
wpabuf_put_buf(beacon, hapd->p2p_beacon_ie);
|
||||
}
|
||||
|
||||
if (hapd->wps_probe_resp_ie == NULL && hapd->p2p_probe_resp_ie == NULL)
|
||||
proberesp = NULL;
|
||||
else {
|
||||
proberesp = wpabuf_alloc(
|
||||
(hapd->wps_probe_resp_ie ?
|
||||
wpabuf_len(hapd->wps_probe_resp_ie) : 0) +
|
||||
(hapd->p2p_probe_resp_ie ?
|
||||
wpabuf_len(hapd->p2p_probe_resp_ie) : 0));
|
||||
if (proberesp == NULL) {
|
||||
wpabuf_free(beacon);
|
||||
return -1;
|
||||
}
|
||||
if (hapd->wps_probe_resp_ie)
|
||||
wpabuf_put_buf(proberesp, hapd->wps_probe_resp_ie);
|
||||
if (hapd->p2p_probe_resp_ie)
|
||||
wpabuf_put_buf(proberesp, hapd->p2p_probe_resp_ie);
|
||||
}
|
||||
#endif /* CONFIG_P2P */
|
||||
|
||||
#ifdef CONFIG_P2P_MANAGER
|
||||
if (hapd->conf->p2p & P2P_MANAGE) {
|
||||
struct wpabuf *a;
|
||||
|
||||
a = wpabuf_alloc(100 + (beacon ? wpabuf_len(beacon) : 0));
|
||||
if (a) {
|
||||
u8 *start, *p;
|
||||
if (beacon)
|
||||
wpabuf_put_buf(a, beacon);
|
||||
if (beacon != hapd->wps_beacon_ie)
|
||||
wpabuf_free(beacon);
|
||||
start = wpabuf_put(a, 0);
|
||||
p = hostapd_eid_p2p_manage(hapd, start);
|
||||
wpabuf_put(a, p - start);
|
||||
beacon = a;
|
||||
}
|
||||
|
||||
a = wpabuf_alloc(100 + (proberesp ? wpabuf_len(proberesp) :
|
||||
0));
|
||||
if (a) {
|
||||
u8 *start, *p;
|
||||
if (proberesp)
|
||||
wpabuf_put_buf(a, proberesp);
|
||||
if (proberesp != hapd->wps_probe_resp_ie)
|
||||
wpabuf_free(proberesp);
|
||||
start = wpabuf_put(a, 0);
|
||||
p = hostapd_eid_p2p_manage(hapd, start);
|
||||
wpabuf_put(a, p - start);
|
||||
proberesp = a;
|
||||
}
|
||||
}
|
||||
#endif /* CONFIG_P2P_MANAGER */
|
||||
|
||||
#ifdef CONFIG_WPS2
|
||||
if (hapd->conf->wps_state)
|
||||
assocresp = wps_build_assoc_resp_ie();
|
||||
#endif /* CONFIG_WPS2 */
|
||||
|
||||
#ifdef CONFIG_P2P_MANAGER
|
||||
if (hapd->conf->p2p & P2P_MANAGE) {
|
||||
struct wpabuf *a;
|
||||
a = wpabuf_alloc(100 + (assocresp ? wpabuf_len(assocresp) :
|
||||
0));
|
||||
if (a) {
|
||||
u8 *start, *p;
|
||||
start = wpabuf_put(a, 0);
|
||||
p = hostapd_eid_p2p_manage(hapd, start);
|
||||
wpabuf_put(a, p - start);
|
||||
if (assocresp) {
|
||||
wpabuf_put_buf(a, assocresp);
|
||||
wpabuf_free(assocresp);
|
||||
}
|
||||
assocresp = a;
|
||||
}
|
||||
}
|
||||
#endif /* CONFIG_P2P_MANAGER */
|
||||
|
||||
ret = hapd->driver->set_ap_wps_ie(hapd->drv_priv, beacon, proberesp,
|
||||
assocresp);
|
||||
|
||||
if (beacon != hapd->wps_beacon_ie)
|
||||
wpabuf_free(beacon);
|
||||
if (proberesp != hapd->wps_probe_resp_ie)
|
||||
wpabuf_free(proberesp);
|
||||
wpabuf_free(assocresp);
|
||||
|
||||
return ret;
|
||||
}
|
||||
|
||||
|
||||
int hostapd_set_authorized(struct hostapd_data *hapd,
|
||||
struct sta_info *sta, int authorized)
|
||||
{
|
||||
if (authorized) {
|
||||
return hostapd_sta_set_flags(hapd, sta->addr,
|
||||
hostapd_sta_flags_to_drv(
|
||||
sta->flags),
|
||||
WPA_STA_AUTHORIZED, ~0);
|
||||
}
|
||||
|
||||
return hostapd_sta_set_flags(hapd, sta->addr,
|
||||
hostapd_sta_flags_to_drv(sta->flags),
|
||||
0, ~WPA_STA_AUTHORIZED);
|
||||
}
|
||||
|
||||
|
||||
int hostapd_set_sta_flags(struct hostapd_data *hapd, struct sta_info *sta)
|
||||
{
|
||||
int set_flags, total_flags, flags_and, flags_or;
|
||||
total_flags = hostapd_sta_flags_to_drv(sta->flags);
|
||||
set_flags = WPA_STA_SHORT_PREAMBLE | WPA_STA_WMM | WPA_STA_MFP;
|
||||
if (((!hapd->conf->ieee802_1x && !hapd->conf->wpa) ||
|
||||
sta->auth_alg == WLAN_AUTH_FT) &&
|
||||
sta->flags & WLAN_STA_AUTHORIZED)
|
||||
set_flags |= WPA_STA_AUTHORIZED;
|
||||
flags_or = total_flags & set_flags;
|
||||
flags_and = total_flags | ~set_flags;
|
||||
return hostapd_sta_set_flags(hapd, sta->addr, total_flags,
|
||||
flags_or, flags_and);
|
||||
}
|
||||
|
||||
|
||||
int hostapd_set_drv_ieee8021x(struct hostapd_data *hapd, const char *ifname,
|
||||
int enabled)
|
||||
{
|
||||
struct wpa_bss_params params;
|
||||
os_memset(¶ms, 0, sizeof(params));
|
||||
params.ifname = ifname;
|
||||
params.enabled = enabled;
|
||||
if (enabled) {
|
||||
params.wpa = hapd->conf->wpa;
|
||||
params.ieee802_1x = hapd->conf->ieee802_1x;
|
||||
params.wpa_group = hapd->conf->wpa_group;
|
||||
params.wpa_pairwise = hapd->conf->wpa_pairwise;
|
||||
params.wpa_key_mgmt = hapd->conf->wpa_key_mgmt;
|
||||
params.rsn_preauth = hapd->conf->rsn_preauth;
|
||||
#ifdef CONFIG_IEEE80211W
|
||||
params.ieee80211w = hapd->conf->ieee80211w;
|
||||
#endif /* CONFIG_IEEE80211W */
|
||||
}
|
||||
return hostapd_set_ieee8021x(hapd, ¶ms);
|
||||
}
|
||||
|
||||
|
||||
static int hostapd_set_ap_isolate(struct hostapd_data *hapd, int value)
|
||||
{
|
||||
if (hapd->driver == NULL || hapd->driver->set_intra_bss == NULL)
|
||||
return 0;
|
||||
return hapd->driver->set_intra_bss(hapd->drv_priv, !value);
|
||||
}
|
||||
|
||||
|
||||
int hostapd_set_bss_params(struct hostapd_data *hapd, int use_protection)
|
||||
{
|
||||
int ret = 0;
|
||||
int preamble;
|
||||
#ifdef CONFIG_IEEE80211N
|
||||
u8 buf[60], *ht_capab, *ht_oper, *pos;
|
||||
|
||||
pos = buf;
|
||||
ht_capab = pos;
|
||||
pos = hostapd_eid_ht_capabilities(hapd, pos);
|
||||
ht_oper = pos;
|
||||
pos = hostapd_eid_ht_operation(hapd, pos);
|
||||
if (pos > ht_oper && ht_oper > ht_capab &&
|
||||
hostapd_set_ht_params(hapd, ht_capab + 2, ht_capab[1],
|
||||
ht_oper + 2, ht_oper[1])) {
|
||||
wpa_printf(MSG_ERROR, "Could not set HT capabilities "
|
||||
"for kernel driver");
|
||||
ret = -1;
|
||||
}
|
||||
|
||||
#endif /* CONFIG_IEEE80211N */
|
||||
|
||||
if (hostapd_set_cts_protect(hapd, use_protection)) {
|
||||
wpa_printf(MSG_ERROR, "Failed to set CTS protect in kernel "
|
||||
"driver");
|
||||
ret = -1;
|
||||
}
|
||||
|
||||
if (hapd->iface->current_mode &&
|
||||
hapd->iface->current_mode->mode == HOSTAPD_MODE_IEEE80211G &&
|
||||
hostapd_set_short_slot_time(hapd,
|
||||
hapd->iface->num_sta_no_short_slot_time
|
||||
> 0 ? 0 : 1)) {
|
||||
wpa_printf(MSG_ERROR, "Failed to set Short Slot Time option "
|
||||
"in kernel driver");
|
||||
ret = -1;
|
||||
}
|
||||
|
||||
if (hapd->iface->num_sta_no_short_preamble == 0 &&
|
||||
hapd->iconf->preamble == SHORT_PREAMBLE)
|
||||
preamble = SHORT_PREAMBLE;
|
||||
else
|
||||
preamble = LONG_PREAMBLE;
|
||||
if (hostapd_set_preamble(hapd, preamble)) {
|
||||
wpa_printf(MSG_ERROR, "Could not set preamble for kernel "
|
||||
"driver");
|
||||
ret = -1;
|
||||
}
|
||||
|
||||
if (hostapd_set_ap_isolate(hapd, hapd->conf->isolate) &&
|
||||
hapd->conf->isolate) {
|
||||
wpa_printf(MSG_ERROR, "Could not enable AP isolation in "
|
||||
"kernel driver");
|
||||
ret = -1;
|
||||
}
|
||||
|
||||
return ret;
|
||||
}
|
||||
|
||||
|
||||
int hostapd_vlan_if_add(struct hostapd_data *hapd, const char *ifname)
|
||||
{
|
||||
char force_ifname[IFNAMSIZ];
|
||||
u8 if_addr[ETH_ALEN];
|
||||
return hostapd_if_add(hapd, WPA_IF_AP_VLAN, ifname, hapd->own_addr,
|
||||
NULL, NULL, force_ifname, if_addr, NULL);
|
||||
}
|
||||
|
||||
|
||||
int hostapd_vlan_if_remove(struct hostapd_data *hapd, const char *ifname)
|
||||
{
|
||||
return hostapd_if_remove(hapd, WPA_IF_AP_VLAN, ifname);
|
||||
}
|
||||
|
||||
|
||||
int hostapd_set_wds_sta(struct hostapd_data *hapd, const u8 *addr, int aid,
|
||||
int val)
|
||||
{
|
||||
const char *bridge = NULL;
|
||||
|
||||
if (hapd->driver == NULL || hapd->driver->set_wds_sta == NULL)
|
||||
return 0;
|
||||
if (hapd->conf->wds_bridge[0])
|
||||
bridge = hapd->conf->wds_bridge;
|
||||
else if (hapd->conf->bridge[0])
|
||||
bridge = hapd->conf->bridge;
|
||||
return hapd->driver->set_wds_sta(hapd->drv_priv, addr, aid, val,
|
||||
bridge);
|
||||
}
|
||||
|
||||
|
||||
int hostapd_sta_add(struct hostapd_data *hapd,
|
||||
const u8 *addr, u16 aid, u16 capability,
|
||||
const u8 *supp_rates, size_t supp_rates_len,
|
||||
u16 listen_interval,
|
||||
const struct ieee80211_ht_capabilities *ht_capab)
|
||||
{
|
||||
struct hostapd_sta_add_params params;
|
||||
|
||||
if (hapd->driver == NULL)
|
||||
return 0;
|
||||
if (hapd->driver->sta_add == NULL)
|
||||
return 0;
|
||||
|
||||
os_memset(¶ms, 0, sizeof(params));
|
||||
params.addr = addr;
|
||||
params.aid = aid;
|
||||
params.capability = capability;
|
||||
params.supp_rates = supp_rates;
|
||||
params.supp_rates_len = supp_rates_len;
|
||||
params.listen_interval = listen_interval;
|
||||
params.ht_capabilities = ht_capab;
|
||||
return hapd->driver->sta_add(hapd->drv_priv, ¶ms);
|
||||
}
|
||||
|
||||
|
||||
int hostapd_set_privacy(struct hostapd_data *hapd, int enabled)
|
||||
{
|
||||
if (hapd->driver == NULL || hapd->driver->set_privacy == NULL)
|
||||
return 0;
|
||||
return hapd->driver->set_privacy(hapd->drv_priv, enabled);
|
||||
}
|
||||
|
||||
|
||||
int hostapd_set_generic_elem(struct hostapd_data *hapd, const u8 *elem,
|
||||
size_t elem_len)
|
||||
{
|
||||
if (hapd->driver == NULL || hapd->driver->set_generic_elem == NULL)
|
||||
return 0;
|
||||
return hapd->driver->set_generic_elem(hapd->drv_priv, elem, elem_len);
|
||||
}
|
||||
|
||||
|
||||
int hostapd_get_ssid(struct hostapd_data *hapd, u8 *buf, size_t len)
|
||||
{
|
||||
if (hapd->driver == NULL || hapd->driver->hapd_get_ssid == NULL)
|
||||
return 0;
|
||||
return hapd->driver->hapd_get_ssid(hapd->drv_priv, buf, len);
|
||||
}
|
||||
|
||||
|
||||
int hostapd_set_ssid(struct hostapd_data *hapd, const u8 *buf, size_t len)
|
||||
{
|
||||
if (hapd->driver == NULL || hapd->driver->hapd_set_ssid == NULL)
|
||||
return 0;
|
||||
return hapd->driver->hapd_set_ssid(hapd->drv_priv, buf, len);
|
||||
}
|
||||
|
||||
|
||||
int hostapd_if_add(struct hostapd_data *hapd, enum wpa_driver_if_type type,
|
||||
const char *ifname, const u8 *addr, void *bss_ctx,
|
||||
void **drv_priv, char *force_ifname, u8 *if_addr,
|
||||
const char *bridge)
|
||||
{
|
||||
if (hapd->driver == NULL || hapd->driver->if_add == NULL)
|
||||
return -1;
|
||||
return hapd->driver->if_add(hapd->drv_priv, type, ifname, addr,
|
||||
bss_ctx, drv_priv, force_ifname, if_addr,
|
||||
bridge);
|
||||
}
|
||||
|
||||
|
||||
int hostapd_if_remove(struct hostapd_data *hapd, enum wpa_driver_if_type type,
|
||||
const char *ifname)
|
||||
{
|
||||
if (hapd->driver == NULL || hapd->driver->if_remove == NULL)
|
||||
return -1;
|
||||
return hapd->driver->if_remove(hapd->drv_priv, type, ifname);
|
||||
}
|
||||
|
||||
|
||||
int hostapd_set_ieee8021x(struct hostapd_data *hapd,
|
||||
struct wpa_bss_params *params)
|
||||
{
|
||||
if (hapd->driver == NULL || hapd->driver->set_ieee8021x == NULL)
|
||||
return 0;
|
||||
return hapd->driver->set_ieee8021x(hapd->drv_priv, params);
|
||||
}
|
||||
|
||||
|
||||
int hostapd_get_seqnum(const char *ifname, struct hostapd_data *hapd,
|
||||
const u8 *addr, int idx, u8 *seq)
|
||||
{
|
||||
if (hapd->driver == NULL || hapd->driver->get_seqnum == NULL)
|
||||
return 0;
|
||||
return hapd->driver->get_seqnum(ifname, hapd->drv_priv, addr, idx,
|
||||
seq);
|
||||
}
|
||||
|
||||
|
||||
int hostapd_flush(struct hostapd_data *hapd)
|
||||
{
|
||||
if (hapd->driver == NULL || hapd->driver->flush == NULL)
|
||||
return 0;
|
||||
return hapd->driver->flush(hapd->drv_priv);
|
||||
}
|
||||
|
||||
|
||||
int hostapd_set_freq(struct hostapd_data *hapd, int mode, int freq,
|
||||
int channel, int ht_enabled, int sec_channel_offset)
|
||||
{
|
||||
struct hostapd_freq_params data;
|
||||
if (hapd->driver == NULL)
|
||||
return 0;
|
||||
if (hapd->driver->set_freq == NULL)
|
||||
return 0;
|
||||
os_memset(&data, 0, sizeof(data));
|
||||
data.mode = mode;
|
||||
data.freq = freq;
|
||||
data.channel = channel;
|
||||
data.ht_enabled = ht_enabled;
|
||||
data.sec_channel_offset = sec_channel_offset;
|
||||
return hapd->driver->set_freq(hapd->drv_priv, &data);
|
||||
}
|
||||
|
||||
int hostapd_set_rts(struct hostapd_data *hapd, int rts)
|
||||
{
|
||||
if (hapd->driver == NULL || hapd->driver->set_rts == NULL)
|
||||
return 0;
|
||||
return hapd->driver->set_rts(hapd->drv_priv, rts);
|
||||
}
|
||||
|
||||
|
||||
int hostapd_set_frag(struct hostapd_data *hapd, int frag)
|
||||
{
|
||||
if (hapd->driver == NULL || hapd->driver->set_frag == NULL)
|
||||
return 0;
|
||||
return hapd->driver->set_frag(hapd->drv_priv, frag);
|
||||
}
|
||||
|
||||
|
||||
int hostapd_sta_set_flags(struct hostapd_data *hapd, u8 *addr,
|
||||
int total_flags, int flags_or, int flags_and)
|
||||
{
|
||||
if (hapd->driver == NULL || hapd->driver->sta_set_flags == NULL)
|
||||
return 0;
|
||||
return hapd->driver->sta_set_flags(hapd->drv_priv, addr, total_flags,
|
||||
flags_or, flags_and);
|
||||
}
|
||||
|
||||
|
||||
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 ||
|
||||
hapd->driver->set_country == NULL)
|
||||
return 0;
|
||||
return hapd->driver->set_country(hapd->drv_priv, country);
|
||||
}
|
||||
|
||||
|
||||
int hostapd_set_cts_protect(struct hostapd_data *hapd, int value)
|
||||
{
|
||||
if (hapd->driver == NULL || hapd->driver->set_cts_protect == NULL)
|
||||
return 0;
|
||||
return hapd->driver->set_cts_protect(hapd->drv_priv, value);
|
||||
}
|
||||
|
||||
|
||||
int hostapd_set_preamble(struct hostapd_data *hapd, int value)
|
||||
{
|
||||
if (hapd->driver == NULL || hapd->driver->set_preamble == NULL)
|
||||
return 0;
|
||||
return hapd->driver->set_preamble(hapd->drv_priv, value);
|
||||
}
|
||||
|
||||
|
||||
int hostapd_set_short_slot_time(struct hostapd_data *hapd, int value)
|
||||
{
|
||||
if (hapd->driver == NULL || hapd->driver->set_short_slot_time == NULL)
|
||||
return 0;
|
||||
return hapd->driver->set_short_slot_time(hapd->drv_priv, value);
|
||||
}
|
||||
|
||||
|
||||
int hostapd_set_tx_queue_params(struct hostapd_data *hapd, int queue, int aifs,
|
||||
int cw_min, int cw_max, int burst_time)
|
||||
{
|
||||
if (hapd->driver == NULL || hapd->driver->set_tx_queue_params == NULL)
|
||||
return 0;
|
||||
return hapd->driver->set_tx_queue_params(hapd->drv_priv, queue, aifs,
|
||||
cw_min, cw_max, burst_time);
|
||||
}
|
||||
|
||||
|
||||
int hostapd_valid_bss_mask(struct hostapd_data *hapd, const u8 *addr,
|
||||
const u8 *mask)
|
||||
{
|
||||
if (hapd->driver == NULL || hapd->driver->valid_bss_mask == NULL)
|
||||
return 1;
|
||||
return hapd->driver->valid_bss_mask(hapd->drv_priv, addr, mask);
|
||||
}
|
||||
|
||||
|
||||
struct hostapd_hw_modes *
|
||||
hostapd_get_hw_feature_data(struct hostapd_data *hapd, u16 *num_modes,
|
||||
u16 *flags)
|
||||
{
|
||||
if (hapd->driver == NULL ||
|
||||
hapd->driver->get_hw_feature_data == NULL)
|
||||
return NULL;
|
||||
return hapd->driver->get_hw_feature_data(hapd->drv_priv, num_modes,
|
||||
flags);
|
||||
}
|
||||
|
||||
|
||||
int hostapd_driver_commit(struct hostapd_data *hapd)
|
||||
{
|
||||
if (hapd->driver == NULL || hapd->driver->commit == NULL)
|
||||
return 0;
|
||||
return hapd->driver->commit(hapd->drv_priv);
|
||||
}
|
||||
|
||||
|
||||
int hostapd_set_ht_params(struct hostapd_data *hapd,
|
||||
const u8 *ht_capab, size_t ht_capab_len,
|
||||
const u8 *ht_oper, size_t ht_oper_len)
|
||||
{
|
||||
if (hapd->driver == NULL || hapd->driver->set_ht_params == NULL ||
|
||||
ht_capab == NULL || ht_oper == NULL)
|
||||
return 0;
|
||||
return hapd->driver->set_ht_params(hapd->drv_priv,
|
||||
ht_capab, ht_capab_len,
|
||||
ht_oper, ht_oper_len);
|
||||
}
|
||||
|
||||
|
||||
int hostapd_drv_none(struct hostapd_data *hapd)
|
||||
{
|
||||
return hapd->driver && os_strcmp(hapd->driver->name, "none") == 0;
|
||||
}
|
||||
|
||||
|
||||
int hostapd_driver_scan(struct hostapd_data *hapd,
|
||||
struct wpa_driver_scan_params *params)
|
||||
{
|
||||
if (hapd->driver && hapd->driver->scan2)
|
||||
return hapd->driver->scan2(hapd->drv_priv, params);
|
||||
return -1;
|
||||
}
|
||||
|
||||
|
||||
struct wpa_scan_results * hostapd_driver_get_scan_results(
|
||||
struct hostapd_data *hapd)
|
||||
{
|
||||
if (hapd->driver && hapd->driver->get_scan_results2)
|
||||
return hapd->driver->get_scan_results2(hapd->drv_priv);
|
||||
return NULL;
|
||||
}
|
||||
|
||||
|
||||
int hostapd_driver_set_noa(struct hostapd_data *hapd, u8 count, int start,
|
||||
int duration)
|
||||
{
|
||||
if (hapd->driver && hapd->driver->set_noa)
|
||||
return hapd->driver->set_noa(hapd->drv_priv, count, start,
|
||||
duration);
|
||||
return -1;
|
||||
}
|
||||
|
||||
|
||||
int hostapd_drv_set_key(const char *ifname, struct hostapd_data *hapd,
|
||||
enum wpa_alg alg, const u8 *addr,
|
||||
int key_idx, int set_tx,
|
||||
const u8 *seq, size_t seq_len,
|
||||
const u8 *key, size_t key_len)
|
||||
{
|
||||
if (hapd->driver == NULL || hapd->driver->set_key == NULL)
|
||||
return 0;
|
||||
return hapd->driver->set_key(ifname, hapd->drv_priv, alg, addr,
|
||||
key_idx, set_tx, seq, seq_len, key,
|
||||
key_len);
|
||||
}
|
||||
|
||||
|
||||
int hostapd_drv_send_mlme(struct hostapd_data *hapd,
|
||||
const void *msg, size_t len)
|
||||
{
|
||||
if (hapd->driver == NULL || hapd->driver->send_mlme == NULL)
|
||||
return 0;
|
||||
return hapd->driver->send_mlme(hapd->drv_priv, msg, len);
|
||||
}
|
||||
|
||||
|
||||
int hostapd_drv_sta_deauth(struct hostapd_data *hapd,
|
||||
const u8 *addr, int reason)
|
||||
{
|
||||
if (hapd->driver == NULL || hapd->driver->sta_deauth == NULL)
|
||||
return 0;
|
||||
return hapd->driver->sta_deauth(hapd->drv_priv, hapd->own_addr, addr,
|
||||
reason);
|
||||
}
|
||||
|
||||
|
||||
int hostapd_drv_sta_disassoc(struct hostapd_data *hapd,
|
||||
const u8 *addr, int reason)
|
||||
{
|
||||
if (hapd->driver == NULL || hapd->driver->sta_disassoc == NULL)
|
||||
return 0;
|
||||
return hapd->driver->sta_disassoc(hapd->drv_priv, hapd->own_addr, addr,
|
||||
reason);
|
||||
}
|
197
hostapd-0.8/src/ap/ap_drv_ops.h
Normal file
197
hostapd-0.8/src/ap/ap_drv_ops.h
Normal file
|
@ -0,0 +1,197 @@
|
|||
/*
|
||||
* 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.
|
||||
*/
|
||||
|
||||
#ifndef AP_DRV_OPS
|
||||
#define AP_DRV_OPS
|
||||
|
||||
enum wpa_driver_if_type;
|
||||
struct wpa_bss_params;
|
||||
struct wpa_driver_scan_params;
|
||||
struct ieee80211_ht_capabilities;
|
||||
|
||||
u32 hostapd_sta_flags_to_drv(u32 flags);
|
||||
int hostapd_set_ap_wps_ie(struct hostapd_data *hapd);
|
||||
int hostapd_set_authorized(struct hostapd_data *hapd,
|
||||
struct sta_info *sta, int authorized);
|
||||
int hostapd_set_sta_flags(struct hostapd_data *hapd, struct sta_info *sta);
|
||||
int hostapd_set_drv_ieee8021x(struct hostapd_data *hapd, const char *ifname,
|
||||
int enabled);
|
||||
int hostapd_set_bss_params(struct hostapd_data *hapd, int use_protection);
|
||||
int hostapd_vlan_if_add(struct hostapd_data *hapd, const char *ifname);
|
||||
int hostapd_vlan_if_remove(struct hostapd_data *hapd, const char *ifname);
|
||||
int hostapd_set_wds_sta(struct hostapd_data *hapd, const u8 *addr, int aid,
|
||||
int val);
|
||||
int hostapd_sta_add(struct hostapd_data *hapd,
|
||||
const u8 *addr, u16 aid, u16 capability,
|
||||
const u8 *supp_rates, size_t supp_rates_len,
|
||||
u16 listen_interval,
|
||||
const struct ieee80211_ht_capabilities *ht_capab);
|
||||
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);
|
||||
int hostapd_get_ssid(struct hostapd_data *hapd, u8 *buf, size_t len);
|
||||
int hostapd_set_ssid(struct hostapd_data *hapd, const u8 *buf, size_t len);
|
||||
int hostapd_if_add(struct hostapd_data *hapd, enum wpa_driver_if_type type,
|
||||
const char *ifname, const u8 *addr, void *bss_ctx,
|
||||
void **drv_priv, char *force_ifname, u8 *if_addr,
|
||||
const char *bridge);
|
||||
int hostapd_if_remove(struct hostapd_data *hapd, enum wpa_driver_if_type type,
|
||||
const char *ifname);
|
||||
int hostapd_set_ieee8021x(struct hostapd_data *hapd,
|
||||
struct wpa_bss_params *params);
|
||||
int hostapd_get_seqnum(const char *ifname, struct hostapd_data *hapd,
|
||||
const u8 *addr, int idx, u8 *seq);
|
||||
int hostapd_flush(struct hostapd_data *hapd);
|
||||
int hostapd_set_freq(struct hostapd_data *hapd, int mode, int freq,
|
||||
int channel, int ht_enabled, int sec_channel_offset);
|
||||
int hostapd_set_rts(struct hostapd_data *hapd, int rts);
|
||||
int hostapd_set_frag(struct hostapd_data *hapd, int frag);
|
||||
int hostapd_sta_set_flags(struct hostapd_data *hapd, u8 *addr,
|
||||
int total_flags, int flags_or, int flags_and);
|
||||
int hostapd_set_rate_sets(struct hostapd_data *hapd, int *supp_rates,
|
||||
int *basic_rates, int mode);
|
||||
int hostapd_set_country(struct hostapd_data *hapd, const char *country);
|
||||
int hostapd_set_cts_protect(struct hostapd_data *hapd, int value);
|
||||
int hostapd_set_preamble(struct hostapd_data *hapd, int value);
|
||||
int hostapd_set_short_slot_time(struct hostapd_data *hapd, int value);
|
||||
int hostapd_set_tx_queue_params(struct hostapd_data *hapd, int queue, int aifs,
|
||||
int cw_min, int cw_max, int burst_time);
|
||||
int hostapd_valid_bss_mask(struct hostapd_data *hapd, const u8 *addr,
|
||||
const u8 *mask);
|
||||
struct hostapd_hw_modes *
|
||||
hostapd_get_hw_feature_data(struct hostapd_data *hapd, u16 *num_modes,
|
||||
u16 *flags);
|
||||
int hostapd_driver_commit(struct hostapd_data *hapd);
|
||||
int hostapd_set_ht_params(struct hostapd_data *hapd,
|
||||
const u8 *ht_capab, size_t ht_capab_len,
|
||||
const u8 *ht_oper, size_t ht_oper_len);
|
||||
int hostapd_drv_none(struct hostapd_data *hapd);
|
||||
int hostapd_driver_scan(struct hostapd_data *hapd,
|
||||
struct wpa_driver_scan_params *params);
|
||||
struct wpa_scan_results * hostapd_driver_get_scan_results(
|
||||
struct hostapd_data *hapd);
|
||||
int hostapd_driver_set_noa(struct hostapd_data *hapd, u8 count, int start,
|
||||
int duration);
|
||||
int hostapd_drv_set_key(const char *ifname,
|
||||
struct hostapd_data *hapd,
|
||||
enum wpa_alg alg, const u8 *addr,
|
||||
int key_idx, int set_tx,
|
||||
const u8 *seq, size_t seq_len,
|
||||
const u8 *key, size_t key_len);
|
||||
int hostapd_drv_send_mlme(struct hostapd_data *hapd,
|
||||
const void *msg, size_t len);
|
||||
int 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);
|
||||
|
||||
|
||||
#include "drivers/driver.h"
|
||||
|
||||
static inline int hostapd_drv_set_countermeasures(struct hostapd_data *hapd,
|
||||
int enabled)
|
||||
{
|
||||
if (hapd->driver == NULL ||
|
||||
hapd->driver->hapd_set_countermeasures == NULL)
|
||||
return 0;
|
||||
return hapd->driver->hapd_set_countermeasures(hapd->drv_priv, enabled);
|
||||
}
|
||||
|
||||
static inline int hostapd_drv_set_sta_vlan(const char *ifname,
|
||||
struct hostapd_data *hapd,
|
||||
const u8 *addr, int vlan_id)
|
||||
{
|
||||
if (hapd->driver == NULL || hapd->driver->set_sta_vlan == NULL)
|
||||
return 0;
|
||||
return hapd->driver->set_sta_vlan(hapd->drv_priv, addr, ifname,
|
||||
vlan_id);
|
||||
}
|
||||
|
||||
static inline int hostapd_drv_get_inact_sec(struct hostapd_data *hapd,
|
||||
const u8 *addr)
|
||||
{
|
||||
if (hapd->driver == NULL || hapd->driver->get_inact_sec == NULL)
|
||||
return 0;
|
||||
return hapd->driver->get_inact_sec(hapd->drv_priv, addr);
|
||||
}
|
||||
|
||||
static inline int hostapd_drv_sta_remove(struct hostapd_data *hapd,
|
||||
const u8 *addr)
|
||||
{
|
||||
if (hapd->driver == NULL || hapd->driver->sta_remove == NULL)
|
||||
return 0;
|
||||
return hapd->driver->sta_remove(hapd->drv_priv, addr);
|
||||
}
|
||||
|
||||
static inline int hostapd_drv_hapd_send_eapol(struct hostapd_data *hapd,
|
||||
const u8 *addr, const u8 *data,
|
||||
size_t data_len, int encrypt,
|
||||
u32 flags)
|
||||
{
|
||||
if (hapd->driver == NULL || hapd->driver->hapd_send_eapol == NULL)
|
||||
return 0;
|
||||
return hapd->driver->hapd_send_eapol(hapd->drv_priv, addr, data,
|
||||
data_len, encrypt,
|
||||
hapd->own_addr, flags);
|
||||
}
|
||||
|
||||
static inline int hostapd_drv_read_sta_data(
|
||||
struct hostapd_data *hapd, struct hostap_sta_driver_data *data,
|
||||
const u8 *addr)
|
||||
{
|
||||
if (hapd->driver == NULL || hapd->driver->read_sta_data == NULL)
|
||||
return -1;
|
||||
return hapd->driver->read_sta_data(hapd->drv_priv, data, addr);
|
||||
}
|
||||
|
||||
static inline int hostapd_drv_sta_clear_stats(struct hostapd_data *hapd,
|
||||
const u8 *addr)
|
||||
{
|
||||
if (hapd->driver == NULL || hapd->driver->sta_clear_stats == NULL)
|
||||
return 0;
|
||||
return hapd->driver->sta_clear_stats(hapd->drv_priv, addr);
|
||||
}
|
||||
|
||||
static inline int hostapd_drv_set_beacon(struct hostapd_data *hapd,
|
||||
const u8 *head, size_t head_len,
|
||||
const u8 *tail, size_t tail_len,
|
||||
int dtim_period, int beacon_int)
|
||||
{
|
||||
if (hapd->driver == NULL || hapd->driver->set_beacon == NULL)
|
||||
return 0;
|
||||
return hapd->driver->set_beacon(hapd->drv_priv,
|
||||
head, head_len, tail, tail_len,
|
||||
dtim_period, beacon_int);
|
||||
}
|
||||
|
||||
static inline int hostapd_drv_set_radius_acl_auth(struct hostapd_data *hapd,
|
||||
const u8 *mac, int accepted,
|
||||
u32 session_timeout)
|
||||
{
|
||||
if (hapd->driver == NULL || hapd->driver->set_radius_acl_auth == NULL)
|
||||
return 0;
|
||||
return hapd->driver->set_radius_acl_auth(hapd->drv_priv, mac, accepted,
|
||||
session_timeout);
|
||||
}
|
||||
|
||||
static inline int hostapd_drv_set_radius_acl_expire(struct hostapd_data *hapd,
|
||||
const u8 *mac)
|
||||
{
|
||||
if (hapd->driver == NULL ||
|
||||
hapd->driver->set_radius_acl_expire == NULL)
|
||||
return 0;
|
||||
return hapd->driver->set_radius_acl_expire(hapd->drv_priv, mac);
|
||||
}
|
||||
|
||||
#endif /* AP_DRV_OPS */
|
399
hostapd-0.8/src/ap/ap_list.c
Normal file
399
hostapd-0.8/src/ap/ap_list.c
Normal file
|
@ -0,0 +1,399 @@
|
|||
/*
|
||||
* hostapd / AP table
|
||||
* Copyright (c) 2002-2009, Jouni Malinen <j@w1.fi>
|
||||
* 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.
|
||||
*/
|
||||
|
||||
#include "utils/includes.h"
|
||||
|
||||
#include "utils/common.h"
|
||||
#include "utils/eloop.h"
|
||||
#include "common/ieee802_11_defs.h"
|
||||
#include "common/ieee802_11_common.h"
|
||||
#include "drivers/driver.h"
|
||||
#include "hostapd.h"
|
||||
#include "ap_config.h"
|
||||
#include "ieee802_11.h"
|
||||
#include "sta_info.h"
|
||||
#include "beacon.h"
|
||||
#include "ap_list.h"
|
||||
|
||||
|
||||
/* AP list is a double linked list with head->prev pointing to the end of the
|
||||
* list and tail->next = NULL. Entries are moved to the head of the list
|
||||
* whenever a beacon has been received from the AP in question. The tail entry
|
||||
* in this link will thus be the least recently used entry. */
|
||||
|
||||
|
||||
static int ap_list_beacon_olbc(struct hostapd_iface *iface, struct ap_info *ap)
|
||||
{
|
||||
int i;
|
||||
|
||||
if (iface->current_mode->mode != HOSTAPD_MODE_IEEE80211G ||
|
||||
iface->conf->channel != ap->channel)
|
||||
return 0;
|
||||
|
||||
if (ap->erp != -1 && (ap->erp & ERP_INFO_NON_ERP_PRESENT))
|
||||
return 1;
|
||||
|
||||
for (i = 0; i < WLAN_SUPP_RATES_MAX; i++) {
|
||||
int rate = (ap->supported_rates[i] & 0x7f) * 5;
|
||||
if (rate == 60 || rate == 90 || rate > 110)
|
||||
return 0;
|
||||
}
|
||||
|
||||
return 1;
|
||||
}
|
||||
|
||||
|
||||
struct ap_info * ap_get_ap(struct hostapd_iface *iface, const u8 *ap)
|
||||
{
|
||||
struct ap_info *s;
|
||||
|
||||
s = iface->ap_hash[STA_HASH(ap)];
|
||||
while (s != NULL && os_memcmp(s->addr, ap, ETH_ALEN) != 0)
|
||||
s = s->hnext;
|
||||
return s;
|
||||
}
|
||||
|
||||
|
||||
static void ap_ap_list_add(struct hostapd_iface *iface, struct ap_info *ap)
|
||||
{
|
||||
if (iface->ap_list) {
|
||||
ap->prev = iface->ap_list->prev;
|
||||
iface->ap_list->prev = ap;
|
||||
} else
|
||||
ap->prev = ap;
|
||||
ap->next = iface->ap_list;
|
||||
iface->ap_list = ap;
|
||||
}
|
||||
|
||||
|
||||
static void ap_ap_list_del(struct hostapd_iface *iface, struct ap_info *ap)
|
||||
{
|
||||
if (iface->ap_list == ap)
|
||||
iface->ap_list = ap->next;
|
||||
else
|
||||
ap->prev->next = ap->next;
|
||||
|
||||
if (ap->next)
|
||||
ap->next->prev = ap->prev;
|
||||
else if (iface->ap_list)
|
||||
iface->ap_list->prev = ap->prev;
|
||||
}
|
||||
|
||||
|
||||
static void ap_ap_iter_list_add(struct hostapd_iface *iface,
|
||||
struct ap_info *ap)
|
||||
{
|
||||
if (iface->ap_iter_list) {
|
||||
ap->iter_prev = iface->ap_iter_list->iter_prev;
|
||||
iface->ap_iter_list->iter_prev = ap;
|
||||
} else
|
||||
ap->iter_prev = ap;
|
||||
ap->iter_next = iface->ap_iter_list;
|
||||
iface->ap_iter_list = ap;
|
||||
}
|
||||
|
||||
|
||||
static void ap_ap_iter_list_del(struct hostapd_iface *iface,
|
||||
struct ap_info *ap)
|
||||
{
|
||||
if (iface->ap_iter_list == ap)
|
||||
iface->ap_iter_list = ap->iter_next;
|
||||
else
|
||||
ap->iter_prev->iter_next = ap->iter_next;
|
||||
|
||||
if (ap->iter_next)
|
||||
ap->iter_next->iter_prev = ap->iter_prev;
|
||||
else if (iface->ap_iter_list)
|
||||
iface->ap_iter_list->iter_prev = ap->iter_prev;
|
||||
}
|
||||
|
||||
|
||||
static void ap_ap_hash_add(struct hostapd_iface *iface, struct ap_info *ap)
|
||||
{
|
||||
ap->hnext = iface->ap_hash[STA_HASH(ap->addr)];
|
||||
iface->ap_hash[STA_HASH(ap->addr)] = ap;
|
||||
}
|
||||
|
||||
|
||||
static void ap_ap_hash_del(struct hostapd_iface *iface, struct ap_info *ap)
|
||||
{
|
||||
struct ap_info *s;
|
||||
|
||||
s = iface->ap_hash[STA_HASH(ap->addr)];
|
||||
if (s == NULL) return;
|
||||
if (os_memcmp(s->addr, ap->addr, ETH_ALEN) == 0) {
|
||||
iface->ap_hash[STA_HASH(ap->addr)] = s->hnext;
|
||||
return;
|
||||
}
|
||||
|
||||
while (s->hnext != NULL &&
|
||||
os_memcmp(s->hnext->addr, ap->addr, ETH_ALEN) != 0)
|
||||
s = s->hnext;
|
||||
if (s->hnext != NULL)
|
||||
s->hnext = s->hnext->hnext;
|
||||
else
|
||||
printf("AP: could not remove AP " MACSTR " from hash table\n",
|
||||
MAC2STR(ap->addr));
|
||||
}
|
||||
|
||||
|
||||
static void ap_free_ap(struct hostapd_iface *iface, struct ap_info *ap)
|
||||
{
|
||||
ap_ap_hash_del(iface, ap);
|
||||
ap_ap_list_del(iface, ap);
|
||||
ap_ap_iter_list_del(iface, ap);
|
||||
|
||||
iface->num_ap--;
|
||||
os_free(ap);
|
||||
}
|
||||
|
||||
|
||||
static void hostapd_free_aps(struct hostapd_iface *iface)
|
||||
{
|
||||
struct ap_info *ap, *prev;
|
||||
|
||||
ap = iface->ap_list;
|
||||
|
||||
while (ap) {
|
||||
prev = ap;
|
||||
ap = ap->next;
|
||||
ap_free_ap(iface, prev);
|
||||
}
|
||||
|
||||
iface->ap_list = NULL;
|
||||
}
|
||||
|
||||
|
||||
int ap_ap_for_each(struct hostapd_iface *iface,
|
||||
int (*func)(struct ap_info *s, void *data), void *data)
|
||||
{
|
||||
struct ap_info *s;
|
||||
int ret = 0;
|
||||
|
||||
s = iface->ap_list;
|
||||
|
||||
while (s) {
|
||||
ret = func(s, data);
|
||||
if (ret)
|
||||
break;
|
||||
s = s->next;
|
||||
}
|
||||
|
||||
return ret;
|
||||
}
|
||||
|
||||
|
||||
static struct ap_info * ap_ap_add(struct hostapd_iface *iface, const u8 *addr)
|
||||
{
|
||||
struct ap_info *ap;
|
||||
|
||||
ap = os_zalloc(sizeof(struct ap_info));
|
||||
if (ap == NULL)
|
||||
return NULL;
|
||||
|
||||
/* initialize AP info data */
|
||||
os_memcpy(ap->addr, addr, ETH_ALEN);
|
||||
ap_ap_list_add(iface, ap);
|
||||
iface->num_ap++;
|
||||
ap_ap_hash_add(iface, ap);
|
||||
ap_ap_iter_list_add(iface, ap);
|
||||
|
||||
if (iface->num_ap > iface->conf->ap_table_max_size && ap != ap->prev) {
|
||||
wpa_printf(MSG_DEBUG, "Removing the least recently used AP "
|
||||
MACSTR " from AP table", MAC2STR(ap->prev->addr));
|
||||
ap_free_ap(iface, ap->prev);
|
||||
}
|
||||
|
||||
return ap;
|
||||
}
|
||||
|
||||
|
||||
void ap_list_process_beacon(struct hostapd_iface *iface,
|
||||
const struct ieee80211_mgmt *mgmt,
|
||||
struct ieee802_11_elems *elems,
|
||||
struct hostapd_frame_info *fi)
|
||||
{
|
||||
struct ap_info *ap;
|
||||
struct os_time now;
|
||||
int new_ap = 0;
|
||||
size_t len;
|
||||
int set_beacon = 0;
|
||||
|
||||
if (iface->conf->ap_table_max_size < 1)
|
||||
return;
|
||||
|
||||
ap = ap_get_ap(iface, mgmt->bssid);
|
||||
if (!ap) {
|
||||
ap = ap_ap_add(iface, mgmt->bssid);
|
||||
if (!ap) {
|
||||
printf("Failed to allocate AP information entry\n");
|
||||
return;
|
||||
}
|
||||
new_ap = 1;
|
||||
}
|
||||
|
||||
ap->beacon_int = le_to_host16(mgmt->u.beacon.beacon_int);
|
||||
ap->capability = le_to_host16(mgmt->u.beacon.capab_info);
|
||||
|
||||
if (elems->ssid) {
|
||||
len = elems->ssid_len;
|
||||
if (len >= sizeof(ap->ssid))
|
||||
len = sizeof(ap->ssid) - 1;
|
||||
os_memcpy(ap->ssid, elems->ssid, len);
|
||||
ap->ssid[len] = '\0';
|
||||
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);
|
||||
}
|
||||
|
||||
ap->wpa = elems->wpa_ie != NULL;
|
||||
|
||||
if (elems->erp_info && elems->erp_info_len == 1)
|
||||
ap->erp = elems->erp_info[0];
|
||||
else
|
||||
ap->erp = -1;
|
||||
|
||||
if (elems->ds_params && elems->ds_params_len == 1)
|
||||
ap->channel = elems->ds_params[0];
|
||||
else if (fi)
|
||||
ap->channel = fi->channel;
|
||||
|
||||
if (elems->ht_capabilities)
|
||||
ap->ht_support = 1;
|
||||
else
|
||||
ap->ht_support = 0;
|
||||
|
||||
ap->num_beacons++;
|
||||
os_get_time(&now);
|
||||
ap->last_beacon = now.sec;
|
||||
if (fi) {
|
||||
ap->ssi_signal = fi->ssi_signal;
|
||||
ap->datarate = fi->datarate;
|
||||
}
|
||||
|
||||
if (!new_ap && ap != iface->ap_list) {
|
||||
/* move AP entry into the beginning of the list so that the
|
||||
* oldest entry is always in the end of the list */
|
||||
ap_ap_list_del(iface, ap);
|
||||
ap_ap_list_add(iface, ap);
|
||||
}
|
||||
|
||||
if (!iface->olbc &&
|
||||
ap_list_beacon_olbc(iface, ap)) {
|
||||
iface->olbc = 1;
|
||||
wpa_printf(MSG_DEBUG, "OLBC AP detected: " MACSTR " - enable "
|
||||
"protection", MAC2STR(ap->addr));
|
||||
set_beacon++;
|
||||
}
|
||||
|
||||
#ifdef CONFIG_IEEE80211N
|
||||
if (!iface->olbc_ht && !ap->ht_support) {
|
||||
iface->olbc_ht = 1;
|
||||
hostapd_ht_operation_update(iface);
|
||||
wpa_printf(MSG_DEBUG, "OLBC HT AP detected: " MACSTR
|
||||
" - enable protection", MAC2STR(ap->addr));
|
||||
set_beacon++;
|
||||
}
|
||||
#endif /* CONFIG_IEEE80211N */
|
||||
|
||||
if (set_beacon)
|
||||
ieee802_11_set_beacons(iface);
|
||||
}
|
||||
|
||||
|
||||
static void ap_list_timer(void *eloop_ctx, void *timeout_ctx)
|
||||
{
|
||||
struct hostapd_iface *iface = eloop_ctx;
|
||||
struct os_time now;
|
||||
struct ap_info *ap;
|
||||
int set_beacon = 0;
|
||||
|
||||
eloop_register_timeout(10, 0, ap_list_timer, iface, NULL);
|
||||
|
||||
if (!iface->ap_list)
|
||||
return;
|
||||
|
||||
os_get_time(&now);
|
||||
|
||||
while (iface->ap_list) {
|
||||
ap = iface->ap_list->prev;
|
||||
if (ap->last_beacon + iface->conf->ap_table_expiration_time >=
|
||||
now.sec)
|
||||
break;
|
||||
|
||||
ap_free_ap(iface, ap);
|
||||
}
|
||||
|
||||
if (iface->olbc || iface->olbc_ht) {
|
||||
int olbc = 0;
|
||||
int olbc_ht = 0;
|
||||
|
||||
ap = iface->ap_list;
|
||||
while (ap && (olbc == 0 || olbc_ht == 0)) {
|
||||
if (ap_list_beacon_olbc(iface, ap))
|
||||
olbc = 1;
|
||||
if (!ap->ht_support)
|
||||
olbc_ht = 1;
|
||||
ap = ap->next;
|
||||
}
|
||||
if (!olbc && iface->olbc) {
|
||||
wpa_printf(MSG_DEBUG, "OLBC not detected anymore");
|
||||
iface->olbc = 0;
|
||||
set_beacon++;
|
||||
}
|
||||
#ifdef CONFIG_IEEE80211N
|
||||
if (!olbc_ht && iface->olbc_ht) {
|
||||
wpa_printf(MSG_DEBUG, "OLBC HT not detected anymore");
|
||||
iface->olbc_ht = 0;
|
||||
hostapd_ht_operation_update(iface);
|
||||
set_beacon++;
|
||||
}
|
||||
#endif /* CONFIG_IEEE80211N */
|
||||
}
|
||||
|
||||
if (set_beacon)
|
||||
ieee802_11_set_beacons(iface);
|
||||
}
|
||||
|
||||
|
||||
int ap_list_init(struct hostapd_iface *iface)
|
||||
{
|
||||
eloop_register_timeout(10, 0, ap_list_timer, iface, NULL);
|
||||
return 0;
|
||||
}
|
||||
|
||||
|
||||
void ap_list_deinit(struct hostapd_iface *iface)
|
||||
{
|
||||
eloop_cancel_timeout(ap_list_timer, iface, NULL);
|
||||
hostapd_free_aps(iface);
|
||||
}
|
78
hostapd-0.8/src/ap/ap_list.h
Normal file
78
hostapd-0.8/src/ap/ap_list.h
Normal file
|
@ -0,0 +1,78 @@
|
|||
/*
|
||||
* hostapd / AP table
|
||||
* Copyright (c) 2002-2003, Jouni Malinen <j@w1.fi>
|
||||
* 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.
|
||||
*/
|
||||
|
||||
#ifndef AP_LIST_H
|
||||
#define AP_LIST_H
|
||||
|
||||
struct ap_info {
|
||||
/* Note: next/prev pointers are updated whenever a new beacon is
|
||||
* received because these are used to find the least recently used
|
||||
* entries. iter_next/iter_prev are updated only when adding new BSSes
|
||||
* and when removing old ones. These should be used when iterating
|
||||
* through the table in a manner that allows beacons to be received
|
||||
* during the iteration. */
|
||||
struct ap_info *next; /* next entry in AP list */
|
||||
struct ap_info *prev; /* previous entry in AP list */
|
||||
struct ap_info *hnext; /* next entry in hash table list */
|
||||
struct ap_info *iter_next; /* next entry in AP iteration list */
|
||||
struct ap_info *iter_prev; /* previous entry in AP iteration list */
|
||||
u8 addr[6];
|
||||
u16 beacon_int;
|
||||
u16 capability;
|
||||
u8 supported_rates[WLAN_SUPP_RATES_MAX];
|
||||
u8 ssid[33];
|
||||
size_t ssid_len;
|
||||
int wpa;
|
||||
int erp; /* ERP Info or -1 if ERP info element not present */
|
||||
|
||||
int channel;
|
||||
int datarate; /* in 100 kbps */
|
||||
int ssi_signal;
|
||||
|
||||
int ht_support;
|
||||
|
||||
unsigned int num_beacons; /* number of beacon frames received */
|
||||
os_time_t last_beacon;
|
||||
|
||||
int already_seen; /* whether API call AP-NEW has already fetched
|
||||
* information about this AP */
|
||||
};
|
||||
|
||||
struct ieee802_11_elems;
|
||||
struct hostapd_frame_info;
|
||||
|
||||
struct ap_info * ap_get_ap(struct hostapd_iface *iface, const u8 *sta);
|
||||
int ap_ap_for_each(struct hostapd_iface *iface,
|
||||
int (*func)(struct ap_info *s, void *data), void *data);
|
||||
void ap_list_process_beacon(struct hostapd_iface *iface,
|
||||
const struct ieee80211_mgmt *mgmt,
|
||||
struct ieee802_11_elems *elems,
|
||||
struct hostapd_frame_info *fi);
|
||||
#ifdef NEED_AP_MLME
|
||||
int ap_list_init(struct hostapd_iface *iface);
|
||||
void ap_list_deinit(struct hostapd_iface *iface);
|
||||
#else /* NEED_AP_MLME */
|
||||
static inline int ap_list_init(struct hostapd_iface *iface)
|
||||
{
|
||||
return 0;
|
||||
}
|
||||
|
||||
static inline void ap_list_deinit(struct hostapd_iface *iface)
|
||||
{
|
||||
}
|
||||
#endif /* NEED_AP_MLME */
|
||||
|
||||
#endif /* AP_LIST_H */
|
184
hostapd-0.8/src/ap/ap_mlme.c
Normal file
184
hostapd-0.8/src/ap/ap_mlme.c
Normal file
|
@ -0,0 +1,184 @@
|
|||
/*
|
||||
* hostapd / IEEE 802.11 MLME
|
||||
* Copyright 2003-2006, Jouni Malinen <j@w1.fi>
|
||||
* 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.
|
||||
*/
|
||||
|
||||
#include "utils/includes.h"
|
||||
|
||||
#include "utils/common.h"
|
||||
#include "common/ieee802_11_defs.h"
|
||||
#include "ieee802_11.h"
|
||||
#include "wpa_auth.h"
|
||||
#include "sta_info.h"
|
||||
#include "ap_mlme.h"
|
||||
|
||||
|
||||
#ifndef CONFIG_NO_HOSTAPD_LOGGER
|
||||
static const char * mlme_auth_alg_str(int alg)
|
||||
{
|
||||
switch (alg) {
|
||||
case WLAN_AUTH_OPEN:
|
||||
return "OPEN_SYSTEM";
|
||||
case WLAN_AUTH_SHARED_KEY:
|
||||
return "SHARED_KEY";
|
||||
case WLAN_AUTH_FT:
|
||||
return "FT";
|
||||
}
|
||||
|
||||
return "unknown";
|
||||
}
|
||||
#endif /* CONFIG_NO_HOSTAPD_LOGGER */
|
||||
|
||||
|
||||
/**
|
||||
* mlme_authenticate_indication - Report the establishment of an authentication
|
||||
* relationship with a specific peer MAC entity
|
||||
* @hapd: BSS data
|
||||
* @sta: peer STA data
|
||||
*
|
||||
* MLME calls this function as a result of the establishment of an
|
||||
* authentication relationship with a specific peer MAC entity that
|
||||
* resulted from an authentication procedure that was initiated by
|
||||
* that specific peer MAC entity.
|
||||
*
|
||||
* PeerSTAAddress = sta->addr
|
||||
* AuthenticationType = sta->auth_alg (WLAN_AUTH_OPEN / WLAN_AUTH_SHARED_KEY)
|
||||
*/
|
||||
void mlme_authenticate_indication(struct hostapd_data *hapd,
|
||||
struct sta_info *sta)
|
||||
{
|
||||
hostapd_logger(hapd, sta->addr, HOSTAPD_MODULE_MLME,
|
||||
HOSTAPD_LEVEL_DEBUG,
|
||||
"MLME-AUTHENTICATE.indication(" MACSTR ", %s)",
|
||||
MAC2STR(sta->addr), mlme_auth_alg_str(sta->auth_alg));
|
||||
if (sta->auth_alg != WLAN_AUTH_FT && !(sta->flags & WLAN_STA_MFP))
|
||||
mlme_deletekeys_request(hapd, sta);
|
||||
}
|
||||
|
||||
|
||||
/**
|
||||
* mlme_deauthenticate_indication - Report the invalidation of an
|
||||
* authentication relationship with a specific peer MAC entity
|
||||
* @hapd: BSS data
|
||||
* @sta: Peer STA data
|
||||
* @reason_code: ReasonCode from Deauthentication frame
|
||||
*
|
||||
* MLME calls this function as a result of the invalidation of an
|
||||
* authentication relationship with a specific peer MAC entity.
|
||||
*
|
||||
* PeerSTAAddress = sta->addr
|
||||
*/
|
||||
void mlme_deauthenticate_indication(struct hostapd_data *hapd,
|
||||
struct sta_info *sta, u16 reason_code)
|
||||
{
|
||||
hostapd_logger(hapd, sta->addr, HOSTAPD_MODULE_MLME,
|
||||
HOSTAPD_LEVEL_DEBUG,
|
||||
"MLME-DEAUTHENTICATE.indication(" MACSTR ", %d)",
|
||||
MAC2STR(sta->addr), reason_code);
|
||||
mlme_deletekeys_request(hapd, sta);
|
||||
}
|
||||
|
||||
|
||||
/**
|
||||
* mlme_associate_indication - Report the establishment of an association with
|
||||
* a specific peer MAC entity
|
||||
* @hapd: BSS data
|
||||
* @sta: peer STA data
|
||||
*
|
||||
* MLME calls this function as a result of the establishment of an
|
||||
* association with a specific peer MAC entity that resulted from an
|
||||
* association procedure that was initiated by that specific peer MAC entity.
|
||||
*
|
||||
* PeerSTAAddress = sta->addr
|
||||
*/
|
||||
void mlme_associate_indication(struct hostapd_data *hapd, struct sta_info *sta)
|
||||
{
|
||||
hostapd_logger(hapd, sta->addr, HOSTAPD_MODULE_MLME,
|
||||
HOSTAPD_LEVEL_DEBUG,
|
||||
"MLME-ASSOCIATE.indication(" MACSTR ")",
|
||||
MAC2STR(sta->addr));
|
||||
if (sta->auth_alg != WLAN_AUTH_FT)
|
||||
mlme_deletekeys_request(hapd, sta);
|
||||
}
|
||||
|
||||
|
||||
/**
|
||||
* mlme_reassociate_indication - Report the establishment of an reassociation
|
||||
* with a specific peer MAC entity
|
||||
* @hapd: BSS data
|
||||
* @sta: peer STA data
|
||||
*
|
||||
* MLME calls this function as a result of the establishment of an
|
||||
* reassociation with a specific peer MAC entity that resulted from a
|
||||
* reassociation procedure that was initiated by that specific peer MAC entity.
|
||||
*
|
||||
* PeerSTAAddress = sta->addr
|
||||
*
|
||||
* sta->previous_ap contains the "Current AP" information from ReassocReq.
|
||||
*/
|
||||
void mlme_reassociate_indication(struct hostapd_data *hapd,
|
||||
struct sta_info *sta)
|
||||
{
|
||||
hostapd_logger(hapd, sta->addr, HOSTAPD_MODULE_MLME,
|
||||
HOSTAPD_LEVEL_DEBUG,
|
||||
"MLME-REASSOCIATE.indication(" MACSTR ")",
|
||||
MAC2STR(sta->addr));
|
||||
if (sta->auth_alg != WLAN_AUTH_FT)
|
||||
mlme_deletekeys_request(hapd, sta);
|
||||
}
|
||||
|
||||
|
||||
/**
|
||||
* mlme_disassociate_indication - Report disassociation with a specific peer
|
||||
* MAC entity
|
||||
* @hapd: BSS data
|
||||
* @sta: Peer STA data
|
||||
* @reason_code: ReasonCode from Disassociation frame
|
||||
*
|
||||
* MLME calls this function as a result of the invalidation of an association
|
||||
* relationship with a specific peer MAC entity.
|
||||
*
|
||||
* PeerSTAAddress = sta->addr
|
||||
*/
|
||||
void mlme_disassociate_indication(struct hostapd_data *hapd,
|
||||
struct sta_info *sta, u16 reason_code)
|
||||
{
|
||||
hostapd_logger(hapd, sta->addr, HOSTAPD_MODULE_MLME,
|
||||
HOSTAPD_LEVEL_DEBUG,
|
||||
"MLME-DISASSOCIATE.indication(" MACSTR ", %d)",
|
||||
MAC2STR(sta->addr), reason_code);
|
||||
mlme_deletekeys_request(hapd, sta);
|
||||
}
|
||||
|
||||
|
||||
void mlme_michaelmicfailure_indication(struct hostapd_data *hapd,
|
||||
const u8 *addr)
|
||||
{
|
||||
hostapd_logger(hapd, addr, HOSTAPD_MODULE_MLME,
|
||||
HOSTAPD_LEVEL_DEBUG,
|
||||
"MLME-MichaelMICFailure.indication(" MACSTR ")",
|
||||
MAC2STR(addr));
|
||||
}
|
||||
|
||||
|
||||
void mlme_deletekeys_request(struct hostapd_data *hapd, struct sta_info *sta)
|
||||
{
|
||||
hostapd_logger(hapd, sta->addr, HOSTAPD_MODULE_MLME,
|
||||
HOSTAPD_LEVEL_DEBUG,
|
||||
"MLME-DELETEKEYS.request(" MACSTR ")",
|
||||
MAC2STR(sta->addr));
|
||||
|
||||
if (sta->wpa_sm)
|
||||
wpa_remove_ptk(sta->wpa_sm);
|
||||
}
|
40
hostapd-0.8/src/ap/ap_mlme.h
Normal file
40
hostapd-0.8/src/ap/ap_mlme.h
Normal file
|
@ -0,0 +1,40 @@
|
|||
/*
|
||||
* hostapd / IEEE 802.11 MLME
|
||||
* Copyright 2003, Jouni Malinen <j@w1.fi>
|
||||
* 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.
|
||||
*/
|
||||
|
||||
#ifndef MLME_H
|
||||
#define MLME_H
|
||||
|
||||
void mlme_authenticate_indication(struct hostapd_data *hapd,
|
||||
struct sta_info *sta);
|
||||
|
||||
void mlme_deauthenticate_indication(struct hostapd_data *hapd,
|
||||
struct sta_info *sta, u16 reason_code);
|
||||
|
||||
void mlme_associate_indication(struct hostapd_data *hapd,
|
||||
struct sta_info *sta);
|
||||
|
||||
void mlme_reassociate_indication(struct hostapd_data *hapd,
|
||||
struct sta_info *sta);
|
||||
|
||||
void mlme_disassociate_indication(struct hostapd_data *hapd,
|
||||
struct sta_info *sta, u16 reason_code);
|
||||
|
||||
void mlme_michaelmicfailure_indication(struct hostapd_data *hapd,
|
||||
const u8 *addr);
|
||||
|
||||
void mlme_deletekeys_request(struct hostapd_data *hapd, struct sta_info *sta);
|
||||
|
||||
#endif /* MLME_H */
|
217
hostapd-0.8/src/ap/authsrv.c
Normal file
217
hostapd-0.8/src/ap/authsrv.c
Normal file
|
@ -0,0 +1,217 @@
|
|||
/*
|
||||
* 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.
|
||||
*/
|
||||
|
||||
#include "utils/includes.h"
|
||||
|
||||
#include "utils/common.h"
|
||||
#include "crypto/tls.h"
|
||||
#include "eap_server/eap.h"
|
||||
#include "eap_server/eap_sim_db.h"
|
||||
#include "eapol_auth/eapol_auth_sm.h"
|
||||
#include "radius/radius_server.h"
|
||||
#include "hostapd.h"
|
||||
#include "ap_config.h"
|
||||
#include "sta_info.h"
|
||||
#include "authsrv.h"
|
||||
|
||||
|
||||
#if defined(EAP_SERVER_SIM) || defined(EAP_SERVER_AKA)
|
||||
#define EAP_SIM_DB
|
||||
#endif /* EAP_SERVER_SIM || EAP_SERVER_AKA */
|
||||
|
||||
|
||||
#ifdef EAP_SIM_DB
|
||||
static int hostapd_sim_db_cb_sta(struct hostapd_data *hapd,
|
||||
struct sta_info *sta, void *ctx)
|
||||
{
|
||||
if (eapol_auth_eap_pending_cb(sta->eapol_sm, ctx) == 0)
|
||||
return 1;
|
||||
return 0;
|
||||
}
|
||||
|
||||
|
||||
static void hostapd_sim_db_cb(void *ctx, void *session_ctx)
|
||||
{
|
||||
struct hostapd_data *hapd = ctx;
|
||||
if (ap_for_each_sta(hapd, hostapd_sim_db_cb_sta, session_ctx) == 0) {
|
||||
#ifdef RADIUS_SERVER
|
||||
radius_server_eap_pending_cb(hapd->radius_srv, session_ctx);
|
||||
#endif /* RADIUS_SERVER */
|
||||
}
|
||||
}
|
||||
#endif /* EAP_SIM_DB */
|
||||
|
||||
|
||||
#ifdef RADIUS_SERVER
|
||||
|
||||
static int hostapd_radius_get_eap_user(void *ctx, const u8 *identity,
|
||||
size_t identity_len, int phase2,
|
||||
struct eap_user *user)
|
||||
{
|
||||
const struct hostapd_eap_user *eap_user;
|
||||
int i, count;
|
||||
|
||||
eap_user = hostapd_get_eap_user(ctx, identity, identity_len, phase2);
|
||||
if (eap_user == NULL)
|
||||
return -1;
|
||||
|
||||
if (user == NULL)
|
||||
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++) {
|
||||
user->methods[i].vendor = eap_user->methods[i].vendor;
|
||||
user->methods[i].method = eap_user->methods[i].method;
|
||||
}
|
||||
|
||||
if (eap_user->password) {
|
||||
user->password = os_malloc(eap_user->password_len);
|
||||
if (user->password == NULL)
|
||||
return -1;
|
||||
os_memcpy(user->password, eap_user->password,
|
||||
eap_user->password_len);
|
||||
user->password_len = eap_user->password_len;
|
||||
user->password_hash = eap_user->password_hash;
|
||||
}
|
||||
user->force_version = eap_user->force_version;
|
||||
user->ttls_auth = eap_user->ttls_auth;
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
|
||||
static int hostapd_setup_radius_srv(struct hostapd_data *hapd)
|
||||
{
|
||||
struct radius_server_conf srv;
|
||||
struct hostapd_bss_config *conf = hapd->conf;
|
||||
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.eap_sim_db_priv = hapd->eap_sim_db_priv;
|
||||
srv.ssl_ctx = hapd->ssl_ctx;
|
||||
srv.msg_ctx = hapd->msg_ctx;
|
||||
srv.pac_opaque_encr_key = conf->pac_opaque_encr_key;
|
||||
srv.eap_fast_a_id = conf->eap_fast_a_id;
|
||||
srv.eap_fast_a_id_len = conf->eap_fast_a_id_len;
|
||||
srv.eap_fast_a_id_info = conf->eap_fast_a_id_info;
|
||||
srv.eap_fast_prov = conf->eap_fast_prov;
|
||||
srv.pac_key_lifetime = conf->pac_key_lifetime;
|
||||
srv.pac_key_refresh_time = conf->pac_key_refresh_time;
|
||||
srv.eap_sim_aka_result_ind = conf->eap_sim_aka_result_ind;
|
||||
srv.tnc = conf->tnc;
|
||||
srv.wps = hapd->wps;
|
||||
srv.ipv6 = conf->radius_server_ipv6;
|
||||
srv.get_eap_user = hostapd_radius_get_eap_user;
|
||||
srv.eap_req_id_text = conf->eap_req_id_text;
|
||||
srv.eap_req_id_text_len = conf->eap_req_id_text_len;
|
||||
srv.pwd_group = conf->pwd_group;
|
||||
|
||||
hapd->radius_srv = radius_server_init(&srv);
|
||||
if (hapd->radius_srv == NULL) {
|
||||
wpa_printf(MSG_ERROR, "RADIUS server initialization failed.");
|
||||
return -1;
|
||||
}
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
#endif /* RADIUS_SERVER */
|
||||
|
||||
|
||||
int authsrv_init(struct hostapd_data *hapd)
|
||||
{
|
||||
#ifdef EAP_TLS_FUNCS
|
||||
if (hapd->conf->eap_server &&
|
||||
(hapd->conf->ca_cert || hapd->conf->server_cert ||
|
||||
hapd->conf->dh_file)) {
|
||||
struct tls_connection_params params;
|
||||
|
||||
hapd->ssl_ctx = tls_init(NULL);
|
||||
if (hapd->ssl_ctx == NULL) {
|
||||
wpa_printf(MSG_ERROR, "Failed to initialize TLS");
|
||||
authsrv_deinit(hapd);
|
||||
return -1;
|
||||
}
|
||||
|
||||
os_memset(¶ms, 0, sizeof(params));
|
||||
params.ca_cert = hapd->conf->ca_cert;
|
||||
params.client_cert = hapd->conf->server_cert;
|
||||
params.private_key = hapd->conf->private_key;
|
||||
params.private_key_passwd = hapd->conf->private_key_passwd;
|
||||
params.dh_file = hapd->conf->dh_file;
|
||||
|
||||
if (tls_global_set_params(hapd->ssl_ctx, ¶ms)) {
|
||||
wpa_printf(MSG_ERROR, "Failed to set TLS parameters");
|
||||
authsrv_deinit(hapd);
|
||||
return -1;
|
||||
}
|
||||
|
||||
if (tls_global_set_verify(hapd->ssl_ctx,
|
||||
hapd->conf->check_crl)) {
|
||||
wpa_printf(MSG_ERROR, "Failed to enable check_crl");
|
||||
authsrv_deinit(hapd);
|
||||
return -1;
|
||||
}
|
||||
}
|
||||
#endif /* EAP_TLS_FUNCS */
|
||||
|
||||
#ifdef EAP_SIM_DB
|
||||
if (hapd->conf->eap_sim_db) {
|
||||
hapd->eap_sim_db_priv =
|
||||
eap_sim_db_init(hapd->conf->eap_sim_db,
|
||||
hostapd_sim_db_cb, hapd);
|
||||
if (hapd->eap_sim_db_priv == NULL) {
|
||||
wpa_printf(MSG_ERROR, "Failed to initialize EAP-SIM "
|
||||
"database interface");
|
||||
authsrv_deinit(hapd);
|
||||
return -1;
|
||||
}
|
||||
}
|
||||
#endif /* EAP_SIM_DB */
|
||||
|
||||
#ifdef RADIUS_SERVER
|
||||
if (hapd->conf->radius_server_clients &&
|
||||
hostapd_setup_radius_srv(hapd))
|
||||
return -1;
|
||||
#endif /* RADIUS_SERVER */
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
|
||||
void authsrv_deinit(struct hostapd_data *hapd)
|
||||
{
|
||||
#ifdef RADIUS_SERVER
|
||||
radius_server_deinit(hapd->radius_srv);
|
||||
hapd->radius_srv = NULL;
|
||||
#endif /* RADIUS_SERVER */
|
||||
|
||||
#ifdef EAP_TLS_FUNCS
|
||||
if (hapd->ssl_ctx) {
|
||||
tls_deinit(hapd->ssl_ctx);
|
||||
hapd->ssl_ctx = NULL;
|
||||
}
|
||||
#endif /* EAP_TLS_FUNCS */
|
||||
|
||||
#ifdef EAP_SIM_DB
|
||||
if (hapd->eap_sim_db_priv) {
|
||||
eap_sim_db_deinit(hapd->eap_sim_db_priv);
|
||||
hapd->eap_sim_db_priv = NULL;
|
||||
}
|
||||
#endif /* EAP_SIM_DB */
|
||||
}
|
21
hostapd-0.8/src/ap/authsrv.h
Normal file
21
hostapd-0.8/src/ap/authsrv.h
Normal file
|
@ -0,0 +1,21 @@
|
|||
/*
|
||||
* 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.
|
||||
*/
|
||||
|
||||
#ifndef AUTHSRV_H
|
||||
#define AUTHSRV_H
|
||||
|
||||
int authsrv_init(struct hostapd_data *hapd);
|
||||
void authsrv_deinit(struct hostapd_data *hapd);
|
||||
|
||||
#endif /* AUTHSRV_H */
|
540
hostapd-0.8/src/ap/beacon.c
Normal file
540
hostapd-0.8/src/ap/beacon.c
Normal file
|
@ -0,0 +1,540 @@
|
|||
/*
|
||||
* 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>
|
||||
*
|
||||
* This program is free software; you can 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.
|
||||
*/
|
||||
|
||||
#include "utils/includes.h"
|
||||
|
||||
#ifndef CONFIG_NATIVE_WINDOWS
|
||||
|
||||
#include "utils/common.h"
|
||||
#include "common/ieee802_11_defs.h"
|
||||
#include "common/ieee802_11_common.h"
|
||||
#include "drivers/driver.h"
|
||||
#include "wps/wps_defs.h"
|
||||
#include "p2p/p2p.h"
|
||||
#include "hostapd.h"
|
||||
#include "ieee802_11.h"
|
||||
#include "wpa_auth.h"
|
||||
#include "wmm.h"
|
||||
#include "ap_config.h"
|
||||
#include "sta_info.h"
|
||||
#include "p2p_hostapd.h"
|
||||
#include "ap_drv_ops.h"
|
||||
#include "beacon.h"
|
||||
|
||||
|
||||
static u8 ieee802_11_erp_info(struct hostapd_data *hapd)
|
||||
{
|
||||
u8 erp = 0;
|
||||
|
||||
if (hapd->iface->current_mode == NULL ||
|
||||
hapd->iface->current_mode->mode != HOSTAPD_MODE_IEEE80211G)
|
||||
return 0;
|
||||
|
||||
switch (hapd->iconf->cts_protection_type) {
|
||||
case CTS_PROTECTION_FORCE_ENABLED:
|
||||
erp |= ERP_INFO_NON_ERP_PRESENT | ERP_INFO_USE_PROTECTION;
|
||||
break;
|
||||
case CTS_PROTECTION_FORCE_DISABLED:
|
||||
erp = 0;
|
||||
break;
|
||||
case CTS_PROTECTION_AUTOMATIC:
|
||||
if (hapd->iface->olbc)
|
||||
erp |= ERP_INFO_USE_PROTECTION;
|
||||
/* continue */
|
||||
case CTS_PROTECTION_AUTOMATIC_NO_OLBC:
|
||||
if (hapd->iface->num_sta_non_erp > 0) {
|
||||
erp |= ERP_INFO_NON_ERP_PRESENT |
|
||||
ERP_INFO_USE_PROTECTION;
|
||||
}
|
||||
break;
|
||||
}
|
||||
if (hapd->iface->num_sta_no_short_preamble > 0 ||
|
||||
hapd->iconf->preamble == LONG_PREAMBLE)
|
||||
erp |= ERP_INFO_BARKER_PREAMBLE_MODE;
|
||||
|
||||
return erp;
|
||||
}
|
||||
|
||||
|
||||
static u8 * hostapd_eid_ds_params(struct hostapd_data *hapd, u8 *eid)
|
||||
{
|
||||
*eid++ = WLAN_EID_DS_PARAMS;
|
||||
*eid++ = 1;
|
||||
*eid++ = hapd->iconf->channel;
|
||||
return eid;
|
||||
}
|
||||
|
||||
|
||||
static u8 * hostapd_eid_erp_info(struct hostapd_data *hapd, u8 *eid)
|
||||
{
|
||||
if (hapd->iface->current_mode == NULL ||
|
||||
hapd->iface->current_mode->mode != HOSTAPD_MODE_IEEE80211G)
|
||||
return eid;
|
||||
|
||||
/* Set NonERP_present and use_protection bits if there
|
||||
* are any associated NonERP stations. */
|
||||
/* TODO: use_protection bit can be set to zero even if
|
||||
* there are NonERP stations present. This optimization
|
||||
* might be useful if NonERP stations are "quiet".
|
||||
* See 802.11g/D6 E-1 for recommended practice.
|
||||
* In addition, Non ERP present might be set, if AP detects Non ERP
|
||||
* operation on other APs. */
|
||||
|
||||
/* Add ERP Information element */
|
||||
*eid++ = WLAN_EID_ERP_INFO;
|
||||
*eid++ = 1;
|
||||
*eid++ = ieee802_11_erp_info(hapd);
|
||||
|
||||
return eid;
|
||||
}
|
||||
|
||||
|
||||
static u8 * hostapd_eid_country_add(u8 *pos, u8 *end, int chan_spacing,
|
||||
struct hostapd_channel_data *start,
|
||||
struct hostapd_channel_data *prev)
|
||||
{
|
||||
if (end - pos < 3)
|
||||
return pos;
|
||||
|
||||
/* first channel number */
|
||||
*pos++ = start->chan;
|
||||
/* number of channels */
|
||||
*pos++ = (prev->chan - start->chan) / chan_spacing + 1;
|
||||
/* maximum transmit power level */
|
||||
*pos++ = start->max_tx_power;
|
||||
|
||||
return pos;
|
||||
}
|
||||
|
||||
|
||||
static u8 * hostapd_eid_country(struct hostapd_data *hapd, u8 *eid,
|
||||
int max_len)
|
||||
{
|
||||
u8 *pos = eid;
|
||||
u8 *end = eid + max_len;
|
||||
int i;
|
||||
struct hostapd_hw_modes *mode;
|
||||
struct hostapd_channel_data *start, *prev;
|
||||
int chan_spacing = 1;
|
||||
|
||||
if (!hapd->iconf->ieee80211d || max_len < 6 ||
|
||||
hapd->iface->current_mode == NULL)
|
||||
return eid;
|
||||
|
||||
*pos++ = WLAN_EID_COUNTRY;
|
||||
pos++; /* length will be set later */
|
||||
os_memcpy(pos, hapd->iconf->country, 3); /* e.g., 'US ' */
|
||||
pos += 3;
|
||||
|
||||
mode = hapd->iface->current_mode;
|
||||
if (mode->mode == HOSTAPD_MODE_IEEE80211A)
|
||||
chan_spacing = 4;
|
||||
|
||||
start = prev = NULL;
|
||||
for (i = 0; i < mode->num_channels; i++) {
|
||||
struct hostapd_channel_data *chan = &mode->channels[i];
|
||||
if (chan->flag & HOSTAPD_CHAN_DISABLED)
|
||||
continue;
|
||||
if (start && prev &&
|
||||
prev->chan + chan_spacing == chan->chan &&
|
||||
start->max_tx_power == chan->max_tx_power) {
|
||||
prev = chan;
|
||||
continue; /* can use same entry */
|
||||
}
|
||||
|
||||
if (start) {
|
||||
pos = hostapd_eid_country_add(pos, end, chan_spacing,
|
||||
start, prev);
|
||||
start = NULL;
|
||||
}
|
||||
|
||||
/* Start new group */
|
||||
start = prev = chan;
|
||||
}
|
||||
|
||||
if (start) {
|
||||
pos = hostapd_eid_country_add(pos, end, chan_spacing,
|
||||
start, prev);
|
||||
}
|
||||
|
||||
if ((pos - eid) & 1) {
|
||||
if (end - pos < 1)
|
||||
return eid;
|
||||
*pos++ = 0; /* pad for 16-bit alignment */
|
||||
}
|
||||
|
||||
eid[1] = (pos - eid) - 2;
|
||||
|
||||
return pos;
|
||||
}
|
||||
|
||||
|
||||
static u8 * hostapd_eid_wpa(struct hostapd_data *hapd, u8 *eid, size_t len,
|
||||
struct sta_info *sta)
|
||||
{
|
||||
const u8 *ie;
|
||||
size_t ielen;
|
||||
|
||||
ie = wpa_auth_get_wpa_ie(hapd->wpa_auth, &ielen);
|
||||
if (ie == NULL || ielen > len)
|
||||
return eid;
|
||||
|
||||
os_memcpy(eid, ie, ielen);
|
||||
return eid + ielen;
|
||||
}
|
||||
|
||||
|
||||
void handle_probe_req(struct hostapd_data *hapd,
|
||||
const struct ieee80211_mgmt *mgmt, size_t len)
|
||||
{
|
||||
struct ieee80211_mgmt *resp;
|
||||
struct ieee802_11_elems elems;
|
||||
char *ssid;
|
||||
u8 *pos, *epos;
|
||||
const u8 *ie;
|
||||
size_t ssid_len, ie_len;
|
||||
struct sta_info *sta = NULL;
|
||||
size_t buflen;
|
||||
size_t i;
|
||||
|
||||
ie = mgmt->u.probe_req.variable;
|
||||
if (len < IEEE80211_HDRLEN + sizeof(mgmt->u.probe_req))
|
||||
return;
|
||||
ie_len = len - (IEEE80211_HDRLEN + sizeof(mgmt->u.probe_req));
|
||||
|
||||
for (i = 0; hapd->probereq_cb && i < hapd->num_probereq_cb; i++)
|
||||
if (hapd->probereq_cb[i].cb(hapd->probereq_cb[i].ctx,
|
||||
mgmt->sa, ie, ie_len) > 0)
|
||||
return;
|
||||
|
||||
if (!hapd->iconf->send_probe_response)
|
||||
return;
|
||||
|
||||
if (ieee802_11_parse_elems(ie, ie_len, &elems, 0) == ParseFailed) {
|
||||
wpa_printf(MSG_DEBUG, "Could not parse ProbeReq from " MACSTR,
|
||||
MAC2STR(mgmt->sa));
|
||||
return;
|
||||
}
|
||||
|
||||
ssid = NULL;
|
||||
ssid_len = 0;
|
||||
|
||||
if ((!elems.ssid || !elems.supp_rates)) {
|
||||
wpa_printf(MSG_DEBUG, "STA " MACSTR " sent probe request "
|
||||
"without SSID or supported rates element",
|
||||
MAC2STR(mgmt->sa));
|
||||
return;
|
||||
}
|
||||
|
||||
#ifdef CONFIG_P2P
|
||||
if (hapd->p2p && elems.wps_ie) {
|
||||
struct wpabuf *wps;
|
||||
wps = ieee802_11_vendor_ie_concat(ie, ie_len, WPS_DEV_OUI_WFA);
|
||||
if (wps && !p2p_group_match_dev_type(hapd->p2p_group, wps)) {
|
||||
wpa_printf(MSG_MSGDUMP, "P2P: Ignore Probe Request "
|
||||
"due to mismatch with Requested Device "
|
||||
"Type");
|
||||
wpabuf_free(wps);
|
||||
return;
|
||||
}
|
||||
wpabuf_free(wps);
|
||||
}
|
||||
#endif /* CONFIG_P2P */
|
||||
|
||||
if (hapd->conf->ignore_broadcast_ssid && elems.ssid_len == 0) {
|
||||
wpa_printf(MSG_MSGDUMP, "Probe Request from " MACSTR " for "
|
||||
"broadcast SSID ignored", MAC2STR(mgmt->sa));
|
||||
return;
|
||||
}
|
||||
|
||||
sta = ap_get_sta(hapd, mgmt->sa);
|
||||
|
||||
#ifdef CONFIG_P2P
|
||||
if ((hapd->conf->p2p & P2P_GROUP_OWNER) &&
|
||||
elems.ssid_len == P2P_WILDCARD_SSID_LEN &&
|
||||
os_memcmp(elems.ssid, P2P_WILDCARD_SSID,
|
||||
P2P_WILDCARD_SSID_LEN) == 0) {
|
||||
/* Process P2P Wildcard SSID like Wildcard SSID */
|
||||
elems.ssid_len = 0;
|
||||
}
|
||||
#endif /* CONFIG_P2P */
|
||||
|
||||
if (elems.ssid_len == 0 ||
|
||||
(elems.ssid_len == hapd->conf->ssid.ssid_len &&
|
||||
os_memcmp(elems.ssid, hapd->conf->ssid.ssid, elems.ssid_len) ==
|
||||
0)) {
|
||||
ssid = hapd->conf->ssid.ssid;
|
||||
ssid_len = hapd->conf->ssid.ssid_len;
|
||||
if (sta)
|
||||
sta->ssid_probe = &hapd->conf->ssid;
|
||||
}
|
||||
|
||||
if (!ssid) {
|
||||
if (!(mgmt->da[0] & 0x01)) {
|
||||
char ssid_txt[33];
|
||||
ieee802_11_print_ssid(ssid_txt, elems.ssid,
|
||||
elems.ssid_len);
|
||||
wpa_printf(MSG_MSGDUMP, "Probe Request from " MACSTR
|
||||
" for foreign SSID '%s' (DA " MACSTR ")",
|
||||
MAC2STR(mgmt->sa), ssid_txt,
|
||||
MAC2STR(mgmt->da));
|
||||
}
|
||||
return;
|
||||
}
|
||||
|
||||
/* TODO: verify that supp_rates contains at least one matching rate
|
||||
* with AP configuration */
|
||||
#define MAX_PROBERESP_LEN 768
|
||||
buflen = MAX_PROBERESP_LEN;
|
||||
#ifdef CONFIG_WPS
|
||||
if (hapd->wps_probe_resp_ie)
|
||||
buflen += wpabuf_len(hapd->wps_probe_resp_ie);
|
||||
#endif /* CONFIG_WPS */
|
||||
#ifdef CONFIG_P2P
|
||||
if (hapd->p2p_probe_resp_ie)
|
||||
buflen += wpabuf_len(hapd->p2p_probe_resp_ie);
|
||||
#endif /* CONFIG_P2P */
|
||||
resp = os_zalloc(buflen);
|
||||
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);
|
||||
|
||||
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, sta);
|
||||
|
||||
#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);
|
||||
|
||||
/* 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)
|
||||
perror("handle_probe_req: send");
|
||||
|
||||
os_free(resp);
|
||||
|
||||
wpa_printf(MSG_EXCESSIVE, "STA " MACSTR " sent probe request for %s "
|
||||
"SSID", MAC2STR(mgmt->sa),
|
||||
elems.ssid_len == 0 ? "broadcast" : "our");
|
||||
}
|
||||
|
||||
|
||||
void ieee802_11_set_beacon(struct hostapd_data *hapd)
|
||||
{
|
||||
struct ieee80211_mgmt *head;
|
||||
u8 *pos, *tail, *tailpos;
|
||||
u16 capab_info;
|
||||
size_t head_len, tail_len;
|
||||
|
||||
#ifdef CONFIG_P2P
|
||||
if ((hapd->conf->p2p & (P2P_ENABLED | P2P_GROUP_OWNER)) == P2P_ENABLED)
|
||||
goto no_beacon;
|
||||
#endif /* CONFIG_P2P */
|
||||
|
||||
#define BEACON_HEAD_BUF_SIZE 256
|
||||
#define BEACON_TAIL_BUF_SIZE 512
|
||||
head = os_zalloc(BEACON_HEAD_BUF_SIZE);
|
||||
tail_len = BEACON_TAIL_BUF_SIZE;
|
||||
#ifdef CONFIG_WPS
|
||||
if (hapd->conf->wps_state && hapd->wps_beacon_ie)
|
||||
tail_len += wpabuf_len(hapd->wps_beacon_ie);
|
||||
#endif /* CONFIG_WPS */
|
||||
#ifdef CONFIG_P2P
|
||||
if (hapd->p2p_beacon_ie)
|
||||
tail_len += wpabuf_len(hapd->p2p_beacon_ie);
|
||||
#endif /* CONFIG_P2P */
|
||||
tailpos = tail = os_malloc(tail_len);
|
||||
if (head == NULL || tail == NULL) {
|
||||
wpa_printf(MSG_ERROR, "Failed to set beacon data");
|
||||
os_free(head);
|
||||
os_free(tail);
|
||||
return;
|
||||
}
|
||||
|
||||
head->frame_control = IEEE80211_FC(WLAN_FC_TYPE_MGMT,
|
||||
WLAN_FC_STYPE_BEACON);
|
||||
head->duration = host_to_le16(0);
|
||||
os_memset(head->da, 0xff, ETH_ALEN);
|
||||
|
||||
os_memcpy(head->sa, hapd->own_addr, ETH_ALEN);
|
||||
os_memcpy(head->bssid, hapd->own_addr, ETH_ALEN);
|
||||
head->u.beacon.beacon_int =
|
||||
host_to_le16(hapd->iconf->beacon_int);
|
||||
|
||||
/* hardware or low-level driver will setup seq_ctrl and timestamp */
|
||||
capab_info = hostapd_own_capab_info(hapd, NULL, 0);
|
||||
head->u.beacon.capab_info = host_to_le16(capab_info);
|
||||
pos = &head->u.beacon.variable[0];
|
||||
|
||||
/* SSID */
|
||||
*pos++ = WLAN_EID_SSID;
|
||||
if (hapd->conf->ignore_broadcast_ssid == 2) {
|
||||
/* clear the data, but keep the correct length of the SSID */
|
||||
*pos++ = hapd->conf->ssid.ssid_len;
|
||||
os_memset(pos, 0, hapd->conf->ssid.ssid_len);
|
||||
pos += hapd->conf->ssid.ssid_len;
|
||||
} else if (hapd->conf->ignore_broadcast_ssid) {
|
||||
*pos++ = 0; /* empty SSID */
|
||||
} else {
|
||||
*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);
|
||||
|
||||
head_len = pos - (u8 *) head;
|
||||
|
||||
tailpos = hostapd_eid_country(hapd, tailpos,
|
||||
tail + BEACON_TAIL_BUF_SIZE - tailpos);
|
||||
|
||||
/* ERP Information element */
|
||||
tailpos = hostapd_eid_erp_info(hapd, tailpos);
|
||||
|
||||
/* Extended supported rates */
|
||||
tailpos = hostapd_eid_ext_supp_rates(hapd, tailpos);
|
||||
|
||||
/* RSN, MDIE, WPA */
|
||||
tailpos = hostapd_eid_wpa(hapd, tailpos, tail + BEACON_TAIL_BUF_SIZE -
|
||||
tailpos, NULL);
|
||||
|
||||
#ifdef CONFIG_IEEE80211N
|
||||
tailpos = hostapd_eid_ht_capabilities(hapd, tailpos);
|
||||
tailpos = hostapd_eid_ht_operation(hapd, tailpos);
|
||||
|
||||
//DRIVER_RTW ADD
|
||||
if(hapd->iconf->ieee80211n)
|
||||
hapd->conf->wmm_enabled = 1;
|
||||
|
||||
#endif /* CONFIG_IEEE80211N */
|
||||
|
||||
tailpos = hostapd_eid_ext_capab(hapd, tailpos);
|
||||
|
||||
/* Wi-Fi Alliance WMM */
|
||||
tailpos = hostapd_eid_wmm(hapd, tailpos);
|
||||
|
||||
#ifdef CONFIG_WPS
|
||||
if (hapd->conf->wps_state && hapd->wps_beacon_ie) {
|
||||
os_memcpy(tailpos, wpabuf_head(hapd->wps_beacon_ie),
|
||||
wpabuf_len(hapd->wps_beacon_ie));
|
||||
tailpos += wpabuf_len(hapd->wps_beacon_ie);
|
||||
}
|
||||
#endif /* CONFIG_WPS */
|
||||
|
||||
#ifdef CONFIG_P2P
|
||||
if ((hapd->conf->p2p & P2P_ENABLED) && hapd->p2p_beacon_ie) {
|
||||
os_memcpy(tailpos, wpabuf_head(hapd->p2p_beacon_ie),
|
||||
wpabuf_len(hapd->p2p_beacon_ie));
|
||||
tailpos += wpabuf_len(hapd->p2p_beacon_ie);
|
||||
}
|
||||
#endif /* CONFIG_P2P */
|
||||
#ifdef CONFIG_P2P_MANAGER
|
||||
if ((hapd->conf->p2p & (P2P_MANAGE | P2P_ENABLED | P2P_GROUP_OWNER)) ==
|
||||
P2P_MANAGE)
|
||||
tailpos = hostapd_eid_p2p_manage(hapd, tailpos);
|
||||
#endif /* CONFIG_P2P_MANAGER */
|
||||
|
||||
tail_len = tailpos > tail ? tailpos - tail : 0;
|
||||
|
||||
if (hostapd_drv_set_beacon(hapd, (u8 *) head, head_len,
|
||||
tail, tail_len, hapd->conf->dtim_period,
|
||||
hapd->iconf->beacon_int))
|
||||
wpa_printf(MSG_ERROR, "Failed to set beacon head/tail or DTIM "
|
||||
"period");
|
||||
|
||||
os_free(tail);
|
||||
os_free(head);
|
||||
|
||||
#ifdef CONFIG_P2P
|
||||
no_beacon:
|
||||
#endif /* CONFIG_P2P */
|
||||
hostapd_set_bss_params(hapd, !!(ieee802_11_erp_info(hapd) &
|
||||
ERP_INFO_USE_PROTECTION));
|
||||
}
|
||||
|
||||
|
||||
void ieee802_11_set_beacons(struct hostapd_iface *iface)
|
||||
{
|
||||
size_t i;
|
||||
for (i = 0; i < iface->num_bss; i++)
|
||||
ieee802_11_set_beacon(iface->bss[i]);
|
||||
}
|
||||
|
||||
#endif /* CONFIG_NATIVE_WINDOWS */
|
36
hostapd-0.8/src/ap/beacon.h
Normal file
36
hostapd-0.8/src/ap/beacon.h
Normal file
|
@ -0,0 +1,36 @@
|
|||
/*
|
||||
* hostapd / IEEE 802.11 Management: Beacon and Probe Request/Response
|
||||
* Copyright (c) 2002-2004, Instant802 Networks, Inc.
|
||||
* Copyright (c) 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.
|
||||
*/
|
||||
|
||||
#ifndef BEACON_H
|
||||
#define BEACON_H
|
||||
|
||||
struct ieee80211_mgmt;
|
||||
|
||||
void handle_probe_req(struct hostapd_data *hapd,
|
||||
const struct ieee80211_mgmt *mgmt, size_t len);
|
||||
#ifdef NEED_AP_MLME
|
||||
void ieee802_11_set_beacon(struct hostapd_data *hapd);
|
||||
void ieee802_11_set_beacons(struct hostapd_iface *iface);
|
||||
#else /* NEED_AP_MLME */
|
||||
static inline void ieee802_11_set_beacon(struct hostapd_data *hapd)
|
||||
{
|
||||
}
|
||||
|
||||
static inline void ieee802_11_set_beacons(struct hostapd_iface *iface)
|
||||
{
|
||||
}
|
||||
#endif /* NEED_AP_MLME */
|
||||
|
||||
#endif /* BEACON_H */
|
108
hostapd-0.8/src/ap/ctrl_iface_ap.c
Normal file
108
hostapd-0.8/src/ap/ctrl_iface_ap.c
Normal file
|
@ -0,0 +1,108 @@
|
|||
/*
|
||||
* 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.
|
||||
*/
|
||||
|
||||
#include "utils/includes.h"
|
||||
|
||||
#include "utils/common.h"
|
||||
#include "hostapd.h"
|
||||
#include "ieee802_1x.h"
|
||||
#include "wpa_auth.h"
|
||||
#include "ieee802_11.h"
|
||||
#include "sta_info.h"
|
||||
#include "wps_hostapd.h"
|
||||
#include "p2p_hostapd.h"
|
||||
#include "ctrl_iface_ap.h"
|
||||
|
||||
|
||||
static int hostapd_ctrl_iface_sta_mib(struct hostapd_data *hapd,
|
||||
struct sta_info *sta,
|
||||
char *buf, size_t buflen)
|
||||
{
|
||||
int len, res, ret;
|
||||
|
||||
if (sta == NULL) {
|
||||
ret = os_snprintf(buf, buflen, "FAIL\n");
|
||||
if (ret < 0 || (size_t) ret >= buflen)
|
||||
return 0;
|
||||
return ret;
|
||||
}
|
||||
|
||||
len = 0;
|
||||
ret = os_snprintf(buf + len, buflen - len, MACSTR "\n",
|
||||
MAC2STR(sta->addr));
|
||||
if (ret < 0 || (size_t) ret >= buflen - len)
|
||||
return len;
|
||||
len += ret;
|
||||
|
||||
res = ieee802_11_get_mib_sta(hapd, sta, buf + len, buflen - len);
|
||||
if (res >= 0)
|
||||
len += res;
|
||||
res = wpa_get_mib_sta(sta->wpa_sm, buf + len, buflen - len);
|
||||
if (res >= 0)
|
||||
len += res;
|
||||
res = ieee802_1x_get_mib_sta(hapd, sta, buf + len, buflen - len);
|
||||
if (res >= 0)
|
||||
len += res;
|
||||
res = hostapd_wps_get_mib_sta(hapd, sta->addr, buf + len,
|
||||
buflen - len);
|
||||
if (res >= 0)
|
||||
len += res;
|
||||
res = hostapd_p2p_get_mib_sta(hapd, sta, buf + len, buflen - len);
|
||||
if (res >= 0)
|
||||
len += res;
|
||||
|
||||
return len;
|
||||
}
|
||||
|
||||
|
||||
int hostapd_ctrl_iface_sta_first(struct hostapd_data *hapd,
|
||||
char *buf, size_t buflen)
|
||||
{
|
||||
return hostapd_ctrl_iface_sta_mib(hapd, hapd->sta_list, buf, buflen);
|
||||
}
|
||||
|
||||
|
||||
int hostapd_ctrl_iface_sta(struct hostapd_data *hapd, const char *txtaddr,
|
||||
char *buf, size_t buflen)
|
||||
{
|
||||
u8 addr[ETH_ALEN];
|
||||
int ret;
|
||||
|
||||
if (hwaddr_aton(txtaddr, addr)) {
|
||||
ret = os_snprintf(buf, buflen, "FAIL\n");
|
||||
if (ret < 0 || (size_t) ret >= buflen)
|
||||
return 0;
|
||||
return ret;
|
||||
}
|
||||
return hostapd_ctrl_iface_sta_mib(hapd, ap_get_sta(hapd, addr),
|
||||
buf, buflen);
|
||||
}
|
||||
|
||||
|
||||
int hostapd_ctrl_iface_sta_next(struct hostapd_data *hapd, const char *txtaddr,
|
||||
char *buf, size_t buflen)
|
||||
{
|
||||
u8 addr[ETH_ALEN];
|
||||
struct sta_info *sta;
|
||||
int ret;
|
||||
|
||||
if (hwaddr_aton(txtaddr, addr) ||
|
||||
(sta = ap_get_sta(hapd, addr)) == NULL) {
|
||||
ret = os_snprintf(buf, buflen, "FAIL\n");
|
||||
if (ret < 0 || (size_t) ret >= buflen)
|
||||
return 0;
|
||||
return ret;
|
||||
}
|
||||
return hostapd_ctrl_iface_sta_mib(hapd, sta->next, buf, buflen);
|
||||
}
|
25
hostapd-0.8/src/ap/ctrl_iface_ap.h
Normal file
25
hostapd-0.8/src/ap/ctrl_iface_ap.h
Normal file
|
@ -0,0 +1,25 @@
|
|||
/*
|
||||
* 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.
|
||||
*/
|
||||
|
||||
#ifndef CTRL_IFACE_AP_H
|
||||
#define CTRL_IFACE_AP_H
|
||||
|
||||
int hostapd_ctrl_iface_sta_first(struct hostapd_data *hapd,
|
||||
char *buf, size_t buflen);
|
||||
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);
|
||||
|
||||
#endif /* CTRL_IFACE_AP_H */
|
539
hostapd-0.8/src/ap/drv_callbacks.c
Normal file
539
hostapd-0.8/src/ap/drv_callbacks.c
Normal file
|
@ -0,0 +1,539 @@
|
|||
/*
|
||||
* 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.
|
||||
*/
|
||||
|
||||
#include "utils/includes.h"
|
||||
|
||||
#include "utils/common.h"
|
||||
#include "radius/radius.h"
|
||||
#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 "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"
|
||||
|
||||
|
||||
int hostapd_notif_assoc(struct hostapd_data *hapd, const u8 *addr,
|
||||
const u8 *ie, size_t ielen, int reassoc)
|
||||
{
|
||||
struct sta_info *sta;
|
||||
int new_assoc, res;
|
||||
struct ieee802_11_elems elems;
|
||||
#ifdef CONFIG_P2P
|
||||
const u8 *all_ies = ie;
|
||||
size_t all_ies_len = ielen;
|
||||
#endif /* CONFIG_P2P */
|
||||
|
||||
if (addr == NULL) {
|
||||
/*
|
||||
* This could potentially happen with unexpected event from the
|
||||
* driver wrapper. This was seen at least in one case where the
|
||||
* driver ended up being set to station mode while hostapd was
|
||||
* running, so better make sure we stop processing such an
|
||||
* event here.
|
||||
*/
|
||||
wpa_printf(MSG_DEBUG, "hostapd_notif_assoc: Skip event with "
|
||||
"no address");
|
||||
return -1;
|
||||
}
|
||||
random_add_randomness(addr, ETH_ALEN);
|
||||
|
||||
hostapd_logger(hapd, addr, HOSTAPD_MODULE_IEEE80211,
|
||||
HOSTAPD_LEVEL_INFO, "associated");
|
||||
|
||||
ieee802_11_parse_elems(ie, ielen, &elems, 0);
|
||||
if (elems.wps_ie) {
|
||||
ie = elems.wps_ie - 2;
|
||||
ielen = elems.wps_ie_len + 2;
|
||||
wpa_printf(MSG_DEBUG, "STA included WPS IE in (Re)AssocReq");
|
||||
} else if (elems.rsn_ie) {
|
||||
ie = elems.rsn_ie - 2;
|
||||
ielen = elems.rsn_ie_len + 2;
|
||||
wpa_printf(MSG_DEBUG, "STA included RSN IE in (Re)AssocReq");
|
||||
} else if (elems.wpa_ie) {
|
||||
ie = elems.wpa_ie - 2;
|
||||
ielen = elems.wpa_ie_len + 2;
|
||||
wpa_printf(MSG_DEBUG, "STA included WPA IE in (Re)AssocReq");
|
||||
} else {
|
||||
ie = NULL;
|
||||
ielen = 0;
|
||||
wpa_printf(MSG_DEBUG, "STA did not include WPS/RSN/WPA IE in "
|
||||
"(Re)AssocReq");
|
||||
}
|
||||
|
||||
sta = ap_get_sta(hapd, addr);
|
||||
if (sta) {
|
||||
accounting_sta_stop(hapd, sta);
|
||||
} else {
|
||||
sta = ap_sta_add(hapd, addr);
|
||||
if (sta == NULL)
|
||||
return -1;
|
||||
}
|
||||
sta->flags &= ~(WLAN_STA_WPS | WLAN_STA_MAYBE_WPS);
|
||||
|
||||
#ifdef CONFIG_P2P
|
||||
if (elems.p2p) {
|
||||
wpabuf_free(sta->p2p_ie);
|
||||
sta->p2p_ie = ieee802_11_vendor_ie_concat(all_ies, all_ies_len,
|
||||
P2P_IE_VENDOR_TYPE);
|
||||
}
|
||||
#endif /* CONFIG_P2P */
|
||||
|
||||
if (hapd->conf->wpa) {
|
||||
if (ie == NULL || ielen == 0) {
|
||||
if (hapd->conf->wps_state) {
|
||||
wpa_printf(MSG_DEBUG, "STA did not include "
|
||||
"WPA/RSN IE in (Re)Association "
|
||||
"Request - possible WPS use");
|
||||
sta->flags |= WLAN_STA_MAYBE_WPS;
|
||||
goto skip_wpa_check;
|
||||
}
|
||||
|
||||
wpa_printf(MSG_DEBUG, "No WPA/RSN IE from STA");
|
||||
return -1;
|
||||
}
|
||||
if (hapd->conf->wps_state && ie[0] == 0xdd && ie[1] >= 4 &&
|
||||
os_memcmp(ie + 2, "\x00\x50\xf2\x04", 4) == 0) {
|
||||
sta->flags |= WLAN_STA_WPS;
|
||||
goto skip_wpa_check;
|
||||
}
|
||||
|
||||
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_ERROR, "Failed to initialize WPA state "
|
||||
"machine");
|
||||
return -1;
|
||||
}
|
||||
res = wpa_validate_wpa_ie(hapd->wpa_auth, sta->wpa_sm,
|
||||
ie, ielen, NULL, 0);
|
||||
if (res != WPA_IE_OK) {
|
||||
int resp;
|
||||
wpa_printf(MSG_DEBUG, "WPA/RSN information element "
|
||||
"rejected? (res %u)", res);
|
||||
wpa_hexdump(MSG_DEBUG, "IE", ie, ielen);
|
||||
if (res == WPA_INVALID_GROUP)
|
||||
resp = WLAN_REASON_GROUP_CIPHER_NOT_VALID;
|
||||
else if (res == WPA_INVALID_PAIRWISE)
|
||||
resp = WLAN_REASON_PAIRWISE_CIPHER_NOT_VALID;
|
||||
else if (res == WPA_INVALID_AKMP)
|
||||
resp = WLAN_REASON_AKMP_NOT_VALID;
|
||||
#ifdef CONFIG_IEEE80211W
|
||||
else if (res == WPA_MGMT_FRAME_PROTECTION_VIOLATION)
|
||||
resp = WLAN_REASON_INVALID_IE;
|
||||
else if (res == WPA_INVALID_MGMT_GROUP_CIPHER)
|
||||
resp = WLAN_REASON_GROUP_CIPHER_NOT_VALID;
|
||||
#endif /* CONFIG_IEEE80211W */
|
||||
else
|
||||
resp = WLAN_REASON_INVALID_IE;
|
||||
hostapd_drv_sta_disassoc(hapd, sta->addr, resp);
|
||||
ap_free_sta(hapd, sta);
|
||||
return -1;
|
||||
}
|
||||
} else if (hapd->conf->wps_state) {
|
||||
#ifdef CONFIG_WPS_STRICT
|
||||
if (ie) {
|
||||
struct wpabuf *wps;
|
||||
wps = ieee802_11_vendor_ie_concat(ie, ielen,
|
||||
WPS_IE_VENDOR_TYPE);
|
||||
if (wps && wps_validate_assoc_req(wps) < 0) {
|
||||
hostapd_drv_sta_disassoc(
|
||||
hapd, sta->addr,
|
||||
WLAN_REASON_INVALID_IE);
|
||||
ap_free_sta(hapd, sta);
|
||||
wpabuf_free(wps);
|
||||
return -1;
|
||||
}
|
||||
wpabuf_free(wps);
|
||||
}
|
||||
#endif /* CONFIG_WPS_STRICT */
|
||||
if (ie && ielen > 4 && ie[0] == 0xdd && ie[1] >= 4 &&
|
||||
os_memcmp(ie + 2, "\x00\x50\xf2\x04", 4) == 0) {
|
||||
sta->flags |= WLAN_STA_WPS;
|
||||
} else
|
||||
sta->flags |= WLAN_STA_MAYBE_WPS;
|
||||
}
|
||||
skip_wpa_check:
|
||||
|
||||
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);
|
||||
|
||||
hostapd_new_assoc_sta(hapd, sta, !new_assoc);
|
||||
|
||||
ieee802_1x_notify_port_enabled(sta->eapol_sm, 1);
|
||||
|
||||
#ifdef CONFIG_P2P
|
||||
p2p_group_notif_assoc(hapd->p2p_group, sta->addr,
|
||||
all_ies, all_ies_len);
|
||||
#endif /* CONFIG_P2P */
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
|
||||
void hostapd_notif_disassoc(struct hostapd_data *hapd, const u8 *addr)
|
||||
{
|
||||
struct sta_info *sta;
|
||||
|
||||
if (addr == NULL) {
|
||||
/*
|
||||
* This could potentially happen with unexpected event from the
|
||||
* driver wrapper. This was seen at least in one case where the
|
||||
* driver ended up reporting a station mode event while hostapd
|
||||
* was running, so better make sure we stop processing such an
|
||||
* event here.
|
||||
*/
|
||||
wpa_printf(MSG_DEBUG, "hostapd_notif_disassoc: Skip event "
|
||||
"with no address");
|
||||
return;
|
||||
}
|
||||
|
||||
hostapd_logger(hapd, addr, HOSTAPD_MODULE_IEEE80211,
|
||||
HOSTAPD_LEVEL_INFO, "disassociated");
|
||||
|
||||
sta = ap_get_sta(hapd, addr);
|
||||
if (sta == NULL) {
|
||||
wpa_printf(MSG_DEBUG, "Disassociation notification for "
|
||||
"unknown STA " MACSTR, MAC2STR(addr));
|
||||
return;
|
||||
}
|
||||
|
||||
sta->flags &= ~(WLAN_STA_AUTH | WLAN_STA_ASSOC);
|
||||
wpa_msg(hapd->msg_ctx, MSG_INFO, AP_STA_DISCONNECTED MACSTR,
|
||||
MAC2STR(sta->addr));
|
||||
wpa_auth_sm_event(sta->wpa_sm, WPA_DISASSOC);
|
||||
sta->acct_terminate_cause = RADIUS_ACCT_TERMINATE_CAUSE_USER_REQUEST;
|
||||
ieee802_1x_notify_port_enabled(sta->eapol_sm, 0);
|
||||
ap_free_sta(hapd, sta);
|
||||
}
|
||||
|
||||
|
||||
void hostapd_event_sta_low_ack(struct hostapd_data *hapd, const u8 *addr)
|
||||
{
|
||||
struct sta_info *sta = ap_get_sta(hapd, addr);
|
||||
|
||||
if (!sta || !hapd->conf->disassoc_low_ack)
|
||||
return;
|
||||
|
||||
hostapd_logger(hapd, addr, HOSTAPD_MODULE_IEEE80211,
|
||||
HOSTAPD_LEVEL_INFO, "disconnected due to excessive "
|
||||
"missing ACKs");
|
||||
hostapd_drv_sta_disassoc(hapd, addr, WLAN_REASON_DISASSOC_LOW_ACK);
|
||||
if (sta)
|
||||
ap_sta_disassociate(hapd, sta, WLAN_REASON_DISASSOC_LOW_ACK);
|
||||
}
|
||||
|
||||
|
||||
int hostapd_probe_req_rx(struct hostapd_data *hapd, const u8 *sa,
|
||||
const u8 *ie, size_t ie_len)
|
||||
{
|
||||
size_t i;
|
||||
int ret = 0;
|
||||
|
||||
if (sa == NULL || ie == NULL)
|
||||
return -1;
|
||||
|
||||
random_add_randomness(sa, ETH_ALEN);
|
||||
for (i = 0; hapd->probereq_cb && i < hapd->num_probereq_cb; i++) {
|
||||
if (hapd->probereq_cb[i].cb(hapd->probereq_cb[i].ctx,
|
||||
sa, ie, ie_len) > 0) {
|
||||
ret = 1;
|
||||
break;
|
||||
}
|
||||
}
|
||||
return ret;
|
||||
}
|
||||
|
||||
|
||||
#ifdef HOSTAPD
|
||||
|
||||
#ifdef NEED_AP_MLME
|
||||
|
||||
static const u8 * get_hdr_bssid(const struct ieee80211_hdr *hdr, size_t len)
|
||||
{
|
||||
u16 fc, type, stype;
|
||||
|
||||
/*
|
||||
* PS-Poll frames are 16 bytes. All other frames are
|
||||
* 24 bytes or longer.
|
||||
*/
|
||||
if (len < 16)
|
||||
return NULL;
|
||||
|
||||
fc = le_to_host16(hdr->frame_control);
|
||||
type = WLAN_FC_GET_TYPE(fc);
|
||||
stype = WLAN_FC_GET_STYPE(fc);
|
||||
|
||||
switch (type) {
|
||||
case WLAN_FC_TYPE_DATA:
|
||||
if (len < 24)
|
||||
return NULL;
|
||||
switch (fc & (WLAN_FC_FROMDS | WLAN_FC_TODS)) {
|
||||
case WLAN_FC_FROMDS | WLAN_FC_TODS:
|
||||
case WLAN_FC_TODS:
|
||||
return hdr->addr1;
|
||||
case WLAN_FC_FROMDS:
|
||||
return hdr->addr2;
|
||||
default:
|
||||
return NULL;
|
||||
}
|
||||
case WLAN_FC_TYPE_CTRL:
|
||||
if (stype != WLAN_FC_STYPE_PSPOLL)
|
||||
return NULL;
|
||||
return hdr->addr1;
|
||||
case WLAN_FC_TYPE_MGMT:
|
||||
return hdr->addr3;
|
||||
default:
|
||||
return NULL;
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
#define HAPD_BROADCAST ((struct hostapd_data *) -1)
|
||||
|
||||
static struct hostapd_data * get_hapd_bssid(struct hostapd_iface *iface,
|
||||
const u8 *bssid)
|
||||
{
|
||||
size_t i;
|
||||
|
||||
if (bssid == NULL)
|
||||
return NULL;
|
||||
if (bssid[0] == 0xff && bssid[1] == 0xff && bssid[2] == 0xff &&
|
||||
bssid[3] == 0xff && bssid[4] == 0xff && bssid[5] == 0xff)
|
||||
return HAPD_BROADCAST;
|
||||
|
||||
for (i = 0; i < iface->num_bss; i++) {
|
||||
if (os_memcmp(bssid, iface->bss[i]->own_addr, ETH_ALEN) == 0)
|
||||
return iface->bss[i];
|
||||
}
|
||||
|
||||
return NULL;
|
||||
}
|
||||
|
||||
|
||||
static void hostapd_rx_from_unknown_sta(struct hostapd_data *hapd,
|
||||
const u8 *frame, size_t len)
|
||||
{
|
||||
const struct ieee80211_hdr *hdr = (const struct ieee80211_hdr *) frame;
|
||||
u16 fc = le_to_host16(hdr->frame_control);
|
||||
hapd = get_hapd_bssid(hapd->iface, get_hdr_bssid(hdr, len));
|
||||
if (hapd == NULL || hapd == HAPD_BROADCAST)
|
||||
return;
|
||||
|
||||
ieee802_11_rx_from_unknown(hapd, hdr->addr2,
|
||||
(fc & (WLAN_FC_TODS | WLAN_FC_FROMDS)) ==
|
||||
(WLAN_FC_TODS | WLAN_FC_FROMDS));
|
||||
}
|
||||
|
||||
|
||||
static void hostapd_mgmt_rx(struct hostapd_data *hapd, struct rx_mgmt *rx_mgmt)
|
||||
{
|
||||
struct hostapd_iface *iface = hapd->iface;
|
||||
const struct ieee80211_hdr *hdr;
|
||||
const u8 *bssid;
|
||||
struct hostapd_frame_info fi;
|
||||
|
||||
hdr = (const struct ieee80211_hdr *) rx_mgmt->frame;
|
||||
bssid = get_hdr_bssid(hdr, rx_mgmt->frame_len);
|
||||
if (bssid == NULL)
|
||||
return;
|
||||
|
||||
hapd = get_hapd_bssid(iface, bssid);
|
||||
if (hapd == NULL) {
|
||||
u16 fc;
|
||||
fc = le_to_host16(hdr->frame_control);
|
||||
|
||||
/*
|
||||
* Drop frames to unknown BSSIDs except for Beacon frames which
|
||||
* could be used to update neighbor information.
|
||||
*/
|
||||
if (WLAN_FC_GET_TYPE(fc) == WLAN_FC_TYPE_MGMT &&
|
||||
WLAN_FC_GET_STYPE(fc) == WLAN_FC_STYPE_BEACON)
|
||||
hapd = iface->bss[0];
|
||||
else
|
||||
return;
|
||||
}
|
||||
|
||||
os_memset(&fi, 0, sizeof(fi));
|
||||
fi.datarate = rx_mgmt->datarate;
|
||||
fi.ssi_signal = rx_mgmt->ssi_signal;
|
||||
|
||||
if (hapd == HAPD_BROADCAST) {
|
||||
size_t i;
|
||||
for (i = 0; i < iface->num_bss; i++)
|
||||
ieee802_11_mgmt(iface->bss[i], rx_mgmt->frame,
|
||||
rx_mgmt->frame_len, &fi);
|
||||
} else
|
||||
ieee802_11_mgmt(hapd, rx_mgmt->frame, rx_mgmt->frame_len, &fi);
|
||||
|
||||
random_add_randomness(&fi, sizeof(fi));
|
||||
}
|
||||
|
||||
|
||||
static void hostapd_mgmt_tx_cb(struct hostapd_data *hapd, const u8 *buf,
|
||||
size_t len, u16 stype, int ok)
|
||||
{
|
||||
struct ieee80211_hdr *hdr;
|
||||
hdr = (struct ieee80211_hdr *) buf;
|
||||
hapd = get_hapd_bssid(hapd->iface, get_hdr_bssid(hdr, len));
|
||||
if (hapd == NULL || hapd == HAPD_BROADCAST)
|
||||
return;
|
||||
ieee802_11_mgmt_cb(hapd, buf, len, stype, ok);
|
||||
}
|
||||
|
||||
#endif /* NEED_AP_MLME */
|
||||
|
||||
|
||||
static int hostapd_event_new_sta(struct hostapd_data *hapd, const u8 *addr)
|
||||
{
|
||||
struct sta_info *sta = ap_get_sta(hapd, addr);
|
||||
if (sta)
|
||||
return 0;
|
||||
|
||||
wpa_printf(MSG_DEBUG, "Data frame from unknown STA " MACSTR
|
||||
" - adding a new STA", MAC2STR(addr));
|
||||
sta = ap_sta_add(hapd, addr);
|
||||
if (sta) {
|
||||
hostapd_new_assoc_sta(hapd, sta, 0);
|
||||
} else {
|
||||
wpa_printf(MSG_DEBUG, "Failed to add STA entry for " MACSTR,
|
||||
MAC2STR(addr));
|
||||
return -1;
|
||||
}
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
|
||||
static void hostapd_event_eapol_rx(struct hostapd_data *hapd, const u8 *src,
|
||||
const u8 *data, size_t data_len)
|
||||
{
|
||||
struct hostapd_iface *iface = hapd->iface;
|
||||
size_t j;
|
||||
|
||||
for (j = 0; j < iface->num_bss; j++) {
|
||||
if (ap_get_sta(iface->bss[j], src)) {
|
||||
hapd = iface->bss[j];
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
ieee802_1x_receive(hapd, src, data, data_len);
|
||||
}
|
||||
|
||||
|
||||
void wpa_supplicant_event(void *ctx, enum wpa_event_type event,
|
||||
union wpa_event_data *data)
|
||||
{
|
||||
struct hostapd_data *hapd = ctx;
|
||||
|
||||
switch (event) {
|
||||
case EVENT_MICHAEL_MIC_FAILURE:
|
||||
michael_mic_failure(hapd, data->michael_mic_failure.src, 1);
|
||||
break;
|
||||
case EVENT_SCAN_RESULTS:
|
||||
if (hapd->iface->scan_cb)
|
||||
hapd->iface->scan_cb(hapd->iface);
|
||||
break;
|
||||
#ifdef CONFIG_IEEE80211R
|
||||
case EVENT_FT_RRB_RX:
|
||||
wpa_ft_rrb_rx(hapd->wpa_auth, data->ft_rrb_rx.src,
|
||||
data->ft_rrb_rx.data, data->ft_rrb_rx.data_len);
|
||||
break;
|
||||
#endif /* CONFIG_IEEE80211R */
|
||||
case EVENT_WPS_BUTTON_PUSHED:
|
||||
hostapd_wps_button_pushed(hapd, NULL);
|
||||
break;
|
||||
#ifdef NEED_AP_MLME
|
||||
case EVENT_TX_STATUS:
|
||||
switch (data->tx_status.type) {
|
||||
case WLAN_FC_TYPE_MGMT:
|
||||
hostapd_mgmt_tx_cb(hapd, data->tx_status.data,
|
||||
data->tx_status.data_len,
|
||||
data->tx_status.stype,
|
||||
data->tx_status.ack);
|
||||
break;
|
||||
case WLAN_FC_TYPE_DATA:
|
||||
hostapd_tx_status(hapd, data->tx_status.dst,
|
||||
data->tx_status.data,
|
||||
data->tx_status.data_len,
|
||||
data->tx_status.ack);
|
||||
break;
|
||||
}
|
||||
break;
|
||||
case EVENT_RX_FROM_UNKNOWN:
|
||||
hostapd_rx_from_unknown_sta(hapd, data->rx_from_unknown.frame,
|
||||
data->rx_from_unknown.len);
|
||||
break;
|
||||
case EVENT_RX_MGMT:
|
||||
hostapd_mgmt_rx(hapd, &data->rx_mgmt);
|
||||
break;
|
||||
#endif /* NEED_AP_MLME */
|
||||
case EVENT_RX_PROBE_REQ:
|
||||
if (data->rx_probe_req.sa == NULL ||
|
||||
data->rx_probe_req.ie == NULL)
|
||||
break;
|
||||
hostapd_probe_req_rx(hapd, data->rx_probe_req.sa,
|
||||
data->rx_probe_req.ie,
|
||||
data->rx_probe_req.ie_len);
|
||||
break;
|
||||
case EVENT_NEW_STA:
|
||||
hostapd_event_new_sta(hapd, data->new_sta.addr);
|
||||
break;
|
||||
case EVENT_EAPOL_RX:
|
||||
hostapd_event_eapol_rx(hapd, data->eapol_rx.src,
|
||||
data->eapol_rx.data,
|
||||
data->eapol_rx.data_len);
|
||||
break;
|
||||
case EVENT_ASSOC:
|
||||
hostapd_notif_assoc(hapd, data->assoc_info.addr,
|
||||
data->assoc_info.req_ies,
|
||||
data->assoc_info.req_ies_len,
|
||||
data->assoc_info.reassoc);
|
||||
break;
|
||||
case EVENT_DISASSOC:
|
||||
if (data)
|
||||
hostapd_notif_disassoc(hapd, data->disassoc_info.addr);
|
||||
break;
|
||||
case EVENT_DEAUTH:
|
||||
if (data)
|
||||
hostapd_notif_disassoc(hapd, data->deauth_info.addr);
|
||||
break;
|
||||
case EVENT_STATION_LOW_ACK:
|
||||
if (!data)
|
||||
break;
|
||||
hostapd_event_sta_low_ack(hapd, data->low_ack.addr);
|
||||
break;
|
||||
default:
|
||||
wpa_printf(MSG_DEBUG, "Unknown event %d", event);
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
#endif /* HOSTAPD */
|
929
hostapd-0.8/src/ap/hostapd.c
Normal file
929
hostapd-0.8/src/ap/hostapd.c
Normal file
|
@ -0,0 +1,929 @@
|
|||
/*
|
||||
* 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.
|
||||
*/
|
||||
|
||||
#include "utils/includes.h"
|
||||
|
||||
#include "utils/common.h"
|
||||
#include "utils/eloop.h"
|
||||
#include "common/ieee802_11_defs.h"
|
||||
#include "radius/radius_client.h"
|
||||
#include "drivers/driver.h"
|
||||
#include "hostapd.h"
|
||||
#include "authsrv.h"
|
||||
#include "sta_info.h"
|
||||
#include "accounting.h"
|
||||
#include "ap_list.h"
|
||||
#include "beacon.h"
|
||||
#include "iapp.h"
|
||||
#include "ieee802_1x.h"
|
||||
#include "ieee802_11_auth.h"
|
||||
#include "vlan_init.h"
|
||||
#include "wpa_auth.h"
|
||||
#include "wps_hostapd.h"
|
||||
#include "hw_features.h"
|
||||
#include "wpa_auth_glue.h"
|
||||
#include "ap_drv_ops.h"
|
||||
#include "ap_config.h"
|
||||
#include "p2p_hostapd.h"
|
||||
|
||||
|
||||
static int hostapd_flush_old_stations(struct hostapd_data *hapd);
|
||||
static int hostapd_setup_encryption(char *iface, struct hostapd_data *hapd);
|
||||
|
||||
extern int wpa_debug_level;
|
||||
|
||||
|
||||
static void hostapd_reload_bss(struct hostapd_data *hapd)
|
||||
{
|
||||
#ifndef CONFIG_NO_RADIUS
|
||||
radius_client_reconfig(hapd->radius, hapd->conf->radius);
|
||||
#endif /* CONFIG_NO_RADIUS */
|
||||
|
||||
if (hostapd_setup_wpa_psk(hapd->conf)) {
|
||||
wpa_printf(MSG_ERROR, "Failed to re-configure WPA PSK "
|
||||
"after reloading configuration");
|
||||
}
|
||||
|
||||
if (hapd->conf->ieee802_1x || hapd->conf->wpa)
|
||||
hostapd_set_drv_ieee8021x(hapd, hapd->conf->iface, 1);
|
||||
else
|
||||
hostapd_set_drv_ieee8021x(hapd, hapd->conf->iface, 0);
|
||||
|
||||
if (hapd->conf->wpa && hapd->wpa_auth == NULL)
|
||||
hostapd_setup_wpa(hapd);
|
||||
else if (hapd->conf->wpa) {
|
||||
const u8 *wpa_ie;
|
||||
size_t wpa_ie_len;
|
||||
hostapd_reconfig_wpa(hapd);
|
||||
wpa_ie = wpa_auth_get_wpa_ie(hapd->wpa_auth, &wpa_ie_len);
|
||||
if (hostapd_set_generic_elem(hapd, wpa_ie, wpa_ie_len))
|
||||
wpa_printf(MSG_ERROR, "Failed to configure WPA IE for "
|
||||
"the kernel driver.");
|
||||
} else if (hapd->wpa_auth) {
|
||||
wpa_deinit(hapd->wpa_auth);
|
||||
hapd->wpa_auth = NULL;
|
||||
hostapd_set_privacy(hapd, 0);
|
||||
hostapd_setup_encryption(hapd->conf->iface, hapd);
|
||||
hostapd_set_generic_elem(hapd, (u8 *) "", 0);
|
||||
}
|
||||
|
||||
ieee802_11_set_beacon(hapd);
|
||||
hostapd_update_wps(hapd);
|
||||
|
||||
if (hapd->conf->ssid.ssid_set &&
|
||||
hostapd_set_ssid(hapd, (u8 *) hapd->conf->ssid.ssid,
|
||||
hapd->conf->ssid.ssid_len)) {
|
||||
wpa_printf(MSG_ERROR, "Could not set SSID for kernel driver");
|
||||
/* try to continue */
|
||||
}
|
||||
wpa_printf(MSG_DEBUG, "Reconfigured interface %s", hapd->conf->iface);
|
||||
}
|
||||
|
||||
|
||||
int hostapd_reload_config(struct hostapd_iface *iface)
|
||||
{
|
||||
struct hostapd_data *hapd = iface->bss[0];
|
||||
struct hostapd_config *newconf, *oldconf;
|
||||
size_t j;
|
||||
|
||||
if (iface->config_read_cb == NULL)
|
||||
return -1;
|
||||
newconf = iface->config_read_cb(iface->config_fname);
|
||||
if (newconf == NULL)
|
||||
return -1;
|
||||
|
||||
/*
|
||||
* Deauthenticate all stations since the new configuration may not
|
||||
* allow them to use the BSS anymore.
|
||||
*/
|
||||
for (j = 0; j < iface->num_bss; j++) {
|
||||
hostapd_flush_old_stations(iface->bss[j]);
|
||||
|
||||
#ifndef CONFIG_NO_RADIUS
|
||||
/* TODO: update dynamic data based on changed configuration
|
||||
* items (e.g., open/close sockets, etc.) */
|
||||
radius_client_flush(iface->bss[j]->radius, 0);
|
||||
#endif /* CONFIG_NO_RADIUS */
|
||||
}
|
||||
|
||||
oldconf = hapd->iconf;
|
||||
iface->conf = newconf;
|
||||
|
||||
for (j = 0; j < iface->num_bss; j++) {
|
||||
hapd = iface->bss[j];
|
||||
hapd->iconf = newconf;
|
||||
hapd->conf = &newconf->bss[j];
|
||||
hostapd_reload_bss(hapd);
|
||||
}
|
||||
|
||||
hostapd_config_free(oldconf);
|
||||
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
|
||||
static void hostapd_broadcast_key_clear_iface(struct hostapd_data *hapd,
|
||||
char *ifname)
|
||||
{
|
||||
int i;
|
||||
|
||||
for (i = 0; i < NUM_WEP_KEYS; i++) {
|
||||
if (hostapd_drv_set_key(ifname, hapd, WPA_ALG_NONE, NULL, i,
|
||||
0, NULL, 0, NULL, 0)) {
|
||||
wpa_printf(MSG_DEBUG, "Failed to clear default "
|
||||
"encryption keys (ifname=%s keyidx=%d)",
|
||||
ifname, i);
|
||||
}
|
||||
}
|
||||
#ifdef CONFIG_IEEE80211W
|
||||
if (hapd->conf->ieee80211w) {
|
||||
for (i = NUM_WEP_KEYS; i < NUM_WEP_KEYS + 2; i++) {
|
||||
if (hostapd_drv_set_key(ifname, hapd, WPA_ALG_NONE,
|
||||
NULL, i, 0, NULL,
|
||||
0, NULL, 0)) {
|
||||
wpa_printf(MSG_DEBUG, "Failed to clear "
|
||||
"default mgmt encryption keys "
|
||||
"(ifname=%s keyidx=%d)", ifname, i);
|
||||
}
|
||||
}
|
||||
}
|
||||
#endif /* CONFIG_IEEE80211W */
|
||||
}
|
||||
|
||||
|
||||
static int hostapd_broadcast_wep_clear(struct hostapd_data *hapd)
|
||||
{
|
||||
hostapd_broadcast_key_clear_iface(hapd, hapd->conf->iface);
|
||||
return 0;
|
||||
}
|
||||
|
||||
|
||||
static int hostapd_broadcast_wep_set(struct hostapd_data *hapd)
|
||||
{
|
||||
int errors = 0, idx;
|
||||
struct hostapd_ssid *ssid = &hapd->conf->ssid;
|
||||
|
||||
idx = ssid->wep.idx;
|
||||
if (ssid->wep.default_len &&
|
||||
hostapd_drv_set_key(hapd->conf->iface,
|
||||
hapd, WPA_ALG_WEP, broadcast_ether_addr, idx,
|
||||
1, NULL, 0, ssid->wep.key[idx],
|
||||
ssid->wep.len[idx])) {
|
||||
wpa_printf(MSG_WARNING, "Could not set WEP encryption.");
|
||||
errors++;
|
||||
}
|
||||
|
||||
if (ssid->dyn_vlan_keys) {
|
||||
size_t i;
|
||||
for (i = 0; i <= ssid->max_dyn_vlan_keys; i++) {
|
||||
const char *ifname;
|
||||
struct hostapd_wep_keys *key = ssid->dyn_vlan_keys[i];
|
||||
if (key == NULL)
|
||||
continue;
|
||||
ifname = hostapd_get_vlan_id_ifname(hapd->conf->vlan,
|
||||
i);
|
||||
if (ifname == NULL)
|
||||
continue;
|
||||
|
||||
idx = key->idx;
|
||||
if (hostapd_drv_set_key(ifname, hapd, WPA_ALG_WEP,
|
||||
broadcast_ether_addr, idx, 1,
|
||||
NULL, 0, key->key[idx],
|
||||
key->len[idx])) {
|
||||
wpa_printf(MSG_WARNING, "Could not set "
|
||||
"dynamic VLAN WEP encryption.");
|
||||
errors++;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
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);
|
||||
|
||||
iapp_deinit(hapd->iapp);
|
||||
hapd->iapp = NULL;
|
||||
accounting_deinit(hapd);
|
||||
hostapd_deinit_wpa(hapd);
|
||||
vlan_deinit(hapd);
|
||||
hostapd_acl_deinit(hapd);
|
||||
#ifndef CONFIG_NO_RADIUS
|
||||
radius_client_deinit(hapd->radius);
|
||||
hapd->radius = NULL;
|
||||
#endif /* CONFIG_NO_RADIUS */
|
||||
|
||||
hostapd_deinit_wps(hapd);
|
||||
|
||||
authsrv_deinit(hapd);
|
||||
|
||||
if (hapd->interface_added &&
|
||||
hostapd_if_remove(hapd, WPA_IF_AP_BSS, hapd->conf->iface)) {
|
||||
wpa_printf(MSG_WARNING, "Failed to remove BSS interface %s",
|
||||
hapd->conf->iface);
|
||||
}
|
||||
|
||||
os_free(hapd->probereq_cb);
|
||||
hapd->probereq_cb = NULL;
|
||||
|
||||
#ifdef CONFIG_P2P
|
||||
wpabuf_free(hapd->p2p_beacon_ie);
|
||||
hapd->p2p_beacon_ie = NULL;
|
||||
wpabuf_free(hapd->p2p_probe_resp_ie);
|
||||
hapd->p2p_probe_resp_ie = NULL;
|
||||
#endif /* CONFIG_P2P */
|
||||
}
|
||||
|
||||
|
||||
/**
|
||||
* hostapd_cleanup_iface_pre - Preliminary per-interface cleanup
|
||||
* @iface: Pointer to interface data
|
||||
*
|
||||
* This function is called before per-BSS data structures are deinitialized
|
||||
* with hostapd_cleanup().
|
||||
*/
|
||||
static void hostapd_cleanup_iface_pre(struct hostapd_iface *iface)
|
||||
{
|
||||
}
|
||||
|
||||
|
||||
/**
|
||||
* hostapd_cleanup_iface - Complete per-interface cleanup
|
||||
* @iface: Pointer to interface data
|
||||
*
|
||||
* This function is called after per-BSS data structures are deinitialized
|
||||
* with hostapd_cleanup().
|
||||
*/
|
||||
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_config_free(iface->conf);
|
||||
iface->conf = NULL;
|
||||
|
||||
os_free(iface->config_fname);
|
||||
os_free(iface->bss);
|
||||
os_free(iface);
|
||||
}
|
||||
|
||||
|
||||
static int hostapd_setup_encryption(char *iface, struct hostapd_data *hapd)
|
||||
{
|
||||
int i;
|
||||
|
||||
hostapd_broadcast_wep_set(hapd);
|
||||
|
||||
if (hapd->conf->ssid.wep.default_len) {
|
||||
hostapd_set_privacy(hapd, 1);
|
||||
return 0;
|
||||
}
|
||||
|
||||
for (i = 0; i < 4; i++) {
|
||||
if (hapd->conf->ssid.wep.key[i] &&
|
||||
hostapd_drv_set_key(iface, hapd, WPA_ALG_WEP, NULL, i,
|
||||
i == hapd->conf->ssid.wep.idx, NULL, 0,
|
||||
hapd->conf->ssid.wep.key[i],
|
||||
hapd->conf->ssid.wep.len[i])) {
|
||||
wpa_printf(MSG_WARNING, "Could not set WEP "
|
||||
"encryption.");
|
||||
return -1;
|
||||
}
|
||||
if (hapd->conf->ssid.wep.key[i] &&
|
||||
i == hapd->conf->ssid.wep.idx)
|
||||
hostapd_set_privacy(hapd, 1);
|
||||
}
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
|
||||
static int hostapd_flush_old_stations(struct hostapd_data *hapd)
|
||||
{
|
||||
int ret = 0;
|
||||
u8 addr[ETH_ALEN];
|
||||
|
||||
if (hostapd_drv_none(hapd) || hapd->drv_priv == NULL)
|
||||
return 0;
|
||||
|
||||
wpa_printf(MSG_DEBUG, "Flushing old station entries");
|
||||
if (hostapd_flush(hapd)) {
|
||||
wpa_printf(MSG_WARNING, "Could not connect to kernel driver.");
|
||||
ret = -1;
|
||||
}
|
||||
wpa_printf(MSG_DEBUG, "Deauthenticate all stations");
|
||||
os_memset(addr, 0xff, ETH_ALEN);
|
||||
hostapd_drv_sta_deauth(hapd, addr, WLAN_REASON_PREV_AUTH_NOT_VALID);
|
||||
hostapd_free_stas(hapd);
|
||||
|
||||
return ret;
|
||||
}
|
||||
|
||||
|
||||
/**
|
||||
* hostapd_validate_bssid_configuration - Validate BSSID configuration
|
||||
* @iface: Pointer to interface data
|
||||
* Returns: 0 on success, -1 on failure
|
||||
*
|
||||
* This function is used to validate that the configured BSSIDs are valid.
|
||||
*/
|
||||
static int hostapd_validate_bssid_configuration(struct hostapd_iface *iface)
|
||||
{
|
||||
u8 mask[ETH_ALEN] = { 0 };
|
||||
struct hostapd_data *hapd = iface->bss[0];
|
||||
unsigned int i = iface->conf->num_bss, bits = 0, j;
|
||||
int res;
|
||||
int auto_addr = 0;
|
||||
|
||||
if (hostapd_drv_none(hapd))
|
||||
return 0;
|
||||
|
||||
/* Generate BSSID mask that is large enough to cover the BSSIDs. */
|
||||
|
||||
/* Determine the bits necessary to cover the number of BSSIDs. */
|
||||
for (i--; i; i >>= 1)
|
||||
bits++;
|
||||
|
||||
/* Determine the bits necessary to any configured BSSIDs,
|
||||
if they are higher than the number of BSSIDs. */
|
||||
for (j = 0; j < iface->conf->num_bss; j++) {
|
||||
if (hostapd_mac_comp_empty(iface->conf->bss[j].bssid) == 0) {
|
||||
if (j)
|
||||
auto_addr++;
|
||||
continue;
|
||||
}
|
||||
|
||||
for (i = 0; i < ETH_ALEN; i++) {
|
||||
mask[i] |=
|
||||
iface->conf->bss[j].bssid[i] ^
|
||||
hapd->own_addr[i];
|
||||
}
|
||||
}
|
||||
|
||||
if (!auto_addr)
|
||||
goto skip_mask_ext;
|
||||
|
||||
for (i = 0; i < ETH_ALEN && mask[i] == 0; i++)
|
||||
;
|
||||
j = 0;
|
||||
if (i < ETH_ALEN) {
|
||||
j = (5 - i) * 8;
|
||||
|
||||
while (mask[i] != 0) {
|
||||
mask[i] >>= 1;
|
||||
j++;
|
||||
}
|
||||
}
|
||||
|
||||
if (bits < j)
|
||||
bits = j;
|
||||
|
||||
if (bits > 40) {
|
||||
wpa_printf(MSG_ERROR, "Too many bits in the BSSID mask (%u)",
|
||||
bits);
|
||||
return -1;
|
||||
}
|
||||
|
||||
os_memset(mask, 0xff, ETH_ALEN);
|
||||
j = bits / 8;
|
||||
for (i = 5; i > 5 - j; i--)
|
||||
mask[i] = 0;
|
||||
j = bits % 8;
|
||||
while (j--)
|
||||
mask[i] <<= 1;
|
||||
|
||||
skip_mask_ext:
|
||||
wpa_printf(MSG_DEBUG, "BSS count %lu, BSSID mask " MACSTR " (%d bits)",
|
||||
(unsigned long) iface->conf->num_bss, MAC2STR(mask), bits);
|
||||
|
||||
res = hostapd_valid_bss_mask(hapd, hapd->own_addr, mask);
|
||||
if (res == 0)
|
||||
return 0;
|
||||
|
||||
if (res < 0) {
|
||||
wpa_printf(MSG_ERROR, "Driver did not accept BSSID mask "
|
||||
MACSTR " for start address " MACSTR ".",
|
||||
MAC2STR(mask), MAC2STR(hapd->own_addr));
|
||||
return -1;
|
||||
}
|
||||
|
||||
if (!auto_addr)
|
||||
return 0;
|
||||
|
||||
for (i = 0; i < ETH_ALEN; i++) {
|
||||
if ((hapd->own_addr[i] & mask[i]) != hapd->own_addr[i]) {
|
||||
wpa_printf(MSG_ERROR, "Invalid BSSID mask " MACSTR
|
||||
" for start address " MACSTR ".",
|
||||
MAC2STR(mask), MAC2STR(hapd->own_addr));
|
||||
wpa_printf(MSG_ERROR, "Start address must be the "
|
||||
"first address in the block (i.e., addr "
|
||||
"AND mask == addr).");
|
||||
return -1;
|
||||
}
|
||||
}
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
|
||||
static int mac_in_conf(struct hostapd_config *conf, const void *a)
|
||||
{
|
||||
size_t i;
|
||||
|
||||
for (i = 0; i < conf->num_bss; i++) {
|
||||
if (hostapd_mac_comp(conf->bss[i].bssid, a) == 0) {
|
||||
return 1;
|
||||
}
|
||||
}
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
|
||||
|
||||
|
||||
/**
|
||||
* hostapd_setup_bss - Per-BSS setup (initialization)
|
||||
* @hapd: Pointer to BSS data
|
||||
* @first: Whether this BSS is the first BSS of an interface
|
||||
*
|
||||
* This function is used to initialize all per-BSS data structures and
|
||||
* resources. This gets called in a loop for each BSS when an interface is
|
||||
* initialized. Most of the modules that are initialized here will be
|
||||
* deinitialized in hostapd_cleanup().
|
||||
*/
|
||||
static int hostapd_setup_bss(struct hostapd_data *hapd, int first)
|
||||
{
|
||||
struct hostapd_bss_config *conf = hapd->conf;
|
||||
u8 ssid[HOSTAPD_MAX_SSID_LEN + 1];
|
||||
int ssid_len, set_ssid;
|
||||
char force_ifname[IFNAMSIZ];
|
||||
u8 if_addr[ETH_ALEN];
|
||||
|
||||
if (!first) {
|
||||
if (hostapd_mac_comp_empty(hapd->conf->bssid) == 0) {
|
||||
/* Allocate the next available BSSID. */
|
||||
do {
|
||||
inc_byte_array(hapd->own_addr, ETH_ALEN);
|
||||
} while (mac_in_conf(hapd->iconf, hapd->own_addr));
|
||||
} else {
|
||||
/* Allocate the configured BSSID. */
|
||||
os_memcpy(hapd->own_addr, hapd->conf->bssid, ETH_ALEN);
|
||||
|
||||
if (hostapd_mac_comp(hapd->own_addr,
|
||||
hapd->iface->bss[0]->own_addr) ==
|
||||
0) {
|
||||
wpa_printf(MSG_ERROR, "BSS '%s' may not have "
|
||||
"BSSID set to the MAC address of "
|
||||
"the radio", hapd->conf->iface);
|
||||
return -1;
|
||||
}
|
||||
}
|
||||
|
||||
hapd->interface_added = 1;
|
||||
if (hostapd_if_add(hapd->iface->bss[0], WPA_IF_AP_BSS,
|
||||
hapd->conf->iface, hapd->own_addr, hapd,
|
||||
&hapd->drv_priv, force_ifname, if_addr,
|
||||
hapd->conf->bridge[0] ? hapd->conf->bridge :
|
||||
NULL)) {
|
||||
wpa_printf(MSG_ERROR, "Failed to add BSS (BSSID="
|
||||
MACSTR ")", MAC2STR(hapd->own_addr));
|
||||
return -1;
|
||||
}
|
||||
}
|
||||
|
||||
if (conf->wmm_enabled < 0)
|
||||
conf->wmm_enabled = hapd->iconf->ieee80211n;
|
||||
|
||||
hostapd_flush_old_stations(hapd);
|
||||
hostapd_set_privacy(hapd, 0);
|
||||
|
||||
hostapd_broadcast_wep_clear(hapd);
|
||||
if (hostapd_setup_encryption(hapd->conf->iface, hapd))
|
||||
return -1;
|
||||
|
||||
/*
|
||||
* Fetch the SSID from the system and use it or,
|
||||
* if one was specified in the config file, verify they
|
||||
* match.
|
||||
*/
|
||||
ssid_len = hostapd_get_ssid(hapd, ssid, sizeof(ssid));
|
||||
if (ssid_len < 0) {
|
||||
wpa_printf(MSG_ERROR, "Could not read SSID from system");
|
||||
return -1;
|
||||
}
|
||||
if (conf->ssid.ssid_set) {
|
||||
/*
|
||||
* If SSID is specified in the config file and it differs
|
||||
* from what is being used then force installation of the
|
||||
* new SSID.
|
||||
*/
|
||||
set_ssid = (conf->ssid.ssid_len != (size_t) ssid_len ||
|
||||
os_memcmp(conf->ssid.ssid, ssid, ssid_len) != 0);
|
||||
} else {
|
||||
/*
|
||||
* No SSID in the config file; just use the one we got
|
||||
* from the system.
|
||||
*/
|
||||
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'",
|
||||
hapd->conf->iface, MAC2STR(hapd->own_addr),
|
||||
hapd->conf->ssid.ssid);
|
||||
}
|
||||
|
||||
if (hostapd_setup_wpa_psk(conf)) {
|
||||
wpa_printf(MSG_ERROR, "WPA-PSK setup failed.");
|
||||
return -1;
|
||||
}
|
||||
|
||||
/* 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,
|
||||
conf->ssid.ssid_len)) {
|
||||
wpa_printf(MSG_ERROR, "Could not set SSID for kernel driver");
|
||||
return -1;
|
||||
}
|
||||
|
||||
if (wpa_debug_level == MSG_MSGDUMP)
|
||||
conf->radius->msg_dumps = 1;
|
||||
#ifndef CONFIG_NO_RADIUS
|
||||
hapd->radius = radius_client_init(hapd, conf->radius);
|
||||
if (hapd->radius == NULL) {
|
||||
wpa_printf(MSG_ERROR, "RADIUS client initialization failed.");
|
||||
return -1;
|
||||
}
|
||||
#endif /* CONFIG_NO_RADIUS */
|
||||
|
||||
if (hostapd_acl_init(hapd)) {
|
||||
wpa_printf(MSG_ERROR, "ACL initialization failed.");
|
||||
return -1;
|
||||
}
|
||||
if (hostapd_init_wps(hapd, conf))
|
||||
return -1;
|
||||
|
||||
if (authsrv_init(hapd) < 0)
|
||||
return -1;
|
||||
|
||||
if (ieee802_1x_init(hapd)) {
|
||||
wpa_printf(MSG_ERROR, "IEEE 802.1X initialization failed.");
|
||||
return -1;
|
||||
}
|
||||
|
||||
if (hapd->conf->wpa && hostapd_setup_wpa(hapd))
|
||||
return -1;
|
||||
|
||||
if (accounting_init(hapd)) {
|
||||
wpa_printf(MSG_ERROR, "Accounting initialization failed.");
|
||||
return -1;
|
||||
}
|
||||
|
||||
if (hapd->conf->ieee802_11f &&
|
||||
(hapd->iapp = iapp_init(hapd, hapd->conf->iapp_iface)) == NULL) {
|
||||
wpa_printf(MSG_ERROR, "IEEE 802.11F (IAPP) initialization "
|
||||
"failed.");
|
||||
return -1;
|
||||
}
|
||||
|
||||
if (hapd->iface->ctrl_iface_init &&
|
||||
hapd->iface->ctrl_iface_init(hapd)) {
|
||||
wpa_printf(MSG_ERROR, "Failed to setup control interface");
|
||||
return -1;
|
||||
}
|
||||
|
||||
if (!hostapd_drv_none(hapd) && vlan_init(hapd)) {
|
||||
wpa_printf(MSG_ERROR, "VLAN initialization failed.");
|
||||
return -1;
|
||||
}
|
||||
|
||||
ieee802_11_set_beacon(hapd);
|
||||
|
||||
if (hapd->driver && hapd->driver->set_operstate)
|
||||
hapd->driver->set_operstate(hapd->drv_priv, 1);
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
|
||||
static void hostapd_tx_queue_params(struct hostapd_iface *iface)
|
||||
{
|
||||
struct hostapd_data *hapd = iface->bss[0];
|
||||
int i;
|
||||
struct hostapd_tx_queue_params *p;
|
||||
|
||||
for (i = 0; i < NUM_TX_QUEUES; i++) {
|
||||
p = &iface->conf->tx_queue[i];
|
||||
|
||||
if (hostapd_set_tx_queue_params(hapd, i, p->aifs, p->cwmin,
|
||||
p->cwmax, p->burst)) {
|
||||
wpa_printf(MSG_DEBUG, "Failed to set TX queue "
|
||||
"parameters for queue %d.", i);
|
||||
/* Continue anyway */
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
static int setup_interface(struct hostapd_iface *iface)
|
||||
{
|
||||
struct hostapd_data *hapd = iface->bss[0];
|
||||
size_t i;
|
||||
char country[4];
|
||||
|
||||
/*
|
||||
* Make sure that all BSSes get configured with a pointer to the same
|
||||
* driver interface.
|
||||
*/
|
||||
for (i = 1; i < iface->num_bss; i++) {
|
||||
iface->bss[i]->driver = hapd->driver;
|
||||
iface->bss[i]->drv_priv = hapd->drv_priv;
|
||||
}
|
||||
|
||||
if (hostapd_validate_bssid_configuration(iface))
|
||||
return -1;
|
||||
|
||||
if (hapd->iconf->country[0] && hapd->iconf->country[1]) {
|
||||
os_memcpy(country, hapd->iconf->country, 3);
|
||||
country[3] = '\0';
|
||||
if (hostapd_set_country(hapd, country) < 0) {
|
||||
wpa_printf(MSG_ERROR, "Failed to set country code");
|
||||
return -1;
|
||||
}
|
||||
}
|
||||
|
||||
if (hostapd_get_hw_features(iface)) {
|
||||
/* Not all drivers support this yet, so continue without hw
|
||||
* feature data. */
|
||||
} else {
|
||||
int ret = hostapd_select_hw_mode(iface);
|
||||
if (ret < 0) {
|
||||
wpa_printf(MSG_ERROR, "Could not select hw_mode and "
|
||||
"channel. (%d)", ret);
|
||||
return -1;
|
||||
}
|
||||
ret = hostapd_check_ht_capab(iface);
|
||||
if (ret < 0)
|
||||
return -1;
|
||||
if (ret == 1) {
|
||||
wpa_printf(MSG_DEBUG, "Interface initialization will "
|
||||
"be completed in a callback");
|
||||
return 0;
|
||||
}
|
||||
}
|
||||
return hostapd_setup_interface_complete(iface, 0);
|
||||
}
|
||||
|
||||
|
||||
int hostapd_setup_interface_complete(struct hostapd_iface *iface, int err)
|
||||
{
|
||||
struct hostapd_data *hapd = iface->bss[0];
|
||||
size_t j;
|
||||
u8 *prev_addr;
|
||||
|
||||
if (err) {
|
||||
wpa_printf(MSG_ERROR, "Interface initialization failed");
|
||||
eloop_terminate();
|
||||
return -1;
|
||||
}
|
||||
|
||||
wpa_printf(MSG_DEBUG, "Completing interface initialization");
|
||||
if (hapd->iconf->channel) {
|
||||
iface->freq = hostapd_hw_get_freq(hapd, hapd->iconf->channel);
|
||||
wpa_printf(MSG_DEBUG, "Mode: %s Channel: %d "
|
||||
"Frequency: %d MHz",
|
||||
hostapd_hw_mode_txt(hapd->iconf->hw_mode),
|
||||
hapd->iconf->channel, iface->freq);
|
||||
|
||||
if (hostapd_set_freq(hapd, hapd->iconf->hw_mode, iface->freq,
|
||||
hapd->iconf->channel,
|
||||
hapd->iconf->ieee80211n,
|
||||
hapd->iconf->secondary_channel)) {
|
||||
wpa_printf(MSG_ERROR, "Could not set channel for "
|
||||
"kernel driver");
|
||||
return -1;
|
||||
}
|
||||
}
|
||||
|
||||
if (iface->current_mode) {
|
||||
if (hostapd_prepare_rates(hapd, iface->current_mode)) {
|
||||
wpa_printf(MSG_ERROR, "Failed to prepare rates "
|
||||
"table.");
|
||||
hostapd_logger(hapd, NULL, HOSTAPD_MODULE_IEEE80211,
|
||||
HOSTAPD_LEVEL_WARNING,
|
||||
"Failed to prepare rates table.");
|
||||
return -1;
|
||||
}
|
||||
}
|
||||
|
||||
if (hapd->iconf->rts_threshold > -1 &&
|
||||
hostapd_set_rts(hapd, hapd->iconf->rts_threshold)) {
|
||||
wpa_printf(MSG_ERROR, "Could not set RTS threshold for "
|
||||
"kernel driver");
|
||||
return -1;
|
||||
}
|
||||
|
||||
if (hapd->iconf->fragm_threshold > -1 &&
|
||||
hostapd_set_frag(hapd, hapd->iconf->fragm_threshold)) {
|
||||
wpa_printf(MSG_ERROR, "Could not set fragmentation threshold "
|
||||
"for kernel driver");
|
||||
return -1;
|
||||
}
|
||||
|
||||
prev_addr = hapd->own_addr;
|
||||
|
||||
for (j = 0; j < iface->num_bss; j++) {
|
||||
hapd = iface->bss[j];
|
||||
if (j)
|
||||
os_memcpy(hapd->own_addr, prev_addr, ETH_ALEN);
|
||||
if (hostapd_setup_bss(hapd, j == 0))
|
||||
return -1;
|
||||
if (hostapd_mac_comp_empty(hapd->conf->bssid) == 0)
|
||||
prev_addr = hapd->own_addr;
|
||||
}
|
||||
|
||||
hostapd_tx_queue_params(iface);
|
||||
|
||||
ap_list_init(iface);
|
||||
|
||||
if (hostapd_driver_commit(hapd) < 0) {
|
||||
wpa_printf(MSG_ERROR, "%s: Failed to commit driver "
|
||||
"configuration", __func__);
|
||||
return -1;
|
||||
}
|
||||
|
||||
if (hapd->setup_complete_cb)
|
||||
hapd->setup_complete_cb(hapd->setup_complete_cb_ctx);
|
||||
|
||||
wpa_printf(MSG_DEBUG, "%s: Setup of interface done.",
|
||||
iface->bss[0]->conf->iface);
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
|
||||
/**
|
||||
* hostapd_setup_interface - Setup of an interface
|
||||
* @iface: Pointer to interface data.
|
||||
* Returns: 0 on success, -1 on failure
|
||||
*
|
||||
* Initializes the driver interface, validates the configuration,
|
||||
* and sets driver parameters based on the configuration.
|
||||
* Flushes old stations, sets the channel, encryption,
|
||||
* beacons, and WDS links based on the configuration.
|
||||
*/
|
||||
int hostapd_setup_interface(struct hostapd_iface *iface)
|
||||
{
|
||||
int ret;
|
||||
|
||||
ret = setup_interface(iface);
|
||||
if (ret) {
|
||||
wpa_printf(MSG_ERROR, "%s: Unable to setup interface.",
|
||||
iface->bss[0]->conf->iface);
|
||||
return -1;
|
||||
}
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
|
||||
/**
|
||||
* hostapd_alloc_bss_data - Allocate and initialize per-BSS data
|
||||
* @hapd_iface: Pointer to interface data
|
||||
* @conf: Pointer to per-interface configuration
|
||||
* @bss: Pointer to per-BSS configuration for this BSS
|
||||
* Returns: Pointer to allocated BSS data
|
||||
*
|
||||
* This function is used to allocate per-BSS data structure. This data will be
|
||||
* freed after hostapd_cleanup() is called for it during interface
|
||||
* deinitialization.
|
||||
*/
|
||||
struct hostapd_data *
|
||||
hostapd_alloc_bss_data(struct hostapd_iface *hapd_iface,
|
||||
struct hostapd_config *conf,
|
||||
struct hostapd_bss_config *bss)
|
||||
{
|
||||
struct hostapd_data *hapd;
|
||||
|
||||
hapd = os_zalloc(sizeof(*hapd));
|
||||
if (hapd == NULL)
|
||||
return NULL;
|
||||
|
||||
hapd->new_assoc_sta_cb = hostapd_new_assoc_sta;
|
||||
hapd->iconf = conf;
|
||||
hapd->conf = bss;
|
||||
hapd->iface = hapd_iface;
|
||||
hapd->driver = hapd->iconf->driver;
|
||||
|
||||
return hapd;
|
||||
}
|
||||
|
||||
|
||||
void hostapd_interface_deinit(struct hostapd_iface *iface)
|
||||
{
|
||||
size_t j;
|
||||
|
||||
if (iface == NULL)
|
||||
return;
|
||||
|
||||
hostapd_cleanup_iface_pre(iface);
|
||||
for (j = 0; j < iface->num_bss; j++) {
|
||||
struct hostapd_data *hapd = iface->bss[j];
|
||||
hostapd_free_stas(hapd);
|
||||
hostapd_flush_old_stations(hapd);
|
||||
hostapd_cleanup(hapd);
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
void hostapd_interface_free(struct hostapd_iface *iface)
|
||||
{
|
||||
size_t j;
|
||||
for (j = 0; j < iface->num_bss; j++)
|
||||
os_free(iface->bss[j]);
|
||||
hostapd_cleanup_iface(iface);
|
||||
}
|
||||
|
||||
|
||||
/**
|
||||
* hostapd_new_assoc_sta - Notify that a new station associated with the AP
|
||||
* @hapd: Pointer to BSS data
|
||||
* @sta: Pointer to the associated STA data
|
||||
* @reassoc: 1 to indicate this was a re-association; 0 = first association
|
||||
*
|
||||
* This function will be called whenever a station associates with the AP. It
|
||||
* can be called from ieee802_11.c for drivers that export MLME to hostapd and
|
||||
* from drv_callbacks.c based on driver events for drivers that take care of
|
||||
* management frames (IEEE 802.11 authentication and association) internally.
|
||||
*/
|
||||
void hostapd_new_assoc_sta(struct hostapd_data *hapd, struct sta_info *sta,
|
||||
int reassoc)
|
||||
{
|
||||
if (hapd->tkip_countermeasures) {
|
||||
hostapd_drv_sta_deauth(hapd, sta->addr,
|
||||
WLAN_REASON_MICHAEL_MIC_FAILURE);
|
||||
return;
|
||||
}
|
||||
|
||||
hostapd_prune_associations(hapd, sta->addr);
|
||||
|
||||
/* IEEE 802.11F (IAPP) */
|
||||
if (hapd->conf->ieee802_11f)
|
||||
iapp_new_station(hapd->iapp, sta);
|
||||
|
||||
#ifdef CONFIG_P2P
|
||||
if (sta->p2p_ie == NULL && !sta->no_p2p_set) {
|
||||
sta->no_p2p_set = 1;
|
||||
hapd->num_sta_no_p2p++;
|
||||
if (hapd->num_sta_no_p2p == 1)
|
||||
hostapd_p2p_non_p2p_sta_connected(hapd);
|
||||
}
|
||||
#endif /* CONFIG_P2P */
|
||||
|
||||
/* 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)
|
||||
accounting_sta_start(hapd, sta);
|
||||
|
||||
/* Start IEEE 802.1X authentication process for new stations */
|
||||
ieee802_1x_new_station(hapd, sta);
|
||||
if (reassoc) {
|
||||
if (sta->auth_alg != WLAN_AUTH_FT &&
|
||||
!(sta->flags & (WLAN_STA_WPS | WLAN_STA_MAYBE_WPS)))
|
||||
wpa_auth_sm_event(sta->wpa_sm, WPA_REAUTH);
|
||||
} else
|
||||
wpa_auth_sta_associated(hapd->wpa_auth, sta->wpa_sm);
|
||||
}
|
262
hostapd-0.8/src/ap/hostapd.h
Normal file
262
hostapd-0.8/src/ap/hostapd.h
Normal file
|
@ -0,0 +1,262 @@
|
|||
/*
|
||||
* 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.
|
||||
*/
|
||||
|
||||
#ifndef HOSTAPD_H
|
||||
#define HOSTAPD_H
|
||||
|
||||
#include "common/defs.h"
|
||||
|
||||
struct wpa_driver_ops;
|
||||
struct wpa_ctrl_dst;
|
||||
struct radius_server_data;
|
||||
struct upnp_wps_device_sm;
|
||||
struct hapd_interfaces;
|
||||
struct hostapd_data;
|
||||
struct sta_info;
|
||||
struct hostap_sta_driver_data;
|
||||
struct ieee80211_ht_capabilities;
|
||||
struct full_dynamic_vlan;
|
||||
enum wps_event;
|
||||
union wps_event_data;
|
||||
|
||||
struct hostapd_probereq_cb {
|
||||
int (*cb)(void *ctx, const u8 *sa, const u8 *ie, size_t ie_len);
|
||||
void *ctx;
|
||||
};
|
||||
|
||||
#define HOSTAPD_RATE_BASIC 0x00000001
|
||||
|
||||
struct hostapd_rate_data {
|
||||
int rate; /* rate in 100 kbps */
|
||||
int flags; /* HOSTAPD_RATE_ flags */
|
||||
};
|
||||
|
||||
struct hostapd_frame_info {
|
||||
u32 channel;
|
||||
u32 datarate;
|
||||
u32 ssi_signal;
|
||||
};
|
||||
|
||||
|
||||
/**
|
||||
* struct hostapd_data - hostapd per-BSS data structure
|
||||
*/
|
||||
struct hostapd_data {
|
||||
struct hostapd_iface *iface;
|
||||
struct hostapd_config *iconf;
|
||||
struct hostapd_bss_config *conf;
|
||||
int interface_added; /* virtual interface added for this BSS */
|
||||
|
||||
u8 own_addr[ETH_ALEN];
|
||||
|
||||
int num_sta; /* number of entries in sta_list */
|
||||
struct sta_info *sta_list; /* STA info list head */
|
||||
#define STA_HASH_SIZE 256
|
||||
#define STA_HASH(sta) (sta[5])
|
||||
struct sta_info *sta_hash[STA_HASH_SIZE];
|
||||
|
||||
/*
|
||||
* Bitfield for indicating which AIDs are allocated. Only AID values
|
||||
* 1-2007 are used and as such, the bit at index 0 corresponds to AID
|
||||
* 1.
|
||||
*/
|
||||
#define AID_WORDS ((2008 + 31) / 32)
|
||||
u32 sta_aid[AID_WORDS];
|
||||
|
||||
const struct wpa_driver_ops *driver;
|
||||
void *drv_priv;
|
||||
|
||||
void (*new_assoc_sta_cb)(struct hostapd_data *hapd,
|
||||
struct sta_info *sta, int reassoc);
|
||||
|
||||
void *msg_ctx; /* ctx for wpa_msg() calls */
|
||||
|
||||
struct radius_client_data *radius;
|
||||
u32 acct_session_id_hi, acct_session_id_lo;
|
||||
|
||||
struct iapp_data *iapp;
|
||||
|
||||
struct hostapd_cached_radius_acl *acl_cache;
|
||||
struct hostapd_acl_query_data *acl_queries;
|
||||
|
||||
struct wpa_authenticator *wpa_auth;
|
||||
struct eapol_authenticator *eapol_auth;
|
||||
|
||||
struct rsn_preauth_interface *preauth_iface;
|
||||
time_t michael_mic_failure;
|
||||
int michael_mic_failures;
|
||||
int tkip_countermeasures;
|
||||
|
||||
int ctrl_sock;
|
||||
struct wpa_ctrl_dst *ctrl_dst;
|
||||
|
||||
void *ssl_ctx;
|
||||
void *eap_sim_db_priv;
|
||||
struct radius_server_data *radius_srv;
|
||||
|
||||
int parameter_set_count;
|
||||
|
||||
#ifdef CONFIG_FULL_DYNAMIC_VLAN
|
||||
struct full_dynamic_vlan *full_dynamic_vlan;
|
||||
#endif /* CONFIG_FULL_DYNAMIC_VLAN */
|
||||
|
||||
struct l2_packet_data *l2;
|
||||
struct wps_context *wps;
|
||||
|
||||
struct wpabuf *wps_beacon_ie;
|
||||
struct wpabuf *wps_probe_resp_ie;
|
||||
#ifdef CONFIG_WPS
|
||||
unsigned int ap_pin_failures;
|
||||
struct upnp_wps_device_sm *wps_upnp;
|
||||
unsigned int ap_pin_lockout_time;
|
||||
#endif /* CONFIG_WPS */
|
||||
|
||||
struct hostapd_probereq_cb *probereq_cb;
|
||||
size_t num_probereq_cb;
|
||||
|
||||
void (*public_action_cb)(void *ctx, const u8 *buf, size_t len,
|
||||
int freq);
|
||||
void *public_action_cb_ctx;
|
||||
|
||||
int (*vendor_action_cb)(void *ctx, const u8 *buf, size_t len,
|
||||
int freq);
|
||||
void *vendor_action_cb_ctx;
|
||||
|
||||
void (*wps_reg_success_cb)(void *ctx, const u8 *mac_addr,
|
||||
const u8 *uuid_e);
|
||||
void *wps_reg_success_cb_ctx;
|
||||
|
||||
void (*wps_event_cb)(void *ctx, enum wps_event event,
|
||||
union wps_event_data *data);
|
||||
void *wps_event_cb_ctx;
|
||||
|
||||
void (*sta_authorized_cb)(void *ctx, const u8 *mac_addr,
|
||||
int authorized);
|
||||
void *sta_authorized_cb_ctx;
|
||||
|
||||
void (*setup_complete_cb)(void *ctx);
|
||||
void *setup_complete_cb_ctx;
|
||||
|
||||
#ifdef CONFIG_P2P
|
||||
struct p2p_data *p2p;
|
||||
struct p2p_group *p2p_group;
|
||||
struct wpabuf *p2p_beacon_ie;
|
||||
struct wpabuf *p2p_probe_resp_ie;
|
||||
|
||||
/* Number of non-P2P association stations */
|
||||
int num_sta_no_p2p;
|
||||
|
||||
/* Periodic NoA (used only when no non-P2P clients in the group) */
|
||||
int noa_enabled;
|
||||
int noa_start;
|
||||
int noa_duration;
|
||||
#endif /* CONFIG_P2P */
|
||||
};
|
||||
|
||||
|
||||
/**
|
||||
* struct hostapd_iface - hostapd per-interface data structure
|
||||
*/
|
||||
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;
|
||||
|
||||
size_t num_bss;
|
||||
struct hostapd_data **bss;
|
||||
|
||||
int num_ap; /* number of entries in ap_list */
|
||||
struct ap_info *ap_list; /* AP info list head */
|
||||
struct ap_info *ap_hash[STA_HASH_SIZE];
|
||||
struct ap_info *ap_iter_list;
|
||||
|
||||
unsigned int drv_flags;
|
||||
struct hostapd_hw_modes *hw_features;
|
||||
int num_hw_features;
|
||||
struct hostapd_hw_modes *current_mode;
|
||||
/* Rates that are currently used (i.e., filtered copy of
|
||||
* current_mode->channels */
|
||||
int num_rates;
|
||||
struct hostapd_rate_data *current_rates;
|
||||
int freq;
|
||||
|
||||
u16 hw_flags;
|
||||
|
||||
/* Number of associated Non-ERP stations (i.e., stations using 802.11b
|
||||
* in 802.11g BSS) */
|
||||
int num_sta_non_erp;
|
||||
|
||||
/* Number of associated stations that do not support Short Slot Time */
|
||||
int num_sta_no_short_slot_time;
|
||||
|
||||
/* Number of associated stations that do not support Short Preamble */
|
||||
int num_sta_no_short_preamble;
|
||||
|
||||
int olbc; /* Overlapping Legacy BSS Condition */
|
||||
|
||||
/* Number of HT associated stations that do not support greenfield */
|
||||
int num_sta_ht_no_gf;
|
||||
|
||||
/* Number of associated non-HT stations */
|
||||
int num_sta_no_ht;
|
||||
|
||||
/* Number of HT associated stations 20 MHz */
|
||||
int num_sta_ht_20mhz;
|
||||
|
||||
/* Overlapping BSS information */
|
||||
int olbc_ht;
|
||||
|
||||
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_reload_config(struct hostapd_iface *iface);
|
||||
struct hostapd_data *
|
||||
hostapd_alloc_bss_data(struct hostapd_iface *hapd_iface,
|
||||
struct hostapd_config *conf,
|
||||
struct hostapd_bss_config *bss);
|
||||
int hostapd_setup_interface(struct hostapd_iface *iface);
|
||||
int hostapd_setup_interface_complete(struct hostapd_iface *iface, int err);
|
||||
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);
|
||||
|
||||
/* utils.c */
|
||||
int hostapd_register_probereq_cb(struct hostapd_data *hapd,
|
||||
int (*cb)(void *ctx, const u8 *sa,
|
||||
const u8 *ie, size_t ie_len),
|
||||
void *ctx);
|
||||
void hostapd_prune_associations(struct hostapd_data *hapd, const u8 *addr);
|
||||
|
||||
/* drv_callbacks.c (TODO: move to somewhere else?) */
|
||||
int hostapd_notif_assoc(struct hostapd_data *hapd, const u8 *addr,
|
||||
const u8 *ie, size_t ielen, int reassoc);
|
||||
void hostapd_notif_disassoc(struct hostapd_data *hapd, const u8 *addr);
|
||||
void hostapd_event_sta_low_ack(struct hostapd_data *hapd, const u8 *addr);
|
||||
int hostapd_probe_req_rx(struct hostapd_data *hapd, const u8 *sa,
|
||||
const u8 *ie, size_t ie_len);
|
||||
|
||||
#endif /* HOSTAPD_H */
|
754
hostapd-0.8/src/ap/hw_features.c
Normal file
754
hostapd-0.8/src/ap/hw_features.c
Normal file
|
@ -0,0 +1,754 @@
|
|||
/*
|
||||
* 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>
|
||||
*
|
||||
* This program is free software; you can 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.
|
||||
*/
|
||||
|
||||
#include "utils/includes.h"
|
||||
|
||||
#include "utils/common.h"
|
||||
#include "utils/eloop.h"
|
||||
#include "common/ieee802_11_defs.h"
|
||||
#include "common/ieee802_11_common.h"
|
||||
#include "drivers/driver.h"
|
||||
#include "hostapd.h"
|
||||
#include "ap_config.h"
|
||||
#include "ap_drv_ops.h"
|
||||
#include "hw_features.h"
|
||||
|
||||
|
||||
void hostapd_free_hw_features(struct hostapd_hw_modes *hw_features,
|
||||
size_t num_hw_features)
|
||||
{
|
||||
size_t i;
|
||||
|
||||
if (hw_features == NULL)
|
||||
return;
|
||||
|
||||
for (i = 0; i < num_hw_features; i++) {
|
||||
os_free(hw_features[i].channels);
|
||||
os_free(hw_features[i].rates);
|
||||
}
|
||||
|
||||
os_free(hw_features);
|
||||
}
|
||||
|
||||
|
||||
int hostapd_get_hw_features(struct hostapd_iface *iface)
|
||||
{
|
||||
struct hostapd_data *hapd = iface->bss[0];
|
||||
int ret = 0, i, j;
|
||||
u16 num_modes, flags;
|
||||
struct hostapd_hw_modes *modes;
|
||||
|
||||
if (hostapd_drv_none(hapd))
|
||||
return -1;
|
||||
modes = hostapd_get_hw_feature_data(hapd, &num_modes, &flags);
|
||||
if (modes == NULL) {
|
||||
hostapd_logger(hapd, NULL, HOSTAPD_MODULE_IEEE80211,
|
||||
HOSTAPD_LEVEL_DEBUG,
|
||||
"Fetching hardware channel/rate support not "
|
||||
"supported.");
|
||||
return -1;
|
||||
}
|
||||
|
||||
iface->hw_flags = flags;
|
||||
|
||||
hostapd_free_hw_features(iface->hw_features, iface->num_hw_features);
|
||||
iface->hw_features = modes;
|
||||
iface->num_hw_features = num_modes;
|
||||
|
||||
for (i = 0; i < num_modes; i++) {
|
||||
struct hostapd_hw_modes *feature = &modes[i];
|
||||
/* set flag for channels we can use in current regulatory
|
||||
* domain */
|
||||
for (j = 0; j < feature->num_channels; j++) {
|
||||
/*
|
||||
* Disable all channels that are marked not to allow
|
||||
* IBSS operation or active scanning. In addition,
|
||||
* disable all channels that require radar detection,
|
||||
* since that (in addition to full DFS) is not yet
|
||||
* supported.
|
||||
*/
|
||||
if (feature->channels[j].flag &
|
||||
(HOSTAPD_CHAN_NO_IBSS |
|
||||
HOSTAPD_CHAN_PASSIVE_SCAN |
|
||||
HOSTAPD_CHAN_RADAR))
|
||||
feature->channels[j].flag |=
|
||||
HOSTAPD_CHAN_DISABLED;
|
||||
if (feature->channels[j].flag & HOSTAPD_CHAN_DISABLED)
|
||||
continue;
|
||||
wpa_printf(MSG_MSGDUMP, "Allowed channel: mode=%d "
|
||||
"chan=%d freq=%d MHz max_tx_power=%d dBm",
|
||||
feature->mode,
|
||||
feature->channels[j].chan,
|
||||
feature->channels[j].freq,
|
||||
feature->channels[j].max_tx_power);
|
||||
}
|
||||
}
|
||||
|
||||
return ret;
|
||||
}
|
||||
|
||||
|
||||
int hostapd_prepare_rates(struct hostapd_data *hapd,
|
||||
struct hostapd_hw_modes *mode)
|
||||
{
|
||||
int i, num_basic_rates = 0;
|
||||
int basic_rates_a[] = { 60, 120, 240, -1 };
|
||||
int basic_rates_b[] = { 10, 20, -1 };
|
||||
int basic_rates_g[] = { 10, 20, 55, 110, -1 };
|
||||
int *basic_rates;
|
||||
|
||||
if (hapd->iconf->basic_rates)
|
||||
basic_rates = hapd->iconf->basic_rates;
|
||||
else switch (mode->mode) {
|
||||
case HOSTAPD_MODE_IEEE80211A:
|
||||
basic_rates = basic_rates_a;
|
||||
break;
|
||||
case HOSTAPD_MODE_IEEE80211B:
|
||||
basic_rates = basic_rates_b;
|
||||
break;
|
||||
case HOSTAPD_MODE_IEEE80211G:
|
||||
basic_rates = basic_rates_g;
|
||||
break;
|
||||
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");
|
||||
}
|
||||
|
||||
os_free(hapd->iface->current_rates);
|
||||
hapd->iface->num_rates = 0;
|
||||
|
||||
hapd->iface->current_rates =
|
||||
os_zalloc(mode->num_rates * sizeof(struct hostapd_rate_data));
|
||||
if (!hapd->iface->current_rates) {
|
||||
wpa_printf(MSG_ERROR, "Failed to allocate memory for rate "
|
||||
"table.");
|
||||
return -1;
|
||||
}
|
||||
|
||||
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,
|
||||
mode->rates[i]))
|
||||
continue;
|
||||
|
||||
rate = &hapd->iface->current_rates[hapd->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++;
|
||||
}
|
||||
|
||||
if ((hapd->iface->num_rates == 0 || num_basic_rates == 0) &&
|
||||
(!hapd->iconf->ieee80211n || !hapd->iconf->require_ht)) {
|
||||
wpa_printf(MSG_ERROR, "No rates remaining in supported/basic "
|
||||
"rate sets (%d,%d).",
|
||||
hapd->iface->num_rates, num_basic_rates);
|
||||
return -1;
|
||||
}
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
|
||||
#ifdef CONFIG_IEEE80211N
|
||||
static int ieee80211n_allowed_ht40_channel_pair(struct hostapd_iface *iface)
|
||||
{
|
||||
int sec_chan, ok, j, first;
|
||||
int allowed[] = { 36, 44, 52, 60, 100, 108, 116, 124, 132, 149, 157,
|
||||
184, 192 };
|
||||
size_t k;
|
||||
|
||||
if (!iface->conf->secondary_channel)
|
||||
return 1; /* HT40 not used */
|
||||
|
||||
sec_chan = iface->conf->channel + iface->conf->secondary_channel * 4;
|
||||
wpa_printf(MSG_DEBUG, "HT40: control channel: %d "
|
||||
"secondary channel: %d",
|
||||
iface->conf->channel, sec_chan);
|
||||
|
||||
/* Verify that HT40 secondary channel is an allowed 20 MHz
|
||||
* channel */
|
||||
ok = 0;
|
||||
for (j = 0; j < iface->current_mode->num_channels; j++) {
|
||||
struct hostapd_channel_data *chan =
|
||||
&iface->current_mode->channels[j];
|
||||
if (!(chan->flag & HOSTAPD_CHAN_DISABLED) &&
|
||||
chan->chan == sec_chan) {
|
||||
ok = 1;
|
||||
break;
|
||||
}
|
||||
}
|
||||
if (!ok) {
|
||||
wpa_printf(MSG_ERROR, "HT40 secondary channel %d not allowed",
|
||||
sec_chan);
|
||||
return 0;
|
||||
}
|
||||
|
||||
/*
|
||||
* Verify that HT40 primary,secondary channel pair is allowed per
|
||||
* IEEE 802.11n Annex J. This is only needed for 5 GHz band since
|
||||
* 2.4 GHz rules allow all cases where the secondary channel fits into
|
||||
* the list of allowed channels (already checked above).
|
||||
*/
|
||||
if (iface->current_mode->mode != HOSTAPD_MODE_IEEE80211A)
|
||||
return 1;
|
||||
|
||||
if (iface->conf->secondary_channel > 0)
|
||||
first = iface->conf->channel;
|
||||
else
|
||||
first = sec_chan;
|
||||
|
||||
ok = 0;
|
||||
for (k = 0; k < sizeof(allowed) / sizeof(allowed[0]); k++) {
|
||||
if (first == allowed[k]) {
|
||||
ok = 1;
|
||||
break;
|
||||
}
|
||||
}
|
||||
if (!ok) {
|
||||
wpa_printf(MSG_ERROR, "HT40 channel pair (%d, %d) not allowed",
|
||||
iface->conf->channel,
|
||||
iface->conf->secondary_channel);
|
||||
return 0;
|
||||
}
|
||||
|
||||
return 1;
|
||||
}
|
||||
|
||||
|
||||
static void ieee80211n_switch_pri_sec(struct hostapd_iface *iface)
|
||||
{
|
||||
if (iface->conf->secondary_channel > 0) {
|
||||
iface->conf->channel += 4;
|
||||
iface->conf->secondary_channel = -1;
|
||||
} else {
|
||||
iface->conf->channel -= 4;
|
||||
iface->conf->secondary_channel = 1;
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
static void ieee80211n_get_pri_sec_chan(struct wpa_scan_res *bss,
|
||||
int *pri_chan, int *sec_chan)
|
||||
{
|
||||
struct ieee80211_ht_operation *oper;
|
||||
struct ieee802_11_elems elems;
|
||||
|
||||
*pri_chan = *sec_chan = 0;
|
||||
|
||||
ieee802_11_parse_elems((u8 *) (bss + 1), bss->ie_len, &elems, 0);
|
||||
if (elems.ht_operation &&
|
||||
elems.ht_operation_len >= sizeof(*oper)) {
|
||||
oper = (struct ieee80211_ht_operation *) elems.ht_operation;
|
||||
*pri_chan = oper->control_chan;
|
||||
if (oper->ht_param & HT_INFO_HT_PARAM_REC_TRANS_CHNL_WIDTH) {
|
||||
int sec = oper->ht_param &
|
||||
HT_INFO_HT_PARAM_SECONDARY_CHNL_OFF_MASK;
|
||||
if (sec == HT_INFO_HT_PARAM_SECONDARY_CHNL_ABOVE)
|
||||
*sec_chan = *pri_chan + 4;
|
||||
else if (sec == HT_INFO_HT_PARAM_SECONDARY_CHNL_BELOW)
|
||||
*sec_chan = *pri_chan - 4;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
static int ieee80211n_check_40mhz_5g(struct hostapd_iface *iface,
|
||||
struct wpa_scan_results *scan_res)
|
||||
{
|
||||
int pri_chan, sec_chan, pri_freq, sec_freq, pri_bss, sec_bss;
|
||||
int bss_pri_chan, bss_sec_chan;
|
||||
size_t i;
|
||||
int match;
|
||||
|
||||
pri_chan = iface->conf->channel;
|
||||
sec_chan = iface->conf->secondary_channel * 4;
|
||||
pri_freq = hostapd_hw_get_freq(iface->bss[0], pri_chan);
|
||||
if (iface->conf->secondary_channel > 0)
|
||||
sec_freq = pri_freq + 20;
|
||||
else
|
||||
sec_freq = pri_freq - 20;
|
||||
|
||||
/*
|
||||
* Switch PRI/SEC channels if Beacons were detected on selected SEC
|
||||
* channel, but not on selected PRI channel.
|
||||
*/
|
||||
pri_bss = sec_bss = 0;
|
||||
for (i = 0; i < scan_res->num; i++) {
|
||||
struct wpa_scan_res *bss = scan_res->res[i];
|
||||
if (bss->freq == pri_freq)
|
||||
pri_bss++;
|
||||
else if (bss->freq == sec_freq)
|
||||
sec_bss++;
|
||||
}
|
||||
if (sec_bss && !pri_bss) {
|
||||
wpa_printf(MSG_INFO, "Switch own primary and secondary "
|
||||
"channel to get secondary channel with no Beacons "
|
||||
"from other BSSes");
|
||||
ieee80211n_switch_pri_sec(iface);
|
||||
}
|
||||
|
||||
/*
|
||||
* Match PRI/SEC channel with any existing HT40 BSS on the same
|
||||
* channels that we are about to use (if already mixed order in
|
||||
* existing BSSes, use own preference).
|
||||
*/
|
||||
match = 0;
|
||||
for (i = 0; i < scan_res->num; i++) {
|
||||
struct wpa_scan_res *bss = scan_res->res[i];
|
||||
ieee80211n_get_pri_sec_chan(bss, &bss_pri_chan, &bss_sec_chan);
|
||||
if (pri_chan == bss_pri_chan &&
|
||||
sec_chan == bss_sec_chan) {
|
||||
match = 1;
|
||||
break;
|
||||
}
|
||||
}
|
||||
if (!match) {
|
||||
for (i = 0; i < scan_res->num; i++) {
|
||||
struct wpa_scan_res *bss = scan_res->res[i];
|
||||
ieee80211n_get_pri_sec_chan(bss, &bss_pri_chan,
|
||||
&bss_sec_chan);
|
||||
if (pri_chan == bss_sec_chan &&
|
||||
sec_chan == bss_pri_chan) {
|
||||
wpa_printf(MSG_INFO, "Switch own primary and "
|
||||
"secondary channel due to BSS "
|
||||
"overlap with " MACSTR,
|
||||
MAC2STR(bss->bssid));
|
||||
ieee80211n_switch_pri_sec(iface);
|
||||
break;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
return 1;
|
||||
}
|
||||
|
||||
|
||||
static int ieee80211n_check_40mhz_2g4(struct hostapd_iface *iface,
|
||||
struct wpa_scan_results *scan_res)
|
||||
{
|
||||
int pri_freq, sec_freq;
|
||||
int affected_start, affected_end;
|
||||
size_t i;
|
||||
|
||||
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);
|
||||
for (i = 0; i < scan_res->num; i++) {
|
||||
struct wpa_scan_res *bss = scan_res->res[i];
|
||||
int pri = bss->freq;
|
||||
int sec = pri;
|
||||
int sec_chan, pri_chan;
|
||||
|
||||
ieee80211n_get_pri_sec_chan(bss, &pri_chan, &sec_chan);
|
||||
|
||||
if (sec_chan) {
|
||||
if (sec_chan < pri_chan)
|
||||
sec = pri - 20;
|
||||
else
|
||||
sec = pri + 20;
|
||||
}
|
||||
|
||||
if ((pri < affected_start || pri > affected_end) &&
|
||||
(sec < affected_start || sec > affected_end))
|
||||
continue; /* not within affected channel range */
|
||||
|
||||
wpa_printf(MSG_DEBUG, "Neighboring BSS: " MACSTR
|
||||
" freq=%d pri=%d sec=%d",
|
||||
MAC2STR(bss->bssid), bss->freq, pri_chan, sec_chan);
|
||||
|
||||
if (sec_chan) {
|
||||
if (pri_freq != pri || sec_freq != sec) {
|
||||
wpa_printf(MSG_DEBUG, "40 MHz pri/sec "
|
||||
"mismatch with BSS " MACSTR
|
||||
" <%d,%d> (chan=%d%c) vs. <%d,%d>",
|
||||
MAC2STR(bss->bssid),
|
||||
pri, sec, pri_chan,
|
||||
sec > pri ? '+' : '-',
|
||||
pri_freq, sec_freq);
|
||||
return 0;
|
||||
}
|
||||
}
|
||||
|
||||
/* TODO: 40 MHz intolerant */
|
||||
}
|
||||
|
||||
return 1;
|
||||
}
|
||||
|
||||
|
||||
static void wpa_scan_results_free(struct wpa_scan_results *res)
|
||||
{
|
||||
size_t i;
|
||||
|
||||
if (res == NULL)
|
||||
return;
|
||||
|
||||
for (i = 0; i < res->num; i++)
|
||||
os_free(res->res[i]);
|
||||
os_free(res->res);
|
||||
os_free(res);
|
||||
}
|
||||
|
||||
|
||||
static void ieee80211n_check_scan(struct hostapd_iface *iface)
|
||||
{
|
||||
struct wpa_scan_results *scan_res;
|
||||
int oper40;
|
||||
int res;
|
||||
|
||||
/* Check list of neighboring BSSes (from scan) to see whether 40 MHz is
|
||||
* allowed per IEEE 802.11n/D7.0, 11.14.3.2 */
|
||||
|
||||
iface->scan_cb = NULL;
|
||||
|
||||
scan_res = hostapd_driver_get_scan_results(iface->bss[0]);
|
||||
if (scan_res == NULL) {
|
||||
hostapd_setup_interface_complete(iface, 1);
|
||||
return;
|
||||
}
|
||||
|
||||
if (iface->current_mode->mode == HOSTAPD_MODE_IEEE80211A)
|
||||
oper40 = ieee80211n_check_40mhz_5g(iface, scan_res);
|
||||
else
|
||||
oper40 = ieee80211n_check_40mhz_2g4(iface, scan_res);
|
||||
wpa_scan_results_free(scan_res);
|
||||
|
||||
if (!oper40) {
|
||||
wpa_printf(MSG_INFO, "20/40 MHz operation not permitted on "
|
||||
"channel pri=%d sec=%d based on overlapping BSSes",
|
||||
iface->conf->channel,
|
||||
iface->conf->channel +
|
||||
iface->conf->secondary_channel * 4);
|
||||
iface->conf->secondary_channel = 0;
|
||||
iface->conf->ht_capab &= ~HT_CAP_INFO_SUPP_CHANNEL_WIDTH_SET;
|
||||
}
|
||||
|
||||
res = ieee80211n_allowed_ht40_channel_pair(iface);
|
||||
hostapd_setup_interface_complete(iface, !res);
|
||||
}
|
||||
|
||||
|
||||
static int ieee80211n_check_40mhz(struct hostapd_iface *iface)
|
||||
{
|
||||
struct wpa_driver_scan_params params;
|
||||
|
||||
if (!iface->conf->secondary_channel)
|
||||
return 0; /* HT40 not used */
|
||||
|
||||
wpa_printf(MSG_DEBUG, "Scan for neighboring BSSes prior to enabling "
|
||||
"40 MHz channel");
|
||||
os_memset(¶ms, 0, sizeof(params));
|
||||
/* TODO: scan only the needed frequency */
|
||||
if (hostapd_driver_scan(iface->bss[0], ¶ms) < 0) {
|
||||
wpa_printf(MSG_ERROR, "Failed to request a scan of "
|
||||
"neighboring BSSes");
|
||||
|
||||
//DRIVER_RTW Modify
|
||||
//return -1;
|
||||
return 0;//ignore this error
|
||||
}
|
||||
|
||||
iface->scan_cb = ieee80211n_check_scan;
|
||||
return 1;
|
||||
}
|
||||
|
||||
|
||||
static int ieee80211n_supported_ht_capab(struct hostapd_iface *iface)
|
||||
{
|
||||
u16 hw = iface->current_mode->ht_capab;
|
||||
u16 conf = iface->conf->ht_capab;
|
||||
|
||||
if ((conf & HT_CAP_INFO_LDPC_CODING_CAP) &&
|
||||
!(hw & HT_CAP_INFO_LDPC_CODING_CAP)) {
|
||||
wpa_printf(MSG_ERROR, "Driver does not support configured "
|
||||
"HT capability [LDPC]");
|
||||
return 0;
|
||||
}
|
||||
|
||||
if ((conf & HT_CAP_INFO_SUPP_CHANNEL_WIDTH_SET) &&
|
||||
!(hw & HT_CAP_INFO_SUPP_CHANNEL_WIDTH_SET)) {
|
||||
wpa_printf(MSG_ERROR, "Driver does not support configured "
|
||||
"HT capability [HT40*]");
|
||||
return 0;
|
||||
}
|
||||
|
||||
if ((conf & HT_CAP_INFO_SMPS_MASK) != (hw & HT_CAP_INFO_SMPS_MASK) &&
|
||||
(conf & HT_CAP_INFO_SMPS_MASK) != HT_CAP_INFO_SMPS_DISABLED) {
|
||||
wpa_printf(MSG_ERROR, "Driver does not support configured "
|
||||
"HT capability [SMPS-*]");
|
||||
return 0;
|
||||
}
|
||||
|
||||
if ((conf & HT_CAP_INFO_GREEN_FIELD) &&
|
||||
!(hw & HT_CAP_INFO_GREEN_FIELD)) {
|
||||
wpa_printf(MSG_ERROR, "Driver does not support configured "
|
||||
"HT capability [GF]");
|
||||
return 0;
|
||||
}
|
||||
|
||||
if ((conf & HT_CAP_INFO_SHORT_GI20MHZ) &&
|
||||
!(hw & HT_CAP_INFO_SHORT_GI20MHZ)) {
|
||||
wpa_printf(MSG_ERROR, "Driver does not support configured "
|
||||
"HT capability [SHORT-GI-20]");
|
||||
return 0;
|
||||
}
|
||||
|
||||
if ((conf & HT_CAP_INFO_SHORT_GI40MHZ) &&
|
||||
!(hw & HT_CAP_INFO_SHORT_GI40MHZ)) {
|
||||
wpa_printf(MSG_ERROR, "Driver does not support configured "
|
||||
"HT capability [SHORT-GI-40]");
|
||||
return 0;
|
||||
}
|
||||
|
||||
if ((conf & HT_CAP_INFO_TX_STBC) && !(hw & HT_CAP_INFO_TX_STBC)) {
|
||||
wpa_printf(MSG_ERROR, "Driver does not support configured "
|
||||
"HT capability [TX-STBC]");
|
||||
return 0;
|
||||
}
|
||||
|
||||
if ((conf & HT_CAP_INFO_RX_STBC_MASK) >
|
||||
(hw & HT_CAP_INFO_RX_STBC_MASK)) {
|
||||
wpa_printf(MSG_ERROR, "Driver does not support configured "
|
||||
"HT capability [RX-STBC*]");
|
||||
return 0;
|
||||
}
|
||||
|
||||
if ((conf & HT_CAP_INFO_DELAYED_BA) &&
|
||||
!(hw & HT_CAP_INFO_DELAYED_BA)) {
|
||||
wpa_printf(MSG_ERROR, "Driver does not support configured "
|
||||
"HT capability [DELAYED-BA]");
|
||||
return 0;
|
||||
}
|
||||
|
||||
if ((conf & HT_CAP_INFO_MAX_AMSDU_SIZE) &&
|
||||
!(hw & HT_CAP_INFO_MAX_AMSDU_SIZE)) {
|
||||
wpa_printf(MSG_ERROR, "Driver does not support configured "
|
||||
"HT capability [MAX-AMSDU-7935]");
|
||||
return 0;
|
||||
}
|
||||
|
||||
if ((conf & HT_CAP_INFO_DSSS_CCK40MHZ) &&
|
||||
!(hw & HT_CAP_INFO_DSSS_CCK40MHZ)) {
|
||||
wpa_printf(MSG_ERROR, "Driver does not support configured "
|
||||
"HT capability [DSSS_CCK-40]");
|
||||
return 0;
|
||||
}
|
||||
|
||||
if ((conf & HT_CAP_INFO_PSMP_SUPP) && !(hw & HT_CAP_INFO_PSMP_SUPP)) {
|
||||
wpa_printf(MSG_ERROR, "Driver does not support configured "
|
||||
"HT capability [PSMP]");
|
||||
return 0;
|
||||
}
|
||||
|
||||
if ((conf & HT_CAP_INFO_LSIG_TXOP_PROTECT_SUPPORT) &&
|
||||
!(hw & HT_CAP_INFO_LSIG_TXOP_PROTECT_SUPPORT)) {
|
||||
wpa_printf(MSG_ERROR, "Driver does not support configured "
|
||||
"HT capability [LSIG-TXOP-PROT]");
|
||||
return 0;
|
||||
}
|
||||
|
||||
return 1;
|
||||
}
|
||||
|
||||
#endif /* CONFIG_IEEE80211N */
|
||||
|
||||
|
||||
int hostapd_check_ht_capab(struct hostapd_iface *iface)
|
||||
{
|
||||
#ifdef CONFIG_IEEE80211N
|
||||
int ret;
|
||||
if (!iface->conf->ieee80211n)
|
||||
return 0;
|
||||
if (!ieee80211n_supported_ht_capab(iface))
|
||||
return -1;
|
||||
ret = ieee80211n_check_40mhz(iface);
|
||||
if (ret)
|
||||
return ret;
|
||||
if (!ieee80211n_allowed_ht40_channel_pair(iface))
|
||||
return -1;
|
||||
#endif /* CONFIG_IEEE80211N */
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
|
||||
/**
|
||||
* hostapd_select_hw_mode - Select the hardware mode
|
||||
* @iface: Pointer to interface data.
|
||||
* Returns: 0 on success, -1 on failure
|
||||
*
|
||||
* Sets up the hardware mode, channel, rates, and passive scanning
|
||||
* based on the configuration.
|
||||
*/
|
||||
int hostapd_select_hw_mode(struct hostapd_iface *iface)
|
||||
{
|
||||
int i, j, ok;
|
||||
|
||||
if (iface->num_hw_features < 1)
|
||||
return -1;
|
||||
|
||||
iface->current_mode = NULL;
|
||||
for (i = 0; i < iface->num_hw_features; i++) {
|
||||
struct hostapd_hw_modes *mode = &iface->hw_features[i];
|
||||
if (mode->mode == iface->conf->hw_mode) {
|
||||
iface->current_mode = mode;
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
if (iface->current_mode == NULL) {
|
||||
wpa_printf(MSG_ERROR, "Hardware does not support configured "
|
||||
"mode");
|
||||
hostapd_logger(iface->bss[0], NULL, HOSTAPD_MODULE_IEEE80211,
|
||||
HOSTAPD_LEVEL_WARNING,
|
||||
"Hardware does not support configured mode "
|
||||
"(%d)", (int) iface->conf->hw_mode);
|
||||
return -1;
|
||||
}
|
||||
|
||||
ok = 0;
|
||||
for (j = 0; j < iface->current_mode->num_channels; j++) {
|
||||
struct hostapd_channel_data *chan =
|
||||
&iface->current_mode->channels[j];
|
||||
if (!(chan->flag & HOSTAPD_CHAN_DISABLED) &&
|
||||
(chan->chan == iface->conf->channel)) {
|
||||
ok = 1;
|
||||
break;
|
||||
}
|
||||
}
|
||||
if (ok && iface->conf->secondary_channel) {
|
||||
int sec_ok = 0;
|
||||
int sec_chan = iface->conf->channel +
|
||||
iface->conf->secondary_channel * 4;
|
||||
for (j = 0; j < iface->current_mode->num_channels; j++) {
|
||||
struct hostapd_channel_data *chan =
|
||||
&iface->current_mode->channels[j];
|
||||
if (!(chan->flag & HOSTAPD_CHAN_DISABLED) &&
|
||||
(chan->chan == sec_chan)) {
|
||||
sec_ok = 1;
|
||||
break;
|
||||
}
|
||||
}
|
||||
if (!sec_ok) {
|
||||
hostapd_logger(iface->bss[0], NULL,
|
||||
HOSTAPD_MODULE_IEEE80211,
|
||||
HOSTAPD_LEVEL_WARNING,
|
||||
"Configured HT40 secondary channel "
|
||||
"(%d) not found from the channel list "
|
||||
"of current mode (%d) %s",
|
||||
sec_chan, iface->current_mode->mode,
|
||||
hostapd_hw_mode_txt(
|
||||
iface->current_mode->mode));
|
||||
ok = 0;
|
||||
}
|
||||
}
|
||||
if (iface->conf->channel == 0) {
|
||||
/* TODO: could request a scan of neighboring BSSes and select
|
||||
* the channel automatically */
|
||||
wpa_printf(MSG_ERROR, "Channel not configured "
|
||||
"(hw_mode/channel in hostapd.conf)");
|
||||
return -1;
|
||||
}
|
||||
if (ok == 0 && iface->conf->channel != 0) {
|
||||
hostapd_logger(iface->bss[0], NULL,
|
||||
HOSTAPD_MODULE_IEEE80211,
|
||||
HOSTAPD_LEVEL_WARNING,
|
||||
"Configured channel (%d) not found from the "
|
||||
"channel list of current mode (%d) %s",
|
||||
iface->conf->channel,
|
||||
iface->current_mode->mode,
|
||||
hostapd_hw_mode_txt(iface->current_mode->mode));
|
||||
iface->current_mode = NULL;
|
||||
}
|
||||
|
||||
if (iface->current_mode == NULL) {
|
||||
hostapd_logger(iface->bss[0], NULL, HOSTAPD_MODULE_IEEE80211,
|
||||
HOSTAPD_LEVEL_WARNING,
|
||||
"Hardware does not support configured channel");
|
||||
return -1;
|
||||
}
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
|
||||
const char * hostapd_hw_mode_txt(int mode)
|
||||
{
|
||||
switch (mode) {
|
||||
case HOSTAPD_MODE_IEEE80211A:
|
||||
return "IEEE 802.11a";
|
||||
case HOSTAPD_MODE_IEEE80211B:
|
||||
return "IEEE 802.11b";
|
||||
case HOSTAPD_MODE_IEEE80211G:
|
||||
return "IEEE 802.11g";
|
||||
default:
|
||||
return "UNKNOWN";
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
int hostapd_hw_get_freq(struct hostapd_data *hapd, int chan)
|
||||
{
|
||||
int i;
|
||||
|
||||
if (!hapd->iface->current_mode)
|
||||
return 0;
|
||||
|
||||
for (i = 0; i < hapd->iface->current_mode->num_channels; i++) {
|
||||
struct hostapd_channel_data *ch =
|
||||
&hapd->iface->current_mode->channels[i];
|
||||
if (ch->chan == chan)
|
||||
return ch->freq;
|
||||
}
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
|
||||
int hostapd_hw_get_channel(struct hostapd_data *hapd, int freq)
|
||||
{
|
||||
int i;
|
||||
|
||||
if (!hapd->iface->current_mode)
|
||||
return 0;
|
||||
|
||||
for (i = 0; i < hapd->iface->current_mode->num_channels; i++) {
|
||||
struct hostapd_channel_data *ch =
|
||||
&hapd->iface->current_mode->channels[i];
|
||||
if (ch->freq == freq)
|
||||
return ch->chan;
|
||||
}
|
||||
|
||||
return 0;
|
||||
}
|
70
hostapd-0.8/src/ap/hw_features.h
Normal file
70
hostapd-0.8/src/ap/hw_features.h
Normal file
|
@ -0,0 +1,70 @@
|
|||
/*
|
||||
* hostapd / Hardware feature query and different modes
|
||||
* Copyright 2002-2003, 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.
|
||||
*/
|
||||
|
||||
#ifndef HW_FEATURES_H
|
||||
#define HW_FEATURES_H
|
||||
|
||||
#ifdef NEED_AP_MLME
|
||||
void hostapd_free_hw_features(struct hostapd_hw_modes *hw_features,
|
||||
size_t num_hw_features);
|
||||
int hostapd_get_hw_features(struct hostapd_iface *iface);
|
||||
int hostapd_select_hw_mode(struct hostapd_iface *iface);
|
||||
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,
|
||||
struct hostapd_hw_modes *mode);
|
||||
#else /* NEED_AP_MLME */
|
||||
static inline void
|
||||
hostapd_free_hw_features(struct hostapd_hw_modes *hw_features,
|
||||
size_t num_hw_features)
|
||||
{
|
||||
}
|
||||
|
||||
static inline int hostapd_get_hw_features(struct hostapd_iface *iface)
|
||||
{
|
||||
return -1;
|
||||
}
|
||||
|
||||
static inline int hostapd_select_hw_mode(struct hostapd_iface *iface)
|
||||
{
|
||||
return -1;
|
||||
}
|
||||
|
||||
static inline const char * hostapd_hw_mode_txt(int mode)
|
||||
{
|
||||
return NULL;
|
||||
}
|
||||
|
||||
static inline int hostapd_hw_get_freq(struct hostapd_data *hapd, int chan)
|
||||
{
|
||||
return -1;
|
||||
}
|
||||
|
||||
static inline int hostapd_check_ht_capab(struct hostapd_iface *iface)
|
||||
{
|
||||
return 0;
|
||||
}
|
||||
|
||||
static inline int hostapd_prepare_rates(struct hostapd_data *hapd,
|
||||
struct hostapd_hw_modes *mode)
|
||||
{
|
||||
return 0;
|
||||
}
|
||||
|
||||
#endif /* NEED_AP_MLME */
|
||||
|
||||
#endif /* HW_FEATURES_H */
|
535
hostapd-0.8/src/ap/iapp.c
Normal file
535
hostapd-0.8/src/ap/iapp.c
Normal file
|
@ -0,0 +1,535 @@
|
|||
/*
|
||||
* 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.
|
||||
*
|
||||
* 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
|
||||
* using some other mechanism for AP-to-AP communication than extending the
|
||||
* implementation here.
|
||||
*/
|
||||
|
||||
/* TODO:
|
||||
* Level 1: no administrative or security support
|
||||
* (e.g., static BSSID to IP address mapping in each AP)
|
||||
* Level 2: support for dynamic mapping of BSSID to IP address
|
||||
* Level 3: support for encryption and authentication of IAPP messages
|
||||
* - add support for MOVE-notify and MOVE-response (this requires support for
|
||||
* finding out IP address for previous AP using RADIUS)
|
||||
* - add support for Send- and ACK-Security-Block to speedup IEEE 802.1X during
|
||||
* reassociation to another AP
|
||||
* - implement counters etc. for IAPP MIB
|
||||
* - verify endianness of fields in IAPP messages; are they big-endian as
|
||||
* used here?
|
||||
* - RADIUS connection for AP registration and BSSID to IP address mapping
|
||||
* - TCP connection for IAPP MOVE, CACHE
|
||||
* - broadcast ESP for IAPP ADD-notify
|
||||
* - ESP for IAPP MOVE messages
|
||||
* - security block sending/processing
|
||||
* - IEEE 802.11 context transfer
|
||||
*/
|
||||
|
||||
#include "utils/includes.h"
|
||||
#include <net/if.h>
|
||||
#include <sys/ioctl.h>
|
||||
#ifdef USE_KERNEL_HEADERS
|
||||
#include <linux/if_packet.h>
|
||||
#else /* USE_KERNEL_HEADERS */
|
||||
#include <netpacket/packet.h>
|
||||
#endif /* USE_KERNEL_HEADERS */
|
||||
|
||||
#include "utils/common.h"
|
||||
#include "utils/eloop.h"
|
||||
#include "common/ieee802_11_defs.h"
|
||||
#include "hostapd.h"
|
||||
#include "ap_config.h"
|
||||
#include "ieee802_11.h"
|
||||
#include "sta_info.h"
|
||||
#include "iapp.h"
|
||||
|
||||
|
||||
#define IAPP_MULTICAST "224.0.1.178"
|
||||
#define IAPP_UDP_PORT 3517
|
||||
#define IAPP_TCP_PORT 3517
|
||||
|
||||
struct iapp_hdr {
|
||||
u8 version;
|
||||
u8 command;
|
||||
be16 identifier;
|
||||
be16 length;
|
||||
/* followed by length-6 octets of data */
|
||||
} __attribute__ ((packed));
|
||||
|
||||
#define IAPP_VERSION 0
|
||||
|
||||
enum IAPP_COMMAND {
|
||||
IAPP_CMD_ADD_notify = 0,
|
||||
IAPP_CMD_MOVE_notify = 1,
|
||||
IAPP_CMD_MOVE_response = 2,
|
||||
IAPP_CMD_Send_Security_Block = 3,
|
||||
IAPP_CMD_ACK_Security_Block = 4,
|
||||
IAPP_CMD_CACHE_notify = 5,
|
||||
IAPP_CMD_CACHE_response = 6,
|
||||
};
|
||||
|
||||
|
||||
/* ADD-notify - multicast UDP on the local LAN */
|
||||
struct iapp_add_notify {
|
||||
u8 addr_len; /* ETH_ALEN */
|
||||
u8 reserved;
|
||||
u8 mac_addr[ETH_ALEN];
|
||||
be16 seq_num;
|
||||
} __attribute__ ((packed));
|
||||
|
||||
|
||||
/* Layer 2 Update frame (802.2 Type 1 LLC XID Update response) */
|
||||
struct iapp_layer2_update {
|
||||
u8 da[ETH_ALEN]; /* broadcast */
|
||||
u8 sa[ETH_ALEN]; /* STA addr */
|
||||
be16 len; /* 6 */
|
||||
u8 dsap; /* null DSAP address */
|
||||
u8 ssap; /* null SSAP address, CR=Response */
|
||||
u8 control;
|
||||
u8 xid_info[3];
|
||||
} __attribute__ ((packed));
|
||||
|
||||
|
||||
/* MOVE-notify - unicast TCP */
|
||||
struct iapp_move_notify {
|
||||
u8 addr_len; /* ETH_ALEN */
|
||||
u8 reserved;
|
||||
u8 mac_addr[ETH_ALEN];
|
||||
u16 seq_num;
|
||||
u16 ctx_block_len;
|
||||
/* followed by ctx_block_len bytes */
|
||||
} __attribute__ ((packed));
|
||||
|
||||
|
||||
/* MOVE-response - unicast TCP */
|
||||
struct iapp_move_response {
|
||||
u8 addr_len; /* ETH_ALEN */
|
||||
u8 status;
|
||||
u8 mac_addr[ETH_ALEN];
|
||||
u16 seq_num;
|
||||
u16 ctx_block_len;
|
||||
/* followed by ctx_block_len bytes */
|
||||
} __attribute__ ((packed));
|
||||
|
||||
enum {
|
||||
IAPP_MOVE_SUCCESSFUL = 0,
|
||||
IAPP_MOVE_DENIED = 1,
|
||||
IAPP_MOVE_STALE_MOVE = 2,
|
||||
};
|
||||
|
||||
|
||||
/* CACHE-notify */
|
||||
struct iapp_cache_notify {
|
||||
u8 addr_len; /* ETH_ALEN */
|
||||
u8 reserved;
|
||||
u8 mac_addr[ETH_ALEN];
|
||||
u16 seq_num;
|
||||
u8 current_ap[ETH_ALEN];
|
||||
u16 ctx_block_len;
|
||||
/* ctx_block_len bytes of context block followed by 16-bit context
|
||||
* timeout */
|
||||
} __attribute__ ((packed));
|
||||
|
||||
|
||||
/* CACHE-response - unicast TCP */
|
||||
struct iapp_cache_response {
|
||||
u8 addr_len; /* ETH_ALEN */
|
||||
u8 status;
|
||||
u8 mac_addr[ETH_ALEN];
|
||||
u16 seq_num;
|
||||
} __attribute__ ((packed));
|
||||
|
||||
enum {
|
||||
IAPP_CACHE_SUCCESSFUL = 0,
|
||||
IAPP_CACHE_STALE_CACHE = 1,
|
||||
};
|
||||
|
||||
|
||||
/* Send-Security-Block - unicast TCP */
|
||||
struct iapp_send_security_block {
|
||||
u8 iv[8];
|
||||
u16 sec_block_len;
|
||||
/* followed by sec_block_len bytes of security block */
|
||||
} __attribute__ ((packed));
|
||||
|
||||
|
||||
/* ACK-Security-Block - unicast TCP */
|
||||
struct iapp_ack_security_block {
|
||||
u8 iv[8];
|
||||
u8 new_ap_ack_authenticator[48];
|
||||
} __attribute__ ((packed));
|
||||
|
||||
|
||||
struct iapp_data {
|
||||
struct hostapd_data *hapd;
|
||||
u16 identifier; /* next IAPP identifier */
|
||||
struct in_addr own, multicast;
|
||||
int udp_sock;
|
||||
int packet_sock;
|
||||
};
|
||||
|
||||
|
||||
static void iapp_send_add(struct iapp_data *iapp, u8 *mac_addr, u16 seq_num)
|
||||
{
|
||||
char buf[128];
|
||||
struct iapp_hdr *hdr;
|
||||
struct iapp_add_notify *add;
|
||||
struct sockaddr_in addr;
|
||||
|
||||
/* Send IAPP ADD-notify to remove possible association from other APs
|
||||
*/
|
||||
|
||||
hdr = (struct iapp_hdr *) buf;
|
||||
hdr->version = IAPP_VERSION;
|
||||
hdr->command = IAPP_CMD_ADD_notify;
|
||||
hdr->identifier = host_to_be16(iapp->identifier++);
|
||||
hdr->length = host_to_be16(sizeof(*hdr) + sizeof(*add));
|
||||
|
||||
add = (struct iapp_add_notify *) (hdr + 1);
|
||||
add->addr_len = ETH_ALEN;
|
||||
add->reserved = 0;
|
||||
os_memcpy(add->mac_addr, mac_addr, ETH_ALEN);
|
||||
|
||||
add->seq_num = host_to_be16(seq_num);
|
||||
|
||||
os_memset(&addr, 0, sizeof(addr));
|
||||
addr.sin_family = AF_INET;
|
||||
addr.sin_addr.s_addr = iapp->multicast.s_addr;
|
||||
addr.sin_port = htons(IAPP_UDP_PORT);
|
||||
if (sendto(iapp->udp_sock, buf, (char *) (add + 1) - buf, 0,
|
||||
(struct sockaddr *) &addr, sizeof(addr)) < 0)
|
||||
perror("sendto[IAPP-ADD]");
|
||||
}
|
||||
|
||||
|
||||
static void iapp_send_layer2_update(struct iapp_data *iapp, u8 *addr)
|
||||
{
|
||||
struct iapp_layer2_update msg;
|
||||
|
||||
/* Send Level 2 Update Frame to update forwarding tables in layer 2
|
||||
* bridge devices */
|
||||
|
||||
/* 802.2 Type 1 Logical Link Control (LLC) Exchange Identifier (XID)
|
||||
* Update response frame; IEEE Std 802.2-1998, 5.4.1.2.1 */
|
||||
|
||||
os_memset(msg.da, 0xff, ETH_ALEN);
|
||||
os_memcpy(msg.sa, addr, ETH_ALEN);
|
||||
msg.len = host_to_be16(6);
|
||||
msg.dsap = 0; /* NULL DSAP address */
|
||||
msg.ssap = 0x01; /* NULL SSAP address, CR Bit: Response */
|
||||
msg.control = 0xaf; /* XID response lsb.1111F101.
|
||||
* F=0 (no poll command; unsolicited frame) */
|
||||
msg.xid_info[0] = 0x81; /* XID format identifier */
|
||||
msg.xid_info[1] = 1; /* LLC types/classes: Type 1 LLC */
|
||||
msg.xid_info[2] = 1 << 1; /* XID sender's receive window size (RW)
|
||||
* FIX: what is correct RW with 802.11? */
|
||||
|
||||
if (send(iapp->packet_sock, &msg, sizeof(msg), 0) < 0)
|
||||
perror("send[L2 Update]");
|
||||
}
|
||||
|
||||
|
||||
/**
|
||||
* iapp_new_station - IAPP processing for a new STA
|
||||
* @iapp: IAPP data
|
||||
* @sta: The associated station
|
||||
*/
|
||||
void iapp_new_station(struct iapp_data *iapp, struct sta_info *sta)
|
||||
{
|
||||
struct ieee80211_mgmt *assoc;
|
||||
u16 seq;
|
||||
|
||||
if (iapp == NULL)
|
||||
return;
|
||||
|
||||
assoc = sta->last_assoc_req;
|
||||
seq = assoc ? WLAN_GET_SEQ_SEQ(le_to_host16(assoc->seq_ctrl)) : 0;
|
||||
|
||||
/* IAPP-ADD.request(MAC Address, Sequence Number, Timeout) */
|
||||
hostapd_logger(iapp->hapd, sta->addr, HOSTAPD_MODULE_IAPP,
|
||||
HOSTAPD_LEVEL_DEBUG, "IAPP-ADD.request(seq=%d)", seq);
|
||||
iapp_send_layer2_update(iapp, sta->addr);
|
||||
iapp_send_add(iapp, sta->addr, seq);
|
||||
|
||||
if (assoc && WLAN_FC_GET_STYPE(le_to_host16(assoc->frame_control)) ==
|
||||
WLAN_FC_STYPE_REASSOC_REQ) {
|
||||
/* IAPP-MOVE.request(MAC Address, Sequence Number, Old AP,
|
||||
* Context Block, Timeout)
|
||||
*/
|
||||
/* TODO: Send IAPP-MOVE to the old AP; Map Old AP BSSID to
|
||||
* IP address */
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
static void iapp_process_add_notify(struct iapp_data *iapp,
|
||||
struct sockaddr_in *from,
|
||||
struct iapp_hdr *hdr, int len)
|
||||
{
|
||||
struct iapp_add_notify *add = (struct iapp_add_notify *) (hdr + 1);
|
||||
struct sta_info *sta;
|
||||
|
||||
if (len != sizeof(*add)) {
|
||||
printf("Invalid IAPP-ADD packet length %d (expected %lu)\n",
|
||||
len, (unsigned long) sizeof(*add));
|
||||
return;
|
||||
}
|
||||
|
||||
sta = ap_get_sta(iapp->hapd, add->mac_addr);
|
||||
|
||||
/* IAPP-ADD.indication(MAC Address, Sequence Number) */
|
||||
hostapd_logger(iapp->hapd, add->mac_addr, HOSTAPD_MODULE_IAPP,
|
||||
HOSTAPD_LEVEL_INFO,
|
||||
"Received IAPP ADD-notify (seq# %d) from %s:%d%s",
|
||||
be_to_host16(add->seq_num),
|
||||
inet_ntoa(from->sin_addr), ntohs(from->sin_port),
|
||||
sta ? "" : " (STA not found)");
|
||||
|
||||
if (!sta)
|
||||
return;
|
||||
|
||||
/* TODO: could use seq_num to try to determine whether last association
|
||||
* to this AP is newer than the one advertised in IAPP-ADD. Although,
|
||||
* this is not really a reliable verification. */
|
||||
|
||||
hostapd_logger(iapp->hapd, add->mac_addr, HOSTAPD_MODULE_IAPP,
|
||||
HOSTAPD_LEVEL_DEBUG,
|
||||
"Removing STA due to IAPP ADD-notify");
|
||||
ap_sta_disconnect(iapp->hapd, sta, NULL, 0);
|
||||
}
|
||||
|
||||
|
||||
/**
|
||||
* iapp_receive_udp - Process IAPP UDP frames
|
||||
* @sock: File descriptor for the socket
|
||||
* @eloop_ctx: IAPP data (struct iapp_data *)
|
||||
* @sock_ctx: Not used
|
||||
*/
|
||||
static void iapp_receive_udp(int sock, void *eloop_ctx, void *sock_ctx)
|
||||
{
|
||||
struct iapp_data *iapp = eloop_ctx;
|
||||
int len, hlen;
|
||||
unsigned char buf[128];
|
||||
struct sockaddr_in from;
|
||||
socklen_t fromlen;
|
||||
struct iapp_hdr *hdr;
|
||||
|
||||
/* Handle incoming IAPP frames (over UDP/IP) */
|
||||
|
||||
fromlen = sizeof(from);
|
||||
len = recvfrom(iapp->udp_sock, buf, sizeof(buf), 0,
|
||||
(struct sockaddr *) &from, &fromlen);
|
||||
if (len < 0) {
|
||||
perror("recvfrom");
|
||||
return;
|
||||
}
|
||||
|
||||
if (from.sin_addr.s_addr == iapp->own.s_addr)
|
||||
return; /* ignore own IAPP messages */
|
||||
|
||||
hostapd_logger(iapp->hapd, NULL, HOSTAPD_MODULE_IAPP,
|
||||
HOSTAPD_LEVEL_DEBUG,
|
||||
"Received %d byte IAPP frame from %s%s\n",
|
||||
len, inet_ntoa(from.sin_addr),
|
||||
len < (int) sizeof(*hdr) ? " (too short)" : "");
|
||||
|
||||
if (len < (int) sizeof(*hdr))
|
||||
return;
|
||||
|
||||
hdr = (struct iapp_hdr *) buf;
|
||||
hlen = be_to_host16(hdr->length);
|
||||
hostapd_logger(iapp->hapd, NULL, HOSTAPD_MODULE_IAPP,
|
||||
HOSTAPD_LEVEL_DEBUG,
|
||||
"RX: version=%d command=%d id=%d len=%d\n",
|
||||
hdr->version, hdr->command,
|
||||
be_to_host16(hdr->identifier), hlen);
|
||||
if (hdr->version != IAPP_VERSION) {
|
||||
printf("Dropping IAPP frame with unknown version %d\n",
|
||||
hdr->version);
|
||||
return;
|
||||
}
|
||||
if (hlen > len) {
|
||||
printf("Underflow IAPP frame (hlen=%d len=%d)\n", hlen, len);
|
||||
return;
|
||||
}
|
||||
if (hlen < len) {
|
||||
printf("Ignoring %d extra bytes from IAPP frame\n",
|
||||
len - hlen);
|
||||
len = hlen;
|
||||
}
|
||||
|
||||
switch (hdr->command) {
|
||||
case IAPP_CMD_ADD_notify:
|
||||
iapp_process_add_notify(iapp, &from, hdr, hlen - sizeof(*hdr));
|
||||
break;
|
||||
case IAPP_CMD_MOVE_notify:
|
||||
/* TODO: MOVE is using TCP; so move this to TCP handler once it
|
||||
* is implemented.. */
|
||||
/* IAPP-MOVE.indication(MAC Address, New BSSID,
|
||||
* Sequence Number, AP Address, Context Block) */
|
||||
/* TODO: process */
|
||||
break;
|
||||
default:
|
||||
printf("Unknown IAPP command %d\n", hdr->command);
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
struct iapp_data * iapp_init(struct hostapd_data *hapd, const char *iface)
|
||||
{
|
||||
struct ifreq ifr;
|
||||
struct sockaddr_ll addr;
|
||||
int ifindex;
|
||||
struct sockaddr_in *paddr, uaddr;
|
||||
struct iapp_data *iapp;
|
||||
struct ip_mreqn mreq;
|
||||
|
||||
iapp = os_zalloc(sizeof(*iapp));
|
||||
if (iapp == NULL)
|
||||
return NULL;
|
||||
iapp->hapd = hapd;
|
||||
iapp->udp_sock = iapp->packet_sock = -1;
|
||||
|
||||
/* TODO:
|
||||
* open socket for sending and receiving IAPP frames over TCP
|
||||
*/
|
||||
|
||||
iapp->udp_sock = socket(PF_INET, SOCK_DGRAM, 0);
|
||||
if (iapp->udp_sock < 0) {
|
||||
perror("socket[PF_INET,SOCK_DGRAM]");
|
||||
iapp_deinit(iapp);
|
||||
return NULL;
|
||||
}
|
||||
|
||||
os_memset(&ifr, 0, sizeof(ifr));
|
||||
os_strlcpy(ifr.ifr_name, iface, sizeof(ifr.ifr_name));
|
||||
if (ioctl(iapp->udp_sock, SIOCGIFINDEX, &ifr) != 0) {
|
||||
perror("ioctl(SIOCGIFINDEX)");
|
||||
iapp_deinit(iapp);
|
||||
return NULL;
|
||||
}
|
||||
ifindex = ifr.ifr_ifindex;
|
||||
|
||||
if (ioctl(iapp->udp_sock, SIOCGIFADDR, &ifr) != 0) {
|
||||
perror("ioctl(SIOCGIFADDR)");
|
||||
iapp_deinit(iapp);
|
||||
return NULL;
|
||||
}
|
||||
paddr = (struct sockaddr_in *) &ifr.ifr_addr;
|
||||
if (paddr->sin_family != AF_INET) {
|
||||
printf("Invalid address family %i (SIOCGIFADDR)\n",
|
||||
paddr->sin_family);
|
||||
iapp_deinit(iapp);
|
||||
return NULL;
|
||||
}
|
||||
iapp->own.s_addr = paddr->sin_addr.s_addr;
|
||||
|
||||
if (ioctl(iapp->udp_sock, SIOCGIFBRDADDR, &ifr) != 0) {
|
||||
perror("ioctl(SIOCGIFBRDADDR)");
|
||||
iapp_deinit(iapp);
|
||||
return NULL;
|
||||
}
|
||||
paddr = (struct sockaddr_in *) &ifr.ifr_addr;
|
||||
if (paddr->sin_family != AF_INET) {
|
||||
printf("Invalid address family %i (SIOCGIFBRDADDR)\n",
|
||||
paddr->sin_family);
|
||||
iapp_deinit(iapp);
|
||||
return NULL;
|
||||
}
|
||||
inet_aton(IAPP_MULTICAST, &iapp->multicast);
|
||||
|
||||
os_memset(&uaddr, 0, sizeof(uaddr));
|
||||
uaddr.sin_family = AF_INET;
|
||||
uaddr.sin_port = htons(IAPP_UDP_PORT);
|
||||
if (bind(iapp->udp_sock, (struct sockaddr *) &uaddr,
|
||||
sizeof(uaddr)) < 0) {
|
||||
perror("bind[UDP]");
|
||||
iapp_deinit(iapp);
|
||||
return NULL;
|
||||
}
|
||||
|
||||
os_memset(&mreq, 0, sizeof(mreq));
|
||||
mreq.imr_multiaddr = iapp->multicast;
|
||||
mreq.imr_address.s_addr = INADDR_ANY;
|
||||
mreq.imr_ifindex = 0;
|
||||
if (setsockopt(iapp->udp_sock, SOL_IP, IP_ADD_MEMBERSHIP, &mreq,
|
||||
sizeof(mreq)) < 0) {
|
||||
perror("setsockopt[UDP,IP_ADD_MEMBERSHIP]");
|
||||
iapp_deinit(iapp);
|
||||
return NULL;
|
||||
}
|
||||
|
||||
iapp->packet_sock = socket(PF_PACKET, SOCK_RAW, htons(ETH_P_ALL));
|
||||
if (iapp->packet_sock < 0) {
|
||||
perror("socket[PF_PACKET,SOCK_RAW]");
|
||||
iapp_deinit(iapp);
|
||||
return NULL;
|
||||
}
|
||||
|
||||
os_memset(&addr, 0, sizeof(addr));
|
||||
addr.sll_family = AF_PACKET;
|
||||
addr.sll_ifindex = ifindex;
|
||||
if (bind(iapp->packet_sock, (struct sockaddr *) &addr,
|
||||
sizeof(addr)) < 0) {
|
||||
perror("bind[PACKET]");
|
||||
iapp_deinit(iapp);
|
||||
return NULL;
|
||||
}
|
||||
|
||||
if (eloop_register_read_sock(iapp->udp_sock, iapp_receive_udp,
|
||||
iapp, NULL)) {
|
||||
printf("Could not register read socket for IAPP.\n");
|
||||
iapp_deinit(iapp);
|
||||
return NULL;
|
||||
}
|
||||
|
||||
printf("IEEE 802.11F (IAPP) using interface %s\n", iface);
|
||||
|
||||
/* TODO: For levels 2 and 3: send RADIUS Initiate-Request, receive
|
||||
* RADIUS Initiate-Accept or Initiate-Reject. IAPP port should actually
|
||||
* be openned only after receiving Initiate-Accept. If Initiate-Reject
|
||||
* is received, IAPP is not started. */
|
||||
|
||||
return iapp;
|
||||
}
|
||||
|
||||
|
||||
void iapp_deinit(struct iapp_data *iapp)
|
||||
{
|
||||
struct ip_mreqn mreq;
|
||||
|
||||
if (iapp == NULL)
|
||||
return;
|
||||
|
||||
if (iapp->udp_sock >= 0) {
|
||||
os_memset(&mreq, 0, sizeof(mreq));
|
||||
mreq.imr_multiaddr = iapp->multicast;
|
||||
mreq.imr_address.s_addr = INADDR_ANY;
|
||||
mreq.imr_ifindex = 0;
|
||||
if (setsockopt(iapp->udp_sock, SOL_IP, IP_DROP_MEMBERSHIP,
|
||||
&mreq, sizeof(mreq)) < 0) {
|
||||
perror("setsockopt[UDP,IP_DEL_MEMBERSHIP]");
|
||||
}
|
||||
|
||||
eloop_unregister_read_sock(iapp->udp_sock);
|
||||
close(iapp->udp_sock);
|
||||
}
|
||||
if (iapp->packet_sock >= 0) {
|
||||
eloop_unregister_read_sock(iapp->packet_sock);
|
||||
close(iapp->packet_sock);
|
||||
}
|
||||
os_free(iapp);
|
||||
}
|
45
hostapd-0.8/src/ap/iapp.h
Normal file
45
hostapd-0.8/src/ap/iapp.h
Normal file
|
@ -0,0 +1,45 @@
|
|||
/*
|
||||
* 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.
|
||||
*/
|
||||
|
||||
#ifndef IAPP_H
|
||||
#define IAPP_H
|
||||
|
||||
struct iapp_data;
|
||||
|
||||
#ifdef CONFIG_IAPP
|
||||
|
||||
void iapp_new_station(struct iapp_data *iapp, struct sta_info *sta);
|
||||
struct iapp_data * iapp_init(struct hostapd_data *hapd, const char *iface);
|
||||
void iapp_deinit(struct iapp_data *iapp);
|
||||
|
||||
#else /* CONFIG_IAPP */
|
||||
|
||||
static inline void iapp_new_station(struct iapp_data *iapp,
|
||||
struct sta_info *sta)
|
||||
{
|
||||
}
|
||||
|
||||
static inline struct iapp_data * iapp_init(struct hostapd_data *hapd,
|
||||
const char *iface)
|
||||
{
|
||||
return NULL;
|
||||
}
|
||||
|
||||
static inline void iapp_deinit(struct iapp_data *iapp)
|
||||
{
|
||||
}
|
||||
|
||||
#endif /* CONFIG_IAPP */
|
||||
|
||||
#endif /* IAPP_H */
|
1884
hostapd-0.8/src/ap/ieee802_11.c
Normal file
1884
hostapd-0.8/src/ap/ieee802_11.c
Normal file
File diff suppressed because it is too large
Load diff
68
hostapd-0.8/src/ap/ieee802_11.h
Normal file
68
hostapd-0.8/src/ap/ieee802_11.h
Normal file
|
@ -0,0 +1,68 @@
|
|||
/*
|
||||
* 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.
|
||||
*/
|
||||
|
||||
#ifndef IEEE802_11_H
|
||||
#define IEEE802_11_H
|
||||
|
||||
struct hostapd_iface;
|
||||
struct hostapd_data;
|
||||
struct sta_info;
|
||||
struct hostapd_frame_info;
|
||||
struct ieee80211_ht_capabilities;
|
||||
|
||||
void ieee802_11_mgmt(struct hostapd_data *hapd, const u8 *buf, size_t len,
|
||||
struct hostapd_frame_info *fi);
|
||||
void ieee802_11_mgmt_cb(struct hostapd_data *hapd, const u8 *buf, size_t len,
|
||||
u16 stype, int ok);
|
||||
void ieee802_11_print_ssid(char *buf, const u8 *ssid, u8 len);
|
||||
#ifdef NEED_AP_MLME
|
||||
int ieee802_11_get_mib(struct hostapd_data *hapd, char *buf, size_t buflen);
|
||||
int ieee802_11_get_mib_sta(struct hostapd_data *hapd, struct sta_info *sta,
|
||||
char *buf, size_t buflen);
|
||||
#else /* NEED_AP_MLME */
|
||||
static inline int ieee802_11_get_mib(struct hostapd_data *hapd, char *buf,
|
||||
size_t buflen)
|
||||
{
|
||||
return 0;
|
||||
}
|
||||
|
||||
static inline int ieee802_11_get_mib_sta(struct hostapd_data *hapd,
|
||||
struct sta_info *sta,
|
||||
char *buf, size_t buflen)
|
||||
{
|
||||
return 0;
|
||||
}
|
||||
#endif /* NEED_AP_MLME */
|
||||
u16 hostapd_own_capab_info(struct hostapd_data *hapd, struct sta_info *sta,
|
||||
int probe);
|
||||
u8 * hostapd_eid_ext_capab(struct hostapd_data *hapd, u8 *eid);
|
||||
u8 * hostapd_eid_supp_rates(struct hostapd_data *hapd, u8 *eid);
|
||||
u8 * hostapd_eid_ext_supp_rates(struct hostapd_data *hapd, u8 *eid);
|
||||
u8 * hostapd_eid_ht_capabilities(struct hostapd_data *hapd, u8 *eid);
|
||||
u8 * hostapd_eid_ht_operation(struct hostapd_data *hapd, u8 *eid);
|
||||
int hostapd_ht_operation_update(struct hostapd_iface *iface);
|
||||
void ieee802_11_send_sa_query_req(struct hostapd_data *hapd,
|
||||
const u8 *addr, const u8 *trans_id);
|
||||
void hostapd_get_ht_capab(struct hostapd_data *hapd,
|
||||
struct ieee80211_ht_capabilities *ht_cap,
|
||||
struct ieee80211_ht_capabilities *neg_ht_cap);
|
||||
u16 copy_sta_ht_capab(struct 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);
|
||||
void hostapd_tx_status(struct hostapd_data *hapd, const u8 *addr,
|
||||
const u8 *buf, size_t len, int ack);
|
||||
void ieee802_11_rx_from_unknown(struct hostapd_data *hapd, const u8 *src,
|
||||
int wds);
|
||||
|
||||
#endif /* IEEE802_11_H */
|
524
hostapd-0.8/src/ap/ieee802_11_auth.c
Normal file
524
hostapd-0.8/src/ap/ieee802_11_auth.c
Normal file
|
@ -0,0 +1,524 @@
|
|||
/*
|
||||
* hostapd / IEEE 802.11 authentication (ACL)
|
||||
* 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.
|
||||
*
|
||||
* Access control list for IEEE 802.11 authentication can uses statically
|
||||
* configured ACL from configuration files or an external RADIUS server.
|
||||
* Results from external RADIUS queries are cached to allow faster
|
||||
* authentication frame processing.
|
||||
*/
|
||||
|
||||
#include "utils/includes.h"
|
||||
|
||||
#include "utils/common.h"
|
||||
#include "utils/eloop.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_11_auth.h"
|
||||
|
||||
#define RADIUS_ACL_TIMEOUT 30
|
||||
|
||||
|
||||
struct hostapd_cached_radius_acl {
|
||||
os_time_t timestamp;
|
||||
macaddr addr;
|
||||
int accepted; /* HOSTAPD_ACL_* */
|
||||
struct hostapd_cached_radius_acl *next;
|
||||
u32 session_timeout;
|
||||
u32 acct_interim_interval;
|
||||
int vlan_id;
|
||||
};
|
||||
|
||||
|
||||
struct hostapd_acl_query_data {
|
||||
os_time_t timestamp;
|
||||
u8 radius_id;
|
||||
macaddr addr;
|
||||
u8 *auth_msg; /* IEEE 802.11 authentication frame from station */
|
||||
size_t auth_msg_len;
|
||||
struct hostapd_acl_query_data *next;
|
||||
};
|
||||
|
||||
|
||||
#ifndef CONFIG_NO_RADIUS
|
||||
static void hostapd_acl_cache_free(struct hostapd_cached_radius_acl *acl_cache)
|
||||
{
|
||||
struct hostapd_cached_radius_acl *prev;
|
||||
|
||||
while (acl_cache) {
|
||||
prev = acl_cache;
|
||||
acl_cache = acl_cache->next;
|
||||
os_free(prev);
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
static int hostapd_acl_cache_get(struct hostapd_data *hapd, const u8 *addr,
|
||||
u32 *session_timeout,
|
||||
u32 *acct_interim_interval, int *vlan_id)
|
||||
{
|
||||
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;
|
||||
}
|
||||
|
||||
entry = entry->next;
|
||||
}
|
||||
|
||||
return -1;
|
||||
}
|
||||
#endif /* CONFIG_NO_RADIUS */
|
||||
|
||||
|
||||
static void hostapd_acl_query_free(struct hostapd_acl_query_data *query)
|
||||
{
|
||||
if (query == NULL)
|
||||
return;
|
||||
os_free(query->auth_msg);
|
||||
os_free(query);
|
||||
}
|
||||
|
||||
|
||||
#ifndef CONFIG_NO_RADIUS
|
||||
static int hostapd_radius_acl_query(struct hostapd_data *hapd, const u8 *addr,
|
||||
struct hostapd_acl_query_data *query)
|
||||
{
|
||||
struct radius_msg *msg;
|
||||
char buf[128];
|
||||
|
||||
query->radius_id = radius_client_get_id(hapd->radius);
|
||||
msg = radius_msg_new(RADIUS_CODE_ACCESS_REQUEST, query->radius_id);
|
||||
if (msg == NULL)
|
||||
return -1;
|
||||
|
||||
radius_msg_make_authenticator(msg, addr, ETH_ALEN);
|
||||
|
||||
os_snprintf(buf, sizeof(buf), RADIUS_ADDR_FORMAT, MAC2STR(addr));
|
||||
if (!radius_msg_add_attr(msg, RADIUS_ATTR_USER_NAME, (u8 *) buf,
|
||||
os_strlen(buf))) {
|
||||
wpa_printf(MSG_DEBUG, "Could not add User-Name");
|
||||
goto fail;
|
||||
}
|
||||
|
||||
if (!radius_msg_add_attr_user_password(
|
||||
msg, (u8 *) buf, os_strlen(buf),
|
||||
hapd->conf->radius->auth_server->shared_secret,
|
||||
hapd->conf->radius->auth_server->shared_secret_len)) {
|
||||
wpa_printf(MSG_DEBUG, "Could not add User-Password");
|
||||
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");
|
||||
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));
|
||||
if (!radius_msg_add_attr(msg, RADIUS_ATTR_CALLING_STATION_ID,
|
||||
(u8 *) buf, os_strlen(buf))) {
|
||||
wpa_printf(MSG_DEBUG, "Could not add Calling-Station-Id");
|
||||
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))) {
|
||||
wpa_printf(MSG_DEBUG, "Could not add Connect-Info");
|
||||
goto fail;
|
||||
}
|
||||
|
||||
radius_client_send(hapd->radius, msg, RADIUS_AUTH, addr);
|
||||
return 0;
|
||||
|
||||
fail:
|
||||
radius_msg_free(msg);
|
||||
return -1;
|
||||
}
|
||||
#endif /* CONFIG_NO_RADIUS */
|
||||
|
||||
|
||||
/**
|
||||
* hostapd_allowed_address - Check whether a specified STA can be authenticated
|
||||
* @hapd: hostapd BSS data
|
||||
* @addr: MAC address of the STA
|
||||
* @msg: Authentication message
|
||||
* @len: Length of msg in octets
|
||||
* @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
|
||||
* Returns: HOSTAPD_ACL_ACCEPT, HOSTAPD_ACL_REJECT, or HOSTAPD_ACL_PENDING
|
||||
*/
|
||||
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)
|
||||
{
|
||||
if (session_timeout)
|
||||
*session_timeout = 0;
|
||||
if (acct_interim_interval)
|
||||
*acct_interim_interval = 0;
|
||||
if (vlan_id)
|
||||
*vlan_id = 0;
|
||||
|
||||
if (hostapd_maclist_found(hapd->conf->accept_mac,
|
||||
hapd->conf->num_accept_mac, addr, vlan_id))
|
||||
return HOSTAPD_ACL_ACCEPT;
|
||||
|
||||
if (hostapd_maclist_found(hapd->conf->deny_mac,
|
||||
hapd->conf->num_deny_mac, addr, vlan_id))
|
||||
return HOSTAPD_ACL_REJECT;
|
||||
|
||||
if (hapd->conf->macaddr_acl == ACCEPT_UNLESS_DENIED)
|
||||
return HOSTAPD_ACL_ACCEPT;
|
||||
if (hapd->conf->macaddr_acl == DENY_UNLESS_ACCEPTED)
|
||||
return HOSTAPD_ACL_REJECT;
|
||||
|
||||
if (hapd->conf->macaddr_acl == USE_EXTERNAL_RADIUS_AUTH) {
|
||||
#ifdef CONFIG_NO_RADIUS
|
||||
return HOSTAPD_ACL_REJECT;
|
||||
#else /* CONFIG_NO_RADIUS */
|
||||
struct hostapd_acl_query_data *query;
|
||||
|
||||
/* 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);
|
||||
if (res == HOSTAPD_ACL_ACCEPT ||
|
||||
res == HOSTAPD_ACL_ACCEPT_TIMEOUT)
|
||||
return res;
|
||||
if (res == HOSTAPD_ACL_REJECT)
|
||||
return HOSTAPD_ACL_REJECT;
|
||||
|
||||
query = hapd->acl_queries;
|
||||
while (query) {
|
||||
if (os_memcmp(query->addr, addr, ETH_ALEN) == 0) {
|
||||
/* pending query in RADIUS retransmit queue;
|
||||
* do not generate a new one */
|
||||
return HOSTAPD_ACL_PENDING;
|
||||
}
|
||||
query = query->next;
|
||||
}
|
||||
|
||||
if (!hapd->conf->radius->auth_server)
|
||||
return HOSTAPD_ACL_REJECT;
|
||||
|
||||
/* No entry in the cache - query external RADIUS server */
|
||||
query = os_zalloc(sizeof(*query));
|
||||
if (query == NULL) {
|
||||
wpa_printf(MSG_ERROR, "malloc for query data failed");
|
||||
return HOSTAPD_ACL_REJECT;
|
||||
}
|
||||
time(&query->timestamp);
|
||||
os_memcpy(query->addr, addr, ETH_ALEN);
|
||||
if (hostapd_radius_acl_query(hapd, addr, query)) {
|
||||
wpa_printf(MSG_DEBUG, "Failed to send Access-Request "
|
||||
"for ACL query.");
|
||||
hostapd_acl_query_free(query);
|
||||
return HOSTAPD_ACL_REJECT;
|
||||
}
|
||||
|
||||
query->auth_msg = os_malloc(len);
|
||||
if (query->auth_msg == NULL) {
|
||||
wpa_printf(MSG_ERROR, "Failed to allocate memory for "
|
||||
"auth frame.");
|
||||
hostapd_acl_query_free(query);
|
||||
return HOSTAPD_ACL_REJECT;
|
||||
}
|
||||
os_memcpy(query->auth_msg, msg, len);
|
||||
query->auth_msg_len = len;
|
||||
query->next = hapd->acl_queries;
|
||||
hapd->acl_queries = query;
|
||||
|
||||
/* Queued data will be processed in hostapd_acl_recv_radius()
|
||||
* when RADIUS server replies to the sent Access-Request. */
|
||||
return HOSTAPD_ACL_PENDING;
|
||||
#endif /* CONFIG_NO_RADIUS */
|
||||
}
|
||||
|
||||
return HOSTAPD_ACL_REJECT;
|
||||
}
|
||||
|
||||
|
||||
#ifndef CONFIG_NO_RADIUS
|
||||
static void hostapd_acl_expire_cache(struct hostapd_data *hapd, os_time_t now)
|
||||
{
|
||||
struct hostapd_cached_radius_acl *prev, *entry, *tmp;
|
||||
|
||||
prev = NULL;
|
||||
entry = hapd->acl_cache;
|
||||
|
||||
while (entry) {
|
||||
if (now - entry->timestamp > RADIUS_ACL_TIMEOUT) {
|
||||
wpa_printf(MSG_DEBUG, "Cached ACL entry for " MACSTR
|
||||
" has expired.", MAC2STR(entry->addr));
|
||||
if (prev)
|
||||
prev->next = entry->next;
|
||||
else
|
||||
hapd->acl_cache = entry->next;
|
||||
hostapd_drv_set_radius_acl_expire(hapd, entry->addr);
|
||||
tmp = entry;
|
||||
entry = entry->next;
|
||||
os_free(tmp);
|
||||
continue;
|
||||
}
|
||||
|
||||
prev = entry;
|
||||
entry = entry->next;
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
static void hostapd_acl_expire_queries(struct hostapd_data *hapd,
|
||||
os_time_t now)
|
||||
{
|
||||
struct hostapd_acl_query_data *prev, *entry, *tmp;
|
||||
|
||||
prev = NULL;
|
||||
entry = hapd->acl_queries;
|
||||
|
||||
while (entry) {
|
||||
if (now - entry->timestamp > RADIUS_ACL_TIMEOUT) {
|
||||
wpa_printf(MSG_DEBUG, "ACL query for " MACSTR
|
||||
" has expired.", MAC2STR(entry->addr));
|
||||
if (prev)
|
||||
prev->next = entry->next;
|
||||
else
|
||||
hapd->acl_queries = entry->next;
|
||||
|
||||
tmp = entry;
|
||||
entry = entry->next;
|
||||
hostapd_acl_query_free(tmp);
|
||||
continue;
|
||||
}
|
||||
|
||||
prev = entry;
|
||||
entry = entry->next;
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
/**
|
||||
* hostapd_acl_expire - ACL cache expiration callback
|
||||
* @eloop_ctx: struct hostapd_data *
|
||||
* @timeout_ctx: Not used
|
||||
*/
|
||||
static void hostapd_acl_expire(void *eloop_ctx, void *timeout_ctx)
|
||||
{
|
||||
struct hostapd_data *hapd = eloop_ctx;
|
||||
struct os_time now;
|
||||
|
||||
os_get_time(&now);
|
||||
hostapd_acl_expire_cache(hapd, now.sec);
|
||||
hostapd_acl_expire_queries(hapd, now.sec);
|
||||
|
||||
eloop_register_timeout(10, 0, hostapd_acl_expire, hapd, NULL);
|
||||
}
|
||||
|
||||
|
||||
/**
|
||||
* hostapd_acl_recv_radius - Process incoming RADIUS Authentication messages
|
||||
* @msg: RADIUS response message
|
||||
* @req: RADIUS request message
|
||||
* @shared_secret: RADIUS shared secret
|
||||
* @shared_secret_len: Length of shared_secret in octets
|
||||
* @data: Context data (struct hostapd_data *)
|
||||
* Returns: RADIUS_RX_PROCESSED if RADIUS message was a reply to ACL query (and
|
||||
* was processed here) or RADIUS_RX_UNKNOWN if not.
|
||||
*/
|
||||
static RadiusRxResult
|
||||
hostapd_acl_recv_radius(struct radius_msg *msg, struct radius_msg *req,
|
||||
const u8 *shared_secret, size_t shared_secret_len,
|
||||
void *data)
|
||||
{
|
||||
struct hostapd_data *hapd = data;
|
||||
struct hostapd_acl_query_data *query, *prev;
|
||||
struct hostapd_cached_radius_acl *cache;
|
||||
struct radius_hdr *hdr = radius_msg_get_hdr(msg);
|
||||
|
||||
query = hapd->acl_queries;
|
||||
prev = NULL;
|
||||
while (query) {
|
||||
if (query->radius_id == hdr->identifier)
|
||||
break;
|
||||
prev = query;
|
||||
query = query->next;
|
||||
}
|
||||
if (query == NULL)
|
||||
return RADIUS_RX_UNKNOWN;
|
||||
|
||||
wpa_printf(MSG_DEBUG, "Found matching Access-Request for RADIUS "
|
||||
"message (id=%d)", query->radius_id);
|
||||
|
||||
if (radius_msg_verify(msg, shared_secret, shared_secret_len, req, 0)) {
|
||||
wpa_printf(MSG_INFO, "Incoming RADIUS packet did not have "
|
||||
"correct authenticator - dropped\n");
|
||||
return RADIUS_RX_INVALID_AUTHENTICATOR;
|
||||
}
|
||||
|
||||
if (hdr->code != RADIUS_CODE_ACCESS_ACCEPT &&
|
||||
hdr->code != RADIUS_CODE_ACCESS_REJECT) {
|
||||
wpa_printf(MSG_DEBUG, "Unknown RADIUS message code %d to ACL "
|
||||
"query", hdr->code);
|
||||
return RADIUS_RX_UNKNOWN;
|
||||
}
|
||||
|
||||
/* Insert Accept/Reject info into ACL cache */
|
||||
cache = os_zalloc(sizeof(*cache));
|
||||
if (cache == NULL) {
|
||||
wpa_printf(MSG_DEBUG, "Failed to add ACL cache entry");
|
||||
goto done;
|
||||
}
|
||||
time(&cache->timestamp);
|
||||
os_memcpy(cache->addr, query->addr, sizeof(cache->addr));
|
||||
if (hdr->code == RADIUS_CODE_ACCESS_ACCEPT) {
|
||||
if (radius_msg_get_attr_int32(msg, RADIUS_ATTR_SESSION_TIMEOUT,
|
||||
&cache->session_timeout) == 0)
|
||||
cache->accepted = HOSTAPD_ACL_ACCEPT_TIMEOUT;
|
||||
else
|
||||
cache->accepted = HOSTAPD_ACL_ACCEPT;
|
||||
|
||||
if (radius_msg_get_attr_int32(
|
||||
msg, RADIUS_ATTR_ACCT_INTERIM_INTERVAL,
|
||||
&cache->acct_interim_interval) == 0 &&
|
||||
cache->acct_interim_interval < 60) {
|
||||
wpa_printf(MSG_DEBUG, "Ignored too small "
|
||||
"Acct-Interim-Interval %d for STA " MACSTR,
|
||||
cache->acct_interim_interval,
|
||||
MAC2STR(query->addr));
|
||||
cache->acct_interim_interval = 0;
|
||||
}
|
||||
|
||||
cache->vlan_id = radius_msg_get_vlanid(msg);
|
||||
} else
|
||||
cache->accepted = HOSTAPD_ACL_REJECT;
|
||||
cache->next = hapd->acl_cache;
|
||||
hapd->acl_cache = cache;
|
||||
|
||||
#ifdef CONFIG_DRIVER_RADIUS_ACL
|
||||
hostapd_drv_set_radius_acl_auth(hapd, query->addr, cache->accepted,
|
||||
cache->session_timeout);
|
||||
#else /* CONFIG_DRIVER_RADIUS_ACL */
|
||||
#ifdef NEED_AP_MLME
|
||||
/* Re-send original authentication frame for 802.11 processing */
|
||||
wpa_printf(MSG_DEBUG, "Re-sending authentication frame after "
|
||||
"successful RADIUS ACL query");
|
||||
ieee802_11_mgmt(hapd, query->auth_msg, query->auth_msg_len, NULL);
|
||||
#endif /* NEED_AP_MLME */
|
||||
#endif /* CONFIG_DRIVER_RADIUS_ACL */
|
||||
|
||||
done:
|
||||
if (prev == NULL)
|
||||
hapd->acl_queries = query->next;
|
||||
else
|
||||
prev->next = query->next;
|
||||
|
||||
hostapd_acl_query_free(query);
|
||||
|
||||
return RADIUS_RX_PROCESSED;
|
||||
}
|
||||
#endif /* CONFIG_NO_RADIUS */
|
||||
|
||||
|
||||
/**
|
||||
* hostapd_acl_init: Initialize IEEE 802.11 ACL
|
||||
* @hapd: hostapd BSS data
|
||||
* Returns: 0 on success, -1 on failure
|
||||
*/
|
||||
int hostapd_acl_init(struct hostapd_data *hapd)
|
||||
{
|
||||
#ifndef CONFIG_NO_RADIUS
|
||||
if (radius_client_register(hapd->radius, RADIUS_AUTH,
|
||||
hostapd_acl_recv_radius, hapd))
|
||||
return -1;
|
||||
|
||||
eloop_register_timeout(10, 0, hostapd_acl_expire, hapd, NULL);
|
||||
#endif /* CONFIG_NO_RADIUS */
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
|
||||
/**
|
||||
* hostapd_acl_deinit - Deinitialize IEEE 802.11 ACL
|
||||
* @hapd: hostapd BSS data
|
||||
*/
|
||||
void hostapd_acl_deinit(struct hostapd_data *hapd)
|
||||
{
|
||||
struct hostapd_acl_query_data *query, *prev;
|
||||
|
||||
#ifndef CONFIG_NO_RADIUS
|
||||
eloop_cancel_timeout(hostapd_acl_expire, hapd, NULL);
|
||||
|
||||
hostapd_acl_cache_free(hapd->acl_cache);
|
||||
#endif /* CONFIG_NO_RADIUS */
|
||||
|
||||
query = hapd->acl_queries;
|
||||
while (query) {
|
||||
prev = query;
|
||||
query = query->next;
|
||||
hostapd_acl_query_free(prev);
|
||||
}
|
||||
}
|
31
hostapd-0.8/src/ap/ieee802_11_auth.h
Normal file
31
hostapd-0.8/src/ap/ieee802_11_auth.h
Normal file
|
@ -0,0 +1,31 @@
|
|||
/*
|
||||
* 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.
|
||||
*/
|
||||
|
||||
#ifndef IEEE802_11_AUTH_H
|
||||
#define IEEE802_11_AUTH_H
|
||||
|
||||
enum {
|
||||
HOSTAPD_ACL_REJECT = 0,
|
||||
HOSTAPD_ACL_ACCEPT = 1,
|
||||
HOSTAPD_ACL_PENDING = 2,
|
||||
HOSTAPD_ACL_ACCEPT_TIMEOUT = 3
|
||||
};
|
||||
|
||||
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);
|
||||
int hostapd_acl_init(struct hostapd_data *hapd);
|
||||
void hostapd_acl_deinit(struct hostapd_data *hapd);
|
||||
|
||||
#endif /* IEEE802_11_AUTH_H */
|
267
hostapd-0.8/src/ap/ieee802_11_ht.c
Normal file
267
hostapd-0.8/src/ap/ieee802_11_ht.c
Normal file
|
@ -0,0 +1,267 @@
|
|||
/*
|
||||
* hostapd / IEEE 802.11n HT
|
||||
* 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.
|
||||
*/
|
||||
|
||||
#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_ht_capabilities(struct hostapd_data *hapd, u8 *eid)
|
||||
{
|
||||
struct ieee80211_ht_capabilities *cap;
|
||||
u8 *pos = eid;
|
||||
|
||||
if (!hapd->iconf->ieee80211n || !hapd->iface->current_mode ||
|
||||
hapd->conf->disable_11n)
|
||||
return eid;
|
||||
|
||||
*pos++ = WLAN_EID_HT_CAP;
|
||||
*pos++ = sizeof(*cap);
|
||||
|
||||
cap = (struct ieee80211_ht_capabilities *) pos;
|
||||
os_memset(cap, 0, sizeof(*cap));
|
||||
cap->ht_capabilities_info = host_to_le16(hapd->iconf->ht_capab);
|
||||
cap->a_mpdu_params = hapd->iface->current_mode->a_mpdu_params;
|
||||
os_memcpy(cap->supported_mcs_set, hapd->iface->current_mode->mcs_set,
|
||||
16);
|
||||
|
||||
/* TODO: ht_extended_capabilities (now fully disabled) */
|
||||
/* TODO: tx_bf_capability_info (now fully disabled) */
|
||||
/* TODO: asel_capabilities (now fully disabled) */
|
||||
|
||||
pos += sizeof(*cap);
|
||||
|
||||
return pos;
|
||||
}
|
||||
|
||||
|
||||
u8 * hostapd_eid_ht_operation(struct hostapd_data *hapd, u8 *eid)
|
||||
{
|
||||
struct ieee80211_ht_operation *oper;
|
||||
u8 *pos = eid;
|
||||
|
||||
if (!hapd->iconf->ieee80211n || hapd->conf->disable_11n)
|
||||
return eid;
|
||||
|
||||
*pos++ = WLAN_EID_HT_OPERATION;
|
||||
*pos++ = sizeof(*oper);
|
||||
|
||||
oper = (struct ieee80211_ht_operation *) pos;
|
||||
os_memset(oper, 0, sizeof(*oper));
|
||||
|
||||
oper->control_chan = hapd->iconf->channel;
|
||||
oper->operation_mode = host_to_le16(hapd->iface->ht_op_mode);
|
||||
if (hapd->iconf->secondary_channel == 1)
|
||||
oper->ht_param |= HT_INFO_HT_PARAM_SECONDARY_CHNL_ABOVE |
|
||||
HT_INFO_HT_PARAM_REC_TRANS_CHNL_WIDTH;
|
||||
if (hapd->iconf->secondary_channel == -1)
|
||||
oper->ht_param |= HT_INFO_HT_PARAM_SECONDARY_CHNL_BELOW |
|
||||
HT_INFO_HT_PARAM_REC_TRANS_CHNL_WIDTH;
|
||||
|
||||
pos += sizeof(*oper);
|
||||
|
||||
return pos;
|
||||
}
|
||||
|
||||
|
||||
/*
|
||||
op_mode
|
||||
Set to 0 (HT pure) under the followign conditions
|
||||
- all STAs in the BSS are 20/40 MHz HT in 20/40 MHz BSS or
|
||||
- all STAs in the BSS are 20 MHz HT in 20 MHz BSS
|
||||
Set to 1 (HT non-member protection) if there may be non-HT STAs
|
||||
in both the primary and the secondary channel
|
||||
Set to 2 if only HT STAs are associated in BSS,
|
||||
however and at least one 20 MHz HT STA is associated
|
||||
Set to 3 (HT mixed mode) when one or more non-HT STAs are associated
|
||||
*/
|
||||
int hostapd_ht_operation_update(struct hostapd_iface *iface)
|
||||
{
|
||||
u16 cur_op_mode, new_op_mode;
|
||||
int op_mode_changes = 0;
|
||||
|
||||
if (!iface->conf->ieee80211n || iface->conf->ht_op_mode_fixed)
|
||||
return 0;
|
||||
|
||||
wpa_printf(MSG_DEBUG, "%s current operation mode=0x%X",
|
||||
__func__, iface->ht_op_mode);
|
||||
|
||||
if (!(iface->ht_op_mode & HT_INFO_OPERATION_MODE_NON_GF_DEVS_PRESENT)
|
||||
&& iface->num_sta_ht_no_gf) {
|
||||
iface->ht_op_mode |=
|
||||
HT_INFO_OPERATION_MODE_NON_GF_DEVS_PRESENT;
|
||||
op_mode_changes++;
|
||||
} else if ((iface->ht_op_mode &
|
||||
HT_INFO_OPERATION_MODE_NON_GF_DEVS_PRESENT) &&
|
||||
iface->num_sta_ht_no_gf == 0) {
|
||||
iface->ht_op_mode &=
|
||||
~HT_INFO_OPERATION_MODE_NON_GF_DEVS_PRESENT;
|
||||
op_mode_changes++;
|
||||
}
|
||||
|
||||
if (!(iface->ht_op_mode & HT_INFO_OPERATION_MODE_NON_HT_STA_PRESENT) &&
|
||||
(iface->num_sta_no_ht || iface->olbc_ht)) {
|
||||
iface->ht_op_mode |= HT_INFO_OPERATION_MODE_NON_HT_STA_PRESENT;
|
||||
op_mode_changes++;
|
||||
} else if ((iface->ht_op_mode &
|
||||
HT_INFO_OPERATION_MODE_NON_HT_STA_PRESENT) &&
|
||||
(iface->num_sta_no_ht == 0 && !iface->olbc_ht)) {
|
||||
iface->ht_op_mode &=
|
||||
~HT_INFO_OPERATION_MODE_NON_HT_STA_PRESENT;
|
||||
op_mode_changes++;
|
||||
}
|
||||
|
||||
new_op_mode = 0;
|
||||
if (iface->num_sta_no_ht)
|
||||
new_op_mode = OP_MODE_MIXED;
|
||||
else if ((iface->conf->ht_capab & HT_CAP_INFO_SUPP_CHANNEL_WIDTH_SET)
|
||||
&& iface->num_sta_ht_20mhz)
|
||||
new_op_mode = OP_MODE_20MHZ_HT_STA_ASSOCED;
|
||||
else if (iface->olbc_ht)
|
||||
new_op_mode = OP_MODE_MAY_BE_LEGACY_STAS;
|
||||
else
|
||||
new_op_mode = OP_MODE_PURE;
|
||||
|
||||
cur_op_mode = iface->ht_op_mode & HT_INFO_OPERATION_MODE_OP_MODE_MASK;
|
||||
if (cur_op_mode != new_op_mode) {
|
||||
iface->ht_op_mode &= ~HT_INFO_OPERATION_MODE_OP_MODE_MASK;
|
||||
iface->ht_op_mode |= new_op_mode;
|
||||
op_mode_changes++;
|
||||
}
|
||||
|
||||
wpa_printf(MSG_DEBUG, "%s new operation mode=0x%X changes=%d",
|
||||
__func__, iface->ht_op_mode, op_mode_changes);
|
||||
|
||||
return op_mode_changes;
|
||||
}
|
||||
|
||||
|
||||
u16 copy_sta_ht_capab(struct hostapd_data *hapd, struct sta_info *sta,
|
||||
const u8 *ht_capab, size_t ht_capab_len)
|
||||
{
|
||||
/* Disable HT caps for STAs associated to no-HT BSSes. */
|
||||
if (!ht_capab ||
|
||||
ht_capab_len < sizeof(struct ieee80211_ht_capabilities) ||
|
||||
hapd->conf->disable_11n) {
|
||||
sta->flags &= ~WLAN_STA_HT;
|
||||
os_free(sta->ht_capabilities);
|
||||
sta->ht_capabilities = NULL;
|
||||
return WLAN_STATUS_SUCCESS;
|
||||
}
|
||||
|
||||
if (sta->ht_capabilities == NULL) {
|
||||
sta->ht_capabilities =
|
||||
os_zalloc(sizeof(struct ieee80211_ht_capabilities));
|
||||
if (sta->ht_capabilities == NULL)
|
||||
return WLAN_STATUS_UNSPECIFIED_FAILURE;
|
||||
}
|
||||
|
||||
sta->flags |= WLAN_STA_HT;
|
||||
os_memcpy(sta->ht_capabilities, ht_capab,
|
||||
sizeof(struct ieee80211_ht_capabilities));
|
||||
|
||||
return WLAN_STATUS_SUCCESS;
|
||||
}
|
||||
|
||||
|
||||
static void update_sta_ht(struct hostapd_data *hapd, struct sta_info *sta)
|
||||
{
|
||||
u16 ht_capab;
|
||||
|
||||
ht_capab = le_to_host16(sta->ht_capabilities->ht_capabilities_info);
|
||||
wpa_printf(MSG_DEBUG, "HT: STA " MACSTR " HT Capabilities Info: "
|
||||
"0x%04x", MAC2STR(sta->addr), ht_capab);
|
||||
if ((ht_capab & HT_CAP_INFO_GREEN_FIELD) == 0) {
|
||||
if (!sta->no_ht_gf_set) {
|
||||
sta->no_ht_gf_set = 1;
|
||||
hapd->iface->num_sta_ht_no_gf++;
|
||||
}
|
||||
wpa_printf(MSG_DEBUG, "%s STA " MACSTR " - no greenfield, num "
|
||||
"of non-gf stations %d",
|
||||
__func__, MAC2STR(sta->addr),
|
||||
hapd->iface->num_sta_ht_no_gf);
|
||||
}
|
||||
if ((ht_capab & HT_CAP_INFO_SUPP_CHANNEL_WIDTH_SET) == 0) {
|
||||
if (!sta->ht_20mhz_set) {
|
||||
sta->ht_20mhz_set = 1;
|
||||
hapd->iface->num_sta_ht_20mhz++;
|
||||
}
|
||||
wpa_printf(MSG_DEBUG, "%s STA " MACSTR " - 20 MHz HT, num of "
|
||||
"20MHz HT STAs %d",
|
||||
__func__, MAC2STR(sta->addr),
|
||||
hapd->iface->num_sta_ht_20mhz);
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
static void update_sta_no_ht(struct hostapd_data *hapd, struct sta_info *sta)
|
||||
{
|
||||
if (!sta->no_ht_set) {
|
||||
sta->no_ht_set = 1;
|
||||
hapd->iface->num_sta_no_ht++;
|
||||
}
|
||||
if (hapd->iconf->ieee80211n) {
|
||||
wpa_printf(MSG_DEBUG, "%s STA " MACSTR " - no HT, num of "
|
||||
"non-HT stations %d",
|
||||
__func__, MAC2STR(sta->addr),
|
||||
hapd->iface->num_sta_no_ht);
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
void update_ht_state(struct hostapd_data *hapd, struct sta_info *sta)
|
||||
{
|
||||
if ((sta->flags & WLAN_STA_HT) && sta->ht_capabilities)
|
||||
update_sta_ht(hapd, sta);
|
||||
else
|
||||
update_sta_no_ht(hapd, sta);
|
||||
|
||||
if (hostapd_ht_operation_update(hapd->iface) > 0)
|
||||
ieee802_11_set_beacons(hapd->iface);
|
||||
}
|
||||
|
||||
|
||||
void hostapd_get_ht_capab(struct hostapd_data *hapd,
|
||||
struct ieee80211_ht_capabilities *ht_cap,
|
||||
struct ieee80211_ht_capabilities *neg_ht_cap)
|
||||
{
|
||||
u16 cap;
|
||||
|
||||
if (ht_cap == NULL)
|
||||
return;
|
||||
os_memcpy(neg_ht_cap, ht_cap, sizeof(*neg_ht_cap));
|
||||
cap = le_to_host16(neg_ht_cap->ht_capabilities_info);
|
||||
cap &= hapd->iconf->ht_capab;
|
||||
cap |= (hapd->iconf->ht_capab & HT_CAP_INFO_SMPS_DISABLED);
|
||||
|
||||
/*
|
||||
* STBC needs to be handled specially
|
||||
* if we don't support RX STBC, mask out TX STBC in the STA's HT caps
|
||||
* if we don't support TX STBC, mask out RX STBC in the STA's HT caps
|
||||
*/
|
||||
if (!(hapd->iconf->ht_capab & HT_CAP_INFO_RX_STBC_MASK))
|
||||
cap &= ~HT_CAP_INFO_TX_STBC;
|
||||
if (!(hapd->iconf->ht_capab & HT_CAP_INFO_TX_STBC))
|
||||
cap &= ~HT_CAP_INFO_RX_STBC_MASK;
|
||||
|
||||
neg_ht_cap->ht_capabilities_info = host_to_le16(cap);
|
||||
}
|
2085
hostapd-0.8/src/ap/ieee802_1x.c
Normal file
2085
hostapd-0.8/src/ap/ieee802_1x.c
Normal file
File diff suppressed because it is too large
Load diff
89
hostapd-0.8/src/ap/ieee802_1x.h
Normal file
89
hostapd-0.8/src/ap/ieee802_1x.h
Normal file
|
@ -0,0 +1,89 @@
|
|||
/*
|
||||
* hostapd / IEEE 802.1X-2004 Authenticator
|
||||
* 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.
|
||||
*/
|
||||
|
||||
#ifndef IEEE802_1X_H
|
||||
#define IEEE802_1X_H
|
||||
|
||||
struct hostapd_data;
|
||||
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 */
|
||||
|
||||
|
||||
void ieee802_1x_receive(struct hostapd_data *hapd, const u8 *sa, const u8 *buf,
|
||||
size_t len);
|
||||
void ieee802_1x_new_station(struct hostapd_data *hapd, struct sta_info *sta);
|
||||
void ieee802_1x_free_station(struct sta_info *sta);
|
||||
|
||||
void ieee802_1x_tx_key(struct hostapd_data *hapd, struct sta_info *sta);
|
||||
void ieee802_1x_abort_auth(struct hostapd_data *hapd, struct sta_info *sta);
|
||||
void ieee802_1x_set_sta_authorized(struct hostapd_data *hapd,
|
||||
struct sta_info *sta, int authorized);
|
||||
void ieee802_1x_dump_state(FILE *f, const char *prefix, struct sta_info *sta);
|
||||
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);
|
||||
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);
|
||||
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);
|
||||
void ieee802_1x_notify_port_valid(struct eapol_state_machine *sm,
|
||||
int valid);
|
||||
void ieee802_1x_notify_pre_auth(struct eapol_state_machine *sm, int pre_auth);
|
||||
int ieee802_1x_get_mib(struct hostapd_data *hapd, char *buf, size_t buflen);
|
||||
int ieee802_1x_get_mib_sta(struct hostapd_data *hapd, struct sta_info *sta,
|
||||
char *buf, size_t buflen);
|
||||
void hostapd_get_ntp_timestamp(u8 *buf);
|
||||
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);
|
||||
|
||||
#endif /* IEEE802_1X_H */
|
120
hostapd-0.8/src/ap/p2p_hostapd.c
Normal file
120
hostapd-0.8/src/ap/p2p_hostapd.c
Normal file
|
@ -0,0 +1,120 @@
|
|||
/*
|
||||
* 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.
|
||||
*/
|
||||
|
||||
#include "utils/includes.h"
|
||||
|
||||
#include "utils/common.h"
|
||||
#include "common/ieee802_11_defs.h"
|
||||
#include "p2p/p2p.h"
|
||||
#include "hostapd.h"
|
||||
#include "ap_config.h"
|
||||
#include "ap_drv_ops.h"
|
||||
#include "sta_info.h"
|
||||
#include "p2p_hostapd.h"
|
||||
|
||||
|
||||
#ifdef CONFIG_P2P
|
||||
|
||||
int hostapd_p2p_get_mib_sta(struct hostapd_data *hapd, struct sta_info *sta,
|
||||
char *buf, size_t buflen)
|
||||
{
|
||||
if (sta->p2p_ie == NULL)
|
||||
return 0;
|
||||
|
||||
return p2p_ie_text(sta->p2p_ie, buf, buf + buflen);
|
||||
}
|
||||
|
||||
|
||||
int hostapd_p2p_set_noa(struct hostapd_data *hapd, u8 count, int start,
|
||||
int duration)
|
||||
{
|
||||
wpa_printf(MSG_DEBUG, "P2P: Set NoA parameters: count=%u start=%d "
|
||||
"duration=%d", count, start, duration);
|
||||
|
||||
if (count == 0) {
|
||||
hapd->noa_enabled = 0;
|
||||
hapd->noa_start = 0;
|
||||
hapd->noa_duration = 0;
|
||||
}
|
||||
|
||||
if (count != 255) {
|
||||
wpa_printf(MSG_DEBUG, "P2P: Non-periodic NoA - set "
|
||||
"NoA parameters");
|
||||
return hostapd_driver_set_noa(hapd, count, start, duration);
|
||||
}
|
||||
|
||||
hapd->noa_enabled = 1;
|
||||
hapd->noa_start = start;
|
||||
hapd->noa_duration = duration;
|
||||
|
||||
if (hapd->num_sta_no_p2p == 0) {
|
||||
wpa_printf(MSG_DEBUG, "P2P: No legacy STAs connected - update "
|
||||
"periodic NoA parameters");
|
||||
return hostapd_driver_set_noa(hapd, count, start, duration);
|
||||
}
|
||||
|
||||
wpa_printf(MSG_DEBUG, "P2P: Legacy STA(s) connected - do not enable "
|
||||
"periodic NoA");
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
|
||||
void hostapd_p2p_non_p2p_sta_connected(struct hostapd_data *hapd)
|
||||
{
|
||||
wpa_printf(MSG_DEBUG, "P2P: First non-P2P device connected");
|
||||
|
||||
if (hapd->noa_enabled) {
|
||||
wpa_printf(MSG_DEBUG, "P2P: Disable periodic NoA");
|
||||
hostapd_driver_set_noa(hapd, 0, 0, 0);
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
void hostapd_p2p_non_p2p_sta_disconnected(struct hostapd_data *hapd)
|
||||
{
|
||||
wpa_printf(MSG_DEBUG, "P2P: Last non-P2P device disconnected");
|
||||
|
||||
if (hapd->noa_enabled) {
|
||||
wpa_printf(MSG_DEBUG, "P2P: Enable periodic NoA");
|
||||
hostapd_driver_set_noa(hapd, 255, hapd->noa_start,
|
||||
hapd->noa_duration);
|
||||
}
|
||||
}
|
||||
|
||||
#endif /* CONFIG_P2P */
|
||||
|
||||
|
||||
#ifdef CONFIG_P2P_MANAGER
|
||||
u8 * hostapd_eid_p2p_manage(struct hostapd_data *hapd, u8 *eid)
|
||||
{
|
||||
u8 bitmap;
|
||||
*eid++ = WLAN_EID_VENDOR_SPECIFIC;
|
||||
*eid++ = 4 + 3 + 1;
|
||||
WPA_PUT_BE24(eid, OUI_WFA);
|
||||
eid += 3;
|
||||
*eid++ = P2P_OUI_TYPE;
|
||||
|
||||
*eid++ = P2P_ATTR_MANAGEABILITY;
|
||||
WPA_PUT_LE16(eid, 1);
|
||||
eid += 2;
|
||||
bitmap = P2P_MAN_DEVICE_MANAGEMENT;
|
||||
if (hapd->conf->p2p & P2P_ALLOW_CROSS_CONNECTION)
|
||||
bitmap |= P2P_MAN_CROSS_CONNECTION_PERMITTED;
|
||||
bitmap |= P2P_MAN_COEXISTENCE_OPTIONAL;
|
||||
*eid++ = bitmap;
|
||||
|
||||
return eid;
|
||||
}
|
||||
#endif /* CONFIG_P2P_MANAGER */
|
41
hostapd-0.8/src/ap/p2p_hostapd.h
Normal file
41
hostapd-0.8/src/ap/p2p_hostapd.h
Normal file
|
@ -0,0 +1,41 @@
|
|||
/*
|
||||
* 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.
|
||||
*/
|
||||
|
||||
#ifndef P2P_HOSTAPD_H
|
||||
#define P2P_HOSTAPD_H
|
||||
|
||||
#ifdef CONFIG_P2P
|
||||
|
||||
int hostapd_p2p_get_mib_sta(struct hostapd_data *hapd, struct sta_info *sta,
|
||||
char *buf, size_t buflen);
|
||||
int hostapd_p2p_set_noa(struct hostapd_data *hapd, u8 count, int start,
|
||||
int duration);
|
||||
void hostapd_p2p_non_p2p_sta_connected(struct hostapd_data *hapd);
|
||||
void hostapd_p2p_non_p2p_sta_disconnected(struct hostapd_data *hapd);
|
||||
|
||||
|
||||
#else /* CONFIG_P2P */
|
||||
|
||||
static inline int hostapd_p2p_get_mib_sta(struct hostapd_data *hapd,
|
||||
struct sta_info *sta,
|
||||
char *buf, size_t buflen)
|
||||
{
|
||||
return 0;
|
||||
}
|
||||
|
||||
#endif /* CONFIG_P2P */
|
||||
|
||||
u8 * hostapd_eid_p2p_manage(struct hostapd_data *hapd, u8 *eid);
|
||||
|
||||
#endif /* P2P_HOSTAPD_H */
|
402
hostapd-0.8/src/ap/peerkey_auth.c
Normal file
402
hostapd-0.8/src/ap/peerkey_auth.c
Normal file
|
@ -0,0 +1,402 @@
|
|||
/*
|
||||
* 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.
|
||||
*/
|
||||
|
||||
#include "utils/includes.h"
|
||||
|
||||
#include "utils/common.h"
|
||||
#include "utils/eloop.h"
|
||||
#include "crypto/sha1.h"
|
||||
#include "crypto/sha256.h"
|
||||
#include "crypto/random.h"
|
||||
#include "wpa_auth.h"
|
||||
#include "wpa_auth_i.h"
|
||||
#include "wpa_auth_ie.h"
|
||||
|
||||
#ifdef CONFIG_PEERKEY
|
||||
|
||||
static void wpa_stsl_step(void *eloop_ctx, void *timeout_ctx)
|
||||
{
|
||||
#if 0
|
||||
struct wpa_authenticator *wpa_auth = eloop_ctx;
|
||||
struct wpa_stsl_negotiation *neg = timeout_ctx;
|
||||
#endif
|
||||
|
||||
/* TODO: ? */
|
||||
}
|
||||
|
||||
|
||||
struct wpa_stsl_search {
|
||||
const u8 *addr;
|
||||
struct wpa_state_machine *sm;
|
||||
};
|
||||
|
||||
|
||||
static int wpa_stsl_select_sta(struct wpa_state_machine *sm, void *ctx)
|
||||
{
|
||||
struct wpa_stsl_search *search = ctx;
|
||||
if (os_memcmp(search->addr, sm->addr, ETH_ALEN) == 0) {
|
||||
search->sm = sm;
|
||||
return 1;
|
||||
}
|
||||
return 0;
|
||||
}
|
||||
|
||||
|
||||
static void wpa_smk_send_error(struct wpa_authenticator *wpa_auth,
|
||||
struct wpa_state_machine *sm, const u8 *peer,
|
||||
u16 mui, u16 error_type)
|
||||
{
|
||||
u8 kde[2 + RSN_SELECTOR_LEN + ETH_ALEN +
|
||||
2 + RSN_SELECTOR_LEN + sizeof(struct rsn_error_kde)];
|
||||
u8 *pos;
|
||||
struct rsn_error_kde error;
|
||||
|
||||
wpa_auth_logger(wpa_auth, sm->addr, LOGGER_DEBUG,
|
||||
"Sending SMK Error");
|
||||
|
||||
pos = kde;
|
||||
|
||||
if (peer) {
|
||||
pos = wpa_add_kde(pos, RSN_KEY_DATA_MAC_ADDR, peer, ETH_ALEN,
|
||||
NULL, 0);
|
||||
}
|
||||
|
||||
error.mui = host_to_be16(mui);
|
||||
error.error_type = host_to_be16(error_type);
|
||||
pos = wpa_add_kde(pos, RSN_KEY_DATA_ERROR,
|
||||
(u8 *) &error, sizeof(error), NULL, 0);
|
||||
|
||||
__wpa_send_eapol(wpa_auth, sm,
|
||||
WPA_KEY_INFO_SECURE | WPA_KEY_INFO_MIC |
|
||||
WPA_KEY_INFO_SMK_MESSAGE | WPA_KEY_INFO_ERROR,
|
||||
NULL, NULL, kde, pos - kde, 0, 0, 0);
|
||||
}
|
||||
|
||||
|
||||
void wpa_smk_m1(struct wpa_authenticator *wpa_auth,
|
||||
struct wpa_state_machine *sm, struct wpa_eapol_key *key)
|
||||
{
|
||||
struct wpa_eapol_ie_parse kde;
|
||||
struct wpa_stsl_search search;
|
||||
u8 *buf, *pos;
|
||||
size_t buf_len;
|
||||
|
||||
if (wpa_parse_kde_ies((const u8 *) (key + 1),
|
||||
WPA_GET_BE16(key->key_data_length), &kde) < 0) {
|
||||
wpa_printf(MSG_INFO, "RSN: Failed to parse KDEs in SMK M1");
|
||||
return;
|
||||
}
|
||||
|
||||
if (kde.rsn_ie == NULL || kde.mac_addr == NULL ||
|
||||
kde.mac_addr_len < ETH_ALEN) {
|
||||
wpa_printf(MSG_INFO, "RSN: No RSN IE or MAC address KDE in "
|
||||
"SMK M1");
|
||||
return;
|
||||
}
|
||||
|
||||
/* Initiator = sm->addr; Peer = kde.mac_addr */
|
||||
|
||||
search.addr = kde.mac_addr;
|
||||
search.sm = NULL;
|
||||
if (wpa_auth_for_each_sta(wpa_auth, wpa_stsl_select_sta, &search) ==
|
||||
0 || search.sm == NULL) {
|
||||
wpa_printf(MSG_DEBUG, "RSN: SMK handshake with " MACSTR
|
||||
" aborted - STA not associated anymore",
|
||||
MAC2STR(kde.mac_addr));
|
||||
wpa_smk_send_error(wpa_auth, sm, kde.mac_addr, STK_MUI_SMK,
|
||||
STK_ERR_STA_NR);
|
||||
/* FIX: wpa_stsl_remove(wpa_auth, neg); */
|
||||
return;
|
||||
}
|
||||
|
||||
buf_len = kde.rsn_ie_len + 2 + RSN_SELECTOR_LEN + ETH_ALEN;
|
||||
buf = os_malloc(buf_len);
|
||||
if (buf == NULL)
|
||||
return;
|
||||
/* Initiator RSN IE */
|
||||
os_memcpy(buf, kde.rsn_ie, kde.rsn_ie_len);
|
||||
pos = buf + kde.rsn_ie_len;
|
||||
/* Initiator MAC Address */
|
||||
pos = wpa_add_kde(pos, RSN_KEY_DATA_MAC_ADDR, sm->addr, ETH_ALEN,
|
||||
NULL, 0);
|
||||
|
||||
/* SMK M2:
|
||||
* EAPOL-Key(S=1, M=1, A=1, I=0, K=0, SM=1, KeyRSC=0, Nonce=INonce,
|
||||
* MIC=MIC, DataKDs=(RSNIE_I, MAC_I KDE)
|
||||
*/
|
||||
|
||||
wpa_auth_logger(wpa_auth, search.sm->addr, LOGGER_DEBUG,
|
||||
"Sending SMK M2");
|
||||
|
||||
__wpa_send_eapol(wpa_auth, search.sm,
|
||||
WPA_KEY_INFO_SECURE | WPA_KEY_INFO_MIC |
|
||||
WPA_KEY_INFO_ACK | WPA_KEY_INFO_SMK_MESSAGE,
|
||||
NULL, key->key_nonce, buf, pos - buf, 0, 0, 0);
|
||||
|
||||
os_free(buf);
|
||||
}
|
||||
|
||||
|
||||
static void wpa_send_smk_m4(struct wpa_authenticator *wpa_auth,
|
||||
struct wpa_state_machine *sm,
|
||||
struct wpa_eapol_key *key,
|
||||
struct wpa_eapol_ie_parse *kde,
|
||||
const u8 *smk)
|
||||
{
|
||||
u8 *buf, *pos;
|
||||
size_t buf_len;
|
||||
u32 lifetime;
|
||||
|
||||
/* SMK M4:
|
||||
* EAPOL-Key(S=1, M=1, A=0, I=1, K=0, SM=1, KeyRSC=0, Nonce=PNonce,
|
||||
* MIC=MIC, DataKDs=(MAC_I KDE, INonce KDE, SMK KDE,
|
||||
* Lifetime KDE)
|
||||
*/
|
||||
|
||||
buf_len = 2 + RSN_SELECTOR_LEN + ETH_ALEN +
|
||||
2 + RSN_SELECTOR_LEN + WPA_NONCE_LEN +
|
||||
2 + RSN_SELECTOR_LEN + PMK_LEN + WPA_NONCE_LEN +
|
||||
2 + RSN_SELECTOR_LEN + sizeof(lifetime);
|
||||
pos = buf = os_malloc(buf_len);
|
||||
if (buf == NULL)
|
||||
return;
|
||||
|
||||
/* Initiator MAC Address */
|
||||
pos = wpa_add_kde(pos, RSN_KEY_DATA_MAC_ADDR, kde->mac_addr, ETH_ALEN,
|
||||
NULL, 0);
|
||||
|
||||
/* Initiator Nonce */
|
||||
pos = wpa_add_kde(pos, RSN_KEY_DATA_NONCE, kde->nonce, WPA_NONCE_LEN,
|
||||
NULL, 0);
|
||||
|
||||
/* SMK with PNonce */
|
||||
pos = wpa_add_kde(pos, RSN_KEY_DATA_SMK, smk, PMK_LEN,
|
||||
key->key_nonce, WPA_NONCE_LEN);
|
||||
|
||||
/* Lifetime */
|
||||
lifetime = htonl(43200); /* dot11RSNAConfigSMKLifetime */
|
||||
pos = wpa_add_kde(pos, RSN_KEY_DATA_LIFETIME,
|
||||
(u8 *) &lifetime, sizeof(lifetime), NULL, 0);
|
||||
|
||||
wpa_auth_logger(sm->wpa_auth, sm->addr, LOGGER_DEBUG,
|
||||
"Sending SMK M4");
|
||||
|
||||
__wpa_send_eapol(wpa_auth, sm,
|
||||
WPA_KEY_INFO_SECURE | WPA_KEY_INFO_MIC |
|
||||
WPA_KEY_INFO_INSTALL | WPA_KEY_INFO_SMK_MESSAGE,
|
||||
NULL, key->key_nonce, buf, pos - buf, 0, 1, 0);
|
||||
|
||||
os_free(buf);
|
||||
}
|
||||
|
||||
|
||||
static void wpa_send_smk_m5(struct wpa_authenticator *wpa_auth,
|
||||
struct wpa_state_machine *sm,
|
||||
struct wpa_eapol_key *key,
|
||||
struct wpa_eapol_ie_parse *kde,
|
||||
const u8 *smk, const u8 *peer)
|
||||
{
|
||||
u8 *buf, *pos;
|
||||
size_t buf_len;
|
||||
u32 lifetime;
|
||||
|
||||
/* SMK M5:
|
||||
* EAPOL-Key(S=1, M=1, A=0, I=0, K=0, SM=1, KeyRSC=0, Nonce=INonce,
|
||||
* MIC=MIC, DataKDs=(RSNIE_P, MAC_P KDE, PNonce, SMK KDE,
|
||||
* Lifetime KDE))
|
||||
*/
|
||||
|
||||
buf_len = kde->rsn_ie_len +
|
||||
2 + RSN_SELECTOR_LEN + ETH_ALEN +
|
||||
2 + RSN_SELECTOR_LEN + WPA_NONCE_LEN +
|
||||
2 + RSN_SELECTOR_LEN + PMK_LEN + WPA_NONCE_LEN +
|
||||
2 + RSN_SELECTOR_LEN + sizeof(lifetime);
|
||||
pos = buf = os_malloc(buf_len);
|
||||
if (buf == NULL)
|
||||
return;
|
||||
|
||||
/* Peer RSN IE */
|
||||
os_memcpy(buf, kde->rsn_ie, kde->rsn_ie_len);
|
||||
pos = buf + kde->rsn_ie_len;
|
||||
|
||||
/* Peer MAC Address */
|
||||
pos = wpa_add_kde(pos, RSN_KEY_DATA_MAC_ADDR, peer, ETH_ALEN, NULL, 0);
|
||||
|
||||
/* PNonce */
|
||||
pos = wpa_add_kde(pos, RSN_KEY_DATA_NONCE, key->key_nonce,
|
||||
WPA_NONCE_LEN, NULL, 0);
|
||||
|
||||
/* SMK and INonce */
|
||||
pos = wpa_add_kde(pos, RSN_KEY_DATA_SMK, smk, PMK_LEN,
|
||||
kde->nonce, WPA_NONCE_LEN);
|
||||
|
||||
/* Lifetime */
|
||||
lifetime = htonl(43200); /* dot11RSNAConfigSMKLifetime */
|
||||
pos = wpa_add_kde(pos, RSN_KEY_DATA_LIFETIME,
|
||||
(u8 *) &lifetime, sizeof(lifetime), NULL, 0);
|
||||
|
||||
wpa_auth_logger(sm->wpa_auth, sm->addr, LOGGER_DEBUG,
|
||||
"Sending SMK M5");
|
||||
|
||||
__wpa_send_eapol(wpa_auth, sm,
|
||||
WPA_KEY_INFO_SECURE | WPA_KEY_INFO_MIC |
|
||||
WPA_KEY_INFO_SMK_MESSAGE,
|
||||
NULL, kde->nonce, buf, pos - buf, 0, 1, 0);
|
||||
|
||||
os_free(buf);
|
||||
}
|
||||
|
||||
|
||||
void wpa_smk_m3(struct wpa_authenticator *wpa_auth,
|
||||
struct wpa_state_machine *sm, struct wpa_eapol_key *key)
|
||||
{
|
||||
struct wpa_eapol_ie_parse kde;
|
||||
struct wpa_stsl_search search;
|
||||
u8 smk[32], buf[ETH_ALEN + 8 + 2 * WPA_NONCE_LEN], *pos;
|
||||
|
||||
if (wpa_parse_kde_ies((const u8 *) (key + 1),
|
||||
WPA_GET_BE16(key->key_data_length), &kde) < 0) {
|
||||
wpa_printf(MSG_INFO, "RSN: Failed to parse KDEs in SMK M3");
|
||||
return;
|
||||
}
|
||||
|
||||
if (kde.rsn_ie == NULL ||
|
||||
kde.mac_addr == NULL || kde.mac_addr_len < ETH_ALEN ||
|
||||
kde.nonce == NULL || kde.nonce_len < WPA_NONCE_LEN) {
|
||||
wpa_printf(MSG_INFO, "RSN: No RSN IE, MAC address KDE, or "
|
||||
"Nonce KDE in SMK M3");
|
||||
return;
|
||||
}
|
||||
|
||||
/* Peer = sm->addr; Initiator = kde.mac_addr;
|
||||
* Peer Nonce = key->key_nonce; Initiator Nonce = kde.nonce */
|
||||
|
||||
search.addr = kde.mac_addr;
|
||||
search.sm = NULL;
|
||||
if (wpa_auth_for_each_sta(wpa_auth, wpa_stsl_select_sta, &search) ==
|
||||
0 || search.sm == NULL) {
|
||||
wpa_printf(MSG_DEBUG, "RSN: SMK handshake with " MACSTR
|
||||
" aborted - STA not associated anymore",
|
||||
MAC2STR(kde.mac_addr));
|
||||
wpa_smk_send_error(wpa_auth, sm, kde.mac_addr, STK_MUI_SMK,
|
||||
STK_ERR_STA_NR);
|
||||
/* FIX: wpa_stsl_remove(wpa_auth, neg); */
|
||||
return;
|
||||
}
|
||||
|
||||
if (random_get_bytes(smk, PMK_LEN)) {
|
||||
wpa_printf(MSG_DEBUG, "RSN: Failed to generate SMK");
|
||||
return;
|
||||
}
|
||||
|
||||
/* SMK = PRF-256(Random number, "SMK Derivation",
|
||||
* AA || Time || INonce || PNonce)
|
||||
*/
|
||||
os_memcpy(buf, wpa_auth->addr, ETH_ALEN);
|
||||
pos = buf + ETH_ALEN;
|
||||
wpa_get_ntp_timestamp(pos);
|
||||
pos += 8;
|
||||
os_memcpy(pos, kde.nonce, WPA_NONCE_LEN);
|
||||
pos += WPA_NONCE_LEN;
|
||||
os_memcpy(pos, key->key_nonce, WPA_NONCE_LEN);
|
||||
#ifdef CONFIG_IEEE80211W
|
||||
sha256_prf(smk, PMK_LEN, "SMK Derivation", buf, sizeof(buf),
|
||||
smk, PMK_LEN);
|
||||
#else /* CONFIG_IEEE80211W */
|
||||
sha1_prf(smk, PMK_LEN, "SMK Derivation", buf, sizeof(buf),
|
||||
smk, PMK_LEN);
|
||||
#endif /* CONFIG_IEEE80211W */
|
||||
|
||||
wpa_hexdump_key(MSG_DEBUG, "RSN: SMK", smk, PMK_LEN);
|
||||
|
||||
wpa_send_smk_m4(wpa_auth, sm, key, &kde, smk);
|
||||
wpa_send_smk_m5(wpa_auth, search.sm, key, &kde, smk, sm->addr);
|
||||
|
||||
/* Authenticator does not need SMK anymore and it is required to forget
|
||||
* it. */
|
||||
os_memset(smk, 0, sizeof(*smk));
|
||||
}
|
||||
|
||||
|
||||
void wpa_smk_error(struct wpa_authenticator *wpa_auth,
|
||||
struct wpa_state_machine *sm, struct wpa_eapol_key *key)
|
||||
{
|
||||
struct wpa_eapol_ie_parse kde;
|
||||
struct wpa_stsl_search search;
|
||||
struct rsn_error_kde error;
|
||||
u16 mui, error_type;
|
||||
|
||||
if (wpa_parse_kde_ies((const u8 *) (key + 1),
|
||||
WPA_GET_BE16(key->key_data_length), &kde) < 0) {
|
||||
wpa_printf(MSG_INFO, "RSN: Failed to parse KDEs in SMK Error");
|
||||
return;
|
||||
}
|
||||
|
||||
if (kde.mac_addr == NULL || kde.mac_addr_len < ETH_ALEN ||
|
||||
kde.error == NULL || kde.error_len < sizeof(error)) {
|
||||
wpa_printf(MSG_INFO, "RSN: No MAC address or Error KDE in "
|
||||
"SMK Error");
|
||||
return;
|
||||
}
|
||||
|
||||
search.addr = kde.mac_addr;
|
||||
search.sm = NULL;
|
||||
if (wpa_auth_for_each_sta(wpa_auth, wpa_stsl_select_sta, &search) ==
|
||||
0 || search.sm == NULL) {
|
||||
wpa_printf(MSG_DEBUG, "RSN: Peer STA " MACSTR " not "
|
||||
"associated for SMK Error message from " MACSTR,
|
||||
MAC2STR(kde.mac_addr), MAC2STR(sm->addr));
|
||||
return;
|
||||
}
|
||||
|
||||
os_memcpy(&error, kde.error, sizeof(error));
|
||||
mui = be_to_host16(error.mui);
|
||||
error_type = be_to_host16(error.error_type);
|
||||
wpa_auth_vlogger(wpa_auth, sm->addr, LOGGER_INFO,
|
||||
"STA reported SMK Error: Peer " MACSTR
|
||||
" MUI %d Error Type %d",
|
||||
MAC2STR(kde.mac_addr), mui, error_type);
|
||||
|
||||
wpa_smk_send_error(wpa_auth, search.sm, sm->addr, mui, error_type);
|
||||
}
|
||||
|
||||
|
||||
int wpa_stsl_remove(struct wpa_authenticator *wpa_auth,
|
||||
struct wpa_stsl_negotiation *neg)
|
||||
{
|
||||
struct wpa_stsl_negotiation *pos, *prev;
|
||||
|
||||
if (wpa_auth == NULL)
|
||||
return -1;
|
||||
pos = wpa_auth->stsl_negotiations;
|
||||
prev = NULL;
|
||||
while (pos) {
|
||||
if (pos == neg) {
|
||||
if (prev)
|
||||
prev->next = pos->next;
|
||||
else
|
||||
wpa_auth->stsl_negotiations = pos->next;
|
||||
|
||||
eloop_cancel_timeout(wpa_stsl_step, wpa_auth, pos);
|
||||
os_free(pos);
|
||||
return 0;
|
||||
}
|
||||
prev = pos;
|
||||
pos = pos->next;
|
||||
}
|
||||
|
||||
return -1;
|
||||
}
|
||||
|
||||
#endif /* CONFIG_PEERKEY */
|
425
hostapd-0.8/src/ap/pmksa_cache_auth.c
Normal file
425
hostapd-0.8/src/ap/pmksa_cache_auth.c
Normal file
|
@ -0,0 +1,425 @@
|
|||
/*
|
||||
* hostapd - PMKSA cache for IEEE 802.11i RSN
|
||||
* 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.
|
||||
*/
|
||||
|
||||
#include "utils/includes.h"
|
||||
|
||||
#include "utils/common.h"
|
||||
#include "utils/eloop.h"
|
||||
#include "eapol_auth/eapol_auth_sm.h"
|
||||
#include "eapol_auth/eapol_auth_sm_i.h"
|
||||
#include "sta_info.h"
|
||||
#include "ap_config.h"
|
||||
#include "pmksa_cache_auth.h"
|
||||
|
||||
|
||||
static const int pmksa_cache_max_entries = 1024;
|
||||
static const int dot11RSNAConfigPMKLifetime = 43200;
|
||||
|
||||
struct rsn_pmksa_cache {
|
||||
#define PMKID_HASH_SIZE 128
|
||||
#define PMKID_HASH(pmkid) (unsigned int) ((pmkid)[0] & 0x7f)
|
||||
struct rsn_pmksa_cache_entry *pmkid[PMKID_HASH_SIZE];
|
||||
struct rsn_pmksa_cache_entry *pmksa;
|
||||
int pmksa_count;
|
||||
|
||||
void (*free_cb)(struct rsn_pmksa_cache_entry *entry, void *ctx);
|
||||
void *ctx;
|
||||
};
|
||||
|
||||
|
||||
static void pmksa_cache_set_expiration(struct rsn_pmksa_cache *pmksa);
|
||||
|
||||
|
||||
static void _pmksa_cache_free_entry(struct rsn_pmksa_cache_entry *entry)
|
||||
{
|
||||
if (entry == NULL)
|
||||
return;
|
||||
os_free(entry->identity);
|
||||
#ifndef CONFIG_NO_RADIUS
|
||||
radius_free_class(&entry->radius_class);
|
||||
#endif /* CONFIG_NO_RADIUS */
|
||||
os_free(entry);
|
||||
}
|
||||
|
||||
|
||||
static void pmksa_cache_free_entry(struct rsn_pmksa_cache *pmksa,
|
||||
struct rsn_pmksa_cache_entry *entry)
|
||||
{
|
||||
struct rsn_pmksa_cache_entry *pos, *prev;
|
||||
|
||||
pmksa->pmksa_count--;
|
||||
pmksa->free_cb(entry, pmksa->ctx);
|
||||
pos = pmksa->pmkid[PMKID_HASH(entry->pmkid)];
|
||||
prev = NULL;
|
||||
while (pos) {
|
||||
if (pos == entry) {
|
||||
if (prev != NULL) {
|
||||
prev->hnext = pos->hnext;
|
||||
} else {
|
||||
pmksa->pmkid[PMKID_HASH(entry->pmkid)] =
|
||||
pos->hnext;
|
||||
}
|
||||
break;
|
||||
}
|
||||
prev = pos;
|
||||
pos = pos->hnext;
|
||||
}
|
||||
|
||||
pos = pmksa->pmksa;
|
||||
prev = NULL;
|
||||
while (pos) {
|
||||
if (pos == entry) {
|
||||
if (prev != NULL)
|
||||
prev->next = pos->next;
|
||||
else
|
||||
pmksa->pmksa = pos->next;
|
||||
break;
|
||||
}
|
||||
prev = pos;
|
||||
pos = pos->next;
|
||||
}
|
||||
_pmksa_cache_free_entry(entry);
|
||||
}
|
||||
|
||||
|
||||
static void pmksa_cache_expire(void *eloop_ctx, void *timeout_ctx)
|
||||
{
|
||||
struct rsn_pmksa_cache *pmksa = eloop_ctx;
|
||||
struct os_time now;
|
||||
|
||||
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);
|
||||
}
|
||||
|
||||
pmksa_cache_set_expiration(pmksa);
|
||||
}
|
||||
|
||||
|
||||
static void pmksa_cache_set_expiration(struct rsn_pmksa_cache *pmksa)
|
||||
{
|
||||
int sec;
|
||||
struct os_time now;
|
||||
|
||||
eloop_cancel_timeout(pmksa_cache_expire, pmksa, NULL);
|
||||
if (pmksa->pmksa == NULL)
|
||||
return;
|
||||
os_get_time(&now);
|
||||
sec = pmksa->pmksa->expiration - now.sec;
|
||||
if (sec < 0)
|
||||
sec = 0;
|
||||
eloop_register_timeout(sec + 1, 0, pmksa_cache_expire, pmksa, NULL);
|
||||
}
|
||||
|
||||
|
||||
static void pmksa_cache_from_eapol_data(struct rsn_pmksa_cache_entry *entry,
|
||||
struct eapol_state_machine *eapol)
|
||||
{
|
||||
if (eapol == NULL)
|
||||
return;
|
||||
|
||||
if (eapol->identity) {
|
||||
entry->identity = os_malloc(eapol->identity_len);
|
||||
if (entry->identity) {
|
||||
entry->identity_len = eapol->identity_len;
|
||||
os_memcpy(entry->identity, eapol->identity,
|
||||
eapol->identity_len);
|
||||
}
|
||||
}
|
||||
|
||||
#ifndef CONFIG_NO_RADIUS
|
||||
radius_copy_class(&entry->radius_class, &eapol->radius_class);
|
||||
#endif /* CONFIG_NO_RADIUS */
|
||||
|
||||
entry->eap_type_authsrv = eapol->eap_type_authsrv;
|
||||
entry->vlan_id = ((struct sta_info *) eapol->sta)->vlan_id;
|
||||
}
|
||||
|
||||
|
||||
void pmksa_cache_to_eapol_data(struct rsn_pmksa_cache_entry *entry,
|
||||
struct eapol_state_machine *eapol)
|
||||
{
|
||||
if (entry == NULL || eapol == NULL)
|
||||
return;
|
||||
|
||||
if (entry->identity) {
|
||||
os_free(eapol->identity);
|
||||
eapol->identity = os_malloc(entry->identity_len);
|
||||
if (eapol->identity) {
|
||||
eapol->identity_len = entry->identity_len;
|
||||
os_memcpy(eapol->identity, entry->identity,
|
||||
entry->identity_len);
|
||||
}
|
||||
wpa_hexdump_ascii(MSG_DEBUG, "STA identity from PMKSA",
|
||||
eapol->identity, eapol->identity_len);
|
||||
}
|
||||
|
||||
#ifndef CONFIG_NO_RADIUS
|
||||
radius_free_class(&eapol->radius_class);
|
||||
radius_copy_class(&eapol->radius_class, &entry->radius_class);
|
||||
#endif /* CONFIG_NO_RADIUS */
|
||||
if (eapol->radius_class.attr) {
|
||||
wpa_printf(MSG_DEBUG, "Copied %lu Class attribute(s) from "
|
||||
"PMKSA", (unsigned long) eapol->radius_class.count);
|
||||
}
|
||||
|
||||
eapol->eap_type_authsrv = entry->eap_type_authsrv;
|
||||
((struct sta_info *) eapol->sta)->vlan_id = entry->vlan_id;
|
||||
}
|
||||
|
||||
|
||||
static void pmksa_cache_link_entry(struct rsn_pmksa_cache *pmksa,
|
||||
struct rsn_pmksa_cache_entry *entry)
|
||||
{
|
||||
struct rsn_pmksa_cache_entry *pos, *prev;
|
||||
|
||||
/* Add the new entry; order by expiration time */
|
||||
pos = pmksa->pmksa;
|
||||
prev = NULL;
|
||||
while (pos) {
|
||||
if (pos->expiration > entry->expiration)
|
||||
break;
|
||||
prev = pos;
|
||||
pos = pos->next;
|
||||
}
|
||||
if (prev == NULL) {
|
||||
entry->next = pmksa->pmksa;
|
||||
pmksa->pmksa = entry;
|
||||
} else {
|
||||
entry->next = prev->next;
|
||||
prev->next = entry;
|
||||
}
|
||||
entry->hnext = pmksa->pmkid[PMKID_HASH(entry->pmkid)];
|
||||
pmksa->pmkid[PMKID_HASH(entry->pmkid)] = entry;
|
||||
|
||||
pmksa->pmksa_count++;
|
||||
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);
|
||||
}
|
||||
|
||||
|
||||
/**
|
||||
* pmksa_cache_auth_add - Add a PMKSA cache entry
|
||||
* @pmksa: Pointer to PMKSA cache data from pmksa_cache_auth_init()
|
||||
* @pmk: The new pairwise master key
|
||||
* @pmk_len: PMK length in bytes, usually PMK_LEN (32)
|
||||
* @aa: Authenticator address
|
||||
* @spa: Supplicant address
|
||||
* @session_timeout: Session timeout
|
||||
* @eapol: Pointer to EAPOL state machine data
|
||||
* @akmp: WPA_KEY_MGMT_* used in key derivation
|
||||
* Returns: Pointer to the added PMKSA cache entry or %NULL on error
|
||||
*
|
||||
* This function create a PMKSA entry for a new PMK and adds it to the PMKSA
|
||||
* cache. If an old entry is already in the cache for the same Supplicant,
|
||||
* this entry will be replaced with the new entry. PMKID will be calculated
|
||||
* based on the PMK.
|
||||
*/
|
||||
struct rsn_pmksa_cache_entry *
|
||||
pmksa_cache_auth_add(struct rsn_pmksa_cache *pmksa,
|
||||
const u8 *pmk, size_t pmk_len,
|
||||
const u8 *aa, const u8 *spa, int session_timeout,
|
||||
struct eapol_state_machine *eapol, int akmp)
|
||||
{
|
||||
struct rsn_pmksa_cache_entry *entry, *pos;
|
||||
struct os_time now;
|
||||
|
||||
if (pmk_len > PMK_LEN)
|
||||
return NULL;
|
||||
|
||||
entry = os_zalloc(sizeof(*entry));
|
||||
if (entry == NULL)
|
||||
return NULL;
|
||||
os_memcpy(entry->pmk, pmk, pmk_len);
|
||||
entry->pmk_len = pmk_len;
|
||||
rsn_pmkid(pmk, pmk_len, aa, spa, entry->pmkid,
|
||||
wpa_key_mgmt_sha256(akmp));
|
||||
os_get_time(&now);
|
||||
entry->expiration = now.sec;
|
||||
if (session_timeout > 0)
|
||||
entry->expiration += session_timeout;
|
||||
else
|
||||
entry->expiration += dot11RSNAConfigPMKLifetime;
|
||||
entry->akmp = akmp;
|
||||
os_memcpy(entry->spa, spa, ETH_ALEN);
|
||||
pmksa_cache_from_eapol_data(entry, eapol);
|
||||
|
||||
/* Replace an old entry for the same STA (if found) with the new entry
|
||||
*/
|
||||
pos = pmksa_cache_auth_get(pmksa, spa, NULL);
|
||||
if (pos)
|
||||
pmksa_cache_free_entry(pmksa, pos);
|
||||
|
||||
if (pmksa->pmksa_count >= pmksa_cache_max_entries && pmksa->pmksa) {
|
||||
/* Remove the oldest entry to make room for the new entry */
|
||||
wpa_printf(MSG_DEBUG, "RSN: removed the oldest PMKSA cache "
|
||||
"entry (for " MACSTR ") to make room for new one",
|
||||
MAC2STR(pmksa->pmksa->spa));
|
||||
pmksa_cache_free_entry(pmksa, pmksa->pmksa);
|
||||
}
|
||||
|
||||
pmksa_cache_link_entry(pmksa, entry);
|
||||
|
||||
return entry;
|
||||
}
|
||||
|
||||
|
||||
struct rsn_pmksa_cache_entry *
|
||||
pmksa_cache_add_okc(struct rsn_pmksa_cache *pmksa,
|
||||
const struct rsn_pmksa_cache_entry *old_entry,
|
||||
const u8 *aa, const u8 *pmkid)
|
||||
{
|
||||
struct rsn_pmksa_cache_entry *entry;
|
||||
|
||||
entry = os_zalloc(sizeof(*entry));
|
||||
if (entry == NULL)
|
||||
return NULL;
|
||||
os_memcpy(entry->pmkid, pmkid, PMKID_LEN);
|
||||
os_memcpy(entry->pmk, old_entry->pmk, old_entry->pmk_len);
|
||||
entry->pmk_len = old_entry->pmk_len;
|
||||
entry->expiration = old_entry->expiration;
|
||||
entry->akmp = old_entry->akmp;
|
||||
os_memcpy(entry->spa, old_entry->spa, ETH_ALEN);
|
||||
entry->opportunistic = 1;
|
||||
if (old_entry->identity) {
|
||||
entry->identity = os_malloc(old_entry->identity_len);
|
||||
if (entry->identity) {
|
||||
entry->identity_len = old_entry->identity_len;
|
||||
os_memcpy(entry->identity, old_entry->identity,
|
||||
old_entry->identity_len);
|
||||
}
|
||||
}
|
||||
#ifndef CONFIG_NO_RADIUS
|
||||
radius_copy_class(&entry->radius_class, &old_entry->radius_class);
|
||||
#endif /* CONFIG_NO_RADIUS */
|
||||
entry->eap_type_authsrv = old_entry->eap_type_authsrv;
|
||||
entry->vlan_id = old_entry->vlan_id;
|
||||
entry->opportunistic = 1;
|
||||
|
||||
pmksa_cache_link_entry(pmksa, entry);
|
||||
|
||||
return entry;
|
||||
}
|
||||
|
||||
|
||||
/**
|
||||
* pmksa_cache_auth_deinit - Free all entries in PMKSA cache
|
||||
* @pmksa: Pointer to PMKSA cache data from pmksa_cache_auth_init()
|
||||
*/
|
||||
void pmksa_cache_auth_deinit(struct rsn_pmksa_cache *pmksa)
|
||||
{
|
||||
struct rsn_pmksa_cache_entry *entry, *prev;
|
||||
int i;
|
||||
|
||||
if (pmksa == NULL)
|
||||
return;
|
||||
|
||||
entry = pmksa->pmksa;
|
||||
while (entry) {
|
||||
prev = entry;
|
||||
entry = entry->next;
|
||||
_pmksa_cache_free_entry(prev);
|
||||
}
|
||||
eloop_cancel_timeout(pmksa_cache_expire, pmksa, NULL);
|
||||
for (i = 0; i < PMKID_HASH_SIZE; i++)
|
||||
pmksa->pmkid[i] = NULL;
|
||||
os_free(pmksa);
|
||||
}
|
||||
|
||||
|
||||
/**
|
||||
* pmksa_cache_auth_get - Fetch a PMKSA cache entry
|
||||
* @pmksa: Pointer to PMKSA cache data from pmksa_cache_auth_init()
|
||||
* @spa: Supplicant address or %NULL to match any
|
||||
* @pmkid: PMKID or %NULL to match any
|
||||
* Returns: Pointer to PMKSA cache entry or %NULL if no match was found
|
||||
*/
|
||||
struct rsn_pmksa_cache_entry *
|
||||
pmksa_cache_auth_get(struct rsn_pmksa_cache *pmksa,
|
||||
const u8 *spa, const u8 *pmkid)
|
||||
{
|
||||
struct rsn_pmksa_cache_entry *entry;
|
||||
|
||||
if (pmkid)
|
||||
entry = pmksa->pmkid[PMKID_HASH(pmkid)];
|
||||
else
|
||||
entry = pmksa->pmksa;
|
||||
while (entry) {
|
||||
if ((spa == NULL ||
|
||||
os_memcmp(entry->spa, spa, ETH_ALEN) == 0) &&
|
||||
(pmkid == NULL ||
|
||||
os_memcmp(entry->pmkid, pmkid, PMKID_LEN) == 0))
|
||||
return entry;
|
||||
entry = pmkid ? entry->hnext : entry->next;
|
||||
}
|
||||
return NULL;
|
||||
}
|
||||
|
||||
|
||||
/**
|
||||
* pmksa_cache_get_okc - Fetch a PMKSA cache entry using OKC
|
||||
* @pmksa: Pointer to PMKSA cache data from pmksa_cache_auth_init()
|
||||
* @aa: Authenticator address
|
||||
* @spa: Supplicant address
|
||||
* @pmkid: PMKID
|
||||
* Returns: Pointer to PMKSA cache entry or %NULL if no match was found
|
||||
*
|
||||
* Use opportunistic key caching (OKC) to find a PMK for a supplicant.
|
||||
*/
|
||||
struct rsn_pmksa_cache_entry * pmksa_cache_get_okc(
|
||||
struct rsn_pmksa_cache *pmksa, const u8 *aa, const u8 *spa,
|
||||
const u8 *pmkid)
|
||||
{
|
||||
struct rsn_pmksa_cache_entry *entry;
|
||||
u8 new_pmkid[PMKID_LEN];
|
||||
|
||||
entry = pmksa->pmksa;
|
||||
while (entry) {
|
||||
if (os_memcmp(entry->spa, spa, ETH_ALEN) != 0)
|
||||
continue;
|
||||
rsn_pmkid(entry->pmk, entry->pmk_len, aa, spa, new_pmkid,
|
||||
wpa_key_mgmt_sha256(entry->akmp));
|
||||
if (os_memcmp(new_pmkid, pmkid, PMKID_LEN) == 0)
|
||||
return entry;
|
||||
entry = entry->next;
|
||||
}
|
||||
return NULL;
|
||||
}
|
||||
|
||||
|
||||
/**
|
||||
* pmksa_cache_auth_init - Initialize PMKSA cache
|
||||
* @free_cb: Callback function to be called when a PMKSA cache entry is freed
|
||||
* @ctx: Context pointer for free_cb function
|
||||
* Returns: Pointer to PMKSA cache data or %NULL on failure
|
||||
*/
|
||||
struct rsn_pmksa_cache *
|
||||
pmksa_cache_auth_init(void (*free_cb)(struct rsn_pmksa_cache_entry *entry,
|
||||
void *ctx), void *ctx)
|
||||
{
|
||||
struct rsn_pmksa_cache *pmksa;
|
||||
|
||||
pmksa = os_zalloc(sizeof(*pmksa));
|
||||
if (pmksa) {
|
||||
pmksa->free_cb = free_cb;
|
||||
pmksa->ctx = ctx;
|
||||
}
|
||||
|
||||
return pmksa;
|
||||
}
|
64
hostapd-0.8/src/ap/pmksa_cache_auth.h
Normal file
64
hostapd-0.8/src/ap/pmksa_cache_auth.h
Normal file
|
@ -0,0 +1,64 @@
|
|||
/*
|
||||
* hostapd - PMKSA cache for IEEE 802.11i RSN
|
||||
* 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.
|
||||
*/
|
||||
|
||||
#ifndef PMKSA_CACHE_H
|
||||
#define PMKSA_CACHE_H
|
||||
|
||||
#include "radius/radius.h"
|
||||
|
||||
/**
|
||||
* struct rsn_pmksa_cache_entry - PMKSA cache entry
|
||||
*/
|
||||
struct rsn_pmksa_cache_entry {
|
||||
struct rsn_pmksa_cache_entry *next, *hnext;
|
||||
u8 pmkid[PMKID_LEN];
|
||||
u8 pmk[PMK_LEN];
|
||||
size_t pmk_len;
|
||||
os_time_t expiration;
|
||||
int akmp; /* WPA_KEY_MGMT_* */
|
||||
u8 spa[ETH_ALEN];
|
||||
|
||||
u8 *identity;
|
||||
size_t identity_len;
|
||||
struct radius_class_data radius_class;
|
||||
u8 eap_type_authsrv;
|
||||
int vlan_id;
|
||||
int opportunistic;
|
||||
};
|
||||
|
||||
struct rsn_pmksa_cache;
|
||||
|
||||
struct rsn_pmksa_cache *
|
||||
pmksa_cache_auth_init(void (*free_cb)(struct rsn_pmksa_cache_entry *entry,
|
||||
void *ctx), void *ctx);
|
||||
void pmksa_cache_auth_deinit(struct rsn_pmksa_cache *pmksa);
|
||||
struct rsn_pmksa_cache_entry *
|
||||
pmksa_cache_auth_get(struct rsn_pmksa_cache *pmksa,
|
||||
const u8 *spa, const u8 *pmkid);
|
||||
struct rsn_pmksa_cache_entry * pmksa_cache_get_okc(
|
||||
struct rsn_pmksa_cache *pmksa, const u8 *spa, const u8 *aa,
|
||||
const u8 *pmkid);
|
||||
struct rsn_pmksa_cache_entry *
|
||||
pmksa_cache_auth_add(struct rsn_pmksa_cache *pmksa,
|
||||
const u8 *pmk, size_t pmk_len,
|
||||
const u8 *aa, const u8 *spa, int session_timeout,
|
||||
struct eapol_state_machine *eapol, int akmp);
|
||||
struct rsn_pmksa_cache_entry *
|
||||
pmksa_cache_add_okc(struct rsn_pmksa_cache *pmksa,
|
||||
const struct rsn_pmksa_cache_entry *old_entry,
|
||||
const u8 *aa, const u8 *pmkid);
|
||||
void pmksa_cache_to_eapol_data(struct rsn_pmksa_cache_entry *entry,
|
||||
struct eapol_state_machine *eapol);
|
||||
|
||||
#endif /* PMKSA_CACHE_H */
|
279
hostapd-0.8/src/ap/preauth_auth.c
Normal file
279
hostapd-0.8/src/ap/preauth_auth.c
Normal file
|
@ -0,0 +1,279 @@
|
|||
/*
|
||||
* 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.
|
||||
*/
|
||||
|
||||
#include "utils/includes.h"
|
||||
|
||||
#ifdef CONFIG_RSN_PREAUTH
|
||||
|
||||
#include "utils/common.h"
|
||||
#include "utils/eloop.h"
|
||||
#include "l2_packet/l2_packet.h"
|
||||
#include "common/wpa_common.h"
|
||||
#include "eapol_auth/eapol_auth_sm.h"
|
||||
#include "eapol_auth/eapol_auth_sm_i.h"
|
||||
#include "hostapd.h"
|
||||
#include "ap_config.h"
|
||||
#include "ieee802_1x.h"
|
||||
#include "sta_info.h"
|
||||
#include "wpa_auth.h"
|
||||
#include "preauth_auth.h"
|
||||
|
||||
#ifndef ETH_P_PREAUTH
|
||||
#define ETH_P_PREAUTH 0x88C7 /* IEEE 802.11i pre-authentication */
|
||||
#endif /* ETH_P_PREAUTH */
|
||||
|
||||
static const int dot11RSNAConfigPMKLifetime = 43200;
|
||||
|
||||
struct rsn_preauth_interface {
|
||||
struct rsn_preauth_interface *next;
|
||||
struct hostapd_data *hapd;
|
||||
struct l2_packet_data *l2;
|
||||
char *ifname;
|
||||
int ifindex;
|
||||
};
|
||||
|
||||
|
||||
static void rsn_preauth_receive(void *ctx, const u8 *src_addr,
|
||||
const u8 *buf, size_t len)
|
||||
{
|
||||
struct rsn_preauth_interface *piface = ctx;
|
||||
struct hostapd_data *hapd = piface->hapd;
|
||||
struct ieee802_1x_hdr *hdr;
|
||||
struct sta_info *sta;
|
||||
struct l2_ethhdr *ethhdr;
|
||||
|
||||
wpa_printf(MSG_DEBUG, "RSN: receive pre-auth packet "
|
||||
"from interface '%s'", piface->ifname);
|
||||
if (len < sizeof(*ethhdr) + sizeof(*hdr)) {
|
||||
wpa_printf(MSG_DEBUG, "RSN: too short pre-auth packet "
|
||||
"(len=%lu)", (unsigned long) len);
|
||||
return;
|
||||
}
|
||||
|
||||
ethhdr = (struct l2_ethhdr *) buf;
|
||||
hdr = (struct ieee802_1x_hdr *) (ethhdr + 1);
|
||||
|
||||
if (os_memcmp(ethhdr->h_dest, hapd->own_addr, ETH_ALEN) != 0) {
|
||||
wpa_printf(MSG_DEBUG, "RSN: pre-auth for foreign address "
|
||||
MACSTR, MAC2STR(ethhdr->h_dest));
|
||||
return;
|
||||
}
|
||||
|
||||
sta = ap_get_sta(hapd, ethhdr->h_source);
|
||||
if (sta && (sta->flags & WLAN_STA_ASSOC)) {
|
||||
wpa_printf(MSG_DEBUG, "RSN: pre-auth for already association "
|
||||
"STA " MACSTR, MAC2STR(sta->addr));
|
||||
return;
|
||||
}
|
||||
if (!sta && hdr->type == IEEE802_1X_TYPE_EAPOL_START) {
|
||||
sta = ap_sta_add(hapd, ethhdr->h_source);
|
||||
if (sta == NULL)
|
||||
return;
|
||||
sta->flags = WLAN_STA_PREAUTH;
|
||||
|
||||
ieee802_1x_new_station(hapd, sta);
|
||||
if (sta->eapol_sm == NULL) {
|
||||
ap_free_sta(hapd, sta);
|
||||
sta = NULL;
|
||||
} else {
|
||||
sta->eapol_sm->radius_identifier = -1;
|
||||
sta->eapol_sm->portValid = TRUE;
|
||||
sta->eapol_sm->flags |= EAPOL_SM_PREAUTH;
|
||||
}
|
||||
}
|
||||
if (sta == NULL)
|
||||
return;
|
||||
sta->preauth_iface = piface;
|
||||
ieee802_1x_receive(hapd, ethhdr->h_source, (u8 *) (ethhdr + 1),
|
||||
len - sizeof(*ethhdr));
|
||||
}
|
||||
|
||||
|
||||
static int rsn_preauth_iface_add(struct hostapd_data *hapd, const char *ifname)
|
||||
{
|
||||
struct rsn_preauth_interface *piface;
|
||||
|
||||
wpa_printf(MSG_DEBUG, "RSN pre-auth interface '%s'", ifname);
|
||||
|
||||
piface = os_zalloc(sizeof(*piface));
|
||||
if (piface == NULL)
|
||||
return -1;
|
||||
piface->hapd = hapd;
|
||||
|
||||
piface->ifname = os_strdup(ifname);
|
||||
if (piface->ifname == NULL) {
|
||||
goto fail1;
|
||||
}
|
||||
|
||||
piface->l2 = l2_packet_init(piface->ifname, NULL, ETH_P_PREAUTH,
|
||||
rsn_preauth_receive, piface, 1);
|
||||
if (piface->l2 == NULL) {
|
||||
wpa_printf(MSG_ERROR, "Failed to open register layer 2 access "
|
||||
"to ETH_P_PREAUTH");
|
||||
goto fail2;
|
||||
}
|
||||
|
||||
piface->next = hapd->preauth_iface;
|
||||
hapd->preauth_iface = piface;
|
||||
return 0;
|
||||
|
||||
fail2:
|
||||
os_free(piface->ifname);
|
||||
fail1:
|
||||
os_free(piface);
|
||||
return -1;
|
||||
}
|
||||
|
||||
|
||||
void rsn_preauth_iface_deinit(struct hostapd_data *hapd)
|
||||
{
|
||||
struct rsn_preauth_interface *piface, *prev;
|
||||
|
||||
piface = hapd->preauth_iface;
|
||||
hapd->preauth_iface = NULL;
|
||||
while (piface) {
|
||||
prev = piface;
|
||||
piface = piface->next;
|
||||
l2_packet_deinit(prev->l2);
|
||||
os_free(prev->ifname);
|
||||
os_free(prev);
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
int rsn_preauth_iface_init(struct hostapd_data *hapd)
|
||||
{
|
||||
char *tmp, *start, *end;
|
||||
|
||||
if (hapd->conf->rsn_preauth_interfaces == NULL)
|
||||
return 0;
|
||||
|
||||
tmp = os_strdup(hapd->conf->rsn_preauth_interfaces);
|
||||
if (tmp == NULL)
|
||||
return -1;
|
||||
start = tmp;
|
||||
for (;;) {
|
||||
while (*start == ' ')
|
||||
start++;
|
||||
if (*start == '\0')
|
||||
break;
|
||||
end = os_strchr(start, ' ');
|
||||
if (end)
|
||||
*end = '\0';
|
||||
|
||||
if (rsn_preauth_iface_add(hapd, start)) {
|
||||
rsn_preauth_iface_deinit(hapd);
|
||||
os_free(tmp);
|
||||
return -1;
|
||||
}
|
||||
|
||||
if (end)
|
||||
start = end + 1;
|
||||
else
|
||||
break;
|
||||
}
|
||||
os_free(tmp);
|
||||
return 0;
|
||||
}
|
||||
|
||||
|
||||
static void rsn_preauth_finished_cb(void *eloop_ctx, void *timeout_ctx)
|
||||
{
|
||||
struct hostapd_data *hapd = eloop_ctx;
|
||||
struct sta_info *sta = timeout_ctx;
|
||||
wpa_printf(MSG_DEBUG, "RSN: Removing pre-authentication STA entry for "
|
||||
MACSTR, MAC2STR(sta->addr));
|
||||
ap_free_sta(hapd, sta);
|
||||
}
|
||||
|
||||
|
||||
void rsn_preauth_finished(struct hostapd_data *hapd, struct sta_info *sta,
|
||||
int success)
|
||||
{
|
||||
const u8 *key;
|
||||
size_t len;
|
||||
hostapd_logger(hapd, sta->addr, HOSTAPD_MODULE_WPA,
|
||||
HOSTAPD_LEVEL_INFO, "pre-authentication %s",
|
||||
success ? "succeeded" : "failed");
|
||||
|
||||
key = ieee802_1x_get_key(sta->eapol_sm, &len);
|
||||
if (len > PMK_LEN)
|
||||
len = PMK_LEN;
|
||||
if (success && key) {
|
||||
if (wpa_auth_pmksa_add_preauth(hapd->wpa_auth, key, len,
|
||||
sta->addr,
|
||||
dot11RSNAConfigPMKLifetime,
|
||||
sta->eapol_sm) == 0) {
|
||||
hostapd_logger(hapd, sta->addr, HOSTAPD_MODULE_WPA,
|
||||
HOSTAPD_LEVEL_DEBUG,
|
||||
"added PMKSA cache entry (pre-auth)");
|
||||
} else {
|
||||
hostapd_logger(hapd, sta->addr, HOSTAPD_MODULE_WPA,
|
||||
HOSTAPD_LEVEL_DEBUG,
|
||||
"failed to add PMKSA cache entry "
|
||||
"(pre-auth)");
|
||||
}
|
||||
}
|
||||
|
||||
/*
|
||||
* Finish STA entry removal from timeout in order to avoid freeing
|
||||
* STA data before the caller has finished processing.
|
||||
*/
|
||||
eloop_register_timeout(0, 0, rsn_preauth_finished_cb, hapd, sta);
|
||||
}
|
||||
|
||||
|
||||
void rsn_preauth_send(struct hostapd_data *hapd, struct sta_info *sta,
|
||||
u8 *buf, size_t len)
|
||||
{
|
||||
struct rsn_preauth_interface *piface;
|
||||
struct l2_ethhdr *ethhdr;
|
||||
|
||||
piface = hapd->preauth_iface;
|
||||
while (piface) {
|
||||
if (piface == sta->preauth_iface)
|
||||
break;
|
||||
piface = piface->next;
|
||||
}
|
||||
|
||||
if (piface == NULL) {
|
||||
wpa_printf(MSG_DEBUG, "RSN: Could not find pre-authentication "
|
||||
"interface for " MACSTR, MAC2STR(sta->addr));
|
||||
return;
|
||||
}
|
||||
|
||||
ethhdr = os_malloc(sizeof(*ethhdr) + len);
|
||||
if (ethhdr == NULL)
|
||||
return;
|
||||
|
||||
os_memcpy(ethhdr->h_dest, sta->addr, ETH_ALEN);
|
||||
os_memcpy(ethhdr->h_source, hapd->own_addr, ETH_ALEN);
|
||||
ethhdr->h_proto = host_to_be16(ETH_P_PREAUTH);
|
||||
os_memcpy(ethhdr + 1, buf, len);
|
||||
|
||||
if (l2_packet_send(piface->l2, sta->addr, ETH_P_PREAUTH, (u8 *) ethhdr,
|
||||
sizeof(*ethhdr) + len) < 0) {
|
||||
wpa_printf(MSG_ERROR, "Failed to send preauth packet using "
|
||||
"l2_packet_send\n");
|
||||
}
|
||||
os_free(ethhdr);
|
||||
}
|
||||
|
||||
|
||||
void rsn_preauth_free_station(struct hostapd_data *hapd, struct sta_info *sta)
|
||||
{
|
||||
eloop_cancel_timeout(rsn_preauth_finished_cb, hapd, sta);
|
||||
}
|
||||
|
||||
#endif /* CONFIG_RSN_PREAUTH */
|
58
hostapd-0.8/src/ap/preauth_auth.h
Normal file
58
hostapd-0.8/src/ap/preauth_auth.h
Normal file
|
@ -0,0 +1,58 @@
|
|||
/*
|
||||
* 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.
|
||||
*/
|
||||
|
||||
#ifndef PREAUTH_H
|
||||
#define PREAUTH_H
|
||||
|
||||
#ifdef CONFIG_RSN_PREAUTH
|
||||
|
||||
int rsn_preauth_iface_init(struct hostapd_data *hapd);
|
||||
void rsn_preauth_iface_deinit(struct hostapd_data *hapd);
|
||||
void rsn_preauth_finished(struct hostapd_data *hapd, struct sta_info *sta,
|
||||
int success);
|
||||
void rsn_preauth_send(struct hostapd_data *hapd, struct sta_info *sta,
|
||||
u8 *buf, size_t len);
|
||||
void rsn_preauth_free_station(struct hostapd_data *hapd, struct sta_info *sta);
|
||||
|
||||
#else /* CONFIG_RSN_PREAUTH */
|
||||
|
||||
static inline int rsn_preauth_iface_init(struct hostapd_data *hapd)
|
||||
{
|
||||
return 0;
|
||||
}
|
||||
|
||||
static inline void rsn_preauth_iface_deinit(struct hostapd_data *hapd)
|
||||
{
|
||||
}
|
||||
|
||||
static inline void rsn_preauth_finished(struct hostapd_data *hapd,
|
||||
struct sta_info *sta,
|
||||
int success)
|
||||
{
|
||||
}
|
||||
|
||||
static inline void rsn_preauth_send(struct hostapd_data *hapd,
|
||||
struct sta_info *sta,
|
||||
u8 *buf, size_t len)
|
||||
{
|
||||
}
|
||||
|
||||
static inline void rsn_preauth_free_station(struct hostapd_data *hapd,
|
||||
struct sta_info *sta)
|
||||
{
|
||||
}
|
||||
|
||||
#endif /* CONFIG_RSN_PREAUTH */
|
||||
|
||||
#endif /* PREAUTH_H */
|
796
hostapd-0.8/src/ap/sta_info.c
Normal file
796
hostapd-0.8/src/ap/sta_info.c
Normal file
|
@ -0,0 +1,796 @@
|
|||
/*
|
||||
* hostapd / Station table
|
||||
* 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.
|
||||
*/
|
||||
|
||||
#include "utils/includes.h"
|
||||
|
||||
#include "utils/common.h"
|
||||
#include "utils/eloop.h"
|
||||
#include "common/ieee802_11_defs.h"
|
||||
#include "radius/radius.h"
|
||||
#include "radius/radius_client.h"
|
||||
#include "drivers/driver.h"
|
||||
#include "p2p/p2p.h"
|
||||
#include "hostapd.h"
|
||||
#include "accounting.h"
|
||||
#include "ieee802_1x.h"
|
||||
#include "ieee802_11.h"
|
||||
#include "wpa_auth.h"
|
||||
#include "preauth_auth.h"
|
||||
#include "ap_config.h"
|
||||
#include "beacon.h"
|
||||
#include "ap_mlme.h"
|
||||
#include "vlan_init.h"
|
||||
#include "p2p_hostapd.h"
|
||||
#include "ap_drv_ops.h"
|
||||
#include "sta_info.h"
|
||||
|
||||
static void ap_sta_remove_in_other_bss(struct hostapd_data *hapd,
|
||||
struct sta_info *sta);
|
||||
static void ap_handle_session_timer(void *eloop_ctx, void *timeout_ctx);
|
||||
#ifdef CONFIG_IEEE80211W
|
||||
static void ap_sa_query_timer(void *eloop_ctx, void *timeout_ctx);
|
||||
#endif /* CONFIG_IEEE80211W */
|
||||
|
||||
int ap_for_each_sta(struct hostapd_data *hapd,
|
||||
int (*cb)(struct hostapd_data *hapd, struct sta_info *sta,
|
||||
void *ctx),
|
||||
void *ctx)
|
||||
{
|
||||
struct sta_info *sta;
|
||||
|
||||
for (sta = hapd->sta_list; sta; sta = sta->next) {
|
||||
if (cb(hapd, sta, ctx))
|
||||
return 1;
|
||||
}
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
|
||||
struct sta_info * ap_get_sta(struct hostapd_data *hapd, const u8 *sta)
|
||||
{
|
||||
struct sta_info *s;
|
||||
|
||||
s = hapd->sta_hash[STA_HASH(sta)];
|
||||
while (s != NULL && os_memcmp(s->addr, sta, 6) != 0)
|
||||
s = s->hnext;
|
||||
return s;
|
||||
}
|
||||
|
||||
|
||||
static void ap_sta_list_del(struct hostapd_data *hapd, struct sta_info *sta)
|
||||
{
|
||||
struct sta_info *tmp;
|
||||
|
||||
if (hapd->sta_list == sta) {
|
||||
hapd->sta_list = sta->next;
|
||||
return;
|
||||
}
|
||||
|
||||
tmp = hapd->sta_list;
|
||||
while (tmp != NULL && tmp->next != sta)
|
||||
tmp = tmp->next;
|
||||
if (tmp == NULL) {
|
||||
wpa_printf(MSG_DEBUG, "Could not remove STA " MACSTR " from "
|
||||
"list.", MAC2STR(sta->addr));
|
||||
} else
|
||||
tmp->next = sta->next;
|
||||
}
|
||||
|
||||
|
||||
void ap_sta_hash_add(struct hostapd_data *hapd, struct sta_info *sta)
|
||||
{
|
||||
sta->hnext = hapd->sta_hash[STA_HASH(sta->addr)];
|
||||
hapd->sta_hash[STA_HASH(sta->addr)] = sta;
|
||||
}
|
||||
|
||||
|
||||
static void ap_sta_hash_del(struct hostapd_data *hapd, struct sta_info *sta)
|
||||
{
|
||||
struct sta_info *s;
|
||||
|
||||
s = hapd->sta_hash[STA_HASH(sta->addr)];
|
||||
if (s == NULL) return;
|
||||
if (os_memcmp(s->addr, sta->addr, 6) == 0) {
|
||||
hapd->sta_hash[STA_HASH(sta->addr)] = s->hnext;
|
||||
return;
|
||||
}
|
||||
|
||||
while (s->hnext != NULL &&
|
||||
os_memcmp(s->hnext->addr, sta->addr, ETH_ALEN) != 0)
|
||||
s = s->hnext;
|
||||
if (s->hnext != NULL)
|
||||
s->hnext = s->hnext->hnext;
|
||||
else
|
||||
wpa_printf(MSG_DEBUG, "AP: could not remove STA " MACSTR
|
||||
" from hash table", MAC2STR(sta->addr));
|
||||
}
|
||||
|
||||
|
||||
void ap_free_sta(struct hostapd_data *hapd, struct sta_info *sta)
|
||||
{
|
||||
int set_beacon = 0;
|
||||
|
||||
accounting_sta_stop(hapd, sta);
|
||||
|
||||
/* just in case */
|
||||
ap_sta_set_authorized(hapd, sta, 0);
|
||||
|
||||
if (sta->flags & WLAN_STA_WDS)
|
||||
hostapd_set_wds_sta(hapd, sta->addr, sta->aid, 0);
|
||||
|
||||
if (!(sta->flags & WLAN_STA_PREAUTH))
|
||||
hostapd_drv_sta_remove(hapd, sta->addr);
|
||||
|
||||
ap_sta_hash_del(hapd, sta);
|
||||
ap_sta_list_del(hapd, sta);
|
||||
|
||||
if (sta->aid > 0)
|
||||
hapd->sta_aid[(sta->aid - 1) / 32] &=
|
||||
~BIT((sta->aid - 1) % 32);
|
||||
|
||||
hapd->num_sta--;
|
||||
if (sta->nonerp_set) {
|
||||
sta->nonerp_set = 0;
|
||||
hapd->iface->num_sta_non_erp--;
|
||||
if (hapd->iface->num_sta_non_erp == 0)
|
||||
set_beacon++;
|
||||
}
|
||||
|
||||
if (sta->no_short_slot_time_set) {
|
||||
sta->no_short_slot_time_set = 0;
|
||||
hapd->iface->num_sta_no_short_slot_time--;
|
||||
if (hapd->iface->current_mode->mode == HOSTAPD_MODE_IEEE80211G
|
||||
&& hapd->iface->num_sta_no_short_slot_time == 0)
|
||||
set_beacon++;
|
||||
}
|
||||
|
||||
if (sta->no_short_preamble_set) {
|
||||
sta->no_short_preamble_set = 0;
|
||||
hapd->iface->num_sta_no_short_preamble--;
|
||||
if (hapd->iface->current_mode->mode == HOSTAPD_MODE_IEEE80211G
|
||||
&& hapd->iface->num_sta_no_short_preamble == 0)
|
||||
set_beacon++;
|
||||
}
|
||||
|
||||
if (sta->no_ht_gf_set) {
|
||||
sta->no_ht_gf_set = 0;
|
||||
hapd->iface->num_sta_ht_no_gf--;
|
||||
}
|
||||
|
||||
if (sta->no_ht_set) {
|
||||
sta->no_ht_set = 0;
|
||||
hapd->iface->num_sta_no_ht--;
|
||||
}
|
||||
|
||||
if (sta->ht_20mhz_set) {
|
||||
sta->ht_20mhz_set = 0;
|
||||
hapd->iface->num_sta_ht_20mhz--;
|
||||
}
|
||||
|
||||
#ifdef CONFIG_P2P
|
||||
if (sta->no_p2p_set) {
|
||||
sta->no_p2p_set = 0;
|
||||
hapd->num_sta_no_p2p--;
|
||||
if (hapd->num_sta_no_p2p == 0)
|
||||
hostapd_p2p_non_p2p_sta_disconnected(hapd);
|
||||
}
|
||||
#endif /* CONFIG_P2P */
|
||||
|
||||
#if defined(NEED_AP_MLME) && defined(CONFIG_IEEE80211N)
|
||||
if (hostapd_ht_operation_update(hapd->iface) > 0)
|
||||
set_beacon++;
|
||||
#endif /* NEED_AP_MLME && CONFIG_IEEE80211N */
|
||||
|
||||
if (set_beacon)
|
||||
ieee802_11_set_beacons(hapd->iface);
|
||||
|
||||
eloop_cancel_timeout(ap_handle_timer, hapd, sta);
|
||||
eloop_cancel_timeout(ap_handle_session_timer, hapd, sta);
|
||||
|
||||
ieee802_1x_free_station(sta);
|
||||
wpa_auth_sta_deinit(sta->wpa_sm);
|
||||
rsn_preauth_free_station(hapd, sta);
|
||||
#ifndef CONFIG_NO_RADIUS
|
||||
radius_client_flush_auth(hapd->radius, sta->addr);
|
||||
#endif /* CONFIG_NO_RADIUS */
|
||||
|
||||
os_free(sta->last_assoc_req);
|
||||
os_free(sta->challenge);
|
||||
|
||||
#ifdef CONFIG_IEEE80211W
|
||||
os_free(sta->sa_query_trans_id);
|
||||
eloop_cancel_timeout(ap_sa_query_timer, hapd, sta);
|
||||
#endif /* CONFIG_IEEE80211W */
|
||||
|
||||
#ifdef CONFIG_P2P
|
||||
p2p_group_notif_disassoc(hapd->p2p_group, sta->addr);
|
||||
#endif /* CONFIG_P2P */
|
||||
|
||||
wpabuf_free(sta->wps_ie);
|
||||
wpabuf_free(sta->p2p_ie);
|
||||
|
||||
os_free(sta->ht_capabilities);
|
||||
|
||||
os_free(sta);
|
||||
}
|
||||
|
||||
|
||||
void hostapd_free_stas(struct hostapd_data *hapd)
|
||||
{
|
||||
struct sta_info *sta, *prev;
|
||||
|
||||
sta = hapd->sta_list;
|
||||
|
||||
while (sta) {
|
||||
prev = sta;
|
||||
if (sta->flags & WLAN_STA_AUTH) {
|
||||
mlme_deauthenticate_indication(
|
||||
hapd, sta, WLAN_REASON_UNSPECIFIED);
|
||||
}
|
||||
sta = sta->next;
|
||||
wpa_printf(MSG_DEBUG, "Removing station " MACSTR,
|
||||
MAC2STR(prev->addr));
|
||||
ap_free_sta(hapd, prev);
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
/**
|
||||
* ap_handle_timer - Per STA timer handler
|
||||
* @eloop_ctx: struct hostapd_data *
|
||||
* @timeout_ctx: struct sta_info *
|
||||
*
|
||||
* This function is called to check station activity and to remove inactive
|
||||
* stations.
|
||||
*/
|
||||
void ap_handle_timer(void *eloop_ctx, void *timeout_ctx)
|
||||
{
|
||||
struct hostapd_data *hapd = eloop_ctx;
|
||||
struct sta_info *sta = timeout_ctx;
|
||||
unsigned long next_time = 0;
|
||||
|
||||
if (sta->timeout_next == STA_REMOVE) {
|
||||
hostapd_logger(hapd, sta->addr, HOSTAPD_MODULE_IEEE80211,
|
||||
HOSTAPD_LEVEL_INFO, "deauthenticated due to "
|
||||
"local deauth request");
|
||||
ap_free_sta(hapd, sta);
|
||||
return;
|
||||
}
|
||||
|
||||
if ((sta->flags & WLAN_STA_ASSOC) &&
|
||||
(sta->timeout_next == STA_NULLFUNC ||
|
||||
sta->timeout_next == STA_DISASSOC)) {
|
||||
int inactive_sec;
|
||||
inactive_sec = hostapd_drv_get_inact_sec(hapd, sta->addr);
|
||||
if (inactive_sec == -1) {
|
||||
wpa_msg(hapd, MSG_DEBUG, "Check inactivity: Could not "
|
||||
"get station info rom kernel driver for "
|
||||
MACSTR, MAC2STR(sta->addr));
|
||||
} else if (inactive_sec < hapd->conf->ap_max_inactivity &&
|
||||
sta->flags & WLAN_STA_ASSOC) {
|
||||
/* station activity detected; reset timeout state */
|
||||
wpa_msg(hapd, MSG_DEBUG, "Station " MACSTR " has been "
|
||||
"active %is ago",
|
||||
MAC2STR(sta->addr), inactive_sec);
|
||||
sta->timeout_next = STA_NULLFUNC;
|
||||
next_time = hapd->conf->ap_max_inactivity -
|
||||
inactive_sec;
|
||||
} else {
|
||||
wpa_msg(hapd, MSG_DEBUG, "Station " MACSTR " has been "
|
||||
"inactive too long: %d sec, max allowed: %d",
|
||||
MAC2STR(sta->addr), inactive_sec,
|
||||
hapd->conf->ap_max_inactivity);
|
||||
}
|
||||
}
|
||||
|
||||
if ((sta->flags & WLAN_STA_ASSOC) &&
|
||||
sta->timeout_next == STA_DISASSOC &&
|
||||
!(sta->flags & WLAN_STA_PENDING_POLL)) {
|
||||
wpa_msg(hapd, MSG_DEBUG, "Station " MACSTR " has ACKed data "
|
||||
"poll", MAC2STR(sta->addr));
|
||||
/* data nullfunc frame poll did not produce TX errors; assume
|
||||
* station ACKed it */
|
||||
sta->timeout_next = STA_NULLFUNC;
|
||||
next_time = hapd->conf->ap_max_inactivity;
|
||||
}
|
||||
|
||||
if (next_time) {
|
||||
eloop_register_timeout(next_time, 0, ap_handle_timer, hapd,
|
||||
sta);
|
||||
return;
|
||||
}
|
||||
|
||||
if (sta->timeout_next == STA_NULLFUNC &&
|
||||
(sta->flags & WLAN_STA_ASSOC)) {
|
||||
#ifndef CONFIG_NATIVE_WINDOWS
|
||||
/* send data frame to poll STA and check whether this frame
|
||||
* is ACKed */
|
||||
struct ieee80211_hdr hdr;
|
||||
|
||||
wpa_printf(MSG_DEBUG, " Polling STA with data frame");
|
||||
sta->flags |= WLAN_STA_PENDING_POLL;
|
||||
|
||||
os_memset(&hdr, 0, sizeof(hdr));
|
||||
if (hapd->driver &&
|
||||
os_strcmp(hapd->driver->name, "hostap") == 0) {
|
||||
/*
|
||||
* WLAN_FC_STYPE_NULLFUNC would be more appropriate,
|
||||
* but it is apparently not retried so TX Exc events
|
||||
* are not received for it.
|
||||
*/
|
||||
hdr.frame_control =
|
||||
IEEE80211_FC(WLAN_FC_TYPE_DATA,
|
||||
WLAN_FC_STYPE_DATA);
|
||||
} else {
|
||||
hdr.frame_control =
|
||||
IEEE80211_FC(WLAN_FC_TYPE_DATA,
|
||||
WLAN_FC_STYPE_NULLFUNC);
|
||||
}
|
||||
|
||||
hdr.frame_control |= host_to_le16(WLAN_FC_FROMDS);
|
||||
os_memcpy(hdr.IEEE80211_DA_FROMDS, sta->addr, ETH_ALEN);
|
||||
os_memcpy(hdr.IEEE80211_BSSID_FROMDS, hapd->own_addr,
|
||||
ETH_ALEN);
|
||||
os_memcpy(hdr.IEEE80211_SA_FROMDS, hapd->own_addr, ETH_ALEN);
|
||||
|
||||
if (hostapd_drv_send_mlme(hapd, &hdr, sizeof(hdr)) < 0)
|
||||
perror("ap_handle_timer: send");
|
||||
#endif /* CONFIG_NATIVE_WINDOWS */
|
||||
} 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));
|
||||
|
||||
if (deauth) {
|
||||
hostapd_drv_sta_deauth(
|
||||
hapd, sta->addr,
|
||||
WLAN_REASON_PREV_AUTH_NOT_VALID);
|
||||
} else {
|
||||
hostapd_drv_sta_disassoc(
|
||||
hapd, sta->addr,
|
||||
WLAN_REASON_DISASSOC_DUE_TO_INACTIVITY);
|
||||
}
|
||||
}
|
||||
|
||||
switch (sta->timeout_next) {
|
||||
case STA_NULLFUNC:
|
||||
sta->timeout_next = STA_DISASSOC;
|
||||
eloop_register_timeout(AP_DISASSOC_DELAY, 0, ap_handle_timer,
|
||||
hapd, sta);
|
||||
break;
|
||||
case STA_DISASSOC:
|
||||
sta->flags &= ~WLAN_STA_ASSOC;
|
||||
ieee802_1x_notify_port_enabled(sta->eapol_sm, 0);
|
||||
if (!sta->acct_terminate_cause)
|
||||
sta->acct_terminate_cause =
|
||||
RADIUS_ACCT_TERMINATE_CAUSE_IDLE_TIMEOUT;
|
||||
accounting_sta_stop(hapd, sta);
|
||||
ieee802_1x_free_station(sta);
|
||||
hostapd_logger(hapd, sta->addr, HOSTAPD_MODULE_IEEE80211,
|
||||
HOSTAPD_LEVEL_INFO, "disassociated due to "
|
||||
"inactivity");
|
||||
sta->timeout_next = STA_DEAUTH;
|
||||
eloop_register_timeout(AP_DEAUTH_DELAY, 0, ap_handle_timer,
|
||||
hapd, sta);
|
||||
mlme_disassociate_indication(
|
||||
hapd, sta, WLAN_REASON_DISASSOC_DUE_TO_INACTIVITY);
|
||||
break;
|
||||
case STA_DEAUTH:
|
||||
case STA_REMOVE:
|
||||
hostapd_logger(hapd, sta->addr, HOSTAPD_MODULE_IEEE80211,
|
||||
HOSTAPD_LEVEL_INFO, "deauthenticated due to "
|
||||
"inactivity");
|
||||
if (!sta->acct_terminate_cause)
|
||||
sta->acct_terminate_cause =
|
||||
RADIUS_ACCT_TERMINATE_CAUSE_IDLE_TIMEOUT;
|
||||
mlme_deauthenticate_indication(
|
||||
hapd, sta,
|
||||
WLAN_REASON_PREV_AUTH_NOT_VALID);
|
||||
ap_free_sta(hapd, sta);
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
static void ap_handle_session_timer(void *eloop_ctx, void *timeout_ctx)
|
||||
{
|
||||
struct hostapd_data *hapd = eloop_ctx;
|
||||
struct sta_info *sta = timeout_ctx;
|
||||
u8 addr[ETH_ALEN];
|
||||
|
||||
if (!(sta->flags & WLAN_STA_AUTH))
|
||||
return;
|
||||
|
||||
mlme_deauthenticate_indication(hapd, sta,
|
||||
WLAN_REASON_PREV_AUTH_NOT_VALID);
|
||||
hostapd_logger(hapd, sta->addr, HOSTAPD_MODULE_IEEE80211,
|
||||
HOSTAPD_LEVEL_INFO, "deauthenticated due to "
|
||||
"session timeout");
|
||||
sta->acct_terminate_cause =
|
||||
RADIUS_ACCT_TERMINATE_CAUSE_SESSION_TIMEOUT;
|
||||
os_memcpy(addr, sta->addr, ETH_ALEN);
|
||||
ap_free_sta(hapd, sta);
|
||||
hostapd_drv_sta_deauth(hapd, addr, WLAN_REASON_PREV_AUTH_NOT_VALID);
|
||||
}
|
||||
|
||||
|
||||
void ap_sta_session_timeout(struct hostapd_data *hapd, struct sta_info *sta,
|
||||
u32 session_timeout)
|
||||
{
|
||||
hostapd_logger(hapd, sta->addr, HOSTAPD_MODULE_IEEE80211,
|
||||
HOSTAPD_LEVEL_DEBUG, "setting session timeout to %d "
|
||||
"seconds", session_timeout);
|
||||
eloop_cancel_timeout(ap_handle_session_timer, hapd, sta);
|
||||
eloop_register_timeout(session_timeout, 0, ap_handle_session_timer,
|
||||
hapd, sta);
|
||||
}
|
||||
|
||||
|
||||
void ap_sta_no_session_timeout(struct hostapd_data *hapd, struct sta_info *sta)
|
||||
{
|
||||
eloop_cancel_timeout(ap_handle_session_timer, hapd, sta);
|
||||
}
|
||||
|
||||
|
||||
struct sta_info * ap_sta_add(struct hostapd_data *hapd, const u8 *addr)
|
||||
{
|
||||
struct sta_info *sta;
|
||||
|
||||
sta = ap_get_sta(hapd, addr);
|
||||
if (sta)
|
||||
return sta;
|
||||
|
||||
wpa_printf(MSG_DEBUG, " New STA");
|
||||
if (hapd->num_sta >= hapd->conf->max_num_sta) {
|
||||
/* FIX: might try to remove some old STAs first? */
|
||||
wpa_printf(MSG_DEBUG, "no more room for new STAs (%d/%d)",
|
||||
hapd->num_sta, hapd->conf->max_num_sta);
|
||||
return NULL;
|
||||
}
|
||||
|
||||
sta = os_zalloc(sizeof(struct sta_info));
|
||||
if (sta == NULL) {
|
||||
wpa_printf(MSG_ERROR, "malloc failed");
|
||||
return NULL;
|
||||
}
|
||||
sta->acct_interim_interval = hapd->conf->acct_interim_interval;
|
||||
|
||||
/* initialize STA info data */
|
||||
eloop_register_timeout(hapd->conf->ap_max_inactivity, 0,
|
||||
ap_handle_timer, hapd, sta);
|
||||
os_memcpy(sta->addr, addr, ETH_ALEN);
|
||||
sta->next = hapd->sta_list;
|
||||
hapd->sta_list = sta;
|
||||
hapd->num_sta++;
|
||||
ap_sta_hash_add(hapd, sta);
|
||||
sta->ssid = &hapd->conf->ssid;
|
||||
ap_sta_remove_in_other_bss(hapd, sta);
|
||||
|
||||
return sta;
|
||||
}
|
||||
|
||||
|
||||
static int ap_sta_remove(struct hostapd_data *hapd, struct sta_info *sta)
|
||||
{
|
||||
ieee802_1x_notify_port_enabled(sta->eapol_sm, 0);
|
||||
|
||||
wpa_printf(MSG_DEBUG, "Removing STA " MACSTR " from kernel driver",
|
||||
MAC2STR(sta->addr));
|
||||
if (hostapd_drv_sta_remove(hapd, sta->addr) &&
|
||||
sta->flags & WLAN_STA_ASSOC) {
|
||||
wpa_printf(MSG_DEBUG, "Could not remove station " MACSTR
|
||||
" from kernel driver.", MAC2STR(sta->addr));
|
||||
return -1;
|
||||
}
|
||||
return 0;
|
||||
}
|
||||
|
||||
|
||||
static void ap_sta_remove_in_other_bss(struct hostapd_data *hapd,
|
||||
struct sta_info *sta)
|
||||
{
|
||||
struct hostapd_iface *iface = hapd->iface;
|
||||
size_t i;
|
||||
|
||||
for (i = 0; i < iface->num_bss; i++) {
|
||||
struct hostapd_data *bss = iface->bss[i];
|
||||
struct sta_info *sta2;
|
||||
/* bss should always be set during operation, but it may be
|
||||
* NULL during reconfiguration. Assume the STA is not
|
||||
* associated to another BSS in that case to avoid NULL pointer
|
||||
* dereferences. */
|
||||
if (bss == hapd || bss == NULL)
|
||||
continue;
|
||||
sta2 = ap_get_sta(bss, sta->addr);
|
||||
if (!sta2)
|
||||
continue;
|
||||
|
||||
ap_sta_disconnect(bss, sta2, sta2->addr,
|
||||
WLAN_REASON_PREV_AUTH_NOT_VALID);
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
void ap_sta_disassociate(struct hostapd_data *hapd, struct sta_info *sta,
|
||||
u16 reason)
|
||||
{
|
||||
wpa_printf(MSG_DEBUG, "%s: disassociate STA " MACSTR,
|
||||
hapd->conf->iface, MAC2STR(sta->addr));
|
||||
sta->flags &= ~WLAN_STA_ASSOC;
|
||||
ap_sta_remove(hapd, sta);
|
||||
sta->timeout_next = STA_DEAUTH;
|
||||
eloop_cancel_timeout(ap_handle_timer, hapd, sta);
|
||||
eloop_register_timeout(AP_MAX_INACTIVITY_AFTER_DISASSOC, 0,
|
||||
ap_handle_timer, hapd, sta);
|
||||
accounting_sta_stop(hapd, sta);
|
||||
ieee802_1x_free_station(sta);
|
||||
|
||||
mlme_disassociate_indication(hapd, sta, reason);
|
||||
}
|
||||
|
||||
|
||||
void ap_sta_deauthenticate(struct hostapd_data *hapd, struct sta_info *sta,
|
||||
u16 reason)
|
||||
{
|
||||
wpa_printf(MSG_DEBUG, "%s: deauthenticate STA " MACSTR,
|
||||
hapd->conf->iface, MAC2STR(sta->addr));
|
||||
sta->flags &= ~(WLAN_STA_AUTH | WLAN_STA_ASSOC);
|
||||
ap_sta_remove(hapd, sta);
|
||||
sta->timeout_next = STA_REMOVE;
|
||||
eloop_cancel_timeout(ap_handle_timer, hapd, sta);
|
||||
eloop_register_timeout(AP_MAX_INACTIVITY_AFTER_DEAUTH, 0,
|
||||
ap_handle_timer, hapd, sta);
|
||||
accounting_sta_stop(hapd, sta);
|
||||
ieee802_1x_free_station(sta);
|
||||
|
||||
mlme_deauthenticate_indication(hapd, sta, reason);
|
||||
}
|
||||
|
||||
|
||||
int ap_sta_bind_vlan(struct hostapd_data *hapd, struct sta_info *sta,
|
||||
int old_vlanid)
|
||||
{
|
||||
#ifndef CONFIG_NO_VLAN
|
||||
const char *iface;
|
||||
struct hostapd_vlan *vlan = NULL;
|
||||
int ret;
|
||||
|
||||
/*
|
||||
* Do not proceed furthur if the vlan id remains same. We do not want
|
||||
* duplicate dynamic vlan entries.
|
||||
*/
|
||||
if (sta->vlan_id == old_vlanid)
|
||||
return 0;
|
||||
|
||||
/*
|
||||
* During 1x reauth, if the vlan id changes, then remove the old id and
|
||||
* proceed furthur to add the new one.
|
||||
*/
|
||||
if (old_vlanid > 0)
|
||||
vlan_remove_dynamic(hapd, old_vlanid);
|
||||
|
||||
iface = hapd->conf->iface;
|
||||
if (sta->ssid->vlan[0])
|
||||
iface = sta->ssid->vlan;
|
||||
|
||||
if (sta->ssid->dynamic_vlan == DYNAMIC_VLAN_DISABLED)
|
||||
sta->vlan_id = 0;
|
||||
else if (sta->vlan_id > 0) {
|
||||
vlan = hapd->conf->vlan;
|
||||
while (vlan) {
|
||||
if (vlan->vlan_id == sta->vlan_id ||
|
||||
vlan->vlan_id == VLAN_ID_WILDCARD) {
|
||||
iface = vlan->ifname;
|
||||
break;
|
||||
}
|
||||
vlan = vlan->next;
|
||||
}
|
||||
}
|
||||
|
||||
if (sta->vlan_id > 0 && vlan == NULL) {
|
||||
hostapd_logger(hapd, sta->addr, HOSTAPD_MODULE_IEEE80211,
|
||||
HOSTAPD_LEVEL_DEBUG, "could not find VLAN for "
|
||||
"binding station to (vlan_id=%d)",
|
||||
sta->vlan_id);
|
||||
return -1;
|
||||
} else if (sta->vlan_id > 0 && vlan->vlan_id == VLAN_ID_WILDCARD) {
|
||||
vlan = vlan_add_dynamic(hapd, vlan, sta->vlan_id);
|
||||
if (vlan == NULL) {
|
||||
hostapd_logger(hapd, sta->addr,
|
||||
HOSTAPD_MODULE_IEEE80211,
|
||||
HOSTAPD_LEVEL_DEBUG, "could not add "
|
||||
"dynamic VLAN interface for vlan_id=%d",
|
||||
sta->vlan_id);
|
||||
return -1;
|
||||
}
|
||||
|
||||
iface = vlan->ifname;
|
||||
if (vlan_setup_encryption_dyn(hapd, sta->ssid, iface) != 0) {
|
||||
hostapd_logger(hapd, sta->addr,
|
||||
HOSTAPD_MODULE_IEEE80211,
|
||||
HOSTAPD_LEVEL_DEBUG, "could not "
|
||||
"configure encryption for dynamic VLAN "
|
||||
"interface for vlan_id=%d",
|
||||
sta->vlan_id);
|
||||
}
|
||||
|
||||
hostapd_logger(hapd, sta->addr, HOSTAPD_MODULE_IEEE80211,
|
||||
HOSTAPD_LEVEL_DEBUG, "added new dynamic VLAN "
|
||||
"interface '%s'", iface);
|
||||
} else if (vlan && vlan->vlan_id == sta->vlan_id) {
|
||||
if (sta->vlan_id > 0) {
|
||||
vlan->dynamic_vlan++;
|
||||
hostapd_logger(hapd, sta->addr,
|
||||
HOSTAPD_MODULE_IEEE80211,
|
||||
HOSTAPD_LEVEL_DEBUG, "updated existing "
|
||||
"dynamic VLAN interface '%s'", iface);
|
||||
}
|
||||
|
||||
/*
|
||||
* Update encryption configuration for statically generated
|
||||
* VLAN interface. This is only used for static WEP
|
||||
* configuration for the case where hostapd did not yet know
|
||||
* which keys are to be used when the interface was added.
|
||||
*/
|
||||
if (vlan_setup_encryption_dyn(hapd, sta->ssid, iface) != 0) {
|
||||
hostapd_logger(hapd, sta->addr,
|
||||
HOSTAPD_MODULE_IEEE80211,
|
||||
HOSTAPD_LEVEL_DEBUG, "could not "
|
||||
"configure encryption for VLAN "
|
||||
"interface for vlan_id=%d",
|
||||
sta->vlan_id);
|
||||
}
|
||||
}
|
||||
|
||||
hostapd_logger(hapd, sta->addr, HOSTAPD_MODULE_IEEE80211,
|
||||
HOSTAPD_LEVEL_DEBUG, "binding station to interface "
|
||||
"'%s'", iface);
|
||||
|
||||
if (wpa_auth_sta_set_vlan(sta->wpa_sm, sta->vlan_id) < 0)
|
||||
wpa_printf(MSG_INFO, "Failed to update VLAN-ID for WPA");
|
||||
|
||||
ret = hostapd_drv_set_sta_vlan(iface, hapd, sta->addr, sta->vlan_id);
|
||||
if (ret < 0) {
|
||||
hostapd_logger(hapd, sta->addr, HOSTAPD_MODULE_IEEE80211,
|
||||
HOSTAPD_LEVEL_DEBUG, "could not bind the STA "
|
||||
"entry to vlan_id=%d", sta->vlan_id);
|
||||
}
|
||||
return ret;
|
||||
#else /* CONFIG_NO_VLAN */
|
||||
return 0;
|
||||
#endif /* CONFIG_NO_VLAN */
|
||||
}
|
||||
|
||||
|
||||
#ifdef CONFIG_IEEE80211W
|
||||
|
||||
int ap_check_sa_query_timeout(struct hostapd_data *hapd, struct sta_info *sta)
|
||||
{
|
||||
u32 tu;
|
||||
struct os_time now, passed;
|
||||
os_get_time(&now);
|
||||
os_time_sub(&now, &sta->sa_query_start, &passed);
|
||||
tu = (passed.sec * 1000000 + passed.usec) / 1024;
|
||||
if (hapd->conf->assoc_sa_query_max_timeout < tu) {
|
||||
hostapd_logger(hapd, sta->addr,
|
||||
HOSTAPD_MODULE_IEEE80211,
|
||||
HOSTAPD_LEVEL_DEBUG,
|
||||
"association SA Query timed out");
|
||||
sta->sa_query_timed_out = 1;
|
||||
os_free(sta->sa_query_trans_id);
|
||||
sta->sa_query_trans_id = NULL;
|
||||
sta->sa_query_count = 0;
|
||||
eloop_cancel_timeout(ap_sa_query_timer, hapd, sta);
|
||||
return 1;
|
||||
}
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
|
||||
static void ap_sa_query_timer(void *eloop_ctx, void *timeout_ctx)
|
||||
{
|
||||
struct hostapd_data *hapd = eloop_ctx;
|
||||
struct sta_info *sta = timeout_ctx;
|
||||
unsigned int timeout, sec, usec;
|
||||
u8 *trans_id, *nbuf;
|
||||
|
||||
if (sta->sa_query_count > 0 &&
|
||||
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);
|
||||
if (nbuf == NULL)
|
||||
return;
|
||||
if (sta->sa_query_count == 0) {
|
||||
/* Starting a new SA Query procedure */
|
||||
os_get_time(&sta->sa_query_start);
|
||||
}
|
||||
trans_id = nbuf + sta->sa_query_count * WLAN_SA_QUERY_TR_ID_LEN;
|
||||
sta->sa_query_trans_id = nbuf;
|
||||
sta->sa_query_count++;
|
||||
|
||||
os_get_random(trans_id, WLAN_SA_QUERY_TR_ID_LEN);
|
||||
|
||||
timeout = hapd->conf->assoc_sa_query_retry_timeout;
|
||||
sec = ((timeout / 1000) * 1024) / 1000;
|
||||
usec = (timeout % 1000) * 1024;
|
||||
eloop_register_timeout(sec, usec, ap_sa_query_timer, hapd, sta);
|
||||
|
||||
hostapd_logger(hapd, sta->addr, HOSTAPD_MODULE_IEEE80211,
|
||||
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 */
|
||||
}
|
||||
|
||||
|
||||
void ap_sta_start_sa_query(struct hostapd_data *hapd, struct sta_info *sta)
|
||||
{
|
||||
ap_sa_query_timer(hapd, sta);
|
||||
}
|
||||
|
||||
|
||||
void ap_sta_stop_sa_query(struct hostapd_data *hapd, struct sta_info *sta)
|
||||
{
|
||||
eloop_cancel_timeout(ap_sa_query_timer, hapd, sta);
|
||||
os_free(sta->sa_query_trans_id);
|
||||
sta->sa_query_trans_id = NULL;
|
||||
sta->sa_query_count = 0;
|
||||
}
|
||||
|
||||
#endif /* CONFIG_IEEE80211W */
|
||||
|
||||
|
||||
void ap_sta_set_authorized(struct hostapd_data *hapd, struct sta_info *sta,
|
||||
int authorized)
|
||||
{
|
||||
if (!!authorized == !!(sta->flags & WLAN_STA_AUTHORIZED))
|
||||
return;
|
||||
|
||||
if (authorized)
|
||||
sta->flags |= WLAN_STA_AUTHORIZED;
|
||||
else
|
||||
sta->flags &= ~WLAN_STA_AUTHORIZED;
|
||||
|
||||
if (hapd->sta_authorized_cb)
|
||||
hapd->sta_authorized_cb(hapd->sta_authorized_cb_ctx,
|
||||
sta->addr, authorized);
|
||||
}
|
||||
|
||||
|
||||
void ap_sta_disconnect(struct hostapd_data *hapd, struct sta_info *sta,
|
||||
const u8 *addr, u16 reason)
|
||||
{
|
||||
|
||||
if (sta == NULL && addr)
|
||||
sta = ap_get_sta(hapd, addr);
|
||||
|
||||
if (addr)
|
||||
hostapd_drv_sta_deauth(hapd, addr, reason);
|
||||
|
||||
if (sta == NULL)
|
||||
return;
|
||||
ap_sta_set_authorized(hapd, sta, 0);
|
||||
sta->flags &= ~(WLAN_STA_AUTH | WLAN_STA_ASSOC);
|
||||
eloop_cancel_timeout(ap_handle_timer, hapd, sta);
|
||||
eloop_register_timeout(0, 0, ap_handle_timer, hapd, sta);
|
||||
sta->timeout_next = STA_REMOVE;
|
||||
}
|
165
hostapd-0.8/src/ap/sta_info.h
Normal file
165
hostapd-0.8/src/ap/sta_info.h
Normal file
|
@ -0,0 +1,165 @@
|
|||
/*
|
||||
* hostapd / Station table
|
||||
* 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.
|
||||
*/
|
||||
|
||||
#ifndef STA_INFO_H
|
||||
#define STA_INFO_H
|
||||
|
||||
/* STA flags */
|
||||
#define WLAN_STA_AUTH BIT(0)
|
||||
#define WLAN_STA_ASSOC BIT(1)
|
||||
#define WLAN_STA_PS BIT(2)
|
||||
#define WLAN_STA_TIM BIT(3)
|
||||
#define WLAN_STA_PERM BIT(4)
|
||||
#define WLAN_STA_AUTHORIZED BIT(5)
|
||||
#define WLAN_STA_PENDING_POLL BIT(6) /* pending activity poll not ACKed */
|
||||
#define WLAN_STA_SHORT_PREAMBLE BIT(7)
|
||||
#define WLAN_STA_PREAUTH BIT(8)
|
||||
#define WLAN_STA_WMM BIT(9)
|
||||
#define WLAN_STA_MFP BIT(10)
|
||||
#define WLAN_STA_HT BIT(11)
|
||||
#define WLAN_STA_WPS BIT(12)
|
||||
#define WLAN_STA_MAYBE_WPS BIT(13)
|
||||
#define WLAN_STA_WDS BIT(14)
|
||||
#define WLAN_STA_ASSOC_REQ_OK BIT(15)
|
||||
#define WLAN_STA_NONERP BIT(31)
|
||||
|
||||
/* Maximum number of supported rates (from both Supported Rates and Extended
|
||||
* Supported Rates IEs). */
|
||||
#define WLAN_SUPP_RATES_MAX 32
|
||||
|
||||
|
||||
struct sta_info {
|
||||
struct sta_info *next; /* next entry in sta list */
|
||||
struct sta_info *hnext; /* next entry in hash table list */
|
||||
u8 addr[6];
|
||||
u16 aid; /* STA's unique AID (1 .. 2007) or 0 if not yet assigned */
|
||||
u32 flags; /* Bitfield of WLAN_STA_* */
|
||||
u16 capability;
|
||||
u16 listen_interval; /* or beacon_int for APs */
|
||||
u8 supported_rates[WLAN_SUPP_RATES_MAX];
|
||||
int supported_rates_len;
|
||||
|
||||
unsigned int nonerp_set:1;
|
||||
unsigned int no_short_slot_time_set:1;
|
||||
unsigned int no_short_preamble_set:1;
|
||||
unsigned int no_ht_gf_set:1;
|
||||
unsigned int no_ht_set:1;
|
||||
unsigned int ht_20mhz_set:1;
|
||||
unsigned int no_p2p_set:1;
|
||||
|
||||
u16 auth_alg;
|
||||
u8 previous_ap[6];
|
||||
|
||||
enum {
|
||||
STA_NULLFUNC = 0, STA_DISASSOC, STA_DEAUTH, STA_REMOVE
|
||||
} timeout_next;
|
||||
|
||||
/* IEEE 802.1X related data */
|
||||
struct eapol_state_machine *eapol_sm;
|
||||
|
||||
/* IEEE 802.11f (IAPP) related data */
|
||||
struct ieee80211_mgmt *last_assoc_req;
|
||||
|
||||
u32 acct_session_id_hi;
|
||||
u32 acct_session_id_lo;
|
||||
time_t acct_session_start;
|
||||
int acct_session_started;
|
||||
int acct_terminate_cause; /* Acct-Terminate-Cause */
|
||||
int acct_interim_interval; /* Acct-Interim-Interval */
|
||||
|
||||
unsigned long last_rx_bytes;
|
||||
unsigned long last_tx_bytes;
|
||||
u32 acct_input_gigawords; /* Acct-Input-Gigawords */
|
||||
u32 acct_output_gigawords; /* Acct-Output-Gigawords */
|
||||
|
||||
u8 *challenge; /* IEEE 802.11 Shared Key Authentication Challenge */
|
||||
|
||||
struct wpa_state_machine *wpa_sm;
|
||||
struct rsn_preauth_interface *preauth_iface;
|
||||
|
||||
struct hostapd_ssid *ssid; /* SSID selection based on (Re)AssocReq */
|
||||
struct hostapd_ssid *ssid_probe; /* SSID selection based on ProbeReq */
|
||||
|
||||
int vlan_id;
|
||||
|
||||
struct ieee80211_ht_capabilities *ht_capabilities;
|
||||
|
||||
#ifdef CONFIG_IEEE80211W
|
||||
int sa_query_count; /* number of pending SA Query requests;
|
||||
* 0 = no SA Query in progress */
|
||||
int sa_query_timed_out;
|
||||
u8 *sa_query_trans_id; /* buffer of WLAN_SA_QUERY_TR_ID_LEN *
|
||||
* sa_query_count octets of pending SA Query
|
||||
* transaction identifiers */
|
||||
struct os_time sa_query_start;
|
||||
#endif /* CONFIG_IEEE80211W */
|
||||
|
||||
struct wpabuf *wps_ie; /* WPS IE from (Re)Association Request */
|
||||
struct wpabuf *p2p_ie; /* P2P IE from (Re)Association Request */
|
||||
};
|
||||
|
||||
|
||||
/* Default value for maximum station inactivity. After AP_MAX_INACTIVITY has
|
||||
* passed since last received frame from the station, a nullfunc data frame is
|
||||
* sent to the station. If this frame is not acknowledged and no other frames
|
||||
* have been received, the station will be disassociated after
|
||||
* AP_DISASSOC_DELAY seconds. Similarily, the station will be deauthenticated
|
||||
* after AP_DEAUTH_DELAY seconds has passed after disassociation. */
|
||||
#define AP_MAX_INACTIVITY (5 * 60)
|
||||
#define AP_DISASSOC_DELAY (1)
|
||||
#define AP_DEAUTH_DELAY (1)
|
||||
/* Number of seconds to keep STA entry with Authenticated flag after it has
|
||||
* been disassociated. */
|
||||
#define AP_MAX_INACTIVITY_AFTER_DISASSOC (1 * 30)
|
||||
/* Number of seconds to keep STA entry after it has been deauthenticated. */
|
||||
#define AP_MAX_INACTIVITY_AFTER_DEAUTH (1 * 5)
|
||||
|
||||
|
||||
struct hostapd_data;
|
||||
|
||||
int ap_for_each_sta(struct hostapd_data *hapd,
|
||||
int (*cb)(struct hostapd_data *hapd, struct sta_info *sta,
|
||||
void *ctx),
|
||||
void *ctx);
|
||||
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,
|
||||
u32 session_timeout);
|
||||
void ap_sta_no_session_timeout(struct hostapd_data *hapd,
|
||||
struct sta_info *sta);
|
||||
struct sta_info * ap_sta_add(struct hostapd_data *hapd, const u8 *addr);
|
||||
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);
|
||||
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);
|
||||
void ap_sta_stop_sa_query(struct hostapd_data *hapd, struct sta_info *sta);
|
||||
int ap_check_sa_query_timeout(struct hostapd_data *hapd, struct sta_info *sta);
|
||||
void ap_sta_disconnect(struct hostapd_data *hapd, struct sta_info *sta,
|
||||
const u8 *addr, u16 reason);
|
||||
|
||||
void ap_sta_set_authorized(struct hostapd_data *hapd,
|
||||
struct sta_info *sta, int authorized);
|
||||
static inline int ap_sta_is_authorized(struct sta_info *sta)
|
||||
{
|
||||
return sta->flags & WLAN_STA_AUTHORIZED;
|
||||
}
|
||||
|
||||
#endif /* STA_INFO_H */
|
94
hostapd-0.8/src/ap/tkip_countermeasures.c
Normal file
94
hostapd-0.8/src/ap/tkip_countermeasures.c
Normal file
|
@ -0,0 +1,94 @@
|
|||
/*
|
||||
* hostapd / TKIP countermeasures
|
||||
* 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.
|
||||
*/
|
||||
|
||||
#include "utils/includes.h"
|
||||
|
||||
#include "utils/common.h"
|
||||
#include "utils/eloop.h"
|
||||
#include "common/ieee802_11_defs.h"
|
||||
#include "hostapd.h"
|
||||
#include "sta_info.h"
|
||||
#include "ap_mlme.h"
|
||||
#include "wpa_auth.h"
|
||||
#include "ap_drv_ops.h"
|
||||
#include "tkip_countermeasures.h"
|
||||
|
||||
|
||||
static void ieee80211_tkip_countermeasures_stop(void *eloop_ctx,
|
||||
void *timeout_ctx)
|
||||
{
|
||||
struct hostapd_data *hapd = eloop_ctx;
|
||||
hapd->tkip_countermeasures = 0;
|
||||
hostapd_drv_set_countermeasures(hapd, 0);
|
||||
hostapd_logger(hapd, NULL, HOSTAPD_MODULE_IEEE80211,
|
||||
HOSTAPD_LEVEL_INFO, "TKIP countermeasures ended");
|
||||
}
|
||||
|
||||
|
||||
static void ieee80211_tkip_countermeasures_start(struct hostapd_data *hapd)
|
||||
{
|
||||
struct sta_info *sta;
|
||||
|
||||
hostapd_logger(hapd, NULL, HOSTAPD_MODULE_IEEE80211,
|
||||
HOSTAPD_LEVEL_INFO, "TKIP countermeasures initiated");
|
||||
|
||||
wpa_auth_countermeasures_start(hapd->wpa_auth);
|
||||
hapd->tkip_countermeasures = 1;
|
||||
hostapd_drv_set_countermeasures(hapd, 1);
|
||||
wpa_gtk_rekey(hapd->wpa_auth);
|
||||
eloop_cancel_timeout(ieee80211_tkip_countermeasures_stop, hapd, NULL);
|
||||
eloop_register_timeout(60, 0, ieee80211_tkip_countermeasures_stop,
|
||||
hapd, NULL);
|
||||
for (sta = hapd->sta_list; sta != NULL; sta = sta->next) {
|
||||
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);
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
void michael_mic_failure(struct hostapd_data *hapd, const u8 *addr, int local)
|
||||
{
|
||||
time_t now;
|
||||
|
||||
if (addr && local) {
|
||||
struct sta_info *sta = ap_get_sta(hapd, addr);
|
||||
if (sta != NULL) {
|
||||
wpa_auth_sta_local_mic_failure_report(sta->wpa_sm);
|
||||
hostapd_logger(hapd, addr, HOSTAPD_MODULE_IEEE80211,
|
||||
HOSTAPD_LEVEL_INFO,
|
||||
"Michael MIC failure detected in "
|
||||
"received frame");
|
||||
mlme_michaelmicfailure_indication(hapd, addr);
|
||||
} else {
|
||||
wpa_printf(MSG_DEBUG,
|
||||
"MLME-MICHAELMICFAILURE.indication "
|
||||
"for not associated STA (" MACSTR
|
||||
") ignored", MAC2STR(addr));
|
||||
return;
|
||||
}
|
||||
}
|
||||
|
||||
time(&now);
|
||||
if (now > hapd->michael_mic_failure + 60) {
|
||||
hapd->michael_mic_failures = 1;
|
||||
} else {
|
||||
hapd->michael_mic_failures++;
|
||||
if (hapd->michael_mic_failures > 1)
|
||||
ieee80211_tkip_countermeasures_start(hapd);
|
||||
}
|
||||
hapd->michael_mic_failure = now;
|
||||
}
|
20
hostapd-0.8/src/ap/tkip_countermeasures.h
Normal file
20
hostapd-0.8/src/ap/tkip_countermeasures.h
Normal file
|
@ -0,0 +1,20 @@
|
|||
/*
|
||||
* hostapd / TKIP countermeasures
|
||||
* 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.
|
||||
*/
|
||||
|
||||
#ifndef TKIP_COUNTERMEASURES_H
|
||||
#define TKIP_COUNTERMEASURES_H
|
||||
|
||||
void michael_mic_failure(struct hostapd_data *hapd, const u8 *addr, int local);
|
||||
|
||||
#endif /* TKIP_COUNTERMEASURES_H */
|
88
hostapd-0.8/src/ap/utils.c
Normal file
88
hostapd-0.8/src/ap/utils.c
Normal file
|
@ -0,0 +1,88 @@
|
|||
/*
|
||||
* 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.
|
||||
*/
|
||||
|
||||
#include "includes.h"
|
||||
|
||||
#include "common.h"
|
||||
#include "common/ieee802_11_defs.h"
|
||||
#include "sta_info.h"
|
||||
#include "hostapd.h"
|
||||
|
||||
|
||||
int hostapd_register_probereq_cb(struct hostapd_data *hapd,
|
||||
int (*cb)(void *ctx, const u8 *sa,
|
||||
const u8 *ie, size_t ie_len),
|
||||
void *ctx)
|
||||
{
|
||||
struct hostapd_probereq_cb *n;
|
||||
|
||||
n = os_realloc(hapd->probereq_cb, (hapd->num_probereq_cb + 1) *
|
||||
sizeof(struct hostapd_probereq_cb));
|
||||
if (n == NULL)
|
||||
return -1;
|
||||
|
||||
hapd->probereq_cb = n;
|
||||
n = &hapd->probereq_cb[hapd->num_probereq_cb];
|
||||
hapd->num_probereq_cb++;
|
||||
|
||||
n->cb = cb;
|
||||
n->ctx = ctx;
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
|
||||
struct prune_data {
|
||||
struct hostapd_data *hapd;
|
||||
const u8 *addr;
|
||||
};
|
||||
|
||||
static int prune_associations(struct hostapd_iface *iface, void *ctx)
|
||||
{
|
||||
struct prune_data *data = ctx;
|
||||
struct sta_info *osta;
|
||||
struct hostapd_data *ohapd;
|
||||
size_t j;
|
||||
|
||||
for (j = 0; j < iface->num_bss; j++) {
|
||||
ohapd = iface->bss[j];
|
||||
if (ohapd == data->hapd)
|
||||
continue;
|
||||
osta = ap_get_sta(ohapd, data->addr);
|
||||
if (!osta)
|
||||
continue;
|
||||
|
||||
ap_sta_disassociate(ohapd, osta, WLAN_REASON_UNSPECIFIED);
|
||||
}
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
/**
|
||||
* hostapd_prune_associations - Remove extraneous associations
|
||||
* @hapd: Pointer to BSS data for the most recent association
|
||||
* @addr: Associated STA address
|
||||
*
|
||||
* This function looks through all radios and BSS's for previous
|
||||
* (stale) associations of STA. If any are found they are removed.
|
||||
*/
|
||||
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);
|
||||
}
|
905
hostapd-0.8/src/ap/vlan_init.c
Normal file
905
hostapd-0.8/src/ap/vlan_init.c
Normal file
|
@ -0,0 +1,905 @@
|
|||
/*
|
||||
* hostapd / VLAN initialization
|
||||
* Copyright 2003, Instant802 Networks, Inc.
|
||||
* Copyright 2005-2006, Devicescape Software, Inc.
|
||||
* 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.
|
||||
*/
|
||||
|
||||
#include "utils/includes.h"
|
||||
|
||||
#include "utils/common.h"
|
||||
#include "hostapd.h"
|
||||
#include "ap_config.h"
|
||||
#include "ap_drv_ops.h"
|
||||
#include "vlan_init.h"
|
||||
|
||||
|
||||
#ifdef CONFIG_FULL_DYNAMIC_VLAN
|
||||
|
||||
#include <net/if.h>
|
||||
#include <sys/ioctl.h>
|
||||
#include <linux/sockios.h>
|
||||
#include <linux/if_vlan.h>
|
||||
#include <linux/if_bridge.h>
|
||||
|
||||
#include "drivers/priv_netlink.h"
|
||||
#include "utils/eloop.h"
|
||||
|
||||
|
||||
struct full_dynamic_vlan {
|
||||
int s; /* socket on which to listen for new/removed interfaces. */
|
||||
};
|
||||
|
||||
|
||||
static int ifconfig_helper(const char *if_name, int up)
|
||||
{
|
||||
int fd;
|
||||
struct ifreq ifr;
|
||||
|
||||
if ((fd = socket(AF_INET, SOCK_STREAM, 0)) < 0) {
|
||||
wpa_printf(MSG_ERROR, "VLAN: %s: socket(AF_INET,SOCK_STREAM) "
|
||||
"failed: %s", __func__, strerror(errno));
|
||||
return -1;
|
||||
}
|
||||
|
||||
os_memset(&ifr, 0, sizeof(ifr));
|
||||
os_strlcpy(ifr.ifr_name, if_name, IFNAMSIZ);
|
||||
|
||||
if (ioctl(fd, SIOCGIFFLAGS, &ifr) != 0) {
|
||||
wpa_printf(MSG_ERROR, "VLAN: %s: ioctl(SIOCGIFFLAGS) failed "
|
||||
"for interface %s: %s",
|
||||
__func__, if_name, strerror(errno));
|
||||
close(fd);
|
||||
return -1;
|
||||
}
|
||||
|
||||
if (up)
|
||||
ifr.ifr_flags |= IFF_UP;
|
||||
else
|
||||
ifr.ifr_flags &= ~IFF_UP;
|
||||
|
||||
if (ioctl(fd, SIOCSIFFLAGS, &ifr) != 0) {
|
||||
wpa_printf(MSG_ERROR, "VLAN: %s: ioctl(SIOCSIFFLAGS) failed "
|
||||
"for interface %s (up=%d): %s",
|
||||
__func__, if_name, up, strerror(errno));
|
||||
close(fd);
|
||||
return -1;
|
||||
}
|
||||
|
||||
close(fd);
|
||||
return 0;
|
||||
}
|
||||
|
||||
|
||||
static int ifconfig_up(const char *if_name)
|
||||
{
|
||||
wpa_printf(MSG_DEBUG, "VLAN: Set interface %s up", if_name);
|
||||
return ifconfig_helper(if_name, 1);
|
||||
}
|
||||
|
||||
|
||||
static int ifconfig_down(const char *if_name)
|
||||
{
|
||||
wpa_printf(MSG_DEBUG, "VLAN: Set interface %s down", if_name);
|
||||
return ifconfig_helper(if_name, 0);
|
||||
}
|
||||
|
||||
|
||||
/*
|
||||
* These are only available in recent linux headers (without the leading
|
||||
* underscore).
|
||||
*/
|
||||
#define _GET_VLAN_REALDEV_NAME_CMD 8
|
||||
#define _GET_VLAN_VID_CMD 9
|
||||
|
||||
/* This value should be 256 ONLY. If it is something else, then hostapd
|
||||
* might crash!, as this value has been hard-coded in 2.4.x kernel
|
||||
* bridging code.
|
||||
*/
|
||||
#define MAX_BR_PORTS 256
|
||||
|
||||
static int br_delif(const char *br_name, const char *if_name)
|
||||
{
|
||||
int fd;
|
||||
struct ifreq ifr;
|
||||
unsigned long args[2];
|
||||
int if_index;
|
||||
|
||||
wpa_printf(MSG_DEBUG, "VLAN: br_delif(%s, %s)", br_name, if_name);
|
||||
if ((fd = socket(AF_INET, SOCK_STREAM, 0)) < 0) {
|
||||
wpa_printf(MSG_ERROR, "VLAN: %s: socket(AF_INET,SOCK_STREAM) "
|
||||
"failed: %s", __func__, strerror(errno));
|
||||
return -1;
|
||||
}
|
||||
|
||||
if_index = if_nametoindex(if_name);
|
||||
|
||||
if (if_index == 0) {
|
||||
wpa_printf(MSG_ERROR, "VLAN: %s: Failure determining "
|
||||
"interface index for '%s'",
|
||||
__func__, if_name);
|
||||
close(fd);
|
||||
return -1;
|
||||
}
|
||||
|
||||
args[0] = BRCTL_DEL_IF;
|
||||
args[1] = if_index;
|
||||
|
||||
os_strlcpy(ifr.ifr_name, br_name, sizeof(ifr.ifr_name));
|
||||
ifr.ifr_data = (__caddr_t) args;
|
||||
|
||||
if (ioctl(fd, SIOCDEVPRIVATE, &ifr) < 0 && errno != EINVAL) {
|
||||
/* No error if interface already removed. */
|
||||
wpa_printf(MSG_ERROR, "VLAN: %s: ioctl[SIOCDEVPRIVATE,"
|
||||
"BRCTL_DEL_IF] failed for br_name=%s if_name=%s: "
|
||||
"%s", __func__, br_name, if_name, strerror(errno));
|
||||
close(fd);
|
||||
return -1;
|
||||
}
|
||||
|
||||
close(fd);
|
||||
return 0;
|
||||
}
|
||||
|
||||
|
||||
/*
|
||||
Add interface 'if_name' to the bridge 'br_name'
|
||||
|
||||
returns -1 on error
|
||||
returns 1 if the interface is already part of the bridge
|
||||
returns 0 otherwise
|
||||
*/
|
||||
static int br_addif(const char *br_name, const char *if_name)
|
||||
{
|
||||
int fd;
|
||||
struct ifreq ifr;
|
||||
unsigned long args[2];
|
||||
int if_index;
|
||||
|
||||
wpa_printf(MSG_DEBUG, "VLAN: br_addif(%s, %s)", br_name, if_name);
|
||||
if ((fd = socket(AF_INET, SOCK_STREAM, 0)) < 0) {
|
||||
wpa_printf(MSG_ERROR, "VLAN: %s: socket(AF_INET,SOCK_STREAM) "
|
||||
"failed: %s", __func__, strerror(errno));
|
||||
return -1;
|
||||
}
|
||||
|
||||
if_index = if_nametoindex(if_name);
|
||||
|
||||
if (if_index == 0) {
|
||||
wpa_printf(MSG_ERROR, "VLAN: %s: Failure determining "
|
||||
"interface index for '%s'",
|
||||
__func__, if_name);
|
||||
close(fd);
|
||||
return -1;
|
||||
}
|
||||
|
||||
args[0] = BRCTL_ADD_IF;
|
||||
args[1] = if_index;
|
||||
|
||||
os_strlcpy(ifr.ifr_name, br_name, sizeof(ifr.ifr_name));
|
||||
ifr.ifr_data = (__caddr_t) args;
|
||||
|
||||
if (ioctl(fd, SIOCDEVPRIVATE, &ifr) < 0) {
|
||||
if (errno == EBUSY) {
|
||||
/* The interface is already added. */
|
||||
close(fd);
|
||||
return 1;
|
||||
}
|
||||
|
||||
wpa_printf(MSG_ERROR, "VLAN: %s: ioctl[SIOCDEVPRIVATE,"
|
||||
"BRCTL_ADD_IF] failed for br_name=%s if_name=%s: "
|
||||
"%s", __func__, br_name, if_name, strerror(errno));
|
||||
close(fd);
|
||||
return -1;
|
||||
}
|
||||
|
||||
close(fd);
|
||||
return 0;
|
||||
}
|
||||
|
||||
|
||||
static int br_delbr(const char *br_name)
|
||||
{
|
||||
int fd;
|
||||
unsigned long arg[2];
|
||||
|
||||
wpa_printf(MSG_DEBUG, "VLAN: br_delbr(%s)", br_name);
|
||||
if ((fd = socket(AF_INET, SOCK_STREAM, 0)) < 0) {
|
||||
wpa_printf(MSG_ERROR, "VLAN: %s: socket(AF_INET,SOCK_STREAM) "
|
||||
"failed: %s", __func__, strerror(errno));
|
||||
return -1;
|
||||
}
|
||||
|
||||
arg[0] = BRCTL_DEL_BRIDGE;
|
||||
arg[1] = (unsigned long) br_name;
|
||||
|
||||
if (ioctl(fd, SIOCGIFBR, arg) < 0 && errno != ENXIO) {
|
||||
/* No error if bridge already removed. */
|
||||
wpa_printf(MSG_ERROR, "VLAN: %s: BRCTL_DEL_BRIDGE failed for "
|
||||
"%s: %s", __func__, br_name, strerror(errno));
|
||||
close(fd);
|
||||
return -1;
|
||||
}
|
||||
|
||||
close(fd);
|
||||
return 0;
|
||||
}
|
||||
|
||||
|
||||
/*
|
||||
Add a bridge with the name 'br_name'.
|
||||
|
||||
returns -1 on error
|
||||
returns 1 if the bridge already exists
|
||||
returns 0 otherwise
|
||||
*/
|
||||
static int br_addbr(const char *br_name)
|
||||
{
|
||||
int fd;
|
||||
unsigned long arg[4];
|
||||
struct ifreq ifr;
|
||||
|
||||
wpa_printf(MSG_DEBUG, "VLAN: br_addbr(%s)", br_name);
|
||||
if ((fd = socket(AF_INET, SOCK_STREAM, 0)) < 0) {
|
||||
wpa_printf(MSG_ERROR, "VLAN: %s: socket(AF_INET,SOCK_STREAM) "
|
||||
"failed: %s", __func__, strerror(errno));
|
||||
return -1;
|
||||
}
|
||||
|
||||
arg[0] = BRCTL_ADD_BRIDGE;
|
||||
arg[1] = (unsigned long) br_name;
|
||||
|
||||
if (ioctl(fd, SIOCGIFBR, arg) < 0) {
|
||||
if (errno == EEXIST) {
|
||||
/* The bridge is already added. */
|
||||
close(fd);
|
||||
return 1;
|
||||
} else {
|
||||
wpa_printf(MSG_ERROR, "VLAN: %s: BRCTL_ADD_BRIDGE "
|
||||
"failed for %s: %s",
|
||||
__func__, br_name, strerror(errno));
|
||||
close(fd);
|
||||
return -1;
|
||||
}
|
||||
}
|
||||
|
||||
/* Decrease forwarding delay to avoid EAPOL timeouts. */
|
||||
os_memset(&ifr, 0, sizeof(ifr));
|
||||
os_strlcpy(ifr.ifr_name, br_name, IFNAMSIZ);
|
||||
arg[0] = BRCTL_SET_BRIDGE_FORWARD_DELAY;
|
||||
arg[1] = 1;
|
||||
arg[2] = 0;
|
||||
arg[3] = 0;
|
||||
ifr.ifr_data = (char *) &arg;
|
||||
if (ioctl(fd, SIOCDEVPRIVATE, &ifr) < 0) {
|
||||
wpa_printf(MSG_ERROR, "VLAN: %s: "
|
||||
"BRCTL_SET_BRIDGE_FORWARD_DELAY (1 sec) failed for "
|
||||
"%s: %s", __func__, br_name, strerror(errno));
|
||||
/* Continue anyway */
|
||||
}
|
||||
|
||||
close(fd);
|
||||
return 0;
|
||||
}
|
||||
|
||||
|
||||
static int br_getnumports(const char *br_name)
|
||||
{
|
||||
int fd;
|
||||
int i;
|
||||
int port_cnt = 0;
|
||||
unsigned long arg[4];
|
||||
int ifindices[MAX_BR_PORTS];
|
||||
struct ifreq ifr;
|
||||
|
||||
if ((fd = socket(AF_INET, SOCK_STREAM, 0)) < 0) {
|
||||
wpa_printf(MSG_ERROR, "VLAN: %s: socket(AF_INET,SOCK_STREAM) "
|
||||
"failed: %s", __func__, strerror(errno));
|
||||
return -1;
|
||||
}
|
||||
|
||||
arg[0] = BRCTL_GET_PORT_LIST;
|
||||
arg[1] = (unsigned long) ifindices;
|
||||
arg[2] = MAX_BR_PORTS;
|
||||
arg[3] = 0;
|
||||
|
||||
os_memset(ifindices, 0, sizeof(ifindices));
|
||||
os_strlcpy(ifr.ifr_name, br_name, sizeof(ifr.ifr_name));
|
||||
ifr.ifr_data = (__caddr_t) arg;
|
||||
|
||||
if (ioctl(fd, SIOCDEVPRIVATE, &ifr) < 0) {
|
||||
wpa_printf(MSG_ERROR, "VLAN: %s: BRCTL_GET_PORT_LIST "
|
||||
"failed for %s: %s",
|
||||
__func__, br_name, strerror(errno));
|
||||
close(fd);
|
||||
return -1;
|
||||
}
|
||||
|
||||
for (i = 1; i < MAX_BR_PORTS; i++) {
|
||||
if (ifindices[i] > 0) {
|
||||
port_cnt++;
|
||||
}
|
||||
}
|
||||
|
||||
close(fd);
|
||||
return port_cnt;
|
||||
}
|
||||
|
||||
|
||||
static int vlan_rem(const char *if_name)
|
||||
{
|
||||
int fd;
|
||||
struct vlan_ioctl_args if_request;
|
||||
|
||||
wpa_printf(MSG_DEBUG, "VLAN: vlan_rem(%s)", if_name);
|
||||
if ((os_strlen(if_name) + 1) > sizeof(if_request.device1)) {
|
||||
wpa_printf(MSG_ERROR, "VLAN: Interface name too long: '%s'",
|
||||
if_name);
|
||||
return -1;
|
||||
}
|
||||
|
||||
if ((fd = socket(AF_INET, SOCK_STREAM, 0)) < 0) {
|
||||
wpa_printf(MSG_ERROR, "VLAN: %s: socket(AF_INET,SOCK_STREAM) "
|
||||
"failed: %s", __func__, strerror(errno));
|
||||
return -1;
|
||||
}
|
||||
|
||||
os_memset(&if_request, 0, sizeof(if_request));
|
||||
|
||||
os_strlcpy(if_request.device1, if_name, sizeof(if_request.device1));
|
||||
if_request.cmd = DEL_VLAN_CMD;
|
||||
|
||||
if (ioctl(fd, SIOCSIFVLAN, &if_request) < 0) {
|
||||
wpa_printf(MSG_ERROR, "VLAN: %s: DEL_VLAN_CMD failed for %s: "
|
||||
"%s", __func__, if_name, strerror(errno));
|
||||
close(fd);
|
||||
return -1;
|
||||
}
|
||||
|
||||
close(fd);
|
||||
return 0;
|
||||
}
|
||||
|
||||
|
||||
/*
|
||||
Add a vlan interface with VLAN ID 'vid' and tagged interface
|
||||
'if_name'.
|
||||
|
||||
returns -1 on error
|
||||
returns 1 if the interface already exists
|
||||
returns 0 otherwise
|
||||
*/
|
||||
static int vlan_add(const char *if_name, int vid)
|
||||
{
|
||||
int fd;
|
||||
struct vlan_ioctl_args if_request;
|
||||
|
||||
wpa_printf(MSG_DEBUG, "VLAN: vlan_add(if_name=%s, vid=%d)",
|
||||
if_name, vid);
|
||||
ifconfig_up(if_name);
|
||||
|
||||
if ((os_strlen(if_name) + 1) > sizeof(if_request.device1)) {
|
||||
wpa_printf(MSG_ERROR, "VLAN: Interface name too long: '%s'",
|
||||
if_name);
|
||||
return -1;
|
||||
}
|
||||
|
||||
if ((fd = socket(AF_INET, SOCK_STREAM, 0)) < 0) {
|
||||
wpa_printf(MSG_ERROR, "VLAN: %s: socket(AF_INET,SOCK_STREAM) "
|
||||
"failed: %s", __func__, strerror(errno));
|
||||
return -1;
|
||||
}
|
||||
|
||||
os_memset(&if_request, 0, sizeof(if_request));
|
||||
|
||||
/* Determine if a suitable vlan device already exists. */
|
||||
|
||||
os_snprintf(if_request.device1, sizeof(if_request.device1), "vlan%d",
|
||||
vid);
|
||||
|
||||
if_request.cmd = _GET_VLAN_VID_CMD;
|
||||
|
||||
if (ioctl(fd, SIOCSIFVLAN, &if_request) == 0) {
|
||||
|
||||
if (if_request.u.VID == vid) {
|
||||
if_request.cmd = _GET_VLAN_REALDEV_NAME_CMD;
|
||||
|
||||
if (ioctl(fd, SIOCSIFVLAN, &if_request) == 0 &&
|
||||
os_strncmp(if_request.u.device2, if_name,
|
||||
sizeof(if_request.u.device2)) == 0) {
|
||||
close(fd);
|
||||
wpa_printf(MSG_DEBUG, "VLAN: vlan_add: "
|
||||
"if_name %s exists already",
|
||||
if_request.device1);
|
||||
return 1;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
/* A suitable vlan device does not already exist, add one. */
|
||||
|
||||
os_memset(&if_request, 0, sizeof(if_request));
|
||||
os_strlcpy(if_request.device1, if_name, sizeof(if_request.device1));
|
||||
if_request.u.VID = vid;
|
||||
if_request.cmd = ADD_VLAN_CMD;
|
||||
|
||||
if (ioctl(fd, SIOCSIFVLAN, &if_request) < 0) {
|
||||
wpa_printf(MSG_ERROR, "VLAN: %s: ADD_VLAN_CMD failed for %s: "
|
||||
"%s",
|
||||
__func__, if_request.device1, strerror(errno));
|
||||
close(fd);
|
||||
return -1;
|
||||
}
|
||||
|
||||
close(fd);
|
||||
return 0;
|
||||
}
|
||||
|
||||
|
||||
static int vlan_set_name_type(unsigned int name_type)
|
||||
{
|
||||
int fd;
|
||||
struct vlan_ioctl_args if_request;
|
||||
|
||||
wpa_printf(MSG_DEBUG, "VLAN: vlan_set_name_type(name_type=%u)",
|
||||
name_type);
|
||||
if ((fd = socket(AF_INET, SOCK_STREAM, 0)) < 0) {
|
||||
wpa_printf(MSG_ERROR, "VLAN: %s: socket(AF_INET,SOCK_STREAM) "
|
||||
"failed: %s", __func__, strerror(errno));
|
||||
return -1;
|
||||
}
|
||||
|
||||
os_memset(&if_request, 0, sizeof(if_request));
|
||||
|
||||
if_request.u.name_type = name_type;
|
||||
if_request.cmd = SET_VLAN_NAME_TYPE_CMD;
|
||||
if (ioctl(fd, SIOCSIFVLAN, &if_request) < 0) {
|
||||
wpa_printf(MSG_ERROR, "VLAN: %s: SET_VLAN_NAME_TYPE_CMD "
|
||||
"name_type=%u failed: %s",
|
||||
__func__, name_type, strerror(errno));
|
||||
close(fd);
|
||||
return -1;
|
||||
}
|
||||
|
||||
close(fd);
|
||||
return 0;
|
||||
}
|
||||
|
||||
|
||||
static void vlan_newlink(char *ifname, struct hostapd_data *hapd)
|
||||
{
|
||||
char vlan_ifname[IFNAMSIZ];
|
||||
char br_name[IFNAMSIZ];
|
||||
struct hostapd_vlan *vlan = hapd->conf->vlan;
|
||||
char *tagged_interface = hapd->conf->ssid.vlan_tagged_interface;
|
||||
|
||||
wpa_printf(MSG_DEBUG, "VLAN: vlan_newlink(%s)", ifname);
|
||||
|
||||
while (vlan) {
|
||||
if (os_strcmp(ifname, vlan->ifname) == 0) {
|
||||
|
||||
os_snprintf(br_name, sizeof(br_name), "brvlan%d",
|
||||
vlan->vlan_id);
|
||||
|
||||
if (!br_addbr(br_name))
|
||||
vlan->clean |= DVLAN_CLEAN_BR;
|
||||
|
||||
ifconfig_up(br_name);
|
||||
|
||||
if (tagged_interface) {
|
||||
|
||||
if (!vlan_add(tagged_interface, vlan->vlan_id))
|
||||
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;
|
||||
|
||||
ifconfig_up(vlan_ifname);
|
||||
}
|
||||
|
||||
if (!br_addif(br_name, ifname))
|
||||
vlan->clean |= DVLAN_CLEAN_WLAN_PORT;
|
||||
|
||||
ifconfig_up(ifname);
|
||||
|
||||
break;
|
||||
}
|
||||
vlan = vlan->next;
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
static void vlan_dellink(char *ifname, struct hostapd_data *hapd)
|
||||
{
|
||||
char vlan_ifname[IFNAMSIZ];
|
||||
char br_name[IFNAMSIZ];
|
||||
struct hostapd_vlan *first, *prev, *vlan = hapd->conf->vlan;
|
||||
char *tagged_interface = hapd->conf->ssid.vlan_tagged_interface;
|
||||
|
||||
wpa_printf(MSG_DEBUG, "VLAN: vlan_dellink(%s)", ifname);
|
||||
|
||||
first = prev = vlan;
|
||||
|
||||
while (vlan) {
|
||||
if (os_strcmp(ifname, vlan->ifname) == 0) {
|
||||
os_snprintf(br_name, sizeof(br_name), "brvlan%d",
|
||||
vlan->vlan_id);
|
||||
|
||||
if (vlan->clean & DVLAN_CLEAN_WLAN_PORT)
|
||||
br_delif(br_name, vlan->ifname);
|
||||
|
||||
if (tagged_interface) {
|
||||
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);
|
||||
|
||||
if (vlan->clean & DVLAN_CLEAN_VLAN)
|
||||
vlan_rem(vlan_ifname);
|
||||
}
|
||||
|
||||
if ((vlan->clean & DVLAN_CLEAN_BR) &&
|
||||
br_getnumports(br_name) == 0) {
|
||||
ifconfig_down(br_name);
|
||||
br_delbr(br_name);
|
||||
}
|
||||
|
||||
if (vlan == first) {
|
||||
hapd->conf->vlan = vlan->next;
|
||||
} else {
|
||||
prev->next = vlan->next;
|
||||
}
|
||||
os_free(vlan);
|
||||
|
||||
break;
|
||||
}
|
||||
prev = vlan;
|
||||
vlan = vlan->next;
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
static void
|
||||
vlan_read_ifnames(struct nlmsghdr *h, size_t len, int del,
|
||||
struct hostapd_data *hapd)
|
||||
{
|
||||
struct ifinfomsg *ifi;
|
||||
int attrlen, nlmsg_len, rta_len;
|
||||
struct rtattr *attr;
|
||||
|
||||
if (len < sizeof(*ifi))
|
||||
return;
|
||||
|
||||
ifi = NLMSG_DATA(h);
|
||||
|
||||
nlmsg_len = NLMSG_ALIGN(sizeof(struct ifinfomsg));
|
||||
|
||||
attrlen = h->nlmsg_len - nlmsg_len;
|
||||
if (attrlen < 0)
|
||||
return;
|
||||
|
||||
attr = (struct rtattr *) (((char *) ifi) + nlmsg_len);
|
||||
|
||||
rta_len = RTA_ALIGN(sizeof(struct rtattr));
|
||||
while (RTA_OK(attr, attrlen)) {
|
||||
char ifname[IFNAMSIZ + 1];
|
||||
|
||||
if (attr->rta_type == IFLA_IFNAME) {
|
||||
int n = attr->rta_len - rta_len;
|
||||
if (n < 0)
|
||||
break;
|
||||
|
||||
os_memset(ifname, 0, sizeof(ifname));
|
||||
|
||||
if ((size_t) n > sizeof(ifname))
|
||||
n = sizeof(ifname);
|
||||
os_memcpy(ifname, ((char *) attr) + rta_len, n);
|
||||
|
||||
if (del)
|
||||
vlan_dellink(ifname, hapd);
|
||||
else
|
||||
vlan_newlink(ifname, hapd);
|
||||
}
|
||||
|
||||
attr = RTA_NEXT(attr, attrlen);
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
static void vlan_event_receive(int sock, void *eloop_ctx, void *sock_ctx)
|
||||
{
|
||||
char buf[8192];
|
||||
int left;
|
||||
struct sockaddr_nl from;
|
||||
socklen_t fromlen;
|
||||
struct nlmsghdr *h;
|
||||
struct hostapd_data *hapd = eloop_ctx;
|
||||
|
||||
fromlen = sizeof(from);
|
||||
left = recvfrom(sock, buf, sizeof(buf), MSG_DONTWAIT,
|
||||
(struct sockaddr *) &from, &fromlen);
|
||||
if (left < 0) {
|
||||
if (errno != EINTR && errno != EAGAIN)
|
||||
wpa_printf(MSG_ERROR, "VLAN: %s: recvfrom failed: %s",
|
||||
__func__, strerror(errno));
|
||||
return;
|
||||
}
|
||||
|
||||
h = (struct nlmsghdr *) buf;
|
||||
while (left >= (int) sizeof(*h)) {
|
||||
int len, plen;
|
||||
|
||||
len = h->nlmsg_len;
|
||||
plen = len - sizeof(*h);
|
||||
if (len > left || plen < 0) {
|
||||
wpa_printf(MSG_DEBUG, "VLAN: Malformed netlink "
|
||||
"message: len=%d left=%d plen=%d",
|
||||
len, left, plen);
|
||||
break;
|
||||
}
|
||||
|
||||
switch (h->nlmsg_type) {
|
||||
case RTM_NEWLINK:
|
||||
vlan_read_ifnames(h, plen, 0, hapd);
|
||||
break;
|
||||
case RTM_DELLINK:
|
||||
vlan_read_ifnames(h, plen, 1, hapd);
|
||||
break;
|
||||
}
|
||||
|
||||
len = NLMSG_ALIGN(len);
|
||||
left -= len;
|
||||
h = (struct nlmsghdr *) ((char *) h + len);
|
||||
}
|
||||
|
||||
if (left > 0) {
|
||||
wpa_printf(MSG_DEBUG, "VLAN: %s: %d extra bytes in the end of "
|
||||
"netlink message", __func__, left);
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
static struct full_dynamic_vlan *
|
||||
full_dynamic_vlan_init(struct hostapd_data *hapd)
|
||||
{
|
||||
struct sockaddr_nl local;
|
||||
struct full_dynamic_vlan *priv;
|
||||
|
||||
priv = os_zalloc(sizeof(*priv));
|
||||
if (priv == NULL)
|
||||
return NULL;
|
||||
|
||||
vlan_set_name_type(VLAN_NAME_TYPE_PLUS_VID_NO_PAD);
|
||||
|
||||
priv->s = socket(PF_NETLINK, SOCK_RAW, NETLINK_ROUTE);
|
||||
if (priv->s < 0) {
|
||||
wpa_printf(MSG_ERROR, "VLAN: %s: socket(PF_NETLINK,SOCK_RAW,"
|
||||
"NETLINK_ROUTE) failed: %s",
|
||||
__func__, strerror(errno));
|
||||
os_free(priv);
|
||||
return NULL;
|
||||
}
|
||||
|
||||
os_memset(&local, 0, sizeof(local));
|
||||
local.nl_family = AF_NETLINK;
|
||||
local.nl_groups = RTMGRP_LINK;
|
||||
if (bind(priv->s, (struct sockaddr *) &local, sizeof(local)) < 0) {
|
||||
wpa_printf(MSG_ERROR, "VLAN: %s: bind(netlink) failed: %s",
|
||||
__func__, strerror(errno));
|
||||
close(priv->s);
|
||||
os_free(priv);
|
||||
return NULL;
|
||||
}
|
||||
|
||||
if (eloop_register_read_sock(priv->s, vlan_event_receive, hapd, NULL))
|
||||
{
|
||||
close(priv->s);
|
||||
os_free(priv);
|
||||
return NULL;
|
||||
}
|
||||
|
||||
return priv;
|
||||
}
|
||||
|
||||
|
||||
static void full_dynamic_vlan_deinit(struct full_dynamic_vlan *priv)
|
||||
{
|
||||
if (priv == NULL)
|
||||
return;
|
||||
eloop_unregister_read_sock(priv->s);
|
||||
close(priv->s);
|
||||
os_free(priv);
|
||||
}
|
||||
#endif /* CONFIG_FULL_DYNAMIC_VLAN */
|
||||
|
||||
|
||||
int vlan_setup_encryption_dyn(struct hostapd_data *hapd,
|
||||
struct hostapd_ssid *mssid, const char *dyn_vlan)
|
||||
{
|
||||
int i;
|
||||
|
||||
if (dyn_vlan == NULL)
|
||||
return 0;
|
||||
|
||||
/* Static WEP keys are set here; IEEE 802.1X and WPA uses their own
|
||||
* functions for setting up dynamic broadcast keys. */
|
||||
for (i = 0; i < 4; i++) {
|
||||
if (mssid->wep.key[i] &&
|
||||
hostapd_drv_set_key(dyn_vlan, hapd, WPA_ALG_WEP, NULL, i,
|
||||
i == mssid->wep.idx, NULL, 0,
|
||||
mssid->wep.key[i], mssid->wep.len[i]))
|
||||
{
|
||||
wpa_printf(MSG_ERROR, "VLAN: Could not set WEP "
|
||||
"encryption for dynamic VLAN");
|
||||
return -1;
|
||||
}
|
||||
}
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
|
||||
static int vlan_dynamic_add(struct hostapd_data *hapd,
|
||||
struct hostapd_vlan *vlan)
|
||||
{
|
||||
while (vlan) {
|
||||
if (vlan->vlan_id != VLAN_ID_WILDCARD) {
|
||||
if (hostapd_vlan_if_add(hapd, vlan->ifname)) {
|
||||
if (errno != EEXIST) {
|
||||
wpa_printf(MSG_ERROR, "VLAN: Could "
|
||||
"not add VLAN %s: %s",
|
||||
vlan->ifname,
|
||||
strerror(errno));
|
||||
return -1;
|
||||
}
|
||||
}
|
||||
#ifdef CONFIG_FULL_DYNAMIC_VLAN
|
||||
ifconfig_up(vlan->ifname);
|
||||
#endif /* CONFIG_FULL_DYNAMIC_VLAN */
|
||||
}
|
||||
|
||||
vlan = vlan->next;
|
||||
}
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
|
||||
static void vlan_dynamic_remove(struct hostapd_data *hapd,
|
||||
struct hostapd_vlan *vlan)
|
||||
{
|
||||
struct hostapd_vlan *next;
|
||||
|
||||
while (vlan) {
|
||||
next = vlan->next;
|
||||
|
||||
if (vlan->vlan_id != VLAN_ID_WILDCARD &&
|
||||
hostapd_vlan_if_remove(hapd, vlan->ifname)) {
|
||||
wpa_printf(MSG_ERROR, "VLAN: Could not remove VLAN "
|
||||
"iface: %s: %s",
|
||||
vlan->ifname, strerror(errno));
|
||||
}
|
||||
#ifdef CONFIG_FULL_DYNAMIC_VLAN
|
||||
if (vlan->clean)
|
||||
vlan_dellink(vlan->ifname, hapd);
|
||||
#endif /* CONFIG_FULL_DYNAMIC_VLAN */
|
||||
|
||||
vlan = next;
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
int vlan_init(struct hostapd_data *hapd)
|
||||
{
|
||||
#ifdef CONFIG_FULL_DYNAMIC_VLAN
|
||||
hapd->full_dynamic_vlan = full_dynamic_vlan_init(hapd);
|
||||
#endif /* CONFIG_FULL_DYNAMIC_VLAN */
|
||||
|
||||
if (vlan_dynamic_add(hapd, hapd->conf->vlan))
|
||||
return -1;
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
|
||||
void vlan_deinit(struct hostapd_data *hapd)
|
||||
{
|
||||
vlan_dynamic_remove(hapd, hapd->conf->vlan);
|
||||
|
||||
#ifdef CONFIG_FULL_DYNAMIC_VLAN
|
||||
full_dynamic_vlan_deinit(hapd->full_dynamic_vlan);
|
||||
#endif /* CONFIG_FULL_DYNAMIC_VLAN */
|
||||
}
|
||||
|
||||
|
||||
struct hostapd_vlan * vlan_add_dynamic(struct hostapd_data *hapd,
|
||||
struct hostapd_vlan *vlan,
|
||||
int vlan_id)
|
||||
{
|
||||
struct hostapd_vlan *n;
|
||||
char *ifname, *pos;
|
||||
|
||||
if (vlan == NULL || vlan_id <= 0 || vlan_id > MAX_VLAN_ID ||
|
||||
vlan->vlan_id != VLAN_ID_WILDCARD)
|
||||
return NULL;
|
||||
|
||||
wpa_printf(MSG_DEBUG, "VLAN: %s(vlan_id=%d ifname=%s)",
|
||||
__func__, vlan_id, vlan->ifname);
|
||||
ifname = os_strdup(vlan->ifname);
|
||||
if (ifname == NULL)
|
||||
return NULL;
|
||||
pos = os_strchr(ifname, '#');
|
||||
if (pos == NULL) {
|
||||
os_free(ifname);
|
||||
return NULL;
|
||||
}
|
||||
*pos++ = '\0';
|
||||
|
||||
n = os_zalloc(sizeof(*n));
|
||||
if (n == NULL) {
|
||||
os_free(ifname);
|
||||
return NULL;
|
||||
}
|
||||
|
||||
n->vlan_id = vlan_id;
|
||||
n->dynamic_vlan = 1;
|
||||
|
||||
os_snprintf(n->ifname, sizeof(n->ifname), "%s%d%s", ifname, vlan_id,
|
||||
pos);
|
||||
os_free(ifname);
|
||||
|
||||
if (hostapd_vlan_if_add(hapd, n->ifname)) {
|
||||
os_free(n);
|
||||
return NULL;
|
||||
}
|
||||
|
||||
n->next = hapd->conf->vlan;
|
||||
hapd->conf->vlan = n;
|
||||
|
||||
#ifdef CONFIG_FULL_DYNAMIC_VLAN
|
||||
ifconfig_up(n->ifname);
|
||||
#endif /* CONFIG_FULL_DYNAMIC_VLAN */
|
||||
|
||||
return n;
|
||||
}
|
||||
|
||||
|
||||
int vlan_remove_dynamic(struct hostapd_data *hapd, int vlan_id)
|
||||
{
|
||||
struct hostapd_vlan *vlan;
|
||||
|
||||
if (vlan_id <= 0 || vlan_id > MAX_VLAN_ID)
|
||||
return 1;
|
||||
|
||||
wpa_printf(MSG_DEBUG, "VLAN: %s(vlan_id=%d)", __func__, vlan_id);
|
||||
|
||||
vlan = hapd->conf->vlan;
|
||||
while (vlan) {
|
||||
if (vlan->vlan_id == vlan_id && vlan->dynamic_vlan > 0) {
|
||||
vlan->dynamic_vlan--;
|
||||
break;
|
||||
}
|
||||
vlan = vlan->next;
|
||||
}
|
||||
|
||||
if (vlan == NULL)
|
||||
return 1;
|
||||
|
||||
if (vlan->dynamic_vlan == 0)
|
||||
hostapd_vlan_if_remove(hapd, vlan->ifname);
|
||||
|
||||
return 0;
|
||||
}
|
59
hostapd-0.8/src/ap/vlan_init.h
Normal file
59
hostapd-0.8/src/ap/vlan_init.h
Normal file
|
@ -0,0 +1,59 @@
|
|||
/*
|
||||
* hostapd / VLAN initialization
|
||||
* Copyright 2003, Instant802 Networks, Inc.
|
||||
* Copyright 2005, 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.
|
||||
*/
|
||||
|
||||
#ifndef VLAN_INIT_H
|
||||
#define VLAN_INIT_H
|
||||
|
||||
#ifndef CONFIG_NO_VLAN
|
||||
int vlan_init(struct hostapd_data *hapd);
|
||||
void vlan_deinit(struct hostapd_data *hapd);
|
||||
struct hostapd_vlan * vlan_add_dynamic(struct hostapd_data *hapd,
|
||||
struct hostapd_vlan *vlan,
|
||||
int vlan_id);
|
||||
int vlan_remove_dynamic(struct hostapd_data *hapd, int vlan_id);
|
||||
int vlan_setup_encryption_dyn(struct hostapd_data *hapd,
|
||||
struct hostapd_ssid *mssid,
|
||||
const char *dyn_vlan);
|
||||
#else /* CONFIG_NO_VLAN */
|
||||
static inline int vlan_init(struct hostapd_data *hapd)
|
||||
{
|
||||
return 0;
|
||||
}
|
||||
|
||||
static inline void vlan_deinit(struct hostapd_data *hapd)
|
||||
{
|
||||
}
|
||||
|
||||
static inline struct hostapd_vlan * vlan_add_dynamic(struct hostapd_data *hapd,
|
||||
struct hostapd_vlan *vlan,
|
||||
int vlan_id)
|
||||
{
|
||||
return NULL;
|
||||
}
|
||||
|
||||
static inline int vlan_remove_dynamic(struct hostapd_data *hapd, int vlan_id)
|
||||
{
|
||||
return -1;
|
||||
}
|
||||
|
||||
static inline int vlan_setup_encryption_dyn(struct hostapd_data *hapd,
|
||||
struct hostapd_ssid *mssid,
|
||||
const char *dyn_vlan)
|
||||
{
|
||||
return -1;
|
||||
}
|
||||
#endif /* CONFIG_NO_VLAN */
|
||||
|
||||
#endif /* VLAN_INIT_H */
|
327
hostapd-0.8/src/ap/wmm.c
Normal file
327
hostapd-0.8/src/ap/wmm.c
Normal file
|
@ -0,0 +1,327 @@
|
|||
/*
|
||||
* hostapd / WMM (Wi-Fi Multimedia)
|
||||
* Copyright 2002-2003, Instant802 Networks, Inc.
|
||||
* Copyright 2005-2006, Devicescape Software, Inc.
|
||||
* 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.
|
||||
*/
|
||||
|
||||
#include "utils/includes.h"
|
||||
|
||||
#include "utils/common.h"
|
||||
#include "common/ieee802_11_defs.h"
|
||||
#include "common/ieee802_11_common.h"
|
||||
#include "hostapd.h"
|
||||
#include "ieee802_11.h"
|
||||
#include "sta_info.h"
|
||||
#include "ap_config.h"
|
||||
#include "ap_drv_ops.h"
|
||||
#include "wmm.h"
|
||||
|
||||
|
||||
/* TODO: maintain separate sequence and fragment numbers for each AC
|
||||
* TODO: IGMP snooping to track which multicasts to forward - and use QOS-DATA
|
||||
* if only WMM stations are receiving a certain group */
|
||||
|
||||
|
||||
static inline u8 wmm_aci_aifsn(int aifsn, int acm, int aci)
|
||||
{
|
||||
u8 ret;
|
||||
ret = (aifsn << WMM_AC_AIFNS_SHIFT) & WMM_AC_AIFSN_MASK;
|
||||
if (acm)
|
||||
ret |= WMM_AC_ACM;
|
||||
ret |= (aci << WMM_AC_ACI_SHIFT) & WMM_AC_ACI_MASK;
|
||||
return ret;
|
||||
}
|
||||
|
||||
|
||||
static inline u8 wmm_ecw(int ecwmin, int ecwmax)
|
||||
{
|
||||
return ((ecwmin << WMM_AC_ECWMIN_SHIFT) & WMM_AC_ECWMIN_MASK) |
|
||||
((ecwmax << WMM_AC_ECWMAX_SHIFT) & WMM_AC_ECWMAX_MASK);
|
||||
}
|
||||
|
||||
|
||||
/*
|
||||
* Add WMM Parameter Element to Beacon, Probe Response, and (Re)Association
|
||||
* Response frames.
|
||||
*/
|
||||
u8 * hostapd_eid_wmm(struct hostapd_data *hapd, u8 *eid)
|
||||
{
|
||||
u8 *pos = eid;
|
||||
struct wmm_parameter_element *wmm =
|
||||
(struct wmm_parameter_element *) (pos + 2);
|
||||
int e;
|
||||
|
||||
if (!hapd->conf->wmm_enabled)
|
||||
return eid;
|
||||
eid[0] = WLAN_EID_VENDOR_SPECIFIC;
|
||||
wmm->oui[0] = 0x00;
|
||||
wmm->oui[1] = 0x50;
|
||||
wmm->oui[2] = 0xf2;
|
||||
wmm->oui_type = WMM_OUI_TYPE;
|
||||
wmm->oui_subtype = WMM_OUI_SUBTYPE_PARAMETER_ELEMENT;
|
||||
wmm->version = WMM_VERSION;
|
||||
wmm->qos_info = hapd->parameter_set_count & 0xf;
|
||||
|
||||
if (hapd->conf->wmm_uapsd)
|
||||
wmm->qos_info |= 0x80;
|
||||
|
||||
wmm->reserved = 0;
|
||||
|
||||
/* fill in a parameter set record for each AC */
|
||||
for (e = 0; e < 4; e++) {
|
||||
struct wmm_ac_parameter *ac = &wmm->ac[e];
|
||||
struct hostapd_wmm_ac_params *acp =
|
||||
&hapd->iconf->wmm_ac_params[e];
|
||||
|
||||
ac->aci_aifsn = wmm_aci_aifsn(acp->aifs,
|
||||
acp->admission_control_mandatory,
|
||||
e);
|
||||
ac->cw = wmm_ecw(acp->cwmin, acp->cwmax);
|
||||
ac->txop_limit = host_to_le16(acp->txop_limit);
|
||||
}
|
||||
|
||||
pos = (u8 *) (wmm + 1);
|
||||
eid[1] = pos - eid - 2; /* element length */
|
||||
|
||||
return pos;
|
||||
}
|
||||
|
||||
|
||||
/* This function is called when a station sends an association request with
|
||||
* WMM info element. The function returns zero on success or non-zero on any
|
||||
* error in WMM element. eid does not include Element ID and Length octets. */
|
||||
int hostapd_eid_wmm_valid(struct hostapd_data *hapd, const u8 *eid, size_t len)
|
||||
{
|
||||
struct wmm_information_element *wmm;
|
||||
|
||||
wpa_hexdump(MSG_MSGDUMP, "WMM IE", eid, len);
|
||||
|
||||
if (len < sizeof(struct wmm_information_element)) {
|
||||
wpa_printf(MSG_DEBUG, "Too short WMM IE (len=%lu)",
|
||||
(unsigned long) len);
|
||||
return -1;
|
||||
}
|
||||
|
||||
wmm = (struct wmm_information_element *) eid;
|
||||
wpa_printf(MSG_DEBUG, "Validating WMM IE: OUI %02x:%02x:%02x "
|
||||
"OUI type %d OUI sub-type %d version %d QoS info 0x%x",
|
||||
wmm->oui[0], wmm->oui[1], wmm->oui[2], wmm->oui_type,
|
||||
wmm->oui_subtype, wmm->version, wmm->qos_info);
|
||||
if (wmm->oui_subtype != WMM_OUI_SUBTYPE_INFORMATION_ELEMENT ||
|
||||
wmm->version != WMM_VERSION) {
|
||||
wpa_printf(MSG_DEBUG, "Unsupported WMM IE Subtype/Version");
|
||||
return -1;
|
||||
}
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
|
||||
static void wmm_send_action(struct hostapd_data *hapd, const u8 *addr,
|
||||
const struct wmm_tspec_element *tspec,
|
||||
u8 action_code, u8 dialogue_token, u8 status_code)
|
||||
{
|
||||
u8 buf[256];
|
||||
struct ieee80211_mgmt *m = (struct ieee80211_mgmt *) buf;
|
||||
struct wmm_tspec_element *t = (struct wmm_tspec_element *)
|
||||
m->u.action.u.wmm_action.variable;
|
||||
int len;
|
||||
|
||||
hostapd_logger(hapd, addr, HOSTAPD_MODULE_IEEE80211,
|
||||
HOSTAPD_LEVEL_DEBUG,
|
||||
"action response - reason %d", status_code);
|
||||
os_memset(buf, 0, sizeof(buf));
|
||||
m->frame_control = IEEE80211_FC(WLAN_FC_TYPE_MGMT,
|
||||
WLAN_FC_STYPE_ACTION);
|
||||
os_memcpy(m->da, addr, ETH_ALEN);
|
||||
os_memcpy(m->sa, hapd->own_addr, ETH_ALEN);
|
||||
os_memcpy(m->bssid, hapd->own_addr, ETH_ALEN);
|
||||
m->u.action.category = WLAN_ACTION_WMM;
|
||||
m->u.action.u.wmm_action.action_code = action_code;
|
||||
m->u.action.u.wmm_action.dialog_token = dialogue_token;
|
||||
m->u.action.u.wmm_action.status_code = status_code;
|
||||
os_memcpy(t, tspec, sizeof(struct wmm_tspec_element));
|
||||
len = ((u8 *) (t + 1)) - buf;
|
||||
|
||||
if (hostapd_drv_send_mlme(hapd, m, len) < 0)
|
||||
perror("wmm_send_action: send");
|
||||
}
|
||||
|
||||
|
||||
int wmm_process_tspec(struct wmm_tspec_element *tspec)
|
||||
{
|
||||
int medium_time, pps, duration;
|
||||
int up, psb, dir, tid;
|
||||
u16 val, surplus;
|
||||
|
||||
up = (tspec->ts_info[1] >> 3) & 0x07;
|
||||
psb = (tspec->ts_info[1] >> 2) & 0x01;
|
||||
dir = (tspec->ts_info[0] >> 5) & 0x03;
|
||||
tid = (tspec->ts_info[0] >> 1) & 0x0f;
|
||||
wpa_printf(MSG_DEBUG, "WMM: TS Info: UP=%d PSB=%d Direction=%d TID=%d",
|
||||
up, psb, dir, tid);
|
||||
val = le_to_host16(tspec->nominal_msdu_size);
|
||||
wpa_printf(MSG_DEBUG, "WMM: Nominal MSDU Size: %d%s",
|
||||
val & 0x7fff, val & 0x8000 ? " (fixed)" : "");
|
||||
wpa_printf(MSG_DEBUG, "WMM: Mean Data Rate: %u bps",
|
||||
le_to_host32(tspec->mean_data_rate));
|
||||
wpa_printf(MSG_DEBUG, "WMM: Minimum PHY Rate: %u bps",
|
||||
le_to_host32(tspec->minimum_phy_rate));
|
||||
val = le_to_host16(tspec->surplus_bandwidth_allowance);
|
||||
wpa_printf(MSG_DEBUG, "WMM: Surplus Bandwidth Allowance: %u.%04u",
|
||||
val >> 13, 10000 * (val & 0x1fff) / 0x2000);
|
||||
|
||||
val = le_to_host16(tspec->nominal_msdu_size);
|
||||
if (val == 0) {
|
||||
wpa_printf(MSG_DEBUG, "WMM: Invalid Nominal MSDU Size (0)");
|
||||
return WMM_ADDTS_STATUS_INVALID_PARAMETERS;
|
||||
}
|
||||
/* pps = Ceiling((Mean Data Rate / 8) / Nominal MSDU Size) */
|
||||
pps = ((le_to_host32(tspec->mean_data_rate) / 8) + val - 1) / val;
|
||||
wpa_printf(MSG_DEBUG, "WMM: Packets-per-second estimate for TSPEC: %d",
|
||||
pps);
|
||||
|
||||
if (le_to_host32(tspec->minimum_phy_rate) < 1000000) {
|
||||
wpa_printf(MSG_DEBUG, "WMM: Too small Minimum PHY Rate");
|
||||
return WMM_ADDTS_STATUS_INVALID_PARAMETERS;
|
||||
}
|
||||
|
||||
duration = (le_to_host16(tspec->nominal_msdu_size) & 0x7fff) * 8 /
|
||||
(le_to_host32(tspec->minimum_phy_rate) / 1000000) +
|
||||
50 /* FIX: proper SIFS + ACK duration */;
|
||||
|
||||
/* unsigned binary number with an implicit binary point after the
|
||||
* leftmost 3 bits, i.e., 0x2000 = 1.0 */
|
||||
surplus = le_to_host16(tspec->surplus_bandwidth_allowance);
|
||||
if (surplus <= 0x2000) {
|
||||
wpa_printf(MSG_DEBUG, "WMM: Surplus Bandwidth Allowance not "
|
||||
"greater than unity");
|
||||
return WMM_ADDTS_STATUS_INVALID_PARAMETERS;
|
||||
}
|
||||
|
||||
medium_time = surplus * pps * duration / 0x2000;
|
||||
wpa_printf(MSG_DEBUG, "WMM: Estimated medium time: %u", medium_time);
|
||||
|
||||
/*
|
||||
* TODO: store list of granted (and still active) TSPECs and check
|
||||
* whether there is available medium time for this request. For now,
|
||||
* just refuse requests that would by themselves take very large
|
||||
* portion of the available bandwidth.
|
||||
*/
|
||||
if (medium_time > 750000) {
|
||||
wpa_printf(MSG_DEBUG, "WMM: Refuse TSPEC request for over "
|
||||
"75%% of available bandwidth");
|
||||
return WMM_ADDTS_STATUS_REFUSED;
|
||||
}
|
||||
|
||||
/* Convert to 32 microseconds per second unit */
|
||||
tspec->medium_time = host_to_le16(medium_time / 32);
|
||||
|
||||
return WMM_ADDTS_STATUS_ADMISSION_ACCEPTED;
|
||||
}
|
||||
|
||||
|
||||
static void wmm_addts_req(struct hostapd_data *hapd,
|
||||
const struct ieee80211_mgmt *mgmt,
|
||||
struct wmm_tspec_element *tspec, size_t len)
|
||||
{
|
||||
const u8 *end = ((const u8 *) mgmt) + len;
|
||||
int res;
|
||||
|
||||
if ((const u8 *) (tspec + 1) > end) {
|
||||
wpa_printf(MSG_DEBUG, "WMM: TSPEC overflow in ADDTS Request");
|
||||
return;
|
||||
}
|
||||
|
||||
wpa_printf(MSG_DEBUG, "WMM: ADDTS Request (Dialog Token %d) for TSPEC "
|
||||
"from " MACSTR,
|
||||
mgmt->u.action.u.wmm_action.dialog_token,
|
||||
MAC2STR(mgmt->sa));
|
||||
|
||||
res = wmm_process_tspec(tspec);
|
||||
wpa_printf(MSG_DEBUG, "WMM: ADDTS processing result: %d", res);
|
||||
|
||||
wmm_send_action(hapd, mgmt->sa, tspec, WMM_ACTION_CODE_ADDTS_RESP,
|
||||
mgmt->u.action.u.wmm_action.dialog_token, res);
|
||||
}
|
||||
|
||||
|
||||
void hostapd_wmm_action(struct hostapd_data *hapd,
|
||||
const struct ieee80211_mgmt *mgmt, size_t len)
|
||||
{
|
||||
int action_code;
|
||||
int left = len - IEEE80211_HDRLEN - 4;
|
||||
const u8 *pos = ((const u8 *) mgmt) + IEEE80211_HDRLEN + 4;
|
||||
struct ieee802_11_elems elems;
|
||||
struct sta_info *sta = ap_get_sta(hapd, mgmt->sa);
|
||||
|
||||
/* check that the request comes from a valid station */
|
||||
if (!sta ||
|
||||
(sta->flags & (WLAN_STA_ASSOC | WLAN_STA_WMM)) !=
|
||||
(WLAN_STA_ASSOC | WLAN_STA_WMM)) {
|
||||
hostapd_logger(hapd, mgmt->sa, HOSTAPD_MODULE_IEEE80211,
|
||||
HOSTAPD_LEVEL_DEBUG,
|
||||
"wmm action received is not from associated wmm"
|
||||
" station");
|
||||
/* TODO: respond with action frame refused status code */
|
||||
return;
|
||||
}
|
||||
|
||||
/* extract the tspec info element */
|
||||
if (ieee802_11_parse_elems(pos, left, &elems, 1) == ParseFailed) {
|
||||
hostapd_logger(hapd, mgmt->sa, HOSTAPD_MODULE_IEEE80211,
|
||||
HOSTAPD_LEVEL_DEBUG,
|
||||
"hostapd_wmm_action - could not parse wmm "
|
||||
"action");
|
||||
/* TODO: respond with action frame invalid parameters status
|
||||
* code */
|
||||
return;
|
||||
}
|
||||
|
||||
if (!elems.wmm_tspec ||
|
||||
elems.wmm_tspec_len != (sizeof(struct wmm_tspec_element) - 2)) {
|
||||
hostapd_logger(hapd, mgmt->sa, HOSTAPD_MODULE_IEEE80211,
|
||||
HOSTAPD_LEVEL_DEBUG,
|
||||
"hostapd_wmm_action - missing or wrong length "
|
||||
"tspec");
|
||||
/* TODO: respond with action frame invalid parameters status
|
||||
* code */
|
||||
return;
|
||||
}
|
||||
|
||||
/* TODO: check the request is for an AC with ACM set, if not, refuse
|
||||
* request */
|
||||
|
||||
action_code = mgmt->u.action.u.wmm_action.action_code;
|
||||
switch (action_code) {
|
||||
case WMM_ACTION_CODE_ADDTS_REQ:
|
||||
wmm_addts_req(hapd, mgmt, (struct wmm_tspec_element *)
|
||||
(elems.wmm_tspec - 2), len);
|
||||
return;
|
||||
#if 0
|
||||
/* TODO: needed for client implementation */
|
||||
case WMM_ACTION_CODE_ADDTS_RESP:
|
||||
wmm_setup_request(hapd, mgmt, len);
|
||||
return;
|
||||
/* TODO: handle station teardown requests */
|
||||
case WMM_ACTION_CODE_DELTS:
|
||||
wmm_teardown(hapd, mgmt, len);
|
||||
return;
|
||||
#endif
|
||||
}
|
||||
|
||||
hostapd_logger(hapd, mgmt->sa, HOSTAPD_MODULE_IEEE80211,
|
||||
HOSTAPD_LEVEL_DEBUG,
|
||||
"hostapd_wmm_action - unknown action code %d",
|
||||
action_code);
|
||||
}
|
29
hostapd-0.8/src/ap/wmm.h
Normal file
29
hostapd-0.8/src/ap/wmm.h
Normal file
|
@ -0,0 +1,29 @@
|
|||
/*
|
||||
* hostapd / WMM (Wi-Fi Multimedia)
|
||||
* Copyright 2002-2003, 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.
|
||||
*/
|
||||
|
||||
#ifndef WME_H
|
||||
#define WME_H
|
||||
|
||||
struct ieee80211_mgmt;
|
||||
struct wmm_tspec_element;
|
||||
|
||||
u8 * hostapd_eid_wmm(struct hostapd_data *hapd, u8 *eid);
|
||||
int hostapd_eid_wmm_valid(struct hostapd_data *hapd, const u8 *eid,
|
||||
size_t len);
|
||||
void hostapd_wmm_action(struct hostapd_data *hapd,
|
||||
const struct ieee80211_mgmt *mgmt, size_t len);
|
||||
int wmm_process_tspec(struct wmm_tspec_element *tspec);
|
||||
|
||||
#endif /* WME_H */
|
2838
hostapd-0.8/src/ap/wpa_auth.c
Normal file
2838
hostapd-0.8/src/ap/wpa_auth.c
Normal file
File diff suppressed because it is too large
Load diff
285
hostapd-0.8/src/ap/wpa_auth.h
Normal file
285
hostapd-0.8/src/ap/wpa_auth.h
Normal file
|
@ -0,0 +1,285 @@
|
|||
/*
|
||||
* 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.
|
||||
*/
|
||||
|
||||
#ifndef WPA_AUTH_H
|
||||
#define WPA_AUTH_H
|
||||
|
||||
#include "common/defs.h"
|
||||
#include "common/eapol_common.h"
|
||||
#include "common/wpa_common.h"
|
||||
|
||||
#ifdef _MSC_VER
|
||||
#pragma pack(push, 1)
|
||||
#endif /* _MSC_VER */
|
||||
|
||||
/* IEEE Std 802.11r-2008, 11A.10.3 - Remote request/response frame definition
|
||||
*/
|
||||
struct ft_rrb_frame {
|
||||
u8 frame_type; /* RSN_REMOTE_FRAME_TYPE_FT_RRB */
|
||||
u8 packet_type; /* FT_PACKET_REQUEST/FT_PACKET_RESPONSE */
|
||||
le16 action_length; /* little endian length of action_frame */
|
||||
u8 ap_address[ETH_ALEN];
|
||||
/*
|
||||
* Followed by action_length bytes of FT Action frame (from Category
|
||||
* field to the end of Action Frame body.
|
||||
*/
|
||||
} STRUCT_PACKED;
|
||||
|
||||
#define RSN_REMOTE_FRAME_TYPE_FT_RRB 1
|
||||
|
||||
#define FT_PACKET_REQUEST 0
|
||||
#define FT_PACKET_RESPONSE 1
|
||||
/* Vendor-specific types for R0KH-R1KH protocol; not defined in 802.11r */
|
||||
#define FT_PACKET_R0KH_R1KH_PULL 200
|
||||
#define FT_PACKET_R0KH_R1KH_RESP 201
|
||||
#define FT_PACKET_R0KH_R1KH_PUSH 202
|
||||
|
||||
#define FT_R0KH_R1KH_PULL_DATA_LEN 44
|
||||
#define FT_R0KH_R1KH_RESP_DATA_LEN 76
|
||||
#define FT_R0KH_R1KH_PUSH_DATA_LEN 88
|
||||
|
||||
struct ft_r0kh_r1kh_pull_frame {
|
||||
u8 frame_type; /* RSN_REMOTE_FRAME_TYPE_FT_RRB */
|
||||
u8 packet_type; /* FT_PACKET_R0KH_R1KH_PULL */
|
||||
le16 data_length; /* little endian length of data (44) */
|
||||
u8 ap_address[ETH_ALEN];
|
||||
|
||||
u8 nonce[16];
|
||||
u8 pmk_r0_name[WPA_PMK_NAME_LEN];
|
||||
u8 r1kh_id[FT_R1KH_ID_LEN];
|
||||
u8 s1kh_id[ETH_ALEN];
|
||||
u8 pad[4]; /* 8-octet boundary for AES key wrap */
|
||||
u8 key_wrap_extra[8];
|
||||
} STRUCT_PACKED;
|
||||
|
||||
struct ft_r0kh_r1kh_resp_frame {
|
||||
u8 frame_type; /* RSN_REMOTE_FRAME_TYPE_FT_RRB */
|
||||
u8 packet_type; /* FT_PACKET_R0KH_R1KH_RESP */
|
||||
le16 data_length; /* little endian length of data (76) */
|
||||
u8 ap_address[ETH_ALEN];
|
||||
|
||||
u8 nonce[16]; /* copied from pull */
|
||||
u8 r1kh_id[FT_R1KH_ID_LEN]; /* copied from pull */
|
||||
u8 s1kh_id[ETH_ALEN]; /* copied from pull */
|
||||
u8 pmk_r1[PMK_LEN];
|
||||
u8 pmk_r1_name[WPA_PMK_NAME_LEN];
|
||||
le16 pairwise;
|
||||
u8 pad[2]; /* 8-octet boundary for AES key wrap */
|
||||
u8 key_wrap_extra[8];
|
||||
} STRUCT_PACKED;
|
||||
|
||||
struct ft_r0kh_r1kh_push_frame {
|
||||
u8 frame_type; /* RSN_REMOTE_FRAME_TYPE_FT_RRB */
|
||||
u8 packet_type; /* FT_PACKET_R0KH_R1KH_PUSH */
|
||||
le16 data_length; /* little endian length of data (88) */
|
||||
u8 ap_address[ETH_ALEN];
|
||||
|
||||
/* Encrypted with AES key-wrap */
|
||||
u8 timestamp[4]; /* current time in seconds since unix epoch, little
|
||||
* endian */
|
||||
u8 r1kh_id[FT_R1KH_ID_LEN];
|
||||
u8 s1kh_id[ETH_ALEN];
|
||||
u8 pmk_r0_name[WPA_PMK_NAME_LEN];
|
||||
u8 pmk_r1[PMK_LEN];
|
||||
u8 pmk_r1_name[WPA_PMK_NAME_LEN];
|
||||
le16 pairwise;
|
||||
u8 pad[6]; /* 8-octet boundary for AES key wrap */
|
||||
u8 key_wrap_extra[8];
|
||||
} STRUCT_PACKED;
|
||||
|
||||
#ifdef _MSC_VER
|
||||
#pragma pack(pop)
|
||||
#endif /* _MSC_VER */
|
||||
|
||||
|
||||
/* per STA state machine data */
|
||||
|
||||
struct wpa_authenticator;
|
||||
struct wpa_state_machine;
|
||||
struct rsn_pmksa_cache_entry;
|
||||
struct eapol_state_machine;
|
||||
|
||||
|
||||
struct ft_remote_r0kh {
|
||||
struct ft_remote_r0kh *next;
|
||||
u8 addr[ETH_ALEN];
|
||||
u8 id[FT_R0KH_ID_MAX_LEN];
|
||||
size_t id_len;
|
||||
u8 key[16];
|
||||
};
|
||||
|
||||
|
||||
struct ft_remote_r1kh {
|
||||
struct ft_remote_r1kh *next;
|
||||
u8 addr[ETH_ALEN];
|
||||
u8 id[FT_R1KH_ID_LEN];
|
||||
u8 key[16];
|
||||
};
|
||||
|
||||
|
||||
struct wpa_auth_config {
|
||||
int wpa;
|
||||
int wpa_key_mgmt;
|
||||
int wpa_pairwise;
|
||||
int wpa_group;
|
||||
int wpa_group_rekey;
|
||||
int wpa_strict_rekey;
|
||||
int wpa_gmk_rekey;
|
||||
int wpa_ptk_rekey;
|
||||
int rsn_pairwise;
|
||||
int rsn_preauth;
|
||||
int eapol_version;
|
||||
int peerkey;
|
||||
int wmm_enabled;
|
||||
int wmm_uapsd;
|
||||
int okc;
|
||||
int tx_status;
|
||||
#ifdef CONFIG_IEEE80211W
|
||||
enum mfp_options ieee80211w;
|
||||
#endif /* CONFIG_IEEE80211W */
|
||||
#ifdef CONFIG_IEEE80211R
|
||||
#define SSID_LEN 32
|
||||
u8 ssid[SSID_LEN];
|
||||
size_t ssid_len;
|
||||
u8 mobility_domain[MOBILITY_DOMAIN_ID_LEN];
|
||||
u8 r0_key_holder[FT_R0KH_ID_MAX_LEN];
|
||||
size_t r0_key_holder_len;
|
||||
u8 r1_key_holder[FT_R1KH_ID_LEN];
|
||||
u32 r0_key_lifetime;
|
||||
u32 reassociation_deadline;
|
||||
struct ft_remote_r0kh *r0kh_list;
|
||||
struct ft_remote_r1kh *r1kh_list;
|
||||
int pmk_r1_push;
|
||||
int ft_over_ds;
|
||||
#endif /* CONFIG_IEEE80211R */
|
||||
};
|
||||
|
||||
typedef enum {
|
||||
LOGGER_DEBUG, LOGGER_INFO, LOGGER_WARNING
|
||||
} logger_level;
|
||||
|
||||
typedef enum {
|
||||
WPA_EAPOL_portEnabled, WPA_EAPOL_portValid, WPA_EAPOL_authorized,
|
||||
WPA_EAPOL_portControl_Auto, WPA_EAPOL_keyRun, WPA_EAPOL_keyAvailable,
|
||||
WPA_EAPOL_keyDone, WPA_EAPOL_inc_EapolFramesTx
|
||||
} wpa_eapol_variable;
|
||||
|
||||
struct wpa_auth_callbacks {
|
||||
void *ctx;
|
||||
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);
|
||||
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);
|
||||
const u8 * (*get_psk)(void *ctx, const u8 *addr, const u8 *prev_psk);
|
||||
int (*get_msk)(void *ctx, const u8 *addr, u8 *msk, size_t *len);
|
||||
int (*set_key)(void *ctx, int vlan_id, enum wpa_alg alg,
|
||||
const u8 *addr, int idx, u8 *key, size_t key_len);
|
||||
int (*get_seqnum)(void *ctx, const u8 *addr, int idx, u8 *seq);
|
||||
int (*send_eapol)(void *ctx, const u8 *addr, const u8 *data,
|
||||
size_t data_len, int encrypt);
|
||||
int (*for_each_sta)(void *ctx, int (*cb)(struct wpa_state_machine *sm,
|
||||
void *ctx), void *cb_ctx);
|
||||
int (*for_each_auth)(void *ctx, int (*cb)(struct wpa_authenticator *a,
|
||||
void *ctx), void *cb_ctx);
|
||||
int (*send_ether)(void *ctx, const u8 *dst, u16 proto, const u8 *data,
|
||||
size_t data_len);
|
||||
#ifdef CONFIG_IEEE80211R
|
||||
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);
|
||||
#endif /* CONFIG_IEEE80211R */
|
||||
};
|
||||
|
||||
struct wpa_authenticator * wpa_init(const u8 *addr,
|
||||
struct wpa_auth_config *conf,
|
||||
struct wpa_auth_callbacks *cb);
|
||||
void wpa_deinit(struct wpa_authenticator *wpa_auth);
|
||||
int wpa_reconfig(struct wpa_authenticator *wpa_auth,
|
||||
struct wpa_auth_config *conf);
|
||||
|
||||
enum {
|
||||
WPA_IE_OK, WPA_INVALID_IE, WPA_INVALID_GROUP, WPA_INVALID_PAIRWISE,
|
||||
WPA_INVALID_AKMP, WPA_NOT_ENABLED, WPA_ALLOC_FAIL,
|
||||
WPA_MGMT_FRAME_PROTECTION_VIOLATION, WPA_INVALID_MGMT_GROUP_CIPHER,
|
||||
WPA_INVALID_MDIE, WPA_INVALID_PROTO
|
||||
};
|
||||
|
||||
int wpa_validate_wpa_ie(struct wpa_authenticator *wpa_auth,
|
||||
struct wpa_state_machine *sm,
|
||||
const u8 *wpa_ie, size_t wpa_ie_len,
|
||||
const u8 *mdie, size_t mdie_len);
|
||||
int wpa_auth_uses_mfp(struct wpa_state_machine *sm);
|
||||
struct wpa_state_machine *
|
||||
wpa_auth_sta_init(struct wpa_authenticator *wpa_auth, const u8 *addr);
|
||||
int wpa_auth_sta_associated(struct wpa_authenticator *wpa_auth,
|
||||
struct wpa_state_machine *sm);
|
||||
void wpa_auth_sta_no_wpa(struct wpa_state_machine *sm);
|
||||
void wpa_auth_sta_deinit(struct wpa_state_machine *sm);
|
||||
void wpa_receive(struct wpa_authenticator *wpa_auth,
|
||||
struct wpa_state_machine *sm,
|
||||
u8 *data, size_t data_len);
|
||||
typedef enum {
|
||||
WPA_AUTH, WPA_ASSOC, WPA_DISASSOC, WPA_DEAUTH, WPA_REAUTH,
|
||||
WPA_REAUTH_EAPOL, WPA_ASSOC_FT
|
||||
} wpa_event;
|
||||
void wpa_remove_ptk(struct wpa_state_machine *sm);
|
||||
int wpa_auth_sm_event(struct wpa_state_machine *sm, wpa_event event);
|
||||
void wpa_auth_sm_notify(struct wpa_state_machine *sm);
|
||||
void wpa_gtk_rekey(struct wpa_authenticator *wpa_auth);
|
||||
int wpa_get_mib(struct wpa_authenticator *wpa_auth, char *buf, size_t buflen);
|
||||
int wpa_get_mib_sta(struct wpa_state_machine *sm, char *buf, size_t buflen);
|
||||
void wpa_auth_countermeasures_start(struct wpa_authenticator *wpa_auth);
|
||||
int wpa_auth_pairwise_set(struct wpa_state_machine *sm);
|
||||
int wpa_auth_get_pairwise(struct wpa_state_machine *sm);
|
||||
int wpa_auth_sta_key_mgmt(struct wpa_state_machine *sm);
|
||||
int wpa_auth_sta_wpa_version(struct wpa_state_machine *sm);
|
||||
int wpa_auth_sta_clear_pmksa(struct wpa_state_machine *sm,
|
||||
struct rsn_pmksa_cache_entry *entry);
|
||||
struct rsn_pmksa_cache_entry *
|
||||
wpa_auth_sta_get_pmksa(struct wpa_state_machine *sm);
|
||||
void wpa_auth_sta_local_mic_failure_report(struct wpa_state_machine *sm);
|
||||
const u8 * wpa_auth_get_wpa_ie(struct wpa_authenticator *wpa_auth,
|
||||
size_t *len);
|
||||
int wpa_auth_pmksa_add(struct wpa_state_machine *sm, const u8 *pmk,
|
||||
int session_timeout, struct eapol_state_machine *eapol);
|
||||
int wpa_auth_pmksa_add_preauth(struct wpa_authenticator *wpa_auth,
|
||||
const u8 *pmk, size_t len, const u8 *sta_addr,
|
||||
int session_timeout,
|
||||
struct eapol_state_machine *eapol);
|
||||
int wpa_auth_sta_set_vlan(struct wpa_state_machine *sm, int vlan_id);
|
||||
void wpa_auth_eapol_key_tx_status(struct wpa_authenticator *wpa_auth,
|
||||
struct wpa_state_machine *sm, int ack);
|
||||
|
||||
#ifdef CONFIG_IEEE80211R
|
||||
u8 * wpa_sm_write_assoc_resp_ies(struct wpa_state_machine *sm, u8 *pos,
|
||||
size_t max_len, int auth_alg,
|
||||
const u8 *req_ies, size_t req_ies_len);
|
||||
void wpa_ft_process_auth(struct wpa_state_machine *sm, const u8 *bssid,
|
||||
u16 auth_transaction, const u8 *ies, size_t ies_len,
|
||||
void (*cb)(void *ctx, const u8 *dst, const u8 *bssid,
|
||||
u16 auth_transaction, u16 resp,
|
||||
const u8 *ies, size_t ies_len),
|
||||
void *ctx);
|
||||
u16 wpa_ft_validate_reassoc(struct wpa_state_machine *sm, const u8 *ies,
|
||||
size_t ies_len);
|
||||
int wpa_ft_action_rx(struct wpa_state_machine *sm, const u8 *data, size_t len);
|
||||
int wpa_ft_rrb_rx(struct wpa_authenticator *wpa_auth, const u8 *src_addr,
|
||||
const u8 *data, size_t data_len);
|
||||
void wpa_ft_push_pmk_r1(struct wpa_authenticator *wpa_auth, const u8 *addr);
|
||||
#endif /* CONFIG_IEEE80211R */
|
||||
|
||||
#endif /* WPA_AUTH_H */
|
1779
hostapd-0.8/src/ap/wpa_auth_ft.c
Normal file
1779
hostapd-0.8/src/ap/wpa_auth_ft.c
Normal file
File diff suppressed because it is too large
Load diff
571
hostapd-0.8/src/ap/wpa_auth_glue.c
Normal file
571
hostapd-0.8/src/ap/wpa_auth_glue.c
Normal file
|
@ -0,0 +1,571 @@
|
|||
/*
|
||||
* 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.
|
||||
*/
|
||||
|
||||
#include "utils/includes.h"
|
||||
|
||||
#include "utils/common.h"
|
||||
#include "common/ieee802_11_defs.h"
|
||||
#include "eapol_auth/eapol_auth_sm.h"
|
||||
#include "eapol_auth/eapol_auth_sm_i.h"
|
||||
#include "eap_server/eap.h"
|
||||
#include "l2_packet/l2_packet.h"
|
||||
#include "drivers/driver.h"
|
||||
#include "hostapd.h"
|
||||
#include "ieee802_1x.h"
|
||||
#include "preauth_auth.h"
|
||||
#include "sta_info.h"
|
||||
#include "tkip_countermeasures.h"
|
||||
#include "ap_drv_ops.h"
|
||||
#include "ap_config.h"
|
||||
#include "wpa_auth.h"
|
||||
|
||||
|
||||
static void hostapd_wpa_auth_conf(struct hostapd_bss_config *conf,
|
||||
struct wpa_auth_config *wconf)
|
||||
{
|
||||
wconf->wpa = conf->wpa;
|
||||
wconf->wpa_key_mgmt = conf->wpa_key_mgmt;
|
||||
wconf->wpa_pairwise = conf->wpa_pairwise;
|
||||
wconf->wpa_group = conf->wpa_group;
|
||||
wconf->wpa_group_rekey = conf->wpa_group_rekey;
|
||||
wconf->wpa_strict_rekey = conf->wpa_strict_rekey;
|
||||
wconf->wpa_gmk_rekey = conf->wpa_gmk_rekey;
|
||||
wconf->wpa_ptk_rekey = conf->wpa_ptk_rekey;
|
||||
wconf->rsn_pairwise = conf->rsn_pairwise;
|
||||
wconf->rsn_preauth = conf->rsn_preauth;
|
||||
wconf->eapol_version = conf->eapol_version;
|
||||
wconf->peerkey = conf->peerkey;
|
||||
wconf->wmm_enabled = conf->wmm_enabled;
|
||||
wconf->wmm_uapsd = conf->wmm_uapsd;
|
||||
wconf->okc = conf->okc;
|
||||
#ifdef CONFIG_IEEE80211W
|
||||
wconf->ieee80211w = conf->ieee80211w;
|
||||
#endif /* CONFIG_IEEE80211W */
|
||||
#ifdef CONFIG_IEEE80211R
|
||||
wconf->ssid_len = conf->ssid.ssid_len;
|
||||
if (wconf->ssid_len > SSID_LEN)
|
||||
wconf->ssid_len = SSID_LEN;
|
||||
os_memcpy(wconf->ssid, conf->ssid.ssid, wconf->ssid_len);
|
||||
os_memcpy(wconf->mobility_domain, conf->mobility_domain,
|
||||
MOBILITY_DOMAIN_ID_LEN);
|
||||
if (conf->nas_identifier &&
|
||||
os_strlen(conf->nas_identifier) <= FT_R0KH_ID_MAX_LEN) {
|
||||
wconf->r0_key_holder_len = os_strlen(conf->nas_identifier);
|
||||
os_memcpy(wconf->r0_key_holder, conf->nas_identifier,
|
||||
wconf->r0_key_holder_len);
|
||||
}
|
||||
os_memcpy(wconf->r1_key_holder, conf->r1_key_holder, FT_R1KH_ID_LEN);
|
||||
wconf->r0_key_lifetime = conf->r0_key_lifetime;
|
||||
wconf->reassociation_deadline = conf->reassociation_deadline;
|
||||
wconf->r0kh_list = conf->r0kh_list;
|
||||
wconf->r1kh_list = conf->r1kh_list;
|
||||
wconf->pmk_r1_push = conf->pmk_r1_push;
|
||||
wconf->ft_over_ds = conf->ft_over_ds;
|
||||
#endif /* CONFIG_IEEE80211R */
|
||||
}
|
||||
|
||||
|
||||
static void hostapd_wpa_auth_logger(void *ctx, const u8 *addr,
|
||||
logger_level level, const char *txt)
|
||||
{
|
||||
#ifndef CONFIG_NO_HOSTAPD_LOGGER
|
||||
struct hostapd_data *hapd = ctx;
|
||||
int hlevel;
|
||||
|
||||
switch (level) {
|
||||
case LOGGER_WARNING:
|
||||
hlevel = HOSTAPD_LEVEL_WARNING;
|
||||
break;
|
||||
case LOGGER_INFO:
|
||||
hlevel = HOSTAPD_LEVEL_INFO;
|
||||
break;
|
||||
case LOGGER_DEBUG:
|
||||
default:
|
||||
hlevel = HOSTAPD_LEVEL_DEBUG;
|
||||
break;
|
||||
}
|
||||
|
||||
hostapd_logger(hapd, addr, HOSTAPD_MODULE_WPA, hlevel, "%s", txt);
|
||||
#endif /* CONFIG_NO_HOSTAPD_LOGGER */
|
||||
}
|
||||
|
||||
|
||||
static void hostapd_wpa_auth_disconnect(void *ctx, const u8 *addr,
|
||||
u16 reason)
|
||||
{
|
||||
struct hostapd_data *hapd = ctx;
|
||||
wpa_printf(MSG_DEBUG, "%s: WPA authenticator requests disconnect: "
|
||||
"STA " MACSTR " reason %d",
|
||||
__func__, MAC2STR(addr), reason);
|
||||
ap_sta_disconnect(hapd, NULL, addr, reason);
|
||||
}
|
||||
|
||||
|
||||
static void hostapd_wpa_auth_mic_failure_report(void *ctx, const u8 *addr)
|
||||
{
|
||||
struct hostapd_data *hapd = ctx;
|
||||
michael_mic_failure(hapd, addr, 0);
|
||||
}
|
||||
|
||||
|
||||
static void hostapd_wpa_auth_set_eapol(void *ctx, const u8 *addr,
|
||||
wpa_eapol_variable var, int value)
|
||||
{
|
||||
struct hostapd_data *hapd = ctx;
|
||||
struct sta_info *sta = ap_get_sta(hapd, addr);
|
||||
if (sta == NULL)
|
||||
return;
|
||||
switch (var) {
|
||||
case WPA_EAPOL_portEnabled:
|
||||
ieee802_1x_notify_port_enabled(sta->eapol_sm, value);
|
||||
break;
|
||||
case WPA_EAPOL_portValid:
|
||||
ieee802_1x_notify_port_valid(sta->eapol_sm, value);
|
||||
break;
|
||||
case WPA_EAPOL_authorized:
|
||||
ieee802_1x_set_sta_authorized(hapd, sta, value);
|
||||
break;
|
||||
case WPA_EAPOL_portControl_Auto:
|
||||
if (sta->eapol_sm)
|
||||
sta->eapol_sm->portControl = Auto;
|
||||
break;
|
||||
case WPA_EAPOL_keyRun:
|
||||
if (sta->eapol_sm)
|
||||
sta->eapol_sm->keyRun = value ? TRUE : FALSE;
|
||||
break;
|
||||
case WPA_EAPOL_keyAvailable:
|
||||
if (sta->eapol_sm)
|
||||
sta->eapol_sm->eap_if->eapKeyAvailable =
|
||||
value ? TRUE : FALSE;
|
||||
break;
|
||||
case WPA_EAPOL_keyDone:
|
||||
if (sta->eapol_sm)
|
||||
sta->eapol_sm->keyDone = value ? TRUE : FALSE;
|
||||
break;
|
||||
case WPA_EAPOL_inc_EapolFramesTx:
|
||||
if (sta->eapol_sm)
|
||||
sta->eapol_sm->dot1xAuthEapolFramesTx++;
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
static int hostapd_wpa_auth_get_eapol(void *ctx, const u8 *addr,
|
||||
wpa_eapol_variable var)
|
||||
{
|
||||
struct hostapd_data *hapd = ctx;
|
||||
struct sta_info *sta = ap_get_sta(hapd, addr);
|
||||
if (sta == NULL || sta->eapol_sm == NULL)
|
||||
return -1;
|
||||
switch (var) {
|
||||
case WPA_EAPOL_keyRun:
|
||||
return sta->eapol_sm->keyRun;
|
||||
case WPA_EAPOL_keyAvailable:
|
||||
return sta->eapol_sm->eap_if->eapKeyAvailable;
|
||||
default:
|
||||
return -1;
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
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);
|
||||
}
|
||||
|
||||
|
||||
static int hostapd_wpa_auth_get_msk(void *ctx, const u8 *addr, u8 *msk,
|
||||
size_t *len)
|
||||
{
|
||||
struct hostapd_data *hapd = ctx;
|
||||
const u8 *key;
|
||||
size_t keylen;
|
||||
struct sta_info *sta;
|
||||
|
||||
sta = ap_get_sta(hapd, addr);
|
||||
if (sta == NULL)
|
||||
return -1;
|
||||
|
||||
key = ieee802_1x_get_key(sta->eapol_sm, &keylen);
|
||||
if (key == NULL)
|
||||
return -1;
|
||||
|
||||
if (keylen > *len)
|
||||
keylen = *len;
|
||||
os_memcpy(msk, key, keylen);
|
||||
*len = keylen;
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
|
||||
static int hostapd_wpa_auth_set_key(void *ctx, int vlan_id, enum wpa_alg alg,
|
||||
const u8 *addr, int idx, u8 *key,
|
||||
size_t key_len)
|
||||
{
|
||||
struct hostapd_data *hapd = ctx;
|
||||
const char *ifname = hapd->conf->iface;
|
||||
|
||||
if (vlan_id > 0) {
|
||||
ifname = hostapd_get_vlan_id_ifname(hapd->conf->vlan, vlan_id);
|
||||
if (ifname == NULL)
|
||||
return -1;
|
||||
}
|
||||
|
||||
return hostapd_drv_set_key(ifname, hapd, alg, addr, idx, 1, NULL, 0,
|
||||
key, key_len);
|
||||
}
|
||||
|
||||
|
||||
static int hostapd_wpa_auth_get_seqnum(void *ctx, const u8 *addr, int idx,
|
||||
u8 *seq)
|
||||
{
|
||||
struct hostapd_data *hapd = ctx;
|
||||
return hostapd_get_seqnum(hapd->conf->iface, hapd, addr, idx, seq);
|
||||
}
|
||||
|
||||
|
||||
static int hostapd_wpa_auth_send_eapol(void *ctx, const u8 *addr,
|
||||
const u8 *data, size_t data_len,
|
||||
int encrypt)
|
||||
{
|
||||
struct hostapd_data *hapd = ctx;
|
||||
struct sta_info *sta;
|
||||
u32 flags = 0;
|
||||
|
||||
sta = ap_get_sta(hapd, addr);
|
||||
if (sta)
|
||||
flags = hostapd_sta_flags_to_drv(sta->flags);
|
||||
|
||||
return hostapd_drv_hapd_send_eapol(hapd, addr, data, data_len,
|
||||
encrypt, flags);
|
||||
}
|
||||
|
||||
|
||||
static int hostapd_wpa_auth_for_each_sta(
|
||||
void *ctx, int (*cb)(struct wpa_state_machine *sm, void *ctx),
|
||||
void *cb_ctx)
|
||||
{
|
||||
struct hostapd_data *hapd = ctx;
|
||||
struct sta_info *sta;
|
||||
|
||||
for (sta = hapd->sta_list; sta; sta = sta->next) {
|
||||
if (sta->wpa_sm && cb(sta->wpa_sm, cb_ctx))
|
||||
return 1;
|
||||
}
|
||||
return 0;
|
||||
}
|
||||
|
||||
|
||||
struct wpa_auth_iface_iter_data {
|
||||
int (*cb)(struct wpa_authenticator *sm, void *ctx);
|
||||
void *cb_ctx;
|
||||
};
|
||||
|
||||
static int wpa_auth_iface_iter(struct hostapd_iface *iface, void *ctx)
|
||||
{
|
||||
struct wpa_auth_iface_iter_data *data = ctx;
|
||||
size_t i;
|
||||
for (i = 0; i < iface->num_bss; i++) {
|
||||
if (iface->bss[i]->wpa_auth &&
|
||||
data->cb(iface->bss[i]->wpa_auth, data->cb_ctx))
|
||||
return 1;
|
||||
}
|
||||
return 0;
|
||||
}
|
||||
|
||||
|
||||
static int hostapd_wpa_auth_for_each_auth(
|
||||
void *ctx, int (*cb)(struct wpa_authenticator *sm, void *ctx),
|
||||
void *cb_ctx)
|
||||
{
|
||||
struct hostapd_data *hapd = ctx;
|
||||
struct wpa_auth_iface_iter_data data;
|
||||
if (hapd->iface->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);
|
||||
}
|
||||
|
||||
|
||||
#ifdef CONFIG_IEEE80211R
|
||||
|
||||
struct wpa_auth_ft_iface_iter_data {
|
||||
struct hostapd_data *src_hapd;
|
||||
const u8 *dst;
|
||||
const u8 *data;
|
||||
size_t data_len;
|
||||
};
|
||||
|
||||
|
||||
static int hostapd_wpa_auth_ft_iter(struct hostapd_iface *iface, void *ctx)
|
||||
{
|
||||
struct wpa_auth_ft_iface_iter_data *idata = ctx;
|
||||
struct hostapd_data *hapd;
|
||||
size_t j;
|
||||
|
||||
for (j = 0; j < iface->num_bss; j++) {
|
||||
hapd = iface->bss[j];
|
||||
if (hapd == idata->src_hapd)
|
||||
continue;
|
||||
if (os_memcmp(hapd->own_addr, idata->dst, ETH_ALEN) == 0) {
|
||||
wpa_printf(MSG_DEBUG, "FT: Send RRB data directly to "
|
||||
"locally managed BSS " MACSTR "@%s -> "
|
||||
MACSTR "@%s",
|
||||
MAC2STR(idata->src_hapd->own_addr),
|
||||
idata->src_hapd->conf->iface,
|
||||
MAC2STR(hapd->own_addr), hapd->conf->iface);
|
||||
wpa_ft_rrb_rx(hapd->wpa_auth,
|
||||
idata->src_hapd->own_addr,
|
||||
idata->data, idata->data_len);
|
||||
return 1;
|
||||
}
|
||||
}
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
#endif /* CONFIG_IEEE80211R */
|
||||
|
||||
|
||||
static int hostapd_wpa_auth_send_ether(void *ctx, const u8 *dst, u16 proto,
|
||||
const u8 *data, size_t data_len)
|
||||
{
|
||||
struct hostapd_data *hapd = ctx;
|
||||
struct l2_ethhdr *buf;
|
||||
int ret;
|
||||
|
||||
#ifdef CONFIG_IEEE80211R
|
||||
if (proto == ETH_P_RRB && hapd->iface->for_each_interface) {
|
||||
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);
|
||||
if (res == 1)
|
||||
return data_len;
|
||||
}
|
||||
#endif /* CONFIG_IEEE80211R */
|
||||
|
||||
if (hapd->driver && hapd->driver->send_ether)
|
||||
return hapd->driver->send_ether(hapd->drv_priv, dst,
|
||||
hapd->own_addr, proto,
|
||||
data, data_len);
|
||||
if (hapd->l2 == NULL)
|
||||
return -1;
|
||||
|
||||
buf = os_malloc(sizeof(*buf) + data_len);
|
||||
if (buf == NULL)
|
||||
return -1;
|
||||
os_memcpy(buf->h_dest, dst, ETH_ALEN);
|
||||
os_memcpy(buf->h_source, hapd->own_addr, ETH_ALEN);
|
||||
buf->h_proto = host_to_be16(proto);
|
||||
os_memcpy(buf + 1, data, data_len);
|
||||
ret = l2_packet_send(hapd->l2, dst, proto, (u8 *) buf,
|
||||
sizeof(*buf) + data_len);
|
||||
os_free(buf);
|
||||
return ret;
|
||||
}
|
||||
|
||||
|
||||
#ifdef CONFIG_IEEE80211R
|
||||
|
||||
static int hostapd_wpa_auth_send_ft_action(void *ctx, const u8 *dst,
|
||||
const u8 *data, size_t data_len)
|
||||
{
|
||||
struct hostapd_data *hapd = ctx;
|
||||
int res;
|
||||
struct ieee80211_mgmt *m;
|
||||
size_t mlen;
|
||||
struct sta_info *sta;
|
||||
|
||||
sta = ap_get_sta(hapd, dst);
|
||||
if (sta == NULL || sta->wpa_sm == NULL)
|
||||
return -1;
|
||||
|
||||
m = os_zalloc(sizeof(*m) + data_len);
|
||||
if (m == NULL)
|
||||
return -1;
|
||||
mlen = ((u8 *) &m->u - (u8 *) m) + data_len;
|
||||
m->frame_control = IEEE80211_FC(WLAN_FC_TYPE_MGMT,
|
||||
WLAN_FC_STYPE_ACTION);
|
||||
os_memcpy(m->da, dst, ETH_ALEN);
|
||||
os_memcpy(m->sa, hapd->own_addr, ETH_ALEN);
|
||||
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);
|
||||
os_free(m);
|
||||
return res;
|
||||
}
|
||||
|
||||
|
||||
static struct wpa_state_machine *
|
||||
hostapd_wpa_auth_add_sta(void *ctx, const u8 *sta_addr)
|
||||
{
|
||||
struct hostapd_data *hapd = ctx;
|
||||
struct sta_info *sta;
|
||||
|
||||
sta = ap_sta_add(hapd, sta_addr);
|
||||
if (sta == NULL)
|
||||
return NULL;
|
||||
if (sta->wpa_sm) {
|
||||
sta->auth_alg = WLAN_AUTH_FT;
|
||||
return sta->wpa_sm;
|
||||
}
|
||||
|
||||
sta->wpa_sm = wpa_auth_sta_init(hapd->wpa_auth, sta->addr);
|
||||
if (sta->wpa_sm == NULL) {
|
||||
ap_free_sta(hapd, sta);
|
||||
return NULL;
|
||||
}
|
||||
sta->auth_alg = WLAN_AUTH_FT;
|
||||
|
||||
return sta->wpa_sm;
|
||||
}
|
||||
|
||||
|
||||
static void hostapd_rrb_receive(void *ctx, const u8 *src_addr, const u8 *buf,
|
||||
size_t len)
|
||||
{
|
||||
struct hostapd_data *hapd = ctx;
|
||||
struct l2_ethhdr *ethhdr;
|
||||
if (len < sizeof(*ethhdr))
|
||||
return;
|
||||
ethhdr = (struct l2_ethhdr *) buf;
|
||||
wpa_printf(MSG_DEBUG, "FT: RRB received packet " MACSTR " -> "
|
||||
MACSTR, MAC2STR(ethhdr->h_source), MAC2STR(ethhdr->h_dest));
|
||||
wpa_ft_rrb_rx(hapd->wpa_auth, ethhdr->h_source, buf + sizeof(*ethhdr),
|
||||
len - sizeof(*ethhdr));
|
||||
}
|
||||
|
||||
#endif /* CONFIG_IEEE80211R */
|
||||
|
||||
|
||||
int hostapd_setup_wpa(struct hostapd_data *hapd)
|
||||
{
|
||||
struct wpa_auth_config _conf;
|
||||
struct wpa_auth_callbacks cb;
|
||||
const u8 *wpa_ie;
|
||||
size_t wpa_ie_len;
|
||||
|
||||
hostapd_wpa_auth_conf(hapd->conf, &_conf);
|
||||
if (hapd->iface->drv_flags & WPA_DRIVER_FLAGS_EAPOL_TX_STATUS)
|
||||
_conf.tx_status = 1;
|
||||
os_memset(&cb, 0, sizeof(cb));
|
||||
cb.ctx = hapd;
|
||||
cb.logger = hostapd_wpa_auth_logger;
|
||||
cb.disconnect = hostapd_wpa_auth_disconnect;
|
||||
cb.mic_failure_report = hostapd_wpa_auth_mic_failure_report;
|
||||
cb.set_eapol = hostapd_wpa_auth_set_eapol;
|
||||
cb.get_eapol = hostapd_wpa_auth_get_eapol;
|
||||
cb.get_psk = hostapd_wpa_auth_get_psk;
|
||||
cb.get_msk = hostapd_wpa_auth_get_msk;
|
||||
cb.set_key = hostapd_wpa_auth_set_key;
|
||||
cb.get_seqnum = hostapd_wpa_auth_get_seqnum;
|
||||
cb.send_eapol = hostapd_wpa_auth_send_eapol;
|
||||
cb.for_each_sta = hostapd_wpa_auth_for_each_sta;
|
||||
cb.for_each_auth = hostapd_wpa_auth_for_each_auth;
|
||||
cb.send_ether = hostapd_wpa_auth_send_ether;
|
||||
#ifdef CONFIG_IEEE80211R
|
||||
cb.send_ft_action = hostapd_wpa_auth_send_ft_action;
|
||||
cb.add_sta = hostapd_wpa_auth_add_sta;
|
||||
#endif /* CONFIG_IEEE80211R */
|
||||
hapd->wpa_auth = wpa_init(hapd->own_addr, &_conf, &cb);
|
||||
if (hapd->wpa_auth == NULL) {
|
||||
wpa_printf(MSG_ERROR, "WPA initialization failed.");
|
||||
return -1;
|
||||
}
|
||||
|
||||
if (hostapd_set_privacy(hapd, 1)) {
|
||||
wpa_printf(MSG_ERROR, "Could not set PrivacyInvoked "
|
||||
"for interface %s", hapd->conf->iface);
|
||||
return -1;
|
||||
}
|
||||
|
||||
wpa_ie = wpa_auth_get_wpa_ie(hapd->wpa_auth, &wpa_ie_len);
|
||||
if (hostapd_set_generic_elem(hapd, wpa_ie, wpa_ie_len)) {
|
||||
wpa_printf(MSG_ERROR, "Failed to configure WPA IE for "
|
||||
"the kernel driver.");
|
||||
return -1;
|
||||
}
|
||||
|
||||
if (rsn_preauth_iface_init(hapd)) {
|
||||
wpa_printf(MSG_ERROR, "Initialization of RSN "
|
||||
"pre-authentication failed.");
|
||||
return -1;
|
||||
}
|
||||
|
||||
#ifdef CONFIG_IEEE80211R
|
||||
if (!hostapd_drv_none(hapd)) {
|
||||
hapd->l2 = l2_packet_init(hapd->conf->bridge[0] ?
|
||||
hapd->conf->bridge :
|
||||
hapd->conf->iface, NULL, ETH_P_RRB,
|
||||
hostapd_rrb_receive, hapd, 1);
|
||||
if (hapd->l2 == NULL &&
|
||||
(hapd->driver == NULL ||
|
||||
hapd->driver->send_ether == NULL)) {
|
||||
wpa_printf(MSG_ERROR, "Failed to open l2_packet "
|
||||
"interface");
|
||||
return -1;
|
||||
}
|
||||
}
|
||||
#endif /* CONFIG_IEEE80211R */
|
||||
|
||||
return 0;
|
||||
|
||||
}
|
||||
|
||||
|
||||
void hostapd_reconfig_wpa(struct hostapd_data *hapd)
|
||||
{
|
||||
struct wpa_auth_config wpa_auth_conf;
|
||||
hostapd_wpa_auth_conf(hapd->conf, &wpa_auth_conf);
|
||||
wpa_reconfig(hapd->wpa_auth, &wpa_auth_conf);
|
||||
}
|
||||
|
||||
|
||||
void hostapd_deinit_wpa(struct hostapd_data *hapd)
|
||||
{
|
||||
rsn_preauth_iface_deinit(hapd);
|
||||
if (hapd->wpa_auth) {
|
||||
wpa_deinit(hapd->wpa_auth);
|
||||
hapd->wpa_auth = NULL;
|
||||
|
||||
if (hostapd_set_privacy(hapd, 0)) {
|
||||
wpa_printf(MSG_DEBUG, "Could not disable "
|
||||
"PrivacyInvoked for interface %s",
|
||||
hapd->conf->iface);
|
||||
}
|
||||
|
||||
if (hostapd_set_generic_elem(hapd, (u8 *) "", 0)) {
|
||||
wpa_printf(MSG_DEBUG, "Could not remove generic "
|
||||
"information element from interface %s",
|
||||
hapd->conf->iface);
|
||||
}
|
||||
}
|
||||
ieee802_1x_deinit(hapd);
|
||||
|
||||
#ifdef CONFIG_IEEE80211R
|
||||
l2_packet_deinit(hapd->l2);
|
||||
#endif /* CONFIG_IEEE80211R */
|
||||
}
|
22
hostapd-0.8/src/ap/wpa_auth_glue.h
Normal file
22
hostapd-0.8/src/ap/wpa_auth_glue.h
Normal file
|
@ -0,0 +1,22 @@
|
|||
/*
|
||||
* 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.
|
||||
*/
|
||||
|
||||
#ifndef WPA_AUTH_GLUE_H
|
||||
#define WPA_AUTH_GLUE_H
|
||||
|
||||
int hostapd_setup_wpa(struct hostapd_data *hapd);
|
||||
void hostapd_reconfig_wpa(struct hostapd_data *hapd);
|
||||
void hostapd_deinit_wpa(struct hostapd_data *hapd);
|
||||
|
||||
#endif /* WPA_AUTH_GLUE_H */
|
234
hostapd-0.8/src/ap/wpa_auth_i.h
Normal file
234
hostapd-0.8/src/ap/wpa_auth_i.h
Normal file
|
@ -0,0 +1,234 @@
|
|||
/*
|
||||
* 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.
|
||||
*/
|
||||
|
||||
#ifndef WPA_AUTH_I_H
|
||||
#define WPA_AUTH_I_H
|
||||
|
||||
/* max(dot11RSNAConfigGroupUpdateCount,dot11RSNAConfigPairwiseUpdateCount) */
|
||||
#define RSNA_MAX_EAPOL_RETRIES 4
|
||||
|
||||
struct wpa_group;
|
||||
|
||||
struct wpa_stsl_negotiation {
|
||||
struct wpa_stsl_negotiation *next;
|
||||
u8 initiator[ETH_ALEN];
|
||||
u8 peer[ETH_ALEN];
|
||||
};
|
||||
|
||||
|
||||
struct wpa_state_machine {
|
||||
struct wpa_authenticator *wpa_auth;
|
||||
struct wpa_group *group;
|
||||
|
||||
u8 addr[ETH_ALEN];
|
||||
|
||||
enum {
|
||||
WPA_PTK_INITIALIZE, WPA_PTK_DISCONNECT, WPA_PTK_DISCONNECTED,
|
||||
WPA_PTK_AUTHENTICATION, WPA_PTK_AUTHENTICATION2,
|
||||
WPA_PTK_INITPMK, WPA_PTK_INITPSK, WPA_PTK_PTKSTART,
|
||||
WPA_PTK_PTKCALCNEGOTIATING, WPA_PTK_PTKCALCNEGOTIATING2,
|
||||
WPA_PTK_PTKINITNEGOTIATING, WPA_PTK_PTKINITDONE
|
||||
} wpa_ptk_state;
|
||||
|
||||
enum {
|
||||
WPA_PTK_GROUP_IDLE = 0,
|
||||
WPA_PTK_GROUP_REKEYNEGOTIATING,
|
||||
WPA_PTK_GROUP_REKEYESTABLISHED,
|
||||
WPA_PTK_GROUP_KEYERROR
|
||||
} wpa_ptk_group_state;
|
||||
|
||||
Boolean Init;
|
||||
Boolean DeauthenticationRequest;
|
||||
Boolean AuthenticationRequest;
|
||||
Boolean ReAuthenticationRequest;
|
||||
Boolean Disconnect;
|
||||
int TimeoutCtr;
|
||||
int GTimeoutCtr;
|
||||
Boolean TimeoutEvt;
|
||||
Boolean EAPOLKeyReceived;
|
||||
Boolean EAPOLKeyPairwise;
|
||||
Boolean EAPOLKeyRequest;
|
||||
Boolean MICVerified;
|
||||
Boolean GUpdateStationKeys;
|
||||
u8 ANonce[WPA_NONCE_LEN];
|
||||
u8 SNonce[WPA_NONCE_LEN];
|
||||
u8 PMK[PMK_LEN];
|
||||
struct wpa_ptk PTK;
|
||||
Boolean PTK_valid;
|
||||
Boolean pairwise_set;
|
||||
int keycount;
|
||||
Boolean Pair;
|
||||
struct {
|
||||
u8 counter[WPA_REPLAY_COUNTER_LEN];
|
||||
Boolean valid;
|
||||
} 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;
|
||||
Boolean PtkGroupInit; /* init request for PTK Group state machine */
|
||||
|
||||
u8 *last_rx_eapol_key; /* starting from IEEE 802.1X header */
|
||||
size_t last_rx_eapol_key_len;
|
||||
|
||||
unsigned int changed:1;
|
||||
unsigned int in_step_loop:1;
|
||||
unsigned int pending_deinit:1;
|
||||
unsigned int started:1;
|
||||
unsigned int mgmt_frame_prot:1;
|
||||
#ifdef CONFIG_IEEE80211R
|
||||
unsigned int ft_completed:1;
|
||||
unsigned int pmk_r1_name_valid:1;
|
||||
#endif /* CONFIG_IEEE80211R */
|
||||
|
||||
u8 req_replay_counter[WPA_REPLAY_COUNTER_LEN];
|
||||
int req_replay_counter_used;
|
||||
|
||||
u8 *wpa_ie;
|
||||
size_t wpa_ie_len;
|
||||
|
||||
enum {
|
||||
WPA_VERSION_NO_WPA = 0 /* WPA not used */,
|
||||
WPA_VERSION_WPA = 1 /* WPA / IEEE 802.11i/D3.0 */,
|
||||
WPA_VERSION_WPA2 = 2 /* WPA2 / IEEE 802.11i */
|
||||
} wpa;
|
||||
int pairwise; /* Pairwise cipher suite, WPA_CIPHER_* */
|
||||
int wpa_key_mgmt; /* the selected WPA_KEY_MGMT_* */
|
||||
struct rsn_pmksa_cache_entry *pmksa;
|
||||
|
||||
u32 dot11RSNAStatsTKIPLocalMICFailures;
|
||||
u32 dot11RSNAStatsTKIPRemoteMICFailures;
|
||||
|
||||
#ifdef CONFIG_IEEE80211R
|
||||
u8 xxkey[PMK_LEN]; /* PSK or the second 256 bits of MSK */
|
||||
size_t xxkey_len;
|
||||
u8 pmk_r1_name[WPA_PMK_NAME_LEN]; /* PMKR1Name derived from FT Auth
|
||||
* Request */
|
||||
u8 r0kh_id[FT_R0KH_ID_MAX_LEN]; /* R0KH-ID from FT Auth Request */
|
||||
size_t r0kh_id_len;
|
||||
u8 sup_pmk_r1_name[WPA_PMK_NAME_LEN]; /* PMKR1Name from EAPOL-Key
|
||||
* message 2/4 */
|
||||
u8 *assoc_resp_ftie;
|
||||
#endif /* CONFIG_IEEE80211R */
|
||||
|
||||
int pending_1_of_4_timeout;
|
||||
};
|
||||
|
||||
|
||||
/* per group key state machine data */
|
||||
struct wpa_group {
|
||||
struct wpa_group *next;
|
||||
int vlan_id;
|
||||
|
||||
Boolean GInit;
|
||||
int GKeyDoneStations;
|
||||
Boolean GTKReKey;
|
||||
int GTK_len;
|
||||
int GN, GM;
|
||||
Boolean GTKAuthenticator;
|
||||
u8 Counter[WPA_NONCE_LEN];
|
||||
|
||||
enum {
|
||||
WPA_GROUP_GTK_INIT = 0,
|
||||
WPA_GROUP_SETKEYS, WPA_GROUP_SETKEYSDONE
|
||||
} wpa_group_state;
|
||||
|
||||
u8 GMK[WPA_GMK_LEN];
|
||||
u8 GTK[2][WPA_GTK_MAX_LEN];
|
||||
u8 GNonce[WPA_NONCE_LEN];
|
||||
Boolean changed;
|
||||
Boolean first_sta_seen;
|
||||
Boolean reject_4way_hs_for_entropy;
|
||||
#ifdef CONFIG_IEEE80211W
|
||||
u8 IGTK[2][WPA_IGTK_LEN];
|
||||
int GN_igtk, GM_igtk;
|
||||
#endif /* CONFIG_IEEE80211W */
|
||||
};
|
||||
|
||||
|
||||
struct wpa_ft_pmk_cache;
|
||||
|
||||
/* per authenticator data */
|
||||
struct wpa_authenticator {
|
||||
struct wpa_group *group;
|
||||
|
||||
unsigned int dot11RSNAStatsTKIPRemoteMICFailures;
|
||||
u32 dot11RSNAAuthenticationSuiteSelected;
|
||||
u32 dot11RSNAPairwiseCipherSelected;
|
||||
u32 dot11RSNAGroupCipherSelected;
|
||||
u8 dot11RSNAPMKIDUsed[PMKID_LEN];
|
||||
u32 dot11RSNAAuthenticationSuiteRequested; /* FIX: update */
|
||||
u32 dot11RSNAPairwiseCipherRequested; /* FIX: update */
|
||||
u32 dot11RSNAGroupCipherRequested; /* FIX: update */
|
||||
unsigned int dot11RSNATKIPCounterMeasuresInvoked;
|
||||
unsigned int dot11RSNA4WayHandshakeFailures;
|
||||
|
||||
struct wpa_stsl_negotiation *stsl_negotiations;
|
||||
|
||||
struct wpa_auth_config conf;
|
||||
struct wpa_auth_callbacks cb;
|
||||
|
||||
u8 *wpa_ie;
|
||||
size_t wpa_ie_len;
|
||||
|
||||
u8 addr[ETH_ALEN];
|
||||
|
||||
struct rsn_pmksa_cache *pmksa;
|
||||
struct wpa_ft_pmk_cache *ft_pmk_cache;
|
||||
};
|
||||
|
||||
|
||||
int wpa_write_rsn_ie(struct wpa_auth_config *conf, u8 *buf, size_t len,
|
||||
const u8 *pmkid);
|
||||
void wpa_auth_logger(struct wpa_authenticator *wpa_auth, const u8 *addr,
|
||||
logger_level level, const char *txt);
|
||||
void wpa_auth_vlogger(struct wpa_authenticator *wpa_auth, const u8 *addr,
|
||||
logger_level level, const char *fmt, ...);
|
||||
void __wpa_send_eapol(struct wpa_authenticator *wpa_auth,
|
||||
struct wpa_state_machine *sm, int key_info,
|
||||
const u8 *key_rsc, const u8 *nonce,
|
||||
const u8 *kde, size_t kde_len,
|
||||
int keyidx, int encr, int force_version);
|
||||
int wpa_auth_for_each_sta(struct wpa_authenticator *wpa_auth,
|
||||
int (*cb)(struct wpa_state_machine *sm, void *ctx),
|
||||
void *cb_ctx);
|
||||
int wpa_auth_for_each_auth(struct wpa_authenticator *wpa_auth,
|
||||
int (*cb)(struct wpa_authenticator *a, void *ctx),
|
||||
void *cb_ctx);
|
||||
|
||||
#ifdef CONFIG_PEERKEY
|
||||
int wpa_stsl_remove(struct wpa_authenticator *wpa_auth,
|
||||
struct wpa_stsl_negotiation *neg);
|
||||
void wpa_smk_error(struct wpa_authenticator *wpa_auth,
|
||||
struct wpa_state_machine *sm, struct wpa_eapol_key *key);
|
||||
void wpa_smk_m1(struct wpa_authenticator *wpa_auth,
|
||||
struct wpa_state_machine *sm, struct wpa_eapol_key *key);
|
||||
void wpa_smk_m3(struct wpa_authenticator *wpa_auth,
|
||||
struct wpa_state_machine *sm, struct wpa_eapol_key *key);
|
||||
#endif /* CONFIG_PEERKEY */
|
||||
|
||||
#ifdef CONFIG_IEEE80211R
|
||||
int wpa_write_mdie(struct wpa_auth_config *conf, u8 *buf, size_t len);
|
||||
int wpa_write_ftie(struct wpa_auth_config *conf, const u8 *r0kh_id,
|
||||
size_t r0kh_id_len,
|
||||
const u8 *anonce, const u8 *snonce,
|
||||
u8 *buf, size_t len, const u8 *subelem,
|
||||
size_t subelem_len);
|
||||
int wpa_auth_derive_ptk_ft(struct wpa_state_machine *sm, const u8 *pmk,
|
||||
struct wpa_ptk *ptk, size_t ptk_len);
|
||||
struct wpa_ft_pmk_cache * wpa_ft_pmk_cache_init(void);
|
||||
void wpa_ft_pmk_cache_deinit(struct wpa_ft_pmk_cache *cache);
|
||||
void wpa_ft_install_ptk(struct wpa_state_machine *sm);
|
||||
#endif /* CONFIG_IEEE80211R */
|
||||
|
||||
#endif /* WPA_AUTH_I_H */
|
824
hostapd-0.8/src/ap/wpa_auth_ie.c
Normal file
824
hostapd-0.8/src/ap/wpa_auth_ie.c
Normal file
|
@ -0,0 +1,824 @@
|
|||
/*
|
||||
* 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.
|
||||
*/
|
||||
|
||||
#include "utils/includes.h"
|
||||
|
||||
#include "utils/common.h"
|
||||
#include "common/ieee802_11_defs.h"
|
||||
#include "eapol_auth/eapol_auth_sm.h"
|
||||
#include "ap_config.h"
|
||||
#include "ieee802_11.h"
|
||||
#include "wpa_auth.h"
|
||||
#include "pmksa_cache_auth.h"
|
||||
#include "wpa_auth_ie.h"
|
||||
#include "wpa_auth_i.h"
|
||||
|
||||
|
||||
#ifdef CONFIG_RSN_TESTING
|
||||
int rsn_testing = 0;
|
||||
#endif /* CONFIG_RSN_TESTING */
|
||||
|
||||
|
||||
static int wpa_write_wpa_ie(struct wpa_auth_config *conf, u8 *buf, size_t len)
|
||||
{
|
||||
struct wpa_ie_hdr *hdr;
|
||||
int num_suites;
|
||||
u8 *pos, *count;
|
||||
|
||||
hdr = (struct wpa_ie_hdr *) buf;
|
||||
hdr->elem_id = WLAN_EID_VENDOR_SPECIFIC;
|
||||
RSN_SELECTOR_PUT(hdr->oui, WPA_OUI_TYPE);
|
||||
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 {
|
||||
wpa_printf(MSG_DEBUG, "Invalid group cipher (%d).",
|
||||
conf->wpa_group);
|
||||
return -1;
|
||||
}
|
||||
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++;
|
||||
}
|
||||
|
||||
if (num_suites == 0) {
|
||||
wpa_printf(MSG_DEBUG, "Invalid pairwise cipher (%d).",
|
||||
conf->wpa_pairwise);
|
||||
return -1;
|
||||
}
|
||||
WPA_PUT_LE16(count, num_suites);
|
||||
|
||||
num_suites = 0;
|
||||
count = pos;
|
||||
pos += 2;
|
||||
|
||||
if (conf->wpa_key_mgmt & WPA_KEY_MGMT_IEEE8021X) {
|
||||
RSN_SELECTOR_PUT(pos, WPA_AUTH_KEY_MGMT_UNSPEC_802_1X);
|
||||
pos += WPA_SELECTOR_LEN;
|
||||
num_suites++;
|
||||
}
|
||||
if (conf->wpa_key_mgmt & WPA_KEY_MGMT_PSK) {
|
||||
RSN_SELECTOR_PUT(pos, WPA_AUTH_KEY_MGMT_PSK_OVER_802_1X);
|
||||
pos += WPA_SELECTOR_LEN;
|
||||
num_suites++;
|
||||
}
|
||||
|
||||
if (num_suites == 0) {
|
||||
wpa_printf(MSG_DEBUG, "Invalid key management type (%d).",
|
||||
conf->wpa_key_mgmt);
|
||||
return -1;
|
||||
}
|
||||
WPA_PUT_LE16(count, num_suites);
|
||||
|
||||
/* WPA Capabilities; use defaults, so no need to include it */
|
||||
|
||||
hdr->len = (pos - buf) - 2;
|
||||
|
||||
return pos - buf;
|
||||
}
|
||||
|
||||
|
||||
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;
|
||||
u8 *pos, *count;
|
||||
u16 capab;
|
||||
|
||||
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 {
|
||||
wpa_printf(MSG_DEBUG, "Invalid group cipher (%d).",
|
||||
conf->wpa_group);
|
||||
return -1;
|
||||
}
|
||||
pos += RSN_SELECTOR_LEN;
|
||||
|
||||
num_suites = 0;
|
||||
count = pos;
|
||||
pos += 2;
|
||||
|
||||
#ifdef CONFIG_RSN_TESTING
|
||||
if (rsn_testing) {
|
||||
RSN_SELECTOR_PUT(pos, RSN_SELECTOR(0x12, 0x34, 0x56, 1));
|
||||
pos += RSN_SELECTOR_LEN;
|
||||
num_suites++;
|
||||
}
|
||||
#endif /* CONFIG_RSN_TESTING */
|
||||
|
||||
if (conf->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++;
|
||||
}
|
||||
|
||||
#ifdef CONFIG_RSN_TESTING
|
||||
if (rsn_testing) {
|
||||
RSN_SELECTOR_PUT(pos, RSN_SELECTOR(0x12, 0x34, 0x56, 2));
|
||||
pos += RSN_SELECTOR_LEN;
|
||||
num_suites++;
|
||||
}
|
||||
#endif /* CONFIG_RSN_TESTING */
|
||||
|
||||
if (num_suites == 0) {
|
||||
wpa_printf(MSG_DEBUG, "Invalid pairwise cipher (%d).",
|
||||
conf->rsn_pairwise);
|
||||
return -1;
|
||||
}
|
||||
WPA_PUT_LE16(count, num_suites);
|
||||
|
||||
num_suites = 0;
|
||||
count = pos;
|
||||
pos += 2;
|
||||
|
||||
#ifdef CONFIG_RSN_TESTING
|
||||
if (rsn_testing) {
|
||||
RSN_SELECTOR_PUT(pos, RSN_SELECTOR(0x12, 0x34, 0x56, 1));
|
||||
pos += RSN_SELECTOR_LEN;
|
||||
num_suites++;
|
||||
}
|
||||
#endif /* CONFIG_RSN_TESTING */
|
||||
|
||||
if (conf->wpa_key_mgmt & WPA_KEY_MGMT_IEEE8021X) {
|
||||
RSN_SELECTOR_PUT(pos, RSN_AUTH_KEY_MGMT_UNSPEC_802_1X);
|
||||
pos += RSN_SELECTOR_LEN;
|
||||
num_suites++;
|
||||
}
|
||||
if (conf->wpa_key_mgmt & WPA_KEY_MGMT_PSK) {
|
||||
RSN_SELECTOR_PUT(pos, RSN_AUTH_KEY_MGMT_PSK_OVER_802_1X);
|
||||
pos += RSN_SELECTOR_LEN;
|
||||
num_suites++;
|
||||
}
|
||||
#ifdef CONFIG_IEEE80211R
|
||||
if (conf->wpa_key_mgmt & WPA_KEY_MGMT_FT_IEEE8021X) {
|
||||
RSN_SELECTOR_PUT(pos, RSN_AUTH_KEY_MGMT_FT_802_1X);
|
||||
pos += RSN_SELECTOR_LEN;
|
||||
num_suites++;
|
||||
}
|
||||
if (conf->wpa_key_mgmt & WPA_KEY_MGMT_FT_PSK) {
|
||||
RSN_SELECTOR_PUT(pos, RSN_AUTH_KEY_MGMT_FT_PSK);
|
||||
pos += RSN_SELECTOR_LEN;
|
||||
num_suites++;
|
||||
}
|
||||
#endif /* CONFIG_IEEE80211R */
|
||||
#ifdef CONFIG_IEEE80211W
|
||||
if (conf->wpa_key_mgmt & WPA_KEY_MGMT_IEEE8021X_SHA256) {
|
||||
RSN_SELECTOR_PUT(pos, RSN_AUTH_KEY_MGMT_802_1X_SHA256);
|
||||
pos += RSN_SELECTOR_LEN;
|
||||
num_suites++;
|
||||
}
|
||||
if (conf->wpa_key_mgmt & WPA_KEY_MGMT_PSK_SHA256) {
|
||||
RSN_SELECTOR_PUT(pos, RSN_AUTH_KEY_MGMT_PSK_SHA256);
|
||||
pos += RSN_SELECTOR_LEN;
|
||||
num_suites++;
|
||||
}
|
||||
#endif /* CONFIG_IEEE80211W */
|
||||
|
||||
#ifdef CONFIG_RSN_TESTING
|
||||
if (rsn_testing) {
|
||||
RSN_SELECTOR_PUT(pos, RSN_SELECTOR(0x12, 0x34, 0x56, 2));
|
||||
pos += RSN_SELECTOR_LEN;
|
||||
num_suites++;
|
||||
}
|
||||
#endif /* CONFIG_RSN_TESTING */
|
||||
|
||||
if (num_suites == 0) {
|
||||
wpa_printf(MSG_DEBUG, "Invalid key management type (%d).",
|
||||
conf->wpa_key_mgmt);
|
||||
return -1;
|
||||
}
|
||||
WPA_PUT_LE16(count, num_suites);
|
||||
|
||||
/* RSN Capabilities */
|
||||
capab = 0;
|
||||
if (conf->rsn_preauth)
|
||||
capab |= WPA_CAPABILITY_PREAUTH;
|
||||
if (conf->peerkey)
|
||||
capab |= WPA_CAPABILITY_PEERKEY_ENABLED;
|
||||
if (conf->wmm_enabled) {
|
||||
/* 4 PTKSA replay counters when using WMM */
|
||||
capab |= (RSN_NUM_REPLAY_COUNTERS_16 << 2);
|
||||
}
|
||||
#ifdef CONFIG_IEEE80211W
|
||||
if (conf->ieee80211w != NO_MGMT_FRAME_PROTECTION) {
|
||||
capab |= WPA_CAPABILITY_MFPC;
|
||||
if (conf->ieee80211w == MGMT_FRAME_PROTECTION_REQUIRED)
|
||||
capab |= WPA_CAPABILITY_MFPR;
|
||||
}
|
||||
#endif /* CONFIG_IEEE80211W */
|
||||
#ifdef CONFIG_RSN_TESTING
|
||||
if (rsn_testing)
|
||||
capab |= BIT(8) | BIT(14) | BIT(15);
|
||||
#endif /* CONFIG_RSN_TESTING */
|
||||
WPA_PUT_LE16(pos, capab);
|
||||
pos += 2;
|
||||
|
||||
if (pmkid) {
|
||||
if (pos + 2 + PMKID_LEN > buf + len)
|
||||
return -1;
|
||||
/* PMKID Count */
|
||||
WPA_PUT_LE16(pos, 1);
|
||||
pos += 2;
|
||||
os_memcpy(pos, pmkid, PMKID_LEN);
|
||||
pos += PMKID_LEN;
|
||||
}
|
||||
|
||||
#ifdef CONFIG_IEEE80211W
|
||||
if (conf->ieee80211w != NO_MGMT_FRAME_PROTECTION) {
|
||||
if (pos + 2 + 4 > buf + len)
|
||||
return -1;
|
||||
if (pmkid == NULL) {
|
||||
/* PMKID Count */
|
||||
WPA_PUT_LE16(pos, 0);
|
||||
pos += 2;
|
||||
}
|
||||
|
||||
/* Management Group Cipher Suite */
|
||||
RSN_SELECTOR_PUT(pos, RSN_CIPHER_SUITE_AES_128_CMAC);
|
||||
pos += RSN_SELECTOR_LEN;
|
||||
}
|
||||
#endif /* CONFIG_IEEE80211W */
|
||||
|
||||
#ifdef CONFIG_RSN_TESTING
|
||||
if (rsn_testing) {
|
||||
/*
|
||||
* Fill in any defined fields and add extra data to the end of
|
||||
* the element.
|
||||
*/
|
||||
int pmkid_count_set = pmkid != NULL;
|
||||
if (conf->ieee80211w != NO_MGMT_FRAME_PROTECTION)
|
||||
pmkid_count_set = 1;
|
||||
/* PMKID Count */
|
||||
WPA_PUT_LE16(pos, 0);
|
||||
pos += 2;
|
||||
if (conf->ieee80211w == NO_MGMT_FRAME_PROTECTION) {
|
||||
/* Management Group Cipher Suite */
|
||||
RSN_SELECTOR_PUT(pos, RSN_CIPHER_SUITE_AES_128_CMAC);
|
||||
pos += RSN_SELECTOR_LEN;
|
||||
}
|
||||
|
||||
os_memset(pos, 0x12, 17);
|
||||
pos += 17;
|
||||
}
|
||||
#endif /* CONFIG_RSN_TESTING */
|
||||
|
||||
hdr->len = (pos - buf) - 2;
|
||||
|
||||
return pos - buf;
|
||||
}
|
||||
|
||||
|
||||
int wpa_auth_gen_wpa_ie(struct wpa_authenticator *wpa_auth)
|
||||
{
|
||||
u8 *pos, buf[128];
|
||||
int res;
|
||||
|
||||
pos = buf;
|
||||
|
||||
if (wpa_auth->conf.wpa & WPA_PROTO_RSN) {
|
||||
res = wpa_write_rsn_ie(&wpa_auth->conf,
|
||||
pos, buf + sizeof(buf) - pos, NULL);
|
||||
if (res < 0)
|
||||
return res;
|
||||
pos += res;
|
||||
}
|
||||
#ifdef CONFIG_IEEE80211R
|
||||
if (wpa_auth->conf.wpa_key_mgmt &
|
||||
(WPA_KEY_MGMT_FT_IEEE8021X | WPA_KEY_MGMT_FT_PSK)) {
|
||||
res = wpa_write_mdie(&wpa_auth->conf, pos,
|
||||
buf + sizeof(buf) - pos);
|
||||
if (res < 0)
|
||||
return res;
|
||||
pos += res;
|
||||
}
|
||||
#endif /* CONFIG_IEEE80211R */
|
||||
if (wpa_auth->conf.wpa & WPA_PROTO_WPA) {
|
||||
res = wpa_write_wpa_ie(&wpa_auth->conf,
|
||||
pos, buf + sizeof(buf) - pos);
|
||||
if (res < 0)
|
||||
return res;
|
||||
pos += res;
|
||||
}
|
||||
|
||||
os_free(wpa_auth->wpa_ie);
|
||||
wpa_auth->wpa_ie = os_malloc(pos - buf);
|
||||
if (wpa_auth->wpa_ie == NULL)
|
||||
return -1;
|
||||
os_memcpy(wpa_auth->wpa_ie, buf, pos - buf);
|
||||
wpa_auth->wpa_ie_len = pos - buf;
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
|
||||
u8 * wpa_add_kde(u8 *pos, u32 kde, const u8 *data, size_t data_len,
|
||||
const u8 *data2, size_t data2_len)
|
||||
{
|
||||
*pos++ = WLAN_EID_VENDOR_SPECIFIC;
|
||||
*pos++ = RSN_SELECTOR_LEN + data_len + data2_len;
|
||||
RSN_SELECTOR_PUT(pos, kde);
|
||||
pos += RSN_SELECTOR_LEN;
|
||||
os_memcpy(pos, data, data_len);
|
||||
pos += data_len;
|
||||
if (data2) {
|
||||
os_memcpy(pos, data2, data2_len);
|
||||
pos += data2_len;
|
||||
}
|
||||
return pos;
|
||||
}
|
||||
|
||||
|
||||
struct wpa_auth_okc_iter_data {
|
||||
struct rsn_pmksa_cache_entry *pmksa;
|
||||
const u8 *aa;
|
||||
const u8 *spa;
|
||||
const u8 *pmkid;
|
||||
};
|
||||
|
||||
|
||||
static int wpa_auth_okc_iter(struct wpa_authenticator *a, void *ctx)
|
||||
{
|
||||
struct wpa_auth_okc_iter_data *data = ctx;
|
||||
data->pmksa = pmksa_cache_get_okc(a->pmksa, data->aa, data->spa,
|
||||
data->pmkid);
|
||||
if (data->pmksa)
|
||||
return 1;
|
||||
return 0;
|
||||
}
|
||||
|
||||
|
||||
int wpa_validate_wpa_ie(struct wpa_authenticator *wpa_auth,
|
||||
struct wpa_state_machine *sm,
|
||||
const u8 *wpa_ie, size_t wpa_ie_len,
|
||||
const u8 *mdie, size_t mdie_len)
|
||||
{
|
||||
struct wpa_ie_data data;
|
||||
int ciphers, key_mgmt, res, version;
|
||||
u32 selector;
|
||||
size_t i;
|
||||
const u8 *pmkid = NULL;
|
||||
|
||||
if (wpa_auth == NULL || sm == NULL)
|
||||
return WPA_NOT_ENABLED;
|
||||
|
||||
if (wpa_ie == NULL || wpa_ie_len < 1)
|
||||
return WPA_INVALID_IE;
|
||||
|
||||
if (wpa_ie[0] == WLAN_EID_RSN)
|
||||
version = WPA_PROTO_RSN;
|
||||
else
|
||||
version = WPA_PROTO_WPA;
|
||||
|
||||
if (!(wpa_auth->conf.wpa & version)) {
|
||||
wpa_printf(MSG_DEBUG, "Invalid WPA proto (%d) from " MACSTR,
|
||||
version, MAC2STR(sm->addr));
|
||||
return WPA_INVALID_PROTO;
|
||||
}
|
||||
|
||||
if (version == WPA_PROTO_RSN) {
|
||||
res = wpa_parse_wpa_ie_rsn(wpa_ie, wpa_ie_len, &data);
|
||||
|
||||
selector = RSN_AUTH_KEY_MGMT_UNSPEC_802_1X;
|
||||
if (0) {
|
||||
}
|
||||
#ifdef CONFIG_IEEE80211R
|
||||
else if (data.key_mgmt & WPA_KEY_MGMT_FT_IEEE8021X)
|
||||
selector = RSN_AUTH_KEY_MGMT_FT_802_1X;
|
||||
else if (data.key_mgmt & WPA_KEY_MGMT_FT_PSK)
|
||||
selector = RSN_AUTH_KEY_MGMT_FT_PSK;
|
||||
#endif /* CONFIG_IEEE80211R */
|
||||
#ifdef CONFIG_IEEE80211W
|
||||
else if (data.key_mgmt & WPA_KEY_MGMT_IEEE8021X_SHA256)
|
||||
selector = RSN_AUTH_KEY_MGMT_802_1X_SHA256;
|
||||
else if (data.key_mgmt & WPA_KEY_MGMT_PSK_SHA256)
|
||||
selector = RSN_AUTH_KEY_MGMT_PSK_SHA256;
|
||||
#endif /* CONFIG_IEEE80211W */
|
||||
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 = 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 = 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);
|
||||
|
||||
selector = WPA_AUTH_KEY_MGMT_UNSPEC_802_1X;
|
||||
if (data.key_mgmt & WPA_KEY_MGMT_IEEE8021X)
|
||||
selector = WPA_AUTH_KEY_MGMT_UNSPEC_802_1X;
|
||||
else if (data.key_mgmt & WPA_KEY_MGMT_PSK)
|
||||
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;
|
||||
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_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) {
|
||||
wpa_printf(MSG_DEBUG, "Failed to parse WPA/RSN IE from "
|
||||
MACSTR " (res=%d)", MAC2STR(sm->addr), res);
|
||||
wpa_hexdump(MSG_DEBUG, "WPA/RSN IE", wpa_ie, wpa_ie_len);
|
||||
return WPA_INVALID_IE;
|
||||
}
|
||||
|
||||
if (data.group_cipher != wpa_auth->conf.wpa_group) {
|
||||
wpa_printf(MSG_DEBUG, "Invalid WPA group cipher (0x%x) from "
|
||||
MACSTR, data.group_cipher, MAC2STR(sm->addr));
|
||||
return WPA_INVALID_GROUP;
|
||||
}
|
||||
|
||||
key_mgmt = data.key_mgmt & wpa_auth->conf.wpa_key_mgmt;
|
||||
if (!key_mgmt) {
|
||||
wpa_printf(MSG_DEBUG, "Invalid WPA key mgmt (0x%x) from "
|
||||
MACSTR, data.key_mgmt, MAC2STR(sm->addr));
|
||||
return WPA_INVALID_AKMP;
|
||||
}
|
||||
if (0) {
|
||||
}
|
||||
#ifdef CONFIG_IEEE80211R
|
||||
else if (key_mgmt & WPA_KEY_MGMT_FT_IEEE8021X)
|
||||
sm->wpa_key_mgmt = WPA_KEY_MGMT_FT_IEEE8021X;
|
||||
else if (key_mgmt & WPA_KEY_MGMT_FT_PSK)
|
||||
sm->wpa_key_mgmt = WPA_KEY_MGMT_FT_PSK;
|
||||
#endif /* CONFIG_IEEE80211R */
|
||||
#ifdef CONFIG_IEEE80211W
|
||||
else if (key_mgmt & WPA_KEY_MGMT_IEEE8021X_SHA256)
|
||||
sm->wpa_key_mgmt = WPA_KEY_MGMT_IEEE8021X_SHA256;
|
||||
else if (key_mgmt & WPA_KEY_MGMT_PSK_SHA256)
|
||||
sm->wpa_key_mgmt = WPA_KEY_MGMT_PSK_SHA256;
|
||||
#endif /* CONFIG_IEEE80211W */
|
||||
else if (key_mgmt & WPA_KEY_MGMT_IEEE8021X)
|
||||
sm->wpa_key_mgmt = WPA_KEY_MGMT_IEEE8021X;
|
||||
else
|
||||
sm->wpa_key_mgmt = WPA_KEY_MGMT_PSK;
|
||||
|
||||
if (version == WPA_PROTO_RSN)
|
||||
ciphers = data.pairwise_cipher & wpa_auth->conf.rsn_pairwise;
|
||||
else
|
||||
ciphers = data.pairwise_cipher & wpa_auth->conf.wpa_pairwise;
|
||||
if (!ciphers) {
|
||||
wpa_printf(MSG_DEBUG, "Invalid %s pairwise cipher (0x%x) "
|
||||
"from " MACSTR,
|
||||
version == WPA_PROTO_RSN ? "RSN" : "WPA",
|
||||
data.pairwise_cipher, MAC2STR(sm->addr));
|
||||
return WPA_INVALID_PAIRWISE;
|
||||
}
|
||||
|
||||
#ifdef CONFIG_IEEE80211W
|
||||
if (wpa_auth->conf.ieee80211w == MGMT_FRAME_PROTECTION_REQUIRED) {
|
||||
if (!(data.capabilities & WPA_CAPABILITY_MFPC)) {
|
||||
wpa_printf(MSG_DEBUG, "Management frame protection "
|
||||
"required, but client did not enable it");
|
||||
return WPA_MGMT_FRAME_PROTECTION_VIOLATION;
|
||||
}
|
||||
|
||||
if (ciphers & WPA_CIPHER_TKIP) {
|
||||
wpa_printf(MSG_DEBUG, "Management frame protection "
|
||||
"cannot use TKIP");
|
||||
return WPA_MGMT_FRAME_PROTECTION_VIOLATION;
|
||||
}
|
||||
|
||||
if (data.mgmt_group_cipher != WPA_CIPHER_AES_128_CMAC) {
|
||||
wpa_printf(MSG_DEBUG, "Unsupported management group "
|
||||
"cipher %d", data.mgmt_group_cipher);
|
||||
return WPA_INVALID_MGMT_GROUP_CIPHER;
|
||||
}
|
||||
}
|
||||
|
||||
if (wpa_auth->conf.ieee80211w == NO_MGMT_FRAME_PROTECTION ||
|
||||
!(data.capabilities & WPA_CAPABILITY_MFPC))
|
||||
sm->mgmt_frame_prot = 0;
|
||||
else
|
||||
sm->mgmt_frame_prot = 1;
|
||||
#endif /* CONFIG_IEEE80211W */
|
||||
|
||||
#ifdef CONFIG_IEEE80211R
|
||||
if (wpa_key_mgmt_ft(sm->wpa_key_mgmt)) {
|
||||
if (mdie == NULL || mdie_len < MOBILITY_DOMAIN_ID_LEN + 1) {
|
||||
wpa_printf(MSG_DEBUG, "RSN: Trying to use FT, but "
|
||||
"MDIE not included");
|
||||
return WPA_INVALID_MDIE;
|
||||
}
|
||||
if (os_memcmp(mdie, wpa_auth->conf.mobility_domain,
|
||||
MOBILITY_DOMAIN_ID_LEN) != 0) {
|
||||
wpa_hexdump(MSG_DEBUG, "RSN: Attempted to use unknown "
|
||||
"MDIE", mdie, MOBILITY_DOMAIN_ID_LEN);
|
||||
return WPA_INVALID_MDIE;
|
||||
}
|
||||
}
|
||||
#endif /* CONFIG_IEEE80211R */
|
||||
|
||||
if (ciphers & WPA_CIPHER_CCMP)
|
||||
sm->pairwise = WPA_CIPHER_CCMP;
|
||||
else
|
||||
sm->pairwise = WPA_CIPHER_TKIP;
|
||||
|
||||
/* TODO: clear WPA/WPA2 state if STA changes from one to another */
|
||||
if (wpa_ie[0] == WLAN_EID_RSN)
|
||||
sm->wpa = WPA_VERSION_WPA2;
|
||||
else
|
||||
sm->wpa = WPA_VERSION_WPA;
|
||||
|
||||
sm->pmksa = NULL;
|
||||
for (i = 0; i < data.num_pmkid; i++) {
|
||||
wpa_hexdump(MSG_DEBUG, "RSN IE: STA PMKID",
|
||||
&data.pmkid[i * PMKID_LEN], PMKID_LEN);
|
||||
sm->pmksa = pmksa_cache_auth_get(wpa_auth->pmksa, sm->addr,
|
||||
&data.pmkid[i * PMKID_LEN]);
|
||||
if (sm->pmksa) {
|
||||
pmkid = sm->pmksa->pmkid;
|
||||
break;
|
||||
}
|
||||
}
|
||||
for (i = 0; sm->pmksa == NULL && wpa_auth->conf.okc &&
|
||||
i < data.num_pmkid; i++) {
|
||||
struct wpa_auth_okc_iter_data idata;
|
||||
idata.pmksa = NULL;
|
||||
idata.aa = wpa_auth->addr;
|
||||
idata.spa = sm->addr;
|
||||
idata.pmkid = &data.pmkid[i * PMKID_LEN];
|
||||
wpa_auth_for_each_auth(wpa_auth, wpa_auth_okc_iter, &idata);
|
||||
if (idata.pmksa) {
|
||||
wpa_auth_vlogger(wpa_auth, sm->addr, LOGGER_DEBUG,
|
||||
"OKC match for PMKID");
|
||||
sm->pmksa = pmksa_cache_add_okc(wpa_auth->pmksa,
|
||||
idata.pmksa,
|
||||
wpa_auth->addr,
|
||||
idata.pmkid);
|
||||
pmkid = idata.pmkid;
|
||||
break;
|
||||
}
|
||||
}
|
||||
if (sm->pmksa) {
|
||||
wpa_auth_vlogger(wpa_auth, sm->addr, LOGGER_DEBUG,
|
||||
"PMKID found from PMKSA cache "
|
||||
"eap_type=%d vlan_id=%d",
|
||||
sm->pmksa->eap_type_authsrv,
|
||||
sm->pmksa->vlan_id);
|
||||
os_memcpy(wpa_auth->dot11RSNAPMKIDUsed, pmkid, PMKID_LEN);
|
||||
}
|
||||
|
||||
if (sm->wpa_ie == NULL || sm->wpa_ie_len < wpa_ie_len) {
|
||||
os_free(sm->wpa_ie);
|
||||
sm->wpa_ie = os_malloc(wpa_ie_len);
|
||||
if (sm->wpa_ie == NULL)
|
||||
return WPA_ALLOC_FAIL;
|
||||
}
|
||||
os_memcpy(sm->wpa_ie, wpa_ie, wpa_ie_len);
|
||||
sm->wpa_ie_len = wpa_ie_len;
|
||||
|
||||
return WPA_IE_OK;
|
||||
}
|
||||
|
||||
|
||||
/**
|
||||
* wpa_parse_generic - Parse EAPOL-Key Key Data Generic IEs
|
||||
* @pos: Pointer to the IE header
|
||||
* @end: Pointer to the end of the Key Data buffer
|
||||
* @ie: Pointer to parsed IE data
|
||||
* Returns: 0 on success, 1 if end mark is found, -1 on failure
|
||||
*/
|
||||
static int wpa_parse_generic(const u8 *pos, const u8 *end,
|
||||
struct wpa_eapol_ie_parse *ie)
|
||||
{
|
||||
if (pos[1] == 0)
|
||||
return 1;
|
||||
|
||||
if (pos[1] >= 6 &&
|
||||
RSN_SELECTOR_GET(pos + 2) == WPA_OUI_TYPE &&
|
||||
pos[2 + WPA_SELECTOR_LEN] == 1 &&
|
||||
pos[2 + WPA_SELECTOR_LEN + 1] == 0) {
|
||||
ie->wpa_ie = pos;
|
||||
ie->wpa_ie_len = pos[1] + 2;
|
||||
return 0;
|
||||
}
|
||||
|
||||
if (pos + 1 + RSN_SELECTOR_LEN < end &&
|
||||
pos[1] >= RSN_SELECTOR_LEN + PMKID_LEN &&
|
||||
RSN_SELECTOR_GET(pos + 2) == RSN_KEY_DATA_PMKID) {
|
||||
ie->pmkid = pos + 2 + RSN_SELECTOR_LEN;
|
||||
return 0;
|
||||
}
|
||||
|
||||
if (pos[1] > RSN_SELECTOR_LEN + 2 &&
|
||||
RSN_SELECTOR_GET(pos + 2) == RSN_KEY_DATA_GROUPKEY) {
|
||||
ie->gtk = pos + 2 + RSN_SELECTOR_LEN;
|
||||
ie->gtk_len = pos[1] - RSN_SELECTOR_LEN;
|
||||
return 0;
|
||||
}
|
||||
|
||||
if (pos[1] > RSN_SELECTOR_LEN + 2 &&
|
||||
RSN_SELECTOR_GET(pos + 2) == RSN_KEY_DATA_MAC_ADDR) {
|
||||
ie->mac_addr = pos + 2 + RSN_SELECTOR_LEN;
|
||||
ie->mac_addr_len = pos[1] - RSN_SELECTOR_LEN;
|
||||
return 0;
|
||||
}
|
||||
|
||||
#ifdef CONFIG_PEERKEY
|
||||
if (pos[1] > RSN_SELECTOR_LEN + 2 &&
|
||||
RSN_SELECTOR_GET(pos + 2) == RSN_KEY_DATA_SMK) {
|
||||
ie->smk = pos + 2 + RSN_SELECTOR_LEN;
|
||||
ie->smk_len = pos[1] - RSN_SELECTOR_LEN;
|
||||
return 0;
|
||||
}
|
||||
|
||||
if (pos[1] > RSN_SELECTOR_LEN + 2 &&
|
||||
RSN_SELECTOR_GET(pos + 2) == RSN_KEY_DATA_NONCE) {
|
||||
ie->nonce = pos + 2 + RSN_SELECTOR_LEN;
|
||||
ie->nonce_len = pos[1] - RSN_SELECTOR_LEN;
|
||||
return 0;
|
||||
}
|
||||
|
||||
if (pos[1] > RSN_SELECTOR_LEN + 2 &&
|
||||
RSN_SELECTOR_GET(pos + 2) == RSN_KEY_DATA_LIFETIME) {
|
||||
ie->lifetime = pos + 2 + RSN_SELECTOR_LEN;
|
||||
ie->lifetime_len = pos[1] - RSN_SELECTOR_LEN;
|
||||
return 0;
|
||||
}
|
||||
|
||||
if (pos[1] > RSN_SELECTOR_LEN + 2 &&
|
||||
RSN_SELECTOR_GET(pos + 2) == RSN_KEY_DATA_ERROR) {
|
||||
ie->error = pos + 2 + RSN_SELECTOR_LEN;
|
||||
ie->error_len = pos[1] - RSN_SELECTOR_LEN;
|
||||
return 0;
|
||||
}
|
||||
#endif /* CONFIG_PEERKEY */
|
||||
|
||||
#ifdef CONFIG_IEEE80211W
|
||||
if (pos[1] > RSN_SELECTOR_LEN + 2 &&
|
||||
RSN_SELECTOR_GET(pos + 2) == RSN_KEY_DATA_IGTK) {
|
||||
ie->igtk = pos + 2 + RSN_SELECTOR_LEN;
|
||||
ie->igtk_len = pos[1] - RSN_SELECTOR_LEN;
|
||||
return 0;
|
||||
}
|
||||
#endif /* CONFIG_IEEE80211W */
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
|
||||
/**
|
||||
* wpa_parse_kde_ies - Parse EAPOL-Key Key Data IEs
|
||||
* @buf: Pointer to the Key Data buffer
|
||||
* @len: Key Data Length
|
||||
* @ie: Pointer to parsed IE data
|
||||
* Returns: 0 on success, -1 on failure
|
||||
*/
|
||||
int wpa_parse_kde_ies(const u8 *buf, size_t len, struct wpa_eapol_ie_parse *ie)
|
||||
{
|
||||
const u8 *pos, *end;
|
||||
int ret = 0;
|
||||
|
||||
os_memset(ie, 0, sizeof(*ie));
|
||||
for (pos = buf, end = pos + len; pos + 1 < end; pos += 2 + pos[1]) {
|
||||
if (pos[0] == 0xdd &&
|
||||
((pos == buf + len - 1) || pos[1] == 0)) {
|
||||
/* Ignore padding */
|
||||
break;
|
||||
}
|
||||
if (pos + 2 + pos[1] > end) {
|
||||
wpa_printf(MSG_DEBUG, "WPA: EAPOL-Key Key Data "
|
||||
"underflow (ie=%d len=%d pos=%d)",
|
||||
pos[0], pos[1], (int) (pos - buf));
|
||||
wpa_hexdump_key(MSG_DEBUG, "WPA: Key Data",
|
||||
buf, len);
|
||||
ret = -1;
|
||||
break;
|
||||
}
|
||||
if (*pos == WLAN_EID_RSN) {
|
||||
ie->rsn_ie = pos;
|
||||
ie->rsn_ie_len = pos[1] + 2;
|
||||
#ifdef CONFIG_IEEE80211R
|
||||
} else if (*pos == WLAN_EID_MOBILITY_DOMAIN) {
|
||||
ie->mdie = pos;
|
||||
ie->mdie_len = pos[1] + 2;
|
||||
} else if (*pos == WLAN_EID_FAST_BSS_TRANSITION) {
|
||||
ie->ftie = pos;
|
||||
ie->ftie_len = pos[1] + 2;
|
||||
#endif /* CONFIG_IEEE80211R */
|
||||
} else if (*pos == WLAN_EID_VENDOR_SPECIFIC) {
|
||||
ret = wpa_parse_generic(pos, end, ie);
|
||||
if (ret < 0)
|
||||
break;
|
||||
if (ret > 0) {
|
||||
ret = 0;
|
||||
break;
|
||||
}
|
||||
} else {
|
||||
wpa_hexdump(MSG_DEBUG, "WPA: Unrecognized EAPOL-Key "
|
||||
"Key Data IE", pos, 2 + pos[1]);
|
||||
}
|
||||
}
|
||||
|
||||
return ret;
|
||||
}
|
||||
|
||||
|
||||
int wpa_auth_uses_mfp(struct wpa_state_machine *sm)
|
||||
{
|
||||
return sm ? sm->mgmt_frame_prot : 0;
|
||||
}
|
56
hostapd-0.8/src/ap/wpa_auth_ie.h
Normal file
56
hostapd-0.8/src/ap/wpa_auth_ie.h
Normal file
|
@ -0,0 +1,56 @@
|
|||
/*
|
||||
* 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.
|
||||
*/
|
||||
|
||||
#ifndef WPA_AUTH_IE_H
|
||||
#define WPA_AUTH_IE_H
|
||||
|
||||
struct wpa_eapol_ie_parse {
|
||||
const u8 *wpa_ie;
|
||||
size_t wpa_ie_len;
|
||||
const u8 *rsn_ie;
|
||||
size_t rsn_ie_len;
|
||||
const u8 *pmkid;
|
||||
const u8 *gtk;
|
||||
size_t gtk_len;
|
||||
const u8 *mac_addr;
|
||||
size_t mac_addr_len;
|
||||
#ifdef CONFIG_PEERKEY
|
||||
const u8 *smk;
|
||||
size_t smk_len;
|
||||
const u8 *nonce;
|
||||
size_t nonce_len;
|
||||
const u8 *lifetime;
|
||||
size_t lifetime_len;
|
||||
const u8 *error;
|
||||
size_t error_len;
|
||||
#endif /* CONFIG_PEERKEY */
|
||||
#ifdef CONFIG_IEEE80211W
|
||||
const u8 *igtk;
|
||||
size_t igtk_len;
|
||||
#endif /* CONFIG_IEEE80211W */
|
||||
#ifdef CONFIG_IEEE80211R
|
||||
const u8 *mdie;
|
||||
size_t mdie_len;
|
||||
const u8 *ftie;
|
||||
size_t ftie_len;
|
||||
#endif /* CONFIG_IEEE80211R */
|
||||
};
|
||||
|
||||
int wpa_parse_kde_ies(const u8 *buf, size_t len,
|
||||
struct wpa_eapol_ie_parse *ie);
|
||||
u8 * wpa_add_kde(u8 *pos, u32 kde, const u8 *data, size_t data_len,
|
||||
const u8 *data2, size_t data2_len);
|
||||
int wpa_auth_gen_wpa_ie(struct wpa_authenticator *wpa_auth);
|
||||
|
||||
#endif /* WPA_AUTH_IE_H */
|
1380
hostapd-0.8/src/ap/wps_hostapd.c
Normal file
1380
hostapd-0.8/src/ap/wps_hostapd.c
Normal file
File diff suppressed because it is too large
Load diff
72
hostapd-0.8/src/ap/wps_hostapd.h
Normal file
72
hostapd-0.8/src/ap/wps_hostapd.h
Normal file
|
@ -0,0 +1,72 @@
|
|||
/*
|
||||
* hostapd / WPS integration
|
||||
* Copyright (c) 2008-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.
|
||||
*/
|
||||
|
||||
#ifndef WPS_HOSTAPD_H
|
||||
#define WPS_HOSTAPD_H
|
||||
|
||||
#ifdef CONFIG_WPS
|
||||
|
||||
int hostapd_init_wps(struct hostapd_data *hapd,
|
||||
struct hostapd_bss_config *conf);
|
||||
void hostapd_deinit_wps(struct hostapd_data *hapd);
|
||||
void hostapd_update_wps(struct hostapd_data *hapd);
|
||||
int hostapd_wps_add_pin(struct hostapd_data *hapd, const 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_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);
|
||||
const char * hostapd_wps_ap_pin_random(struct hostapd_data *hapd, int timeout);
|
||||
const char * hostapd_wps_ap_pin_get(struct hostapd_data *hapd);
|
||||
int hostapd_wps_ap_pin_set(struct hostapd_data *hapd, const char *pin,
|
||||
int timeout);
|
||||
void hostapd_wps_update_ie(struct hostapd_data *hapd);
|
||||
int hostapd_wps_config_ap(struct hostapd_data *hapd, const char *ssid,
|
||||
const char *auth, const char *encr, const char *key);
|
||||
|
||||
#else /* CONFIG_WPS */
|
||||
|
||||
static inline int hostapd_init_wps(struct hostapd_data *hapd,
|
||||
struct hostapd_bss_config *conf)
|
||||
{
|
||||
return 0;
|
||||
}
|
||||
|
||||
static inline void hostapd_deinit_wps(struct hostapd_data *hapd)
|
||||
{
|
||||
}
|
||||
|
||||
static inline void hostapd_update_wps(struct hostapd_data *hapd)
|
||||
{
|
||||
}
|
||||
|
||||
static inline int hostapd_wps_get_mib_sta(struct hostapd_data *hapd,
|
||||
const u8 *addr,
|
||||
char *buf, size_t buflen)
|
||||
{
|
||||
return 0;
|
||||
}
|
||||
|
||||
static inline int hostapd_wps_button_pushed(struct hostapd_data *hapd,
|
||||
const u8 *p2p_dev_addr)
|
||||
{
|
||||
return 0;
|
||||
}
|
||||
|
||||
#endif /* CONFIG_WPS */
|
||||
|
||||
#endif /* WPS_HOSTAPD_H */
|
8
hostapd-0.8/src/common/Makefile
Normal file
8
hostapd-0.8/src/common/Makefile
Normal file
|
@ -0,0 +1,8 @@
|
|||
all:
|
||||
@echo Nothing to be made.
|
||||
|
||||
clean:
|
||||
rm -f *~ *.o *.d
|
||||
|
||||
install:
|
||||
@echo Nothing to be made.
|
270
hostapd-0.8/src/common/defs.h
Normal file
270
hostapd-0.8/src/common/defs.h
Normal file
|
@ -0,0 +1,270 @@
|
|||
/*
|
||||
* 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.
|
||||
*/
|
||||
|
||||
#ifndef DEFS_H
|
||||
#define DEFS_H
|
||||
|
||||
#ifdef FALSE
|
||||
#undef FALSE
|
||||
#endif
|
||||
#ifdef TRUE
|
||||
#undef TRUE
|
||||
#endif
|
||||
typedef enum { FALSE = 0, TRUE = 1 } Boolean;
|
||||
|
||||
|
||||
#define WPA_CIPHER_NONE BIT(0)
|
||||
#define WPA_CIPHER_WEP40 BIT(1)
|
||||
#define WPA_CIPHER_WEP104 BIT(2)
|
||||
#define WPA_CIPHER_TKIP BIT(3)
|
||||
#define WPA_CIPHER_CCMP BIT(4)
|
||||
#ifdef CONFIG_IEEE80211W
|
||||
#define WPA_CIPHER_AES_128_CMAC BIT(5)
|
||||
#endif /* CONFIG_IEEE80211W */
|
||||
|
||||
#define WPA_KEY_MGMT_IEEE8021X BIT(0)
|
||||
#define WPA_KEY_MGMT_PSK BIT(1)
|
||||
#define WPA_KEY_MGMT_NONE BIT(2)
|
||||
#define WPA_KEY_MGMT_IEEE8021X_NO_WPA BIT(3)
|
||||
#define WPA_KEY_MGMT_WPA_NONE BIT(4)
|
||||
#define WPA_KEY_MGMT_FT_IEEE8021X BIT(5)
|
||||
#define WPA_KEY_MGMT_FT_PSK BIT(6)
|
||||
#define WPA_KEY_MGMT_IEEE8021X_SHA256 BIT(7)
|
||||
#define WPA_KEY_MGMT_PSK_SHA256 BIT(8)
|
||||
#define WPA_KEY_MGMT_WPS BIT(9)
|
||||
|
||||
static inline int wpa_key_mgmt_wpa_ieee8021x(int akm)
|
||||
{
|
||||
return !!(akm & (WPA_KEY_MGMT_IEEE8021X |
|
||||
WPA_KEY_MGMT_FT_IEEE8021X |
|
||||
WPA_KEY_MGMT_IEEE8021X_SHA256));
|
||||
}
|
||||
|
||||
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));
|
||||
}
|
||||
|
||||
static inline int wpa_key_mgmt_ft(int akm)
|
||||
{
|
||||
return !!(akm & (WPA_KEY_MGMT_FT_PSK |
|
||||
WPA_KEY_MGMT_FT_IEEE8021X));
|
||||
}
|
||||
|
||||
static inline int wpa_key_mgmt_sha256(int akm)
|
||||
{
|
||||
return !!(akm & (WPA_KEY_MGMT_PSK_SHA256 |
|
||||
WPA_KEY_MGMT_IEEE8021X_SHA256));
|
||||
}
|
||||
|
||||
static inline int wpa_key_mgmt_wpa(int akm)
|
||||
{
|
||||
return wpa_key_mgmt_wpa_ieee8021x(akm) ||
|
||||
wpa_key_mgmt_wpa_psk(akm);
|
||||
}
|
||||
|
||||
|
||||
#define WPA_PROTO_WPA BIT(0)
|
||||
#define WPA_PROTO_RSN BIT(1)
|
||||
|
||||
#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)
|
||||
|
||||
|
||||
enum wpa_alg {
|
||||
WPA_ALG_NONE,
|
||||
WPA_ALG_WEP,
|
||||
WPA_ALG_TKIP,
|
||||
WPA_ALG_CCMP,
|
||||
WPA_ALG_IGTK,
|
||||
WPA_ALG_PMK
|
||||
};
|
||||
|
||||
/**
|
||||
* enum wpa_cipher - Cipher suites
|
||||
*/
|
||||
enum wpa_cipher {
|
||||
CIPHER_NONE,
|
||||
CIPHER_WEP40,
|
||||
CIPHER_TKIP,
|
||||
CIPHER_CCMP,
|
||||
CIPHER_WEP104
|
||||
};
|
||||
|
||||
/**
|
||||
* enum wpa_key_mgmt - Key management suites
|
||||
*/
|
||||
enum wpa_key_mgmt {
|
||||
KEY_MGMT_802_1X,
|
||||
KEY_MGMT_PSK,
|
||||
KEY_MGMT_NONE,
|
||||
KEY_MGMT_802_1X_NO_WPA,
|
||||
KEY_MGMT_WPA_NONE,
|
||||
KEY_MGMT_FT_802_1X,
|
||||
KEY_MGMT_FT_PSK,
|
||||
KEY_MGMT_802_1X_SHA256,
|
||||
KEY_MGMT_PSK_SHA256,
|
||||
KEY_MGMT_WPS
|
||||
};
|
||||
|
||||
/**
|
||||
* enum wpa_states - wpa_supplicant state
|
||||
*
|
||||
* These enumeration values are used to indicate the current wpa_supplicant
|
||||
* state (wpa_s->wpa_state). The current state can be retrieved with
|
||||
* wpa_supplicant_get_state() function and the state can be changed by calling
|
||||
* wpa_supplicant_set_state(). In WPA state machine (wpa.c and preauth.c), the
|
||||
* wrapper functions wpa_sm_get_state() and wpa_sm_set_state() should be used
|
||||
* to access the state variable.
|
||||
*/
|
||||
enum wpa_states {
|
||||
/**
|
||||
* WPA_DISCONNECTED - Disconnected state
|
||||
*
|
||||
* This state indicates that client is not associated, but is likely to
|
||||
* start looking for an access point. This state is entered when a
|
||||
* connection is lost.
|
||||
*/
|
||||
WPA_DISCONNECTED,
|
||||
|
||||
/**
|
||||
* WPA_INTERFACE_DISABLED - Interface disabled
|
||||
*
|
||||
* This stat eis entered if the network interface is disabled, e.g.,
|
||||
* due to rfkill. wpa_supplicant refuses any new operations that would
|
||||
* use the radio until the interface has been enabled.
|
||||
*/
|
||||
WPA_INTERFACE_DISABLED,
|
||||
|
||||
/**
|
||||
* WPA_INACTIVE - Inactive state (wpa_supplicant disabled)
|
||||
*
|
||||
* This state is entered if there are no enabled networks in the
|
||||
* configuration. wpa_supplicant is not trying to associate with a new
|
||||
* network and external interaction (e.g., ctrl_iface call to add or
|
||||
* enable a network) is needed to start association.
|
||||
*/
|
||||
WPA_INACTIVE,
|
||||
|
||||
/**
|
||||
* WPA_SCANNING - Scanning for a network
|
||||
*
|
||||
* This state is entered when wpa_supplicant starts scanning for a
|
||||
* network.
|
||||
*/
|
||||
WPA_SCANNING,
|
||||
|
||||
/**
|
||||
* WPA_AUTHENTICATING - Trying to authenticate with a BSS/SSID
|
||||
*
|
||||
* This state is entered when wpa_supplicant has found a suitable BSS
|
||||
* to authenticate with and the driver is configured to try to
|
||||
* authenticate with this BSS. This state is used only with drivers
|
||||
* that use wpa_supplicant as the SME.
|
||||
*/
|
||||
WPA_AUTHENTICATING,
|
||||
|
||||
/**
|
||||
* WPA_ASSOCIATING - Trying to associate with a BSS/SSID
|
||||
*
|
||||
* This state is entered when wpa_supplicant has found a suitable BSS
|
||||
* to associate with and the driver is configured to try to associate
|
||||
* with this BSS in ap_scan=1 mode. When using ap_scan=2 mode, this
|
||||
* state is entered when the driver is configured to try to associate
|
||||
* with a network using the configured SSID and security policy.
|
||||
*/
|
||||
WPA_ASSOCIATING,
|
||||
|
||||
/**
|
||||
* WPA_ASSOCIATED - Association completed
|
||||
*
|
||||
* This state is entered when the driver reports that association has
|
||||
* been successfully completed with an AP. If IEEE 802.1X is used
|
||||
* (with or without WPA/WPA2), wpa_supplicant remains in this state
|
||||
* until the IEEE 802.1X/EAPOL authentication has been completed.
|
||||
*/
|
||||
WPA_ASSOCIATED,
|
||||
|
||||
/**
|
||||
* WPA_4WAY_HANDSHAKE - WPA 4-Way Key Handshake in progress
|
||||
*
|
||||
* This state is entered when WPA/WPA2 4-Way Handshake is started. In
|
||||
* case of WPA-PSK, this happens when receiving the first EAPOL-Key
|
||||
* frame after association. In case of WPA-EAP, this state is entered
|
||||
* when the IEEE 802.1X/EAPOL authentication has been completed.
|
||||
*/
|
||||
WPA_4WAY_HANDSHAKE,
|
||||
|
||||
/**
|
||||
* WPA_GROUP_HANDSHAKE - WPA Group Key Handshake in progress
|
||||
*
|
||||
* This state is entered when 4-Way Key Handshake has been completed
|
||||
* (i.e., when the supplicant sends out message 4/4) and when Group
|
||||
* Key rekeying is started by the AP (i.e., when supplicant receives
|
||||
* message 1/2).
|
||||
*/
|
||||
WPA_GROUP_HANDSHAKE,
|
||||
|
||||
/**
|
||||
* WPA_COMPLETED - All authentication completed
|
||||
*
|
||||
* This state is entered when the full authentication process is
|
||||
* completed. In case of WPA2, this happens when the 4-Way Handshake is
|
||||
* successfully completed. With WPA, this state is entered after the
|
||||
* Group Key Handshake; with IEEE 802.1X (non-WPA) connection is
|
||||
* completed after dynamic keys are received (or if not used, after
|
||||
* the EAP authentication has been completed). With static WEP keys and
|
||||
* plaintext connections, this state is entered when an association
|
||||
* has been completed.
|
||||
*
|
||||
* This state indicates that the supplicant has completed its
|
||||
* processing for the association phase and that data connection is
|
||||
* fully configured.
|
||||
*/
|
||||
WPA_COMPLETED
|
||||
};
|
||||
|
||||
#define MLME_SETPROTECTION_PROTECT_TYPE_NONE 0
|
||||
#define MLME_SETPROTECTION_PROTECT_TYPE_RX 1
|
||||
#define MLME_SETPROTECTION_PROTECT_TYPE_TX 2
|
||||
#define MLME_SETPROTECTION_PROTECT_TYPE_RX_TX 3
|
||||
|
||||
#define MLME_SETPROTECTION_KEY_TYPE_GROUP 0
|
||||
#define MLME_SETPROTECTION_KEY_TYPE_PAIRWISE 1
|
||||
|
||||
|
||||
/**
|
||||
* enum mfp_options - Management frame protection (IEEE 802.11w) options
|
||||
*/
|
||||
enum mfp_options {
|
||||
NO_MGMT_FRAME_PROTECTION = 0,
|
||||
MGMT_FRAME_PROTECTION_OPTIONAL = 1,
|
||||
MGMT_FRAME_PROTECTION_REQUIRED = 2
|
||||
};
|
||||
|
||||
/**
|
||||
* enum hostapd_hw_mode - Hardware mode
|
||||
*/
|
||||
enum hostapd_hw_mode {
|
||||
HOSTAPD_MODE_IEEE80211B,
|
||||
HOSTAPD_MODE_IEEE80211G,
|
||||
HOSTAPD_MODE_IEEE80211A,
|
||||
NUM_HOSTAPD_MODES
|
||||
};
|
||||
|
||||
#endif /* DEFS_H */
|
47
hostapd-0.8/src/common/eapol_common.h
Normal file
47
hostapd-0.8/src/common/eapol_common.h
Normal file
|
@ -0,0 +1,47 @@
|
|||
/*
|
||||
* 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.
|
||||
*/
|
||||
|
||||
#ifndef EAPOL_COMMON_H
|
||||
#define EAPOL_COMMON_H
|
||||
|
||||
/* IEEE Std 802.1X-2004 */
|
||||
|
||||
#ifdef _MSC_VER
|
||||
#pragma pack(push, 1)
|
||||
#endif /* _MSC_VER */
|
||||
|
||||
struct ieee802_1x_hdr {
|
||||
u8 version;
|
||||
u8 type;
|
||||
be16 length;
|
||||
/* followed by length octets of data */
|
||||
} STRUCT_PACKED;
|
||||
|
||||
#ifdef _MSC_VER
|
||||
#pragma pack(pop)
|
||||
#endif /* _MSC_VER */
|
||||
|
||||
#define EAPOL_VERSION 2
|
||||
|
||||
enum { IEEE802_1X_TYPE_EAP_PACKET = 0,
|
||||
IEEE802_1X_TYPE_EAPOL_START = 1,
|
||||
IEEE802_1X_TYPE_EAPOL_LOGOFF = 2,
|
||||
IEEE802_1X_TYPE_EAPOL_KEY = 3,
|
||||
IEEE802_1X_TYPE_EAPOL_ENCAPSULATED_ASF_ALERT = 4
|
||||
};
|
||||
|
||||
enum { EAPOL_KEY_TYPE_RC4 = 1, EAPOL_KEY_TYPE_RSN = 2,
|
||||
EAPOL_KEY_TYPE_WPA = 254 };
|
||||
|
||||
#endif /* EAPOL_COMMON_H */
|
347
hostapd-0.8/src/common/ieee802_11_common.c
Normal file
347
hostapd-0.8/src/common/ieee802_11_common.c
Normal file
|
@ -0,0 +1,347 @@
|
|||
/*
|
||||
* IEEE 802.11 Common routines
|
||||
* 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.
|
||||
*/
|
||||
|
||||
#include "includes.h"
|
||||
|
||||
#include "common.h"
|
||||
#include "ieee802_11_defs.h"
|
||||
#include "ieee802_11_common.h"
|
||||
|
||||
|
||||
static int ieee802_11_parse_vendor_specific(const u8 *pos, size_t elen,
|
||||
struct ieee802_11_elems *elems,
|
||||
int show_errors)
|
||||
{
|
||||
unsigned int oui;
|
||||
|
||||
/* first 3 bytes in vendor specific information element are the IEEE
|
||||
* OUI of the vendor. The following byte is used a vendor specific
|
||||
* sub-type. */
|
||||
if (elen < 4) {
|
||||
if (show_errors) {
|
||||
wpa_printf(MSG_MSGDUMP, "short vendor specific "
|
||||
"information element ignored (len=%lu)",
|
||||
(unsigned long) elen);
|
||||
}
|
||||
return -1;
|
||||
}
|
||||
|
||||
oui = WPA_GET_BE24(pos);
|
||||
switch (oui) {
|
||||
case OUI_MICROSOFT:
|
||||
/* Microsoft/Wi-Fi information elements are further typed and
|
||||
* subtyped */
|
||||
switch (pos[3]) {
|
||||
case 1:
|
||||
/* Microsoft OUI (00:50:F2) with OUI Type 1:
|
||||
* real WPA information element */
|
||||
elems->wpa_ie = pos;
|
||||
elems->wpa_ie_len = elen;
|
||||
break;
|
||||
case WMM_OUI_TYPE:
|
||||
/* WMM information element */
|
||||
if (elen < 5) {
|
||||
wpa_printf(MSG_MSGDUMP, "short WMM "
|
||||
"information element ignored "
|
||||
"(len=%lu)",
|
||||
(unsigned long) elen);
|
||||
return -1;
|
||||
}
|
||||
switch (pos[4]) {
|
||||
case WMM_OUI_SUBTYPE_INFORMATION_ELEMENT:
|
||||
case WMM_OUI_SUBTYPE_PARAMETER_ELEMENT:
|
||||
/*
|
||||
* Share same pointer since only one of these
|
||||
* is used and they start with same data.
|
||||
* Length field can be used to distinguish the
|
||||
* IEs.
|
||||
*/
|
||||
elems->wmm = pos;
|
||||
elems->wmm_len = elen;
|
||||
break;
|
||||
case WMM_OUI_SUBTYPE_TSPEC_ELEMENT:
|
||||
elems->wmm_tspec = pos;
|
||||
elems->wmm_tspec_len = elen;
|
||||
break;
|
||||
default:
|
||||
wpa_printf(MSG_EXCESSIVE, "unknown WMM "
|
||||
"information element ignored "
|
||||
"(subtype=%d len=%lu)",
|
||||
pos[4], (unsigned long) elen);
|
||||
return -1;
|
||||
}
|
||||
break;
|
||||
case 4:
|
||||
/* Wi-Fi Protected Setup (WPS) IE */
|
||||
elems->wps_ie = pos;
|
||||
elems->wps_ie_len = elen;
|
||||
break;
|
||||
default:
|
||||
wpa_printf(MSG_EXCESSIVE, "Unknown Microsoft "
|
||||
"information element ignored "
|
||||
"(type=%d len=%lu)",
|
||||
pos[3], (unsigned long) elen);
|
||||
return -1;
|
||||
}
|
||||
break;
|
||||
|
||||
case OUI_WFA:
|
||||
switch (pos[3]) {
|
||||
case P2P_OUI_TYPE:
|
||||
/* Wi-Fi Alliance - P2P IE */
|
||||
elems->p2p = pos;
|
||||
elems->p2p_len = elen;
|
||||
break;
|
||||
default:
|
||||
wpa_printf(MSG_MSGDUMP, "Unknown WFA "
|
||||
"information element ignored "
|
||||
"(type=%d len=%lu)\n",
|
||||
pos[3], (unsigned long) elen);
|
||||
return -1;
|
||||
}
|
||||
break;
|
||||
|
||||
case OUI_BROADCOM:
|
||||
switch (pos[3]) {
|
||||
case VENDOR_HT_CAPAB_OUI_TYPE:
|
||||
elems->vendor_ht_cap = pos;
|
||||
elems->vendor_ht_cap_len = elen;
|
||||
break;
|
||||
default:
|
||||
wpa_printf(MSG_EXCESSIVE, "Unknown Broadcom "
|
||||
"information element ignored "
|
||||
"(type=%d len=%lu)",
|
||||
pos[3], (unsigned long) elen);
|
||||
return -1;
|
||||
}
|
||||
break;
|
||||
|
||||
default:
|
||||
wpa_printf(MSG_EXCESSIVE, "unknown vendor specific "
|
||||
"information element ignored (vendor OUI "
|
||||
"%02x:%02x:%02x len=%lu)",
|
||||
pos[0], pos[1], pos[2], (unsigned long) elen);
|
||||
return -1;
|
||||
}
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
|
||||
/**
|
||||
* ieee802_11_parse_elems - Parse information elements in management frames
|
||||
* @start: Pointer to the start of IEs
|
||||
* @len: Length of IE buffer in octets
|
||||
* @elems: Data structure for parsed elements
|
||||
* @show_errors: Whether to show parsing errors in debug log
|
||||
* Returns: Parsing result
|
||||
*/
|
||||
ParseRes ieee802_11_parse_elems(const u8 *start, size_t len,
|
||||
struct ieee802_11_elems *elems,
|
||||
int show_errors)
|
||||
{
|
||||
size_t left = len;
|
||||
const u8 *pos = start;
|
||||
int unknown = 0;
|
||||
|
||||
os_memset(elems, 0, sizeof(*elems));
|
||||
|
||||
while (left >= 2) {
|
||||
u8 id, elen;
|
||||
|
||||
id = *pos++;
|
||||
elen = *pos++;
|
||||
left -= 2;
|
||||
|
||||
if (elen > left) {
|
||||
if (show_errors) {
|
||||
wpa_printf(MSG_DEBUG, "IEEE 802.11 element "
|
||||
"parse failed (id=%d elen=%d "
|
||||
"left=%lu)",
|
||||
id, elen, (unsigned long) left);
|
||||
wpa_hexdump(MSG_MSGDUMP, "IEs", start, len);
|
||||
}
|
||||
return ParseFailed;
|
||||
}
|
||||
|
||||
switch (id) {
|
||||
case WLAN_EID_SSID:
|
||||
elems->ssid = pos;
|
||||
elems->ssid_len = elen;
|
||||
break;
|
||||
case WLAN_EID_SUPP_RATES:
|
||||
elems->supp_rates = pos;
|
||||
elems->supp_rates_len = elen;
|
||||
break;
|
||||
case WLAN_EID_FH_PARAMS:
|
||||
elems->fh_params = pos;
|
||||
elems->fh_params_len = elen;
|
||||
break;
|
||||
case WLAN_EID_DS_PARAMS:
|
||||
elems->ds_params = pos;
|
||||
elems->ds_params_len = elen;
|
||||
break;
|
||||
case WLAN_EID_CF_PARAMS:
|
||||
elems->cf_params = pos;
|
||||
elems->cf_params_len = elen;
|
||||
break;
|
||||
case WLAN_EID_TIM:
|
||||
elems->tim = pos;
|
||||
elems->tim_len = elen;
|
||||
break;
|
||||
case WLAN_EID_IBSS_PARAMS:
|
||||
elems->ibss_params = pos;
|
||||
elems->ibss_params_len = elen;
|
||||
break;
|
||||
case WLAN_EID_CHALLENGE:
|
||||
elems->challenge = pos;
|
||||
elems->challenge_len = elen;
|
||||
break;
|
||||
case WLAN_EID_ERP_INFO:
|
||||
elems->erp_info = pos;
|
||||
elems->erp_info_len = elen;
|
||||
break;
|
||||
case WLAN_EID_EXT_SUPP_RATES:
|
||||
elems->ext_supp_rates = pos;
|
||||
elems->ext_supp_rates_len = elen;
|
||||
break;
|
||||
case WLAN_EID_VENDOR_SPECIFIC:
|
||||
if (ieee802_11_parse_vendor_specific(pos, elen,
|
||||
elems,
|
||||
show_errors))
|
||||
unknown++;
|
||||
break;
|
||||
case WLAN_EID_RSN:
|
||||
elems->rsn_ie = pos;
|
||||
elems->rsn_ie_len = elen;
|
||||
break;
|
||||
case WLAN_EID_PWR_CAPABILITY:
|
||||
elems->power_cap = pos;
|
||||
elems->power_cap_len = elen;
|
||||
break;
|
||||
case WLAN_EID_SUPPORTED_CHANNELS:
|
||||
elems->supp_channels = pos;
|
||||
elems->supp_channels_len = elen;
|
||||
break;
|
||||
case WLAN_EID_MOBILITY_DOMAIN:
|
||||
elems->mdie = pos;
|
||||
elems->mdie_len = elen;
|
||||
break;
|
||||
case WLAN_EID_FAST_BSS_TRANSITION:
|
||||
elems->ftie = pos;
|
||||
elems->ftie_len = elen;
|
||||
break;
|
||||
case WLAN_EID_TIMEOUT_INTERVAL:
|
||||
elems->timeout_int = pos;
|
||||
elems->timeout_int_len = elen;
|
||||
break;
|
||||
case WLAN_EID_HT_CAP:
|
||||
elems->ht_capabilities = pos;
|
||||
elems->ht_capabilities_len = elen;
|
||||
break;
|
||||
case WLAN_EID_HT_OPERATION:
|
||||
elems->ht_operation = pos;
|
||||
elems->ht_operation_len = elen;
|
||||
break;
|
||||
case WLAN_EID_LINK_ID:
|
||||
if (elen < 18)
|
||||
break;
|
||||
elems->link_id = pos;
|
||||
break;
|
||||
default:
|
||||
unknown++;
|
||||
if (!show_errors)
|
||||
break;
|
||||
wpa_printf(MSG_MSGDUMP, "IEEE 802.11 element parse "
|
||||
"ignored unknown element (id=%d elen=%d)",
|
||||
id, elen);
|
||||
break;
|
||||
}
|
||||
|
||||
left -= elen;
|
||||
pos += elen;
|
||||
}
|
||||
|
||||
if (left)
|
||||
return ParseFailed;
|
||||
|
||||
return unknown ? ParseUnknown : ParseOK;
|
||||
}
|
||||
|
||||
|
||||
int ieee802_11_ie_count(const u8 *ies, size_t ies_len)
|
||||
{
|
||||
int count = 0;
|
||||
const u8 *pos, *end;
|
||||
|
||||
if (ies == NULL)
|
||||
return 0;
|
||||
|
||||
pos = ies;
|
||||
end = ies + ies_len;
|
||||
|
||||
while (pos + 2 <= end) {
|
||||
if (pos + 2 + pos[1] > end)
|
||||
break;
|
||||
count++;
|
||||
pos += 2 + pos[1];
|
||||
}
|
||||
|
||||
return count;
|
||||
}
|
||||
|
||||
|
||||
struct wpabuf * ieee802_11_vendor_ie_concat(const u8 *ies, size_t ies_len,
|
||||
u32 oui_type)
|
||||
{
|
||||
struct wpabuf *buf;
|
||||
const u8 *end, *pos, *ie;
|
||||
|
||||
pos = ies;
|
||||
end = ies + ies_len;
|
||||
ie = NULL;
|
||||
|
||||
while (pos + 1 < end) {
|
||||
if (pos + 2 + pos[1] > end)
|
||||
return NULL;
|
||||
if (pos[0] == WLAN_EID_VENDOR_SPECIFIC && pos[1] >= 4 &&
|
||||
WPA_GET_BE32(&pos[2]) == oui_type) {
|
||||
ie = pos;
|
||||
break;
|
||||
}
|
||||
pos += 2 + pos[1];
|
||||
}
|
||||
|
||||
if (ie == NULL)
|
||||
return NULL; /* No specified vendor IE found */
|
||||
|
||||
buf = wpabuf_alloc(ies_len);
|
||||
if (buf == NULL)
|
||||
return NULL;
|
||||
|
||||
/*
|
||||
* There may be multiple vendor IEs in the message, so need to
|
||||
* concatenate their data fields.
|
||||
*/
|
||||
while (pos + 1 < end) {
|
||||
if (pos + 2 + pos[1] > end)
|
||||
break;
|
||||
if (pos[0] == WLAN_EID_VENDOR_SPECIFIC && pos[1] >= 4 &&
|
||||
WPA_GET_BE32(&pos[2]) == oui_type)
|
||||
wpabuf_put_data(buf, pos + 6, pos[1] - 4);
|
||||
pos += 2 + pos[1];
|
||||
}
|
||||
|
||||
return buf;
|
||||
}
|
81
hostapd-0.8/src/common/ieee802_11_common.h
Normal file
81
hostapd-0.8/src/common/ieee802_11_common.h
Normal file
|
@ -0,0 +1,81 @@
|
|||
/*
|
||||
* IEEE 802.11 Common routines
|
||||
* 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.
|
||||
*/
|
||||
|
||||
#ifndef IEEE802_11_COMMON_H
|
||||
#define IEEE802_11_COMMON_H
|
||||
|
||||
/* Parsed Information Elements */
|
||||
struct ieee802_11_elems {
|
||||
const u8 *ssid;
|
||||
const u8 *supp_rates;
|
||||
const u8 *fh_params;
|
||||
const u8 *ds_params;
|
||||
const u8 *cf_params;
|
||||
const u8 *tim;
|
||||
const u8 *ibss_params;
|
||||
const u8 *challenge;
|
||||
const u8 *erp_info;
|
||||
const u8 *ext_supp_rates;
|
||||
const u8 *wpa_ie;
|
||||
const u8 *rsn_ie;
|
||||
const u8 *wmm; /* WMM Information or Parameter Element */
|
||||
const u8 *wmm_tspec;
|
||||
const u8 *wps_ie;
|
||||
const u8 *power_cap;
|
||||
const u8 *supp_channels;
|
||||
const u8 *mdie;
|
||||
const u8 *ftie;
|
||||
const u8 *timeout_int;
|
||||
const u8 *ht_capabilities;
|
||||
const u8 *ht_operation;
|
||||
const u8 *vendor_ht_cap;
|
||||
const u8 *p2p;
|
||||
const u8 *link_id;
|
||||
|
||||
u8 ssid_len;
|
||||
u8 supp_rates_len;
|
||||
u8 fh_params_len;
|
||||
u8 ds_params_len;
|
||||
u8 cf_params_len;
|
||||
u8 tim_len;
|
||||
u8 ibss_params_len;
|
||||
u8 challenge_len;
|
||||
u8 erp_info_len;
|
||||
u8 ext_supp_rates_len;
|
||||
u8 wpa_ie_len;
|
||||
u8 rsn_ie_len;
|
||||
u8 wmm_len; /* 7 = WMM Information; 24 = WMM Parameter */
|
||||
u8 wmm_tspec_len;
|
||||
u8 wps_ie_len;
|
||||
u8 power_cap_len;
|
||||
u8 supp_channels_len;
|
||||
u8 mdie_len;
|
||||
u8 ftie_len;
|
||||
u8 timeout_int_len;
|
||||
u8 ht_capabilities_len;
|
||||
u8 ht_operation_len;
|
||||
u8 vendor_ht_cap_len;
|
||||
u8 p2p_len;
|
||||
};
|
||||
|
||||
typedef enum { ParseOK = 0, ParseUnknown = 1, ParseFailed = -1 } ParseRes;
|
||||
|
||||
ParseRes ieee802_11_parse_elems(const u8 *start, size_t len,
|
||||
struct ieee802_11_elems *elems,
|
||||
int show_errors);
|
||||
int ieee802_11_ie_count(const u8 *ies, size_t ies_len);
|
||||
struct wpabuf * ieee802_11_vendor_ie_concat(const u8 *ies, size_t ies_len,
|
||||
u32 oui_type);
|
||||
|
||||
#endif /* IEEE802_11_COMMON_H */
|
800
hostapd-0.8/src/common/ieee802_11_defs.h
Normal file
800
hostapd-0.8/src/common/ieee802_11_defs.h
Normal file
|
@ -0,0 +1,800 @@
|
|||
/*
|
||||
* IEEE 802.11 Frame type definitions
|
||||
* 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.
|
||||
*/
|
||||
|
||||
#ifndef IEEE802_11_DEFS_H
|
||||
#define IEEE802_11_DEFS_H
|
||||
|
||||
/* IEEE 802.11 defines */
|
||||
|
||||
#define WLAN_FC_PVER 0x0003
|
||||
#define WLAN_FC_TODS 0x0100
|
||||
#define WLAN_FC_FROMDS 0x0200
|
||||
#define WLAN_FC_MOREFRAG 0x0400
|
||||
#define WLAN_FC_RETRY 0x0800
|
||||
#define WLAN_FC_PWRMGT 0x1000
|
||||
#define WLAN_FC_MOREDATA 0x2000
|
||||
#define WLAN_FC_ISWEP 0x4000
|
||||
#define WLAN_FC_ORDER 0x8000
|
||||
|
||||
#define WLAN_FC_GET_TYPE(fc) (((fc) & 0x000c) >> 2)
|
||||
#define WLAN_FC_GET_STYPE(fc) (((fc) & 0x00f0) >> 4)
|
||||
|
||||
#define WLAN_GET_SEQ_FRAG(seq) ((seq) & (BIT(3) | BIT(2) | BIT(1) | BIT(0)))
|
||||
#define WLAN_GET_SEQ_SEQ(seq) \
|
||||
(((seq) & (~(BIT(3) | BIT(2) | BIT(1) | BIT(0)))) >> 4)
|
||||
|
||||
#define WLAN_FC_TYPE_MGMT 0
|
||||
#define WLAN_FC_TYPE_CTRL 1
|
||||
#define WLAN_FC_TYPE_DATA 2
|
||||
|
||||
/* management */
|
||||
#define WLAN_FC_STYPE_ASSOC_REQ 0
|
||||
#define WLAN_FC_STYPE_ASSOC_RESP 1
|
||||
#define WLAN_FC_STYPE_REASSOC_REQ 2
|
||||
#define WLAN_FC_STYPE_REASSOC_RESP 3
|
||||
#define WLAN_FC_STYPE_PROBE_REQ 4
|
||||
#define WLAN_FC_STYPE_PROBE_RESP 5
|
||||
#define WLAN_FC_STYPE_BEACON 8
|
||||
#define WLAN_FC_STYPE_ATIM 9
|
||||
#define WLAN_FC_STYPE_DISASSOC 10
|
||||
#define WLAN_FC_STYPE_AUTH 11
|
||||
#define WLAN_FC_STYPE_DEAUTH 12
|
||||
#define WLAN_FC_STYPE_ACTION 13
|
||||
|
||||
/* control */
|
||||
#define WLAN_FC_STYPE_PSPOLL 10
|
||||
#define WLAN_FC_STYPE_RTS 11
|
||||
#define WLAN_FC_STYPE_CTS 12
|
||||
#define WLAN_FC_STYPE_ACK 13
|
||||
#define WLAN_FC_STYPE_CFEND 14
|
||||
#define WLAN_FC_STYPE_CFENDACK 15
|
||||
|
||||
/* data */
|
||||
#define WLAN_FC_STYPE_DATA 0
|
||||
#define WLAN_FC_STYPE_DATA_CFACK 1
|
||||
#define WLAN_FC_STYPE_DATA_CFPOLL 2
|
||||
#define WLAN_FC_STYPE_DATA_CFACKPOLL 3
|
||||
#define WLAN_FC_STYPE_NULLFUNC 4
|
||||
#define WLAN_FC_STYPE_CFACK 5
|
||||
#define WLAN_FC_STYPE_CFPOLL 6
|
||||
#define WLAN_FC_STYPE_CFACKPOLL 7
|
||||
#define WLAN_FC_STYPE_QOS_DATA 8
|
||||
#define WLAN_FC_STYPE_QOS_DATA_CFACK 9
|
||||
#define WLAN_FC_STYPE_QOS_DATA_CFPOLL 10
|
||||
#define WLAN_FC_STYPE_QOS_DATA_CFACKPOLL 11
|
||||
#define WLAN_FC_STYPE_QOS_NULL 12
|
||||
#define WLAN_FC_STYPE_QOS_CFPOLL 14
|
||||
#define WLAN_FC_STYPE_QOS_CFACKPOLL 15
|
||||
|
||||
/* Authentication algorithms */
|
||||
#define WLAN_AUTH_OPEN 0
|
||||
#define WLAN_AUTH_SHARED_KEY 1
|
||||
#define WLAN_AUTH_FT 2
|
||||
#define WLAN_AUTH_LEAP 128
|
||||
|
||||
#define WLAN_AUTH_CHALLENGE_LEN 128
|
||||
|
||||
#define WLAN_CAPABILITY_ESS BIT(0)
|
||||
#define WLAN_CAPABILITY_IBSS BIT(1)
|
||||
#define WLAN_CAPABILITY_CF_POLLABLE BIT(2)
|
||||
#define WLAN_CAPABILITY_CF_POLL_REQUEST BIT(3)
|
||||
#define WLAN_CAPABILITY_PRIVACY BIT(4)
|
||||
#define WLAN_CAPABILITY_SHORT_PREAMBLE BIT(5)
|
||||
#define WLAN_CAPABILITY_PBCC BIT(6)
|
||||
#define WLAN_CAPABILITY_CHANNEL_AGILITY BIT(7)
|
||||
#define WLAN_CAPABILITY_SPECTRUM_MGMT BIT(8)
|
||||
#define WLAN_CAPABILITY_SHORT_SLOT_TIME BIT(10)
|
||||
#define WLAN_CAPABILITY_DSSS_OFDM BIT(13)
|
||||
|
||||
/* Status codes (IEEE 802.11-2007, 7.3.1.9, Table 7-23) */
|
||||
#define WLAN_STATUS_SUCCESS 0
|
||||
#define WLAN_STATUS_UNSPECIFIED_FAILURE 1
|
||||
#define WLAN_STATUS_TDLS_WAKEUP_ALTERNATE 2
|
||||
#define WLAN_STATUS_TDLS_WAKEUP_REJECT 3
|
||||
#define WLAN_STATUS_SECURITY_DISABLED 5
|
||||
#define WLAN_STATUS_UNACCEPTABLE_LIFETIME 6
|
||||
#define WLAN_STATUS_NOT_IN_SAME_BSS 7
|
||||
#define WLAN_STATUS_CAPS_UNSUPPORTED 10
|
||||
#define WLAN_STATUS_REASSOC_NO_ASSOC 11
|
||||
#define WLAN_STATUS_ASSOC_DENIED_UNSPEC 12
|
||||
#define WLAN_STATUS_NOT_SUPPORTED_AUTH_ALG 13
|
||||
#define WLAN_STATUS_UNKNOWN_AUTH_TRANSACTION 14
|
||||
#define WLAN_STATUS_CHALLENGE_FAIL 15
|
||||
#define WLAN_STATUS_AUTH_TIMEOUT 16
|
||||
#define WLAN_STATUS_AP_UNABLE_TO_HANDLE_NEW_STA 17
|
||||
#define WLAN_STATUS_ASSOC_DENIED_RATES 18
|
||||
/* IEEE 802.11b */
|
||||
#define WLAN_STATUS_ASSOC_DENIED_NOSHORT 19
|
||||
#define WLAN_STATUS_ASSOC_DENIED_NOPBCC 20
|
||||
#define WLAN_STATUS_ASSOC_DENIED_NOAGILITY 21
|
||||
/* IEEE 802.11h */
|
||||
#define WLAN_STATUS_SPEC_MGMT_REQUIRED 22
|
||||
#define WLAN_STATUS_PWR_CAPABILITY_NOT_VALID 23
|
||||
#define WLAN_STATUS_SUPPORTED_CHANNEL_NOT_VALID 24
|
||||
/* IEEE 802.11g */
|
||||
#define WLAN_STATUS_ASSOC_DENIED_NO_SHORT_SLOT_TIME 25
|
||||
#define WLAN_STATUS_ASSOC_DENIED_NO_DSSS_OFDM 26
|
||||
#define WLAN_STATUS_ASSOC_DENIED_NO_HT 27
|
||||
#define WLAN_STATUS_R0KH_UNREACHABLE 28
|
||||
#define WLAN_STATUS_ASSOC_DENIED_NO_PCO 29
|
||||
/* IEEE 802.11w */
|
||||
#define WLAN_STATUS_ASSOC_REJECTED_TEMPORARILY 30
|
||||
#define WLAN_STATUS_ROBUST_MGMT_FRAME_POLICY_VIOLATION 31
|
||||
#define WLAN_STATUS_UNSPECIFIED_QOS_FAILURE 32
|
||||
#define WLAN_STATUS_REQUEST_DECLINED 37
|
||||
#define WLAN_STATUS_INVALID_PARAMETERS 38
|
||||
/* IEEE 802.11i */
|
||||
#define WLAN_STATUS_INVALID_IE 40
|
||||
#define WLAN_STATUS_GROUP_CIPHER_NOT_VALID 41
|
||||
#define WLAN_STATUS_PAIRWISE_CIPHER_NOT_VALID 42
|
||||
#define WLAN_STATUS_AKMP_NOT_VALID 43
|
||||
#define WLAN_STATUS_UNSUPPORTED_RSN_IE_VERSION 44
|
||||
#define WLAN_STATUS_INVALID_RSN_IE_CAPAB 45
|
||||
#define WLAN_STATUS_CIPHER_REJECTED_PER_POLICY 46
|
||||
#define WLAN_STATUS_TS_NOT_CREATED 47
|
||||
#define WLAN_STATUS_DIRECT_LINK_NOT_ALLOWED 48
|
||||
#define WLAN_STATUS_DEST_STA_NOT_PRESENT 49
|
||||
#define WLAN_STATUS_DEST_STA_NOT_QOS_STA 50
|
||||
#define WLAN_STATUS_ASSOC_DENIED_LISTEN_INT_TOO_LARGE 51
|
||||
/* IEEE 802.11r */
|
||||
#define WLAN_STATUS_INVALID_FT_ACTION_FRAME_COUNT 52
|
||||
#define WLAN_STATUS_INVALID_PMKID 53
|
||||
#define WLAN_STATUS_INVALID_MDIE 54
|
||||
#define WLAN_STATUS_INVALID_FTIE 55
|
||||
#define WLAN_STATUS_INVALID_RSNIE 72
|
||||
|
||||
/* Reason codes (IEEE 802.11-2007, 7.3.1.7, Table 7-22) */
|
||||
#define WLAN_REASON_UNSPECIFIED 1
|
||||
#define WLAN_REASON_PREV_AUTH_NOT_VALID 2
|
||||
#define WLAN_REASON_DEAUTH_LEAVING 3
|
||||
#define WLAN_REASON_DISASSOC_DUE_TO_INACTIVITY 4
|
||||
#define WLAN_REASON_DISASSOC_AP_BUSY 5
|
||||
#define WLAN_REASON_CLASS2_FRAME_FROM_NONAUTH_STA 6
|
||||
#define WLAN_REASON_CLASS3_FRAME_FROM_NONASSOC_STA 7
|
||||
#define WLAN_REASON_DISASSOC_STA_HAS_LEFT 8
|
||||
#define WLAN_REASON_STA_REQ_ASSOC_WITHOUT_AUTH 9
|
||||
/* IEEE 802.11h */
|
||||
#define WLAN_REASON_PWR_CAPABILITY_NOT_VALID 10
|
||||
#define WLAN_REASON_SUPPORTED_CHANNEL_NOT_VALID 11
|
||||
/* IEEE 802.11i */
|
||||
#define WLAN_REASON_INVALID_IE 13
|
||||
#define WLAN_REASON_MICHAEL_MIC_FAILURE 14
|
||||
#define WLAN_REASON_4WAY_HANDSHAKE_TIMEOUT 15
|
||||
#define WLAN_REASON_GROUP_KEY_UPDATE_TIMEOUT 16
|
||||
#define WLAN_REASON_IE_IN_4WAY_DIFFERS 17
|
||||
#define WLAN_REASON_GROUP_CIPHER_NOT_VALID 18
|
||||
#define WLAN_REASON_PAIRWISE_CIPHER_NOT_VALID 19
|
||||
#define WLAN_REASON_AKMP_NOT_VALID 20
|
||||
#define WLAN_REASON_UNSUPPORTED_RSN_IE_VERSION 21
|
||||
#define WLAN_REASON_INVALID_RSN_IE_CAPAB 22
|
||||
#define WLAN_REASON_IEEE_802_1X_AUTH_FAILED 23
|
||||
#define WLAN_REASON_CIPHER_SUITE_REJECTED 24
|
||||
#define WLAN_REASON_TDLS_TEARDOWN_UNREACHABLE 25
|
||||
#define WLAN_REASON_TDLS_TEARDOWN_UNSPECIFIED 26
|
||||
/* IEEE 802.11e */
|
||||
#define WLAN_REASON_DISASSOC_LOW_ACK 34
|
||||
|
||||
|
||||
/* Information Element IDs */
|
||||
#define WLAN_EID_SSID 0
|
||||
#define WLAN_EID_SUPP_RATES 1
|
||||
#define WLAN_EID_FH_PARAMS 2
|
||||
#define WLAN_EID_DS_PARAMS 3
|
||||
#define WLAN_EID_CF_PARAMS 4
|
||||
#define WLAN_EID_TIM 5
|
||||
#define WLAN_EID_IBSS_PARAMS 6
|
||||
#define WLAN_EID_COUNTRY 7
|
||||
#define WLAN_EID_CHALLENGE 16
|
||||
/* EIDs defined by IEEE 802.11h - START */
|
||||
#define WLAN_EID_PWR_CONSTRAINT 32
|
||||
#define WLAN_EID_PWR_CAPABILITY 33
|
||||
#define WLAN_EID_TPC_REQUEST 34
|
||||
#define WLAN_EID_TPC_REPORT 35
|
||||
#define WLAN_EID_SUPPORTED_CHANNELS 36
|
||||
#define WLAN_EID_CHANNEL_SWITCH 37
|
||||
#define WLAN_EID_MEASURE_REQUEST 38
|
||||
#define WLAN_EID_MEASURE_REPORT 39
|
||||
#define WLAN_EID_QUITE 40
|
||||
#define WLAN_EID_IBSS_DFS 41
|
||||
/* EIDs defined by IEEE 802.11h - END */
|
||||
#define WLAN_EID_ERP_INFO 42
|
||||
#define WLAN_EID_HT_CAP 45
|
||||
#define WLAN_EID_RSN 48
|
||||
#define WLAN_EID_EXT_SUPP_RATES 50
|
||||
#define WLAN_EID_MOBILITY_DOMAIN 54
|
||||
#define WLAN_EID_FAST_BSS_TRANSITION 55
|
||||
#define WLAN_EID_TIMEOUT_INTERVAL 56
|
||||
#define WLAN_EID_RIC_DATA 57
|
||||
#define WLAN_EID_HT_OPERATION 61
|
||||
#define WLAN_EID_SECONDARY_CHANNEL_OFFSET 62
|
||||
#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_LINK_ID 101
|
||||
#define WLAN_EID_ADV_PROTO 108
|
||||
#define WLAN_EID_EXT_CAPAB 127
|
||||
#define WLAN_EID_VENDOR_SPECIFIC 221
|
||||
|
||||
|
||||
/* Action frame categories (IEEE 802.11-2007, 7.3.1.11, Table 7-24) */
|
||||
#define WLAN_ACTION_SPECTRUM_MGMT 0
|
||||
#define WLAN_ACTION_QOS 1
|
||||
#define WLAN_ACTION_DLS 2
|
||||
#define WLAN_ACTION_BLOCK_ACK 3
|
||||
#define WLAN_ACTION_PUBLIC 4
|
||||
#define WLAN_ACTION_RADIO_MEASUREMENT 5
|
||||
#define WLAN_ACTION_FT 6
|
||||
#define WLAN_ACTION_HT 7
|
||||
#define WLAN_ACTION_SA_QUERY 8
|
||||
#define WLAN_ACTION_TDLS 12
|
||||
#define WLAN_ACTION_WMM 17 /* WMM Specification 1.1 */
|
||||
#define WLAN_ACTION_VENDOR_SPECIFIC 127
|
||||
|
||||
/* Public action codes */
|
||||
#define WLAN_PA_VENDOR_SPECIFIC 9
|
||||
#define WLAN_PA_GAS_INITIAL_REQ 10
|
||||
#define WLAN_PA_GAS_INITIAL_RESP 11
|
||||
#define WLAN_PA_GAS_COMEBACK_REQ 12
|
||||
#define WLAN_PA_GAS_COMEBACK_RESP 13
|
||||
|
||||
/* SA Query Action frame (IEEE 802.11w/D8.0, 7.4.9) */
|
||||
#define WLAN_SA_QUERY_REQUEST 0
|
||||
#define WLAN_SA_QUERY_RESPONSE 1
|
||||
|
||||
#define WLAN_SA_QUERY_TR_ID_LEN 2
|
||||
|
||||
/* TDLS action codes */
|
||||
#define WLAN_TDLS_SETUP_REQUEST 0
|
||||
#define WLAN_TDLS_SETUP_RESPONSE 1
|
||||
#define WLAN_TDLS_SETUP_CONFIRM 2
|
||||
#define WLAN_TDLS_TEARDOWN 3
|
||||
#define WLAN_TDLS_PEER_TRAFFIC_INDICATION 4
|
||||
#define WLAN_TDLS_CHANNEL_SWITCH_REQUEST 5
|
||||
#define WLAN_TDLS_CHANNEL_SWITCH_RESPONSE 6
|
||||
#define WLAN_TDLS_PEER_PSM_REQUEST 7
|
||||
#define WLAN_TDLS_PEER_PSM_RESPONSE 8
|
||||
#define WLAN_TDLS_PEER_TRAFFIC_RESPONSE 9
|
||||
#define WLAN_TDLS_DISCOVERY_REQUEST 10
|
||||
|
||||
/* Timeout Interval Type */
|
||||
#define WLAN_TIMEOUT_REASSOC_DEADLINE 1
|
||||
#define WLAN_TIMEOUT_KEY_LIFETIME 2
|
||||
#define WLAN_TIMEOUT_ASSOC_COMEBACK 3
|
||||
|
||||
/* Advertisement Protocol ID definitions (IEEE 802.11u) */
|
||||
enum adv_proto_id {
|
||||
NATIVE_QUERY_PROTOCOL = 0,
|
||||
MIH_INFO_SERVICE = 1,
|
||||
MIH_CMD_AND_EVENT_DISCOVERY = 2,
|
||||
EMERGENCY_ALERT_SYSTEM = 3,
|
||||
LOCATION_TO_SERVICE = 4,
|
||||
ADV_PROTO_VENDOR_SPECIFIC = 221
|
||||
};
|
||||
|
||||
/* Native Query Protocol info ID definitions (IEEE 802.11u) */
|
||||
enum nqp_info_id {
|
||||
NQP_CAPABILITY_LIST = 256,
|
||||
NQP_VENUE_NAME = 257,
|
||||
NQP_EMERGENCY_CALL_NUMBER = 258,
|
||||
NQP_NETWORK_AUTH_TYPE = 259,
|
||||
NQP_ROAMING_CONSORTIUM = 260,
|
||||
NQP_IP_ADDR_TYPE_AVAILABILITY = 261,
|
||||
NQP_NAI_REALM = 262,
|
||||
NQP_3GPP_CELLULAR_NETWORK = 263,
|
||||
NQP_AP_GEOSPATIAL_LOCATION = 264,
|
||||
NQP_AP_CIVIC_LOCATION = 265,
|
||||
NQP_DOMAIN_NAME = 266,
|
||||
NQP_EMERGENCY_ALERT_URI = 267,
|
||||
NQP_VENDOR_SPECIFIC = 56797
|
||||
};
|
||||
|
||||
|
||||
#ifdef _MSC_VER
|
||||
#pragma pack(push, 1)
|
||||
#endif /* _MSC_VER */
|
||||
|
||||
struct ieee80211_hdr {
|
||||
le16 frame_control;
|
||||
le16 duration_id;
|
||||
u8 addr1[6];
|
||||
u8 addr2[6];
|
||||
u8 addr3[6];
|
||||
le16 seq_ctrl;
|
||||
/* followed by 'u8 addr4[6];' if ToDS and FromDS is set in data frame
|
||||
*/
|
||||
} STRUCT_PACKED;
|
||||
|
||||
#define IEEE80211_DA_FROMDS addr1
|
||||
#define IEEE80211_BSSID_FROMDS addr2
|
||||
#define IEEE80211_SA_FROMDS addr3
|
||||
|
||||
#define IEEE80211_HDRLEN (sizeof(struct ieee80211_hdr))
|
||||
|
||||
#define IEEE80211_FC(type, stype) host_to_le16((type << 2) | (stype << 4))
|
||||
|
||||
struct ieee80211_mgmt {
|
||||
le16 frame_control;
|
||||
le16 duration;
|
||||
u8 da[6];
|
||||
u8 sa[6];
|
||||
u8 bssid[6];
|
||||
le16 seq_ctrl;
|
||||
union {
|
||||
struct {
|
||||
le16 auth_alg;
|
||||
le16 auth_transaction;
|
||||
le16 status_code;
|
||||
/* possibly followed by Challenge text */
|
||||
u8 variable[0];
|
||||
} STRUCT_PACKED auth;
|
||||
struct {
|
||||
le16 reason_code;
|
||||
u8 variable[0];
|
||||
} STRUCT_PACKED deauth;
|
||||
struct {
|
||||
le16 capab_info;
|
||||
le16 listen_interval;
|
||||
/* followed by SSID and Supported rates */
|
||||
u8 variable[0];
|
||||
} STRUCT_PACKED assoc_req;
|
||||
struct {
|
||||
le16 capab_info;
|
||||
le16 status_code;
|
||||
le16 aid;
|
||||
/* followed by Supported rates */
|
||||
u8 variable[0];
|
||||
} STRUCT_PACKED assoc_resp, reassoc_resp;
|
||||
struct {
|
||||
le16 capab_info;
|
||||
le16 listen_interval;
|
||||
u8 current_ap[6];
|
||||
/* followed by SSID and Supported rates */
|
||||
u8 variable[0];
|
||||
} STRUCT_PACKED reassoc_req;
|
||||
struct {
|
||||
le16 reason_code;
|
||||
u8 variable[0];
|
||||
} STRUCT_PACKED disassoc;
|
||||
struct {
|
||||
u8 timestamp[8];
|
||||
le16 beacon_int;
|
||||
le16 capab_info;
|
||||
/* followed by some of SSID, Supported rates,
|
||||
* FH Params, DS Params, CF Params, IBSS Params, TIM */
|
||||
u8 variable[0];
|
||||
} STRUCT_PACKED beacon;
|
||||
struct {
|
||||
/* only variable items: SSID, Supported rates */
|
||||
u8 variable[0];
|
||||
} STRUCT_PACKED probe_req;
|
||||
struct {
|
||||
u8 timestamp[8];
|
||||
le16 beacon_int;
|
||||
le16 capab_info;
|
||||
/* followed by some of SSID, Supported rates,
|
||||
* FH Params, DS Params, CF Params, IBSS Params */
|
||||
u8 variable[0];
|
||||
} STRUCT_PACKED probe_resp;
|
||||
struct {
|
||||
u8 category;
|
||||
union {
|
||||
struct {
|
||||
u8 action_code;
|
||||
u8 dialog_token;
|
||||
u8 status_code;
|
||||
u8 variable[0];
|
||||
} STRUCT_PACKED wmm_action;
|
||||
struct{
|
||||
u8 action_code;
|
||||
u8 element_id;
|
||||
u8 length;
|
||||
u8 switch_mode;
|
||||
u8 new_chan;
|
||||
u8 switch_count;
|
||||
} STRUCT_PACKED chan_switch;
|
||||
struct {
|
||||
u8 action;
|
||||
u8 sta_addr[ETH_ALEN];
|
||||
u8 target_ap_addr[ETH_ALEN];
|
||||
u8 variable[0]; /* FT Request */
|
||||
} STRUCT_PACKED ft_action_req;
|
||||
struct {
|
||||
u8 action;
|
||||
u8 sta_addr[ETH_ALEN];
|
||||
u8 target_ap_addr[ETH_ALEN];
|
||||
le16 status_code;
|
||||
u8 variable[0]; /* FT Request */
|
||||
} STRUCT_PACKED ft_action_resp;
|
||||
struct {
|
||||
u8 action;
|
||||
u8 trans_id[WLAN_SA_QUERY_TR_ID_LEN];
|
||||
} STRUCT_PACKED sa_query_req;
|
||||
struct {
|
||||
u8 action; /* */
|
||||
u8 trans_id[WLAN_SA_QUERY_TR_ID_LEN];
|
||||
} STRUCT_PACKED sa_query_resp;
|
||||
struct {
|
||||
u8 action;
|
||||
u8 variable[0];
|
||||
} STRUCT_PACKED public_action;
|
||||
struct {
|
||||
u8 action; /* 9 */
|
||||
u8 oui[3];
|
||||
/* Vendor-specific content */
|
||||
u8 variable[0];
|
||||
} STRUCT_PACKED vs_public_action;
|
||||
} u;
|
||||
} STRUCT_PACKED action;
|
||||
} u;
|
||||
} STRUCT_PACKED;
|
||||
|
||||
|
||||
struct ieee80211_ht_capabilities {
|
||||
le16 ht_capabilities_info;
|
||||
u8 a_mpdu_params;
|
||||
u8 supported_mcs_set[16];
|
||||
le16 ht_extended_capabilities;
|
||||
le32 tx_bf_capability_info;
|
||||
u8 asel_capabilities;
|
||||
} STRUCT_PACKED;
|
||||
|
||||
|
||||
struct ieee80211_ht_operation {
|
||||
u8 control_chan;
|
||||
u8 ht_param;
|
||||
le16 operation_mode;
|
||||
le16 stbc_param;
|
||||
u8 basic_set[16];
|
||||
} STRUCT_PACKED;
|
||||
|
||||
#ifdef _MSC_VER
|
||||
#pragma pack(pop)
|
||||
#endif /* _MSC_VER */
|
||||
|
||||
#define ERP_INFO_NON_ERP_PRESENT BIT(0)
|
||||
#define ERP_INFO_USE_PROTECTION BIT(1)
|
||||
#define ERP_INFO_BARKER_PREAMBLE_MODE BIT(2)
|
||||
|
||||
|
||||
#define HT_CAP_INFO_LDPC_CODING_CAP ((u16) BIT(0))
|
||||
#define HT_CAP_INFO_SUPP_CHANNEL_WIDTH_SET ((u16) BIT(1))
|
||||
#define HT_CAP_INFO_SMPS_MASK ((u16) (BIT(2) | BIT(3)))
|
||||
#define HT_CAP_INFO_SMPS_STATIC ((u16) 0)
|
||||
#define HT_CAP_INFO_SMPS_DYNAMIC ((u16) BIT(2))
|
||||
#define HT_CAP_INFO_SMPS_DISABLED ((u16) (BIT(2) | BIT(3)))
|
||||
#define HT_CAP_INFO_GREEN_FIELD ((u16) BIT(4))
|
||||
#define HT_CAP_INFO_SHORT_GI20MHZ ((u16) BIT(5))
|
||||
#define HT_CAP_INFO_SHORT_GI40MHZ ((u16) BIT(6))
|
||||
#define HT_CAP_INFO_TX_STBC ((u16) BIT(7))
|
||||
#define HT_CAP_INFO_RX_STBC_MASK ((u16) (BIT(8) | BIT(9)))
|
||||
#define HT_CAP_INFO_RX_STBC_1 ((u16) BIT(8))
|
||||
#define HT_CAP_INFO_RX_STBC_12 ((u16) BIT(9))
|
||||
#define HT_CAP_INFO_RX_STBC_123 ((u16) (BIT(8) | BIT(9)))
|
||||
#define HT_CAP_INFO_DELAYED_BA ((u16) BIT(10))
|
||||
#define HT_CAP_INFO_MAX_AMSDU_SIZE ((u16) BIT(11))
|
||||
#define HT_CAP_INFO_DSSS_CCK40MHZ ((u16) BIT(12))
|
||||
#define HT_CAP_INFO_PSMP_SUPP ((u16) BIT(13))
|
||||
#define HT_CAP_INFO_40MHZ_INTOLERANT ((u16) BIT(14))
|
||||
#define HT_CAP_INFO_LSIG_TXOP_PROTECT_SUPPORT ((u16) BIT(15))
|
||||
|
||||
|
||||
#define EXT_HT_CAP_INFO_PCO ((u16) BIT(0))
|
||||
#define EXT_HT_CAP_INFO_TRANS_TIME_OFFSET 1
|
||||
#define EXT_HT_CAP_INFO_MCS_FEEDBACK_OFFSET 8
|
||||
#define EXT_HT_CAP_INFO_HTC_SUPPORTED ((u16) BIT(10))
|
||||
#define EXT_HT_CAP_INFO_RD_RESPONDER ((u16) BIT(11))
|
||||
|
||||
|
||||
#define TX_BEAMFORM_CAP_TXBF_CAP ((u32) BIT(0))
|
||||
#define TX_BEAMFORM_CAP_RX_STAGGERED_SOUNDING_CAP ((u32) BIT(1))
|
||||
#define TX_BEAMFORM_CAP_TX_STAGGERED_SOUNDING_CAP ((u32) BIT(2))
|
||||
#define TX_BEAMFORM_CAP_RX_ZLF_CAP ((u32) BIT(3))
|
||||
#define TX_BEAMFORM_CAP_TX_ZLF_CAP ((u32) BIT(4))
|
||||
#define TX_BEAMFORM_CAP_IMPLICIT_ZLF_CAP ((u32) BIT(5))
|
||||
#define TX_BEAMFORM_CAP_CALIB_OFFSET 6
|
||||
#define TX_BEAMFORM_CAP_EXPLICIT_CSI_TXBF_CAP ((u32) BIT(8))
|
||||
#define TX_BEAMFORM_CAP_EXPLICIT_UNCOMPR_STEERING_MATRIX_CAP ((u32) BIT(9))
|
||||
#define TX_BEAMFORM_CAP_EXPLICIT_BF_CSI_FEEDBACK_CAP ((u32) BIT(10))
|
||||
#define TX_BEAMFORM_CAP_EXPLICIT_BF_CSI_FEEDBACK_OFFSET 11
|
||||
#define TX_BEAMFORM_CAP_EXPLICIT_UNCOMPR_STEERING_MATRIX_FEEDBACK_OFFSET 13
|
||||
#define TX_BEAMFORM_CAP_EXPLICIT_COMPRESSED_STEERING_MATRIX_FEEDBACK_OFFSET 15
|
||||
#define TX_BEAMFORM_CAP_MINIMAL_GROUPING_OFFSET 17
|
||||
#define TX_BEAMFORM_CAP_CSI_NUM_BEAMFORMER_ANT_OFFSET 19
|
||||
#define TX_BEAMFORM_CAP_UNCOMPRESSED_STEERING_MATRIX_BEAMFORMER_ANT_OFFSET 21
|
||||
#define TX_BEAMFORM_CAP_COMPRESSED_STEERING_MATRIX_BEAMFORMER_ANT_OFFSET 23
|
||||
#define TX_BEAMFORM_CAP_SCI_MAX_OF_ROWS_BEANFORMER_SUPPORTED_OFFSET 25
|
||||
|
||||
|
||||
#define ASEL_CAPABILITY_ASEL_CAPABLE ((u8) BIT(0))
|
||||
#define ASEL_CAPABILITY_EXPLICIT_CSI_FEEDBACK_BASED_TX_AS_CAP ((u8) BIT(1))
|
||||
#define ASEL_CAPABILITY_ANT_INDICES_FEEDBACK_BASED_TX_AS_CAP ((u8) BIT(2))
|
||||
#define ASEL_CAPABILITY_EXPLICIT_CSI_FEEDBACK_CAP ((u8) BIT(3))
|
||||
#define ASEL_CAPABILITY_ANT_INDICES_FEEDBACK_CAP ((u8) BIT(4))
|
||||
#define ASEL_CAPABILITY_RX_AS_CAP ((u8) BIT(5))
|
||||
#define ASEL_CAPABILITY_TX_SOUND_PPDUS_CAP ((u8) BIT(6))
|
||||
|
||||
#define HT_INFO_HT_PARAM_SECONDARY_CHNL_OFF_MASK ((u8) BIT(0) | BIT(1))
|
||||
#define HT_INFO_HT_PARAM_SECONDARY_CHNL_ABOVE ((u8) BIT(0))
|
||||
#define HT_INFO_HT_PARAM_SECONDARY_CHNL_BELOW ((u8) BIT(0) | BIT(1))
|
||||
#define HT_INFO_HT_PARAM_REC_TRANS_CHNL_WIDTH ((u8) BIT(2))
|
||||
#define HT_INFO_HT_PARAM_RIFS_MODE ((u8) BIT(3))
|
||||
#define HT_INFO_HT_PARAM_CTRL_ACCESS_ONLY ((u8) BIT(4))
|
||||
#define HT_INFO_HT_PARAM_SRV_INTERVAL_GRANULARITY ((u8) BIT(5))
|
||||
|
||||
|
||||
#define OP_MODE_PURE 0
|
||||
#define OP_MODE_MAY_BE_LEGACY_STAS 1
|
||||
#define OP_MODE_20MHZ_HT_STA_ASSOCED 2
|
||||
#define OP_MODE_MIXED 3
|
||||
|
||||
#define HT_INFO_OPERATION_MODE_OP_MODE_MASK \
|
||||
((le16) (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))
|
||||
#define HT_INFO_OPERATION_MODE_NON_HT_STA_PRESENT ((u8) BIT(4))
|
||||
|
||||
#define HT_INFO_STBC_PARAM_DUAL_BEACON ((u16) BIT(6))
|
||||
#define HT_INFO_STBC_PARAM_DUAL_STBC_PROTECT ((u16) BIT(7))
|
||||
#define HT_INFO_STBC_PARAM_SECONDARY_BCN ((u16) BIT(8))
|
||||
#define HT_INFO_STBC_PARAM_LSIG_TXOP_PROTECT_ALLOWED ((u16) BIT(9))
|
||||
#define HT_INFO_STBC_PARAM_PCO_ACTIVE ((u16) BIT(10))
|
||||
#define HT_INFO_STBC_PARAM_PCO_PHASE ((u16) BIT(11))
|
||||
|
||||
#define BSS_MEMBERSHIP_SELECTOR_HT_PHY 127
|
||||
|
||||
#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 WMM_OUI_TYPE 2
|
||||
#define WMM_OUI_SUBTYPE_INFORMATION_ELEMENT 0
|
||||
#define WMM_OUI_SUBTYPE_PARAMETER_ELEMENT 1
|
||||
#define WMM_OUI_SUBTYPE_TSPEC_ELEMENT 2
|
||||
#define WMM_VERSION 1
|
||||
|
||||
#define WMM_ACTION_CODE_ADDTS_REQ 0
|
||||
#define WMM_ACTION_CODE_ADDTS_RESP 1
|
||||
#define WMM_ACTION_CODE_DELTS 2
|
||||
|
||||
#define WMM_ADDTS_STATUS_ADMISSION_ACCEPTED 0
|
||||
#define WMM_ADDTS_STATUS_INVALID_PARAMETERS 1
|
||||
/* 2 - Reserved */
|
||||
#define WMM_ADDTS_STATUS_REFUSED 3
|
||||
/* 4-255 - Reserved */
|
||||
|
||||
/* WMM TSPEC Direction Field Values */
|
||||
#define WMM_TSPEC_DIRECTION_UPLINK 0
|
||||
#define WMM_TSPEC_DIRECTION_DOWNLINK 1
|
||||
/* 2 - Reserved */
|
||||
#define WMM_TSPEC_DIRECTION_BI_DIRECTIONAL 3
|
||||
|
||||
/*
|
||||
* WMM Information Element (used in (Re)Association Request frames; may also be
|
||||
* used in Beacon frames)
|
||||
*/
|
||||
struct wmm_information_element {
|
||||
/* Element ID: 221 (0xdd); Length: 7 */
|
||||
/* required fields for WMM version 1 */
|
||||
u8 oui[3]; /* 00:50:f2 */
|
||||
u8 oui_type; /* 2 */
|
||||
u8 oui_subtype; /* 0 */
|
||||
u8 version; /* 1 for WMM version 1.0 */
|
||||
u8 qos_info; /* AP/STA specific QoS info */
|
||||
|
||||
} STRUCT_PACKED;
|
||||
|
||||
#define WMM_AC_AIFSN_MASK 0x0f
|
||||
#define WMM_AC_AIFNS_SHIFT 0
|
||||
#define WMM_AC_ACM 0x10
|
||||
#define WMM_AC_ACI_MASK 0x60
|
||||
#define WMM_AC_ACI_SHIFT 5
|
||||
|
||||
#define WMM_AC_ECWMIN_MASK 0x0f
|
||||
#define WMM_AC_ECWMIN_SHIFT 0
|
||||
#define WMM_AC_ECWMAX_MASK 0xf0
|
||||
#define WMM_AC_ECWMAX_SHIFT 4
|
||||
|
||||
struct wmm_ac_parameter {
|
||||
u8 aci_aifsn; /* AIFSN, ACM, ACI */
|
||||
u8 cw; /* ECWmin, ECWmax (CW = 2^ECW - 1) */
|
||||
le16 txop_limit;
|
||||
} STRUCT_PACKED;
|
||||
|
||||
/*
|
||||
* WMM Parameter Element (used in Beacon, Probe Response, and (Re)Association
|
||||
* Response frmaes)
|
||||
*/
|
||||
struct wmm_parameter_element {
|
||||
/* Element ID: 221 (0xdd); Length: 24 */
|
||||
/* required fields for WMM version 1 */
|
||||
u8 oui[3]; /* 00:50:f2 */
|
||||
u8 oui_type; /* 2 */
|
||||
u8 oui_subtype; /* 1 */
|
||||
u8 version; /* 1 for WMM version 1.0 */
|
||||
u8 qos_info; /* AP/STA specif QoS info */
|
||||
u8 reserved; /* 0 */
|
||||
struct wmm_ac_parameter ac[4]; /* AC_BE, AC_BK, AC_VI, AC_VO */
|
||||
|
||||
} STRUCT_PACKED;
|
||||
|
||||
/* WMM TSPEC Element */
|
||||
struct wmm_tspec_element {
|
||||
u8 eid; /* 221 = 0xdd */
|
||||
u8 length; /* 6 + 55 = 61 */
|
||||
u8 oui[3]; /* 00:50:f2 */
|
||||
u8 oui_type; /* 2 */
|
||||
u8 oui_subtype; /* 2 */
|
||||
u8 version; /* 1 */
|
||||
/* WMM TSPEC body (55 octets): */
|
||||
u8 ts_info[3];
|
||||
le16 nominal_msdu_size;
|
||||
le16 maximum_msdu_size;
|
||||
le32 minimum_service_interval;
|
||||
le32 maximum_service_interval;
|
||||
le32 inactivity_interval;
|
||||
le32 suspension_interval;
|
||||
le32 service_start_time;
|
||||
le32 minimum_data_rate;
|
||||
le32 mean_data_rate;
|
||||
le32 peak_data_rate;
|
||||
le32 maximum_burst_size;
|
||||
le32 delay_bound;
|
||||
le32 minimum_phy_rate;
|
||||
le16 surplus_bandwidth_allowance;
|
||||
le16 medium_time;
|
||||
} STRUCT_PACKED;
|
||||
|
||||
|
||||
/* Access Categories / ACI to AC coding */
|
||||
enum {
|
||||
WMM_AC_BE = 0 /* Best Effort */,
|
||||
WMM_AC_BK = 1 /* Background */,
|
||||
WMM_AC_VI = 2 /* Video */,
|
||||
WMM_AC_VO = 3 /* Voice */
|
||||
};
|
||||
|
||||
|
||||
/* Wi-Fi Direct (P2P) */
|
||||
|
||||
#define P2P_OUI_TYPE 9
|
||||
|
||||
enum p2p_attr_id {
|
||||
P2P_ATTR_STATUS = 0,
|
||||
P2P_ATTR_MINOR_REASON_CODE = 1,
|
||||
P2P_ATTR_CAPABILITY = 2,
|
||||
P2P_ATTR_DEVICE_ID = 3,
|
||||
P2P_ATTR_GROUP_OWNER_INTENT = 4,
|
||||
P2P_ATTR_CONFIGURATION_TIMEOUT = 5,
|
||||
P2P_ATTR_LISTEN_CHANNEL = 6,
|
||||
P2P_ATTR_GROUP_BSSID = 7,
|
||||
P2P_ATTR_EXT_LISTEN_TIMING = 8,
|
||||
P2P_ATTR_INTENDED_INTERFACE_ADDR = 9,
|
||||
P2P_ATTR_MANAGEABILITY = 10,
|
||||
P2P_ATTR_CHANNEL_LIST = 11,
|
||||
P2P_ATTR_NOTICE_OF_ABSENCE = 12,
|
||||
P2P_ATTR_DEVICE_INFO = 13,
|
||||
P2P_ATTR_GROUP_INFO = 14,
|
||||
P2P_ATTR_GROUP_ID = 15,
|
||||
P2P_ATTR_INTERFACE = 16,
|
||||
P2P_ATTR_OPERATING_CHANNEL = 17,
|
||||
P2P_ATTR_INVITATION_FLAGS = 18,
|
||||
P2P_ATTR_VENDOR_SPECIFIC = 221
|
||||
};
|
||||
|
||||
#define P2P_MAX_GO_INTENT 15
|
||||
|
||||
/* P2P Capability - Device Capability bitmap */
|
||||
#define P2P_DEV_CAPAB_SERVICE_DISCOVERY BIT(0)
|
||||
#define P2P_DEV_CAPAB_CLIENT_DISCOVERABILITY BIT(1)
|
||||
#define P2P_DEV_CAPAB_CONCURRENT_OPER BIT(2)
|
||||
#define P2P_DEV_CAPAB_INFRA_MANAGED BIT(3)
|
||||
#define P2P_DEV_CAPAB_DEVICE_LIMIT BIT(4)
|
||||
#define P2P_DEV_CAPAB_INVITATION_PROCEDURE BIT(5)
|
||||
|
||||
/* P2P Capability - Group Capability bitmap */
|
||||
#define P2P_GROUP_CAPAB_GROUP_OWNER BIT(0)
|
||||
#define P2P_GROUP_CAPAB_PERSISTENT_GROUP BIT(1)
|
||||
#define P2P_GROUP_CAPAB_GROUP_LIMIT BIT(2)
|
||||
#define P2P_GROUP_CAPAB_INTRA_BSS_DIST BIT(3)
|
||||
#define P2P_GROUP_CAPAB_CROSS_CONN BIT(4)
|
||||
#define P2P_GROUP_CAPAB_PERSISTENT_RECONN BIT(5)
|
||||
#define P2P_GROUP_CAPAB_GROUP_FORMATION BIT(6)
|
||||
|
||||
/* Invitation Flags */
|
||||
#define P2P_INVITATION_FLAGS_TYPE BIT(0)
|
||||
|
||||
/* P2P Manageability */
|
||||
#define P2P_MAN_DEVICE_MANAGEMENT BIT(0)
|
||||
#define P2P_MAN_CROSS_CONNECTION_PERMITTED BIT(1)
|
||||
#define P2P_MAN_COEXISTENCE_OPTIONAL BIT(2)
|
||||
|
||||
enum p2p_status_code {
|
||||
P2P_SC_SUCCESS = 0,
|
||||
P2P_SC_FAIL_INFO_CURRENTLY_UNAVAILABLE = 1,
|
||||
P2P_SC_FAIL_INCOMPATIBLE_PARAMS = 2,
|
||||
P2P_SC_FAIL_LIMIT_REACHED = 3,
|
||||
P2P_SC_FAIL_INVALID_PARAMS = 4,
|
||||
P2P_SC_FAIL_UNABLE_TO_ACCOMMODATE = 5,
|
||||
P2P_SC_FAIL_PREV_PROTOCOL_ERROR = 6,
|
||||
P2P_SC_FAIL_NO_COMMON_CHANNELS = 7,
|
||||
P2P_SC_FAIL_UNKNOWN_GROUP = 8,
|
||||
P2P_SC_FAIL_BOTH_GO_INTENT_15 = 9,
|
||||
P2P_SC_FAIL_INCOMPATIBLE_PROV_METHOD = 10,
|
||||
P2P_SC_FAIL_REJECTED_BY_USER = 11,
|
||||
};
|
||||
|
||||
#define P2P_WILDCARD_SSID "DIRECT-"
|
||||
#define P2P_WILDCARD_SSID_LEN 7
|
||||
|
||||
/* P2P action frames */
|
||||
enum p2p_act_frame_type {
|
||||
P2P_NOA = 0,
|
||||
P2P_PRESENCE_REQ = 1,
|
||||
P2P_PRESENCE_RESP = 2,
|
||||
P2P_GO_DISC_REQ = 3
|
||||
};
|
||||
|
||||
/* P2P public action frames */
|
||||
enum p2p_action_frame_type {
|
||||
P2P_GO_NEG_REQ = 0,
|
||||
P2P_GO_NEG_RESP = 1,
|
||||
P2P_GO_NEG_CONF = 2,
|
||||
P2P_INVITATION_REQ = 3,
|
||||
P2P_INVITATION_RESP = 4,
|
||||
P2P_DEV_DISC_REQ = 5,
|
||||
P2P_DEV_DISC_RESP = 6,
|
||||
P2P_PROV_DISC_REQ = 7,
|
||||
P2P_PROV_DISC_RESP = 8
|
||||
};
|
||||
|
||||
enum p2p_service_protocol_type {
|
||||
P2P_SERV_ALL_SERVICES = 0,
|
||||
P2P_SERV_BONJOUR = 1,
|
||||
P2P_SERV_UPNP = 2,
|
||||
P2P_SERV_WS_DISCOVERY = 3,
|
||||
P2P_SERV_VENDOR_SPECIFIC = 255
|
||||
};
|
||||
|
||||
enum p2p_sd_status {
|
||||
P2P_SD_SUCCESS = 0,
|
||||
P2P_SD_PROTO_NOT_AVAILABLE = 1,
|
||||
P2P_SD_REQUESTED_INFO_NOT_AVAILABLE = 2,
|
||||
P2P_SD_BAD_REQUEST = 3
|
||||
};
|
||||
|
||||
|
||||
#define OUI_BROADCOM 0x00904c /* Broadcom (Epigram) */
|
||||
|
||||
#define VENDOR_HT_CAPAB_OUI_TYPE 0x33 /* 00-90-4c:0x33 */
|
||||
|
||||
/* cipher suite selectors */
|
||||
#define WLAN_CIPHER_SUITE_USE_GROUP 0x000FAC00
|
||||
#define WLAN_CIPHER_SUITE_WEP40 0x000FAC01
|
||||
#define WLAN_CIPHER_SUITE_TKIP 0x000FAC02
|
||||
/* reserved: 0x000FAC03 */
|
||||
#define WLAN_CIPHER_SUITE_CCMP 0x000FAC04
|
||||
#define WLAN_CIPHER_SUITE_WEP104 0x000FAC05
|
||||
#define WLAN_CIPHER_SUITE_AES_CMAC 0x000FAC06
|
||||
|
||||
/* AKM suite selectors */
|
||||
#define WLAN_AKM_SUITE_8021X 0x000FAC01
|
||||
#define WLAN_AKM_SUITE_PSK 0x000FAC02
|
||||
|
||||
#endif /* IEEE802_11_DEFS_H */
|
Some files were not shown because too many files have changed in this diff Show more
Loading…
Reference in a new issue