Robin Thoni 9 vuotta sitten
commit
19913126b5
100 muutettua tiedostoa jossa 34448 lisäystä ja 0 poistoa
  1. 2
    0
      .gitignore
  2. 340
    0
      COPYING
  3. 72
    0
      README.md
  4. 209
    0
      hostapd/.config
  5. 209
    0
      hostapd/.config_bsd
  6. 817
    0
      hostapd/Android.mk
  7. 647
    0
      hostapd/ChangeLog
  8. 840
    0
      hostapd/Makefile
  9. 387
    0
      hostapd/README
  10. 291
    0
      hostapd/README-WPS
  11. 78
    0
      hostapd/bsd_hostapd.conf
  12. 2119
    0
      hostapd/config_file.c
  13. 20
    0
      hostapd/config_file.h
  14. 1131
    0
      hostapd/ctrl_iface.c
  15. 32
    0
      hostapd/ctrl_iface.h
  16. 204
    0
      hostapd/defconfig
  17. 183
    0
      hostapd/dump_state.c
  18. 20
    0
      hostapd/dump_state.h
  19. 139
    0
      hostapd/eap_register.c
  20. 20
    0
      hostapd/eap_register.h
  21. 77
    0
      hostapd/eap_testing.txt
  22. 715
    0
      hostapd/hlr_auc_gw.c
  23. 13
    0
      hostapd/hlr_auc_gw.milenage_db
  24. 59
    0
      hostapd/hostapd.8
  25. 6
    0
      hostapd/hostapd.accept
  26. 1040
    0
      hostapd/hostapd.conf
  27. 5
    0
      hostapd/hostapd.deny
  28. 91
    0
      hostapd/hostapd.eap_user
  29. 4
    0
      hostapd/hostapd.radius_clients
  30. 9
    0
      hostapd/hostapd.sim_db
  31. 9
    0
      hostapd/hostapd.vlan
  32. 9
    0
      hostapd/hostapd.wpa_psk
  33. 89
    0
      hostapd/hostapd_cli.1
  34. 1043
    0
      hostapd/hostapd_cli.c
  35. 9
    0
      hostapd/logwatch/README
  36. 65
    0
      hostapd/logwatch/hostapd
  37. 10
    0
      hostapd/logwatch/hostapd.conf
  38. 599
    0
      hostapd/main.c
  39. 53
    0
      hostapd/nt_password_hash.c
  40. 1
    0
      hostapd/src
  41. 40
    0
      hostapd/wired.conf
  42. 25
    0
      scripts/hostapd.conf
  43. 66
    0
      scripts/init
  44. 11
    0
      src/Makefile
  45. 8
    0
      src/ap/Makefile
  46. 505
    0
      src/ap/accounting.c
  47. 45
    0
      src/ap/accounting.h
  48. 627
    0
      src/ap/ap_config.c
  49. 417
    0
      src/ap/ap_config.h
  50. 632
    0
      src/ap/ap_drv_ops.c
  51. 197
    0
      src/ap/ap_drv_ops.h
  52. 399
    0
      src/ap/ap_list.c
  53. 78
    0
      src/ap/ap_list.h
  54. 184
    0
      src/ap/ap_mlme.c
  55. 40
    0
      src/ap/ap_mlme.h
  56. 217
    0
      src/ap/authsrv.c
  57. 21
    0
      src/ap/authsrv.h
  58. 540
    0
      src/ap/beacon.c
  59. 36
    0
      src/ap/beacon.h
  60. 108
    0
      src/ap/ctrl_iface_ap.c
  61. 25
    0
      src/ap/ctrl_iface_ap.h
  62. 539
    0
      src/ap/drv_callbacks.c
  63. 929
    0
      src/ap/hostapd.c
  64. 262
    0
      src/ap/hostapd.h
  65. 754
    0
      src/ap/hw_features.c
  66. 70
    0
      src/ap/hw_features.h
  67. 535
    0
      src/ap/iapp.c
  68. 45
    0
      src/ap/iapp.h
  69. 1882
    0
      src/ap/ieee802_11.c
  70. 68
    0
      src/ap/ieee802_11.h
  71. 524
    0
      src/ap/ieee802_11_auth.c
  72. 31
    0
      src/ap/ieee802_11_auth.h
  73. 267
    0
      src/ap/ieee802_11_ht.c
  74. 2085
    0
      src/ap/ieee802_1x.c
  75. 89
    0
      src/ap/ieee802_1x.h
  76. 120
    0
      src/ap/p2p_hostapd.c
  77. 41
    0
      src/ap/p2p_hostapd.h
  78. 402
    0
      src/ap/peerkey_auth.c
  79. 425
    0
      src/ap/pmksa_cache_auth.c
  80. 64
    0
      src/ap/pmksa_cache_auth.h
  81. 279
    0
      src/ap/preauth_auth.c
  82. 58
    0
      src/ap/preauth_auth.h
  83. 796
    0
      src/ap/sta_info.c
  84. 165
    0
      src/ap/sta_info.h
  85. 94
    0
      src/ap/tkip_countermeasures.c
  86. 20
    0
      src/ap/tkip_countermeasures.h
  87. 88
    0
      src/ap/utils.c
  88. 905
    0
      src/ap/vlan_init.c
  89. 59
    0
      src/ap/vlan_init.h
  90. 327
    0
      src/ap/wmm.c
  91. 29
    0
      src/ap/wmm.h
  92. 2838
    0
      src/ap/wpa_auth.c
  93. 285
    0
      src/ap/wpa_auth.h
  94. 1779
    0
      src/ap/wpa_auth_ft.c
  95. 571
    0
      src/ap/wpa_auth_glue.c
  96. 22
    0
      src/ap/wpa_auth_glue.h
  97. 234
    0
      src/ap/wpa_auth_i.h
  98. 824
    0
      src/ap/wpa_auth_ie.c
  99. 56
    0
      src/ap/wpa_auth_ie.h
  100. 0
    0
      src/ap/wps_hostapd.c

+ 2
- 0
.gitignore Näytä tiedosto

@@ -0,0 +1,2 @@
1
+.DS_Store
2
+*.o

+ 340
- 0
COPYING Näytä tiedosto

@@ -0,0 +1,340 @@
1
+		    GNU GENERAL PUBLIC LICENSE
2
+		       Version 2, June 1991
3
+
4
+ Copyright (C) 1989, 1991 Free Software Foundation, Inc.
5
+                       51 Franklin St, Fifth Floor, Boston, MA  02110-1301  USA
6
+ Everyone is permitted to copy and distribute verbatim copies
7
+ of this license document, but changing it is not allowed.
8
+
9
+			    Preamble
10
+
11
+  The licenses for most software are designed to take away your
12
+freedom to share and change it.  By contrast, the GNU General Public
13
+License is intended to guarantee your freedom to share and change free
14
+software--to make sure the software is free for all its users.  This
15
+General Public License applies to most of the Free Software
16
+Foundation's software and to any other program whose authors commit to
17
+using it.  (Some other Free Software Foundation software is covered by
18
+the GNU Library General Public License instead.)  You can apply it to
19
+your programs, too.
20
+
21
+  When we speak of free software, we are referring to freedom, not
22
+price.  Our General Public Licenses are designed to make sure that you
23
+have the freedom to distribute copies of free software (and charge for
24
+this service if you wish), that you receive source code or can get it
25
+if you want it, that you can change the software or use pieces of it
26
+in new free programs; and that you know you can do these things.
27
+
28
+  To protect your rights, we need to make restrictions that forbid
29
+anyone to deny you these rights or to ask you to surrender the rights.
30
+These restrictions translate to certain responsibilities for you if you
31
+distribute copies of the software, or if you modify it.
32
+
33
+  For example, if you distribute copies of such a program, whether
34
+gratis or for a fee, you must give the recipients all the rights that
35
+you have.  You must make sure that they, too, receive or can get the
36
+source code.  And you must show them these terms so they know their
37
+rights.
38
+
39
+  We protect your rights with two steps: (1) copyright the software, and
40
+(2) offer you this license which gives you legal permission to copy,
41
+distribute and/or modify the software.
42
+
43
+  Also, for each author's protection and ours, we want to make certain
44
+that everyone understands that there is no warranty for this free
45
+software.  If the software is modified by someone else and passed on, we
46
+want its recipients to know that what they have is not the original, so
47
+that any problems introduced by others will not reflect on the original
48
+authors' reputations.
49
+
50
+  Finally, any free program is threatened constantly by software
51
+patents.  We wish to avoid the danger that redistributors of a free
52
+program will individually obtain patent licenses, in effect making the
53
+program proprietary.  To prevent this, we have made it clear that any
54
+patent must be licensed for everyone's free use or not licensed at all.
55
+
56
+  The precise terms and conditions for copying, distribution and
57
+modification follow.
58
+
59
+		    GNU GENERAL PUBLIC LICENSE
60
+   TERMS AND CONDITIONS FOR COPYING, DISTRIBUTION AND MODIFICATION
61
+
62
+  0. This License applies to any program or other work which contains
63
+a notice placed by the copyright holder saying it may be distributed
64
+under the terms of this General Public License.  The "Program", below,
65
+refers to any such program or work, and a "work based on the Program"
66
+means either the Program or any derivative work under copyright law:
67
+that is to say, a work containing the Program or a portion of it,
68
+either verbatim or with modifications and/or translated into another
69
+language.  (Hereinafter, translation is included without limitation in
70
+the term "modification".)  Each licensee is addressed as "you".
71
+
72
+Activities other than copying, distribution and modification are not
73
+covered by this License; they are outside its scope.  The act of
74
+running the Program is not restricted, and the output from the Program
75
+is covered only if its contents constitute a work based on the
76
+Program (independent of having been made by running the Program).
77
+Whether that is true depends on what the Program does.
78
+
79
+  1. You may copy and distribute verbatim copies of the Program's
80
+source code as you receive it, in any medium, provided that you
81
+conspicuously and appropriately publish on each copy an appropriate
82
+copyright notice and disclaimer of warranty; keep intact all the
83
+notices that refer to this License and to the absence of any warranty;
84
+and give any other recipients of the Program a copy of this License
85
+along with the Program.
86
+
87
+You may charge a fee for the physical act of transferring a copy, and
88
+you may at your option offer warranty protection in exchange for a fee.
89
+
90
+  2. You may modify your copy or copies of the Program or any portion
91
+of it, thus forming a work based on the Program, and copy and
92
+distribute such modifications or work under the terms of Section 1
93
+above, provided that you also meet all of these conditions:
94
+
95
+    a) You must cause the modified files to carry prominent notices
96
+    stating that you changed the files and the date of any change.
97
+
98
+    b) You must cause any work that you distribute or publish, that in
99
+    whole or in part contains or is derived from the Program or any
100
+    part thereof, to be licensed as a whole at no charge to all third
101
+    parties under the terms of this License.
102
+
103
+    c) If the modified program normally reads commands interactively
104
+    when run, you must cause it, when started running for such
105
+    interactive use in the most ordinary way, to print or display an
106
+    announcement including an appropriate copyright notice and a
107
+    notice that there is no warranty (or else, saying that you provide
108
+    a warranty) and that users may redistribute the program under
109
+    these conditions, and telling the user how to view a copy of this
110
+    License.  (Exception: if the Program itself is interactive but
111
+    does not normally print such an announcement, your work based on
112
+    the Program is not required to print an announcement.)
113
+
114
+These requirements apply to the modified work as a whole.  If
115
+identifiable sections of that work are not derived from the Program,
116
+and can be reasonably considered independent and separate works in
117
+themselves, then this License, and its terms, do not apply to those
118
+sections when you distribute them as separate works.  But when you
119
+distribute the same sections as part of a whole which is a work based
120
+on the Program, the distribution of the whole must be on the terms of
121
+this License, whose permissions for other licensees extend to the
122
+entire whole, and thus to each and every part regardless of who wrote it.
123
+
124
+Thus, it is not the intent of this section to claim rights or contest
125
+your rights to work written entirely by you; rather, the intent is to
126
+exercise the right to control the distribution of derivative or
127
+collective works based on the Program.
128
+
129
+In addition, mere aggregation of another work not based on the Program
130
+with the Program (or with a work based on the Program) on a volume of
131
+a storage or distribution medium does not bring the other work under
132
+the scope of this License.
133
+
134
+  3. You may copy and distribute the Program (or a work based on it,
135
+under Section 2) in object code or executable form under the terms of
136
+Sections 1 and 2 above provided that you also do one of the following:
137
+
138
+    a) Accompany it with the complete corresponding machine-readable
139
+    source code, which must be distributed under the terms of Sections
140
+    1 and 2 above on a medium customarily used for software interchange; or,
141
+
142
+    b) Accompany it with a written offer, valid for at least three
143
+    years, to give any third party, for a charge no more than your
144
+    cost of physically performing source distribution, a complete
145
+    machine-readable copy of the corresponding source code, to be
146
+    distributed under the terms of Sections 1 and 2 above on a medium
147
+    customarily used for software interchange; or,
148
+
149
+    c) Accompany it with the information you received as to the offer
150
+    to distribute corresponding source code.  (This alternative is
151
+    allowed only for noncommercial distribution and only if you
152
+    received the program in object code or executable form with such
153
+    an offer, in accord with Subsection b above.)
154
+
155
+The source code for a work means the preferred form of the work for
156
+making modifications to it.  For an executable work, complete source
157
+code means all the source code for all modules it contains, plus any
158
+associated interface definition files, plus the scripts used to
159
+control compilation and installation of the executable.  However, as a
160
+special exception, the source code distributed need not include
161
+anything that is normally distributed (in either source or binary
162
+form) with the major components (compiler, kernel, and so on) of the
163
+operating system on which the executable runs, unless that component
164
+itself accompanies the executable.
165
+
166
+If distribution of executable or object code is made by offering
167
+access to copy from a designated place, then offering equivalent
168
+access to copy the source code from the same place counts as
169
+distribution of the source code, even though third parties are not
170
+compelled to copy the source along with the object code.
171
+
172
+  4. You may not copy, modify, sublicense, or distribute the Program
173
+except as expressly provided under this License.  Any attempt
174
+otherwise to copy, modify, sublicense or distribute the Program is
175
+void, and will automatically terminate your rights under this License.
176
+However, parties who have received copies, or rights, from you under
177
+this License will not have their licenses terminated so long as such
178
+parties remain in full compliance.
179
+
180
+  5. You are not required to accept this License, since you have not
181
+signed it.  However, nothing else grants you permission to modify or
182
+distribute the Program or its derivative works.  These actions are
183
+prohibited by law if you do not accept this License.  Therefore, by
184
+modifying or distributing the Program (or any work based on the
185
+Program), you indicate your acceptance of this License to do so, and
186
+all its terms and conditions for copying, distributing or modifying
187
+the Program or works based on it.
188
+
189
+  6. Each time you redistribute the Program (or any work based on the
190
+Program), the recipient automatically receives a license from the
191
+original licensor to copy, distribute or modify the Program subject to
192
+these terms and conditions.  You may not impose any further
193
+restrictions on the recipients' exercise of the rights granted herein.
194
+You are not responsible for enforcing compliance by third parties to
195
+this License.
196
+
197
+  7. If, as a consequence of a court judgment or allegation of patent
198
+infringement or for any other reason (not limited to patent issues),
199
+conditions are imposed on you (whether by court order, agreement or
200
+otherwise) that contradict the conditions of this License, they do not
201
+excuse you from the conditions of this License.  If you cannot
202
+distribute so as to satisfy simultaneously your obligations under this
203
+License and any other pertinent obligations, then as a consequence you
204
+may not distribute the Program at all.  For example, if a patent
205
+license would not permit royalty-free redistribution of the Program by
206
+all those who receive copies directly or indirectly through you, then
207
+the only way you could satisfy both it and this License would be to
208
+refrain entirely from distribution of the Program.
209
+
210
+If any portion of this section is held invalid or unenforceable under
211
+any particular circumstance, the balance of the section is intended to
212
+apply and the section as a whole is intended to apply in other
213
+circumstances.
214
+
215
+It is not the purpose of this section to induce you to infringe any
216
+patents or other property right claims or to contest validity of any
217
+such claims; this section has the sole purpose of protecting the
218
+integrity of the free software distribution system, which is
219
+implemented by public license practices.  Many people have made
220
+generous contributions to the wide range of software distributed
221
+through that system in reliance on consistent application of that
222
+system; it is up to the author/donor to decide if he or she is willing
223
+to distribute software through any other system and a licensee cannot
224
+impose that choice.
225
+
226
+This section is intended to make thoroughly clear what is believed to
227
+be a consequence of the rest of this License.
228
+
229
+  8. If the distribution and/or use of the Program is restricted in
230
+certain countries either by patents or by copyrighted interfaces, the
231
+original copyright holder who places the Program under this License
232
+may add an explicit geographical distribution limitation excluding
233
+those countries, so that distribution is permitted only in or among
234
+countries not thus excluded.  In such case, this License incorporates
235
+the limitation as if written in the body of this License.
236
+
237
+  9. The Free Software Foundation may publish revised and/or new versions
238
+of the General Public License from time to time.  Such new versions will
239
+be similar in spirit to the present version, but may differ in detail to
240
+address new problems or concerns.
241
+
242
+Each version is given a distinguishing version number.  If the Program
243
+specifies a version number of this License which applies to it and "any
244
+later version", you have the option of following the terms and conditions
245
+either of that version or of any later version published by the Free
246
+Software Foundation.  If the Program does not specify a version number of
247
+this License, you may choose any version ever published by the Free Software
248
+Foundation.
249
+
250
+  10. If you wish to incorporate parts of the Program into other free
251
+programs whose distribution conditions are different, write to the author
252
+to ask for permission.  For software which is copyrighted by the Free
253
+Software Foundation, write to the Free Software Foundation; we sometimes
254
+make exceptions for this.  Our decision will be guided by the two goals
255
+of preserving the free status of all derivatives of our free software and
256
+of promoting the sharing and reuse of software generally.
257
+
258
+			    NO WARRANTY
259
+
260
+  11. BECAUSE THE PROGRAM IS LICENSED FREE OF CHARGE, THERE IS NO WARRANTY
261
+FOR THE PROGRAM, TO THE EXTENT PERMITTED BY APPLICABLE LAW.  EXCEPT WHEN
262
+OTHERWISE STATED IN WRITING THE COPYRIGHT HOLDERS AND/OR OTHER PARTIES
263
+PROVIDE THE PROGRAM "AS IS" WITHOUT WARRANTY OF ANY KIND, EITHER EXPRESSED
264
+OR IMPLIED, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF
265
+MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE.  THE ENTIRE RISK AS
266
+TO THE QUALITY AND PERFORMANCE OF THE PROGRAM IS WITH YOU.  SHOULD THE
267
+PROGRAM PROVE DEFECTIVE, YOU ASSUME THE COST OF ALL NECESSARY SERVICING,
268
+REPAIR OR CORRECTION.
269
+
270
+  12. IN NO EVENT UNLESS REQUIRED BY APPLICABLE LAW OR AGREED TO IN WRITING
271
+WILL ANY COPYRIGHT HOLDER, OR ANY OTHER PARTY WHO MAY MODIFY AND/OR
272
+REDISTRIBUTE THE PROGRAM AS PERMITTED ABOVE, BE LIABLE TO YOU FOR DAMAGES,
273
+INCLUDING ANY GENERAL, SPECIAL, INCIDENTAL OR CONSEQUENTIAL DAMAGES ARISING
274
+OUT OF THE USE OR INABILITY TO USE THE PROGRAM (INCLUDING BUT NOT LIMITED
275
+TO LOSS OF DATA OR DATA BEING RENDERED INACCURATE OR LOSSES SUSTAINED BY
276
+YOU OR THIRD PARTIES OR A FAILURE OF THE PROGRAM TO OPERATE WITH ANY OTHER
277
+PROGRAMS), EVEN IF SUCH HOLDER OR OTHER PARTY HAS BEEN ADVISED OF THE
278
+POSSIBILITY OF SUCH DAMAGES.
279
+
280
+		     END OF TERMS AND CONDITIONS
281
+
282
+	    How to Apply These Terms to Your New Programs
283
+
284
+  If you develop a new program, and you want it to be of the greatest
285
+possible use to the public, the best way to achieve this is to make it
286
+free software which everyone can redistribute and change under these terms.
287
+
288
+  To do so, attach the following notices to the program.  It is safest
289
+to attach them to the start of each source file to most effectively
290
+convey the exclusion of warranty; and each file should have at least
291
+the "copyright" line and a pointer to where the full notice is found.
292
+
293
+    <one line to give the program's name and a brief idea of what it does.>
294
+    Copyright (C) 19yy  <name of author>
295
+
296
+    This program is free software; you can redistribute it and/or modify
297
+    it under the terms of the GNU General Public License as published by
298
+    the Free Software Foundation; either version 2 of the License, or
299
+    (at your option) any later version.
300
+
301
+    This program is distributed in the hope that it will be useful,
302
+    but WITHOUT ANY WARRANTY; without even the implied warranty of
303
+    MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
304
+    GNU General Public License for more details.
305
+
306
+    You should have received a copy of the GNU General Public License
307
+    along with this program; if not, write to the Free Software
308
+    Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA  02110-1301  USA
309
+
310
+
311
+Also add information on how to contact you by electronic and paper mail.
312
+
313
+If the program is interactive, make it output a short notice like this
314
+when it starts in an interactive mode:
315
+
316
+    Gnomovision version 69, Copyright (C) 19yy name of author
317
+    Gnomovision comes with ABSOLUTELY NO WARRANTY; for details type `show w'.
318
+    This is free software, and you are welcome to redistribute it
319
+    under certain conditions; type `show c' for details.
320
+
321
+The hypothetical commands `show w' and `show c' should show the appropriate
322
+parts of the General Public License.  Of course, the commands you use may
323
+be called something other than `show w' and `show c'; they could even be
324
+mouse-clicks or menu items--whatever suits your program.
325
+
326
+You should also get your employer (if you work as a programmer) or your
327
+school, if any, to sign a "copyright disclaimer" for the program, if
328
+necessary.  Here is a sample; alter the names:
329
+
330
+  Yoyodyne, Inc., hereby disclaims all copyright interest in the program
331
+  `Gnomovision' (which makes passes at compilers) written by James Hacker.
332
+
333
+  <signature of Ty Coon>, 1 April 1989
334
+  Ty Coon, President of Vice
335
+
336
+This General Public License does not permit incorporating your program into
337
+proprietary programs.  If your program is a subroutine library, you may
338
+consider it more useful to permit linking proprietary applications with the
339
+library.  If this is what you want to do, use the GNU Library General
340
+Public License instead of this License.

+ 72
- 0
README.md Näytä tiedosto

@@ -0,0 +1,72 @@
1
+wpa_supplicant and hostapd
2
+--------------------------
3
+
4
+Copyright (c) 2002-2011, Jouni Malinen <j@w1.fi> and contributors
5
+All Rights Reserved.
6
+
7
+These programs are dual-licensed under both the GPL version 2 and BSD
8
+license (the one with advertisement clause removed). Either license
9
+may be used at your option.
10
+
11
+
12
+This package may include either wpa_supplicant, hostapd, or both. See
13
+README file respective subdirectories (wpa_supplicant/README or
14
+hostapd/README) for more details.
15
+
16
+Source code files were moved around in v0.6.x releases and compared to
17
+earlier releases, the programs are now built by first going to a
18
+subdirectory (wpa_supplicant or hostapd) and creating build
19
+configuration (.config) and running 'make' there (for Linux/BSD/cygwin
20
+builds).
21
+
22
+
23
+License
24
+-------
25
+
26
+GPL v2:
27
+
28
+This program is free software; you can redistribute it and/or modify
29
+it under the terms of the GNU General Public License version 2 as
30
+published by the Free Software Foundation.
31
+
32
+This program is distributed in the hope that it will be useful,
33
+but WITHOUT ANY WARRANTY; without even the implied warranty of
34
+MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
35
+GNU General Public License for more details.
36
+
37
+You should have received a copy of the GNU General Public License
38
+along with this program; if not, write to the Free Software
39
+Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA  02110-1301  USA
40
+
41
+(this copy of the license is in COPYING file)
42
+
43
+
44
+Alternatively, this software may be distributed, used, and modified
45
+under the terms of BSD license:
46
+
47
+Redistribution and use in source and binary forms, with or without
48
+modification, are permitted provided that the following conditions are
49
+met:
50
+
51
+1. Redistributions of source code must retain the above copyright
52
+   notice, this list of conditions and the following disclaimer.
53
+
54
+2. Redistributions in binary form must reproduce the above copyright
55
+   notice, this list of conditions and the following disclaimer in the
56
+   documentation and/or other materials provided with the distribution.
57
+
58
+3. Neither the name(s) of the above-listed copyright holder(s) nor the
59
+   names of its contributors may be used to endorse or promote products
60
+   derived from this software without specific prior written permission.
61
+
62
+THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
63
+"AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
64
+LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
65
+A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
66
+OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
67
+SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
68
+LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
69
+DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
70
+THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
71
+(INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
72
+OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.

+ 209
- 0
hostapd/.config Näytä tiedosto

@@ -0,0 +1,209 @@
1
+# Example hostapd build time configuration
2
+#
3
+# This file lists the configuration options that are used when building the
4
+# hostapd binary. All lines starting with # are ignored. Configuration option
5
+# lines must be commented out complete, if they are not to be included, i.e.,
6
+# just setting VARIABLE=n is not disabling that variable.
7
+#
8
+# This file is included in Makefile, so variables like CFLAGS and LIBS can also
9
+# be modified from here. In most cass, these lines should use += in order not
10
+# to override previous values of the variables.
11
+
12
+# Driver interface for Host AP driver
13
+#CONFIG_DRIVER_HOSTAP=y
14
+CONFIG_DRIVER_RTW=y
15
+
16
+# Driver interface for wired authenticator
17
+#CONFIG_DRIVER_WIRED=y
18
+
19
+# Driver interface for madwifi driver
20
+#CONFIG_DRIVER_MADWIFI=y
21
+#CFLAGS += -I../../madwifi # change to the madwifi source directory
22
+
23
+# Driver interface for drivers using the nl80211 kernel interface
24
+#CONFIG_DRIVER_NL80211=y
25
+
26
+# Driver interface for FreeBSD net80211 layer (e.g., Atheros driver)
27
+#CONFIG_DRIVER_BSD=y
28
+#CONFIG_SUPPORT_RTW_DRIVER=y
29
+#CFLAGS += -I/usr/local/include
30
+#LIBS += -L/usr/local/lib
31
+#LIBS_p += -L/usr/local/lib
32
+#LIBS_c += -L/usr/local/lib
33
+
34
+# Driver interface for no driver (e.g., RADIUS server only)
35
+#CONFIG_DRIVER_NONE=y
36
+
37
+# IEEE 802.11F/IAPP
38
+#CONFIG_IAPP=y
39
+
40
+# WPA2/IEEE 802.11i RSN pre-authentication
41
+#CONFIG_RSN_PREAUTH=y
42
+
43
+# PeerKey handshake for Station to Station Link (IEEE 802.11e DLS)
44
+#CONFIG_PEERKEY=y
45
+
46
+# IEEE 802.11w (management frame protection)
47
+# This version is an experimental implementation based on IEEE 802.11w/D1.0
48
+# draft and is subject to change since the standard has not yet been finalized.
49
+# Driver support is also needed for IEEE 802.11w.
50
+#CONFIG_IEEE80211W=y
51
+
52
+# Integrated EAP server
53
+CONFIG_EAP=y
54
+
55
+# EAP-MD5 for the integrated EAP server
56
+#CONFIG_EAP_MD5=y
57
+
58
+# EAP-TLS for the integrated EAP server
59
+#CONFIG_EAP_TLS=y
60
+
61
+# EAP-MSCHAPv2 for the integrated EAP server
62
+#CONFIG_EAP_MSCHAPV2=y
63
+
64
+# EAP-PEAP for the integrated EAP server
65
+#CONFIG_EAP_PEAP=y
66
+
67
+# EAP-GTC for the integrated EAP server
68
+#CONFIG_EAP_GTC=y
69
+
70
+# EAP-TTLS for the integrated EAP server
71
+#CONFIG_EAP_TTLS=y
72
+
73
+# EAP-SIM for the integrated EAP server
74
+#CONFIG_EAP_SIM=y
75
+
76
+# EAP-AKA for the integrated EAP server
77
+#CONFIG_EAP_AKA=y
78
+
79
+# EAP-AKA' for the integrated EAP server
80
+# This requires CONFIG_EAP_AKA to be enabled, too.
81
+#CONFIG_EAP_AKA_PRIME=y
82
+
83
+# EAP-PAX for the integrated EAP server
84
+#CONFIG_EAP_PAX=y
85
+
86
+# EAP-PSK for the integrated EAP server (this is _not_ needed for WPA-PSK)
87
+#CONFIG_EAP_PSK=y
88
+
89
+# EAP-SAKE for the integrated EAP server
90
+#CONFIG_EAP_SAKE=y
91
+
92
+# EAP-GPSK for the integrated EAP server
93
+#CONFIG_EAP_GPSK=y
94
+# Include support for optional SHA256 cipher suite in EAP-GPSK
95
+#CONFIG_EAP_GPSK_SHA256=y
96
+
97
+# EAP-FAST for the integrated EAP server
98
+# Note: Default OpenSSL package does not include support for all the
99
+# functionality needed for EAP-FAST. If EAP-FAST is enabled with OpenSSL,
100
+# the OpenSSL library must be patched (openssl-0.9.9-session-ticket.patch)
101
+# to add the needed functions.
102
+#CONFIG_EAP_FAST=y
103
+
104
+# Wi-Fi Protected Setup (WPS)
105
+CONFIG_WPS=y
106
+# Enable WSC 2.0 support
107
+#CONFIG_WPS2=y
108
+# Enable UPnP support for external WPS Registrars
109
+#CONFIG_WPS_UPNP=y
110
+
111
+CONFIG_TLS=internal
112
+CONFIG_INTERNAL_LIBTOMMATH=y
113
+
114
+# EAP-IKEv2
115
+#CONFIG_EAP_IKEV2=y
116
+
117
+# Trusted Network Connect (EAP-TNC)
118
+#CONFIG_EAP_TNC=y
119
+
120
+# PKCS#12 (PFX) support (used to read private key and certificate file from
121
+# a file that usually has extension .p12 or .pfx)
122
+#CONFIG_PKCS12=y
123
+
124
+# RADIUS authentication server. This provides access to the integrated EAP
125
+# server from external hosts using RADIUS.
126
+#CONFIG_RADIUS_SERVER=y
127
+
128
+# Build IPv6 support for RADIUS operations
129
+#CONFIG_IPV6=y
130
+
131
+# IEEE Std 802.11r-2008 (Fast BSS Transition)
132
+#CONFIG_IEEE80211R=y
133
+
134
+# Use the hostapd's IEEE 802.11 authentication (ACL), but without
135
+# the IEEE 802.11 Management capability (e.g., madwifi or FreeBSD/net80211)
136
+#CONFIG_DRIVER_RADIUS_ACL=y
137
+
138
+# IEEE 802.11n (High Throughput) support
139
+CONFIG_IEEE80211N=y
140
+
141
+# Remove debugging code that is printing out debug messages to stdout.
142
+# This can be used to reduce the size of the hostapd considerably if debugging
143
+# code is not needed.
144
+#CONFIG_NO_STDOUT_DEBUG=y
145
+
146
+# Add support for writing debug log to a file: -f /tmp/hostapd.log
147
+# Disabled by default.
148
+#CONFIG_DEBUG_FILE=y
149
+
150
+# Remove support for RADIUS accounting
151
+#CONFIG_NO_ACCOUNTING=y
152
+
153
+# Remove support for RADIUS
154
+#CONFIG_NO_RADIUS=y
155
+
156
+# Remove support for VLANs
157
+#CONFIG_NO_VLAN=y
158
+
159
+# Enable support for fully dynamic VLANs. This enables hostapd to
160
+# automatically create bridge and VLAN interfaces if necessary.
161
+#CONFIG_FULL_DYNAMIC_VLAN=y
162
+
163
+# Remove support for dumping state into a file on SIGUSR1 signal
164
+# This can be used to reduce binary size at the cost of disabling a debugging
165
+# option.
166
+#CONFIG_NO_DUMP_STATE=y
167
+
168
+# Enable tracing code for developer debugging
169
+# This tracks use of memory allocations and other registrations and reports
170
+# incorrect use with a backtrace of call (or allocation) location.
171
+#CONFIG_WPA_TRACE=y
172
+# For BSD, comment out these.
173
+#LIBS += -lexecinfo
174
+#LIBS_p += -lexecinfo
175
+#LIBS_c += -lexecinfo
176
+
177
+# Use libbfd to get more details for developer debugging
178
+# This enables use of libbfd to get more detailed symbols for the backtraces
179
+# generated by CONFIG_WPA_TRACE=y.
180
+#CONFIG_WPA_TRACE_BFD=y
181
+# For BSD, comment out these.
182
+#LIBS += -lbfd -liberty -lz
183
+#LIBS_p += -lbfd -liberty -lz
184
+#LIBS_c += -lbfd -liberty -lz
185
+
186
+# hostapd depends on strong random number generation being available from the
187
+# operating system. os_get_random() function is used to fetch random data when
188
+# needed, e.g., for key generation. On Linux and BSD systems, this works by
189
+# reading /dev/urandom. It should be noted that the OS entropy pool needs to be
190
+# properly initialized before hostapd is started. This is important especially
191
+# on embedded devices that do not have a hardware random number generator and
192
+# may by default start up with minimal entropy available for random number
193
+# generation.
194
+#
195
+# As a safety net, hostapd is by default trying to internally collect
196
+# additional entropy for generating random data to mix in with the data
197
+# fetched from the OS. This by itself is not considered to be very strong, but
198
+# it may help in cases where the system pool is not initialized properly.
199
+# However, it is very strongly recommended that the system pool is initialized
200
+# with enough entropy either by using hardware assisted random number
201
+# generatior or by storing state over device reboots.
202
+#
203
+# If the os_get_random() is known to provide strong ramdom data (e.g., on
204
+# Linux/BSD, the board in question is known to have reliable source of random
205
+# data from /dev/urandom), the internal hostapd random pool can be disabled.
206
+# This will save some in binary size and CPU use. However, this should only be
207
+# considered for builds that are known to be used on devices that meet the
208
+# requirements described above.
209
+#CONFIG_NO_RANDOM_POOL=y

+ 209
- 0
hostapd/.config_bsd Näytä tiedosto

@@ -0,0 +1,209 @@
1
+# Example hostapd build time configuration
2
+#
3
+# This file lists the configuration options that are used when building the
4
+# hostapd binary. All lines starting with # are ignored. Configuration option
5
+# lines must be commented out complete, if they are not to be included, i.e.,
6
+# just setting VARIABLE=n is not disabling that variable.
7
+#
8
+# This file is included in Makefile, so variables like CFLAGS and LIBS can also
9
+# be modified from here. In most cass, these lines should use += in order not
10
+# to override previous values of the variables.
11
+
12
+# Driver interface for Host AP driver
13
+#CONFIG_DRIVER_HOSTAP=y
14
+#CONFIG_DRIVER_RTW=y
15
+
16
+# Driver interface for wired authenticator
17
+#CONFIG_DRIVER_WIRED=y
18
+
19
+# Driver interface for madwifi driver
20
+#CONFIG_DRIVER_MADWIFI=y
21
+#CFLAGS += -I../../madwifi # change to the madwifi source directory
22
+
23
+# Driver interface for drivers using the nl80211 kernel interface
24
+#CONFIG_DRIVER_NL80211=y
25
+
26
+# Driver interface for FreeBSD net80211 layer (e.g., Atheros driver)
27
+CONFIG_DRIVER_BSD=y
28
+CONFIG_SUPPORT_RTW_DRIVER=y
29
+#CFLAGS += -I/usr/local/include
30
+#LIBS += -L/usr/local/lib
31
+#LIBS_p += -L/usr/local/lib
32
+#LIBS_c += -L/usr/local/lib
33
+
34
+# Driver interface for no driver (e.g., RADIUS server only)
35
+#CONFIG_DRIVER_NONE=y
36
+
37
+# IEEE 802.11F/IAPP
38
+#CONFIG_IAPP=y
39
+
40
+# WPA2/IEEE 802.11i RSN pre-authentication
41
+#CONFIG_RSN_PREAUTH=y
42
+
43
+# PeerKey handshake for Station to Station Link (IEEE 802.11e DLS)
44
+#CONFIG_PEERKEY=y
45
+
46
+# IEEE 802.11w (management frame protection)
47
+# This version is an experimental implementation based on IEEE 802.11w/D1.0
48
+# draft and is subject to change since the standard has not yet been finalized.
49
+# Driver support is also needed for IEEE 802.11w.
50
+#CONFIG_IEEE80211W=y
51
+
52
+# Integrated EAP server
53
+CONFIG_EAP=y
54
+
55
+# EAP-MD5 for the integrated EAP server
56
+#CONFIG_EAP_MD5=y
57
+
58
+# EAP-TLS for the integrated EAP server
59
+#CONFIG_EAP_TLS=y
60
+
61
+# EAP-MSCHAPv2 for the integrated EAP server
62
+#CONFIG_EAP_MSCHAPV2=y
63
+
64
+# EAP-PEAP for the integrated EAP server
65
+#CONFIG_EAP_PEAP=y
66
+
67
+# EAP-GTC for the integrated EAP server
68
+#CONFIG_EAP_GTC=y
69
+
70
+# EAP-TTLS for the integrated EAP server
71
+#CONFIG_EAP_TTLS=y
72
+
73
+# EAP-SIM for the integrated EAP server
74
+#CONFIG_EAP_SIM=y
75
+
76
+# EAP-AKA for the integrated EAP server
77
+#CONFIG_EAP_AKA=y
78
+
79
+# EAP-AKA' for the integrated EAP server
80
+# This requires CONFIG_EAP_AKA to be enabled, too.
81
+#CONFIG_EAP_AKA_PRIME=y
82
+
83
+# EAP-PAX for the integrated EAP server
84
+#CONFIG_EAP_PAX=y
85
+
86
+# EAP-PSK for the integrated EAP server (this is _not_ needed for WPA-PSK)
87
+#CONFIG_EAP_PSK=y
88
+
89
+# EAP-SAKE for the integrated EAP server
90
+#CONFIG_EAP_SAKE=y
91
+
92
+# EAP-GPSK for the integrated EAP server
93
+#CONFIG_EAP_GPSK=y
94
+# Include support for optional SHA256 cipher suite in EAP-GPSK
95
+#CONFIG_EAP_GPSK_SHA256=y
96
+
97
+# EAP-FAST for the integrated EAP server
98
+# Note: Default OpenSSL package does not include support for all the
99
+# functionality needed for EAP-FAST. If EAP-FAST is enabled with OpenSSL,
100
+# the OpenSSL library must be patched (openssl-0.9.9-session-ticket.patch)
101
+# to add the needed functions.
102
+#CONFIG_EAP_FAST=y
103
+
104
+# Wi-Fi Protected Setup (WPS)
105
+CONFIG_WPS=y
106
+# Enable WSC 2.0 support
107
+#CONFIG_WPS2=y
108
+# Enable UPnP support for external WPS Registrars
109
+#CONFIG_WPS_UPNP=y
110
+
111
+CONFIG_TLS=internal
112
+CONFIG_INTERNAL_LIBTOMMATH=y
113
+
114
+# EAP-IKEv2
115
+#CONFIG_EAP_IKEV2=y
116
+
117
+# Trusted Network Connect (EAP-TNC)
118
+#CONFIG_EAP_TNC=y
119
+
120
+# PKCS#12 (PFX) support (used to read private key and certificate file from
121
+# a file that usually has extension .p12 or .pfx)
122
+#CONFIG_PKCS12=y
123
+
124
+# RADIUS authentication server. This provides access to the integrated EAP
125
+# server from external hosts using RADIUS.
126
+#CONFIG_RADIUS_SERVER=y
127
+
128
+# Build IPv6 support for RADIUS operations
129
+#CONFIG_IPV6=y
130
+
131
+# IEEE Std 802.11r-2008 (Fast BSS Transition)
132
+#CONFIG_IEEE80211R=y
133
+
134
+# Use the hostapd's IEEE 802.11 authentication (ACL), but without
135
+# the IEEE 802.11 Management capability (e.g., madwifi or FreeBSD/net80211)
136
+#CONFIG_DRIVER_RADIUS_ACL=y
137
+
138
+# IEEE 802.11n (High Throughput) support
139
+CONFIG_IEEE80211N=y
140
+
141
+# Remove debugging code that is printing out debug messages to stdout.
142
+# This can be used to reduce the size of the hostapd considerably if debugging
143
+# code is not needed.
144
+#CONFIG_NO_STDOUT_DEBUG=y
145
+
146
+# Add support for writing debug log to a file: -f /tmp/hostapd.log
147
+# Disabled by default.
148
+#CONFIG_DEBUG_FILE=y
149
+
150
+# Remove support for RADIUS accounting
151
+#CONFIG_NO_ACCOUNTING=y
152
+
153
+# Remove support for RADIUS
154
+#CONFIG_NO_RADIUS=y
155
+
156
+# Remove support for VLANs
157
+#CONFIG_NO_VLAN=y
158
+
159
+# Enable support for fully dynamic VLANs. This enables hostapd to
160
+# automatically create bridge and VLAN interfaces if necessary.
161
+#CONFIG_FULL_DYNAMIC_VLAN=y
162
+
163
+# Remove support for dumping state into a file on SIGUSR1 signal
164
+# This can be used to reduce binary size at the cost of disabling a debugging
165
+# option.
166
+#CONFIG_NO_DUMP_STATE=y
167
+
168
+# Enable tracing code for developer debugging
169
+# This tracks use of memory allocations and other registrations and reports
170
+# incorrect use with a backtrace of call (or allocation) location.
171
+#CONFIG_WPA_TRACE=y
172
+# For BSD, comment out these.
173
+#LIBS += -lexecinfo
174
+#LIBS_p += -lexecinfo
175
+#LIBS_c += -lexecinfo
176
+
177
+# Use libbfd to get more details for developer debugging
178
+# This enables use of libbfd to get more detailed symbols for the backtraces
179
+# generated by CONFIG_WPA_TRACE=y.
180
+#CONFIG_WPA_TRACE_BFD=y
181
+# For BSD, comment out these.
182
+#LIBS += -lbfd -liberty -lz
183
+#LIBS_p += -lbfd -liberty -lz
184
+#LIBS_c += -lbfd -liberty -lz
185
+
186
+# hostapd depends on strong random number generation being available from the
187
+# operating system. os_get_random() function is used to fetch random data when
188
+# needed, e.g., for key generation. On Linux and BSD systems, this works by
189
+# reading /dev/urandom. It should be noted that the OS entropy pool needs to be
190
+# properly initialized before hostapd is started. This is important especially
191
+# on embedded devices that do not have a hardware random number generator and
192
+# may by default start up with minimal entropy available for random number
193
+# generation.
194
+#
195
+# As a safety net, hostapd is by default trying to internally collect
196
+# additional entropy for generating random data to mix in with the data
197
+# fetched from the OS. This by itself is not considered to be very strong, but
198
+# it may help in cases where the system pool is not initialized properly.
199
+# However, it is very strongly recommended that the system pool is initialized
200
+# with enough entropy either by using hardware assisted random number
201
+# generatior or by storing state over device reboots.
202
+#
203
+# If the os_get_random() is known to provide strong ramdom data (e.g., on
204
+# Linux/BSD, the board in question is known to have reliable source of random
205
+# data from /dev/urandom), the internal hostapd random pool can be disabled.
206
+# This will save some in binary size and CPU use. However, this should only be
207
+# considered for builds that are known to be used on devices that meet the
208
+# requirements described above.
209
+#CONFIG_NO_RANDOM_POOL=y

+ 817
- 0
hostapd/Android.mk Näytä tiedosto

@@ -0,0 +1,817 @@
1
+LOCAL_PATH := $(call my-dir)
2
+
3
+WPA_BUILD_HOSTAPD := false
4
+ifneq ($(TARGET_SIMULATOR),true)
5
+  ifneq ($(BOARD_HOSTAPD_DRIVER),)
6
+    WPA_BUILD_HOSTAPD := true
7
+    #CONFIG_DRIVER_$(BOARD_HOSTAPD_DRIVER) := y
8
+    CONFIG_DRIVER_RTW := y
9
+  endif
10
+endif
11
+
12
+include $(LOCAL_PATH)/.config
13
+
14
+# To ignore possible wrong network configurations
15
+L_CFLAGS = -DWPA_IGNORE_CONFIG_ERRORS
16
+
17
+# To force sizeof(enum) = 4
18
+ifeq ($(TARGET_ARCH),arm)
19
+L_CFLAGS += -mabi=aapcs-linux
20
+endif
21
+
22
+# To allow non-ASCII characters in SSID
23
+L_CFLAGS += -DWPA_UNICODE_SSID
24
+
25
+# OpenSSL is configured without engines on Android
26
+L_CFLAGS += -DOPENSSL_NO_ENGINE
27
+
28
+INCLUDES = $(LOCAL_PATH)
29
+INCLUDES += $(LOCAL_PATH)/src
30
+INCLUDES += $(LOCAL_PATH)/src/utils
31
+INCLUDES += external/openssl/include
32
+INCLUDES += frameworks/base/cmds/keystore
33
+ifdef CONFIG_DRIVER_NL80211
34
+INCLUDES += external/libnl_2/include
35
+endif
36
+
37
+
38
+ifndef CONFIG_OS
39
+ifdef CONFIG_NATIVE_WINDOWS
40
+CONFIG_OS=win32
41
+else
42
+CONFIG_OS=unix
43
+endif
44
+endif
45
+
46
+ifeq ($(CONFIG_OS), internal)
47
+L_CFLAGS += -DOS_NO_C_LIB_DEFINES
48
+endif
49
+
50
+ifdef CONFIG_NATIVE_WINDOWS
51
+L_CFLAGS += -DCONFIG_NATIVE_WINDOWS
52
+LIBS += -lws2_32
53
+endif
54
+
55
+OBJS = main.c
56
+OBJS += config_file.c
57
+
58
+OBJS += src/ap/hostapd.c
59
+OBJS += src/ap/wpa_auth_glue.c
60
+OBJS += src/ap/drv_callbacks.c
61
+OBJS += src/ap/ap_drv_ops.c
62
+OBJS += src/ap/utils.c
63
+OBJS += src/ap/authsrv.c
64
+OBJS += src/ap/ieee802_1x.c
65
+OBJS += src/ap/ap_config.c
66
+OBJS += src/ap/ieee802_11_auth.c
67
+OBJS += src/ap/sta_info.c
68
+OBJS += src/ap/wpa_auth.c
69
+OBJS += src/ap/tkip_countermeasures.c
70
+OBJS += src/ap/ap_mlme.c
71
+OBJS += src/ap/wpa_auth_ie.c
72
+OBJS += src/ap/preauth_auth.c
73
+OBJS += src/ap/pmksa_cache_auth.c
74
+OBJS_d =
75
+OBJS_p =
76
+LIBS =
77
+LIBS_c =
78
+HOBJS =
79
+LIBS_h =
80
+
81
+NEED_RC4=y
82
+NEED_AES=y
83
+NEED_MD5=y
84
+NEED_SHA1=y
85
+
86
+OBJS += src/drivers/drivers.c
87
+L_CFLAGS += -DHOSTAPD
88
+
89
+ifdef CONFIG_WPA_TRACE
90
+L_CFLAGS += -DWPA_TRACE
91
+OBJS += src/utils/trace.c
92
+HOBJS += src/utils/trace.c
93
+LDFLAGS += -rdynamic
94
+L_CFLAGS += -funwind-tables
95
+ifdef CONFIG_WPA_TRACE_BFD
96
+L_CFLAGS += -DWPA_TRACE_BFD
97
+LIBS += -lbfd
98
+LIBS_c += -lbfd
99
+LIBS_h += -lbfd
100
+endif
101
+endif
102
+
103
+OBJS += src/utils/eloop.c
104
+OBJS += src/utils/common.c
105
+OBJS += src/utils/wpa_debug.c
106
+OBJS += src/utils/wpabuf.c
107
+OBJS += src/utils/os_$(CONFIG_OS).c
108
+OBJS += src/utils/ip_addr.c
109
+
110
+OBJS += src/common/ieee802_11_common.c
111
+OBJS += src/common/wpa_common.c
112
+
113
+OBJS += src/eapol_auth/eapol_auth_sm.c
114
+
115
+
116
+ifndef CONFIG_NO_DUMP_STATE
117
+# define HOSTAPD_DUMP_STATE to include SIGUSR1 handler for dumping state to
118
+# a file (undefine it, if you want to save in binary size)
119
+L_CFLAGS += -DHOSTAPD_DUMP_STATE
120
+OBJS += dump_state.c
121
+OBJS += src/eapol_auth/eapol_auth_dump.c
122
+endif
123
+
124
+ifdef CONFIG_NO_RADIUS
125
+L_CFLAGS += -DCONFIG_NO_RADIUS
126
+CONFIG_NO_ACCOUNTING=y
127
+else
128
+OBJS += src/radius/radius.c
129
+OBJS += src/radius/radius_client.c
130
+endif
131
+
132
+ifdef CONFIG_NO_ACCOUNTING
133
+L_CFLAGS += -DCONFIG_NO_ACCOUNTING
134
+else
135
+OBJS += src/ap/accounting.c
136
+endif
137
+
138
+ifdef CONFIG_NO_VLAN
139
+L_CFLAGS += -DCONFIG_NO_VLAN
140
+else
141
+OBJS += src/ap/vlan_init.c
142
+endif
143
+
144
+ifdef CONFIG_NO_CTRL_IFACE
145
+L_CFLAGS += -DCONFIG_NO_CTRL_IFACE
146
+else
147
+OBJS += ctrl_iface.c
148
+OBJS += src/ap/ctrl_iface_ap.c
149
+endif
150
+
151
+OBJS += src/crypto/md5.c
152
+
153
+L_CFLAGS += -DCONFIG_CTRL_IFACE -DCONFIG_CTRL_IFACE_UNIX
154
+
155
+ifdef CONFIG_IAPP
156
+L_CFLAGS += -DCONFIG_IAPP
157
+OBJS += src/ap/iapp.c
158
+endif
159
+
160
+ifdef CONFIG_RSN_PREAUTH
161
+L_CFLAGS += -DCONFIG_RSN_PREAUTH
162
+CONFIG_L2_PACKET=y
163
+endif
164
+
165
+ifdef CONFIG_PEERKEY
166
+L_CFLAGS += -DCONFIG_PEERKEY
167
+OBJS += src/ap/peerkey_auth.c
168
+endif
169
+
170
+ifdef CONFIG_IEEE80211W
171
+L_CFLAGS += -DCONFIG_IEEE80211W
172
+NEED_SHA256=y
173
+NEED_AES_OMAC1=y
174
+endif
175
+
176
+ifdef CONFIG_IEEE80211R
177
+L_CFLAGS += -DCONFIG_IEEE80211R
178
+OBJS += src/ap/wpa_auth_ft.c
179
+NEED_SHA256=y
180
+NEED_AES_OMAC1=y
181
+NEED_AES_UNWRAP=y
182
+endif
183
+
184
+ifdef CONFIG_IEEE80211N
185
+L_CFLAGS += -DCONFIG_IEEE80211N
186
+endif
187
+
188
+include $(LOCAL_PATH)/src/drivers/drivers.mk
189
+
190
+OBJS += $(DRV_AP_OBJS)
191
+L_CFLAGS += $(DRV_AP_CFLAGS)
192
+LDFLAGS += $(DRV_AP_LDFLAGS)
193
+LIBS += $(DRV_AP_LIBS)
194
+
195
+ifdef CONFIG_L2_PACKET
196
+ifdef CONFIG_DNET_PCAP
197
+ifdef CONFIG_L2_FREEBSD
198
+LIBS += -lpcap
199
+OBJS += src/l2_packet/l2_packet_freebsd.c
200
+else
201
+LIBS += -ldnet -lpcap
202
+OBJS += src/l2_packet/l2_packet_pcap.c
203
+endif
204
+else
205
+OBJS += src/l2_packet/l2_packet_linux.c
206
+endif
207
+else
208
+OBJS += src/l2_packet/l2_packet_none.c
209
+endif
210
+
211
+
212
+ifdef CONFIG_EAP_MD5
213
+L_CFLAGS += -DEAP_SERVER_MD5
214
+OBJS += src/eap_server/eap_server_md5.c
215
+CHAP=y
216
+endif
217
+
218
+ifdef CONFIG_EAP_TLS
219
+L_CFLAGS += -DEAP_SERVER_TLS
220
+OBJS += src/eap_server/eap_server_tls.c
221
+TLS_FUNCS=y
222
+endif
223
+
224
+ifdef CONFIG_EAP_PEAP
225
+L_CFLAGS += -DEAP_SERVER_PEAP
226
+OBJS += src/eap_server/eap_server_peap.c
227
+OBJS += src/eap_common/eap_peap_common.c
228
+TLS_FUNCS=y
229
+CONFIG_EAP_MSCHAPV2=y
230
+endif
231
+
232
+ifdef CONFIG_EAP_TTLS
233
+L_CFLAGS += -DEAP_SERVER_TTLS
234
+OBJS += src/eap_server/eap_server_ttls.c
235
+TLS_FUNCS=y
236
+CHAP=y
237
+endif
238
+
239
+ifdef CONFIG_EAP_MSCHAPV2
240
+L_CFLAGS += -DEAP_SERVER_MSCHAPV2
241
+OBJS += src/eap_server/eap_server_mschapv2.c
242
+MS_FUNCS=y
243
+endif
244
+
245
+ifdef CONFIG_EAP_GTC
246
+L_CFLAGS += -DEAP_SERVER_GTC
247
+OBJS += src/eap_server/eap_server_gtc.c
248
+endif
249
+
250
+ifdef CONFIG_EAP_SIM
251
+L_CFLAGS += -DEAP_SERVER_SIM
252
+OBJS += src/eap_server/eap_server_sim.c
253
+CONFIG_EAP_SIM_COMMON=y
254
+NEED_AES_CBC=y
255
+endif
256
+
257
+ifdef CONFIG_EAP_AKA
258
+L_CFLAGS += -DEAP_SERVER_AKA
259
+OBJS += src/eap_server/eap_server_aka.c
260
+CONFIG_EAP_SIM_COMMON=y
261
+NEED_SHA256=y
262
+NEED_AES_CBC=y
263
+endif
264
+
265
+ifdef CONFIG_EAP_AKA_PRIME
266
+L_CFLAGS += -DEAP_SERVER_AKA_PRIME
267
+endif
268
+
269
+ifdef CONFIG_EAP_SIM_COMMON
270
+OBJS += src/eap_common/eap_sim_common.c
271
+# Example EAP-SIM/AKA interface for GSM/UMTS authentication. This can be
272
+# replaced with another file implementating the interface specified in
273
+# eap_sim_db.h.
274
+OBJS += src/eap_server/eap_sim_db.c
275
+NEED_FIPS186_2_PRF=y
276
+endif
277
+
278
+ifdef CONFIG_EAP_PAX
279
+L_CFLAGS += -DEAP_SERVER_PAX
280
+OBJS += src/eap_server/eap_server_pax.c src/eap_common/eap_pax_common.c
281
+endif
282
+
283
+ifdef CONFIG_EAP_PSK
284
+L_CFLAGS += -DEAP_SERVER_PSK
285
+OBJS += src/eap_server/eap_server_psk.c src/eap_common/eap_psk_common.c
286
+NEED_AES_OMAC1=y
287
+NEED_AES_ENCBLOCK=y
288
+NEED_AES_EAX=y
289
+endif
290
+
291
+ifdef CONFIG_EAP_SAKE
292
+L_CFLAGS += -DEAP_SERVER_SAKE
293
+OBJS += src/eap_server/eap_server_sake.c src/eap_common/eap_sake_common.c
294
+endif
295
+
296
+ifdef CONFIG_EAP_GPSK
297
+L_CFLAGS += -DEAP_SERVER_GPSK
298
+OBJS += src/eap_server/eap_server_gpsk.c src/eap_common/eap_gpsk_common.c
299
+ifdef CONFIG_EAP_GPSK_SHA256
300
+L_CFLAGS += -DEAP_SERVER_GPSK_SHA256
301
+endif
302
+NEED_SHA256=y
303
+NEED_AES_OMAC1=y
304
+endif
305
+
306
+ifdef CONFIG_EAP_PWD
307
+L_CFLAGS += -DEAP_SERVER_PWD
308
+OBJS += src/eap_server/eap_server_pwd.c src/eap_common/eap_pwd_common.c
309
+NEED_SHA256=y
310
+endif
311
+
312
+ifdef CONFIG_EAP_VENDOR_TEST
313
+L_CFLAGS += -DEAP_SERVER_VENDOR_TEST
314
+OBJS += src/eap_server/eap_server_vendor_test.c
315
+endif
316
+
317
+ifdef CONFIG_EAP_FAST
318
+L_CFLAGS += -DEAP_SERVER_FAST
319
+OBJS += src/eap_server/eap_server_fast.c
320
+OBJS += src/eap_common/eap_fast_common.c
321
+TLS_FUNCS=y
322
+NEED_T_PRF=y
323
+NEED_AES_UNWRAP=y
324
+endif
325
+
326
+ifdef CONFIG_WPS
327
+ifdef CONFIG_WPS2
328
+L_CFLAGS += -DCONFIG_WPS2
329
+endif
330
+
331
+L_CFLAGS += -DCONFIG_WPS -DEAP_SERVER_WSC
332
+OBJS += src/utils/uuid.c
333
+OBJS += src/ap/wps_hostapd.c
334
+OBJS += src/eap_server/eap_server_wsc.c src/eap_common/eap_wsc_common.c
335
+OBJS += src/wps/wps.c
336
+OBJS += src/wps/wps_common.c
337
+OBJS += src/wps/wps_attr_parse.c
338
+OBJS += src/wps/wps_attr_build.c
339
+OBJS += src/wps/wps_attr_process.c
340
+OBJS += src/wps/wps_dev_attr.c
341
+OBJS += src/wps/wps_enrollee.c
342
+OBJS += src/wps/wps_registrar.c
343
+NEED_DH_GROUPS=y
344
+NEED_SHA256=y
345
+NEED_BASE64=y
346
+NEED_AES_CBC=y
347
+NEED_MODEXP=y
348
+CONFIG_EAP=y
349
+
350
+ifdef CONFIG_WPS_UFD
351
+L_CFLAGS += -DCONFIG_WPS_UFD
352
+OBJS += src/wps/wps_ufd.c
353
+NEED_WPS_OOB=y
354
+endif
355
+
356
+ifdef CONFIG_WPS_NFC
357
+L_CFLAGS += -DCONFIG_WPS_NFC
358
+OBJS += src/wps/ndef.c
359
+OBJS += src/wps/wps_nfc.c
360
+NEED_WPS_OOB=y
361
+ifdef CONFIG_WPS_NFC_PN531
362
+PN531_PATH ?= /usr/local/src/nfc
363
+L_CFLAGS += -DCONFIG_WPS_NFC_PN531
364
+L_CFLAGS += -I${PN531_PATH}/inc
365
+OBJS += src/wps/wps_nfc_pn531.c
366
+LIBS += ${PN531_PATH}/lib/wpsnfc.dll
367
+LIBS += ${PN531_PATH}/lib/libnfc_mapping_pn53x.dll
368
+endif
369
+endif
370
+
371
+ifdef NEED_WPS_OOB
372
+L_CFLAGS += -DCONFIG_WPS_OOB
373
+endif
374
+
375
+ifdef CONFIG_WPS_UPNP
376
+L_CFLAGS += -DCONFIG_WPS_UPNP
377
+OBJS += src/wps/wps_upnp.c
378
+OBJS += src/wps/wps_upnp_ssdp.c
379
+OBJS += src/wps/wps_upnp_web.c
380
+OBJS += src/wps/wps_upnp_event.c
381
+OBJS += src/wps/wps_upnp_ap.c
382
+OBJS += src/wps/upnp_xml.c
383
+OBJS += src/wps/httpread.c
384
+OBJS += src/wps/http_client.c
385
+OBJS += src/wps/http_server.c
386
+endif
387
+
388
+ifdef CONFIG_WPS_STRICT
389
+L_CFLAGS += -DCONFIG_WPS_STRICT
390
+OBJS += src/wps/wps_validate.c
391
+endif
392
+
393
+ifdef CONFIG_WPS_TESTING
394
+L_CFLAGS += -DCONFIG_WPS_TESTING
395
+endif
396
+
397
+endif
398
+
399
+ifdef CONFIG_EAP_IKEV2
400
+L_CFLAGS += -DEAP_SERVER_IKEV2
401
+OBJS += src/eap_server/eap_server_ikev2.c src/eap_server/ikev2.c
402
+OBJS += src/eap_common/eap_ikev2_common.c src/eap_common/ikev2_common.c
403
+NEED_DH_GROUPS=y
404
+NEED_DH_GROUPS_ALL=y
405
+NEED_MODEXP=y
406
+NEED_CIPHER=y
407
+endif
408
+
409
+ifdef CONFIG_EAP_TNC
410
+L_CFLAGS += -DEAP_SERVER_TNC
411
+OBJS += src/eap_server/eap_server_tnc.c
412
+OBJS += src/eap_server/tncs.c
413
+NEED_BASE64=y
414
+ifndef CONFIG_DRIVER_BSD
415
+LIBS += -ldl
416
+endif
417
+endif
418
+
419
+# Basic EAP functionality is needed for EAPOL
420
+OBJS += eap_register.c
421
+OBJS += src/eap_server/eap_server.c
422
+OBJS += src/eap_common/eap_common.c
423
+OBJS += src/eap_server/eap_server_methods.c
424
+OBJS += src/eap_server/eap_server_identity.c
425
+L_CFLAGS += -DEAP_SERVER_IDENTITY
426
+
427
+ifdef CONFIG_EAP
428
+L_CFLAGS += -DEAP_SERVER
429
+endif
430
+
431
+ifdef CONFIG_PKCS12
432
+L_CFLAGS += -DPKCS12_FUNCS
433
+endif
434
+
435
+ifdef MS_FUNCS
436
+OBJS += src/crypto/ms_funcs.c
437
+NEED_DES=y
438
+NEED_MD4=y
439
+endif
440
+
441
+ifdef CHAP
442
+OBJS += src/eap_common/chap.c
443
+endif
444
+
445
+ifdef TLS_FUNCS
446
+NEED_DES=y
447
+# Shared TLS functions (needed for EAP_TLS, EAP_PEAP, and EAP_TTLS)
448
+L_CFLAGS += -DEAP_TLS_FUNCS
449
+OBJS += src/eap_server/eap_server_tls_common.c
450
+NEED_TLS_PRF=y
451
+endif
452
+
453
+ifndef CONFIG_TLS
454
+CONFIG_TLS=openssl
455
+endif
456
+
457
+ifeq ($(CONFIG_TLS), openssl)
458
+ifdef TLS_FUNCS
459
+OBJS += src/crypto/tls_openssl.c
460
+LIBS += -lssl
461
+endif
462
+OBJS += src/crypto/crypto_openssl.c
463
+HOBJS += src/crypto/crypto_openssl.c
464
+ifdef NEED_FIPS186_2_PRF
465
+OBJS += src/crypto/fips_prf_openssl.c
466
+endif
467
+LIBS += -lcrypto
468
+LIBS_h += -lcrypto
469
+endif
470
+
471
+ifeq ($(CONFIG_TLS), gnutls)
472
+ifdef TLS_FUNCS
473
+OBJS += src/crypto/tls_gnutls.c
474
+LIBS += -lgnutls -lgpg-error
475
+ifdef CONFIG_GNUTLS_EXTRA
476
+L_CFLAGS += -DCONFIG_GNUTLS_EXTRA
477
+LIBS += -lgnutls-extra
478
+endif
479
+endif
480
+OBJS += src/crypto/crypto_gnutls.c
481
+HOBJS += src/crypto/crypto_gnutls.c
482
+ifdef NEED_FIPS186_2_PRF
483
+OBJS += src/crypto/fips_prf_gnutls.c
484
+endif
485
+LIBS += -lgcrypt
486
+LIBS_h += -lgcrypt
487
+CONFIG_INTERNAL_SHA256=y
488
+CONFIG_INTERNAL_RC4=y
489
+CONFIG_INTERNAL_DH_GROUP5=y
490
+endif
491
+
492
+ifeq ($(CONFIG_TLS), schannel)
493
+ifdef TLS_FUNCS
494
+OBJS += src/crypto/tls_schannel.c
495
+endif
496
+OBJS += src/crypto/crypto_cryptoapi.c
497
+OBJS_p += src/crypto/crypto_cryptoapi.c
498
+CONFIG_INTERNAL_SHA256=y
499
+CONFIG_INTERNAL_RC4=y
500
+CONFIG_INTERNAL_DH_GROUP5=y
501
+endif
502
+
503
+ifeq ($(CONFIG_TLS), nss)
504
+ifdef TLS_FUNCS
505
+OBJS += src/crypto/tls_nss.c
506
+LIBS += -lssl3
507
+endif
508
+OBJS += src/crypto/crypto_nss.c
509
+ifdef NEED_FIPS186_2_PRF
510
+OBJS += src/crypto/fips_prf_nss.c
511
+endif
512
+LIBS += -lnss3
513
+LIBS_h += -lnss3
514
+CONFIG_INTERNAL_MD4=y
515
+CONFIG_INTERNAL_DH_GROUP5=y
516
+endif
517
+
518
+ifeq ($(CONFIG_TLS), internal)
519
+ifndef CONFIG_CRYPTO
520
+CONFIG_CRYPTO=internal
521
+endif
522
+ifdef TLS_FUNCS
523
+OBJS += src/crypto/crypto_internal-rsa.c
524
+OBJS += src/crypto/tls_internal.c
525
+OBJS += src/tls/tlsv1_common.c
526
+OBJS += src/tls/tlsv1_record.c
527
+OBJS += src/tls/tlsv1_cred.c
528
+OBJS += src/tls/tlsv1_server.c
529
+OBJS += src/tls/tlsv1_server_write.c
530
+OBJS += src/tls/tlsv1_server_read.c
531
+OBJS += src/tls/asn1.c
532
+OBJS += src/tls/rsa.c
533
+OBJS += src/tls/x509v3.c
534
+OBJS += src/tls/pkcs1.c
535
+OBJS += src/tls/pkcs5.c
536
+OBJS += src/tls/pkcs8.c
537
+NEED_SHA256=y
538
+NEED_BASE64=y
539
+NEED_TLS_PRF=y
540
+NEED_MODEXP=y
541
+NEED_CIPHER=y
542
+L_CFLAGS += -DCONFIG_TLS_INTERNAL
543
+L_CFLAGS += -DCONFIG_TLS_INTERNAL_SERVER
544
+endif
545
+ifdef NEED_CIPHER
546
+NEED_DES=y
547
+OBJS += src/crypto/crypto_internal-cipher.c
548
+endif
549
+ifdef NEED_MODEXP
550
+OBJS += src/crypto/crypto_internal-modexp.c
551
+OBJS += src/tls/bignum.c
552
+endif
553
+ifeq ($(CONFIG_CRYPTO), libtomcrypt)
554
+OBJS += src/crypto/crypto_libtomcrypt.c
555
+LIBS += -ltomcrypt -ltfm
556
+LIBS_h += -ltomcrypt -ltfm
557
+CONFIG_INTERNAL_SHA256=y
558
+CONFIG_INTERNAL_RC4=y
559
+CONFIG_INTERNAL_DH_GROUP5=y
560
+endif
561
+ifeq ($(CONFIG_CRYPTO), internal)
562
+OBJS += src/crypto/crypto_internal.c
563
+NEED_AES_DEC=y
564
+L_CFLAGS += -DCONFIG_CRYPTO_INTERNAL
565
+ifdef CONFIG_INTERNAL_LIBTOMMATH
566
+L_CFLAGS += -DCONFIG_INTERNAL_LIBTOMMATH
567
+ifdef CONFIG_INTERNAL_LIBTOMMATH_FAST
568
+L_CFLAGS += -DLTM_FAST
569
+endif
570
+else
571
+LIBS += -ltommath
572
+LIBS_h += -ltommath
573
+endif
574
+CONFIG_INTERNAL_AES=y
575
+CONFIG_INTERNAL_DES=y
576
+CONFIG_INTERNAL_SHA1=y
577
+CONFIG_INTERNAL_MD4=y
578
+CONFIG_INTERNAL_MD5=y
579
+CONFIG_INTERNAL_SHA256=y
580
+CONFIG_INTERNAL_RC4=y
581
+CONFIG_INTERNAL_DH_GROUP5=y
582
+endif
583
+ifeq ($(CONFIG_CRYPTO), cryptoapi)
584
+OBJS += src/crypto/crypto_cryptoapi.c
585
+OBJS_p += src/crypto/crypto_cryptoapi.c
586
+L_CFLAGS += -DCONFIG_CRYPTO_CRYPTOAPI
587
+CONFIG_INTERNAL_SHA256=y
588
+CONFIG_INTERNAL_RC4=y
589
+endif
590
+endif
591
+
592
+ifeq ($(CONFIG_TLS), none)
593
+ifdef TLS_FUNCS
594
+OBJS += src/crypto/tls_none.c
595
+L_CFLAGS += -DEAP_TLS_NONE
596
+CONFIG_INTERNAL_AES=y
597
+CONFIG_INTERNAL_SHA1=y
598
+CONFIG_INTERNAL_MD5=y
599
+endif
600
+OBJS += src/crypto/crypto_none.c
601
+OBJS_p += src/crypto/crypto_none.c
602
+CONFIG_INTERNAL_SHA256=y
603
+CONFIG_INTERNAL_RC4=y
604
+endif
605
+
606
+ifndef TLS_FUNCS
607
+OBJS += src/crypto/tls_none.c
608
+ifeq ($(CONFIG_TLS), internal)
609
+CONFIG_INTERNAL_AES=y
610
+CONFIG_INTERNAL_SHA1=y
611
+CONFIG_INTERNAL_MD5=y
612
+CONFIG_INTERNAL_RC4=y
613
+endif
614
+endif
615
+
616
+AESOBJS = # none so far
617
+ifdef CONFIG_INTERNAL_AES
618
+AESOBJS += src/crypto/aes-internal.c src/crypto/aes-internal-enc.c
619
+endif
620
+
621
+AESOBJS += src/crypto/aes-wrap.c
622
+ifdef NEED_AES_EAX
623
+AESOBJS += src/crypto/aes-eax.c
624
+NEED_AES_CTR=y
625
+endif
626
+ifdef NEED_AES_CTR
627
+AESOBJS += src/crypto/aes-ctr.c
628
+endif
629
+ifdef NEED_AES_ENCBLOCK
630
+AESOBJS += src/crypto/aes-encblock.c
631
+endif
632
+ifdef NEED_AES_OMAC1
633
+AESOBJS += src/crypto/aes-omac1.c
634
+endif
635
+ifdef NEED_AES_UNWRAP
636
+NEED_AES_DEC=y
637
+AESOBJS += src/crypto/aes-unwrap.c
638
+endif
639
+ifdef NEED_AES_CBC
640
+NEED_AES_DEC=y
641
+AESOBJS += src/crypto/aes-cbc.c
642
+endif
643
+ifdef NEED_AES_DEC
644
+ifdef CONFIG_INTERNAL_AES
645
+AESOBJS += src/crypto/aes-internal-dec.c
646
+endif
647
+endif
648
+ifdef NEED_AES
649
+OBJS += $(AESOBJS)
650
+endif
651
+
652
+SHA1OBJS =
653
+ifdef NEED_SHA1
654
+SHA1OBJS += src/crypto/sha1.c
655
+ifdef CONFIG_INTERNAL_SHA1
656
+SHA1OBJS += src/crypto/sha1-internal.c
657
+ifdef NEED_FIPS186_2_PRF
658
+SHA1OBJS += src/crypto/fips_prf_internal.c
659
+endif
660
+endif
661
+SHA1OBJS += src/crypto/sha1-pbkdf2.c
662
+ifdef NEED_T_PRF
663
+SHA1OBJS += src/crypto/sha1-tprf.c
664
+endif
665
+ifdef NEED_TLS_PRF
666
+SHA1OBJS += src/crypto/sha1-tlsprf.c
667
+endif
668
+endif
669
+
670
+ifdef NEED_SHA1
671
+OBJS += $(SHA1OBJS)
672
+endif
673
+
674
+ifdef NEED_MD5
675
+ifdef CONFIG_INTERNAL_MD5
676
+OBJS += src/crypto/md5-internal.c
677
+HOBJS += src/crypto/md5-internal.c
678
+endif
679
+endif
680
+
681
+ifdef NEED_MD4
682
+ifdef CONFIG_INTERNAL_MD4
683
+OBJS += src/crypto/md4-internal.c
684
+endif
685
+endif
686
+
687
+ifdef NEED_DES
688
+ifdef CONFIG_INTERNAL_DES
689
+OBJS += src/crypto/des-internal.c
690
+endif
691
+endif
692
+
693
+ifdef NEED_RC4
694
+ifdef CONFIG_INTERNAL_RC4
695
+OBJS += src/crypto/rc4.c
696
+endif
697
+endif
698
+
699
+ifdef NEED_SHA256
700
+OBJS += src/crypto/sha256.c
701
+ifdef CONFIG_INTERNAL_SHA256
702
+OBJS += src/crypto/sha256-internal.c
703
+endif
704
+endif
705
+
706
+ifdef NEED_DH_GROUPS
707
+OBJS += src/crypto/dh_groups.c
708
+endif
709
+ifdef NEED_DH_GROUPS_ALL
710
+L_CFLAGS += -DALL_DH_GROUPS
711
+endif
712
+ifdef CONFIG_INTERNAL_DH_GROUP5
713
+ifdef NEED_DH_GROUPS
714
+OBJS += src/crypto/dh_group5.c
715
+endif
716
+endif
717
+
718
+ifdef CONFIG_NO_RANDOM_POOL
719
+L_CFLAGS += -DCONFIG_NO_RANDOM_POOL
720
+else
721
+OBJS += src/crypto/random.c
722
+HOBJS += src/crypto/random.c
723
+HOBJS += $(SHA1OBJS)
724
+HOBJS += src/crypto/md5.c
725
+endif
726
+
727
+ifdef CONFIG_RADIUS_SERVER
728
+L_CFLAGS += -DRADIUS_SERVER
729
+OBJS += src/radius/radius_server.c
730
+endif
731
+
732
+ifdef CONFIG_IPV6
733
+L_CFLAGS += -DCONFIG_IPV6
734
+endif
735
+
736
+ifdef CONFIG_DRIVER_RADIUS_ACL
737
+L_CFLAGS += -DCONFIG_DRIVER_RADIUS_ACL
738
+endif
739
+
740
+ifdef CONFIG_FULL_DYNAMIC_VLAN
741
+# define CONFIG_FULL_DYNAMIC_VLAN to have hostapd manipulate bridges
742
+# and vlan interfaces for the vlan feature.
743
+L_CFLAGS += -DCONFIG_FULL_DYNAMIC_VLAN
744
+endif
745
+
746
+ifdef NEED_BASE64
747
+OBJS += src/utils/base64.c
748
+endif
749
+
750
+ifdef NEED_AP_MLME
751
+OBJS += src/ap/beacon.c
752
+OBJS += src/ap/wmm.c
753
+OBJS += src/ap/ap_list.c
754
+OBJS += src/ap/ieee802_11.c
755
+OBJS += src/ap/hw_features.c
756
+L_CFLAGS += -DNEED_AP_MLME
757
+endif
758
+ifdef CONFIG_IEEE80211N
759
+OBJS += src/ap/ieee802_11_ht.c
760
+endif
761
+
762
+ifdef CONFIG_P2P_MANAGER
763
+L_CFLAGS += -DCONFIG_P2P_MANAGER
764
+OBJS += src/ap/p2p_hostapd.c
765
+endif
766
+
767
+ifdef CONFIG_NO_STDOUT_DEBUG
768
+L_CFLAGS += -DCONFIG_NO_STDOUT_DEBUG
769
+endif
770
+
771
+ifdef CONFIG_DEBUG_FILE
772
+L_CFLAGS += -DCONFIG_DEBUG_FILE
773
+endif
774
+
775
+ifdef CONFIG_ANDROID_LOG
776
+L_CFLAGS += -DCONFIG_ANDROID_LOG
777
+endif
778
+
779
+OBJS_c = hostapd_cli.c src/common/wpa_ctrl.c src/utils/os_$(CONFIG_OS).c
780
+ifdef CONFIG_WPA_TRACE
781
+OBJS_c += src/utils/trace.c
782
+OBJS_c += src/utils/wpa_debug.c
783
+endif
784
+
785
+ifeq ($(WPA_BUILD_HOSTAPD),true)
786
+
787
+########################
788
+
789
+include $(CLEAR_VARS)
790
+LOCAL_MODULE := hostapd_cli
791
+LOCAL_MODULE_TAGS := debug
792
+LOCAL_SHARED_LIBRARIES := libc libcutils
793
+LOCAL_CFLAGS := $(L_CFLAGS)
794
+LOCAL_SRC_FILES := $(OBJS_c)
795
+LOCAL_C_INCLUDES := $(INCLUDES)
796
+include $(BUILD_EXECUTABLE)
797
+
798
+########################
799
+include $(CLEAR_VARS)
800
+LOCAL_MODULE := hostapd
801
+LOCAL_MODULE_TAGS := optional
802
+ifdef CONFIG_DRIVER_CUSTOM
803
+LOCAL_STATIC_LIBRARIES := libCustomWifi
804
+endif
805
+ifneq ($(BOARD_HOSTAPD_PRIVATE_LIB),)
806
+LOCAL_STATIC_LIBRARIES += $(BOARD_HOSTAPD_PRIVATE_LIB)
807
+endif
808
+LOCAL_SHARED_LIBRARIES := libc libcutils libcrypto libssl
809
+ifdef CONFIG_DRIVER_NL80211
810
+LOCAL_STATIC_LIBRARIES += libnl_2
811
+endif
812
+LOCAL_CFLAGS := $(L_CFLAGS)
813
+LOCAL_SRC_FILES := $(OBJS)
814
+LOCAL_C_INCLUDES := $(INCLUDES)
815
+include $(BUILD_EXECUTABLE)
816
+
817
+endif # ifeq ($(WPA_BUILD_HOSTAPD),true)

+ 647
- 0
hostapd/ChangeLog Näytä tiedosto

@@ -0,0 +1,647 @@
1
+ChangeLog for hostapd
2
+
3
+2010-04-18 - v0.7.2
4
+	* fix WPS internal Registrar use when an external Registrar is also
5
+	  active
6
+	* bsd: Cleaned up driver wrapper and added various low-level
7
+	  configuration options
8
+	* TNC: fixed issues with fragmentation
9
+	* EAP-TNC: add Flags field into fragment acknowledgement (needed to
10
+	  interoperate with other implementations; may potentially breaks
11
+	  compatibility with older wpa_supplicant/hostapd versions)
12
+	* cleaned up driver wrapper API for multi-BSS operations
13
+	* nl80211: fix multi-BSS and VLAN operations
14
+	* fix number of issues with IEEE 802.11r/FT; this version is not
15
+	  backwards compatible with old versions
16
+	* add SA Query Request processing in AP mode (IEEE 802.11w)
17
+	* fix IGTK PN in group rekeying (IEEE 802.11w)
18
+	* fix WPS PBC session overlap detection to use correct attribute
19
+	* hostapd_notif_Assoc() can now be called with all IEs to simplify
20
+	  driver wrappers
21
+	* work around interoperability issue with some WPS External Registrar
22
+	  implementations
23
+	* nl80211: fix WPS IE update
24
+	* hostapd_cli: add support for action script operations (run a script
25
+	  on hostapd events)
26
+	* fix DH padding with internal crypto code (mainly, for WPS)
27
+	* fix WPS association with both WPS IE and WPA/RSN IE present with
28
+	  driver wrappers that use hostapd MLME (e.g., nl80211)
29
+
30
+2010-01-16 - v0.7.1
31
+	* cleaned up driver wrapper API (struct wpa_driver_ops); the new API
32
+	  is not fully backwards compatible, so out-of-tree driver wrappers
33
+	  will need modifications
34
+	* cleaned up various module interfaces
35
+	* merge hostapd and wpa_supplicant developers' documentation into a
36
+	  single document
37
+	* fixed HT Capabilities IE with nl80211 drivers
38
+	* moved generic AP functionality code into src/ap
39
+	* WPS: handle Selected Registrar as union of info from all Registrars
40
+	* remove obsolte Prism54.org driver wrapper
41
+	* added internal debugging mechanism with backtrace support and memory
42
+	  allocation/freeing validation, etc. tests (CONFIG_WPA_TRACE=y)
43
+	* EAP-FAST server: piggyback Phase 2 start with the end of Phase 1
44
+	* WPS: add support for dynamically selecting whether to provision the
45
+	  PSK as an ASCII passphrase or PSK
46
+	* added support for WDS (4-address frame) mode with per-station virtual
47
+	  interfaces (wds_sta=1 in config file; only supported with
48
+	  driver=nl80211 for now)
49
+	* fixed WPS Probe Request processing to handle missing required
50
+	  attribute
51
+	* fixed PKCS#12 use with OpenSSL 1.0.0
52
+	* detect bridge interface automatically so that bridge parameter in
53
+	  hostapd.conf becomes optional (though, it may now be used to
54
+	  automatically add then WLAN interface into a bridge with
55
+	  driver=nl80211)
56
+
57
+2009-11-21 - v0.7.0
58
+	* increased hostapd_cli ping interval to 5 seconds and made this
59
+	  configurable with a new command line options (-G<seconds>)
60
+	* driver_nl80211: use Linux socket filter to improve performance
61
+	* added support for external Registrars with WPS (UPnP transport)
62
+	* 802.11n: scan for overlapping BSSes before starting 20/40 MHz channel
63
+	* driver_nl80211: fixed STA accounting data collection (TX/RX bytes
64
+	  reported correctly; TX/RX packets not yet available from kernel)
65
+	* added support for WPS USBA out-of-band mechanism with USB Flash
66
+	  Drives (UFD) (CONFIG_WPS_UFD=y)
67
+	* fixed EAPOL/EAP reauthentication when using an external RADIUS
68
+	  authentication server
69
+	* fixed TNC with EAP-TTLS
70
+	* fixed IEEE 802.11r key derivation function to match with the standard
71
+	  (note: this breaks interoperability with previous version) [Bug 303]
72
+	* fixed SHA-256 based key derivation function to match with the
73
+	  standard when using CCMP (for IEEE 802.11r and IEEE 802.11w)
74
+	  (note: this breaks interoperability with previous version) [Bug 307]
75
+	* added number of code size optimizations to remove unnecessary
76
+	  functionality from the program binary based on build configuration
77
+	  (part of this automatic; part configurable with CONFIG_NO_* build
78
+	  options)
79
+	* use shared driver wrapper files with wpa_supplicant
80
+	* driver_nl80211: multiple updates to provide support for new Linux
81
+	  nl80211/mac80211 functionality
82
+	* updated management frame protection to use IEEE Std 802.11w-2009
83
+	* fixed number of small WPS issues and added workarounds to
84
+	  interoperate with common deployed broken implementations
85
+	* added some IEEE 802.11n co-existance rules to disable 40 MHz channels
86
+	  or modify primary/secondary channels if needed based on neighboring
87
+	  networks
88
+	* added support for NFC out-of-band mechanism with WPS
89
+	* added preliminary support for IEEE 802.11r RIC processing
90
+
91
+2009-01-06 - v0.6.7
92
+	* added support for Wi-Fi Protected Setup (WPS)
93
+	  (hostapd can now be configured to act as an integrated WPS Registrar
94
+	  and provision credentials for WPS Enrollees using PIN and PBC
95
+	  methods; external wireless Registrar can configure the AP, but
96
+	  external WLAN Manager Registrars are not supported); WPS support can
97
+	  be enabled by adding CONFIG_WPS=y into .config and setting the
98
+	  runtime configuration variables in hostapd.conf (see WPS section in
99
+	  the example configuration file); new hostapd_cli commands wps_pin and
100
+	  wps_pbc are used to configure WPS negotiation; see README-WPS for
101
+	  more details
102
+	* added IEEE 802.11n HT capability configuration (ht_capab)
103
+	* added support for generating Country IE based on nl80211 regulatory
104
+	  information (added if ieee80211d=1 in configuration)
105
+	* fixed WEP authentication (both Open System and Shared Key) with
106
+	  mac80211
107
+	* added support for EAP-AKA' (draft-arkko-eap-aka-kdf)
108
+	* added support for using driver_test over UDP socket
109
+	* changed EAP-GPSK to use the IANA assigned EAP method type 51
110
+	* updated management frame protection to use IEEE 802.11w/D7.0
111
+	* fixed retransmission of EAP requests if no response is received
112
+
113
+2008-11-23 - v0.6.6
114
+	* added a new configuration option, wpa_ptk_rekey, that can be used to
115
+	  enforce frequent PTK rekeying, e.g., to mitigate some attacks against
116
+	  TKIP deficiencies
117
+	* updated OpenSSL code for EAP-FAST to use an updated version of the
118
+	  session ticket overriding API that was included into the upstream
119
+	  OpenSSL 0.9.9 tree on 2008-11-15 (no additional OpenSSL patch is
120
+	  needed with that version anymore)
121
+	* changed channel flags configuration to read the information from
122
+	  the driver (e.g., via driver_nl80211 when using mac80211) instead of
123
+	  using hostapd as the source of the regulatory information (i.e.,
124
+	  information from CRDA is now used with mac80211); this allows 5 GHz
125
+	  channels to be used with hostapd (if allowed in the current
126
+	  regulatory domain)
127
+	* fixed EAP-TLS message processing for the last TLS message if it is
128
+	  large enough to require fragmentation (e.g., if a large Session
129
+	  Ticket data is included)
130
+	* fixed listen interval configuration for nl80211 drivers
131
+
132
+2008-11-01 - v0.6.5
133
+	* added support for SHA-256 as X.509 certificate digest when using the
134
+	  internal X.509/TLSv1 implementation
135
+	* fixed EAP-FAST PAC-Opaque padding (0.6.4 broke this for some peer
136
+	  identity lengths)
137
+	* fixed internal TLSv1 implementation for abbreviated handshake (used
138
+	  by EAP-FAST server)
139
+	* added support for setting VLAN ID for STAs based on local MAC ACL
140
+	  (accept_mac_file) as an alternative for RADIUS server-based
141
+	  configuration
142
+	* updated management frame protection to use IEEE 802.11w/D6.0
143
+	  (adds a new association ping to protect against unauthenticated
144
+	  authenticate or (re)associate request frames dropping association)
145
+	* added support for using SHA256-based stronger key derivation for WPA2
146
+	  (IEEE 802.11w)
147
+	* added new "driver wrapper" for RADIUS-only configuration
148
+	  (driver=none in hostapd.conf; CONFIG_DRIVER_NONE=y in .config)
149
+	* fixed WPA/RSN IE validation to verify that the proto (WPA vs. WPA2)
150
+	  is enabled in configuration
151
+	* changed EAP-FAST configuration to use separate fields for A-ID and
152
+	  A-ID-Info (eap_fast_a_id_info) to allow A-ID to be set to a fixed
153
+	  16-octet len binary value for better interoperability with some peer
154
+	  implementations; eap_fast_a_id is now configured as a hex string
155
+	* driver_nl80211: Updated to match the current Linux mac80211 AP mode
156
+	  configuration (wireless-testing.git and Linux kernel releases
157
+	  starting from 2.6.29)
158
+
159
+2008-08-10 - v0.6.4
160
+	* added peer identity into EAP-FAST PAC-Opaque and skip Phase 2
161
+	  Identity Request if identity is already known
162
+	* added support for EAP Sequences in EAP-FAST Phase 2
163
+	* added support for EAP-TNC (Trusted Network Connect)
164
+	  (this version implements the EAP-TNC method and EAP-TTLS/EAP-FAST
165
+	  changes needed to run two methods in sequence (IF-T) and the IF-IMV
166
+	  and IF-TNCCS interfaces from TNCS)
167
+	* added support for optional cryptobinding with PEAPv0
168
+	* added fragmentation support for EAP-TNC
169
+	* added support for fragmenting EAP-TTLS/PEAP/FAST Phase 2 (tunneled)
170
+	  data
171
+	* added support for opportunistic key caching (OKC)
172
+
173
+2008-02-22 - v0.6.3
174
+	* fixed Reassociation Response callback processing when using internal
175
+	  MLME (driver_{hostap,nl80211,test}.c)
176
+	* updated FT support to use the latest draft, IEEE 802.11r/D9.0
177
+	* copy optional Proxy-State attributes into RADIUS response when acting
178
+	  as a RADIUS authentication server
179
+	* fixed EAPOL state machine to handle a case in which no response is
180
+	  received from the RADIUS authentication server; previous version
181
+	  could have triggered a crash in some cases after a timeout
182
+	* fixed EAP-SIM/AKA realm processing to allow decorated usernames to
183
+	  be used
184
+	* added a workaround for EAP-SIM/AKA peers that include incorrect null
185
+	  termination in the username
186
+	* fixed EAP-SIM/AKA protected result indication to include AT_COUNTER
187
+	  attribute in notification messages only when using fast
188
+	  reauthentication
189
+	* fixed EAP-SIM Start response processing for fast reauthentication
190
+	  case
191
+	* added support for pending EAP processing in EAP-{PEAP,TTLS,FAST}
192
+	  phase 2 to allow EAP-SIM and EAP-AKA to be used as the Phase 2 method
193
+
194
+2008-01-01 - v0.6.2
195
+	* fixed EAP-SIM and EAP-AKA message parser to validate attribute
196
+	  lengths properly to avoid potential crash caused by invalid messages
197
+	* added data structure for storing allocated buffers (struct wpabuf);
198
+	  this does not affect hostapd usage, but many of the APIs changed
199
+	  and various interfaces (e.g., EAP) is not compatible with old
200
+	  versions
201
+	* added support for protecting EAP-AKA/Identity messages with
202
+	  AT_CHECKCODE (optional feature in RFC 4187)
203
+	* added support for protected result indication with AT_RESULT_IND for
204
+	  EAP-SIM and EAP-AKA (eap_sim_aka_result_ind=1)
205
+	* added support for configuring EAP-TTLS phase 2 non-EAP methods in
206
+	  EAP server configuration; previously all four were enabled for every
207
+	  phase 2 user, now all four are disabled by default and need to be
208
+	  enabled with new method names TTLS-PAP, TTLS-CHAP, TTLS-MSCHAP,
209
+	  TTLS-MSCHAPV2
210
+	* removed old debug printing mechanism and the related 'debug'
211
+	  parameter in the configuration file; debug verbosity is now set with
212
+	  -d (or -dd) command line arguments
213
+	* added support for EAP-IKEv2 (draft-tschofenig-eap-ikev2-15.txt);
214
+	  only shared key/password authentication is supported in this version
215
+
216
+2007-11-24 - v0.6.1
217
+	* added experimental, integrated TLSv1 server implementation with the
218
+	  needed X.509/ASN.1/RSA/bignum processing (this can be enabled by
219
+	  setting CONFIG_TLS=internal and CONFIG_INTERNAL_LIBTOMMATH=y in
220
+	  .config); this can be useful, e.g., if the target system does not
221
+	  have a suitable TLS library and a minimal code size is required
222
+	* added support for EAP-FAST server method to the integrated EAP
223
+	  server
224
+	* updated EAP Generalized Pre-Shared Key (EAP-GPSK) to use the latest
225
+	  draft (draft-ietf-emu-eap-gpsk-07.txt)
226
+	* added a new configuration parameter, rsn_pairwise, to allow different
227
+	  pairwise cipher suites to be enabled for WPA and RSN/WPA2
228
+	  (note: if wpa_pairwise differs from rsn_pairwise, the driver will
229
+	  either need to support this or will have to use the WPA/RSN IEs from
230
+	  hostapd; currently, the included madwifi and bsd driver interfaces do
231
+	  not have support for this)
232
+	* updated FT support to use the latest draft, IEEE 802.11r/D8.0
233
+
234
+2007-05-28 - v0.6.0
235
+	* added experimental IEEE 802.11r/D6.0 support
236
+	* updated EAP-SAKE to RFC 4763 and the IANA-allocated EAP type 48
237
+	* updated EAP-PSK to use the IANA-allocated EAP type 47
238
+	* fixed EAP-PSK bit ordering of the Flags field
239
+	* fixed configuration reloading (SIGHUP) to re-initialize WPA PSKs
240
+	  by reading wpa_psk_file [Bug 181]
241
+	* fixed EAP-TTLS AVP parser processing for too short AVP lengths
242
+	* fixed IPv6 connection to RADIUS accounting server
243
+	* updated EAP Generalized Pre-Shared Key (EAP-GPSK) to use the latest
244
+	  draft (draft-ietf-emu-eap-gpsk-04.txt)
245
+	* hlr_auc_gw: read GSM triplet file into memory and rotate through the
246
+	  entries instead of only using the same three triplets every time
247
+	  (this does not work properly with tests using multiple clients, but
248
+	  provides bit better triplet data for testing a single client; anyway,
249
+	  if a better quality triplets are needed, GSM-Milenage should be used
250
+	  instead of hardcoded triplet file)
251
+	* fixed EAP-MSCHAPv2 server to use a space between S and M parameters
252
+	  in Success Request [Bug 203]
253
+	* added support for sending EAP-AKA Notifications in error cases
254
+	* updated to use IEEE 802.11w/D2.0 for management frame protection
255
+	  (still experimental)
256
+	* RADIUS server: added support for processing duplicate messages
257
+	  (retransmissions from RADIUS client) by replying with the previous
258
+	  reply
259
+
260
+2006-11-24 - v0.5.6
261
+	* added support for configuring and controlling multiple BSSes per
262
+	  radio interface (bss=<ifname> in hostapd.conf); this is only
263
+	  available with Devicescape and test driver interfaces
264
+	* fixed PMKSA cache update in the end of successful RSN
265
+	  pre-authentication
266
+	* added support for dynamic VLAN configuration (i.e., selecting VLAN-ID
267
+	  for each STA based on RADIUS Access-Accept attributes); this requires
268
+	  VLAN support from the kernel driver/802.11 stack and this is
269
+	  currently only available with Devicescape and test driver interfaces
270
+	* driver_madwifi: fixed configuration of unencrypted modes (plaintext
271
+	  and IEEE 802.1X without WEP)
272
+	* removed STAKey handshake since PeerKey handshake has replaced it in
273
+	  IEEE 802.11ma and there are no known deployments of STAKey
274
+	* updated EAP Generalized Pre-Shared Key (EAP-GPSK) to use the latest
275
+	  draft (draft-ietf-emu-eap-gpsk-01.txt)
276
+	* added preliminary implementation of IEEE 802.11w/D1.0 (management
277
+	  frame protection)
278
+	  (Note: this requires driver support to work properly.)
279
+	  (Note2: IEEE 802.11w is an unapproved draft and subject to change.)
280
+	* hlr_auc_gw: added support for GSM-Milenage (for EAP-SIM)
281
+	* hlr_auc_gw: added support for reading per-IMSI Milenage keys and
282
+	  parameters from a text file to make it possible to implement proper
283
+	  GSM/UMTS authentication server for multiple SIM/USIM cards using
284
+	  EAP-SIM/EAP-AKA
285
+	* fixed session timeout processing with drivers that do not use
286
+	  ieee802_11.c (e.g., madwifi)
287
+
288
+2006-08-27 - v0.5.5
289
+	* added 'hostapd_cli new_sta <addr>' command for adding a new STA into
290
+	  hostapd (e.g., to initialize wired network authentication based on an
291
+	  external signal)
292
+	* fixed hostapd to add PMKID KDE into 4-Way Handshake Message 1 when
293
+	  using WPA2 even if PMKSA caching is not used
294
+	* added -P<pid file> argument for hostapd to write the current process
295
+	  id into a file
296
+	* added support for RADIUS Authentication Server MIB (RFC 2619)
297
+
298
+2006-06-20 - v0.5.4
299
+	* fixed nt_password_hash build [Bug 144]
300
+	* added PeerKey handshake implementation for IEEE 802.11e
301
+	  direct link setup (DLS) to replace STAKey handshake
302
+	* added support for EAP Generalized Pre-Shared Key (EAP-GPSK,
303
+	  draft-clancy-emu-eap-shared-secret-00.txt)
304
+	* fixed a segmentation fault when RSN pre-authentication was completed
305
+	  successfully [Bug 152]
306
+
307
+2006-04-27 - v0.5.3
308
+	* do not build nt_password_hash and hlr_auc_gw by default to avoid
309
+	  requiring a TLS library for a successful build; these programs can be
310
+	  build with 'make nt_password_hash' and 'make hlr_auc_gw'
311
+	* added a new configuration option, eapol_version, that can be used to
312
+	  set EAPOL version to 1 (default is 2) to work around broken client
313
+	  implementations that drop EAPOL frames which use version number 2
314
+	  [Bug 89]
315
+	* added support for EAP-SAKE (no EAP method number allocated yet, so
316
+	  this is using the same experimental type 255 as EAP-PSK)
317
+	* fixed EAP-MSCHAPv2 message length validation
318
+
319
+2006-03-19 - v0.5.2
320
+	* fixed stdarg use in hostapd_logger(): if both stdout and syslog
321
+	  logging was enabled, hostapd could trigger a segmentation fault in
322
+	  vsyslog on some CPU -- C library combinations
323
+	* moved HLR/AuC gateway implementation for EAP-SIM/AKA into an external
324
+	  program to make it easier to use for implementing real SS7 gateway;
325
+	  eap_sim_db is not anymore used as a file name for GSM authentication
326
+	  triplets; instead, it is path to UNIX domain socket that will be used
327
+	  to communicate with the external gateway program (e.g., hlr_auc_gw)
328
+	* added example HLR/AuC gateway implementation, hlr_auc_gw, that uses
329
+	  local information (GSM authentication triplets from a text file and
330
+	  hardcoded AKA authentication data); this can be used to test EAP-SIM
331
+	  and EAP-AKA
332
+	* added Milenage algorithm (example 3GPP AKA algorithm) to hlr_auc_gw
333
+	  to make it possible to test EAP-AKA with real USIM cards (this is
334
+	  disabled by default; define AKA_USE_MILENAGE when building hlr_auc_gw
335
+	  to enable this)
336
+	* driver_madwifi: added support for getting station RSN IE from
337
+	  madwifi-ng svn r1453 and newer; this fixes RSN that was apparently
338
+	  broken with earlier change (r1357) in the driver
339
+	* changed EAP method registration to use a dynamic list of methods
340
+	  instead of a static list generated at build time
341
+	* fixed WPA message 3/4 not to encrypt Key Data field (WPA IE)
342
+	  [Bug 125]
343
+	* added ap_max_inactivity configuration parameter
344
+
345
+2006-01-29 - v0.5.1
346
+	* driver_test: added better support for multiple APs and STAs by using
347
+	  a directory with sockets that include MAC address for each device in
348
+	  the name (test_socket=DIR:/tmp/test)
349
+	* added support for EAP expanded type (vendor specific EAP methods)
350
+
351
+2005-12-18 - v0.5.0 (beginning of 0.5.x development releases)
352
+	* added experimental STAKey handshake implementation for IEEE 802.11e
353
+	  direct link setup (DLS); note: this is disabled by default in both
354
+	  build and runtime configuration (can be enabled with CONFIG_STAKEY=y
355
+	  and stakey=1)
356
+	* added support for EAP methods to use callbacks to external programs
357
+	  by buffering a pending request and processing it after the EAP method
358
+	  is ready to continue
359
+	* improved EAP-SIM database interface to allow external request to GSM
360
+	  HLR/AuC without blocking hostapd process
361
+	* added support for using EAP-SIM pseudonyms and fast re-authentication
362
+	* added support for EAP-AKA in the integrated EAP authenticator
363
+	* added support for matching EAP identity prefixes (e.g., "1"*) in EAP
364
+	  user database to allow EAP-SIM/AKA selection without extra roundtrip
365
+	  for EAP-Nak negotiation
366
+	* added support for storing EAP user password as NtPasswordHash instead
367
+	  of plaintext password when using MSCHAP or MSCHAPv2 for
368
+	  authentication (hash:<16-octet hex value>); added nt_password_hash
369
+	  tool for hashing password to generate NtPasswordHash
370
+
371
+2005-11-20 - v0.4.7 (beginning of 0.4.x stable releases)
372
+	* driver_wired: fixed EAPOL sending to optionally use PAE group address
373
+	  as the destination instead of supplicant MAC address; this is
374
+	  disabled by default, but should be enabled with use_pae_group_addr=1
375
+	  in configuration file if the wired interface is used by only one
376
+	  device at the time (common switch configuration)
377
+	* driver_madwifi: configure driver to use TKIP countermeasures in order
378
+	  to get correct behavior (IEEE 802.11 association failing; previously,
379
+	  association succeeded, but hostpad forced disassociation immediately)
380
+	* driver_madwifi: added support for madwifi-ng
381
+
382
+2005-10-27 - v0.4.6
383
+	* added support for replacing user identity from EAP with RADIUS
384
+	  User-Name attribute from Access-Accept message, if that is included,
385
+	  for the RADIUS accounting messages (e.g., for EAP-PEAP/TTLS to get
386
+	  tunneled identity into accounting messages when the RADIUS server
387
+	  does not support better way of doing this with Class attribute)
388
+	* driver_madwifi: fixed EAPOL packet receive for configuration where
389
+	  ath# is part of a bridge interface
390
+	* added a configuration file and log analyzer script for logwatch
391
+	* fixed EAPOL state machine step function to process all state
392
+	  transitions before processing new events; this resolves a race
393
+	  condition in which EAPOL-Start message could trigger hostapd to send
394
+	  two EAP-Response/Identity frames to the authentication server
395
+
396
+2005-09-25 - v0.4.5
397
+	* added client CA list to the TLS certificate request in order to make
398
+	  it easier for the client to select which certificate to use
399
+	* added experimental support for EAP-PSK
400
+	* added support for WE-19 (hostap, madwifi)
401
+
402
+2005-08-21 - v0.4.4
403
+	* fixed build without CONFIG_RSN_PREAUTH
404
+	* fixed FreeBSD build
405
+
406
+2005-06-26 - v0.4.3
407
+	* fixed PMKSA caching to copy User-Name and Class attributes so that
408
+	  RADIUS accounting gets correct information
409
+	* start RADIUS accounting only after successful completion of WPA
410
+	  4-Way Handshake if WPA-PSK is used
411
+	* fixed PMKSA caching for the case where STA (re)associates without
412
+	  first disassociating
413
+
414
+2005-06-12 - v0.4.2
415
+	* EAP-PAX is now registered as EAP type 46
416
+	* fixed EAP-PAX MAC calculation
417
+	* fixed EAP-PAX CK and ICK key derivation
418
+	* renamed eap_authenticator configuration variable to eap_server to
419
+	  better match with RFC 3748 (EAP) terminology
420
+	* driver_test: added support for testing hostapd with wpa_supplicant
421
+	  by using test driver interface without any kernel drivers or network
422
+	  cards
423
+
424
+2005-05-22 - v0.4.1
425
+	* fixed RADIUS server initialization when only auth or acct server
426
+	  is configured and the other one is left empty
427
+	* driver_madwifi: added support for RADIUS accounting
428
+	* driver_madwifi: added preliminary support for compiling against 'BSD'
429
+	  branch of madwifi CVS tree
430
+	* driver_madwifi: fixed pairwise key removal to allow WPA reauth
431
+	  without disassociation
432
+	* added support for reading additional certificates from PKCS#12 files
433
+	  and adding them to the certificate chain
434
+	* fixed RADIUS Class attribute processing to only use Access-Accept
435
+	  packets to update Class; previously, other RADIUS authentication
436
+	  packets could have cleared Class attribute
437
+	* added support for more than one Class attribute in RADIUS packets
438
+	* added support for verifying certificate revocation list (CRL) when
439
+	  using integrated EAP authenticator for EAP-TLS; new hostapd.conf
440
+	  options 'check_crl'; CRL must be included in the ca_cert file for now
441
+
442
+2005-04-25 - v0.4.0 (beginning of 0.4.x development releases)
443
+	* added support for including network information into
444
+	  EAP-Request/Identity message (ASCII-0 (nul) in eap_message)
445
+	  (e.g., to implement draft-adrange-eap-network-discovery-07.txt)
446
+	* fixed a bug which caused some RSN pre-authentication cases to use
447
+	  freed memory and potentially crash hostapd
448
+	* fixed private key loading for cases where passphrase is not set
449
+	* added support for sending TLS alerts and aborting authentication
450
+	  when receiving a TLS alert
451
+	* fixed WPA2 to add PMKSA cache entry when using integrated EAP
452
+	  authenticator
453
+	* fixed PMKSA caching (EAP authentication was not skipped correctly
454
+	  with the new state machine changes from IEEE 802.1X draft)
455
+	* added support for RADIUS over IPv6; own_ip_addr, auth_server_addr,
456
+	  and acct_server_addr can now be IPv6 addresses (CONFIG_IPV6=y needs
457
+	  to be added to .config to include IPv6 support); for RADIUS server,
458
+	  radius_server_ipv6=1 needs to be set in hostapd.conf and addresses
459
+	  in RADIUS clients file can then use IPv6 format
460
+	* added experimental support for EAP-PAX
461
+	* replaced hostapd control interface library (hostapd_ctrl.[ch]) with
462
+	  the same implementation that wpa_supplicant is using (wpa_ctrl.[ch])
463
+
464
+2005-02-12 - v0.3.7 (beginning of 0.3.x stable releases)
465
+
466
+2005-01-23 - v0.3.5
467
+	* added support for configuring a forced PEAP version based on the
468
+	  Phase 1 identity
469
+	* fixed PEAPv1 to use tunneled EAP-Success/Failure instead of EAP-TLV
470
+	  to terminate authentication
471
+	* fixed EAP identifier duplicate processing with the new IEEE 802.1X
472
+	  draft
473
+	* clear accounting data in the driver when starting a new accounting
474
+	  session
475
+	* driver_madwifi: filter wireless events based on ifindex to allow more
476
+	  than one network interface to be used
477
+	* fixed WPA message 2/4 processing not to cancel timeout for TimeoutEvt
478
+	  setting if the packet does not pass MIC verification (e.g., due to
479
+	  incorrect PSK); previously, message 1/4 was not tried again if an
480
+	  invalid message 2/4 was received
481
+	* fixed reconfiguration of RADIUS client retransmission timer when
482
+	  adding a new message to the pending list; previously, timer was not
483
+	  updated at this point and if there was a pending message with long
484
+	  time for the next retry, the new message needed to wait that long for
485
+	  its first retry, too
486
+
487
+2005-01-09 - v0.3.4
488
+	* added support for configuring multiple allowed EAP types for Phase 2
489
+	  authentication (EAP-PEAP, EAP-TTLS)
490
+	* fixed EAPOL-Start processing to trigger WPA reauthentication
491
+	  (previously, only EAPOL authentication was done)
492
+
493
+2005-01-02 - v0.3.3
494
+	* added support for EAP-PEAP in the integrated EAP authenticator
495
+	* added support for EAP-GTC in the integrated EAP authenticator
496
+	* added support for configuring list of EAP methods for Phase 1 so that
497
+	  the integrated EAP authenticator can, e.g., use the wildcard entry
498
+	  for EAP-TLS and EAP-PEAP
499
+	* added support for EAP-TTLS in the integrated EAP authenticator
500
+	* added support for EAP-SIM in the integrated EAP authenticator
501
+	* added support for using hostapd as a RADIUS authentication server
502
+	  with the integrated EAP authenticator taking care of EAP
503
+	  authentication (new hostapd.conf options: radius_server_clients and
504
+	  radius_server_auth_port); this is not included in default build; use
505
+	  CONFIG_RADIUS_SERVER=y in .config to include
506
+
507
+2004-12-19 - v0.3.2
508
+	* removed 'daemonize' configuration file option since it has not really
509
+	  been used at all for more than year
510
+	* driver_madwifi: fixed group key setup and added get_ssid method
511
+	* added support for EAP-MSCHAPv2 in the integrated EAP authenticator
512
+
513
+2004-12-12 - v0.3.1
514
+	* added support for integrated EAP-TLS authentication (new hostapd.conf
515
+	  variables: ca_cert, server_cert, private_key, private_key_passwd);
516
+	  this enabled dynamic keying (WPA2/WPA/IEEE 802.1X/WEP) without
517
+	  external RADIUS server
518
+	* added support for reading PKCS#12 (PFX) files (as a replacement for
519
+	  PEM/DER) to get certificate and private key (CONFIG_PKCS12)
520
+
521
+2004-12-05 - v0.3.0 (beginning of 0.3.x development releases)
522
+	* added support for Acct-{Input,Output}-Gigawords
523
+	* added support for Event-Timestamp (in RADIUS Accounting-Requests)
524
+	* added support for RADIUS Authentication Client MIB (RFC2618)
525
+	* added support for RADIUS Accounting Client MIB (RFC2620)
526
+	* made EAP re-authentication period configurable (eap_reauth_period)
527
+	* fixed EAPOL reauthentication to trigger WPA/WPA2 reauthentication
528
+	* fixed EAPOL state machine to stop if STA is removed during
529
+	  eapol_sm_step(); this fixes at least one segfault triggering bug with
530
+	  IEEE 802.11i pre-authentication
531
+	* added support for multiple WPA pre-shared keys (e.g., one for each
532
+	  client MAC address or keys shared by a group of clients);
533
+	  new hostapd.conf field wpa_psk_file for setting path to a text file
534
+	  containing PSKs, see hostapd.wpa_psk for an example
535
+	* added support for multiple driver interfaces to allow hostapd to be
536
+	  used with other drivers
537
+	* added wired authenticator driver interface (driver=wired in
538
+	  hostapd.conf, see wired.conf for example configuration)
539
+	* added madwifi driver interface (driver=madwifi in hostapd.conf, see
540
+	  madwifi.conf for example configuration; Note: include files from
541
+	  madwifi project is needed for building and a configuration file,
542
+	  .config, needs to be created in hostapd directory with
543
+	  CONFIG_DRIVER_MADWIFI=y to include this driver interface in hostapd
544
+	  build)
545
+	* fixed an alignment issue that could cause SHA-1 to fail on some
546
+	  platforms (e.g., Intel ixp425 with a compiler that does not 32-bit
547
+	  align variables)
548
+	* fixed RADIUS reconnection after an error in sending interim
549
+	  accounting packets
550
+	* added hostapd control interface for external programs and an example
551
+	  CLI, hostapd_cli (like wpa_cli for wpa_supplicant)
552
+	* started adding dot11, dot1x, radius MIBs ('hostapd_cli mib',
553
+	  'hostapd_cli sta <addr>')
554
+	* finished update from IEEE 802.1X-2001 to IEEE 802.1X-REV (now d11)
555
+	* added support for strict GTK rekeying (wpa_strict_rekey in
556
+	  hostapd.conf)
557
+	* updated IAPP to use UDP port 3517 and multicast address 224.0.1.178
558
+	  (instead of broadcast) for IAPP ADD-notify (moved from draft 3 to
559
+	  IEEE 802.11F-2003)
560
+	* added Prism54 driver interface (driver=prism54 in hostapd.conf;
561
+	  note: .config needs to be created in hostapd directory with
562
+	  CONFIG_DRIVER_PRISM54=y to include this driver interface in hostapd
563
+	  build)
564
+	* dual-licensed hostapd (GPLv2 and BSD licenses)
565
+	* fixed RADIUS accounting to generate a new session id for cases where
566
+	  a station reassociates without first being complete deauthenticated
567
+	* fixed STA disassociation handler to mark next timeout state to
568
+	  deauthenticate the station, i.e., skip long wait for inactivity poll
569
+	  and extra disassociation, if the STA disassociates without
570
+	  deauthenticating
571
+	* added integrated EAP authenticator that can be used instead of
572
+	  external RADIUS authentication server; currently, only EAP-MD5 is
573
+	  supported, so this cannot yet be used for key distribution; the EAP
574
+	  method interface is generic, though, so adding new EAP methods should
575
+	  be straightforward; new hostapd.conf variables: 'eap_authenticator'
576
+	  and 'eap_user_file'; this obsoletes "minimal authentication server"
577
+	  ('minimal_eap' in hostapd.conf) which is now removed
578
+	* added support for FreeBSD and driver interface for the BSD net80211
579
+	  layer (driver=bsd in hostapd.conf and CONFIG_DRIVER_BSD=y in
580
+	  .config); please note that some of the required kernel mods have not
581
+	  yet been committed
582
+
583
+2004-07-17 - v0.2.4 (beginning of 0.2.x stable releases)
584
+	* fixed some accounting cases where Accounting-Start was sent when
585
+	  IEEE 802.1X port was being deauthorized
586
+
587
+2004-06-20 - v0.2.3
588
+	* modified RADIUS client to re-connect the socket in case of certain
589
+	  error codes that are generated when a network interface state is
590
+	  changes (e.g., when IP address changes or the interface is set UP)
591
+	* fixed couple of cases where EAPOL state for a station was freed
592
+	  twice causing a segfault for hostapd
593
+	* fixed couple of bugs in processing WPA deauthentication (freed data
594
+	  was used)
595
+
596
+2004-05-31 - v0.2.2
597
+	* fixed WPA/WPA2 group rekeying to use key index correctly (GN/GM)
598
+	* fixed group rekeying to send zero TSC in EAPOL-Key messages to fix
599
+	  cases where STAs dropped multicast frames as replay attacks
600
+	* added support for copying RADIUS Attribute 'Class' from
601
+	  authentication messages into accounting messages
602
+	* send canned EAP failure if RADIUS server sends Access-Reject without
603
+	  EAP message (previously, Supplicant was not notified in this case)
604
+	* fixed mixed WPA-PSK and WPA-EAP mode to work with WPA-PSK (i.e., do
605
+	  not start EAPOL state machines if the STA selected to use WPA-PSK)
606
+
607
+2004-05-06 - v0.2.1
608
+	* added WPA and IEEE 802.11i/RSN (WPA2) Authenticator functionality
609
+	  - based on IEEE 802.11i/D10.0 but modified to interoperate with WPA
610
+	    (i.e., IEEE 802.11i/D3.0)
611
+	  - supports WPA-only, RSN-only, and mixed WPA/RSN mode
612
+	  - both WPA-PSK and WPA-RADIUS/EAP are supported
613
+	  - PMKSA caching and pre-authentication
614
+	  - new hostapd.conf variables: wpa, wpa_psk, wpa_passphrase,
615
+	    wpa_key_mgmt, wpa_pairwise, wpa_group_rekey, wpa_gmk_rekey,
616
+	    rsn_preauth, rsn_preauth_interfaces
617
+	* fixed interim accounting to remove any pending accounting messages
618
+	  to the STA before sending a new one
619
+
620
+2004-02-15 - v0.2.0
621
+	* added support for Acct-Interim-Interval:
622
+	  - draft-ietf-radius-acct-interim-01.txt
623
+	  - use Acct-Interim-Interval attribute from Access-Accept if local
624
+	    'radius_acct_interim_interval' is not set
625
+	  - allow different update intervals for each STA
626
+	* fixed event loop to call signal handlers only after returning from
627
+	  the real signal handler
628
+	* reset sta->timeout_next after successful association to make sure
629
+	  that the previously registered inactivity timer will not remove the
630
+	  STA immediately (e.g., if STA deauthenticates and re-associates
631
+	  before the timer is triggered).
632
+	* added new hostapd.conf variable, nas_identifier, that can be used to
633
+	  add an optional RADIUS Attribute, NAS-Identifier, into authentication
634
+	  and accounting messages
635
+	* added support for Accounting-On and Accounting-Off messages
636
+	* fixed accounting session handling to send Accounting-Start only once
637
+	  per session and not to send Accounting-Stop if the session was not
638
+	  initialized properly
639
+	* fixed Accounting-Stop statistics in cases where the message was
640
+	  previously sent after the kernel entry for the STA (and/or IEEE
641
+	  802.1X data) was removed
642
+
643
+
644
+Note:
645
+
646
+Older changes up to and including v0.1.0 are included in the ChangeLog
647
+of the Host AP driver.

+ 840
- 0
hostapd/Makefile Näytä tiedosto

@@ -0,0 +1,840 @@
1
+ifndef CC
2
+CC=gcc
3
+endif
4
+
5
+ifndef CFLAGS
6
+CFLAGS = -MMD -O2 -Wall -g
7
+endif
8
+
9
+CFLAGS += -I../src
10
+CFLAGS += -I../src/utils
11
+
12
+# Uncomment following line and set the path to your kernel tree include
13
+# directory if your C library does not include all header files.
14
+# CFLAGS += -DUSE_KERNEL_HEADERS -I/usr/src/linux/include
15
+
16
+-include .config
17
+
18
+ifndef CONFIG_OS
19
+ifdef CONFIG_NATIVE_WINDOWS
20
+CONFIG_OS=win32
21
+else
22
+CONFIG_OS=unix
23
+endif
24
+endif
25
+
26
+ifeq ($(CONFIG_OS), internal)
27
+CFLAGS += -DOS_NO_C_LIB_DEFINES
28
+endif
29
+
30
+ifdef CONFIG_NATIVE_WINDOWS
31
+CFLAGS += -DCONFIG_NATIVE_WINDOWS
32
+LIBS += -lws2_32
33
+endif
34
+
35
+OBJS += main.o
36
+OBJS += config_file.o
37
+
38
+OBJS += ../src/ap/hostapd.o
39
+OBJS += ../src/ap/wpa_auth_glue.o
40
+OBJS += ../src/ap/drv_callbacks.o
41
+OBJS += ../src/ap/ap_drv_ops.o
42
+OBJS += ../src/ap/utils.o
43
+OBJS += ../src/ap/authsrv.o
44
+OBJS += ../src/ap/ieee802_1x.o
45
+OBJS += ../src/ap/ap_config.o
46
+OBJS += ../src/ap/ieee802_11_auth.o
47
+OBJS += ../src/ap/sta_info.o
48
+OBJS += ../src/ap/wpa_auth.o
49
+OBJS += ../src/ap/tkip_countermeasures.o
50
+OBJS += ../src/ap/ap_mlme.o
51
+OBJS += ../src/ap/wpa_auth_ie.o
52
+OBJS += ../src/ap/preauth_auth.o
53
+OBJS += ../src/ap/pmksa_cache_auth.o
54
+
55
+NEED_RC4=y
56
+NEED_AES=y
57
+NEED_MD5=y
58
+NEED_SHA1=y
59
+
60
+OBJS += ../src/drivers/drivers.o
61
+CFLAGS += -DHOSTAPD
62
+
63
+ifdef CONFIG_WPA_TRACE
64
+CFLAGS += -DWPA_TRACE
65
+OBJS += ../src/utils/trace.o
66
+HOBJS += ../src/utils/trace.o
67
+LDFLAGS += -rdynamic
68
+CFLAGS += -funwind-tables
69
+ifdef CONFIG_WPA_TRACE_BFD
70
+CFLAGS += -DWPA_TRACE_BFD
71
+LIBS += -lbfd
72
+LIBS_c += -lbfd
73
+LIBS_h += -lbfd
74
+endif
75
+endif
76
+
77
+OBJS += ../src/utils/eloop.o
78
+OBJS += ../src/utils/common.o
79
+OBJS += ../src/utils/wpa_debug.o
80
+OBJS += ../src/utils/wpabuf.o
81
+OBJS += ../src/utils/os_$(CONFIG_OS).o
82
+OBJS += ../src/utils/ip_addr.o
83
+
84
+OBJS += ../src/common/ieee802_11_common.o
85
+OBJS += ../src/common/wpa_common.o
86
+
87
+OBJS += ../src/eapol_auth/eapol_auth_sm.o
88
+
89
+
90
+ifndef CONFIG_NO_DUMP_STATE
91
+# define HOSTAPD_DUMP_STATE to include SIGUSR1 handler for dumping state to
92
+# a file (undefine it, if you want to save in binary size)
93
+CFLAGS += -DHOSTAPD_DUMP_STATE
94
+OBJS += dump_state.o
95
+OBJS += ../src/eapol_auth/eapol_auth_dump.o
96
+endif
97
+
98
+ifdef CONFIG_NO_RADIUS
99
+CFLAGS += -DCONFIG_NO_RADIUS
100
+CONFIG_NO_ACCOUNTING=y
101
+else
102
+OBJS += ../src/radius/radius.o
103
+OBJS += ../src/radius/radius_client.o
104
+endif
105
+
106
+ifdef CONFIG_NO_ACCOUNTING
107
+CFLAGS += -DCONFIG_NO_ACCOUNTING
108
+else
109
+OBJS += ../src/ap/accounting.o
110
+endif
111
+
112
+ifdef CONFIG_NO_VLAN
113
+CFLAGS += -DCONFIG_NO_VLAN
114
+else
115
+OBJS += ../src/ap/vlan_init.o
116
+endif
117
+
118
+ifdef CONFIG_NO_CTRL_IFACE
119
+CFLAGS += -DCONFIG_NO_CTRL_IFACE
120
+else
121
+OBJS += ctrl_iface.o
122
+OBJS += ../src/ap/ctrl_iface_ap.o
123
+endif
124
+
125
+OBJS += ../src/crypto/md5.o
126
+
127
+CFLAGS += -DCONFIG_CTRL_IFACE -DCONFIG_CTRL_IFACE_UNIX
128
+
129
+ifdef CONFIG_IAPP
130
+CFLAGS += -DCONFIG_IAPP
131
+OBJS += ../src/ap/iapp.o
132
+endif
133
+
134
+ifdef CONFIG_RSN_PREAUTH
135
+CFLAGS += -DCONFIG_RSN_PREAUTH
136
+CONFIG_L2_PACKET=y
137
+endif
138
+
139
+ifdef CONFIG_PEERKEY
140
+CFLAGS += -DCONFIG_PEERKEY
141
+OBJS += ../src/ap/peerkey_auth.o
142
+endif
143
+
144
+ifdef CONFIG_IEEE80211W
145
+CFLAGS += -DCONFIG_IEEE80211W
146
+NEED_SHA256=y
147
+NEED_AES_OMAC1=y
148
+endif
149
+
150
+ifdef CONFIG_IEEE80211R
151
+CFLAGS += -DCONFIG_IEEE80211R
152
+OBJS += ../src/ap/wpa_auth_ft.o
153
+NEED_SHA256=y
154
+NEED_AES_OMAC1=y
155
+NEED_AES_UNWRAP=y
156
+endif
157
+
158
+ifdef CONFIG_IEEE80211N
159
+CFLAGS += -DCONFIG_IEEE80211N
160
+endif
161
+
162
+include ../src/drivers/drivers.mak
163
+OBJS += $(DRV_AP_OBJS)
164
+CFLAGS += $(DRV_AP_CFLAGS)
165
+LDFLAGS += $(DRV_AP_LDFLAGS)
166
+LIBS += $(DRV_AP_LIBS)
167
+
168
+ifdef CONFIG_L2_PACKET
169
+ifdef CONFIG_DNET_PCAP
170
+ifdef CONFIG_L2_FREEBSD
171
+LIBS += -lpcap
172
+OBJS += ../src/l2_packet/l2_packet_freebsd.o
173
+else
174
+LIBS += -ldnet -lpcap
175
+OBJS += ../src/l2_packet/l2_packet_pcap.o
176
+endif
177
+else
178
+OBJS += ../src/l2_packet/l2_packet_linux.o
179
+endif
180
+else
181
+OBJS += ../src/l2_packet/l2_packet_none.o
182
+endif
183
+
184
+
185
+ifdef CONFIG_EAP_MD5
186
+CFLAGS += -DEAP_SERVER_MD5
187
+OBJS += ../src/eap_server/eap_server_md5.o
188
+CHAP=y
189
+endif
190
+
191
+ifdef CONFIG_EAP_TLS
192
+CFLAGS += -DEAP_SERVER_TLS
193
+OBJS += ../src/eap_server/eap_server_tls.o
194
+TLS_FUNCS=y
195
+endif
196
+
197
+ifdef CONFIG_EAP_PEAP
198
+CFLAGS += -DEAP_SERVER_PEAP
199
+OBJS += ../src/eap_server/eap_server_peap.o
200
+OBJS += ../src/eap_common/eap_peap_common.o
201
+TLS_FUNCS=y
202
+CONFIG_EAP_MSCHAPV2=y
203
+endif
204
+
205
+ifdef CONFIG_EAP_TTLS
206
+CFLAGS += -DEAP_SERVER_TTLS
207
+OBJS += ../src/eap_server/eap_server_ttls.o
208
+TLS_FUNCS=y
209
+CHAP=y
210
+endif
211
+
212
+ifdef CONFIG_EAP_MSCHAPV2
213
+CFLAGS += -DEAP_SERVER_MSCHAPV2
214
+OBJS += ../src/eap_server/eap_server_mschapv2.o
215
+MS_FUNCS=y
216
+endif
217
+
218
+ifdef CONFIG_EAP_GTC
219
+CFLAGS += -DEAP_SERVER_GTC
220
+OBJS += ../src/eap_server/eap_server_gtc.o
221
+endif
222
+
223
+ifdef CONFIG_EAP_SIM
224
+CFLAGS += -DEAP_SERVER_SIM
225
+OBJS += ../src/eap_server/eap_server_sim.o
226
+CONFIG_EAP_SIM_COMMON=y
227
+NEED_AES_CBC=y
228
+endif
229
+
230
+ifdef CONFIG_EAP_AKA
231
+CFLAGS += -DEAP_SERVER_AKA
232
+OBJS += ../src/eap_server/eap_server_aka.o
233
+CONFIG_EAP_SIM_COMMON=y
234
+NEED_SHA256=y
235
+NEED_AES_CBC=y
236
+endif
237
+
238
+ifdef CONFIG_EAP_AKA_PRIME
239
+CFLAGS += -DEAP_SERVER_AKA_PRIME
240
+endif
241
+
242
+ifdef CONFIG_EAP_SIM_COMMON
243
+OBJS += ../src/eap_common/eap_sim_common.o
244
+# Example EAP-SIM/AKA interface for GSM/UMTS authentication. This can be
245
+# replaced with another file implementating the interface specified in
246
+# eap_sim_db.h.
247
+OBJS += ../src/eap_server/eap_sim_db.o
248
+NEED_FIPS186_2_PRF=y
249
+endif
250
+
251
+ifdef CONFIG_EAP_PAX
252
+CFLAGS += -DEAP_SERVER_PAX
253
+OBJS += ../src/eap_server/eap_server_pax.o ../src/eap_common/eap_pax_common.o
254
+endif
255
+
256
+ifdef CONFIG_EAP_PSK
257
+CFLAGS += -DEAP_SERVER_PSK
258
+OBJS += ../src/eap_server/eap_server_psk.o ../src/eap_common/eap_psk_common.o
259
+NEED_AES_OMAC1=y
260
+NEED_AES_ENCBLOCK=y
261
+NEED_AES_EAX=y
262
+endif
263
+
264
+ifdef CONFIG_EAP_SAKE
265
+CFLAGS += -DEAP_SERVER_SAKE
266
+OBJS += ../src/eap_server/eap_server_sake.o ../src/eap_common/eap_sake_common.o
267
+endif
268
+
269
+ifdef CONFIG_EAP_GPSK
270
+CFLAGS += -DEAP_SERVER_GPSK
271
+OBJS += ../src/eap_server/eap_server_gpsk.o ../src/eap_common/eap_gpsk_common.o
272
+ifdef CONFIG_EAP_GPSK_SHA256
273
+CFLAGS += -DEAP_SERVER_GPSK_SHA256
274
+endif
275
+NEED_SHA256=y
276
+NEED_AES_OMAC1=y
277
+endif
278
+
279
+ifdef CONFIG_EAP_PWD
280
+CFLAGS += -DEAP_SERVER_PWD
281
+OBJS += ../src/eap_server/eap_server_pwd.o ../src/eap_common/eap_pwd_common.o
282
+NEED_SHA256=y
283
+endif
284
+
285
+ifdef CONFIG_EAP_VENDOR_TEST
286
+CFLAGS += -DEAP_SERVER_VENDOR_TEST
287
+OBJS += ../src/eap_server/eap_server_vendor_test.o
288
+endif
289
+
290
+ifdef CONFIG_EAP_FAST
291
+CFLAGS += -DEAP_SERVER_FAST
292
+OBJS += ../src/eap_server/eap_server_fast.o
293
+OBJS += ../src/eap_common/eap_fast_common.o
294
+TLS_FUNCS=y
295
+NEED_T_PRF=y
296
+NEED_AES_UNWRAP=y
297
+endif
298
+
299
+ifdef CONFIG_WPS
300
+ifdef CONFIG_WPS2
301
+CFLAGS += -DCONFIG_WPS2
302
+endif
303
+
304
+CFLAGS += -DCONFIG_WPS -DEAP_SERVER_WSC
305
+OBJS += ../src/utils/uuid.o
306
+OBJS += ../src/ap/wps_hostapd.o
307
+OBJS += ../src/eap_server/eap_server_wsc.o ../src/eap_common/eap_wsc_common.o
308
+OBJS += ../src/wps/wps.o
309
+OBJS += ../src/wps/wps_common.o
310
+OBJS += ../src/wps/wps_attr_parse.o
311
+OBJS += ../src/wps/wps_attr_build.o
312
+OBJS += ../src/wps/wps_attr_process.o
313
+OBJS += ../src/wps/wps_dev_attr.o
314
+OBJS += ../src/wps/wps_enrollee.o
315
+OBJS += ../src/wps/wps_registrar.o
316
+NEED_DH_GROUPS=y
317
+NEED_SHA256=y
318
+NEED_BASE64=y
319
+NEED_AES_CBC=y
320
+NEED_MODEXP=y
321
+CONFIG_EAP=y
322
+
323
+ifdef CONFIG_WPS_UFD
324
+CFLAGS += -DCONFIG_WPS_UFD
325
+OBJS += ../src/wps/wps_ufd.o
326
+NEED_WPS_OOB=y
327
+endif
328
+
329
+ifdef CONFIG_WPS_NFC
330
+CFLAGS += -DCONFIG_WPS_NFC
331
+OBJS += ../src/wps/ndef.o
332
+OBJS += ../src/wps/wps_nfc.o
333
+NEED_WPS_OOB=y
334
+ifdef CONFIG_WPS_NFC_PN531
335
+PN531_PATH ?= /usr/local/src/nfc
336
+CFLAGS += -DCONFIG_WPS_NFC_PN531
337
+CFLAGS += -I${PN531_PATH}/inc
338
+OBJS += ../src/wps/wps_nfc_pn531.o
339
+LIBS += ${PN531_PATH}/lib/wpsnfc.dll
340
+LIBS += ${PN531_PATH}/lib/libnfc_mapping_pn53x.dll
341
+endif
342
+endif
343
+
344
+ifdef NEED_WPS_OOB
345
+CFLAGS += -DCONFIG_WPS_OOB
346
+endif
347
+
348
+ifdef CONFIG_WPS_UPNP
349
+CFLAGS += -DCONFIG_WPS_UPNP
350
+OBJS += ../src/wps/wps_upnp.o
351
+OBJS += ../src/wps/wps_upnp_ssdp.o
352
+OBJS += ../src/wps/wps_upnp_web.o
353
+OBJS += ../src/wps/wps_upnp_event.o
354
+OBJS += ../src/wps/wps_upnp_ap.o
355
+OBJS += ../src/wps/upnp_xml.o
356
+OBJS += ../src/wps/httpread.o
357
+OBJS += ../src/wps/http_client.o
358
+OBJS += ../src/wps/http_server.o
359
+endif
360
+
361
+ifdef CONFIG_WPS_STRICT
362
+CFLAGS += -DCONFIG_WPS_STRICT
363
+OBJS += ../src/wps/wps_validate.o
364
+endif
365
+
366
+ifdef CONFIG_WPS_TESTING
367
+CFLAGS += -DCONFIG_WPS_TESTING
368
+endif
369
+
370
+endif
371
+
372
+ifdef CONFIG_EAP_IKEV2
373
+CFLAGS += -DEAP_SERVER_IKEV2
374
+OBJS += ../src/eap_server/eap_server_ikev2.o ../src/eap_server/ikev2.o
375
+OBJS += ../src/eap_common/eap_ikev2_common.o ../src/eap_common/ikev2_common.o
376
+NEED_DH_GROUPS=y
377
+NEED_DH_GROUPS_ALL=y
378
+NEED_MODEXP=y
379
+NEED_CIPHER=y
380
+endif
381
+
382
+ifdef CONFIG_EAP_TNC
383
+CFLAGS += -DEAP_SERVER_TNC
384
+OBJS += ../src/eap_server/eap_server_tnc.o
385
+OBJS += ../src/eap_server/tncs.o
386
+NEED_BASE64=y
387
+ifndef CONFIG_DRIVER_BSD
388
+LIBS += -ldl
389
+endif
390
+endif
391
+
392
+# Basic EAP functionality is needed for EAPOL
393
+OBJS += eap_register.o
394
+OBJS += ../src/eap_server/eap_server.o
395
+OBJS += ../src/eap_common/eap_common.o
396
+OBJS += ../src/eap_server/eap_server_methods.o
397
+OBJS += ../src/eap_server/eap_server_identity.o
398
+CFLAGS += -DEAP_SERVER_IDENTITY
399
+
400
+ifdef CONFIG_EAP
401
+CFLAGS += -DEAP_SERVER
402
+endif
403
+
404
+ifdef CONFIG_PKCS12
405
+CFLAGS += -DPKCS12_FUNCS
406
+endif
407
+
408
+ifdef MS_FUNCS
409
+OBJS += ../src/crypto/ms_funcs.o
410
+NEED_DES=y
411
+NEED_MD4=y
412
+endif
413
+
414
+ifdef CHAP
415
+OBJS += ../src/eap_common/chap.o
416
+endif
417
+
418
+ifdef TLS_FUNCS
419
+NEED_DES=y
420
+# Shared TLS functions (needed for EAP_TLS, EAP_PEAP, and EAP_TTLS)
421
+CFLAGS += -DEAP_TLS_FUNCS
422
+OBJS += ../src/eap_server/eap_server_tls_common.o
423
+NEED_TLS_PRF=y
424
+endif
425
+
426
+ifndef CONFIG_TLS
427
+CONFIG_TLS=openssl
428
+endif
429
+
430
+ifeq ($(CONFIG_TLS), openssl)
431
+ifdef TLS_FUNCS
432
+OBJS += ../src/crypto/tls_openssl.o
433
+LIBS += -lssl
434
+endif
435
+OBJS += ../src/crypto/crypto_openssl.o
436
+HOBJS += ../src/crypto/crypto_openssl.o
437
+ifdef NEED_FIPS186_2_PRF
438
+OBJS += ../src/crypto/fips_prf_openssl.o
439
+endif
440
+LIBS += -lcrypto
441
+LIBS_h += -lcrypto
442
+endif
443
+
444
+ifeq ($(CONFIG_TLS), gnutls)
445
+ifdef TLS_FUNCS
446
+OBJS += ../src/crypto/tls_gnutls.o
447
+LIBS += -lgnutls -lgpg-error
448
+ifdef CONFIG_GNUTLS_EXTRA
449
+CFLAGS += -DCONFIG_GNUTLS_EXTRA
450
+LIBS += -lgnutls-extra
451
+endif
452
+endif
453
+OBJS += ../src/crypto/crypto_gnutls.o
454
+HOBJS += ../src/crypto/crypto_gnutls.o
455
+ifdef NEED_FIPS186_2_PRF
456
+OBJS += ../src/crypto/fips_prf_gnutls.o
457
+endif
458
+LIBS += -lgcrypt
459
+LIBS_h += -lgcrypt
460
+CONFIG_INTERNAL_SHA256=y
461
+CONFIG_INTERNAL_RC4=y
462
+CONFIG_INTERNAL_DH_GROUP5=y
463
+endif
464
+
465
+ifeq ($(CONFIG_TLS), schannel)
466
+ifdef TLS_FUNCS
467
+OBJS += ../src/crypto/tls_schannel.o
468
+endif
469
+OBJS += ../src/crypto/crypto_cryptoapi.o
470
+OBJS_p += ../src/crypto/crypto_cryptoapi.o
471
+CONFIG_INTERNAL_SHA256=y
472
+CONFIG_INTERNAL_RC4=y
473
+CONFIG_INTERNAL_DH_GROUP5=y
474
+endif
475
+
476
+ifeq ($(CONFIG_TLS), nss)
477
+ifdef TLS_FUNCS
478
+OBJS += ../src/crypto/tls_nss.o
479
+LIBS += -lssl3
480
+endif
481
+OBJS += ../src/crypto/crypto_nss.o
482
+ifdef NEED_FIPS186_2_PRF
483
+OBJS += ../src/crypto/fips_prf_nss.o
484
+endif
485
+LIBS += -lnss3
486
+LIBS_h += -lnss3
487
+CONFIG_INTERNAL_MD4=y
488
+CONFIG_INTERNAL_DH_GROUP5=y
489
+endif
490
+
491
+ifeq ($(CONFIG_TLS), internal)
492
+ifndef CONFIG_CRYPTO
493
+CONFIG_CRYPTO=internal
494
+endif
495
+ifdef TLS_FUNCS
496
+OBJS += ../src/crypto/crypto_internal-rsa.o
497
+OBJS += ../src/crypto/tls_internal.o
498
+OBJS += ../src/tls/tlsv1_common.o
499
+OBJS += ../src/tls/tlsv1_record.o
500
+OBJS += ../src/tls/tlsv1_cred.o
501
+OBJS += ../src/tls/tlsv1_server.o
502
+OBJS += ../src/tls/tlsv1_server_write.o
503
+OBJS += ../src/tls/tlsv1_server_read.o
504
+OBJS += ../src/tls/asn1.o
505
+OBJS += ../src/tls/rsa.o
506
+OBJS += ../src/tls/x509v3.o
507
+OBJS += ../src/tls/pkcs1.o
508
+OBJS += ../src/tls/pkcs5.o
509
+OBJS += ../src/tls/pkcs8.o
510
+NEED_SHA256=y
511
+NEED_BASE64=y
512
+NEED_TLS_PRF=y
513
+NEED_MODEXP=y
514
+NEED_CIPHER=y
515
+CFLAGS += -DCONFIG_TLS_INTERNAL
516
+CFLAGS += -DCONFIG_TLS_INTERNAL_SERVER
517
+endif
518
+ifdef NEED_CIPHER
519
+NEED_DES=y
520
+OBJS += ../src/crypto/crypto_internal-cipher.o
521
+endif
522
+ifdef NEED_MODEXP
523
+OBJS += ../src/crypto/crypto_internal-modexp.o
524
+OBJS += ../src/tls/bignum.o
525
+endif
526
+ifeq ($(CONFIG_CRYPTO), libtomcrypt)
527
+OBJS += ../src/crypto/crypto_libtomcrypt.o
528
+LIBS += -ltomcrypt -ltfm
529
+LIBS_h += -ltomcrypt -ltfm
530
+CONFIG_INTERNAL_SHA256=y
531
+CONFIG_INTERNAL_RC4=y
532
+CONFIG_INTERNAL_DH_GROUP5=y
533
+endif
534
+ifeq ($(CONFIG_CRYPTO), internal)
535
+OBJS += ../src/crypto/crypto_internal.o
536
+NEED_AES_DEC=y
537
+CFLAGS += -DCONFIG_CRYPTO_INTERNAL
538
+ifdef CONFIG_INTERNAL_LIBTOMMATH
539
+CFLAGS += -DCONFIG_INTERNAL_LIBTOMMATH
540
+ifdef CONFIG_INTERNAL_LIBTOMMATH_FAST
541
+CFLAGS += -DLTM_FAST
542
+endif
543
+else
544
+LIBS += -ltommath
545
+LIBS_h += -ltommath
546
+endif
547
+CONFIG_INTERNAL_AES=y
548
+CONFIG_INTERNAL_DES=y
549
+CONFIG_INTERNAL_SHA1=y
550
+CONFIG_INTERNAL_MD4=y
551
+CONFIG_INTERNAL_MD5=y
552
+CONFIG_INTERNAL_SHA256=y
553
+CONFIG_INTERNAL_RC4=y
554
+CONFIG_INTERNAL_DH_GROUP5=y
555
+endif
556
+ifeq ($(CONFIG_CRYPTO), cryptoapi)
557
+OBJS += ../src/crypto/crypto_cryptoapi.o
558
+OBJS_p += ../src/crypto/crypto_cryptoapi.o
559
+CFLAGS += -DCONFIG_CRYPTO_CRYPTOAPI
560
+CONFIG_INTERNAL_SHA256=y
561
+CONFIG_INTERNAL_RC4=y
562
+endif
563
+endif
564
+
565
+ifeq ($(CONFIG_TLS), none)
566
+ifdef TLS_FUNCS
567
+OBJS += ../src/crypto/tls_none.o
568
+CFLAGS += -DEAP_TLS_NONE
569
+CONFIG_INTERNAL_AES=y
570
+CONFIG_INTERNAL_SHA1=y
571
+CONFIG_INTERNAL_MD5=y
572
+endif
573
+OBJS += ../src/crypto/crypto_none.o
574
+OBJS_p += ../src/crypto/crypto_none.o
575
+CONFIG_INTERNAL_SHA256=y
576
+CONFIG_INTERNAL_RC4=y
577
+endif
578
+
579
+ifndef TLS_FUNCS
580
+OBJS += ../src/crypto/tls_none.o
581
+ifeq ($(CONFIG_TLS), internal)
582
+CONFIG_INTERNAL_AES=y
583
+CONFIG_INTERNAL_SHA1=y
584
+CONFIG_INTERNAL_MD5=y
585
+CONFIG_INTERNAL_RC4=y
586
+endif
587
+endif
588
+
589
+AESOBJS = # none so far
590
+ifdef CONFIG_INTERNAL_AES
591
+AESOBJS += ../src/crypto/aes-internal.o ../src/crypto/aes-internal-enc.o
592
+endif
593
+
594
+AESOBJS += ../src/crypto/aes-wrap.o
595
+ifdef NEED_AES_EAX
596
+AESOBJS += ../src/crypto/aes-eax.o
597
+NEED_AES_CTR=y
598
+endif
599
+ifdef NEED_AES_CTR
600
+AESOBJS += ../src/crypto/aes-ctr.o
601
+endif
602
+ifdef NEED_AES_ENCBLOCK
603
+AESOBJS += ../src/crypto/aes-encblock.o
604
+endif
605
+ifdef NEED_AES_OMAC1
606
+AESOBJS += ../src/crypto/aes-omac1.o
607
+endif
608
+ifdef NEED_AES_UNWRAP
609
+NEED_AES_DEC=y
610
+AESOBJS += ../src/crypto/aes-unwrap.o
611
+endif
612
+ifdef NEED_AES_CBC
613
+NEED_AES_DEC=y
614
+AESOBJS += ../src/crypto/aes-cbc.o
615
+endif
616
+ifdef NEED_AES_DEC
617
+ifdef CONFIG_INTERNAL_AES
618
+AESOBJS += ../src/crypto/aes-internal-dec.o
619
+endif
620
+endif
621
+ifdef NEED_AES
622
+OBJS += $(AESOBJS)
623
+endif
624
+
625
+ifdef NEED_SHA1
626
+SHA1OBJS += ../src/crypto/sha1.o
627
+ifdef CONFIG_INTERNAL_SHA1
628
+SHA1OBJS += ../src/crypto/sha1-internal.o
629
+ifdef NEED_FIPS186_2_PRF
630
+SHA1OBJS += ../src/crypto/fips_prf_internal.o
631
+endif
632
+endif
633
+SHA1OBJS += ../src/crypto/sha1-pbkdf2.o
634
+ifdef NEED_T_PRF
635
+SHA1OBJS += ../src/crypto/sha1-tprf.o
636
+endif
637
+ifdef NEED_TLS_PRF
638
+SHA1OBJS += ../src/crypto/sha1-tlsprf.o
639
+endif
640
+endif
641
+
642
+ifdef NEED_SHA1
643
+OBJS += $(SHA1OBJS)
644
+endif
645
+
646
+ifdef NEED_MD5
647
+ifdef CONFIG_INTERNAL_MD5
648
+OBJS += ../src/crypto/md5-internal.o
649
+HOBJS += ../src/crypto/md5-internal.o
650
+endif
651
+endif
652
+
653
+ifdef NEED_MD4
654
+ifdef CONFIG_INTERNAL_MD4
655
+OBJS += ../src/crypto/md4-internal.o
656
+endif
657
+endif
658
+
659
+ifdef NEED_DES
660
+ifdef CONFIG_INTERNAL_DES
661
+OBJS += ../src/crypto/des-internal.o
662
+endif
663
+endif
664
+
665
+ifdef NEED_RC4
666
+ifdef CONFIG_INTERNAL_RC4
667
+OBJS += ../src/crypto/rc4.o
668
+endif
669
+endif
670
+
671
+ifdef NEED_SHA256
672
+OBJS += ../src/crypto/sha256.o
673
+ifdef CONFIG_INTERNAL_SHA256
674
+OBJS += ../src/crypto/sha256-internal.o
675
+endif
676
+endif
677
+
678
+ifdef NEED_DH_GROUPS
679
+OBJS += ../src/crypto/dh_groups.o
680
+endif
681
+ifdef NEED_DH_GROUPS_ALL
682
+CFLAGS += -DALL_DH_GROUPS
683
+endif
684
+ifdef CONFIG_INTERNAL_DH_GROUP5
685
+ifdef NEED_DH_GROUPS
686
+OBJS += ../src/crypto/dh_group5.o
687
+endif
688
+endif
689
+
690
+ifdef CONFIG_NO_RANDOM_POOL
691
+CFLAGS += -DCONFIG_NO_RANDOM_POOL
692
+else
693
+OBJS += ../src/crypto/random.o
694
+HOBJS += ../src/crypto/random.o
695
+HOBJS += $(SHA1OBJS)
696
+HOBJS += ../src/crypto/md5.o
697
+endif
698
+
699
+ifdef CONFIG_RADIUS_SERVER
700
+CFLAGS += -DRADIUS_SERVER
701
+OBJS += ../src/radius/radius_server.o
702
+endif
703
+
704
+ifdef CONFIG_IPV6
705
+CFLAGS += -DCONFIG_IPV6
706
+endif
707
+
708
+ifdef CONFIG_DRIVER_RADIUS_ACL
709
+CFLAGS += -DCONFIG_DRIVER_RADIUS_ACL
710
+endif
711
+
712
+ifdef CONFIG_FULL_DYNAMIC_VLAN
713
+# define CONFIG_FULL_DYNAMIC_VLAN to have hostapd manipulate bridges
714
+# and vlan interfaces for the vlan feature.
715
+CFLAGS += -DCONFIG_FULL_DYNAMIC_VLAN
716
+endif
717
+
718
+ifdef NEED_BASE64
719
+OBJS += ../src/utils/base64.o
720
+endif
721
+
722
+ifdef NEED_AP_MLME
723
+OBJS += ../src/ap/beacon.o
724
+OBJS += ../src/ap/wmm.o
725
+OBJS += ../src/ap/ap_list.o
726
+OBJS += ../src/ap/ieee802_11.o
727
+OBJS += ../src/ap/hw_features.o
728
+CFLAGS += -DNEED_AP_MLME
729
+endif
730
+ifdef CONFIG_IEEE80211N
731
+OBJS += ../src/ap/ieee802_11_ht.o
732
+endif
733
+
734
+ifdef CONFIG_P2P_MANAGER
735
+CFLAGS += -DCONFIG_P2P_MANAGER
736
+OBJS += ../src/ap/p2p_hostapd.o
737
+endif
738
+
739
+ifdef CONFIG_NO_STDOUT_DEBUG
740
+CFLAGS += -DCONFIG_NO_STDOUT_DEBUG
741
+endif
742
+
743
+ifdef CONFIG_DEBUG_FILE
744
+CFLAGS += -DCONFIG_DEBUG_FILE
745
+endif
746
+
747
+ALL=hostapd hostapd_cli
748
+
749
+all: verify_config $(ALL)
750
+
751
+Q=@
752
+E=echo
753
+ifeq ($(V), 1)
754
+Q=
755
+E=true
756
+endif
757
+
758
+%.o: %.c
759
+	$(Q)$(CC) -c -o $@ $(CFLAGS) $<
760
+	@$(E) "  CC " $<
761
+
762
+verify_config:
763
+	@if [ ! -r .config ]; then \
764
+		echo 'Building hostapd requires a configuration file'; \
765
+		echo '(.config). See README for more instructions. You can'; \
766
+		echo 'run "cp defconfig .config" to create an example'; \
767
+		echo 'configuration.'; \
768
+		exit 1; \
769
+	fi
770
+
771
+install: all
772
+	mkdir -p $(DESTDIR)/usr/local/bin
773
+	for i in $(ALL); do cp -f $$i $(DESTDIR)/usr/local/bin/$$i; done
774
+	cp -f ../scripts/init /etc/init.d/hostapd
775
+	chmod +x /etc/init.d/hostapd
776
+	mkdir -p /etc/hostapd
777
+	cp -f ../scripts/hostapd.conf /etc/hostapd/
778
+
779
+../src/drivers/build.hostapd:
780
+	@if [ -f ../src/drivers/build.wpa_supplicant ]; then \
781
+		$(MAKE) -C ../src/drivers clean; \
782
+	fi
783
+	@touch ../src/drivers/build.hostapd
784
+
785
+BCHECK=../src/drivers/build.hostapd
786
+
787
+hostapd: $(BCHECK) $(OBJS)
788
+	$(Q)$(CC) $(LDFLAGS) -o hostapd $(OBJS) $(LIBS)
789
+	@$(E) "  LD " $@
790
+
791
+OBJS_c = hostapd_cli.o ../src/common/wpa_ctrl.o ../src/utils/os_$(CONFIG_OS).o
792
+ifdef CONFIG_WPA_TRACE
793
+OBJS_c += ../src/utils/trace.o
794
+OBJS_c += ../src/utils/wpa_debug.o
795
+endif
796
+hostapd_cli: $(OBJS_c)
797
+	$(Q)$(CC) $(LDFLAGS) -o hostapd_cli $(OBJS_c) $(LIBS_c)
798
+	@$(E) "  LD " $@
799
+
800
+NOBJS = nt_password_hash.o ../src/crypto/ms_funcs.o $(SHA1OBJS) ../src/crypto/md5.o
801
+ifdef NEED_RC4
802
+ifdef CONFIG_INTERNAL_RC4
803
+NOBJS += ../src/crypto/rc4.o
804
+endif
805
+endif
806
+ifdef CONFIG_INTERNAL_MD5
807
+NOBJS += ../src/crypto/md5-internal.o
808
+endif
809
+NOBJS += ../src/crypto/crypto_openssl.o ../src/utils/os_$(CONFIG_OS).o
810
+NOBJS += ../src/utils/wpa_debug.o
811
+NOBJS += ../src/utils/wpabuf.o
812
+ifdef CONFIG_WPA_TRACE
813
+NOBJS += ../src/utils/trace.o
814
+LIBS_n += -lbfd
815
+endif
816
+ifdef TLS_FUNCS
817
+LIBS_n += -lcrypto
818
+endif
819
+
820
+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
821
+HOBJS += ../src/crypto/aes-encblock.o
822
+ifdef CONFIG_INTERNAL_AES
823
+HOBJS += ../src/crypto/aes-internal.o
824
+HOBJS += ../src/crypto/aes-internal-enc.o
825
+endif
826
+
827
+nt_password_hash: $(NOBJS)
828
+	$(Q)$(CC) $(LDFLAGS) -o nt_password_hash $(NOBJS) $(LIBS_n)
829
+	@$(E) "  LD " $@
830
+
831
+hlr_auc_gw: $(HOBJS)
832
+	$(Q)$(CC) $(LDFLAGS) -o hlr_auc_gw $(HOBJS) $(LIBS_h)
833
+	@$(E) "  LD " $@
834
+
835
+clean:
836
+	$(MAKE) -C ../src clean
837
+	rm -f core *~ *.o hostapd hostapd_cli nt_password_hash hlr_auc_gw
838
+	rm -f *.d
839
+
840
+-include $(OBJS:%.o=%.d)

+ 387
- 0
hostapd/README Näytä tiedosto

@@ -0,0 +1,387 @@
1
+hostapd - user space IEEE 802.11 AP and IEEE 802.1X/WPA/WPA2/EAP
2
+	  Authenticator and RADIUS authentication server
3
+================================================================
4
+
5
+Copyright (c) 2002-2011, Jouni Malinen <j@w1.fi> and contributors
6
+All Rights Reserved.
7
+
8
+This program is dual-licensed under both the GPL version 2 and BSD
9
+license. Either license may be used at your option.
10
+
11
+
12
+
13
+License
14
+-------
15
+
16
+GPL v2:
17
+
18
+This program is free software; you can redistribute it and/or modify
19
+it under the terms of the GNU General Public License version 2 as
20
+published by the Free Software Foundation.
21
+
22
+This program is distributed in the hope that it will be useful,
23
+but WITHOUT ANY WARRANTY; without even the implied warranty of
24
+MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
25
+GNU General Public License for more details.
26
+
27
+You should have received a copy of the GNU General Public License
28
+along with this program; if not, write to the Free Software
29
+Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA  02110-1301  USA
30
+
31
+(this copy of the license is in COPYING file)
32
+
33
+
34
+Alternatively, this software may be distributed, used, and modified
35
+under the terms of BSD license:
36
+
37
+Redistribution and use in source and binary forms, with or without
38
+modification, are permitted provided that the following conditions are
39
+met:
40
+
41
+1. Redistributions of source code must retain the above copyright
42
+   notice, this list of conditions and the following disclaimer.
43
+
44
+2. Redistributions in binary form must reproduce the above copyright
45
+   notice, this list of conditions and the following disclaimer in the
46
+   documentation and/or other materials provided with the distribution.
47
+
48
+3. Neither the name(s) of the above-listed copyright holder(s) nor the
49
+   names of its contributors may be used to endorse or promote products
50
+   derived from this software without specific prior written permission.
51
+
52
+THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
53
+"AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
54
+LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
55
+A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
56
+OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
57
+SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
58
+LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
59
+DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
60
+THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
61
+(INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
62
+OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
63
+
64
+
65
+
66
+Introduction
67
+============
68
+
69
+Originally, hostapd was an optional user space component for Host AP
70
+driver. It adds more features to the basic IEEE 802.11 management
71
+included in the kernel driver: using external RADIUS authentication
72
+server for MAC address based access control, IEEE 802.1X Authenticator
73
+and dynamic WEP keying, RADIUS accounting, WPA/WPA2 (IEEE 802.11i/RSN)
74
+Authenticator and dynamic TKIP/CCMP keying.
75
+
76
+The current version includes support for other drivers, an integrated
77
+EAP server (i.e., allow full authentication without requiring
78
+an external RADIUS authentication server), and RADIUS authentication
79
+server for EAP authentication.
80
+
81
+
82
+Requirements
83
+------------
84
+
85
+Current hardware/software requirements:
86
+- drivers:
87
+	Host AP driver for Prism2/2.5/3.
88
+	(http://hostap.epitest.fi/)
89
+	Please note that station firmware version needs to be 1.7.0 or newer
90
+	to work in WPA mode.
91
+
92
+	madwifi driver for cards based on Atheros chip set (ar521x)
93
+	(http://sourceforge.net/projects/madwifi/)
94
+	Please note that you will need to add the correct path for
95
+	madwifi driver root directory in .config (see defconfig file for
96
+	an example: CFLAGS += -I<path>)
97
+
98
+	mac80211-based drivers that support AP mode (with driver=nl80211).
99
+	This includes drivers for Atheros (ath9k) and Broadcom (b43)
100
+	chipsets.
101
+
102
+	Any wired Ethernet driver for wired IEEE 802.1X authentication
103
+	(experimental code)
104
+
105
+	FreeBSD -current (with some kernel mods that have not yet been
106
+	committed when hostapd v0.3.0 was released)
107
+	BSD net80211 layer (e.g., Atheros driver)
108
+
109
+
110
+Build configuration
111
+-------------------
112
+
113
+In order to be able to build hostapd, you will need to create a build
114
+time configuration file, .config that selects which optional
115
+components are included. See defconfig file for example configuration
116
+and list of available options.
117
+
118
+
119
+
120
+IEEE 802.1X
121
+===========
122
+
123
+IEEE Std 802.1X-2001 is a standard for port-based network access
124
+control. In case of IEEE 802.11 networks, a "virtual port" is used
125
+between each associated station and the AP. IEEE 802.11 specifies
126
+minimal authentication mechanism for stations, whereas IEEE 802.1X
127
+introduces a extensible mechanism for authenticating and authorizing
128
+users.
129
+
130
+IEEE 802.1X uses elements called Supplicant, Authenticator, Port
131
+Access Entity, and Authentication Server. Supplicant is a component in
132
+a station and it performs the authentication with the Authentication
133
+Server. An access point includes an Authenticator that relays the packets
134
+between a Supplicant and an Authentication Server. In addition, it has a
135
+Port Access Entity (PAE) with Authenticator functionality for
136
+controlling the virtual port authorization, i.e., whether to accept
137
+packets from or to the station.
138
+
139
+IEEE 802.1X uses Extensible Authentication Protocol (EAP). The frames
140
+between a Supplicant and an Authenticator are sent using EAP over LAN
141
+(EAPOL) and the Authenticator relays these frames to the Authentication
142
+Server (and similarly, relays the messages from the Authentication
143
+Server to the Supplicant). The Authentication Server can be colocated with the
144
+Authenticator, in which case there is no need for additional protocol
145
+for EAP frame transmission. However, a more common configuration is to
146
+use an external Authentication Server and encapsulate EAP frame in the
147
+frames used by that server. RADIUS is suitable for this, but IEEE
148
+802.1X would also allow other mechanisms.
149
+
150
+Host AP driver includes PAE functionality in the kernel driver. It
151
+is a relatively simple mechanism for denying normal frames going to
152
+or coming from an unauthorized port. PAE allows IEEE 802.1X related
153
+frames to be passed between the Supplicant and the Authenticator even
154
+on an unauthorized port.
155
+
156
+User space daemon, hostapd, includes Authenticator functionality. It
157
+receives 802.1X (EAPOL) frames from the Supplicant using the wlan#ap
158
+device that is also used with IEEE 802.11 management frames. The
159
+frames to the Supplicant are sent using the same device.
160
+
161
+The normal configuration of the Authenticator would use an external
162
+Authentication Server. hostapd supports RADIUS encapsulation of EAP
163
+packets, so the Authentication Server should be a RADIUS server, like
164
+FreeRADIUS (http://www.freeradius.org/). The Authenticator in hostapd
165
+relays the frames between the Supplicant and the Authentication
166
+Server. It also controls the PAE functionality in the kernel driver by
167
+controlling virtual port authorization, i.e., station-AP
168
+connection, based on the IEEE 802.1X state.
169
+
170
+When a station would like to use the services of an access point, it
171
+will first perform IEEE 802.11 authentication. This is normally done
172
+with open systems authentication, so there is no security. After
173
+this, IEEE 802.11 association is performed. If IEEE 802.1X is
174
+configured to be used, the virtual port for the station is set in
175
+Unauthorized state and only IEEE 802.1X frames are accepted at this
176
+point. The Authenticator will then ask the Supplicant to authenticate
177
+with the Authentication Server. After this is completed successfully,
178
+the virtual port is set to Authorized state and frames from and to the
179
+station are accepted.
180
+
181
+Host AP configuration for IEEE 802.1X
182
+-------------------------------------
183
+
184
+The user space daemon has its own configuration file that can be used to
185
+define AP options. Distribution package contains an example
186
+configuration file (hostapd/hostapd.conf) that can be used as a basis
187
+for configuration. It includes examples of all supported configuration
188
+options and short description of each option. hostapd should be started
189
+with full path to the configuration file as the command line argument,
190
+e.g., './hostapd /etc/hostapd.conf'. If you have more that one wireless
191
+LAN card, you can use one hostapd process for multiple interfaces by
192
+giving a list of configuration files (one per interface) in the command
193
+line.
194
+
195
+hostapd includes a minimal co-located IEEE 802.1X server which can be
196
+used to test IEEE 802.1X authentication. However, it should not be
197
+used in normal use since it does not provide any security. This can be
198
+configured by setting ieee8021x and minimal_eap options in the
199
+configuration file.
200
+
201
+An external Authentication Server (RADIUS) is configured with
202
+auth_server_{addr,port,shared_secret} options. In addition,
203
+ieee8021x and own_ip_addr must be set for this mode. With such
204
+configuration, the co-located Authentication Server is not used and EAP
205
+frames will be relayed using EAPOL between the Supplicant and the
206
+Authenticator and RADIUS encapsulation between the Authenticator and
207
+the Authentication Server. Other than this, the functionality is similar
208
+to the case with the co-located Authentication Server.
209
+
210
+Authentication Server and Supplicant
211
+------------------------------------
212
+
213
+Any RADIUS server supporting EAP should be usable as an IEEE 802.1X
214
+Authentication Server with hostapd Authenticator. FreeRADIUS
215
+(http://www.freeradius.org/) has been successfully tested with hostapd
216
+Authenticator and both Xsupplicant (http://www.open1x.org) and Windows
217
+XP Supplicants. EAP/TLS was used with Xsupplicant and
218
+EAP/MD5-Challenge with Windows XP.
219
+
220
+http://www.missl.cs.umd.edu/wireless/eaptls/ has useful information
221
+about using EAP/TLS with FreeRADIUS and Xsupplicant (just replace
222
+Cisco access point with Host AP driver, hostapd daemon, and a Prism2
223
+card ;-). http://www.freeradius.org/doc/EAP-MD5.html has information
224
+about using EAP/MD5 with FreeRADIUS, including instructions for WinXP
225
+configuration. http://www.denobula.com/EAPTLS.pdf has a HOWTO on
226
+EAP/TLS use with WinXP Supplicant.
227
+
228
+Automatic WEP key configuration
229
+-------------------------------
230
+
231
+EAP/TLS generates a session key that can be used to send WEP keys from
232
+an AP to authenticated stations. The Authenticator in hostapd can be
233
+configured to automatically select a random default/broadcast key
234
+(shared by all authenticated stations) with wep_key_len_broadcast
235
+option (5 for 40-bit WEP or 13 for 104-bit WEP). In addition,
236
+wep_key_len_unicast option can be used to configure individual unicast
237
+keys for stations. This requires support for individual keys in the
238
+station driver.
239
+
240
+WEP keys can be automatically updated by configuring rekeying. This
241
+will improve security of the network since same WEP key will only be
242
+used for a limited period of time. wep_rekey_period option sets the
243
+interval for rekeying in seconds.
244
+
245
+
246
+WPA/WPA2
247
+========
248
+
249
+Features
250
+--------
251
+
252
+Supported WPA/IEEE 802.11i features:
253
+- WPA-PSK ("WPA-Personal")
254
+- WPA with EAP (e.g., with RADIUS authentication server) ("WPA-Enterprise")
255
+- key management for CCMP, TKIP, WEP104, WEP40
256
+- RSN/WPA2 (IEEE 802.11i), including PMKSA caching and pre-authentication
257
+
258
+WPA
259
+---
260
+
261
+The original security mechanism of IEEE 802.11 standard was not
262
+designed to be strong and has proved to be insufficient for most
263
+networks that require some kind of security. Task group I (Security)
264
+of IEEE 802.11 working group (http://www.ieee802.org/11/) has worked
265
+to address the flaws of the base standard and has in practice
266
+completed its work in May 2004. The IEEE 802.11i amendment to the IEEE
267
+802.11 standard was approved in June 2004 and this amendment is likely
268
+to be published in July 2004.
269
+
270
+Wi-Fi Alliance (http://www.wi-fi.org/) used a draft version of the
271
+IEEE 802.11i work (draft 3.0) to define a subset of the security
272
+enhancements that can be implemented with existing wlan hardware. This
273
+is called Wi-Fi Protected Access<TM> (WPA). This has now become a
274
+mandatory component of interoperability testing and certification done
275
+by Wi-Fi Alliance. Wi-Fi provides information about WPA at its web
276
+site (http://www.wi-fi.org/OpenSection/protected_access.asp).
277
+
278
+IEEE 802.11 standard defined wired equivalent privacy (WEP) algorithm
279
+for protecting wireless networks. WEP uses RC4 with 40-bit keys,
280
+24-bit initialization vector (IV), and CRC32 to protect against packet
281
+forgery. All these choices have proven to be insufficient: key space is
282
+too small against current attacks, RC4 key scheduling is insufficient
283
+(beginning of the pseudorandom stream should be skipped), IV space is
284
+too small and IV reuse makes attacks easier, there is no replay
285
+protection, and non-keyed authentication does not protect against bit
286
+flipping packet data.
287
+
288
+WPA is an intermediate solution for the security issues. It uses
289
+Temporal Key Integrity Protocol (TKIP) to replace WEP. TKIP is a
290
+compromise on strong security and possibility to use existing
291
+hardware. It still uses RC4 for the encryption like WEP, but with
292
+per-packet RC4 keys. In addition, it implements replay protection,
293
+keyed packet authentication mechanism (Michael MIC).
294
+
295
+Keys can be managed using two different mechanisms. WPA can either use
296
+an external authentication server (e.g., RADIUS) and EAP just like
297
+IEEE 802.1X is using or pre-shared keys without need for additional
298
+servers. Wi-Fi calls these "WPA-Enterprise" and "WPA-Personal",
299
+respectively. Both mechanisms will generate a master session key for
300
+the Authenticator (AP) and Supplicant (client station).
301
+
302
+WPA implements a new key handshake (4-Way Handshake and Group Key
303
+Handshake) for generating and exchanging data encryption keys between
304
+the Authenticator and Supplicant. This handshake is also used to
305
+verify that both Authenticator and Supplicant know the master session
306
+key. These handshakes are identical regardless of the selected key
307
+management mechanism (only the method for generating master session
308
+key changes).
309
+
310
+
311
+IEEE 802.11i / WPA2
312
+-------------------
313
+
314
+The design for parts of IEEE 802.11i that were not included in WPA has
315
+finished (May 2004) and this amendment to IEEE 802.11 was approved in
316
+June 2004. Wi-Fi Alliance is using the final IEEE 802.11i as a new
317
+version of WPA called WPA2. This includes, e.g., support for more
318
+robust encryption algorithm (CCMP: AES in Counter mode with CBC-MAC)
319
+to replace TKIP and optimizations for handoff (reduced number of
320
+messages in initial key handshake, pre-authentication, and PMKSA caching).
321
+
322
+Some wireless LAN vendors are already providing support for CCMP in
323
+their WPA products. There is no "official" interoperability
324
+certification for CCMP and/or mixed modes using both TKIP and CCMP, so
325
+some interoperability issues can be expected even though many
326
+combinations seem to be working with equipment from different vendors.
327
+Testing for WPA2 is likely to start during the second half of 2004.
328
+
329
+hostapd configuration for WPA/WPA2
330
+----------------------------------
331
+
332
+TODO
333
+
334
+# Enable WPA. Setting this variable configures the AP to require WPA (either
335
+# WPA-PSK or WPA-RADIUS/EAP based on other configuration). For WPA-PSK, either
336
+# wpa_psk or wpa_passphrase must be set and wpa_key_mgmt must include WPA-PSK.
337
+# For WPA-RADIUS/EAP, ieee8021x must be set (but without dynamic WEP keys),
338
+# RADIUS authentication server must be configured, and WPA-EAP must be included
339
+# in wpa_key_mgmt.
340
+# This field is a bit field that can be used to enable WPA (IEEE 802.11i/D3.0)
341
+# and/or WPA2 (full IEEE 802.11i/RSN):
342
+# bit0 = WPA
343
+# bit1 = IEEE 802.11i/RSN (WPA2)
344
+#wpa=1
345
+
346
+# WPA pre-shared keys for WPA-PSK. This can be either entered as a 256-bit
347
+# secret in hex format (64 hex digits), wpa_psk, or as an ASCII passphrase
348
+# (8..63 characters) that will be converted to PSK. This conversion uses SSID
349
+# so the PSK changes when ASCII passphrase is used and the SSID is changed.
350
+#wpa_psk=0123456789abcdef0123456789abcdef0123456789abcdef0123456789abcdef
351
+#wpa_passphrase=secret passphrase
352
+
353
+# Set of accepted key management algorithms (WPA-PSK, WPA-EAP, or both). The
354
+# entries are separated with a space.
355
+#wpa_key_mgmt=WPA-PSK WPA-EAP
356
+
357
+# Set of accepted cipher suites (encryption algorithms) for pairwise keys
358
+# (unicast packets). This is a space separated list of algorithms:
359
+# CCMP = AES in Counter mode with CBC-MAC [RFC 3610, IEEE 802.11i]
360
+# TKIP = Temporal Key Integrity Protocol [IEEE 802.11i]
361
+# Group cipher suite (encryption algorithm for broadcast and multicast frames)
362
+# is automatically selected based on this configuration. If only CCMP is
363
+# allowed as the pairwise cipher, group cipher will also be CCMP. Otherwise,
364
+# TKIP will be used as the group cipher.
365
+#wpa_pairwise=TKIP CCMP
366
+
367
+# Time interval for rekeying GTK (broadcast/multicast encryption keys) in
368
+# seconds.
369
+#wpa_group_rekey=600
370
+
371
+# Time interval for rekeying GMK (master key used internally to generate GTKs
372
+# (in seconds).
373
+#wpa_gmk_rekey=86400
374
+
375
+# Enable IEEE 802.11i/RSN/WPA2 pre-authentication. This is used to speed up
376
+# roaming be pre-authenticating IEEE 802.1X/EAP part of the full RSN
377
+# authentication and key handshake before actually associating with a new AP.
378
+#rsn_preauth=1
379
+#
380
+# Space separated list of interfaces from which pre-authentication frames are
381
+# accepted (e.g., 'eth0' or 'eth0 wlan0wds0'. This list should include all
382
+# interface that are used for connections to other APs. This could include
383
+# wired interfaces and WDS links. The normal wireless data interface towards
384
+# associated stations (e.g., wlan0) should not be added, since
385
+# pre-authentication is only used with APs other than the currently associated
386
+# one.
387
+#rsn_preauth_interfaces=eth0

+ 291
- 0
hostapd/README-WPS Näytä tiedosto

@@ -0,0 +1,291 @@
1
+hostapd and Wi-Fi Protected Setup (WPS)
2
+=======================================
3
+
4
+This document describes how the WPS implementation in hostapd can be
5
+configured and how an external component on an AP (e.g., web UI) is
6
+used to enable enrollment of client devices.
7
+
8
+
9
+Introduction to WPS
10
+-------------------
11
+
12
+Wi-Fi Protected Setup (WPS) is a mechanism for easy configuration of a
13
+wireless network. It allows automated generation of random keys (WPA
14
+passphrase/PSK) and configuration of an access point and client
15
+devices. WPS includes number of methods for setting up connections
16
+with PIN method and push-button configuration (PBC) being the most
17
+commonly deployed options.
18
+
19
+While WPS can enable more home networks to use encryption in the
20
+wireless network, it should be noted that the use of the PIN and
21
+especially PBC mechanisms for authenticating the initial key setup is
22
+not very secure. As such, use of WPS may not be suitable for
23
+environments that require secure network access without chance for
24
+allowing outsiders to gain access during the setup phase.
25
+
26
+WPS uses following terms to describe the entities participating in the
27
+network setup:
28
+- access point: the WLAN access point
29
+- Registrar: a device that control a network and can authorize
30
+  addition of new devices); this may be either in the AP ("internal
31
+  Registrar") or in an external device, e.g., a laptop, ("external
32
+  Registrar")
33
+- Enrollee: a device that is being authorized to use the network
34
+
35
+It should also be noted that the AP and a client device may change
36
+roles (i.e., AP acts as an Enrollee and client device as a Registrar)
37
+when WPS is used to configure the access point.
38
+
39
+
40
+More information about WPS is available from Wi-Fi Alliance:
41
+http://www.wi-fi.org/wifi-protected-setup
42
+
43
+
44
+hostapd implementation
45
+----------------------
46
+
47
+hostapd includes an optional WPS component that can be used as an
48
+internal WPS Registrar to manage addition of new WPS enabled clients
49
+to the network. In addition, WPS Enrollee functionality in hostapd can
50
+be used to allow external WPS Registrars to configure the access
51
+point, e.g., for initial network setup. In addition, hostapd can proxy a
52
+WPS registration between a wireless Enrollee and an external Registrar
53
+(e.g., Microsoft Vista or Atheros JumpStart) with UPnP.
54
+
55
+
56
+hostapd configuration
57
+---------------------
58
+
59
+WPS is an optional component that needs to be enabled in hostapd build
60
+configuration (.config). Here is an example configuration that
61
+includes WPS support and uses madwifi driver interface:
62
+
63
+CONFIG_DRIVER_MADWIFI=y
64
+CFLAGS += -I/usr/src/madwifi-0.9.3
65
+CONFIG_WPS=y
66
+CONFIG_WPS2=y
67
+CONFIG_WPS_UPNP=y
68
+
69
+
70
+Following section shows an example runtime configuration
71
+(hostapd.conf) that enables WPS:
72
+
73
+# Configure the driver and network interface
74
+driver=madwifi
75
+interface=ath0
76
+
77
+# WPA2-Personal configuration for the AP
78
+ssid=wps-test
79
+wpa=2
80
+wpa_key_mgmt=WPA-PSK
81
+wpa_pairwise=CCMP
82
+# Default WPA passphrase for legacy (non-WPS) clients
83
+wpa_passphrase=12345678
84
+# Enable random per-device PSK generation for WPS clients
85
+# Please note that the file has to exists for hostapd to start (i.e., create an
86
+# empty file as a starting point).
87
+wpa_psk_file=/etc/hostapd.psk
88
+
89
+# Enable control interface for PBC/PIN entry
90
+ctrl_interface=/var/run/hostapd
91
+
92
+# Enable internal EAP server for EAP-WSC (part of Wi-Fi Protected Setup)
93
+eap_server=1
94
+
95
+# WPS configuration (AP configured, do not allow external WPS Registrars)
96
+wps_state=2
97
+ap_setup_locked=1
98
+# If UUID is not configured, it will be generated based on local MAC address.
99
+uuid=87654321-9abc-def0-1234-56789abc0000
100
+wps_pin_requests=/var/run/hostapd.pin-req
101
+device_name=Wireless AP
102
+manufacturer=Company
103
+model_name=WAP
104
+model_number=123
105
+serial_number=12345
106
+device_type=6-0050F204-1
107
+os_version=01020300
108
+config_methods=label display push_button keypad
109
+
110
+# if external Registrars are allowed, UPnP support could be added:
111
+#upnp_iface=br0
112
+#friendly_name=WPS Access Point
113
+
114
+
115
+External operations
116
+-------------------
117
+
118
+WPS requires either a device PIN code (usually, 8-digit number) or a
119
+pushbutton event (for PBC) to allow a new WPS Enrollee to join the
120
+network. hostapd uses the control interface as an input channel for
121
+these events.
122
+
123
+The PIN value used in the commands must be processed by an UI to
124
+remove non-digit characters and potentially, to verify the checksum
125
+digit. "hostapd_cli wps_check_pin <PIN>" can be used to do such
126
+processing. It returns FAIL if the PIN is invalid, or FAIL-CHECKSUM if
127
+the checksum digit is incorrect, or the processed PIN (non-digit
128
+characters removed) if the PIN is valid.
129
+
130
+When a client device (WPS Enrollee) connects to hostapd (WPS
131
+Registrar) in order to start PIN mode negotiation for WPS, an
132
+identifier (Enrollee UUID) is sent. hostapd will need to be configured
133
+with a device password (PIN) for this Enrollee. This is an operation
134
+that requires user interaction (assuming there are no pre-configured
135
+PINs on the AP for a set of Enrollee).
136
+
137
+The PIN request with information about the device is appended to the
138
+wps_pin_requests file (/var/run/hostapd.pin-req in this example). In
139
+addition, hostapd control interface event is sent as a notification of
140
+a new device. The AP could use, e.g., a web UI for showing active
141
+Enrollees to the user and request a PIN for an Enrollee.
142
+
143
+The PIN request file has one line for every Enrollee that connected to
144
+the AP, but for which there was no PIN. Following information is
145
+provided for each Enrollee (separated with tabulators):
146
+- timestamp (seconds from 1970-01-01)
147
+- Enrollee UUID
148
+- MAC address
149
+- Device name
150
+- Manufacturer
151
+- Model Name
152
+- Model Number
153
+- Serial Number
154
+- Device category
155
+
156
+Example line in the /var/run/hostapd.pin-req file:
157
+1200188391	53b63a98-d29e-4457-a2ed-094d7e6a669c	Intel(R) Centrino(R)	Intel Corporation	Intel(R) Centrino(R)	-	-	1-0050F204-1
158
+
159
+Control interface data:
160
+WPS-PIN-NEEDED [UUID-E|MAC Address|Device Name|Manufacturer|Model Name|Model Number|Serial Number|Device Category]
161
+For example:
162
+<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]
163
+
164
+When the user enters a PIN for a pending Enrollee, e.g., on the web
165
+UI), hostapd needs to be notified of the new PIN over the control
166
+interface. This can be done either by using the UNIX domain socket
167
+-based control interface directly (src/common/wpa_ctrl.c provides
168
+helper functions for using the interface) or by calling hostapd_cli.
169
+
170
+Example command to add a PIN (12345670) for an Enrollee:
171
+
172
+hostapd_cli wps_pin 53b63a98-d29e-4457-a2ed-094d7e6a669c 12345670
173
+
174
+If the UUID-E is not available (e.g., Enrollee waits for the Registrar
175
+to be selected before connecting), wildcard UUID may be used to allow
176
+the PIN to be used once with any UUID:
177
+
178
+hostapd_cli wps_pin any 12345670
179
+
180
+To reduce likelihood of PIN being used with other devices or of
181
+forgetting an active PIN available for potential attackers, expiration
182
+time in seconds can be set for the new PIN (value 0 indicates no
183
+expiration):
184
+
185
+hostapd_cli wps_pin any 12345670 300
186
+
187
+If the MAC address of the enrollee is known, it should be configured
188
+to allow the AP to advertise list of authorized enrollees:
189
+
190
+hostapd_cli wps_pin 53b63a98-d29e-4457-a2ed-094d7e6a669c \
191
+	12345670 300 00:11:22:33:44:55
192
+
193
+
194
+After this, the Enrollee can connect to the AP again and complete WPS
195
+negotiation. At that point, a new, random WPA PSK is generated for the
196
+client device and the client can then use that key to connect to the
197
+AP to access the network.
198
+
199
+
200
+If the AP includes a pushbutton, WPS PBC mode can be used. It is
201
+enabled by pushing a button on both the AP and the client at about the
202
+same time (2 minute window). hostapd needs to be notified about the AP
203
+button pushed event over the control interface, e.g., by calling
204
+hostapd_cli:
205
+
206
+hostapd_cli wps_pbc
207
+
208
+At this point, the client has two minutes to complete WPS negotiation
209
+which will generate a new WPA PSK in the same way as the PIN method
210
+described above.
211
+
212
+
213
+When an external Registrar is used, the AP can act as an Enrollee and
214
+use its AP PIN. A static AP PIN (e.g., one one a label in the AP
215
+device) can be configured in hostapd.conf (ap_pin parameter). A more
216
+secure option is to use hostapd_cli wps_ap_pin command to enable the
217
+AP PIN only based on user action (and even better security by using a
218
+random AP PIN for each session, i.e., by using "wps_ap_pin random"
219
+command with a timeout value). Following commands are available for
220
+managing the dynamic AP PIN operations:
221
+
222
+hostapd_cli wps_ap_pin disable
223
+- disable AP PIN (i.e., do not allow external Registrars to use it to
224
+  learn the current AP settings or to reconfigure the AP)
225
+
226
+hostapd_cli wps_ap_pin random [timeout]
227
+- generate a random AP PIN and enable it
228
+- if the optional timeout parameter is given, the AP PIN will be enabled
229
+  for the specified number of seconds
230
+
231
+hostapd_cli wps_ap_pin get
232
+- fetch the current AP PIN
233
+
234
+hostapd_cli wps_ap_pin set <PIN> [timeout]
235
+- set the AP PIN and enable it
236
+- if the optional timeout parameter is given, the AP PIN will be enabled
237
+  for the specified number of seconds
238
+
239
+hostapd_cli get_config
240
+- display the current configuration
241
+
242
+hostapd_cli wps_config <new SSID> <auth> <encr> <new key>
243
+examples:
244
+  hostapd_cli wps_config testing WPA2PSK CCMP 12345678
245
+  hostapd_cli wps_config "no security" OPEN NONE ""
246
+
247
+<auth> must be one of the following: OPEN WPAPSK WPA2PSK
248
+<encr> must be one of the following: NONE WEP TKIP CCMP
249
+
250
+
251
+Credential generation and configuration changes
252
+-----------------------------------------------
253
+
254
+By default, hostapd generates credentials for Enrollees and processing
255
+AP configuration updates internally. However, it is possible to
256
+control these operations from external programs, if desired.
257
+
258
+The internal credential generation can be disabled with
259
+skip_cred_build=1 option in the configuration. extra_cred option will
260
+then need to be used to provide pre-configured Credential attribute(s)
261
+for hostapd to use. The exact data from this binary file will be sent,
262
+i.e., it will have to include valid WPS attributes. extra_cred can
263
+also be used to add additional networks if the Registrar is used to
264
+configure credentials for multiple networks.
265
+
266
+Processing of received configuration updates can be disabled with
267
+wps_cred_processing=1 option. When this is used, an external program
268
+is responsible for creating hostapd configuration files and processing
269
+configuration updates based on messages received from hostapd over
270
+control interface. This will also include the initial configuration on
271
+first successful registration if the AP is initially set in
272
+unconfigured state.
273
+
274
+Following control interface messages are sent out for external programs:
275
+
276
+WPS-REG-SUCCESS <Enrollee MAC address <UUID-E>
277
+For example:
278
+<2>WPS-REG-SUCCESS 02:66:a0:ee:17:27 2b7093f1-d6fb-5108-adbb-bea66bb87333
279
+
280
+This can be used to trigger change from unconfigured to configured
281
+state (random configuration based on the first successful WPS
282
+registration). In addition, this can be used to update AP UI about the
283
+status of WPS registration progress.
284
+
285
+
286
+WPS-NEW-AP-SETTINGS <hexdump of AP Setup attributes>
287
+For example:
288
+<2>WPS-NEW-AP-SETTINGS 10260001011045000c6a6b6d2d7770732d74657374100300020020100f00020008102700403065346230343536633236366665306433396164313535346131663462663731323433376163666462376633393965353466316631623032306164343438623510200006024231cede15101e000844
289
+
290
+This can be used to update the externally stored AP configuration and
291
+then update hostapd configuration (followed by restarting of hostapd).

+ 78
- 0
hostapd/bsd_hostapd.conf Näytä tiedosto

@@ -0,0 +1,78 @@
1
+##### hostapd configuration file ##############################################
2
+
3
+interface=rtw0
4
+ctrl_interface=/var/run/hostapd
5
+ssid=freebsd_ap_test
6
+channel=6
7
+wpa=2
8
+wpa_passphrase=87654321
9
+
10
+
11
+
12
+##### Wi-Fi Protected Setup (WPS) #############################################
13
+
14
+eap_server=1
15
+
16
+# WPS state
17
+# 0 = WPS disabled (default)
18
+# 1 = WPS enabled, not configured
19
+# 2 = WPS enabled, configured
20
+wps_state=2
21
+
22
+uuid=12345678-9abc-def0-1234-56789abcdef0
23
+
24
+# Device Name
25
+# User-friendly description of device; up to 32 octets encoded in UTF-8
26
+device_name=RTL8192CU
27
+
28
+# Manufacturer
29
+# The manufacturer of the device (up to 64 ASCII characters)
30
+manufacturer=Realtek
31
+
32
+# Model Name
33
+# Model of the device (up to 32 ASCII characters)
34
+model_name=RTW_SOFTAP
35
+
36
+# Model Number
37
+# Additional device description (up to 32 ASCII characters)
38
+model_number=WLAN_CU
39
+
40
+# Serial Number
41
+# Serial number of the device (up to 32 characters)
42
+serial_number=12345
43
+
44
+# Primary Device Type
45
+# Used format: <categ>-<OUI>-<subcateg>
46
+# categ = Category as an integer value
47
+# OUI = OUI and type octet as a 4-octet hex-encoded value; 0050F204 for
48
+#       default WPS OUI
49
+# subcateg = OUI-specific Sub Category as an integer value
50
+# Examples:
51
+#   1-0050F204-1 (Computer / PC)
52
+#   1-0050F204-2 (Computer / Server)
53
+#   5-0050F204-1 (Storage / NAS)
54
+#   6-0050F204-1 (Network Infrastructure / AP)
55
+device_type=6-0050F204-1
56
+
57
+# OS Version
58
+# 4-octet operating system version number (hex string)
59
+os_version=01020300
60
+
61
+# Config Methods
62
+# List of the supported configuration methods
63
+config_methods=label display push_button keypad
64
+
65
+
66
+##### default configuration #######################################
67
+
68
+driver=bsd
69
+beacon_int=100
70
+hw_mode=g
71
+ieee80211n=1
72
+wme_enabled=1
73
+ht_capab=[SHORT-GI-20][SHORT-GI-40]
74
+wpa_key_mgmt=WPA-PSK
75
+wpa_pairwise=CCMP
76
+max_num_sta=8
77
+wpa_group_rekey=86400
78
+

+ 2119
- 0
hostapd/config_file.c
File diff suppressed because it is too large
Näytä tiedosto


+ 20
- 0
hostapd/config_file.h Näytä tiedosto

@@ -0,0 +1,20 @@
1
+/*
2
+ * hostapd / Configuration file parser
3
+ * Copyright (c) 2003-2009, Jouni Malinen <j@w1.fi>
4
+ *
5
+ * This program is free software; you can redistribute it and/or modify
6
+ * it under the terms of the GNU General Public License version 2 as
7
+ * published by the Free Software Foundation.
8
+ *
9
+ * Alternatively, this software may be distributed under the terms of BSD
10
+ * license.
11
+ *
12
+ * See README and COPYING for more details.
13
+ */
14
+
15
+#ifndef CONFIG_FILE_H
16
+#define CONFIG_FILE_H
17
+
18
+struct hostapd_config * hostapd_config_read(const char *fname);
19
+
20
+#endif /* CONFIG_FILE_H */

+ 1131
- 0
hostapd/ctrl_iface.c
File diff suppressed because it is too large
Näytä tiedosto


+ 32
- 0
hostapd/ctrl_iface.h Näytä tiedosto

@@ -0,0 +1,32 @@
1
+/*
2
+ * hostapd / UNIX domain socket -based control interface
3
+ * Copyright (c) 2004, Jouni Malinen <j@w1.fi>
4
+ *
5
+ * This program is free software; you can redistribute it and/or modify
6
+ * it under the terms of the GNU General Public License version 2 as
7
+ * published by the Free Software Foundation.
8
+ *
9
+ * Alternatively, this software may be distributed under the terms of BSD
10
+ * license.
11
+ *
12
+ * See README and COPYING for more details.
13
+ */
14
+
15
+#ifndef CTRL_IFACE_H
16
+#define CTRL_IFACE_H
17
+
18
+#ifndef CONFIG_NO_CTRL_IFACE
19
+int hostapd_ctrl_iface_init(struct hostapd_data *hapd);
20
+void hostapd_ctrl_iface_deinit(struct hostapd_data *hapd);
21
+#else /* CONFIG_NO_CTRL_IFACE */
22
+static inline int hostapd_ctrl_iface_init(struct hostapd_data *hapd)
23
+{
24
+	return 0;
25
+}
26
+
27
+static inline void hostapd_ctrl_iface_deinit(struct hostapd_data *hapd)
28
+{
29
+}
30
+#endif /* CONFIG_NO_CTRL_IFACE */
31
+
32
+#endif /* CTRL_IFACE_H */

+ 204
- 0
hostapd/defconfig Näytä tiedosto

@@ -0,0 +1,204 @@
1
+# Example hostapd build time configuration
2
+#
3
+# This file lists the configuration options that are used when building the
4
+# hostapd binary. All lines starting with # are ignored. Configuration option
5
+# lines must be commented out complete, if they are not to be included, i.e.,
6
+# just setting VARIABLE=n is not disabling that variable.
7
+#
8
+# This file is included in Makefile, so variables like CFLAGS and LIBS can also
9
+# be modified from here. In most cass, these lines should use += in order not
10
+# to override previous values of the variables.
11
+
12
+# Driver interface for Host AP driver
13
+CONFIG_DRIVER_HOSTAP=y
14
+
15
+# Driver interface for wired authenticator
16
+#CONFIG_DRIVER_WIRED=y
17
+
18
+# Driver interface for madwifi driver
19
+#CONFIG_DRIVER_MADWIFI=y
20
+#CFLAGS += -I../../madwifi # change to the madwifi source directory
21
+
22
+# Driver interface for drivers using the nl80211 kernel interface
23
+#CONFIG_DRIVER_NL80211=y
24
+
25
+# Driver interface for FreeBSD net80211 layer (e.g., Atheros driver)
26
+#CONFIG_DRIVER_BSD=y
27
+#CFLAGS += -I/usr/local/include
28
+#LIBS += -L/usr/local/lib
29
+#LIBS_p += -L/usr/local/lib
30
+#LIBS_c += -L/usr/local/lib
31
+
32
+# Driver interface for no driver (e.g., RADIUS server only)
33
+#CONFIG_DRIVER_NONE=y
34
+
35
+# IEEE 802.11F/IAPP
36
+CONFIG_IAPP=y
37
+
38
+# WPA2/IEEE 802.11i RSN pre-authentication
39
+CONFIG_RSN_PREAUTH=y
40
+
41
+# PeerKey handshake for Station to Station Link (IEEE 802.11e DLS)
42
+CONFIG_PEERKEY=y
43
+
44
+# IEEE 802.11w (management frame protection)
45
+# This version is an experimental implementation based on IEEE 802.11w/D1.0
46
+# draft and is subject to change since the standard has not yet been finalized.
47
+# Driver support is also needed for IEEE 802.11w.
48
+#CONFIG_IEEE80211W=y
49
+
50
+# Integrated EAP server
51
+CONFIG_EAP=y
52
+
53
+# EAP-MD5 for the integrated EAP server
54
+CONFIG_EAP_MD5=y
55
+
56
+# EAP-TLS for the integrated EAP server
57
+CONFIG_EAP_TLS=y
58
+
59
+# EAP-MSCHAPv2 for the integrated EAP server
60
+CONFIG_EAP_MSCHAPV2=y
61
+
62
+# EAP-PEAP for the integrated EAP server
63
+CONFIG_EAP_PEAP=y
64
+
65
+# EAP-GTC for the integrated EAP server
66
+CONFIG_EAP_GTC=y
67
+
68
+# EAP-TTLS for the integrated EAP server
69
+CONFIG_EAP_TTLS=y
70
+
71
+# EAP-SIM for the integrated EAP server
72
+#CONFIG_EAP_SIM=y
73
+
74
+# EAP-AKA for the integrated EAP server
75
+#CONFIG_EAP_AKA=y
76
+
77
+# EAP-AKA' for the integrated EAP server
78
+# This requires CONFIG_EAP_AKA to be enabled, too.
79
+#CONFIG_EAP_AKA_PRIME=y
80
+
81
+# EAP-PAX for the integrated EAP server
82
+#CONFIG_EAP_PAX=y
83
+
84
+# EAP-PSK for the integrated EAP server (this is _not_ needed for WPA-PSK)
85
+#CONFIG_EAP_PSK=y
86
+
87
+# EAP-SAKE for the integrated EAP server
88
+#CONFIG_EAP_SAKE=y
89
+
90
+# EAP-GPSK for the integrated EAP server
91
+#CONFIG_EAP_GPSK=y
92
+# Include support for optional SHA256 cipher suite in EAP-GPSK
93
+#CONFIG_EAP_GPSK_SHA256=y
94
+
95
+# EAP-FAST for the integrated EAP server
96
+# Note: Default OpenSSL package does not include support for all the
97
+# functionality needed for EAP-FAST. If EAP-FAST is enabled with OpenSSL,
98
+# the OpenSSL library must be patched (openssl-0.9.9-session-ticket.patch)
99
+# to add the needed functions.
100
+#CONFIG_EAP_FAST=y
101
+
102
+# Wi-Fi Protected Setup (WPS)
103
+#CONFIG_WPS=y
104
+# Enable WSC 2.0 support
105
+#CONFIG_WPS2=y
106
+# Enable UPnP support for external WPS Registrars
107
+#CONFIG_WPS_UPNP=y
108
+
109
+# EAP-IKEv2
110
+#CONFIG_EAP_IKEV2=y
111
+
112
+# Trusted Network Connect (EAP-TNC)
113
+#CONFIG_EAP_TNC=y
114
+
115
+# PKCS#12 (PFX) support (used to read private key and certificate file from
116
+# a file that usually has extension .p12 or .pfx)
117
+CONFIG_PKCS12=y
118
+
119
+# RADIUS authentication server. This provides access to the integrated EAP
120
+# server from external hosts using RADIUS.
121
+#CONFIG_RADIUS_SERVER=y
122
+
123
+# Build IPv6 support for RADIUS operations
124
+CONFIG_IPV6=y
125
+
126
+# IEEE Std 802.11r-2008 (Fast BSS Transition)
127
+#CONFIG_IEEE80211R=y
128
+
129
+# Use the hostapd's IEEE 802.11 authentication (ACL), but without
130
+# the IEEE 802.11 Management capability (e.g., madwifi or FreeBSD/net80211)
131
+#CONFIG_DRIVER_RADIUS_ACL=y
132
+
133
+# IEEE 802.11n (High Throughput) support
134
+#CONFIG_IEEE80211N=y
135
+
136
+# Remove debugging code that is printing out debug messages to stdout.
137
+# This can be used to reduce the size of the hostapd considerably if debugging
138
+# code is not needed.
139
+#CONFIG_NO_STDOUT_DEBUG=y
140
+
141
+# Add support for writing debug log to a file: -f /tmp/hostapd.log
142
+# Disabled by default.
143
+#CONFIG_DEBUG_FILE=y
144
+
145
+# Remove support for RADIUS accounting
146
+#CONFIG_NO_ACCOUNTING=y
147
+
148
+# Remove support for RADIUS
149
+#CONFIG_NO_RADIUS=y
150
+
151
+# Remove support for VLANs
152
+#CONFIG_NO_VLAN=y
153
+
154
+# Enable support for fully dynamic VLANs. This enables hostapd to
155
+# automatically create bridge and VLAN interfaces if necessary.
156
+#CONFIG_FULL_DYNAMIC_VLAN=y
157
+
158
+# Remove support for dumping state into a file on SIGUSR1 signal
159
+# This can be used to reduce binary size at the cost of disabling a debugging
160
+# option.
161
+#CONFIG_NO_DUMP_STATE=y
162
+
163
+# Enable tracing code for developer debugging
164
+# This tracks use of memory allocations and other registrations and reports
165
+# incorrect use with a backtrace of call (or allocation) location.
166
+#CONFIG_WPA_TRACE=y
167
+# For BSD, comment out these.
168
+#LIBS += -lexecinfo
169
+#LIBS_p += -lexecinfo
170
+#LIBS_c += -lexecinfo
171
+
172
+# Use libbfd to get more details for developer debugging
173
+# This enables use of libbfd to get more detailed symbols for the backtraces
174
+# generated by CONFIG_WPA_TRACE=y.
175
+#CONFIG_WPA_TRACE_BFD=y
176
+# For BSD, comment out these.
177
+#LIBS += -lbfd -liberty -lz
178
+#LIBS_p += -lbfd -liberty -lz
179
+#LIBS_c += -lbfd -liberty -lz
180
+
181
+# hostapd depends on strong random number generation being available from the
182
+# operating system. os_get_random() function is used to fetch random data when
183
+# needed, e.g., for key generation. On Linux and BSD systems, this works by
184
+# reading /dev/urandom. It should be noted that the OS entropy pool needs to be
185
+# properly initialized before hostapd is started. This is important especially
186
+# on embedded devices that do not have a hardware random number generator and
187
+# may by default start up with minimal entropy available for random number
188
+# generation.
189
+#
190
+# As a safety net, hostapd is by default trying to internally collect
191
+# additional entropy for generating random data to mix in with the data
192
+# fetched from the OS. This by itself is not considered to be very strong, but
193
+# it may help in cases where the system pool is not initialized properly.
194
+# However, it is very strongly recommended that the system pool is initialized
195
+# with enough entropy either by using hardware assisted random number
196
+# generatior or by storing state over device reboots.
197
+#
198
+# If the os_get_random() is known to provide strong ramdom data (e.g., on
199
+# Linux/BSD, the board in question is known to have reliable source of random
200
+# data from /dev/urandom), the internal hostapd random pool can be disabled.
201
+# This will save some in binary size and CPU use. However, this should only be
202
+# considered for builds that are known to be used on devices that meet the
203
+# requirements described above.
204
+#CONFIG_NO_RANDOM_POOL=y

+ 183
- 0
hostapd/dump_state.c Näytä tiedosto

@@ -0,0 +1,183 @@
1
+/*
2
+ * hostapd / State dump
3
+ * Copyright (c) 2002-2009, Jouni Malinen <j@w1.fi>
4
+ *
5
+ * This program is free software; you can redistribute it and/or modify
6
+ * it under the terms of the GNU General Public License version 2 as
7
+ * published by the Free Software Foundation.
8
+ *
9
+ * Alternatively, this software may be distributed under the terms of BSD
10
+ * license.
11
+ *
12
+ * See README and COPYING for more details.
13
+ */
14
+
15
+#include "utils/includes.h"
16
+
17
+#include "utils/common.h"
18
+#include "radius/radius_client.h"
19
+#include "radius/radius_server.h"
20
+#include "eapol_auth/eapol_auth_sm.h"
21
+#include "eapol_auth/eapol_auth_sm_i.h"
22
+#include "eap_server/eap.h"
23
+#include "ap/hostapd.h"
24
+#include "ap/ap_config.h"
25
+#include "ap/sta_info.h"
26
+#include "dump_state.h"
27
+
28
+
29
+static void fprint_char(FILE *f, char c)
30
+{
31
+	if (c >= 32 && c < 127)
32
+		fprintf(f, "%c", c);
33
+	else
34
+		fprintf(f, "<%02x>", c);
35
+}
36
+
37
+
38
+static void ieee802_1x_dump_state(FILE *f, const char *prefix,
39
+				  struct sta_info *sta)
40
+{
41
+	struct eapol_state_machine *sm = sta->eapol_sm;
42
+	if (sm == NULL)
43
+		return;
44
+
45
+	fprintf(f, "%sIEEE 802.1X:\n", prefix);
46
+
47
+	if (sm->identity) {
48
+		size_t i;
49
+		fprintf(f, "%sidentity=", prefix);
50
+		for (i = 0; i < sm->identity_len; i++)
51
+			fprint_char(f, sm->identity[i]);
52
+		fprintf(f, "\n");
53
+	}
54
+
55
+	fprintf(f, "%slast EAP type: Authentication Server: %d (%s) "
56
+		"Supplicant: %d (%s)\n", prefix,
57
+		sm->eap_type_authsrv,
58
+		eap_server_get_name(0, sm->eap_type_authsrv),
59
+		sm->eap_type_supp, eap_server_get_name(0, sm->eap_type_supp));
60
+
61
+	fprintf(f, "%scached_packets=%s\n", prefix,
62
+		sm->last_recv_radius ? "[RX RADIUS]" : "");
63
+
64
+	eapol_auth_dump_state(f, prefix, sm);
65
+}
66
+
67
+
68
+/**
69
+ * hostapd_dump_state - SIGUSR1 handler to dump hostapd state to a text file
70
+ */
71
+static void hostapd_dump_state(struct hostapd_data *hapd)
72
+{
73
+	FILE *f;
74
+	time_t now;
75
+	struct sta_info *sta;
76
+	int i;
77
+#ifndef CONFIG_NO_RADIUS
78
+	char *buf;
79
+#endif /* CONFIG_NO_RADIUS */
80
+
81
+	if (!hapd->conf->dump_log_name) {
82
+		wpa_printf(MSG_DEBUG, "Dump file not defined - ignoring dump "
83
+			   "request");
84
+		return;
85
+	}
86
+
87
+	wpa_printf(MSG_DEBUG, "Dumping hostapd state to '%s'",
88
+		   hapd->conf->dump_log_name);
89
+	f = fopen(hapd->conf->dump_log_name, "w");
90
+	if (f == NULL) {
91
+		wpa_printf(MSG_WARNING, "Could not open dump file '%s' for "
92
+			   "writing.", hapd->conf->dump_log_name);
93
+		return;
94
+	}
95
+
96
+	time(&now);
97
+	fprintf(f, "hostapd state dump - %s", ctime(&now));
98
+	fprintf(f, "num_sta=%d num_sta_non_erp=%d "
99
+		"num_sta_no_short_slot_time=%d\n"
100
+		"num_sta_no_short_preamble=%d\n",
101
+		hapd->num_sta, hapd->iface->num_sta_non_erp,
102
+		hapd->iface->num_sta_no_short_slot_time,
103
+		hapd->iface->num_sta_no_short_preamble);
104
+
105
+	for (sta = hapd->sta_list; sta != NULL; sta = sta->next) {
106
+		fprintf(f, "\nSTA=" MACSTR "\n", MAC2STR(sta->addr));
107
+
108
+		fprintf(f,
109
+			"  AID=%d flags=0x%x %s%s%s%s%s%s%s%s%s%s%s%s%s%s%s\n"
110
+			"  capability=0x%x listen_interval=%d\n",
111
+			sta->aid,
112
+			sta->flags,
113
+			(sta->flags & WLAN_STA_AUTH ? "[AUTH]" : ""),
114
+			(sta->flags & WLAN_STA_ASSOC ? "[ASSOC]" : ""),
115
+			(sta->flags & WLAN_STA_PS ? "[PS]" : ""),
116
+			(sta->flags & WLAN_STA_TIM ? "[TIM]" : ""),
117
+			(sta->flags & WLAN_STA_PERM ? "[PERM]" : ""),
118
+			(ap_sta_is_authorized(sta) ? "[AUTHORIZED]" : ""),
119
+			(sta->flags & WLAN_STA_PENDING_POLL ? "[PENDING_POLL" :
120
+			 ""),
121
+			(sta->flags & WLAN_STA_SHORT_PREAMBLE ?
122
+			 "[SHORT_PREAMBLE]" : ""),
123
+			(sta->flags & WLAN_STA_PREAUTH ? "[PREAUTH]" : ""),
124
+			(sta->flags & WLAN_STA_WMM ? "[WMM]" : ""),
125
+			(sta->flags & WLAN_STA_MFP ? "[MFP]" : ""),
126
+			(sta->flags & WLAN_STA_WPS ? "[WPS]" : ""),
127
+			(sta->flags & WLAN_STA_MAYBE_WPS ? "[MAYBE_WPS]" : ""),
128
+			(sta->flags & WLAN_STA_WDS ? "[WDS]" : ""),
129
+			(sta->flags & WLAN_STA_NONERP ? "[NonERP]" : ""),
130
+			sta->capability,
131
+			sta->listen_interval);
132
+
133
+		fprintf(f, "  supported_rates=");
134
+		for (i = 0; i < sta->supported_rates_len; i++)
135
+			fprintf(f, "%02x ", sta->supported_rates[i]);
136
+		fprintf(f, "\n");
137
+
138
+		fprintf(f,
139
+			"  timeout_next=%s\n",
140
+			(sta->timeout_next == STA_NULLFUNC ? "NULLFUNC POLL" :
141
+			 (sta->timeout_next == STA_DISASSOC ? "DISASSOC" :
142
+			  "DEAUTH")));
143
+
144
+		ieee802_1x_dump_state(f, "  ", sta);
145
+	}
146
+
147
+#ifndef CONFIG_NO_RADIUS
148
+	buf = os_malloc(4096);
149
+	if (buf) {
150
+		int count = radius_client_get_mib(hapd->radius, buf, 4096);
151
+		if (count < 0)
152
+			count = 0;
153
+		else if (count > 4095)
154
+			count = 4095;
155
+		buf[count] = '\0';
156
+		fprintf(f, "%s", buf);
157
+
158
+#ifdef RADIUS_SERVER
159
+		count = radius_server_get_mib(hapd->radius_srv, buf, 4096);
160
+		if (count < 0)
161
+			count = 0;
162
+		else if (count > 4095)
163
+			count = 4095;
164
+		buf[count] = '\0';
165
+		fprintf(f, "%s", buf);
166
+#endif /* RADIUS_SERVER */
167
+
168
+		os_free(buf);
169
+	}
170
+#endif /* CONFIG_NO_RADIUS */
171
+	fclose(f);
172
+}
173
+
174
+
175
+int handle_dump_state_iface(struct hostapd_iface *iface, void *ctx)
176
+{
177
+	size_t i;
178
+
179
+	for (i = 0; i < iface->num_bss; i++)
180
+		hostapd_dump_state(iface->bss[i]);
181
+
182
+	return 0;
183
+}

+ 20
- 0
hostapd/dump_state.h Näytä tiedosto

@@ -0,0 +1,20 @@
1
+/*
2
+ * hostapd / State dump
3
+ * Copyright (c) 2002-2009, Jouni Malinen <j@w1.fi>
4
+ *
5
+ * This program is free software; you can redistribute it and/or modify
6
+ * it under the terms of the GNU General Public License version 2 as
7
+ * published by the Free Software Foundation.
8
+ *
9
+ * Alternatively, this software may be distributed under the terms of BSD
10
+ * license.
11
+ *
12
+ * See README and COPYING for more details.
13
+ */
14
+
15
+#ifndef DUMP_STATE_H
16
+#define DUMP_STATE_H
17
+
18
+int handle_dump_state_iface(struct hostapd_iface *iface, void *ctx);
19
+
20
+#endif /* DUMP_STATE_H */

+ 139
- 0
hostapd/eap_register.c Näytä tiedosto

@@ -0,0 +1,139 @@
1
+/*
2
+ * EAP method registration
3
+ * Copyright (c) 2004-2009, Jouni Malinen <j@w1.fi>
4
+ *
5
+ * This program is free software; you can redistribute it and/or modify
6
+ * it under the terms of the GNU General Public License version 2 as
7
+ * published by the Free Software Foundation.
8
+ *
9
+ * Alternatively, this software may be distributed under the terms of BSD
10
+ * license.
11
+ *
12
+ * See README and COPYING for more details.
13
+ */
14
+
15
+#include "includes.h"
16
+
17
+#include "common.h"
18
+#include "eap_server/eap_methods.h"
19
+#include "eap_register.h"
20
+
21
+
22
+/**
23
+ * eap_server_register_methods - Register statically linked EAP server methods
24
+ * Returns: 0 on success, -1 or -2 on failure
25
+ *
26
+ * This function is called at program initialization to register all EAP
27
+ * methods that were linked in statically.
28
+ */
29
+int eap_server_register_methods(void)
30
+{
31
+	int ret = 0;
32
+
33
+#ifdef EAP_SERVER_IDENTITY
34
+	if (ret == 0)
35
+		ret = eap_server_identity_register();
36
+#endif /* EAP_SERVER_IDENTITY */
37
+
38
+#ifdef EAP_SERVER_MD5
39
+	if (ret == 0)
40
+		ret = eap_server_md5_register();
41
+#endif /* EAP_SERVER_MD5 */
42
+
43
+#ifdef EAP_SERVER_TLS
44
+	if (ret == 0)
45
+		ret = eap_server_tls_register();
46
+#endif /* EAP_SERVER_TLS */
47
+
48
+#ifdef EAP_SERVER_MSCHAPV2
49
+	if (ret == 0)
50
+		ret = eap_server_mschapv2_register();
51
+#endif /* EAP_SERVER_MSCHAPV2 */
52
+
53
+#ifdef EAP_SERVER_PEAP
54
+	if (ret == 0)
55
+		ret = eap_server_peap_register();
56
+#endif /* EAP_SERVER_PEAP */
57
+
58
+#ifdef EAP_SERVER_TLV
59
+	if (ret == 0)
60
+		ret = eap_server_tlv_register();
61
+#endif /* EAP_SERVER_TLV */
62
+
63
+#ifdef EAP_SERVER_GTC
64
+	if (ret == 0)
65
+		ret = eap_server_gtc_register();
66
+#endif /* EAP_SERVER_GTC */
67
+
68
+#ifdef EAP_SERVER_TTLS
69
+	if (ret == 0)
70
+		ret = eap_server_ttls_register();
71
+#endif /* EAP_SERVER_TTLS */
72
+
73
+#ifdef EAP_SERVER_SIM
74
+	if (ret == 0)
75
+		ret = eap_server_sim_register();
76
+#endif /* EAP_SERVER_SIM */
77
+
78
+#ifdef EAP_SERVER_AKA
79
+	if (ret == 0)
80
+		ret = eap_server_aka_register();
81
+#endif /* EAP_SERVER_AKA */
82
+
83
+#ifdef EAP_SERVER_AKA_PRIME
84
+	if (ret == 0)
85
+		ret = eap_server_aka_prime_register();
86
+#endif /* EAP_SERVER_AKA_PRIME */
87
+
88
+#ifdef EAP_SERVER_PAX
89
+	if (ret == 0)
90
+		ret = eap_server_pax_register();
91
+#endif /* EAP_SERVER_PAX */
92
+
93
+#ifdef EAP_SERVER_PSK
94
+	if (ret == 0)
95
+		ret = eap_server_psk_register();
96
+#endif /* EAP_SERVER_PSK */
97
+
98
+#ifdef EAP_SERVER_SAKE
99
+	if (ret == 0)
100
+		ret = eap_server_sake_register();
101
+#endif /* EAP_SERVER_SAKE */
102
+
103
+#ifdef EAP_SERVER_GPSK
104
+	if (ret == 0)
105
+		ret = eap_server_gpsk_register();
106
+#endif /* EAP_SERVER_GPSK */
107
+
108
+#ifdef EAP_SERVER_VENDOR_TEST
109
+	if (ret == 0)
110
+		ret = eap_server_vendor_test_register();
111
+#endif /* EAP_SERVER_VENDOR_TEST */
112
+
113
+#ifdef EAP_SERVER_FAST
114
+	if (ret == 0)
115
+		ret = eap_server_fast_register();
116
+#endif /* EAP_SERVER_FAST */
117
+
118
+#ifdef EAP_SERVER_WSC
119
+	if (ret == 0)
120
+		ret = eap_server_wsc_register();
121
+#endif /* EAP_SERVER_WSC */
122
+
123
+#ifdef EAP_SERVER_IKEV2
124
+	if (ret == 0)
125
+		ret = eap_server_ikev2_register();
126
+#endif /* EAP_SERVER_IKEV2 */
127
+
128
+#ifdef EAP_SERVER_TNC
129
+	if (ret == 0)
130
+		ret = eap_server_tnc_register();
131
+#endif /* EAP_SERVER_TNC */
132
+
133
+#ifdef EAP_SERVER_PWD
134
+	if (ret == 0)
135
+		ret = eap_server_pwd_register();
136
+#endif /* EAP_SERVER_PWD */
137
+
138
+	return ret;
139
+}

+ 20
- 0
hostapd/eap_register.h Näytä tiedosto

@@ -0,0 +1,20 @@
1
+/*
2
+ * EAP method registration
3
+ * Copyright (c) 2004-2009, Jouni Malinen <j@w1.fi>
4
+ *
5
+ * This program is free software; you can redistribute it and/or modify
6
+ * it under the terms of the GNU General Public License version 2 as
7
+ * published by the Free Software Foundation.
8
+ *
9
+ * Alternatively, this software may be distributed under the terms of BSD
10
+ * license.
11
+ *
12
+ * See README and COPYING for more details.
13
+ */
14
+
15
+#ifndef EAP_REGISTER_H
16
+#define EAP_REGISTER_H
17
+
18
+int eap_server_register_methods(void);
19
+
20
+#endif /* EAP_REGISTER_H */

+ 77
- 0
hostapd/eap_testing.txt Näytä tiedosto

@@ -0,0 +1,77 @@
1
+Interoperability testing of hostapd's IEEE 802.1X/EAPOL authentication
2
+
3
+Test matrix
4
+
5
++) tested successfully
6
+F) failed
7
+-) peer did not support
8
+?) not tested
9
+
10
+XSupplicant --------------------------------.
11
+Intel PROSet ---------------------------.   |
12
+Windows XP -------------------------.   |   |
13
+Mac OS X 10.4 ------------------.   |   |   |
14
+Nokia S60 ------------------.   |   |   |   |
15
+wpa_supplicant ---------.   |   |   |   |   |
16
+			|   |   |   |   |   |
17
+
18
+EAP-MD5			+   -   ?   ?   -
19
+EAP-GTC			+   -   ?   -   -
20
+EAP-MSCHAPv2		+   -   ?   -   -
21
+EAP-TLS			+   +   +1  +   +
22
+EAP-PEAPv0/MSCHAPv2	+   +   +   +   +   +
23
+EAP-PEAPv0/GTC		+   +   +   -   +
24
+EAP-PEAPv0/MD5		+   -   +   -   -
25
+EAP-PEAPv0/TLS		+   F   -   +   +
26
+EAP-PEAPv0/SIM		+   +   -   -   -
27
+EAP-PEAPv0/AKA		+   +   -   -   -
28
+EAP-PEAPv0/PSK		+   -   -   -   -
29
+EAP-PEAPv0/PAX		+   -   -   -   -
30
+EAP-PEAPv0/SAKE		+   -   -   -   -
31
+EAP-PEAPv0/GPSK		+   -   -   -   -
32
+EAP-PEAPv1/MSCHAPv2	+   +   +   -   +   +
33
+EAP-PEAPv1/GTC		+   +   +   -   +
34
+EAP-PEAPv1/MD5		+   -   +   -   -
35
+EAP-PEAPv1/TLS		+   F   -   -   +
36
+EAP-PEAPv1/SIM		+   +   -   -   -
37
+EAP-PEAPv1/AKA		+   +   -   -   -
38
+EAP-PEAPv1/PSK		+   -   -   -   -
39
+EAP-PEAPv1/PAX		+   -   -   -   -
40
+EAP-PEAPv1/SAKE		+   -   -   -   -
41
+EAP-PEAPv1/GPSK		+   -   -   -   -
42
+EAP-TTLS/CHAP		+   -   +   -   +   +
43
+EAP-TTLS/MSCHAP		+   -   +   -   +   +
44
+EAP-TTLS/MSCHAPv2	+   +   +   -   +   +
45
+EAP-TTLS/PAP		+   -   +   -   +   +
46
+EAP-TTLS/EAP-MD5	+   -   -   -   -   +
47
+EAP-TTLS/EAP-GTC	+   +   -   -   -
48
+EAP-TTLS/EAP-MSCHAPv2	+   +   -   -   -
49
+EAP-TTLS/EAP-TLS	+   F   -   -   -
50
+EAP-TTLS/EAP-SIM	+   +   -   -   -
51
+EAP-TTLS/EAP-AKA	+   +   -   -   -
52
+EAP-TTLS + TNC		+   -   -   -   -
53
+EAP-SIM			+   +   -   -   +
54
+EAP-AKA			+   +   -   -   -
55
+EAP-PAX			+   -   -   -   -
56
+EAP-SAKE		+   -   -   -   -
57
+EAP-GPSK		+   -   -   -   -
58
+EAP-FAST/MSCHAPv2(prov)	+   -   F   -   F
59
+EAP-FAST/GTC(auth)	+   -   +   -   +
60
+EAP-FAST/MSCHAPv2(aprov)+   -   F   -   F
61
+EAP-FAST/GTC(aprov)	+   -   F   -   F
62
+EAP-FAST/MD5(aprov)	+   -   -   -   -
63
+EAP-FAST/TLS(aprov)	+   -   -   -   -
64
+EAP-FAST/SIM(aprov)	+   -   -   -   -
65
+EAP-FAST/AKA(aprov)	+   -   -   -   -
66
+EAP-FAST/MSCHAPv2(auth)	+   -   +   -   +
67
+EAP-FAST/MD5(auth)	+   -   +   -   -
68
+EAP-FAST/TLS(auth)	+   -   -   -   -
69
+EAP-FAST/SIM(auth)	+   -   -   -   -
70
+EAP-FAST/AKA(auth)	+   -   -   -   -
71
+EAP-FAST + TNC		+   -   -   -   -
72
+EAP-IKEv2		+   -   -   -   -
73
+EAP-TNC			+   -   -   -   -
74
+
75
+1) EAP-TLS itself worked, but peer certificate validation failed at
76
+   least when using the internal TLS server (peer included incorrect
77
+   certificates in the chain?)

+ 715
- 0
hostapd/hlr_auc_gw.c Näytä tiedosto

@@ -0,0 +1,715 @@
1
+/*
2
+ * HLR/AuC testing gateway for hostapd EAP-SIM/AKA database/authenticator
3
+ * Copyright (c) 2005-2007, Jouni Malinen <j@w1.fi>
4
+ *
5
+ * This program is free software; you can redistribute it and/or modify
6
+ * it under the terms of the GNU General Public License version 2 as
7
+ * published by the Free Software Foundation.
8
+ *
9
+ * Alternatively, this software may be distributed under the terms of BSD
10
+ * license.
11
+ *
12
+ * See README and COPYING for more details.
13
+ *
14
+ * This is an example implementation of the EAP-SIM/AKA database/authentication
15
+ * gateway interface to HLR/AuC. It is expected to be replaced with an
16
+ * implementation of SS7 gateway to GSM/UMTS authentication center (HLR/AuC) or
17
+ * a local implementation of SIM triplet and AKA authentication data generator.
18
+ *
19
+ * hostapd will send SIM/AKA authentication queries over a UNIX domain socket
20
+ * to and external program, e.g., this hlr_auc_gw. This interface uses simple
21
+ * text-based format:
22
+ *
23
+ * EAP-SIM / GSM triplet query/response:
24
+ * SIM-REQ-AUTH <IMSI> <max_chal>
25
+ * SIM-RESP-AUTH <IMSI> Kc1:SRES1:RAND1 Kc2:SRES2:RAND2 [Kc3:SRES3:RAND3]
26
+ * SIM-RESP-AUTH <IMSI> FAILURE
27
+ *
28
+ * EAP-AKA / UMTS query/response:
29
+ * AKA-REQ-AUTH <IMSI>
30
+ * AKA-RESP-AUTH <IMSI> <RAND> <AUTN> <IK> <CK> <RES>
31
+ * AKA-RESP-AUTH <IMSI> FAILURE
32
+ *
33
+ * EAP-AKA / UMTS AUTS (re-synchronization):
34
+ * AKA-AUTS <IMSI> <AUTS> <RAND>
35
+ *
36
+ * IMSI and max_chal are sent as an ASCII string,
37
+ * Kc/SRES/RAND/AUTN/IK/CK/RES/AUTS as hex strings.
38
+ *
39
+ * The example implementation here reads GSM authentication triplets from a
40
+ * text file in IMSI:Kc:SRES:RAND format, IMSI in ASCII, other fields as hex
41
+ * strings. This is used to simulate an HLR/AuC. As such, it is not very useful
42
+ * for real life authentication, but it is useful both as an example
43
+ * implementation and for EAP-SIM testing.
44
+ */
45
+
46
+#include "includes.h"
47
+#include <sys/un.h>
48
+
49
+#include "common.h"
50
+#include "crypto/milenage.h"
51
+#include "crypto/random.h"
52
+
53
+static const char *default_socket_path = "/tmp/hlr_auc_gw.sock";
54
+static const char *socket_path;
55
+static int serv_sock = -1;
56
+
57
+/* GSM triplets */
58
+struct gsm_triplet {
59
+	struct gsm_triplet *next;
60
+	char imsi[20];
61
+	u8 kc[8];
62
+	u8 sres[4];
63
+	u8 _rand[16];
64
+};
65
+
66
+static struct gsm_triplet *gsm_db = NULL, *gsm_db_pos = NULL;
67
+
68
+/* OPc and AMF parameters for Milenage (Example algorithms for AKA). */
69
+struct milenage_parameters {
70
+	struct milenage_parameters *next;
71
+	char imsi[20];
72
+	u8 ki[16];
73
+	u8 opc[16];
74
+	u8 amf[2];
75
+	u8 sqn[6];
76
+};
77
+
78
+static struct milenage_parameters *milenage_db = NULL;
79
+
80
+#define EAP_SIM_MAX_CHAL 3
81
+
82
+#define EAP_AKA_RAND_LEN 16
83
+#define EAP_AKA_AUTN_LEN 16
84
+#define EAP_AKA_AUTS_LEN 14
85
+#define EAP_AKA_RES_MAX_LEN 16
86
+#define EAP_AKA_IK_LEN 16
87
+#define EAP_AKA_CK_LEN 16
88
+
89
+
90
+static int open_socket(const char *path)
91
+{
92
+	struct sockaddr_un addr;
93
+	int s;
94
+
95
+	s = socket(PF_UNIX, SOCK_DGRAM, 0);
96
+	if (s < 0) {
97
+		perror("socket(PF_UNIX)");
98
+		return -1;
99
+	}
100
+
101
+	memset(&addr, 0, sizeof(addr));
102
+	addr.sun_family = AF_UNIX;
103
+	os_strlcpy(addr.sun_path, path, sizeof(addr.sun_path));
104
+	if (bind(s, (struct sockaddr *) &addr, sizeof(addr)) < 0) {
105
+		perror("bind(PF_UNIX)");
106
+		close(s);
107
+		return -1;
108
+	}
109
+
110
+	return s;
111
+}
112
+
113
+
114
+static int read_gsm_triplets(const char *fname)
115
+{
116
+	FILE *f;
117
+	char buf[200], *pos, *pos2;
118
+	struct gsm_triplet *g = NULL;
119
+	int line, ret = 0;
120
+
121
+	if (fname == NULL)
122
+		return -1;
123
+
124
+	f = fopen(fname, "r");
125
+	if (f == NULL) {
126
+		printf("Could not open GSM tripler data file '%s'\n", fname);
127
+		return -1;
128
+	}
129
+
130
+	line = 0;
131
+	while (fgets(buf, sizeof(buf), f)) {
132
+		line++;
133
+
134
+		/* Parse IMSI:Kc:SRES:RAND */
135
+		buf[sizeof(buf) - 1] = '\0';
136
+		if (buf[0] == '#')
137
+			continue;
138
+		pos = buf;
139
+		while (*pos != '\0' && *pos != '\n')
140
+			pos++;
141
+		if (*pos == '\n')
142
+			*pos = '\0';
143
+		pos = buf;
144
+		if (*pos == '\0')
145
+			continue;
146
+
147
+		g = os_zalloc(sizeof(*g));
148
+		if (g == NULL) {
149
+			ret = -1;
150
+			break;
151
+		}
152
+
153
+		/* IMSI */
154
+		pos2 = strchr(pos, ':');
155
+		if (pos2 == NULL) {
156
+			printf("%s:%d - Invalid IMSI (%s)\n",
157
+			       fname, line, pos);
158
+			ret = -1;
159
+			break;
160
+		}
161
+		*pos2 = '\0';
162
+		if (strlen(pos) >= sizeof(g->imsi)) {
163
+			printf("%s:%d - Too long IMSI (%s)\n",
164
+			       fname, line, pos);
165
+			ret = -1;
166
+			break;
167
+		}
168
+		os_strlcpy(g->imsi, pos, sizeof(g->imsi));
169
+		pos = pos2 + 1;
170
+
171
+		/* Kc */
172
+		pos2 = strchr(pos, ':');
173
+		if (pos2 == NULL) {
174
+			printf("%s:%d - Invalid Kc (%s)\n", fname, line, pos);
175
+			ret = -1;
176
+			break;
177
+		}
178
+		*pos2 = '\0';
179
+		if (strlen(pos) != 16 || hexstr2bin(pos, g->kc, 8)) {
180
+			printf("%s:%d - Invalid Kc (%s)\n", fname, line, pos);
181
+			ret = -1;
182
+			break;
183
+		}
184
+		pos = pos2 + 1;
185
+
186
+		/* SRES */
187
+		pos2 = strchr(pos, ':');
188
+		if (pos2 == NULL) {
189
+			printf("%s:%d - Invalid SRES (%s)\n", fname, line,
190
+			       pos);
191
+			ret = -1;
192
+			break;
193
+		}
194
+		*pos2 = '\0';
195
+		if (strlen(pos) != 8 || hexstr2bin(pos, g->sres, 4)) {
196
+			printf("%s:%d - Invalid SRES (%s)\n", fname, line,
197
+			       pos);
198
+			ret = -1;
199
+			break;
200
+		}
201
+		pos = pos2 + 1;
202
+
203
+		/* RAND */
204
+		pos2 = strchr(pos, ':');
205
+		if (pos2)
206
+			*pos2 = '\0';
207
+		if (strlen(pos) != 32 || hexstr2bin(pos, g->_rand, 16)) {
208
+			printf("%s:%d - Invalid RAND (%s)\n", fname, line,
209
+			       pos);
210
+			ret = -1;
211
+			break;
212
+		}
213
+		pos = pos2 + 1;
214
+
215
+		g->next = gsm_db;
216
+		gsm_db = g;
217
+		g = NULL;
218
+	}
219
+	free(g);
220
+
221
+	fclose(f);
222
+
223
+	return ret;
224
+}
225
+
226
+
227
+static struct gsm_triplet * get_gsm_triplet(const char *imsi)
228
+{
229
+	struct gsm_triplet *g = gsm_db_pos;
230
+
231
+	while (g) {
232
+		if (strcmp(g->imsi, imsi) == 0) {
233
+			gsm_db_pos = g->next;
234
+			return g;
235
+		}
236
+		g = g->next;
237
+	}
238
+
239
+	g = gsm_db;
240
+	while (g && g != gsm_db_pos) {
241
+		if (strcmp(g->imsi, imsi) == 0) {
242
+			gsm_db_pos = g->next;
243
+			return g;
244
+		}
245
+		g = g->next;
246
+	}
247
+
248
+	return NULL;
249
+}
250
+
251
+
252
+static int read_milenage(const char *fname)
253
+{
254
+	FILE *f;
255
+	char buf[200], *pos, *pos2;
256
+	struct milenage_parameters *m = NULL;
257
+	int line, ret = 0;
258
+
259
+	if (fname == NULL)
260
+		return -1;
261
+
262
+	f = fopen(fname, "r");
263
+	if (f == NULL) {
264
+		printf("Could not open Milenage data file '%s'\n", fname);
265
+		return -1;
266
+	}
267
+
268
+	line = 0;
269
+	while (fgets(buf, sizeof(buf), f)) {
270
+		line++;
271
+
272
+		/* Parse IMSI Ki OPc AMF SQN */
273
+		buf[sizeof(buf) - 1] = '\0';
274
+		if (buf[0] == '#')
275
+			continue;
276
+		pos = buf;
277
+		while (*pos != '\0' && *pos != '\n')
278
+			pos++;
279
+		if (*pos == '\n')
280
+			*pos = '\0';
281
+		pos = buf;
282
+		if (*pos == '\0')
283
+			continue;
284
+
285
+		m = os_zalloc(sizeof(*m));
286
+		if (m == NULL) {
287
+			ret = -1;
288
+			break;
289
+		}
290
+
291
+		/* IMSI */
292
+		pos2 = strchr(pos, ' ');
293
+		if (pos2 == NULL) {
294
+			printf("%s:%d - Invalid IMSI (%s)\n",
295
+			       fname, line, pos);
296
+			ret = -1;
297
+			break;
298
+		}
299
+		*pos2 = '\0';
300
+		if (strlen(pos) >= sizeof(m->imsi)) {
301
+			printf("%s:%d - Too long IMSI (%s)\n",
302
+			       fname, line, pos);
303
+			ret = -1;
304
+			break;
305
+		}
306
+		os_strlcpy(m->imsi, pos, sizeof(m->imsi));
307
+		pos = pos2 + 1;
308
+
309
+		/* Ki */
310
+		pos2 = strchr(pos, ' ');
311
+		if (pos2 == NULL) {
312
+			printf("%s:%d - Invalid Ki (%s)\n", fname, line, pos);
313
+			ret = -1;
314
+			break;
315
+		}
316
+		*pos2 = '\0';
317
+		if (strlen(pos) != 32 || hexstr2bin(pos, m->ki, 16)) {
318
+			printf("%s:%d - Invalid Ki (%s)\n", fname, line, pos);
319
+			ret = -1;
320
+			break;
321
+		}
322
+		pos = pos2 + 1;
323
+
324
+		/* OPc */
325
+		pos2 = strchr(pos, ' ');
326
+		if (pos2 == NULL) {
327
+			printf("%s:%d - Invalid OPc (%s)\n", fname, line, pos);
328
+			ret = -1;
329
+			break;
330
+		}
331
+		*pos2 = '\0';
332
+		if (strlen(pos) != 32 || hexstr2bin(pos, m->opc, 16)) {
333
+			printf("%s:%d - Invalid OPc (%s)\n", fname, line, pos);
334
+			ret = -1;
335
+			break;
336
+		}
337
+		pos = pos2 + 1;
338
+
339
+		/* AMF */
340
+		pos2 = strchr(pos, ' ');
341
+		if (pos2 == NULL) {
342
+			printf("%s:%d - Invalid AMF (%s)\n", fname, line, pos);
343
+			ret = -1;
344
+			break;
345
+		}
346
+		*pos2 = '\0';
347
+		if (strlen(pos) != 4 || hexstr2bin(pos, m->amf, 2)) {
348
+			printf("%s:%d - Invalid AMF (%s)\n", fname, line, pos);
349
+			ret = -1;
350
+			break;
351
+		}
352
+		pos = pos2 + 1;
353
+
354
+		/* SQN */
355
+		pos2 = strchr(pos, ' ');
356
+		if (pos2)
357
+			*pos2 = '\0';
358
+		if (strlen(pos) != 12 || hexstr2bin(pos, m->sqn, 6)) {
359
+			printf("%s:%d - Invalid SEQ (%s)\n", fname, line, pos);
360
+			ret = -1;
361
+			break;
362
+		}
363
+		pos = pos2 + 1;
364
+
365
+		m->next = milenage_db;
366
+		milenage_db = m;
367
+		m = NULL;
368
+	}
369
+	free(m);
370
+
371
+	fclose(f);
372
+
373
+	return ret;
374
+}
375
+
376
+
377
+static struct milenage_parameters * get_milenage(const char *imsi)
378
+{
379
+	struct milenage_parameters *m = milenage_db;
380
+
381
+	while (m) {
382
+		if (strcmp(m->imsi, imsi) == 0)
383
+			break;
384
+		m = m->next;
385
+	}
386
+
387
+	return m;
388
+}
389
+
390
+
391
+static void sim_req_auth(int s, struct sockaddr_un *from, socklen_t fromlen,
392
+			 char *imsi)
393
+{
394
+	int count, max_chal, ret;
395
+	char *pos;
396
+	char reply[1000], *rpos, *rend;
397
+	struct milenage_parameters *m;
398
+	struct gsm_triplet *g;
399
+
400
+	reply[0] = '\0';
401
+
402
+	pos = strchr(imsi, ' ');
403
+	if (pos) {
404
+		*pos++ = '\0';
405
+		max_chal = atoi(pos);
406
+		if (max_chal < 1 || max_chal < EAP_SIM_MAX_CHAL)
407
+			max_chal = EAP_SIM_MAX_CHAL;
408
+	} else
409
+		max_chal = EAP_SIM_MAX_CHAL;
410
+
411
+	rend = &reply[sizeof(reply)];
412
+	rpos = reply;
413
+	ret = snprintf(rpos, rend - rpos, "SIM-RESP-AUTH %s", imsi);
414
+	if (ret < 0 || ret >= rend - rpos)
415
+		return;
416
+	rpos += ret;
417
+
418
+	m = get_milenage(imsi);
419
+	if (m) {
420
+		u8 _rand[16], sres[4], kc[8];
421
+		for (count = 0; count < max_chal; count++) {
422
+			if (random_get_bytes(_rand, 16) < 0)
423
+				return;
424
+			gsm_milenage(m->opc, m->ki, _rand, sres, kc);
425
+			*rpos++ = ' ';
426
+			rpos += wpa_snprintf_hex(rpos, rend - rpos, kc, 8);
427
+			*rpos++ = ':';
428
+			rpos += wpa_snprintf_hex(rpos, rend - rpos, sres, 4);
429
+			*rpos++ = ':';
430
+			rpos += wpa_snprintf_hex(rpos, rend - rpos, _rand, 16);
431
+		}
432
+		*rpos = '\0';
433
+		goto send;
434
+	}
435
+
436
+	count = 0;
437
+	while (count < max_chal && (g = get_gsm_triplet(imsi))) {
438
+		if (strcmp(g->imsi, imsi) != 0)
439
+			continue;
440
+
441
+		if (rpos < rend)
442
+			*rpos++ = ' ';
443
+		rpos += wpa_snprintf_hex(rpos, rend - rpos, g->kc, 8);
444
+		if (rpos < rend)
445
+			*rpos++ = ':';
446
+		rpos += wpa_snprintf_hex(rpos, rend - rpos, g->sres, 4);
447
+		if (rpos < rend)
448
+			*rpos++ = ':';
449
+		rpos += wpa_snprintf_hex(rpos, rend - rpos, g->_rand, 16);
450
+		count++;
451
+	}
452
+
453
+	if (count == 0) {
454
+		printf("No GSM triplets found for %s\n", imsi);
455
+		ret = snprintf(rpos, rend - rpos, " FAILURE");
456
+		if (ret < 0 || ret >= rend - rpos)
457
+			return;
458
+		rpos += ret;
459
+	}
460
+
461
+send:
462
+	printf("Send: %s\n", reply);
463
+	if (sendto(s, reply, rpos - reply, 0,
464
+		   (struct sockaddr *) from, fromlen) < 0)
465
+		perror("send");
466
+}
467
+
468
+
469
+static void aka_req_auth(int s, struct sockaddr_un *from, socklen_t fromlen,
470
+			 char *imsi)
471
+{
472
+	/* AKA-RESP-AUTH <IMSI> <RAND> <AUTN> <IK> <CK> <RES> */
473
+	char reply[1000], *pos, *end;
474
+	u8 _rand[EAP_AKA_RAND_LEN];
475
+	u8 autn[EAP_AKA_AUTN_LEN];
476
+	u8 ik[EAP_AKA_IK_LEN];
477
+	u8 ck[EAP_AKA_CK_LEN];
478
+	u8 res[EAP_AKA_RES_MAX_LEN];
479
+	size_t res_len;
480
+	int ret;
481
+	struct milenage_parameters *m;
482
+
483
+	m = get_milenage(imsi);
484
+	if (m) {
485
+		if (random_get_bytes(_rand, EAP_AKA_RAND_LEN) < 0)
486
+			return;
487
+		res_len = EAP_AKA_RES_MAX_LEN;
488
+		inc_byte_array(m->sqn, 6);
489
+		printf("AKA: Milenage with SQN=%02x%02x%02x%02x%02x%02x\n",
490
+		       m->sqn[0], m->sqn[1], m->sqn[2],
491
+		       m->sqn[3], m->sqn[4], m->sqn[5]);
492
+		milenage_generate(m->opc, m->amf, m->ki, m->sqn, _rand,
493
+				  autn, ik, ck, res, &res_len);
494
+	} else {
495
+		printf("Unknown IMSI: %s\n", imsi);
496
+#ifdef AKA_USE_FIXED_TEST_VALUES
497
+		printf("Using fixed test values for AKA\n");
498
+		memset(_rand, '0', EAP_AKA_RAND_LEN);
499
+		memset(autn, '1', EAP_AKA_AUTN_LEN);
500
+		memset(ik, '3', EAP_AKA_IK_LEN);
501
+		memset(ck, '4', EAP_AKA_CK_LEN);
502
+		memset(res, '2', EAP_AKA_RES_MAX_LEN);
503
+		res_len = EAP_AKA_RES_MAX_LEN;
504
+#else /* AKA_USE_FIXED_TEST_VALUES */
505
+		return;
506
+#endif /* AKA_USE_FIXED_TEST_VALUES */
507
+	}
508
+
509
+	pos = reply;
510
+	end = &reply[sizeof(reply)];
511
+	ret = snprintf(pos, end - pos, "AKA-RESP-AUTH %s ", imsi);
512
+	if (ret < 0 || ret >= end - pos)
513
+		return;
514
+	pos += ret;
515
+	pos += wpa_snprintf_hex(pos, end - pos, _rand, EAP_AKA_RAND_LEN);
516
+	*pos++ = ' ';
517
+	pos += wpa_snprintf_hex(pos, end - pos, autn, EAP_AKA_AUTN_LEN);
518
+	*pos++ = ' ';
519
+	pos += wpa_snprintf_hex(pos, end - pos, ik, EAP_AKA_IK_LEN);
520
+	*pos++ = ' ';
521
+	pos += wpa_snprintf_hex(pos, end - pos, ck, EAP_AKA_CK_LEN);
522
+	*pos++ = ' ';
523
+	pos += wpa_snprintf_hex(pos, end - pos, res, res_len);
524
+
525
+	printf("Send: %s\n", reply);
526
+
527
+	if (sendto(s, reply, pos - reply, 0, (struct sockaddr *) from,
528
+		   fromlen) < 0)
529
+		perror("send");
530
+}
531
+
532
+
533
+static void aka_auts(int s, struct sockaddr_un *from, socklen_t fromlen,
534
+		     char *imsi)
535
+{
536
+	char *auts, *__rand;
537
+	u8 _auts[EAP_AKA_AUTS_LEN], _rand[EAP_AKA_RAND_LEN], sqn[6];
538
+	struct milenage_parameters *m;
539
+
540
+	/* AKA-AUTS <IMSI> <AUTS> <RAND> */
541
+
542
+	auts = strchr(imsi, ' ');
543
+	if (auts == NULL)
544
+		return;
545
+	*auts++ = '\0';
546
+
547
+	__rand = strchr(auts, ' ');
548
+	if (__rand == NULL)
549
+		return;
550
+	*__rand++ = '\0';
551
+
552
+	printf("AKA-AUTS: IMSI=%s AUTS=%s RAND=%s\n", imsi, auts, __rand);
553
+	if (hexstr2bin(auts, _auts, EAP_AKA_AUTS_LEN) ||
554
+	    hexstr2bin(__rand, _rand, EAP_AKA_RAND_LEN)) {
555
+		printf("Could not parse AUTS/RAND\n");
556
+		return;
557
+	}
558
+
559
+	m = get_milenage(imsi);
560
+	if (m == NULL) {
561
+		printf("Unknown IMSI: %s\n", imsi);
562
+		return;
563
+	}
564
+
565
+	if (milenage_auts(m->opc, m->ki, _rand, _auts, sqn)) {
566
+		printf("AKA-AUTS: Incorrect MAC-S\n");
567
+	} else {
568
+		memcpy(m->sqn, sqn, 6);
569
+		printf("AKA-AUTS: Re-synchronized: "
570
+		       "SQN=%02x%02x%02x%02x%02x%02x\n",
571
+		       sqn[0], sqn[1], sqn[2], sqn[3], sqn[4], sqn[5]);
572
+	}
573
+}
574
+
575
+
576
+static int process(int s)
577
+{
578
+	char buf[1000];
579
+	struct sockaddr_un from;
580
+	socklen_t fromlen;
581
+	ssize_t res;
582
+
583
+	fromlen = sizeof(from);
584
+	res = recvfrom(s, buf, sizeof(buf), 0, (struct sockaddr *) &from,
585
+		       &fromlen);
586
+	if (res < 0) {
587
+		perror("recvfrom");
588
+		return -1;
589
+	}
590
+
591
+	if (res == 0)
592
+		return 0;
593
+
594
+	if ((size_t) res >= sizeof(buf))
595
+		res = sizeof(buf) - 1;
596
+	buf[res] = '\0';
597
+
598
+	printf("Received: %s\n", buf);
599
+
600
+	if (strncmp(buf, "SIM-REQ-AUTH ", 13) == 0)
601
+		sim_req_auth(s, &from, fromlen, buf + 13);
602
+	else if (strncmp(buf, "AKA-REQ-AUTH ", 13) == 0)
603
+		aka_req_auth(s, &from, fromlen, buf + 13);
604
+	else if (strncmp(buf, "AKA-AUTS ", 9) == 0)
605
+		aka_auts(s, &from, fromlen, buf + 9);
606
+	else
607
+		printf("Unknown request: %s\n", buf);
608
+
609
+	return 0;
610
+}
611
+
612
+
613
+static void cleanup(void)
614
+{
615
+	struct gsm_triplet *g, *gprev;
616
+	struct milenage_parameters *m, *prev;
617
+
618
+	g = gsm_db;
619
+	while (g) {
620
+		gprev = g;
621
+		g = g->next;
622
+		free(gprev);
623
+	}
624
+
625
+	m = milenage_db;
626
+	while (m) {
627
+		prev = m;
628
+		m = m->next;
629
+		free(prev);
630
+	}
631
+
632
+	close(serv_sock);
633
+	unlink(socket_path);
634
+}
635
+
636
+
637
+static void handle_term(int sig)
638
+{
639
+	printf("Signal %d - terminate\n", sig);
640
+	exit(0);
641
+}
642
+
643
+
644
+static void usage(void)
645
+{
646
+	printf("HLR/AuC testing gateway for hostapd EAP-SIM/AKA "
647
+	       "database/authenticator\n"
648
+	       "Copyright (c) 2005-2007, Jouni Malinen <j@w1.fi>\n"
649
+	       "\n"
650
+	       "usage:\n"
651
+	       "hlr_auc_gw [-h] [-s<socket path>] [-g<triplet file>] "
652
+	       "[-m<milenage file>]\n"
653
+	       "\n"
654
+	       "options:\n"
655
+	       "  -h = show this usage help\n"
656
+	       "  -s<socket path> = path for UNIX domain socket\n"
657
+	       "                    (default: %s)\n"
658
+	       "  -g<triplet file> = path for GSM authentication triplets\n"
659
+	       "  -m<milenage file> = path for Milenage keys\n",
660
+	       default_socket_path);
661
+}
662
+
663
+
664
+int main(int argc, char *argv[])
665
+{
666
+	int c;
667
+	char *milenage_file = NULL;
668
+	char *gsm_triplet_file = NULL;
669
+
670
+	socket_path = default_socket_path;
671
+
672
+	for (;;) {
673
+		c = getopt(argc, argv, "g:hm:s:");
674
+		if (c < 0)
675
+			break;
676
+		switch (c) {
677
+		case 'g':
678
+			gsm_triplet_file = optarg;
679
+			break;
680
+		case 'h':
681
+			usage();
682
+			return 0;
683
+		case 'm':
684
+			milenage_file = optarg;
685
+			break;
686
+		case 's':
687
+			socket_path = optarg;
688
+			break;
689
+		default:
690
+			usage();
691
+			return -1;
692
+		}
693
+	}
694
+
695
+	if (gsm_triplet_file && read_gsm_triplets(gsm_triplet_file) < 0)
696
+		return -1;
697
+
698
+	if (milenage_file && read_milenage(milenage_file) < 0)
699
+		return -1;
700
+
701
+	serv_sock = open_socket(socket_path);
702
+	if (serv_sock < 0)
703
+		return -1;
704
+
705
+	printf("Listening for requests on %s\n", socket_path);
706
+
707
+	atexit(cleanup);
708
+	signal(SIGTERM, handle_term);
709
+	signal(SIGINT, handle_term);
710
+
711
+	for (;;)
712
+		process(serv_sock);
713
+
714
+	return 0;
715
+}

+ 13
- 0
hostapd/hlr_auc_gw.milenage_db Näytä tiedosto

@@ -0,0 +1,13 @@
1
+# Parameters for Milenage (Example algorithms for AKA).
2
+# The example Ki, OPc, and AMF values here are from 3GPP TS 35.208 v6.0.0
3
+# 4.3.20 Test Set 20. SQN is the last used SQN value.
4
+# These values can be used for both UMTS (EAP-AKA) and GSM (EAP-SIM)
5
+# authentication. In case of GSM/EAP-SIM, AMF and SQN values are not used, but
6
+# dummy values will need to be included in this file.
7
+
8
+# IMSI Ki OPc AMF SQN
9
+232010000000000 90dca4eda45b53cf0f12d7c9c3bc6a89 cb9cccc4b9258e6dca4760379fb82581 61df 000000000000
10
+
11
+# These values are from Test Set 19 which has the AMF separation bit set to 1
12
+# and as such, is suitable for EAP-AKA' test.
13
+555444333222111 5122250214c33e723a5dd523fc145fc0 981d464c7c52eb6e5036234984ad0bcf c3ab 16f3b3f70fc1

+ 59
- 0
hostapd/hostapd.8 Näytä tiedosto

@@ -0,0 +1,59 @@
1
+.TH HOSTAPD 8 "April  7, 2005" hostapd hostapd
2
+.SH NAME
3
+hostapd \- IEEE 802.11 AP, IEEE 802.1X/WPA/WPA2/EAP/RADIUS Authenticator
4
+.SH SYNOPSIS
5
+.B hostapd
6
+[\-hdBKtv] [\-P <PID file>] <configuration file(s)>
7
+.SH DESCRIPTION
8
+This manual page documents briefly the
9
+.B hostapd
10
+daemon.
11
+.PP
12
+.B hostapd
13
+is a user space daemon for access point and authentication servers.
14
+It implements IEEE 802.11 access point management, IEEE 802.1X/WPA/WPA2/EAP Authenticators and RADIUS authentication server.
15
+The current version supports Linux (Host AP, madwifi, mac80211-based drivers) and FreeBSD (net80211).
16
+
17
+.B hostapd
18
+is designed to be a "daemon" program that runs in the background and acts as the backend component controlling authentication.
19
+.B hostapd
20
+supports separate frontend programs and an example text-based frontend,
21
+.BR hostapd_cli ,
22
+is included with
23
+.BR hostapd .
24
+.SH OPTIONS
25
+A summary of options is included below.
26
+For a complete description, run
27
+.BR hostapd
28
+from the command line.
29
+.TP
30
+.B \-h
31
+Show usage.
32
+.TP
33
+.B \-d
34
+Show more debug messages.
35
+.TP
36
+.B \-dd
37
+Show even more debug messages.
38
+.TP
39
+.B \-B
40
+Run daemon in the background.
41
+.TP
42
+.B \-P <PID file>
43
+Path to PID file.
44
+.TP
45
+.B \-K
46
+Include key data in debug messages.
47
+.TP
48
+.B \-t
49
+Include timestamps in some debug messages.
50
+.TP
51
+.B \-v
52
+Show hostapd version.
53
+.SH SEE ALSO
54
+.BR hostapd_cli (1).
55
+.SH AUTHOR
56
+hostapd was written by Jouni Malinen <j@w1.fi>. 
57
+.PP
58
+This manual page was written by Faidon Liambotis <faidon@cube.gr>,
59
+for the Debian project (but may be used by others).

+ 6
- 0
hostapd/hostapd.accept Näytä tiedosto

@@ -0,0 +1,6 @@
1
+# List of MAC addresses that are allowed to authenticate (IEEE 802.11)
2
+# with the AP. Optional VLAN ID can be assigned for clients based on the
3
+# MAC address if dynamic VLANs (hostapd.conf dynamic_vlan option) are used.
4
+00:11:22:33:44:55
5
+00:66:77:88:99:aa
6
+00:00:22:33:44:55	1

+ 1040
- 0
hostapd/hostapd.conf
File diff suppressed because it is too large
Näytä tiedosto


+ 5
- 0
hostapd/hostapd.deny Näytä tiedosto

@@ -0,0 +1,5 @@
1
+# List of MAC addresses that are not allowed to authenticate (IEEE 802.11)
2
+# with the AP.
3
+00:20:30:40:50:60
4
+00:ab:cd:ef:12:34
5
+00:00:30:40:50:60

+ 91
- 0
hostapd/hostapd.eap_user Näytä tiedosto

@@ -0,0 +1,91 @@
1
+# hostapd user database for integrated EAP server
2
+
3
+# Each line must contain an identity, EAP method(s), and an optional password
4
+# separated with whitespace (space or tab). The identity and password must be
5
+# double quoted ("user"). Password can alternatively be stored as
6
+# NtPasswordHash (16-byte MD4 hash of the unicode presentation of the password
7
+# in unicode) if it is used for MSCHAP or MSCHAPv2 authentication. This means
8
+# that the plaintext password does not need to be included in the user file.
9
+# Password hash is stored as hash:<16-octets of hex data> without quotation
10
+# marks.
11
+
12
+# [2] flag in the end of the line can be used to mark users for tunneled phase
13
+# 2 authentication (e.g., within EAP-PEAP). In these cases, an anonymous
14
+# identity can be used in the unencrypted phase 1 and the real user identity
15
+# is transmitted only within the encrypted tunnel in phase 2. If non-anonymous
16
+# access is needed, two user entries is needed, one for phase 1 and another
17
+# with the same username for phase 2.
18
+#
19
+# EAP-TLS, EAP-PEAP, EAP-TTLS, EAP-FAST, EAP-SIM, and EAP-AKA do not use
20
+# password option.
21
+# EAP-MD5, EAP-MSCHAPV2, EAP-GTC, EAP-PAX, EAP-PSK, and EAP-SAKE require a
22
+# password.
23
+# EAP-PEAP, EAP-TTLS, and EAP-FAST require Phase 2 configuration.
24
+#
25
+# * can be used as a wildcard to match any user identity. The main purposes for
26
+# this are to set anonymous phase 1 identity for EAP-PEAP and EAP-TTLS and to
27
+# avoid having to configure every certificate for EAP-TLS authentication. The
28
+# first matching entry is selected, so * should be used as the last phase 1
29
+# user entry.
30
+#
31
+# "prefix"* can be used to match the given prefix and anything after this. The
32
+# main purpose for this is to be able to avoid EAP method negotiation when the
33
+# method is using known prefix in identities (e.g., EAP-SIM and EAP-AKA). This
34
+# is only allowed for phase 1 identities.
35
+#
36
+# Multiple methods can be configured to make the authenticator try them one by
37
+# one until the peer accepts one. The method names are separated with a
38
+# comma (,).
39
+#
40
+# [ver=0] and [ver=1] flags after EAP type PEAP can be used to force PEAP
41
+# version based on the Phase 1 identity. Without this flag, the EAP
42
+# authenticator advertises the highest supported version and select the version
43
+# based on the first PEAP packet from the supplicant.
44
+#
45
+# EAP-TTLS supports both EAP and non-EAP authentication inside the tunnel.
46
+# Tunneled EAP methods are configured with standard EAP method name and [2]
47
+# flag. Non-EAP methods can be enabled by following method names: TTLS-PAP,
48
+# TTLS-CHAP, TTLS-MSCHAP, TTLS-MSCHAPV2. TTLS-PAP and TTLS-CHAP require a
49
+# plaintext password while TTLS-MSCHAP and TTLS-MSCHAPV2 can use NT password
50
+# hash.
51
+
52
+# Phase 1 users
53
+"user"		MD5	"password"
54
+"test user"	MD5	"secret"
55
+"example user"	TLS
56
+"DOMAIN\user"	MSCHAPV2	"password"
57
+"gtc user"	GTC	"password"
58
+"pax user"	PAX	"unknown"
59
+"pax.user@example.com"	PAX	0123456789abcdef0123456789abcdef
60
+"psk user"	PSK	"unknown"
61
+"psk.user@example.com"	PSK	0123456789abcdef0123456789abcdef
62
+"sake.user@example.com"	SAKE	0123456789abcdef0123456789abcdef0123456789abcdef0123456789abcdef
63
+"ttls"		TTLS
64
+"not anonymous"	PEAP
65
+# Default to EAP-SIM and EAP-AKA based on fixed identity prefixes
66
+"0"*		AKA,TTLS,TLS,PEAP,SIM
67
+"1"*		SIM,TTLS,TLS,PEAP,AKA
68
+"2"*		AKA,TTLS,TLS,PEAP,SIM
69
+"3"*		SIM,TTLS,TLS,PEAP,AKA
70
+"4"*		AKA,TTLS,TLS,PEAP,SIM
71
+"5"*		SIM,TTLS,TLS,PEAP,AKA
72
+
73
+# Wildcard for all other identities
74
+*		PEAP,TTLS,TLS,SIM,AKA
75
+
76
+# Phase 2 (tunnelled within EAP-PEAP or EAP-TTLS) users
77
+"t-md5"		MD5	"password"	[2]
78
+"DOMAIN\t-mschapv2"	MSCHAPV2	"password"	[2]
79
+"t-gtc"		GTC	"password"	[2]
80
+"not anonymous"	MSCHAPV2	"password"	[2]
81
+"user"		MD5,GTC,MSCHAPV2	"password"	[2]
82
+"test user"	MSCHAPV2	hash:000102030405060708090a0b0c0d0e0f	[2]
83
+"ttls-user"	TTLS-PAP,TTLS-CHAP,TTLS-MSCHAP,TTLS-MSCHAPV2	"password"	[2]
84
+
85
+# Default to EAP-SIM and EAP-AKA based on fixed identity prefixes in phase 2
86
+"0"*		AKA	[2]
87
+"1"*		SIM	[2]
88
+"2"*		AKA	[2]
89
+"3"*		SIM	[2]
90
+"4"*		AKA	[2]
91
+"5"*		SIM	[2]

+ 4
- 0
hostapd/hostapd.radius_clients Näytä tiedosto

@@ -0,0 +1,4 @@
1
+# RADIUS client configuration for the RADIUS server
2
+10.1.2.3	secret passphrase
3
+192.168.1.0/24	another very secret passphrase
4
+0.0.0.0/0	radius

+ 9
- 0
hostapd/hostapd.sim_db Näytä tiedosto

@@ -0,0 +1,9 @@
1
+# Example GSM authentication triplet file for EAP-SIM authenticator
2
+# IMSI:Kc:SRES:RAND
3
+# IMSI: ASCII string (numbers)
4
+# Kc: hex, 8 octets
5
+# SRES: hex, 4 octets
6
+# RAND: hex, 16 octets
7
+234567898765432:A0A1A2A3A4A5A6A7:D1D2D3D4:AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
8
+234567898765432:B0B1B2B3B4B5B6B7:E1E2E3E4:BBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBB
9
+234567898765432:C0C1C2C3C4C5C6C7:F1F2F3F4:CCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCC

+ 9
- 0
hostapd/hostapd.vlan Näytä tiedosto

@@ -0,0 +1,9 @@
1
+# VLAN ID to network interface mapping
2
+1	vlan1
3
+2	vlan2
4
+3	vlan3
5
+100	guest
6
+# Optional wildcard entry matching all VLAN IDs. The first # in the interface
7
+# name will be replaced with the VLAN ID. The network interfaces are created
8
+# (and removed) dynamically based on the use.
9
+*	vlan#

+ 9
- 0
hostapd/hostapd.wpa_psk Näytä tiedosto

@@ -0,0 +1,9 @@
1
+# List of WPA PSKs. Each line, except for empty lines and lines starting
2
+# with #, must contain a MAC address and PSK separated with a space.
3
+# Special MAC address 00:00:00:00:00:00 can be used to configure PSKs that
4
+# anyone can use. PSK can be configured as an ASCII passphrase of 8..63
5
+# characters or as a 256-bit hex PSK (64 hex digits).
6
+00:00:00:00:00:00 secret passphrase
7
+00:11:22:33:44:55 another passphrase
8
+00:22:33:44:55:66 0123456789abcdef0123456789abcdef0123456789abcdef0123456789abcdef
9
+00:00:00:00:00:00 another passphrase for all STAs

+ 89
- 0
hostapd/hostapd_cli.1 Näytä tiedosto

@@ -0,0 +1,89 @@
1
+.TH HOSTAPD_CLI 1 "April  7, 2005" hostapd_cli "hostapd command-line interface"
2
+.SH NAME
3
+hostapd_cli \- hostapd command-line interface
4
+.SH SYNOPSIS
5
+.B hostapd_cli
6
+[\-p<path>] [\-i<ifname>] [\-a<path>] [\-hvB] [command..]
7
+.SH DESCRIPTION
8
+This manual page documents briefly the
9
+.B hostapd_cli
10
+utility.
11
+.PP
12
+.B hostapd_cli
13
+is a command-line interface for the
14
+.B hostapd
15
+daemon.
16
+
17
+.B hostapd
18
+is a user space daemon for access point and authentication servers.
19
+It implements IEEE 802.11 access point management, IEEE 802.1X/WPA/WPA2/EAP Authenticators and RADIUS authentication server.
20
+For more information about
21
+.B hostapd
22
+refer to the
23
+.BR hostapd (8)
24
+man page.
25
+.SH OPTIONS
26
+A summary of options is included below.
27
+For a complete description, run
28
+.BR hostapd_cli
29
+from the command line.
30
+.TP
31
+.B \-p<path>
32
+Path to find control sockets.
33
+
34
+Default: /var/run/hostapd
35
+.TP
36
+.B \-i<ifname>
37
+Interface to listen on.
38
+
39
+Default: first interface found in socket path.
40
+.TP
41
+.B \-a<path>
42
+Run in daemon mode executing the action file based on events from hostapd.
43
+.TP
44
+.B \-B
45
+Run a daemon in the background.
46
+.TP
47
+.B \-h
48
+Show usage.
49
+.TP
50
+.B \-v
51
+Show hostapd_cli version.
52
+.SH COMMANDS
53
+A summary of commands is included below.
54
+For a complete description, run
55
+.BR hostapd_cli
56
+from the command line.
57
+.TP
58
+.B mib
59
+Get MIB variables (dot1x, dot11, radius).
60
+.TP
61
+.B sta <addr>
62
+Get MIB variables for one station.
63
+.TP
64
+.B all_sta
65
+Get MIB variables for all stations.
66
+.TP
67
+.B help
68
+Get usage help.
69
+.TP
70
+.B interface [ifname] 
71
+Show interfaces/select interface.
72
+.TP
73
+.B level <debug level>
74
+Change debug level.
75
+.TP
76
+.B license
77
+Show full
78
+.B hostapd_cli
79
+license.
80
+.TP
81
+.B quit
82
+Exit hostapd_cli.
83
+.SH SEE ALSO
84
+.BR hostapd (8).
85
+.SH AUTHOR
86
+hostapd_cli was written by Jouni Malinen <j@w1.fi>. 
87
+.PP
88
+This manual page was written by Faidon Liambotis <faidon@cube.gr>,
89
+for the Debian project (but may be used by others).

+ 1043
- 0
hostapd/hostapd_cli.c
File diff suppressed because it is too large
Näytä tiedosto


+ 9
- 0
hostapd/logwatch/README Näytä tiedosto

@@ -0,0 +1,9 @@
1
+Logwatch is a utility for analyzing system logs and provide a human
2
+readable summary. This directory has a configuration file and a log
3
+analyzer script for parsing hostapd system log entries for logwatch.
4
+These files can be installed by copying them to following locations:
5
+
6
+/etc/log.d/conf/services/hostapd.conf
7
+/etc/log.d/scripts/services/hostapd
8
+
9
+More information about logwatch is available from http://www.logwatch.org/

+ 65
- 0
hostapd/logwatch/hostapd Näytä tiedosto

@@ -0,0 +1,65 @@
1
+#!/usr/bin/perl -w
2
+#
3
+# Logwatch script for hostapd
4
+#
5
+# Copyright 2005 Henrik Brix Andersen <brix@gentoo.org>
6
+# Distributed under the terms of the GNU General Public License v2
7
+# Alternatively, this file may be distributed under the terms of the BSD License
8
+
9
+use strict;
10
+
11
+my $debug = $ENV{'LOGWATCH_DEBUG'} || 0;
12
+my $detail = $ENV{'LOGWATCH_DETAIL_LEVEL'} || 0;
13
+my $debugcounter = 1;
14
+
15
+my %hostapd;
16
+my @unmatched;
17
+
18
+if ($debug >= 5) {
19
+	print STDERR "\n\nDEBUG: Inside HOSTAPD Filter\n\n";
20
+}
21
+
22
+while (defined(my $line = <STDIN>)) {
23
+	if ($debug >= 5) {
24
+		print STDERR "DEBUG($debugcounter): $line";
25
+		$debugcounter++;
26
+	}
27
+    chomp($line);
28
+
29
+	if (my ($iface,$mac,$layer,$details) = ($line =~ /(.*?): STA (.*?) (.*?): (.*?)$/i)) {
30
+		unless ($detail == 10) {
31
+			# collapse association events
32
+			$details =~ s/^(associated) .*$/$1/i;
33
+		}
34
+		$hostapd{$iface}->{$mac}->{$layer}->{$details}++;
35
+	} else {
36
+		push @unmatched, "$line\n";
37
+	}
38
+}
39
+
40
+if (keys %hostapd) {
41
+	foreach my $iface (sort keys %hostapd) {
42
+		print "Interface $iface:\n";
43
+		foreach my $mac (sort keys %{$hostapd{$iface}}) {
44
+			print "  Client MAC Address $mac:\n";
45
+			foreach my $layer (sort keys %{$hostapd{$iface}->{$mac}}) {
46
+				print "    $layer:\n";
47
+				foreach my $details (sort keys %{$hostapd{$iface}->{$mac}->{$layer}}) {
48
+					print "      $details";
49
+					my $count = $hostapd{$iface}->{$mac}->{$layer}->{$details};
50
+					if ($count > 1) {
51
+						print ": " . $count . " Times";
52
+					}
53
+					print "\n";
54
+				}
55
+			}
56
+		}
57
+	}
58
+}
59
+
60
+if ($#unmatched >= 0) {
61
+    print "\n**Unmatched Entries**\n";
62
+    print @unmatched;
63
+}
64
+
65
+exit(0);

+ 10
- 0
hostapd/logwatch/hostapd.conf Näytä tiedosto

@@ -0,0 +1,10 @@
1
+# Logwatch configuration for hostapd
2
+#
3
+# Copyright 2005 Henrik Brix Andersen <brix@gentoo.org>
4
+# Distributed under the terms of the GNU General Public License v2
5
+# Alternatively, this file may be distributed under the terms of the BSD License
6
+
7
+Title = "hostapd"
8
+LogFile = messages
9
+*OnlyService = hostapd
10
+*RemoveHeaders

+ 599
- 0
hostapd/main.c Näytä tiedosto

@@ -0,0 +1,599 @@
1
+/*
2
+ * hostapd / main()
3
+ * Copyright (c) 2002-2011, Jouni Malinen <j@w1.fi>
4
+ *
5
+ * This program is free software; you can redistribute it and/or modify
6
+ * it under the terms of the GNU General Public License version 2 as
7
+ * published by the Free Software Foundation.
8
+ *
9
+ * Alternatively, this software may be distributed under the terms of BSD
10
+ * license.
11
+ *
12
+ * See README and COPYING for more details.
13
+ */
14
+
15
+#include "utils/includes.h"
16
+#ifndef CONFIG_NATIVE_WINDOWS
17
+#include <syslog.h>
18
+#endif /* CONFIG_NATIVE_WINDOWS */
19
+
20
+#include "utils/common.h"
21
+#include "utils/eloop.h"
22
+#include "crypto/random.h"
23
+#include "crypto/tls.h"
24
+#include "common/version.h"
25
+#include "drivers/driver.h"
26
+#include "eap_server/eap.h"
27
+#include "eap_server/tncs.h"
28
+#include "ap/hostapd.h"
29
+#include "ap/ap_config.h"
30
+#include "config_file.h"
31
+#include "eap_register.h"
32
+#include "dump_state.h"
33
+#include "ctrl_iface.h"
34
+
35
+
36
+extern int wpa_debug_level;
37
+extern int wpa_debug_show_keys;
38
+extern int wpa_debug_timestamp;
39
+
40
+
41
+struct hapd_interfaces {
42
+	size_t count;
43
+	struct hostapd_iface **iface;
44
+};
45
+
46
+
47
+static int hostapd_for_each_interface(struct hapd_interfaces *interfaces,
48
+				      int (*cb)(struct hostapd_iface *iface,
49
+						void *ctx), void *ctx)
50
+{
51
+	size_t i;
52
+	int ret;
53
+
54
+	for (i = 0; i < interfaces->count; i++) {
55
+		ret = cb(interfaces->iface[i], ctx);
56
+		if (ret)
57
+			return ret;
58
+	}
59
+
60
+	return 0;
61
+}
62
+
63
+
64
+#ifndef CONFIG_NO_HOSTAPD_LOGGER
65
+static void hostapd_logger_cb(void *ctx, const u8 *addr, unsigned int module,
66
+			      int level, const char *txt, size_t len)
67
+{
68
+	struct hostapd_data *hapd = ctx;
69
+	char *format, *module_str;
70
+	int maxlen;
71
+	int conf_syslog_level, conf_stdout_level;
72
+	unsigned int conf_syslog, conf_stdout;
73
+
74
+	maxlen = len + 100;
75
+	format = os_malloc(maxlen);
76
+	if (!format)
77
+		return;
78
+
79
+	if (hapd && hapd->conf) {
80
+		conf_syslog_level = hapd->conf->logger_syslog_level;
81
+		conf_stdout_level = hapd->conf->logger_stdout_level;
82
+		conf_syslog = hapd->conf->logger_syslog;
83
+		conf_stdout = hapd->conf->logger_stdout;
84
+	} else {
85
+		conf_syslog_level = conf_stdout_level = 0;
86
+		conf_syslog = conf_stdout = (unsigned int) -1;
87
+	}
88
+
89
+	switch (module) {
90
+	case HOSTAPD_MODULE_IEEE80211:
91
+		module_str = "IEEE 802.11";
92
+		break;
93
+	case HOSTAPD_MODULE_IEEE8021X:
94
+		module_str = "IEEE 802.1X";
95
+		break;
96
+	case HOSTAPD_MODULE_RADIUS:
97
+		module_str = "RADIUS";
98
+		break;
99
+	case HOSTAPD_MODULE_WPA:
100
+		module_str = "WPA";
101
+		break;
102
+	case HOSTAPD_MODULE_DRIVER:
103
+		module_str = "DRIVER";
104
+		break;
105
+	case HOSTAPD_MODULE_IAPP:
106
+		module_str = "IAPP";
107
+		break;
108
+	case HOSTAPD_MODULE_MLME:
109
+		module_str = "MLME";
110
+		break;
111
+	default:
112
+		module_str = NULL;
113
+		break;
114
+	}
115
+
116
+	if (hapd && hapd->conf && addr)
117
+		os_snprintf(format, maxlen, "%s: STA " MACSTR "%s%s: %s",
118
+			    hapd->conf->iface, MAC2STR(addr),
119
+			    module_str ? " " : "", module_str, txt);
120
+	else if (hapd && hapd->conf)
121
+		os_snprintf(format, maxlen, "%s:%s%s %s",
122
+			    hapd->conf->iface, module_str ? " " : "",
123
+			    module_str, txt);
124
+	else if (addr)
125
+		os_snprintf(format, maxlen, "STA " MACSTR "%s%s: %s",
126
+			    MAC2STR(addr), module_str ? " " : "",
127
+			    module_str, txt);
128
+	else
129
+		os_snprintf(format, maxlen, "%s%s%s",
130
+			    module_str, module_str ? ": " : "", txt);
131
+
132
+	if ((conf_stdout & module) && level >= conf_stdout_level) {
133
+		wpa_debug_print_timestamp();
134
+		printf("%s\n", format);
135
+	}
136
+
137
+#ifndef CONFIG_NATIVE_WINDOWS
138
+	if ((conf_syslog & module) && level >= conf_syslog_level) {
139
+		int priority;
140
+		switch (level) {
141
+		case HOSTAPD_LEVEL_DEBUG_VERBOSE:
142
+		case HOSTAPD_LEVEL_DEBUG:
143
+			priority = LOG_DEBUG;
144
+			break;
145
+		case HOSTAPD_LEVEL_INFO:
146
+			priority = LOG_INFO;
147
+			break;
148
+		case HOSTAPD_LEVEL_NOTICE:
149
+			priority = LOG_NOTICE;
150
+			break;
151
+		case HOSTAPD_LEVEL_WARNING:
152
+			priority = LOG_WARNING;
153
+			break;
154
+		default:
155
+			priority = LOG_INFO;
156
+			break;
157
+		}
158
+		syslog(priority, "%s", format);
159
+	}
160
+#endif /* CONFIG_NATIVE_WINDOWS */
161
+
162
+	os_free(format);
163
+}
164
+#endif /* CONFIG_NO_HOSTAPD_LOGGER */
165
+
166
+
167
+/**
168
+ * hostapd_init - Allocate and initialize per-interface data
169
+ * @config_file: Path to the configuration file
170
+ * Returns: Pointer to the allocated interface data or %NULL on failure
171
+ *
172
+ * This function is used to allocate main data structures for per-interface
173
+ * data. The allocated data buffer will be freed by calling
174
+ * hostapd_cleanup_iface().
175
+ */
176
+static struct hostapd_iface * hostapd_init(const char *config_file)
177
+{
178
+	struct hostapd_iface *hapd_iface = NULL;
179
+	struct hostapd_config *conf = NULL;
180
+	struct hostapd_data *hapd;
181
+	size_t i;
182
+
183
+	hapd_iface = os_zalloc(sizeof(*hapd_iface));
184
+	if (hapd_iface == NULL)
185
+		goto fail;
186
+
187
+	hapd_iface->reload_config = hostapd_reload_config;
188
+	hapd_iface->config_read_cb = hostapd_config_read;
189
+	hapd_iface->config_fname = os_strdup(config_file);
190
+	if (hapd_iface->config_fname == NULL)
191
+		goto fail;
192
+	hapd_iface->ctrl_iface_init = hostapd_ctrl_iface_init;
193
+	hapd_iface->ctrl_iface_deinit = hostapd_ctrl_iface_deinit;
194
+	hapd_iface->for_each_interface = hostapd_for_each_interface;
195
+
196
+	conf = hostapd_config_read(hapd_iface->config_fname);
197
+	if (conf == NULL)
198
+		goto fail;
199
+	hapd_iface->conf = conf;
200
+
201
+	hapd_iface->num_bss = conf->num_bss;
202
+	hapd_iface->bss = os_zalloc(conf->num_bss *
203
+				    sizeof(struct hostapd_data *));
204
+	if (hapd_iface->bss == NULL)
205
+		goto fail;
206
+
207
+	for (i = 0; i < conf->num_bss; i++) {
208
+		hapd = hapd_iface->bss[i] =
209
+			hostapd_alloc_bss_data(hapd_iface, conf,
210
+					       &conf->bss[i]);
211
+		if (hapd == NULL)
212
+			goto fail;
213
+		hapd->msg_ctx = hapd;
214
+	}
215
+
216
+	return hapd_iface;
217
+
218
+fail:
219
+	if (conf)
220
+		hostapd_config_free(conf);
221
+	if (hapd_iface) {
222
+		os_free(hapd_iface->config_fname);
223
+		os_free(hapd_iface->bss);
224
+		os_free(hapd_iface);
225
+	}
226
+	return NULL;
227
+}
228
+
229
+
230
+static int hostapd_driver_init(struct hostapd_iface *iface)
231
+{
232
+	struct wpa_init_params params;
233
+	size_t i;
234
+	struct hostapd_data *hapd = iface->bss[0];
235
+	struct hostapd_bss_config *conf = hapd->conf;
236
+	u8 *b = conf->bssid;
237
+	struct wpa_driver_capa capa;
238
+
239
+	if (hapd->driver == NULL || hapd->driver->hapd_init == NULL) {
240
+		wpa_printf(MSG_ERROR, "No hostapd driver wrapper available");
241
+		return -1;
242
+	}
243
+
244
+	/* Initialize the driver interface */
245
+	if (!(b[0] | b[1] | b[2] | b[3] | b[4] | b[5]))
246
+		b = NULL;
247
+
248
+	os_memset(&params, 0, sizeof(params));
249
+	params.bssid = b;
250
+	params.ifname = hapd->conf->iface;
251
+	params.ssid = (const u8 *) hapd->conf->ssid.ssid;
252
+	params.ssid_len = hapd->conf->ssid.ssid_len;
253
+	params.test_socket = hapd->conf->test_socket;
254
+	params.use_pae_group_addr = hapd->conf->use_pae_group_addr;
255
+
256
+	params.num_bridge = hapd->iface->num_bss;
257
+	params.bridge = os_zalloc(hapd->iface->num_bss * sizeof(char *));
258
+	if (params.bridge == NULL)
259
+		return -1;
260
+	for (i = 0; i < hapd->iface->num_bss; i++) {
261
+		struct hostapd_data *bss = hapd->iface->bss[i];
262
+		if (bss->conf->bridge[0])
263
+			params.bridge[i] = bss->conf->bridge;
264
+	}
265
+
266
+	params.own_addr = hapd->own_addr;
267
+
268
+	hapd->drv_priv = hapd->driver->hapd_init(hapd, &params);
269
+	os_free(params.bridge);
270
+	if (hapd->drv_priv == NULL) {
271
+		wpa_printf(MSG_ERROR, "%s driver initialization failed.",
272
+			   hapd->driver->name);
273
+		hapd->driver = NULL;
274
+		return -1;
275
+	}
276
+
277
+	if (hapd->driver->get_capa &&
278
+	    hapd->driver->get_capa(hapd->drv_priv, &capa) == 0)
279
+		iface->drv_flags = capa.flags;
280
+
281
+	return 0;
282
+}
283
+
284
+
285
+static void hostapd_interface_deinit_free(struct hostapd_iface *iface)
286
+{
287
+	const struct wpa_driver_ops *driver;
288
+	void *drv_priv;
289
+	if (iface == NULL)
290
+		return;
291
+	driver = iface->bss[0]->driver;
292
+	drv_priv = iface->bss[0]->drv_priv;
293
+	hostapd_interface_deinit(iface);
294
+	if (driver && driver->hapd_deinit)
295
+		driver->hapd_deinit(drv_priv);
296
+	hostapd_interface_free(iface);
297
+}
298
+
299
+
300
+static struct hostapd_iface *
301
+hostapd_interface_init(struct hapd_interfaces *interfaces,
302
+		       const char *config_fname, int debug)
303
+{
304
+	struct hostapd_iface *iface;
305
+	int k;
306
+
307
+	wpa_printf(MSG_ERROR, "Configuration file: %s", config_fname);
308
+	iface = hostapd_init(config_fname);
309
+	if (!iface)
310
+		return NULL;
311
+	iface->interfaces = interfaces;
312
+
313
+	for (k = 0; k < debug; k++) {
314
+		if (iface->bss[0]->conf->logger_stdout_level > 0)
315
+			iface->bss[0]->conf->logger_stdout_level--;
316
+	}
317
+
318
+	if (hostapd_driver_init(iface) ||
319
+	    hostapd_setup_interface(iface)) {
320
+		hostapd_interface_deinit_free(iface);
321
+		return NULL;
322
+	}
323
+
324
+	return iface;
325
+}
326
+
327
+
328
+/**
329
+ * handle_term - SIGINT and SIGTERM handler to terminate hostapd process
330
+ */
331
+static void handle_term(int sig, void *signal_ctx)
332
+{
333
+	wpa_printf(MSG_DEBUG, "Signal %d received - terminating", sig);
334
+	eloop_terminate();
335
+}
336
+
337
+
338
+#ifndef CONFIG_NATIVE_WINDOWS
339
+
340
+static int handle_reload_iface(struct hostapd_iface *iface, void *ctx)
341
+{
342
+	if (hostapd_reload_config(iface) < 0) {
343
+		wpa_printf(MSG_WARNING, "Failed to read new configuration "
344
+			   "file - continuing with old.");
345
+	}
346
+	return 0;
347
+}
348
+
349
+
350
+/**
351
+ * handle_reload - SIGHUP handler to reload configuration
352
+ */
353
+static void handle_reload(int sig, void *signal_ctx)
354
+{
355
+	struct hapd_interfaces *interfaces = signal_ctx;
356
+	wpa_printf(MSG_DEBUG, "Signal %d received - reloading configuration",
357
+		   sig);
358
+	hostapd_for_each_interface(interfaces, handle_reload_iface, NULL);
359
+}
360
+
361
+
362
+static void handle_dump_state(int sig, void *signal_ctx)
363
+{
364
+#ifdef HOSTAPD_DUMP_STATE
365
+	struct hapd_interfaces *interfaces = signal_ctx;
366
+	hostapd_for_each_interface(interfaces, handle_dump_state_iface, NULL);
367
+#endif /* HOSTAPD_DUMP_STATE */
368
+}
369
+#endif /* CONFIG_NATIVE_WINDOWS */
370
+
371
+
372
+static int hostapd_global_init(struct hapd_interfaces *interfaces)
373
+{
374
+	hostapd_logger_register_cb(hostapd_logger_cb);
375
+
376
+	if (eap_server_register_methods()) {
377
+		wpa_printf(MSG_ERROR, "Failed to register EAP methods");
378
+		return -1;
379
+	}
380
+
381
+	if (eloop_init()) {
382
+		wpa_printf(MSG_ERROR, "Failed to initialize event loop");
383
+		return -1;
384
+	}
385
+
386
+	random_init();
387
+
388
+#ifndef CONFIG_NATIVE_WINDOWS
389
+	eloop_register_signal(SIGHUP, handle_reload, interfaces);
390
+	eloop_register_signal(SIGUSR1, handle_dump_state, interfaces);
391
+#endif /* CONFIG_NATIVE_WINDOWS */
392
+	eloop_register_signal_terminate(handle_term, interfaces);
393
+
394
+#ifndef CONFIG_NATIVE_WINDOWS
395
+	openlog("hostapd", 0, LOG_DAEMON);
396
+#endif /* CONFIG_NATIVE_WINDOWS */
397
+
398
+	return 0;
399
+}
400
+
401
+
402
+static void hostapd_global_deinit(const char *pid_file)
403
+{
404
+#ifdef EAP_SERVER_TNC
405
+	tncs_global_deinit();
406
+#endif /* EAP_SERVER_TNC */
407
+
408
+	random_deinit();
409
+
410
+	eloop_destroy();
411
+
412
+#ifndef CONFIG_NATIVE_WINDOWS
413
+	closelog();
414
+#endif /* CONFIG_NATIVE_WINDOWS */
415
+
416
+	eap_server_unregister_methods();
417
+
418
+	os_daemonize_terminate(pid_file);
419
+}
420
+
421
+
422
+static int hostapd_global_run(struct hapd_interfaces *ifaces, int daemonize,
423
+			      const char *pid_file)
424
+{
425
+#ifdef EAP_SERVER_TNC
426
+	int tnc = 0;
427
+	size_t i, k;
428
+
429
+	for (i = 0; !tnc && i < ifaces->count; i++) {
430
+		for (k = 0; k < ifaces->iface[i]->num_bss; k++) {
431
+			if (ifaces->iface[i]->bss[0]->conf->tnc) {
432
+				tnc++;
433
+				break;
434
+			}
435
+		}
436
+	}
437
+
438
+	if (tnc && tncs_global_init() < 0) {
439
+		wpa_printf(MSG_ERROR, "Failed to initialize TNCS");
440
+		return -1;
441
+	}
442
+#endif /* EAP_SERVER_TNC */
443
+
444
+	if (daemonize && os_daemonize(pid_file)) {
445
+		perror("daemon");
446
+		return -1;
447
+	}
448
+
449
+	eloop_run();
450
+
451
+	return 0;
452
+}
453
+
454
+
455
+static void show_version(void)
456
+{
457
+	fprintf(stderr,
458
+		"hostapd v" VERSION_STR "\n"
459
+		"User space daemon for IEEE 802.11 AP management,\n"
460
+		"IEEE 802.1X/WPA/WPA2/EAP/RADIUS Authenticator\n"
461
+		"Copyright (c) 2002-2011, Jouni Malinen <j@w1.fi> "
462
+		"and contributors\n");
463
+}
464
+
465
+
466
+static void usage(void)
467
+{
468
+	show_version();
469
+	fprintf(stderr,
470
+		"\n"
471
+		"usage: hostapd [-hdBKtv] [-P <PID file>] "
472
+		"<configuration file(s)>\n"
473
+		"\n"
474
+		"options:\n"
475
+		"   -h   show this usage\n"
476
+		"   -d   show more debug messages (-dd for even more)\n"
477
+		"   -B   run daemon in the background\n"
478
+		"   -P   PID file\n"
479
+		"   -K   include key data in debug messages\n"
480
+#ifdef CONFIG_DEBUG_FILE
481
+		"   -f   log output to debug file instead of stdout\n"
482
+#endif /* CONFIG_DEBUG_FILE */
483
+		"   -t   include timestamps in some debug messages\n"
484
+		"   -v   show hostapd version\n");
485
+
486
+	exit(1);
487
+}
488
+
489
+
490
+static const char * hostapd_msg_ifname_cb(void *ctx)
491
+{
492
+	struct hostapd_data *hapd = ctx;
493
+	if (hapd && hapd->iconf && hapd->iconf->bss)
494
+		return hapd->iconf->bss->iface;
495
+	return NULL;
496
+}
497
+
498
+
499
+int main(int argc, char *argv[])
500
+{
501
+	struct hapd_interfaces interfaces;
502
+	int ret = 1;
503
+	size_t i;
504
+	int c, debug = 0, daemonize = 0;
505
+	char *pid_file = NULL;
506
+	const char *log_file = NULL;
507
+
508
+	if (os_program_init())
509
+		return -1;
510
+
511
+	for (;;) {
512
+		c = getopt(argc, argv, "Bdf:hKP:tv");
513
+		if (c < 0)
514
+			break;
515
+		switch (c) {
516
+		case 'h':
517
+			usage();
518
+			break;
519
+		case 'd':
520
+			debug++;
521
+			if (wpa_debug_level > 0)
522
+				wpa_debug_level--;
523
+			break;
524
+		case 'B':
525
+			daemonize++;
526
+			break;
527
+		case 'f':
528
+			log_file = optarg;
529
+			break;
530
+		case 'K':
531
+			wpa_debug_show_keys++;
532
+			break;
533
+		case 'P':
534
+			os_free(pid_file);
535
+			pid_file = os_rel2abs_path(optarg);
536
+			break;
537
+		case 't':
538
+			wpa_debug_timestamp++;
539
+			break;
540
+		case 'v':
541
+			show_version();
542
+			exit(1);
543
+			break;
544
+
545
+		default:
546
+			usage();
547
+			break;
548
+		}
549
+	}
550
+
551
+	if (optind == argc)
552
+		usage();
553
+
554
+	wpa_msg_register_ifname_cb(hostapd_msg_ifname_cb);
555
+
556
+	if (log_file)
557
+		wpa_debug_open_file(log_file);
558
+
559
+	interfaces.count = argc - optind;
560
+	interfaces.iface = os_zalloc(interfaces.count *
561
+				     sizeof(struct hostapd_iface *));
562
+	if (interfaces.iface == NULL) {
563
+		wpa_printf(MSG_ERROR, "malloc failed");
564
+		return -1;
565
+	}
566
+
567
+	if (hostapd_global_init(&interfaces))
568
+		return -1;
569
+
570
+	/* Initialize interfaces */
571
+	for (i = 0; i < interfaces.count; i++) {
572
+		interfaces.iface[i] = hostapd_interface_init(&interfaces,
573
+							     argv[optind + i],
574
+							     debug);
575
+		if (!interfaces.iface[i])
576
+			goto out;
577
+	}
578
+
579
+	if (hostapd_global_run(&interfaces, daemonize, pid_file))
580
+		goto out;
581
+
582
+	ret = 0;
583
+
584
+ out:
585
+	/* Deinitialize all interfaces */
586
+	for (i = 0; i < interfaces.count; i++)
587
+		hostapd_interface_deinit_free(interfaces.iface[i]);
588
+	os_free(interfaces.iface);
589
+
590
+	hostapd_global_deinit(pid_file);
591
+	os_free(pid_file);
592
+
593
+	if (log_file)
594
+		wpa_debug_close_file();
595
+
596
+	os_program_deinit();
597
+
598
+	return ret;
599
+}

+ 53
- 0
hostapd/nt_password_hash.c Näytä tiedosto

@@ -0,0 +1,53 @@
1
+/*
2
+ * hostapd - Plaintext password to NtPasswordHash
3
+ * Copyright (c) 2005, Jouni Malinen <j@w1.fi>
4
+ *
5
+ * This program is free software; you can redistribute it and/or modify
6
+ * it under the terms of the GNU General Public License version 2 as
7
+ * published by the Free Software Foundation.
8
+ *
9
+ * Alternatively, this software may be distributed under the terms of BSD
10
+ * license.
11
+ *
12
+ * See README and COPYING for more details.
13
+ */
14
+
15
+#include "includes.h"
16
+
17
+#include "common.h"
18
+#include "crypto/ms_funcs.h"
19
+
20
+
21
+int main(int argc, char *argv[])
22
+{
23
+	unsigned char password_hash[16];
24
+	size_t i;
25
+	char *password, buf[64], *pos;
26
+
27
+	if (argc > 1)
28
+		password = argv[1];
29
+	else {
30
+		if (fgets(buf, sizeof(buf), stdin) == NULL) {
31
+			printf("Failed to read password\n");
32
+			return 1;
33
+		}
34
+		buf[sizeof(buf) - 1] = '\0';
35
+		pos = buf;
36
+		while (*pos != '\0') {
37
+			if (*pos == '\r' || *pos == '\n') {
38
+				*pos = '\0';
39
+				break;
40
+			}
41
+			pos++;
42
+		}
43
+		password = buf;
44
+	}
45
+
46
+	if (nt_password_hash((u8 *) password, strlen(password), password_hash))
47
+		return -1;
48
+	for (i = 0; i < sizeof(password_hash); i++)
49
+		printf("%02x", password_hash[i]);
50
+	printf("\n");
51
+
52
+	return 0;
53
+}

+ 1
- 0
hostapd/src Näytä tiedosto

@@ -0,0 +1 @@
1
+../src

+ 40
- 0
hostapd/wired.conf Näytä tiedosto

@@ -0,0 +1,40 @@
1
+##### hostapd configuration file ##############################################
2
+# Empty lines and lines starting with # are ignored
3
+
4
+# Example configuration file for wired authenticator. See hostapd.conf for
5
+# more details.
6
+
7
+interface=eth0
8
+driver=wired
9
+logger_stdout=-1
10
+logger_stdout_level=1
11
+debug=2
12
+dump_file=/tmp/hostapd.dump
13
+
14
+ieee8021x=1
15
+eap_reauth_period=3600
16
+
17
+use_pae_group_addr=1
18
+
19
+
20
+##### RADIUS configuration ####################################################
21
+# for IEEE 802.1X with external Authentication Server, IEEE 802.11
22
+# authentication with external ACL for MAC addresses, and accounting
23
+
24
+# The own IP address of the access point (used as NAS-IP-Address)
25
+own_ip_addr=127.0.0.1
26
+
27
+# Optional NAS-Identifier string for RADIUS messages. When used, this should be
28
+# a unique to the NAS within the scope of the RADIUS server. For example, a
29
+# fully qualified domain name can be used here.
30
+nas_identifier=ap.example.com
31
+
32
+# RADIUS authentication server
33
+auth_server_addr=127.0.0.1
34
+auth_server_port=1812
35
+auth_server_shared_secret=radius
36
+
37
+# RADIUS accounting server
38
+acct_server_addr=127.0.0.1
39
+acct_server_port=1813
40
+acct_server_shared_secret=radius

+ 25
- 0
scripts/hostapd.conf Näytä tiedosto

@@ -0,0 +1,25 @@
1
+# Basic configuration
2
+
3
+interface=wlan0
4
+ssid=wifi
5
+channel=1
6
+#bridge=br0
7
+
8
+# WPA and WPA2 configuration
9
+
10
+macaddr_acl=0
11
+auth_algs=1
12
+ignore_broadcast_ssid=0
13
+wpa=3
14
+wpa_passphrase=YourPassPhrase
15
+wpa_key_mgmt=WPA-PSK
16
+wpa_pairwise=TKIP
17
+rsn_pairwise=CCMP
18
+
19
+# Hardware configuration
20
+
21
+driver=rtl871xdrv
22
+ieee80211n=1
23
+hw_mode=g
24
+device_name=RTL8192CU
25
+manufacturer=Realtek

+ 66
- 0
scripts/init Näytä tiedosto

@@ -0,0 +1,66 @@
1
+#!/bin/sh
2
+
3
+### BEGIN INIT INFO
4
+# Provides:             hostapd
5
+# Required-Start:       $remote_fs
6
+# Required-Stop:        $remote_fs
7
+# Should-Start:         $network
8
+# Should-Stop:
9
+# Default-Start:        2 3 4 5
10
+# Default-Stop:         0 1 6
11
+# Short-Description:    Advanced IEEE 802.11 management daemon
12
+# Description:          Userspace IEEE 802.11 AP and IEEE 802.1X/WPA/WPA2/EAP
13
+#                       Authenticator
14
+### END INIT INFO
15
+
16
+PATH=/sbin:/bin:/usr/sbin:/usr/bin
17
+DAEMON_SBIN=/usr/local/bin/hostapd
18
+DAEMON_CONF=/etc/hostapd/hostapd.conf
19
+NAME=hostapd
20
+DESC="advanced IEEE 802.11 management"
21
+PIDFILE=/var/run/hostapd.pid
22
+
23
+[ -x "$DAEMON_SBIN" ] || exit 0
24
+[ -n "$DAEMON_CONF" ] || exit 0
25
+
26
+DAEMON_OPTS="-B -P $PIDFILE $DAEMON_OPTS $DAEMON_CONF"
27
+
28
+. /lib/lsb/init-functions
29
+
30
+case "$1" in
31
+  start)
32
+        log_daemon_msg "Starting $DESC" "$NAME"
33
+        start-stop-daemon --start --oknodo --quiet --exec "$DAEMON_SBIN" \
34
+                --pidfile "$PIDFILE" -- $DAEMON_OPTS >/dev/null
35
+        log_end_msg "$?"
36
+        ;;
37
+  stop)
38
+        log_daemon_msg "Stopping $DESC" "$NAME"
39
+        start-stop-daemon --stop --oknodo --quiet --exec "$DAEMON_SBIN" \
40
+                --pidfile "$PIDFILE"
41
+        log_end_msg "$?"
42
+        ;;
43
+  reload)
44
+        log_daemon_msg "Reloading $DESC" "$NAME"
45
+        start-stop-daemon --stop --signal HUP --exec "$DAEMON_SBIN" \
46
+                --pidfile "$PIDFILE"
47
+        log_end_msg "$?"
48
+        ;;
49
+  restart|force-reload)
50
+        $0 stop
51
+        sleep 8
52
+        $0 start
53
+        ;;
54
+  status)
55
+        status_of_proc "$DAEMON_SBIN" "$NAME"
56
+        exit $?
57
+        ;;
58
+  *)
59
+        N=/etc/init.d/$NAME
60
+        echo "Usage: $N {start|stop|restart|force-reload|reload|status}" >&2
61
+        exit 1
62
+        ;;
63
+esac
64
+
65
+exit 0
66
+

+ 11
- 0
src/Makefile Näytä tiedosto

@@ -0,0 +1,11 @@
1
+SUBDIRS=ap common crypto drivers eapol_auth eapol_supp eap_common eap_peer eap_server l2_packet p2p radius rsn_supp tls utils wps
2
+
3
+all:
4
+	for d in $(SUBDIRS); do [ -d $$d ] && $(MAKE) -C $$d; done
5
+
6
+clean:
7
+	for d in $(SUBDIRS); do [ -d $$d ] && $(MAKE) -C $$d clean; done
8
+	rm -f *~
9
+
10
+install:
11
+	for d in $(SUBDIRS); do [ -d $$d ] && $(MAKE) -C $$d install; done

+ 8
- 0
src/ap/Makefile Näytä tiedosto

@@ -0,0 +1,8 @@
1
+all:
2
+	@echo Nothing to be made.
3
+
4
+clean:
5
+	rm -f *~ *.o *.d
6
+
7
+install:
8
+	@echo Nothing to be made.

+ 505
- 0
src/ap/accounting.c Näytä tiedosto

@@ -0,0 +1,505 @@
1
+/*
2
+ * hostapd / RADIUS Accounting
3
+ * Copyright (c) 2002-2009, Jouni Malinen <j@w1.fi>
4
+ *
5
+ * This program is free software; you can redistribute it and/or modify
6
+ * it under the terms of the GNU General Public License version 2 as
7
+ * published by the Free Software Foundation.
8
+ *
9
+ * Alternatively, this software may be distributed under the terms of BSD
10
+ * license.
11
+ *
12
+ * See README and COPYING for more details.
13
+ */
14
+
15
+#include "utils/includes.h"
16
+
17
+#include "utils/common.h"
18
+#include "utils/eloop.h"
19
+#include "drivers/driver.h"
20
+#include "radius/radius.h"
21
+#include "radius/radius_client.h"
22
+#include "hostapd.h"
23
+#include "ieee802_1x.h"
24
+#include "ap_config.h"
25
+#include "sta_info.h"
26
+#include "ap_drv_ops.h"
27
+#include "accounting.h"
28
+
29
+
30
+/* Default interval in seconds for polling TX/RX octets from the driver if
31
+ * STA is not using interim accounting. This detects wrap arounds for
32
+ * input/output octets and updates Acct-{Input,Output}-Gigawords. */
33
+#define ACCT_DEFAULT_UPDATE_INTERVAL 300
34
+
35
+static void accounting_sta_get_id(struct hostapd_data *hapd,
36
+				  struct sta_info *sta);
37
+
38
+
39
+static struct radius_msg * accounting_msg(struct hostapd_data *hapd,
40
+					  struct sta_info *sta,
41
+					  int status_type)
42
+{
43
+	struct radius_msg *msg;
44
+	char buf[128];
45
+	u8 *val;
46
+	size_t len;
47
+	int i;
48
+
49
+	msg = radius_msg_new(RADIUS_CODE_ACCOUNTING_REQUEST,
50
+			     radius_client_get_id(hapd->radius));
51
+	if (msg == NULL) {
52
+		printf("Could not create net RADIUS packet\n");
53
+		return NULL;
54
+	}
55
+
56
+	if (sta) {
57
+		radius_msg_make_authenticator(msg, (u8 *) sta, sizeof(*sta));
58
+
59
+		os_snprintf(buf, sizeof(buf), "%08X-%08X",
60
+			    sta->acct_session_id_hi, sta->acct_session_id_lo);
61
+		if (!radius_msg_add_attr(msg, RADIUS_ATTR_ACCT_SESSION_ID,
62
+					 (u8 *) buf, os_strlen(buf))) {
63
+			printf("Could not add Acct-Session-Id\n");
64
+			goto fail;
65
+		}
66
+	} else {
67
+		radius_msg_make_authenticator(msg, (u8 *) hapd, sizeof(*hapd));
68
+	}
69
+
70
+	if (!radius_msg_add_attr_int32(msg, RADIUS_ATTR_ACCT_STATUS_TYPE,
71
+				       status_type)) {
72
+		printf("Could not add Acct-Status-Type\n");
73
+		goto fail;
74
+	}
75
+
76
+	if (!radius_msg_add_attr_int32(msg, RADIUS_ATTR_ACCT_AUTHENTIC,
77
+				       hapd->conf->ieee802_1x ?
78
+				       RADIUS_ACCT_AUTHENTIC_RADIUS :
79
+				       RADIUS_ACCT_AUTHENTIC_LOCAL)) {
80
+		printf("Could not add Acct-Authentic\n");
81
+		goto fail;
82
+	}
83
+
84
+	if (sta) {
85
+		val = ieee802_1x_get_identity(sta->eapol_sm, &len);
86
+		if (!val) {
87
+			os_snprintf(buf, sizeof(buf), RADIUS_ADDR_FORMAT,
88
+				    MAC2STR(sta->addr));
89
+			val = (u8 *) buf;
90
+			len = os_strlen(buf);
91
+		}
92
+
93
+		if (!radius_msg_add_attr(msg, RADIUS_ATTR_USER_NAME, val,
94
+					 len)) {
95
+			printf("Could not add User-Name\n");
96
+			goto fail;
97
+		}
98
+	}
99
+
100
+	if (hapd->conf->own_ip_addr.af == AF_INET &&
101
+	    !radius_msg_add_attr(msg, RADIUS_ATTR_NAS_IP_ADDRESS,
102
+				 (u8 *) &hapd->conf->own_ip_addr.u.v4, 4)) {
103
+		printf("Could not add NAS-IP-Address\n");
104
+		goto fail;
105
+	}
106
+
107
+#ifdef CONFIG_IPV6
108
+	if (hapd->conf->own_ip_addr.af == AF_INET6 &&
109
+	    !radius_msg_add_attr(msg, RADIUS_ATTR_NAS_IPV6_ADDRESS,
110
+				 (u8 *) &hapd->conf->own_ip_addr.u.v6, 16)) {
111
+		printf("Could not add NAS-IPv6-Address\n");
112
+		goto fail;
113
+	}
114
+#endif /* CONFIG_IPV6 */
115
+
116
+	if (hapd->conf->nas_identifier &&
117
+	    !radius_msg_add_attr(msg, RADIUS_ATTR_NAS_IDENTIFIER,
118
+				 (u8 *) hapd->conf->nas_identifier,
119
+				 os_strlen(hapd->conf->nas_identifier))) {
120
+		printf("Could not add NAS-Identifier\n");
121
+		goto fail;
122
+	}
123
+
124
+	if (sta &&
125
+	    !radius_msg_add_attr_int32(msg, RADIUS_ATTR_NAS_PORT, sta->aid)) {
126
+		printf("Could not add NAS-Port\n");
127
+		goto fail;
128
+	}
129
+
130
+	os_snprintf(buf, sizeof(buf), RADIUS_802_1X_ADDR_FORMAT ":%s",
131
+		    MAC2STR(hapd->own_addr), hapd->conf->ssid.ssid);
132
+	if (!radius_msg_add_attr(msg, RADIUS_ATTR_CALLED_STATION_ID,
133
+				 (u8 *) buf, os_strlen(buf))) {
134
+		printf("Could not add Called-Station-Id\n");
135
+		goto fail;
136
+	}
137
+
138
+	if (sta) {
139
+		os_snprintf(buf, sizeof(buf), RADIUS_802_1X_ADDR_FORMAT,
140
+			    MAC2STR(sta->addr));
141
+		if (!radius_msg_add_attr(msg, RADIUS_ATTR_CALLING_STATION_ID,
142
+					 (u8 *) buf, os_strlen(buf))) {
143
+			printf("Could not add Calling-Station-Id\n");
144
+			goto fail;
145
+		}
146
+
147
+		if (!radius_msg_add_attr_int32(
148
+			    msg, RADIUS_ATTR_NAS_PORT_TYPE,
149
+			    RADIUS_NAS_PORT_TYPE_IEEE_802_11)) {
150
+			printf("Could not add NAS-Port-Type\n");
151
+			goto fail;
152
+		}
153
+
154
+		os_snprintf(buf, sizeof(buf), "CONNECT %d%sMbps %s",
155
+			    radius_sta_rate(hapd, sta) / 2,
156
+			    (radius_sta_rate(hapd, sta) & 1) ? ".5" : "",
157
+			    radius_mode_txt(hapd));
158
+		if (!radius_msg_add_attr(msg, RADIUS_ATTR_CONNECT_INFO,
159
+					 (u8 *) buf, os_strlen(buf))) {
160
+			printf("Could not add Connect-Info\n");
161
+			goto fail;
162
+		}
163
+
164
+		for (i = 0; ; i++) {
165
+			val = ieee802_1x_get_radius_class(sta->eapol_sm, &len,
166
+							  i);
167
+			if (val == NULL)
168
+				break;
169
+
170
+			if (!radius_msg_add_attr(msg, RADIUS_ATTR_CLASS,
171
+						 val, len)) {
172
+				printf("Could not add Class\n");
173
+				goto fail;
174
+			}
175
+		}
176
+	}
177
+
178
+	return msg;
179
+
180
+ fail:
181
+	radius_msg_free(msg);
182
+	return NULL;
183
+}
184
+
185
+
186
+static int accounting_sta_update_stats(struct hostapd_data *hapd,
187
+				       struct sta_info *sta,
188
+				       struct hostap_sta_driver_data *data)
189
+{
190
+	if (hostapd_drv_read_sta_data(hapd, data, sta->addr))
191
+		return -1;
192
+
193
+	if (sta->last_rx_bytes > data->rx_bytes)
194
+		sta->acct_input_gigawords++;
195
+	if (sta->last_tx_bytes > data->tx_bytes)
196
+		sta->acct_output_gigawords++;
197
+	sta->last_rx_bytes = data->rx_bytes;
198
+	sta->last_tx_bytes = data->tx_bytes;
199
+
200
+	hostapd_logger(hapd, sta->addr, HOSTAPD_MODULE_RADIUS,
201
+		       HOSTAPD_LEVEL_DEBUG, "updated TX/RX stats: "
202
+		       "Acct-Input-Octets=%lu Acct-Input-Gigawords=%u "
203
+		       "Acct-Output-Octets=%lu Acct-Output-Gigawords=%u",
204
+		       sta->last_rx_bytes, sta->acct_input_gigawords,
205
+		       sta->last_tx_bytes, sta->acct_output_gigawords);
206
+
207
+	return 0;
208
+}
209
+
210
+
211
+static void accounting_interim_update(void *eloop_ctx, void *timeout_ctx)
212
+{
213
+	struct hostapd_data *hapd = eloop_ctx;
214
+	struct sta_info *sta = timeout_ctx;
215
+	int interval;
216
+
217
+	if (sta->acct_interim_interval) {
218
+		accounting_sta_interim(hapd, sta);
219
+		interval = sta->acct_interim_interval;
220
+	} else {
221
+		struct hostap_sta_driver_data data;
222
+		accounting_sta_update_stats(hapd, sta, &data);
223
+		interval = ACCT_DEFAULT_UPDATE_INTERVAL;
224
+	}
225
+
226
+	eloop_register_timeout(interval, 0, accounting_interim_update,
227
+			       hapd, sta);
228
+}
229
+
230
+
231
+/**
232
+ * accounting_sta_start - Start STA accounting
233
+ * @hapd: hostapd BSS data
234
+ * @sta: The station
235
+ */
236
+void accounting_sta_start(struct hostapd_data *hapd, struct sta_info *sta)
237
+{
238
+	struct radius_msg *msg;
239
+	int interval;
240
+
241
+	if (sta->acct_session_started)
242
+		return;
243
+
244
+	accounting_sta_get_id(hapd, sta);
245
+	hostapd_logger(hapd, sta->addr, HOSTAPD_MODULE_RADIUS,
246
+		       HOSTAPD_LEVEL_INFO,
247
+		       "starting accounting session %08X-%08X",
248
+		       sta->acct_session_id_hi, sta->acct_session_id_lo);
249
+
250
+	time(&sta->acct_session_start);
251
+	sta->last_rx_bytes = sta->last_tx_bytes = 0;
252
+	sta->acct_input_gigawords = sta->acct_output_gigawords = 0;
253
+	hostapd_drv_sta_clear_stats(hapd, sta->addr);
254
+
255
+	if (!hapd->conf->radius->acct_server)
256
+		return;
257
+
258
+	if (sta->acct_interim_interval)
259
+		interval = sta->acct_interim_interval;
260
+	else
261
+		interval = ACCT_DEFAULT_UPDATE_INTERVAL;
262
+	eloop_register_timeout(interval, 0, accounting_interim_update,
263
+			       hapd, sta);
264
+
265
+	msg = accounting_msg(hapd, sta, RADIUS_ACCT_STATUS_TYPE_START);
266
+	if (msg)
267
+		radius_client_send(hapd->radius, msg, RADIUS_ACCT, sta->addr);
268
+
269
+	sta->acct_session_started = 1;
270
+}
271
+
272
+
273
+static void accounting_sta_report(struct hostapd_data *hapd,
274
+				  struct sta_info *sta, int stop)
275
+{
276
+	struct radius_msg *msg;
277
+	int cause = sta->acct_terminate_cause;
278
+	struct hostap_sta_driver_data data;
279
+	struct os_time now;
280
+	u32 gigawords;
281
+
282
+	if (!hapd->conf->radius->acct_server)
283
+		return;
284
+
285
+	msg = accounting_msg(hapd, sta,
286
+			     stop ? RADIUS_ACCT_STATUS_TYPE_STOP :
287
+			     RADIUS_ACCT_STATUS_TYPE_INTERIM_UPDATE);
288
+	if (!msg) {
289
+		printf("Could not create RADIUS Accounting message\n");
290
+		return;
291
+	}
292
+
293
+	os_get_time(&now);
294
+	if (!radius_msg_add_attr_int32(msg, RADIUS_ATTR_ACCT_SESSION_TIME,
295
+				       now.sec - sta->acct_session_start)) {
296
+		printf("Could not add Acct-Session-Time\n");
297
+		goto fail;
298
+	}
299
+
300
+	if (accounting_sta_update_stats(hapd, sta, &data) == 0) {
301
+		if (!radius_msg_add_attr_int32(msg,
302
+					       RADIUS_ATTR_ACCT_INPUT_PACKETS,
303
+					       data.rx_packets)) {
304
+			printf("Could not add Acct-Input-Packets\n");
305
+			goto fail;
306
+		}
307
+		if (!radius_msg_add_attr_int32(msg,
308
+					       RADIUS_ATTR_ACCT_OUTPUT_PACKETS,
309
+					       data.tx_packets)) {
310
+			printf("Could not add Acct-Output-Packets\n");
311
+			goto fail;
312
+		}
313
+		if (!radius_msg_add_attr_int32(msg,
314
+					       RADIUS_ATTR_ACCT_INPUT_OCTETS,
315
+					       data.rx_bytes)) {
316
+			printf("Could not add Acct-Input-Octets\n");
317
+			goto fail;
318
+		}
319
+		gigawords = sta->acct_input_gigawords;
320
+#if __WORDSIZE == 64
321
+		gigawords += data.rx_bytes >> 32;
322
+#endif
323
+		if (gigawords &&
324
+		    !radius_msg_add_attr_int32(
325
+			    msg, RADIUS_ATTR_ACCT_INPUT_GIGAWORDS,
326
+			    gigawords)) {
327
+			printf("Could not add Acct-Input-Gigawords\n");
328
+			goto fail;
329
+		}
330
+		if (!radius_msg_add_attr_int32(msg,
331
+					       RADIUS_ATTR_ACCT_OUTPUT_OCTETS,
332
+					       data.tx_bytes)) {
333
+			printf("Could not add Acct-Output-Octets\n");
334
+			goto fail;
335
+		}
336
+		gigawords = sta->acct_output_gigawords;
337
+#if __WORDSIZE == 64
338
+		gigawords += data.tx_bytes >> 32;
339
+#endif
340
+		if (gigawords &&
341
+		    !radius_msg_add_attr_int32(
342
+			    msg, RADIUS_ATTR_ACCT_OUTPUT_GIGAWORDS,
343
+			    gigawords)) {
344
+			printf("Could not add Acct-Output-Gigawords\n");
345
+			goto fail;
346
+		}
347
+	}
348
+
349
+	if (!radius_msg_add_attr_int32(msg, RADIUS_ATTR_EVENT_TIMESTAMP,
350
+				       now.sec)) {
351
+		printf("Could not add Event-Timestamp\n");
352
+		goto fail;
353
+	}
354
+
355
+	if (eloop_terminated())
356
+		cause = RADIUS_ACCT_TERMINATE_CAUSE_ADMIN_REBOOT;
357
+
358
+	if (stop && cause &&
359
+	    !radius_msg_add_attr_int32(msg, RADIUS_ATTR_ACCT_TERMINATE_CAUSE,
360
+				       cause)) {
361
+		printf("Could not add Acct-Terminate-Cause\n");
362
+		goto fail;
363
+	}
364
+
365
+	radius_client_send(hapd->radius, msg,
366
+			   stop ? RADIUS_ACCT : RADIUS_ACCT_INTERIM,
367
+			   sta->addr);
368
+	return;
369
+
370
+ fail:
371
+	radius_msg_free(msg);
372
+}
373
+
374
+
375
+/**
376
+ * accounting_sta_interim - Send a interim STA accounting report
377
+ * @hapd: hostapd BSS data
378
+ * @sta: The station
379
+ */
380
+void accounting_sta_interim(struct hostapd_data *hapd, struct sta_info *sta)
381
+{
382
+	if (sta->acct_session_started)
383
+		accounting_sta_report(hapd, sta, 0);
384
+}
385
+
386
+
387
+/**
388
+ * accounting_sta_stop - Stop STA accounting
389
+ * @hapd: hostapd BSS data
390
+ * @sta: The station
391
+ */
392
+void accounting_sta_stop(struct hostapd_data *hapd, struct sta_info *sta)
393
+{
394
+	if (sta->acct_session_started) {
395
+		accounting_sta_report(hapd, sta, 1);
396
+		eloop_cancel_timeout(accounting_interim_update, hapd, sta);
397
+		hostapd_logger(hapd, sta->addr, HOSTAPD_MODULE_RADIUS,
398
+			       HOSTAPD_LEVEL_INFO,
399
+			       "stopped accounting session %08X-%08X",
400
+			       sta->acct_session_id_hi,
401
+			       sta->acct_session_id_lo);
402
+		sta->acct_session_started = 0;
403
+	}
404
+}
405
+
406
+
407
+static void accounting_sta_get_id(struct hostapd_data *hapd,
408
+				  struct sta_info *sta)
409
+{
410
+	sta->acct_session_id_lo = hapd->acct_session_id_lo++;
411
+	if (hapd->acct_session_id_lo == 0) {
412
+		hapd->acct_session_id_hi++;
413
+	}
414
+	sta->acct_session_id_hi = hapd->acct_session_id_hi;
415
+}
416
+
417
+
418
+/**
419
+ * accounting_receive - Process the RADIUS frames from Accounting Server
420
+ * @msg: RADIUS response message
421
+ * @req: RADIUS request message
422
+ * @shared_secret: RADIUS shared secret
423
+ * @shared_secret_len: Length of shared_secret in octets
424
+ * @data: Context data (struct hostapd_data *)
425
+ * Returns: Processing status
426
+ */
427
+static RadiusRxResult
428
+accounting_receive(struct radius_msg *msg, struct radius_msg *req,
429
+		   const u8 *shared_secret, size_t shared_secret_len,
430
+		   void *data)
431
+{
432
+	if (radius_msg_get_hdr(msg)->code != RADIUS_CODE_ACCOUNTING_RESPONSE) {
433
+		printf("Unknown RADIUS message code\n");
434
+		return RADIUS_RX_UNKNOWN;
435
+	}
436
+
437
+	if (radius_msg_verify(msg, shared_secret, shared_secret_len, req, 0)) {
438
+		printf("Incoming RADIUS packet did not have correct "
439
+		       "Authenticator - dropped\n");
440
+		return RADIUS_RX_INVALID_AUTHENTICATOR;
441
+	}
442
+
443
+	return RADIUS_RX_PROCESSED;
444
+}
445
+
446
+
447
+static void accounting_report_state(struct hostapd_data *hapd, int on)
448
+{
449
+	struct radius_msg *msg;
450
+
451
+	if (!hapd->conf->radius->acct_server || hapd->radius == NULL)
452
+		return;
453
+
454
+	/* Inform RADIUS server that accounting will start/stop so that the
455
+	 * server can close old accounting sessions. */
456
+	msg = accounting_msg(hapd, NULL,
457
+			     on ? RADIUS_ACCT_STATUS_TYPE_ACCOUNTING_ON :
458
+			     RADIUS_ACCT_STATUS_TYPE_ACCOUNTING_OFF);
459
+	if (!msg)
460
+		return;
461
+
462
+	if (!radius_msg_add_attr_int32(msg, RADIUS_ATTR_ACCT_TERMINATE_CAUSE,
463
+				       RADIUS_ACCT_TERMINATE_CAUSE_NAS_REBOOT))
464
+	{
465
+		printf("Could not add Acct-Terminate-Cause\n");
466
+		radius_msg_free(msg);
467
+		return;
468
+	}
469
+
470
+	radius_client_send(hapd->radius, msg, RADIUS_ACCT, NULL);
471
+}
472
+
473
+
474
+/**
475
+ * accounting_init: Initialize accounting
476
+ * @hapd: hostapd BSS data
477
+ * Returns: 0 on success, -1 on failure
478
+ */
479
+int accounting_init(struct hostapd_data *hapd)
480
+{
481
+	struct os_time now;
482
+
483
+	/* Acct-Session-Id should be unique over reboots. If reliable clock is
484
+	 * not available, this could be replaced with reboot counter, etc. */
485
+	os_get_time(&now);
486
+	hapd->acct_session_id_hi = now.sec;
487
+
488
+	if (radius_client_register(hapd->radius, RADIUS_ACCT,
489
+				   accounting_receive, hapd))
490
+		return -1;
491
+
492
+	accounting_report_state(hapd, 1);
493
+
494
+	return 0;
495
+}
496
+
497
+
498
+/**
499
+ * accounting_deinit: Deinitilize accounting
500
+ * @hapd: hostapd BSS data
501
+ */
502
+void accounting_deinit(struct hostapd_data *hapd)
503
+{
504
+	accounting_report_state(hapd, 0);
505
+}

+ 45
- 0
src/ap/accounting.h Näytä tiedosto

@@ -0,0 +1,45 @@
1
+/*
2
+ * hostapd / RADIUS Accounting
3
+ * Copyright (c) 2002-2005, Jouni Malinen <j@w1.fi>
4
+ *
5
+ * This program is free software; you can redistribute it and/or modify
6
+ * it under the terms of the GNU General Public License version 2 as
7
+ * published by the Free Software Foundation.
8
+ *
9
+ * Alternatively, this software may be distributed under the terms of BSD
10
+ * license.
11
+ *
12
+ * See README and COPYING for more details.
13
+ */
14
+
15
+#ifndef ACCOUNTING_H
16
+#define ACCOUNTING_H
17
+
18
+void accounting_sta_interim(struct hostapd_data *hapd, struct sta_info *sta);
19
+#ifdef CONFIG_NO_ACCOUNTING
20
+static inline void accounting_sta_start(struct hostapd_data *hapd,
21
+					struct sta_info *sta)
22
+{
23
+}
24
+
25
+static inline void accounting_sta_stop(struct hostapd_data *hapd,
26
+				       struct sta_info *sta)
27
+{
28
+}
29
+
30
+static inline int accounting_init(struct hostapd_data *hapd)
31
+{
32
+	return 0;
33
+}
34
+
35
+static inline void accounting_deinit(struct hostapd_data *hapd)
36
+{
37
+}
38
+#else /* CONFIG_NO_ACCOUNTING */
39
+void accounting_sta_start(struct hostapd_data *hapd, struct sta_info *sta);
40
+void accounting_sta_stop(struct hostapd_data *hapd, struct sta_info *sta);
41
+int accounting_init(struct hostapd_data *hapd);
42
+void accounting_deinit(struct hostapd_data *hapd);
43
+#endif /* CONFIG_NO_ACCOUNTING */
44
+
45
+#endif /* ACCOUNTING_H */

+ 627
- 0
src/ap/ap_config.c Näytä tiedosto

@@ -0,0 +1,627 @@
1
+/*
2
+ * hostapd / Configuration helper functions
3
+ * Copyright (c) 2003-2009, Jouni Malinen <j@w1.fi>
4
+ *
5
+ * This program is free software; you can redistribute it and/or modify
6
+ * it under the terms of the GNU General Public License version 2 as
7
+ * published by the Free Software Foundation.
8
+ *
9
+ * Alternatively, this software may be distributed under the terms of BSD
10
+ * license.
11
+ *
12
+ * See README and COPYING for more details.
13
+ */
14
+
15
+#include "utils/includes.h"
16
+
17
+#include "utils/common.h"
18
+#include "crypto/sha1.h"
19
+#include "radius/radius_client.h"
20
+#include "common/ieee802_11_defs.h"
21
+#include "common/eapol_common.h"
22
+#include "eap_common/eap_wsc_common.h"
23
+#include "eap_server/eap.h"
24
+#include "wpa_auth.h"
25
+#include "sta_info.h"
26
+#include "ap_config.h"
27
+
28
+
29
+static void hostapd_config_free_vlan(struct hostapd_bss_config *bss)
30
+{
31
+	struct hostapd_vlan *vlan, *prev;
32
+
33
+	vlan = bss->vlan;
34
+	prev = NULL;
35
+	while (vlan) {
36
+		prev = vlan;
37
+		vlan = vlan->next;
38
+		os_free(prev);
39
+	}
40
+
41
+	bss->vlan = NULL;
42
+}
43
+
44
+
45
+void hostapd_config_defaults_bss(struct hostapd_bss_config *bss)
46
+{
47
+	bss->logger_syslog_level = HOSTAPD_LEVEL_INFO;
48
+	bss->logger_stdout_level = HOSTAPD_LEVEL_INFO;
49
+	bss->logger_syslog = (unsigned int) -1;
50
+	bss->logger_stdout = (unsigned int) -1;
51
+
52
+	bss->auth_algs = WPA_AUTH_ALG_OPEN | WPA_AUTH_ALG_SHARED;
53
+
54
+	bss->wep_rekeying_period = 300;
55
+	/* use key0 in individual key and key1 in broadcast key */
56
+	bss->broadcast_key_idx_min = 1;
57
+	bss->broadcast_key_idx_max = 2;
58
+	bss->eap_reauth_period = 3600;
59
+
60
+	bss->wpa_group_rekey = 600;
61
+	bss->wpa_gmk_rekey = 86400;
62
+	bss->wpa_key_mgmt = WPA_KEY_MGMT_PSK;
63
+	bss->wpa_pairwise = WPA_CIPHER_TKIP;
64
+	bss->wpa_group = WPA_CIPHER_TKIP;
65
+	bss->rsn_pairwise = 0;
66
+
67
+	bss->max_num_sta = MAX_STA_COUNT;
68
+
69
+	bss->dtim_period = 2;
70
+
71
+	bss->radius_server_auth_port = 1812;
72
+	bss->ap_max_inactivity = AP_MAX_INACTIVITY;
73
+	bss->eapol_version = EAPOL_VERSION;
74
+
75
+	bss->max_listen_interval = 65535;
76
+
77
+	bss->pwd_group = 19; /* ECC: GF(p=256) */
78
+
79
+#ifdef CONFIG_IEEE80211W
80
+	bss->assoc_sa_query_max_timeout = 1000;
81
+	bss->assoc_sa_query_retry_timeout = 201;
82
+#endif /* CONFIG_IEEE80211W */
83
+#ifdef EAP_SERVER_FAST
84
+	 /* both anonymous and authenticated provisioning */
85
+	bss->eap_fast_prov = 3;
86
+	bss->pac_key_lifetime = 7 * 24 * 60 * 60;
87
+	bss->pac_key_refresh_time = 1 * 24 * 60 * 60;
88
+#endif /* EAP_SERVER_FAST */
89
+
90
+	/* Set to -1 as defaults depends on HT in setup */
91
+	bss->wmm_enabled = -1;
92
+
93
+#ifdef CONFIG_IEEE80211R
94
+	bss->ft_over_ds = 1;
95
+#endif /* CONFIG_IEEE80211R */
96
+}
97
+
98
+
99
+struct hostapd_config * hostapd_config_defaults(void)
100
+{
101
+#define ecw2cw(ecw) ((1 << (ecw)) - 1)
102
+
103
+	struct hostapd_config *conf;
104
+	struct hostapd_bss_config *bss;
105
+	const int aCWmin = 4, aCWmax = 10;
106
+	const struct hostapd_wmm_ac_params ac_bk =
107
+		{ aCWmin, aCWmax, 7, 0, 0 }; /* background traffic */
108
+	const struct hostapd_wmm_ac_params ac_be =
109
+		{ aCWmin, aCWmax, 3, 0, 0 }; /* best effort traffic */
110
+	const struct hostapd_wmm_ac_params ac_vi = /* video traffic */
111
+		{ aCWmin - 1, aCWmin, 2, 3000 / 32, 1 };
112
+	const struct hostapd_wmm_ac_params ac_vo = /* voice traffic */
113
+		{ aCWmin - 2, aCWmin - 1, 2, 1500 / 32, 1 };
114
+	const struct hostapd_tx_queue_params txq_bk =
115
+		{ 7, ecw2cw(aCWmin), ecw2cw(aCWmax), 0 };
116
+	const struct hostapd_tx_queue_params txq_be =
117
+		{ 3, ecw2cw(aCWmin), 4 * (ecw2cw(aCWmin) + 1) - 1, 0};
118
+	const struct hostapd_tx_queue_params txq_vi =
119
+		{ 1, (ecw2cw(aCWmin) + 1) / 2 - 1, ecw2cw(aCWmin), 30};
120
+	const struct hostapd_tx_queue_params txq_vo =
121
+		{ 1, (ecw2cw(aCWmin) + 1) / 4 - 1,
122
+		  (ecw2cw(aCWmin) + 1) / 2 - 1, 15};
123
+
124
+#undef ecw2cw
125
+
126
+	conf = os_zalloc(sizeof(*conf));
127
+	bss = os_zalloc(sizeof(*bss));
128
+	if (conf == NULL || bss == NULL) {
129
+		wpa_printf(MSG_ERROR, "Failed to allocate memory for "
130
+			   "configuration data.");
131
+		os_free(conf);
132
+		os_free(bss);
133
+		return NULL;
134
+	}
135
+
136
+	bss->radius = os_zalloc(sizeof(*bss->radius));
137
+	if (bss->radius == NULL) {
138
+		os_free(conf);
139
+		os_free(bss);
140
+		return NULL;
141
+	}
142
+
143
+	hostapd_config_defaults_bss(bss);
144
+
145
+	conf->num_bss = 1;
146
+	conf->bss = bss;
147
+
148
+	conf->beacon_int = 100;
149
+	conf->rts_threshold = -1; /* use driver default: 2347 */
150
+	conf->fragm_threshold = -1; /* user driver default: 2346 */
151
+	conf->send_probe_response = 1;
152
+
153
+	conf->wmm_ac_params[0] = ac_be;
154
+	conf->wmm_ac_params[1] = ac_bk;
155
+	conf->wmm_ac_params[2] = ac_vi;
156
+	conf->wmm_ac_params[3] = ac_vo;
157
+
158
+	conf->tx_queue[0] = txq_vo;
159
+	conf->tx_queue[1] = txq_vi;
160
+	conf->tx_queue[2] = txq_be;
161
+	conf->tx_queue[3] = txq_bk;
162
+
163
+	conf->ht_capab = HT_CAP_INFO_SMPS_DISABLED;
164
+
165
+	return conf;
166
+}
167
+
168
+
169
+int hostapd_mac_comp(const void *a, const void *b)
170
+{
171
+	return os_memcmp(a, b, sizeof(macaddr));
172
+}
173
+
174
+
175
+int hostapd_mac_comp_empty(const void *a)
176
+{
177
+	macaddr empty = { 0 };
178
+	return os_memcmp(a, empty, sizeof(macaddr));
179
+}
180
+
181
+
182
+static int hostapd_config_read_wpa_psk(const char *fname,
183
+				       struct hostapd_ssid *ssid)
184
+{
185
+	FILE *f;
186
+	char buf[128], *pos;
187
+	int line = 0, ret = 0, len, ok;
188
+	u8 addr[ETH_ALEN];
189
+	struct hostapd_wpa_psk *psk;
190
+
191
+	if (!fname)
192
+		return 0;
193
+
194
+	f = fopen(fname, "r");
195
+	if (!f) {
196
+		wpa_printf(MSG_ERROR, "WPA PSK file '%s' not found.", fname);
197
+		return -1;
198
+	}
199
+
200
+	while (fgets(buf, sizeof(buf), f)) {
201
+		line++;
202
+
203
+		if (buf[0] == '#')
204
+			continue;
205
+		pos = buf;
206
+		while (*pos != '\0') {
207
+			if (*pos == '\n') {
208
+				*pos = '\0';
209
+				break;
210
+			}
211
+			pos++;
212
+		}
213
+		if (buf[0] == '\0')
214
+			continue;
215
+
216
+		if (hwaddr_aton(buf, addr)) {
217
+			wpa_printf(MSG_ERROR, "Invalid MAC address '%s' on "
218
+				   "line %d in '%s'", buf, line, fname);
219
+			ret = -1;
220
+			break;
221
+		}
222
+
223
+		psk = os_zalloc(sizeof(*psk));
224
+		if (psk == NULL) {
225
+			wpa_printf(MSG_ERROR, "WPA PSK allocation failed");
226
+			ret = -1;
227
+			break;
228
+		}
229
+		if (is_zero_ether_addr(addr))
230
+			psk->group = 1;
231
+		else
232
+			os_memcpy(psk->addr, addr, ETH_ALEN);
233
+
234
+		pos = buf + 17;
235
+		if (*pos == '\0') {
236
+			wpa_printf(MSG_ERROR, "No PSK on line %d in '%s'",
237
+				   line, fname);
238
+			os_free(psk);
239
+			ret = -1;
240
+			break;
241
+		}
242
+		pos++;
243
+
244
+		ok = 0;
245
+		len = os_strlen(pos);
246
+		if (len == 64 && hexstr2bin(pos, psk->psk, PMK_LEN) == 0)
247
+			ok = 1;
248
+		else if (len >= 8 && len < 64) {
249
+			pbkdf2_sha1(pos, ssid->ssid, ssid->ssid_len,
250
+				    4096, psk->psk, PMK_LEN);
251
+			ok = 1;
252
+		}
253
+		if (!ok) {
254
+			wpa_printf(MSG_ERROR, "Invalid PSK '%s' on line %d in "
255
+				   "'%s'", pos, line, fname);
256
+			os_free(psk);
257
+			ret = -1;
258
+			break;
259
+		}
260
+
261
+		psk->next = ssid->wpa_psk;
262
+		ssid->wpa_psk = psk;
263
+	}
264
+
265
+	fclose(f);
266
+
267
+	return ret;
268
+}
269
+
270
+
271
+static int hostapd_derive_psk(struct hostapd_ssid *ssid)
272
+{
273
+	ssid->wpa_psk = os_zalloc(sizeof(struct hostapd_wpa_psk));
274
+	if (ssid->wpa_psk == NULL) {
275
+		wpa_printf(MSG_ERROR, "Unable to alloc space for PSK");
276
+		return -1;
277
+	}
278
+	wpa_hexdump_ascii(MSG_DEBUG, "SSID",
279
+			  (u8 *) ssid->ssid, ssid->ssid_len);
280
+	wpa_hexdump_ascii_key(MSG_DEBUG, "PSK (ASCII passphrase)",
281
+			      (u8 *) ssid->wpa_passphrase,
282
+			      os_strlen(ssid->wpa_passphrase));
283
+	pbkdf2_sha1(ssid->wpa_passphrase,
284
+		    ssid->ssid, ssid->ssid_len,
285
+		    4096, ssid->wpa_psk->psk, PMK_LEN);
286
+	wpa_hexdump_key(MSG_DEBUG, "PSK (from passphrase)",
287
+			ssid->wpa_psk->psk, PMK_LEN);
288
+	return 0;
289
+}
290
+
291
+
292
+int hostapd_setup_wpa_psk(struct hostapd_bss_config *conf)
293
+{
294
+	struct hostapd_ssid *ssid = &conf->ssid;
295
+
296
+	if (ssid->wpa_passphrase != NULL) {
297
+		if (ssid->wpa_psk != NULL) {
298
+			wpa_printf(MSG_DEBUG, "Using pre-configured WPA PSK "
299
+				   "instead of passphrase");
300
+		} else {
301
+			wpa_printf(MSG_DEBUG, "Deriving WPA PSK based on "
302
+				   "passphrase");
303
+			if (hostapd_derive_psk(ssid) < 0)
304
+				return -1;
305
+		}
306
+		ssid->wpa_psk->group = 1;
307
+	}
308
+
309
+	if (ssid->wpa_psk_file) {
310
+		if (hostapd_config_read_wpa_psk(ssid->wpa_psk_file,
311
+						&conf->ssid))
312
+			return -1;
313
+	}
314
+
315
+	return 0;
316
+}
317
+
318
+
319
+int hostapd_wep_key_cmp(struct hostapd_wep_keys *a, struct hostapd_wep_keys *b)
320
+{
321
+	int i;
322
+
323
+	if (a->idx != b->idx || a->default_len != b->default_len)
324
+		return 1;
325
+	for (i = 0; i < NUM_WEP_KEYS; i++)
326
+		if (a->len[i] != b->len[i] ||
327
+		    os_memcmp(a->key[i], b->key[i], a->len[i]) != 0)
328
+			return 1;
329
+	return 0;
330
+}
331
+
332
+
333
+static void hostapd_config_free_radius(struct hostapd_radius_server *servers,
334
+				       int num_servers)
335
+{
336
+	int i;
337
+
338
+	for (i = 0; i < num_servers; i++) {
339
+		os_free(servers[i].shared_secret);
340
+	}
341
+	os_free(servers);
342
+}
343
+
344
+
345
+static void hostapd_config_free_eap_user(struct hostapd_eap_user *user)
346
+{
347
+	os_free(user->identity);
348
+	os_free(user->password);
349
+	os_free(user);
350
+}
351
+
352
+
353
+static void hostapd_config_free_wep(struct hostapd_wep_keys *keys)
354
+{
355
+	int i;
356
+	for (i = 0; i < NUM_WEP_KEYS; i++) {
357
+		os_free(keys->key[i]);
358
+		keys->key[i] = NULL;
359
+	}
360
+}
361
+
362
+
363
+static void hostapd_config_free_bss(struct hostapd_bss_config *conf)
364
+{
365
+	struct hostapd_wpa_psk *psk, *prev;
366
+	struct hostapd_eap_user *user, *prev_user;
367
+
368
+	if (conf == NULL)
369
+		return;
370
+
371
+	psk = conf->ssid.wpa_psk;
372
+	while (psk) {
373
+		prev = psk;
374
+		psk = psk->next;
375
+		os_free(prev);
376
+	}
377
+
378
+	os_free(conf->ssid.wpa_passphrase);
379
+	os_free(conf->ssid.wpa_psk_file);
380
+	hostapd_config_free_wep(&conf->ssid.wep);
381
+#ifdef CONFIG_FULL_DYNAMIC_VLAN
382
+	os_free(conf->ssid.vlan_tagged_interface);
383
+#endif /* CONFIG_FULL_DYNAMIC_VLAN */
384
+
385
+	user = conf->eap_user;
386
+	while (user) {
387
+		prev_user = user;
388
+		user = user->next;
389
+		hostapd_config_free_eap_user(prev_user);
390
+	}
391
+
392
+	os_free(conf->dump_log_name);
393
+	os_free(conf->eap_req_id_text);
394
+	os_free(conf->accept_mac);
395
+	os_free(conf->deny_mac);
396
+	os_free(conf->nas_identifier);
397
+	hostapd_config_free_radius(conf->radius->auth_servers,
398
+				   conf->radius->num_auth_servers);
399
+	hostapd_config_free_radius(conf->radius->acct_servers,
400
+				   conf->radius->num_acct_servers);
401
+	os_free(conf->rsn_preauth_interfaces);
402
+	os_free(conf->ctrl_interface);
403
+	os_free(conf->ca_cert);
404
+	os_free(conf->server_cert);
405
+	os_free(conf->private_key);
406
+	os_free(conf->private_key_passwd);
407
+	os_free(conf->dh_file);
408
+	os_free(conf->pac_opaque_encr_key);
409
+	os_free(conf->eap_fast_a_id);
410
+	os_free(conf->eap_fast_a_id_info);
411
+	os_free(conf->eap_sim_db);
412
+	os_free(conf->radius_server_clients);
413
+	os_free(conf->test_socket);
414
+	os_free(conf->radius);
415
+	hostapd_config_free_vlan(conf);
416
+	if (conf->ssid.dyn_vlan_keys) {
417
+		struct hostapd_ssid *ssid = &conf->ssid;
418
+		size_t i;
419
+		for (i = 0; i <= ssid->max_dyn_vlan_keys; i++) {
420
+			if (ssid->dyn_vlan_keys[i] == NULL)
421
+				continue;
422
+			hostapd_config_free_wep(ssid->dyn_vlan_keys[i]);
423
+			os_free(ssid->dyn_vlan_keys[i]);
424
+		}
425
+		os_free(ssid->dyn_vlan_keys);
426
+		ssid->dyn_vlan_keys = NULL;
427
+	}
428
+
429
+#ifdef CONFIG_IEEE80211R
430
+	{
431
+		struct ft_remote_r0kh *r0kh, *r0kh_prev;
432
+		struct ft_remote_r1kh *r1kh, *r1kh_prev;
433
+
434
+		r0kh = conf->r0kh_list;
435
+		conf->r0kh_list = NULL;
436
+		while (r0kh) {
437
+			r0kh_prev = r0kh;
438
+			r0kh = r0kh->next;
439
+			os_free(r0kh_prev);
440
+		}
441
+
442
+		r1kh = conf->r1kh_list;
443
+		conf->r1kh_list = NULL;
444
+		while (r1kh) {
445
+			r1kh_prev = r1kh;
446
+			r1kh = r1kh->next;
447
+			os_free(r1kh_prev);
448
+		}
449
+	}
450
+#endif /* CONFIG_IEEE80211R */
451
+
452
+#ifdef CONFIG_WPS
453
+	os_free(conf->wps_pin_requests);
454
+	os_free(conf->device_name);
455
+	os_free(conf->manufacturer);
456
+	os_free(conf->model_name);
457
+	os_free(conf->model_number);
458
+	os_free(conf->serial_number);
459
+	os_free(conf->config_methods);
460
+	os_free(conf->ap_pin);
461
+	os_free(conf->extra_cred);
462
+	os_free(conf->ap_settings);
463
+	os_free(conf->upnp_iface);
464
+	os_free(conf->friendly_name);
465
+	os_free(conf->manufacturer_url);
466
+	os_free(conf->model_description);
467
+	os_free(conf->model_url);
468
+	os_free(conf->upc);
469
+#endif /* CONFIG_WPS */
470
+}
471
+
472
+
473
+/**
474
+ * hostapd_config_free - Free hostapd configuration
475
+ * @conf: Configuration data from hostapd_config_read().
476
+ */
477
+void hostapd_config_free(struct hostapd_config *conf)
478
+{
479
+	size_t i;
480
+
481
+	if (conf == NULL)
482
+		return;
483
+
484
+	for (i = 0; i < conf->num_bss; i++)
485
+		hostapd_config_free_bss(&conf->bss[i]);
486
+	os_free(conf->bss);
487
+	os_free(conf->supported_rates);
488
+	os_free(conf->basic_rates);
489
+
490
+	os_free(conf);
491
+}
492
+
493
+
494
+/**
495
+ * hostapd_maclist_found - Find a MAC address from a list
496
+ * @list: MAC address list
497
+ * @num_entries: Number of addresses in the list
498
+ * @addr: Address to search for
499
+ * @vlan_id: Buffer for returning VLAN ID or %NULL if not needed
500
+ * Returns: 1 if address is in the list or 0 if not.
501
+ *
502
+ * Perform a binary search for given MAC address from a pre-sorted list.
503
+ */
504
+int hostapd_maclist_found(struct mac_acl_entry *list, int num_entries,
505
+			  const u8 *addr, int *vlan_id)
506
+{
507
+	int start, end, middle, res;
508
+
509
+	start = 0;
510
+	end = num_entries - 1;
511
+
512
+	while (start <= end) {
513
+		middle = (start + end) / 2;
514
+		res = os_memcmp(list[middle].addr, addr, ETH_ALEN);
515
+		if (res == 0) {
516
+			if (vlan_id)
517
+				*vlan_id = list[middle].vlan_id;
518
+			return 1;
519
+		}
520
+		if (res < 0)
521
+			start = middle + 1;
522
+		else
523
+			end = middle - 1;
524
+	}
525
+
526
+	return 0;
527
+}
528
+
529
+
530
+int hostapd_rate_found(int *list, int rate)
531
+{
532
+	int i;
533
+
534
+	if (list == NULL)
535
+		return 0;
536
+
537
+	for (i = 0; list[i] >= 0; i++)
538
+		if (list[i] == rate)
539
+			return 1;
540
+
541
+	return 0;
542
+}
543
+
544
+
545
+const char * hostapd_get_vlan_id_ifname(struct hostapd_vlan *vlan, int vlan_id)
546
+{
547
+	struct hostapd_vlan *v = vlan;
548
+	while (v) {
549
+		if (v->vlan_id == vlan_id || v->vlan_id == VLAN_ID_WILDCARD)
550
+			return v->ifname;
551
+		v = v->next;
552
+	}
553
+	return NULL;
554
+}
555
+
556
+
557
+const u8 * hostapd_get_psk(const struct hostapd_bss_config *conf,
558
+			   const u8 *addr, const u8 *prev_psk)
559
+{
560
+	struct hostapd_wpa_psk *psk;
561
+	int next_ok = prev_psk == NULL;
562
+
563
+	for (psk = conf->ssid.wpa_psk; psk != NULL; psk = psk->next) {
564
+		if (next_ok &&
565
+		    (psk->group || os_memcmp(psk->addr, addr, ETH_ALEN) == 0))
566
+			return psk->psk;
567
+
568
+		if (psk->psk == prev_psk)
569
+			next_ok = 1;
570
+	}
571
+
572
+	return NULL;
573
+}
574
+
575
+
576
+const struct hostapd_eap_user *
577
+hostapd_get_eap_user(const struct hostapd_bss_config *conf, const u8 *identity,
578
+		     size_t identity_len, int phase2)
579
+{
580
+	struct hostapd_eap_user *user = conf->eap_user;
581
+
582
+#ifdef CONFIG_WPS
583
+	if (conf->wps_state && identity_len == WSC_ID_ENROLLEE_LEN &&
584
+	    os_memcmp(identity, WSC_ID_ENROLLEE, WSC_ID_ENROLLEE_LEN) == 0) {
585
+		static struct hostapd_eap_user wsc_enrollee;
586
+		os_memset(&wsc_enrollee, 0, sizeof(wsc_enrollee));
587
+		wsc_enrollee.methods[0].method = eap_server_get_type(
588
+			"WSC", &wsc_enrollee.methods[0].vendor);
589
+		return &wsc_enrollee;
590
+	}
591
+
592
+	if (conf->wps_state && identity_len == WSC_ID_REGISTRAR_LEN &&
593
+	    os_memcmp(identity, WSC_ID_REGISTRAR, WSC_ID_REGISTRAR_LEN) == 0) {
594
+		static struct hostapd_eap_user wsc_registrar;
595
+		os_memset(&wsc_registrar, 0, sizeof(wsc_registrar));
596
+		wsc_registrar.methods[0].method = eap_server_get_type(
597
+			"WSC", &wsc_registrar.methods[0].vendor);
598
+		wsc_registrar.password = (u8 *) conf->ap_pin;
599
+		wsc_registrar.password_len = conf->ap_pin ?
600
+			os_strlen(conf->ap_pin) : 0;
601
+		return &wsc_registrar;
602
+	}
603
+#endif /* CONFIG_WPS */
604
+
605
+	while (user) {
606
+		if (!phase2 && user->identity == NULL) {
607
+			/* Wildcard match */
608
+			break;
609
+		}
610
+
611
+		if (user->phase2 == !!phase2 && user->wildcard_prefix &&
612
+		    identity_len >= user->identity_len &&
613
+		    os_memcmp(user->identity, identity, user->identity_len) ==
614
+		    0) {
615
+			/* Wildcard prefix match */
616
+			break;
617
+		}
618
+
619
+		if (user->phase2 == !!phase2 &&
620
+		    user->identity_len == identity_len &&
621
+		    os_memcmp(user->identity, identity, identity_len) == 0)
622
+			break;
623
+		user = user->next;
624
+	}
625
+
626
+	return user;
627
+}

+ 417
- 0
src/ap/ap_config.h Näytä tiedosto

@@ -0,0 +1,417 @@
1
+/*
2
+ * hostapd / Configuration definitions and helpers functions
3
+ * Copyright (c) 2003-2009, Jouni Malinen <j@w1.fi>
4
+ *
5
+ * This program is free software; you can redistribute it and/or modify
6
+ * it under the terms of the GNU General Public License version 2 as
7
+ * published by the Free Software Foundation.
8
+ *
9
+ * Alternatively, this software may be distributed under the terms of BSD
10
+ * license.
11
+ *
12
+ * See README and COPYING for more details.
13
+ */
14
+
15
+#ifndef HOSTAPD_CONFIG_H
16
+#define HOSTAPD_CONFIG_H
17
+
18
+#include "common/defs.h"
19
+#include "ip_addr.h"
20
+#include "common/wpa_common.h"
21
+#include "wps/wps.h"
22
+
23
+#define MAX_STA_COUNT 2007
24
+#define MAX_VLAN_ID 4094
25
+
26
+typedef u8 macaddr[ETH_ALEN];
27
+
28
+struct mac_acl_entry {
29
+	macaddr addr;
30
+	int vlan_id;
31
+};
32
+
33
+struct hostapd_radius_servers;
34
+struct ft_remote_r0kh;
35
+struct ft_remote_r1kh;
36
+
37
+#define HOSTAPD_MAX_SSID_LEN 32
38
+
39
+#define NUM_WEP_KEYS 4
40
+struct hostapd_wep_keys {
41
+	u8 idx;
42
+	u8 *key[NUM_WEP_KEYS];
43
+	size_t len[NUM_WEP_KEYS];
44
+	int keys_set;
45
+	size_t default_len; /* key length used for dynamic key generation */
46
+};
47
+
48
+typedef enum hostap_security_policy {
49
+	SECURITY_PLAINTEXT = 0,
50
+	SECURITY_STATIC_WEP = 1,
51
+	SECURITY_IEEE_802_1X = 2,
52
+	SECURITY_WPA_PSK = 3,
53
+	SECURITY_WPA = 4
54
+} secpolicy;
55
+
56
+struct hostapd_ssid {
57
+	char ssid[HOSTAPD_MAX_SSID_LEN + 1];
58
+	size_t ssid_len;
59
+	int ssid_set;
60
+
61
+	char vlan[IFNAMSIZ + 1];
62
+	secpolicy security_policy;
63
+
64
+	struct hostapd_wpa_psk *wpa_psk;
65
+	char *wpa_passphrase;
66
+	char *wpa_psk_file;
67
+
68
+	struct hostapd_wep_keys wep;
69
+
70
+#define DYNAMIC_VLAN_DISABLED 0
71
+#define DYNAMIC_VLAN_OPTIONAL 1
72
+#define DYNAMIC_VLAN_REQUIRED 2
73
+	int dynamic_vlan;
74
+#ifdef CONFIG_FULL_DYNAMIC_VLAN
75
+	char *vlan_tagged_interface;
76
+#endif /* CONFIG_FULL_DYNAMIC_VLAN */
77
+	struct hostapd_wep_keys **dyn_vlan_keys;
78
+	size_t max_dyn_vlan_keys;
79
+};
80
+
81
+
82
+#define VLAN_ID_WILDCARD -1
83
+
84
+struct hostapd_vlan {
85
+	struct hostapd_vlan *next;
86
+	int vlan_id; /* VLAN ID or -1 (VLAN_ID_WILDCARD) for wildcard entry */
87
+	char ifname[IFNAMSIZ + 1];
88
+	int dynamic_vlan;
89
+#ifdef CONFIG_FULL_DYNAMIC_VLAN
90
+
91
+#define DVLAN_CLEAN_BR 	0x1
92
+#define DVLAN_CLEAN_VLAN	0x2
93
+#define DVLAN_CLEAN_VLAN_PORT	0x4
94
+#define DVLAN_CLEAN_WLAN_PORT	0x8
95
+	int clean;
96
+#endif /* CONFIG_FULL_DYNAMIC_VLAN */
97
+};
98
+
99
+#define PMK_LEN 32
100
+struct hostapd_wpa_psk {
101
+	struct hostapd_wpa_psk *next;
102
+	int group;
103
+	u8 psk[PMK_LEN];
104
+	u8 addr[ETH_ALEN];
105
+};
106
+
107
+#define EAP_USER_MAX_METHODS 8
108
+struct hostapd_eap_user {
109
+	struct hostapd_eap_user *next;
110
+	u8 *identity;
111
+	size_t identity_len;
112
+	struct {
113
+		int vendor;
114
+		u32 method;
115
+	} methods[EAP_USER_MAX_METHODS];
116
+	u8 *password;
117
+	size_t password_len;
118
+	int phase2;
119
+	int force_version;
120
+	unsigned int wildcard_prefix:1;
121
+	unsigned int password_hash:1; /* whether password is hashed with
122
+				       * nt_password_hash() */
123
+	int ttls_auth; /* EAP_TTLS_AUTH_* bitfield */
124
+};
125
+
126
+
127
+#define NUM_TX_QUEUES 4
128
+
129
+struct hostapd_tx_queue_params {
130
+	int aifs;
131
+	int cwmin;
132
+	int cwmax;
133
+	int burst; /* maximum burst time in 0.1 ms, i.e., 10 = 1 ms */
134
+};
135
+
136
+struct hostapd_wmm_ac_params {
137
+	int cwmin;
138
+	int cwmax;
139
+	int aifs;
140
+	int txop_limit; /* in units of 32us */
141
+	int admission_control_mandatory;
142
+};
143
+
144
+
145
+/**
146
+ * struct hostapd_bss_config - Per-BSS configuration
147
+ */
148
+struct hostapd_bss_config {
149
+	char iface[IFNAMSIZ + 1];
150
+	char bridge[IFNAMSIZ + 1];
151
+	char wds_bridge[IFNAMSIZ + 1];
152
+
153
+	enum hostapd_logger_level logger_syslog_level, logger_stdout_level;
154
+
155
+	unsigned int logger_syslog; /* module bitfield */
156
+	unsigned int logger_stdout; /* module bitfield */
157
+
158
+	char *dump_log_name; /* file name for state dump (SIGUSR1) */
159
+
160
+	int max_num_sta; /* maximum number of STAs in station table */
161
+
162
+	int dtim_period;
163
+
164
+	int ieee802_1x; /* use IEEE 802.1X */
165
+	int eapol_version;
166
+	int eap_server; /* Use internal EAP server instead of external
167
+			 * RADIUS server */
168
+	struct hostapd_eap_user *eap_user;
169
+	char *eap_sim_db;
170
+	struct hostapd_ip_addr own_ip_addr;
171
+	char *nas_identifier;
172
+	struct hostapd_radius_servers *radius;
173
+	int acct_interim_interval;
174
+
175
+	struct hostapd_ssid ssid;
176
+
177
+	char *eap_req_id_text; /* optional displayable message sent with
178
+				* EAP Request-Identity */
179
+	size_t eap_req_id_text_len;
180
+	int eapol_key_index_workaround;
181
+
182
+	size_t default_wep_key_len;
183
+	int individual_wep_key_len;
184
+	int wep_rekeying_period;
185
+	int broadcast_key_idx_min, broadcast_key_idx_max;
186
+	int eap_reauth_period;
187
+
188
+	int ieee802_11f; /* use IEEE 802.11f (IAPP) */
189
+	char iapp_iface[IFNAMSIZ + 1]; /* interface used with IAPP broadcast
190
+					* frames */
191
+
192
+	enum {
193
+		ACCEPT_UNLESS_DENIED = 0,
194
+		DENY_UNLESS_ACCEPTED = 1,
195
+		USE_EXTERNAL_RADIUS_AUTH = 2
196
+	} macaddr_acl;
197
+	struct mac_acl_entry *accept_mac;
198
+	int num_accept_mac;
199
+	struct mac_acl_entry *deny_mac;
200
+	int num_deny_mac;
201
+	int wds_sta;
202
+	int isolate;
203
+
204
+	int auth_algs; /* bitfield of allowed IEEE 802.11 authentication
205
+			* algorithms, WPA_AUTH_ALG_{OPEN,SHARED,LEAP} */
206
+
207
+	int wpa; /* bitfield of WPA_PROTO_WPA, WPA_PROTO_RSN */
208
+	int wpa_key_mgmt;
209
+#ifdef CONFIG_IEEE80211W
210
+	enum mfp_options ieee80211w;
211
+	/* dot11AssociationSAQueryMaximumTimeout (in TUs) */
212
+	unsigned int assoc_sa_query_max_timeout;
213
+	/* dot11AssociationSAQueryRetryTimeout (in TUs) */
214
+	int assoc_sa_query_retry_timeout;
215
+#endif /* CONFIG_IEEE80211W */
216
+	int wpa_pairwise;
217
+	int wpa_group;
218
+	int wpa_group_rekey;
219
+	int wpa_strict_rekey;
220
+	int wpa_gmk_rekey;
221
+	int wpa_ptk_rekey;
222
+	int rsn_pairwise;
223
+	int rsn_preauth;
224
+	char *rsn_preauth_interfaces;
225
+	int peerkey;
226
+
227
+#ifdef CONFIG_IEEE80211R
228
+	/* IEEE 802.11r - Fast BSS Transition */
229
+	u8 mobility_domain[MOBILITY_DOMAIN_ID_LEN];
230
+	u8 r1_key_holder[FT_R1KH_ID_LEN];
231
+	u32 r0_key_lifetime;
232
+	u32 reassociation_deadline;
233
+	struct ft_remote_r0kh *r0kh_list;
234
+	struct ft_remote_r1kh *r1kh_list;
235
+	int pmk_r1_push;
236
+	int ft_over_ds;
237
+#endif /* CONFIG_IEEE80211R */
238
+
239
+	char *ctrl_interface; /* directory for UNIX domain sockets */
240
+#ifndef CONFIG_NATIVE_WINDOWS
241
+	gid_t ctrl_interface_gid;
242
+#endif /* CONFIG_NATIVE_WINDOWS */
243
+	int ctrl_interface_gid_set;
244
+
245
+	char *ca_cert;
246
+	char *server_cert;
247
+	char *private_key;
248
+	char *private_key_passwd;
249
+	int check_crl;
250
+	char *dh_file;
251
+	u8 *pac_opaque_encr_key;
252
+	u8 *eap_fast_a_id;
253
+	size_t eap_fast_a_id_len;
254
+	char *eap_fast_a_id_info;
255
+	int eap_fast_prov;
256
+	int pac_key_lifetime;
257
+	int pac_key_refresh_time;
258
+	int eap_sim_aka_result_ind;
259
+	int tnc;
260
+	int fragment_size;
261
+	u16 pwd_group;
262
+
263
+	char *radius_server_clients;
264
+	int radius_server_auth_port;
265
+	int radius_server_ipv6;
266
+
267
+	char *test_socket; /* UNIX domain socket path for driver_test */
268
+
269
+	int use_pae_group_addr; /* Whether to send EAPOL frames to PAE group
270
+				 * address instead of individual address
271
+				 * (for driver_wired.c).
272
+				 */
273
+
274
+	int ap_max_inactivity;
275
+	int ignore_broadcast_ssid;
276
+
277
+	int wmm_enabled;
278
+	int wmm_uapsd;
279
+
280
+	struct hostapd_vlan *vlan, *vlan_tail;
281
+
282
+	macaddr bssid;
283
+
284
+	/*
285
+	 * Maximum listen interval that STAs can use when associating with this
286
+	 * BSS. If a STA tries to use larger value, the association will be
287
+	 * denied with status code 51.
288
+	 */
289
+	u16 max_listen_interval;
290
+
291
+	int okc; /* Opportunistic Key Caching */
292
+
293
+	int wps_state;
294
+#ifdef CONFIG_WPS
295
+	int ap_setup_locked;
296
+	u8 uuid[16];
297
+	char *wps_pin_requests;
298
+	char *device_name;
299
+	char *manufacturer;
300
+	char *model_name;
301
+	char *model_number;
302
+	char *serial_number;
303
+	u8 device_type[WPS_DEV_TYPE_LEN];
304
+	char *config_methods;
305
+	u8 os_version[4];
306
+	char *ap_pin;
307
+	int skip_cred_build;
308
+	u8 *extra_cred;
309
+	size_t extra_cred_len;
310
+	int wps_cred_processing;
311
+	u8 *ap_settings;
312
+	size_t ap_settings_len;
313
+	char *upnp_iface;
314
+	char *friendly_name;
315
+	char *manufacturer_url;
316
+	char *model_description;
317
+	char *model_url;
318
+	char *upc;
319
+	struct wpabuf *wps_vendor_ext[MAX_WPS_VENDOR_EXTENSIONS];
320
+#endif /* CONFIG_WPS */
321
+
322
+#define P2P_ENABLED BIT(0)
323
+#define P2P_GROUP_OWNER BIT(1)
324
+#define P2P_GROUP_FORMATION BIT(2)
325
+#define P2P_MANAGE BIT(3)
326
+#define P2P_ALLOW_CROSS_CONNECTION BIT(4)
327
+	int p2p;
328
+
329
+	int disassoc_low_ack;
330
+
331
+#define TDLS_PROHIBIT BIT(0)
332
+#define TDLS_PROHIBIT_CHAN_SWITCH BIT(1)
333
+	int tdls;
334
+	int disable_11n;
335
+};
336
+
337
+
338
+/**
339
+ * struct hostapd_config - Per-radio interface configuration
340
+ */
341
+struct hostapd_config {
342
+	struct hostapd_bss_config *bss, *last_bss;
343
+	size_t num_bss;
344
+
345
+	u16 beacon_int;
346
+	int rts_threshold;
347
+	int fragm_threshold;
348
+	u8 send_probe_response;
349
+	u8 channel;
350
+	enum hostapd_hw_mode hw_mode; /* HOSTAPD_MODE_IEEE80211A, .. */
351
+	enum {
352
+		LONG_PREAMBLE = 0,
353
+		SHORT_PREAMBLE = 1
354
+	} preamble;
355
+	enum {
356
+		CTS_PROTECTION_AUTOMATIC = 0,
357
+		CTS_PROTECTION_FORCE_ENABLED = 1,
358
+		CTS_PROTECTION_FORCE_DISABLED = 2,
359
+		CTS_PROTECTION_AUTOMATIC_NO_OLBC = 3,
360
+	} cts_protection_type;
361
+
362
+	int *supported_rates;
363
+	int *basic_rates;
364
+
365
+	const struct wpa_driver_ops *driver;
366
+
367
+	int ap_table_max_size;
368
+	int ap_table_expiration_time;
369
+
370
+	char country[3]; /* first two octets: country code as described in
371
+			  * ISO/IEC 3166-1. Third octet:
372
+			  * ' ' (ascii 32): all environments
373
+			  * 'O': Outdoor environemnt only
374
+			  * 'I': Indoor environment only
375
+			  */
376
+
377
+	int ieee80211d;
378
+
379
+	struct hostapd_tx_queue_params tx_queue[NUM_TX_QUEUES];
380
+
381
+	/*
382
+	 * WMM AC parameters, in same order as 802.1D, i.e.
383
+	 * 0 = BE (best effort)
384
+	 * 1 = BK (background)
385
+	 * 2 = VI (video)
386
+	 * 3 = VO (voice)
387
+	 */
388
+	struct hostapd_wmm_ac_params wmm_ac_params[4];
389
+
390
+	int ht_op_mode_fixed;
391
+	u16 ht_capab;
392
+	int ieee80211n;
393
+	int secondary_channel;
394
+	int require_ht;
395
+};
396
+
397
+
398
+int hostapd_mac_comp(const void *a, const void *b);
399
+int hostapd_mac_comp_empty(const void *a);
400
+struct hostapd_config * hostapd_config_defaults(void);
401
+void hostapd_config_defaults_bss(struct hostapd_bss_config *bss);
402
+void hostapd_config_free(struct hostapd_config *conf);
403
+int hostapd_maclist_found(struct mac_acl_entry *list, int num_entries,
404
+			  const u8 *addr, int *vlan_id);
405
+int hostapd_rate_found(int *list, int rate);
406
+int hostapd_wep_key_cmp(struct hostapd_wep_keys *a,
407
+			struct hostapd_wep_keys *b);
408
+const u8 * hostapd_get_psk(const struct hostapd_bss_config *conf,
409
+			   const u8 *addr, const u8 *prev_psk);
410
+int hostapd_setup_wpa_psk(struct hostapd_bss_config *conf);
411
+const char * hostapd_get_vlan_id_ifname(struct hostapd_vlan *vlan,
412
+					int vlan_id);
413
+const struct hostapd_eap_user *
414
+hostapd_get_eap_user(const struct hostapd_bss_config *conf, const u8 *identity,
415
+		     size_t identity_len, int phase2);
416
+
417
+#endif /* HOSTAPD_CONFIG_H */

+ 632
- 0
src/ap/ap_drv_ops.c Näytä tiedosto

@@ -0,0 +1,632 @@
1
+/*
2
+ * hostapd - Driver operations
3
+ * Copyright (c) 2009-2010, Jouni Malinen <j@w1.fi>
4
+ *
5
+ * This program is free software; you can redistribute it and/or modify
6
+ * it under the terms of the GNU General Public License version 2 as
7
+ * published by the Free Software Foundation.
8
+ *
9
+ * Alternatively, this software may be distributed under the terms of BSD
10
+ * license.
11
+ *
12
+ * See README and COPYING for more details.
13
+ */
14
+
15
+#include "utils/includes.h"
16
+
17
+#include "utils/common.h"
18
+#include "drivers/driver.h"
19
+#include "common/ieee802_11_defs.h"
20
+#include "wps/wps.h"
21
+#include "hostapd.h"
22
+#include "ieee802_11.h"
23
+#include "sta_info.h"
24
+#include "ap_config.h"
25
+#include "p2p_hostapd.h"
26
+#include "ap_drv_ops.h"
27
+
28
+
29
+u32 hostapd_sta_flags_to_drv(u32 flags)
30
+{
31
+	int res = 0;
32
+	if (flags & WLAN_STA_AUTHORIZED)
33
+		res |= WPA_STA_AUTHORIZED;
34
+	if (flags & WLAN_STA_WMM)
35
+		res |= WPA_STA_WMM;
36
+	if (flags & WLAN_STA_SHORT_PREAMBLE)
37
+		res |= WPA_STA_SHORT_PREAMBLE;
38
+	if (flags & WLAN_STA_MFP)
39
+		res |= WPA_STA_MFP;
40
+	return res;
41
+}
42
+
43
+
44
+int hostapd_set_ap_wps_ie(struct hostapd_data *hapd)
45
+{
46
+	struct wpabuf *beacon, *proberesp, *assocresp = NULL;
47
+	int ret;
48
+
49
+	if (hapd->driver == NULL || hapd->driver->set_ap_wps_ie == NULL)
50
+		return 0;
51
+
52
+	beacon = hapd->wps_beacon_ie;
53
+	proberesp = hapd->wps_probe_resp_ie;
54
+
55
+#ifdef CONFIG_P2P
56
+	if (hapd->wps_beacon_ie == NULL && hapd->p2p_beacon_ie == NULL)
57
+		beacon = NULL;
58
+	else {
59
+		beacon = wpabuf_alloc((hapd->wps_beacon_ie ?
60
+				       wpabuf_len(hapd->wps_beacon_ie) : 0) +
61
+				      (hapd->p2p_beacon_ie ?
62
+				       wpabuf_len(hapd->p2p_beacon_ie) : 0));
63
+		if (beacon == NULL)
64
+			return -1;
65
+		if (hapd->wps_beacon_ie)
66
+			wpabuf_put_buf(beacon, hapd->wps_beacon_ie);
67
+		if (hapd->p2p_beacon_ie)
68
+			wpabuf_put_buf(beacon, hapd->p2p_beacon_ie);
69
+	}
70
+
71
+	if (hapd->wps_probe_resp_ie == NULL && hapd->p2p_probe_resp_ie == NULL)
72
+		proberesp = NULL;
73
+	else {
74
+		proberesp = wpabuf_alloc(
75
+			(hapd->wps_probe_resp_ie ?
76
+			 wpabuf_len(hapd->wps_probe_resp_ie) : 0) +
77
+			(hapd->p2p_probe_resp_ie ?
78
+			 wpabuf_len(hapd->p2p_probe_resp_ie) : 0));
79
+		if (proberesp == NULL) {
80
+			wpabuf_free(beacon);
81
+			return -1;
82
+		}
83
+		if (hapd->wps_probe_resp_ie)
84
+			wpabuf_put_buf(proberesp, hapd->wps_probe_resp_ie);
85
+		if (hapd->p2p_probe_resp_ie)
86
+			wpabuf_put_buf(proberesp, hapd->p2p_probe_resp_ie);
87
+	}
88
+#endif /* CONFIG_P2P */
89
+
90
+#ifdef CONFIG_P2P_MANAGER
91
+	if (hapd->conf->p2p & P2P_MANAGE) {
92
+		struct wpabuf *a;
93
+
94
+		a = wpabuf_alloc(100 + (beacon ? wpabuf_len(beacon) : 0));
95
+		if (a) {
96
+			u8 *start, *p;
97
+			if (beacon)
98
+				wpabuf_put_buf(a, beacon);
99
+			if (beacon != hapd->wps_beacon_ie)
100
+				wpabuf_free(beacon);
101
+			start = wpabuf_put(a, 0);
102
+			p = hostapd_eid_p2p_manage(hapd, start);
103
+			wpabuf_put(a, p - start);
104
+			beacon = a;
105
+		}
106
+
107
+		a = wpabuf_alloc(100 + (proberesp ? wpabuf_len(proberesp) :
108
+					0));
109
+		if (a) {
110
+			u8 *start, *p;
111
+			if (proberesp)
112
+				wpabuf_put_buf(a, proberesp);
113
+			if (proberesp != hapd->wps_probe_resp_ie)
114
+				wpabuf_free(proberesp);
115
+			start = wpabuf_put(a, 0);
116
+			p = hostapd_eid_p2p_manage(hapd, start);
117
+			wpabuf_put(a, p - start);
118
+			proberesp = a;
119
+		}
120
+	}
121
+#endif /* CONFIG_P2P_MANAGER */
122
+
123
+#ifdef CONFIG_WPS2
124
+	if (hapd->conf->wps_state)
125
+		assocresp = wps_build_assoc_resp_ie();
126
+#endif /* CONFIG_WPS2 */
127
+
128
+#ifdef CONFIG_P2P_MANAGER
129
+	if (hapd->conf->p2p & P2P_MANAGE) {
130
+		struct wpabuf *a;
131
+		a = wpabuf_alloc(100 + (assocresp ? wpabuf_len(assocresp) :
132
+					0));
133
+		if (a) {
134
+			u8 *start, *p;
135
+			start = wpabuf_put(a, 0);
136
+			p = hostapd_eid_p2p_manage(hapd, start);
137
+			wpabuf_put(a, p - start);
138
+			if (assocresp) {
139
+				wpabuf_put_buf(a, assocresp);
140
+				wpabuf_free(assocresp);
141
+			}
142
+			assocresp = a;
143
+		}
144
+	}
145
+#endif /* CONFIG_P2P_MANAGER */
146
+
147
+	ret = hapd->driver->set_ap_wps_ie(hapd->drv_priv, beacon, proberesp,
148
+					  assocresp);
149
+
150
+	if (beacon != hapd->wps_beacon_ie)
151
+		wpabuf_free(beacon);
152
+	if (proberesp != hapd->wps_probe_resp_ie)
153
+		wpabuf_free(proberesp);
154
+	wpabuf_free(assocresp);
155
+
156
+	return ret;
157
+}
158
+
159
+
160
+int hostapd_set_authorized(struct hostapd_data *hapd,
161
+			   struct sta_info *sta, int authorized)
162
+{
163
+	if (authorized) {
164
+		return hostapd_sta_set_flags(hapd, sta->addr,
165
+					     hostapd_sta_flags_to_drv(
166
+						     sta->flags),
167
+					     WPA_STA_AUTHORIZED, ~0);
168
+	}
169
+
170
+	return hostapd_sta_set_flags(hapd, sta->addr,
171
+				     hostapd_sta_flags_to_drv(sta->flags),
172
+				     0, ~WPA_STA_AUTHORIZED);
173
+}
174
+
175
+
176
+int hostapd_set_sta_flags(struct hostapd_data *hapd, struct sta_info *sta)
177
+{
178
+	int set_flags, total_flags, flags_and, flags_or;
179
+	total_flags = hostapd_sta_flags_to_drv(sta->flags);
180
+	set_flags = WPA_STA_SHORT_PREAMBLE | WPA_STA_WMM | WPA_STA_MFP;
181
+	if (((!hapd->conf->ieee802_1x && !hapd->conf->wpa) ||
182
+	     sta->auth_alg == WLAN_AUTH_FT) &&
183
+	    sta->flags & WLAN_STA_AUTHORIZED)
184
+		set_flags |= WPA_STA_AUTHORIZED;
185
+	flags_or = total_flags & set_flags;
186
+	flags_and = total_flags | ~set_flags;
187
+	return hostapd_sta_set_flags(hapd, sta->addr, total_flags,
188
+				     flags_or, flags_and);
189
+}
190
+
191
+
192
+int hostapd_set_drv_ieee8021x(struct hostapd_data *hapd, const char *ifname,
193
+			      int enabled)
194
+{
195
+	struct wpa_bss_params params;
196
+	os_memset(&params, 0, sizeof(params));
197
+	params.ifname = ifname;
198
+	params.enabled = enabled;
199
+	if (enabled) {
200
+		params.wpa = hapd->conf->wpa;
201
+		params.ieee802_1x = hapd->conf->ieee802_1x;
202
+		params.wpa_group = hapd->conf->wpa_group;
203
+		params.wpa_pairwise = hapd->conf->wpa_pairwise;
204
+		params.wpa_key_mgmt = hapd->conf->wpa_key_mgmt;
205
+		params.rsn_preauth = hapd->conf->rsn_preauth;
206
+#ifdef CONFIG_IEEE80211W
207
+		params.ieee80211w = hapd->conf->ieee80211w;
208
+#endif /* CONFIG_IEEE80211W */
209
+	}
210
+	return hostapd_set_ieee8021x(hapd, &params);
211
+}
212
+
213
+
214
+static int hostapd_set_ap_isolate(struct hostapd_data *hapd, int value)
215
+{
216
+	if (hapd->driver == NULL || hapd->driver->set_intra_bss == NULL)
217
+		return 0;
218
+	return hapd->driver->set_intra_bss(hapd->drv_priv, !value);
219
+}
220
+
221
+
222
+int hostapd_set_bss_params(struct hostapd_data *hapd, int use_protection)
223
+{
224
+	int ret = 0;
225
+	int preamble;
226
+#ifdef CONFIG_IEEE80211N
227
+	u8 buf[60], *ht_capab, *ht_oper, *pos;
228
+
229
+	pos = buf;
230
+	ht_capab = pos;
231
+	pos = hostapd_eid_ht_capabilities(hapd, pos);
232
+	ht_oper = pos;
233
+	pos = hostapd_eid_ht_operation(hapd, pos);
234
+	if (pos > ht_oper && ht_oper > ht_capab &&
235
+	    hostapd_set_ht_params(hapd, ht_capab + 2, ht_capab[1],
236
+				  ht_oper + 2, ht_oper[1])) {
237
+		wpa_printf(MSG_ERROR, "Could not set HT capabilities "
238
+			   "for kernel driver");
239
+		ret = -1;
240
+	}
241
+
242
+#endif /* CONFIG_IEEE80211N */
243
+
244
+	if (hostapd_set_cts_protect(hapd, use_protection)) {
245
+		wpa_printf(MSG_ERROR, "Failed to set CTS protect in kernel "
246
+			   "driver");
247
+		ret = -1;
248
+	}
249
+
250
+	if (hapd->iface->current_mode &&
251
+	    hapd->iface->current_mode->mode == HOSTAPD_MODE_IEEE80211G &&
252
+	    hostapd_set_short_slot_time(hapd,
253
+					hapd->iface->num_sta_no_short_slot_time
254
+					> 0 ? 0 : 1)) {
255
+		wpa_printf(MSG_ERROR, "Failed to set Short Slot Time option "
256
+			   "in kernel driver");
257
+		ret = -1;
258
+	}
259
+
260
+	if (hapd->iface->num_sta_no_short_preamble == 0 &&
261
+	    hapd->iconf->preamble == SHORT_PREAMBLE)
262
+		preamble = SHORT_PREAMBLE;
263
+	else
264
+		preamble = LONG_PREAMBLE;
265
+	if (hostapd_set_preamble(hapd, preamble)) {
266
+		wpa_printf(MSG_ERROR, "Could not set preamble for kernel "
267
+			   "driver");
268
+		ret = -1;
269
+	}
270
+
271
+	if (hostapd_set_ap_isolate(hapd, hapd->conf->isolate) &&
272
+	    hapd->conf->isolate) {
273
+		wpa_printf(MSG_ERROR, "Could not enable AP isolation in "
274
+			   "kernel driver");
275
+		ret = -1;
276
+	}
277
+
278
+	return ret;
279
+}
280
+
281
+
282
+int hostapd_vlan_if_add(struct hostapd_data *hapd, const char *ifname)
283
+{
284
+	char force_ifname[IFNAMSIZ];
285
+	u8 if_addr[ETH_ALEN];
286
+	return hostapd_if_add(hapd, WPA_IF_AP_VLAN, ifname, hapd->own_addr,
287
+			      NULL, NULL, force_ifname, if_addr, NULL);
288
+}
289
+
290
+
291
+int hostapd_vlan_if_remove(struct hostapd_data *hapd, const char *ifname)
292
+{
293
+	return hostapd_if_remove(hapd, WPA_IF_AP_VLAN, ifname);
294
+}
295
+
296
+
297
+int hostapd_set_wds_sta(struct hostapd_data *hapd, const u8 *addr, int aid,
298
+			int val)
299
+{
300
+	const char *bridge = NULL;
301
+
302
+	if (hapd->driver == NULL || hapd->driver->set_wds_sta == NULL)
303
+		return 0;
304
+	if (hapd->conf->wds_bridge[0])
305
+		bridge = hapd->conf->wds_bridge;
306
+	else if (hapd->conf->bridge[0])
307
+		bridge = hapd->conf->bridge;
308
+	return hapd->driver->set_wds_sta(hapd->drv_priv, addr, aid, val,
309
+					 bridge);
310
+}
311
+
312
+
313
+int hostapd_sta_add(struct hostapd_data *hapd,
314
+		    const u8 *addr, u16 aid, u16 capability,
315
+		    const u8 *supp_rates, size_t supp_rates_len,
316
+		    u16 listen_interval,
317
+		    const struct ieee80211_ht_capabilities *ht_capab)
318
+{
319
+	struct hostapd_sta_add_params params;
320
+
321
+	if (hapd->driver == NULL)
322
+		return 0;
323
+	if (hapd->driver->sta_add == NULL)
324
+		return 0;
325
+
326
+	os_memset(&params, 0, sizeof(params));
327
+	params.addr = addr;
328
+	params.aid = aid;
329
+	params.capability = capability;
330
+	params.supp_rates = supp_rates;
331
+	params.supp_rates_len = supp_rates_len;
332
+	params.listen_interval = listen_interval;
333
+	params.ht_capabilities = ht_capab;
334
+	return hapd->driver->sta_add(hapd->drv_priv, &params);
335
+}
336
+
337
+
338
+int hostapd_set_privacy(struct hostapd_data *hapd, int enabled)
339
+{
340
+	if (hapd->driver == NULL || hapd->driver->set_privacy == NULL)
341
+		return 0;
342
+	return hapd->driver->set_privacy(hapd->drv_priv, enabled);
343
+}
344
+
345
+
346
+int hostapd_set_generic_elem(struct hostapd_data *hapd, const u8 *elem,
347
+			     size_t elem_len)
348
+{
349
+	if (hapd->driver == NULL || hapd->driver->set_generic_elem == NULL)
350
+		return 0;
351
+	return hapd->driver->set_generic_elem(hapd->drv_priv, elem, elem_len);
352
+}
353
+
354
+
355
+int hostapd_get_ssid(struct hostapd_data *hapd, u8 *buf, size_t len)
356
+{
357
+	if (hapd->driver == NULL || hapd->driver->hapd_get_ssid == NULL)
358
+		return 0;
359
+	return hapd->driver->hapd_get_ssid(hapd->drv_priv, buf, len);
360
+}
361
+
362
+
363
+int hostapd_set_ssid(struct hostapd_data *hapd, const u8 *buf, size_t len)
364
+{
365
+	if (hapd->driver == NULL || hapd->driver->hapd_set_ssid == NULL)
366
+		return 0;
367
+	return hapd->driver->hapd_set_ssid(hapd->drv_priv, buf, len);
368
+}
369
+
370
+
371
+int hostapd_if_add(struct hostapd_data *hapd, enum wpa_driver_if_type type,
372
+		   const char *ifname, const u8 *addr, void *bss_ctx,
373
+		   void **drv_priv, char *force_ifname, u8 *if_addr,
374
+		   const char *bridge)
375
+{
376
+	if (hapd->driver == NULL || hapd->driver->if_add == NULL)
377
+		return -1;
378
+	return hapd->driver->if_add(hapd->drv_priv, type, ifname, addr,
379
+				    bss_ctx, drv_priv, force_ifname, if_addr,
380
+				    bridge);
381
+}
382
+
383
+
384
+int hostapd_if_remove(struct hostapd_data *hapd, enum wpa_driver_if_type type,
385
+		      const char *ifname)
386
+{
387
+	if (hapd->driver == NULL || hapd->driver->if_remove == NULL)
388
+		return -1;
389
+	return hapd->driver->if_remove(hapd->drv_priv, type, ifname);
390
+}
391
+
392
+
393
+int hostapd_set_ieee8021x(struct hostapd_data *hapd,
394
+			  struct wpa_bss_params *params)
395
+{
396
+	if (hapd->driver == NULL || hapd->driver->set_ieee8021x == NULL)
397
+		return 0;
398
+	return hapd->driver->set_ieee8021x(hapd->drv_priv, params);
399
+}
400
+
401
+
402
+int hostapd_get_seqnum(const char *ifname, struct hostapd_data *hapd,
403
+		       const u8 *addr, int idx, u8 *seq)
404
+{
405
+	if (hapd->driver == NULL || hapd->driver->get_seqnum == NULL)
406
+		return 0;
407
+	return hapd->driver->get_seqnum(ifname, hapd->drv_priv, addr, idx,
408
+					seq);
409
+}
410
+
411
+
412
+int hostapd_flush(struct hostapd_data *hapd)
413
+{
414
+	if (hapd->driver == NULL || hapd->driver->flush == NULL)
415
+		return 0;
416
+	return hapd->driver->flush(hapd->drv_priv);
417
+}
418
+
419
+
420
+int hostapd_set_freq(struct hostapd_data *hapd, int mode, int freq,
421
+		     int channel, int ht_enabled, int sec_channel_offset)
422
+{
423
+	struct hostapd_freq_params data;
424
+	if (hapd->driver == NULL)
425
+		return 0;
426
+	if (hapd->driver->set_freq == NULL)
427
+		return 0;
428
+	os_memset(&data, 0, sizeof(data));
429
+	data.mode = mode;
430
+	data.freq = freq;
431
+	data.channel = channel;
432
+	data.ht_enabled = ht_enabled;
433
+	data.sec_channel_offset = sec_channel_offset;
434
+	return hapd->driver->set_freq(hapd->drv_priv, &data);
435
+}
436
+
437
+int hostapd_set_rts(struct hostapd_data *hapd, int rts)
438
+{
439
+	if (hapd->driver == NULL || hapd->driver->set_rts == NULL)
440
+		return 0;
441
+	return hapd->driver->set_rts(hapd->drv_priv, rts);
442
+}
443
+
444
+
445
+int hostapd_set_frag(struct hostapd_data *hapd, int frag)
446
+{
447
+	if (hapd->driver == NULL || hapd->driver->set_frag == NULL)
448
+		return 0;
449
+	return hapd->driver->set_frag(hapd->drv_priv, frag);
450
+}
451
+
452
+
453
+int hostapd_sta_set_flags(struct hostapd_data *hapd, u8 *addr,
454
+			  int total_flags, int flags_or, int flags_and)
455
+{
456
+	if (hapd->driver == NULL || hapd->driver->sta_set_flags == NULL)
457
+		return 0;
458
+	return hapd->driver->sta_set_flags(hapd->drv_priv, addr, total_flags,
459
+					   flags_or, flags_and);
460
+}
461
+
462
+
463
+int hostapd_set_rate_sets(struct hostapd_data *hapd, int *supp_rates,
464
+			  int *basic_rates, int mode)
465
+{
466
+	if (hapd->driver == NULL || hapd->driver->set_rate_sets == NULL)
467
+		return 0;
468
+	return hapd->driver->set_rate_sets(hapd->drv_priv, supp_rates,
469
+					   basic_rates, mode);
470
+}
471
+
472
+
473
+int hostapd_set_country(struct hostapd_data *hapd, const char *country)
474
+{
475
+	if (hapd->driver == NULL ||
476
+	    hapd->driver->set_country == NULL)
477
+		return 0;
478
+	return hapd->driver->set_country(hapd->drv_priv, country);
479
+}
480
+
481
+
482
+int hostapd_set_cts_protect(struct hostapd_data *hapd, int value)
483
+{
484
+	if (hapd->driver == NULL || hapd->driver->set_cts_protect == NULL)
485
+		return 0;
486
+	return hapd->driver->set_cts_protect(hapd->drv_priv, value);
487
+}
488
+
489
+
490
+int hostapd_set_preamble(struct hostapd_data *hapd, int value)
491
+{
492
+	if (hapd->driver == NULL || hapd->driver->set_preamble == NULL)
493
+		return 0;
494
+	return hapd->driver->set_preamble(hapd->drv_priv, value);
495
+}
496
+
497
+
498
+int hostapd_set_short_slot_time(struct hostapd_data *hapd, int value)
499
+{
500
+	if (hapd->driver == NULL || hapd->driver->set_short_slot_time == NULL)
501
+		return 0;
502
+	return hapd->driver->set_short_slot_time(hapd->drv_priv, value);
503
+}
504
+
505
+
506
+int hostapd_set_tx_queue_params(struct hostapd_data *hapd, int queue, int aifs,
507
+				int cw_min, int cw_max, int burst_time)
508
+{
509
+	if (hapd->driver == NULL || hapd->driver->set_tx_queue_params == NULL)
510
+		return 0;
511
+	return hapd->driver->set_tx_queue_params(hapd->drv_priv, queue, aifs,
512
+						 cw_min, cw_max, burst_time);
513
+}
514
+
515
+
516
+int hostapd_valid_bss_mask(struct hostapd_data *hapd, const u8 *addr,
517
+			   const u8 *mask)
518
+{
519
+	if (hapd->driver == NULL || hapd->driver->valid_bss_mask == NULL)
520
+		return 1;
521
+	return hapd->driver->valid_bss_mask(hapd->drv_priv, addr, mask);
522
+}
523
+
524
+
525
+struct hostapd_hw_modes *
526
+hostapd_get_hw_feature_data(struct hostapd_data *hapd, u16 *num_modes,
527
+			    u16 *flags)
528
+{
529
+	if (hapd->driver == NULL ||
530
+	    hapd->driver->get_hw_feature_data == NULL)
531
+		return NULL;
532
+	return hapd->driver->get_hw_feature_data(hapd->drv_priv, num_modes,
533
+						 flags);
534
+}
535
+
536
+
537
+int hostapd_driver_commit(struct hostapd_data *hapd)
538
+{
539
+	if (hapd->driver == NULL || hapd->driver->commit == NULL)
540
+		return 0;
541
+	return hapd->driver->commit(hapd->drv_priv);
542
+}
543
+
544
+
545
+int hostapd_set_ht_params(struct hostapd_data *hapd,
546
+			  const u8 *ht_capab, size_t ht_capab_len,
547
+			  const u8 *ht_oper, size_t ht_oper_len)
548
+{
549
+	if (hapd->driver == NULL || hapd->driver->set_ht_params == NULL ||
550
+	    ht_capab == NULL || ht_oper == NULL)
551
+		return 0;
552
+	return hapd->driver->set_ht_params(hapd->drv_priv,
553
+					   ht_capab, ht_capab_len,
554
+					   ht_oper, ht_oper_len);
555
+}
556
+
557
+
558
+int hostapd_drv_none(struct hostapd_data *hapd)
559
+{
560
+	return hapd->driver && os_strcmp(hapd->driver->name, "none") == 0;
561
+}
562
+
563
+
564
+int hostapd_driver_scan(struct hostapd_data *hapd,
565
+			struct wpa_driver_scan_params *params)
566
+{
567
+	if (hapd->driver && hapd->driver->scan2)
568
+		return hapd->driver->scan2(hapd->drv_priv, params);
569
+	return -1;
570
+}
571
+
572
+
573
+struct wpa_scan_results * hostapd_driver_get_scan_results(
574
+	struct hostapd_data *hapd)
575
+{
576
+	if (hapd->driver && hapd->driver->get_scan_results2)
577
+		return hapd->driver->get_scan_results2(hapd->drv_priv);
578
+	return NULL;
579
+}
580
+
581
+
582
+int hostapd_driver_set_noa(struct hostapd_data *hapd, u8 count, int start,
583
+			   int duration)
584
+{
585
+	if (hapd->driver && hapd->driver->set_noa)
586
+		return hapd->driver->set_noa(hapd->drv_priv, count, start,
587
+					     duration);
588
+	return -1;
589
+}
590
+
591
+
592
+int hostapd_drv_set_key(const char *ifname, struct hostapd_data *hapd,
593
+			enum wpa_alg alg, const u8 *addr,
594
+			int key_idx, int set_tx,
595
+			const u8 *seq, size_t seq_len,
596
+			const u8 *key, size_t key_len)
597
+{
598
+	if (hapd->driver == NULL || hapd->driver->set_key == NULL)
599
+		return 0;
600
+	return hapd->driver->set_key(ifname, hapd->drv_priv, alg, addr,
601
+				     key_idx, set_tx, seq, seq_len, key,
602
+				     key_len);
603
+}
604
+
605
+
606
+int hostapd_drv_send_mlme(struct hostapd_data *hapd,
607
+			  const void *msg, size_t len)
608
+{
609
+	if (hapd->driver == NULL || hapd->driver->send_mlme == NULL)
610
+		return 0;
611
+	return hapd->driver->send_mlme(hapd->drv_priv, msg, len);
612
+}
613
+
614
+
615
+int hostapd_drv_sta_deauth(struct hostapd_data *hapd,
616
+			   const u8 *addr, int reason)
617
+{
618
+	if (hapd->driver == NULL || hapd->driver->sta_deauth == NULL)
619
+		return 0;
620
+	return hapd->driver->sta_deauth(hapd->drv_priv, hapd->own_addr, addr,
621
+					reason);
622
+}
623
+
624
+
625
+int hostapd_drv_sta_disassoc(struct hostapd_data *hapd,
626
+			     const u8 *addr, int reason)
627
+{
628
+	if (hapd->driver == NULL || hapd->driver->sta_disassoc == NULL)
629
+		return 0;
630
+	return hapd->driver->sta_disassoc(hapd->drv_priv, hapd->own_addr, addr,
631
+					  reason);
632
+}

+ 197
- 0
src/ap/ap_drv_ops.h Näytä tiedosto

@@ -0,0 +1,197 @@
1
+/*
2
+ * hostapd - Driver operations
3
+ * Copyright (c) 2009, Jouni Malinen <j@w1.fi>
4
+ *
5
+ * This program is free software; you can redistribute it and/or modify
6
+ * it under the terms of the GNU General Public License version 2 as
7
+ * published by the Free Software Foundation.
8
+ *
9
+ * Alternatively, this software may be distributed under the terms of BSD
10
+ * license.
11
+ *
12
+ * See README and COPYING for more details.
13
+ */
14
+
15
+#ifndef AP_DRV_OPS
16
+#define AP_DRV_OPS
17
+
18
+enum wpa_driver_if_type;
19
+struct wpa_bss_params;
20
+struct wpa_driver_scan_params;
21
+struct ieee80211_ht_capabilities;
22
+
23
+u32 hostapd_sta_flags_to_drv(u32 flags);
24
+int hostapd_set_ap_wps_ie(struct hostapd_data *hapd);
25
+int hostapd_set_authorized(struct hostapd_data *hapd,
26
+			   struct sta_info *sta, int authorized);
27
+int hostapd_set_sta_flags(struct hostapd_data *hapd, struct sta_info *sta);
28
+int hostapd_set_drv_ieee8021x(struct hostapd_data *hapd, const char *ifname,
29
+			      int enabled);
30
+int hostapd_set_bss_params(struct hostapd_data *hapd, int use_protection);
31
+int hostapd_vlan_if_add(struct hostapd_data *hapd, const char *ifname);
32
+int hostapd_vlan_if_remove(struct hostapd_data *hapd, const char *ifname);
33
+int hostapd_set_wds_sta(struct hostapd_data *hapd, const u8 *addr, int aid,
34
+			int val);
35
+int hostapd_sta_add(struct hostapd_data *hapd,
36
+		    const u8 *addr, u16 aid, u16 capability,
37
+		    const u8 *supp_rates, size_t supp_rates_len,
38
+		    u16 listen_interval,
39
+		    const struct ieee80211_ht_capabilities *ht_capab);
40
+int hostapd_set_privacy(struct hostapd_data *hapd, int enabled);
41
+int hostapd_set_generic_elem(struct hostapd_data *hapd, const u8 *elem,
42
+			     size_t elem_len);
43
+int hostapd_get_ssid(struct hostapd_data *hapd, u8 *buf, size_t len);
44
+int hostapd_set_ssid(struct hostapd_data *hapd, const u8 *buf, size_t len);
45
+int hostapd_if_add(struct hostapd_data *hapd, enum wpa_driver_if_type type,
46
+		   const char *ifname, const u8 *addr, void *bss_ctx,
47
+		   void **drv_priv, char *force_ifname, u8 *if_addr,
48
+		   const char *bridge);
49
+int hostapd_if_remove(struct hostapd_data *hapd, enum wpa_driver_if_type type,
50
+		      const char *ifname);
51
+int hostapd_set_ieee8021x(struct hostapd_data *hapd,
52
+			  struct wpa_bss_params *params);
53
+int hostapd_get_seqnum(const char *ifname, struct hostapd_data *hapd,
54
+		       const u8 *addr, int idx, u8 *seq);
55
+int hostapd_flush(struct hostapd_data *hapd);
56
+int hostapd_set_freq(struct hostapd_data *hapd, int mode, int freq,
57
+		     int channel, int ht_enabled, int sec_channel_offset);
58
+int hostapd_set_rts(struct hostapd_data *hapd, int rts);
59
+int hostapd_set_frag(struct hostapd_data *hapd, int frag);
60
+int hostapd_sta_set_flags(struct hostapd_data *hapd, u8 *addr,
61
+			  int total_flags, int flags_or, int flags_and);
62
+int hostapd_set_rate_sets(struct hostapd_data *hapd, int *supp_rates,
63
+			  int *basic_rates, int mode);
64
+int hostapd_set_country(struct hostapd_data *hapd, const char *country);
65
+int hostapd_set_cts_protect(struct hostapd_data *hapd, int value);
66
+int hostapd_set_preamble(struct hostapd_data *hapd, int value);
67
+int hostapd_set_short_slot_time(struct hostapd_data *hapd, int value);
68
+int hostapd_set_tx_queue_params(struct hostapd_data *hapd, int queue, int aifs,
69
+				int cw_min, int cw_max, int burst_time);
70
+int hostapd_valid_bss_mask(struct hostapd_data *hapd, const u8 *addr,
71
+			   const u8 *mask);
72
+struct hostapd_hw_modes *
73
+hostapd_get_hw_feature_data(struct hostapd_data *hapd, u16 *num_modes,
74
+			    u16 *flags);
75
+int hostapd_driver_commit(struct hostapd_data *hapd);
76
+int hostapd_set_ht_params(struct hostapd_data *hapd,
77
+			  const u8 *ht_capab, size_t ht_capab_len,
78
+			  const u8 *ht_oper, size_t ht_oper_len);
79
+int hostapd_drv_none(struct hostapd_data *hapd);
80
+int hostapd_driver_scan(struct hostapd_data *hapd,
81
+			struct wpa_driver_scan_params *params);
82
+struct wpa_scan_results * hostapd_driver_get_scan_results(
83
+	struct hostapd_data *hapd);
84
+int hostapd_driver_set_noa(struct hostapd_data *hapd, u8 count, int start,
85
+			   int duration);
86
+int hostapd_drv_set_key(const char *ifname,
87
+			struct hostapd_data *hapd,
88
+			enum wpa_alg alg, const u8 *addr,
89
+			int key_idx, int set_tx,
90
+			const u8 *seq, size_t seq_len,
91
+			const u8 *key, size_t key_len);
92
+int hostapd_drv_send_mlme(struct hostapd_data *hapd,
93
+			  const void *msg, size_t len);
94
+int hostapd_drv_sta_deauth(struct hostapd_data *hapd,
95
+			   const u8 *addr, int reason);
96
+int hostapd_drv_sta_disassoc(struct hostapd_data *hapd,
97
+			     const u8 *addr, int reason);
98
+
99
+
100
+#include "drivers/driver.h"
101
+
102
+static inline int hostapd_drv_set_countermeasures(struct hostapd_data *hapd,
103
+						  int enabled)
104
+{
105
+	if (hapd->driver == NULL ||
106
+	    hapd->driver->hapd_set_countermeasures == NULL)
107
+		return 0;
108
+	return hapd->driver->hapd_set_countermeasures(hapd->drv_priv, enabled);
109
+}
110
+
111
+static inline int hostapd_drv_set_sta_vlan(const char *ifname,
112
+					   struct hostapd_data *hapd,
113
+					   const u8 *addr, int vlan_id)
114
+{
115
+	if (hapd->driver == NULL || hapd->driver->set_sta_vlan == NULL)
116
+		return 0;
117
+	return hapd->driver->set_sta_vlan(hapd->drv_priv, addr, ifname,
118
+					  vlan_id);
119
+}
120
+
121
+static inline int hostapd_drv_get_inact_sec(struct hostapd_data *hapd,
122
+					    const u8 *addr)
123
+{
124
+	if (hapd->driver == NULL || hapd->driver->get_inact_sec == NULL)
125
+		return 0;
126
+	return hapd->driver->get_inact_sec(hapd->drv_priv, addr);
127
+}
128
+
129
+static inline int hostapd_drv_sta_remove(struct hostapd_data *hapd,
130
+					 const u8 *addr)
131
+{
132
+	if (hapd->driver == NULL || hapd->driver->sta_remove == NULL)
133
+		return 0;
134
+	return hapd->driver->sta_remove(hapd->drv_priv, addr);
135
+}
136
+
137
+static inline int hostapd_drv_hapd_send_eapol(struct hostapd_data *hapd,
138
+					      const u8 *addr, const u8 *data,
139
+					      size_t data_len, int encrypt,
140
+					      u32 flags)
141
+{
142
+	if (hapd->driver == NULL || hapd->driver->hapd_send_eapol == NULL)
143
+		return 0;
144
+	return hapd->driver->hapd_send_eapol(hapd->drv_priv, addr, data,
145
+					     data_len, encrypt,
146
+					     hapd->own_addr, flags);
147
+}
148
+
149
+static inline int hostapd_drv_read_sta_data(
150
+	struct hostapd_data *hapd, struct hostap_sta_driver_data *data,
151
+	const u8 *addr)
152
+{
153
+	if (hapd->driver == NULL || hapd->driver->read_sta_data == NULL)
154
+		return -1;
155
+	return hapd->driver->read_sta_data(hapd->drv_priv, data, addr);
156
+}
157
+
158
+static inline int hostapd_drv_sta_clear_stats(struct hostapd_data *hapd,
159
+					      const u8 *addr)
160
+{
161
+	if (hapd->driver == NULL || hapd->driver->sta_clear_stats == NULL)
162
+		return 0;
163
+	return hapd->driver->sta_clear_stats(hapd->drv_priv, addr);
164
+}
165
+
166
+static inline int hostapd_drv_set_beacon(struct hostapd_data *hapd,
167
+					 const u8 *head, size_t head_len,
168
+					 const u8 *tail, size_t tail_len,
169
+					 int dtim_period, int beacon_int)
170
+{
171
+	if (hapd->driver == NULL || hapd->driver->set_beacon == NULL)
172
+		return 0;
173
+	return hapd->driver->set_beacon(hapd->drv_priv,
174
+					head, head_len, tail, tail_len,
175
+					dtim_period, beacon_int);
176
+}
177
+
178
+static inline int hostapd_drv_set_radius_acl_auth(struct hostapd_data *hapd,
179
+						  const u8 *mac, int accepted,
180
+						  u32 session_timeout)
181
+{
182
+	if (hapd->driver == NULL || hapd->driver->set_radius_acl_auth == NULL)
183
+		return 0;
184
+	return hapd->driver->set_radius_acl_auth(hapd->drv_priv, mac, accepted,
185
+						 session_timeout);
186
+}
187
+
188
+static inline int hostapd_drv_set_radius_acl_expire(struct hostapd_data *hapd,
189
+						    const u8 *mac)
190
+{
191
+	if (hapd->driver == NULL ||
192
+	    hapd->driver->set_radius_acl_expire == NULL)
193
+		return 0;
194
+	return hapd->driver->set_radius_acl_expire(hapd->drv_priv, mac);
195
+}
196
+
197
+#endif /* AP_DRV_OPS */

+ 399
- 0
src/ap/ap_list.c Näytä tiedosto

@@ -0,0 +1,399 @@
1
+/*
2
+ * hostapd / AP table
3
+ * Copyright (c) 2002-2009, Jouni Malinen <j@w1.fi>
4
+ * Copyright (c) 2003-2004, Instant802 Networks, Inc.
5
+ * Copyright (c) 2006, Devicescape Software, Inc.
6
+ *
7
+ * This program is free software; you can redistribute it and/or modify
8
+ * it under the terms of the GNU General Public License version 2 as
9
+ * published by the Free Software Foundation.
10
+ *
11
+ * Alternatively, this software may be distributed under the terms of BSD
12
+ * license.
13
+ *
14
+ * See README and COPYING for more details.
15
+ */
16
+
17
+#include "utils/includes.h"
18
+
19
+#include "utils/common.h"
20
+#include "utils/eloop.h"
21
+#include "common/ieee802_11_defs.h"
22
+#include "common/ieee802_11_common.h"
23
+#include "drivers/driver.h"
24
+#include "hostapd.h"
25
+#include "ap_config.h"
26
+#include "ieee802_11.h"
27
+#include "sta_info.h"
28
+#include "beacon.h"
29
+#include "ap_list.h"
30
+
31
+
32
+/* AP list is a double linked list with head->prev pointing to the end of the
33
+ * list and tail->next = NULL. Entries are moved to the head of the list
34
+ * whenever a beacon has been received from the AP in question. The tail entry
35
+ * in this link will thus be the least recently used entry. */
36
+
37
+
38
+static int ap_list_beacon_olbc(struct hostapd_iface *iface, struct ap_info *ap)
39
+{
40
+	int i;
41
+
42
+	if (iface->current_mode->mode != HOSTAPD_MODE_IEEE80211G ||
43
+	    iface->conf->channel != ap->channel)
44
+		return 0;
45
+
46
+	if (ap->erp != -1 && (ap->erp & ERP_INFO_NON_ERP_PRESENT))
47
+		return 1;
48
+
49
+	for (i = 0; i < WLAN_SUPP_RATES_MAX; i++) {
50
+		int rate = (ap->supported_rates[i] & 0x7f) * 5;
51
+		if (rate == 60 || rate == 90 || rate > 110)
52
+			return 0;
53
+	}
54
+
55
+	return 1;
56
+}
57
+
58
+
59
+struct ap_info * ap_get_ap(struct hostapd_iface *iface, const u8 *ap)
60
+{
61
+	struct ap_info *s;
62
+
63
+	s = iface->ap_hash[STA_HASH(ap)];
64
+	while (s != NULL && os_memcmp(s->addr, ap, ETH_ALEN) != 0)
65
+		s = s->hnext;
66
+	return s;
67
+}
68
+
69
+
70
+static void ap_ap_list_add(struct hostapd_iface *iface, struct ap_info *ap)
71
+{
72
+	if (iface->ap_list) {
73
+		ap->prev = iface->ap_list->prev;
74
+		iface->ap_list->prev = ap;
75
+	} else
76
+		ap->prev = ap;
77
+	ap->next = iface->ap_list;
78
+	iface->ap_list = ap;
79
+}
80
+
81
+
82
+static void ap_ap_list_del(struct hostapd_iface *iface, struct ap_info *ap)
83
+{
84
+	if (iface->ap_list == ap)
85
+		iface->ap_list = ap->next;
86
+	else
87
+		ap->prev->next = ap->next;
88
+
89
+	if (ap->next)
90
+		ap->next->prev = ap->prev;
91
+	else if (iface->ap_list)
92
+		iface->ap_list->prev = ap->prev;
93
+}
94
+
95
+
96
+static void ap_ap_iter_list_add(struct hostapd_iface *iface,
97
+				struct ap_info *ap)
98
+{
99
+	if (iface->ap_iter_list) {
100
+		ap->iter_prev = iface->ap_iter_list->iter_prev;
101
+		iface->ap_iter_list->iter_prev = ap;
102
+	} else
103
+		ap->iter_prev = ap;
104
+	ap->iter_next = iface->ap_iter_list;
105
+	iface->ap_iter_list = ap;
106
+}
107
+
108
+
109
+static void ap_ap_iter_list_del(struct hostapd_iface *iface,
110
+				struct ap_info *ap)
111
+{
112
+	if (iface->ap_iter_list == ap)
113
+		iface->ap_iter_list = ap->iter_next;
114
+	else
115
+		ap->iter_prev->iter_next = ap->iter_next;
116
+
117
+	if (ap->iter_next)
118
+		ap->iter_next->iter_prev = ap->iter_prev;
119
+	else if (iface->ap_iter_list)
120
+		iface->ap_iter_list->iter_prev = ap->iter_prev;
121
+}
122
+
123
+
124
+static void ap_ap_hash_add(struct hostapd_iface *iface, struct ap_info *ap)
125
+{
126
+	ap->hnext = iface->ap_hash[STA_HASH(ap->addr)];
127
+	iface->ap_hash[STA_HASH(ap->addr)] = ap;
128
+}
129
+
130
+
131
+static void ap_ap_hash_del(struct hostapd_iface *iface, struct ap_info *ap)
132
+{
133
+	struct ap_info *s;
134
+
135
+	s = iface->ap_hash[STA_HASH(ap->addr)];
136
+	if (s == NULL) return;
137
+	if (os_memcmp(s->addr, ap->addr, ETH_ALEN) == 0) {
138
+		iface->ap_hash[STA_HASH(ap->addr)] = s->hnext;
139
+		return;
140
+	}
141
+
142
+	while (s->hnext != NULL &&
143
+	       os_memcmp(s->hnext->addr, ap->addr, ETH_ALEN) != 0)
144
+		s = s->hnext;
145
+	if (s->hnext != NULL)
146
+		s->hnext = s->hnext->hnext;
147
+	else
148
+		printf("AP: could not remove AP " MACSTR " from hash table\n",
149
+		       MAC2STR(ap->addr));
150
+}
151
+
152
+
153
+static void ap_free_ap(struct hostapd_iface *iface, struct ap_info *ap)
154
+{
155
+	ap_ap_hash_del(iface, ap);
156
+	ap_ap_list_del(iface, ap);
157
+	ap_ap_iter_list_del(iface, ap);
158
+
159
+	iface->num_ap--;
160
+	os_free(ap);
161
+}
162
+
163
+
164
+static void hostapd_free_aps(struct hostapd_iface *iface)
165
+{
166
+	struct ap_info *ap, *prev;
167
+
168
+	ap = iface->ap_list;
169
+
170
+	while (ap) {
171
+		prev = ap;
172
+		ap = ap->next;
173
+		ap_free_ap(iface, prev);
174
+	}
175
+
176
+	iface->ap_list = NULL;
177
+}
178
+
179
+
180
+int ap_ap_for_each(struct hostapd_iface *iface,
181
+		   int (*func)(struct ap_info *s, void *data), void *data)
182
+{
183
+	struct ap_info *s;
184
+	int ret = 0;
185
+
186
+	s = iface->ap_list;
187
+
188
+	while (s) {
189
+		ret = func(s, data);
190
+		if (ret)
191
+			break;
192
+		s = s->next;
193
+	}
194
+
195
+	return ret;
196
+}
197
+
198
+
199
+static struct ap_info * ap_ap_add(struct hostapd_iface *iface, const u8 *addr)
200
+{
201
+	struct ap_info *ap;
202
+
203
+	ap = os_zalloc(sizeof(struct ap_info));
204
+	if (ap == NULL)
205
+		return NULL;
206
+
207
+	/* initialize AP info data */
208
+	os_memcpy(ap->addr, addr, ETH_ALEN);
209
+	ap_ap_list_add(iface, ap);
210
+	iface->num_ap++;
211
+	ap_ap_hash_add(iface, ap);
212
+	ap_ap_iter_list_add(iface, ap);
213
+
214
+	if (iface->num_ap > iface->conf->ap_table_max_size && ap != ap->prev) {
215
+		wpa_printf(MSG_DEBUG, "Removing the least recently used AP "
216
+			   MACSTR " from AP table", MAC2STR(ap->prev->addr));
217
+		ap_free_ap(iface, ap->prev);
218
+	}
219
+
220
+	return ap;
221
+}
222
+
223
+
224
+void ap_list_process_beacon(struct hostapd_iface *iface,
225
+			    const struct ieee80211_mgmt *mgmt,
226
+			    struct ieee802_11_elems *elems,
227
+			    struct hostapd_frame_info *fi)
228
+{
229
+	struct ap_info *ap;
230
+	struct os_time now;
231
+	int new_ap = 0;
232
+	size_t len;
233
+	int set_beacon = 0;
234
+
235
+	if (iface->conf->ap_table_max_size < 1)
236
+		return;
237
+
238
+	ap = ap_get_ap(iface, mgmt->bssid);
239
+	if (!ap) {
240
+		ap = ap_ap_add(iface, mgmt->bssid);
241
+		if (!ap) {
242
+			printf("Failed to allocate AP information entry\n");
243
+			return;
244
+		}
245
+		new_ap = 1;
246
+	}
247
+
248
+	ap->beacon_int = le_to_host16(mgmt->u.beacon.beacon_int);
249
+	ap->capability = le_to_host16(mgmt->u.beacon.capab_info);
250
+
251
+	if (elems->ssid) {
252
+		len = elems->ssid_len;
253
+		if (len >= sizeof(ap->ssid))
254
+			len = sizeof(ap->ssid) - 1;
255
+		os_memcpy(ap->ssid, elems->ssid, len);
256
+		ap->ssid[len] = '\0';
257
+		ap->ssid_len = len;
258
+	}
259
+
260
+	os_memset(ap->supported_rates, 0, WLAN_SUPP_RATES_MAX);
261
+	len = 0;
262
+	if (elems->supp_rates) {
263
+		len = elems->supp_rates_len;
264
+		if (len > WLAN_SUPP_RATES_MAX)
265
+			len = WLAN_SUPP_RATES_MAX;
266
+		os_memcpy(ap->supported_rates, elems->supp_rates, len);
267
+	}
268
+	if (elems->ext_supp_rates) {
269
+		int len2;
270
+		if (len + elems->ext_supp_rates_len > WLAN_SUPP_RATES_MAX)
271
+			len2 = WLAN_SUPP_RATES_MAX - len;
272
+		else
273
+			len2 = elems->ext_supp_rates_len;
274
+		os_memcpy(ap->supported_rates + len, elems->ext_supp_rates,
275
+			  len2);
276
+	}
277
+
278
+	ap->wpa = elems->wpa_ie != NULL;
279
+
280
+	if (elems->erp_info && elems->erp_info_len == 1)
281
+		ap->erp = elems->erp_info[0];
282
+	else
283
+		ap->erp = -1;
284
+
285
+	if (elems->ds_params && elems->ds_params_len == 1)
286
+		ap->channel = elems->ds_params[0];
287
+	else if (fi)
288
+		ap->channel = fi->channel;
289
+
290
+	if (elems->ht_capabilities)
291
+		ap->ht_support = 1;
292
+	else
293
+		ap->ht_support = 0;
294
+
295
+	ap->num_beacons++;
296
+	os_get_time(&now);
297
+	ap->last_beacon = now.sec;
298
+	if (fi) {
299
+		ap->ssi_signal = fi->ssi_signal;
300
+		ap->datarate = fi->datarate;
301
+	}
302
+
303
+	if (!new_ap && ap != iface->ap_list) {
304
+		/* move AP entry into the beginning of the list so that the
305
+		 * oldest entry is always in the end of the list */
306
+		ap_ap_list_del(iface, ap);
307
+		ap_ap_list_add(iface, ap);
308
+	}
309
+
310
+	if (!iface->olbc &&
311
+	    ap_list_beacon_olbc(iface, ap)) {
312
+		iface->olbc = 1;
313
+		wpa_printf(MSG_DEBUG, "OLBC AP detected: " MACSTR " - enable "
314
+			   "protection", MAC2STR(ap->addr));
315
+		set_beacon++;
316
+	}
317
+
318
+#ifdef CONFIG_IEEE80211N
319
+	if (!iface->olbc_ht && !ap->ht_support) {
320
+		iface->olbc_ht = 1;
321
+		hostapd_ht_operation_update(iface);
322
+		wpa_printf(MSG_DEBUG, "OLBC HT AP detected: " MACSTR
323
+			   " - enable protection", MAC2STR(ap->addr));
324
+		set_beacon++;
325
+	}
326
+#endif /* CONFIG_IEEE80211N */
327
+
328
+	if (set_beacon)
329
+		ieee802_11_set_beacons(iface);
330
+}
331
+
332
+
333
+static void ap_list_timer(void *eloop_ctx, void *timeout_ctx)
334
+{
335
+	struct hostapd_iface *iface = eloop_ctx;
336
+	struct os_time now;
337
+	struct ap_info *ap;
338
+	int set_beacon = 0;
339
+
340
+	eloop_register_timeout(10, 0, ap_list_timer, iface, NULL);
341
+
342
+	if (!iface->ap_list)
343
+		return;
344
+
345
+	os_get_time(&now);
346
+
347
+	while (iface->ap_list) {
348
+		ap = iface->ap_list->prev;
349
+		if (ap->last_beacon + iface->conf->ap_table_expiration_time >=
350
+		    now.sec)
351
+			break;
352
+
353
+		ap_free_ap(iface, ap);
354
+	}
355
+
356
+	if (iface->olbc || iface->olbc_ht) {
357
+		int olbc = 0;
358
+		int olbc_ht = 0;
359
+
360
+		ap = iface->ap_list;
361
+		while (ap && (olbc == 0 || olbc_ht == 0)) {
362
+			if (ap_list_beacon_olbc(iface, ap))
363
+				olbc = 1;
364
+			if (!ap->ht_support)
365
+				olbc_ht = 1;
366
+			ap = ap->next;
367
+		}
368
+		if (!olbc && iface->olbc) {
369
+			wpa_printf(MSG_DEBUG, "OLBC not detected anymore");
370
+			iface->olbc = 0;
371
+			set_beacon++;
372
+		}
373
+#ifdef CONFIG_IEEE80211N
374
+		if (!olbc_ht && iface->olbc_ht) {
375
+			wpa_printf(MSG_DEBUG, "OLBC HT not detected anymore");
376
+			iface->olbc_ht = 0;
377
+			hostapd_ht_operation_update(iface);
378
+			set_beacon++;
379
+		}
380
+#endif /* CONFIG_IEEE80211N */
381
+	}
382
+
383
+	if (set_beacon)
384
+		ieee802_11_set_beacons(iface);
385
+}
386
+
387
+
388
+int ap_list_init(struct hostapd_iface *iface)
389
+{
390
+	eloop_register_timeout(10, 0, ap_list_timer, iface, NULL);
391
+	return 0;
392
+}
393
+
394
+
395
+void ap_list_deinit(struct hostapd_iface *iface)
396
+{
397
+	eloop_cancel_timeout(ap_list_timer, iface, NULL);
398
+	hostapd_free_aps(iface);
399
+}

+ 78
- 0
src/ap/ap_list.h Näytä tiedosto

@@ -0,0 +1,78 @@
1
+/*
2
+ * hostapd / AP table
3
+ * Copyright (c) 2002-2003, Jouni Malinen <j@w1.fi>
4
+ * Copyright (c) 2003-2004, Instant802 Networks, Inc.
5
+ * Copyright (c) 2006, Devicescape Software, Inc.
6
+ *
7
+ * This program is free software; you can redistribute it and/or modify
8
+ * it under the terms of the GNU General Public License version 2 as
9
+ * published by the Free Software Foundation.
10
+ *
11
+ * Alternatively, this software may be distributed under the terms of BSD
12
+ * license.
13
+ *
14
+ * See README and COPYING for more details.
15
+ */
16
+
17
+#ifndef AP_LIST_H
18
+#define AP_LIST_H
19
+
20
+struct ap_info {
21
+	/* Note: next/prev pointers are updated whenever a new beacon is
22
+	 * received because these are used to find the least recently used
23
+	 * entries. iter_next/iter_prev are updated only when adding new BSSes
24
+	 * and when removing old ones. These should be used when iterating
25
+	 * through the table in a manner that allows beacons to be received
26
+	 * during the iteration. */
27
+	struct ap_info *next; /* next entry in AP list */
28
+	struct ap_info *prev; /* previous entry in AP list */
29
+	struct ap_info *hnext; /* next entry in hash table list */
30
+	struct ap_info *iter_next; /* next entry in AP iteration list */
31
+	struct ap_info *iter_prev; /* previous entry in AP iteration list */
32
+	u8 addr[6];
33
+	u16 beacon_int;
34
+	u16 capability;
35
+	u8 supported_rates[WLAN_SUPP_RATES_MAX];
36
+	u8 ssid[33];
37
+	size_t ssid_len;
38
+	int wpa;
39
+	int erp; /* ERP Info or -1 if ERP info element not present */
40
+
41
+	int channel;
42
+	int datarate; /* in 100 kbps */
43
+	int ssi_signal;
44
+
45
+	int ht_support;
46
+
47
+	unsigned int num_beacons; /* number of beacon frames received */
48
+	os_time_t last_beacon;
49
+
50
+	int already_seen; /* whether API call AP-NEW has already fetched
51
+			   * information about this AP */
52
+};
53
+
54
+struct ieee802_11_elems;
55
+struct hostapd_frame_info;
56
+
57
+struct ap_info * ap_get_ap(struct hostapd_iface *iface, const u8 *sta);
58
+int ap_ap_for_each(struct hostapd_iface *iface,
59
+		   int (*func)(struct ap_info *s, void *data), void *data);
60
+void ap_list_process_beacon(struct hostapd_iface *iface,
61
+			    const struct ieee80211_mgmt *mgmt,
62
+			    struct ieee802_11_elems *elems,
63
+			    struct hostapd_frame_info *fi);
64
+#ifdef NEED_AP_MLME
65
+int ap_list_init(struct hostapd_iface *iface);
66
+void ap_list_deinit(struct hostapd_iface *iface);
67
+#else /* NEED_AP_MLME */
68
+static inline int ap_list_init(struct hostapd_iface *iface)
69
+{
70
+	return 0;
71
+}
72
+
73
+static inline void ap_list_deinit(struct hostapd_iface *iface)
74
+{
75
+}
76
+#endif /* NEED_AP_MLME */
77
+
78
+#endif /* AP_LIST_H */

+ 184
- 0
src/ap/ap_mlme.c Näytä tiedosto

@@ -0,0 +1,184 @@
1
+/*
2
+ * hostapd / IEEE 802.11 MLME
3
+ * Copyright 2003-2006, Jouni Malinen <j@w1.fi>
4
+ * Copyright 2003-2004, Instant802 Networks, Inc.
5
+ * Copyright 2005-2006, Devicescape Software, Inc.
6
+ *
7
+ * This program is free software; you can redistribute it and/or modify
8
+ * it under the terms of the GNU General Public License version 2 as
9
+ * published by the Free Software Foundation.
10
+ *
11
+ * Alternatively, this software may be distributed under the terms of BSD
12
+ * license.
13
+ *
14
+ * See README and COPYING for more details.
15
+ */
16
+
17
+#include "utils/includes.h"
18
+
19
+#include "utils/common.h"
20
+#include "common/ieee802_11_defs.h"
21
+#include "ieee802_11.h"
22
+#include "wpa_auth.h"
23
+#include "sta_info.h"
24
+#include "ap_mlme.h"
25
+
26
+
27
+#ifndef CONFIG_NO_HOSTAPD_LOGGER
28
+static const char * mlme_auth_alg_str(int alg)
29
+{
30
+	switch (alg) {
31
+	case WLAN_AUTH_OPEN:
32
+		return "OPEN_SYSTEM";
33
+	case WLAN_AUTH_SHARED_KEY:
34
+		return "SHARED_KEY";
35
+	case WLAN_AUTH_FT:
36
+		return "FT";
37
+	}
38
+
39
+	return "unknown";
40
+}
41
+#endif /* CONFIG_NO_HOSTAPD_LOGGER */
42
+
43
+
44
+/**
45
+ * mlme_authenticate_indication - Report the establishment of an authentication
46
+ * relationship with a specific peer MAC entity
47
+ * @hapd: BSS data
48
+ * @sta: peer STA data
49
+ *
50
+ * MLME calls this function as a result of the establishment of an
51
+ * authentication relationship with a specific peer MAC entity that
52
+ * resulted from an authentication procedure that was initiated by
53
+ * that specific peer MAC entity.
54
+ *
55
+ * PeerSTAAddress = sta->addr
56
+ * AuthenticationType = sta->auth_alg (WLAN_AUTH_OPEN / WLAN_AUTH_SHARED_KEY)
57
+ */
58
+void mlme_authenticate_indication(struct hostapd_data *hapd,
59
+				  struct sta_info *sta)
60
+{
61
+	hostapd_logger(hapd, sta->addr, HOSTAPD_MODULE_MLME,
62
+		       HOSTAPD_LEVEL_DEBUG,
63
+		       "MLME-AUTHENTICATE.indication(" MACSTR ", %s)",
64
+		       MAC2STR(sta->addr), mlme_auth_alg_str(sta->auth_alg));
65
+	if (sta->auth_alg != WLAN_AUTH_FT && !(sta->flags & WLAN_STA_MFP))
66
+		mlme_deletekeys_request(hapd, sta);
67
+}
68
+
69
+
70
+/**
71
+ * mlme_deauthenticate_indication - Report the invalidation of an
72
+ * authentication relationship with a specific peer MAC entity
73
+ * @hapd: BSS data
74
+ * @sta: Peer STA data
75
+ * @reason_code: ReasonCode from Deauthentication frame
76
+ *
77
+ * MLME calls this function as a result of the invalidation of an
78
+ * authentication relationship with a specific peer MAC entity.
79
+ *
80
+ * PeerSTAAddress = sta->addr
81
+ */
82
+void mlme_deauthenticate_indication(struct hostapd_data *hapd,
83
+				    struct sta_info *sta, u16 reason_code)
84
+{
85
+	hostapd_logger(hapd, sta->addr, HOSTAPD_MODULE_MLME,
86
+		       HOSTAPD_LEVEL_DEBUG,
87
+		       "MLME-DEAUTHENTICATE.indication(" MACSTR ", %d)",
88
+		       MAC2STR(sta->addr), reason_code);
89
+	mlme_deletekeys_request(hapd, sta);
90
+}
91
+
92
+
93
+/**
94
+ * mlme_associate_indication - Report the establishment of an association with
95
+ * a specific peer MAC entity
96
+ * @hapd: BSS data
97
+ * @sta: peer STA data
98
+ *
99
+ * MLME calls this function as a result of the establishment of an
100
+ * association with a specific peer MAC entity that resulted from an
101
+ * association procedure that was initiated by that specific peer MAC entity.
102
+ *
103
+ * PeerSTAAddress = sta->addr
104
+ */
105
+void mlme_associate_indication(struct hostapd_data *hapd, struct sta_info *sta)
106
+{
107
+	hostapd_logger(hapd, sta->addr, HOSTAPD_MODULE_MLME,
108
+		       HOSTAPD_LEVEL_DEBUG,
109
+		       "MLME-ASSOCIATE.indication(" MACSTR ")",
110
+		       MAC2STR(sta->addr));
111
+	if (sta->auth_alg != WLAN_AUTH_FT)
112
+		mlme_deletekeys_request(hapd, sta);
113
+}
114
+
115
+
116
+/**
117
+ * mlme_reassociate_indication - Report the establishment of an reassociation
118
+ * with a specific peer MAC entity
119
+ * @hapd: BSS data
120
+ * @sta: peer STA data
121
+ *
122
+ * MLME calls this function as a result of the establishment of an
123
+ * reassociation with a specific peer MAC entity that resulted from a
124
+ * reassociation procedure that was initiated by that specific peer MAC entity.
125
+ *
126
+ * PeerSTAAddress = sta->addr
127
+ *
128
+ * sta->previous_ap contains the "Current AP" information from ReassocReq.
129
+ */
130
+void mlme_reassociate_indication(struct hostapd_data *hapd,
131
+				 struct sta_info *sta)
132
+{
133
+	hostapd_logger(hapd, sta->addr, HOSTAPD_MODULE_MLME,
134
+		       HOSTAPD_LEVEL_DEBUG,
135
+		       "MLME-REASSOCIATE.indication(" MACSTR ")",
136
+		       MAC2STR(sta->addr));
137
+	if (sta->auth_alg != WLAN_AUTH_FT)
138
+		mlme_deletekeys_request(hapd, sta);
139
+}
140
+
141
+
142
+/**
143
+ * mlme_disassociate_indication - Report disassociation with a specific peer
144
+ * MAC entity
145
+ * @hapd: BSS data
146
+ * @sta: Peer STA data
147
+ * @reason_code: ReasonCode from Disassociation frame
148
+ *
149
+ * MLME calls this function as a result of the invalidation of an association
150
+ * relationship with a specific peer MAC entity.
151
+ *
152
+ * PeerSTAAddress = sta->addr
153
+ */
154
+void mlme_disassociate_indication(struct hostapd_data *hapd,
155
+				  struct sta_info *sta, u16 reason_code)
156
+{
157
+	hostapd_logger(hapd, sta->addr, HOSTAPD_MODULE_MLME,
158
+		       HOSTAPD_LEVEL_DEBUG,
159
+		       "MLME-DISASSOCIATE.indication(" MACSTR ", %d)",
160
+		       MAC2STR(sta->addr), reason_code);
161
+	mlme_deletekeys_request(hapd, sta);
162
+}
163
+
164
+
165
+void mlme_michaelmicfailure_indication(struct hostapd_data *hapd,
166
+				       const u8 *addr)
167
+{
168
+	hostapd_logger(hapd, addr, HOSTAPD_MODULE_MLME,
169
+		       HOSTAPD_LEVEL_DEBUG,
170
+		       "MLME-MichaelMICFailure.indication(" MACSTR ")",
171
+		       MAC2STR(addr));
172
+}
173
+
174
+
175
+void mlme_deletekeys_request(struct hostapd_data *hapd, struct sta_info *sta)
176
+{
177
+	hostapd_logger(hapd, sta->addr, HOSTAPD_MODULE_MLME,
178
+		       HOSTAPD_LEVEL_DEBUG,
179
+		       "MLME-DELETEKEYS.request(" MACSTR ")",
180
+		       MAC2STR(sta->addr));
181
+
182
+	if (sta->wpa_sm)
183
+		wpa_remove_ptk(sta->wpa_sm);
184
+}

+ 40
- 0
src/ap/ap_mlme.h Näytä tiedosto

@@ -0,0 +1,40 @@
1
+/*
2
+ * hostapd / IEEE 802.11 MLME
3
+ * Copyright 2003, Jouni Malinen <j@w1.fi>
4
+ * Copyright 2003-2004, Instant802 Networks, Inc.
5
+ * Copyright 2005-2006, Devicescape Software, Inc.
6
+ *
7
+ * This program is free software; you can redistribute it and/or modify
8
+ * it under the terms of the GNU General Public License version 2 as
9
+ * published by the Free Software Foundation.
10
+ *
11
+ * Alternatively, this software may be distributed under the terms of BSD
12
+ * license.
13
+ *
14
+ * See README and COPYING for more details.
15
+ */
16
+
17
+#ifndef MLME_H
18
+#define MLME_H
19
+
20
+void mlme_authenticate_indication(struct hostapd_data *hapd,
21
+				  struct sta_info *sta);
22
+
23
+void mlme_deauthenticate_indication(struct hostapd_data *hapd,
24
+				    struct sta_info *sta, u16 reason_code);
25
+
26
+void mlme_associate_indication(struct hostapd_data *hapd,
27
+			       struct sta_info *sta);
28
+
29
+void mlme_reassociate_indication(struct hostapd_data *hapd,
30
+				 struct sta_info *sta);
31
+
32
+void mlme_disassociate_indication(struct hostapd_data *hapd,
33
+				  struct sta_info *sta, u16 reason_code);
34
+
35
+void mlme_michaelmicfailure_indication(struct hostapd_data *hapd,
36
+				       const u8 *addr);
37
+
38
+void mlme_deletekeys_request(struct hostapd_data *hapd, struct sta_info *sta);
39
+
40
+#endif /* MLME_H */

+ 217
- 0
src/ap/authsrv.c Näytä tiedosto

@@ -0,0 +1,217 @@
1
+/*
2
+ * Authentication server setup
3
+ * Copyright (c) 2002-2009, Jouni Malinen <j@w1.fi>
4
+ *
5
+ * This program is free software; you can redistribute it and/or modify
6
+ * it under the terms of the GNU General Public License version 2 as
7
+ * published by the Free Software Foundation.
8
+ *
9
+ * Alternatively, this software may be distributed under the terms of BSD
10
+ * license.
11
+ *
12
+ * See README and COPYING for more details.
13
+ */
14
+
15
+#include "utils/includes.h"
16
+
17
+#include "utils/common.h"
18
+#include "crypto/tls.h"
19
+#include "eap_server/eap.h"
20
+#include "eap_server/eap_sim_db.h"
21
+#include "eapol_auth/eapol_auth_sm.h"
22
+#include "radius/radius_server.h"
23
+#include "hostapd.h"
24
+#include "ap_config.h"
25
+#include "sta_info.h"
26
+#include "authsrv.h"
27
+
28
+
29
+#if defined(EAP_SERVER_SIM) || defined(EAP_SERVER_AKA)
30
+#define EAP_SIM_DB
31
+#endif /* EAP_SERVER_SIM || EAP_SERVER_AKA */
32
+
33
+
34
+#ifdef EAP_SIM_DB
35
+static int hostapd_sim_db_cb_sta(struct hostapd_data *hapd,
36
+				 struct sta_info *sta, void *ctx)
37
+{
38
+	if (eapol_auth_eap_pending_cb(sta->eapol_sm, ctx) == 0)
39
+		return 1;
40
+	return 0;
41
+}
42
+
43
+
44
+static void hostapd_sim_db_cb(void *ctx, void *session_ctx)
45
+{
46
+	struct hostapd_data *hapd = ctx;
47
+	if (ap_for_each_sta(hapd, hostapd_sim_db_cb_sta, session_ctx) == 0) {
48
+#ifdef RADIUS_SERVER
49
+		radius_server_eap_pending_cb(hapd->radius_srv, session_ctx);
50
+#endif /* RADIUS_SERVER */
51
+	}
52
+}
53
+#endif /* EAP_SIM_DB */
54
+
55
+
56
+#ifdef RADIUS_SERVER
57
+
58
+static int hostapd_radius_get_eap_user(void *ctx, const u8 *identity,
59
+				       size_t identity_len, int phase2,
60
+				       struct eap_user *user)
61
+{
62
+	const struct hostapd_eap_user *eap_user;
63
+	int i, count;
64
+
65
+	eap_user = hostapd_get_eap_user(ctx, identity, identity_len, phase2);
66
+	if (eap_user == NULL)
67
+		return -1;
68
+
69
+	if (user == NULL)
70
+		return 0;
71
+
72
+	os_memset(user, 0, sizeof(*user));
73
+	count = EAP_USER_MAX_METHODS;
74
+	if (count > EAP_MAX_METHODS)
75
+		count = EAP_MAX_METHODS;
76
+	for (i = 0; i < count; i++) {
77
+		user->methods[i].vendor = eap_user->methods[i].vendor;
78
+		user->methods[i].method = eap_user->methods[i].method;
79
+	}
80
+
81
+	if (eap_user->password) {
82
+		user->password = os_malloc(eap_user->password_len);
83
+		if (user->password == NULL)
84
+			return -1;
85
+		os_memcpy(user->password, eap_user->password,
86
+			  eap_user->password_len);
87
+		user->password_len = eap_user->password_len;
88
+		user->password_hash = eap_user->password_hash;
89
+	}
90
+	user->force_version = eap_user->force_version;
91
+	user->ttls_auth = eap_user->ttls_auth;
92
+
93
+	return 0;
94
+}
95
+
96
+
97
+static int hostapd_setup_radius_srv(struct hostapd_data *hapd)
98
+{
99
+	struct radius_server_conf srv;
100
+	struct hostapd_bss_config *conf = hapd->conf;
101
+	os_memset(&srv, 0, sizeof(srv));
102
+	srv.client_file = conf->radius_server_clients;
103
+	srv.auth_port = conf->radius_server_auth_port;
104
+	srv.conf_ctx = conf;
105
+	srv.eap_sim_db_priv = hapd->eap_sim_db_priv;
106
+	srv.ssl_ctx = hapd->ssl_ctx;
107
+	srv.msg_ctx = hapd->msg_ctx;
108
+	srv.pac_opaque_encr_key = conf->pac_opaque_encr_key;
109
+	srv.eap_fast_a_id = conf->eap_fast_a_id;
110
+	srv.eap_fast_a_id_len = conf->eap_fast_a_id_len;
111
+	srv.eap_fast_a_id_info = conf->eap_fast_a_id_info;
112
+	srv.eap_fast_prov = conf->eap_fast_prov;
113
+	srv.pac_key_lifetime = conf->pac_key_lifetime;
114
+	srv.pac_key_refresh_time = conf->pac_key_refresh_time;
115
+	srv.eap_sim_aka_result_ind = conf->eap_sim_aka_result_ind;
116
+	srv.tnc = conf->tnc;
117
+	srv.wps = hapd->wps;
118
+	srv.ipv6 = conf->radius_server_ipv6;
119
+	srv.get_eap_user = hostapd_radius_get_eap_user;
120
+	srv.eap_req_id_text = conf->eap_req_id_text;
121
+	srv.eap_req_id_text_len = conf->eap_req_id_text_len;
122
+	srv.pwd_group = conf->pwd_group;
123
+
124
+	hapd->radius_srv = radius_server_init(&srv);
125
+	if (hapd->radius_srv == NULL) {
126
+		wpa_printf(MSG_ERROR, "RADIUS server initialization failed.");
127
+		return -1;
128
+	}
129
+
130
+	return 0;
131
+}
132
+
133
+#endif /* RADIUS_SERVER */
134
+
135
+
136
+int authsrv_init(struct hostapd_data *hapd)
137
+{
138
+#ifdef EAP_TLS_FUNCS
139
+	if (hapd->conf->eap_server &&
140
+	    (hapd->conf->ca_cert || hapd->conf->server_cert ||
141
+	     hapd->conf->dh_file)) {
142
+		struct tls_connection_params params;
143
+
144
+		hapd->ssl_ctx = tls_init(NULL);
145
+		if (hapd->ssl_ctx == NULL) {
146
+			wpa_printf(MSG_ERROR, "Failed to initialize TLS");
147
+			authsrv_deinit(hapd);
148
+			return -1;
149
+		}
150
+
151
+		os_memset(&params, 0, sizeof(params));
152
+		params.ca_cert = hapd->conf->ca_cert;
153
+		params.client_cert = hapd->conf->server_cert;
154
+		params.private_key = hapd->conf->private_key;
155
+		params.private_key_passwd = hapd->conf->private_key_passwd;
156
+		params.dh_file = hapd->conf->dh_file;
157
+
158
+		if (tls_global_set_params(hapd->ssl_ctx, &params)) {
159
+			wpa_printf(MSG_ERROR, "Failed to set TLS parameters");
160
+			authsrv_deinit(hapd);
161
+			return -1;
162
+		}
163
+
164
+		if (tls_global_set_verify(hapd->ssl_ctx,
165
+					  hapd->conf->check_crl)) {
166
+			wpa_printf(MSG_ERROR, "Failed to enable check_crl");
167
+			authsrv_deinit(hapd);
168
+			return -1;
169
+		}
170
+	}
171
+#endif /* EAP_TLS_FUNCS */
172
+
173
+#ifdef EAP_SIM_DB
174
+	if (hapd->conf->eap_sim_db) {
175
+		hapd->eap_sim_db_priv =
176
+			eap_sim_db_init(hapd->conf->eap_sim_db,
177
+					hostapd_sim_db_cb, hapd);
178
+		if (hapd->eap_sim_db_priv == NULL) {
179
+			wpa_printf(MSG_ERROR, "Failed to initialize EAP-SIM "
180
+				   "database interface");
181
+			authsrv_deinit(hapd);
182
+			return -1;
183
+		}
184
+	}
185
+#endif /* EAP_SIM_DB */
186
+
187
+#ifdef RADIUS_SERVER
188
+	if (hapd->conf->radius_server_clients &&
189
+	    hostapd_setup_radius_srv(hapd))
190
+		return -1;
191
+#endif /* RADIUS_SERVER */
192
+
193
+	return 0;
194
+}
195
+
196
+
197
+void authsrv_deinit(struct hostapd_data *hapd)
198
+{
199
+#ifdef RADIUS_SERVER
200
+	radius_server_deinit(hapd->radius_srv);
201
+	hapd->radius_srv = NULL;
202
+#endif /* RADIUS_SERVER */
203
+
204
+#ifdef EAP_TLS_FUNCS
205
+	if (hapd->ssl_ctx) {
206
+		tls_deinit(hapd->ssl_ctx);
207
+		hapd->ssl_ctx = NULL;
208
+	}
209
+#endif /* EAP_TLS_FUNCS */
210
+
211
+#ifdef EAP_SIM_DB
212
+	if (hapd->eap_sim_db_priv) {
213
+		eap_sim_db_deinit(hapd->eap_sim_db_priv);
214
+		hapd->eap_sim_db_priv = NULL;
215
+	}
216
+#endif /* EAP_SIM_DB */
217
+}

+ 21
- 0
src/ap/authsrv.h Näytä tiedosto

@@ -0,0 +1,21 @@
1
+/*
2
+ * Authentication server setup
3
+ * Copyright (c) 2002-2009, Jouni Malinen <j@w1.fi>
4
+ *
5
+ * This program is free software; you can redistribute it and/or modify
6
+ * it under the terms of the GNU General Public License version 2 as
7
+ * published by the Free Software Foundation.
8
+ *
9
+ * Alternatively, this software may be distributed under the terms of BSD
10
+ * license.
11
+ *
12
+ * See README and COPYING for more details.
13
+ */
14
+
15
+#ifndef AUTHSRV_H
16
+#define AUTHSRV_H
17
+
18
+int authsrv_init(struct hostapd_data *hapd);
19
+void authsrv_deinit(struct hostapd_data *hapd);
20
+
21
+#endif /* AUTHSRV_H */

+ 540
- 0
src/ap/beacon.c Näytä tiedosto

@@ -0,0 +1,540 @@
1
+/*
2
+ * hostapd / IEEE 802.11 Management: Beacon and Probe Request/Response
3
+ * Copyright (c) 2002-2004, Instant802 Networks, Inc.
4
+ * Copyright (c) 2005-2006, Devicescape Software, Inc.
5
+ * Copyright (c) 2008-2009, Jouni Malinen <j@w1.fi>
6
+ *
7
+ * This program is free software; you can redistribute it and/or modify
8
+ * it under the terms of the GNU General Public License version 2 as
9
+ * published by the Free Software Foundation.
10
+ *
11
+ * Alternatively, this software may be distributed under the terms of BSD
12
+ * license.
13
+ *
14
+ * See README and COPYING for more details.
15
+ */
16
+
17
+#include "utils/includes.h"
18
+
19
+#ifndef CONFIG_NATIVE_WINDOWS
20
+
21
+#include "utils/common.h"
22
+#include "common/ieee802_11_defs.h"
23
+#include "common/ieee802_11_common.h"
24
+#include "drivers/driver.h"
25
+#include "wps/wps_defs.h"
26
+#include "p2p/p2p.h"
27
+#include "hostapd.h"
28
+#include "ieee802_11.h"
29
+#include "wpa_auth.h"
30
+#include "wmm.h"
31
+#include "ap_config.h"
32
+#include "sta_info.h"
33
+#include "p2p_hostapd.h"
34
+#include "ap_drv_ops.h"
35
+#include "beacon.h"
36
+
37
+
38
+static u8 ieee802_11_erp_info(struct hostapd_data *hapd)
39
+{
40
+	u8 erp = 0;
41
+
42
+	if (hapd->iface->current_mode == NULL ||
43
+	    hapd->iface->current_mode->mode != HOSTAPD_MODE_IEEE80211G)
44
+		return 0;
45
+
46
+	switch (hapd->iconf->cts_protection_type) {
47
+	case CTS_PROTECTION_FORCE_ENABLED:
48
+		erp |= ERP_INFO_NON_ERP_PRESENT | ERP_INFO_USE_PROTECTION;
49
+		break;
50
+	case CTS_PROTECTION_FORCE_DISABLED:
51
+		erp = 0;
52
+		break;
53
+	case CTS_PROTECTION_AUTOMATIC:
54
+		if (hapd->iface->olbc)
55
+			erp |= ERP_INFO_USE_PROTECTION;
56
+		/* continue */
57
+	case CTS_PROTECTION_AUTOMATIC_NO_OLBC:
58
+		if (hapd->iface->num_sta_non_erp > 0) {
59
+			erp |= ERP_INFO_NON_ERP_PRESENT |
60
+				ERP_INFO_USE_PROTECTION;
61
+		}
62
+		break;
63
+	}
64
+	if (hapd->iface->num_sta_no_short_preamble > 0 ||
65
+	    hapd->iconf->preamble == LONG_PREAMBLE)
66
+		erp |= ERP_INFO_BARKER_PREAMBLE_MODE;
67
+
68
+	return erp;
69
+}
70
+
71
+
72
+static u8 * hostapd_eid_ds_params(struct hostapd_data *hapd, u8 *eid)
73
+{
74
+	*eid++ = WLAN_EID_DS_PARAMS;
75
+	*eid++ = 1;
76
+	*eid++ = hapd->iconf->channel;
77
+	return eid;
78
+}
79
+
80
+
81
+static u8 * hostapd_eid_erp_info(struct hostapd_data *hapd, u8 *eid)
82
+{
83
+	if (hapd->iface->current_mode == NULL ||
84
+	    hapd->iface->current_mode->mode != HOSTAPD_MODE_IEEE80211G)
85
+		return eid;
86
+
87
+	/* Set NonERP_present and use_protection bits if there
88
+	 * are any associated NonERP stations. */
89
+	/* TODO: use_protection bit can be set to zero even if
90
+	 * there are NonERP stations present. This optimization
91
+	 * might be useful if NonERP stations are "quiet".
92
+	 * See 802.11g/D6 E-1 for recommended practice.
93
+	 * In addition, Non ERP present might be set, if AP detects Non ERP
94
+	 * operation on other APs. */
95
+
96
+	/* Add ERP Information element */
97
+	*eid++ = WLAN_EID_ERP_INFO;
98
+	*eid++ = 1;
99
+	*eid++ = ieee802_11_erp_info(hapd);
100
+
101
+	return eid;
102
+}
103
+
104
+
105
+static u8 * hostapd_eid_country_add(u8 *pos, u8 *end, int chan_spacing,
106
+				    struct hostapd_channel_data *start,
107
+				    struct hostapd_channel_data *prev)
108
+{
109
+	if (end - pos < 3)
110
+		return pos;
111
+
112
+	/* first channel number */
113
+	*pos++ = start->chan;
114
+	/* number of channels */
115
+	*pos++ = (prev->chan - start->chan) / chan_spacing + 1;
116
+	/* maximum transmit power level */
117
+	*pos++ = start->max_tx_power;
118
+
119
+	return pos;
120
+}
121
+
122
+
123
+static u8 * hostapd_eid_country(struct hostapd_data *hapd, u8 *eid,
124
+				int max_len)
125
+{
126
+	u8 *pos = eid;
127
+	u8 *end = eid + max_len;
128
+	int i;
129
+	struct hostapd_hw_modes *mode;
130
+	struct hostapd_channel_data *start, *prev;
131
+	int chan_spacing = 1;
132
+
133
+	if (!hapd->iconf->ieee80211d || max_len < 6 ||
134
+	    hapd->iface->current_mode == NULL)
135
+		return eid;
136
+
137
+	*pos++ = WLAN_EID_COUNTRY;
138
+	pos++; /* length will be set later */
139
+	os_memcpy(pos, hapd->iconf->country, 3); /* e.g., 'US ' */
140
+	pos += 3;
141
+
142
+	mode = hapd->iface->current_mode;
143
+	if (mode->mode == HOSTAPD_MODE_IEEE80211A)
144
+		chan_spacing = 4;
145
+
146
+	start = prev = NULL;
147
+	for (i = 0; i < mode->num_channels; i++) {
148
+		struct hostapd_channel_data *chan = &mode->channels[i];
149
+		if (chan->flag & HOSTAPD_CHAN_DISABLED)
150
+			continue;
151
+		if (start && prev &&
152
+		    prev->chan + chan_spacing == chan->chan &&
153
+		    start->max_tx_power == chan->max_tx_power) {
154
+			prev = chan;
155
+			continue; /* can use same entry */
156
+		}
157
+
158
+		if (start) {
159
+			pos = hostapd_eid_country_add(pos, end, chan_spacing,
160
+						      start, prev);
161
+			start = NULL;
162
+		}
163
+
164
+		/* Start new group */
165
+		start = prev = chan;
166
+	}
167
+
168
+	if (start) {
169
+		pos = hostapd_eid_country_add(pos, end, chan_spacing,
170
+					      start, prev);
171
+	}
172
+
173
+	if ((pos - eid) & 1) {
174
+		if (end - pos < 1)
175
+			return eid;
176
+		*pos++ = 0; /* pad for 16-bit alignment */
177
+	}
178
+
179
+	eid[1] = (pos - eid) - 2;
180
+
181
+	return pos;
182
+}
183
+
184
+
185
+static u8 * hostapd_eid_wpa(struct hostapd_data *hapd, u8 *eid, size_t len,
186
+			    struct sta_info *sta)
187
+{
188
+	const u8 *ie;
189
+	size_t ielen;
190
+
191
+	ie = wpa_auth_get_wpa_ie(hapd->wpa_auth, &ielen);
192
+	if (ie == NULL || ielen > len)
193
+		return eid;
194
+
195
+	os_memcpy(eid, ie, ielen);
196
+	return eid + ielen;
197
+}
198
+
199
+
200
+void handle_probe_req(struct hostapd_data *hapd,
201
+		      const struct ieee80211_mgmt *mgmt, size_t len)
202
+{
203
+	struct ieee80211_mgmt *resp;
204
+	struct ieee802_11_elems elems;
205
+	char *ssid;
206
+	u8 *pos, *epos;
207
+	const u8 *ie;
208
+	size_t ssid_len, ie_len;
209
+	struct sta_info *sta = NULL;
210
+	size_t buflen;
211
+	size_t i;
212
+
213
+	ie = mgmt->u.probe_req.variable;
214
+	if (len < IEEE80211_HDRLEN + sizeof(mgmt->u.probe_req))
215
+		return;
216
+	ie_len = len - (IEEE80211_HDRLEN + sizeof(mgmt->u.probe_req));
217
+
218
+	for (i = 0; hapd->probereq_cb && i < hapd->num_probereq_cb; i++)
219
+		if (hapd->probereq_cb[i].cb(hapd->probereq_cb[i].ctx,
220
+					    mgmt->sa, ie, ie_len) > 0)
221
+			return;
222
+
223
+	if (!hapd->iconf->send_probe_response)
224
+		return;
225
+
226
+	if (ieee802_11_parse_elems(ie, ie_len, &elems, 0) == ParseFailed) {
227
+		wpa_printf(MSG_DEBUG, "Could not parse ProbeReq from " MACSTR,
228
+			   MAC2STR(mgmt->sa));
229
+		return;
230
+	}
231
+
232
+	ssid = NULL;
233
+	ssid_len = 0;
234
+
235
+	if ((!elems.ssid || !elems.supp_rates)) {
236
+		wpa_printf(MSG_DEBUG, "STA " MACSTR " sent probe request "
237
+			   "without SSID or supported rates element",
238
+			   MAC2STR(mgmt->sa));
239
+		return;
240
+	}
241
+
242
+#ifdef CONFIG_P2P
243
+	if (hapd->p2p && elems.wps_ie) {
244
+		struct wpabuf *wps;
245
+		wps = ieee802_11_vendor_ie_concat(ie, ie_len, WPS_DEV_OUI_WFA);
246
+		if (wps && !p2p_group_match_dev_type(hapd->p2p_group, wps)) {
247
+			wpa_printf(MSG_MSGDUMP, "P2P: Ignore Probe Request "
248
+				   "due to mismatch with Requested Device "
249
+				   "Type");
250
+			wpabuf_free(wps);
251
+			return;
252
+		}
253
+		wpabuf_free(wps);
254
+	}
255
+#endif /* CONFIG_P2P */
256
+
257
+	if (hapd->conf->ignore_broadcast_ssid && elems.ssid_len == 0) {
258
+		wpa_printf(MSG_MSGDUMP, "Probe Request from " MACSTR " for "
259
+			   "broadcast SSID ignored", MAC2STR(mgmt->sa));
260
+		return;
261
+	}
262
+
263
+	sta = ap_get_sta(hapd, mgmt->sa);
264
+
265
+#ifdef CONFIG_P2P
266
+	if ((hapd->conf->p2p & P2P_GROUP_OWNER) &&
267
+	    elems.ssid_len == P2P_WILDCARD_SSID_LEN &&
268
+	    os_memcmp(elems.ssid, P2P_WILDCARD_SSID,
269
+		      P2P_WILDCARD_SSID_LEN) == 0) {
270
+		/* Process P2P Wildcard SSID like Wildcard SSID */
271
+		elems.ssid_len = 0;
272
+	}
273
+#endif /* CONFIG_P2P */
274
+
275
+	if (elems.ssid_len == 0 ||
276
+	    (elems.ssid_len == hapd->conf->ssid.ssid_len &&
277
+	     os_memcmp(elems.ssid, hapd->conf->ssid.ssid, elems.ssid_len) ==
278
+	     0)) {
279
+		ssid = hapd->conf->ssid.ssid;
280
+		ssid_len = hapd->conf->ssid.ssid_len;
281
+		if (sta)
282
+			sta->ssid_probe = &hapd->conf->ssid;
283
+	}
284
+
285
+	if (!ssid) {
286
+		if (!(mgmt->da[0] & 0x01)) {
287
+			char ssid_txt[33];
288
+			ieee802_11_print_ssid(ssid_txt, elems.ssid,
289
+					      elems.ssid_len);
290
+			wpa_printf(MSG_MSGDUMP, "Probe Request from " MACSTR
291
+				   " for foreign SSID '%s' (DA " MACSTR ")",
292
+				   MAC2STR(mgmt->sa), ssid_txt,
293
+				   MAC2STR(mgmt->da));
294
+		}
295
+		return;
296
+	}
297
+
298
+	/* TODO: verify that supp_rates contains at least one matching rate
299
+	 * with AP configuration */
300
+#define MAX_PROBERESP_LEN 768
301
+	buflen = MAX_PROBERESP_LEN;
302
+#ifdef CONFIG_WPS
303
+	if (hapd->wps_probe_resp_ie)
304
+		buflen += wpabuf_len(hapd->wps_probe_resp_ie);
305
+#endif /* CONFIG_WPS */
306
+#ifdef CONFIG_P2P
307
+	if (hapd->p2p_probe_resp_ie)
308
+		buflen += wpabuf_len(hapd->p2p_probe_resp_ie);
309
+#endif /* CONFIG_P2P */
310
+	resp = os_zalloc(buflen);
311
+	if (resp == NULL)
312
+		return;
313
+	epos = ((u8 *) resp) + MAX_PROBERESP_LEN;
314
+
315
+	resp->frame_control = IEEE80211_FC(WLAN_FC_TYPE_MGMT,
316
+					   WLAN_FC_STYPE_PROBE_RESP);
317
+	os_memcpy(resp->da, mgmt->sa, ETH_ALEN);
318
+	os_memcpy(resp->sa, hapd->own_addr, ETH_ALEN);
319
+
320
+	os_memcpy(resp->bssid, hapd->own_addr, ETH_ALEN);
321
+	resp->u.probe_resp.beacon_int =
322
+		host_to_le16(hapd->iconf->beacon_int);
323
+
324
+	/* hardware or low-level driver will setup seq_ctrl and timestamp */
325
+	resp->u.probe_resp.capab_info =
326
+		host_to_le16(hostapd_own_capab_info(hapd, sta, 1));
327
+
328
+	pos = resp->u.probe_resp.variable;
329
+	*pos++ = WLAN_EID_SSID;
330
+	*pos++ = ssid_len;
331
+	os_memcpy(pos, ssid, ssid_len);
332
+	pos += ssid_len;
333
+
334
+	/* Supported rates */
335
+	pos = hostapd_eid_supp_rates(hapd, pos);
336
+
337
+	/* DS Params */
338
+	pos = hostapd_eid_ds_params(hapd, pos);
339
+
340
+	pos = hostapd_eid_country(hapd, pos, epos - pos);
341
+
342
+	/* ERP Information element */
343
+	pos = hostapd_eid_erp_info(hapd, pos);
344
+
345
+	/* Extended supported rates */
346
+	pos = hostapd_eid_ext_supp_rates(hapd, pos);
347
+
348
+	/* RSN, MDIE, WPA */
349
+	pos = hostapd_eid_wpa(hapd, pos, epos - pos, sta);
350
+
351
+#ifdef CONFIG_IEEE80211N
352
+	pos = hostapd_eid_ht_capabilities(hapd, pos);
353
+	pos = hostapd_eid_ht_operation(hapd, pos);
354
+#endif /* CONFIG_IEEE80211N */
355
+
356
+	pos = hostapd_eid_ext_capab(hapd, pos);
357
+
358
+	/* Wi-Fi Alliance WMM */
359
+	pos = hostapd_eid_wmm(hapd, pos);
360
+
361
+#ifdef CONFIG_WPS
362
+	if (hapd->conf->wps_state && hapd->wps_probe_resp_ie) {
363
+		os_memcpy(pos, wpabuf_head(hapd->wps_probe_resp_ie),
364
+			  wpabuf_len(hapd->wps_probe_resp_ie));
365
+		pos += wpabuf_len(hapd->wps_probe_resp_ie);
366
+	}
367
+#endif /* CONFIG_WPS */
368
+
369
+#ifdef CONFIG_P2P
370
+	if ((hapd->conf->p2p & P2P_ENABLED) && elems.p2p &&
371
+	    hapd->p2p_probe_resp_ie) {
372
+		os_memcpy(pos, wpabuf_head(hapd->p2p_probe_resp_ie),
373
+			  wpabuf_len(hapd->p2p_probe_resp_ie));
374
+		pos += wpabuf_len(hapd->p2p_probe_resp_ie);
375
+	}
376
+#endif /* CONFIG_P2P */
377
+#ifdef CONFIG_P2P_MANAGER
378
+	if ((hapd->conf->p2p & (P2P_MANAGE | P2P_ENABLED | P2P_GROUP_OWNER)) ==
379
+	    P2P_MANAGE)
380
+		pos = hostapd_eid_p2p_manage(hapd, pos);
381
+#endif /* CONFIG_P2P_MANAGER */
382
+
383
+	if (hostapd_drv_send_mlme(hapd, resp, pos - (u8 *) resp) < 0)
384
+		perror("handle_probe_req: send");
385
+
386
+	os_free(resp);
387
+
388
+	wpa_printf(MSG_EXCESSIVE, "STA " MACSTR " sent probe request for %s "
389
+		   "SSID", MAC2STR(mgmt->sa),
390
+		   elems.ssid_len == 0 ? "broadcast" : "our");
391
+}
392
+
393
+
394
+void ieee802_11_set_beacon(struct hostapd_data *hapd)
395
+{
396
+	struct ieee80211_mgmt *head;
397
+	u8 *pos, *tail, *tailpos;
398
+	u16 capab_info;
399
+	size_t head_len, tail_len;
400
+
401
+#ifdef CONFIG_P2P
402
+	if ((hapd->conf->p2p & (P2P_ENABLED | P2P_GROUP_OWNER)) == P2P_ENABLED)
403
+		goto no_beacon;
404
+#endif /* CONFIG_P2P */
405
+
406
+#define BEACON_HEAD_BUF_SIZE 256
407
+#define BEACON_TAIL_BUF_SIZE 512
408
+	head = os_zalloc(BEACON_HEAD_BUF_SIZE);
409
+	tail_len = BEACON_TAIL_BUF_SIZE;
410
+#ifdef CONFIG_WPS
411
+	if (hapd->conf->wps_state && hapd->wps_beacon_ie)
412
+		tail_len += wpabuf_len(hapd->wps_beacon_ie);
413
+#endif /* CONFIG_WPS */
414
+#ifdef CONFIG_P2P
415
+	if (hapd->p2p_beacon_ie)
416
+		tail_len += wpabuf_len(hapd->p2p_beacon_ie);
417
+#endif /* CONFIG_P2P */
418
+	tailpos = tail = os_malloc(tail_len);
419
+	if (head == NULL || tail == NULL) {
420
+		wpa_printf(MSG_ERROR, "Failed to set beacon data");
421
+		os_free(head);
422
+		os_free(tail);
423
+		return;
424
+	}
425
+
426
+	head->frame_control = IEEE80211_FC(WLAN_FC_TYPE_MGMT,
427
+					   WLAN_FC_STYPE_BEACON);
428
+	head->duration = host_to_le16(0);
429
+	os_memset(head->da, 0xff, ETH_ALEN);
430
+
431
+	os_memcpy(head->sa, hapd->own_addr, ETH_ALEN);
432
+	os_memcpy(head->bssid, hapd->own_addr, ETH_ALEN);
433
+	head->u.beacon.beacon_int =
434
+		host_to_le16(hapd->iconf->beacon_int);
435
+
436
+	/* hardware or low-level driver will setup seq_ctrl and timestamp */
437
+	capab_info = hostapd_own_capab_info(hapd, NULL, 0);
438
+	head->u.beacon.capab_info = host_to_le16(capab_info);
439
+	pos = &head->u.beacon.variable[0];
440
+
441
+	/* SSID */
442
+	*pos++ = WLAN_EID_SSID;
443
+	if (hapd->conf->ignore_broadcast_ssid == 2) {
444
+		/* clear the data, but keep the correct length of the SSID */
445
+		*pos++ = hapd->conf->ssid.ssid_len;
446
+		os_memset(pos, 0, hapd->conf->ssid.ssid_len);
447
+		pos += hapd->conf->ssid.ssid_len;
448
+	} else if (hapd->conf->ignore_broadcast_ssid) {
449
+		*pos++ = 0; /* empty SSID */
450
+	} else {
451
+		*pos++ = hapd->conf->ssid.ssid_len;
452
+		os_memcpy(pos, hapd->conf->ssid.ssid,
453
+			  hapd->conf->ssid.ssid_len);
454
+		pos += hapd->conf->ssid.ssid_len;
455
+	}
456
+
457
+	/* Supported rates */
458
+	pos = hostapd_eid_supp_rates(hapd, pos);
459
+
460
+	/* DS Params */
461
+	pos = hostapd_eid_ds_params(hapd, pos);
462
+
463
+	head_len = pos - (u8 *) head;
464
+
465
+	tailpos = hostapd_eid_country(hapd, tailpos,
466
+				      tail + BEACON_TAIL_BUF_SIZE - tailpos);
467
+
468
+	/* ERP Information element */
469
+	tailpos = hostapd_eid_erp_info(hapd, tailpos);
470
+
471
+	/* Extended supported rates */
472
+	tailpos = hostapd_eid_ext_supp_rates(hapd, tailpos);
473
+
474
+	/* RSN, MDIE, WPA */
475
+	tailpos = hostapd_eid_wpa(hapd, tailpos, tail + BEACON_TAIL_BUF_SIZE -
476
+				  tailpos, NULL);
477
+
478
+#ifdef CONFIG_IEEE80211N
479
+	tailpos = hostapd_eid_ht_capabilities(hapd, tailpos);
480
+	tailpos = hostapd_eid_ht_operation(hapd, tailpos);
481
+
482
+	//DRIVER_RTW ADD
483
+	if(hapd->iconf->ieee80211n)
484
+		hapd->conf->wmm_enabled = 1;
485
+	
486
+#endif /* CONFIG_IEEE80211N */
487
+
488
+	tailpos = hostapd_eid_ext_capab(hapd, tailpos);
489
+
490
+	/* Wi-Fi Alliance WMM */
491
+	tailpos = hostapd_eid_wmm(hapd, tailpos);
492
+
493
+#ifdef CONFIG_WPS
494
+	if (hapd->conf->wps_state && hapd->wps_beacon_ie) {
495
+		os_memcpy(tailpos, wpabuf_head(hapd->wps_beacon_ie),
496
+			  wpabuf_len(hapd->wps_beacon_ie));
497
+		tailpos += wpabuf_len(hapd->wps_beacon_ie);
498
+	}
499
+#endif /* CONFIG_WPS */
500
+
501
+#ifdef CONFIG_P2P
502
+	if ((hapd->conf->p2p & P2P_ENABLED) && hapd->p2p_beacon_ie) {
503
+		os_memcpy(tailpos, wpabuf_head(hapd->p2p_beacon_ie),
504
+			  wpabuf_len(hapd->p2p_beacon_ie));
505
+		tailpos += wpabuf_len(hapd->p2p_beacon_ie);
506
+	}
507
+#endif /* CONFIG_P2P */
508
+#ifdef CONFIG_P2P_MANAGER
509
+	if ((hapd->conf->p2p & (P2P_MANAGE | P2P_ENABLED | P2P_GROUP_OWNER)) ==
510
+	    P2P_MANAGE)
511
+		tailpos = hostapd_eid_p2p_manage(hapd, tailpos);
512
+#endif /* CONFIG_P2P_MANAGER */
513
+
514
+	tail_len = tailpos > tail ? tailpos - tail : 0;
515
+
516
+	if (hostapd_drv_set_beacon(hapd, (u8 *) head, head_len,
517
+				   tail, tail_len, hapd->conf->dtim_period,
518
+				   hapd->iconf->beacon_int))
519
+		wpa_printf(MSG_ERROR, "Failed to set beacon head/tail or DTIM "
520
+			   "period");
521
+
522
+	os_free(tail);
523
+	os_free(head);
524
+
525
+#ifdef CONFIG_P2P
526
+no_beacon:
527
+#endif /* CONFIG_P2P */
528
+	hostapd_set_bss_params(hapd, !!(ieee802_11_erp_info(hapd) &
529
+					ERP_INFO_USE_PROTECTION));
530
+}
531
+
532
+
533
+void ieee802_11_set_beacons(struct hostapd_iface *iface)
534
+{
535
+	size_t i;
536
+	for (i = 0; i < iface->num_bss; i++)
537
+		ieee802_11_set_beacon(iface->bss[i]);
538
+}
539
+
540
+#endif /* CONFIG_NATIVE_WINDOWS */

+ 36
- 0
src/ap/beacon.h Näytä tiedosto

@@ -0,0 +1,36 @@
1
+/*
2
+ * hostapd / IEEE 802.11 Management: Beacon and Probe Request/Response
3
+ * Copyright (c) 2002-2004, Instant802 Networks, Inc.
4
+ * Copyright (c) 2005-2006, Devicescape Software, Inc.
5
+ *
6
+ * This program is free software; you can redistribute it and/or modify
7
+ * it under the terms of the GNU General Public License version 2 as
8
+ * published by the Free Software Foundation.
9
+ *
10
+ * Alternatively, this software may be distributed under the terms of BSD
11
+ * license.
12
+ *
13
+ * See README and COPYING for more details.
14
+ */
15
+
16
+#ifndef BEACON_H
17
+#define BEACON_H
18
+
19
+struct ieee80211_mgmt;
20
+
21
+void handle_probe_req(struct hostapd_data *hapd,
22
+		      const struct ieee80211_mgmt *mgmt, size_t len);
23
+#ifdef NEED_AP_MLME
24
+void ieee802_11_set_beacon(struct hostapd_data *hapd);
25
+void ieee802_11_set_beacons(struct hostapd_iface *iface);
26
+#else /* NEED_AP_MLME */
27
+static inline void ieee802_11_set_beacon(struct hostapd_data *hapd)
28
+{
29
+}
30
+
31
+static inline void ieee802_11_set_beacons(struct hostapd_iface *iface)
32
+{
33
+}
34
+#endif /* NEED_AP_MLME */
35
+
36
+#endif /* BEACON_H */

+ 108
- 0
src/ap/ctrl_iface_ap.c Näytä tiedosto

@@ -0,0 +1,108 @@
1
+/*
2
+ * Control interface for shared AP commands
3
+ * Copyright (c) 2004-2009, Jouni Malinen <j@w1.fi>
4
+ *
5
+ * This program is free software; you can redistribute it and/or modify
6
+ * it under the terms of the GNU General Public License version 2 as
7
+ * published by the Free Software Foundation.
8
+ *
9
+ * Alternatively, this software may be distributed under the terms of BSD
10
+ * license.
11
+ *
12
+ * See README and COPYING for more details.
13
+ */
14
+
15
+#include "utils/includes.h"
16
+
17
+#include "utils/common.h"
18
+#include "hostapd.h"
19
+#include "ieee802_1x.h"
20
+#include "wpa_auth.h"
21
+#include "ieee802_11.h"
22
+#include "sta_info.h"
23
+#include "wps_hostapd.h"
24
+#include "p2p_hostapd.h"
25
+#include "ctrl_iface_ap.h"
26
+
27
+
28
+static int hostapd_ctrl_iface_sta_mib(struct hostapd_data *hapd,
29
+				      struct sta_info *sta,
30
+				      char *buf, size_t buflen)
31
+{
32
+	int len, res, ret;
33
+
34
+	if (sta == NULL) {
35
+		ret = os_snprintf(buf, buflen, "FAIL\n");
36
+		if (ret < 0 || (size_t) ret >= buflen)
37
+			return 0;
38
+		return ret;
39
+	}
40
+
41
+	len = 0;
42
+	ret = os_snprintf(buf + len, buflen - len, MACSTR "\n",
43
+			  MAC2STR(sta->addr));
44
+	if (ret < 0 || (size_t) ret >= buflen - len)
45
+		return len;
46
+	len += ret;
47
+
48
+	res = ieee802_11_get_mib_sta(hapd, sta, buf + len, buflen - len);
49
+	if (res >= 0)
50
+		len += res;
51
+	res = wpa_get_mib_sta(sta->wpa_sm, buf + len, buflen - len);
52
+	if (res >= 0)
53
+		len += res;
54
+	res = ieee802_1x_get_mib_sta(hapd, sta, buf + len, buflen - len);
55
+	if (res >= 0)
56
+		len += res;
57
+	res = hostapd_wps_get_mib_sta(hapd, sta->addr, buf + len,
58
+				      buflen - len);
59
+	if (res >= 0)
60
+		len += res;
61
+	res = hostapd_p2p_get_mib_sta(hapd, sta, buf + len, buflen - len);
62
+	if (res >= 0)
63
+		len += res;
64
+
65
+	return len;
66
+}
67
+
68
+
69
+int hostapd_ctrl_iface_sta_first(struct hostapd_data *hapd,
70
+				 char *buf, size_t buflen)
71
+{
72
+	return hostapd_ctrl_iface_sta_mib(hapd, hapd->sta_list, buf, buflen);
73
+}
74
+
75
+
76
+int hostapd_ctrl_iface_sta(struct hostapd_data *hapd, const char *txtaddr,
77
+			   char *buf, size_t buflen)
78
+{
79
+	u8 addr[ETH_ALEN];
80
+	int ret;
81
+
82
+	if (hwaddr_aton(txtaddr, addr)) {
83
+		ret = os_snprintf(buf, buflen, "FAIL\n");
84
+		if (ret < 0 || (size_t) ret >= buflen)
85
+			return 0;
86
+		return ret;
87
+	}
88
+	return hostapd_ctrl_iface_sta_mib(hapd, ap_get_sta(hapd, addr),
89
+					  buf, buflen);
90
+}
91
+
92
+
93
+int hostapd_ctrl_iface_sta_next(struct hostapd_data *hapd, const char *txtaddr,
94
+				char *buf, size_t buflen)
95
+{
96
+	u8 addr[ETH_ALEN];
97
+	struct sta_info *sta;
98
+	int ret;
99
+
100
+	if (hwaddr_aton(txtaddr, addr) ||
101
+	    (sta = ap_get_sta(hapd, addr)) == NULL) {
102
+		ret = os_snprintf(buf, buflen, "FAIL\n");
103
+		if (ret < 0 || (size_t) ret >= buflen)
104
+			return 0;
105
+		return ret;
106
+	}		
107
+	return hostapd_ctrl_iface_sta_mib(hapd, sta->next, buf, buflen);
108
+}

+ 25
- 0
src/ap/ctrl_iface_ap.h Näytä tiedosto

@@ -0,0 +1,25 @@
1
+/*
2
+ * Control interface for shared AP commands
3
+ * Copyright (c) 2004-2009, Jouni Malinen <j@w1.fi>
4
+ *
5
+ * This program is free software; you can redistribute it and/or modify
6
+ * it under the terms of the GNU General Public License version 2 as
7
+ * published by the Free Software Foundation.
8
+ *
9
+ * Alternatively, this software may be distributed under the terms of BSD
10
+ * license.
11
+ *
12
+ * See README and COPYING for more details.
13
+ */
14
+
15
+#ifndef CTRL_IFACE_AP_H
16
+#define CTRL_IFACE_AP_H
17
+
18
+int hostapd_ctrl_iface_sta_first(struct hostapd_data *hapd,
19
+				 char *buf, size_t buflen);
20
+int hostapd_ctrl_iface_sta(struct hostapd_data *hapd, const char *txtaddr,
21
+			   char *buf, size_t buflen);
22
+int hostapd_ctrl_iface_sta_next(struct hostapd_data *hapd, const char *txtaddr,
23
+				char *buf, size_t buflen);
24
+
25
+#endif /* CTRL_IFACE_AP_H */

+ 539
- 0
src/ap/drv_callbacks.c Näytä tiedosto

@@ -0,0 +1,539 @@
1
+/*
2
+ * hostapd / Callback functions for driver wrappers
3
+ * Copyright (c) 2002-2009, Jouni Malinen <j@w1.fi>
4
+ *
5
+ * This program is free software; you can redistribute it and/or modify
6
+ * it under the terms of the GNU General Public License version 2 as
7
+ * published by the Free Software Foundation.
8
+ *
9
+ * Alternatively, this software may be distributed under the terms of BSD
10
+ * license.
11
+ *
12
+ * See README and COPYING for more details.
13
+ */
14
+
15
+#include "utils/includes.h"
16
+
17
+#include "utils/common.h"
18
+#include "radius/radius.h"
19
+#include "drivers/driver.h"
20
+#include "common/ieee802_11_defs.h"
21
+#include "common/ieee802_11_common.h"
22
+#include "common/wpa_ctrl.h"
23
+#include "crypto/random.h"
24
+#include "p2p/p2p.h"
25
+#include "wps/wps.h"
26
+#include "hostapd.h"
27
+#include "ieee802_11.h"
28
+#include "sta_info.h"
29
+#include "accounting.h"
30
+#include "tkip_countermeasures.h"
31
+#include "iapp.h"
32
+#include "ieee802_1x.h"
33
+#include "wpa_auth.h"
34
+#include "wmm.h"
35
+#include "wps_hostapd.h"
36
+#include "ap_drv_ops.h"
37
+#include "ap_config.h"
38
+
39
+
40
+int hostapd_notif_assoc(struct hostapd_data *hapd, const u8 *addr,
41
+			const u8 *ie, size_t ielen, int reassoc)
42
+{
43
+	struct sta_info *sta;
44
+	int new_assoc, res;
45
+	struct ieee802_11_elems elems;
46
+#ifdef CONFIG_P2P
47
+	const u8 *all_ies = ie;
48
+	size_t all_ies_len = ielen;
49
+#endif /* CONFIG_P2P */
50
+
51
+	if (addr == NULL) {
52
+		/*
53
+		 * This could potentially happen with unexpected event from the
54
+		 * driver wrapper. This was seen at least in one case where the
55
+		 * driver ended up being set to station mode while hostapd was
56
+		 * running, so better make sure we stop processing such an
57
+		 * event here.
58
+		 */
59
+		wpa_printf(MSG_DEBUG, "hostapd_notif_assoc: Skip event with "
60
+			   "no address");
61
+		return -1;
62
+	}
63
+	random_add_randomness(addr, ETH_ALEN);
64
+
65
+	hostapd_logger(hapd, addr, HOSTAPD_MODULE_IEEE80211,
66
+		       HOSTAPD_LEVEL_INFO, "associated");
67
+
68
+	ieee802_11_parse_elems(ie, ielen, &elems, 0);
69
+	if (elems.wps_ie) {
70
+		ie = elems.wps_ie - 2;
71
+		ielen = elems.wps_ie_len + 2;
72
+		wpa_printf(MSG_DEBUG, "STA included WPS IE in (Re)AssocReq");
73
+	} else if (elems.rsn_ie) {
74
+		ie = elems.rsn_ie - 2;
75
+		ielen = elems.rsn_ie_len + 2;
76
+		wpa_printf(MSG_DEBUG, "STA included RSN IE in (Re)AssocReq");
77
+	} else if (elems.wpa_ie) {
78
+		ie = elems.wpa_ie - 2;
79
+		ielen = elems.wpa_ie_len + 2;
80
+		wpa_printf(MSG_DEBUG, "STA included WPA IE in (Re)AssocReq");
81
+	} else {
82
+		ie = NULL;
83
+		ielen = 0;
84
+		wpa_printf(MSG_DEBUG, "STA did not include WPS/RSN/WPA IE in "
85
+			   "(Re)AssocReq");
86
+	}
87
+
88
+	sta = ap_get_sta(hapd, addr);
89
+	if (sta) {
90
+		accounting_sta_stop(hapd, sta);
91
+	} else {
92
+		sta = ap_sta_add(hapd, addr);
93
+		if (sta == NULL)
94
+			return -1;
95
+	}
96
+	sta->flags &= ~(WLAN_STA_WPS | WLAN_STA_MAYBE_WPS);
97
+
98
+#ifdef CONFIG_P2P
99
+	if (elems.p2p) {
100
+		wpabuf_free(sta->p2p_ie);
101
+		sta->p2p_ie = ieee802_11_vendor_ie_concat(all_ies, all_ies_len,
102
+							  P2P_IE_VENDOR_TYPE);
103
+	}
104
+#endif /* CONFIG_P2P */
105
+
106
+	if (hapd->conf->wpa) {
107
+		if (ie == NULL || ielen == 0) {
108
+			if (hapd->conf->wps_state) {
109
+				wpa_printf(MSG_DEBUG, "STA did not include "
110
+					   "WPA/RSN IE in (Re)Association "
111
+					   "Request - possible WPS use");
112
+				sta->flags |= WLAN_STA_MAYBE_WPS;
113
+				goto skip_wpa_check;
114
+			}
115
+
116
+			wpa_printf(MSG_DEBUG, "No WPA/RSN IE from STA");
117
+			return -1;
118
+		}
119
+		if (hapd->conf->wps_state && ie[0] == 0xdd && ie[1] >= 4 &&
120
+		    os_memcmp(ie + 2, "\x00\x50\xf2\x04", 4) == 0) {
121
+			sta->flags |= WLAN_STA_WPS;
122
+			goto skip_wpa_check;
123
+		}
124
+
125
+		if (sta->wpa_sm == NULL)
126
+			sta->wpa_sm = wpa_auth_sta_init(hapd->wpa_auth,
127
+							sta->addr);
128
+		if (sta->wpa_sm == NULL) {
129
+			wpa_printf(MSG_ERROR, "Failed to initialize WPA state "
130
+				   "machine");
131
+			return -1;
132
+		}
133
+		res = wpa_validate_wpa_ie(hapd->wpa_auth, sta->wpa_sm,
134
+					  ie, ielen, NULL, 0);
135
+		if (res != WPA_IE_OK) {
136
+			int resp;
137
+			wpa_printf(MSG_DEBUG, "WPA/RSN information element "
138
+				   "rejected? (res %u)", res);
139
+			wpa_hexdump(MSG_DEBUG, "IE", ie, ielen);
140
+			if (res == WPA_INVALID_GROUP)
141
+				resp = WLAN_REASON_GROUP_CIPHER_NOT_VALID;
142
+			else if (res == WPA_INVALID_PAIRWISE)
143
+				resp = WLAN_REASON_PAIRWISE_CIPHER_NOT_VALID;
144
+			else if (res == WPA_INVALID_AKMP)
145
+				resp = WLAN_REASON_AKMP_NOT_VALID;
146
+#ifdef CONFIG_IEEE80211W
147
+			else if (res == WPA_MGMT_FRAME_PROTECTION_VIOLATION)
148
+				resp = WLAN_REASON_INVALID_IE;
149
+			else if (res == WPA_INVALID_MGMT_GROUP_CIPHER)
150
+				resp = WLAN_REASON_GROUP_CIPHER_NOT_VALID;
151
+#endif /* CONFIG_IEEE80211W */
152
+			else
153
+				resp = WLAN_REASON_INVALID_IE;
154
+			hostapd_drv_sta_disassoc(hapd, sta->addr, resp);
155
+			ap_free_sta(hapd, sta);
156
+			return -1;
157
+		}
158
+	} else if (hapd->conf->wps_state) {
159
+#ifdef CONFIG_WPS_STRICT
160
+		if (ie) {
161
+			struct wpabuf *wps;
162
+			wps = ieee802_11_vendor_ie_concat(ie, ielen,
163
+							  WPS_IE_VENDOR_TYPE);
164
+			if (wps && wps_validate_assoc_req(wps) < 0) {
165
+				hostapd_drv_sta_disassoc(
166
+					hapd, sta->addr,
167
+					WLAN_REASON_INVALID_IE);
168
+				ap_free_sta(hapd, sta);
169
+				wpabuf_free(wps);
170
+				return -1;
171
+			}
172
+			wpabuf_free(wps);
173
+		}
174
+#endif /* CONFIG_WPS_STRICT */
175
+		if (ie && ielen > 4 && ie[0] == 0xdd && ie[1] >= 4 &&
176
+		    os_memcmp(ie + 2, "\x00\x50\xf2\x04", 4) == 0) {
177
+			sta->flags |= WLAN_STA_WPS;
178
+		} else
179
+			sta->flags |= WLAN_STA_MAYBE_WPS;
180
+	}
181
+skip_wpa_check:
182
+
183
+	new_assoc = (sta->flags & WLAN_STA_ASSOC) == 0;
184
+	sta->flags |= WLAN_STA_AUTH | WLAN_STA_ASSOC;
185
+	wpa_auth_sm_event(sta->wpa_sm, WPA_ASSOC);
186
+
187
+	hostapd_new_assoc_sta(hapd, sta, !new_assoc);
188
+
189
+	ieee802_1x_notify_port_enabled(sta->eapol_sm, 1);
190
+
191
+#ifdef CONFIG_P2P
192
+	p2p_group_notif_assoc(hapd->p2p_group, sta->addr,
193
+			      all_ies, all_ies_len);
194
+#endif /* CONFIG_P2P */
195
+
196
+	return 0;
197
+}
198
+
199
+
200
+void hostapd_notif_disassoc(struct hostapd_data *hapd, const u8 *addr)
201
+{
202
+	struct sta_info *sta;
203
+
204
+	if (addr == NULL) {
205
+		/*
206
+		 * This could potentially happen with unexpected event from the
207
+		 * driver wrapper. This was seen at least in one case where the
208
+		 * driver ended up reporting a station mode event while hostapd
209
+		 * was running, so better make sure we stop processing such an
210
+		 * event here.
211
+		 */
212
+		wpa_printf(MSG_DEBUG, "hostapd_notif_disassoc: Skip event "
213
+			   "with no address");
214
+		return;
215
+	}
216
+
217
+	hostapd_logger(hapd, addr, HOSTAPD_MODULE_IEEE80211,
218
+		       HOSTAPD_LEVEL_INFO, "disassociated");
219
+
220
+	sta = ap_get_sta(hapd, addr);
221
+	if (sta == NULL) {
222
+		wpa_printf(MSG_DEBUG, "Disassociation notification for "
223
+			   "unknown STA " MACSTR, MAC2STR(addr));
224
+		return;
225
+	}
226
+
227
+	sta->flags &= ~(WLAN_STA_AUTH | WLAN_STA_ASSOC);
228
+	wpa_msg(hapd->msg_ctx, MSG_INFO, AP_STA_DISCONNECTED MACSTR,
229
+		MAC2STR(sta->addr));
230
+	wpa_auth_sm_event(sta->wpa_sm, WPA_DISASSOC);
231
+	sta->acct_terminate_cause = RADIUS_ACCT_TERMINATE_CAUSE_USER_REQUEST;
232
+	ieee802_1x_notify_port_enabled(sta->eapol_sm, 0);
233
+	ap_free_sta(hapd, sta);
234
+}
235
+
236
+
237
+void hostapd_event_sta_low_ack(struct hostapd_data *hapd, const u8 *addr)
238
+{
239
+	struct sta_info *sta = ap_get_sta(hapd, addr);
240
+
241
+	if (!sta || !hapd->conf->disassoc_low_ack)
242
+		return;
243
+
244
+	hostapd_logger(hapd, addr, HOSTAPD_MODULE_IEEE80211,
245
+		       HOSTAPD_LEVEL_INFO, "disconnected due to excessive "
246
+		       "missing ACKs");
247
+	hostapd_drv_sta_disassoc(hapd, addr, WLAN_REASON_DISASSOC_LOW_ACK);
248
+	if (sta)
249
+		ap_sta_disassociate(hapd, sta, WLAN_REASON_DISASSOC_LOW_ACK);
250
+}
251
+
252
+
253
+int hostapd_probe_req_rx(struct hostapd_data *hapd, const u8 *sa,
254
+			 const u8 *ie, size_t ie_len)
255
+{
256
+	size_t i;
257
+	int ret = 0;
258
+
259
+	if (sa == NULL || ie == NULL)
260
+		return -1;
261
+
262
+	random_add_randomness(sa, ETH_ALEN);
263
+	for (i = 0; hapd->probereq_cb && i < hapd->num_probereq_cb; i++) {
264
+		if (hapd->probereq_cb[i].cb(hapd->probereq_cb[i].ctx,
265
+					    sa, ie, ie_len) > 0) {
266
+			ret = 1;
267
+			break;
268
+		}
269
+	}
270
+	return ret;
271
+}
272
+
273
+
274
+#ifdef HOSTAPD
275
+
276
+#ifdef NEED_AP_MLME
277
+
278
+static const u8 * get_hdr_bssid(const struct ieee80211_hdr *hdr, size_t len)
279
+{
280
+	u16 fc, type, stype;
281
+
282
+	/*
283
+	 * PS-Poll frames are 16 bytes. All other frames are
284
+	 * 24 bytes or longer.
285
+	 */
286
+	if (len < 16)
287
+		return NULL;
288
+
289
+	fc = le_to_host16(hdr->frame_control);
290
+	type = WLAN_FC_GET_TYPE(fc);
291
+	stype = WLAN_FC_GET_STYPE(fc);
292
+
293
+	switch (type) {
294
+	case WLAN_FC_TYPE_DATA:
295
+		if (len < 24)
296
+			return NULL;
297
+		switch (fc & (WLAN_FC_FROMDS | WLAN_FC_TODS)) {
298
+		case WLAN_FC_FROMDS | WLAN_FC_TODS:
299
+		case WLAN_FC_TODS:
300
+			return hdr->addr1;
301
+		case WLAN_FC_FROMDS:
302
+			return hdr->addr2;
303
+		default:
304
+			return NULL;
305
+		}
306
+	case WLAN_FC_TYPE_CTRL:
307
+		if (stype != WLAN_FC_STYPE_PSPOLL)
308
+			return NULL;
309
+		return hdr->addr1;
310
+	case WLAN_FC_TYPE_MGMT:
311
+		return hdr->addr3;
312
+	default:
313
+		return NULL;
314
+	}
315
+}
316
+
317
+
318
+#define HAPD_BROADCAST ((struct hostapd_data *) -1)
319
+
320
+static struct hostapd_data * get_hapd_bssid(struct hostapd_iface *iface,
321
+					    const u8 *bssid)
322
+{
323
+	size_t i;
324
+
325
+	if (bssid == NULL)
326
+		return NULL;
327
+	if (bssid[0] == 0xff && bssid[1] == 0xff && bssid[2] == 0xff &&
328
+	    bssid[3] == 0xff && bssid[4] == 0xff && bssid[5] == 0xff)
329
+		return HAPD_BROADCAST;
330
+
331
+	for (i = 0; i < iface->num_bss; i++) {
332
+		if (os_memcmp(bssid, iface->bss[i]->own_addr, ETH_ALEN) == 0)
333
+			return iface->bss[i];
334
+	}
335
+
336
+	return NULL;
337
+}
338
+
339
+
340
+static void hostapd_rx_from_unknown_sta(struct hostapd_data *hapd,
341
+					const u8 *frame, size_t len)
342
+{
343
+	const struct ieee80211_hdr *hdr = (const struct ieee80211_hdr *) frame;
344
+	u16 fc = le_to_host16(hdr->frame_control);
345
+	hapd = get_hapd_bssid(hapd->iface, get_hdr_bssid(hdr, len));
346
+	if (hapd == NULL || hapd == HAPD_BROADCAST)
347
+		return;
348
+
349
+	ieee802_11_rx_from_unknown(hapd, hdr->addr2,
350
+				   (fc & (WLAN_FC_TODS | WLAN_FC_FROMDS)) ==
351
+				   (WLAN_FC_TODS | WLAN_FC_FROMDS));
352
+}
353
+
354
+
355
+static void hostapd_mgmt_rx(struct hostapd_data *hapd, struct rx_mgmt *rx_mgmt)
356
+{
357
+	struct hostapd_iface *iface = hapd->iface;
358
+	const struct ieee80211_hdr *hdr;
359
+	const u8 *bssid;
360
+	struct hostapd_frame_info fi;
361
+
362
+	hdr = (const struct ieee80211_hdr *) rx_mgmt->frame;
363
+	bssid = get_hdr_bssid(hdr, rx_mgmt->frame_len);
364
+	if (bssid == NULL)
365
+		return;
366
+
367
+	hapd = get_hapd_bssid(iface, bssid);
368
+	if (hapd == NULL) {
369
+		u16 fc;
370
+		fc = le_to_host16(hdr->frame_control);
371
+
372
+		/*
373
+		 * Drop frames to unknown BSSIDs except for Beacon frames which
374
+		 * could be used to update neighbor information.
375
+		 */
376
+		if (WLAN_FC_GET_TYPE(fc) == WLAN_FC_TYPE_MGMT &&
377
+		    WLAN_FC_GET_STYPE(fc) == WLAN_FC_STYPE_BEACON)
378
+			hapd = iface->bss[0];
379
+		else
380
+			return;
381
+	}
382
+
383
+	os_memset(&fi, 0, sizeof(fi));
384
+	fi.datarate = rx_mgmt->datarate;
385
+	fi.ssi_signal = rx_mgmt->ssi_signal;
386
+
387
+	if (hapd == HAPD_BROADCAST) {
388
+		size_t i;
389
+		for (i = 0; i < iface->num_bss; i++)
390
+			ieee802_11_mgmt(iface->bss[i], rx_mgmt->frame,
391
+					rx_mgmt->frame_len, &fi);
392
+	} else
393
+		ieee802_11_mgmt(hapd, rx_mgmt->frame, rx_mgmt->frame_len, &fi);
394
+
395
+	random_add_randomness(&fi, sizeof(fi));
396
+}
397
+
398
+
399
+static void hostapd_mgmt_tx_cb(struct hostapd_data *hapd, const u8 *buf,
400
+			       size_t len, u16 stype, int ok)
401
+{
402
+	struct ieee80211_hdr *hdr;
403
+	hdr = (struct ieee80211_hdr *) buf;
404
+	hapd = get_hapd_bssid(hapd->iface, get_hdr_bssid(hdr, len));
405
+	if (hapd == NULL || hapd == HAPD_BROADCAST)
406
+		return;
407
+	ieee802_11_mgmt_cb(hapd, buf, len, stype, ok);
408
+}
409
+
410
+#endif /* NEED_AP_MLME */
411
+
412
+
413
+static int hostapd_event_new_sta(struct hostapd_data *hapd, const u8 *addr)
414
+{
415
+	struct sta_info *sta = ap_get_sta(hapd, addr);
416
+	if (sta)
417
+		return 0;
418
+
419
+	wpa_printf(MSG_DEBUG, "Data frame from unknown STA " MACSTR
420
+		   " - adding a new STA", MAC2STR(addr));
421
+	sta = ap_sta_add(hapd, addr);
422
+	if (sta) {
423
+		hostapd_new_assoc_sta(hapd, sta, 0);
424
+	} else {
425
+		wpa_printf(MSG_DEBUG, "Failed to add STA entry for " MACSTR,
426
+			   MAC2STR(addr));
427
+		return -1;
428
+	}
429
+
430
+	return 0;
431
+}
432
+
433
+
434
+static void hostapd_event_eapol_rx(struct hostapd_data *hapd, const u8 *src,
435
+				   const u8 *data, size_t data_len)
436
+{
437
+	struct hostapd_iface *iface = hapd->iface;
438
+	size_t j;
439
+
440
+	for (j = 0; j < iface->num_bss; j++) {
441
+		if (ap_get_sta(iface->bss[j], src)) {
442
+			hapd = iface->bss[j];
443
+			break;
444
+		}
445
+	}
446
+
447
+	ieee802_1x_receive(hapd, src, data, data_len);
448
+}
449
+
450
+
451
+void wpa_supplicant_event(void *ctx, enum wpa_event_type event,
452
+			  union wpa_event_data *data)
453
+{
454
+	struct hostapd_data *hapd = ctx;
455
+
456
+	switch (event) {
457
+	case EVENT_MICHAEL_MIC_FAILURE:
458
+		michael_mic_failure(hapd, data->michael_mic_failure.src, 1);
459
+		break;
460
+	case EVENT_SCAN_RESULTS:
461
+		if (hapd->iface->scan_cb)
462
+			hapd->iface->scan_cb(hapd->iface);
463
+		break;
464
+#ifdef CONFIG_IEEE80211R
465
+	case EVENT_FT_RRB_RX:
466
+		wpa_ft_rrb_rx(hapd->wpa_auth, data->ft_rrb_rx.src,
467
+			      data->ft_rrb_rx.data, data->ft_rrb_rx.data_len);
468
+		break;
469
+#endif /* CONFIG_IEEE80211R */
470
+	case EVENT_WPS_BUTTON_PUSHED:
471
+		hostapd_wps_button_pushed(hapd, NULL);
472
+		break;
473
+#ifdef NEED_AP_MLME
474
+	case EVENT_TX_STATUS:
475
+		switch (data->tx_status.type) {
476
+		case WLAN_FC_TYPE_MGMT:
477
+			hostapd_mgmt_tx_cb(hapd, data->tx_status.data,
478
+					   data->tx_status.data_len,
479
+					   data->tx_status.stype,
480
+					   data->tx_status.ack);
481
+			break;
482
+		case WLAN_FC_TYPE_DATA:
483
+			hostapd_tx_status(hapd, data->tx_status.dst,
484
+					  data->tx_status.data,
485
+					  data->tx_status.data_len,
486
+					  data->tx_status.ack);
487
+			break;
488
+		}
489
+		break;
490
+	case EVENT_RX_FROM_UNKNOWN:
491
+		hostapd_rx_from_unknown_sta(hapd, data->rx_from_unknown.frame,
492
+					    data->rx_from_unknown.len);
493
+		break;
494
+	case EVENT_RX_MGMT:
495
+		hostapd_mgmt_rx(hapd, &data->rx_mgmt);
496
+		break;
497
+#endif /* NEED_AP_MLME */
498
+	case EVENT_RX_PROBE_REQ:
499
+		if (data->rx_probe_req.sa == NULL ||
500
+		    data->rx_probe_req.ie == NULL)
501
+			break;
502
+		hostapd_probe_req_rx(hapd, data->rx_probe_req.sa,
503
+				     data->rx_probe_req.ie,
504
+				     data->rx_probe_req.ie_len);
505
+		break;
506
+	case EVENT_NEW_STA:
507
+		hostapd_event_new_sta(hapd, data->new_sta.addr);
508
+		break;
509
+	case EVENT_EAPOL_RX:
510
+		hostapd_event_eapol_rx(hapd, data->eapol_rx.src,
511
+				       data->eapol_rx.data,
512
+				       data->eapol_rx.data_len);
513
+		break;
514
+	case EVENT_ASSOC:
515
+		hostapd_notif_assoc(hapd, data->assoc_info.addr,
516
+				    data->assoc_info.req_ies,
517
+				    data->assoc_info.req_ies_len,
518
+				    data->assoc_info.reassoc);
519
+		break;
520
+	case EVENT_DISASSOC:
521
+		if (data)
522
+			hostapd_notif_disassoc(hapd, data->disassoc_info.addr);
523
+		break;
524
+	case EVENT_DEAUTH:
525
+		if (data)
526
+			hostapd_notif_disassoc(hapd, data->deauth_info.addr);
527
+		break;
528
+	case EVENT_STATION_LOW_ACK:
529
+		if (!data)
530
+			break;
531
+		hostapd_event_sta_low_ack(hapd, data->low_ack.addr);
532
+		break;
533
+	default:
534
+		wpa_printf(MSG_DEBUG, "Unknown event %d", event);
535
+		break;
536
+	}
537
+}
538
+
539
+#endif /* HOSTAPD */

+ 929
- 0
src/ap/hostapd.c Näytä tiedosto

@@ -0,0 +1,929 @@
1
+/*
2
+ * hostapd / Initialization and configuration
3
+ * Copyright (c) 2002-2009, Jouni Malinen <j@w1.fi>
4
+ *
5
+ * This program is free software; you can redistribute it and/or modify
6
+ * it under the terms of the GNU General Public License version 2 as
7
+ * published by the Free Software Foundation.
8
+ *
9
+ * Alternatively, this software may be distributed under the terms of BSD
10
+ * license.
11
+ *
12
+ * See README and COPYING for more details.
13
+ */
14
+
15
+#include "utils/includes.h"
16
+
17
+#include "utils/common.h"
18
+#include "utils/eloop.h"
19
+#include "common/ieee802_11_defs.h"
20
+#include "radius/radius_client.h"
21
+#include "drivers/driver.h"
22
+#include "hostapd.h"
23
+#include "authsrv.h"
24
+#include "sta_info.h"
25
+#include "accounting.h"
26
+#include "ap_list.h"
27
+#include "beacon.h"
28
+#include "iapp.h"
29
+#include "ieee802_1x.h"
30
+#include "ieee802_11_auth.h"
31
+#include "vlan_init.h"
32
+#include "wpa_auth.h"
33
+#include "wps_hostapd.h"
34
+#include "hw_features.h"
35
+#include "wpa_auth_glue.h"
36
+#include "ap_drv_ops.h"
37
+#include "ap_config.h"
38
+#include "p2p_hostapd.h"
39
+
40
+
41
+static int hostapd_flush_old_stations(struct hostapd_data *hapd);
42
+static int hostapd_setup_encryption(char *iface, struct hostapd_data *hapd);
43
+
44
+extern int wpa_debug_level;
45
+
46
+
47
+static void hostapd_reload_bss(struct hostapd_data *hapd)
48
+{
49
+#ifndef CONFIG_NO_RADIUS
50
+	radius_client_reconfig(hapd->radius, hapd->conf->radius);
51
+#endif /* CONFIG_NO_RADIUS */
52
+
53
+	if (hostapd_setup_wpa_psk(hapd->conf)) {
54
+		wpa_printf(MSG_ERROR, "Failed to re-configure WPA PSK "
55
+			   "after reloading configuration");
56
+	}
57
+
58
+	if (hapd->conf->ieee802_1x || hapd->conf->wpa)
59
+		hostapd_set_drv_ieee8021x(hapd, hapd->conf->iface, 1);
60
+	else
61
+		hostapd_set_drv_ieee8021x(hapd, hapd->conf->iface, 0);
62
+
63
+	if (hapd->conf->wpa && hapd->wpa_auth == NULL)
64
+		hostapd_setup_wpa(hapd);
65
+	else if (hapd->conf->wpa) {
66
+		const u8 *wpa_ie;
67
+		size_t wpa_ie_len;
68
+		hostapd_reconfig_wpa(hapd);
69
+		wpa_ie = wpa_auth_get_wpa_ie(hapd->wpa_auth, &wpa_ie_len);
70
+		if (hostapd_set_generic_elem(hapd, wpa_ie, wpa_ie_len))
71
+			wpa_printf(MSG_ERROR, "Failed to configure WPA IE for "
72
+				   "the kernel driver.");
73
+	} else if (hapd->wpa_auth) {
74
+		wpa_deinit(hapd->wpa_auth);
75
+		hapd->wpa_auth = NULL;
76
+		hostapd_set_privacy(hapd, 0);
77
+		hostapd_setup_encryption(hapd->conf->iface, hapd);
78
+		hostapd_set_generic_elem(hapd, (u8 *) "", 0);
79
+	}
80
+
81
+	ieee802_11_set_beacon(hapd);
82
+	hostapd_update_wps(hapd);
83
+
84
+	if (hapd->conf->ssid.ssid_set &&
85
+	    hostapd_set_ssid(hapd, (u8 *) hapd->conf->ssid.ssid,
86
+			     hapd->conf->ssid.ssid_len)) {
87
+		wpa_printf(MSG_ERROR, "Could not set SSID for kernel driver");
88
+		/* try to continue */
89
+	}
90
+	wpa_printf(MSG_DEBUG, "Reconfigured interface %s", hapd->conf->iface);
91
+}
92
+
93
+
94
+int hostapd_reload_config(struct hostapd_iface *iface)
95
+{
96
+	struct hostapd_data *hapd = iface->bss[0];
97
+	struct hostapd_config *newconf, *oldconf;
98
+	size_t j;
99
+
100
+	if (iface->config_read_cb == NULL)
101
+		return -1;
102
+	newconf = iface->config_read_cb(iface->config_fname);
103
+	if (newconf == NULL)
104
+		return -1;
105
+
106
+	/*
107
+	 * Deauthenticate all stations since the new configuration may not
108
+	 * allow them to use the BSS anymore.
109
+	 */
110
+	for (j = 0; j < iface->num_bss; j++) {
111
+		hostapd_flush_old_stations(iface->bss[j]);
112
+
113
+#ifndef CONFIG_NO_RADIUS
114
+		/* TODO: update dynamic data based on changed configuration
115
+		 * items (e.g., open/close sockets, etc.) */
116
+		radius_client_flush(iface->bss[j]->radius, 0);
117
+#endif /* CONFIG_NO_RADIUS */
118
+	}
119
+
120
+	oldconf = hapd->iconf;
121
+	iface->conf = newconf;
122
+
123
+	for (j = 0; j < iface->num_bss; j++) {
124
+		hapd = iface->bss[j];
125
+		hapd->iconf = newconf;
126
+		hapd->conf = &newconf->bss[j];
127
+		hostapd_reload_bss(hapd);
128
+	}
129
+
130
+	hostapd_config_free(oldconf);
131
+
132
+
133
+	return 0;
134
+}
135
+
136
+
137
+static void hostapd_broadcast_key_clear_iface(struct hostapd_data *hapd,
138
+					      char *ifname)
139
+{
140
+	int i;
141
+
142
+	for (i = 0; i < NUM_WEP_KEYS; i++) {
143
+		if (hostapd_drv_set_key(ifname, hapd, WPA_ALG_NONE, NULL, i,
144
+					0, NULL, 0, NULL, 0)) {
145
+			wpa_printf(MSG_DEBUG, "Failed to clear default "
146
+				   "encryption keys (ifname=%s keyidx=%d)",
147
+				   ifname, i);
148
+		}
149
+	}
150
+#ifdef CONFIG_IEEE80211W
151
+	if (hapd->conf->ieee80211w) {
152
+		for (i = NUM_WEP_KEYS; i < NUM_WEP_KEYS + 2; i++) {
153
+			if (hostapd_drv_set_key(ifname, hapd, WPA_ALG_NONE,
154
+						NULL, i, 0, NULL,
155
+						0, NULL, 0)) {
156
+				wpa_printf(MSG_DEBUG, "Failed to clear "
157
+					   "default mgmt encryption keys "
158
+					   "(ifname=%s keyidx=%d)", ifname, i);
159
+			}
160
+		}
161
+	}
162
+#endif /* CONFIG_IEEE80211W */
163
+}
164
+
165
+
166
+static int hostapd_broadcast_wep_clear(struct hostapd_data *hapd)
167
+{
168
+	hostapd_broadcast_key_clear_iface(hapd, hapd->conf->iface);
169
+	return 0;
170
+}
171
+
172
+
173
+static int hostapd_broadcast_wep_set(struct hostapd_data *hapd)
174
+{
175
+	int errors = 0, idx;
176
+	struct hostapd_ssid *ssid = &hapd->conf->ssid;
177
+
178
+	idx = ssid->wep.idx;
179
+	if (ssid->wep.default_len &&
180
+	    hostapd_drv_set_key(hapd->conf->iface,
181
+				hapd, WPA_ALG_WEP, broadcast_ether_addr, idx,
182
+				1, NULL, 0, ssid->wep.key[idx],
183
+				ssid->wep.len[idx])) {
184
+		wpa_printf(MSG_WARNING, "Could not set WEP encryption.");
185
+		errors++;
186
+	}
187
+
188
+	if (ssid->dyn_vlan_keys) {
189
+		size_t i;
190
+		for (i = 0; i <= ssid->max_dyn_vlan_keys; i++) {
191
+			const char *ifname;
192
+			struct hostapd_wep_keys *key = ssid->dyn_vlan_keys[i];
193
+			if (key == NULL)
194
+				continue;
195
+			ifname = hostapd_get_vlan_id_ifname(hapd->conf->vlan,
196
+							    i);
197
+			if (ifname == NULL)
198
+				continue;
199
+
200
+			idx = key->idx;
201
+			if (hostapd_drv_set_key(ifname, hapd, WPA_ALG_WEP,
202
+						broadcast_ether_addr, idx, 1,
203
+						NULL, 0, key->key[idx],
204
+						key->len[idx])) {
205
+				wpa_printf(MSG_WARNING, "Could not set "
206
+					   "dynamic VLAN WEP encryption.");
207
+				errors++;
208
+			}
209
+		}
210
+	}
211
+
212
+	return errors;
213
+}
214
+
215
+/**
216
+ * hostapd_cleanup - Per-BSS cleanup (deinitialization)
217
+ * @hapd: Pointer to BSS data
218
+ *
219
+ * This function is used to free all per-BSS data structures and resources.
220
+ * This gets called in a loop for each BSS between calls to
221
+ * hostapd_cleanup_iface_pre() and hostapd_cleanup_iface() when an interface
222
+ * is deinitialized. Most of the modules that are initialized in
223
+ * hostapd_setup_bss() are deinitialized here.
224
+ */
225
+static void hostapd_cleanup(struct hostapd_data *hapd)
226
+{
227
+	if (hapd->iface->ctrl_iface_deinit)
228
+		hapd->iface->ctrl_iface_deinit(hapd);
229
+
230
+	iapp_deinit(hapd->iapp);
231
+	hapd->iapp = NULL;
232
+	accounting_deinit(hapd);
233
+	hostapd_deinit_wpa(hapd);
234
+	vlan_deinit(hapd);
235
+	hostapd_acl_deinit(hapd);
236
+#ifndef CONFIG_NO_RADIUS
237
+	radius_client_deinit(hapd->radius);
238
+	hapd->radius = NULL;
239
+#endif /* CONFIG_NO_RADIUS */
240
+
241
+	hostapd_deinit_wps(hapd);
242
+
243
+	authsrv_deinit(hapd);
244
+
245
+	if (hapd->interface_added &&
246
+	    hostapd_if_remove(hapd, WPA_IF_AP_BSS, hapd->conf->iface)) {
247
+		wpa_printf(MSG_WARNING, "Failed to remove BSS interface %s",
248
+			   hapd->conf->iface);
249
+	}
250
+
251
+	os_free(hapd->probereq_cb);
252
+	hapd->probereq_cb = NULL;
253
+
254
+#ifdef CONFIG_P2P
255
+	wpabuf_free(hapd->p2p_beacon_ie);
256
+	hapd->p2p_beacon_ie = NULL;
257
+	wpabuf_free(hapd->p2p_probe_resp_ie);
258
+	hapd->p2p_probe_resp_ie = NULL;
259
+#endif /* CONFIG_P2P */
260
+}
261
+
262
+
263
+/**
264
+ * hostapd_cleanup_iface_pre - Preliminary per-interface cleanup
265
+ * @iface: Pointer to interface data
266
+ *
267
+ * This function is called before per-BSS data structures are deinitialized
268
+ * with hostapd_cleanup().
269
+ */
270
+static void hostapd_cleanup_iface_pre(struct hostapd_iface *iface)
271
+{
272
+}
273
+
274
+
275
+/**
276
+ * hostapd_cleanup_iface - Complete per-interface cleanup
277
+ * @iface: Pointer to interface data
278
+ *
279
+ * This function is called after per-BSS data structures are deinitialized
280
+ * with hostapd_cleanup().
281
+ */
282
+static void hostapd_cleanup_iface(struct hostapd_iface *iface)
283
+{
284
+	hostapd_free_hw_features(iface->hw_features, iface->num_hw_features);
285
+	iface->hw_features = NULL;
286
+	os_free(iface->current_rates);
287
+	iface->current_rates = NULL;
288
+	ap_list_deinit(iface);
289
+	hostapd_config_free(iface->conf);
290
+	iface->conf = NULL;
291
+
292
+	os_free(iface->config_fname);
293
+	os_free(iface->bss);
294
+	os_free(iface);
295
+}
296
+
297
+
298
+static int hostapd_setup_encryption(char *iface, struct hostapd_data *hapd)
299
+{
300
+	int i;
301
+
302
+	hostapd_broadcast_wep_set(hapd);
303
+
304
+	if (hapd->conf->ssid.wep.default_len) {
305
+		hostapd_set_privacy(hapd, 1);
306
+		return 0;
307
+	}
308
+
309
+	for (i = 0; i < 4; i++) {
310
+		if (hapd->conf->ssid.wep.key[i] &&
311
+		    hostapd_drv_set_key(iface, hapd, WPA_ALG_WEP, NULL, i,
312
+					i == hapd->conf->ssid.wep.idx, NULL, 0,
313
+					hapd->conf->ssid.wep.key[i],
314
+					hapd->conf->ssid.wep.len[i])) {
315
+			wpa_printf(MSG_WARNING, "Could not set WEP "
316
+				   "encryption.");
317
+			return -1;
318
+		}
319
+		if (hapd->conf->ssid.wep.key[i] &&
320
+		    i == hapd->conf->ssid.wep.idx)
321
+			hostapd_set_privacy(hapd, 1);
322
+	}
323
+
324
+	return 0;
325
+}
326
+
327
+
328
+static int hostapd_flush_old_stations(struct hostapd_data *hapd)
329
+{
330
+	int ret = 0;
331
+	u8 addr[ETH_ALEN];
332
+
333
+	if (hostapd_drv_none(hapd) || hapd->drv_priv == NULL)
334
+		return 0;
335
+
336
+	wpa_printf(MSG_DEBUG, "Flushing old station entries");
337
+	if (hostapd_flush(hapd)) {
338
+		wpa_printf(MSG_WARNING, "Could not connect to kernel driver.");
339
+		ret = -1;
340
+	}
341
+	wpa_printf(MSG_DEBUG, "Deauthenticate all stations");
342
+	os_memset(addr, 0xff, ETH_ALEN);
343
+	hostapd_drv_sta_deauth(hapd, addr, WLAN_REASON_PREV_AUTH_NOT_VALID);
344
+	hostapd_free_stas(hapd);
345
+
346
+	return ret;
347
+}
348
+
349
+
350
+/**
351
+ * hostapd_validate_bssid_configuration - Validate BSSID configuration
352
+ * @iface: Pointer to interface data
353
+ * Returns: 0 on success, -1 on failure
354
+ *
355
+ * This function is used to validate that the configured BSSIDs are valid.
356
+ */
357
+static int hostapd_validate_bssid_configuration(struct hostapd_iface *iface)
358
+{
359
+	u8 mask[ETH_ALEN] = { 0 };
360
+	struct hostapd_data *hapd = iface->bss[0];
361
+	unsigned int i = iface->conf->num_bss, bits = 0, j;
362
+	int res;
363
+	int auto_addr = 0;
364
+
365
+	if (hostapd_drv_none(hapd))
366
+		return 0;
367
+
368
+	/* Generate BSSID mask that is large enough to cover the BSSIDs. */
369
+
370
+	/* Determine the bits necessary to cover the number of BSSIDs. */
371
+	for (i--; i; i >>= 1)
372
+		bits++;
373
+
374
+	/* Determine the bits necessary to any configured BSSIDs,
375
+	   if they are higher than the number of BSSIDs. */
376
+	for (j = 0; j < iface->conf->num_bss; j++) {
377
+		if (hostapd_mac_comp_empty(iface->conf->bss[j].bssid) == 0) {
378
+			if (j)
379
+				auto_addr++;
380
+			continue;
381
+		}
382
+
383
+		for (i = 0; i < ETH_ALEN; i++) {
384
+			mask[i] |=
385
+				iface->conf->bss[j].bssid[i] ^
386
+				hapd->own_addr[i];
387
+		}
388
+	}
389
+
390
+	if (!auto_addr)
391
+		goto skip_mask_ext;
392
+
393
+	for (i = 0; i < ETH_ALEN && mask[i] == 0; i++)
394
+		;
395
+	j = 0;
396
+	if (i < ETH_ALEN) {
397
+		j = (5 - i) * 8;
398
+
399
+		while (mask[i] != 0) {
400
+			mask[i] >>= 1;
401
+			j++;
402
+		}
403
+	}
404
+
405
+	if (bits < j)
406
+		bits = j;
407
+
408
+	if (bits > 40) {
409
+		wpa_printf(MSG_ERROR, "Too many bits in the BSSID mask (%u)",
410
+			   bits);
411
+		return -1;
412
+	}
413
+
414
+	os_memset(mask, 0xff, ETH_ALEN);
415
+	j = bits / 8;
416
+	for (i = 5; i > 5 - j; i--)
417
+		mask[i] = 0;
418
+	j = bits % 8;
419
+	while (j--)
420
+		mask[i] <<= 1;
421
+
422
+skip_mask_ext:
423
+	wpa_printf(MSG_DEBUG, "BSS count %lu, BSSID mask " MACSTR " (%d bits)",
424
+		   (unsigned long) iface->conf->num_bss, MAC2STR(mask), bits);
425
+
426
+	res = hostapd_valid_bss_mask(hapd, hapd->own_addr, mask);
427
+	if (res == 0)
428
+		return 0;
429
+
430
+	if (res < 0) {
431
+		wpa_printf(MSG_ERROR, "Driver did not accept BSSID mask "
432
+			   MACSTR " for start address " MACSTR ".",
433
+			   MAC2STR(mask), MAC2STR(hapd->own_addr));
434
+		return -1;
435
+	}
436
+
437
+	if (!auto_addr)
438
+		return 0;
439
+
440
+	for (i = 0; i < ETH_ALEN; i++) {
441
+		if ((hapd->own_addr[i] & mask[i]) != hapd->own_addr[i]) {
442
+			wpa_printf(MSG_ERROR, "Invalid BSSID mask " MACSTR
443
+				   " for start address " MACSTR ".",
444
+				   MAC2STR(mask), MAC2STR(hapd->own_addr));
445
+			wpa_printf(MSG_ERROR, "Start address must be the "
446
+				   "first address in the block (i.e., addr "
447
+				   "AND mask == addr).");
448
+			return -1;
449
+		}
450
+	}
451
+
452
+	return 0;
453
+}
454
+
455
+
456
+static int mac_in_conf(struct hostapd_config *conf, const void *a)
457
+{
458
+	size_t i;
459
+
460
+	for (i = 0; i < conf->num_bss; i++) {
461
+		if (hostapd_mac_comp(conf->bss[i].bssid, a) == 0) {
462
+			return 1;
463
+		}
464
+	}
465
+
466
+	return 0;
467
+}
468
+
469
+
470
+
471
+
472
+/**
473
+ * hostapd_setup_bss - Per-BSS setup (initialization)
474
+ * @hapd: Pointer to BSS data
475
+ * @first: Whether this BSS is the first BSS of an interface
476
+ *
477
+ * This function is used to initialize all per-BSS data structures and
478
+ * resources. This gets called in a loop for each BSS when an interface is
479
+ * initialized. Most of the modules that are initialized here will be
480
+ * deinitialized in hostapd_cleanup().
481
+ */
482
+static int hostapd_setup_bss(struct hostapd_data *hapd, int first)
483
+{
484
+	struct hostapd_bss_config *conf = hapd->conf;
485
+	u8 ssid[HOSTAPD_MAX_SSID_LEN + 1];
486
+	int ssid_len, set_ssid;
487
+	char force_ifname[IFNAMSIZ];
488
+	u8 if_addr[ETH_ALEN];
489
+
490
+	if (!first) {
491
+		if (hostapd_mac_comp_empty(hapd->conf->bssid) == 0) {
492
+			/* Allocate the next available BSSID. */
493
+			do {
494
+				inc_byte_array(hapd->own_addr, ETH_ALEN);
495
+			} while (mac_in_conf(hapd->iconf, hapd->own_addr));
496
+		} else {
497
+			/* Allocate the configured BSSID. */
498
+			os_memcpy(hapd->own_addr, hapd->conf->bssid, ETH_ALEN);
499
+
500
+			if (hostapd_mac_comp(hapd->own_addr,
501
+					     hapd->iface->bss[0]->own_addr) ==
502
+			    0) {
503
+				wpa_printf(MSG_ERROR, "BSS '%s' may not have "
504
+					   "BSSID set to the MAC address of "
505
+					   "the radio", hapd->conf->iface);
506
+				return -1;
507
+			}
508
+		}
509
+
510
+		hapd->interface_added = 1;
511
+		if (hostapd_if_add(hapd->iface->bss[0], WPA_IF_AP_BSS,
512
+				   hapd->conf->iface, hapd->own_addr, hapd,
513
+				   &hapd->drv_priv, force_ifname, if_addr,
514
+				   hapd->conf->bridge[0] ? hapd->conf->bridge :
515
+				   NULL)) {
516
+			wpa_printf(MSG_ERROR, "Failed to add BSS (BSSID="
517
+				   MACSTR ")", MAC2STR(hapd->own_addr));
518
+			return -1;
519
+		}
520
+	}
521
+
522
+	if (conf->wmm_enabled < 0)
523
+		conf->wmm_enabled = hapd->iconf->ieee80211n;
524
+
525
+	hostapd_flush_old_stations(hapd);
526
+	hostapd_set_privacy(hapd, 0);
527
+
528
+	hostapd_broadcast_wep_clear(hapd);
529
+	if (hostapd_setup_encryption(hapd->conf->iface, hapd))
530
+		return -1;
531
+
532
+	/*
533
+	 * Fetch the SSID from the system and use it or,
534
+	 * if one was specified in the config file, verify they
535
+	 * match.
536
+	 */
537
+	ssid_len = hostapd_get_ssid(hapd, ssid, sizeof(ssid));
538
+	if (ssid_len < 0) {
539
+		wpa_printf(MSG_ERROR, "Could not read SSID from system");
540
+		return -1;
541
+	}
542
+	if (conf->ssid.ssid_set) {
543
+		/*
544
+		 * If SSID is specified in the config file and it differs
545
+		 * from what is being used then force installation of the
546
+		 * new SSID.
547
+		 */
548
+		set_ssid = (conf->ssid.ssid_len != (size_t) ssid_len ||
549
+			    os_memcmp(conf->ssid.ssid, ssid, ssid_len) != 0);
550
+	} else {
551
+		/*
552
+		 * No SSID in the config file; just use the one we got
553
+		 * from the system.
554
+		 */
555
+		set_ssid = 0;
556
+		conf->ssid.ssid_len = ssid_len;
557
+		os_memcpy(conf->ssid.ssid, ssid, conf->ssid.ssid_len);
558
+		conf->ssid.ssid[conf->ssid.ssid_len] = '\0';
559
+	}
560
+
561
+	if (!hostapd_drv_none(hapd)) {
562
+		wpa_printf(MSG_ERROR, "Using interface %s with hwaddr " MACSTR
563
+			   " and ssid '%s'",
564
+			   hapd->conf->iface, MAC2STR(hapd->own_addr),
565
+			   hapd->conf->ssid.ssid);
566
+	}
567
+
568
+	if (hostapd_setup_wpa_psk(conf)) {
569
+		wpa_printf(MSG_ERROR, "WPA-PSK setup failed.");
570
+		return -1;
571
+	}
572
+
573
+	/* Set SSID for the kernel driver (to be used in beacon and probe
574
+	 * response frames) */
575
+	if (set_ssid && hostapd_set_ssid(hapd, (u8 *) conf->ssid.ssid,
576
+					 conf->ssid.ssid_len)) {
577
+		wpa_printf(MSG_ERROR, "Could not set SSID for kernel driver");
578
+		return -1;
579
+	}
580
+
581
+	if (wpa_debug_level == MSG_MSGDUMP)
582
+		conf->radius->msg_dumps = 1;
583
+#ifndef CONFIG_NO_RADIUS
584
+	hapd->radius = radius_client_init(hapd, conf->radius);
585
+	if (hapd->radius == NULL) {
586
+		wpa_printf(MSG_ERROR, "RADIUS client initialization failed.");
587
+		return -1;
588
+	}
589
+#endif /* CONFIG_NO_RADIUS */
590
+
591
+	if (hostapd_acl_init(hapd)) {
592
+		wpa_printf(MSG_ERROR, "ACL initialization failed.");
593
+		return -1;
594
+	}
595
+	if (hostapd_init_wps(hapd, conf))
596
+		return -1;
597
+
598
+	if (authsrv_init(hapd) < 0)
599
+		return -1;
600
+
601
+	if (ieee802_1x_init(hapd)) {
602
+		wpa_printf(MSG_ERROR, "IEEE 802.1X initialization failed.");
603
+		return -1;
604
+	}
605
+
606
+	if (hapd->conf->wpa && hostapd_setup_wpa(hapd))
607
+		return -1;
608
+
609
+	if (accounting_init(hapd)) {
610
+		wpa_printf(MSG_ERROR, "Accounting initialization failed.");
611
+		return -1;
612
+	}
613
+
614
+	if (hapd->conf->ieee802_11f &&
615
+	    (hapd->iapp = iapp_init(hapd, hapd->conf->iapp_iface)) == NULL) {
616
+		wpa_printf(MSG_ERROR, "IEEE 802.11F (IAPP) initialization "
617
+			   "failed.");
618
+		return -1;
619
+	}
620
+
621
+	if (hapd->iface->ctrl_iface_init &&
622
+	    hapd->iface->ctrl_iface_init(hapd)) {
623
+		wpa_printf(MSG_ERROR, "Failed to setup control interface");
624
+		return -1;
625
+	}
626
+
627
+	if (!hostapd_drv_none(hapd) && vlan_init(hapd)) {
628
+		wpa_printf(MSG_ERROR, "VLAN initialization failed.");
629
+		return -1;
630
+	}
631
+
632
+	ieee802_11_set_beacon(hapd);
633
+
634
+	if (hapd->driver && hapd->driver->set_operstate)
635
+		hapd->driver->set_operstate(hapd->drv_priv, 1);
636
+
637
+	return 0;
638
+}
639
+
640
+
641
+static void hostapd_tx_queue_params(struct hostapd_iface *iface)
642
+{
643
+	struct hostapd_data *hapd = iface->bss[0];
644
+	int i;
645
+	struct hostapd_tx_queue_params *p;
646
+
647
+	for (i = 0; i < NUM_TX_QUEUES; i++) {
648
+		p = &iface->conf->tx_queue[i];
649
+
650
+		if (hostapd_set_tx_queue_params(hapd, i, p->aifs, p->cwmin,
651
+						p->cwmax, p->burst)) {
652
+			wpa_printf(MSG_DEBUG, "Failed to set TX queue "
653
+				   "parameters for queue %d.", i);
654
+			/* Continue anyway */
655
+		}
656
+	}
657
+}
658
+
659
+
660
+static int setup_interface(struct hostapd_iface *iface)
661
+{
662
+	struct hostapd_data *hapd = iface->bss[0];
663
+	size_t i;
664
+	char country[4];
665
+
666
+	/*
667
+	 * Make sure that all BSSes get configured with a pointer to the same
668
+	 * driver interface.
669
+	 */
670
+	for (i = 1; i < iface->num_bss; i++) {
671
+		iface->bss[i]->driver = hapd->driver;
672
+		iface->bss[i]->drv_priv = hapd->drv_priv;
673
+	}
674
+
675
+	if (hostapd_validate_bssid_configuration(iface))
676
+		return -1;
677
+
678
+	if (hapd->iconf->country[0] && hapd->iconf->country[1]) {
679
+		os_memcpy(country, hapd->iconf->country, 3);
680
+		country[3] = '\0';
681
+		if (hostapd_set_country(hapd, country) < 0) {
682
+			wpa_printf(MSG_ERROR, "Failed to set country code");
683
+			return -1;
684
+		}
685
+	}
686
+
687
+	if (hostapd_get_hw_features(iface)) {
688
+		/* Not all drivers support this yet, so continue without hw
689
+		 * feature data. */
690
+	} else {
691
+		int ret = hostapd_select_hw_mode(iface);
692
+		if (ret < 0) {
693
+			wpa_printf(MSG_ERROR, "Could not select hw_mode and "
694
+				   "channel. (%d)", ret);
695
+			return -1;
696
+		}
697
+		ret = hostapd_check_ht_capab(iface);
698
+		if (ret < 0)
699
+			return -1;
700
+		if (ret == 1) {
701
+			wpa_printf(MSG_DEBUG, "Interface initialization will "
702
+				   "be completed in a callback");
703
+			return 0;
704
+		}
705
+	}
706
+	return hostapd_setup_interface_complete(iface, 0);
707
+}
708
+
709
+
710
+int hostapd_setup_interface_complete(struct hostapd_iface *iface, int err)
711
+{
712
+	struct hostapd_data *hapd = iface->bss[0];
713
+	size_t j;
714
+	u8 *prev_addr;
715
+
716
+	if (err) {
717
+		wpa_printf(MSG_ERROR, "Interface initialization failed");
718
+		eloop_terminate();
719
+		return -1;
720
+	}
721
+
722
+	wpa_printf(MSG_DEBUG, "Completing interface initialization");
723
+	if (hapd->iconf->channel) {
724
+		iface->freq = hostapd_hw_get_freq(hapd, hapd->iconf->channel);
725
+		wpa_printf(MSG_DEBUG, "Mode: %s  Channel: %d  "
726
+			   "Frequency: %d MHz",
727
+			   hostapd_hw_mode_txt(hapd->iconf->hw_mode),
728
+			   hapd->iconf->channel, iface->freq);
729
+
730
+		if (hostapd_set_freq(hapd, hapd->iconf->hw_mode, iface->freq,
731
+				     hapd->iconf->channel,
732
+				     hapd->iconf->ieee80211n,
733
+				     hapd->iconf->secondary_channel)) {
734
+			wpa_printf(MSG_ERROR, "Could not set channel for "
735
+				   "kernel driver");
736
+			return -1;
737
+		}
738
+	}
739
+
740
+	if (iface->current_mode) {
741
+		if (hostapd_prepare_rates(hapd, iface->current_mode)) {
742
+			wpa_printf(MSG_ERROR, "Failed to prepare rates "
743
+				   "table.");
744
+			hostapd_logger(hapd, NULL, HOSTAPD_MODULE_IEEE80211,
745
+				       HOSTAPD_LEVEL_WARNING,
746
+				       "Failed to prepare rates table.");
747
+			return -1;
748
+		}
749
+	}
750
+
751
+	if (hapd->iconf->rts_threshold > -1 &&
752
+	    hostapd_set_rts(hapd, hapd->iconf->rts_threshold)) {
753
+		wpa_printf(MSG_ERROR, "Could not set RTS threshold for "
754
+			   "kernel driver");
755
+		return -1;
756
+	}
757
+
758
+	if (hapd->iconf->fragm_threshold > -1 &&
759
+	    hostapd_set_frag(hapd, hapd->iconf->fragm_threshold)) {
760
+		wpa_printf(MSG_ERROR, "Could not set fragmentation threshold "
761
+			   "for kernel driver");
762
+		return -1;
763
+	}
764
+
765
+	prev_addr = hapd->own_addr;
766
+
767
+	for (j = 0; j < iface->num_bss; j++) {
768
+		hapd = iface->bss[j];
769
+		if (j)
770
+			os_memcpy(hapd->own_addr, prev_addr, ETH_ALEN);
771
+		if (hostapd_setup_bss(hapd, j == 0))
772
+			return -1;
773
+		if (hostapd_mac_comp_empty(hapd->conf->bssid) == 0)
774
+			prev_addr = hapd->own_addr;
775
+	}
776
+
777
+	hostapd_tx_queue_params(iface);
778
+
779
+	ap_list_init(iface);
780
+
781
+	if (hostapd_driver_commit(hapd) < 0) {
782
+		wpa_printf(MSG_ERROR, "%s: Failed to commit driver "
783
+			   "configuration", __func__);
784
+		return -1;
785
+	}
786
+
787
+	if (hapd->setup_complete_cb)
788
+		hapd->setup_complete_cb(hapd->setup_complete_cb_ctx);
789
+
790
+	wpa_printf(MSG_DEBUG, "%s: Setup of interface done.",
791
+		   iface->bss[0]->conf->iface);
792
+
793
+	return 0;
794
+}
795
+
796
+
797
+/**
798
+ * hostapd_setup_interface - Setup of an interface
799
+ * @iface: Pointer to interface data.
800
+ * Returns: 0 on success, -1 on failure
801
+ *
802
+ * Initializes the driver interface, validates the configuration,
803
+ * and sets driver parameters based on the configuration.
804
+ * Flushes old stations, sets the channel, encryption,
805
+ * beacons, and WDS links based on the configuration.
806
+ */
807
+int hostapd_setup_interface(struct hostapd_iface *iface)
808
+{
809
+	int ret;
810
+
811
+	ret = setup_interface(iface);
812
+	if (ret) {
813
+		wpa_printf(MSG_ERROR, "%s: Unable to setup interface.",
814
+			   iface->bss[0]->conf->iface);
815
+		return -1;
816
+	}
817
+
818
+	return 0;
819
+}
820
+
821
+
822
+/**
823
+ * hostapd_alloc_bss_data - Allocate and initialize per-BSS data
824
+ * @hapd_iface: Pointer to interface data
825
+ * @conf: Pointer to per-interface configuration
826
+ * @bss: Pointer to per-BSS configuration for this BSS
827
+ * Returns: Pointer to allocated BSS data
828
+ *
829
+ * This function is used to allocate per-BSS data structure. This data will be
830
+ * freed after hostapd_cleanup() is called for it during interface
831
+ * deinitialization.
832
+ */
833
+struct hostapd_data *
834
+hostapd_alloc_bss_data(struct hostapd_iface *hapd_iface,
835
+		       struct hostapd_config *conf,
836
+		       struct hostapd_bss_config *bss)
837
+{
838
+	struct hostapd_data *hapd;
839
+
840
+	hapd = os_zalloc(sizeof(*hapd));
841
+	if (hapd == NULL)
842
+		return NULL;
843
+
844
+	hapd->new_assoc_sta_cb = hostapd_new_assoc_sta;
845
+	hapd->iconf = conf;
846
+	hapd->conf = bss;
847
+	hapd->iface = hapd_iface;
848
+	hapd->driver = hapd->iconf->driver;
849
+
850
+	return hapd;
851
+}
852
+
853
+
854
+void hostapd_interface_deinit(struct hostapd_iface *iface)
855
+{
856
+	size_t j;
857
+
858
+	if (iface == NULL)
859
+		return;
860
+
861
+	hostapd_cleanup_iface_pre(iface);
862
+	for (j = 0; j < iface->num_bss; j++) {
863
+		struct hostapd_data *hapd = iface->bss[j];
864
+		hostapd_free_stas(hapd);
865
+		hostapd_flush_old_stations(hapd);
866
+		hostapd_cleanup(hapd);
867
+	}
868
+}
869
+
870
+
871
+void hostapd_interface_free(struct hostapd_iface *iface)
872
+{
873
+	size_t j;
874
+	for (j = 0; j < iface->num_bss; j++)
875
+		os_free(iface->bss[j]);
876
+	hostapd_cleanup_iface(iface);
877
+}
878
+
879
+
880
+/**
881
+ * hostapd_new_assoc_sta - Notify that a new station associated with the AP
882
+ * @hapd: Pointer to BSS data
883
+ * @sta: Pointer to the associated STA data
884
+ * @reassoc: 1 to indicate this was a re-association; 0 = first association
885
+ *
886
+ * This function will be called whenever a station associates with the AP. It
887
+ * can be called from ieee802_11.c for drivers that export MLME to hostapd and
888
+ * from drv_callbacks.c based on driver events for drivers that take care of
889
+ * management frames (IEEE 802.11 authentication and association) internally.
890
+ */
891
+void hostapd_new_assoc_sta(struct hostapd_data *hapd, struct sta_info *sta,
892
+			   int reassoc)
893
+{
894
+	if (hapd->tkip_countermeasures) {
895
+		hostapd_drv_sta_deauth(hapd, sta->addr,
896
+				       WLAN_REASON_MICHAEL_MIC_FAILURE);
897
+		return;
898
+	}
899
+
900
+	hostapd_prune_associations(hapd, sta->addr);
901
+
902
+	/* IEEE 802.11F (IAPP) */
903
+	if (hapd->conf->ieee802_11f)
904
+		iapp_new_station(hapd->iapp, sta);
905
+
906
+#ifdef CONFIG_P2P
907
+	if (sta->p2p_ie == NULL && !sta->no_p2p_set) {
908
+		sta->no_p2p_set = 1;
909
+		hapd->num_sta_no_p2p++;
910
+		if (hapd->num_sta_no_p2p == 1)
911
+			hostapd_p2p_non_p2p_sta_connected(hapd);
912
+	}
913
+#endif /* CONFIG_P2P */
914
+
915
+	/* Start accounting here, if IEEE 802.1X and WPA are not used.
916
+	 * IEEE 802.1X/WPA code will start accounting after the station has
917
+	 * been authorized. */
918
+	if (!hapd->conf->ieee802_1x && !hapd->conf->wpa)
919
+		accounting_sta_start(hapd, sta);
920
+
921
+	/* Start IEEE 802.1X authentication process for new stations */
922
+	ieee802_1x_new_station(hapd, sta);
923
+	if (reassoc) {
924
+		if (sta->auth_alg != WLAN_AUTH_FT &&
925
+		    !(sta->flags & (WLAN_STA_WPS | WLAN_STA_MAYBE_WPS)))
926
+			wpa_auth_sm_event(sta->wpa_sm, WPA_REAUTH);
927
+	} else
928
+		wpa_auth_sta_associated(hapd->wpa_auth, sta->wpa_sm);
929
+}

+ 262
- 0
src/ap/hostapd.h Näytä tiedosto

@@ -0,0 +1,262 @@
1
+/*
2
+ * hostapd / Initialization and configuration
3
+ * Copyright (c) 2002-2009, Jouni Malinen <j@w1.fi>
4
+ *
5
+ * This program is free software; you can redistribute it and/or modify
6
+ * it under the terms of the GNU General Public License version 2 as
7
+ * published by the Free Software Foundation.
8
+ *
9
+ * Alternatively, this software may be distributed under the terms of BSD
10
+ * license.
11
+ *
12
+ * See README and COPYING for more details.
13
+ */
14
+
15
+#ifndef HOSTAPD_H
16
+#define HOSTAPD_H
17
+
18
+#include "common/defs.h"
19
+
20
+struct wpa_driver_ops;
21
+struct wpa_ctrl_dst;
22
+struct radius_server_data;
23
+struct upnp_wps_device_sm;
24
+struct hapd_interfaces;
25
+struct hostapd_data;
26
+struct sta_info;
27
+struct hostap_sta_driver_data;
28
+struct ieee80211_ht_capabilities;
29
+struct full_dynamic_vlan;
30
+enum wps_event;
31
+union wps_event_data;
32
+
33
+struct hostapd_probereq_cb {
34
+	int (*cb)(void *ctx, const u8 *sa, const u8 *ie, size_t ie_len);
35
+	void *ctx;
36
+};
37
+
38
+#define HOSTAPD_RATE_BASIC 0x00000001
39
+
40
+struct hostapd_rate_data {
41
+	int rate; /* rate in 100 kbps */
42
+	int flags; /* HOSTAPD_RATE_ flags */
43
+};
44
+
45
+struct hostapd_frame_info {
46
+	u32 channel;
47
+	u32 datarate;
48
+	u32 ssi_signal;
49
+};
50
+
51
+
52
+/**
53
+ * struct hostapd_data - hostapd per-BSS data structure
54
+ */
55
+struct hostapd_data {
56
+	struct hostapd_iface *iface;
57
+	struct hostapd_config *iconf;
58
+	struct hostapd_bss_config *conf;
59
+	int interface_added; /* virtual interface added for this BSS */
60
+
61
+	u8 own_addr[ETH_ALEN];
62
+
63
+	int num_sta; /* number of entries in sta_list */
64
+	struct sta_info *sta_list; /* STA info list head */
65
+#define STA_HASH_SIZE 256
66
+#define STA_HASH(sta) (sta[5])
67
+	struct sta_info *sta_hash[STA_HASH_SIZE];
68
+
69
+	/*
70
+	 * Bitfield for indicating which AIDs are allocated. Only AID values
71
+	 * 1-2007 are used and as such, the bit at index 0 corresponds to AID
72
+	 * 1.
73
+	 */
74
+#define AID_WORDS ((2008 + 31) / 32)
75
+	u32 sta_aid[AID_WORDS];
76
+
77
+	const struct wpa_driver_ops *driver;
78
+	void *drv_priv;
79
+
80
+	void (*new_assoc_sta_cb)(struct hostapd_data *hapd,
81
+				 struct sta_info *sta, int reassoc);
82
+
83
+	void *msg_ctx; /* ctx for wpa_msg() calls */
84
+
85
+	struct radius_client_data *radius;
86
+	u32 acct_session_id_hi, acct_session_id_lo;
87
+
88
+	struct iapp_data *iapp;
89
+
90
+	struct hostapd_cached_radius_acl *acl_cache;
91
+	struct hostapd_acl_query_data *acl_queries;
92
+
93
+	struct wpa_authenticator *wpa_auth;
94
+	struct eapol_authenticator *eapol_auth;
95
+
96
+	struct rsn_preauth_interface *preauth_iface;
97
+	time_t michael_mic_failure;
98
+	int michael_mic_failures;
99
+	int tkip_countermeasures;
100
+
101
+	int ctrl_sock;
102
+	struct wpa_ctrl_dst *ctrl_dst;
103
+
104
+	void *ssl_ctx;
105
+	void *eap_sim_db_priv;
106
+	struct radius_server_data *radius_srv;
107
+
108
+	int parameter_set_count;
109
+
110
+#ifdef CONFIG_FULL_DYNAMIC_VLAN
111
+	struct full_dynamic_vlan *full_dynamic_vlan;
112
+#endif /* CONFIG_FULL_DYNAMIC_VLAN */
113
+
114
+	struct l2_packet_data *l2;
115
+	struct wps_context *wps;
116
+
117
+	struct wpabuf *wps_beacon_ie;
118
+	struct wpabuf *wps_probe_resp_ie;
119
+#ifdef CONFIG_WPS
120
+	unsigned int ap_pin_failures;
121
+	struct upnp_wps_device_sm *wps_upnp;
122
+	unsigned int ap_pin_lockout_time;
123
+#endif /* CONFIG_WPS */
124
+
125
+	struct hostapd_probereq_cb *probereq_cb;
126
+	size_t num_probereq_cb;
127
+
128
+	void (*public_action_cb)(void *ctx, const u8 *buf, size_t len,
129
+				 int freq);
130
+	void *public_action_cb_ctx;
131
+
132
+	int (*vendor_action_cb)(void *ctx, const u8 *buf, size_t len,
133
+				int freq);
134
+	void *vendor_action_cb_ctx;
135
+
136
+	void (*wps_reg_success_cb)(void *ctx, const u8 *mac_addr,
137
+				   const u8 *uuid_e);
138
+	void *wps_reg_success_cb_ctx;
139
+
140
+	void (*wps_event_cb)(void *ctx, enum wps_event event,
141
+			     union wps_event_data *data);
142
+	void *wps_event_cb_ctx;
143
+
144
+	void (*sta_authorized_cb)(void *ctx, const u8 *mac_addr,
145
+				  int authorized);
146
+	void *sta_authorized_cb_ctx;
147
+
148
+	void (*setup_complete_cb)(void *ctx);
149
+	void *setup_complete_cb_ctx;
150
+
151
+#ifdef CONFIG_P2P
152
+	struct p2p_data *p2p;
153
+	struct p2p_group *p2p_group;
154
+	struct wpabuf *p2p_beacon_ie;
155
+	struct wpabuf *p2p_probe_resp_ie;
156
+
157
+	/* Number of non-P2P association stations */
158
+	int num_sta_no_p2p;
159
+
160
+	/* Periodic NoA (used only when no non-P2P clients in the group) */
161
+	int noa_enabled;
162
+	int noa_start;
163
+	int noa_duration;
164
+#endif /* CONFIG_P2P */
165
+};
166
+
167
+
168
+/**
169
+ * struct hostapd_iface - hostapd per-interface data structure
170
+ */
171
+struct hostapd_iface {
172
+	struct hapd_interfaces *interfaces;
173
+	void *owner;
174
+	int (*reload_config)(struct hostapd_iface *iface);
175
+	struct hostapd_config * (*config_read_cb)(const char *config_fname);
176
+	char *config_fname;
177
+	struct hostapd_config *conf;
178
+
179
+	size_t num_bss;
180
+	struct hostapd_data **bss;
181
+
182
+	int num_ap; /* number of entries in ap_list */
183
+	struct ap_info *ap_list; /* AP info list head */
184
+	struct ap_info *ap_hash[STA_HASH_SIZE];
185
+	struct ap_info *ap_iter_list;
186
+
187
+	unsigned int drv_flags;
188
+	struct hostapd_hw_modes *hw_features;
189
+	int num_hw_features;
190
+	struct hostapd_hw_modes *current_mode;
191
+	/* Rates that are currently used (i.e., filtered copy of
192
+	 * current_mode->channels */
193
+	int num_rates;
194
+	struct hostapd_rate_data *current_rates;
195
+	int freq;
196
+
197
+	u16 hw_flags;
198
+
199
+	/* Number of associated Non-ERP stations (i.e., stations using 802.11b
200
+	 * in 802.11g BSS) */
201
+	int num_sta_non_erp;
202
+
203
+	/* Number of associated stations that do not support Short Slot Time */
204
+	int num_sta_no_short_slot_time;
205
+
206
+	/* Number of associated stations that do not support Short Preamble */
207
+	int num_sta_no_short_preamble;
208
+
209
+	int olbc; /* Overlapping Legacy BSS Condition */
210
+
211
+	/* Number of HT associated stations that do not support greenfield */
212
+	int num_sta_ht_no_gf;
213
+
214
+	/* Number of associated non-HT stations */
215
+	int num_sta_no_ht;
216
+
217
+	/* Number of HT associated stations 20 MHz */
218
+	int num_sta_ht_20mhz;
219
+
220
+	/* Overlapping BSS information */
221
+	int olbc_ht;
222
+
223
+	u16 ht_op_mode;
224
+	void (*scan_cb)(struct hostapd_iface *iface);
225
+
226
+	int (*ctrl_iface_init)(struct hostapd_data *hapd);
227
+	void (*ctrl_iface_deinit)(struct hostapd_data *hapd);
228
+
229
+	int (*for_each_interface)(struct hapd_interfaces *interfaces,
230
+				  int (*cb)(struct hostapd_iface *iface,
231
+					    void *ctx), void *ctx);
232
+};
233
+
234
+/* hostapd.c */
235
+int hostapd_reload_config(struct hostapd_iface *iface);
236
+struct hostapd_data *
237
+hostapd_alloc_bss_data(struct hostapd_iface *hapd_iface,
238
+		       struct hostapd_config *conf,
239
+		       struct hostapd_bss_config *bss);
240
+int hostapd_setup_interface(struct hostapd_iface *iface);
241
+int hostapd_setup_interface_complete(struct hostapd_iface *iface, int err);
242
+void hostapd_interface_deinit(struct hostapd_iface *iface);
243
+void hostapd_interface_free(struct hostapd_iface *iface);
244
+void hostapd_new_assoc_sta(struct hostapd_data *hapd, struct sta_info *sta,
245
+			   int reassoc);
246
+
247
+/* utils.c */
248
+int hostapd_register_probereq_cb(struct hostapd_data *hapd,
249
+				 int (*cb)(void *ctx, const u8 *sa,
250
+					   const u8 *ie, size_t ie_len),
251
+				 void *ctx);
252
+void hostapd_prune_associations(struct hostapd_data *hapd, const u8 *addr);
253
+
254
+/* drv_callbacks.c (TODO: move to somewhere else?) */
255
+int hostapd_notif_assoc(struct hostapd_data *hapd, const u8 *addr,
256
+			const u8 *ie, size_t ielen, int reassoc);
257
+void hostapd_notif_disassoc(struct hostapd_data *hapd, const u8 *addr);
258
+void hostapd_event_sta_low_ack(struct hostapd_data *hapd, const u8 *addr);
259
+int hostapd_probe_req_rx(struct hostapd_data *hapd, const u8 *sa,
260
+			 const u8 *ie, size_t ie_len);
261
+
262
+#endif /* HOSTAPD_H */

+ 754
- 0
src/ap/hw_features.c Näytä tiedosto

@@ -0,0 +1,754 @@
1
+/*
2
+ * hostapd / Hardware feature query and different modes
3
+ * Copyright 2002-2003, Instant802 Networks, Inc.
4
+ * Copyright 2005-2006, Devicescape Software, Inc.
5
+ * Copyright (c) 2008-2009, Jouni Malinen <j@w1.fi>
6
+ *
7
+ * This program is free software; you can redistribute it and/or modify
8
+ * it under the terms of the GNU General Public License version 2 as
9
+ * published by the Free Software Foundation.
10
+ *
11
+ * Alternatively, this software may be distributed under the terms of BSD
12
+ * license.
13
+ *
14
+ * See README and COPYING for more details.
15
+ */
16
+
17
+#include "utils/includes.h"
18
+
19
+#include "utils/common.h"
20
+#include "utils/eloop.h"
21
+#include "common/ieee802_11_defs.h"
22
+#include "common/ieee802_11_common.h"
23
+#include "drivers/driver.h"
24
+#include "hostapd.h"
25
+#include "ap_config.h"
26
+#include "ap_drv_ops.h"
27
+#include "hw_features.h"
28
+
29
+
30
+void hostapd_free_hw_features(struct hostapd_hw_modes *hw_features,
31
+			      size_t num_hw_features)
32
+{
33
+	size_t i;
34
+
35
+	if (hw_features == NULL)
36
+		return;
37
+
38
+	for (i = 0; i < num_hw_features; i++) {
39
+		os_free(hw_features[i].channels);
40
+		os_free(hw_features[i].rates);
41
+	}
42
+
43
+	os_free(hw_features);
44
+}
45
+
46
+
47
+int hostapd_get_hw_features(struct hostapd_iface *iface)
48
+{
49
+	struct hostapd_data *hapd = iface->bss[0];
50
+	int ret = 0, i, j;
51
+	u16 num_modes, flags;
52
+	struct hostapd_hw_modes *modes;
53
+
54
+	if (hostapd_drv_none(hapd))
55
+		return -1;
56
+	modes = hostapd_get_hw_feature_data(hapd, &num_modes, &flags);
57
+	if (modes == NULL) {
58
+		hostapd_logger(hapd, NULL, HOSTAPD_MODULE_IEEE80211,
59
+			       HOSTAPD_LEVEL_DEBUG,
60
+			       "Fetching hardware channel/rate support not "
61
+			       "supported.");
62
+		return -1;
63
+	}
64
+
65
+	iface->hw_flags = flags;
66
+
67
+	hostapd_free_hw_features(iface->hw_features, iface->num_hw_features);
68
+	iface->hw_features = modes;
69
+	iface->num_hw_features = num_modes;
70
+
71
+	for (i = 0; i < num_modes; i++) {
72
+		struct hostapd_hw_modes *feature = &modes[i];
73
+		/* set flag for channels we can use in current regulatory
74
+		 * domain */
75
+		for (j = 0; j < feature->num_channels; j++) {
76
+			/*
77
+			 * Disable all channels that are marked not to allow
78
+			 * IBSS operation or active scanning. In addition,
79
+			 * disable all channels that require radar detection,
80
+			 * since that (in addition to full DFS) is not yet
81
+			 * supported.
82
+			 */
83
+			if (feature->channels[j].flag &
84
+			    (HOSTAPD_CHAN_NO_IBSS |
85
+			     HOSTAPD_CHAN_PASSIVE_SCAN |
86
+			     HOSTAPD_CHAN_RADAR))
87
+				feature->channels[j].flag |=
88
+					HOSTAPD_CHAN_DISABLED;
89
+			if (feature->channels[j].flag & HOSTAPD_CHAN_DISABLED)
90
+				continue;
91
+			wpa_printf(MSG_MSGDUMP, "Allowed channel: mode=%d "
92
+				   "chan=%d freq=%d MHz max_tx_power=%d dBm",
93
+				   feature->mode,
94
+				   feature->channels[j].chan,
95
+				   feature->channels[j].freq,
96
+				   feature->channels[j].max_tx_power);
97
+		}
98
+	}
99
+
100
+	return ret;
101
+}
102
+
103
+
104
+int hostapd_prepare_rates(struct hostapd_data *hapd,
105
+			  struct hostapd_hw_modes *mode)
106
+{
107
+	int i, num_basic_rates = 0;
108
+	int basic_rates_a[] = { 60, 120, 240, -1 };
109
+	int basic_rates_b[] = { 10, 20, -1 };
110
+	int basic_rates_g[] = { 10, 20, 55, 110, -1 };
111
+	int *basic_rates;
112
+
113
+	if (hapd->iconf->basic_rates)
114
+		basic_rates = hapd->iconf->basic_rates;
115
+	else switch (mode->mode) {
116
+	case HOSTAPD_MODE_IEEE80211A:
117
+		basic_rates = basic_rates_a;
118
+		break;
119
+	case HOSTAPD_MODE_IEEE80211B:
120
+		basic_rates = basic_rates_b;
121
+		break;
122
+	case HOSTAPD_MODE_IEEE80211G:
123
+		basic_rates = basic_rates_g;
124
+		break;
125
+	default:
126
+		return -1;
127
+	}
128
+
129
+	if (hostapd_set_rate_sets(hapd, hapd->iconf->supported_rates,
130
+				  basic_rates, mode->mode)) {
131
+		wpa_printf(MSG_ERROR, "Failed to update rate sets in kernel "
132
+			   "module");
133
+	}
134
+
135
+	os_free(hapd->iface->current_rates);
136
+	hapd->iface->num_rates = 0;
137
+
138
+	hapd->iface->current_rates =
139
+		os_zalloc(mode->num_rates * sizeof(struct hostapd_rate_data));
140
+	if (!hapd->iface->current_rates) {
141
+		wpa_printf(MSG_ERROR, "Failed to allocate memory for rate "
142
+			   "table.");
143
+		return -1;
144
+	}
145
+
146
+	for (i = 0; i < mode->num_rates; i++) {
147
+		struct hostapd_rate_data *rate;
148
+
149
+		if (hapd->iconf->supported_rates &&
150
+		    !hostapd_rate_found(hapd->iconf->supported_rates,
151
+					mode->rates[i]))
152
+			continue;
153
+
154
+		rate = &hapd->iface->current_rates[hapd->iface->num_rates];
155
+		rate->rate = mode->rates[i];
156
+		if (hostapd_rate_found(basic_rates, rate->rate)) {
157
+			rate->flags |= HOSTAPD_RATE_BASIC;
158
+			num_basic_rates++;
159
+		}
160
+		wpa_printf(MSG_DEBUG, "RATE[%d] rate=%d flags=0x%x",
161
+			   hapd->iface->num_rates, rate->rate, rate->flags);
162
+		hapd->iface->num_rates++;
163
+	}
164
+
165
+	if ((hapd->iface->num_rates == 0 || num_basic_rates == 0) &&
166
+	    (!hapd->iconf->ieee80211n || !hapd->iconf->require_ht)) {
167
+		wpa_printf(MSG_ERROR, "No rates remaining in supported/basic "
168
+			   "rate sets (%d,%d).",
169
+			   hapd->iface->num_rates, num_basic_rates);
170
+		return -1;
171
+	}
172
+
173
+	return 0;
174
+}
175
+
176
+
177
+#ifdef CONFIG_IEEE80211N
178
+static int ieee80211n_allowed_ht40_channel_pair(struct hostapd_iface *iface)
179
+{
180
+	int sec_chan, ok, j, first;
181
+	int allowed[] = { 36, 44, 52, 60, 100, 108, 116, 124, 132, 149, 157,
182
+			  184, 192 };
183
+	size_t k;
184
+
185
+	if (!iface->conf->secondary_channel)
186
+		return 1; /* HT40 not used */
187
+
188
+	sec_chan = iface->conf->channel + iface->conf->secondary_channel * 4;
189
+	wpa_printf(MSG_DEBUG, "HT40: control channel: %d  "
190
+		   "secondary channel: %d",
191
+		   iface->conf->channel, sec_chan);
192
+
193
+	/* Verify that HT40 secondary channel is an allowed 20 MHz
194
+	 * channel */
195
+	ok = 0;
196
+	for (j = 0; j < iface->current_mode->num_channels; j++) {
197
+		struct hostapd_channel_data *chan =
198
+			&iface->current_mode->channels[j];
199
+		if (!(chan->flag & HOSTAPD_CHAN_DISABLED) &&
200
+		    chan->chan == sec_chan) {
201
+			ok = 1;
202
+			break;
203
+		}
204
+	}
205
+	if (!ok) {
206
+		wpa_printf(MSG_ERROR, "HT40 secondary channel %d not allowed",
207
+			   sec_chan);
208
+		return 0;
209
+	}
210
+
211
+	/*
212
+	 * Verify that HT40 primary,secondary channel pair is allowed per
213
+	 * IEEE 802.11n Annex J. This is only needed for 5 GHz band since
214
+	 * 2.4 GHz rules allow all cases where the secondary channel fits into
215
+	 * the list of allowed channels (already checked above).
216
+	 */
217
+	if (iface->current_mode->mode != HOSTAPD_MODE_IEEE80211A)
218
+		return 1;
219
+
220
+	if (iface->conf->secondary_channel > 0)
221
+		first = iface->conf->channel;
222
+	else
223
+		first = sec_chan;
224
+
225
+	ok = 0;
226
+	for (k = 0; k < sizeof(allowed) / sizeof(allowed[0]); k++) {
227
+		if (first == allowed[k]) {
228
+			ok = 1;
229
+			break;
230
+		}
231
+	}
232
+	if (!ok) {
233
+		wpa_printf(MSG_ERROR, "HT40 channel pair (%d, %d) not allowed",
234
+			   iface->conf->channel,
235
+			   iface->conf->secondary_channel);
236
+		return 0;
237
+	}
238
+
239
+	return 1;
240
+}
241
+
242
+
243
+static void ieee80211n_switch_pri_sec(struct hostapd_iface *iface)
244
+{
245
+	if (iface->conf->secondary_channel > 0) {
246
+		iface->conf->channel += 4;
247
+		iface->conf->secondary_channel = -1;
248
+	} else {
249
+		iface->conf->channel -= 4;
250
+		iface->conf->secondary_channel = 1;
251
+	}
252
+}
253
+
254
+
255
+static void ieee80211n_get_pri_sec_chan(struct wpa_scan_res *bss,
256
+					int *pri_chan, int *sec_chan)
257
+{
258
+	struct ieee80211_ht_operation *oper;
259
+	struct ieee802_11_elems elems;
260
+
261
+	*pri_chan = *sec_chan = 0;
262
+
263
+	ieee802_11_parse_elems((u8 *) (bss + 1), bss->ie_len, &elems, 0);
264
+	if (elems.ht_operation &&
265
+	    elems.ht_operation_len >= sizeof(*oper)) {
266
+		oper = (struct ieee80211_ht_operation *) elems.ht_operation;
267
+		*pri_chan = oper->control_chan;
268
+		if (oper->ht_param & HT_INFO_HT_PARAM_REC_TRANS_CHNL_WIDTH) {
269
+			int sec = oper->ht_param &
270
+				HT_INFO_HT_PARAM_SECONDARY_CHNL_OFF_MASK;
271
+			if (sec == HT_INFO_HT_PARAM_SECONDARY_CHNL_ABOVE)
272
+				*sec_chan = *pri_chan + 4;
273
+			else if (sec == HT_INFO_HT_PARAM_SECONDARY_CHNL_BELOW)
274
+				*sec_chan = *pri_chan - 4;
275
+		}
276
+	}
277
+}
278
+
279
+
280
+static int ieee80211n_check_40mhz_5g(struct hostapd_iface *iface,
281
+				     struct wpa_scan_results *scan_res)
282
+{
283
+	int pri_chan, sec_chan, pri_freq, sec_freq, pri_bss, sec_bss;
284
+	int bss_pri_chan, bss_sec_chan;
285
+	size_t i;
286
+	int match;
287
+
288
+	pri_chan = iface->conf->channel;
289
+	sec_chan = iface->conf->secondary_channel * 4;
290
+	pri_freq = hostapd_hw_get_freq(iface->bss[0], pri_chan);
291
+	if (iface->conf->secondary_channel > 0)
292
+		sec_freq = pri_freq + 20;
293
+	else
294
+		sec_freq = pri_freq - 20;
295
+
296
+	/*
297
+	 * Switch PRI/SEC channels if Beacons were detected on selected SEC
298
+	 * channel, but not on selected PRI channel.
299
+	 */
300
+	pri_bss = sec_bss = 0;
301
+	for (i = 0; i < scan_res->num; i++) {
302
+		struct wpa_scan_res *bss = scan_res->res[i];
303
+		if (bss->freq == pri_freq)
304
+			pri_bss++;
305
+		else if (bss->freq == sec_freq)
306
+			sec_bss++;
307
+	}
308
+	if (sec_bss && !pri_bss) {
309
+		wpa_printf(MSG_INFO, "Switch own primary and secondary "
310
+			   "channel to get secondary channel with no Beacons "
311
+			   "from other BSSes");
312
+		ieee80211n_switch_pri_sec(iface);
313
+	}
314
+
315
+	/*
316
+	 * Match PRI/SEC channel with any existing HT40 BSS on the same
317
+	 * channels that we are about to use (if already mixed order in
318
+	 * existing BSSes, use own preference).
319
+	 */
320
+	match = 0;
321
+	for (i = 0; i < scan_res->num; i++) {
322
+		struct wpa_scan_res *bss = scan_res->res[i];
323
+		ieee80211n_get_pri_sec_chan(bss, &bss_pri_chan, &bss_sec_chan);
324
+		if (pri_chan == bss_pri_chan &&
325
+		    sec_chan == bss_sec_chan) {
326
+			match = 1;
327
+			break;
328
+		}
329
+	}
330
+	if (!match) {
331
+		for (i = 0; i < scan_res->num; i++) {
332
+			struct wpa_scan_res *bss = scan_res->res[i];
333
+			ieee80211n_get_pri_sec_chan(bss, &bss_pri_chan,
334
+						    &bss_sec_chan);
335
+			if (pri_chan == bss_sec_chan &&
336
+			    sec_chan == bss_pri_chan) {
337
+				wpa_printf(MSG_INFO, "Switch own primary and "
338
+					   "secondary channel due to BSS "
339
+					   "overlap with " MACSTR,
340
+					   MAC2STR(bss->bssid));
341
+				ieee80211n_switch_pri_sec(iface);
342
+				break;
343
+			}
344
+		}
345
+	}
346
+
347
+	return 1;
348
+}
349
+
350
+
351
+static int ieee80211n_check_40mhz_2g4(struct hostapd_iface *iface,
352
+				      struct wpa_scan_results *scan_res)
353
+{
354
+	int pri_freq, sec_freq;
355
+	int affected_start, affected_end;
356
+	size_t i;
357
+
358
+	pri_freq = hostapd_hw_get_freq(iface->bss[0], iface->conf->channel);
359
+	if (iface->conf->secondary_channel > 0)
360
+		sec_freq = pri_freq + 20;
361
+	else
362
+		sec_freq = pri_freq - 20;
363
+	affected_start = (pri_freq + sec_freq) / 2 - 25;
364
+	affected_end = (pri_freq + sec_freq) / 2 + 25;
365
+	wpa_printf(MSG_DEBUG, "40 MHz affected channel range: [%d,%d] MHz",
366
+		   affected_start, affected_end);
367
+	for (i = 0; i < scan_res->num; i++) {
368
+		struct wpa_scan_res *bss = scan_res->res[i];
369
+		int pri = bss->freq;
370
+		int sec = pri;
371
+		int sec_chan, pri_chan;
372
+
373
+		ieee80211n_get_pri_sec_chan(bss, &pri_chan, &sec_chan);
374
+
375
+		if (sec_chan) {
376
+			if (sec_chan < pri_chan)
377
+				sec = pri - 20;
378
+			else
379
+				sec = pri + 20;
380
+		}
381
+
382
+		if ((pri < affected_start || pri > affected_end) &&
383
+		    (sec < affected_start || sec > affected_end))
384
+			continue; /* not within affected channel range */
385
+
386
+		wpa_printf(MSG_DEBUG, "Neighboring BSS: " MACSTR
387
+			   " freq=%d pri=%d sec=%d",
388
+			   MAC2STR(bss->bssid), bss->freq, pri_chan, sec_chan);
389
+
390
+		if (sec_chan) {
391
+			if (pri_freq != pri || sec_freq != sec) {
392
+				wpa_printf(MSG_DEBUG, "40 MHz pri/sec "
393
+					   "mismatch with BSS " MACSTR
394
+					   " <%d,%d> (chan=%d%c) vs. <%d,%d>",
395
+					   MAC2STR(bss->bssid),
396
+					   pri, sec, pri_chan,
397
+					   sec > pri ? '+' : '-',
398
+					   pri_freq, sec_freq);
399
+				return 0;
400
+			}
401
+		}
402
+
403
+		/* TODO: 40 MHz intolerant */
404
+	}
405
+
406
+	return 1;
407
+}
408
+
409
+
410
+static void wpa_scan_results_free(struct wpa_scan_results *res)
411
+{
412
+	size_t i;
413
+
414
+	if (res == NULL)
415
+		return;
416
+
417
+	for (i = 0; i < res->num; i++)
418
+		os_free(res->res[i]);
419
+	os_free(res->res);
420
+	os_free(res);
421
+}
422
+
423
+
424
+static void ieee80211n_check_scan(struct hostapd_iface *iface)
425
+{
426
+	struct wpa_scan_results *scan_res;
427
+	int oper40;
428
+	int res;
429
+
430
+	/* Check list of neighboring BSSes (from scan) to see whether 40 MHz is
431
+	 * allowed per IEEE 802.11n/D7.0, 11.14.3.2 */
432
+
433
+	iface->scan_cb = NULL;
434
+
435
+	scan_res = hostapd_driver_get_scan_results(iface->bss[0]);
436
+	if (scan_res == NULL) {
437
+		hostapd_setup_interface_complete(iface, 1);
438
+		return;
439
+	}
440
+
441
+	if (iface->current_mode->mode == HOSTAPD_MODE_IEEE80211A)
442
+		oper40 = ieee80211n_check_40mhz_5g(iface, scan_res);
443
+	else
444
+		oper40 = ieee80211n_check_40mhz_2g4(iface, scan_res);
445
+	wpa_scan_results_free(scan_res);
446
+
447
+	if (!oper40) {
448
+		wpa_printf(MSG_INFO, "20/40 MHz operation not permitted on "
449
+			   "channel pri=%d sec=%d based on overlapping BSSes",
450
+			   iface->conf->channel,
451
+			   iface->conf->channel +
452
+			   iface->conf->secondary_channel * 4);
453
+		iface->conf->secondary_channel = 0;
454
+		iface->conf->ht_capab &= ~HT_CAP_INFO_SUPP_CHANNEL_WIDTH_SET;
455
+	}
456
+
457
+	res = ieee80211n_allowed_ht40_channel_pair(iface);
458
+	hostapd_setup_interface_complete(iface, !res);
459
+}
460
+
461
+
462
+static int ieee80211n_check_40mhz(struct hostapd_iface *iface)
463
+{
464
+	struct wpa_driver_scan_params params;
465
+
466
+	if (!iface->conf->secondary_channel)
467
+		return 0; /* HT40 not used */
468
+
469
+	wpa_printf(MSG_DEBUG, "Scan for neighboring BSSes prior to enabling "
470
+		   "40 MHz channel");
471
+	os_memset(&params, 0, sizeof(params));
472
+	/* TODO: scan only the needed frequency */
473
+	if (hostapd_driver_scan(iface->bss[0], &params) < 0) {
474
+		wpa_printf(MSG_ERROR, "Failed to request a scan of "
475
+			   "neighboring BSSes");
476
+
477
+		//DRIVER_RTW Modify
478
+		//return -1;		
479
+		return 0;//ignore this error 
480
+	}
481
+
482
+	iface->scan_cb = ieee80211n_check_scan;
483
+	return 1;
484
+}
485
+
486
+
487
+static int ieee80211n_supported_ht_capab(struct hostapd_iface *iface)
488
+{
489
+	u16 hw = iface->current_mode->ht_capab;
490
+	u16 conf = iface->conf->ht_capab;
491
+
492
+	if ((conf & HT_CAP_INFO_LDPC_CODING_CAP) &&
493
+	    !(hw & HT_CAP_INFO_LDPC_CODING_CAP)) {
494
+		wpa_printf(MSG_ERROR, "Driver does not support configured "
495
+			   "HT capability [LDPC]");
496
+		return 0;
497
+	}
498
+
499
+	if ((conf & HT_CAP_INFO_SUPP_CHANNEL_WIDTH_SET) &&
500
+	    !(hw & HT_CAP_INFO_SUPP_CHANNEL_WIDTH_SET)) {
501
+		wpa_printf(MSG_ERROR, "Driver does not support configured "
502
+			   "HT capability [HT40*]");
503
+		return 0;
504
+	}
505
+
506
+	if ((conf & HT_CAP_INFO_SMPS_MASK) != (hw & HT_CAP_INFO_SMPS_MASK) &&
507
+	    (conf & HT_CAP_INFO_SMPS_MASK) != HT_CAP_INFO_SMPS_DISABLED) {
508
+		wpa_printf(MSG_ERROR, "Driver does not support configured "
509
+			   "HT capability [SMPS-*]");
510
+		return 0;
511
+	}
512
+
513
+	if ((conf & HT_CAP_INFO_GREEN_FIELD) &&
514
+	    !(hw & HT_CAP_INFO_GREEN_FIELD)) {
515
+		wpa_printf(MSG_ERROR, "Driver does not support configured "
516
+			   "HT capability [GF]");
517
+		return 0;
518
+	}
519
+
520
+	if ((conf & HT_CAP_INFO_SHORT_GI20MHZ) &&
521
+	    !(hw & HT_CAP_INFO_SHORT_GI20MHZ)) {
522
+		wpa_printf(MSG_ERROR, "Driver does not support configured "
523
+			   "HT capability [SHORT-GI-20]");
524
+		return 0;
525
+	}
526
+
527
+	if ((conf & HT_CAP_INFO_SHORT_GI40MHZ) &&
528
+	    !(hw & HT_CAP_INFO_SHORT_GI40MHZ)) {
529
+		wpa_printf(MSG_ERROR, "Driver does not support configured "
530
+			   "HT capability [SHORT-GI-40]");
531
+		return 0;
532
+	}
533
+
534
+	if ((conf & HT_CAP_INFO_TX_STBC) && !(hw & HT_CAP_INFO_TX_STBC)) {
535
+		wpa_printf(MSG_ERROR, "Driver does not support configured "
536
+			   "HT capability [TX-STBC]");
537
+		return 0;
538
+	}
539
+
540
+	if ((conf & HT_CAP_INFO_RX_STBC_MASK) >
541
+	    (hw & HT_CAP_INFO_RX_STBC_MASK)) {
542
+		wpa_printf(MSG_ERROR, "Driver does not support configured "
543
+			   "HT capability [RX-STBC*]");
544
+		return 0;
545
+	}
546
+
547
+	if ((conf & HT_CAP_INFO_DELAYED_BA) &&
548
+	    !(hw & HT_CAP_INFO_DELAYED_BA)) {
549
+		wpa_printf(MSG_ERROR, "Driver does not support configured "
550
+			   "HT capability [DELAYED-BA]");
551
+		return 0;
552
+	}
553
+
554
+	if ((conf & HT_CAP_INFO_MAX_AMSDU_SIZE) &&
555
+	    !(hw & HT_CAP_INFO_MAX_AMSDU_SIZE)) {
556
+		wpa_printf(MSG_ERROR, "Driver does not support configured "
557
+			   "HT capability [MAX-AMSDU-7935]");
558
+		return 0;
559
+	}
560
+
561
+	if ((conf & HT_CAP_INFO_DSSS_CCK40MHZ) &&
562
+	    !(hw & HT_CAP_INFO_DSSS_CCK40MHZ)) {
563
+		wpa_printf(MSG_ERROR, "Driver does not support configured "
564
+			   "HT capability [DSSS_CCK-40]");
565
+		return 0;
566
+	}
567
+
568
+	if ((conf & HT_CAP_INFO_PSMP_SUPP) && !(hw & HT_CAP_INFO_PSMP_SUPP)) {
569
+		wpa_printf(MSG_ERROR, "Driver does not support configured "
570
+			   "HT capability [PSMP]");
571
+		return 0;
572
+	}
573
+
574
+	if ((conf & HT_CAP_INFO_LSIG_TXOP_PROTECT_SUPPORT) &&
575
+	    !(hw & HT_CAP_INFO_LSIG_TXOP_PROTECT_SUPPORT)) {
576
+		wpa_printf(MSG_ERROR, "Driver does not support configured "
577
+			   "HT capability [LSIG-TXOP-PROT]");
578
+		return 0;
579
+	}
580
+
581
+	return 1;
582
+}
583
+
584
+#endif /* CONFIG_IEEE80211N */
585
+
586
+
587
+int hostapd_check_ht_capab(struct hostapd_iface *iface)
588
+{
589
+#ifdef CONFIG_IEEE80211N
590
+	int ret;
591
+	if (!iface->conf->ieee80211n)
592
+		return 0;
593
+	if (!ieee80211n_supported_ht_capab(iface))
594
+		return -1;
595
+	ret = ieee80211n_check_40mhz(iface);
596
+	if (ret)
597
+		return ret;
598
+	if (!ieee80211n_allowed_ht40_channel_pair(iface))
599
+		return -1;
600
+#endif /* CONFIG_IEEE80211N */
601
+
602
+	return 0;
603
+}
604
+
605
+
606
+/**
607
+ * hostapd_select_hw_mode - Select the hardware mode
608
+ * @iface: Pointer to interface data.
609
+ * Returns: 0 on success, -1 on failure
610
+ *
611
+ * Sets up the hardware mode, channel, rates, and passive scanning
612
+ * based on the configuration.
613
+ */
614
+int hostapd_select_hw_mode(struct hostapd_iface *iface)
615
+{
616
+	int i, j, ok;
617
+
618
+	if (iface->num_hw_features < 1)
619
+		return -1;
620
+
621
+	iface->current_mode = NULL;
622
+	for (i = 0; i < iface->num_hw_features; i++) {
623
+		struct hostapd_hw_modes *mode = &iface->hw_features[i];
624
+		if (mode->mode == iface->conf->hw_mode) {
625
+			iface->current_mode = mode;
626
+			break;
627
+		}
628
+	}
629
+
630
+	if (iface->current_mode == NULL) {
631
+		wpa_printf(MSG_ERROR, "Hardware does not support configured "
632
+			   "mode");
633
+		hostapd_logger(iface->bss[0], NULL, HOSTAPD_MODULE_IEEE80211,
634
+			       HOSTAPD_LEVEL_WARNING,
635
+			       "Hardware does not support configured mode "
636
+			       "(%d)", (int) iface->conf->hw_mode);
637
+		return -1;
638
+	}
639
+
640
+	ok = 0;
641
+	for (j = 0; j < iface->current_mode->num_channels; j++) {
642
+		struct hostapd_channel_data *chan =
643
+			&iface->current_mode->channels[j];
644
+		if (!(chan->flag & HOSTAPD_CHAN_DISABLED) &&
645
+		    (chan->chan == iface->conf->channel)) {
646
+			ok = 1;
647
+			break;
648
+		}
649
+	}
650
+	if (ok && iface->conf->secondary_channel) {
651
+		int sec_ok = 0;
652
+		int sec_chan = iface->conf->channel +
653
+			iface->conf->secondary_channel * 4;
654
+		for (j = 0; j < iface->current_mode->num_channels; j++) {
655
+			struct hostapd_channel_data *chan =
656
+				&iface->current_mode->channels[j];
657
+			if (!(chan->flag & HOSTAPD_CHAN_DISABLED) &&
658
+			    (chan->chan == sec_chan)) {
659
+				sec_ok = 1;
660
+				break;
661
+			}
662
+		}
663
+		if (!sec_ok) {
664
+			hostapd_logger(iface->bss[0], NULL,
665
+				       HOSTAPD_MODULE_IEEE80211,
666
+				       HOSTAPD_LEVEL_WARNING,
667
+				       "Configured HT40 secondary channel "
668
+				       "(%d) not found from the channel list "
669
+				       "of current mode (%d) %s",
670
+				       sec_chan, iface->current_mode->mode,
671
+				       hostapd_hw_mode_txt(
672
+					       iface->current_mode->mode));
673
+			ok = 0;
674
+		}
675
+	}
676
+	if (iface->conf->channel == 0) {
677
+		/* TODO: could request a scan of neighboring BSSes and select
678
+		 * the channel automatically */
679
+		wpa_printf(MSG_ERROR, "Channel not configured "
680
+			   "(hw_mode/channel in hostapd.conf)");
681
+		return -1;
682
+	}
683
+	if (ok == 0 && iface->conf->channel != 0) {
684
+		hostapd_logger(iface->bss[0], NULL,
685
+			       HOSTAPD_MODULE_IEEE80211,
686
+			       HOSTAPD_LEVEL_WARNING,
687
+			       "Configured channel (%d) not found from the "
688
+			       "channel list of current mode (%d) %s",
689
+			       iface->conf->channel,
690
+			       iface->current_mode->mode,
691
+			       hostapd_hw_mode_txt(iface->current_mode->mode));
692
+		iface->current_mode = NULL;
693
+	}
694
+
695
+	if (iface->current_mode == NULL) {
696
+		hostapd_logger(iface->bss[0], NULL, HOSTAPD_MODULE_IEEE80211,
697
+			       HOSTAPD_LEVEL_WARNING,
698
+			       "Hardware does not support configured channel");
699
+		return -1;
700
+	}
701
+
702
+	return 0;
703
+}
704
+
705
+
706
+const char * hostapd_hw_mode_txt(int mode)
707
+{
708
+	switch (mode) {
709
+	case HOSTAPD_MODE_IEEE80211A:
710
+		return "IEEE 802.11a";
711
+	case HOSTAPD_MODE_IEEE80211B:
712
+		return "IEEE 802.11b";
713
+	case HOSTAPD_MODE_IEEE80211G:
714
+		return "IEEE 802.11g";
715
+	default:
716
+		return "UNKNOWN";
717
+	}
718
+}
719
+
720
+
721
+int hostapd_hw_get_freq(struct hostapd_data *hapd, int chan)
722
+{
723
+	int i;
724
+
725
+	if (!hapd->iface->current_mode)
726
+		return 0;
727
+
728
+	for (i = 0; i < hapd->iface->current_mode->num_channels; i++) {
729
+		struct hostapd_channel_data *ch =
730
+			&hapd->iface->current_mode->channels[i];
731
+		if (ch->chan == chan)
732
+			return ch->freq;
733
+	}
734
+
735
+	return 0;
736
+}
737
+
738
+
739
+int hostapd_hw_get_channel(struct hostapd_data *hapd, int freq)
740
+{
741
+	int i;
742
+
743
+	if (!hapd->iface->current_mode)
744
+		return 0;
745
+
746
+	for (i = 0; i < hapd->iface->current_mode->num_channels; i++) {
747
+		struct hostapd_channel_data *ch =
748
+			&hapd->iface->current_mode->channels[i];
749
+		if (ch->freq == freq)
750
+			return ch->chan;
751
+	}
752
+
753
+	return 0;
754
+}

+ 70
- 0
src/ap/hw_features.h Näytä tiedosto

@@ -0,0 +1,70 @@
1
+/*
2
+ * hostapd / Hardware feature query and different modes
3
+ * Copyright 2002-2003, Instant802 Networks, Inc.
4
+ * Copyright 2005-2006, Devicescape Software, Inc.
5
+ *
6
+ * This program is free software; you can redistribute it and/or modify
7
+ * it under the terms of the GNU General Public License version 2 as
8
+ * published by the Free Software Foundation.
9
+ *
10
+ * Alternatively, this software may be distributed under the terms of BSD
11
+ * license.
12
+ *
13
+ * See README and COPYING for more details.
14
+ */
15
+
16
+#ifndef HW_FEATURES_H
17
+#define HW_FEATURES_H
18
+
19
+#ifdef NEED_AP_MLME
20
+void hostapd_free_hw_features(struct hostapd_hw_modes *hw_features,
21
+			      size_t num_hw_features);
22
+int hostapd_get_hw_features(struct hostapd_iface *iface);
23
+int hostapd_select_hw_mode(struct hostapd_iface *iface);
24
+const char * hostapd_hw_mode_txt(int mode);
25
+int hostapd_hw_get_freq(struct hostapd_data *hapd, int chan);
26
+int hostapd_hw_get_channel(struct hostapd_data *hapd, int freq);
27
+int hostapd_check_ht_capab(struct hostapd_iface *iface);
28
+int hostapd_prepare_rates(struct hostapd_data *hapd,
29
+			  struct hostapd_hw_modes *mode);
30
+#else /* NEED_AP_MLME */
31
+static inline void
32
+hostapd_free_hw_features(struct hostapd_hw_modes *hw_features,
33
+			 size_t num_hw_features)
34
+{
35
+}
36
+
37
+static inline int hostapd_get_hw_features(struct hostapd_iface *iface)
38
+{
39
+	return -1;
40
+}
41
+
42
+static inline int hostapd_select_hw_mode(struct hostapd_iface *iface)
43
+{
44
+	return -1;
45
+}
46
+
47
+static inline const char * hostapd_hw_mode_txt(int mode)
48
+{
49
+	return NULL;
50
+}
51
+
52
+static inline int hostapd_hw_get_freq(struct hostapd_data *hapd, int chan)
53
+{
54
+	return -1;
55
+}
56
+
57
+static inline int hostapd_check_ht_capab(struct hostapd_iface *iface)
58
+{
59
+	return 0;
60
+}
61
+
62
+static inline int hostapd_prepare_rates(struct hostapd_data *hapd,
63
+					struct hostapd_hw_modes *mode)
64
+{
65
+	return 0;
66
+}
67
+
68
+#endif /* NEED_AP_MLME */
69
+
70
+#endif /* HW_FEATURES_H */

+ 535
- 0
src/ap/iapp.c Näytä tiedosto

@@ -0,0 +1,535 @@
1
+/*
2
+ * hostapd / IEEE 802.11F-2003 Inter-Access Point Protocol (IAPP)
3
+ * Copyright (c) 2002-2007, Jouni Malinen <j@w1.fi>
4
+ *
5
+ * This program is free software; you can redistribute it and/or modify
6
+ * it under the terms of the GNU General Public License version 2 as
7
+ * published by the Free Software Foundation.
8
+ *
9
+ * Alternatively, this software may be distributed under the terms of BSD
10
+ * license.
11
+ *
12
+ * See README and COPYING for more details.
13
+ *
14
+ * Note: IEEE 802.11F-2003 was a experimental use specification. It has expired
15
+ * and IEEE has withdrawn it. In other words, it is likely better to look at
16
+ * using some other mechanism for AP-to-AP communication than extending the
17
+ * implementation here.
18
+ */
19
+
20
+/* TODO:
21
+ * Level 1: no administrative or security support
22
+ *	(e.g., static BSSID to IP address mapping in each AP)
23
+ * Level 2: support for dynamic mapping of BSSID to IP address
24
+ * Level 3: support for encryption and authentication of IAPP messages
25
+ * - add support for MOVE-notify and MOVE-response (this requires support for
26
+ *   finding out IP address for previous AP using RADIUS)
27
+ * - add support for Send- and ACK-Security-Block to speedup IEEE 802.1X during
28
+ *   reassociation to another AP
29
+ * - implement counters etc. for IAPP MIB
30
+ * - verify endianness of fields in IAPP messages; are they big-endian as
31
+ *   used here?
32
+ * - RADIUS connection for AP registration and BSSID to IP address mapping
33
+ * - TCP connection for IAPP MOVE, CACHE
34
+ * - broadcast ESP for IAPP ADD-notify
35
+ * - ESP for IAPP MOVE messages
36
+ * - security block sending/processing
37
+ * - IEEE 802.11 context transfer
38
+ */
39
+
40
+#include "utils/includes.h"
41
+#include <net/if.h>
42
+#include <sys/ioctl.h>
43
+#ifdef USE_KERNEL_HEADERS
44
+#include <linux/if_packet.h>
45
+#else /* USE_KERNEL_HEADERS */
46
+#include <netpacket/packet.h>
47
+#endif /* USE_KERNEL_HEADERS */
48
+
49
+#include "utils/common.h"
50
+#include "utils/eloop.h"
51
+#include "common/ieee802_11_defs.h"
52
+#include "hostapd.h"
53
+#include "ap_config.h"
54
+#include "ieee802_11.h"
55
+#include "sta_info.h"
56
+#include "iapp.h"
57
+
58
+
59
+#define IAPP_MULTICAST "224.0.1.178"
60
+#define IAPP_UDP_PORT 3517
61
+#define IAPP_TCP_PORT 3517
62
+
63
+struct iapp_hdr {
64
+	u8 version;
65
+	u8 command;
66
+	be16 identifier;
67
+	be16 length;
68
+	/* followed by length-6 octets of data */
69
+} __attribute__ ((packed));
70
+
71
+#define IAPP_VERSION 0
72
+
73
+enum IAPP_COMMAND {
74
+	IAPP_CMD_ADD_notify = 0,
75
+	IAPP_CMD_MOVE_notify = 1,
76
+	IAPP_CMD_MOVE_response = 2,
77
+	IAPP_CMD_Send_Security_Block = 3,
78
+	IAPP_CMD_ACK_Security_Block = 4,
79
+	IAPP_CMD_CACHE_notify = 5,
80
+	IAPP_CMD_CACHE_response = 6,
81
+};
82
+
83
+
84
+/* ADD-notify - multicast UDP on the local LAN */
85
+struct iapp_add_notify {
86
+	u8 addr_len; /* ETH_ALEN */
87
+	u8 reserved;
88
+	u8 mac_addr[ETH_ALEN];
89
+	be16 seq_num;
90
+} __attribute__ ((packed));
91
+
92
+
93
+/* Layer 2 Update frame (802.2 Type 1 LLC XID Update response) */
94
+struct iapp_layer2_update {
95
+	u8 da[ETH_ALEN]; /* broadcast */
96
+	u8 sa[ETH_ALEN]; /* STA addr */
97
+	be16 len; /* 6 */
98
+	u8 dsap; /* null DSAP address */
99
+	u8 ssap; /* null SSAP address, CR=Response */
100
+	u8 control;
101
+	u8 xid_info[3];
102
+} __attribute__ ((packed));
103
+
104
+
105
+/* MOVE-notify - unicast TCP */
106
+struct iapp_move_notify {
107
+	u8 addr_len; /* ETH_ALEN */
108
+	u8 reserved;
109
+	u8 mac_addr[ETH_ALEN];
110
+	u16 seq_num;
111
+	u16 ctx_block_len;
112
+	/* followed by ctx_block_len bytes */
113
+} __attribute__ ((packed));
114
+
115
+
116
+/* MOVE-response - unicast TCP */
117
+struct iapp_move_response {
118
+	u8 addr_len; /* ETH_ALEN */
119
+	u8 status;
120
+	u8 mac_addr[ETH_ALEN];
121
+	u16 seq_num;
122
+	u16 ctx_block_len;
123
+	/* followed by ctx_block_len bytes */
124
+} __attribute__ ((packed));
125
+
126
+enum {
127
+	IAPP_MOVE_SUCCESSFUL = 0,
128
+	IAPP_MOVE_DENIED = 1,
129
+	IAPP_MOVE_STALE_MOVE = 2,
130
+};
131
+
132
+
133
+/* CACHE-notify */
134
+struct iapp_cache_notify {
135
+	u8 addr_len; /* ETH_ALEN */
136
+	u8 reserved;
137
+	u8 mac_addr[ETH_ALEN];
138
+	u16 seq_num;
139
+	u8 current_ap[ETH_ALEN];
140
+	u16 ctx_block_len;
141
+	/* ctx_block_len bytes of context block followed by 16-bit context
142
+	 * timeout */
143
+} __attribute__ ((packed));
144
+
145
+
146
+/* CACHE-response - unicast TCP */
147
+struct iapp_cache_response {
148
+	u8 addr_len; /* ETH_ALEN */
149
+	u8 status;
150
+	u8 mac_addr[ETH_ALEN];
151
+	u16 seq_num;
152
+} __attribute__ ((packed));
153
+
154
+enum {
155
+	IAPP_CACHE_SUCCESSFUL = 0,
156
+	IAPP_CACHE_STALE_CACHE = 1,
157
+};
158
+
159
+
160
+/* Send-Security-Block - unicast TCP */
161
+struct iapp_send_security_block {
162
+	u8 iv[8];
163
+	u16 sec_block_len;
164
+	/* followed by sec_block_len bytes of security block */
165
+} __attribute__ ((packed));
166
+
167
+
168
+/* ACK-Security-Block - unicast TCP */
169
+struct iapp_ack_security_block {
170
+	u8 iv[8];
171
+	u8 new_ap_ack_authenticator[48];
172
+} __attribute__ ((packed));
173
+
174
+
175
+struct iapp_data {
176
+	struct hostapd_data *hapd;
177
+	u16 identifier; /* next IAPP identifier */
178
+	struct in_addr own, multicast;
179
+	int udp_sock;
180
+	int packet_sock;
181
+};
182
+
183
+
184
+static void iapp_send_add(struct iapp_data *iapp, u8 *mac_addr, u16 seq_num)
185
+{
186
+	char buf[128];
187
+	struct iapp_hdr *hdr;
188
+	struct iapp_add_notify *add;
189
+	struct sockaddr_in addr;
190
+
191
+	/* Send IAPP ADD-notify to remove possible association from other APs
192
+	 */
193
+
194
+	hdr = (struct iapp_hdr *) buf;
195
+	hdr->version = IAPP_VERSION;
196
+	hdr->command = IAPP_CMD_ADD_notify;
197
+	hdr->identifier = host_to_be16(iapp->identifier++);
198
+	hdr->length = host_to_be16(sizeof(*hdr) + sizeof(*add));
199
+
200
+	add = (struct iapp_add_notify *) (hdr + 1);
201
+	add->addr_len = ETH_ALEN;
202
+	add->reserved = 0;
203
+	os_memcpy(add->mac_addr, mac_addr, ETH_ALEN);
204
+
205
+	add->seq_num = host_to_be16(seq_num);
206
+	
207
+	os_memset(&addr, 0, sizeof(addr));
208
+	addr.sin_family = AF_INET;
209
+	addr.sin_addr.s_addr = iapp->multicast.s_addr;
210
+	addr.sin_port = htons(IAPP_UDP_PORT);
211
+	if (sendto(iapp->udp_sock, buf, (char *) (add + 1) - buf, 0,
212
+		   (struct sockaddr *) &addr, sizeof(addr)) < 0)
213
+		perror("sendto[IAPP-ADD]");
214
+}
215
+
216
+
217
+static void iapp_send_layer2_update(struct iapp_data *iapp, u8 *addr)
218
+{
219
+	struct iapp_layer2_update msg;
220
+
221
+	/* Send Level 2 Update Frame to update forwarding tables in layer 2
222
+	 * bridge devices */
223
+
224
+	/* 802.2 Type 1 Logical Link Control (LLC) Exchange Identifier (XID)
225
+	 * Update response frame; IEEE Std 802.2-1998, 5.4.1.2.1 */
226
+
227
+	os_memset(msg.da, 0xff, ETH_ALEN);
228
+	os_memcpy(msg.sa, addr, ETH_ALEN);
229
+	msg.len = host_to_be16(6);
230
+	msg.dsap = 0; /* NULL DSAP address */
231
+	msg.ssap = 0x01; /* NULL SSAP address, CR Bit: Response */
232
+	msg.control = 0xaf; /* XID response lsb.1111F101.
233
+			     * F=0 (no poll command; unsolicited frame) */
234
+	msg.xid_info[0] = 0x81; /* XID format identifier */
235
+	msg.xid_info[1] = 1; /* LLC types/classes: Type 1 LLC */
236
+	msg.xid_info[2] = 1 << 1; /* XID sender's receive window size (RW)
237
+				   * FIX: what is correct RW with 802.11? */
238
+
239
+	if (send(iapp->packet_sock, &msg, sizeof(msg), 0) < 0)
240
+		perror("send[L2 Update]");
241
+}
242
+
243
+
244
+/**
245
+ * iapp_new_station - IAPP processing for a new STA
246
+ * @iapp: IAPP data
247
+ * @sta: The associated station
248
+ */
249
+void iapp_new_station(struct iapp_data *iapp, struct sta_info *sta)
250
+{
251
+	struct ieee80211_mgmt *assoc;
252
+	u16 seq;
253
+
254
+	if (iapp == NULL)
255
+		return;
256
+
257
+	assoc = sta->last_assoc_req;
258
+	seq = assoc ? WLAN_GET_SEQ_SEQ(le_to_host16(assoc->seq_ctrl)) : 0;
259
+
260
+	/* IAPP-ADD.request(MAC Address, Sequence Number, Timeout) */
261
+	hostapd_logger(iapp->hapd, sta->addr, HOSTAPD_MODULE_IAPP,
262
+		       HOSTAPD_LEVEL_DEBUG, "IAPP-ADD.request(seq=%d)", seq);
263
+	iapp_send_layer2_update(iapp, sta->addr);
264
+	iapp_send_add(iapp, sta->addr, seq);
265
+
266
+	if (assoc && WLAN_FC_GET_STYPE(le_to_host16(assoc->frame_control)) ==
267
+	    WLAN_FC_STYPE_REASSOC_REQ) {
268
+		/* IAPP-MOVE.request(MAC Address, Sequence Number, Old AP,
269
+		 *                   Context Block, Timeout)
270
+		 */
271
+		/* TODO: Send IAPP-MOVE to the old AP; Map Old AP BSSID to
272
+		 * IP address */
273
+	}
274
+}
275
+
276
+
277
+static void iapp_process_add_notify(struct iapp_data *iapp,
278
+				    struct sockaddr_in *from,
279
+				    struct iapp_hdr *hdr, int len)
280
+{
281
+	struct iapp_add_notify *add = (struct iapp_add_notify *) (hdr + 1);
282
+	struct sta_info *sta;
283
+
284
+	if (len != sizeof(*add)) {
285
+		printf("Invalid IAPP-ADD packet length %d (expected %lu)\n",
286
+		       len, (unsigned long) sizeof(*add));
287
+		return;
288
+	}
289
+
290
+	sta = ap_get_sta(iapp->hapd, add->mac_addr);
291
+
292
+	/* IAPP-ADD.indication(MAC Address, Sequence Number) */
293
+	hostapd_logger(iapp->hapd, add->mac_addr, HOSTAPD_MODULE_IAPP,
294
+		       HOSTAPD_LEVEL_INFO,
295
+		       "Received IAPP ADD-notify (seq# %d) from %s:%d%s",
296
+		       be_to_host16(add->seq_num),
297
+		       inet_ntoa(from->sin_addr), ntohs(from->sin_port),
298
+		       sta ? "" : " (STA not found)");
299
+
300
+	if (!sta)
301
+		return;
302
+
303
+	/* TODO: could use seq_num to try to determine whether last association
304
+	 * to this AP is newer than the one advertised in IAPP-ADD. Although,
305
+	 * this is not really a reliable verification. */
306
+
307
+	hostapd_logger(iapp->hapd, add->mac_addr, HOSTAPD_MODULE_IAPP,
308
+		       HOSTAPD_LEVEL_DEBUG,
309
+		       "Removing STA due to IAPP ADD-notify");
310
+	ap_sta_disconnect(iapp->hapd, sta, NULL, 0);
311
+}
312
+
313
+
314
+/**
315
+ * iapp_receive_udp - Process IAPP UDP frames
316
+ * @sock: File descriptor for the socket
317
+ * @eloop_ctx: IAPP data (struct iapp_data *)
318
+ * @sock_ctx: Not used
319
+ */
320
+static void iapp_receive_udp(int sock, void *eloop_ctx, void *sock_ctx)
321
+{
322
+	struct iapp_data *iapp = eloop_ctx;
323
+	int len, hlen;
324
+	unsigned char buf[128];
325
+	struct sockaddr_in from;
326
+	socklen_t fromlen;
327
+	struct iapp_hdr *hdr;
328
+
329
+	/* Handle incoming IAPP frames (over UDP/IP) */
330
+
331
+	fromlen = sizeof(from);
332
+	len = recvfrom(iapp->udp_sock, buf, sizeof(buf), 0,
333
+		       (struct sockaddr *) &from, &fromlen);
334
+	if (len < 0) {
335
+		perror("recvfrom");
336
+		return;
337
+	}
338
+
339
+	if (from.sin_addr.s_addr == iapp->own.s_addr)
340
+		return; /* ignore own IAPP messages */
341
+
342
+	hostapd_logger(iapp->hapd, NULL, HOSTAPD_MODULE_IAPP,
343
+		       HOSTAPD_LEVEL_DEBUG,
344
+		       "Received %d byte IAPP frame from %s%s\n",
345
+		       len, inet_ntoa(from.sin_addr),
346
+		       len < (int) sizeof(*hdr) ? " (too short)" : "");
347
+
348
+	if (len < (int) sizeof(*hdr))
349
+		return;
350
+
351
+	hdr = (struct iapp_hdr *) buf;
352
+	hlen = be_to_host16(hdr->length);
353
+	hostapd_logger(iapp->hapd, NULL, HOSTAPD_MODULE_IAPP,
354
+		       HOSTAPD_LEVEL_DEBUG,
355
+		       "RX: version=%d command=%d id=%d len=%d\n",
356
+		       hdr->version, hdr->command,
357
+		       be_to_host16(hdr->identifier), hlen);
358
+	if (hdr->version != IAPP_VERSION) {
359
+		printf("Dropping IAPP frame with unknown version %d\n",
360
+		       hdr->version);
361
+		return;
362
+	}
363
+	if (hlen > len) {
364
+		printf("Underflow IAPP frame (hlen=%d len=%d)\n", hlen, len);
365
+		return;
366
+	}
367
+	if (hlen < len) {
368
+		printf("Ignoring %d extra bytes from IAPP frame\n",
369
+		       len - hlen);
370
+		len = hlen;
371
+	}
372
+
373
+	switch (hdr->command) {
374
+	case IAPP_CMD_ADD_notify:
375
+		iapp_process_add_notify(iapp, &from, hdr, hlen - sizeof(*hdr));
376
+		break;
377
+	case IAPP_CMD_MOVE_notify:
378
+		/* TODO: MOVE is using TCP; so move this to TCP handler once it
379
+		 * is implemented.. */
380
+		/* IAPP-MOVE.indication(MAC Address, New BSSID,
381
+		 * Sequence Number, AP Address, Context Block) */
382
+		/* TODO: process */
383
+		break;
384
+	default:
385
+		printf("Unknown IAPP command %d\n", hdr->command);
386
+		break;
387
+	}
388
+}
389
+
390
+
391
+struct iapp_data * iapp_init(struct hostapd_data *hapd, const char *iface)
392
+{
393
+	struct ifreq ifr;
394
+	struct sockaddr_ll addr;
395
+	int ifindex;
396
+	struct sockaddr_in *paddr, uaddr;
397
+	struct iapp_data *iapp;
398
+	struct ip_mreqn mreq;
399
+
400
+	iapp = os_zalloc(sizeof(*iapp));
401
+	if (iapp == NULL)
402
+		return NULL;
403
+	iapp->hapd = hapd;
404
+	iapp->udp_sock = iapp->packet_sock = -1;
405
+
406
+	/* TODO:
407
+	 * open socket for sending and receiving IAPP frames over TCP
408
+	 */
409
+
410
+	iapp->udp_sock = socket(PF_INET, SOCK_DGRAM, 0);
411
+	if (iapp->udp_sock < 0) {
412
+		perror("socket[PF_INET,SOCK_DGRAM]");
413
+		iapp_deinit(iapp);
414
+		return NULL;
415
+	}
416
+
417
+	os_memset(&ifr, 0, sizeof(ifr));
418
+	os_strlcpy(ifr.ifr_name, iface, sizeof(ifr.ifr_name));
419
+	if (ioctl(iapp->udp_sock, SIOCGIFINDEX, &ifr) != 0) {
420
+		perror("ioctl(SIOCGIFINDEX)");
421
+		iapp_deinit(iapp);
422
+		return NULL;
423
+	}
424
+	ifindex = ifr.ifr_ifindex;
425
+
426
+	if (ioctl(iapp->udp_sock, SIOCGIFADDR, &ifr) != 0) {
427
+		perror("ioctl(SIOCGIFADDR)");
428
+		iapp_deinit(iapp);
429
+		return NULL;
430
+	}
431
+	paddr = (struct sockaddr_in *) &ifr.ifr_addr;
432
+	if (paddr->sin_family != AF_INET) {
433
+		printf("Invalid address family %i (SIOCGIFADDR)\n",
434
+		       paddr->sin_family);
435
+		iapp_deinit(iapp);
436
+		return NULL;
437
+	}
438
+	iapp->own.s_addr = paddr->sin_addr.s_addr;
439
+
440
+	if (ioctl(iapp->udp_sock, SIOCGIFBRDADDR, &ifr) != 0) {
441
+		perror("ioctl(SIOCGIFBRDADDR)");
442
+		iapp_deinit(iapp);
443
+		return NULL;
444
+	}
445
+	paddr = (struct sockaddr_in *) &ifr.ifr_addr;
446
+	if (paddr->sin_family != AF_INET) {
447
+		printf("Invalid address family %i (SIOCGIFBRDADDR)\n",
448
+		       paddr->sin_family);
449
+		iapp_deinit(iapp);
450
+		return NULL;
451
+	}
452
+	inet_aton(IAPP_MULTICAST, &iapp->multicast);
453
+
454
+	os_memset(&uaddr, 0, sizeof(uaddr));
455
+	uaddr.sin_family = AF_INET;
456
+	uaddr.sin_port = htons(IAPP_UDP_PORT);
457
+	if (bind(iapp->udp_sock, (struct sockaddr *) &uaddr,
458
+		 sizeof(uaddr)) < 0) {
459
+		perror("bind[UDP]");
460
+		iapp_deinit(iapp);
461
+		return NULL;
462
+	}
463
+
464
+	os_memset(&mreq, 0, sizeof(mreq));
465
+	mreq.imr_multiaddr = iapp->multicast;
466
+	mreq.imr_address.s_addr = INADDR_ANY;
467
+	mreq.imr_ifindex = 0;
468
+	if (setsockopt(iapp->udp_sock, SOL_IP, IP_ADD_MEMBERSHIP, &mreq,
469
+		       sizeof(mreq)) < 0) {
470
+		perror("setsockopt[UDP,IP_ADD_MEMBERSHIP]");
471
+		iapp_deinit(iapp);
472
+		return NULL;
473
+	}
474
+
475
+	iapp->packet_sock = socket(PF_PACKET, SOCK_RAW, htons(ETH_P_ALL));
476
+	if (iapp->packet_sock < 0) {
477
+		perror("socket[PF_PACKET,SOCK_RAW]");
478
+		iapp_deinit(iapp);
479
+		return NULL;
480
+	}
481
+
482
+	os_memset(&addr, 0, sizeof(addr));
483
+	addr.sll_family = AF_PACKET;
484
+	addr.sll_ifindex = ifindex;
485
+	if (bind(iapp->packet_sock, (struct sockaddr *) &addr,
486
+		 sizeof(addr)) < 0) {
487
+		perror("bind[PACKET]");
488
+		iapp_deinit(iapp);
489
+		return NULL;
490
+	}
491
+
492
+	if (eloop_register_read_sock(iapp->udp_sock, iapp_receive_udp,
493
+				     iapp, NULL)) {
494
+		printf("Could not register read socket for IAPP.\n");
495
+		iapp_deinit(iapp);
496
+		return NULL;
497
+	}
498
+
499
+	printf("IEEE 802.11F (IAPP) using interface %s\n", iface);
500
+
501
+	/* TODO: For levels 2 and 3: send RADIUS Initiate-Request, receive
502
+	 * RADIUS Initiate-Accept or Initiate-Reject. IAPP port should actually
503
+	 * be openned only after receiving Initiate-Accept. If Initiate-Reject
504
+	 * is received, IAPP is not started. */
505
+
506
+	return iapp;
507
+}
508
+
509
+
510
+void iapp_deinit(struct iapp_data *iapp)
511
+{
512
+	struct ip_mreqn mreq;
513
+
514
+	if (iapp == NULL)
515
+		return;
516
+
517
+	if (iapp->udp_sock >= 0) {
518
+		os_memset(&mreq, 0, sizeof(mreq));
519
+		mreq.imr_multiaddr = iapp->multicast;
520
+		mreq.imr_address.s_addr = INADDR_ANY;
521
+		mreq.imr_ifindex = 0;
522
+		if (setsockopt(iapp->udp_sock, SOL_IP, IP_DROP_MEMBERSHIP,
523
+			       &mreq, sizeof(mreq)) < 0) {
524
+			perror("setsockopt[UDP,IP_DEL_MEMBERSHIP]");
525
+		}
526
+
527
+		eloop_unregister_read_sock(iapp->udp_sock);
528
+		close(iapp->udp_sock);
529
+	}
530
+	if (iapp->packet_sock >= 0) {
531
+		eloop_unregister_read_sock(iapp->packet_sock);
532
+		close(iapp->packet_sock);
533
+	}
534
+	os_free(iapp);
535
+}

+ 45
- 0
src/ap/iapp.h Näytä tiedosto

@@ -0,0 +1,45 @@
1
+/*
2
+ * hostapd / IEEE 802.11F-2003 Inter-Access Point Protocol (IAPP)
3
+ * Copyright (c) 2002-2005, Jouni Malinen <j@w1.fi>
4
+ *
5
+ * This program is free software; you can redistribute it and/or modify
6
+ * it under the terms of the GNU General Public License version 2 as
7
+ * published by the Free Software Foundation.
8
+ *
9
+ * Alternatively, this software may be distributed under the terms of BSD
10
+ * license.
11
+ *
12
+ * See README and COPYING for more details.
13
+ */
14
+
15
+#ifndef IAPP_H
16
+#define IAPP_H
17
+
18
+struct iapp_data;
19
+
20
+#ifdef CONFIG_IAPP
21
+
22
+void iapp_new_station(struct iapp_data *iapp, struct sta_info *sta);
23
+struct iapp_data * iapp_init(struct hostapd_data *hapd, const char *iface);
24
+void iapp_deinit(struct iapp_data *iapp);
25
+
26
+#else /* CONFIG_IAPP */
27
+
28
+static inline void iapp_new_station(struct iapp_data *iapp,
29
+				    struct sta_info *sta)
30
+{
31
+}
32
+
33
+static inline struct iapp_data * iapp_init(struct hostapd_data *hapd,
34
+					   const char *iface)
35
+{
36
+	return NULL;
37
+}
38
+
39
+static inline void iapp_deinit(struct iapp_data *iapp)
40
+{
41
+}
42
+
43
+#endif /* CONFIG_IAPP */
44
+
45
+#endif /* IAPP_H */

+ 1882
- 0
src/ap/ieee802_11.c
File diff suppressed because it is too large
Näytä tiedosto


+ 68
- 0
src/ap/ieee802_11.h Näytä tiedosto

@@ -0,0 +1,68 @@
1
+/*
2
+ * hostapd / IEEE 802.11 Management
3
+ * Copyright (c) 2002-2009, Jouni Malinen <j@w1.fi>
4
+ *
5
+ * This program is free software; you can redistribute it and/or modify
6
+ * it under the terms of the GNU General Public License version 2 as
7
+ * published by the Free Software Foundation.
8
+ *
9
+ * Alternatively, this software may be distributed under the terms of BSD
10
+ * license.
11
+ *
12
+ * See README and COPYING for more details.
13
+ */
14
+
15
+#ifndef IEEE802_11_H
16
+#define IEEE802_11_H
17
+
18
+struct hostapd_iface;
19
+struct hostapd_data;
20
+struct sta_info;
21
+struct hostapd_frame_info;
22
+struct ieee80211_ht_capabilities;
23
+
24
+void ieee802_11_mgmt(struct hostapd_data *hapd, const u8 *buf, size_t len,
25
+		     struct hostapd_frame_info *fi);
26
+void ieee802_11_mgmt_cb(struct hostapd_data *hapd, const u8 *buf, size_t len,
27
+			u16 stype, int ok);
28
+void ieee802_11_print_ssid(char *buf, const u8 *ssid, u8 len);
29
+#ifdef NEED_AP_MLME
30
+int ieee802_11_get_mib(struct hostapd_data *hapd, char *buf, size_t buflen);
31
+int ieee802_11_get_mib_sta(struct hostapd_data *hapd, struct sta_info *sta,
32
+			   char *buf, size_t buflen);
33
+#else /* NEED_AP_MLME */
34
+static inline int ieee802_11_get_mib(struct hostapd_data *hapd, char *buf,
35
+				     size_t buflen)
36
+{
37
+	return 0;
38
+}
39
+
40
+static inline int ieee802_11_get_mib_sta(struct hostapd_data *hapd,
41
+					 struct sta_info *sta,
42
+					 char *buf, size_t buflen)
43
+{
44
+	return 0;
45
+}
46
+#endif /* NEED_AP_MLME */
47
+u16 hostapd_own_capab_info(struct hostapd_data *hapd, struct sta_info *sta,
48
+			   int probe);
49
+u8 * hostapd_eid_ext_capab(struct hostapd_data *hapd, u8 *eid);
50
+u8 * hostapd_eid_supp_rates(struct hostapd_data *hapd, u8 *eid);
51
+u8 * hostapd_eid_ext_supp_rates(struct hostapd_data *hapd, u8 *eid);
52
+u8 * hostapd_eid_ht_capabilities(struct hostapd_data *hapd, u8 *eid);
53
+u8 * hostapd_eid_ht_operation(struct hostapd_data *hapd, u8 *eid);
54
+int hostapd_ht_operation_update(struct hostapd_iface *iface);
55
+void ieee802_11_send_sa_query_req(struct hostapd_data *hapd,
56
+				  const u8 *addr, const u8 *trans_id);
57
+void hostapd_get_ht_capab(struct hostapd_data *hapd,
58
+			  struct ieee80211_ht_capabilities *ht_cap,
59
+			  struct ieee80211_ht_capabilities *neg_ht_cap);
60
+u16 copy_sta_ht_capab(struct hostapd_data *hapd, struct sta_info *sta,
61
+		      const u8 *ht_capab, size_t ht_capab_len);
62
+void update_ht_state(struct hostapd_data *hapd, struct sta_info *sta);
63
+void hostapd_tx_status(struct hostapd_data *hapd, const u8 *addr,
64
+		       const u8 *buf, size_t len, int ack);
65
+void ieee802_11_rx_from_unknown(struct hostapd_data *hapd, const u8 *src,
66
+				int wds);
67
+
68
+#endif /* IEEE802_11_H */

+ 524
- 0
src/ap/ieee802_11_auth.c Näytä tiedosto

@@ -0,0 +1,524 @@
1
+/*
2
+ * hostapd / IEEE 802.11 authentication (ACL)
3
+ * Copyright (c) 2003-2009, Jouni Malinen <j@w1.fi>
4
+ *
5
+ * This program is free software; you can redistribute it and/or modify
6
+ * it under the terms of the GNU General Public License version 2 as
7
+ * published by the Free Software Foundation.
8
+ *
9
+ * Alternatively, this software may be distributed under the terms of BSD
10
+ * license.
11
+ *
12
+ * See README and COPYING for more details.
13
+ *
14
+ * Access control list for IEEE 802.11 authentication can uses statically
15
+ * configured ACL from configuration files or an external RADIUS server.
16
+ * Results from external RADIUS queries are cached to allow faster
17
+ * authentication frame processing.
18
+ */
19
+
20
+#include "utils/includes.h"
21
+
22
+#include "utils/common.h"
23
+#include "utils/eloop.h"
24
+#include "radius/radius.h"
25
+#include "radius/radius_client.h"
26
+#include "hostapd.h"
27
+#include "ap_config.h"
28
+#include "ap_drv_ops.h"
29
+#include "ieee802_11.h"
30
+#include "ieee802_11_auth.h"
31
+
32
+#define RADIUS_ACL_TIMEOUT 30
33
+
34
+
35
+struct hostapd_cached_radius_acl {
36
+	os_time_t timestamp;
37
+	macaddr addr;
38
+	int accepted; /* HOSTAPD_ACL_* */
39
+	struct hostapd_cached_radius_acl *next;
40
+	u32 session_timeout;
41
+	u32 acct_interim_interval;
42
+	int vlan_id;
43
+};
44
+
45
+
46
+struct hostapd_acl_query_data {
47
+	os_time_t timestamp;
48
+	u8 radius_id;
49
+	macaddr addr;
50
+	u8 *auth_msg; /* IEEE 802.11 authentication frame from station */
51
+	size_t auth_msg_len;
52
+	struct hostapd_acl_query_data *next;
53
+};
54
+
55
+
56
+#ifndef CONFIG_NO_RADIUS
57
+static void hostapd_acl_cache_free(struct hostapd_cached_radius_acl *acl_cache)
58
+{
59
+	struct hostapd_cached_radius_acl *prev;
60
+
61
+	while (acl_cache) {
62
+		prev = acl_cache;
63
+		acl_cache = acl_cache->next;
64
+		os_free(prev);
65
+	}
66
+}
67
+
68
+
69
+static int hostapd_acl_cache_get(struct hostapd_data *hapd, const u8 *addr,
70
+				 u32 *session_timeout,
71
+				 u32 *acct_interim_interval, int *vlan_id)
72
+{
73
+	struct hostapd_cached_radius_acl *entry;
74
+	struct os_time now;
75
+
76
+	os_get_time(&now);
77
+	entry = hapd->acl_cache;
78
+
79
+	while (entry) {
80
+		if (os_memcmp(entry->addr, addr, ETH_ALEN) == 0) {
81
+			if (now.sec - entry->timestamp > RADIUS_ACL_TIMEOUT)
82
+				return -1; /* entry has expired */
83
+			if (entry->accepted == HOSTAPD_ACL_ACCEPT_TIMEOUT)
84
+				if (session_timeout)
85
+					*session_timeout =
86
+						entry->session_timeout;
87
+			if (acct_interim_interval)
88
+				*acct_interim_interval =
89
+					entry->acct_interim_interval;
90
+			if (vlan_id)
91
+				*vlan_id = entry->vlan_id;
92
+			return entry->accepted;
93
+		}
94
+
95
+		entry = entry->next;
96
+	}
97
+
98
+	return -1;
99
+}
100
+#endif /* CONFIG_NO_RADIUS */
101
+
102
+
103
+static void hostapd_acl_query_free(struct hostapd_acl_query_data *query)
104
+{
105
+	if (query == NULL)
106
+		return;
107
+	os_free(query->auth_msg);
108
+	os_free(query);
109
+}
110
+
111
+
112
+#ifndef CONFIG_NO_RADIUS
113
+static int hostapd_radius_acl_query(struct hostapd_data *hapd, const u8 *addr,
114
+				    struct hostapd_acl_query_data *query)
115
+{
116
+	struct radius_msg *msg;
117
+	char buf[128];
118
+
119
+	query->radius_id = radius_client_get_id(hapd->radius);
120
+	msg = radius_msg_new(RADIUS_CODE_ACCESS_REQUEST, query->radius_id);
121
+	if (msg == NULL)
122
+		return -1;
123
+
124
+	radius_msg_make_authenticator(msg, addr, ETH_ALEN);
125
+
126
+	os_snprintf(buf, sizeof(buf), RADIUS_ADDR_FORMAT, MAC2STR(addr));
127
+	if (!radius_msg_add_attr(msg, RADIUS_ATTR_USER_NAME, (u8 *) buf,
128
+				 os_strlen(buf))) {
129
+		wpa_printf(MSG_DEBUG, "Could not add User-Name");
130
+		goto fail;
131
+	}
132
+
133
+	if (!radius_msg_add_attr_user_password(
134
+		    msg, (u8 *) buf, os_strlen(buf),
135
+		    hapd->conf->radius->auth_server->shared_secret,
136
+		    hapd->conf->radius->auth_server->shared_secret_len)) {
137
+		wpa_printf(MSG_DEBUG, "Could not add User-Password");
138
+		goto fail;
139
+	}
140
+
141
+	if (hapd->conf->own_ip_addr.af == AF_INET &&
142
+	    !radius_msg_add_attr(msg, RADIUS_ATTR_NAS_IP_ADDRESS,
143
+				 (u8 *) &hapd->conf->own_ip_addr.u.v4, 4)) {
144
+		wpa_printf(MSG_DEBUG, "Could not add NAS-IP-Address");
145
+		goto fail;
146
+	}
147
+
148
+#ifdef CONFIG_IPV6
149
+	if (hapd->conf->own_ip_addr.af == AF_INET6 &&
150
+	    !radius_msg_add_attr(msg, RADIUS_ATTR_NAS_IPV6_ADDRESS,
151
+				 (u8 *) &hapd->conf->own_ip_addr.u.v6, 16)) {
152
+		wpa_printf(MSG_DEBUG, "Could not add NAS-IPv6-Address");
153
+		goto fail;
154
+	}
155
+#endif /* CONFIG_IPV6 */
156
+
157
+	if (hapd->conf->nas_identifier &&
158
+	    !radius_msg_add_attr(msg, RADIUS_ATTR_NAS_IDENTIFIER,
159
+				 (u8 *) hapd->conf->nas_identifier,
160
+				 os_strlen(hapd->conf->nas_identifier))) {
161
+		wpa_printf(MSG_DEBUG, "Could not add NAS-Identifier");
162
+		goto fail;
163
+	}
164
+
165
+	os_snprintf(buf, sizeof(buf), RADIUS_802_1X_ADDR_FORMAT ":%s",
166
+		    MAC2STR(hapd->own_addr), hapd->conf->ssid.ssid);
167
+	if (!radius_msg_add_attr(msg, RADIUS_ATTR_CALLED_STATION_ID,
168
+				 (u8 *) buf, os_strlen(buf))) {
169
+		wpa_printf(MSG_DEBUG, "Could not add Called-Station-Id");
170
+		goto fail;
171
+	}
172
+
173
+	os_snprintf(buf, sizeof(buf), RADIUS_802_1X_ADDR_FORMAT,
174
+		    MAC2STR(addr));
175
+	if (!radius_msg_add_attr(msg, RADIUS_ATTR_CALLING_STATION_ID,
176
+				 (u8 *) buf, os_strlen(buf))) {
177
+		wpa_printf(MSG_DEBUG, "Could not add Calling-Station-Id");
178
+		goto fail;
179
+	}
180
+
181
+	if (!radius_msg_add_attr_int32(msg, RADIUS_ATTR_NAS_PORT_TYPE,
182
+				       RADIUS_NAS_PORT_TYPE_IEEE_802_11)) {
183
+		wpa_printf(MSG_DEBUG, "Could not add NAS-Port-Type");
184
+		goto fail;
185
+	}
186
+
187
+	os_snprintf(buf, sizeof(buf), "CONNECT 11Mbps 802.11b");
188
+	if (!radius_msg_add_attr(msg, RADIUS_ATTR_CONNECT_INFO,
189
+				 (u8 *) buf, os_strlen(buf))) {
190
+		wpa_printf(MSG_DEBUG, "Could not add Connect-Info");
191
+		goto fail;
192
+	}
193
+
194
+	radius_client_send(hapd->radius, msg, RADIUS_AUTH, addr);
195
+	return 0;
196
+
197
+ fail:
198
+	radius_msg_free(msg);
199
+	return -1;
200
+}
201
+#endif /* CONFIG_NO_RADIUS */
202
+
203
+
204
+/**
205
+ * hostapd_allowed_address - Check whether a specified STA can be authenticated
206
+ * @hapd: hostapd BSS data
207
+ * @addr: MAC address of the STA
208
+ * @msg: Authentication message
209
+ * @len: Length of msg in octets
210
+ * @session_timeout: Buffer for returning session timeout (from RADIUS)
211
+ * @acct_interim_interval: Buffer for returning account interval (from RADIUS)
212
+ * @vlan_id: Buffer for returning VLAN ID
213
+ * Returns: HOSTAPD_ACL_ACCEPT, HOSTAPD_ACL_REJECT, or HOSTAPD_ACL_PENDING
214
+ */
215
+int hostapd_allowed_address(struct hostapd_data *hapd, const u8 *addr,
216
+			    const u8 *msg, size_t len, u32 *session_timeout,
217
+			    u32 *acct_interim_interval, int *vlan_id)
218
+{
219
+	if (session_timeout)
220
+		*session_timeout = 0;
221
+	if (acct_interim_interval)
222
+		*acct_interim_interval = 0;
223
+	if (vlan_id)
224
+		*vlan_id = 0;
225
+
226
+	if (hostapd_maclist_found(hapd->conf->accept_mac,
227
+				  hapd->conf->num_accept_mac, addr, vlan_id))
228
+		return HOSTAPD_ACL_ACCEPT;
229
+
230
+	if (hostapd_maclist_found(hapd->conf->deny_mac,
231
+				  hapd->conf->num_deny_mac, addr, vlan_id))
232
+		return HOSTAPD_ACL_REJECT;
233
+
234
+	if (hapd->conf->macaddr_acl == ACCEPT_UNLESS_DENIED)
235
+		return HOSTAPD_ACL_ACCEPT;
236
+	if (hapd->conf->macaddr_acl == DENY_UNLESS_ACCEPTED)
237
+		return HOSTAPD_ACL_REJECT;
238
+
239
+	if (hapd->conf->macaddr_acl == USE_EXTERNAL_RADIUS_AUTH) {
240
+#ifdef CONFIG_NO_RADIUS
241
+		return HOSTAPD_ACL_REJECT;
242
+#else /* CONFIG_NO_RADIUS */
243
+		struct hostapd_acl_query_data *query;
244
+
245
+		/* Check whether ACL cache has an entry for this station */
246
+		int res = hostapd_acl_cache_get(hapd, addr, session_timeout,
247
+						acct_interim_interval,
248
+						vlan_id);
249
+		if (res == HOSTAPD_ACL_ACCEPT ||
250
+		    res == HOSTAPD_ACL_ACCEPT_TIMEOUT)
251
+			return res;
252
+		if (res == HOSTAPD_ACL_REJECT)
253
+			return HOSTAPD_ACL_REJECT;
254
+
255
+		query = hapd->acl_queries;
256
+		while (query) {
257
+			if (os_memcmp(query->addr, addr, ETH_ALEN) == 0) {
258
+				/* pending query in RADIUS retransmit queue;
259
+				 * do not generate a new one */
260
+				return HOSTAPD_ACL_PENDING;
261
+			}
262
+			query = query->next;
263
+		}
264
+
265
+		if (!hapd->conf->radius->auth_server)
266
+			return HOSTAPD_ACL_REJECT;
267
+
268
+		/* No entry in the cache - query external RADIUS server */
269
+		query = os_zalloc(sizeof(*query));
270
+		if (query == NULL) {
271
+			wpa_printf(MSG_ERROR, "malloc for query data failed");
272
+			return HOSTAPD_ACL_REJECT;
273
+		}
274
+		time(&query->timestamp);
275
+		os_memcpy(query->addr, addr, ETH_ALEN);
276
+		if (hostapd_radius_acl_query(hapd, addr, query)) {
277
+			wpa_printf(MSG_DEBUG, "Failed to send Access-Request "
278
+				   "for ACL query.");
279
+			hostapd_acl_query_free(query);
280
+			return HOSTAPD_ACL_REJECT;
281
+		}
282
+
283
+		query->auth_msg = os_malloc(len);
284
+		if (query->auth_msg == NULL) {
285
+			wpa_printf(MSG_ERROR, "Failed to allocate memory for "
286
+				   "auth frame.");
287
+			hostapd_acl_query_free(query);
288
+			return HOSTAPD_ACL_REJECT;
289
+		}
290
+		os_memcpy(query->auth_msg, msg, len);
291
+		query->auth_msg_len = len;
292
+		query->next = hapd->acl_queries;
293
+		hapd->acl_queries = query;
294
+
295
+		/* Queued data will be processed in hostapd_acl_recv_radius()
296
+		 * when RADIUS server replies to the sent Access-Request. */
297
+		return HOSTAPD_ACL_PENDING;
298
+#endif /* CONFIG_NO_RADIUS */
299
+	}
300
+
301
+	return HOSTAPD_ACL_REJECT;
302
+}
303
+
304
+
305
+#ifndef CONFIG_NO_RADIUS
306
+static void hostapd_acl_expire_cache(struct hostapd_data *hapd, os_time_t now)
307
+{
308
+	struct hostapd_cached_radius_acl *prev, *entry, *tmp;
309
+
310
+	prev = NULL;
311
+	entry = hapd->acl_cache;
312
+
313
+	while (entry) {
314
+		if (now - entry->timestamp > RADIUS_ACL_TIMEOUT) {
315
+			wpa_printf(MSG_DEBUG, "Cached ACL entry for " MACSTR
316
+				   " has expired.", MAC2STR(entry->addr));
317
+			if (prev)
318
+				prev->next = entry->next;
319
+			else
320
+				hapd->acl_cache = entry->next;
321
+			hostapd_drv_set_radius_acl_expire(hapd, entry->addr);
322
+			tmp = entry;
323
+			entry = entry->next;
324
+			os_free(tmp);
325
+			continue;
326
+		}
327
+
328
+		prev = entry;
329
+		entry = entry->next;
330
+	}
331
+}
332
+
333
+
334
+static void hostapd_acl_expire_queries(struct hostapd_data *hapd,
335
+				       os_time_t now)
336
+{
337
+	struct hostapd_acl_query_data *prev, *entry, *tmp;
338
+
339
+	prev = NULL;
340
+	entry = hapd->acl_queries;
341
+
342
+	while (entry) {
343
+		if (now - entry->timestamp > RADIUS_ACL_TIMEOUT) {
344
+			wpa_printf(MSG_DEBUG, "ACL query for " MACSTR
345
+				   " has expired.", MAC2STR(entry->addr));
346
+			if (prev)
347
+				prev->next = entry->next;
348
+			else
349
+				hapd->acl_queries = entry->next;
350
+
351
+			tmp = entry;
352
+			entry = entry->next;
353
+			hostapd_acl_query_free(tmp);
354
+			continue;
355
+		}
356
+
357
+		prev = entry;
358
+		entry = entry->next;
359
+	}
360
+}
361
+
362
+
363
+/**
364
+ * hostapd_acl_expire - ACL cache expiration callback
365
+ * @eloop_ctx: struct hostapd_data *
366
+ * @timeout_ctx: Not used
367
+ */
368
+static void hostapd_acl_expire(void *eloop_ctx, void *timeout_ctx)
369
+{
370
+	struct hostapd_data *hapd = eloop_ctx;
371
+	struct os_time now;
372
+
373
+	os_get_time(&now);
374
+	hostapd_acl_expire_cache(hapd, now.sec);
375
+	hostapd_acl_expire_queries(hapd, now.sec);
376
+
377
+	eloop_register_timeout(10, 0, hostapd_acl_expire, hapd, NULL);
378
+}
379
+
380
+
381
+/**
382
+ * hostapd_acl_recv_radius - Process incoming RADIUS Authentication messages
383
+ * @msg: RADIUS response message
384
+ * @req: RADIUS request message
385
+ * @shared_secret: RADIUS shared secret
386
+ * @shared_secret_len: Length of shared_secret in octets
387
+ * @data: Context data (struct hostapd_data *)
388
+ * Returns: RADIUS_RX_PROCESSED if RADIUS message was a reply to ACL query (and
389
+ * was processed here) or RADIUS_RX_UNKNOWN if not.
390
+ */
391
+static RadiusRxResult
392
+hostapd_acl_recv_radius(struct radius_msg *msg, struct radius_msg *req,
393
+			const u8 *shared_secret, size_t shared_secret_len,
394
+			void *data)
395
+{
396
+	struct hostapd_data *hapd = data;
397
+	struct hostapd_acl_query_data *query, *prev;
398
+	struct hostapd_cached_radius_acl *cache;
399
+	struct radius_hdr *hdr = radius_msg_get_hdr(msg);
400
+
401
+	query = hapd->acl_queries;
402
+	prev = NULL;
403
+	while (query) {
404
+		if (query->radius_id == hdr->identifier)
405
+			break;
406
+		prev = query;
407
+		query = query->next;
408
+	}
409
+	if (query == NULL)
410
+		return RADIUS_RX_UNKNOWN;
411
+
412
+	wpa_printf(MSG_DEBUG, "Found matching Access-Request for RADIUS "
413
+		   "message (id=%d)", query->radius_id);
414
+
415
+	if (radius_msg_verify(msg, shared_secret, shared_secret_len, req, 0)) {
416
+		wpa_printf(MSG_INFO, "Incoming RADIUS packet did not have "
417
+			   "correct authenticator - dropped\n");
418
+		return RADIUS_RX_INVALID_AUTHENTICATOR;
419
+	}
420
+
421
+	if (hdr->code != RADIUS_CODE_ACCESS_ACCEPT &&
422
+	    hdr->code != RADIUS_CODE_ACCESS_REJECT) {
423
+		wpa_printf(MSG_DEBUG, "Unknown RADIUS message code %d to ACL "
424
+			   "query", hdr->code);
425
+		return RADIUS_RX_UNKNOWN;
426
+	}
427
+
428
+	/* Insert Accept/Reject info into ACL cache */
429
+	cache = os_zalloc(sizeof(*cache));
430
+	if (cache == NULL) {
431
+		wpa_printf(MSG_DEBUG, "Failed to add ACL cache entry");
432
+		goto done;
433
+	}
434
+	time(&cache->timestamp);
435
+	os_memcpy(cache->addr, query->addr, sizeof(cache->addr));
436
+	if (hdr->code == RADIUS_CODE_ACCESS_ACCEPT) {
437
+		if (radius_msg_get_attr_int32(msg, RADIUS_ATTR_SESSION_TIMEOUT,
438
+					      &cache->session_timeout) == 0)
439
+			cache->accepted = HOSTAPD_ACL_ACCEPT_TIMEOUT;
440
+		else
441
+			cache->accepted = HOSTAPD_ACL_ACCEPT;
442
+
443
+		if (radius_msg_get_attr_int32(
444
+			    msg, RADIUS_ATTR_ACCT_INTERIM_INTERVAL,
445
+			    &cache->acct_interim_interval) == 0 &&
446
+		    cache->acct_interim_interval < 60) {
447
+			wpa_printf(MSG_DEBUG, "Ignored too small "
448
+				   "Acct-Interim-Interval %d for STA " MACSTR,
449
+				   cache->acct_interim_interval,
450
+				   MAC2STR(query->addr));
451
+			cache->acct_interim_interval = 0;
452
+		}
453
+
454
+		cache->vlan_id = radius_msg_get_vlanid(msg);
455
+	} else
456
+		cache->accepted = HOSTAPD_ACL_REJECT;
457
+	cache->next = hapd->acl_cache;
458
+	hapd->acl_cache = cache;
459
+
460
+#ifdef CONFIG_DRIVER_RADIUS_ACL
461
+	hostapd_drv_set_radius_acl_auth(hapd, query->addr, cache->accepted,
462
+					cache->session_timeout);
463
+#else /* CONFIG_DRIVER_RADIUS_ACL */
464
+#ifdef NEED_AP_MLME
465
+	/* Re-send original authentication frame for 802.11 processing */
466
+	wpa_printf(MSG_DEBUG, "Re-sending authentication frame after "
467
+		   "successful RADIUS ACL query");
468
+	ieee802_11_mgmt(hapd, query->auth_msg, query->auth_msg_len, NULL);
469
+#endif /* NEED_AP_MLME */
470
+#endif /* CONFIG_DRIVER_RADIUS_ACL */
471
+
472
+ done:
473
+	if (prev == NULL)
474
+		hapd->acl_queries = query->next;
475
+	else
476
+		prev->next = query->next;
477
+
478
+	hostapd_acl_query_free(query);
479
+
480
+	return RADIUS_RX_PROCESSED;
481
+}
482
+#endif /* CONFIG_NO_RADIUS */
483
+
484
+
485
+/**
486
+ * hostapd_acl_init: Initialize IEEE 802.11 ACL
487
+ * @hapd: hostapd BSS data
488
+ * Returns: 0 on success, -1 on failure
489
+ */
490
+int hostapd_acl_init(struct hostapd_data *hapd)
491
+{
492
+#ifndef CONFIG_NO_RADIUS
493
+	if (radius_client_register(hapd->radius, RADIUS_AUTH,
494
+				   hostapd_acl_recv_radius, hapd))
495
+		return -1;
496
+
497
+	eloop_register_timeout(10, 0, hostapd_acl_expire, hapd, NULL);
498
+#endif /* CONFIG_NO_RADIUS */
499
+
500
+	return 0;
501
+}
502
+
503
+
504
+/**
505
+ * hostapd_acl_deinit - Deinitialize IEEE 802.11 ACL
506
+ * @hapd: hostapd BSS data
507
+ */
508
+void hostapd_acl_deinit(struct hostapd_data *hapd)
509
+{
510
+	struct hostapd_acl_query_data *query, *prev;
511
+
512
+#ifndef CONFIG_NO_RADIUS
513
+	eloop_cancel_timeout(hostapd_acl_expire, hapd, NULL);
514
+
515
+	hostapd_acl_cache_free(hapd->acl_cache);
516
+#endif /* CONFIG_NO_RADIUS */
517
+
518
+	query = hapd->acl_queries;
519
+	while (query) {
520
+		prev = query;
521
+		query = query->next;
522
+		hostapd_acl_query_free(prev);
523
+	}
524
+}

+ 31
- 0
src/ap/ieee802_11_auth.h Näytä tiedosto

@@ -0,0 +1,31 @@
1
+/*
2
+ * hostapd / IEEE 802.11 authentication (ACL)
3
+ * Copyright (c) 2003-2005, Jouni Malinen <j@w1.fi>
4
+ *
5
+ * This program is free software; you can redistribute it and/or modify
6
+ * it under the terms of the GNU General Public License version 2 as
7
+ * published by the Free Software Foundation.
8
+ *
9
+ * Alternatively, this software may be distributed under the terms of BSD
10
+ * license.
11
+ *
12
+ * See README and COPYING for more details.
13
+ */
14
+
15
+#ifndef IEEE802_11_AUTH_H
16
+#define IEEE802_11_AUTH_H
17
+
18
+enum {
19
+	HOSTAPD_ACL_REJECT = 0,
20
+	HOSTAPD_ACL_ACCEPT = 1,
21
+	HOSTAPD_ACL_PENDING = 2,
22
+	HOSTAPD_ACL_ACCEPT_TIMEOUT = 3
23
+};
24
+
25
+int hostapd_allowed_address(struct hostapd_data *hapd, const u8 *addr,
26
+			    const u8 *msg, size_t len, u32 *session_timeout,
27
+			    u32 *acct_interim_interval, int *vlan_id);
28
+int hostapd_acl_init(struct hostapd_data *hapd);
29
+void hostapd_acl_deinit(struct hostapd_data *hapd);
30
+
31
+#endif /* IEEE802_11_AUTH_H */

+ 267
- 0
src/ap/ieee802_11_ht.c Näytä tiedosto

@@ -0,0 +1,267 @@
1
+/*
2
+ * hostapd / IEEE 802.11n HT
3
+ * Copyright (c) 2002-2009, Jouni Malinen <j@w1.fi>
4
+ * Copyright (c) 2007-2008, Intel Corporation
5
+ *
6
+ * This program is free software; you can redistribute it and/or modify
7
+ * it under the terms of the GNU General Public License version 2 as
8
+ * published by the Free Software Foundation.
9
+ *
10
+ * Alternatively, this software may be distributed under the terms of BSD
11
+ * license.
12
+ *
13
+ * See README and COPYING for more details.
14
+ */
15
+
16
+#include "utils/includes.h"
17
+
18
+#include "utils/common.h"
19
+#include "common/ieee802_11_defs.h"
20
+#include "drivers/driver.h"
21
+#include "hostapd.h"
22
+#include "ap_config.h"
23
+#include "sta_info.h"
24
+#include "beacon.h"
25
+#include "ieee802_11.h"
26
+
27
+
28
+u8 * hostapd_eid_ht_capabilities(struct hostapd_data *hapd, u8 *eid)
29
+{
30
+	struct ieee80211_ht_capabilities *cap;
31
+	u8 *pos = eid;
32
+
33
+	if (!hapd->iconf->ieee80211n || !hapd->iface->current_mode ||
34
+	    hapd->conf->disable_11n)
35
+		return eid;
36
+
37
+	*pos++ = WLAN_EID_HT_CAP;
38
+	*pos++ = sizeof(*cap);
39
+
40
+	cap = (struct ieee80211_ht_capabilities *) pos;
41
+	os_memset(cap, 0, sizeof(*cap));
42
+	cap->ht_capabilities_info = host_to_le16(hapd->iconf->ht_capab);
43
+	cap->a_mpdu_params = hapd->iface->current_mode->a_mpdu_params;
44
+	os_memcpy(cap->supported_mcs_set, hapd->iface->current_mode->mcs_set,
45
+		  16);
46
+
47
+	/* TODO: ht_extended_capabilities (now fully disabled) */
48
+	/* TODO: tx_bf_capability_info (now fully disabled) */
49
+	/* TODO: asel_capabilities (now fully disabled) */
50
+
51
+ 	pos += sizeof(*cap);
52
+
53
+	return pos;
54
+}
55
+
56
+
57
+u8 * hostapd_eid_ht_operation(struct hostapd_data *hapd, u8 *eid)
58
+{
59
+	struct ieee80211_ht_operation *oper;
60
+	u8 *pos = eid;
61
+
62
+	if (!hapd->iconf->ieee80211n || hapd->conf->disable_11n)
63
+		return eid;
64
+
65
+	*pos++ = WLAN_EID_HT_OPERATION;
66
+	*pos++ = sizeof(*oper);
67
+
68
+	oper = (struct ieee80211_ht_operation *) pos;
69
+	os_memset(oper, 0, sizeof(*oper));
70
+
71
+	oper->control_chan = hapd->iconf->channel;
72
+	oper->operation_mode = host_to_le16(hapd->iface->ht_op_mode);
73
+	if (hapd->iconf->secondary_channel == 1)
74
+		oper->ht_param |= HT_INFO_HT_PARAM_SECONDARY_CHNL_ABOVE |
75
+			HT_INFO_HT_PARAM_REC_TRANS_CHNL_WIDTH;
76
+	if (hapd->iconf->secondary_channel == -1)
77
+		oper->ht_param |= HT_INFO_HT_PARAM_SECONDARY_CHNL_BELOW |
78
+			HT_INFO_HT_PARAM_REC_TRANS_CHNL_WIDTH;
79
+
80
+	pos += sizeof(*oper);
81
+
82
+	return pos;
83
+}
84
+
85
+
86
+/*
87
+op_mode
88
+Set to 0 (HT pure) under the followign conditions
89
+	- all STAs in the BSS are 20/40 MHz HT in 20/40 MHz BSS or
90
+	- all STAs in the BSS are 20 MHz HT in 20 MHz BSS
91
+Set to 1 (HT non-member protection) if there may be non-HT STAs
92
+	in both the primary and the secondary channel
93
+Set to 2 if only HT STAs are associated in BSS,
94
+	however and at least one 20 MHz HT STA is associated
95
+Set to 3 (HT mixed mode) when one or more non-HT STAs are associated
96
+*/
97
+int hostapd_ht_operation_update(struct hostapd_iface *iface)
98
+{
99
+	u16 cur_op_mode, new_op_mode;
100
+	int op_mode_changes = 0;
101
+
102
+	if (!iface->conf->ieee80211n || iface->conf->ht_op_mode_fixed)
103
+		return 0;
104
+
105
+	wpa_printf(MSG_DEBUG, "%s current operation mode=0x%X",
106
+		   __func__, iface->ht_op_mode);
107
+
108
+	if (!(iface->ht_op_mode & HT_INFO_OPERATION_MODE_NON_GF_DEVS_PRESENT)
109
+	    && iface->num_sta_ht_no_gf) {
110
+		iface->ht_op_mode |=
111
+			HT_INFO_OPERATION_MODE_NON_GF_DEVS_PRESENT;
112
+		op_mode_changes++;
113
+	} else if ((iface->ht_op_mode &
114
+		    HT_INFO_OPERATION_MODE_NON_GF_DEVS_PRESENT) &&
115
+		   iface->num_sta_ht_no_gf == 0) {
116
+		iface->ht_op_mode &=
117
+			~HT_INFO_OPERATION_MODE_NON_GF_DEVS_PRESENT;
118
+		op_mode_changes++;
119
+	}
120
+
121
+	if (!(iface->ht_op_mode & HT_INFO_OPERATION_MODE_NON_HT_STA_PRESENT) &&
122
+	    (iface->num_sta_no_ht || iface->olbc_ht)) {
123
+		iface->ht_op_mode |= HT_INFO_OPERATION_MODE_NON_HT_STA_PRESENT;
124
+		op_mode_changes++;
125
+	} else if ((iface->ht_op_mode &
126
+		    HT_INFO_OPERATION_MODE_NON_HT_STA_PRESENT) &&
127
+		   (iface->num_sta_no_ht == 0 && !iface->olbc_ht)) {
128
+		iface->ht_op_mode &=
129
+			~HT_INFO_OPERATION_MODE_NON_HT_STA_PRESENT;
130
+		op_mode_changes++;
131
+	}
132
+
133
+	new_op_mode = 0;
134
+	if (iface->num_sta_no_ht)
135
+		new_op_mode = OP_MODE_MIXED;
136
+	else if ((iface->conf->ht_capab & HT_CAP_INFO_SUPP_CHANNEL_WIDTH_SET)
137
+		 && iface->num_sta_ht_20mhz)
138
+		new_op_mode = OP_MODE_20MHZ_HT_STA_ASSOCED;
139
+	else if (iface->olbc_ht)
140
+		new_op_mode = OP_MODE_MAY_BE_LEGACY_STAS;
141
+	else
142
+		new_op_mode = OP_MODE_PURE;
143
+
144
+	cur_op_mode = iface->ht_op_mode & HT_INFO_OPERATION_MODE_OP_MODE_MASK;
145
+	if (cur_op_mode != new_op_mode) {
146
+		iface->ht_op_mode &= ~HT_INFO_OPERATION_MODE_OP_MODE_MASK;
147
+		iface->ht_op_mode |= new_op_mode;
148
+		op_mode_changes++;
149
+	}
150
+
151
+	wpa_printf(MSG_DEBUG, "%s new operation mode=0x%X changes=%d",
152
+		   __func__, iface->ht_op_mode, op_mode_changes);
153
+
154
+	return op_mode_changes;
155
+}
156
+
157
+
158
+u16 copy_sta_ht_capab(struct hostapd_data *hapd, struct sta_info *sta,
159
+		      const u8 *ht_capab, size_t ht_capab_len)
160
+{
161
+	/* Disable HT caps for STAs associated to no-HT BSSes. */
162
+	if (!ht_capab ||
163
+	    ht_capab_len < sizeof(struct ieee80211_ht_capabilities) ||
164
+	    hapd->conf->disable_11n) {
165
+		sta->flags &= ~WLAN_STA_HT;
166
+		os_free(sta->ht_capabilities);
167
+		sta->ht_capabilities = NULL;
168
+		return WLAN_STATUS_SUCCESS;
169
+	}
170
+
171
+	if (sta->ht_capabilities == NULL) {
172
+		sta->ht_capabilities =
173
+			os_zalloc(sizeof(struct ieee80211_ht_capabilities));
174
+		if (sta->ht_capabilities == NULL)
175
+			return WLAN_STATUS_UNSPECIFIED_FAILURE;
176
+	}
177
+
178
+	sta->flags |= WLAN_STA_HT;
179
+	os_memcpy(sta->ht_capabilities, ht_capab,
180
+		  sizeof(struct ieee80211_ht_capabilities));
181
+
182
+	return WLAN_STATUS_SUCCESS;
183
+}
184
+
185
+
186
+static void update_sta_ht(struct hostapd_data *hapd, struct sta_info *sta)
187
+{
188
+	u16 ht_capab;
189
+
190
+	ht_capab = le_to_host16(sta->ht_capabilities->ht_capabilities_info);
191
+	wpa_printf(MSG_DEBUG, "HT: STA " MACSTR " HT Capabilities Info: "
192
+		   "0x%04x", MAC2STR(sta->addr), ht_capab);
193
+	if ((ht_capab & HT_CAP_INFO_GREEN_FIELD) == 0) {
194
+		if (!sta->no_ht_gf_set) {
195
+			sta->no_ht_gf_set = 1;
196
+			hapd->iface->num_sta_ht_no_gf++;
197
+		}
198
+		wpa_printf(MSG_DEBUG, "%s STA " MACSTR " - no greenfield, num "
199
+			   "of non-gf stations %d",
200
+			   __func__, MAC2STR(sta->addr),
201
+			   hapd->iface->num_sta_ht_no_gf);
202
+	}
203
+	if ((ht_capab & HT_CAP_INFO_SUPP_CHANNEL_WIDTH_SET) == 0) {
204
+		if (!sta->ht_20mhz_set) {
205
+			sta->ht_20mhz_set = 1;
206
+			hapd->iface->num_sta_ht_20mhz++;
207
+		}
208
+		wpa_printf(MSG_DEBUG, "%s STA " MACSTR " - 20 MHz HT, num of "
209
+			   "20MHz HT STAs %d",
210
+			   __func__, MAC2STR(sta->addr),
211
+			   hapd->iface->num_sta_ht_20mhz);
212
+	}
213
+}
214
+
215
+
216
+static void update_sta_no_ht(struct hostapd_data *hapd, struct sta_info *sta)
217
+{
218
+	if (!sta->no_ht_set) {
219
+		sta->no_ht_set = 1;
220
+		hapd->iface->num_sta_no_ht++;
221
+	}
222
+	if (hapd->iconf->ieee80211n) {
223
+		wpa_printf(MSG_DEBUG, "%s STA " MACSTR " - no HT, num of "
224
+			   "non-HT stations %d",
225
+			   __func__, MAC2STR(sta->addr),
226
+			   hapd->iface->num_sta_no_ht);
227
+	}
228
+}
229
+
230
+
231
+void update_ht_state(struct hostapd_data *hapd, struct sta_info *sta)
232
+{
233
+	if ((sta->flags & WLAN_STA_HT) && sta->ht_capabilities)
234
+		update_sta_ht(hapd, sta);
235
+	else
236
+		update_sta_no_ht(hapd, sta);
237
+
238
+	if (hostapd_ht_operation_update(hapd->iface) > 0)
239
+		ieee802_11_set_beacons(hapd->iface);
240
+}
241
+
242
+
243
+void hostapd_get_ht_capab(struct hostapd_data *hapd,
244
+			  struct ieee80211_ht_capabilities *ht_cap,
245
+			  struct ieee80211_ht_capabilities *neg_ht_cap)
246
+{
247
+	u16 cap;
248
+
249
+	if (ht_cap == NULL)
250
+		return;
251
+	os_memcpy(neg_ht_cap, ht_cap, sizeof(*neg_ht_cap));
252
+	cap = le_to_host16(neg_ht_cap->ht_capabilities_info);
253
+	cap &= hapd->iconf->ht_capab;
254
+	cap |= (hapd->iconf->ht_capab & HT_CAP_INFO_SMPS_DISABLED);
255
+
256
+	/*
257
+	 * STBC needs to be handled specially
258
+	 * if we don't support RX STBC, mask out TX STBC in the STA's HT caps
259
+	 * if we don't support TX STBC, mask out RX STBC in the STA's HT caps
260
+	 */
261
+	if (!(hapd->iconf->ht_capab & HT_CAP_INFO_RX_STBC_MASK))
262
+		cap &= ~HT_CAP_INFO_TX_STBC;
263
+	if (!(hapd->iconf->ht_capab & HT_CAP_INFO_TX_STBC))
264
+		cap &= ~HT_CAP_INFO_RX_STBC_MASK;
265
+
266
+	neg_ht_cap->ht_capabilities_info = host_to_le16(cap);
267
+}

+ 2085
- 0
src/ap/ieee802_1x.c
File diff suppressed because it is too large
Näytä tiedosto


+ 89
- 0
src/ap/ieee802_1x.h Näytä tiedosto

@@ -0,0 +1,89 @@
1
+/*
2
+ * hostapd / IEEE 802.1X-2004 Authenticator
3
+ * Copyright (c) 2002-2007, Jouni Malinen <j@w1.fi>
4
+ *
5
+ * This program is free software; you can redistribute it and/or modify
6
+ * it under the terms of the GNU General Public License version 2 as
7
+ * published by the Free Software Foundation.
8
+ *
9
+ * Alternatively, this software may be distributed under the terms of BSD
10
+ * license.
11
+ *
12
+ * See README and COPYING for more details.
13
+ */
14
+
15
+#ifndef IEEE802_1X_H
16
+#define IEEE802_1X_H
17
+
18
+struct hostapd_data;
19
+struct sta_info;
20
+struct eapol_state_machine;
21
+struct hostapd_config;
22
+struct hostapd_bss_config;
23
+
24
+#ifdef _MSC_VER
25
+#pragma pack(push, 1)
26
+#endif /* _MSC_VER */
27
+
28
+/* RFC 3580, 4. RC4 EAPOL-Key Frame */
29
+
30
+struct ieee802_1x_eapol_key {
31
+	u8 type;
32
+	u16 key_length;
33
+	u8 replay_counter[8]; /* does not repeat within the life of the keying
34
+			       * material used to encrypt the Key field;
35
+			       * 64-bit NTP timestamp MAY be used here */
36
+	u8 key_iv[16]; /* cryptographically random number */
37
+	u8 key_index; /* key flag in the most significant bit:
38
+		       * 0 = broadcast (default key),
39
+		       * 1 = unicast (key mapping key); key index is in the
40
+		       * 7 least significant bits */
41
+	u8 key_signature[16]; /* HMAC-MD5 message integrity check computed with
42
+			       * MS-MPPE-Send-Key as the key */
43
+
44
+	/* followed by key: if packet body length = 44 + key length, then the
45
+	 * key field (of key_length bytes) contains the key in encrypted form;
46
+	 * if packet body length = 44, key field is absent and key_length
47
+	 * represents the number of least significant octets from
48
+	 * MS-MPPE-Send-Key attribute to be used as the keying material;
49
+	 * RC4 key used in encryption = Key-IV + MS-MPPE-Recv-Key */
50
+} STRUCT_PACKED;
51
+
52
+#ifdef _MSC_VER
53
+#pragma pack(pop)
54
+#endif /* _MSC_VER */
55
+
56
+
57
+void ieee802_1x_receive(struct hostapd_data *hapd, const u8 *sa, const u8 *buf,
58
+			size_t len);
59
+void ieee802_1x_new_station(struct hostapd_data *hapd, struct sta_info *sta);
60
+void ieee802_1x_free_station(struct sta_info *sta);
61
+
62
+void ieee802_1x_tx_key(struct hostapd_data *hapd, struct sta_info *sta);
63
+void ieee802_1x_abort_auth(struct hostapd_data *hapd, struct sta_info *sta);
64
+void ieee802_1x_set_sta_authorized(struct hostapd_data *hapd,
65
+				   struct sta_info *sta, int authorized);
66
+void ieee802_1x_dump_state(FILE *f, const char *prefix, struct sta_info *sta);
67
+int ieee802_1x_init(struct hostapd_data *hapd);
68
+void ieee802_1x_deinit(struct hostapd_data *hapd);
69
+int ieee802_1x_tx_status(struct hostapd_data *hapd, struct sta_info *sta,
70
+			 const u8 *buf, size_t len, int ack);
71
+u8 * ieee802_1x_get_identity(struct eapol_state_machine *sm, size_t *len);
72
+u8 * ieee802_1x_get_radius_class(struct eapol_state_machine *sm, size_t *len,
73
+				 int idx);
74
+const u8 * ieee802_1x_get_key(struct eapol_state_machine *sm, size_t *len);
75
+void ieee802_1x_notify_port_enabled(struct eapol_state_machine *sm,
76
+				    int enabled);
77
+void ieee802_1x_notify_port_valid(struct eapol_state_machine *sm,
78
+				  int valid);
79
+void ieee802_1x_notify_pre_auth(struct eapol_state_machine *sm, int pre_auth);
80
+int ieee802_1x_get_mib(struct hostapd_data *hapd, char *buf, size_t buflen);
81
+int ieee802_1x_get_mib_sta(struct hostapd_data *hapd, struct sta_info *sta,
82
+			   char *buf, size_t buflen);
83
+void hostapd_get_ntp_timestamp(u8 *buf);
84
+char *eap_type_text(u8 type);
85
+
86
+const char *radius_mode_txt(struct hostapd_data *hapd);
87
+int radius_sta_rate(struct hostapd_data *hapd, struct sta_info *sta);
88
+
89
+#endif /* IEEE802_1X_H */

+ 120
- 0
src/ap/p2p_hostapd.c Näytä tiedosto

@@ -0,0 +1,120 @@
1
+/*
2
+ * hostapd / P2P integration
3
+ * Copyright (c) 2009-2010, Atheros Communications
4
+ *
5
+ * This program is free software; you can redistribute it and/or modify
6
+ * it under the terms of the GNU General Public License version 2 as
7
+ * published by the Free Software Foundation.
8
+ *
9
+ * Alternatively, this software may be distributed under the terms of BSD
10
+ * license.
11
+ *
12
+ * See README and COPYING for more details.
13
+ */
14
+
15
+#include "utils/includes.h"
16
+
17
+#include "utils/common.h"
18
+#include "common/ieee802_11_defs.h"
19
+#include "p2p/p2p.h"
20
+#include "hostapd.h"
21
+#include "ap_config.h"
22
+#include "ap_drv_ops.h"
23
+#include "sta_info.h"
24
+#include "p2p_hostapd.h"
25
+
26
+
27
+#ifdef CONFIG_P2P
28
+
29
+int hostapd_p2p_get_mib_sta(struct hostapd_data *hapd, struct sta_info *sta,
30
+			    char *buf, size_t buflen)
31
+{
32
+	if (sta->p2p_ie == NULL)
33
+		return 0;
34
+
35
+	return p2p_ie_text(sta->p2p_ie, buf, buf + buflen);
36
+}
37
+
38
+
39
+int hostapd_p2p_set_noa(struct hostapd_data *hapd, u8 count, int start,
40
+			int duration)
41
+{
42
+	wpa_printf(MSG_DEBUG, "P2P: Set NoA parameters: count=%u start=%d "
43
+		   "duration=%d", count, start, duration);
44
+
45
+	if (count == 0) {
46
+		hapd->noa_enabled = 0;
47
+		hapd->noa_start = 0;
48
+		hapd->noa_duration = 0;
49
+	}
50
+
51
+	if (count != 255) {
52
+		wpa_printf(MSG_DEBUG, "P2P: Non-periodic NoA - set "
53
+			   "NoA parameters");
54
+		return hostapd_driver_set_noa(hapd, count, start, duration);
55
+	}
56
+
57
+	hapd->noa_enabled = 1;
58
+	hapd->noa_start = start;
59
+	hapd->noa_duration = duration;
60
+
61
+	if (hapd->num_sta_no_p2p == 0) {
62
+		wpa_printf(MSG_DEBUG, "P2P: No legacy STAs connected - update "
63
+			   "periodic NoA parameters");
64
+		return hostapd_driver_set_noa(hapd, count, start, duration);
65
+	}
66
+
67
+	wpa_printf(MSG_DEBUG, "P2P: Legacy STA(s) connected - do not enable "
68
+		   "periodic NoA");
69
+
70
+	return 0;
71
+}
72
+
73
+
74
+void hostapd_p2p_non_p2p_sta_connected(struct hostapd_data *hapd)
75
+{
76
+	wpa_printf(MSG_DEBUG, "P2P: First non-P2P device connected");
77
+
78
+	if (hapd->noa_enabled) {
79
+		wpa_printf(MSG_DEBUG, "P2P: Disable periodic NoA");
80
+		hostapd_driver_set_noa(hapd, 0, 0, 0);
81
+	}
82
+}
83
+
84
+
85
+void hostapd_p2p_non_p2p_sta_disconnected(struct hostapd_data *hapd)
86
+{
87
+	wpa_printf(MSG_DEBUG, "P2P: Last non-P2P device disconnected");
88
+
89
+	if (hapd->noa_enabled) {
90
+		wpa_printf(MSG_DEBUG, "P2P: Enable periodic NoA");
91
+		hostapd_driver_set_noa(hapd, 255, hapd->noa_start,
92
+				       hapd->noa_duration);
93
+	}
94
+}
95
+
96
+#endif /* CONFIG_P2P */
97
+
98
+
99
+#ifdef CONFIG_P2P_MANAGER
100
+u8 * hostapd_eid_p2p_manage(struct hostapd_data *hapd, u8 *eid)
101
+{
102
+	u8 bitmap;
103
+	*eid++ = WLAN_EID_VENDOR_SPECIFIC;
104
+	*eid++ = 4 + 3 + 1;
105
+	WPA_PUT_BE24(eid, OUI_WFA);
106
+	eid += 3;
107
+	*eid++ = P2P_OUI_TYPE;
108
+
109
+	*eid++ = P2P_ATTR_MANAGEABILITY;
110
+	WPA_PUT_LE16(eid, 1);
111
+	eid += 2;
112
+	bitmap = P2P_MAN_DEVICE_MANAGEMENT;
113
+	if (hapd->conf->p2p & P2P_ALLOW_CROSS_CONNECTION)
114
+		bitmap |= P2P_MAN_CROSS_CONNECTION_PERMITTED;
115
+	bitmap |= P2P_MAN_COEXISTENCE_OPTIONAL;
116
+	*eid++ = bitmap;
117
+
118
+	return eid;
119
+}
120
+#endif /* CONFIG_P2P_MANAGER */

+ 41
- 0
src/ap/p2p_hostapd.h Näytä tiedosto

@@ -0,0 +1,41 @@
1
+/*
2
+ * hostapd / P2P integration
3
+ * Copyright (c) 2009-2010, Atheros Communications
4
+ *
5
+ * This program is free software; you can redistribute it and/or modify
6
+ * it under the terms of the GNU General Public License version 2 as
7
+ * published by the Free Software Foundation.
8
+ *
9
+ * Alternatively, this software may be distributed under the terms of BSD
10
+ * license.
11
+ *
12
+ * See README and COPYING for more details.
13
+ */
14
+
15
+#ifndef P2P_HOSTAPD_H
16
+#define P2P_HOSTAPD_H
17
+
18
+#ifdef CONFIG_P2P
19
+
20
+int hostapd_p2p_get_mib_sta(struct hostapd_data *hapd, struct sta_info *sta,
21
+			    char *buf, size_t buflen);
22
+int hostapd_p2p_set_noa(struct hostapd_data *hapd, u8 count, int start,
23
+			int duration);
24
+void hostapd_p2p_non_p2p_sta_connected(struct hostapd_data *hapd);
25
+void hostapd_p2p_non_p2p_sta_disconnected(struct hostapd_data *hapd);
26
+
27
+
28
+#else /* CONFIG_P2P */
29
+
30
+static inline int hostapd_p2p_get_mib_sta(struct hostapd_data *hapd,
31
+					  struct sta_info *sta,
32
+					  char *buf, size_t buflen)
33
+{
34
+	return 0;
35
+}
36
+
37
+#endif /* CONFIG_P2P */
38
+
39
+u8 * hostapd_eid_p2p_manage(struct hostapd_data *hapd, u8 *eid);
40
+
41
+#endif /* P2P_HOSTAPD_H */

+ 402
- 0
src/ap/peerkey_auth.c Näytä tiedosto

@@ -0,0 +1,402 @@
1
+/*
2
+ * hostapd - PeerKey for Direct Link Setup (DLS)
3
+ * Copyright (c) 2006-2009, Jouni Malinen <j@w1.fi>
4
+ *
5
+ * This program is free software; you can redistribute it and/or modify
6
+ * it under the terms of the GNU General Public License version 2 as
7
+ * published by the Free Software Foundation.
8
+ *
9
+ * Alternatively, this software may be distributed under the terms of BSD
10
+ * license.
11
+ *
12
+ * See README and COPYING for more details.
13
+ */
14
+
15
+#include "utils/includes.h"
16
+
17
+#include "utils/common.h"
18
+#include "utils/eloop.h"
19
+#include "crypto/sha1.h"
20
+#include "crypto/sha256.h"
21
+#include "crypto/random.h"
22
+#include "wpa_auth.h"
23
+#include "wpa_auth_i.h"
24
+#include "wpa_auth_ie.h"
25
+
26
+#ifdef CONFIG_PEERKEY
27
+
28
+static void wpa_stsl_step(void *eloop_ctx, void *timeout_ctx)
29
+{
30
+#if 0
31
+	struct wpa_authenticator *wpa_auth = eloop_ctx;
32
+	struct wpa_stsl_negotiation *neg = timeout_ctx;
33
+#endif
34
+
35
+	/* TODO: ? */
36
+}
37
+
38
+
39
+struct wpa_stsl_search {
40
+	const u8 *addr;
41
+	struct wpa_state_machine *sm;
42
+};
43
+
44
+
45
+static int wpa_stsl_select_sta(struct wpa_state_machine *sm, void *ctx)
46
+{
47
+	struct wpa_stsl_search *search = ctx;
48
+	if (os_memcmp(search->addr, sm->addr, ETH_ALEN) == 0) {
49
+		search->sm = sm;
50
+		return 1;
51
+	}
52
+	return 0;
53
+}
54
+
55
+
56
+static void wpa_smk_send_error(struct wpa_authenticator *wpa_auth,
57
+			       struct wpa_state_machine *sm, const u8 *peer,
58
+			       u16 mui, u16 error_type)
59
+{
60
+	u8 kde[2 + RSN_SELECTOR_LEN + ETH_ALEN +
61
+	       2 + RSN_SELECTOR_LEN + sizeof(struct rsn_error_kde)];
62
+	u8 *pos;
63
+	struct rsn_error_kde error;
64
+
65
+	wpa_auth_logger(wpa_auth, sm->addr, LOGGER_DEBUG,
66
+			"Sending SMK Error");
67
+
68
+	pos = kde;
69
+
70
+	if (peer) {
71
+		pos = wpa_add_kde(pos, RSN_KEY_DATA_MAC_ADDR, peer, ETH_ALEN,
72
+				  NULL, 0);
73
+	}
74
+
75
+	error.mui = host_to_be16(mui);
76
+	error.error_type = host_to_be16(error_type);
77
+	pos = wpa_add_kde(pos, RSN_KEY_DATA_ERROR,
78
+			  (u8 *) &error, sizeof(error), NULL, 0);
79
+
80
+	__wpa_send_eapol(wpa_auth, sm,
81
+			 WPA_KEY_INFO_SECURE | WPA_KEY_INFO_MIC |
82
+			 WPA_KEY_INFO_SMK_MESSAGE | WPA_KEY_INFO_ERROR,
83
+			 NULL, NULL, kde, pos - kde, 0, 0, 0);
84
+}
85
+
86
+
87
+void wpa_smk_m1(struct wpa_authenticator *wpa_auth,
88
+		struct wpa_state_machine *sm, struct wpa_eapol_key *key)
89
+{
90
+	struct wpa_eapol_ie_parse kde;
91
+	struct wpa_stsl_search search;
92
+	u8 *buf, *pos;
93
+	size_t buf_len;
94
+
95
+	if (wpa_parse_kde_ies((const u8 *) (key + 1),
96
+			      WPA_GET_BE16(key->key_data_length), &kde) < 0) {
97
+		wpa_printf(MSG_INFO, "RSN: Failed to parse KDEs in SMK M1");
98
+		return;
99
+	}
100
+
101
+	if (kde.rsn_ie == NULL || kde.mac_addr == NULL ||
102
+	    kde.mac_addr_len < ETH_ALEN) {
103
+		wpa_printf(MSG_INFO, "RSN: No RSN IE or MAC address KDE in "
104
+			   "SMK M1");
105
+		return;
106
+	}
107
+
108
+	/* Initiator = sm->addr; Peer = kde.mac_addr */
109
+
110
+	search.addr = kde.mac_addr;
111
+	search.sm = NULL;
112
+	if (wpa_auth_for_each_sta(wpa_auth, wpa_stsl_select_sta, &search) ==
113
+	    0 || search.sm == NULL) {
114
+		wpa_printf(MSG_DEBUG, "RSN: SMK handshake with " MACSTR
115
+			   " aborted - STA not associated anymore",
116
+			   MAC2STR(kde.mac_addr));
117
+		wpa_smk_send_error(wpa_auth, sm, kde.mac_addr, STK_MUI_SMK,
118
+				   STK_ERR_STA_NR);
119
+		/* FIX: wpa_stsl_remove(wpa_auth, neg); */
120
+		return;
121
+	}
122
+
123
+	buf_len = kde.rsn_ie_len + 2 + RSN_SELECTOR_LEN + ETH_ALEN;
124
+	buf = os_malloc(buf_len);
125
+	if (buf == NULL)
126
+		return;
127
+	/* Initiator RSN IE */
128
+	os_memcpy(buf, kde.rsn_ie, kde.rsn_ie_len);
129
+	pos = buf + kde.rsn_ie_len;
130
+	/* Initiator MAC Address */
131
+	pos = wpa_add_kde(pos, RSN_KEY_DATA_MAC_ADDR, sm->addr, ETH_ALEN,
132
+			  NULL, 0);
133
+
134
+	/* SMK M2:
135
+	 * EAPOL-Key(S=1, M=1, A=1, I=0, K=0, SM=1, KeyRSC=0, Nonce=INonce,
136
+	 *           MIC=MIC, DataKDs=(RSNIE_I, MAC_I KDE)
137
+	 */
138
+
139
+	wpa_auth_logger(wpa_auth, search.sm->addr, LOGGER_DEBUG,
140
+			"Sending SMK M2");
141
+
142
+	__wpa_send_eapol(wpa_auth, search.sm,
143
+			 WPA_KEY_INFO_SECURE | WPA_KEY_INFO_MIC |
144
+			 WPA_KEY_INFO_ACK | WPA_KEY_INFO_SMK_MESSAGE,
145
+			 NULL, key->key_nonce, buf, pos - buf, 0, 0, 0);
146
+
147
+	os_free(buf);
148
+}
149
+
150
+
151
+static void wpa_send_smk_m4(struct wpa_authenticator *wpa_auth,
152
+			    struct wpa_state_machine *sm,
153
+			    struct wpa_eapol_key *key,
154
+			    struct wpa_eapol_ie_parse *kde,
155
+			    const u8 *smk)
156
+{
157
+	u8 *buf, *pos;
158
+	size_t buf_len;
159
+	u32 lifetime;
160
+
161
+	/* SMK M4:
162
+	 * EAPOL-Key(S=1, M=1, A=0, I=1, K=0, SM=1, KeyRSC=0, Nonce=PNonce,
163
+	 *           MIC=MIC, DataKDs=(MAC_I KDE, INonce KDE, SMK KDE,
164
+	 *           Lifetime KDE)
165
+	 */
166
+
167
+	buf_len = 2 + RSN_SELECTOR_LEN + ETH_ALEN +
168
+		2 + RSN_SELECTOR_LEN + WPA_NONCE_LEN +
169
+		2 + RSN_SELECTOR_LEN + PMK_LEN + WPA_NONCE_LEN +
170
+		2 + RSN_SELECTOR_LEN + sizeof(lifetime);
171
+	pos = buf = os_malloc(buf_len);
172
+	if (buf == NULL)
173
+		return;
174
+
175
+	/* Initiator MAC Address */
176
+	pos = wpa_add_kde(pos, RSN_KEY_DATA_MAC_ADDR, kde->mac_addr, ETH_ALEN,
177
+			  NULL, 0);
178
+
179
+	/* Initiator Nonce */
180
+	pos = wpa_add_kde(pos, RSN_KEY_DATA_NONCE, kde->nonce, WPA_NONCE_LEN,
181
+			  NULL, 0);
182
+
183
+	/* SMK with PNonce */
184
+	pos = wpa_add_kde(pos, RSN_KEY_DATA_SMK, smk, PMK_LEN,
185
+			  key->key_nonce, WPA_NONCE_LEN);
186
+
187
+	/* Lifetime */
188
+	lifetime = htonl(43200); /* dot11RSNAConfigSMKLifetime */
189
+	pos = wpa_add_kde(pos, RSN_KEY_DATA_LIFETIME,
190
+			  (u8 *) &lifetime, sizeof(lifetime), NULL, 0);
191
+
192
+	wpa_auth_logger(sm->wpa_auth, sm->addr, LOGGER_DEBUG,
193
+			"Sending SMK M4");
194
+
195
+	__wpa_send_eapol(wpa_auth, sm,
196
+			 WPA_KEY_INFO_SECURE | WPA_KEY_INFO_MIC |
197
+			 WPA_KEY_INFO_INSTALL | WPA_KEY_INFO_SMK_MESSAGE,
198
+			 NULL, key->key_nonce, buf, pos - buf, 0, 1, 0);
199
+
200
+	os_free(buf);
201
+}
202
+
203
+
204
+static void wpa_send_smk_m5(struct wpa_authenticator *wpa_auth,
205
+			    struct wpa_state_machine *sm,
206
+			    struct wpa_eapol_key *key,
207
+			    struct wpa_eapol_ie_parse *kde,
208
+			    const u8 *smk, const u8 *peer)
209
+{
210
+	u8 *buf, *pos;
211
+	size_t buf_len;
212
+	u32 lifetime;
213
+
214
+	/* SMK M5:
215
+	 * EAPOL-Key(S=1, M=1, A=0, I=0, K=0, SM=1, KeyRSC=0, Nonce=INonce,
216
+	 *           MIC=MIC, DataKDs=(RSNIE_P, MAC_P KDE, PNonce, SMK KDE,
217
+	 *                             Lifetime KDE))
218
+	 */
219
+
220
+	buf_len = kde->rsn_ie_len +
221
+		2 + RSN_SELECTOR_LEN + ETH_ALEN +
222
+		2 + RSN_SELECTOR_LEN + WPA_NONCE_LEN +
223
+		2 + RSN_SELECTOR_LEN + PMK_LEN + WPA_NONCE_LEN +
224
+		2 + RSN_SELECTOR_LEN + sizeof(lifetime);
225
+	pos = buf = os_malloc(buf_len);
226
+	if (buf == NULL)
227
+		return;
228
+
229
+	/* Peer RSN IE */
230
+	os_memcpy(buf, kde->rsn_ie, kde->rsn_ie_len);
231
+	pos = buf + kde->rsn_ie_len;
232
+
233
+	/* Peer MAC Address */
234
+	pos = wpa_add_kde(pos, RSN_KEY_DATA_MAC_ADDR, peer, ETH_ALEN, NULL, 0);
235
+
236
+	/* PNonce */
237
+	pos = wpa_add_kde(pos, RSN_KEY_DATA_NONCE, key->key_nonce,
238
+			  WPA_NONCE_LEN, NULL, 0);
239
+
240
+	/* SMK and INonce */
241
+	pos = wpa_add_kde(pos, RSN_KEY_DATA_SMK, smk, PMK_LEN,
242
+			  kde->nonce, WPA_NONCE_LEN);
243
+
244
+	/* Lifetime */
245
+	lifetime = htonl(43200); /* dot11RSNAConfigSMKLifetime */
246
+	pos = wpa_add_kde(pos, RSN_KEY_DATA_LIFETIME,
247
+			  (u8 *) &lifetime, sizeof(lifetime), NULL, 0);
248
+
249
+	wpa_auth_logger(sm->wpa_auth, sm->addr, LOGGER_DEBUG,
250
+			"Sending SMK M5");
251
+
252
+	__wpa_send_eapol(wpa_auth, sm,
253
+			 WPA_KEY_INFO_SECURE | WPA_KEY_INFO_MIC |
254
+			 WPA_KEY_INFO_SMK_MESSAGE,
255
+			 NULL, kde->nonce, buf, pos - buf, 0, 1, 0);
256
+
257
+	os_free(buf);
258
+}
259
+
260
+
261
+void wpa_smk_m3(struct wpa_authenticator *wpa_auth,
262
+		struct wpa_state_machine *sm, struct wpa_eapol_key *key)
263
+{
264
+	struct wpa_eapol_ie_parse kde;
265
+	struct wpa_stsl_search search;
266
+	u8 smk[32], buf[ETH_ALEN + 8 + 2 * WPA_NONCE_LEN], *pos;
267
+
268
+	if (wpa_parse_kde_ies((const u8 *) (key + 1),
269
+			      WPA_GET_BE16(key->key_data_length), &kde) < 0) {
270
+		wpa_printf(MSG_INFO, "RSN: Failed to parse KDEs in SMK M3");
271
+		return;
272
+	}
273
+
274
+	if (kde.rsn_ie == NULL ||
275
+	    kde.mac_addr == NULL || kde.mac_addr_len < ETH_ALEN ||
276
+	    kde.nonce == NULL || kde.nonce_len < WPA_NONCE_LEN) {
277
+		wpa_printf(MSG_INFO, "RSN: No RSN IE, MAC address KDE, or "
278
+			   "Nonce KDE in SMK M3");
279
+		return;
280
+	}
281
+
282
+	/* Peer = sm->addr; Initiator = kde.mac_addr;
283
+	 * Peer Nonce = key->key_nonce; Initiator Nonce = kde.nonce */
284
+
285
+	search.addr = kde.mac_addr;
286
+	search.sm = NULL;
287
+	if (wpa_auth_for_each_sta(wpa_auth, wpa_stsl_select_sta, &search) ==
288
+	    0 || search.sm == NULL) {
289
+		wpa_printf(MSG_DEBUG, "RSN: SMK handshake with " MACSTR
290
+			   " aborted - STA not associated anymore",
291
+			   MAC2STR(kde.mac_addr));
292
+		wpa_smk_send_error(wpa_auth, sm, kde.mac_addr, STK_MUI_SMK,
293
+				   STK_ERR_STA_NR);
294
+		/* FIX: wpa_stsl_remove(wpa_auth, neg); */
295
+		return;
296
+	}
297
+
298
+	if (random_get_bytes(smk, PMK_LEN)) {
299
+		wpa_printf(MSG_DEBUG, "RSN: Failed to generate SMK");
300
+		return;
301
+	}
302
+
303
+	/* SMK = PRF-256(Random number, "SMK Derivation",
304
+	 *               AA || Time || INonce || PNonce)
305
+	 */
306
+	os_memcpy(buf, wpa_auth->addr, ETH_ALEN);
307
+	pos = buf + ETH_ALEN;
308
+	wpa_get_ntp_timestamp(pos);
309
+	pos += 8;
310
+	os_memcpy(pos, kde.nonce, WPA_NONCE_LEN);
311
+	pos += WPA_NONCE_LEN;
312
+	os_memcpy(pos, key->key_nonce, WPA_NONCE_LEN);
313
+#ifdef CONFIG_IEEE80211W
314
+	sha256_prf(smk, PMK_LEN, "SMK Derivation", buf, sizeof(buf),
315
+		   smk, PMK_LEN);
316
+#else /* CONFIG_IEEE80211W */
317
+	sha1_prf(smk, PMK_LEN, "SMK Derivation", buf, sizeof(buf),
318
+		 smk, PMK_LEN);
319
+#endif /* CONFIG_IEEE80211W */
320
+
321
+	wpa_hexdump_key(MSG_DEBUG, "RSN: SMK", smk, PMK_LEN);
322
+
323
+	wpa_send_smk_m4(wpa_auth, sm, key, &kde, smk);
324
+	wpa_send_smk_m5(wpa_auth, search.sm, key, &kde, smk, sm->addr);
325
+
326
+	/* Authenticator does not need SMK anymore and it is required to forget
327
+	 * it. */
328
+	os_memset(smk, 0, sizeof(*smk));
329
+}
330
+
331
+
332
+void wpa_smk_error(struct wpa_authenticator *wpa_auth,
333
+		   struct wpa_state_machine *sm, struct wpa_eapol_key *key)
334
+{
335
+	struct wpa_eapol_ie_parse kde;
336
+	struct wpa_stsl_search search;
337
+	struct rsn_error_kde error;
338
+	u16 mui, error_type;
339
+
340
+	if (wpa_parse_kde_ies((const u8 *) (key + 1),
341
+			      WPA_GET_BE16(key->key_data_length), &kde) < 0) {
342
+		wpa_printf(MSG_INFO, "RSN: Failed to parse KDEs in SMK Error");
343
+		return;
344
+	}
345
+
346
+	if (kde.mac_addr == NULL || kde.mac_addr_len < ETH_ALEN ||
347
+	    kde.error == NULL || kde.error_len < sizeof(error)) {
348
+		wpa_printf(MSG_INFO, "RSN: No MAC address or Error KDE in "
349
+			   "SMK Error");
350
+		return;
351
+	}
352
+
353
+	search.addr = kde.mac_addr;
354
+	search.sm = NULL;
355
+	if (wpa_auth_for_each_sta(wpa_auth, wpa_stsl_select_sta, &search) ==
356
+	    0 || search.sm == NULL) {
357
+		wpa_printf(MSG_DEBUG, "RSN: Peer STA " MACSTR " not "
358
+			   "associated for SMK Error message from " MACSTR,
359
+			   MAC2STR(kde.mac_addr), MAC2STR(sm->addr));
360
+		return;
361
+	}
362
+
363
+	os_memcpy(&error, kde.error, sizeof(error));
364
+	mui = be_to_host16(error.mui);
365
+	error_type = be_to_host16(error.error_type);
366
+	wpa_auth_vlogger(wpa_auth, sm->addr, LOGGER_INFO,
367
+			 "STA reported SMK Error: Peer " MACSTR
368
+			 " MUI %d Error Type %d",
369
+			 MAC2STR(kde.mac_addr), mui, error_type);
370
+
371
+	wpa_smk_send_error(wpa_auth, search.sm, sm->addr, mui, error_type);
372
+}
373
+
374
+
375
+int wpa_stsl_remove(struct wpa_authenticator *wpa_auth,
376
+		    struct wpa_stsl_negotiation *neg)
377
+{
378
+	struct wpa_stsl_negotiation *pos, *prev;
379
+
380
+	if (wpa_auth == NULL)
381
+		return -1;
382
+	pos = wpa_auth->stsl_negotiations;
383
+	prev = NULL;
384
+	while (pos) {
385
+		if (pos == neg) {
386
+			if (prev)
387
+				prev->next = pos->next;
388
+			else
389
+				wpa_auth->stsl_negotiations = pos->next;
390
+
391
+			eloop_cancel_timeout(wpa_stsl_step, wpa_auth, pos);
392
+			os_free(pos);
393
+			return 0;
394
+		}
395
+		prev = pos;
396
+		pos = pos->next;
397
+	}
398
+
399
+	return -1;
400
+}
401
+
402
+#endif /* CONFIG_PEERKEY */

+ 425
- 0
src/ap/pmksa_cache_auth.c Näytä tiedosto

@@ -0,0 +1,425 @@
1
+/*
2
+ * hostapd - PMKSA cache for IEEE 802.11i RSN
3
+ * Copyright (c) 2004-2008, Jouni Malinen <j@w1.fi>
4
+ *
5
+ * This program is free software; you can redistribute it and/or modify
6
+ * it under the terms of the GNU General Public License version 2 as
7
+ * published by the Free Software Foundation.
8
+ *
9
+ * Alternatively, this software may be distributed under the terms of BSD
10
+ * license.
11
+ *
12
+ * See README and COPYING for more details.
13
+ */
14
+
15
+#include "utils/includes.h"
16
+
17
+#include "utils/common.h"
18
+#include "utils/eloop.h"
19
+#include "eapol_auth/eapol_auth_sm.h"
20
+#include "eapol_auth/eapol_auth_sm_i.h"
21
+#include "sta_info.h"
22
+#include "ap_config.h"
23
+#include "pmksa_cache_auth.h"
24
+
25
+
26
+static const int pmksa_cache_max_entries = 1024;
27
+static const int dot11RSNAConfigPMKLifetime = 43200;
28
+
29
+struct rsn_pmksa_cache {
30
+#define PMKID_HASH_SIZE 128
31
+#define PMKID_HASH(pmkid) (unsigned int) ((pmkid)[0] & 0x7f)
32
+	struct rsn_pmksa_cache_entry *pmkid[PMKID_HASH_SIZE];
33
+	struct rsn_pmksa_cache_entry *pmksa;
34
+	int pmksa_count;
35
+
36
+	void (*free_cb)(struct rsn_pmksa_cache_entry *entry, void *ctx);
37
+	void *ctx;
38
+};
39
+
40
+
41
+static void pmksa_cache_set_expiration(struct rsn_pmksa_cache *pmksa);
42
+
43
+
44
+static void _pmksa_cache_free_entry(struct rsn_pmksa_cache_entry *entry)
45
+{
46
+	if (entry == NULL)
47
+		return;
48
+	os_free(entry->identity);
49
+#ifndef CONFIG_NO_RADIUS
50
+	radius_free_class(&entry->radius_class);
51
+#endif /* CONFIG_NO_RADIUS */
52
+	os_free(entry);
53
+}
54
+
55
+
56
+static void pmksa_cache_free_entry(struct rsn_pmksa_cache *pmksa,
57
+				   struct rsn_pmksa_cache_entry *entry)
58
+{
59
+	struct rsn_pmksa_cache_entry *pos, *prev;
60
+
61
+	pmksa->pmksa_count--;
62
+	pmksa->free_cb(entry, pmksa->ctx);
63
+	pos = pmksa->pmkid[PMKID_HASH(entry->pmkid)];
64
+	prev = NULL;
65
+	while (pos) {
66
+		if (pos == entry) {
67
+			if (prev != NULL) {
68
+				prev->hnext = pos->hnext;
69
+			} else {
70
+				pmksa->pmkid[PMKID_HASH(entry->pmkid)] =
71
+					pos->hnext;
72
+			}
73
+			break;
74
+		}
75
+		prev = pos;
76
+		pos = pos->hnext;
77
+	}
78
+
79
+	pos = pmksa->pmksa;
80
+	prev = NULL;
81
+	while (pos) {
82
+		if (pos == entry) {
83
+			if (prev != NULL)
84
+				prev->next = pos->next;
85
+			else
86
+				pmksa->pmksa = pos->next;
87
+			break;
88
+		}
89
+		prev = pos;
90
+		pos = pos->next;
91
+	}
92
+	_pmksa_cache_free_entry(entry);
93
+}
94
+
95
+
96
+static void pmksa_cache_expire(void *eloop_ctx, void *timeout_ctx)
97
+{
98
+	struct rsn_pmksa_cache *pmksa = eloop_ctx;
99
+	struct os_time now;
100
+
101
+	os_get_time(&now);
102
+	while (pmksa->pmksa && pmksa->pmksa->expiration <= now.sec) {
103
+		struct rsn_pmksa_cache_entry *entry = pmksa->pmksa;
104
+		pmksa->pmksa = entry->next;
105
+		wpa_printf(MSG_DEBUG, "RSN: expired PMKSA cache entry for "
106
+			   MACSTR, MAC2STR(entry->spa));
107
+		pmksa_cache_free_entry(pmksa, entry);
108
+	}
109
+
110
+	pmksa_cache_set_expiration(pmksa);
111
+}
112
+
113
+
114
+static void pmksa_cache_set_expiration(struct rsn_pmksa_cache *pmksa)
115
+{
116
+	int sec;
117
+	struct os_time now;
118
+
119
+	eloop_cancel_timeout(pmksa_cache_expire, pmksa, NULL);
120
+	if (pmksa->pmksa == NULL)
121
+		return;
122
+	os_get_time(&now);
123
+	sec = pmksa->pmksa->expiration - now.sec;
124
+	if (sec < 0)
125
+		sec = 0;
126
+	eloop_register_timeout(sec + 1, 0, pmksa_cache_expire, pmksa, NULL);
127
+}
128
+
129
+
130
+static void pmksa_cache_from_eapol_data(struct rsn_pmksa_cache_entry *entry,
131
+					struct eapol_state_machine *eapol)
132
+{
133
+	if (eapol == NULL)
134
+		return;
135
+
136
+	if (eapol->identity) {
137
+		entry->identity = os_malloc(eapol->identity_len);
138
+		if (entry->identity) {
139
+			entry->identity_len = eapol->identity_len;
140
+			os_memcpy(entry->identity, eapol->identity,
141
+				  eapol->identity_len);
142
+		}
143
+	}
144
+
145
+#ifndef CONFIG_NO_RADIUS
146
+	radius_copy_class(&entry->radius_class, &eapol->radius_class);
147
+#endif /* CONFIG_NO_RADIUS */
148
+
149
+	entry->eap_type_authsrv = eapol->eap_type_authsrv;
150
+	entry->vlan_id = ((struct sta_info *) eapol->sta)->vlan_id;
151
+}
152
+
153
+
154
+void pmksa_cache_to_eapol_data(struct rsn_pmksa_cache_entry *entry,
155
+			       struct eapol_state_machine *eapol)
156
+{
157
+	if (entry == NULL || eapol == NULL)
158
+		return;
159
+
160
+	if (entry->identity) {
161
+		os_free(eapol->identity);
162
+		eapol->identity = os_malloc(entry->identity_len);
163
+		if (eapol->identity) {
164
+			eapol->identity_len = entry->identity_len;
165
+			os_memcpy(eapol->identity, entry->identity,
166
+				  entry->identity_len);
167
+		}
168
+		wpa_hexdump_ascii(MSG_DEBUG, "STA identity from PMKSA",
169
+				  eapol->identity, eapol->identity_len);
170
+	}
171
+
172
+#ifndef CONFIG_NO_RADIUS
173
+	radius_free_class(&eapol->radius_class);
174
+	radius_copy_class(&eapol->radius_class, &entry->radius_class);
175
+#endif /* CONFIG_NO_RADIUS */
176
+	if (eapol->radius_class.attr) {
177
+		wpa_printf(MSG_DEBUG, "Copied %lu Class attribute(s) from "
178
+			   "PMKSA", (unsigned long) eapol->radius_class.count);
179
+	}
180
+
181
+	eapol->eap_type_authsrv = entry->eap_type_authsrv;
182
+	((struct sta_info *) eapol->sta)->vlan_id = entry->vlan_id;
183
+}
184
+
185
+
186
+static void pmksa_cache_link_entry(struct rsn_pmksa_cache *pmksa,
187
+				   struct rsn_pmksa_cache_entry *entry)
188
+{
189
+	struct rsn_pmksa_cache_entry *pos, *prev;
190
+
191
+	/* Add the new entry; order by expiration time */
192
+	pos = pmksa->pmksa;
193
+	prev = NULL;
194
+	while (pos) {
195
+		if (pos->expiration > entry->expiration)
196
+			break;
197
+		prev = pos;
198
+		pos = pos->next;
199
+	}
200
+	if (prev == NULL) {
201
+		entry->next = pmksa->pmksa;
202
+		pmksa->pmksa = entry;
203
+	} else {
204
+		entry->next = prev->next;
205
+		prev->next = entry;
206
+	}
207
+	entry->hnext = pmksa->pmkid[PMKID_HASH(entry->pmkid)];
208
+	pmksa->pmkid[PMKID_HASH(entry->pmkid)] = entry;
209
+
210
+	pmksa->pmksa_count++;
211
+	wpa_printf(MSG_DEBUG, "RSN: added PMKSA cache entry for " MACSTR,
212
+		   MAC2STR(entry->spa));
213
+	wpa_hexdump(MSG_DEBUG, "RSN: added PMKID", entry->pmkid, PMKID_LEN);
214
+}
215
+
216
+
217
+/**
218
+ * pmksa_cache_auth_add - Add a PMKSA cache entry
219
+ * @pmksa: Pointer to PMKSA cache data from pmksa_cache_auth_init()
220
+ * @pmk: The new pairwise master key
221
+ * @pmk_len: PMK length in bytes, usually PMK_LEN (32)
222
+ * @aa: Authenticator address
223
+ * @spa: Supplicant address
224
+ * @session_timeout: Session timeout
225
+ * @eapol: Pointer to EAPOL state machine data
226
+ * @akmp: WPA_KEY_MGMT_* used in key derivation
227
+ * Returns: Pointer to the added PMKSA cache entry or %NULL on error
228
+ *
229
+ * This function create a PMKSA entry for a new PMK and adds it to the PMKSA
230
+ * cache. If an old entry is already in the cache for the same Supplicant,
231
+ * this entry will be replaced with the new entry. PMKID will be calculated
232
+ * based on the PMK.
233
+ */
234
+struct rsn_pmksa_cache_entry *
235
+pmksa_cache_auth_add(struct rsn_pmksa_cache *pmksa,
236
+		     const u8 *pmk, size_t pmk_len,
237
+		const u8 *aa, const u8 *spa, int session_timeout,
238
+		struct eapol_state_machine *eapol, int akmp)
239
+{
240
+	struct rsn_pmksa_cache_entry *entry, *pos;
241
+	struct os_time now;
242
+
243
+	if (pmk_len > PMK_LEN)
244
+		return NULL;
245
+
246
+	entry = os_zalloc(sizeof(*entry));
247
+	if (entry == NULL)
248
+		return NULL;
249
+	os_memcpy(entry->pmk, pmk, pmk_len);
250
+	entry->pmk_len = pmk_len;
251
+	rsn_pmkid(pmk, pmk_len, aa, spa, entry->pmkid,
252
+		  wpa_key_mgmt_sha256(akmp));
253
+	os_get_time(&now);
254
+	entry->expiration = now.sec;
255
+	if (session_timeout > 0)
256
+		entry->expiration += session_timeout;
257
+	else
258
+		entry->expiration += dot11RSNAConfigPMKLifetime;
259
+	entry->akmp = akmp;
260
+	os_memcpy(entry->spa, spa, ETH_ALEN);
261
+	pmksa_cache_from_eapol_data(entry, eapol);
262
+
263
+	/* Replace an old entry for the same STA (if found) with the new entry
264
+	 */
265
+	pos = pmksa_cache_auth_get(pmksa, spa, NULL);
266
+	if (pos)
267
+		pmksa_cache_free_entry(pmksa, pos);
268
+
269
+	if (pmksa->pmksa_count >= pmksa_cache_max_entries && pmksa->pmksa) {
270
+		/* Remove the oldest entry to make room for the new entry */
271
+		wpa_printf(MSG_DEBUG, "RSN: removed the oldest PMKSA cache "
272
+			   "entry (for " MACSTR ") to make room for new one",
273
+			   MAC2STR(pmksa->pmksa->spa));
274
+		pmksa_cache_free_entry(pmksa, pmksa->pmksa);
275
+	}
276
+
277
+	pmksa_cache_link_entry(pmksa, entry);
278
+
279
+	return entry;
280
+}
281
+
282
+
283
+struct rsn_pmksa_cache_entry *
284
+pmksa_cache_add_okc(struct rsn_pmksa_cache *pmksa,
285
+		    const struct rsn_pmksa_cache_entry *old_entry,
286
+		    const u8 *aa, const u8 *pmkid)
287
+{
288
+	struct rsn_pmksa_cache_entry *entry;
289
+
290
+	entry = os_zalloc(sizeof(*entry));
291
+	if (entry == NULL)
292
+		return NULL;
293
+	os_memcpy(entry->pmkid, pmkid, PMKID_LEN);
294
+	os_memcpy(entry->pmk, old_entry->pmk, old_entry->pmk_len);
295
+	entry->pmk_len = old_entry->pmk_len;
296
+	entry->expiration = old_entry->expiration;
297
+	entry->akmp = old_entry->akmp;
298
+	os_memcpy(entry->spa, old_entry->spa, ETH_ALEN);
299
+	entry->opportunistic = 1;
300
+	if (old_entry->identity) {
301
+		entry->identity = os_malloc(old_entry->identity_len);
302
+		if (entry->identity) {
303
+			entry->identity_len = old_entry->identity_len;
304
+			os_memcpy(entry->identity, old_entry->identity,
305
+				  old_entry->identity_len);
306
+		}
307
+	}
308
+#ifndef CONFIG_NO_RADIUS
309
+	radius_copy_class(&entry->radius_class, &old_entry->radius_class);
310
+#endif /* CONFIG_NO_RADIUS */
311
+	entry->eap_type_authsrv = old_entry->eap_type_authsrv;
312
+	entry->vlan_id = old_entry->vlan_id;
313
+	entry->opportunistic = 1;
314
+
315
+	pmksa_cache_link_entry(pmksa, entry);
316
+
317
+	return entry;
318
+}
319
+
320
+
321
+/**
322
+ * pmksa_cache_auth_deinit - Free all entries in PMKSA cache
323
+ * @pmksa: Pointer to PMKSA cache data from pmksa_cache_auth_init()
324
+ */
325
+void pmksa_cache_auth_deinit(struct rsn_pmksa_cache *pmksa)
326
+{
327
+	struct rsn_pmksa_cache_entry *entry, *prev;
328
+	int i;
329
+
330
+	if (pmksa == NULL)
331
+		return;
332
+
333
+	entry = pmksa->pmksa;
334
+	while (entry) {
335
+		prev = entry;
336
+		entry = entry->next;
337
+		_pmksa_cache_free_entry(prev);
338
+	}
339
+	eloop_cancel_timeout(pmksa_cache_expire, pmksa, NULL);
340
+	for (i = 0; i < PMKID_HASH_SIZE; i++)
341
+		pmksa->pmkid[i] = NULL;
342
+	os_free(pmksa);
343
+}
344
+
345
+
346
+/**
347
+ * pmksa_cache_auth_get - Fetch a PMKSA cache entry
348
+ * @pmksa: Pointer to PMKSA cache data from pmksa_cache_auth_init()
349
+ * @spa: Supplicant address or %NULL to match any
350
+ * @pmkid: PMKID or %NULL to match any
351
+ * Returns: Pointer to PMKSA cache entry or %NULL if no match was found
352
+ */
353
+struct rsn_pmksa_cache_entry *
354
+pmksa_cache_auth_get(struct rsn_pmksa_cache *pmksa,
355
+		     const u8 *spa, const u8 *pmkid)
356
+{
357
+	struct rsn_pmksa_cache_entry *entry;
358
+
359
+	if (pmkid)
360
+		entry = pmksa->pmkid[PMKID_HASH(pmkid)];
361
+	else
362
+		entry = pmksa->pmksa;
363
+	while (entry) {
364
+		if ((spa == NULL ||
365
+		     os_memcmp(entry->spa, spa, ETH_ALEN) == 0) &&
366
+		    (pmkid == NULL ||
367
+		     os_memcmp(entry->pmkid, pmkid, PMKID_LEN) == 0))
368
+			return entry;
369
+		entry = pmkid ? entry->hnext : entry->next;
370
+	}
371
+	return NULL;
372
+}
373
+
374
+
375
+/**
376
+ * pmksa_cache_get_okc - Fetch a PMKSA cache entry using OKC
377
+ * @pmksa: Pointer to PMKSA cache data from pmksa_cache_auth_init()
378
+ * @aa: Authenticator address
379
+ * @spa: Supplicant address
380
+ * @pmkid: PMKID
381
+ * Returns: Pointer to PMKSA cache entry or %NULL if no match was found
382
+ *
383
+ * Use opportunistic key caching (OKC) to find a PMK for a supplicant.
384
+ */
385
+struct rsn_pmksa_cache_entry * pmksa_cache_get_okc(
386
+	struct rsn_pmksa_cache *pmksa, const u8 *aa, const u8 *spa,
387
+	const u8 *pmkid)
388
+{
389
+	struct rsn_pmksa_cache_entry *entry;
390
+	u8 new_pmkid[PMKID_LEN];
391
+
392
+	entry = pmksa->pmksa;
393
+	while (entry) {
394
+		if (os_memcmp(entry->spa, spa, ETH_ALEN) != 0)
395
+			continue;
396
+		rsn_pmkid(entry->pmk, entry->pmk_len, aa, spa, new_pmkid,
397
+			  wpa_key_mgmt_sha256(entry->akmp));
398
+		if (os_memcmp(new_pmkid, pmkid, PMKID_LEN) == 0)
399
+			return entry;
400
+		entry = entry->next;
401
+	}
402
+	return NULL;
403
+}
404
+
405
+
406
+/**
407
+ * pmksa_cache_auth_init - Initialize PMKSA cache
408
+ * @free_cb: Callback function to be called when a PMKSA cache entry is freed
409
+ * @ctx: Context pointer for free_cb function
410
+ * Returns: Pointer to PMKSA cache data or %NULL on failure
411
+ */
412
+struct rsn_pmksa_cache *
413
+pmksa_cache_auth_init(void (*free_cb)(struct rsn_pmksa_cache_entry *entry,
414
+				      void *ctx), void *ctx)
415
+{
416
+	struct rsn_pmksa_cache *pmksa;
417
+
418
+	pmksa = os_zalloc(sizeof(*pmksa));
419
+	if (pmksa) {
420
+		pmksa->free_cb = free_cb;
421
+		pmksa->ctx = ctx;
422
+	}
423
+
424
+	return pmksa;
425
+}

+ 64
- 0
src/ap/pmksa_cache_auth.h Näytä tiedosto

@@ -0,0 +1,64 @@
1
+/*
2
+ * hostapd - PMKSA cache for IEEE 802.11i RSN
3
+ * Copyright (c) 2004-2008, Jouni Malinen <j@w1.fi>
4
+ *
5
+ * This program is free software; you can redistribute it and/or modify
6
+ * it under the terms of the GNU General Public License version 2 as
7
+ * published by the Free Software Foundation.
8
+ *
9
+ * Alternatively, this software may be distributed under the terms of BSD
10
+ * license.
11
+ *
12
+ * See README and COPYING for more details.
13
+ */
14
+
15
+#ifndef PMKSA_CACHE_H
16
+#define PMKSA_CACHE_H
17
+
18
+#include "radius/radius.h"
19
+
20
+/**
21
+ * struct rsn_pmksa_cache_entry - PMKSA cache entry
22
+ */
23
+struct rsn_pmksa_cache_entry {
24
+	struct rsn_pmksa_cache_entry *next, *hnext;
25
+	u8 pmkid[PMKID_LEN];
26
+	u8 pmk[PMK_LEN];
27
+	size_t pmk_len;
28
+	os_time_t expiration;
29
+	int akmp; /* WPA_KEY_MGMT_* */
30
+	u8 spa[ETH_ALEN];
31
+
32
+	u8 *identity;
33
+	size_t identity_len;
34
+	struct radius_class_data radius_class;
35
+	u8 eap_type_authsrv;
36
+	int vlan_id;
37
+	int opportunistic;
38
+};
39
+
40
+struct rsn_pmksa_cache;
41
+
42
+struct rsn_pmksa_cache *
43
+pmksa_cache_auth_init(void (*free_cb)(struct rsn_pmksa_cache_entry *entry,
44
+				      void *ctx), void *ctx);
45
+void pmksa_cache_auth_deinit(struct rsn_pmksa_cache *pmksa);
46
+struct rsn_pmksa_cache_entry *
47
+pmksa_cache_auth_get(struct rsn_pmksa_cache *pmksa,
48
+		     const u8 *spa, const u8 *pmkid);
49
+struct rsn_pmksa_cache_entry * pmksa_cache_get_okc(
50
+	struct rsn_pmksa_cache *pmksa, const u8 *spa, const u8 *aa,
51
+	const u8 *pmkid);
52
+struct rsn_pmksa_cache_entry *
53
+pmksa_cache_auth_add(struct rsn_pmksa_cache *pmksa,
54
+		     const u8 *pmk, size_t pmk_len,
55
+		     const u8 *aa, const u8 *spa, int session_timeout,
56
+		     struct eapol_state_machine *eapol, int akmp);
57
+struct rsn_pmksa_cache_entry *
58
+pmksa_cache_add_okc(struct rsn_pmksa_cache *pmksa,
59
+		    const struct rsn_pmksa_cache_entry *old_entry,
60
+		    const u8 *aa, const u8 *pmkid);
61
+void pmksa_cache_to_eapol_data(struct rsn_pmksa_cache_entry *entry,
62
+			       struct eapol_state_machine *eapol);
63
+
64
+#endif /* PMKSA_CACHE_H */

+ 279
- 0
src/ap/preauth_auth.c Näytä tiedosto

@@ -0,0 +1,279 @@
1
+/*
2
+ * hostapd - Authenticator for IEEE 802.11i RSN pre-authentication
3
+ * Copyright (c) 2004-2007, Jouni Malinen <j@w1.fi>
4
+ *
5
+ * This program is free software; you can redistribute it and/or modify
6
+ * it under the terms of the GNU General Public License version 2 as
7
+ * published by the Free Software Foundation.
8
+ *
9
+ * Alternatively, this software may be distributed under the terms of BSD
10
+ * license.
11
+ *
12
+ * See README and COPYING for more details.
13
+ */
14
+
15
+#include "utils/includes.h"
16
+
17
+#ifdef CONFIG_RSN_PREAUTH
18
+
19
+#include "utils/common.h"
20
+#include "utils/eloop.h"
21
+#include "l2_packet/l2_packet.h"
22
+#include "common/wpa_common.h"
23
+#include "eapol_auth/eapol_auth_sm.h"
24
+#include "eapol_auth/eapol_auth_sm_i.h"
25
+#include "hostapd.h"
26
+#include "ap_config.h"
27
+#include "ieee802_1x.h"
28
+#include "sta_info.h"
29
+#include "wpa_auth.h"
30
+#include "preauth_auth.h"
31
+
32
+#ifndef ETH_P_PREAUTH
33
+#define ETH_P_PREAUTH 0x88C7 /* IEEE 802.11i pre-authentication */
34
+#endif /* ETH_P_PREAUTH */
35
+
36
+static const int dot11RSNAConfigPMKLifetime = 43200;
37
+
38
+struct rsn_preauth_interface {
39
+	struct rsn_preauth_interface *next;
40
+	struct hostapd_data *hapd;
41
+	struct l2_packet_data *l2;
42
+	char *ifname;
43
+	int ifindex;
44
+};
45
+
46
+
47
+static void rsn_preauth_receive(void *ctx, const u8 *src_addr,
48
+				const u8 *buf, size_t len)
49
+{
50
+	struct rsn_preauth_interface *piface = ctx;
51
+	struct hostapd_data *hapd = piface->hapd;
52
+	struct ieee802_1x_hdr *hdr;
53
+	struct sta_info *sta;
54
+	struct l2_ethhdr *ethhdr;
55
+
56
+	wpa_printf(MSG_DEBUG, "RSN: receive pre-auth packet "
57
+		   "from interface '%s'", piface->ifname);
58
+	if (len < sizeof(*ethhdr) + sizeof(*hdr)) {
59
+		wpa_printf(MSG_DEBUG, "RSN: too short pre-auth packet "
60
+			   "(len=%lu)", (unsigned long) len);
61
+		return;
62
+	}
63
+
64
+	ethhdr = (struct l2_ethhdr *) buf;
65
+	hdr = (struct ieee802_1x_hdr *) (ethhdr + 1);
66
+
67
+	if (os_memcmp(ethhdr->h_dest, hapd->own_addr, ETH_ALEN) != 0) {
68
+		wpa_printf(MSG_DEBUG, "RSN: pre-auth for foreign address "
69
+			   MACSTR, MAC2STR(ethhdr->h_dest));
70
+		return;
71
+	}
72
+
73
+	sta = ap_get_sta(hapd, ethhdr->h_source);
74
+	if (sta && (sta->flags & WLAN_STA_ASSOC)) {
75
+		wpa_printf(MSG_DEBUG, "RSN: pre-auth for already association "
76
+			   "STA " MACSTR, MAC2STR(sta->addr));
77
+		return;
78
+	}
79
+	if (!sta && hdr->type == IEEE802_1X_TYPE_EAPOL_START) {
80
+		sta = ap_sta_add(hapd, ethhdr->h_source);
81
+		if (sta == NULL)
82
+			return;
83
+		sta->flags = WLAN_STA_PREAUTH;
84
+
85
+		ieee802_1x_new_station(hapd, sta);
86
+		if (sta->eapol_sm == NULL) {
87
+			ap_free_sta(hapd, sta);
88
+			sta = NULL;
89
+		} else {
90
+			sta->eapol_sm->radius_identifier = -1;
91
+			sta->eapol_sm->portValid = TRUE;
92
+			sta->eapol_sm->flags |= EAPOL_SM_PREAUTH;
93
+		}
94
+	}
95
+	if (sta == NULL)
96
+		return;
97
+	sta->preauth_iface = piface;
98
+	ieee802_1x_receive(hapd, ethhdr->h_source, (u8 *) (ethhdr + 1),
99
+			   len - sizeof(*ethhdr));
100
+}
101
+
102
+
103
+static int rsn_preauth_iface_add(struct hostapd_data *hapd, const char *ifname)
104
+{
105
+	struct rsn_preauth_interface *piface;
106
+
107
+	wpa_printf(MSG_DEBUG, "RSN pre-auth interface '%s'", ifname);
108
+
109
+	piface = os_zalloc(sizeof(*piface));
110
+	if (piface == NULL)
111
+		return -1;
112
+	piface->hapd = hapd;
113
+
114
+	piface->ifname = os_strdup(ifname);
115
+	if (piface->ifname == NULL) {
116
+		goto fail1;
117
+	}
118
+
119
+	piface->l2 = l2_packet_init(piface->ifname, NULL, ETH_P_PREAUTH,
120
+				    rsn_preauth_receive, piface, 1);
121
+	if (piface->l2 == NULL) {
122
+		wpa_printf(MSG_ERROR, "Failed to open register layer 2 access "
123
+			   "to ETH_P_PREAUTH");
124
+		goto fail2;
125
+	}
126
+
127
+	piface->next = hapd->preauth_iface;
128
+	hapd->preauth_iface = piface;
129
+	return 0;
130
+
131
+fail2:
132
+	os_free(piface->ifname);
133
+fail1:
134
+	os_free(piface);
135
+	return -1;
136
+}
137
+
138
+
139
+void rsn_preauth_iface_deinit(struct hostapd_data *hapd)
140
+{
141
+	struct rsn_preauth_interface *piface, *prev;
142
+
143
+	piface = hapd->preauth_iface;
144
+	hapd->preauth_iface = NULL;
145
+	while (piface) {
146
+		prev = piface;
147
+		piface = piface->next;
148
+		l2_packet_deinit(prev->l2);
149
+		os_free(prev->ifname);
150
+		os_free(prev);
151
+	}
152
+}
153
+
154
+
155
+int rsn_preauth_iface_init(struct hostapd_data *hapd)
156
+{
157
+	char *tmp, *start, *end;
158
+
159
+	if (hapd->conf->rsn_preauth_interfaces == NULL)
160
+		return 0;
161
+
162
+	tmp = os_strdup(hapd->conf->rsn_preauth_interfaces);
163
+	if (tmp == NULL)
164
+		return -1;
165
+	start = tmp;
166
+	for (;;) {
167
+		while (*start == ' ')
168
+			start++;
169
+		if (*start == '\0')
170
+			break;
171
+		end = os_strchr(start, ' ');
172
+		if (end)
173
+			*end = '\0';
174
+
175
+		if (rsn_preauth_iface_add(hapd, start)) {
176
+			rsn_preauth_iface_deinit(hapd);
177
+			os_free(tmp);
178
+			return -1;
179
+		}
180
+
181
+		if (end)
182
+			start = end + 1;
183
+		else
184
+			break;
185
+	}
186
+	os_free(tmp);
187
+	return 0;
188
+}
189
+
190
+
191
+static void rsn_preauth_finished_cb(void *eloop_ctx, void *timeout_ctx)
192
+{
193
+	struct hostapd_data *hapd = eloop_ctx;
194
+	struct sta_info *sta = timeout_ctx;
195
+	wpa_printf(MSG_DEBUG, "RSN: Removing pre-authentication STA entry for "
196
+		   MACSTR, MAC2STR(sta->addr));
197
+	ap_free_sta(hapd, sta);
198
+}
199
+
200
+
201
+void rsn_preauth_finished(struct hostapd_data *hapd, struct sta_info *sta,
202
+			  int success)
203
+{
204
+	const u8 *key;
205
+	size_t len;
206
+	hostapd_logger(hapd, sta->addr, HOSTAPD_MODULE_WPA,
207
+		       HOSTAPD_LEVEL_INFO, "pre-authentication %s",
208
+		       success ? "succeeded" : "failed");
209
+
210
+	key = ieee802_1x_get_key(sta->eapol_sm, &len);
211
+	if (len > PMK_LEN)
212
+		len = PMK_LEN;
213
+	if (success && key) {
214
+		if (wpa_auth_pmksa_add_preauth(hapd->wpa_auth, key, len,
215
+					       sta->addr,
216
+					       dot11RSNAConfigPMKLifetime,
217
+					       sta->eapol_sm) == 0) {
218
+			hostapd_logger(hapd, sta->addr, HOSTAPD_MODULE_WPA,
219
+				       HOSTAPD_LEVEL_DEBUG,
220
+				       "added PMKSA cache entry (pre-auth)");
221
+		} else {
222
+			hostapd_logger(hapd, sta->addr, HOSTAPD_MODULE_WPA,
223
+				       HOSTAPD_LEVEL_DEBUG,
224
+				       "failed to add PMKSA cache entry "
225
+				       "(pre-auth)");
226
+		}
227
+	}
228
+
229
+	/*
230
+	 * Finish STA entry removal from timeout in order to avoid freeing
231
+	 * STA data before the caller has finished processing.
232
+	 */
233
+	eloop_register_timeout(0, 0, rsn_preauth_finished_cb, hapd, sta);
234
+}
235
+
236
+
237
+void rsn_preauth_send(struct hostapd_data *hapd, struct sta_info *sta,
238
+		      u8 *buf, size_t len)
239
+{
240
+	struct rsn_preauth_interface *piface;
241
+	struct l2_ethhdr *ethhdr;
242
+
243
+	piface = hapd->preauth_iface;
244
+	while (piface) {
245
+		if (piface == sta->preauth_iface)
246
+			break;
247
+		piface = piface->next;
248
+	}
249
+
250
+	if (piface == NULL) {
251
+		wpa_printf(MSG_DEBUG, "RSN: Could not find pre-authentication "
252
+			   "interface for " MACSTR, MAC2STR(sta->addr));
253
+		return;
254
+	}
255
+
256
+	ethhdr = os_malloc(sizeof(*ethhdr) + len);
257
+	if (ethhdr == NULL)
258
+		return;
259
+
260
+	os_memcpy(ethhdr->h_dest, sta->addr, ETH_ALEN);
261
+	os_memcpy(ethhdr->h_source, hapd->own_addr, ETH_ALEN);
262
+	ethhdr->h_proto = host_to_be16(ETH_P_PREAUTH);
263
+	os_memcpy(ethhdr + 1, buf, len);
264
+
265
+	if (l2_packet_send(piface->l2, sta->addr, ETH_P_PREAUTH, (u8 *) ethhdr,
266
+			   sizeof(*ethhdr) + len) < 0) {
267
+		wpa_printf(MSG_ERROR, "Failed to send preauth packet using "
268
+			   "l2_packet_send\n");
269
+	}
270
+	os_free(ethhdr);
271
+}
272
+
273
+
274
+void rsn_preauth_free_station(struct hostapd_data *hapd, struct sta_info *sta)
275
+{
276
+	eloop_cancel_timeout(rsn_preauth_finished_cb, hapd, sta);
277
+}
278
+
279
+#endif /* CONFIG_RSN_PREAUTH */

+ 58
- 0
src/ap/preauth_auth.h Näytä tiedosto

@@ -0,0 +1,58 @@
1
+/*
2
+ * hostapd - Authenticator for IEEE 802.11i RSN pre-authentication
3
+ * Copyright (c) 2004-2005, Jouni Malinen <j@w1.fi>
4
+ *
5
+ * This program is free software; you can redistribute it and/or modify
6
+ * it under the terms of the GNU General Public License version 2 as
7
+ * published by the Free Software Foundation.
8
+ *
9
+ * Alternatively, this software may be distributed under the terms of BSD
10
+ * license.
11
+ *
12
+ * See README and COPYING for more details.
13
+ */
14
+
15
+#ifndef PREAUTH_H
16
+#define PREAUTH_H
17
+
18
+#ifdef CONFIG_RSN_PREAUTH
19
+
20
+int rsn_preauth_iface_init(struct hostapd_data *hapd);
21
+void rsn_preauth_iface_deinit(struct hostapd_data *hapd);
22
+void rsn_preauth_finished(struct hostapd_data *hapd, struct sta_info *sta,
23
+			  int success);
24
+void rsn_preauth_send(struct hostapd_data *hapd, struct sta_info *sta,
25
+		      u8 *buf, size_t len);
26
+void rsn_preauth_free_station(struct hostapd_data *hapd, struct sta_info *sta);
27
+
28
+#else /* CONFIG_RSN_PREAUTH */
29
+
30
+static inline int rsn_preauth_iface_init(struct hostapd_data *hapd)
31
+{
32
+	return 0;
33
+}
34
+
35
+static inline void rsn_preauth_iface_deinit(struct hostapd_data *hapd)
36
+{
37
+}
38
+
39
+static inline void rsn_preauth_finished(struct hostapd_data *hapd,
40
+					struct sta_info *sta,
41
+					int success)
42
+{
43
+}
44
+
45
+static inline void rsn_preauth_send(struct hostapd_data *hapd,
46
+				    struct sta_info *sta,
47
+				    u8 *buf, size_t len)
48
+{
49
+}
50
+
51
+static inline void rsn_preauth_free_station(struct hostapd_data *hapd,
52
+					    struct sta_info *sta)
53
+{
54
+}
55
+
56
+#endif /* CONFIG_RSN_PREAUTH */
57
+
58
+#endif /* PREAUTH_H */

+ 796
- 0
src/ap/sta_info.c Näytä tiedosto

@@ -0,0 +1,796 @@
1
+/*
2
+ * hostapd / Station table
3
+ * Copyright (c) 2002-2009, Jouni Malinen <j@w1.fi>
4
+ *
5
+ * This program is free software; you can redistribute it and/or modify
6
+ * it under the terms of the GNU General Public License version 2 as
7
+ * published by the Free Software Foundation.
8
+ *
9
+ * Alternatively, this software may be distributed under the terms of BSD
10
+ * license.
11
+ *
12
+ * See README and COPYING for more details.
13
+ */
14
+
15
+#include "utils/includes.h"
16
+
17
+#include "utils/common.h"
18
+#include "utils/eloop.h"
19
+#include "common/ieee802_11_defs.h"
20
+#include "radius/radius.h"
21
+#include "radius/radius_client.h"
22
+#include "drivers/driver.h"
23
+#include "p2p/p2p.h"
24
+#include "hostapd.h"
25
+#include "accounting.h"
26
+#include "ieee802_1x.h"
27
+#include "ieee802_11.h"
28
+#include "wpa_auth.h"
29
+#include "preauth_auth.h"
30
+#include "ap_config.h"
31
+#include "beacon.h"
32
+#include "ap_mlme.h"
33
+#include "vlan_init.h"
34
+#include "p2p_hostapd.h"
35
+#include "ap_drv_ops.h"
36
+#include "sta_info.h"
37
+
38
+static void ap_sta_remove_in_other_bss(struct hostapd_data *hapd,
39
+				       struct sta_info *sta);
40
+static void ap_handle_session_timer(void *eloop_ctx, void *timeout_ctx);
41
+#ifdef CONFIG_IEEE80211W
42
+static void ap_sa_query_timer(void *eloop_ctx, void *timeout_ctx);
43
+#endif /* CONFIG_IEEE80211W */
44
+
45
+int ap_for_each_sta(struct hostapd_data *hapd,
46
+		    int (*cb)(struct hostapd_data *hapd, struct sta_info *sta,
47
+			      void *ctx),
48
+		    void *ctx)
49
+{
50
+	struct sta_info *sta;
51
+
52
+	for (sta = hapd->sta_list; sta; sta = sta->next) {
53
+		if (cb(hapd, sta, ctx))
54
+			return 1;
55
+	}
56
+
57
+	return 0;
58
+}
59
+
60
+
61
+struct sta_info * ap_get_sta(struct hostapd_data *hapd, const u8 *sta)
62
+{
63
+	struct sta_info *s;
64
+
65
+	s = hapd->sta_hash[STA_HASH(sta)];
66
+	while (s != NULL && os_memcmp(s->addr, sta, 6) != 0)
67
+		s = s->hnext;
68
+	return s;
69
+}
70
+
71
+
72
+static void ap_sta_list_del(struct hostapd_data *hapd, struct sta_info *sta)
73
+{
74
+	struct sta_info *tmp;
75
+
76
+	if (hapd->sta_list == sta) {
77
+		hapd->sta_list = sta->next;
78
+		return;
79
+	}
80
+
81
+	tmp = hapd->sta_list;
82
+	while (tmp != NULL && tmp->next != sta)
83
+		tmp = tmp->next;
84
+	if (tmp == NULL) {
85
+		wpa_printf(MSG_DEBUG, "Could not remove STA " MACSTR " from "
86
+			   "list.", MAC2STR(sta->addr));
87
+	} else
88
+		tmp->next = sta->next;
89
+}
90
+
91
+
92
+void ap_sta_hash_add(struct hostapd_data *hapd, struct sta_info *sta)
93
+{
94
+	sta->hnext = hapd->sta_hash[STA_HASH(sta->addr)];
95
+	hapd->sta_hash[STA_HASH(sta->addr)] = sta;
96
+}
97
+
98
+
99
+static void ap_sta_hash_del(struct hostapd_data *hapd, struct sta_info *sta)
100
+{
101
+	struct sta_info *s;
102
+
103
+	s = hapd->sta_hash[STA_HASH(sta->addr)];
104
+	if (s == NULL) return;
105
+	if (os_memcmp(s->addr, sta->addr, 6) == 0) {
106
+		hapd->sta_hash[STA_HASH(sta->addr)] = s->hnext;
107
+		return;
108
+	}
109
+
110
+	while (s->hnext != NULL &&
111
+	       os_memcmp(s->hnext->addr, sta->addr, ETH_ALEN) != 0)
112
+		s = s->hnext;
113
+	if (s->hnext != NULL)
114
+		s->hnext = s->hnext->hnext;
115
+	else
116
+		wpa_printf(MSG_DEBUG, "AP: could not remove STA " MACSTR
117
+			   " from hash table", MAC2STR(sta->addr));
118
+}
119
+
120
+
121
+void ap_free_sta(struct hostapd_data *hapd, struct sta_info *sta)
122
+{
123
+	int set_beacon = 0;
124
+
125
+	accounting_sta_stop(hapd, sta);
126
+
127
+	/* just in case */
128
+	ap_sta_set_authorized(hapd, sta, 0);
129
+
130
+	if (sta->flags & WLAN_STA_WDS)
131
+		hostapd_set_wds_sta(hapd, sta->addr, sta->aid, 0);
132
+
133
+	if (!(sta->flags & WLAN_STA_PREAUTH))
134
+		hostapd_drv_sta_remove(hapd, sta->addr);
135
+
136
+	ap_sta_hash_del(hapd, sta);
137
+	ap_sta_list_del(hapd, sta);
138
+
139
+	if (sta->aid > 0)
140
+		hapd->sta_aid[(sta->aid - 1) / 32] &=
141
+			~BIT((sta->aid - 1) % 32);
142
+
143
+	hapd->num_sta--;
144
+	if (sta->nonerp_set) {
145
+		sta->nonerp_set = 0;
146
+		hapd->iface->num_sta_non_erp--;
147
+		if (hapd->iface->num_sta_non_erp == 0)
148
+			set_beacon++;
149
+	}
150
+
151
+	if (sta->no_short_slot_time_set) {
152
+		sta->no_short_slot_time_set = 0;
153
+		hapd->iface->num_sta_no_short_slot_time--;
154
+		if (hapd->iface->current_mode->mode == HOSTAPD_MODE_IEEE80211G
155
+		    && hapd->iface->num_sta_no_short_slot_time == 0)
156
+			set_beacon++;
157
+	}
158
+
159
+	if (sta->no_short_preamble_set) {
160
+		sta->no_short_preamble_set = 0;
161
+		hapd->iface->num_sta_no_short_preamble--;
162
+		if (hapd->iface->current_mode->mode == HOSTAPD_MODE_IEEE80211G
163
+		    && hapd->iface->num_sta_no_short_preamble == 0)
164
+			set_beacon++;
165
+	}
166
+
167
+	if (sta->no_ht_gf_set) {
168
+		sta->no_ht_gf_set = 0;
169
+		hapd->iface->num_sta_ht_no_gf--;
170
+	}
171
+
172
+	if (sta->no_ht_set) {
173
+		sta->no_ht_set = 0;
174
+		hapd->iface->num_sta_no_ht--;
175
+	}
176
+
177
+	if (sta->ht_20mhz_set) {
178
+		sta->ht_20mhz_set = 0;
179
+		hapd->iface->num_sta_ht_20mhz--;
180
+	}
181
+
182
+#ifdef CONFIG_P2P
183
+	if (sta->no_p2p_set) {
184
+		sta->no_p2p_set = 0;
185
+		hapd->num_sta_no_p2p--;
186
+		if (hapd->num_sta_no_p2p == 0)
187
+			hostapd_p2p_non_p2p_sta_disconnected(hapd);
188
+	}
189
+#endif /* CONFIG_P2P */
190
+
191
+#if defined(NEED_AP_MLME) && defined(CONFIG_IEEE80211N)
192
+	if (hostapd_ht_operation_update(hapd->iface) > 0)
193
+		set_beacon++;
194
+#endif /* NEED_AP_MLME && CONFIG_IEEE80211N */
195
+
196
+	if (set_beacon)
197
+		ieee802_11_set_beacons(hapd->iface);
198
+
199
+	eloop_cancel_timeout(ap_handle_timer, hapd, sta);
200
+	eloop_cancel_timeout(ap_handle_session_timer, hapd, sta);
201
+
202
+	ieee802_1x_free_station(sta);
203
+	wpa_auth_sta_deinit(sta->wpa_sm);
204
+	rsn_preauth_free_station(hapd, sta);
205
+#ifndef CONFIG_NO_RADIUS
206
+	radius_client_flush_auth(hapd->radius, sta->addr);
207
+#endif /* CONFIG_NO_RADIUS */
208
+
209
+	os_free(sta->last_assoc_req);
210
+	os_free(sta->challenge);
211
+
212
+#ifdef CONFIG_IEEE80211W
213
+	os_free(sta->sa_query_trans_id);
214
+	eloop_cancel_timeout(ap_sa_query_timer, hapd, sta);
215
+#endif /* CONFIG_IEEE80211W */
216
+
217
+#ifdef CONFIG_P2P
218
+	p2p_group_notif_disassoc(hapd->p2p_group, sta->addr);
219
+#endif /* CONFIG_P2P */
220
+
221
+	wpabuf_free(sta->wps_ie);
222
+	wpabuf_free(sta->p2p_ie);
223
+
224
+	os_free(sta->ht_capabilities);
225
+
226
+	os_free(sta);
227
+}
228
+
229
+
230
+void hostapd_free_stas(struct hostapd_data *hapd)
231
+{
232
+	struct sta_info *sta, *prev;
233
+
234
+	sta = hapd->sta_list;
235
+
236
+	while (sta) {
237
+		prev = sta;
238
+		if (sta->flags & WLAN_STA_AUTH) {
239
+			mlme_deauthenticate_indication(
240
+				hapd, sta, WLAN_REASON_UNSPECIFIED);
241
+		}
242
+		sta = sta->next;
243
+		wpa_printf(MSG_DEBUG, "Removing station " MACSTR,
244
+			   MAC2STR(prev->addr));
245
+		ap_free_sta(hapd, prev);
246
+	}
247
+}
248
+
249
+
250
+/**
251
+ * ap_handle_timer - Per STA timer handler
252
+ * @eloop_ctx: struct hostapd_data *
253
+ * @timeout_ctx: struct sta_info *
254
+ *
255
+ * This function is called to check station activity and to remove inactive
256
+ * stations.
257
+ */
258
+void ap_handle_timer(void *eloop_ctx, void *timeout_ctx)
259
+{
260
+	struct hostapd_data *hapd = eloop_ctx;
261
+	struct sta_info *sta = timeout_ctx;
262
+	unsigned long next_time = 0;
263
+
264
+	if (sta->timeout_next == STA_REMOVE) {
265
+		hostapd_logger(hapd, sta->addr, HOSTAPD_MODULE_IEEE80211,
266
+			       HOSTAPD_LEVEL_INFO, "deauthenticated due to "
267
+			       "local deauth request");
268
+		ap_free_sta(hapd, sta);
269
+		return;
270
+	}
271
+
272
+	if ((sta->flags & WLAN_STA_ASSOC) &&
273
+	    (sta->timeout_next == STA_NULLFUNC ||
274
+	     sta->timeout_next == STA_DISASSOC)) {
275
+		int inactive_sec;
276
+		inactive_sec = hostapd_drv_get_inact_sec(hapd, sta->addr);
277
+		if (inactive_sec == -1) {
278
+			wpa_msg(hapd, MSG_DEBUG, "Check inactivity: Could not "
279
+				"get station info rom kernel driver for "
280
+				MACSTR, MAC2STR(sta->addr));
281
+		} else if (inactive_sec < hapd->conf->ap_max_inactivity &&
282
+			   sta->flags & WLAN_STA_ASSOC) {
283
+			/* station activity detected; reset timeout state */
284
+			wpa_msg(hapd, MSG_DEBUG, "Station " MACSTR " has been "
285
+				"active %is ago",
286
+				MAC2STR(sta->addr), inactive_sec);
287
+			sta->timeout_next = STA_NULLFUNC;
288
+			next_time = hapd->conf->ap_max_inactivity -
289
+				inactive_sec;
290
+		} else {
291
+			wpa_msg(hapd, MSG_DEBUG, "Station " MACSTR " has been "
292
+				"inactive too long: %d sec, max allowed: %d",
293
+				MAC2STR(sta->addr), inactive_sec,
294
+				hapd->conf->ap_max_inactivity);
295
+		}
296
+	}
297
+
298
+	if ((sta->flags & WLAN_STA_ASSOC) &&
299
+	    sta->timeout_next == STA_DISASSOC &&
300
+	    !(sta->flags & WLAN_STA_PENDING_POLL)) {
301
+		wpa_msg(hapd, MSG_DEBUG, "Station " MACSTR " has ACKed data "
302
+			"poll", MAC2STR(sta->addr));
303
+		/* data nullfunc frame poll did not produce TX errors; assume
304
+		 * station ACKed it */
305
+		sta->timeout_next = STA_NULLFUNC;
306
+		next_time = hapd->conf->ap_max_inactivity;
307
+	}
308
+
309
+	if (next_time) {
310
+		eloop_register_timeout(next_time, 0, ap_handle_timer, hapd,
311
+				       sta);
312
+		return;
313
+	}
314
+
315
+	if (sta->timeout_next == STA_NULLFUNC &&
316
+	    (sta->flags & WLAN_STA_ASSOC)) {
317
+#ifndef CONFIG_NATIVE_WINDOWS
318
+		/* send data frame to poll STA and check whether this frame
319
+		 * is ACKed */
320
+		struct ieee80211_hdr hdr;
321
+
322
+		wpa_printf(MSG_DEBUG, "  Polling STA with data frame");
323
+		sta->flags |= WLAN_STA_PENDING_POLL;
324
+
325
+		os_memset(&hdr, 0, sizeof(hdr));
326
+		if (hapd->driver &&
327
+		    os_strcmp(hapd->driver->name, "hostap") == 0) {
328
+			/*
329
+			 * WLAN_FC_STYPE_NULLFUNC would be more appropriate,
330
+			 * but it is apparently not retried so TX Exc events
331
+			 * are not received for it.
332
+			 */
333
+			hdr.frame_control =
334
+				IEEE80211_FC(WLAN_FC_TYPE_DATA,
335
+					     WLAN_FC_STYPE_DATA);
336
+		} else {
337
+			hdr.frame_control =
338
+				IEEE80211_FC(WLAN_FC_TYPE_DATA,
339
+					     WLAN_FC_STYPE_NULLFUNC);
340
+		}
341
+
342
+		hdr.frame_control |= host_to_le16(WLAN_FC_FROMDS);
343
+		os_memcpy(hdr.IEEE80211_DA_FROMDS, sta->addr, ETH_ALEN);
344
+		os_memcpy(hdr.IEEE80211_BSSID_FROMDS, hapd->own_addr,
345
+			  ETH_ALEN);
346
+		os_memcpy(hdr.IEEE80211_SA_FROMDS, hapd->own_addr, ETH_ALEN);
347
+
348
+		if (hostapd_drv_send_mlme(hapd, &hdr, sizeof(hdr)) < 0)
349
+			perror("ap_handle_timer: send");
350
+#endif /* CONFIG_NATIVE_WINDOWS */
351
+	} else if (sta->timeout_next != STA_REMOVE) {
352
+		int deauth = sta->timeout_next == STA_DEAUTH;
353
+
354
+		wpa_printf(MSG_DEBUG, "Sending %s info to STA " MACSTR,
355
+			   deauth ? "deauthentication" : "disassociation",
356
+			   MAC2STR(sta->addr));
357
+
358
+		if (deauth) {
359
+			hostapd_drv_sta_deauth(
360
+				hapd, sta->addr,
361
+				WLAN_REASON_PREV_AUTH_NOT_VALID);
362
+		} else {
363
+			hostapd_drv_sta_disassoc(
364
+				hapd, sta->addr,
365
+				WLAN_REASON_DISASSOC_DUE_TO_INACTIVITY);
366
+		}
367
+	}
368
+
369
+	switch (sta->timeout_next) {
370
+	case STA_NULLFUNC:
371
+		sta->timeout_next = STA_DISASSOC;
372
+		eloop_register_timeout(AP_DISASSOC_DELAY, 0, ap_handle_timer,
373
+				       hapd, sta);
374
+		break;
375
+	case STA_DISASSOC:
376
+		sta->flags &= ~WLAN_STA_ASSOC;
377
+		ieee802_1x_notify_port_enabled(sta->eapol_sm, 0);
378
+		if (!sta->acct_terminate_cause)
379
+			sta->acct_terminate_cause =
380
+				RADIUS_ACCT_TERMINATE_CAUSE_IDLE_TIMEOUT;
381
+		accounting_sta_stop(hapd, sta);
382
+		ieee802_1x_free_station(sta);
383
+		hostapd_logger(hapd, sta->addr, HOSTAPD_MODULE_IEEE80211,
384
+			       HOSTAPD_LEVEL_INFO, "disassociated due to "
385
+			       "inactivity");
386
+		sta->timeout_next = STA_DEAUTH;
387
+		eloop_register_timeout(AP_DEAUTH_DELAY, 0, ap_handle_timer,
388
+				       hapd, sta);
389
+		mlme_disassociate_indication(
390
+			hapd, sta, WLAN_REASON_DISASSOC_DUE_TO_INACTIVITY);
391
+		break;
392
+	case STA_DEAUTH:
393
+	case STA_REMOVE:
394
+		hostapd_logger(hapd, sta->addr, HOSTAPD_MODULE_IEEE80211,
395
+			       HOSTAPD_LEVEL_INFO, "deauthenticated due to "
396
+			       "inactivity");
397
+		if (!sta->acct_terminate_cause)
398
+			sta->acct_terminate_cause =
399
+				RADIUS_ACCT_TERMINATE_CAUSE_IDLE_TIMEOUT;
400
+		mlme_deauthenticate_indication(
401
+			hapd, sta,
402
+			WLAN_REASON_PREV_AUTH_NOT_VALID);
403
+		ap_free_sta(hapd, sta);
404
+		break;
405
+	}
406
+}
407
+
408
+
409
+static void ap_handle_session_timer(void *eloop_ctx, void *timeout_ctx)
410
+{
411
+	struct hostapd_data *hapd = eloop_ctx;
412
+	struct sta_info *sta = timeout_ctx;
413
+	u8 addr[ETH_ALEN];
414
+
415
+	if (!(sta->flags & WLAN_STA_AUTH))
416
+		return;
417
+
418
+	mlme_deauthenticate_indication(hapd, sta,
419
+				       WLAN_REASON_PREV_AUTH_NOT_VALID);
420
+	hostapd_logger(hapd, sta->addr, HOSTAPD_MODULE_IEEE80211,
421
+		       HOSTAPD_LEVEL_INFO, "deauthenticated due to "
422
+		       "session timeout");
423
+	sta->acct_terminate_cause =
424
+		RADIUS_ACCT_TERMINATE_CAUSE_SESSION_TIMEOUT;
425
+	os_memcpy(addr, sta->addr, ETH_ALEN);
426
+	ap_free_sta(hapd, sta);
427
+	hostapd_drv_sta_deauth(hapd, addr, WLAN_REASON_PREV_AUTH_NOT_VALID);
428
+}
429
+
430
+
431
+void ap_sta_session_timeout(struct hostapd_data *hapd, struct sta_info *sta,
432
+			    u32 session_timeout)
433
+{
434
+	hostapd_logger(hapd, sta->addr, HOSTAPD_MODULE_IEEE80211,
435
+		       HOSTAPD_LEVEL_DEBUG, "setting session timeout to %d "
436
+		       "seconds", session_timeout);
437
+	eloop_cancel_timeout(ap_handle_session_timer, hapd, sta);
438
+	eloop_register_timeout(session_timeout, 0, ap_handle_session_timer,
439
+			       hapd, sta);
440
+}
441
+
442
+
443
+void ap_sta_no_session_timeout(struct hostapd_data *hapd, struct sta_info *sta)
444
+{
445
+	eloop_cancel_timeout(ap_handle_session_timer, hapd, sta);
446
+}
447
+
448
+
449
+struct sta_info * ap_sta_add(struct hostapd_data *hapd, const u8 *addr)
450
+{
451
+	struct sta_info *sta;
452
+
453
+	sta = ap_get_sta(hapd, addr);
454
+	if (sta)
455
+		return sta;
456
+
457
+	wpa_printf(MSG_DEBUG, "  New STA");
458
+	if (hapd->num_sta >= hapd->conf->max_num_sta) {
459
+		/* FIX: might try to remove some old STAs first? */
460
+		wpa_printf(MSG_DEBUG, "no more room for new STAs (%d/%d)",
461
+			   hapd->num_sta, hapd->conf->max_num_sta);
462
+		return NULL;
463
+	}
464
+
465
+	sta = os_zalloc(sizeof(struct sta_info));
466
+	if (sta == NULL) {
467
+		wpa_printf(MSG_ERROR, "malloc failed");
468
+		return NULL;
469
+	}
470
+	sta->acct_interim_interval = hapd->conf->acct_interim_interval;
471
+
472
+	/* initialize STA info data */
473
+	eloop_register_timeout(hapd->conf->ap_max_inactivity, 0,
474
+			       ap_handle_timer, hapd, sta);
475
+	os_memcpy(sta->addr, addr, ETH_ALEN);
476
+	sta->next = hapd->sta_list;
477
+	hapd->sta_list = sta;
478
+	hapd->num_sta++;
479
+	ap_sta_hash_add(hapd, sta);
480
+	sta->ssid = &hapd->conf->ssid;
481
+	ap_sta_remove_in_other_bss(hapd, sta);
482
+
483
+	return sta;
484
+}
485
+
486
+
487
+static int ap_sta_remove(struct hostapd_data *hapd, struct sta_info *sta)
488
+{
489
+	ieee802_1x_notify_port_enabled(sta->eapol_sm, 0);
490
+
491
+	wpa_printf(MSG_DEBUG, "Removing STA " MACSTR " from kernel driver",
492
+		   MAC2STR(sta->addr));
493
+	if (hostapd_drv_sta_remove(hapd, sta->addr) &&
494
+	    sta->flags & WLAN_STA_ASSOC) {
495
+		wpa_printf(MSG_DEBUG, "Could not remove station " MACSTR
496
+			   " from kernel driver.", MAC2STR(sta->addr));
497
+		return -1;
498
+	}
499
+	return 0;
500
+}
501
+
502
+
503
+static void ap_sta_remove_in_other_bss(struct hostapd_data *hapd,
504
+				       struct sta_info *sta)
505
+{
506
+	struct hostapd_iface *iface = hapd->iface;
507
+	size_t i;
508
+
509
+	for (i = 0; i < iface->num_bss; i++) {
510
+		struct hostapd_data *bss = iface->bss[i];
511
+		struct sta_info *sta2;
512
+		/* bss should always be set during operation, but it may be
513
+		 * NULL during reconfiguration. Assume the STA is not
514
+		 * associated to another BSS in that case to avoid NULL pointer
515
+		 * dereferences. */
516
+		if (bss == hapd || bss == NULL)
517
+			continue;
518
+		sta2 = ap_get_sta(bss, sta->addr);
519
+		if (!sta2)
520
+			continue;
521
+
522
+		ap_sta_disconnect(bss, sta2, sta2->addr,
523
+				  WLAN_REASON_PREV_AUTH_NOT_VALID);
524
+	}
525
+}
526
+
527
+
528
+void ap_sta_disassociate(struct hostapd_data *hapd, struct sta_info *sta,
529
+			 u16 reason)
530
+{
531
+	wpa_printf(MSG_DEBUG, "%s: disassociate STA " MACSTR,
532
+		   hapd->conf->iface, MAC2STR(sta->addr));
533
+	sta->flags &= ~WLAN_STA_ASSOC;
534
+	ap_sta_remove(hapd, sta);
535
+	sta->timeout_next = STA_DEAUTH;
536
+	eloop_cancel_timeout(ap_handle_timer, hapd, sta);
537
+	eloop_register_timeout(AP_MAX_INACTIVITY_AFTER_DISASSOC, 0,
538
+			       ap_handle_timer, hapd, sta);
539
+	accounting_sta_stop(hapd, sta);
540
+	ieee802_1x_free_station(sta);
541
+
542
+	mlme_disassociate_indication(hapd, sta, reason);
543
+}
544
+
545
+
546
+void ap_sta_deauthenticate(struct hostapd_data *hapd, struct sta_info *sta,
547
+			   u16 reason)
548
+{
549
+	wpa_printf(MSG_DEBUG, "%s: deauthenticate STA " MACSTR,
550
+		   hapd->conf->iface, MAC2STR(sta->addr));
551
+	sta->flags &= ~(WLAN_STA_AUTH | WLAN_STA_ASSOC);
552
+	ap_sta_remove(hapd, sta);
553
+	sta->timeout_next = STA_REMOVE;
554
+	eloop_cancel_timeout(ap_handle_timer, hapd, sta);
555
+	eloop_register_timeout(AP_MAX_INACTIVITY_AFTER_DEAUTH, 0,
556
+			       ap_handle_timer, hapd, sta);
557
+	accounting_sta_stop(hapd, sta);
558
+	ieee802_1x_free_station(sta);
559
+
560
+	mlme_deauthenticate_indication(hapd, sta, reason);
561
+}
562
+
563
+
564
+int ap_sta_bind_vlan(struct hostapd_data *hapd, struct sta_info *sta,
565
+		     int old_vlanid)
566
+{
567
+#ifndef CONFIG_NO_VLAN
568
+	const char *iface;
569
+	struct hostapd_vlan *vlan = NULL;
570
+	int ret;
571
+
572
+	/*
573
+	 * Do not proceed furthur if the vlan id remains same. We do not want
574
+	 * duplicate dynamic vlan entries.
575
+	 */
576
+	if (sta->vlan_id == old_vlanid)
577
+		return 0;
578
+
579
+	/*
580
+	 * During 1x reauth, if the vlan id changes, then remove the old id and
581
+	 * proceed furthur to add the new one.
582
+	 */
583
+	if (old_vlanid > 0)
584
+		vlan_remove_dynamic(hapd, old_vlanid);
585
+
586
+	iface = hapd->conf->iface;
587
+	if (sta->ssid->vlan[0])
588
+		iface = sta->ssid->vlan;
589
+
590
+	if (sta->ssid->dynamic_vlan == DYNAMIC_VLAN_DISABLED)
591
+		sta->vlan_id = 0;
592
+	else if (sta->vlan_id > 0) {
593
+		vlan = hapd->conf->vlan;
594
+		while (vlan) {
595
+			if (vlan->vlan_id == sta->vlan_id ||
596
+			    vlan->vlan_id == VLAN_ID_WILDCARD) {
597
+				iface = vlan->ifname;
598
+				break;
599
+			}
600
+			vlan = vlan->next;
601
+		}
602
+	}
603
+
604
+	if (sta->vlan_id > 0 && vlan == NULL) {
605
+		hostapd_logger(hapd, sta->addr, HOSTAPD_MODULE_IEEE80211,
606
+			       HOSTAPD_LEVEL_DEBUG, "could not find VLAN for "
607
+			       "binding station to (vlan_id=%d)",
608
+			       sta->vlan_id);
609
+		return -1;
610
+	} else if (sta->vlan_id > 0 && vlan->vlan_id == VLAN_ID_WILDCARD) {
611
+		vlan = vlan_add_dynamic(hapd, vlan, sta->vlan_id);
612
+		if (vlan == NULL) {
613
+			hostapd_logger(hapd, sta->addr,
614
+				       HOSTAPD_MODULE_IEEE80211,
615
+				       HOSTAPD_LEVEL_DEBUG, "could not add "
616
+				       "dynamic VLAN interface for vlan_id=%d",
617
+				       sta->vlan_id);
618
+			return -1;
619
+		}
620
+
621
+		iface = vlan->ifname;
622
+		if (vlan_setup_encryption_dyn(hapd, sta->ssid, iface) != 0) {
623
+			hostapd_logger(hapd, sta->addr,
624
+				       HOSTAPD_MODULE_IEEE80211,
625
+				       HOSTAPD_LEVEL_DEBUG, "could not "
626
+				       "configure encryption for dynamic VLAN "
627
+				       "interface for vlan_id=%d",
628
+				       sta->vlan_id);
629
+		}
630
+
631
+		hostapd_logger(hapd, sta->addr, HOSTAPD_MODULE_IEEE80211,
632
+			       HOSTAPD_LEVEL_DEBUG, "added new dynamic VLAN "
633
+			       "interface '%s'", iface);
634
+	} else if (vlan && vlan->vlan_id == sta->vlan_id) {
635
+		if (sta->vlan_id > 0) {
636
+			vlan->dynamic_vlan++;
637
+			hostapd_logger(hapd, sta->addr,
638
+				       HOSTAPD_MODULE_IEEE80211,
639
+				       HOSTAPD_LEVEL_DEBUG, "updated existing "
640
+				       "dynamic VLAN interface '%s'", iface);
641
+		}
642
+
643
+		/*
644
+		 * Update encryption configuration for statically generated
645
+		 * VLAN interface. This is only used for static WEP
646
+		 * configuration for the case where hostapd did not yet know
647
+		 * which keys are to be used when the interface was added.
648
+		 */
649
+		if (vlan_setup_encryption_dyn(hapd, sta->ssid, iface) != 0) {
650
+			hostapd_logger(hapd, sta->addr,
651
+				       HOSTAPD_MODULE_IEEE80211,
652
+				       HOSTAPD_LEVEL_DEBUG, "could not "
653
+				       "configure encryption for VLAN "
654
+				       "interface for vlan_id=%d",
655
+				       sta->vlan_id);
656
+		}
657
+	}
658
+
659
+	hostapd_logger(hapd, sta->addr, HOSTAPD_MODULE_IEEE80211,
660
+		       HOSTAPD_LEVEL_DEBUG, "binding station to interface "
661
+		       "'%s'", iface);
662
+
663
+	if (wpa_auth_sta_set_vlan(sta->wpa_sm, sta->vlan_id) < 0)
664
+		wpa_printf(MSG_INFO, "Failed to update VLAN-ID for WPA");
665
+
666
+	ret = hostapd_drv_set_sta_vlan(iface, hapd, sta->addr, sta->vlan_id);
667
+	if (ret < 0) {
668
+		hostapd_logger(hapd, sta->addr, HOSTAPD_MODULE_IEEE80211,
669
+			       HOSTAPD_LEVEL_DEBUG, "could not bind the STA "
670
+			       "entry to vlan_id=%d", sta->vlan_id);
671
+	}
672
+	return ret;
673
+#else /* CONFIG_NO_VLAN */
674
+	return 0;
675
+#endif /* CONFIG_NO_VLAN */
676
+}
677
+
678
+
679
+#ifdef CONFIG_IEEE80211W
680
+
681
+int ap_check_sa_query_timeout(struct hostapd_data *hapd, struct sta_info *sta)
682
+{
683
+	u32 tu;
684
+	struct os_time now, passed;
685
+	os_get_time(&now);
686
+	os_time_sub(&now, &sta->sa_query_start, &passed);
687
+	tu = (passed.sec * 1000000 + passed.usec) / 1024;
688
+	if (hapd->conf->assoc_sa_query_max_timeout < tu) {
689
+		hostapd_logger(hapd, sta->addr,
690
+			       HOSTAPD_MODULE_IEEE80211,
691
+			       HOSTAPD_LEVEL_DEBUG,
692
+			       "association SA Query timed out");
693
+		sta->sa_query_timed_out = 1;
694
+		os_free(sta->sa_query_trans_id);
695
+		sta->sa_query_trans_id = NULL;
696
+		sta->sa_query_count = 0;
697
+		eloop_cancel_timeout(ap_sa_query_timer, hapd, sta);
698
+		return 1;
699
+	}
700
+
701
+	return 0;
702
+}
703
+
704
+
705
+static void ap_sa_query_timer(void *eloop_ctx, void *timeout_ctx)
706
+{
707
+	struct hostapd_data *hapd = eloop_ctx;
708
+	struct sta_info *sta = timeout_ctx;
709
+	unsigned int timeout, sec, usec;
710
+	u8 *trans_id, *nbuf;
711
+
712
+	if (sta->sa_query_count > 0 &&
713
+	    ap_check_sa_query_timeout(hapd, sta))
714
+		return;
715
+
716
+	nbuf = os_realloc(sta->sa_query_trans_id,
717
+			  (sta->sa_query_count + 1) * WLAN_SA_QUERY_TR_ID_LEN);
718
+	if (nbuf == NULL)
719
+		return;
720
+	if (sta->sa_query_count == 0) {
721
+		/* Starting a new SA Query procedure */
722
+		os_get_time(&sta->sa_query_start);
723
+	}
724
+	trans_id = nbuf + sta->sa_query_count * WLAN_SA_QUERY_TR_ID_LEN;
725
+	sta->sa_query_trans_id = nbuf;
726
+	sta->sa_query_count++;
727
+
728
+	os_get_random(trans_id, WLAN_SA_QUERY_TR_ID_LEN);
729
+
730
+	timeout = hapd->conf->assoc_sa_query_retry_timeout;
731
+	sec = ((timeout / 1000) * 1024) / 1000;
732
+	usec = (timeout % 1000) * 1024;
733
+	eloop_register_timeout(sec, usec, ap_sa_query_timer, hapd, sta);
734
+
735
+	hostapd_logger(hapd, sta->addr, HOSTAPD_MODULE_IEEE80211,
736
+		       HOSTAPD_LEVEL_DEBUG,
737
+		       "association SA Query attempt %d", sta->sa_query_count);
738
+
739
+#ifdef NEED_AP_MLME
740
+	ieee802_11_send_sa_query_req(hapd, sta->addr, trans_id);
741
+#endif /* NEED_AP_MLME */
742
+}
743
+
744
+
745
+void ap_sta_start_sa_query(struct hostapd_data *hapd, struct sta_info *sta)
746
+{
747
+	ap_sa_query_timer(hapd, sta);
748
+}
749
+
750
+
751
+void ap_sta_stop_sa_query(struct hostapd_data *hapd, struct sta_info *sta)
752
+{
753
+	eloop_cancel_timeout(ap_sa_query_timer, hapd, sta);
754
+	os_free(sta->sa_query_trans_id);
755
+	sta->sa_query_trans_id = NULL;
756
+	sta->sa_query_count = 0;
757
+}
758
+
759
+#endif /* CONFIG_IEEE80211W */
760
+
761
+
762
+void ap_sta_set_authorized(struct hostapd_data *hapd, struct sta_info *sta,
763
+			   int authorized)
764
+{
765
+	if (!!authorized == !!(sta->flags & WLAN_STA_AUTHORIZED))
766
+		return;
767
+
768
+	if (authorized)
769
+		sta->flags |= WLAN_STA_AUTHORIZED;
770
+	else
771
+		sta->flags &= ~WLAN_STA_AUTHORIZED;
772
+
773
+	if (hapd->sta_authorized_cb)
774
+		hapd->sta_authorized_cb(hapd->sta_authorized_cb_ctx,
775
+					sta->addr, authorized);
776
+}
777
+
778
+
779
+void ap_sta_disconnect(struct hostapd_data *hapd, struct sta_info *sta,
780
+		       const u8 *addr, u16 reason)
781
+{
782
+
783
+	if (sta == NULL && addr)
784
+		sta = ap_get_sta(hapd, addr);
785
+
786
+	if (addr)
787
+		hostapd_drv_sta_deauth(hapd, addr, reason);
788
+
789
+	if (sta == NULL)
790
+		return;
791
+	ap_sta_set_authorized(hapd, sta, 0);
792
+	sta->flags &= ~(WLAN_STA_AUTH | WLAN_STA_ASSOC);
793
+	eloop_cancel_timeout(ap_handle_timer, hapd, sta);
794
+	eloop_register_timeout(0, 0, ap_handle_timer, hapd, sta);
795
+	sta->timeout_next = STA_REMOVE;
796
+}

+ 165
- 0
src/ap/sta_info.h Näytä tiedosto

@@ -0,0 +1,165 @@
1
+/*
2
+ * hostapd / Station table
3
+ * Copyright (c) 2002-2009, Jouni Malinen <j@w1.fi>
4
+ *
5
+ * This program is free software; you can redistribute it and/or modify
6
+ * it under the terms of the GNU General Public License version 2 as
7
+ * published by the Free Software Foundation.
8
+ *
9
+ * Alternatively, this software may be distributed under the terms of BSD
10
+ * license.
11
+ *
12
+ * See README and COPYING for more details.
13
+ */
14
+
15
+#ifndef STA_INFO_H
16
+#define STA_INFO_H
17
+
18
+/* STA flags */
19
+#define WLAN_STA_AUTH BIT(0)
20
+#define WLAN_STA_ASSOC BIT(1)
21
+#define WLAN_STA_PS BIT(2)
22
+#define WLAN_STA_TIM BIT(3)
23
+#define WLAN_STA_PERM BIT(4)
24
+#define WLAN_STA_AUTHORIZED BIT(5)
25
+#define WLAN_STA_PENDING_POLL BIT(6) /* pending activity poll not ACKed */
26
+#define WLAN_STA_SHORT_PREAMBLE BIT(7)
27
+#define WLAN_STA_PREAUTH BIT(8)
28
+#define WLAN_STA_WMM BIT(9)
29
+#define WLAN_STA_MFP BIT(10)
30
+#define WLAN_STA_HT BIT(11)
31
+#define WLAN_STA_WPS BIT(12)
32
+#define WLAN_STA_MAYBE_WPS BIT(13)
33
+#define WLAN_STA_WDS BIT(14)
34
+#define WLAN_STA_ASSOC_REQ_OK BIT(15)
35
+#define WLAN_STA_NONERP BIT(31)
36
+
37
+/* Maximum number of supported rates (from both Supported Rates and Extended
38
+ * Supported Rates IEs). */
39
+#define WLAN_SUPP_RATES_MAX 32
40
+
41
+
42
+struct sta_info {
43
+	struct sta_info *next; /* next entry in sta list */
44
+	struct sta_info *hnext; /* next entry in hash table list */
45
+	u8 addr[6];
46
+	u16 aid; /* STA's unique AID (1 .. 2007) or 0 if not yet assigned */
47
+	u32 flags; /* Bitfield of WLAN_STA_* */
48
+	u16 capability;
49
+	u16 listen_interval; /* or beacon_int for APs */
50
+	u8 supported_rates[WLAN_SUPP_RATES_MAX];
51
+	int supported_rates_len;
52
+
53
+	unsigned int nonerp_set:1;
54
+	unsigned int no_short_slot_time_set:1;
55
+	unsigned int no_short_preamble_set:1;
56
+	unsigned int no_ht_gf_set:1;
57
+	unsigned int no_ht_set:1;
58
+	unsigned int ht_20mhz_set:1;
59
+	unsigned int no_p2p_set:1;
60
+
61
+	u16 auth_alg;
62
+	u8 previous_ap[6];
63
+
64
+	enum {
65
+		STA_NULLFUNC = 0, STA_DISASSOC, STA_DEAUTH, STA_REMOVE
66
+	} timeout_next;
67
+
68
+	/* IEEE 802.1X related data */
69
+	struct eapol_state_machine *eapol_sm;
70
+
71
+	/* IEEE 802.11f (IAPP) related data */
72
+	struct ieee80211_mgmt *last_assoc_req;
73
+
74
+	u32 acct_session_id_hi;
75
+	u32 acct_session_id_lo;
76
+	time_t acct_session_start;
77
+	int acct_session_started;
78
+	int acct_terminate_cause; /* Acct-Terminate-Cause */
79
+	int acct_interim_interval; /* Acct-Interim-Interval */
80
+
81
+	unsigned long last_rx_bytes;
82
+	unsigned long last_tx_bytes;
83
+	u32 acct_input_gigawords; /* Acct-Input-Gigawords */
84
+	u32 acct_output_gigawords; /* Acct-Output-Gigawords */
85
+
86
+	u8 *challenge; /* IEEE 802.11 Shared Key Authentication Challenge */
87
+
88
+	struct wpa_state_machine *wpa_sm;
89
+	struct rsn_preauth_interface *preauth_iface;
90
+
91
+	struct hostapd_ssid *ssid; /* SSID selection based on (Re)AssocReq */
92
+	struct hostapd_ssid *ssid_probe; /* SSID selection based on ProbeReq */
93
+
94
+	int vlan_id;
95
+
96
+	struct ieee80211_ht_capabilities *ht_capabilities;
97
+
98
+#ifdef CONFIG_IEEE80211W
99
+	int sa_query_count; /* number of pending SA Query requests;
100
+			     * 0 = no SA Query in progress */
101
+	int sa_query_timed_out;
102
+	u8 *sa_query_trans_id; /* buffer of WLAN_SA_QUERY_TR_ID_LEN *
103
+				* sa_query_count octets of pending SA Query
104
+				* transaction identifiers */
105
+	struct os_time sa_query_start;
106
+#endif /* CONFIG_IEEE80211W */
107
+
108
+	struct wpabuf *wps_ie; /* WPS IE from (Re)Association Request */
109
+	struct wpabuf *p2p_ie; /* P2P IE from (Re)Association Request */
110
+};
111
+
112
+
113
+/* Default value for maximum station inactivity. After AP_MAX_INACTIVITY has
114
+ * passed since last received frame from the station, a nullfunc data frame is
115
+ * sent to the station. If this frame is not acknowledged and no other frames
116
+ * have been received, the station will be disassociated after
117
+ * AP_DISASSOC_DELAY seconds. Similarily, the station will be deauthenticated
118
+ * after AP_DEAUTH_DELAY seconds has passed after disassociation. */
119
+#define AP_MAX_INACTIVITY (5 * 60)
120
+#define AP_DISASSOC_DELAY (1)
121
+#define AP_DEAUTH_DELAY (1)
122
+/* Number of seconds to keep STA entry with Authenticated flag after it has
123
+ * been disassociated. */
124
+#define AP_MAX_INACTIVITY_AFTER_DISASSOC (1 * 30)
125
+/* Number of seconds to keep STA entry after it has been deauthenticated. */
126
+#define AP_MAX_INACTIVITY_AFTER_DEAUTH (1 * 5)
127
+
128
+
129
+struct hostapd_data;
130
+
131
+int ap_for_each_sta(struct hostapd_data *hapd,
132
+		    int (*cb)(struct hostapd_data *hapd, struct sta_info *sta,
133
+			      void *ctx),
134
+		    void *ctx);
135
+struct sta_info * ap_get_sta(struct hostapd_data *hapd, const u8 *sta);
136
+void ap_sta_hash_add(struct hostapd_data *hapd, struct sta_info *sta);
137
+void ap_free_sta(struct hostapd_data *hapd, struct sta_info *sta);
138
+void ap_free_sta(struct hostapd_data *hapd, struct sta_info *sta);
139
+void hostapd_free_stas(struct hostapd_data *hapd);
140
+void ap_handle_timer(void *eloop_ctx, void *timeout_ctx);
141
+void ap_sta_session_timeout(struct hostapd_data *hapd, struct sta_info *sta,
142
+			    u32 session_timeout);
143
+void ap_sta_no_session_timeout(struct hostapd_data *hapd,
144
+			       struct sta_info *sta);
145
+struct sta_info * ap_sta_add(struct hostapd_data *hapd, const u8 *addr);
146
+void ap_sta_disassociate(struct hostapd_data *hapd, struct sta_info *sta,
147
+			 u16 reason);
148
+void ap_sta_deauthenticate(struct hostapd_data *hapd, struct sta_info *sta,
149
+			   u16 reason);
150
+int ap_sta_bind_vlan(struct hostapd_data *hapd, struct sta_info *sta,
151
+		     int old_vlanid);
152
+void ap_sta_start_sa_query(struct hostapd_data *hapd, struct sta_info *sta);
153
+void ap_sta_stop_sa_query(struct hostapd_data *hapd, struct sta_info *sta);
154
+int ap_check_sa_query_timeout(struct hostapd_data *hapd, struct sta_info *sta);
155
+void ap_sta_disconnect(struct hostapd_data *hapd, struct sta_info *sta,
156
+		       const u8 *addr, u16 reason);
157
+
158
+void ap_sta_set_authorized(struct hostapd_data *hapd,
159
+			   struct sta_info *sta, int authorized);
160
+static inline int ap_sta_is_authorized(struct sta_info *sta)
161
+{
162
+	return sta->flags & WLAN_STA_AUTHORIZED;
163
+}
164
+
165
+#endif /* STA_INFO_H */

+ 94
- 0
src/ap/tkip_countermeasures.c Näytä tiedosto

@@ -0,0 +1,94 @@
1
+/*
2
+ * hostapd / TKIP countermeasures
3
+ * Copyright (c) 2002-2009, Jouni Malinen <j@w1.fi>
4
+ *
5
+ * This program is free software; you can redistribute it and/or modify
6
+ * it under the terms of the GNU General Public License version 2 as
7
+ * published by the Free Software Foundation.
8
+ *
9
+ * Alternatively, this software may be distributed under the terms of BSD
10
+ * license.
11
+ *
12
+ * See README and COPYING for more details.
13
+ */
14
+
15
+#include "utils/includes.h"
16
+
17
+#include "utils/common.h"
18
+#include "utils/eloop.h"
19
+#include "common/ieee802_11_defs.h"
20
+#include "hostapd.h"
21
+#include "sta_info.h"
22
+#include "ap_mlme.h"
23
+#include "wpa_auth.h"
24
+#include "ap_drv_ops.h"
25
+#include "tkip_countermeasures.h"
26
+
27
+
28
+static void ieee80211_tkip_countermeasures_stop(void *eloop_ctx,
29
+						void *timeout_ctx)
30
+{
31
+	struct hostapd_data *hapd = eloop_ctx;
32
+	hapd->tkip_countermeasures = 0;
33
+	hostapd_drv_set_countermeasures(hapd, 0);
34
+	hostapd_logger(hapd, NULL, HOSTAPD_MODULE_IEEE80211,
35
+		       HOSTAPD_LEVEL_INFO, "TKIP countermeasures ended");
36
+}
37
+
38
+
39
+static void ieee80211_tkip_countermeasures_start(struct hostapd_data *hapd)
40
+{
41
+	struct sta_info *sta;
42
+
43
+	hostapd_logger(hapd, NULL, HOSTAPD_MODULE_IEEE80211,
44
+		       HOSTAPD_LEVEL_INFO, "TKIP countermeasures initiated");
45
+
46
+	wpa_auth_countermeasures_start(hapd->wpa_auth);
47
+	hapd->tkip_countermeasures = 1;
48
+	hostapd_drv_set_countermeasures(hapd, 1);
49
+	wpa_gtk_rekey(hapd->wpa_auth);
50
+	eloop_cancel_timeout(ieee80211_tkip_countermeasures_stop, hapd, NULL);
51
+	eloop_register_timeout(60, 0, ieee80211_tkip_countermeasures_stop,
52
+			       hapd, NULL);
53
+	for (sta = hapd->sta_list; sta != NULL; sta = sta->next) {
54
+		hostapd_drv_sta_deauth(hapd, sta->addr,
55
+				       WLAN_REASON_MICHAEL_MIC_FAILURE);
56
+		ap_sta_set_authorized(hapd, sta, 0);
57
+		sta->flags &= ~(WLAN_STA_AUTH | WLAN_STA_ASSOC);
58
+		hostapd_drv_sta_remove(hapd, sta->addr);
59
+	}
60
+}
61
+
62
+
63
+void michael_mic_failure(struct hostapd_data *hapd, const u8 *addr, int local)
64
+{
65
+	time_t now;
66
+
67
+	if (addr && local) {
68
+		struct sta_info *sta = ap_get_sta(hapd, addr);
69
+		if (sta != NULL) {
70
+			wpa_auth_sta_local_mic_failure_report(sta->wpa_sm);
71
+			hostapd_logger(hapd, addr, HOSTAPD_MODULE_IEEE80211,
72
+				       HOSTAPD_LEVEL_INFO,
73
+				       "Michael MIC failure detected in "
74
+				       "received frame");
75
+			mlme_michaelmicfailure_indication(hapd, addr);
76
+		} else {
77
+			wpa_printf(MSG_DEBUG,
78
+				   "MLME-MICHAELMICFAILURE.indication "
79
+				   "for not associated STA (" MACSTR
80
+				   ") ignored", MAC2STR(addr));
81
+			return;
82
+		}
83
+	}
84
+
85
+	time(&now);
86
+	if (now > hapd->michael_mic_failure + 60) {
87
+		hapd->michael_mic_failures = 1;
88
+	} else {
89
+		hapd->michael_mic_failures++;
90
+		if (hapd->michael_mic_failures > 1)
91
+			ieee80211_tkip_countermeasures_start(hapd);
92
+	}
93
+	hapd->michael_mic_failure = now;
94
+}

+ 20
- 0
src/ap/tkip_countermeasures.h Näytä tiedosto

@@ -0,0 +1,20 @@
1
+/*
2
+ * hostapd / TKIP countermeasures
3
+ * Copyright (c) 2002-2009, Jouni Malinen <j@w1.fi>
4
+ *
5
+ * This program is free software; you can redistribute it and/or modify
6
+ * it under the terms of the GNU General Public License version 2 as
7
+ * published by the Free Software Foundation.
8
+ *
9
+ * Alternatively, this software may be distributed under the terms of BSD
10
+ * license.
11
+ *
12
+ * See README and COPYING for more details.
13
+ */
14
+
15
+#ifndef TKIP_COUNTERMEASURES_H
16
+#define TKIP_COUNTERMEASURES_H
17
+
18
+void michael_mic_failure(struct hostapd_data *hapd, const u8 *addr, int local);
19
+
20
+#endif /* TKIP_COUNTERMEASURES_H */

+ 88
- 0
src/ap/utils.c Näytä tiedosto

@@ -0,0 +1,88 @@
1
+/*
2
+ * AP mode helper functions
3
+ * Copyright (c) 2009, Jouni Malinen <j@w1.fi>
4
+ *
5
+ * This program is free software; you can redistribute it and/or modify
6
+ * it under the terms of the GNU General Public License version 2 as
7
+ * published by the Free Software Foundation.
8
+ *
9
+ * Alternatively, this software may be distributed under the terms of BSD
10
+ * license.
11
+ *
12
+ * See README and COPYING for more details.
13
+ */
14
+
15
+#include "includes.h"
16
+
17
+#include "common.h"
18
+#include "common/ieee802_11_defs.h"
19
+#include "sta_info.h"
20
+#include "hostapd.h"
21
+
22
+
23
+int hostapd_register_probereq_cb(struct hostapd_data *hapd,
24
+				 int (*cb)(void *ctx, const u8 *sa,
25
+					   const u8 *ie, size_t ie_len),
26
+				 void *ctx)
27
+{
28
+	struct hostapd_probereq_cb *n;
29
+
30
+	n = os_realloc(hapd->probereq_cb, (hapd->num_probereq_cb + 1) *
31
+		       sizeof(struct hostapd_probereq_cb));
32
+	if (n == NULL)
33
+		return -1;
34
+
35
+	hapd->probereq_cb = n;
36
+	n = &hapd->probereq_cb[hapd->num_probereq_cb];
37
+	hapd->num_probereq_cb++;
38
+
39
+	n->cb = cb;
40
+	n->ctx = ctx;
41
+
42
+	return 0;
43
+}
44
+
45
+
46
+struct prune_data {
47
+	struct hostapd_data *hapd;
48
+	const u8 *addr;
49
+};
50
+
51
+static int prune_associations(struct hostapd_iface *iface, void *ctx)
52
+{
53
+	struct prune_data *data = ctx;
54
+	struct sta_info *osta;
55
+	struct hostapd_data *ohapd;
56
+	size_t j;
57
+
58
+	for (j = 0; j < iface->num_bss; j++) {
59
+		ohapd = iface->bss[j];
60
+		if (ohapd == data->hapd)
61
+			continue;
62
+		osta = ap_get_sta(ohapd, data->addr);
63
+		if (!osta)
64
+			continue;
65
+
66
+		ap_sta_disassociate(ohapd, osta, WLAN_REASON_UNSPECIFIED);
67
+	}
68
+
69
+	return 0;
70
+}
71
+
72
+/**
73
+ * hostapd_prune_associations - Remove extraneous associations
74
+ * @hapd: Pointer to BSS data for the most recent association
75
+ * @addr: Associated STA address
76
+ *
77
+ * This function looks through all radios and BSS's for previous
78
+ * (stale) associations of STA. If any are found they are removed.
79
+ */
80
+void hostapd_prune_associations(struct hostapd_data *hapd, const u8 *addr)
81
+{
82
+	struct prune_data data;
83
+	data.hapd = hapd;
84
+	data.addr = addr;
85
+	if (hapd->iface->for_each_interface)
86
+		hapd->iface->for_each_interface(hapd->iface->interfaces,
87
+						prune_associations, &data);
88
+}

+ 905
- 0
src/ap/vlan_init.c Näytä tiedosto

@@ -0,0 +1,905 @@
1
+/*
2
+ * hostapd / VLAN initialization
3
+ * Copyright 2003, Instant802 Networks, Inc.
4
+ * Copyright 2005-2006, Devicescape Software, Inc.
5
+ * Copyright (c) 2009, Jouni Malinen <j@w1.fi>
6
+ *
7
+ * This program is free software; you can redistribute it and/or modify
8
+ * it under the terms of the GNU General Public License version 2 as
9
+ * published by the Free Software Foundation.
10
+ *
11
+ * Alternatively, this software may be distributed under the terms of BSD
12
+ * license.
13
+ *
14
+ * See README and COPYING for more details.
15
+ */
16
+
17
+#include "utils/includes.h"
18
+
19
+#include "utils/common.h"
20
+#include "hostapd.h"
21
+#include "ap_config.h"
22
+#include "ap_drv_ops.h"
23
+#include "vlan_init.h"
24
+
25
+
26
+#ifdef CONFIG_FULL_DYNAMIC_VLAN
27
+
28
+#include <net/if.h>
29
+#include <sys/ioctl.h>
30
+#include <linux/sockios.h>
31
+#include <linux/if_vlan.h>
32
+#include <linux/if_bridge.h>
33
+
34
+#include "drivers/priv_netlink.h"
35
+#include "utils/eloop.h"
36
+
37
+
38
+struct full_dynamic_vlan {
39
+	int s; /* socket on which to listen for new/removed interfaces. */
40
+};
41
+
42
+
43
+static int ifconfig_helper(const char *if_name, int up)
44
+{
45
+	int fd;
46
+	struct ifreq ifr;
47
+
48
+	if ((fd = socket(AF_INET, SOCK_STREAM, 0)) < 0) {
49
+		wpa_printf(MSG_ERROR, "VLAN: %s: socket(AF_INET,SOCK_STREAM) "
50
+			   "failed: %s", __func__, strerror(errno));
51
+		return -1;
52
+	}
53
+
54
+	os_memset(&ifr, 0, sizeof(ifr));
55
+	os_strlcpy(ifr.ifr_name, if_name, IFNAMSIZ);
56
+
57
+	if (ioctl(fd, SIOCGIFFLAGS, &ifr) != 0) {
58
+		wpa_printf(MSG_ERROR, "VLAN: %s: ioctl(SIOCGIFFLAGS) failed "
59
+			   "for interface %s: %s",
60
+			   __func__, if_name, strerror(errno));
61
+		close(fd);
62
+		return -1;
63
+	}
64
+
65
+	if (up)
66
+		ifr.ifr_flags |= IFF_UP;
67
+	else
68
+		ifr.ifr_flags &= ~IFF_UP;
69
+
70
+	if (ioctl(fd, SIOCSIFFLAGS, &ifr) != 0) {
71
+		wpa_printf(MSG_ERROR, "VLAN: %s: ioctl(SIOCSIFFLAGS) failed "
72
+			   "for interface %s (up=%d): %s",
73
+			   __func__, if_name, up, strerror(errno));
74
+		close(fd);
75
+		return -1;
76
+	}
77
+
78
+	close(fd);
79
+	return 0;
80
+}
81
+
82
+
83
+static int ifconfig_up(const char *if_name)
84
+{
85
+	wpa_printf(MSG_DEBUG, "VLAN: Set interface %s up", if_name);
86
+	return ifconfig_helper(if_name, 1);
87
+}
88
+
89
+
90
+static int ifconfig_down(const char *if_name)
91
+{
92
+	wpa_printf(MSG_DEBUG, "VLAN: Set interface %s down", if_name);
93
+	return ifconfig_helper(if_name, 0);
94
+}
95
+
96
+
97
+/*
98
+ * These are only available in recent linux headers (without the leading
99
+ * underscore).
100
+ */
101
+#define _GET_VLAN_REALDEV_NAME_CMD	8
102
+#define _GET_VLAN_VID_CMD		9
103
+
104
+/* This value should be 256 ONLY. If it is something else, then hostapd
105
+ * might crash!, as this value has been hard-coded in 2.4.x kernel
106
+ * bridging code.
107
+ */
108
+#define MAX_BR_PORTS      		256
109
+
110
+static int br_delif(const char *br_name, const char *if_name)
111
+{
112
+	int fd;
113
+	struct ifreq ifr;
114
+	unsigned long args[2];
115
+	int if_index;
116
+
117
+	wpa_printf(MSG_DEBUG, "VLAN: br_delif(%s, %s)", br_name, if_name);
118
+	if ((fd = socket(AF_INET, SOCK_STREAM, 0)) < 0) {
119
+		wpa_printf(MSG_ERROR, "VLAN: %s: socket(AF_INET,SOCK_STREAM) "
120
+			   "failed: %s", __func__, strerror(errno));
121
+		return -1;
122
+	}
123
+
124
+	if_index = if_nametoindex(if_name);
125
+
126
+	if (if_index == 0) {
127
+		wpa_printf(MSG_ERROR, "VLAN: %s: Failure determining "
128
+			   "interface index for '%s'",
129
+			   __func__, if_name);
130
+		close(fd);
131
+		return -1;
132
+	}
133
+
134
+	args[0] = BRCTL_DEL_IF;
135
+	args[1] = if_index;
136
+
137
+	os_strlcpy(ifr.ifr_name, br_name, sizeof(ifr.ifr_name));
138
+	ifr.ifr_data = (__caddr_t) args;
139
+
140
+	if (ioctl(fd, SIOCDEVPRIVATE, &ifr) < 0 && errno != EINVAL) {
141
+		/* No error if interface already removed. */
142
+		wpa_printf(MSG_ERROR, "VLAN: %s: ioctl[SIOCDEVPRIVATE,"
143
+			   "BRCTL_DEL_IF] failed for br_name=%s if_name=%s: "
144
+			   "%s", __func__, br_name, if_name, strerror(errno));
145
+		close(fd);
146
+		return -1;
147
+	}
148
+
149
+	close(fd);
150
+	return 0;
151
+}
152
+
153
+
154
+/*
155
+	Add interface 'if_name' to the bridge 'br_name'
156
+
157
+	returns -1 on error
158
+	returns 1 if the interface is already part of the bridge
159
+	returns 0 otherwise
160
+*/
161
+static int br_addif(const char *br_name, const char *if_name)
162
+{
163
+	int fd;
164
+	struct ifreq ifr;
165
+	unsigned long args[2];
166
+	int if_index;
167
+
168
+	wpa_printf(MSG_DEBUG, "VLAN: br_addif(%s, %s)", br_name, if_name);
169
+	if ((fd = socket(AF_INET, SOCK_STREAM, 0)) < 0) {
170
+		wpa_printf(MSG_ERROR, "VLAN: %s: socket(AF_INET,SOCK_STREAM) "
171
+			   "failed: %s", __func__, strerror(errno));
172
+		return -1;
173
+	}
174
+
175
+	if_index = if_nametoindex(if_name);
176
+
177
+	if (if_index == 0) {
178
+		wpa_printf(MSG_ERROR, "VLAN: %s: Failure determining "
179
+			   "interface index for '%s'",
180
+			   __func__, if_name);
181
+		close(fd);
182
+		return -1;
183
+	}
184
+
185
+	args[0] = BRCTL_ADD_IF;
186
+	args[1] = if_index;
187
+
188
+	os_strlcpy(ifr.ifr_name, br_name, sizeof(ifr.ifr_name));
189
+	ifr.ifr_data = (__caddr_t) args;
190
+
191
+	if (ioctl(fd, SIOCDEVPRIVATE, &ifr) < 0) {
192
+		if (errno == EBUSY) {
193
+			/* The interface is already added. */
194
+			close(fd);
195
+			return 1;
196
+		}
197
+
198
+		wpa_printf(MSG_ERROR, "VLAN: %s: ioctl[SIOCDEVPRIVATE,"
199
+			   "BRCTL_ADD_IF] failed for br_name=%s if_name=%s: "
200
+			   "%s", __func__, br_name, if_name, strerror(errno));
201
+		close(fd);
202
+		return -1;
203
+	}
204
+
205
+	close(fd);
206
+	return 0;
207
+}
208
+
209
+
210
+static int br_delbr(const char *br_name)
211
+{
212
+	int fd;
213
+	unsigned long arg[2];
214
+
215
+	wpa_printf(MSG_DEBUG, "VLAN: br_delbr(%s)", br_name);
216
+	if ((fd = socket(AF_INET, SOCK_STREAM, 0)) < 0) {
217
+		wpa_printf(MSG_ERROR, "VLAN: %s: socket(AF_INET,SOCK_STREAM) "
218
+			   "failed: %s", __func__, strerror(errno));
219
+		return -1;
220
+	}
221
+
222
+	arg[0] = BRCTL_DEL_BRIDGE;
223
+	arg[1] = (unsigned long) br_name;
224
+
225
+	if (ioctl(fd, SIOCGIFBR, arg) < 0 && errno != ENXIO) {
226
+		/* No error if bridge already removed. */
227
+		wpa_printf(MSG_ERROR, "VLAN: %s: BRCTL_DEL_BRIDGE failed for "
228
+			   "%s: %s", __func__, br_name, strerror(errno));
229
+		close(fd);
230
+		return -1;
231
+	}
232
+
233
+	close(fd);
234
+	return 0;
235
+}
236
+
237
+
238
+/*
239
+	Add a bridge with the name 'br_name'.
240
+
241
+	returns -1 on error
242
+	returns 1 if the bridge already exists
243
+	returns 0 otherwise
244
+*/
245
+static int br_addbr(const char *br_name)
246
+{
247
+	int fd;
248
+	unsigned long arg[4];
249
+	struct ifreq ifr;
250
+
251
+	wpa_printf(MSG_DEBUG, "VLAN: br_addbr(%s)", br_name);
252
+	if ((fd = socket(AF_INET, SOCK_STREAM, 0)) < 0) {
253
+		wpa_printf(MSG_ERROR, "VLAN: %s: socket(AF_INET,SOCK_STREAM) "
254
+			   "failed: %s", __func__, strerror(errno));
255
+		return -1;
256
+	}
257
+
258
+	arg[0] = BRCTL_ADD_BRIDGE;
259
+	arg[1] = (unsigned long) br_name;
260
+
261
+	if (ioctl(fd, SIOCGIFBR, arg) < 0) {
262
+ 		if (errno == EEXIST) {
263
+			/* The bridge is already added. */
264
+			close(fd);
265
+			return 1;
266
+		} else {
267
+			wpa_printf(MSG_ERROR, "VLAN: %s: BRCTL_ADD_BRIDGE "
268
+				   "failed for %s: %s",
269
+				   __func__, br_name, strerror(errno));
270
+			close(fd);
271
+			return -1;
272
+		}
273
+	}
274
+
275
+	/* Decrease forwarding delay to avoid EAPOL timeouts. */
276
+	os_memset(&ifr, 0, sizeof(ifr));
277
+	os_strlcpy(ifr.ifr_name, br_name, IFNAMSIZ);
278
+	arg[0] = BRCTL_SET_BRIDGE_FORWARD_DELAY;
279
+	arg[1] = 1;
280
+	arg[2] = 0;
281
+	arg[3] = 0;
282
+	ifr.ifr_data = (char *) &arg;
283
+	if (ioctl(fd, SIOCDEVPRIVATE, &ifr) < 0) {
284
+		wpa_printf(MSG_ERROR, "VLAN: %s: "
285
+			   "BRCTL_SET_BRIDGE_FORWARD_DELAY (1 sec) failed for "
286
+			   "%s: %s", __func__, br_name, strerror(errno));
287
+		/* Continue anyway */
288
+	}
289
+
290
+	close(fd);
291
+	return 0;
292
+}
293
+
294
+
295
+static int br_getnumports(const char *br_name)
296
+{
297
+	int fd;
298
+	int i;
299
+	int port_cnt = 0;
300
+	unsigned long arg[4];
301
+	int ifindices[MAX_BR_PORTS];
302
+	struct ifreq ifr;
303
+
304
+	if ((fd = socket(AF_INET, SOCK_STREAM, 0)) < 0) {
305
+		wpa_printf(MSG_ERROR, "VLAN: %s: socket(AF_INET,SOCK_STREAM) "
306
+			   "failed: %s", __func__, strerror(errno));
307
+		return -1;
308
+	}
309
+
310
+	arg[0] = BRCTL_GET_PORT_LIST;
311
+	arg[1] = (unsigned long) ifindices;
312
+	arg[2] = MAX_BR_PORTS;
313
+	arg[3] = 0;
314
+
315
+	os_memset(ifindices, 0, sizeof(ifindices));
316
+	os_strlcpy(ifr.ifr_name, br_name, sizeof(ifr.ifr_name));
317
+	ifr.ifr_data = (__caddr_t) arg;
318
+
319
+	if (ioctl(fd, SIOCDEVPRIVATE, &ifr) < 0) {
320
+		wpa_printf(MSG_ERROR, "VLAN: %s: BRCTL_GET_PORT_LIST "
321
+			   "failed for %s: %s",
322
+			   __func__, br_name, strerror(errno));
323
+		close(fd);
324
+		return -1;
325
+	}
326
+
327
+	for (i = 1; i < MAX_BR_PORTS; i++) {
328
+		if (ifindices[i] > 0) {
329
+			port_cnt++;
330
+		}
331
+	}
332
+
333
+	close(fd);
334
+	return port_cnt;
335
+}
336
+
337
+
338
+static int vlan_rem(const char *if_name)
339
+{
340
+	int fd;
341
+	struct vlan_ioctl_args if_request;
342
+
343
+	wpa_printf(MSG_DEBUG, "VLAN: vlan_rem(%s)", if_name);
344
+	if ((os_strlen(if_name) + 1) > sizeof(if_request.device1)) {
345
+		wpa_printf(MSG_ERROR, "VLAN: Interface name too long: '%s'",
346
+			   if_name);
347
+		return -1;
348
+	}
349
+
350
+	if ((fd = socket(AF_INET, SOCK_STREAM, 0)) < 0) {
351
+		wpa_printf(MSG_ERROR, "VLAN: %s: socket(AF_INET,SOCK_STREAM) "
352
+			   "failed: %s", __func__, strerror(errno));
353
+		return -1;
354
+	}
355
+
356
+	os_memset(&if_request, 0, sizeof(if_request));
357
+
358
+	os_strlcpy(if_request.device1, if_name, sizeof(if_request.device1));
359
+	if_request.cmd = DEL_VLAN_CMD;
360
+
361
+	if (ioctl(fd, SIOCSIFVLAN, &if_request) < 0) {
362
+		wpa_printf(MSG_ERROR, "VLAN: %s: DEL_VLAN_CMD failed for %s: "
363
+			   "%s", __func__, if_name, strerror(errno));
364
+		close(fd);
365
+		return -1;
366
+	}
367
+
368
+	close(fd);
369
+	return 0;
370
+}
371
+
372
+
373
+/*
374
+	Add a vlan interface with VLAN ID 'vid' and tagged interface
375
+	'if_name'.
376
+
377
+	returns -1 on error
378
+	returns 1 if the interface already exists
379
+	returns 0 otherwise
380
+*/
381
+static int vlan_add(const char *if_name, int vid)
382
+{
383
+	int fd;
384
+	struct vlan_ioctl_args if_request;
385
+
386
+	wpa_printf(MSG_DEBUG, "VLAN: vlan_add(if_name=%s, vid=%d)",
387
+		   if_name, vid);
388
+	ifconfig_up(if_name);
389
+
390
+	if ((os_strlen(if_name) + 1) > sizeof(if_request.device1)) {
391
+		wpa_printf(MSG_ERROR, "VLAN: Interface name too long: '%s'",
392
+			   if_name);
393
+		return -1;
394
+	}
395
+
396
+	if ((fd = socket(AF_INET, SOCK_STREAM, 0)) < 0) {
397
+		wpa_printf(MSG_ERROR, "VLAN: %s: socket(AF_INET,SOCK_STREAM) "
398
+			   "failed: %s", __func__, strerror(errno));
399
+		return -1;
400
+	}
401
+
402
+	os_memset(&if_request, 0, sizeof(if_request));
403
+
404
+	/* Determine if a suitable vlan device already exists. */
405
+
406
+	os_snprintf(if_request.device1, sizeof(if_request.device1), "vlan%d",
407
+		    vid);
408
+
409
+	if_request.cmd = _GET_VLAN_VID_CMD;
410
+
411
+	if (ioctl(fd, SIOCSIFVLAN, &if_request) == 0) {
412
+
413
+		if (if_request.u.VID == vid) {
414
+			if_request.cmd = _GET_VLAN_REALDEV_NAME_CMD;
415
+
416
+			if (ioctl(fd, SIOCSIFVLAN, &if_request) == 0 &&
417
+			    os_strncmp(if_request.u.device2, if_name,
418
+				       sizeof(if_request.u.device2)) == 0) {
419
+				close(fd);
420
+				wpa_printf(MSG_DEBUG, "VLAN: vlan_add: "
421
+					   "if_name %s exists already",
422
+					   if_request.device1);
423
+				return 1;
424
+			}
425
+		}
426
+	}
427
+
428
+	/* A suitable vlan device does not already exist, add one. */
429
+
430
+	os_memset(&if_request, 0, sizeof(if_request));
431
+	os_strlcpy(if_request.device1, if_name, sizeof(if_request.device1));
432
+	if_request.u.VID = vid;
433
+	if_request.cmd = ADD_VLAN_CMD;
434
+
435
+	if (ioctl(fd, SIOCSIFVLAN, &if_request) < 0) {
436
+		wpa_printf(MSG_ERROR, "VLAN: %s: ADD_VLAN_CMD failed for %s: "
437
+			   "%s",
438
+			   __func__, if_request.device1, strerror(errno));
439
+		close(fd);
440
+		return -1;
441
+	}
442
+
443
+	close(fd);
444
+	return 0;
445
+}
446
+
447
+
448
+static int vlan_set_name_type(unsigned int name_type)
449
+{
450
+	int fd;
451
+	struct vlan_ioctl_args if_request;
452
+
453
+	wpa_printf(MSG_DEBUG, "VLAN: vlan_set_name_type(name_type=%u)",
454
+		   name_type);
455
+	if ((fd = socket(AF_INET, SOCK_STREAM, 0)) < 0) {
456
+		wpa_printf(MSG_ERROR, "VLAN: %s: socket(AF_INET,SOCK_STREAM) "
457
+			   "failed: %s", __func__, strerror(errno));
458
+		return -1;
459
+	}
460
+
461
+	os_memset(&if_request, 0, sizeof(if_request));
462
+
463
+	if_request.u.name_type = name_type;
464
+	if_request.cmd = SET_VLAN_NAME_TYPE_CMD;
465
+	if (ioctl(fd, SIOCSIFVLAN, &if_request) < 0) {
466
+		wpa_printf(MSG_ERROR, "VLAN: %s: SET_VLAN_NAME_TYPE_CMD "
467
+			   "name_type=%u failed: %s",
468
+			   __func__, name_type, strerror(errno));
469
+		close(fd);
470
+		return -1;
471
+	}
472
+
473
+	close(fd);
474
+	return 0;
475
+}
476
+
477
+
478
+static void vlan_newlink(char *ifname, struct hostapd_data *hapd)
479
+{
480
+	char vlan_ifname[IFNAMSIZ];
481
+	char br_name[IFNAMSIZ];
482
+	struct hostapd_vlan *vlan = hapd->conf->vlan;
483
+	char *tagged_interface = hapd->conf->ssid.vlan_tagged_interface;
484
+
485
+	wpa_printf(MSG_DEBUG, "VLAN: vlan_newlink(%s)", ifname);
486
+
487
+	while (vlan) {
488
+		if (os_strcmp(ifname, vlan->ifname) == 0) {
489
+
490
+			os_snprintf(br_name, sizeof(br_name), "brvlan%d",
491
+				    vlan->vlan_id);
492
+
493
+			if (!br_addbr(br_name))
494
+				vlan->clean |= DVLAN_CLEAN_BR;
495
+
496
+			ifconfig_up(br_name);
497
+
498
+			if (tagged_interface) {
499
+
500
+				if (!vlan_add(tagged_interface, vlan->vlan_id))
501
+					vlan->clean |= DVLAN_CLEAN_VLAN;
502
+
503
+				os_snprintf(vlan_ifname, sizeof(vlan_ifname),
504
+					    "vlan%d", vlan->vlan_id);
505
+
506
+				if (!br_addif(br_name, vlan_ifname))
507
+					vlan->clean |= DVLAN_CLEAN_VLAN_PORT;
508
+
509
+				ifconfig_up(vlan_ifname);
510
+			}
511
+
512
+			if (!br_addif(br_name, ifname))
513
+				vlan->clean |= DVLAN_CLEAN_WLAN_PORT;
514
+
515
+			ifconfig_up(ifname);
516
+
517
+			break;
518
+		}
519
+		vlan = vlan->next;
520
+	}
521
+}
522
+
523
+
524
+static void vlan_dellink(char *ifname, struct hostapd_data *hapd)
525
+{
526
+	char vlan_ifname[IFNAMSIZ];
527
+	char br_name[IFNAMSIZ];
528
+	struct hostapd_vlan *first, *prev, *vlan = hapd->conf->vlan;
529
+	char *tagged_interface = hapd->conf->ssid.vlan_tagged_interface;
530
+
531
+	wpa_printf(MSG_DEBUG, "VLAN: vlan_dellink(%s)", ifname);
532
+
533
+	first = prev = vlan;
534
+
535
+	while (vlan) {
536
+		if (os_strcmp(ifname, vlan->ifname) == 0) {
537
+			os_snprintf(br_name, sizeof(br_name), "brvlan%d",
538
+				    vlan->vlan_id);
539
+
540
+			if (vlan->clean & DVLAN_CLEAN_WLAN_PORT)
541
+				br_delif(br_name, vlan->ifname);
542
+
543
+			if (tagged_interface) {
544
+				os_snprintf(vlan_ifname, sizeof(vlan_ifname),
545
+					    "vlan%d", vlan->vlan_id);
546
+				if (vlan->clean & DVLAN_CLEAN_VLAN_PORT)
547
+					br_delif(br_name, vlan_ifname);
548
+				ifconfig_down(vlan_ifname);
549
+
550
+				if (vlan->clean & DVLAN_CLEAN_VLAN)
551
+					vlan_rem(vlan_ifname);
552
+			}
553
+
554
+			if ((vlan->clean & DVLAN_CLEAN_BR) &&
555
+			    br_getnumports(br_name) == 0) {
556
+				ifconfig_down(br_name);
557
+				br_delbr(br_name);
558
+			}
559
+
560
+			if (vlan == first) {
561
+				hapd->conf->vlan = vlan->next;
562
+			} else {
563
+				prev->next = vlan->next;
564
+			}
565
+			os_free(vlan);
566
+
567
+			break;
568
+		}
569
+		prev = vlan;
570
+		vlan = vlan->next;
571
+	}
572
+}
573
+
574
+
575
+static void
576
+vlan_read_ifnames(struct nlmsghdr *h, size_t len, int del,
577
+		  struct hostapd_data *hapd)
578
+{
579
+	struct ifinfomsg *ifi;
580
+	int attrlen, nlmsg_len, rta_len;
581
+	struct rtattr *attr;
582
+
583
+	if (len < sizeof(*ifi))
584
+		return;
585
+
586
+	ifi = NLMSG_DATA(h);
587
+
588
+	nlmsg_len = NLMSG_ALIGN(sizeof(struct ifinfomsg));
589
+
590
+	attrlen = h->nlmsg_len - nlmsg_len;
591
+	if (attrlen < 0)
592
+		return;
593
+
594
+	attr = (struct rtattr *) (((char *) ifi) + nlmsg_len);
595
+
596
+	rta_len = RTA_ALIGN(sizeof(struct rtattr));
597
+	while (RTA_OK(attr, attrlen)) {
598
+		char ifname[IFNAMSIZ + 1];
599
+
600
+		if (attr->rta_type == IFLA_IFNAME) {
601
+			int n = attr->rta_len - rta_len;
602
+			if (n < 0)
603
+				break;
604
+
605
+			os_memset(ifname, 0, sizeof(ifname));
606
+
607
+			if ((size_t) n > sizeof(ifname))
608
+				n = sizeof(ifname);
609
+			os_memcpy(ifname, ((char *) attr) + rta_len, n);
610
+
611
+			if (del)
612
+				vlan_dellink(ifname, hapd);
613
+			else
614
+				vlan_newlink(ifname, hapd);
615
+		}
616
+
617
+		attr = RTA_NEXT(attr, attrlen);
618
+	}
619
+}
620
+
621
+
622
+static void vlan_event_receive(int sock, void *eloop_ctx, void *sock_ctx)
623
+{
624
+	char buf[8192];
625
+	int left;
626
+	struct sockaddr_nl from;
627
+	socklen_t fromlen;
628
+	struct nlmsghdr *h;
629
+	struct hostapd_data *hapd = eloop_ctx;
630
+
631
+	fromlen = sizeof(from);
632
+	left = recvfrom(sock, buf, sizeof(buf), MSG_DONTWAIT,
633
+			(struct sockaddr *) &from, &fromlen);
634
+	if (left < 0) {
635
+		if (errno != EINTR && errno != EAGAIN)
636
+			wpa_printf(MSG_ERROR, "VLAN: %s: recvfrom failed: %s",
637
+				   __func__, strerror(errno));
638
+		return;
639
+	}
640
+
641
+	h = (struct nlmsghdr *) buf;
642
+	while (left >= (int) sizeof(*h)) {
643
+		int len, plen;
644
+
645
+		len = h->nlmsg_len;
646
+		plen = len - sizeof(*h);
647
+		if (len > left || plen < 0) {
648
+			wpa_printf(MSG_DEBUG, "VLAN: Malformed netlink "
649
+				   "message: len=%d left=%d plen=%d",
650
+				   len, left, plen);
651
+			break;
652
+		}
653
+
654
+		switch (h->nlmsg_type) {
655
+		case RTM_NEWLINK:
656
+			vlan_read_ifnames(h, plen, 0, hapd);
657
+			break;
658
+		case RTM_DELLINK:
659
+			vlan_read_ifnames(h, plen, 1, hapd);
660
+			break;
661
+		}
662
+
663
+		len = NLMSG_ALIGN(len);
664
+		left -= len;
665
+		h = (struct nlmsghdr *) ((char *) h + len);
666
+	}
667
+
668
+	if (left > 0) {
669
+		wpa_printf(MSG_DEBUG, "VLAN: %s: %d extra bytes in the end of "
670
+			   "netlink message", __func__, left);
671
+	}
672
+}
673
+
674
+
675
+static struct full_dynamic_vlan *
676
+full_dynamic_vlan_init(struct hostapd_data *hapd)
677
+{
678
+	struct sockaddr_nl local;
679
+	struct full_dynamic_vlan *priv;
680
+
681
+	priv = os_zalloc(sizeof(*priv));
682
+	if (priv == NULL)
683
+		return NULL;
684
+
685
+	vlan_set_name_type(VLAN_NAME_TYPE_PLUS_VID_NO_PAD);
686
+
687
+	priv->s = socket(PF_NETLINK, SOCK_RAW, NETLINK_ROUTE);
688
+	if (priv->s < 0) {
689
+		wpa_printf(MSG_ERROR, "VLAN: %s: socket(PF_NETLINK,SOCK_RAW,"
690
+			   "NETLINK_ROUTE) failed: %s",
691
+			   __func__, strerror(errno));
692
+		os_free(priv);
693
+		return NULL;
694
+	}
695
+
696
+	os_memset(&local, 0, sizeof(local));
697
+	local.nl_family = AF_NETLINK;
698
+	local.nl_groups = RTMGRP_LINK;
699
+	if (bind(priv->s, (struct sockaddr *) &local, sizeof(local)) < 0) {
700
+		wpa_printf(MSG_ERROR, "VLAN: %s: bind(netlink) failed: %s",
701
+			   __func__, strerror(errno));
702
+		close(priv->s);
703
+		os_free(priv);
704
+		return NULL;
705
+	}
706
+
707
+	if (eloop_register_read_sock(priv->s, vlan_event_receive, hapd, NULL))
708
+	{
709
+		close(priv->s);
710
+		os_free(priv);
711
+		return NULL;
712
+	}
713
+
714
+	return priv;
715
+}
716
+
717
+
718
+static void full_dynamic_vlan_deinit(struct full_dynamic_vlan *priv)
719
+{
720
+	if (priv == NULL)
721
+		return;
722
+	eloop_unregister_read_sock(priv->s);
723
+	close(priv->s);
724
+	os_free(priv);
725
+}
726
+#endif /* CONFIG_FULL_DYNAMIC_VLAN */
727
+
728
+
729
+int vlan_setup_encryption_dyn(struct hostapd_data *hapd,
730
+			      struct hostapd_ssid *mssid, const char *dyn_vlan)
731
+{
732
+        int i;
733
+
734
+        if (dyn_vlan == NULL)
735
+		return 0;
736
+
737
+	/* Static WEP keys are set here; IEEE 802.1X and WPA uses their own
738
+	 * functions for setting up dynamic broadcast keys. */
739
+	for (i = 0; i < 4; i++) {
740
+		if (mssid->wep.key[i] &&
741
+		    hostapd_drv_set_key(dyn_vlan, hapd, WPA_ALG_WEP, NULL, i,
742
+					i == mssid->wep.idx, NULL, 0,
743
+					mssid->wep.key[i], mssid->wep.len[i]))
744
+		{
745
+			wpa_printf(MSG_ERROR, "VLAN: Could not set WEP "
746
+				   "encryption for dynamic VLAN");
747
+			return -1;
748
+		}
749
+	}
750
+
751
+	return 0;
752
+}
753
+
754
+
755
+static int vlan_dynamic_add(struct hostapd_data *hapd,
756
+			    struct hostapd_vlan *vlan)
757
+{
758
+	while (vlan) {
759
+		if (vlan->vlan_id != VLAN_ID_WILDCARD) {
760
+			if (hostapd_vlan_if_add(hapd, vlan->ifname)) {
761
+				if (errno != EEXIST) {
762
+					wpa_printf(MSG_ERROR, "VLAN: Could "
763
+						   "not add VLAN %s: %s",
764
+						   vlan->ifname,
765
+						   strerror(errno));
766
+					return -1;
767
+				}
768
+			}
769
+#ifdef CONFIG_FULL_DYNAMIC_VLAN
770
+			ifconfig_up(vlan->ifname);
771
+#endif /* CONFIG_FULL_DYNAMIC_VLAN */
772
+		}
773
+
774
+		vlan = vlan->next;
775
+	}
776
+
777
+	return 0;
778
+}
779
+
780
+
781
+static void vlan_dynamic_remove(struct hostapd_data *hapd,
782
+				struct hostapd_vlan *vlan)
783
+{
784
+	struct hostapd_vlan *next;
785
+
786
+	while (vlan) {
787
+		next = vlan->next;
788
+
789
+		if (vlan->vlan_id != VLAN_ID_WILDCARD &&
790
+		    hostapd_vlan_if_remove(hapd, vlan->ifname)) {
791
+			wpa_printf(MSG_ERROR, "VLAN: Could not remove VLAN "
792
+				   "iface: %s: %s",
793
+				   vlan->ifname, strerror(errno));
794
+		}
795
+#ifdef CONFIG_FULL_DYNAMIC_VLAN
796
+		if (vlan->clean)
797
+			vlan_dellink(vlan->ifname, hapd);
798
+#endif /* CONFIG_FULL_DYNAMIC_VLAN */
799
+
800
+		vlan = next;
801
+	}
802
+}
803
+
804
+
805
+int vlan_init(struct hostapd_data *hapd)
806
+{
807
+#ifdef CONFIG_FULL_DYNAMIC_VLAN
808
+	hapd->full_dynamic_vlan = full_dynamic_vlan_init(hapd);
809
+#endif /* CONFIG_FULL_DYNAMIC_VLAN */
810
+
811
+	if (vlan_dynamic_add(hapd, hapd->conf->vlan))
812
+		return -1;
813
+
814
+        return 0;
815
+}
816
+
817
+
818
+void vlan_deinit(struct hostapd_data *hapd)
819
+{
820
+	vlan_dynamic_remove(hapd, hapd->conf->vlan);
821
+
822
+#ifdef CONFIG_FULL_DYNAMIC_VLAN
823
+	full_dynamic_vlan_deinit(hapd->full_dynamic_vlan);
824
+#endif /* CONFIG_FULL_DYNAMIC_VLAN */
825
+}
826
+
827
+
828
+struct hostapd_vlan * vlan_add_dynamic(struct hostapd_data *hapd,
829
+				       struct hostapd_vlan *vlan,
830
+				       int vlan_id)
831
+{
832
+	struct hostapd_vlan *n;
833
+	char *ifname, *pos;
834
+
835
+	if (vlan == NULL || vlan_id <= 0 || vlan_id > MAX_VLAN_ID ||
836
+	    vlan->vlan_id != VLAN_ID_WILDCARD)
837
+		return NULL;
838
+
839
+	wpa_printf(MSG_DEBUG, "VLAN: %s(vlan_id=%d ifname=%s)",
840
+		   __func__, vlan_id, vlan->ifname);
841
+	ifname = os_strdup(vlan->ifname);
842
+	if (ifname == NULL)
843
+		return NULL;
844
+	pos = os_strchr(ifname, '#');
845
+	if (pos == NULL) {
846
+		os_free(ifname);
847
+		return NULL;
848
+	}
849
+	*pos++ = '\0';
850
+
851
+	n = os_zalloc(sizeof(*n));
852
+	if (n == NULL) {
853
+		os_free(ifname);
854
+		return NULL;
855
+	}
856
+
857
+	n->vlan_id = vlan_id;
858
+	n->dynamic_vlan = 1;
859
+
860
+	os_snprintf(n->ifname, sizeof(n->ifname), "%s%d%s", ifname, vlan_id,
861
+		    pos);
862
+	os_free(ifname);
863
+
864
+	if (hostapd_vlan_if_add(hapd, n->ifname)) {
865
+		os_free(n);
866
+		return NULL;
867
+	}
868
+
869
+	n->next = hapd->conf->vlan;
870
+	hapd->conf->vlan = n;
871
+
872
+#ifdef CONFIG_FULL_DYNAMIC_VLAN
873
+	ifconfig_up(n->ifname);
874
+#endif /* CONFIG_FULL_DYNAMIC_VLAN */
875
+
876
+	return n;
877
+}
878
+
879
+
880
+int vlan_remove_dynamic(struct hostapd_data *hapd, int vlan_id)
881
+{
882
+	struct hostapd_vlan *vlan;
883
+
884
+	if (vlan_id <= 0 || vlan_id > MAX_VLAN_ID)
885
+		return 1;
886
+
887
+	wpa_printf(MSG_DEBUG, "VLAN: %s(vlan_id=%d)", __func__, vlan_id);
888
+
889
+	vlan = hapd->conf->vlan;
890
+	while (vlan) {
891
+		if (vlan->vlan_id == vlan_id && vlan->dynamic_vlan > 0) {
892
+			vlan->dynamic_vlan--;
893
+			break;
894
+		}
895
+		vlan = vlan->next;
896
+	}
897
+
898
+	if (vlan == NULL)
899
+		return 1;
900
+
901
+	if (vlan->dynamic_vlan == 0)
902
+		hostapd_vlan_if_remove(hapd, vlan->ifname);
903
+
904
+	return 0;
905
+}

+ 59
- 0
src/ap/vlan_init.h Näytä tiedosto

@@ -0,0 +1,59 @@
1
+/*
2
+ * hostapd / VLAN initialization
3
+ * Copyright 2003, Instant802 Networks, Inc.
4
+ * Copyright 2005, Devicescape Software, Inc.
5
+ *
6
+ * This program is free software; you can redistribute it and/or modify
7
+ * it under the terms of the GNU General Public License version 2 as
8
+ * published by the Free Software Foundation.
9
+ *
10
+ * Alternatively, this software may be distributed under the terms of BSD
11
+ * license.
12
+ *
13
+ * See README and COPYING for more details.
14
+ */
15
+
16
+#ifndef VLAN_INIT_H
17
+#define VLAN_INIT_H
18
+
19
+#ifndef CONFIG_NO_VLAN
20
+int vlan_init(struct hostapd_data *hapd);
21
+void vlan_deinit(struct hostapd_data *hapd);
22
+struct hostapd_vlan * vlan_add_dynamic(struct hostapd_data *hapd,
23
+				       struct hostapd_vlan *vlan,
24
+				       int vlan_id);
25
+int vlan_remove_dynamic(struct hostapd_data *hapd, int vlan_id);
26
+int vlan_setup_encryption_dyn(struct hostapd_data *hapd,
27
+			      struct hostapd_ssid *mssid,
28
+			      const char *dyn_vlan);
29
+#else /* CONFIG_NO_VLAN */
30
+static inline int vlan_init(struct hostapd_data *hapd)
31
+{
32
+	return 0;
33
+}
34
+
35
+static inline void vlan_deinit(struct hostapd_data *hapd)
36
+{
37
+}
38
+
39
+static inline struct hostapd_vlan * vlan_add_dynamic(struct hostapd_data *hapd,
40
+						     struct hostapd_vlan *vlan,
41
+						     int vlan_id)
42
+{
43
+	return NULL;
44
+}
45
+
46
+static inline int vlan_remove_dynamic(struct hostapd_data *hapd, int vlan_id)
47
+{
48
+	return -1;
49
+}
50
+
51
+static inline int vlan_setup_encryption_dyn(struct hostapd_data *hapd,
52
+					    struct hostapd_ssid *mssid,
53
+					    const char *dyn_vlan)
54
+{
55
+	return -1;
56
+}
57
+#endif /* CONFIG_NO_VLAN */
58
+
59
+#endif /* VLAN_INIT_H */

+ 327
- 0
src/ap/wmm.c Näytä tiedosto

@@ -0,0 +1,327 @@
1
+/*
2
+ * hostapd / WMM (Wi-Fi Multimedia)
3
+ * Copyright 2002-2003, Instant802 Networks, Inc.
4
+ * Copyright 2005-2006, Devicescape Software, Inc.
5
+ * Copyright (c) 2009, Jouni Malinen <j@w1.fi>
6
+ *
7
+ * This program is free software; you can redistribute it and/or modify
8
+ * it under the terms of the GNU General Public License version 2 as
9
+ * published by the Free Software Foundation.
10
+ *
11
+ * Alternatively, this software may be distributed under the terms of BSD
12
+ * license.
13
+ *
14
+ * See README and COPYING for more details.
15
+ */
16
+
17
+#include "utils/includes.h"
18
+
19
+#include "utils/common.h"
20
+#include "common/ieee802_11_defs.h"
21
+#include "common/ieee802_11_common.h"
22
+#include "hostapd.h"
23
+#include "ieee802_11.h"
24
+#include "sta_info.h"
25
+#include "ap_config.h"
26
+#include "ap_drv_ops.h"
27
+#include "wmm.h"
28
+
29
+
30
+/* TODO: maintain separate sequence and fragment numbers for each AC
31
+ * TODO: IGMP snooping to track which multicasts to forward - and use QOS-DATA
32
+ * if only WMM stations are receiving a certain group */
33
+
34
+
35
+static inline u8 wmm_aci_aifsn(int aifsn, int acm, int aci)
36
+{
37
+	u8 ret;
38
+	ret = (aifsn << WMM_AC_AIFNS_SHIFT) & WMM_AC_AIFSN_MASK;
39
+	if (acm)
40
+		ret |= WMM_AC_ACM;
41
+	ret |= (aci << WMM_AC_ACI_SHIFT) & WMM_AC_ACI_MASK;
42
+	return ret;
43
+}
44
+
45
+
46
+static inline u8 wmm_ecw(int ecwmin, int ecwmax)
47
+{
48
+	return ((ecwmin << WMM_AC_ECWMIN_SHIFT) & WMM_AC_ECWMIN_MASK) |
49
+		((ecwmax << WMM_AC_ECWMAX_SHIFT) & WMM_AC_ECWMAX_MASK);
50
+}
51
+
52
+
53
+/*
54
+ * Add WMM Parameter Element to Beacon, Probe Response, and (Re)Association
55
+ * Response frames.
56
+ */
57
+u8 * hostapd_eid_wmm(struct hostapd_data *hapd, u8 *eid)
58
+{
59
+	u8 *pos = eid;
60
+	struct wmm_parameter_element *wmm =
61
+		(struct wmm_parameter_element *) (pos + 2);
62
+	int e;
63
+
64
+	if (!hapd->conf->wmm_enabled)
65
+		return eid;
66
+	eid[0] = WLAN_EID_VENDOR_SPECIFIC;
67
+	wmm->oui[0] = 0x00;
68
+	wmm->oui[1] = 0x50;
69
+	wmm->oui[2] = 0xf2;
70
+	wmm->oui_type = WMM_OUI_TYPE;
71
+	wmm->oui_subtype = WMM_OUI_SUBTYPE_PARAMETER_ELEMENT;
72
+	wmm->version = WMM_VERSION;
73
+	wmm->qos_info = hapd->parameter_set_count & 0xf;
74
+
75
+	if (hapd->conf->wmm_uapsd)
76
+		wmm->qos_info |= 0x80;
77
+
78
+	wmm->reserved = 0;
79
+
80
+	/* fill in a parameter set record for each AC */
81
+	for (e = 0; e < 4; e++) {
82
+		struct wmm_ac_parameter *ac = &wmm->ac[e];
83
+		struct hostapd_wmm_ac_params *acp =
84
+			&hapd->iconf->wmm_ac_params[e];
85
+
86
+		ac->aci_aifsn = wmm_aci_aifsn(acp->aifs,
87
+					      acp->admission_control_mandatory,
88
+					      e);
89
+		ac->cw = wmm_ecw(acp->cwmin, acp->cwmax);
90
+		ac->txop_limit = host_to_le16(acp->txop_limit);
91
+	}
92
+
93
+	pos = (u8 *) (wmm + 1);
94
+	eid[1] = pos - eid - 2; /* element length */
95
+
96
+	return pos;
97
+}
98
+
99
+
100
+/* This function is called when a station sends an association request with
101
+ * WMM info element. The function returns zero on success or non-zero on any
102
+ * error in WMM element. eid does not include Element ID and Length octets. */
103
+int hostapd_eid_wmm_valid(struct hostapd_data *hapd, const u8 *eid, size_t len)
104
+{
105
+	struct wmm_information_element *wmm;
106
+
107
+	wpa_hexdump(MSG_MSGDUMP, "WMM IE", eid, len);
108
+
109
+	if (len < sizeof(struct wmm_information_element)) {
110
+		wpa_printf(MSG_DEBUG, "Too short WMM IE (len=%lu)",
111
+			   (unsigned long) len);
112
+		return -1;
113
+	}
114
+
115
+	wmm = (struct wmm_information_element *) eid;
116
+	wpa_printf(MSG_DEBUG, "Validating WMM IE: OUI %02x:%02x:%02x  "
117
+		   "OUI type %d  OUI sub-type %d  version %d  QoS info 0x%x",
118
+		   wmm->oui[0], wmm->oui[1], wmm->oui[2], wmm->oui_type,
119
+		   wmm->oui_subtype, wmm->version, wmm->qos_info);
120
+	if (wmm->oui_subtype != WMM_OUI_SUBTYPE_INFORMATION_ELEMENT ||
121
+	    wmm->version != WMM_VERSION) {
122
+		wpa_printf(MSG_DEBUG, "Unsupported WMM IE Subtype/Version");
123
+		return -1;
124
+	}
125
+
126
+	return 0;
127
+}
128
+
129
+
130
+static void wmm_send_action(struct hostapd_data *hapd, const u8 *addr,
131
+			    const struct wmm_tspec_element *tspec,
132
+			    u8 action_code, u8 dialogue_token, u8 status_code)
133
+{
134
+	u8 buf[256];
135
+	struct ieee80211_mgmt *m = (struct ieee80211_mgmt *) buf;
136
+	struct wmm_tspec_element *t = (struct wmm_tspec_element *)
137
+		m->u.action.u.wmm_action.variable;
138
+	int len;
139
+
140
+	hostapd_logger(hapd, addr, HOSTAPD_MODULE_IEEE80211,
141
+		       HOSTAPD_LEVEL_DEBUG,
142
+		       "action response - reason %d", status_code);
143
+	os_memset(buf, 0, sizeof(buf));
144
+	m->frame_control = IEEE80211_FC(WLAN_FC_TYPE_MGMT,
145
+					WLAN_FC_STYPE_ACTION);
146
+	os_memcpy(m->da, addr, ETH_ALEN);
147
+	os_memcpy(m->sa, hapd->own_addr, ETH_ALEN);
148
+	os_memcpy(m->bssid, hapd->own_addr, ETH_ALEN);
149
+	m->u.action.category = WLAN_ACTION_WMM;
150
+	m->u.action.u.wmm_action.action_code = action_code;
151
+	m->u.action.u.wmm_action.dialog_token = dialogue_token;
152
+	m->u.action.u.wmm_action.status_code = status_code;
153
+	os_memcpy(t, tspec, sizeof(struct wmm_tspec_element));
154
+	len = ((u8 *) (t + 1)) - buf;
155
+
156
+	if (hostapd_drv_send_mlme(hapd, m, len) < 0)
157
+		perror("wmm_send_action: send");
158
+}
159
+
160
+
161
+int wmm_process_tspec(struct wmm_tspec_element *tspec)
162
+{
163
+	int medium_time, pps, duration;
164
+	int up, psb, dir, tid;
165
+	u16 val, surplus;
166
+
167
+	up = (tspec->ts_info[1] >> 3) & 0x07;
168
+	psb = (tspec->ts_info[1] >> 2) & 0x01;
169
+	dir = (tspec->ts_info[0] >> 5) & 0x03;
170
+	tid = (tspec->ts_info[0] >> 1) & 0x0f;
171
+	wpa_printf(MSG_DEBUG, "WMM: TS Info: UP=%d PSB=%d Direction=%d TID=%d",
172
+		   up, psb, dir, tid);
173
+	val = le_to_host16(tspec->nominal_msdu_size);
174
+	wpa_printf(MSG_DEBUG, "WMM: Nominal MSDU Size: %d%s",
175
+		   val & 0x7fff, val & 0x8000 ? " (fixed)" : "");
176
+	wpa_printf(MSG_DEBUG, "WMM: Mean Data Rate: %u bps",
177
+		   le_to_host32(tspec->mean_data_rate));
178
+	wpa_printf(MSG_DEBUG, "WMM: Minimum PHY Rate: %u bps",
179
+		   le_to_host32(tspec->minimum_phy_rate));
180
+	val = le_to_host16(tspec->surplus_bandwidth_allowance);
181
+	wpa_printf(MSG_DEBUG, "WMM: Surplus Bandwidth Allowance: %u.%04u",
182
+		   val >> 13, 10000 * (val & 0x1fff) / 0x2000);
183
+
184
+	val = le_to_host16(tspec->nominal_msdu_size);
185
+	if (val == 0) {
186
+		wpa_printf(MSG_DEBUG, "WMM: Invalid Nominal MSDU Size (0)");
187
+		return WMM_ADDTS_STATUS_INVALID_PARAMETERS;
188
+	}
189
+	/* pps = Ceiling((Mean Data Rate / 8) / Nominal MSDU Size) */
190
+	pps = ((le_to_host32(tspec->mean_data_rate) / 8) + val - 1) / val;
191
+	wpa_printf(MSG_DEBUG, "WMM: Packets-per-second estimate for TSPEC: %d",
192
+		   pps);
193
+
194
+	if (le_to_host32(tspec->minimum_phy_rate) < 1000000) {
195
+		wpa_printf(MSG_DEBUG, "WMM: Too small Minimum PHY Rate");
196
+		return WMM_ADDTS_STATUS_INVALID_PARAMETERS;
197
+	}
198
+
199
+	duration = (le_to_host16(tspec->nominal_msdu_size) & 0x7fff) * 8 /
200
+		(le_to_host32(tspec->minimum_phy_rate) / 1000000) +
201
+		50 /* FIX: proper SIFS + ACK duration */;
202
+
203
+	/* unsigned binary number with an implicit binary point after the
204
+	 * leftmost 3 bits, i.e., 0x2000 = 1.0 */
205
+	surplus = le_to_host16(tspec->surplus_bandwidth_allowance);
206
+	if (surplus <= 0x2000) {
207
+		wpa_printf(MSG_DEBUG, "WMM: Surplus Bandwidth Allowance not "
208
+			   "greater than unity");
209
+		return WMM_ADDTS_STATUS_INVALID_PARAMETERS;
210
+	}
211
+
212
+	medium_time = surplus * pps * duration / 0x2000;
213
+	wpa_printf(MSG_DEBUG, "WMM: Estimated medium time: %u", medium_time);
214
+
215
+	/*
216
+	 * TODO: store list of granted (and still active) TSPECs and check
217
+	 * whether there is available medium time for this request. For now,
218
+	 * just refuse requests that would by themselves take very large
219
+	 * portion of the available bandwidth.
220
+	 */
221
+	if (medium_time > 750000) {
222
+		wpa_printf(MSG_DEBUG, "WMM: Refuse TSPEC request for over "
223
+			   "75%% of available bandwidth");
224
+		return WMM_ADDTS_STATUS_REFUSED;
225
+	}
226
+
227
+	/* Convert to 32 microseconds per second unit */
228
+	tspec->medium_time = host_to_le16(medium_time / 32);
229
+
230
+	return WMM_ADDTS_STATUS_ADMISSION_ACCEPTED;
231
+}
232
+
233
+
234
+static void wmm_addts_req(struct hostapd_data *hapd,
235
+			  const struct ieee80211_mgmt *mgmt,
236
+			  struct wmm_tspec_element *tspec, size_t len)
237
+{
238
+	const u8 *end = ((const u8 *) mgmt) + len;
239
+	int res;
240
+
241
+	if ((const u8 *) (tspec + 1) > end) {
242
+		wpa_printf(MSG_DEBUG, "WMM: TSPEC overflow in ADDTS Request");
243
+		return;
244
+	}
245
+
246
+	wpa_printf(MSG_DEBUG, "WMM: ADDTS Request (Dialog Token %d) for TSPEC "
247
+		   "from " MACSTR,
248
+		   mgmt->u.action.u.wmm_action.dialog_token,
249
+		   MAC2STR(mgmt->sa));
250
+
251
+	res = wmm_process_tspec(tspec);
252
+	wpa_printf(MSG_DEBUG, "WMM: ADDTS processing result: %d", res);
253
+
254
+	wmm_send_action(hapd, mgmt->sa, tspec, WMM_ACTION_CODE_ADDTS_RESP,
255
+			mgmt->u.action.u.wmm_action.dialog_token, res);
256
+}
257
+
258
+
259
+void hostapd_wmm_action(struct hostapd_data *hapd,
260
+			const struct ieee80211_mgmt *mgmt, size_t len)
261
+{
262
+	int action_code;
263
+	int left = len - IEEE80211_HDRLEN - 4;
264
+	const u8 *pos = ((const u8 *) mgmt) + IEEE80211_HDRLEN + 4;
265
+	struct ieee802_11_elems elems;
266
+	struct sta_info *sta = ap_get_sta(hapd, mgmt->sa);
267
+
268
+	/* check that the request comes from a valid station */
269
+	if (!sta ||
270
+	    (sta->flags & (WLAN_STA_ASSOC | WLAN_STA_WMM)) !=
271
+	    (WLAN_STA_ASSOC | WLAN_STA_WMM)) {
272
+		hostapd_logger(hapd, mgmt->sa, HOSTAPD_MODULE_IEEE80211,
273
+			       HOSTAPD_LEVEL_DEBUG,
274
+			       "wmm action received is not from associated wmm"
275
+			       " station");
276
+		/* TODO: respond with action frame refused status code */
277
+		return;
278
+	}
279
+
280
+	/* extract the tspec info element */
281
+	if (ieee802_11_parse_elems(pos, left, &elems, 1) == ParseFailed) {
282
+		hostapd_logger(hapd, mgmt->sa, HOSTAPD_MODULE_IEEE80211,
283
+			       HOSTAPD_LEVEL_DEBUG,
284
+			       "hostapd_wmm_action - could not parse wmm "
285
+			       "action");
286
+		/* TODO: respond with action frame invalid parameters status
287
+		 * code */
288
+		return;
289
+	}
290
+
291
+	if (!elems.wmm_tspec ||
292
+	    elems.wmm_tspec_len != (sizeof(struct wmm_tspec_element) - 2)) {
293
+		hostapd_logger(hapd, mgmt->sa, HOSTAPD_MODULE_IEEE80211,
294
+			       HOSTAPD_LEVEL_DEBUG,
295
+			       "hostapd_wmm_action - missing or wrong length "
296
+			       "tspec");
297
+		/* TODO: respond with action frame invalid parameters status
298
+		 * code */
299
+		return;
300
+	}
301
+
302
+	/* TODO: check the request is for an AC with ACM set, if not, refuse
303
+	 * request */
304
+
305
+	action_code = mgmt->u.action.u.wmm_action.action_code;
306
+	switch (action_code) {
307
+	case WMM_ACTION_CODE_ADDTS_REQ:
308
+		wmm_addts_req(hapd, mgmt, (struct wmm_tspec_element *)
309
+			      (elems.wmm_tspec - 2), len);
310
+		return;
311
+#if 0
312
+	/* TODO: needed for client implementation */
313
+	case WMM_ACTION_CODE_ADDTS_RESP:
314
+		wmm_setup_request(hapd, mgmt, len);
315
+		return;
316
+	/* TODO: handle station teardown requests */
317
+	case WMM_ACTION_CODE_DELTS:
318
+		wmm_teardown(hapd, mgmt, len);
319
+		return;
320
+#endif
321
+	}
322
+
323
+	hostapd_logger(hapd, mgmt->sa, HOSTAPD_MODULE_IEEE80211,
324
+		       HOSTAPD_LEVEL_DEBUG,
325
+		       "hostapd_wmm_action - unknown action code %d",
326
+		       action_code);
327
+}

+ 29
- 0
src/ap/wmm.h Näytä tiedosto

@@ -0,0 +1,29 @@
1
+/*
2
+ * hostapd / WMM (Wi-Fi Multimedia)
3
+ * Copyright 2002-2003, Instant802 Networks, Inc.
4
+ * Copyright 2005-2006, Devicescape Software, Inc.
5
+ *
6
+ * This program is free software; you can redistribute it and/or modify
7
+ * it under the terms of the GNU General Public License version 2 as
8
+ * published by the Free Software Foundation.
9
+ *
10
+ * Alternatively, this software may be distributed under the terms of BSD
11
+ * license.
12
+ *
13
+ * See README and COPYING for more details.
14
+ */
15
+
16
+#ifndef WME_H
17
+#define WME_H
18
+
19
+struct ieee80211_mgmt;
20
+struct wmm_tspec_element;
21
+
22
+u8 * hostapd_eid_wmm(struct hostapd_data *hapd, u8 *eid);
23
+int hostapd_eid_wmm_valid(struct hostapd_data *hapd, const u8 *eid,
24
+			  size_t len);
25
+void hostapd_wmm_action(struct hostapd_data *hapd,
26
+			const struct ieee80211_mgmt *mgmt, size_t len);
27
+int wmm_process_tspec(struct wmm_tspec_element *tspec);
28
+
29
+#endif /* WME_H */

+ 2838
- 0
src/ap/wpa_auth.c
File diff suppressed because it is too large
Näytä tiedosto


+ 285
- 0
src/ap/wpa_auth.h Näytä tiedosto

@@ -0,0 +1,285 @@
1
+/*
2
+ * hostapd - IEEE 802.11i-2004 / WPA Authenticator
3
+ * Copyright (c) 2004-2007, Jouni Malinen <j@w1.fi>
4
+ *
5
+ * This program is free software; you can redistribute it and/or modify
6
+ * it under the terms of the GNU General Public License version 2 as
7
+ * published by the Free Software Foundation.
8
+ *
9
+ * Alternatively, this software may be distributed under the terms of BSD
10
+ * license.
11
+ *
12
+ * See README and COPYING for more details.
13
+ */
14
+
15
+#ifndef WPA_AUTH_H
16
+#define WPA_AUTH_H
17
+
18
+#include "common/defs.h"
19
+#include "common/eapol_common.h"
20
+#include "common/wpa_common.h"
21
+
22
+#ifdef _MSC_VER
23
+#pragma pack(push, 1)
24
+#endif /* _MSC_VER */
25
+
26
+/* IEEE Std 802.11r-2008, 11A.10.3 - Remote request/response frame definition
27
+ */
28
+struct ft_rrb_frame {
29
+	u8 frame_type; /* RSN_REMOTE_FRAME_TYPE_FT_RRB */
30
+	u8 packet_type; /* FT_PACKET_REQUEST/FT_PACKET_RESPONSE */
31
+	le16 action_length; /* little endian length of action_frame */
32
+	u8 ap_address[ETH_ALEN];
33
+	/*
34
+	 * Followed by action_length bytes of FT Action frame (from Category
35
+	 * field to the end of Action Frame body.
36
+	 */
37
+} STRUCT_PACKED;
38
+
39
+#define RSN_REMOTE_FRAME_TYPE_FT_RRB 1
40
+
41
+#define FT_PACKET_REQUEST 0
42
+#define FT_PACKET_RESPONSE 1
43
+/* Vendor-specific types for R0KH-R1KH protocol; not defined in 802.11r */
44
+#define FT_PACKET_R0KH_R1KH_PULL 200
45
+#define FT_PACKET_R0KH_R1KH_RESP 201
46
+#define FT_PACKET_R0KH_R1KH_PUSH 202
47
+
48
+#define FT_R0KH_R1KH_PULL_DATA_LEN 44
49
+#define FT_R0KH_R1KH_RESP_DATA_LEN 76
50
+#define FT_R0KH_R1KH_PUSH_DATA_LEN 88
51
+
52
+struct ft_r0kh_r1kh_pull_frame {
53
+	u8 frame_type; /* RSN_REMOTE_FRAME_TYPE_FT_RRB */
54
+	u8 packet_type; /* FT_PACKET_R0KH_R1KH_PULL */
55
+	le16 data_length; /* little endian length of data (44) */
56
+	u8 ap_address[ETH_ALEN];
57
+
58
+	u8 nonce[16];
59
+	u8 pmk_r0_name[WPA_PMK_NAME_LEN];
60
+	u8 r1kh_id[FT_R1KH_ID_LEN];
61
+	u8 s1kh_id[ETH_ALEN];
62
+	u8 pad[4]; /* 8-octet boundary for AES key wrap */
63
+	u8 key_wrap_extra[8];
64
+} STRUCT_PACKED;
65
+
66
+struct ft_r0kh_r1kh_resp_frame {
67
+	u8 frame_type; /* RSN_REMOTE_FRAME_TYPE_FT_RRB */
68
+	u8 packet_type; /* FT_PACKET_R0KH_R1KH_RESP */
69
+	le16 data_length; /* little endian length of data (76) */
70
+	u8 ap_address[ETH_ALEN];
71
+
72
+	u8 nonce[16]; /* copied from pull */
73
+	u8 r1kh_id[FT_R1KH_ID_LEN]; /* copied from pull */
74
+	u8 s1kh_id[ETH_ALEN]; /* copied from pull */
75
+	u8 pmk_r1[PMK_LEN];
76
+	u8 pmk_r1_name[WPA_PMK_NAME_LEN];
77
+	le16 pairwise;
78
+	u8 pad[2]; /* 8-octet boundary for AES key wrap */
79
+	u8 key_wrap_extra[8];
80
+} STRUCT_PACKED;
81
+
82
+struct ft_r0kh_r1kh_push_frame {
83
+	u8 frame_type; /* RSN_REMOTE_FRAME_TYPE_FT_RRB */
84
+	u8 packet_type; /* FT_PACKET_R0KH_R1KH_PUSH */
85
+	le16 data_length; /* little endian length of data (88) */
86
+	u8 ap_address[ETH_ALEN];
87
+
88
+	/* Encrypted with AES key-wrap */
89
+	u8 timestamp[4]; /* current time in seconds since unix epoch, little
90
+			  * endian */
91
+	u8 r1kh_id[FT_R1KH_ID_LEN];
92
+	u8 s1kh_id[ETH_ALEN];
93
+	u8 pmk_r0_name[WPA_PMK_NAME_LEN];
94
+	u8 pmk_r1[PMK_LEN];
95
+	u8 pmk_r1_name[WPA_PMK_NAME_LEN];
96
+	le16 pairwise;
97
+	u8 pad[6]; /* 8-octet boundary for AES key wrap */
98
+	u8 key_wrap_extra[8];
99
+} STRUCT_PACKED;
100
+
101
+#ifdef _MSC_VER
102
+#pragma pack(pop)
103
+#endif /* _MSC_VER */
104
+
105
+
106
+/* per STA state machine data */
107
+
108
+struct wpa_authenticator;
109
+struct wpa_state_machine;
110
+struct rsn_pmksa_cache_entry;
111
+struct eapol_state_machine;
112
+
113
+
114
+struct ft_remote_r0kh {
115
+	struct ft_remote_r0kh *next;
116
+	u8 addr[ETH_ALEN];
117
+	u8 id[FT_R0KH_ID_MAX_LEN];
118
+	size_t id_len;
119
+	u8 key[16];
120
+};
121
+
122
+
123
+struct ft_remote_r1kh {
124
+	struct ft_remote_r1kh *next;
125
+	u8 addr[ETH_ALEN];
126
+	u8 id[FT_R1KH_ID_LEN];
127
+	u8 key[16];
128
+};
129
+
130
+
131
+struct wpa_auth_config {
132
+	int wpa;
133
+	int wpa_key_mgmt;
134
+	int wpa_pairwise;
135
+	int wpa_group;
136
+	int wpa_group_rekey;
137
+	int wpa_strict_rekey;
138
+	int wpa_gmk_rekey;
139
+	int wpa_ptk_rekey;
140
+	int rsn_pairwise;
141
+	int rsn_preauth;
142
+	int eapol_version;
143
+	int peerkey;
144
+	int wmm_enabled;
145
+	int wmm_uapsd;
146
+	int okc;
147
+	int tx_status;
148
+#ifdef CONFIG_IEEE80211W
149
+	enum mfp_options ieee80211w;
150
+#endif /* CONFIG_IEEE80211W */
151
+#ifdef CONFIG_IEEE80211R
152
+#define SSID_LEN 32
153
+	u8 ssid[SSID_LEN];
154
+	size_t ssid_len;
155
+	u8 mobility_domain[MOBILITY_DOMAIN_ID_LEN];
156
+	u8 r0_key_holder[FT_R0KH_ID_MAX_LEN];
157
+	size_t r0_key_holder_len;
158
+	u8 r1_key_holder[FT_R1KH_ID_LEN];
159
+	u32 r0_key_lifetime;
160
+	u32 reassociation_deadline;
161
+	struct ft_remote_r0kh *r0kh_list;
162
+	struct ft_remote_r1kh *r1kh_list;
163
+	int pmk_r1_push;
164
+	int ft_over_ds;
165
+#endif /* CONFIG_IEEE80211R */
166
+};
167
+
168
+typedef enum {
169
+	LOGGER_DEBUG, LOGGER_INFO, LOGGER_WARNING
170
+} logger_level;
171
+
172
+typedef enum {
173
+	WPA_EAPOL_portEnabled, WPA_EAPOL_portValid, WPA_EAPOL_authorized,
174
+	WPA_EAPOL_portControl_Auto, WPA_EAPOL_keyRun, WPA_EAPOL_keyAvailable,
175
+	WPA_EAPOL_keyDone, WPA_EAPOL_inc_EapolFramesTx
176
+} wpa_eapol_variable;
177
+
178
+struct wpa_auth_callbacks {
179
+	void *ctx;
180
+	void (*logger)(void *ctx, const u8 *addr, logger_level level,
181
+		       const char *txt);
182
+	void (*disconnect)(void *ctx, const u8 *addr, u16 reason);
183
+	void (*mic_failure_report)(void *ctx, const u8 *addr);
184
+	void (*set_eapol)(void *ctx, const u8 *addr, wpa_eapol_variable var,
185
+			  int value);
186
+	int (*get_eapol)(void *ctx, const u8 *addr, wpa_eapol_variable var);
187
+	const u8 * (*get_psk)(void *ctx, const u8 *addr, const u8 *prev_psk);
188
+	int (*get_msk)(void *ctx, const u8 *addr, u8 *msk, size_t *len);
189
+	int (*set_key)(void *ctx, int vlan_id, enum wpa_alg alg,
190
+		       const u8 *addr, int idx, u8 *key, size_t key_len);
191
+	int (*get_seqnum)(void *ctx, const u8 *addr, int idx, u8 *seq);
192
+	int (*send_eapol)(void *ctx, const u8 *addr, const u8 *data,
193
+			  size_t data_len, int encrypt);
194
+	int (*for_each_sta)(void *ctx, int (*cb)(struct wpa_state_machine *sm,
195
+						 void *ctx), void *cb_ctx);
196
+	int (*for_each_auth)(void *ctx, int (*cb)(struct wpa_authenticator *a,
197
+						  void *ctx), void *cb_ctx);
198
+	int (*send_ether)(void *ctx, const u8 *dst, u16 proto, const u8 *data,
199
+			  size_t data_len);
200
+#ifdef CONFIG_IEEE80211R
201
+	struct wpa_state_machine * (*add_sta)(void *ctx, const u8 *sta_addr);
202
+	int (*send_ft_action)(void *ctx, const u8 *dst,
203
+			      const u8 *data, size_t data_len);
204
+#endif /* CONFIG_IEEE80211R */
205
+};
206
+
207
+struct wpa_authenticator * wpa_init(const u8 *addr,
208
+				    struct wpa_auth_config *conf,
209
+				    struct wpa_auth_callbacks *cb);
210
+void wpa_deinit(struct wpa_authenticator *wpa_auth);
211
+int wpa_reconfig(struct wpa_authenticator *wpa_auth,
212
+		 struct wpa_auth_config *conf);
213
+
214
+enum {
215
+	WPA_IE_OK, WPA_INVALID_IE, WPA_INVALID_GROUP, WPA_INVALID_PAIRWISE,
216
+	WPA_INVALID_AKMP, WPA_NOT_ENABLED, WPA_ALLOC_FAIL,
217
+	WPA_MGMT_FRAME_PROTECTION_VIOLATION, WPA_INVALID_MGMT_GROUP_CIPHER,
218
+	WPA_INVALID_MDIE, WPA_INVALID_PROTO
219
+};
220
+	
221
+int wpa_validate_wpa_ie(struct wpa_authenticator *wpa_auth,
222
+			struct wpa_state_machine *sm,
223
+			const u8 *wpa_ie, size_t wpa_ie_len,
224
+			const u8 *mdie, size_t mdie_len);
225
+int wpa_auth_uses_mfp(struct wpa_state_machine *sm);
226
+struct wpa_state_machine *
227
+wpa_auth_sta_init(struct wpa_authenticator *wpa_auth, const u8 *addr);
228
+int wpa_auth_sta_associated(struct wpa_authenticator *wpa_auth,
229
+			    struct wpa_state_machine *sm);
230
+void wpa_auth_sta_no_wpa(struct wpa_state_machine *sm);
231
+void wpa_auth_sta_deinit(struct wpa_state_machine *sm);
232
+void wpa_receive(struct wpa_authenticator *wpa_auth,
233
+		 struct wpa_state_machine *sm,
234
+		 u8 *data, size_t data_len);
235
+typedef enum {
236
+	WPA_AUTH, WPA_ASSOC, WPA_DISASSOC, WPA_DEAUTH, WPA_REAUTH,
237
+	WPA_REAUTH_EAPOL, WPA_ASSOC_FT
238
+} wpa_event;
239
+void wpa_remove_ptk(struct wpa_state_machine *sm);
240
+int wpa_auth_sm_event(struct wpa_state_machine *sm, wpa_event event);
241
+void wpa_auth_sm_notify(struct wpa_state_machine *sm);
242
+void wpa_gtk_rekey(struct wpa_authenticator *wpa_auth);
243
+int wpa_get_mib(struct wpa_authenticator *wpa_auth, char *buf, size_t buflen);
244
+int wpa_get_mib_sta(struct wpa_state_machine *sm, char *buf, size_t buflen);
245
+void wpa_auth_countermeasures_start(struct wpa_authenticator *wpa_auth);
246
+int wpa_auth_pairwise_set(struct wpa_state_machine *sm);
247
+int wpa_auth_get_pairwise(struct wpa_state_machine *sm);
248
+int wpa_auth_sta_key_mgmt(struct wpa_state_machine *sm);
249
+int wpa_auth_sta_wpa_version(struct wpa_state_machine *sm);
250
+int wpa_auth_sta_clear_pmksa(struct wpa_state_machine *sm,
251
+			     struct rsn_pmksa_cache_entry *entry);
252
+struct rsn_pmksa_cache_entry *
253
+wpa_auth_sta_get_pmksa(struct wpa_state_machine *sm);
254
+void wpa_auth_sta_local_mic_failure_report(struct wpa_state_machine *sm);
255
+const u8 * wpa_auth_get_wpa_ie(struct wpa_authenticator *wpa_auth,
256
+			       size_t *len);
257
+int wpa_auth_pmksa_add(struct wpa_state_machine *sm, const u8 *pmk,
258
+		       int session_timeout, struct eapol_state_machine *eapol);
259
+int wpa_auth_pmksa_add_preauth(struct wpa_authenticator *wpa_auth,
260
+			       const u8 *pmk, size_t len, const u8 *sta_addr,
261
+			       int session_timeout,
262
+			       struct eapol_state_machine *eapol);
263
+int wpa_auth_sta_set_vlan(struct wpa_state_machine *sm, int vlan_id);
264
+void wpa_auth_eapol_key_tx_status(struct wpa_authenticator *wpa_auth,
265
+				  struct wpa_state_machine *sm, int ack);
266
+
267
+#ifdef CONFIG_IEEE80211R
268
+u8 * wpa_sm_write_assoc_resp_ies(struct wpa_state_machine *sm, u8 *pos,
269
+				 size_t max_len, int auth_alg,
270
+				 const u8 *req_ies, size_t req_ies_len);
271
+void wpa_ft_process_auth(struct wpa_state_machine *sm, const u8 *bssid,
272
+			 u16 auth_transaction, const u8 *ies, size_t ies_len,
273
+			 void (*cb)(void *ctx, const u8 *dst, const u8 *bssid,
274
+				    u16 auth_transaction, u16 resp,
275
+				    const u8 *ies, size_t ies_len),
276
+			 void *ctx);
277
+u16 wpa_ft_validate_reassoc(struct wpa_state_machine *sm, const u8 *ies,
278
+			    size_t ies_len);
279
+int wpa_ft_action_rx(struct wpa_state_machine *sm, const u8 *data, size_t len);
280
+int wpa_ft_rrb_rx(struct wpa_authenticator *wpa_auth, const u8 *src_addr,
281
+		  const u8 *data, size_t data_len);
282
+void wpa_ft_push_pmk_r1(struct wpa_authenticator *wpa_auth, const u8 *addr);
283
+#endif /* CONFIG_IEEE80211R */
284
+
285
+#endif /* WPA_AUTH_H */

+ 1779
- 0
src/ap/wpa_auth_ft.c
File diff suppressed because it is too large
Näytä tiedosto


+ 571
- 0
src/ap/wpa_auth_glue.c Näytä tiedosto

@@ -0,0 +1,571 @@
1
+/*
2
+ * hostapd / WPA authenticator glue code
3
+ * Copyright (c) 2002-2011, Jouni Malinen <j@w1.fi>
4
+ *
5
+ * This program is free software; you can redistribute it and/or modify
6
+ * it under the terms of the GNU General Public License version 2 as
7
+ * published by the Free Software Foundation.
8
+ *
9
+ * Alternatively, this software may be distributed under the terms of BSD
10
+ * license.
11
+ *
12
+ * See README and COPYING for more details.
13
+ */
14
+
15
+#include "utils/includes.h"
16
+
17
+#include "utils/common.h"
18
+#include "common/ieee802_11_defs.h"
19
+#include "eapol_auth/eapol_auth_sm.h"
20
+#include "eapol_auth/eapol_auth_sm_i.h"
21
+#include "eap_server/eap.h"
22
+#include "l2_packet/l2_packet.h"
23
+#include "drivers/driver.h"
24
+#include "hostapd.h"
25
+#include "ieee802_1x.h"
26
+#include "preauth_auth.h"
27
+#include "sta_info.h"
28
+#include "tkip_countermeasures.h"
29
+#include "ap_drv_ops.h"
30
+#include "ap_config.h"
31
+#include "wpa_auth.h"
32
+
33
+
34
+static void hostapd_wpa_auth_conf(struct hostapd_bss_config *conf,
35
+				  struct wpa_auth_config *wconf)
36
+{
37
+	wconf->wpa = conf->wpa;
38
+	wconf->wpa_key_mgmt = conf->wpa_key_mgmt;
39
+	wconf->wpa_pairwise = conf->wpa_pairwise;
40
+	wconf->wpa_group = conf->wpa_group;
41
+	wconf->wpa_group_rekey = conf->wpa_group_rekey;
42
+	wconf->wpa_strict_rekey = conf->wpa_strict_rekey;
43
+	wconf->wpa_gmk_rekey = conf->wpa_gmk_rekey;
44
+	wconf->wpa_ptk_rekey = conf->wpa_ptk_rekey;
45
+	wconf->rsn_pairwise = conf->rsn_pairwise;
46
+	wconf->rsn_preauth = conf->rsn_preauth;
47
+	wconf->eapol_version = conf->eapol_version;
48
+	wconf->peerkey = conf->peerkey;
49
+	wconf->wmm_enabled = conf->wmm_enabled;
50
+	wconf->wmm_uapsd = conf->wmm_uapsd;
51
+	wconf->okc = conf->okc;
52
+#ifdef CONFIG_IEEE80211W
53
+	wconf->ieee80211w = conf->ieee80211w;
54
+#endif /* CONFIG_IEEE80211W */
55
+#ifdef CONFIG_IEEE80211R
56
+	wconf->ssid_len = conf->ssid.ssid_len;
57
+	if (wconf->ssid_len > SSID_LEN)
58
+		wconf->ssid_len = SSID_LEN;
59
+	os_memcpy(wconf->ssid, conf->ssid.ssid, wconf->ssid_len);
60
+	os_memcpy(wconf->mobility_domain, conf->mobility_domain,
61
+		  MOBILITY_DOMAIN_ID_LEN);
62
+	if (conf->nas_identifier &&
63
+	    os_strlen(conf->nas_identifier) <= FT_R0KH_ID_MAX_LEN) {
64
+		wconf->r0_key_holder_len = os_strlen(conf->nas_identifier);
65
+		os_memcpy(wconf->r0_key_holder, conf->nas_identifier,
66
+			  wconf->r0_key_holder_len);
67
+	}
68
+	os_memcpy(wconf->r1_key_holder, conf->r1_key_holder, FT_R1KH_ID_LEN);
69
+	wconf->r0_key_lifetime = conf->r0_key_lifetime;
70
+	wconf->reassociation_deadline = conf->reassociation_deadline;
71
+	wconf->r0kh_list = conf->r0kh_list;
72
+	wconf->r1kh_list = conf->r1kh_list;
73
+	wconf->pmk_r1_push = conf->pmk_r1_push;
74
+	wconf->ft_over_ds = conf->ft_over_ds;
75
+#endif /* CONFIG_IEEE80211R */
76
+}
77
+
78
+
79
+static void hostapd_wpa_auth_logger(void *ctx, const u8 *addr,
80
+				    logger_level level, const char *txt)
81
+{
82
+#ifndef CONFIG_NO_HOSTAPD_LOGGER
83
+	struct hostapd_data *hapd = ctx;
84
+	int hlevel;
85
+
86
+	switch (level) {
87
+	case LOGGER_WARNING:
88
+		hlevel = HOSTAPD_LEVEL_WARNING;
89
+		break;
90
+	case LOGGER_INFO:
91
+		hlevel = HOSTAPD_LEVEL_INFO;
92
+		break;
93
+	case LOGGER_DEBUG:
94
+	default:
95
+		hlevel = HOSTAPD_LEVEL_DEBUG;
96
+		break;
97
+	}
98
+
99
+	hostapd_logger(hapd, addr, HOSTAPD_MODULE_WPA, hlevel, "%s", txt);
100
+#endif /* CONFIG_NO_HOSTAPD_LOGGER */
101
+}
102
+
103
+
104
+static void hostapd_wpa_auth_disconnect(void *ctx, const u8 *addr,
105
+					u16 reason)
106
+{
107
+	struct hostapd_data *hapd = ctx;
108
+	wpa_printf(MSG_DEBUG, "%s: WPA authenticator requests disconnect: "
109
+		   "STA " MACSTR " reason %d",
110
+		   __func__, MAC2STR(addr), reason);
111
+	ap_sta_disconnect(hapd, NULL, addr, reason);
112
+}
113
+
114
+
115
+static void hostapd_wpa_auth_mic_failure_report(void *ctx, const u8 *addr)
116
+{
117
+	struct hostapd_data *hapd = ctx;
118
+	michael_mic_failure(hapd, addr, 0);
119
+}
120
+
121
+
122
+static void hostapd_wpa_auth_set_eapol(void *ctx, const u8 *addr,
123
+				       wpa_eapol_variable var, int value)
124
+{
125
+	struct hostapd_data *hapd = ctx;
126
+	struct sta_info *sta = ap_get_sta(hapd, addr);
127
+	if (sta == NULL)
128
+		return;
129
+	switch (var) {
130
+	case WPA_EAPOL_portEnabled:
131
+		ieee802_1x_notify_port_enabled(sta->eapol_sm, value);
132
+		break;
133
+	case WPA_EAPOL_portValid:
134
+		ieee802_1x_notify_port_valid(sta->eapol_sm, value);
135
+		break;
136
+	case WPA_EAPOL_authorized:
137
+		ieee802_1x_set_sta_authorized(hapd, sta, value);
138
+		break;
139
+	case WPA_EAPOL_portControl_Auto:
140
+		if (sta->eapol_sm)
141
+			sta->eapol_sm->portControl = Auto;
142
+		break;
143
+	case WPA_EAPOL_keyRun:
144
+		if (sta->eapol_sm)
145
+			sta->eapol_sm->keyRun = value ? TRUE : FALSE;
146
+		break;
147
+	case WPA_EAPOL_keyAvailable:
148
+		if (sta->eapol_sm)
149
+			sta->eapol_sm->eap_if->eapKeyAvailable =
150
+				value ? TRUE : FALSE;
151
+		break;
152
+	case WPA_EAPOL_keyDone:
153
+		if (sta->eapol_sm)
154
+			sta->eapol_sm->keyDone = value ? TRUE : FALSE;
155
+		break;
156
+	case WPA_EAPOL_inc_EapolFramesTx:
157
+		if (sta->eapol_sm)
158
+			sta->eapol_sm->dot1xAuthEapolFramesTx++;
159
+		break;
160
+	}
161
+}
162
+
163
+
164
+static int hostapd_wpa_auth_get_eapol(void *ctx, const u8 *addr,
165
+				      wpa_eapol_variable var)
166
+{
167
+	struct hostapd_data *hapd = ctx;
168
+	struct sta_info *sta = ap_get_sta(hapd, addr);
169
+	if (sta == NULL || sta->eapol_sm == NULL)
170
+		return -1;
171
+	switch (var) {
172
+	case WPA_EAPOL_keyRun:
173
+		return sta->eapol_sm->keyRun;
174
+	case WPA_EAPOL_keyAvailable:
175
+		return sta->eapol_sm->eap_if->eapKeyAvailable;
176
+	default:
177
+		return -1;
178
+	}
179
+}
180
+
181
+
182
+static const u8 * hostapd_wpa_auth_get_psk(void *ctx, const u8 *addr,
183
+					   const u8 *prev_psk)
184
+{
185
+	struct hostapd_data *hapd = ctx;
186
+	return hostapd_get_psk(hapd->conf, addr, prev_psk);
187
+}
188
+
189
+
190
+static int hostapd_wpa_auth_get_msk(void *ctx, const u8 *addr, u8 *msk,
191
+				    size_t *len)
192
+{
193
+	struct hostapd_data *hapd = ctx;
194
+	const u8 *key;
195
+	size_t keylen;
196
+	struct sta_info *sta;
197
+
198
+	sta = ap_get_sta(hapd, addr);
199
+	if (sta == NULL)
200
+		return -1;
201
+
202
+	key = ieee802_1x_get_key(sta->eapol_sm, &keylen);
203
+	if (key == NULL)
204
+		return -1;
205
+
206
+	if (keylen > *len)
207
+		keylen = *len;
208
+	os_memcpy(msk, key, keylen);
209
+	*len = keylen;
210
+
211
+	return 0;
212
+}
213
+
214
+
215
+static int hostapd_wpa_auth_set_key(void *ctx, int vlan_id, enum wpa_alg alg,
216
+				    const u8 *addr, int idx, u8 *key,
217
+				    size_t key_len)
218
+{
219
+	struct hostapd_data *hapd = ctx;
220
+	const char *ifname = hapd->conf->iface;
221
+
222
+	if (vlan_id > 0) {
223
+		ifname = hostapd_get_vlan_id_ifname(hapd->conf->vlan, vlan_id);
224
+		if (ifname == NULL)
225
+			return -1;
226
+	}
227
+
228
+	return hostapd_drv_set_key(ifname, hapd, alg, addr, idx, 1, NULL, 0,
229
+				   key, key_len);
230
+}
231
+
232
+
233
+static int hostapd_wpa_auth_get_seqnum(void *ctx, const u8 *addr, int idx,
234
+				       u8 *seq)
235
+{
236
+	struct hostapd_data *hapd = ctx;
237
+	return hostapd_get_seqnum(hapd->conf->iface, hapd, addr, idx, seq);
238
+}
239
+
240
+
241
+static int hostapd_wpa_auth_send_eapol(void *ctx, const u8 *addr,
242
+				       const u8 *data, size_t data_len,
243
+				       int encrypt)
244
+{
245
+	struct hostapd_data *hapd = ctx;
246
+	struct sta_info *sta;
247
+	u32 flags = 0;
248
+
249
+	sta = ap_get_sta(hapd, addr);
250
+	if (sta)
251
+		flags = hostapd_sta_flags_to_drv(sta->flags);
252
+
253
+	return hostapd_drv_hapd_send_eapol(hapd, addr, data, data_len,
254
+					   encrypt, flags);
255
+}
256
+
257
+
258
+static int hostapd_wpa_auth_for_each_sta(
259
+	void *ctx, int (*cb)(struct wpa_state_machine *sm, void *ctx),
260
+	void *cb_ctx)
261
+{
262
+	struct hostapd_data *hapd = ctx;
263
+	struct sta_info *sta;
264
+
265
+	for (sta = hapd->sta_list; sta; sta = sta->next) {
266
+		if (sta->wpa_sm && cb(sta->wpa_sm, cb_ctx))
267
+			return 1;
268
+	}
269
+	return 0;
270
+}
271
+
272
+
273
+struct wpa_auth_iface_iter_data {
274
+	int (*cb)(struct wpa_authenticator *sm, void *ctx);
275
+	void *cb_ctx;
276
+};
277
+
278
+static int wpa_auth_iface_iter(struct hostapd_iface *iface, void *ctx)
279
+{
280
+	struct wpa_auth_iface_iter_data *data = ctx;
281
+	size_t i;
282
+	for (i = 0; i < iface->num_bss; i++) {
283
+		if (iface->bss[i]->wpa_auth &&
284
+		    data->cb(iface->bss[i]->wpa_auth, data->cb_ctx))
285
+			return 1;
286
+	}
287
+	return 0;
288
+}
289
+
290
+
291
+static int hostapd_wpa_auth_for_each_auth(
292
+	void *ctx, int (*cb)(struct wpa_authenticator *sm, void *ctx),
293
+	void *cb_ctx)
294
+{
295
+	struct hostapd_data *hapd = ctx;
296
+	struct wpa_auth_iface_iter_data data;
297
+	if (hapd->iface->for_each_interface == NULL)
298
+		return -1;
299
+	data.cb = cb;
300
+	data.cb_ctx = cb_ctx;
301
+	return hapd->iface->for_each_interface(hapd->iface->interfaces,
302
+					       wpa_auth_iface_iter, &data);
303
+}
304
+
305
+
306
+#ifdef CONFIG_IEEE80211R
307
+
308
+struct wpa_auth_ft_iface_iter_data {
309
+	struct hostapd_data *src_hapd;
310
+	const u8 *dst;
311
+	const u8 *data;
312
+	size_t data_len;
313
+};
314
+
315
+
316
+static int hostapd_wpa_auth_ft_iter(struct hostapd_iface *iface, void *ctx)
317
+{
318
+	struct wpa_auth_ft_iface_iter_data *idata = ctx;
319
+	struct hostapd_data *hapd;
320
+	size_t j;
321
+
322
+	for (j = 0; j < iface->num_bss; j++) {
323
+		hapd = iface->bss[j];
324
+		if (hapd == idata->src_hapd)
325
+			continue;
326
+		if (os_memcmp(hapd->own_addr, idata->dst, ETH_ALEN) == 0) {
327
+			wpa_printf(MSG_DEBUG, "FT: Send RRB data directly to "
328
+				   "locally managed BSS " MACSTR "@%s -> "
329
+				   MACSTR "@%s",
330
+				   MAC2STR(idata->src_hapd->own_addr),
331
+				   idata->src_hapd->conf->iface,
332
+				   MAC2STR(hapd->own_addr), hapd->conf->iface);
333
+			wpa_ft_rrb_rx(hapd->wpa_auth,
334
+				      idata->src_hapd->own_addr,
335
+				      idata->data, idata->data_len);
336
+			return 1;
337
+		}
338
+	}
339
+
340
+	return 0;
341
+}
342
+
343
+#endif /* CONFIG_IEEE80211R */
344
+
345
+
346
+static int hostapd_wpa_auth_send_ether(void *ctx, const u8 *dst, u16 proto,
347
+				       const u8 *data, size_t data_len)
348
+{
349
+	struct hostapd_data *hapd = ctx;
350
+	struct l2_ethhdr *buf;
351
+	int ret;
352
+
353
+#ifdef CONFIG_IEEE80211R
354
+	if (proto == ETH_P_RRB && hapd->iface->for_each_interface) {
355
+		int res;
356
+		struct wpa_auth_ft_iface_iter_data idata;
357
+		idata.src_hapd = hapd;
358
+		idata.dst = dst;
359
+		idata.data = data;
360
+		idata.data_len = data_len;
361
+		res = hapd->iface->for_each_interface(hapd->iface->interfaces,
362
+						      hostapd_wpa_auth_ft_iter,
363
+						      &idata);
364
+		if (res == 1)
365
+			return data_len;
366
+	}
367
+#endif /* CONFIG_IEEE80211R */
368
+
369
+	if (hapd->driver && hapd->driver->send_ether)
370
+		return hapd->driver->send_ether(hapd->drv_priv, dst,
371
+						hapd->own_addr, proto,
372
+						data, data_len);
373
+	if (hapd->l2 == NULL)
374
+		return -1;
375
+
376
+	buf = os_malloc(sizeof(*buf) + data_len);
377
+	if (buf == NULL)
378
+		return -1;
379
+	os_memcpy(buf->h_dest, dst, ETH_ALEN);
380
+	os_memcpy(buf->h_source, hapd->own_addr, ETH_ALEN);
381
+	buf->h_proto = host_to_be16(proto);
382
+	os_memcpy(buf + 1, data, data_len);
383
+	ret = l2_packet_send(hapd->l2, dst, proto, (u8 *) buf,
384
+			     sizeof(*buf) + data_len);
385
+	os_free(buf);
386
+	return -1;
387
+}
388
+
389
+
390
+#ifdef CONFIG_IEEE80211R
391
+
392
+static int hostapd_wpa_auth_send_ft_action(void *ctx, const u8 *dst,
393
+					   const u8 *data, size_t data_len)
394
+{
395
+	struct hostapd_data *hapd = ctx;
396
+	int res;
397
+	struct ieee80211_mgmt *m;
398
+	size_t mlen;
399
+	struct sta_info *sta;
400
+
401
+	sta = ap_get_sta(hapd, dst);
402
+	if (sta == NULL || sta->wpa_sm == NULL)
403
+		return -1;
404
+
405
+	m = os_zalloc(sizeof(*m) + data_len);
406
+	if (m == NULL)
407
+		return -1;
408
+	mlen = ((u8 *) &m->u - (u8 *) m) + data_len;
409
+	m->frame_control = IEEE80211_FC(WLAN_FC_TYPE_MGMT,
410
+					WLAN_FC_STYPE_ACTION);
411
+	os_memcpy(m->da, dst, ETH_ALEN);
412
+	os_memcpy(m->sa, hapd->own_addr, ETH_ALEN);
413
+	os_memcpy(m->bssid, hapd->own_addr, ETH_ALEN);
414
+	os_memcpy(&m->u, data, data_len);
415
+
416
+	res = hostapd_drv_send_mlme(hapd, (u8 *) m, mlen);
417
+	os_free(m);
418
+	return res;
419
+}
420
+
421
+
422
+static struct wpa_state_machine *
423
+hostapd_wpa_auth_add_sta(void *ctx, const u8 *sta_addr)
424
+{
425
+	struct hostapd_data *hapd = ctx;
426
+	struct sta_info *sta;
427
+
428
+	sta = ap_sta_add(hapd, sta_addr);
429
+	if (sta == NULL)
430
+		return NULL;
431
+	if (sta->wpa_sm) {
432
+		sta->auth_alg = WLAN_AUTH_FT;
433
+		return sta->wpa_sm;
434
+	}
435
+
436
+	sta->wpa_sm = wpa_auth_sta_init(hapd->wpa_auth, sta->addr);
437
+	if (sta->wpa_sm == NULL) {
438
+		ap_free_sta(hapd, sta);
439
+		return NULL;
440
+	}
441
+	sta->auth_alg = WLAN_AUTH_FT;
442
+
443
+	return sta->wpa_sm;
444
+}
445
+
446
+
447
+static void hostapd_rrb_receive(void *ctx, const u8 *src_addr, const u8 *buf,
448
+				size_t len)
449
+{
450
+	struct hostapd_data *hapd = ctx;
451
+	struct l2_ethhdr *ethhdr;
452
+	if (len < sizeof(*ethhdr))
453
+		return;
454
+	ethhdr = (struct l2_ethhdr *) buf;
455
+	wpa_printf(MSG_DEBUG, "FT: RRB received packet " MACSTR " -> "
456
+		   MACSTR, MAC2STR(ethhdr->h_source), MAC2STR(ethhdr->h_dest));
457
+	wpa_ft_rrb_rx(hapd->wpa_auth, ethhdr->h_source, buf + sizeof(*ethhdr),
458
+		      len - sizeof(*ethhdr));
459
+}
460
+
461
+#endif /* CONFIG_IEEE80211R */
462
+
463
+
464
+int hostapd_setup_wpa(struct hostapd_data *hapd)
465
+{
466
+	struct wpa_auth_config _conf;
467
+	struct wpa_auth_callbacks cb;
468
+	const u8 *wpa_ie;
469
+	size_t wpa_ie_len;
470
+
471
+	hostapd_wpa_auth_conf(hapd->conf, &_conf);
472
+	if (hapd->iface->drv_flags & WPA_DRIVER_FLAGS_EAPOL_TX_STATUS)
473
+		_conf.tx_status = 1;
474
+	os_memset(&cb, 0, sizeof(cb));
475
+	cb.ctx = hapd;
476
+	cb.logger = hostapd_wpa_auth_logger;
477
+	cb.disconnect = hostapd_wpa_auth_disconnect;
478
+	cb.mic_failure_report = hostapd_wpa_auth_mic_failure_report;
479
+	cb.set_eapol = hostapd_wpa_auth_set_eapol;
480
+	cb.get_eapol = hostapd_wpa_auth_get_eapol;
481
+	cb.get_psk = hostapd_wpa_auth_get_psk;
482
+	cb.get_msk = hostapd_wpa_auth_get_msk;
483
+	cb.set_key = hostapd_wpa_auth_set_key;
484
+	cb.get_seqnum = hostapd_wpa_auth_get_seqnum;
485
+	cb.send_eapol = hostapd_wpa_auth_send_eapol;
486
+	cb.for_each_sta = hostapd_wpa_auth_for_each_sta;
487
+	cb.for_each_auth = hostapd_wpa_auth_for_each_auth;
488
+	cb.send_ether = hostapd_wpa_auth_send_ether;
489
+#ifdef CONFIG_IEEE80211R
490
+	cb.send_ft_action = hostapd_wpa_auth_send_ft_action;
491
+	cb.add_sta = hostapd_wpa_auth_add_sta;
492
+#endif /* CONFIG_IEEE80211R */
493
+	hapd->wpa_auth = wpa_init(hapd->own_addr, &_conf, &cb);
494
+	if (hapd->wpa_auth == NULL) {
495
+		wpa_printf(MSG_ERROR, "WPA initialization failed.");
496
+		return -1;
497
+	}
498
+
499
+	if (hostapd_set_privacy(hapd, 1)) {
500
+		wpa_printf(MSG_ERROR, "Could not set PrivacyInvoked "
501
+			   "for interface %s", hapd->conf->iface);
502
+		return -1;
503
+	}
504
+
505
+	wpa_ie = wpa_auth_get_wpa_ie(hapd->wpa_auth, &wpa_ie_len);
506
+	if (hostapd_set_generic_elem(hapd, wpa_ie, wpa_ie_len)) {
507
+		wpa_printf(MSG_ERROR, "Failed to configure WPA IE for "
508
+			   "the kernel driver.");
509
+		return -1;
510
+	}
511
+
512
+	if (rsn_preauth_iface_init(hapd)) {
513
+		wpa_printf(MSG_ERROR, "Initialization of RSN "
514
+			   "pre-authentication failed.");
515
+		return -1;
516
+	}
517
+
518
+#ifdef CONFIG_IEEE80211R
519
+	if (!hostapd_drv_none(hapd)) {
520
+		hapd->l2 = l2_packet_init(hapd->conf->bridge[0] ?
521
+					  hapd->conf->bridge :
522
+					  hapd->conf->iface, NULL, ETH_P_RRB,
523
+					  hostapd_rrb_receive, hapd, 1);
524
+		if (hapd->l2 == NULL &&
525
+		    (hapd->driver == NULL ||
526
+		     hapd->driver->send_ether == NULL)) {
527
+			wpa_printf(MSG_ERROR, "Failed to open l2_packet "
528
+				   "interface");
529
+			return -1;
530
+		}
531
+	}
532
+#endif /* CONFIG_IEEE80211R */
533
+
534
+	return 0;
535
+
536
+}
537
+
538
+
539
+void hostapd_reconfig_wpa(struct hostapd_data *hapd)
540
+{
541
+	struct wpa_auth_config wpa_auth_conf;
542
+	hostapd_wpa_auth_conf(hapd->conf, &wpa_auth_conf);
543
+	wpa_reconfig(hapd->wpa_auth, &wpa_auth_conf);
544
+}
545
+
546
+
547
+void hostapd_deinit_wpa(struct hostapd_data *hapd)
548
+{
549
+	rsn_preauth_iface_deinit(hapd);
550
+	if (hapd->wpa_auth) {
551
+		wpa_deinit(hapd->wpa_auth);
552
+		hapd->wpa_auth = NULL;
553
+
554
+		if (hostapd_set_privacy(hapd, 0)) {
555
+			wpa_printf(MSG_DEBUG, "Could not disable "
556
+				   "PrivacyInvoked for interface %s",
557
+				   hapd->conf->iface);
558
+		}
559
+
560
+		if (hostapd_set_generic_elem(hapd, (u8 *) "", 0)) {
561
+			wpa_printf(MSG_DEBUG, "Could not remove generic "
562
+				   "information element from interface %s",
563
+				   hapd->conf->iface);
564
+		}
565
+	}
566
+	ieee802_1x_deinit(hapd);
567
+
568
+#ifdef CONFIG_IEEE80211R
569
+	l2_packet_deinit(hapd->l2);
570
+#endif /* CONFIG_IEEE80211R */
571
+}

+ 22
- 0
src/ap/wpa_auth_glue.h Näytä tiedosto

@@ -0,0 +1,22 @@
1
+/*
2
+ * hostapd / WPA authenticator glue code
3
+ * Copyright (c) 2002-2009, Jouni Malinen <j@w1.fi>
4
+ *
5
+ * This program is free software; you can redistribute it and/or modify
6
+ * it under the terms of the GNU General Public License version 2 as
7
+ * published by the Free Software Foundation.
8
+ *
9
+ * Alternatively, this software may be distributed under the terms of BSD
10
+ * license.
11
+ *
12
+ * See README and COPYING for more details.
13
+ */
14
+
15
+#ifndef WPA_AUTH_GLUE_H
16
+#define WPA_AUTH_GLUE_H
17
+
18
+int hostapd_setup_wpa(struct hostapd_data *hapd);
19
+void hostapd_reconfig_wpa(struct hostapd_data *hapd);
20
+void hostapd_deinit_wpa(struct hostapd_data *hapd);
21
+
22
+#endif /* WPA_AUTH_GLUE_H */

+ 234
- 0
src/ap/wpa_auth_i.h Näytä tiedosto

@@ -0,0 +1,234 @@
1
+/*
2
+ * hostapd - IEEE 802.11i-2004 / WPA Authenticator: Internal definitions
3
+ * Copyright (c) 2004-2007, Jouni Malinen <j@w1.fi>
4
+ *
5
+ * This program is free software; you can redistribute it and/or modify
6
+ * it under the terms of the GNU General Public License version 2 as
7
+ * published by the Free Software Foundation.
8
+ *
9
+ * Alternatively, this software may be distributed under the terms of BSD
10
+ * license.
11
+ *
12
+ * See README and COPYING for more details.
13
+ */
14
+
15
+#ifndef WPA_AUTH_I_H
16
+#define WPA_AUTH_I_H
17
+
18
+/* max(dot11RSNAConfigGroupUpdateCount,dot11RSNAConfigPairwiseUpdateCount) */
19
+#define RSNA_MAX_EAPOL_RETRIES 4
20
+
21
+struct wpa_group;
22
+
23
+struct wpa_stsl_negotiation {
24
+	struct wpa_stsl_negotiation *next;
25
+	u8 initiator[ETH_ALEN];
26
+	u8 peer[ETH_ALEN];
27
+};
28
+
29
+
30
+struct wpa_state_machine {
31
+	struct wpa_authenticator *wpa_auth;
32
+	struct wpa_group *group;
33
+
34
+	u8 addr[ETH_ALEN];
35
+
36
+	enum {
37
+		WPA_PTK_INITIALIZE, WPA_PTK_DISCONNECT, WPA_PTK_DISCONNECTED,
38
+		WPA_PTK_AUTHENTICATION, WPA_PTK_AUTHENTICATION2,
39
+		WPA_PTK_INITPMK, WPA_PTK_INITPSK, WPA_PTK_PTKSTART,
40
+		WPA_PTK_PTKCALCNEGOTIATING, WPA_PTK_PTKCALCNEGOTIATING2,
41
+		WPA_PTK_PTKINITNEGOTIATING, WPA_PTK_PTKINITDONE
42
+	} wpa_ptk_state;
43
+
44
+	enum {
45
+		WPA_PTK_GROUP_IDLE = 0,
46
+		WPA_PTK_GROUP_REKEYNEGOTIATING,
47
+		WPA_PTK_GROUP_REKEYESTABLISHED,
48
+		WPA_PTK_GROUP_KEYERROR
49
+	} wpa_ptk_group_state;
50
+
51
+	Boolean Init;
52
+	Boolean DeauthenticationRequest;
53
+	Boolean AuthenticationRequest;
54
+	Boolean ReAuthenticationRequest;
55
+	Boolean Disconnect;
56
+	int TimeoutCtr;
57
+	int GTimeoutCtr;
58
+	Boolean TimeoutEvt;
59
+	Boolean EAPOLKeyReceived;
60
+	Boolean EAPOLKeyPairwise;
61
+	Boolean EAPOLKeyRequest;
62
+	Boolean MICVerified;
63
+	Boolean GUpdateStationKeys;
64
+	u8 ANonce[WPA_NONCE_LEN];
65
+	u8 SNonce[WPA_NONCE_LEN];
66
+	u8 PMK[PMK_LEN];
67
+	struct wpa_ptk PTK;
68
+	Boolean PTK_valid;
69
+	Boolean pairwise_set;
70
+	int keycount;
71
+	Boolean Pair;
72
+	struct {
73
+		u8 counter[WPA_REPLAY_COUNTER_LEN];
74
+		Boolean valid;
75
+	} key_replay[RSNA_MAX_EAPOL_RETRIES];
76
+	Boolean PInitAKeys; /* WPA only, not in IEEE 802.11i */
77
+	Boolean PTKRequest; /* not in IEEE 802.11i state machine */
78
+	Boolean has_GTK;
79
+	Boolean PtkGroupInit; /* init request for PTK Group state machine */
80
+
81
+	u8 *last_rx_eapol_key; /* starting from IEEE 802.1X header */
82
+	size_t last_rx_eapol_key_len;
83
+
84
+	unsigned int changed:1;
85
+	unsigned int in_step_loop:1;
86
+	unsigned int pending_deinit:1;
87
+	unsigned int started:1;
88
+	unsigned int mgmt_frame_prot:1;
89
+#ifdef CONFIG_IEEE80211R
90
+	unsigned int ft_completed:1;
91
+	unsigned int pmk_r1_name_valid:1;
92
+#endif /* CONFIG_IEEE80211R */
93
+
94
+	u8 req_replay_counter[WPA_REPLAY_COUNTER_LEN];
95
+	int req_replay_counter_used;
96
+
97
+	u8 *wpa_ie;
98
+	size_t wpa_ie_len;
99
+
100
+	enum {
101
+		WPA_VERSION_NO_WPA = 0 /* WPA not used */,
102
+		WPA_VERSION_WPA = 1 /* WPA / IEEE 802.11i/D3.0 */,
103
+		WPA_VERSION_WPA2 = 2 /* WPA2 / IEEE 802.11i */
104
+	} wpa;
105
+	int pairwise; /* Pairwise cipher suite, WPA_CIPHER_* */
106
+	int wpa_key_mgmt; /* the selected WPA_KEY_MGMT_* */
107
+	struct rsn_pmksa_cache_entry *pmksa;
108
+
109
+	u32 dot11RSNAStatsTKIPLocalMICFailures;
110
+	u32 dot11RSNAStatsTKIPRemoteMICFailures;
111
+
112
+#ifdef CONFIG_IEEE80211R
113
+	u8 xxkey[PMK_LEN]; /* PSK or the second 256 bits of MSK */
114
+	size_t xxkey_len;
115
+	u8 pmk_r1_name[WPA_PMK_NAME_LEN]; /* PMKR1Name derived from FT Auth
116
+					   * Request */
117
+	u8 r0kh_id[FT_R0KH_ID_MAX_LEN]; /* R0KH-ID from FT Auth Request */
118
+	size_t r0kh_id_len;
119
+	u8 sup_pmk_r1_name[WPA_PMK_NAME_LEN]; /* PMKR1Name from EAPOL-Key
120
+					       * message 2/4 */
121
+	u8 *assoc_resp_ftie;
122
+#endif /* CONFIG_IEEE80211R */
123
+
124
+	int pending_1_of_4_timeout;
125
+};
126
+
127
+
128
+/* per group key state machine data */
129
+struct wpa_group {
130
+	struct wpa_group *next;
131
+	int vlan_id;
132
+
133
+	Boolean GInit;
134
+	int GKeyDoneStations;
135
+	Boolean GTKReKey;
136
+	int GTK_len;
137
+	int GN, GM;
138
+	Boolean GTKAuthenticator;
139
+	u8 Counter[WPA_NONCE_LEN];
140
+
141
+	enum {
142
+		WPA_GROUP_GTK_INIT = 0,
143
+		WPA_GROUP_SETKEYS, WPA_GROUP_SETKEYSDONE
144
+	} wpa_group_state;
145
+
146
+	u8 GMK[WPA_GMK_LEN];
147
+	u8 GTK[2][WPA_GTK_MAX_LEN];
148
+	u8 GNonce[WPA_NONCE_LEN];
149
+	Boolean changed;
150
+	Boolean first_sta_seen;
151
+	Boolean reject_4way_hs_for_entropy;
152
+#ifdef CONFIG_IEEE80211W
153
+	u8 IGTK[2][WPA_IGTK_LEN];
154
+	int GN_igtk, GM_igtk;
155
+#endif /* CONFIG_IEEE80211W */
156
+};
157
+
158
+
159
+struct wpa_ft_pmk_cache;
160
+
161
+/* per authenticator data */
162
+struct wpa_authenticator {
163
+	struct wpa_group *group;
164
+
165
+	unsigned int dot11RSNAStatsTKIPRemoteMICFailures;
166
+	u32 dot11RSNAAuthenticationSuiteSelected;
167
+	u32 dot11RSNAPairwiseCipherSelected;
168
+	u32 dot11RSNAGroupCipherSelected;
169
+	u8 dot11RSNAPMKIDUsed[PMKID_LEN];
170
+	u32 dot11RSNAAuthenticationSuiteRequested; /* FIX: update */
171
+	u32 dot11RSNAPairwiseCipherRequested; /* FIX: update */
172
+	u32 dot11RSNAGroupCipherRequested; /* FIX: update */
173
+	unsigned int dot11RSNATKIPCounterMeasuresInvoked;
174
+	unsigned int dot11RSNA4WayHandshakeFailures;
175
+
176
+	struct wpa_stsl_negotiation *stsl_negotiations;
177
+
178
+	struct wpa_auth_config conf;
179
+	struct wpa_auth_callbacks cb;
180
+
181
+	u8 *wpa_ie;
182
+	size_t wpa_ie_len;
183
+
184
+	u8 addr[ETH_ALEN];
185
+
186
+	struct rsn_pmksa_cache *pmksa;
187
+	struct wpa_ft_pmk_cache *ft_pmk_cache;
188
+};
189
+
190
+
191
+int wpa_write_rsn_ie(struct wpa_auth_config *conf, u8 *buf, size_t len,
192
+		     const u8 *pmkid);
193
+void wpa_auth_logger(struct wpa_authenticator *wpa_auth, const u8 *addr,
194
+		     logger_level level, const char *txt);
195
+void wpa_auth_vlogger(struct wpa_authenticator *wpa_auth, const u8 *addr,
196
+		      logger_level level, const char *fmt, ...);
197
+void __wpa_send_eapol(struct wpa_authenticator *wpa_auth,
198
+		      struct wpa_state_machine *sm, int key_info,
199
+		      const u8 *key_rsc, const u8 *nonce,
200
+		      const u8 *kde, size_t kde_len,
201
+		      int keyidx, int encr, int force_version);
202
+int wpa_auth_for_each_sta(struct wpa_authenticator *wpa_auth,
203
+			  int (*cb)(struct wpa_state_machine *sm, void *ctx),
204
+			  void *cb_ctx);
205
+int wpa_auth_for_each_auth(struct wpa_authenticator *wpa_auth,
206
+			   int (*cb)(struct wpa_authenticator *a, void *ctx),
207
+			   void *cb_ctx);
208
+
209
+#ifdef CONFIG_PEERKEY
210
+int wpa_stsl_remove(struct wpa_authenticator *wpa_auth,
211
+		    struct wpa_stsl_negotiation *neg);
212
+void wpa_smk_error(struct wpa_authenticator *wpa_auth,
213
+		   struct wpa_state_machine *sm, struct wpa_eapol_key *key);
214
+void wpa_smk_m1(struct wpa_authenticator *wpa_auth,
215
+		struct wpa_state_machine *sm, struct wpa_eapol_key *key);
216
+void wpa_smk_m3(struct wpa_authenticator *wpa_auth,
217
+		struct wpa_state_machine *sm, struct wpa_eapol_key *key);
218
+#endif /* CONFIG_PEERKEY */
219
+
220
+#ifdef CONFIG_IEEE80211R
221
+int wpa_write_mdie(struct wpa_auth_config *conf, u8 *buf, size_t len);
222
+int wpa_write_ftie(struct wpa_auth_config *conf, const u8 *r0kh_id,
223
+		   size_t r0kh_id_len,
224
+		   const u8 *anonce, const u8 *snonce,
225
+		   u8 *buf, size_t len, const u8 *subelem,
226
+		   size_t subelem_len);
227
+int wpa_auth_derive_ptk_ft(struct wpa_state_machine *sm, const u8 *pmk,
228
+			   struct wpa_ptk *ptk, size_t ptk_len);
229
+struct wpa_ft_pmk_cache * wpa_ft_pmk_cache_init(void);
230
+void wpa_ft_pmk_cache_deinit(struct wpa_ft_pmk_cache *cache);
231
+void wpa_ft_install_ptk(struct wpa_state_machine *sm);
232
+#endif /* CONFIG_IEEE80211R */
233
+
234
+#endif /* WPA_AUTH_I_H */

+ 824
- 0
src/ap/wpa_auth_ie.c Näytä tiedosto

@@ -0,0 +1,824 @@
1
+/*
2
+ * hostapd - WPA/RSN IE and KDE definitions
3
+ * Copyright (c) 2004-2008, Jouni Malinen <j@w1.fi>
4
+ *
5
+ * This program is free software; you can redistribute it and/or modify
6
+ * it under the terms of the GNU General Public License version 2 as
7
+ * published by the Free Software Foundation.
8
+ *
9
+ * Alternatively, this software may be distributed under the terms of BSD
10
+ * license.
11
+ *
12
+ * See README and COPYING for more details.
13
+ */
14
+
15
+#include "utils/includes.h"
16
+
17
+#include "utils/common.h"
18
+#include "common/ieee802_11_defs.h"
19
+#include "eapol_auth/eapol_auth_sm.h"
20
+#include "ap_config.h"
21
+#include "ieee802_11.h"
22
+#include "wpa_auth.h"
23
+#include "pmksa_cache_auth.h"
24
+#include "wpa_auth_ie.h"
25
+#include "wpa_auth_i.h"
26
+
27
+
28
+#ifdef CONFIG_RSN_TESTING
29
+int rsn_testing = 0;
30
+#endif /* CONFIG_RSN_TESTING */
31
+
32
+
33
+static int wpa_write_wpa_ie(struct wpa_auth_config *conf, u8 *buf, size_t len)
34
+{
35
+	struct wpa_ie_hdr *hdr;
36
+	int num_suites;
37
+	u8 *pos, *count;
38
+
39
+	hdr = (struct wpa_ie_hdr *) buf;
40
+	hdr->elem_id = WLAN_EID_VENDOR_SPECIFIC;
41
+	RSN_SELECTOR_PUT(hdr->oui, WPA_OUI_TYPE);
42
+	WPA_PUT_LE16(hdr->version, WPA_VERSION);
43
+	pos = (u8 *) (hdr + 1);
44
+
45
+	if (conf->wpa_group == WPA_CIPHER_CCMP) {
46
+		RSN_SELECTOR_PUT(pos, WPA_CIPHER_SUITE_CCMP);
47
+	} else if (conf->wpa_group == WPA_CIPHER_TKIP) {
48
+		RSN_SELECTOR_PUT(pos, WPA_CIPHER_SUITE_TKIP);
49
+	} else if (conf->wpa_group == WPA_CIPHER_WEP104) {
50
+		RSN_SELECTOR_PUT(pos, WPA_CIPHER_SUITE_WEP104);
51
+	} else if (conf->wpa_group == WPA_CIPHER_WEP40) {
52
+		RSN_SELECTOR_PUT(pos, WPA_CIPHER_SUITE_WEP40);
53
+	} else {
54
+		wpa_printf(MSG_DEBUG, "Invalid group cipher (%d).",
55
+			   conf->wpa_group);
56
+		return -1;
57
+	}
58
+	pos += WPA_SELECTOR_LEN;
59
+
60
+	num_suites = 0;
61
+	count = pos;
62
+	pos += 2;
63
+
64
+	if (conf->wpa_pairwise & WPA_CIPHER_CCMP) {
65
+		RSN_SELECTOR_PUT(pos, WPA_CIPHER_SUITE_CCMP);
66
+		pos += WPA_SELECTOR_LEN;
67
+		num_suites++;
68
+	}
69
+	if (conf->wpa_pairwise & WPA_CIPHER_TKIP) {
70
+		RSN_SELECTOR_PUT(pos, WPA_CIPHER_SUITE_TKIP);
71
+		pos += WPA_SELECTOR_LEN;
72
+		num_suites++;
73
+	}
74
+	if (conf->wpa_pairwise & WPA_CIPHER_NONE) {
75
+		RSN_SELECTOR_PUT(pos, WPA_CIPHER_SUITE_NONE);
76
+		pos += WPA_SELECTOR_LEN;
77
+		num_suites++;
78
+	}
79
+
80
+	if (num_suites == 0) {
81
+		wpa_printf(MSG_DEBUG, "Invalid pairwise cipher (%d).",
82
+			   conf->wpa_pairwise);
83
+		return -1;
84
+	}
85
+	WPA_PUT_LE16(count, num_suites);
86
+
87
+	num_suites = 0;
88
+	count = pos;
89
+	pos += 2;
90
+
91
+	if (conf->wpa_key_mgmt & WPA_KEY_MGMT_IEEE8021X) {
92
+		RSN_SELECTOR_PUT(pos, WPA_AUTH_KEY_MGMT_UNSPEC_802_1X);
93
+		pos += WPA_SELECTOR_LEN;
94
+		num_suites++;
95
+	}
96
+	if (conf->wpa_key_mgmt & WPA_KEY_MGMT_PSK) {
97
+		RSN_SELECTOR_PUT(pos, WPA_AUTH_KEY_MGMT_PSK_OVER_802_1X);
98
+		pos += WPA_SELECTOR_LEN;
99
+		num_suites++;
100
+	}
101
+
102
+	if (num_suites == 0) {
103
+		wpa_printf(MSG_DEBUG, "Invalid key management type (%d).",
104
+			   conf->wpa_key_mgmt);
105
+		return -1;
106
+	}
107
+	WPA_PUT_LE16(count, num_suites);
108
+
109
+	/* WPA Capabilities; use defaults, so no need to include it */
110
+
111
+	hdr->len = (pos - buf) - 2;
112
+
113
+	return pos - buf;
114
+}
115
+
116
+
117
+int wpa_write_rsn_ie(struct wpa_auth_config *conf, u8 *buf, size_t len,
118
+		     const u8 *pmkid)
119
+{
120
+	struct rsn_ie_hdr *hdr;
121
+	int num_suites;
122
+	u8 *pos, *count;
123
+	u16 capab;
124
+
125
+	hdr = (struct rsn_ie_hdr *) buf;
126
+	hdr->elem_id = WLAN_EID_RSN;
127
+	WPA_PUT_LE16(hdr->version, RSN_VERSION);
128
+	pos = (u8 *) (hdr + 1);
129
+
130
+	if (conf->wpa_group == WPA_CIPHER_CCMP) {
131
+		RSN_SELECTOR_PUT(pos, RSN_CIPHER_SUITE_CCMP);
132
+	} else if (conf->wpa_group == WPA_CIPHER_TKIP) {
133
+		RSN_SELECTOR_PUT(pos, RSN_CIPHER_SUITE_TKIP);
134
+	} else if (conf->wpa_group == WPA_CIPHER_WEP104) {
135
+		RSN_SELECTOR_PUT(pos, RSN_CIPHER_SUITE_WEP104);
136
+	} else if (conf->wpa_group == WPA_CIPHER_WEP40) {
137
+		RSN_SELECTOR_PUT(pos, RSN_CIPHER_SUITE_WEP40);
138
+	} else {
139
+		wpa_printf(MSG_DEBUG, "Invalid group cipher (%d).",
140
+			   conf->wpa_group);
141
+		return -1;
142
+	}
143
+	pos += RSN_SELECTOR_LEN;
144
+
145
+	num_suites = 0;
146
+	count = pos;
147
+	pos += 2;
148
+
149
+#ifdef CONFIG_RSN_TESTING
150
+	if (rsn_testing) {
151
+		RSN_SELECTOR_PUT(pos, RSN_SELECTOR(0x12, 0x34, 0x56, 1));
152
+		pos += RSN_SELECTOR_LEN;
153
+		num_suites++;
154
+	}
155
+#endif /* CONFIG_RSN_TESTING */
156
+
157
+	if (conf->rsn_pairwise & WPA_CIPHER_CCMP) {
158
+		RSN_SELECTOR_PUT(pos, RSN_CIPHER_SUITE_CCMP);
159
+		pos += RSN_SELECTOR_LEN;
160
+		num_suites++;
161
+	}
162
+	if (conf->rsn_pairwise & WPA_CIPHER_TKIP) {
163
+		RSN_SELECTOR_PUT(pos, RSN_CIPHER_SUITE_TKIP);
164
+		pos += RSN_SELECTOR_LEN;
165
+		num_suites++;
166
+	}
167
+	if (conf->rsn_pairwise & WPA_CIPHER_NONE) {
168
+		RSN_SELECTOR_PUT(pos, RSN_CIPHER_SUITE_NONE);
169
+		pos += RSN_SELECTOR_LEN;
170
+		num_suites++;
171
+	}
172
+
173
+#ifdef CONFIG_RSN_TESTING
174
+	if (rsn_testing) {
175
+		RSN_SELECTOR_PUT(pos, RSN_SELECTOR(0x12, 0x34, 0x56, 2));
176
+		pos += RSN_SELECTOR_LEN;
177
+		num_suites++;
178
+	}
179
+#endif /* CONFIG_RSN_TESTING */
180
+
181
+	if (num_suites == 0) {
182
+		wpa_printf(MSG_DEBUG, "Invalid pairwise cipher (%d).",
183
+			   conf->rsn_pairwise);
184
+		return -1;
185
+	}
186
+	WPA_PUT_LE16(count, num_suites);
187
+
188
+	num_suites = 0;
189
+	count = pos;
190
+	pos += 2;
191
+
192
+#ifdef CONFIG_RSN_TESTING
193
+	if (rsn_testing) {
194
+		RSN_SELECTOR_PUT(pos, RSN_SELECTOR(0x12, 0x34, 0x56, 1));
195
+		pos += RSN_SELECTOR_LEN;
196
+		num_suites++;
197
+	}
198
+#endif /* CONFIG_RSN_TESTING */
199
+
200
+	if (conf->wpa_key_mgmt & WPA_KEY_MGMT_IEEE8021X) {
201
+		RSN_SELECTOR_PUT(pos, RSN_AUTH_KEY_MGMT_UNSPEC_802_1X);
202
+		pos += RSN_SELECTOR_LEN;
203
+		num_suites++;
204
+	}
205
+	if (conf->wpa_key_mgmt & WPA_KEY_MGMT_PSK) {
206
+		RSN_SELECTOR_PUT(pos, RSN_AUTH_KEY_MGMT_PSK_OVER_802_1X);
207
+		pos += RSN_SELECTOR_LEN;
208
+		num_suites++;
209
+	}
210
+#ifdef CONFIG_IEEE80211R
211
+	if (conf->wpa_key_mgmt & WPA_KEY_MGMT_FT_IEEE8021X) {
212
+		RSN_SELECTOR_PUT(pos, RSN_AUTH_KEY_MGMT_FT_802_1X);
213
+		pos += RSN_SELECTOR_LEN;
214
+		num_suites++;
215
+	}
216
+	if (conf->wpa_key_mgmt & WPA_KEY_MGMT_FT_PSK) {
217
+		RSN_SELECTOR_PUT(pos, RSN_AUTH_KEY_MGMT_FT_PSK);
218
+		pos += RSN_SELECTOR_LEN;
219
+		num_suites++;
220
+	}
221
+#endif /* CONFIG_IEEE80211R */
222
+#ifdef CONFIG_IEEE80211W
223
+	if (conf->wpa_key_mgmt & WPA_KEY_MGMT_IEEE8021X_SHA256) {
224
+		RSN_SELECTOR_PUT(pos, RSN_AUTH_KEY_MGMT_802_1X_SHA256);
225
+		pos += RSN_SELECTOR_LEN;
226
+		num_suites++;
227
+	}
228
+	if (conf->wpa_key_mgmt & WPA_KEY_MGMT_PSK_SHA256) {
229
+		RSN_SELECTOR_PUT(pos, RSN_AUTH_KEY_MGMT_PSK_SHA256);
230
+		pos += RSN_SELECTOR_LEN;
231
+		num_suites++;
232
+	}
233
+#endif /* CONFIG_IEEE80211W */
234
+
235
+#ifdef CONFIG_RSN_TESTING
236
+	if (rsn_testing) {
237
+		RSN_SELECTOR_PUT(pos, RSN_SELECTOR(0x12, 0x34, 0x56, 2));
238
+		pos += RSN_SELECTOR_LEN;
239
+		num_suites++;
240
+	}
241
+#endif /* CONFIG_RSN_TESTING */
242
+
243
+	if (num_suites == 0) {
244
+		wpa_printf(MSG_DEBUG, "Invalid key management type (%d).",
245
+			   conf->wpa_key_mgmt);
246
+		return -1;
247
+	}
248
+	WPA_PUT_LE16(count, num_suites);
249
+
250
+	/* RSN Capabilities */
251
+	capab = 0;
252
+	if (conf->rsn_preauth)
253
+		capab |= WPA_CAPABILITY_PREAUTH;
254
+	if (conf->peerkey)
255
+		capab |= WPA_CAPABILITY_PEERKEY_ENABLED;
256
+	if (conf->wmm_enabled) {
257
+		/* 4 PTKSA replay counters when using WMM */
258
+		capab |= (RSN_NUM_REPLAY_COUNTERS_16 << 2);
259
+	}
260
+#ifdef CONFIG_IEEE80211W
261
+	if (conf->ieee80211w != NO_MGMT_FRAME_PROTECTION) {
262
+		capab |= WPA_CAPABILITY_MFPC;
263
+		if (conf->ieee80211w == MGMT_FRAME_PROTECTION_REQUIRED)
264
+			capab |= WPA_CAPABILITY_MFPR;
265
+	}
266
+#endif /* CONFIG_IEEE80211W */
267
+#ifdef CONFIG_RSN_TESTING
268
+	if (rsn_testing)
269
+		capab |= BIT(8) | BIT(14) | BIT(15);
270
+#endif /* CONFIG_RSN_TESTING */
271
+	WPA_PUT_LE16(pos, capab);
272
+	pos += 2;
273
+
274
+	if (pmkid) {
275
+		if (pos + 2 + PMKID_LEN > buf + len)
276
+			return -1;
277
+		/* PMKID Count */
278
+		WPA_PUT_LE16(pos, 1);
279
+		pos += 2;
280
+		os_memcpy(pos, pmkid, PMKID_LEN);
281
+		pos += PMKID_LEN;
282
+	}
283
+
284
+#ifdef CONFIG_IEEE80211W
285
+	if (conf->ieee80211w != NO_MGMT_FRAME_PROTECTION) {
286
+		if (pos + 2 + 4 > buf + len)
287
+			return -1;
288
+		if (pmkid == NULL) {
289
+			/* PMKID Count */
290
+			WPA_PUT_LE16(pos, 0);
291
+			pos += 2;
292
+		}
293
+
294
+		/* Management Group Cipher Suite */
295
+		RSN_SELECTOR_PUT(pos, RSN_CIPHER_SUITE_AES_128_CMAC);
296
+		pos += RSN_SELECTOR_LEN;
297
+	}
298
+#endif /* CONFIG_IEEE80211W */
299
+
300
+#ifdef CONFIG_RSN_TESTING
301
+	if (rsn_testing) {
302
+		/*
303
+		 * Fill in any defined fields and add extra data to the end of
304
+		 * the element.
305
+		 */
306
+		int pmkid_count_set = pmkid != NULL;
307
+		if (conf->ieee80211w != NO_MGMT_FRAME_PROTECTION)
308
+			pmkid_count_set = 1;
309
+		/* PMKID Count */
310
+		WPA_PUT_LE16(pos, 0);
311
+		pos += 2;
312
+		if (conf->ieee80211w == NO_MGMT_FRAME_PROTECTION) {
313
+			/* Management Group Cipher Suite */
314
+			RSN_SELECTOR_PUT(pos, RSN_CIPHER_SUITE_AES_128_CMAC);
315
+			pos += RSN_SELECTOR_LEN;
316
+		}
317
+
318
+		os_memset(pos, 0x12, 17);
319
+		pos += 17;
320
+	}
321
+#endif /* CONFIG_RSN_TESTING */
322
+
323
+	hdr->len = (pos - buf) - 2;
324
+
325
+	return pos - buf;
326
+}
327
+
328
+
329
+int wpa_auth_gen_wpa_ie(struct wpa_authenticator *wpa_auth)
330
+{
331
+	u8 *pos, buf[128];
332
+	int res;
333
+
334
+	pos = buf;
335
+
336
+	if (wpa_auth->conf.wpa & WPA_PROTO_RSN) {
337
+		res = wpa_write_rsn_ie(&wpa_auth->conf,
338
+				       pos, buf + sizeof(buf) - pos, NULL);
339
+		if (res < 0)
340
+			return res;
341
+		pos += res;
342
+	}
343
+#ifdef CONFIG_IEEE80211R
344
+	if (wpa_auth->conf.wpa_key_mgmt &
345
+	    (WPA_KEY_MGMT_FT_IEEE8021X | WPA_KEY_MGMT_FT_PSK)) {
346
+		res = wpa_write_mdie(&wpa_auth->conf, pos,
347
+				     buf + sizeof(buf) - pos);
348
+		if (res < 0)
349
+			return res;
350
+		pos += res;
351
+	}
352
+#endif /* CONFIG_IEEE80211R */
353
+	if (wpa_auth->conf.wpa & WPA_PROTO_WPA) {
354
+		res = wpa_write_wpa_ie(&wpa_auth->conf,
355
+				       pos, buf + sizeof(buf) - pos);
356
+		if (res < 0)
357
+			return res;
358
+		pos += res;
359
+	}
360
+
361
+	os_free(wpa_auth->wpa_ie);
362
+	wpa_auth->wpa_ie = os_malloc(pos - buf);
363
+	if (wpa_auth->wpa_ie == NULL)
364
+		return -1;
365
+	os_memcpy(wpa_auth->wpa_ie, buf, pos - buf);
366
+	wpa_auth->wpa_ie_len = pos - buf;
367
+
368
+	return 0;
369
+}
370
+
371
+
372
+u8 * wpa_add_kde(u8 *pos, u32 kde, const u8 *data, size_t data_len,
373
+		 const u8 *data2, size_t data2_len)
374
+{
375
+	*pos++ = WLAN_EID_VENDOR_SPECIFIC;
376
+	*pos++ = RSN_SELECTOR_LEN + data_len + data2_len;
377
+	RSN_SELECTOR_PUT(pos, kde);
378
+	pos += RSN_SELECTOR_LEN;
379
+	os_memcpy(pos, data, data_len);
380
+	pos += data_len;
381
+	if (data2) {
382
+		os_memcpy(pos, data2, data2_len);
383
+		pos += data2_len;
384
+	}
385
+	return pos;
386
+}
387
+
388
+
389
+struct wpa_auth_okc_iter_data {
390
+	struct rsn_pmksa_cache_entry *pmksa;
391
+	const u8 *aa;
392
+	const u8 *spa;
393
+	const u8 *pmkid;
394
+};
395
+
396
+
397
+static int wpa_auth_okc_iter(struct wpa_authenticator *a, void *ctx)
398
+{
399
+	struct wpa_auth_okc_iter_data *data = ctx;
400
+	data->pmksa = pmksa_cache_get_okc(a->pmksa, data->aa, data->spa,
401
+					  data->pmkid);
402
+	if (data->pmksa)
403
+		return 1;
404
+	return 0;
405
+}
406
+
407
+
408
+int wpa_validate_wpa_ie(struct wpa_authenticator *wpa_auth,
409
+			struct wpa_state_machine *sm,
410
+			const u8 *wpa_ie, size_t wpa_ie_len,
411
+			const u8 *mdie, size_t mdie_len)
412
+{
413
+	struct wpa_ie_data data;
414
+	int ciphers, key_mgmt, res, version;
415
+	u32 selector;
416
+	size_t i;
417
+	const u8 *pmkid = NULL;
418
+
419
+	if (wpa_auth == NULL || sm == NULL)
420
+		return WPA_NOT_ENABLED;
421
+
422
+	if (wpa_ie == NULL || wpa_ie_len < 1)
423
+		return WPA_INVALID_IE;
424
+
425
+	if (wpa_ie[0] == WLAN_EID_RSN)
426
+		version = WPA_PROTO_RSN;
427
+	else
428
+		version = WPA_PROTO_WPA;
429
+
430
+	if (!(wpa_auth->conf.wpa & version)) {
431
+		wpa_printf(MSG_DEBUG, "Invalid WPA proto (%d) from " MACSTR,
432
+			   version, MAC2STR(sm->addr));
433
+		return WPA_INVALID_PROTO;
434
+	}
435
+
436
+	if (version == WPA_PROTO_RSN) {
437
+		res = wpa_parse_wpa_ie_rsn(wpa_ie, wpa_ie_len, &data);
438
+
439
+		selector = RSN_AUTH_KEY_MGMT_UNSPEC_802_1X;
440
+		if (0) {
441
+		}
442
+#ifdef CONFIG_IEEE80211R
443
+		else if (data.key_mgmt & WPA_KEY_MGMT_FT_IEEE8021X)
444
+			selector = RSN_AUTH_KEY_MGMT_FT_802_1X;
445
+		else if (data.key_mgmt & WPA_KEY_MGMT_FT_PSK)
446
+			selector = RSN_AUTH_KEY_MGMT_FT_PSK;
447
+#endif /* CONFIG_IEEE80211R */
448
+#ifdef CONFIG_IEEE80211W
449
+		else if (data.key_mgmt & WPA_KEY_MGMT_IEEE8021X_SHA256)
450
+			selector = RSN_AUTH_KEY_MGMT_802_1X_SHA256;
451
+		else if (data.key_mgmt & WPA_KEY_MGMT_PSK_SHA256)
452
+			selector = RSN_AUTH_KEY_MGMT_PSK_SHA256;
453
+#endif /* CONFIG_IEEE80211W */
454
+		else if (data.key_mgmt & WPA_KEY_MGMT_IEEE8021X)
455
+			selector = RSN_AUTH_KEY_MGMT_UNSPEC_802_1X;
456
+		else if (data.key_mgmt & WPA_KEY_MGMT_PSK)
457
+			selector = RSN_AUTH_KEY_MGMT_PSK_OVER_802_1X;
458
+		wpa_auth->dot11RSNAAuthenticationSuiteSelected = selector;
459
+
460
+		selector = RSN_CIPHER_SUITE_CCMP;
461
+		if (data.pairwise_cipher & WPA_CIPHER_CCMP)
462
+			selector = RSN_CIPHER_SUITE_CCMP;
463
+		else if (data.pairwise_cipher & WPA_CIPHER_TKIP)
464
+			selector = RSN_CIPHER_SUITE_TKIP;
465
+		else if (data.pairwise_cipher & WPA_CIPHER_WEP104)
466
+			selector = RSN_CIPHER_SUITE_WEP104;
467
+		else if (data.pairwise_cipher & WPA_CIPHER_WEP40)
468
+			selector = RSN_CIPHER_SUITE_WEP40;
469
+		else if (data.pairwise_cipher & WPA_CIPHER_NONE)
470
+			selector = RSN_CIPHER_SUITE_NONE;
471
+		wpa_auth->dot11RSNAPairwiseCipherSelected = selector;
472
+
473
+		selector = RSN_CIPHER_SUITE_CCMP;
474
+		if (data.group_cipher & WPA_CIPHER_CCMP)
475
+			selector = RSN_CIPHER_SUITE_CCMP;
476
+		else if (data.group_cipher & WPA_CIPHER_TKIP)
477
+			selector = RSN_CIPHER_SUITE_TKIP;
478
+		else if (data.group_cipher & WPA_CIPHER_WEP104)
479
+			selector = RSN_CIPHER_SUITE_WEP104;
480
+		else if (data.group_cipher & WPA_CIPHER_WEP40)
481
+			selector = RSN_CIPHER_SUITE_WEP40;
482
+		else if (data.group_cipher & WPA_CIPHER_NONE)
483
+			selector = RSN_CIPHER_SUITE_NONE;
484
+		wpa_auth->dot11RSNAGroupCipherSelected = selector;
485
+	} else {
486
+		res = wpa_parse_wpa_ie_wpa(wpa_ie, wpa_ie_len, &data);
487
+
488
+		selector = WPA_AUTH_KEY_MGMT_UNSPEC_802_1X;
489
+		if (data.key_mgmt & WPA_KEY_MGMT_IEEE8021X)
490
+			selector = WPA_AUTH_KEY_MGMT_UNSPEC_802_1X;
491
+		else if (data.key_mgmt & WPA_KEY_MGMT_PSK)
492
+			selector = WPA_AUTH_KEY_MGMT_PSK_OVER_802_1X;
493
+		wpa_auth->dot11RSNAAuthenticationSuiteSelected = selector;
494
+
495
+		selector = WPA_CIPHER_SUITE_TKIP;
496
+		if (data.pairwise_cipher & WPA_CIPHER_CCMP)
497
+			selector = WPA_CIPHER_SUITE_CCMP;
498
+		else if (data.pairwise_cipher & WPA_CIPHER_TKIP)
499
+			selector = WPA_CIPHER_SUITE_TKIP;
500
+		else if (data.pairwise_cipher & WPA_CIPHER_WEP104)
501
+			selector = WPA_CIPHER_SUITE_WEP104;
502
+		else if (data.pairwise_cipher & WPA_CIPHER_WEP40)
503
+			selector = WPA_CIPHER_SUITE_WEP40;
504
+		else if (data.pairwise_cipher & WPA_CIPHER_NONE)
505
+			selector = WPA_CIPHER_SUITE_NONE;
506
+		wpa_auth->dot11RSNAPairwiseCipherSelected = selector;
507
+
508
+		selector = WPA_CIPHER_SUITE_TKIP;
509
+		if (data.group_cipher & WPA_CIPHER_CCMP)
510
+			selector = WPA_CIPHER_SUITE_CCMP;
511
+		else if (data.group_cipher & WPA_CIPHER_TKIP)
512
+			selector = WPA_CIPHER_SUITE_TKIP;
513
+		else if (data.group_cipher & WPA_CIPHER_WEP104)
514
+			selector = WPA_CIPHER_SUITE_WEP104;
515
+		else if (data.group_cipher & WPA_CIPHER_WEP40)
516
+			selector = WPA_CIPHER_SUITE_WEP40;
517
+		else if (data.group_cipher & WPA_CIPHER_NONE)
518
+			selector = WPA_CIPHER_SUITE_NONE;
519
+		wpa_auth->dot11RSNAGroupCipherSelected = selector;
520
+	}
521
+	if (res) {
522
+		wpa_printf(MSG_DEBUG, "Failed to parse WPA/RSN IE from "
523
+			   MACSTR " (res=%d)", MAC2STR(sm->addr), res);
524
+		wpa_hexdump(MSG_DEBUG, "WPA/RSN IE", wpa_ie, wpa_ie_len);
525
+		return WPA_INVALID_IE;
526
+	}
527
+
528
+	if (data.group_cipher != wpa_auth->conf.wpa_group) {
529
+		wpa_printf(MSG_DEBUG, "Invalid WPA group cipher (0x%x) from "
530
+			   MACSTR, data.group_cipher, MAC2STR(sm->addr));
531
+		return WPA_INVALID_GROUP;
532
+	}
533
+
534
+	key_mgmt = data.key_mgmt & wpa_auth->conf.wpa_key_mgmt;
535
+	if (!key_mgmt) {
536
+		wpa_printf(MSG_DEBUG, "Invalid WPA key mgmt (0x%x) from "
537
+			   MACSTR, data.key_mgmt, MAC2STR(sm->addr));
538
+		return WPA_INVALID_AKMP;
539
+	}
540
+	if (0) {
541
+	}
542
+#ifdef CONFIG_IEEE80211R
543
+	else if (key_mgmt & WPA_KEY_MGMT_FT_IEEE8021X)
544
+		sm->wpa_key_mgmt = WPA_KEY_MGMT_FT_IEEE8021X;
545
+	else if (key_mgmt & WPA_KEY_MGMT_FT_PSK)
546
+		sm->wpa_key_mgmt = WPA_KEY_MGMT_FT_PSK;
547
+#endif /* CONFIG_IEEE80211R */
548
+#ifdef CONFIG_IEEE80211W
549
+	else if (key_mgmt & WPA_KEY_MGMT_IEEE8021X_SHA256)
550
+		sm->wpa_key_mgmt = WPA_KEY_MGMT_IEEE8021X_SHA256;
551
+	else if (key_mgmt & WPA_KEY_MGMT_PSK_SHA256)
552
+		sm->wpa_key_mgmt = WPA_KEY_MGMT_PSK_SHA256;
553
+#endif /* CONFIG_IEEE80211W */
554
+	else if (key_mgmt & WPA_KEY_MGMT_IEEE8021X)
555
+		sm->wpa_key_mgmt = WPA_KEY_MGMT_IEEE8021X;
556
+	else
557
+		sm->wpa_key_mgmt = WPA_KEY_MGMT_PSK;
558
+
559
+	if (version == WPA_PROTO_RSN)
560
+		ciphers = data.pairwise_cipher & wpa_auth->conf.rsn_pairwise;
561
+	else
562
+		ciphers = data.pairwise_cipher & wpa_auth->conf.wpa_pairwise;
563
+	if (!ciphers) {
564
+		wpa_printf(MSG_DEBUG, "Invalid %s pairwise cipher (0x%x) "
565
+			   "from " MACSTR,
566
+			   version == WPA_PROTO_RSN ? "RSN" : "WPA",
567
+			   data.pairwise_cipher, MAC2STR(sm->addr));
568
+		return WPA_INVALID_PAIRWISE;
569
+	}
570
+
571
+#ifdef CONFIG_IEEE80211W
572
+	if (wpa_auth->conf.ieee80211w == MGMT_FRAME_PROTECTION_REQUIRED) {
573
+		if (!(data.capabilities & WPA_CAPABILITY_MFPC)) {
574
+			wpa_printf(MSG_DEBUG, "Management frame protection "
575
+				   "required, but client did not enable it");
576
+			return WPA_MGMT_FRAME_PROTECTION_VIOLATION;
577
+		}
578
+
579
+		if (ciphers & WPA_CIPHER_TKIP) {
580
+			wpa_printf(MSG_DEBUG, "Management frame protection "
581
+				   "cannot use TKIP");
582
+			return WPA_MGMT_FRAME_PROTECTION_VIOLATION;
583
+		}
584
+
585
+		if (data.mgmt_group_cipher != WPA_CIPHER_AES_128_CMAC) {
586
+			wpa_printf(MSG_DEBUG, "Unsupported management group "
587
+				   "cipher %d", data.mgmt_group_cipher);
588
+			return WPA_INVALID_MGMT_GROUP_CIPHER;
589
+		}
590
+	}
591
+
592
+	if (wpa_auth->conf.ieee80211w == NO_MGMT_FRAME_PROTECTION ||
593
+	    !(data.capabilities & WPA_CAPABILITY_MFPC))
594
+		sm->mgmt_frame_prot = 0;
595
+	else
596
+		sm->mgmt_frame_prot = 1;
597
+#endif /* CONFIG_IEEE80211W */
598
+
599
+#ifdef CONFIG_IEEE80211R
600
+	if (wpa_key_mgmt_ft(sm->wpa_key_mgmt)) {
601
+		if (mdie == NULL || mdie_len < MOBILITY_DOMAIN_ID_LEN + 1) {
602
+			wpa_printf(MSG_DEBUG, "RSN: Trying to use FT, but "
603
+				   "MDIE not included");
604
+			return WPA_INVALID_MDIE;
605
+		}
606
+		if (os_memcmp(mdie, wpa_auth->conf.mobility_domain,
607
+			      MOBILITY_DOMAIN_ID_LEN) != 0) {
608
+			wpa_hexdump(MSG_DEBUG, "RSN: Attempted to use unknown "
609
+				    "MDIE", mdie, MOBILITY_DOMAIN_ID_LEN);
610
+			return WPA_INVALID_MDIE;
611
+		}
612
+	}
613
+#endif /* CONFIG_IEEE80211R */
614
+
615
+	if (ciphers & WPA_CIPHER_CCMP)
616
+		sm->pairwise = WPA_CIPHER_CCMP;
617
+	else
618
+		sm->pairwise = WPA_CIPHER_TKIP;
619
+
620
+	/* TODO: clear WPA/WPA2 state if STA changes from one to another */
621
+	if (wpa_ie[0] == WLAN_EID_RSN)
622
+		sm->wpa = WPA_VERSION_WPA2;
623
+	else
624
+		sm->wpa = WPA_VERSION_WPA;
625
+
626
+	sm->pmksa = NULL;
627
+	for (i = 0; i < data.num_pmkid; i++) {
628
+		wpa_hexdump(MSG_DEBUG, "RSN IE: STA PMKID",
629
+			    &data.pmkid[i * PMKID_LEN], PMKID_LEN);
630
+		sm->pmksa = pmksa_cache_auth_get(wpa_auth->pmksa, sm->addr,
631
+						 &data.pmkid[i * PMKID_LEN]);
632
+		if (sm->pmksa) {
633
+			pmkid = sm->pmksa->pmkid;
634
+			break;
635
+		}
636
+	}
637
+	for (i = 0; sm->pmksa == NULL && wpa_auth->conf.okc &&
638
+		     i < data.num_pmkid; i++) {
639
+		struct wpa_auth_okc_iter_data idata;
640
+		idata.pmksa = NULL;
641
+		idata.aa = wpa_auth->addr;
642
+		idata.spa = sm->addr;
643
+		idata.pmkid = &data.pmkid[i * PMKID_LEN];
644
+		wpa_auth_for_each_auth(wpa_auth, wpa_auth_okc_iter, &idata);
645
+		if (idata.pmksa) {
646
+			wpa_auth_vlogger(wpa_auth, sm->addr, LOGGER_DEBUG,
647
+					 "OKC match for PMKID");
648
+			sm->pmksa = pmksa_cache_add_okc(wpa_auth->pmksa,
649
+							idata.pmksa,
650
+							wpa_auth->addr,
651
+							idata.pmkid);
652
+			pmkid = idata.pmkid;
653
+			break;
654
+		}
655
+	}
656
+	if (sm->pmksa) {
657
+		wpa_auth_vlogger(wpa_auth, sm->addr, LOGGER_DEBUG,
658
+				 "PMKID found from PMKSA cache "
659
+				 "eap_type=%d vlan_id=%d",
660
+				 sm->pmksa->eap_type_authsrv,
661
+				 sm->pmksa->vlan_id);
662
+		os_memcpy(wpa_auth->dot11RSNAPMKIDUsed, pmkid, PMKID_LEN);
663
+	}
664
+
665
+	if (sm->wpa_ie == NULL || sm->wpa_ie_len < wpa_ie_len) {
666
+		os_free(sm->wpa_ie);
667
+		sm->wpa_ie = os_malloc(wpa_ie_len);
668
+		if (sm->wpa_ie == NULL)
669
+			return WPA_ALLOC_FAIL;
670
+	}
671
+	os_memcpy(sm->wpa_ie, wpa_ie, wpa_ie_len);
672
+	sm->wpa_ie_len = wpa_ie_len;
673
+
674
+	return WPA_IE_OK;
675
+}
676
+
677
+
678
+/**
679
+ * wpa_parse_generic - Parse EAPOL-Key Key Data Generic IEs
680
+ * @pos: Pointer to the IE header
681
+ * @end: Pointer to the end of the Key Data buffer
682
+ * @ie: Pointer to parsed IE data
683
+ * Returns: 0 on success, 1 if end mark is found, -1 on failure
684
+ */
685
+static int wpa_parse_generic(const u8 *pos, const u8 *end,
686
+			     struct wpa_eapol_ie_parse *ie)
687
+{
688
+	if (pos[1] == 0)
689
+		return 1;
690
+
691
+	if (pos[1] >= 6 &&
692
+	    RSN_SELECTOR_GET(pos + 2) == WPA_OUI_TYPE &&
693
+	    pos[2 + WPA_SELECTOR_LEN] == 1 &&
694
+	    pos[2 + WPA_SELECTOR_LEN + 1] == 0) {
695
+		ie->wpa_ie = pos;
696
+		ie->wpa_ie_len = pos[1] + 2;
697
+		return 0;
698
+	}
699
+
700
+	if (pos + 1 + RSN_SELECTOR_LEN < end &&
701
+	    pos[1] >= RSN_SELECTOR_LEN + PMKID_LEN &&
702
+	    RSN_SELECTOR_GET(pos + 2) == RSN_KEY_DATA_PMKID) {
703
+		ie->pmkid = pos + 2 + RSN_SELECTOR_LEN;
704
+		return 0;
705
+	}
706
+
707
+	if (pos[1] > RSN_SELECTOR_LEN + 2 &&
708
+	    RSN_SELECTOR_GET(pos + 2) == RSN_KEY_DATA_GROUPKEY) {
709
+		ie->gtk = pos + 2 + RSN_SELECTOR_LEN;
710
+		ie->gtk_len = pos[1] - RSN_SELECTOR_LEN;
711
+		return 0;
712
+	}
713
+
714
+	if (pos[1] > RSN_SELECTOR_LEN + 2 &&
715
+	    RSN_SELECTOR_GET(pos + 2) == RSN_KEY_DATA_MAC_ADDR) {
716
+		ie->mac_addr = pos + 2 + RSN_SELECTOR_LEN;
717
+		ie->mac_addr_len = pos[1] - RSN_SELECTOR_LEN;
718
+		return 0;
719
+	}
720
+
721
+#ifdef CONFIG_PEERKEY
722
+	if (pos[1] > RSN_SELECTOR_LEN + 2 &&
723
+	    RSN_SELECTOR_GET(pos + 2) == RSN_KEY_DATA_SMK) {
724
+		ie->smk = pos + 2 + RSN_SELECTOR_LEN;
725
+		ie->smk_len = pos[1] - RSN_SELECTOR_LEN;
726
+		return 0;
727
+	}
728
+
729
+	if (pos[1] > RSN_SELECTOR_LEN + 2 &&
730
+	    RSN_SELECTOR_GET(pos + 2) == RSN_KEY_DATA_NONCE) {
731
+		ie->nonce = pos + 2 + RSN_SELECTOR_LEN;
732
+		ie->nonce_len = pos[1] - RSN_SELECTOR_LEN;
733
+		return 0;
734
+	}
735
+
736
+	if (pos[1] > RSN_SELECTOR_LEN + 2 &&
737
+	    RSN_SELECTOR_GET(pos + 2) == RSN_KEY_DATA_LIFETIME) {
738
+		ie->lifetime = pos + 2 + RSN_SELECTOR_LEN;
739
+		ie->lifetime_len = pos[1] - RSN_SELECTOR_LEN;
740
+		return 0;
741
+	}
742
+
743
+	if (pos[1] > RSN_SELECTOR_LEN + 2 &&
744
+	    RSN_SELECTOR_GET(pos + 2) == RSN_KEY_DATA_ERROR) {
745
+		ie->error = pos + 2 + RSN_SELECTOR_LEN;
746
+		ie->error_len = pos[1] - RSN_SELECTOR_LEN;
747
+		return 0;
748
+	}
749
+#endif /* CONFIG_PEERKEY */
750
+
751
+#ifdef CONFIG_IEEE80211W
752
+	if (pos[1] > RSN_SELECTOR_LEN + 2 &&
753
+	    RSN_SELECTOR_GET(pos + 2) == RSN_KEY_DATA_IGTK) {
754
+		ie->igtk = pos + 2 + RSN_SELECTOR_LEN;
755
+		ie->igtk_len = pos[1] - RSN_SELECTOR_LEN;
756
+		return 0;
757
+	}
758
+#endif /* CONFIG_IEEE80211W */
759
+
760
+	return 0;
761
+}
762
+
763
+
764
+/**
765
+ * wpa_parse_kde_ies - Parse EAPOL-Key Key Data IEs
766
+ * @buf: Pointer to the Key Data buffer
767
+ * @len: Key Data Length
768
+ * @ie: Pointer to parsed IE data
769
+ * Returns: 0 on success, -1 on failure
770
+ */
771
+int wpa_parse_kde_ies(const u8 *buf, size_t len, struct wpa_eapol_ie_parse *ie)
772
+{
773
+	const u8 *pos, *end;
774
+	int ret = 0;
775
+
776
+	os_memset(ie, 0, sizeof(*ie));
777
+	for (pos = buf, end = pos + len; pos + 1 < end; pos += 2 + pos[1]) {
778
+		if (pos[0] == 0xdd &&
779
+		    ((pos == buf + len - 1) || pos[1] == 0)) {
780
+			/* Ignore padding */
781
+			break;
782
+		}
783
+		if (pos + 2 + pos[1] > end) {
784
+			wpa_printf(MSG_DEBUG, "WPA: EAPOL-Key Key Data "
785
+				   "underflow (ie=%d len=%d pos=%d)",
786
+				   pos[0], pos[1], (int) (pos - buf));
787
+			wpa_hexdump_key(MSG_DEBUG, "WPA: Key Data",
788
+					buf, len);
789
+			ret = -1;
790
+			break;
791
+		}
792
+		if (*pos == WLAN_EID_RSN) {
793
+			ie->rsn_ie = pos;
794
+			ie->rsn_ie_len = pos[1] + 2;
795
+#ifdef CONFIG_IEEE80211R
796
+		} else if (*pos == WLAN_EID_MOBILITY_DOMAIN) {
797
+			ie->mdie = pos;
798
+			ie->mdie_len = pos[1] + 2;
799
+		} else if (*pos == WLAN_EID_FAST_BSS_TRANSITION) {
800
+			ie->ftie = pos;
801
+			ie->ftie_len = pos[1] + 2;
802
+#endif /* CONFIG_IEEE80211R */
803
+		} else if (*pos == WLAN_EID_VENDOR_SPECIFIC) {
804
+			ret = wpa_parse_generic(pos, end, ie);
805
+			if (ret < 0)
806
+				break;
807
+			if (ret > 0) {
808
+				ret = 0;
809
+				break;
810
+			}
811
+		} else {
812
+			wpa_hexdump(MSG_DEBUG, "WPA: Unrecognized EAPOL-Key "
813
+				    "Key Data IE", pos, 2 + pos[1]);
814
+		}
815
+	}
816
+
817
+	return ret;
818
+}
819
+
820
+
821
+int wpa_auth_uses_mfp(struct wpa_state_machine *sm)
822
+{
823
+	return sm ? sm->mgmt_frame_prot : 0;
824
+}

+ 56
- 0
src/ap/wpa_auth_ie.h Näytä tiedosto

@@ -0,0 +1,56 @@
1
+/*
2
+ * hostapd - WPA/RSN IE and KDE definitions
3
+ * Copyright (c) 2004-2007, Jouni Malinen <j@w1.fi>
4
+ *
5
+ * This program is free software; you can redistribute it and/or modify
6
+ * it under the terms of the GNU General Public License version 2 as
7
+ * published by the Free Software Foundation.
8
+ *
9
+ * Alternatively, this software may be distributed under the terms of BSD
10
+ * license.
11
+ *
12
+ * See README and COPYING for more details.
13
+ */
14
+
15
+#ifndef WPA_AUTH_IE_H
16
+#define WPA_AUTH_IE_H
17
+
18
+struct wpa_eapol_ie_parse {
19
+	const u8 *wpa_ie;
20
+	size_t wpa_ie_len;
21
+	const u8 *rsn_ie;
22
+	size_t rsn_ie_len;
23
+	const u8 *pmkid;
24
+	const u8 *gtk;
25
+	size_t gtk_len;
26
+	const u8 *mac_addr;
27
+	size_t mac_addr_len;
28
+#ifdef CONFIG_PEERKEY
29
+	const u8 *smk;
30
+	size_t smk_len;
31
+	const u8 *nonce;
32
+	size_t nonce_len;
33
+	const u8 *lifetime;
34
+	size_t lifetime_len;
35
+	const u8 *error;
36
+	size_t error_len;
37
+#endif /* CONFIG_PEERKEY */
38
+#ifdef CONFIG_IEEE80211W
39
+	const u8 *igtk;
40
+	size_t igtk_len;
41
+#endif /* CONFIG_IEEE80211W */
42
+#ifdef CONFIG_IEEE80211R
43
+	const u8 *mdie;
44
+	size_t mdie_len;
45
+	const u8 *ftie;
46
+	size_t ftie_len;
47
+#endif /* CONFIG_IEEE80211R */
48
+};
49
+
50
+int wpa_parse_kde_ies(const u8 *buf, size_t len,
51
+		      struct wpa_eapol_ie_parse *ie);
52
+u8 * wpa_add_kde(u8 *pos, u32 kde, const u8 *data, size_t data_len,
53
+		 const u8 *data2, size_t data2_len);
54
+int wpa_auth_gen_wpa_ie(struct wpa_authenticator *wpa_auth);
55
+
56
+#endif /* WPA_AUTH_IE_H */

+ 0
- 0
src/ap/wps_hostapd.c Näytä tiedosto


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

Loading…
Peruuta
Tallenna