Compare commits
534 commits
87120a5b6e
...
bde17063d5
Author | SHA1 | Date | |
---|---|---|---|
|
bde17063d5 | ||
|
809d9d8172 | ||
|
3ab781fb29 | ||
|
0012c4433c | ||
|
782c89c359 | ||
|
de40e08f70 | ||
|
c3ee46bcbe | ||
|
63df62c6c0 | ||
|
f3fd2f699f | ||
|
14cb3906af | ||
|
757d8d9aac | ||
|
61dfd7ae35 | ||
|
8625001ce5 | ||
|
b7963348cd | ||
|
d15403aefb | ||
|
3935d78e7b | ||
|
2b7277d3f0 | ||
|
97c6ef2588 | ||
|
e33acc2178 | ||
|
59299a8a7d | ||
|
6aa9ad8f8f | ||
|
b4f9742ee2 | ||
|
fa389f2a3b | ||
|
25c6598f30 | ||
|
bcab29a78c | ||
|
58ba550c53 | ||
|
5b0112a185 | ||
|
29f70292e5 | ||
|
a58b2ba2fc | ||
|
ae221945f6 | ||
|
633e969311 | ||
|
87c6b322ee | ||
|
d984172189 | ||
|
c6a8db47c3 | ||
|
c03edfd5bd | ||
|
7683ce1cff | ||
|
d9bb64914a | ||
|
8f21cdf9d7 | ||
|
18116e38a2 | ||
|
882bd2edd5 | ||
|
503e22025b | ||
|
064a46b478 | ||
|
9da9e41612 | ||
|
df8c5e22d7 | ||
|
bbb55af8c3 | ||
|
66d8ac8ccc | ||
|
70b8f64faf | ||
|
5fd3d05a40 | ||
|
fd72d395db | ||
|
88150522ce | ||
|
bc5d3bf623 | ||
|
8c9b9ccb49 | ||
|
7275b65149 | ||
|
5dbbca24ea | ||
|
19e12d5e2d | ||
|
189972d129 | ||
|
43943ea5b3 | ||
|
c4f9279267 | ||
|
7e7e43d6b3 | ||
|
1282787878 | ||
|
015f6a5a0c | ||
|
3e2758b19a | ||
|
15bf093b5b | ||
|
c43e1e5a5f | ||
|
c3beaf6b86 | ||
|
3e420372e7 | ||
|
c6ff28cb63 | ||
|
e1bf37022e | ||
|
f519f472e6 | ||
|
2d290f1966 | ||
|
e9984e3db2 | ||
|
8324947a67 | ||
|
abd7f47958 | ||
|
72ac0ee026 | ||
|
e900bcb149 | ||
|
e33a55d31d | ||
|
de2ee083e7 | ||
|
bd8a1f5ff5 | ||
|
c6faa89366 | ||
|
74db2b7449 | ||
|
023d70d6ca | ||
|
b5359d01ed | ||
|
abe990afb9 | ||
|
2042cae9b3 | ||
|
8f07e9699b | ||
|
5cb6747f97 | ||
|
b7f08c28cd | ||
|
c7e704bdf9 | ||
|
c9d0c6fd7e | ||
|
b592c1586e | ||
|
89c31feb31 | ||
|
83c4adcdac | ||
|
9f334fe683 | ||
|
69deac87fb | ||
|
ca58be3da4 | ||
|
666d695bbd | ||
|
fd55dfe16e | ||
|
23456e480e | ||
|
619ff3d2e8 | ||
|
733069fd4c | ||
|
222d443950 | ||
|
205dbb0fef | ||
|
9ff4fd30ff | ||
|
871bfdcdf6 | ||
|
d3f340c869 | ||
|
d42cfaa397 | ||
|
a66cb09930 | ||
|
acd9332c3b | ||
|
d40788a5cb | ||
|
9c0a6d64d0 | ||
|
b53d7a6a86 | ||
|
9e50c12b31 | ||
|
3cf4b4ad88 | ||
|
54b25b7c1d | ||
|
d9d8627873 | ||
|
3b6abe3580 | ||
|
f4a9cb96d6 | ||
|
020f20a222 | ||
|
adc6ca34a0 | ||
|
a832312806 | ||
|
582b5eff40 | ||
|
4bbe004e06 | ||
|
b791d1f342 | ||
|
da1a86afc6 | ||
|
ebd18f1ade | ||
|
93eb3b83c6 | ||
|
63ac001ed2 | ||
|
bb96540ef5 | ||
|
bc43e75b2b | ||
|
69d18ab9f2 | ||
|
56e8f8bf34 | ||
|
ddfed3f084 | ||
|
1e54160515 | ||
|
21c3a7494c | ||
|
5942965955 | ||
|
e1ab680c98 | ||
|
7e0e69cfea | ||
|
be6e4279fa | ||
|
4d110b4f87 | ||
|
521374b978 | ||
|
6f522baa1b | ||
|
62ca121f96 | ||
|
524c452153 | ||
|
13648dde91 | ||
|
376adfea8d | ||
|
4adf234cd3 | ||
|
9732c8b85c | ||
|
e0053bf9d0 | ||
|
296104d35c | ||
|
2e4c612dd2 | ||
|
bb61f6cb95 | ||
|
8b2ddfdbb6 | ||
|
92374d59d4 | ||
|
ff99012d84 | ||
|
526ea193c8 | ||
|
4417b5ba86 | ||
|
8d54863550 | ||
|
765c48d5ad | ||
|
d0b55eb360 | ||
|
5488e120d3 | ||
|
341bcb2b5c | ||
|
6fad7224be | ||
|
157b016383 | ||
|
b8a2d11ae0 | ||
|
48ca68f6f8 | ||
|
c16ac89be2 | ||
|
6b0ce29d25 | ||
|
e99cdfae41 | ||
|
d945ddd368 | ||
|
aa2dfae5eb | ||
|
70e5bad563 | ||
|
ed5887a8c9 | ||
|
c3d305d939 | ||
|
e7172e26d3 | ||
|
6809f2b955 | ||
|
816e22bba1 | ||
|
93a3c59ad9 | ||
|
90344c323e | ||
|
49fe24e6f5 | ||
|
7d51bf2abd | ||
|
5da59ff1cd | ||
|
7b8517d197 | ||
|
6ad59779c2 | ||
|
f250c34d10 | ||
|
92829d8bee | ||
|
44f20382cc | ||
|
7c935eef36 | ||
|
3137a41247 | ||
|
1023654532 | ||
|
b946a800f0 | ||
|
b7aecfe5f9 | ||
|
c3b3c506b6 | ||
|
fcf799c0dd | ||
|
5f83f4db0b | ||
|
094e188f84 | ||
|
627b67f29b | ||
|
be2ac92918 | ||
|
83cfeb8903 | ||
|
cb91ef2566 | ||
|
7d314d6bdf | ||
|
99e82880e8 | ||
|
454a22daba | ||
|
5452a4a302 | ||
|
89b164138c | ||
|
d5d0012bfb | ||
|
7436b5b012 | ||
|
42c1a512d9 | ||
|
c6f394b888 | ||
|
b745cd33ef | ||
|
e5f76b9153 | ||
|
7f3fe956d8 | ||
|
58b2759551 | ||
|
49344db095 | ||
|
918da644e1 | ||
|
9ba372a23d | ||
|
f6ba44d6f9 | ||
|
050bd6e2b1 | ||
|
ac15b79fe5 | ||
|
7bcede06e0 | ||
|
cf3883f3d1 | ||
|
9f0429c9e1 | ||
|
d22401d895 | ||
|
0c2d8417c6 | ||
|
3b4f127084 | ||
|
8f69e538a9 | ||
|
438a27b369 | ||
|
b7c6aa3ac6 | ||
|
61eb89d5fd | ||
|
5d16ad9ab0 | ||
|
22a592d119 | ||
|
9716bf1160 | ||
|
593a7c2f8c | ||
|
5f98c853e4 | ||
|
f302d9f964 | ||
|
58097123ec | ||
|
934b0c3a45 | ||
|
f54157077f | ||
|
37fe8e48ab | ||
|
689a248260 | ||
|
54abb0d3cf | ||
|
adac846bd0 | ||
|
566dc139a0 | ||
|
2846b74f14 | ||
|
d944ef1c01 | ||
|
368aa0230b | ||
|
0ab009db3c | ||
|
21fe042815 | ||
|
364c2da874 | ||
|
c9db4925f6 | ||
|
0cb42655fb | ||
|
9832f13242 | ||
|
7cf0021267 | ||
|
761041b18a | ||
|
d97b5c6492 | ||
|
2097de2a6a | ||
|
c6e55fb96b | ||
|
b54ccd4129 | ||
|
37a289f8bc | ||
|
dab7549d68 | ||
|
9a022cdc70 | ||
|
cb5c4e49c7 | ||
|
72203b8fe3 | ||
|
320c4c8f8d | ||
|
ecfe2aa61b | ||
|
5913d1a187 | ||
|
d8e1a353a6 | ||
|
3e52a90d34 | ||
|
3cf7bf68f4 | ||
|
2829f1c439 | ||
|
1b96745f1d | ||
|
ffcb7392f0 | ||
|
a5ee11e025 | ||
|
e4e91f5320 | ||
|
2c89b56d64 | ||
|
58ac46baf7 | ||
|
6594ea9ef1 | ||
|
829ab90d27 | ||
|
fdf23679f8 | ||
|
6cd0231112 | ||
|
846b1d618c | ||
|
7566370a96 | ||
|
4c0ea82700 | ||
|
c484a0fca4 | ||
|
cb40986a7e | ||
|
ed56dfc339 | ||
|
0ae087994c | ||
|
bd36dc90f1 | ||
|
1dda619ed2 | ||
|
a1e585fb63 | ||
|
51b5b9512f | ||
|
6f1fbebeb6 | ||
|
7d0c08910b | ||
|
b38f14e13d | ||
|
ef5d2f9e8f | ||
|
195cc3d919 | ||
|
b9113105ad | ||
|
5929b4eb1d | ||
|
5308029f86 | ||
|
11dfdf64c0 | ||
|
df14f1e2bd | ||
|
e141b33a66 | ||
|
97da087c0c | ||
|
42080798b5 | ||
|
df59880042 | ||
|
b26971774c | ||
|
20872d5256 | ||
|
3b68eef7d7 | ||
|
ed78f56dce | ||
|
8f83b7d7d1 | ||
|
e6ec62aa2d | ||
|
f44a07d5c4 | ||
|
2e1f7d091c | ||
|
7cf3ceadaa | ||
|
9b1e0ab4e8 | ||
|
cf36ffd43c | ||
|
ff798fbb83 | ||
|
4d2f76fabf | ||
|
5d9b4a1a14 | ||
|
39fefeada6 | ||
|
6f3e7c5d3e | ||
|
0df2c72c54 | ||
|
2bbe4822a6 | ||
|
42517eb3b0 | ||
|
b3ad54e460 | ||
|
de1bfda64e | ||
|
8d434bf65c | ||
|
b1e463374e | ||
|
5e3c2b489c | ||
|
12acda633b | ||
|
62a8f96e5b | ||
|
78adbf2c08 | ||
|
e5b49876a8 | ||
|
84d2a36da0 | ||
|
8891ebdc1d | ||
|
3ea7cf11db | ||
|
19fdcf511b | ||
|
4a1197acde | ||
|
a518810322 | ||
|
eea52c4b51 | ||
|
636530bc26 | ||
|
93d204b1ee | ||
|
efb484bbce | ||
|
80864d0116 | ||
|
c36ad11500 | ||
|
d9c5d601f1 | ||
|
3d0cc612fc | ||
|
9098535ef1 | ||
|
866ed63243 | ||
|
fd1a35e14a | ||
|
e4e7724560 | ||
|
9e3988fc64 | ||
|
9fcc636daf | ||
|
61c8cc94fa | ||
|
47d1307d2c | ||
|
3c79173c32 | ||
|
54b1df85c6 | ||
|
25e465d5b7 | ||
|
9e59cb8392 | ||
|
ea2c5fe4d1 | ||
|
85ea5f3496 | ||
|
62e0c10193 | ||
|
e8764518bd | ||
|
16aea07e50 | ||
|
ae1a9909e0 | ||
|
41fd49958d | ||
|
d43eb71da7 | ||
|
a6062568ab | ||
|
4b755c9672 | ||
|
9a44236452 | ||
|
dec6fccf17 | ||
|
8634e7343d | ||
|
a210fdb1c7 | ||
|
3ef0579013 | ||
|
e1cd3fe3cd | ||
|
47d7f31693 | ||
|
1be706e862 | ||
|
92fdb49b2e | ||
|
36bd75dfd2 | ||
|
f4b84ecaf7 | ||
|
aaf879ef20 | ||
|
32261721e1 | ||
|
216cfd708d | ||
|
d5e6f79988 | ||
|
c9ad16870b | ||
|
9b682e72d9 | ||
|
147f836924 | ||
|
ab37a57314 | ||
|
ba55088a73 | ||
|
e2ae53e1db | ||
|
1f230a497a | ||
|
37c00c3c5d | ||
|
b818a1be14 | ||
|
07c9f183ea | ||
|
9ac0e785c3 | ||
|
94506e8ed8 | ||
|
0e4bff095b | ||
|
a9bc6e89df | ||
|
4bc61b6577 | ||
|
a6d92da9aa | ||
|
1f88b3daf0 | ||
|
19e50f8627 | ||
|
df34c2ced3 | ||
|
63982fd094 | ||
|
9fdbaf2ed6 | ||
|
7a0501d20d | ||
|
d2b62b3fe5 | ||
|
55c30e8aba | ||
|
a576180cd8 | ||
|
b162886fd0 | ||
|
b810426eaa | ||
|
4200657338 | ||
|
f2f0dd354f | ||
|
60e1dca1ef | ||
|
fac34688ad | ||
|
b19aa9c422 | ||
|
2f0e5303e8 | ||
|
e51f1109b0 | ||
|
259b43a31a | ||
|
272c253dc9 | ||
|
69d53b8b6b | ||
|
666e954ca2 | ||
|
9be122d2e0 | ||
|
bd52684498 | ||
|
64c3c58080 | ||
|
9144f876a5 | ||
|
ec4b755b06 | ||
|
2342d95821 | ||
|
c24453dd93 | ||
|
77f39ed23b | ||
|
58017de69d | ||
|
8f9da72d2e | ||
|
b83797a3eb | ||
|
5b4a78b1f9 | ||
|
8d0bd7f9c8 | ||
|
024d4bca13 | ||
|
69d0862989 | ||
|
210c2b4bd7 | ||
|
9a1512532e | ||
|
420afbdbdf | ||
|
c3e5286537 | ||
|
0034112429 | ||
|
364cb7c943 | ||
|
0e2ca2e4e2 | ||
|
61e46f860c | ||
|
91b9786ced | ||
|
ab719621b7 | ||
|
91282e29ff | ||
|
3054112254 | ||
|
caf0cda761 | ||
|
695277a5b3 | ||
|
541fa25246 | ||
|
2ae1e6f18b | ||
|
2ea04435ec | ||
|
d71c838519 | ||
|
5eb409c4bc | ||
|
a438e52933 | ||
|
b35b1036fe | ||
|
35df7ee09e | ||
|
d8dca78a3a | ||
|
2986146d9c | ||
|
da833a7520 | ||
|
e625b46a9d | ||
|
69dd408fb8 | ||
|
131ee59266 | ||
|
c96c3adc36 | ||
|
9f43c1e26b | ||
|
47dad1ed16 | ||
|
eecaceed8f | ||
|
010d8d10ed | ||
|
0eb67e43bb | ||
|
0a321d1733 | ||
|
40d5fecac2 | ||
|
27dac87b7c | ||
|
c00abc69f2 | ||
|
9e90486bce | ||
|
460df51ed8 | ||
|
5dabc10185 | ||
|
e74d95e0aa | ||
|
59951ebf09 | ||
|
96f0af07e6 | ||
|
6f285fbafc | ||
|
b653420a23 | ||
|
16abdac809 | ||
|
b483ceafc4 | ||
|
040ba112aa | ||
|
31bbc9391e | ||
|
16f7072888 | ||
|
6889380177 | ||
|
0e399ced32 | ||
|
fd24ed9490 | ||
|
b1a880f38f | ||
|
e5b7e5b900 | ||
|
10122e951d | ||
|
e508c070c4 | ||
|
17a2aa822c | ||
|
770f3cb30b | ||
|
c7cafef8a1 | ||
|
261f7f9e51 | ||
|
033adbf833 | ||
|
8b51310f4e | ||
|
939cd294b2 | ||
|
436f07d02b | ||
|
e164943f43 | ||
|
40ef706e55 | ||
|
20ed289a78 | ||
|
4750a4f62a | ||
|
963dbad7dc | ||
|
451d299528 | ||
|
45fffac0fe | ||
|
e90f6678f1 | ||
|
0d4288a005 | ||
|
9ed51186e8 | ||
|
11f26fed64 | ||
|
dbdf7ef679 | ||
|
c9f8fe0664 | ||
|
6cb421c1fa | ||
|
408a399aa4 | ||
|
b532201034 | ||
|
dbcf9ff156 | ||
|
b18d957593 | ||
|
88a0ab87a2 | ||
|
0e4aa28daf | ||
|
a01972a065 | ||
|
8cdb0d3f24 | ||
|
d084ef36b3 | ||
|
7ceafb6e9f | ||
|
8aff823649 | ||
|
95a825bc43 | ||
|
87f33c26b9 | ||
|
971b781479 | ||
|
3386e1327e | ||
|
86c2421711 | ||
|
352ad5f1a2 | ||
|
39da3c7c63 |
264 changed files with 21309 additions and 6931 deletions
3
.gitignore
vendored
3
.gitignore
vendored
|
@ -6,3 +6,6 @@ wpaspy/build
|
|||
**/parallel-vm.log
|
||||
tags
|
||||
build/
|
||||
# clangd commands and cache
|
||||
compile_commands.json
|
||||
.cache
|
||||
|
|
2
README
2
README
|
@ -1,7 +1,7 @@
|
|||
wpa_supplicant and hostapd
|
||||
--------------------------
|
||||
|
||||
Copyright (c) 2002-2022, Jouni Malinen <j@w1.fi> and contributors
|
||||
Copyright (c) 2002-2024, Jouni Malinen <j@w1.fi> and contributors
|
||||
All Rights Reserved.
|
||||
|
||||
These programs are licensed under the BSD license (the one with
|
||||
|
|
|
@ -583,6 +583,24 @@ fi.w1.wpa_supplicant1.CreateInterface.
|
|||
<h3>InterworkingSelect ( ) --> nothing</h3>
|
||||
<p>Perform Interworking (Hotspot 2.0) network selection.</p>
|
||||
</li>
|
||||
<li>
|
||||
<h3>ANQPGet ( a{sv} : args) --> nothing</h3>
|
||||
<p>Send an ANQP request.</p>
|
||||
<h4>Arguments</h4>
|
||||
<dl>
|
||||
<dt>a{sv} : args</dt>
|
||||
<dd>
|
||||
<table>
|
||||
<tr><th>Key</th><th>Value type</th><th>Description</th><th>Required</th>
|
||||
<tr><td>addr</td><td>s</td><td>Address of the BSS</td><td>Yes</td>
|
||||
<tr><td>freq</td><td>u</td><td>Frequency of the BSS</td><td>No</td>
|
||||
<tr><td>ids</td><td>aq</td><td>List of ANQP information IDs to query</td><td>No</td>
|
||||
<tr><td>hs20_ids</td><td>ay</td><td>List of Hotspot 2.0 ANQP information IDs to query</td><td>No</td>
|
||||
<tr><td>mbo_ids</td><td>ay</td><td>List of MBO ANQP information IDs to query</td><td>No</td>
|
||||
</table>
|
||||
</dd>
|
||||
</dl>
|
||||
</li>
|
||||
<li>
|
||||
<h3>EAPLogoff ( ) --> nothing</h3>
|
||||
<p>IEEE 802.1X EAPOL state machine logoff.</p>
|
||||
|
@ -865,6 +883,11 @@ fi.w1.wpa_supplicant1.CreateInterface.
|
|||
<p>The most recent roam success or failure.</p>
|
||||
</li>
|
||||
|
||||
<li>
|
||||
<h3>ScanInProgress6GHz - b - (read)</h3>
|
||||
<p>Whether a 6GHz scan is currently in progress.</p>
|
||||
</li>
|
||||
|
||||
<li>
|
||||
<h3>SessionLength - u - (read)</h3>
|
||||
<p>The most recent BSS session length in milliseconds.</p>
|
||||
|
@ -1129,6 +1152,12 @@ fi.w1.wpa_supplicant1.CreateInterface.
|
|||
<li>
|
||||
<h3>MACAddress - ay - (read)</h3>
|
||||
<p>MAC address of the interface</p>
|
||||
</li>
|
||||
|
||||
<li>
|
||||
<h3>SignalChange - "a{sv}" - (read)</h3>
|
||||
<p>Signal and quality properties of the interface</p>
|
||||
</li>
|
||||
</ul>
|
||||
|
||||
\subsection dbus_interface_signals Signals
|
||||
|
@ -1345,6 +1374,17 @@ fi.w1.wpa_supplicant1.CreateInterface.
|
|||
<dd>URL of the terms and conditions page.</dd>
|
||||
</dl>
|
||||
</li>
|
||||
|
||||
<li>
|
||||
<h3>ANQPQueryDone ( s : addr, s : result )</h3>
|
||||
<p>Result of an ANQP query.</p>
|
||||
<dl>
|
||||
<dt>s : addr</dt>
|
||||
<dd>Address of the BSS targeted by the query.</dd>
|
||||
<dt>s : result</dt>
|
||||
<dd>Determine if the request was successful. If so fields are available in BSS.</dd>
|
||||
</dl>
|
||||
</li>
|
||||
</ul>
|
||||
|
||||
|
||||
|
@ -2185,6 +2225,30 @@ scan results.
|
|||
<h3>Age - u - (read)</h3>
|
||||
<p>Number of seconds since the BSS was last seen.</p>
|
||||
</li>
|
||||
<li>
|
||||
<h3>ANQP - a{sv} - (read)</h3>
|
||||
<p>ANQP information of the BSS. Empty dictionary indicates no ANQP field. Named dictionary entries are:</p>
|
||||
<table>
|
||||
<tr><td>CapabilityList</td><td>ay</td></tr>
|
||||
<tr><td>VenueName</td><td>ay</td></tr>
|
||||
<tr><td>NetworkAuthType</td><td>ay</td></tr>
|
||||
<tr><td>RoamingConsortium</td><td>ay</td></tr>
|
||||
<tr><td>IPAddrTypeAvailability</td><td>ay</td></tr>
|
||||
<tr><td>NAIRealm</td><td>ay</td></tr>
|
||||
<tr><td>3GPP</td><td>ay</td></tr>
|
||||
<tr><td>DomainName</td><td>ay</td></tr>
|
||||
<tr><td>FilsRealmInfo</td><td>ay</td></tr>
|
||||
<tr><td>HS20CapabilityList</td><td>ay</td></tr>
|
||||
<tr><td>HS20OperatorFriendlyName</td><td>ay</td></tr>
|
||||
<tr><td>HS20WanMetrics</td><td>ay</td></tr>
|
||||
<tr><td>HS20ConnectionCapability</td><td>ay</td></tr>
|
||||
<tr><td>HS20OperatingClass</td><td>ay</td></tr>
|
||||
<tr><td>HS20OSUProvidersList</td><td>ay</td></tr>
|
||||
<tr><td>HS20OperatorIconMetadata</td><td>ay</td></tr>
|
||||
<tr><td>HS20OSUProvidersNAIList</td><td>ay</td></tr>
|
||||
</table>
|
||||
<p>Unnamed ANQP elements have a generic entry name 'anqp[id]' where 'id' is the InfoID of the ANQP element as described in IEEE Std 802.11-2020, Table 9-331 (ANQP-element definitions).</p>
|
||||
</li>
|
||||
</ul>
|
||||
|
||||
\subsection dbus_bss_signals Signals
|
||||
|
|
|
@ -31,7 +31,7 @@ PROJECT_NAME = "wpa_supplicant / hostapd"
|
|||
# This could be handy for archiving the generated documentation or
|
||||
# if some version control system is used.
|
||||
|
||||
PROJECT_NUMBER = 2.10
|
||||
PROJECT_NUMBER = 2.11
|
||||
|
||||
# The OUTPUT_DIRECTORY tag is used to specify the (relative or absolute)
|
||||
# base path where the generated documentation will be put.
|
||||
|
|
54
gen_compile_commands.py
Executable file
54
gen_compile_commands.py
Executable file
|
@ -0,0 +1,54 @@
|
|||
#!/usr/bin/env python3
|
||||
# compile_commands.json generator
|
||||
# Copyright (C) 2024 Intel Corporation
|
||||
#
|
||||
# This software may be distributed under the terms of the BSD license.
|
||||
# See README for more details.
|
||||
|
||||
import os
|
||||
import sys
|
||||
import glob
|
||||
import json
|
||||
import argparse
|
||||
|
||||
parser = argparse.ArgumentParser(description='Read each of the build directories that are given and generate '
|
||||
'a compile_commands.json file. If a source file is found multiple times, '
|
||||
'then the compile flags from the last build directory will be used.')
|
||||
parser.add_argument('-o', '--output', default='compile_commands.json', type=str,
|
||||
help="Output file to generate")
|
||||
parser.add_argument('builddirs', nargs='+', type=str, metavar="builddir",
|
||||
help='Build directories to search')
|
||||
|
||||
args = parser.parse_args()
|
||||
|
||||
files = {}
|
||||
|
||||
for builddir in args.builddirs:
|
||||
for cmd_file in glob.glob('**/*.o.cmd', root_dir=builddir, recursive=True):
|
||||
with open(os.path.join(builddir, cmd_file), encoding='ascii') as f:
|
||||
base_dir, cmd = f.readline().split(':', 1)
|
||||
src_file = cmd.rsplit(maxsplit=1)[1]
|
||||
|
||||
src_file = os.path.abspath(os.path.join(base_dir, src_file))
|
||||
files[src_file] = {
|
||||
'command': cmd.strip(),
|
||||
'directory': base_dir,
|
||||
'file': src_file,
|
||||
}
|
||||
|
||||
flist = json.dumps(sorted(list(files.values()), key=lambda k: k['file']), indent=2, sort_keys=True)
|
||||
|
||||
try:
|
||||
# Avoid writing the file if it did not change, first read original
|
||||
with open(args.output, 'rt', encoding='UTF-8') as f:
|
||||
orig = []
|
||||
while data := f.read():
|
||||
orig.append(data)
|
||||
orig = ''.join(orig)
|
||||
except OSError:
|
||||
orig = ''
|
||||
|
||||
# And only write if something changed
|
||||
if orig != flist:
|
||||
with open(args.output, 'wt', encoding='UTF-8') as f:
|
||||
f.write(flist)
|
|
@ -154,6 +154,7 @@ OBJS += src/utils/crc32.c
|
|||
OBJS += src/common/ieee802_11_common.c
|
||||
OBJS += src/common/wpa_common.c
|
||||
OBJS += src/common/hw_features_common.c
|
||||
OBJS += src/common/ptksa_cache.c
|
||||
|
||||
OBJS += src/eapol_auth/eapol_auth_sm.c
|
||||
|
||||
|
@ -594,7 +595,6 @@ NEED_HMAC_SHA256_KDF=y
|
|||
NEED_HMAC_SHA384_KDF=y
|
||||
NEED_SHA256=y
|
||||
NEED_SHA384=y
|
||||
OBJS += src/common/ptksa_cache.c
|
||||
endif
|
||||
|
||||
ifdef CONFIG_EAP_IKEV2
|
||||
|
@ -647,6 +647,11 @@ ifdef CHAP
|
|||
OBJS += src/eap_common/chap.c
|
||||
endif
|
||||
|
||||
ifdef CONFIG_RADIUS_TLS
|
||||
TLS_FUNCS=y
|
||||
L_CFLAGS += -DCONFIG_RADIUS_TLS
|
||||
endif
|
||||
|
||||
ifdef TLS_FUNCS
|
||||
NEED_DES=y
|
||||
# Shared TLS functions (needed for EAP_TLS, EAP_PEAP, and EAP_TTLS)
|
||||
|
@ -1046,6 +1051,7 @@ OBJS += src/ap/wmm.c
|
|||
OBJS += src/ap/ap_list.c
|
||||
OBJS += src/ap/comeback_token.c
|
||||
OBJS += src/pasn/pasn_responder.c
|
||||
OBJS += src/pasn/pasn_common.c
|
||||
OBJS += src/ap/ieee802_11.c
|
||||
OBJS += src/ap/hw_features.c
|
||||
OBJS += src/ap/dfs.c
|
||||
|
|
|
@ -1,5 +1,42 @@
|
|||
ChangeLog for hostapd
|
||||
|
||||
2024-07-20 - v2.11
|
||||
* Wi-Fi Easy Connect
|
||||
- add support for DPP release 3
|
||||
- allow Configurator parameters to be provided during config exchange
|
||||
* HE/IEEE 802.11ax/Wi-Fi 6
|
||||
- various fixes
|
||||
* EHT/IEEE 802.11be/Wi-Fi 7
|
||||
- add preliminary support
|
||||
* SAE: add support for fetching the password from a RADIUS server
|
||||
* support OpenSSL 3.0 API changes
|
||||
* support background radar detection and CAC with some additional
|
||||
drivers
|
||||
* support RADIUS ACL/PSK check during 4-way handshake (wpa_psk_radius=3)
|
||||
* EAP-SIM/AKA: support IMSI privacy
|
||||
* improve 4-way handshake operations
|
||||
- use Secure=1 in message 3 during PTK rekeying
|
||||
* OCV: do not check Frequency Segment 1 Channel Number for 160 MHz cases
|
||||
to avoid interoperability issues
|
||||
* support new SAE AKM suites with variable length keys
|
||||
* support new AKM for 802.1X/EAP with SHA384
|
||||
* extend PASN support for secure ranging
|
||||
* FT: Use SHA256 to derive PMKID for AKM 00-0F-AC:3 (FT-EAP)
|
||||
- this is based on additional details being added in the IEEE 802.11
|
||||
standard
|
||||
- the new implementation is not backwards compatible
|
||||
* improved ACS to cover additional channel types/bandwidths
|
||||
* extended Multiple BSSID support
|
||||
* fix beacon protection with FT protocol (incorrect BIGTK was provided)
|
||||
* support unsynchronized service discovery (USD)
|
||||
* add preliminary support for RADIUS/TLS
|
||||
* add support for explicit SSID protection in 4-way handshake
|
||||
(a mitigation for CVE-2023-52424; disabled by default for now, can be
|
||||
enabled with ssid_protection=1)
|
||||
* fix SAE H2E rejected groups validation to avoid downgrade attacks
|
||||
* use stricter validation for some RADIUS messages
|
||||
* a large number of other fixes, cleanup, and extensions
|
||||
|
||||
2022-01-16 - v2.10
|
||||
* SAE changes
|
||||
- improved protection against side channel attacks
|
||||
|
|
|
@ -84,6 +84,7 @@ OBJS += ../src/ap/beacon.o
|
|||
OBJS += ../src/ap/bss_load.o
|
||||
OBJS += ../src/ap/neighbor_db.o
|
||||
OBJS += ../src/ap/rrm.o
|
||||
OBJS += ../src/common/ptksa_cache.o
|
||||
|
||||
OBJS_c = hostapd_cli.o
|
||||
OBJS_c += ../src/common/wpa_ctrl.o
|
||||
|
@ -620,7 +621,6 @@ NEED_HMAC_SHA256_KDF=y
|
|||
NEED_HMAC_SHA384_KDF=y
|
||||
NEED_SHA256=y
|
||||
NEED_SHA384=y
|
||||
OBJS += ../src/common/ptksa_cache.o
|
||||
endif
|
||||
|
||||
ifdef CONFIG_EAP_IKEV2
|
||||
|
@ -682,6 +682,11 @@ ifdef CHAP
|
|||
OBJS += ../src/eap_common/chap.o
|
||||
endif
|
||||
|
||||
ifdef CONFIG_RADIUS_TLS
|
||||
TLS_FUNCS=y
|
||||
CFLAGS += -DCONFIG_RADIUS_TLS
|
||||
endif
|
||||
|
||||
ifdef TLS_FUNCS
|
||||
NEED_DES=y
|
||||
# Shared TLS functions (needed for EAP_TLS, EAP_PEAP, and EAP_TTLS)
|
||||
|
@ -1192,6 +1197,7 @@ OBJS += ../src/ap/wmm.o
|
|||
OBJS += ../src/ap/ap_list.o
|
||||
OBJS += ../src/ap/comeback_token.o
|
||||
OBJS += ../src/pasn/pasn_responder.o
|
||||
OBJS += ../src/pasn/pasn_common.o
|
||||
OBJS += ../src/ap/ieee802_11.o
|
||||
OBJS += ../src/ap/hw_features.o
|
||||
OBJS += ../src/ap/dfs.o
|
||||
|
|
|
@ -2,7 +2,7 @@ hostapd - user space IEEE 802.11 AP and IEEE 802.1X/WPA/WPA2/EAP
|
|||
Authenticator and RADIUS authentication server
|
||||
================================================================
|
||||
|
||||
Copyright (c) 2002-2022, Jouni Malinen <j@w1.fi> and contributors
|
||||
Copyright (c) 2002-2024, Jouni Malinen <j@w1.fi> and contributors
|
||||
All Rights Reserved.
|
||||
|
||||
This program is licensed under the BSD license (the one with
|
||||
|
|
|
@ -121,6 +121,9 @@ CONFIG_PKCS12=y
|
|||
# Build IPv6 support for RADIUS operations
|
||||
CONFIG_IPV6=y
|
||||
|
||||
# Include support fo RADIUS/TLS into the RADIUS client
|
||||
#CONFIG_RADIUS_TLS=y
|
||||
|
||||
# IEEE Std 802.11r-2008 (Fast BSS Transition)
|
||||
#CONFIG_IEEE80211R=y
|
||||
|
||||
|
|
|
@ -1678,6 +1678,8 @@ static int parse_anqp_elem(struct hostapd_bss_config *bss, char *buf, int line)
|
|||
return 0;
|
||||
}
|
||||
|
||||
#endif /* CONFIG_INTERWORKING */
|
||||
|
||||
|
||||
static int parse_qos_map_set(struct hostapd_bss_config *bss,
|
||||
char *buf, int line)
|
||||
|
@ -1719,8 +1721,6 @@ static int parse_qos_map_set(struct hostapd_bss_config *bss,
|
|||
return 0;
|
||||
}
|
||||
|
||||
#endif /* CONFIG_INTERWORKING */
|
||||
|
||||
|
||||
#ifdef CONFIG_HS20
|
||||
static int hs20_parse_conn_capab(struct hostapd_bss_config *bss, char *buf,
|
||||
|
@ -2436,6 +2436,31 @@ static int get_u16(const char *pos, int line, u16 *ret_val)
|
|||
#endif /* CONFIG_IEEE80211BE */
|
||||
|
||||
|
||||
#ifdef CONFIG_TESTING_OPTIONS
|
||||
static bool get_hexstream(const char *val, struct wpabuf **var,
|
||||
const char *name, int line)
|
||||
{
|
||||
struct wpabuf *tmp;
|
||||
size_t len = os_strlen(val) / 2;
|
||||
|
||||
tmp = wpabuf_alloc(len);
|
||||
if (!tmp)
|
||||
return false;
|
||||
|
||||
if (hexstr2bin(val, wpabuf_put(tmp, len), len)) {
|
||||
wpabuf_free(tmp);
|
||||
wpa_printf(MSG_ERROR, "Line %d: Invalid %s '%s'",
|
||||
line, name, val);
|
||||
return false;
|
||||
}
|
||||
|
||||
wpabuf_free(*var);
|
||||
*var = tmp;
|
||||
return true;
|
||||
}
|
||||
#endif /* CONFIG_TESTING_OPTIONS */
|
||||
|
||||
|
||||
static int hostapd_config_fill(struct hostapd_config *conf,
|
||||
struct hostapd_bss_config *bss,
|
||||
const char *buf, char *pos, int line)
|
||||
|
@ -2549,6 +2574,27 @@ static int hostapd_config_fill(struct hostapd_config *conf,
|
|||
bss->ap_max_inactivity = atoi(pos);
|
||||
} else if (os_strcmp(buf, "skip_inactivity_poll") == 0) {
|
||||
bss->skip_inactivity_poll = atoi(pos);
|
||||
} else if (os_strcmp(buf, "bss_max_idle") == 0) {
|
||||
int val = atoi(pos);
|
||||
|
||||
if (val < 0 || val > 2) {
|
||||
wpa_printf(MSG_ERROR,
|
||||
"Line %d: Invalid bss_max_idle value", line);
|
||||
return 1;
|
||||
}
|
||||
bss->bss_max_idle = val;
|
||||
} else if (os_strcmp(buf, "max_acceptable_idle_period") == 0) {
|
||||
bss->max_acceptable_idle_period = atoi(pos);
|
||||
} else if (os_strcmp(buf, "no_disconnect_on_group_keyerror") == 0) {
|
||||
int val = atoi(pos);
|
||||
|
||||
if (val < 0 || val > 1) {
|
||||
wpa_printf(MSG_ERROR,
|
||||
"Line %d: Invalid no_disconnect_on_group_keyerror",
|
||||
line);
|
||||
return 1;
|
||||
}
|
||||
bss->no_disconnect_on_group_keyerror = val;
|
||||
} else if (os_strcmp(buf, "config_id") == 0) {
|
||||
os_free(bss->config_id);
|
||||
bss->config_id = os_strdup(pos);
|
||||
|
@ -2869,6 +2915,37 @@ static int hostapd_config_fill(struct hostapd_config *conf,
|
|||
os_free(bss->radius->auth_server->shared_secret);
|
||||
bss->radius->auth_server->shared_secret = (u8 *) os_strdup(pos);
|
||||
bss->radius->auth_server->shared_secret_len = len;
|
||||
} else if (bss->radius->auth_server &&
|
||||
os_strcmp(buf, "auth_server_type") == 0) {
|
||||
if (os_strcmp(pos, "UDP") == 0) {
|
||||
bss->radius->auth_server->tls = false;
|
||||
#ifdef CONFIG_RADIUS_TLS
|
||||
} else if (os_strcmp(pos, "TLS") == 0) {
|
||||
bss->radius->auth_server->tls = true;
|
||||
#endif /* CONFIG_RADIUS_TLS */
|
||||
} else {
|
||||
wpa_printf(MSG_ERROR, "Line %d: unsupported RADIUS type '%s'",
|
||||
line, pos);
|
||||
return 1;
|
||||
}
|
||||
#ifdef CONFIG_RADIUS_TLS
|
||||
} else if (bss->radius->auth_server &&
|
||||
os_strcmp(buf, "auth_server_ca_cert") == 0) {
|
||||
os_free(bss->radius->auth_server->ca_cert);
|
||||
bss->radius->auth_server->ca_cert = os_strdup(pos);
|
||||
} else if (bss->radius->auth_server &&
|
||||
os_strcmp(buf, "auth_server_client_cert") == 0) {
|
||||
os_free(bss->radius->auth_server->client_cert);
|
||||
bss->radius->auth_server->client_cert = os_strdup(pos);
|
||||
} else if (bss->radius->auth_server &&
|
||||
os_strcmp(buf, "auth_server_private_key") == 0) {
|
||||
os_free(bss->radius->auth_server->private_key);
|
||||
bss->radius->auth_server->private_key = os_strdup(pos);
|
||||
} else if (bss->radius->auth_server &&
|
||||
os_strcmp(buf, "auth_server_private_key_passwd") == 0) {
|
||||
os_free(bss->radius->auth_server->private_key_passwd);
|
||||
bss->radius->auth_server->private_key_passwd = os_strdup(pos);
|
||||
#endif /* CONFIG_RADIUS_TLS */
|
||||
} else if (os_strcmp(buf, "acct_server_addr") == 0) {
|
||||
if (hostapd_config_read_radius_addr(
|
||||
&bss->radius->acct_servers,
|
||||
|
@ -2903,8 +2980,42 @@ static int hostapd_config_fill(struct hostapd_config *conf,
|
|||
os_free(bss->radius->acct_server->shared_secret);
|
||||
bss->radius->acct_server->shared_secret = (u8 *) os_strdup(pos);
|
||||
bss->radius->acct_server->shared_secret_len = len;
|
||||
} else if (bss->radius->acct_server &&
|
||||
os_strcmp(buf, "acct_server_type") == 0) {
|
||||
if (os_strcmp(pos, "UDP") == 0) {
|
||||
bss->radius->acct_server->tls = false;
|
||||
#ifdef CONFIG_RADIUS_TLS
|
||||
} else if (os_strcmp(pos, "TLS") == 0) {
|
||||
bss->radius->acct_server->tls = true;
|
||||
#endif /* CONFIG_RADIUS_TLS */
|
||||
} else {
|
||||
wpa_printf(MSG_ERROR, "Line %d: unsupported RADIUS type '%s'",
|
||||
line, pos);
|
||||
return 1;
|
||||
}
|
||||
#ifdef CONFIG_RADIUS_TLS
|
||||
} else if (bss->radius->acct_server &&
|
||||
os_strcmp(buf, "acct_server_ca_cert") == 0) {
|
||||
os_free(bss->radius->acct_server->ca_cert);
|
||||
bss->radius->acct_server->ca_cert = os_strdup(pos);
|
||||
} else if (bss->radius->acct_server &&
|
||||
os_strcmp(buf, "acct_server_client_cert") == 0) {
|
||||
os_free(bss->radius->acct_server->client_cert);
|
||||
bss->radius->acct_server->client_cert = os_strdup(pos);
|
||||
} else if (bss->radius->acct_server &&
|
||||
os_strcmp(buf, "acct_server_private_key") == 0) {
|
||||
os_free(bss->radius->acct_server->private_key);
|
||||
bss->radius->acct_server->private_key = os_strdup(pos);
|
||||
} else if (bss->radius->acct_server &&
|
||||
os_strcmp(buf, "acct_server_private_key_passwd") == 0) {
|
||||
os_free(bss->radius->acct_server->private_key_passwd);
|
||||
bss->radius->acct_server->private_key_passwd = os_strdup(pos);
|
||||
#endif /* CONFIG_RADIUS_TLS */
|
||||
} else if (os_strcmp(buf, "radius_retry_primary_interval") == 0) {
|
||||
bss->radius->retry_primary_interval = atoi(pos);
|
||||
} else if (os_strcmp(buf,
|
||||
"radius_require_message_authenticator") == 0) {
|
||||
bss->radius_require_message_authenticator = atoi(pos);
|
||||
} else if (os_strcmp(buf, "radius_acct_interim_interval") == 0) {
|
||||
bss->acct_interim_interval = atoi(pos);
|
||||
} else if (os_strcmp(buf, "radius_request_cui") == 0) {
|
||||
|
@ -3070,6 +3181,16 @@ static int hostapd_config_fill(struct hostapd_config *conf,
|
|||
bss->wpa_key_mgmt = hostapd_config_parse_key_mgmt(line, pos);
|
||||
if (bss->wpa_key_mgmt == -1)
|
||||
return 1;
|
||||
} else if (os_strcmp(buf, "rsn_override_key_mgmt") == 0) {
|
||||
bss->rsn_override_key_mgmt =
|
||||
hostapd_config_parse_key_mgmt(line, pos);
|
||||
if (bss->rsn_override_key_mgmt == -1)
|
||||
return 1;
|
||||
} else if (os_strcmp(buf, "rsn_override_key_mgmt_2") == 0) {
|
||||
bss->rsn_override_key_mgmt_2 =
|
||||
hostapd_config_parse_key_mgmt(line, pos);
|
||||
if (bss->rsn_override_key_mgmt_2 == -1)
|
||||
return 1;
|
||||
} else if (os_strcmp(buf, "wpa_psk_radius") == 0) {
|
||||
bss->wpa_psk_radius = atoi(pos);
|
||||
if (bss->wpa_psk_radius != PSK_RADIUS_IGNORED &&
|
||||
|
@ -3101,6 +3222,32 @@ static int hostapd_config_fill(struct hostapd_config *conf,
|
|||
line, pos);
|
||||
return 1;
|
||||
}
|
||||
} else if (os_strcmp(buf, "rsn_override_pairwise") == 0) {
|
||||
bss->rsn_override_pairwise =
|
||||
hostapd_config_parse_cipher(line, pos);
|
||||
if (bss->rsn_override_pairwise == -1 ||
|
||||
bss->rsn_override_pairwise == 0)
|
||||
return 1;
|
||||
if (bss->rsn_override_pairwise &
|
||||
(WPA_CIPHER_NONE | WPA_CIPHER_WEP40 | WPA_CIPHER_WEP104)) {
|
||||
wpa_printf(MSG_ERROR,
|
||||
"Line %d: unsupported pairwise cipher suite '%s'",
|
||||
line, pos);
|
||||
return 1;
|
||||
}
|
||||
} else if (os_strcmp(buf, "rsn_override_pairwise_2") == 0) {
|
||||
bss->rsn_override_pairwise_2 =
|
||||
hostapd_config_parse_cipher(line, pos);
|
||||
if (bss->rsn_override_pairwise_2 == -1 ||
|
||||
bss->rsn_override_pairwise_2 == 0)
|
||||
return 1;
|
||||
if (bss->rsn_override_pairwise_2 &
|
||||
(WPA_CIPHER_NONE | WPA_CIPHER_WEP40 | WPA_CIPHER_WEP104)) {
|
||||
wpa_printf(MSG_ERROR,
|
||||
"Line %d: unsupported pairwise cipher suite '%s'",
|
||||
line, pos);
|
||||
return 1;
|
||||
}
|
||||
} else if (os_strcmp(buf, "group_cipher") == 0) {
|
||||
bss->group_cipher = hostapd_config_parse_cipher(line, pos);
|
||||
if (bss->group_cipher == -1 || bss->group_cipher == 0)
|
||||
|
@ -3122,6 +3269,8 @@ static int hostapd_config_fill(struct hostapd_config *conf,
|
|||
os_free(bss->rsn_preauth_interfaces);
|
||||
bss->rsn_preauth_interfaces = os_strdup(pos);
|
||||
#endif /* CONFIG_RSN_PREAUTH */
|
||||
} else if (os_strcmp(buf, "rsn_override_omit_rsnxe") == 0) {
|
||||
bss->rsn_override_omit_rsnxe = atoi(pos);
|
||||
} else if (os_strcmp(buf, "peerkey") == 0) {
|
||||
wpa_printf(MSG_INFO,
|
||||
"Line %d: Obsolete peerkey parameter ignored", line);
|
||||
|
@ -3556,6 +3705,10 @@ static int hostapd_config_fill(struct hostapd_config *conf,
|
|||
conf->use_driver_iface_addr = atoi(pos);
|
||||
} else if (os_strcmp(buf, "ieee80211w") == 0) {
|
||||
bss->ieee80211w = atoi(pos);
|
||||
} else if (os_strcmp(buf, "rsn_override_mfp") == 0) {
|
||||
bss->rsn_override_mfp = atoi(pos);
|
||||
} else if (os_strcmp(buf, "rsn_override_mfp_2") == 0) {
|
||||
bss->rsn_override_mfp_2 = atoi(pos);
|
||||
} else if (os_strcmp(buf, "group_mgmt_cipher") == 0) {
|
||||
if (os_strcmp(pos, "AES-128-CMAC") == 0) {
|
||||
bss->group_mgmt_cipher = WPA_CIPHER_AES_128_CMAC;
|
||||
|
@ -3602,6 +3755,8 @@ static int hostapd_config_fill(struct hostapd_config *conf,
|
|||
}
|
||||
} else if (os_strcmp(buf, "require_ht") == 0) {
|
||||
conf->require_ht = atoi(pos);
|
||||
} else if (os_strcmp(buf, "ht_vht_twt_responder") == 0) {
|
||||
conf->ht_vht_twt_responder = atoi(pos);
|
||||
} else if (os_strcmp(buf, "obss_interval") == 0) {
|
||||
conf->obss_interval = atoi(pos);
|
||||
#ifdef CONFIG_IEEE80211AC
|
||||
|
@ -4196,10 +4351,10 @@ static int hostapd_config_fill(struct hostapd_config *conf,
|
|||
bss->gas_frag_limit = val;
|
||||
} else if (os_strcmp(buf, "gas_comeback_delay") == 0) {
|
||||
bss->gas_comeback_delay = atoi(pos);
|
||||
#endif /* CONFIG_INTERWORKING */
|
||||
} else if (os_strcmp(buf, "qos_map_set") == 0) {
|
||||
if (parse_qos_map_set(bss, pos, line) < 0)
|
||||
return 1;
|
||||
#endif /* CONFIG_INTERWORKING */
|
||||
#ifdef CONFIG_RADIUS_TEST
|
||||
} else if (os_strcmp(buf, "dump_msk_file") == 0) {
|
||||
os_free(bss->dump_msk_file);
|
||||
|
@ -4374,23 +4529,29 @@ static int hostapd_config_fill(struct hostapd_config *conf,
|
|||
bss->radio_measurements[0] |=
|
||||
WLAN_RRM_CAPS_NEIGHBOR_REPORT;
|
||||
} else if (os_strcmp(buf, "own_ie_override") == 0) {
|
||||
struct wpabuf *tmp;
|
||||
size_t len = os_strlen(pos) / 2;
|
||||
|
||||
tmp = wpabuf_alloc(len);
|
||||
if (!tmp)
|
||||
if (!get_hexstream(pos, &bss->own_ie_override,
|
||||
"own_ie_override", line))
|
||||
return 1;
|
||||
|
||||
if (hexstr2bin(pos, wpabuf_put(tmp, len), len)) {
|
||||
wpabuf_free(tmp);
|
||||
wpa_printf(MSG_ERROR,
|
||||
"Line %d: Invalid own_ie_override '%s'",
|
||||
line, pos);
|
||||
} else if (os_strcmp(buf, "rsne_override") == 0) {
|
||||
if (!get_hexstream(pos, &bss->rsne_override,
|
||||
"rsne_override", line))
|
||||
return 1;
|
||||
} else if (os_strcmp(buf, "rsnoe_override") == 0) {
|
||||
if (!get_hexstream(pos, &bss->rsnoe_override,
|
||||
"rsnoe_override", line))
|
||||
return 1;
|
||||
} else if (os_strcmp(buf, "rsno2e_override") == 0) {
|
||||
if (!get_hexstream(pos, &bss->rsno2e_override,
|
||||
"rsno2e_override", line))
|
||||
return 1;
|
||||
} else if (os_strcmp(buf, "rsnxe_override") == 0) {
|
||||
if (!get_hexstream(pos, &bss->rsnxe_override,
|
||||
"rsnxe_override", line))
|
||||
return 1;
|
||||
} else if (os_strcmp(buf, "rsnxoe_override") == 0) {
|
||||
if (!get_hexstream(pos, &bss->rsnxoe_override,
|
||||
"rsnxoe_override", line))
|
||||
return 1;
|
||||
}
|
||||
|
||||
wpabuf_free(bss->own_ie_override);
|
||||
bss->own_ie_override = tmp;
|
||||
} else if (os_strcmp(buf, "sae_reflection_attack") == 0) {
|
||||
bss->sae_reflection_attack = atoi(pos);
|
||||
} else if (os_strcmp(buf, "sae_commit_status") == 0) {
|
||||
|
@ -4452,8 +4613,13 @@ static int hostapd_config_fill(struct hostapd_config *conf,
|
|||
return 1;
|
||||
} else if (os_strcmp(buf, "eapol_m3_no_encrypt") == 0) {
|
||||
bss->eapol_m3_no_encrypt = atoi(pos);
|
||||
} else if (os_strcmp(buf, "eapol_key_reserved_random") == 0) {
|
||||
bss->eapol_key_reserved_random = atoi(pos);
|
||||
} else if (os_strcmp(buf, "test_assoc_comeback_type") == 0) {
|
||||
bss->test_assoc_comeback_type = atoi(pos);
|
||||
} else if (os_strcmp(buf, "presp_elements") == 0) {
|
||||
if (parse_wpabuf_hex(line, buf, &bss->presp_elements, pos))
|
||||
return 1;
|
||||
#endif /* CONFIG_TESTING_OPTIONS */
|
||||
#ifdef CONFIG_SAE
|
||||
} else if (os_strcmp(buf, "sae_password") == 0) {
|
||||
|
@ -4600,6 +4766,10 @@ static int hostapd_config_fill(struct hostapd_config *conf,
|
|||
WLAN_RRM_CAPS_BEACON_REPORT_PASSIVE |
|
||||
WLAN_RRM_CAPS_BEACON_REPORT_ACTIVE |
|
||||
WLAN_RRM_CAPS_BEACON_REPORT_TABLE;
|
||||
} else if (os_strcmp(buf, "rrm_link_measurement_report") == 0) {
|
||||
if (atoi(pos))
|
||||
bss->radio_measurements[0] |=
|
||||
WLAN_RRM_CAPS_LINK_MEASUREMENT;
|
||||
} else if (os_strcmp(buf, "gas_address3") == 0) {
|
||||
bss->gas_address3 = atoi(pos);
|
||||
} else if (os_strcmp(buf, "stationary_ap") == 0) {
|
||||
|
@ -4740,6 +4910,36 @@ static int hostapd_config_fill(struct hostapd_config *conf,
|
|||
}
|
||||
|
||||
bss->multi_ap = val;
|
||||
} else if (os_strcmp(buf, "multi_ap_profile") == 0) {
|
||||
int val = atoi(pos);
|
||||
|
||||
if (val < MULTI_AP_PROFILE_1 || val > MULTI_AP_PROFILE_MAX) {
|
||||
wpa_printf(MSG_ERROR,
|
||||
"Line %d: Invalid multi_ap_profile '%s'",
|
||||
line, buf);
|
||||
return -1;
|
||||
}
|
||||
bss->multi_ap_profile = val;
|
||||
} else if (os_strcmp(buf, "multi_ap_client_disallow") == 0) {
|
||||
int val = atoi(pos);
|
||||
|
||||
if (val < 0 || val > 3) {
|
||||
wpa_printf(MSG_ERROR,
|
||||
"Line %d: Invalid multi_ap_client_allow '%s'",
|
||||
line, buf);
|
||||
return -1;
|
||||
}
|
||||
bss->multi_ap_client_disallow = val;
|
||||
} else if (os_strcmp(buf, "multi_ap_vlanid") == 0) {
|
||||
int val = atoi(pos);
|
||||
|
||||
if (val < 0 || val > MAX_VLAN_ID) {
|
||||
wpa_printf(MSG_ERROR,
|
||||
"Line %d: Invalid multi_ap_vlan_id '%s'",
|
||||
line, buf);
|
||||
return -1;
|
||||
}
|
||||
bss->multi_ap_vlanid = val;
|
||||
} else if (os_strcmp(buf, "rssi_reject_assoc_rssi") == 0) {
|
||||
conf->rssi_reject_assoc_rssi = atoi(pos);
|
||||
} else if (os_strcmp(buf, "rssi_reject_assoc_timeout") == 0) {
|
||||
|
@ -4922,6 +5122,12 @@ static int hostapd_config_fill(struct hostapd_config *conf,
|
|||
return 1;
|
||||
} else if (os_strcmp(buf, "rnr") == 0) {
|
||||
bss->rnr = atoi(pos);
|
||||
} else if (os_strcmp(buf, "ssid_protection") == 0) {
|
||||
int val = atoi(pos);
|
||||
|
||||
if (val < 0 || val > 1)
|
||||
return 1;
|
||||
bss->ssid_protection = val;
|
||||
#ifdef CONFIG_IEEE80211BE
|
||||
} else if (os_strcmp(buf, "ieee80211be") == 0) {
|
||||
conf->ieee80211be = atoi(pos);
|
||||
|
@ -4952,8 +5158,6 @@ static int hostapd_config_fill(struct hostapd_config *conf,
|
|||
conf->punct_acs_threshold = val;
|
||||
} else if (os_strcmp(buf, "mld_ap") == 0) {
|
||||
bss->mld_ap = !!atoi(pos);
|
||||
} else if (os_strcmp(buf, "mld_id") == 0) {
|
||||
bss->mld_id = atoi(pos);
|
||||
} else if (os_strcmp(buf, "mld_addr") == 0) {
|
||||
if (hwaddr_aton(pos, bss->mld_addr)) {
|
||||
wpa_printf(MSG_ERROR, "Line %d: Invalid mld_addr",
|
||||
|
|
|
@ -1309,6 +1309,8 @@ static int hostapd_ctrl_iface_set(struct hostapd_data *hapd, char *cmd)
|
|||
hostapd_disassoc_deny_mac(hapd);
|
||||
} else if (os_strcasecmp(cmd, "accept_mac_file") == 0) {
|
||||
hostapd_disassoc_accept_mac(hapd);
|
||||
} else if (os_strcasecmp(cmd, "ssid") == 0) {
|
||||
hostapd_neighbor_sync_own_report(hapd);
|
||||
} else if (os_strncmp(cmd, "wme_ac_", 7) == 0 ||
|
||||
os_strncmp(cmd, "wmm_ac_", 7) == 0) {
|
||||
hapd->parameter_set_count++;
|
||||
|
@ -1942,7 +1944,7 @@ static int hostapd_ctrl_iface_data_test_config(struct hostapd_data *hapd,
|
|||
|
||||
#ifdef CONFIG_IEEE80211BE
|
||||
if (hapd->conf->mld_ap)
|
||||
addr = hapd->mld_addr;
|
||||
addr = hapd->mld->mld_addr;
|
||||
#endif /* CONFIG_IEEE80211BE */
|
||||
hapd->l2_test = l2_packet_init(ifname, addr,
|
||||
ETHERTYPE_IP, hostapd_data_test_rx,
|
||||
|
@ -2452,6 +2454,31 @@ static int hostapd_ctrl_register_frame(struct hostapd_data *hapd,
|
|||
|
||||
|
||||
#ifdef NEED_AP_MLME
|
||||
|
||||
static bool
|
||||
hostapd_ctrl_is_freq_in_cmode(struct hostapd_hw_modes *mode,
|
||||
struct hostapd_multi_hw_info *current_hw_info,
|
||||
int freq)
|
||||
{
|
||||
struct hostapd_channel_data *chan;
|
||||
int i;
|
||||
|
||||
for (i = 0; i < mode->num_channels; i++) {
|
||||
chan = &mode->channels[i];
|
||||
|
||||
if (chan->flag & HOSTAPD_CHAN_DISABLED)
|
||||
continue;
|
||||
|
||||
if (!chan_in_current_hw_info(current_hw_info, chan))
|
||||
continue;
|
||||
|
||||
if (chan->freq == freq)
|
||||
return true;
|
||||
}
|
||||
return false;
|
||||
}
|
||||
|
||||
|
||||
static int hostapd_ctrl_check_freq_params(struct hostapd_freq_params *params,
|
||||
u16 punct_bitmap)
|
||||
{
|
||||
|
@ -2475,6 +2502,21 @@ static int hostapd_ctrl_check_freq_params(struct hostapd_freq_params *params,
|
|||
bw_idx[bw] != params->bandwidth)
|
||||
return -1;
|
||||
}
|
||||
} else { /* Non-6 GHz channel */
|
||||
/* An EHT STA is also an HE STA as defined in
|
||||
* IEEE P802.11be/D5.0, 4.3.16a. */
|
||||
if (params->he_enabled || params->eht_enabled) {
|
||||
params->he_enabled = 1;
|
||||
/* An HE STA is also a VHT STA if operating in the 5 GHz
|
||||
* band and an HE STA is also an HT STA in the 2.4 GHz
|
||||
* band as defined in IEEE Std 802.11ax-2021, 4.3.15a.
|
||||
* A VHT STA is an HT STA as defined in IEEE
|
||||
* Std 802.11, 4.3.15. */
|
||||
if (IS_5GHZ(params->freq))
|
||||
params->vht_enabled = 1;
|
||||
|
||||
params->ht_enabled = 1;
|
||||
}
|
||||
}
|
||||
|
||||
switch (params->bandwidth) {
|
||||
|
@ -2638,6 +2680,8 @@ static int hostapd_ctrl_iface_chan_switch(struct hostapd_iface *iface,
|
|||
unsigned int i;
|
||||
int bandwidth;
|
||||
u8 chan;
|
||||
unsigned int num_err = 0;
|
||||
int err = 0;
|
||||
|
||||
ret = hostapd_parse_csa_settings(pos, &settings);
|
||||
if (ret)
|
||||
|
@ -2649,6 +2693,15 @@ static int hostapd_ctrl_iface_chan_switch(struct hostapd_iface *iface,
|
|||
settings.link_id = iface->bss[0]->mld_link_id;
|
||||
#endif /* CONFIG_IEEE80211BE */
|
||||
|
||||
if (iface->num_hw_features > 1 &&
|
||||
!hostapd_ctrl_is_freq_in_cmode(iface->current_mode,
|
||||
iface->current_hw_info,
|
||||
settings.freq_params.freq)) {
|
||||
wpa_printf(MSG_INFO,
|
||||
"chanswitch: Invalid frequency settings provided for multi band phy");
|
||||
return -1;
|
||||
}
|
||||
|
||||
ret = hostapd_ctrl_check_freq_params(&settings.freq_params,
|
||||
settings.punct_bitmap);
|
||||
if (ret) {
|
||||
|
@ -2711,29 +2764,128 @@ static int hostapd_ctrl_iface_chan_switch(struct hostapd_iface *iface,
|
|||
settings.freq_params.center_freq1);
|
||||
|
||||
/* Perform CAC and switch channel */
|
||||
iface->is_ch_switch_dfs = true;
|
||||
hostapd_switch_channel_fallback(iface, &settings.freq_params);
|
||||
return 0;
|
||||
}
|
||||
|
||||
if (iface->cac_started) {
|
||||
wpa_printf(MSG_DEBUG,
|
||||
"CAC is in progress - switching channel without CSA");
|
||||
return hostapd_force_channel_switch(iface, settings);
|
||||
}
|
||||
|
||||
for (i = 0; i < iface->num_bss; i++) {
|
||||
|
||||
/* Save CHAN_SWITCH VHT, HE, and EHT config */
|
||||
hostapd_chan_switch_config(iface->bss[i],
|
||||
&settings.freq_params);
|
||||
|
||||
ret = hostapd_switch_channel(iface->bss[i], &settings);
|
||||
if (ret) {
|
||||
/* FIX: What do we do if CSA fails in the middle of
|
||||
* submitting multi-BSS CSA requests? */
|
||||
return ret;
|
||||
err = hostapd_switch_channel(iface->bss[i], &settings);
|
||||
if (err) {
|
||||
ret = err;
|
||||
num_err++;
|
||||
}
|
||||
}
|
||||
|
||||
return (iface->num_bss == num_err) ? ret : 0;
|
||||
#else /* NEED_AP_MLME */
|
||||
return -1;
|
||||
#endif /* NEED_AP_MLME */
|
||||
}
|
||||
|
||||
|
||||
#ifdef CONFIG_IEEE80211AX
|
||||
static int hostapd_ctrl_iface_color_change(struct hostapd_iface *iface,
|
||||
const char *pos)
|
||||
{
|
||||
#ifdef NEED_AP_MLME
|
||||
struct cca_settings settings;
|
||||
struct hostapd_data *hapd = iface->bss[0];
|
||||
int ret, color;
|
||||
unsigned int i;
|
||||
char *end;
|
||||
|
||||
os_memset(&settings, 0, sizeof(settings));
|
||||
|
||||
color = strtol(pos, &end, 10);
|
||||
if (pos == end || color < 0 || color > 63) {
|
||||
wpa_printf(MSG_ERROR, "color_change: Invalid color provided");
|
||||
return -1;
|
||||
}
|
||||
|
||||
/* Color value is expected to be [1-63]. If 0 comes, assumption is this
|
||||
* is to disable the color. In this case no need to do CCA, just
|
||||
* changing Beacon frames is sufficient. */
|
||||
if (color == 0) {
|
||||
if (iface->conf->he_op.he_bss_color_disabled) {
|
||||
wpa_printf(MSG_ERROR,
|
||||
"color_change: Color is already disabled");
|
||||
return -1;
|
||||
}
|
||||
|
||||
iface->conf->he_op.he_bss_color_disabled = 1;
|
||||
|
||||
for (i = 0; i < iface->num_bss; i++)
|
||||
ieee802_11_set_beacon(iface->bss[i]);
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
if (color == iface->conf->he_op.he_bss_color) {
|
||||
if (!iface->conf->he_op.he_bss_color_disabled) {
|
||||
wpa_printf(MSG_ERROR,
|
||||
"color_change: Provided color is already set");
|
||||
return -1;
|
||||
}
|
||||
|
||||
iface->conf->he_op.he_bss_color_disabled = 0;
|
||||
|
||||
for (i = 0; i < iface->num_bss; i++)
|
||||
ieee802_11_set_beacon(iface->bss[i]);
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
if (hapd->cca_in_progress) {
|
||||
wpa_printf(MSG_ERROR,
|
||||
"color_change: CCA is already in progress");
|
||||
return -1;
|
||||
}
|
||||
|
||||
iface->conf->he_op.he_bss_color_disabled = 0;
|
||||
|
||||
for (i = 0; i < iface->num_bss; i++) {
|
||||
struct hostapd_data *bss = iface->bss[i];
|
||||
|
||||
hostapd_cleanup_cca_params(bss);
|
||||
|
||||
bss->cca_color = color;
|
||||
bss->cca_count = 10;
|
||||
|
||||
if (hostapd_fill_cca_settings(bss, &settings)) {
|
||||
wpa_printf(MSG_DEBUG,
|
||||
"color_change: Filling CCA settings failed for color: %d\n",
|
||||
color);
|
||||
hostapd_cleanup_cca_params(bss);
|
||||
continue;
|
||||
}
|
||||
|
||||
wpa_printf(MSG_DEBUG, "Setting user selected color: %d", color);
|
||||
ret = hostapd_drv_switch_color(bss, &settings);
|
||||
if (ret)
|
||||
hostapd_cleanup_cca_params(bss);
|
||||
|
||||
free_beacon_data(&settings.beacon_cca);
|
||||
free_beacon_data(&settings.beacon_after);
|
||||
}
|
||||
|
||||
return 0;
|
||||
#else /* NEED_AP_MLME */
|
||||
return -1;
|
||||
#endif /* NEED_AP_MLME */
|
||||
}
|
||||
#endif /* CONFIG_IEEE80211AX */
|
||||
|
||||
|
||||
static u8 hostapd_maxnss(struct hostapd_data *hapd, struct sta_info *sta)
|
||||
|
@ -3203,6 +3355,26 @@ static int hostapd_ctrl_iface_req_beacon(struct hostapd_data *hapd,
|
|||
}
|
||||
|
||||
|
||||
static int hostapd_ctrl_iface_req_link_measurement(struct hostapd_data *hapd,
|
||||
const char *cmd, char *reply,
|
||||
size_t reply_size)
|
||||
{
|
||||
u8 addr[ETH_ALEN];
|
||||
int ret;
|
||||
|
||||
if (hwaddr_aton(cmd, addr)) {
|
||||
wpa_printf(MSG_ERROR,
|
||||
"CTRL: REQ_LINK_MEASUREMENT: Invalid MAC address");
|
||||
return -1;
|
||||
}
|
||||
|
||||
ret = hostapd_send_link_measurement_req(hapd, addr);
|
||||
if (ret >= 0)
|
||||
ret = os_snprintf(reply, reply_size, "%d", ret);
|
||||
return ret;
|
||||
}
|
||||
|
||||
|
||||
static int hostapd_ctrl_iface_show_neighbor(struct hostapd_data *hapd,
|
||||
char *buf, size_t buflen)
|
||||
{
|
||||
|
@ -3473,10 +3645,8 @@ static int hostapd_ctrl_iface_enable_mld(struct hostapd_iface *iface)
|
|||
for (i = 0; i < iface->interfaces->count; ++i) {
|
||||
struct hostapd_iface *h_iface = iface->interfaces->iface[i];
|
||||
struct hostapd_data *h_hapd = h_iface->bss[0];
|
||||
struct hostapd_bss_config *h_conf = h_hapd->conf;
|
||||
|
||||
if (!h_conf->mld_ap ||
|
||||
h_conf->mld_id != iface->bss[0]->conf->mld_id)
|
||||
if (!hostapd_is_ml_partner(h_hapd, iface->bss[0]))
|
||||
continue;
|
||||
|
||||
if (hostapd_enable_iface(h_iface)) {
|
||||
|
@ -3500,7 +3670,6 @@ static void hostapd_disable_iface_bss(struct hostapd_iface *iface)
|
|||
static int hostapd_ctrl_iface_disable_mld(struct hostapd_iface *iface)
|
||||
{
|
||||
unsigned int i;
|
||||
struct hostapd_iface *first_iface = NULL;
|
||||
|
||||
if (!iface || !iface->bss[0]->conf->mld_ap) {
|
||||
wpa_printf(MSG_ERROR,
|
||||
|
@ -3514,32 +3683,19 @@ static int hostapd_ctrl_iface_disable_mld(struct hostapd_iface *iface)
|
|||
for (i = 0; i < iface->interfaces->count; ++i) {
|
||||
struct hostapd_iface *h_iface = iface->interfaces->iface[i];
|
||||
struct hostapd_data *h_hapd = h_iface->bss[0];
|
||||
struct hostapd_bss_config *h_conf = h_hapd->conf;
|
||||
|
||||
if (!h_conf->mld_ap ||
|
||||
h_conf->mld_id != iface->bss[0]->conf->mld_id)
|
||||
if (!hostapd_is_ml_partner(h_hapd, iface->bss[0]))
|
||||
continue;
|
||||
|
||||
if (!h_hapd->mld_first_bss) {
|
||||
first_iface = h_iface;
|
||||
continue;
|
||||
}
|
||||
hostapd_disable_iface_bss(iface);
|
||||
}
|
||||
|
||||
if (first_iface)
|
||||
hostapd_disable_iface_bss(first_iface);
|
||||
|
||||
/* Then, fully disable interfaces */
|
||||
|
||||
for (i = 0; i < iface->interfaces->count; ++i) {
|
||||
struct hostapd_iface *h_iface = iface->interfaces->iface[i];
|
||||
struct hostapd_data *h_hapd = h_iface->bss[0];
|
||||
struct hostapd_bss_config *h_conf = h_hapd->conf;
|
||||
|
||||
if (!h_conf->mld_ap ||
|
||||
h_conf->mld_id != iface->bss[0]->conf->mld_id ||
|
||||
!h_hapd->mld_first_bss)
|
||||
if (!hostapd_is_ml_partner(h_hapd, iface->bss[0]))
|
||||
continue;
|
||||
|
||||
if (hostapd_disable_iface(h_iface)) {
|
||||
|
@ -3548,11 +3704,6 @@ static int hostapd_ctrl_iface_disable_mld(struct hostapd_iface *iface)
|
|||
}
|
||||
}
|
||||
|
||||
if (first_iface && hostapd_disable_iface(first_iface)) {
|
||||
wpa_printf(MSG_ERROR, "Disabling AP MLD failed");
|
||||
return -1;
|
||||
}
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
|
@ -3594,6 +3745,7 @@ static int hostapd_ctrl_nan_publish(struct hostapd_data *hapd, char *cmd,
|
|||
struct wpabuf *ssi = NULL;
|
||||
int ret = -1;
|
||||
enum nan_service_protocol_type srv_proto_type = 0;
|
||||
bool p2p = false;
|
||||
|
||||
os_memset(¶ms, 0, sizeof(params));
|
||||
/* USD shall use both solicited and unsolicited transmissions */
|
||||
|
@ -3627,6 +3779,11 @@ static int hostapd_ctrl_nan_publish(struct hostapd_data *hapd, char *cmd,
|
|||
continue;
|
||||
}
|
||||
|
||||
if (os_strcmp(token, "p2p=1") == 0) {
|
||||
p2p = true;
|
||||
continue;
|
||||
}
|
||||
|
||||
if (os_strcmp(token, "solicited=0") == 0) {
|
||||
params.solicited = false;
|
||||
continue;
|
||||
|
@ -3648,7 +3805,7 @@ static int hostapd_ctrl_nan_publish(struct hostapd_data *hapd, char *cmd,
|
|||
}
|
||||
|
||||
publish_id = hostapd_nan_usd_publish(hapd, service_name, srv_proto_type,
|
||||
ssi, ¶ms);
|
||||
ssi, ¶ms, p2p);
|
||||
if (publish_id > 0)
|
||||
ret = os_snprintf(buf, buflen, "%d", publish_id);
|
||||
fail:
|
||||
|
@ -3731,6 +3888,7 @@ static int hostapd_ctrl_nan_subscribe(struct hostapd_data *hapd, char *cmd,
|
|||
struct wpabuf *ssi = NULL;
|
||||
int ret = -1;
|
||||
enum nan_service_protocol_type srv_proto_type = 0;
|
||||
bool p2p = false;
|
||||
|
||||
os_memset(¶ms, 0, sizeof(params));
|
||||
|
||||
|
@ -3764,6 +3922,11 @@ static int hostapd_ctrl_nan_subscribe(struct hostapd_data *hapd, char *cmd,
|
|||
continue;
|
||||
}
|
||||
|
||||
if (os_strcmp(token, "p2p=1") == 0) {
|
||||
p2p = true;
|
||||
continue;
|
||||
}
|
||||
|
||||
wpa_printf(MSG_INFO,
|
||||
"CTRL: Invalid NAN_SUBSCRIBE parameter: %s",
|
||||
token);
|
||||
|
@ -3772,7 +3935,7 @@ static int hostapd_ctrl_nan_subscribe(struct hostapd_data *hapd, char *cmd,
|
|||
|
||||
subscribe_id = hostapd_nan_usd_subscribe(hapd, service_name,
|
||||
srv_proto_type, ssi,
|
||||
¶ms);
|
||||
¶ms, p2p);
|
||||
if (subscribe_id > 0)
|
||||
ret = os_snprintf(buf, buflen, "%d", subscribe_id);
|
||||
fail:
|
||||
|
@ -4151,6 +4314,11 @@ static int hostapd_ctrl_iface_receive_process(struct hostapd_data *hapd,
|
|||
} else if (os_strncmp(buf, "CHAN_SWITCH ", 12) == 0) {
|
||||
if (hostapd_ctrl_iface_chan_switch(hapd->iface, buf + 12))
|
||||
reply_len = -1;
|
||||
#ifdef CONFIG_IEEE80211AX
|
||||
} else if (os_strncmp(buf, "COLOR_CHANGE ", 13) == 0) {
|
||||
if (hostapd_ctrl_iface_color_change(hapd->iface, buf + 13))
|
||||
reply_len = -1;
|
||||
#endif /* CONFIG_IEEE80211AX */
|
||||
} else if (os_strncmp(buf, "NOTIFY_CW_CHANGE ", 17) == 0) {
|
||||
if (hostapd_ctrl_iface_notify_cw_change(hapd, buf + 17))
|
||||
reply_len = -1;
|
||||
|
@ -4202,6 +4370,9 @@ static int hostapd_ctrl_iface_receive_process(struct hostapd_data *hapd,
|
|||
} else if (os_strncmp(buf, "REQ_BEACON ", 11) == 0) {
|
||||
reply_len = hostapd_ctrl_iface_req_beacon(hapd, buf + 11,
|
||||
reply, reply_size);
|
||||
} else if (os_strncmp(buf, "REQ_LINK_MEASUREMENT ", 21) == 0) {
|
||||
reply_len = hostapd_ctrl_iface_req_link_measurement(
|
||||
hapd, buf + 21, reply, reply_size);
|
||||
} else if (os_strcmp(buf, "DRIVER_FLAGS") == 0) {
|
||||
reply_len = hostapd_ctrl_driver_flags(hapd->iface, reply,
|
||||
reply_size);
|
||||
|
@ -4563,23 +4734,360 @@ done:
|
|||
}
|
||||
|
||||
|
||||
#ifdef CONFIG_IEEE80211BE
|
||||
#ifndef CONFIG_CTRL_IFACE_UDP
|
||||
|
||||
static int hostapd_mld_ctrl_iface_receive_process(struct hostapd_mld *mld,
|
||||
char *buf, char *reply,
|
||||
size_t reply_size,
|
||||
struct sockaddr_storage *from,
|
||||
socklen_t fromlen)
|
||||
{
|
||||
struct hostapd_data *link_hapd, *link_itr;
|
||||
int reply_len = -1, link_id = -1;
|
||||
char *cmd;
|
||||
bool found = false;
|
||||
|
||||
os_memcpy(reply, "OK\n", 3);
|
||||
reply_len = 3;
|
||||
|
||||
cmd = buf;
|
||||
|
||||
/* Check whether the link ID is provided in the command */
|
||||
if (os_strncmp(cmd, "LINKID ", 7) == 0) {
|
||||
cmd += 7;
|
||||
link_id = atoi(cmd);
|
||||
if (link_id < 0 || link_id >= 15) {
|
||||
os_memcpy(reply, "INVALID LINK ID\n", 16);
|
||||
reply_len = 16;
|
||||
goto out;
|
||||
}
|
||||
|
||||
cmd = os_strchr(cmd, ' ');
|
||||
if (!cmd)
|
||||
goto out;
|
||||
cmd++;
|
||||
}
|
||||
if (link_id >= 0) {
|
||||
link_hapd = mld->fbss;
|
||||
if (!link_hapd) {
|
||||
os_memcpy(reply, "NO LINKS ACTIVE\n", 16);
|
||||
reply_len = 16;
|
||||
goto out;
|
||||
}
|
||||
|
||||
for_each_mld_link(link_itr, link_hapd) {
|
||||
if (link_itr->mld_link_id == link_id) {
|
||||
found = true;
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
if (!found)
|
||||
goto out;
|
||||
|
||||
link_hapd = link_itr;
|
||||
} else {
|
||||
link_hapd = mld->fbss;
|
||||
}
|
||||
|
||||
if (os_strcmp(cmd, "PING") == 0) {
|
||||
os_memcpy(reply, "PONG\n", 5);
|
||||
reply_len = 5;
|
||||
} else if (os_strcmp(cmd, "ATTACH") == 0) {
|
||||
if (ctrl_iface_attach(&mld->ctrl_dst, from, fromlen, NULL))
|
||||
reply_len = -1;
|
||||
} else if (os_strncmp(cmd, "ATTACH ", 7) == 0) {
|
||||
if (ctrl_iface_attach(&mld->ctrl_dst, from, fromlen, cmd + 7))
|
||||
reply_len = -1;
|
||||
} else if (os_strcmp(cmd, "DETACH") == 0) {
|
||||
if (ctrl_iface_detach(&mld->ctrl_dst, from, fromlen))
|
||||
reply_len = -1;
|
||||
} else {
|
||||
if (link_id == -1)
|
||||
wpa_printf(MSG_DEBUG,
|
||||
"Link ID not provided, using the first link BSS (if available)");
|
||||
|
||||
if (!link_hapd)
|
||||
reply_len = -1;
|
||||
else
|
||||
reply_len =
|
||||
hostapd_ctrl_iface_receive_process(
|
||||
link_hapd, cmd, reply, reply_size,
|
||||
from, fromlen);
|
||||
}
|
||||
|
||||
out:
|
||||
if (reply_len < 0) {
|
||||
os_memcpy(reply, "FAIL\n", 5);
|
||||
reply_len = 5;
|
||||
}
|
||||
|
||||
return reply_len;
|
||||
}
|
||||
|
||||
|
||||
static void hostapd_mld_ctrl_iface_receive(int sock, void *eloop_ctx,
|
||||
void *sock_ctx)
|
||||
{
|
||||
struct hostapd_mld *mld = eloop_ctx;
|
||||
char buf[4096];
|
||||
int res;
|
||||
struct sockaddr_storage from;
|
||||
socklen_t fromlen = sizeof(from);
|
||||
char *reply, *pos = buf;
|
||||
const size_t reply_size = 4096;
|
||||
int reply_len;
|
||||
int level = MSG_DEBUG;
|
||||
|
||||
res = recvfrom(sock, buf, sizeof(buf) - 1, 0,
|
||||
(struct sockaddr *) &from, &fromlen);
|
||||
if (res < 0) {
|
||||
wpa_printf(MSG_ERROR, "recvfrom(mld ctrl_iface): %s",
|
||||
strerror(errno));
|
||||
return;
|
||||
}
|
||||
buf[res] = '\0';
|
||||
|
||||
reply = os_malloc(reply_size);
|
||||
if (!reply) {
|
||||
if (sendto(sock, "FAIL\n", 5, 0, (struct sockaddr *) &from,
|
||||
fromlen) < 0) {
|
||||
wpa_printf(MSG_DEBUG, "MLD CTRL: sendto failed: %s",
|
||||
strerror(errno));
|
||||
}
|
||||
return;
|
||||
}
|
||||
|
||||
if (os_strcmp(pos, "PING") == 0)
|
||||
level = MSG_EXCESSIVE;
|
||||
|
||||
wpa_hexdump_ascii(level, "RX MLD ctrl_iface", pos, res);
|
||||
|
||||
reply_len = hostapd_mld_ctrl_iface_receive_process(mld, pos,
|
||||
reply, reply_size,
|
||||
&from, fromlen);
|
||||
|
||||
if (sendto(sock, reply, reply_len, 0, (struct sockaddr *) &from,
|
||||
fromlen) < 0) {
|
||||
wpa_printf(MSG_DEBUG, "MLD CTRL: sendto failed: %s",
|
||||
strerror(errno));
|
||||
}
|
||||
os_free(reply);
|
||||
}
|
||||
|
||||
|
||||
static char * hostapd_mld_ctrl_iface_path(struct hostapd_mld *mld)
|
||||
{
|
||||
size_t len;
|
||||
char *buf;
|
||||
int ret;
|
||||
|
||||
if (!mld->ctrl_interface)
|
||||
return NULL;
|
||||
|
||||
len = os_strlen(mld->ctrl_interface) + os_strlen(mld->name) + 2;
|
||||
|
||||
buf = os_malloc(len);
|
||||
if (!buf)
|
||||
return NULL;
|
||||
|
||||
ret = os_snprintf(buf, len, "%s/%s", mld->ctrl_interface, mld->name);
|
||||
if (os_snprintf_error(len, ret)) {
|
||||
os_free(buf);
|
||||
return NULL;
|
||||
}
|
||||
|
||||
return buf;
|
||||
}
|
||||
|
||||
#endif /* !CONFIG_CTRL_IFACE_UDP */
|
||||
|
||||
|
||||
int hostapd_mld_ctrl_iface_init(struct hostapd_mld *mld)
|
||||
{
|
||||
#ifndef CONFIG_CTRL_IFACE_UDP
|
||||
struct sockaddr_un addr;
|
||||
int s = -1;
|
||||
char *fname = NULL;
|
||||
|
||||
if (!mld)
|
||||
return -1;
|
||||
|
||||
if (mld->ctrl_sock > -1) {
|
||||
wpa_printf(MSG_DEBUG, "MLD %s ctrl_iface already exists!",
|
||||
mld->name);
|
||||
return 0;
|
||||
}
|
||||
|
||||
dl_list_init(&mld->ctrl_dst);
|
||||
|
||||
if (!mld->ctrl_interface)
|
||||
return 0;
|
||||
|
||||
if (mkdir(mld->ctrl_interface, S_IRWXU | S_IRWXG) < 0) {
|
||||
if (errno == EEXIST) {
|
||||
wpa_printf(MSG_DEBUG,
|
||||
"Using existing control interface directory.");
|
||||
} else {
|
||||
wpa_printf(MSG_ERROR, "mkdir[ctrl_interface]: %s",
|
||||
strerror(errno));
|
||||
goto fail;
|
||||
}
|
||||
}
|
||||
|
||||
if (os_strlen(mld->ctrl_interface) + 1 + os_strlen(mld->name) >=
|
||||
sizeof(addr.sun_path))
|
||||
goto fail;
|
||||
|
||||
s = socket(PF_UNIX, SOCK_DGRAM, 0);
|
||||
if (s < 0) {
|
||||
wpa_printf(MSG_ERROR, "socket(PF_UNIX): %s", strerror(errno));
|
||||
goto fail;
|
||||
}
|
||||
|
||||
os_memset(&addr, 0, sizeof(addr));
|
||||
#ifdef __FreeBSD__
|
||||
addr.sun_len = sizeof(addr);
|
||||
#endif /* __FreeBSD__ */
|
||||
addr.sun_family = AF_UNIX;
|
||||
|
||||
fname = hostapd_mld_ctrl_iface_path(mld);
|
||||
if (!fname)
|
||||
goto fail;
|
||||
|
||||
os_strlcpy(addr.sun_path, fname, sizeof(addr.sun_path));
|
||||
|
||||
wpa_printf(MSG_DEBUG, "Setting up MLD %s ctrl_iface", mld->name);
|
||||
|
||||
if (bind(s, (struct sockaddr *) &addr, sizeof(addr)) < 0) {
|
||||
wpa_printf(MSG_DEBUG, "ctrl_iface bind(PF_UNIX) failed: %s",
|
||||
strerror(errno));
|
||||
if (connect(s, (struct sockaddr *) &addr, sizeof(addr)) < 0) {
|
||||
wpa_printf(MSG_DEBUG, "ctrl_iface exists, but does not allow connections - assuming it was left over from forced program termination");
|
||||
if (unlink(fname) < 0) {
|
||||
wpa_printf(MSG_ERROR,
|
||||
"Could not unlink existing ctrl_iface socket '%s': %s",
|
||||
fname, strerror(errno));
|
||||
goto fail;
|
||||
}
|
||||
if (bind(s, (struct sockaddr *) &addr, sizeof(addr)) <
|
||||
0) {
|
||||
wpa_printf(MSG_ERROR,
|
||||
"hostapd-ctrl-iface: bind(PF_UNIX): %s",
|
||||
strerror(errno));
|
||||
goto fail;
|
||||
}
|
||||
wpa_printf(MSG_DEBUG,
|
||||
"Successfully replaced leftover ctrl_iface socket '%s'",
|
||||
fname);
|
||||
} else {
|
||||
wpa_printf(MSG_INFO,
|
||||
"ctrl_iface exists and seems to be in use - cannot override it");
|
||||
wpa_printf(MSG_INFO,
|
||||
"Delete '%s' manually if it is not used anymore", fname);
|
||||
os_free(fname);
|
||||
fname = NULL;
|
||||
goto fail;
|
||||
}
|
||||
}
|
||||
|
||||
if (chmod(fname, S_IRWXU | S_IRWXG) < 0) {
|
||||
wpa_printf(MSG_ERROR, "chmod[ctrl_interface/ifname]: %s",
|
||||
strerror(errno));
|
||||
goto fail;
|
||||
}
|
||||
os_free(fname);
|
||||
|
||||
mld->ctrl_sock = s;
|
||||
|
||||
if (eloop_register_read_sock(s, hostapd_mld_ctrl_iface_receive, mld,
|
||||
NULL) < 0)
|
||||
return -1;
|
||||
|
||||
return 0;
|
||||
|
||||
fail:
|
||||
if (s >= 0)
|
||||
close(s);
|
||||
if (fname) {
|
||||
unlink(fname);
|
||||
os_free(fname);
|
||||
}
|
||||
return -1;
|
||||
#endif /* !CONFIG_CTRL_IFACE_UDP */
|
||||
return 0;
|
||||
}
|
||||
|
||||
|
||||
void hostapd_mld_ctrl_iface_deinit(struct hostapd_mld *mld)
|
||||
{
|
||||
#ifndef CONFIG_CTRL_IFACE_UDP
|
||||
struct wpa_ctrl_dst *dst, *prev;
|
||||
|
||||
if (mld->ctrl_sock > -1) {
|
||||
char *fname;
|
||||
|
||||
eloop_unregister_read_sock(mld->ctrl_sock);
|
||||
close(mld->ctrl_sock);
|
||||
mld->ctrl_sock = -1;
|
||||
|
||||
fname = hostapd_mld_ctrl_iface_path(mld);
|
||||
if (fname) {
|
||||
unlink(fname);
|
||||
os_free(fname);
|
||||
}
|
||||
|
||||
if (mld->ctrl_interface &&
|
||||
rmdir(mld->ctrl_interface) < 0) {
|
||||
if (errno == ENOTEMPTY) {
|
||||
wpa_printf(MSG_DEBUG,
|
||||
"MLD control interface directory not empty - leaving it behind");
|
||||
} else {
|
||||
wpa_printf(MSG_ERROR,
|
||||
"rmdir[ctrl_interface=%s]: %s",
|
||||
mld->ctrl_interface,
|
||||
strerror(errno));
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
dl_list_for_each_safe(dst, prev, &mld->ctrl_dst, struct wpa_ctrl_dst,
|
||||
list)
|
||||
os_free(dst);
|
||||
#endif /* !CONFIG_CTRL_IFACE_UDP */
|
||||
|
||||
os_free(mld->ctrl_interface);
|
||||
}
|
||||
|
||||
#endif /* CONFIG_IEEE80211BE */
|
||||
|
||||
|
||||
#ifndef CONFIG_CTRL_IFACE_UDP
|
||||
static char * hostapd_ctrl_iface_path(struct hostapd_data *hapd)
|
||||
{
|
||||
char *buf;
|
||||
size_t len;
|
||||
const char *ctrl_sock_iface;
|
||||
|
||||
#ifdef CONFIG_IEEE80211BE
|
||||
ctrl_sock_iface = hapd->ctrl_sock_iface;
|
||||
#else /* CONFIG_IEEE80211BE */
|
||||
ctrl_sock_iface = hapd->conf->iface;
|
||||
#endif /* CONFIG_IEEE80211BE */
|
||||
|
||||
if (hapd->conf->ctrl_interface == NULL)
|
||||
return NULL;
|
||||
|
||||
len = os_strlen(hapd->conf->ctrl_interface) +
|
||||
os_strlen(hapd->conf->iface) + 2;
|
||||
os_strlen(ctrl_sock_iface) + 2;
|
||||
|
||||
buf = os_malloc(len);
|
||||
if (buf == NULL)
|
||||
return NULL;
|
||||
|
||||
os_snprintf(buf, len, "%s/%s",
|
||||
hapd->conf->ctrl_interface, hapd->conf->iface);
|
||||
hapd->conf->ctrl_interface, ctrl_sock_iface);
|
||||
buf[len - 1] = '\0';
|
||||
return buf;
|
||||
}
|
||||
|
@ -4695,6 +5203,7 @@ fail:
|
|||
struct sockaddr_un addr;
|
||||
int s = -1;
|
||||
char *fname = NULL;
|
||||
size_t iflen;
|
||||
|
||||
if (hapd->ctrl_sock > -1) {
|
||||
wpa_printf(MSG_DEBUG, "ctrl_iface already exists!");
|
||||
|
@ -4749,8 +5258,13 @@ fail:
|
|||
}
|
||||
#endif /* ANDROID */
|
||||
|
||||
#ifdef CONFIG_IEEE80211BE
|
||||
iflen = os_strlen(hapd->ctrl_sock_iface);
|
||||
#else /* CONFIG_IEEE80211BE */
|
||||
iflen = os_strlen(hapd->conf->iface);
|
||||
#endif /* CONFIG_IEEE80211BE */
|
||||
if (os_strlen(hapd->conf->ctrl_interface) + 1 +
|
||||
os_strlen(hapd->conf->iface) >= sizeof(addr.sun_path))
|
||||
iflen >= sizeof(addr.sun_path))
|
||||
goto fail;
|
||||
|
||||
s = socket(PF_UNIX, SOCK_DGRAM, 0);
|
||||
|
@ -5358,7 +5872,7 @@ static void hostapd_global_ctrl_iface_receive(int sock, void *eloop_ctx,
|
|||
reply_len = -1;
|
||||
} else if (os_strncmp(buf, "INTERFACES", 10) == 0) {
|
||||
reply_len = hostapd_global_ctrl_iface_interfaces(
|
||||
interfaces, buf + 10, reply, sizeof(buffer));
|
||||
interfaces, buf + 10, reply, reply_size);
|
||||
} else if (os_strcmp(buf, "TERMINATE") == 0) {
|
||||
eloop_terminate();
|
||||
} else {
|
||||
|
|
|
@ -14,6 +14,8 @@ int hostapd_ctrl_iface_init(struct hostapd_data *hapd);
|
|||
void hostapd_ctrl_iface_deinit(struct hostapd_data *hapd);
|
||||
int hostapd_global_ctrl_iface_init(struct hapd_interfaces *interface);
|
||||
void hostapd_global_ctrl_iface_deinit(struct hapd_interfaces *interface);
|
||||
int hostapd_mld_ctrl_iface_init(struct hostapd_mld *mld);
|
||||
void hostapd_mld_ctrl_iface_deinit(struct hostapd_mld *mld);
|
||||
#else /* CONFIG_NO_CTRL_IFACE */
|
||||
static inline int hostapd_ctrl_iface_init(struct hostapd_data *hapd)
|
||||
{
|
||||
|
|
|
@ -141,6 +141,9 @@ CONFIG_PKCS12=y
|
|||
# Build IPv6 support for RADIUS operations
|
||||
CONFIG_IPV6=y
|
||||
|
||||
# Include support fo RADIUS/TLS into the RADIUS client
|
||||
#CONFIG_RADIUS_TLS=y
|
||||
|
||||
# IEEE Std 802.11r-2008 (Fast BSS Transition)
|
||||
#CONFIG_IEEE80211R=y
|
||||
|
||||
|
|
|
@ -522,6 +522,25 @@ wmm_ac_vo_acm=0
|
|||
# even if they are still in range of the AP. This can be done by setting
|
||||
# skip_inactivity_poll to 1 (default 0).
|
||||
#skip_inactivity_poll=0
|
||||
#
|
||||
# BSS max idle period management
|
||||
# 0 = disabled (do not advertise and manage BSS max idle period)
|
||||
# 1 = enabled (advertise and manage BSS max idle period; default)
|
||||
# 2 = enabled requiring protected frames (advertise and manage BSS max idle
|
||||
# period and require STAs to use protected keep-alive frames)
|
||||
#bss_max_idle=1
|
||||
#
|
||||
# Maximum acceptable BSS maximum idle period
|
||||
# If this is set to a nonzero value, the AP allows STAs to request different
|
||||
# maximum idle period values. This is in the units to 1000 TUs (1.024 s)
|
||||
#max_acceptable_idle_period=600
|
||||
#
|
||||
# Allow STA to skip group key handshake without getting disconnection when
|
||||
# BSS max idle period management is enabled.
|
||||
# 0 = disconnect STA if it does not reply to group key handshake (default)
|
||||
# 1 = do not disconnect STA if it does not reply to group key handshake and
|
||||
# if BSS max idle period management is enabled
|
||||
#no_disconnect_on_group_keyerror=0
|
||||
|
||||
# Disassociate stations based on excessive transmission failures or other
|
||||
# indications of connection loss. This depends on the driver capabilities and
|
||||
|
@ -646,6 +665,12 @@ wmm_ac_vo_acm=0
|
|||
# no co-existence issues with neighboring devices are found.
|
||||
#obss_interval=0
|
||||
|
||||
# ht_vht_twt_responder: Whether TWT responder is enabled in HT and VHT modes
|
||||
# 0 = disable; Disable TWT responder support in HT and VHT modes (default).
|
||||
# 1 = enable; Enable TWT responder support in HT and VHT modes if supported by
|
||||
# the driver.
|
||||
#ht_vht_twt_responder=0
|
||||
|
||||
##### IEEE 802.11ac related configuration #####################################
|
||||
|
||||
# ieee80211ac: Whether IEEE 802.11ac (VHT) is enabled
|
||||
|
@ -1071,9 +1096,6 @@ wmm_ac_vo_acm=0
|
|||
# 1 = yes (MLO)
|
||||
#mld_ap=0
|
||||
|
||||
# MLD ID - Affiliated MLD ID
|
||||
#mld_id=1
|
||||
|
||||
# AP MLD MAC address
|
||||
# The configured address will be set as the interface hardware address and used
|
||||
# as the AP MLD MAC address. If not set, the current interface hardware address
|
||||
|
@ -1581,6 +1603,16 @@ own_ip_addr=127.0.0.1
|
|||
#acct_server_port=1813
|
||||
#acct_server_shared_secret=secret2
|
||||
|
||||
# RADIUS/TLS instead of RADIUS/UDP
|
||||
#auth_server_addr=127.0.0.1
|
||||
#auth_server_port=2083
|
||||
#auth_server_type=TLS
|
||||
#auth_server_shared_secret=radsec
|
||||
#auth_server_ca_cert=<path to trusted CA certificate(s)>
|
||||
#auth_server_client_cert=<path to client certificate>
|
||||
#auth_server_private_key=<path to private key>
|
||||
#auth_server_private_key_passwd=<password for decrypting private key>
|
||||
|
||||
# Retry interval for trying to return to the primary RADIUS server (in
|
||||
# seconds). RADIUS client code will automatically try to use the next server
|
||||
# when the current server is not replying to requests. If this interval is set,
|
||||
|
@ -1588,6 +1620,17 @@ own_ip_addr=127.0.0.1
|
|||
# currently used secondary server is still working.
|
||||
#radius_retry_primary_interval=600
|
||||
|
||||
# Message-Authenticator attribute requirement for non-EAP cases
|
||||
# hostapd requires Message-Authenticator attribute to be included in all cases
|
||||
# where RADIUS is used for EAP authentication. This is also required for cases
|
||||
# where RADIUS is used for MAC ACL (macaddr_acl=2) by default, but that case
|
||||
# can be configured to not require this for compatibility with RADIUS servers
|
||||
# that do not include the attribute. This is not recommended due to potential
|
||||
# security concerns, but can be used as a temporary workaround in networks where
|
||||
# the connection to the RADIUS server is secure.
|
||||
# 0 = Do not require Message-Authenticator in MAC ACL response
|
||||
# 1 = Require Message-Authenticator in all authentication cases (default)
|
||||
#radius_require_message_authenticator=1
|
||||
|
||||
# Interim accounting update interval
|
||||
# If this is set (larger than 0) and acct_server is configured, hostapd will
|
||||
|
@ -2076,7 +2119,7 @@ own_ip_addr=127.0.0.1
|
|||
# Maximum number of SAE synchronization errors (dot11RSNASAESync)
|
||||
# The offending SAE peer will be disconnected if more than this many
|
||||
# synchronization errors happen.
|
||||
#sae_sync=5
|
||||
#sae_sync=3
|
||||
|
||||
# Enabled SAE finite cyclic groups
|
||||
# SAE implementation are required to support group 19 (ECC group defined over a
|
||||
|
@ -2236,6 +2279,86 @@ own_ip_addr=127.0.0.1
|
|||
# (default: 1 = activated)
|
||||
#pasn_noauth=1
|
||||
|
||||
# SSID protection in 4-way handshake
|
||||
# The IEEE 802.11i-2004 RSN design did not provide means for protecting the
|
||||
# SSID in the general case. IEEE P802.11REVme/D6.0 added support for this in
|
||||
# 4-way handshake. This capability allows a STA to confirm that the AP has the
|
||||
# same understanding on which SSID is being used for an association in a
|
||||
# protected manner in cases where both the AP and the STA has this capability.
|
||||
# This can be used to mitigate CVE-2023-52424 (a.k.a. the SSID Confusion
|
||||
# Attack).
|
||||
#
|
||||
# Ideally, this capability would be enabled by default on the AP, but since this
|
||||
# is new functionality with limited testing, the default is to disable this for
|
||||
# now and require explicitly configuration to enable. The default behavior is
|
||||
# like to change once this capability has received more testing.
|
||||
#
|
||||
# 0 = SSID protection in 4-way handshake disabled (default)
|
||||
# 1 = SSID protection in 4-way handshake enabled
|
||||
#
|
||||
#ssid_protection=0
|
||||
|
||||
# RSNE/RSNXE override
|
||||
#
|
||||
# These parameters can be used to configure RSN parameters for STAs that support
|
||||
# the override elements. The RSN parameters for STAs that do not support these
|
||||
# mechanisms are configured in the referenced configuration parameters. The AP
|
||||
# allows STAs to use either of the configured sets for negotiating RSN
|
||||
# parameters.
|
||||
#
|
||||
# The main purpose of this mechanism is to make the AP look like it is using an
|
||||
# older security mechanism (e.g., WPA2-Personal) to older STAs while allowing
|
||||
# new stations use newer security mechanisms (e.g., WPA3-Personal) based on the
|
||||
# override values. This might be needed to work around issues with deployed
|
||||
# STAs that do not implement RSNE extensibility correctly and may fail to
|
||||
# connect when the AP is using a transition mode like WPA3-Personal transition
|
||||
# mode.
|
||||
#
|
||||
# Key management; see wpa_key_mgmt for RSNE configuration
|
||||
#rsn_override_key_mgmt=<accepted key management algorithms>
|
||||
#
|
||||
# Pairwise cipher suites; see rsn_pairwise for RSNE configuration
|
||||
#rsn_override_pairwise=<accepted cipher suites)
|
||||
#
|
||||
# Management frame protection (MFP/PMF); see ieee80211w for RSNE configuration
|
||||
# 0 = disabled
|
||||
# 1 = optional
|
||||
# 2 = required
|
||||
#rsn_override_mfp=<0/1/2>
|
||||
#
|
||||
# Second set of similar parameters. These are required to be used for
|
||||
# Wi-Fi 7 (EHT/MLO) associations with RSN overriding and can optionally be used
|
||||
# in cases that do not use Wi-Fi 7.
|
||||
#rsn_override_key_mgmt_2
|
||||
#rsn_override_pairwise_2
|
||||
#rsn_override_mfp_2
|
||||
#
|
||||
# The RSNXE is normally included if any of the extended RSN capabilities is
|
||||
# enabled/supported. When using RSN overriding, a separate RSNXOE is included
|
||||
# and it may be more interoperable to omit the RSNXE completely. This
|
||||
# configuration parameter can be used to do that.
|
||||
# 0 = Include the RSNXE if any extended RSN capability is enabled/supported
|
||||
# (default).
|
||||
# 1 = Do not include the RSNXE.
|
||||
#rsn_override_omit_rsnxe=0
|
||||
#
|
||||
# Example configuration for WPA2-Personal/PMF-optional in RSNE and
|
||||
# WPA3-Personal/PMF-required/MLO in override elements
|
||||
#wpa_key_mgmt=WPA-PSK
|
||||
#rsn_pairwise=CCMP
|
||||
#ieee80211w=1
|
||||
#rsn_override_key_mgmt=SAE
|
||||
#rsn_override_pairwise=GCMP-256
|
||||
#rsn_override_mfp=2
|
||||
#rsn_override_key_mgmt_2=SAE-EXT-KEY
|
||||
#rsn_override_pairwise_2=GCMP-256
|
||||
#rsn_override_mfp_2=2
|
||||
#beacon_prot=1
|
||||
#sae_groups=19 20
|
||||
#sae_require_mfp=1
|
||||
#sae_pwe=2
|
||||
|
||||
|
||||
##### IEEE 802.11r configuration ##############################################
|
||||
|
||||
# Mobility Domain identifier (dot11FTMobilityDomainID, MDID)
|
||||
|
@ -2555,6 +2678,23 @@ own_ip_addr=127.0.0.1
|
|||
#multi_ap_backhaul_wpa_psk=0123456789abcdef0123456789abcdef0123456789abcdef0123456789abcdef
|
||||
#multi_ap_backhaul_wpa_passphrase=secret passphrase
|
||||
|
||||
# Multi-AP Profile
|
||||
# Indicate the supported Multi-AP profile (default: 2)
|
||||
# 1 = Supports Multi-AP profile 1 as defined in Wi-Fi EasyMesh specification
|
||||
# 2 = Supports Multi-AP profile 2 as defined in Wi-Fi EasyMesh specification
|
||||
#multi_ap_profile=2
|
||||
|
||||
# Multi-AP client disallow
|
||||
# Used to disallow profile specific backhaul STA association
|
||||
# Bitmap of the disallowed Profile-X profiles
|
||||
# 1 = Profile-1 Backhaul STA association disallowed
|
||||
# 2 = Profile-2 Backhaul STA association disallowed
|
||||
#multi_ap_client_disallow=0
|
||||
|
||||
# Multi-AP VLAN ID
|
||||
# A valid non-zero VLAN ID will be used to update Default IEEE 802.1Q Setting
|
||||
#multi_ap_vlanid=0
|
||||
|
||||
# WPS UPnP interface
|
||||
# If set, support for external Registrars is enabled.
|
||||
#upnp_iface=br0
|
||||
|
@ -3088,6 +3228,9 @@ own_ip_addr=127.0.0.1
|
|||
# Enable neighbor report via radio measurements
|
||||
#rrm_neighbor_report=1
|
||||
|
||||
# Enable link measurement report via radio measurements
|
||||
#rrm_link_measurement_report=1
|
||||
|
||||
# Enable beacon report via radio measurements
|
||||
#rrm_beacon_report=1
|
||||
|
||||
|
@ -3189,6 +3332,13 @@ own_ip_addr=127.0.0.1
|
|||
# attempt (wpa_pairwise_update_count). This will trigger a timeout on all
|
||||
# previous attempts and thus delays the frame. (testing only)
|
||||
#delay_eapol_tx=0
|
||||
#
|
||||
# Additional elements for Probe Response frames.
|
||||
# This parameter can be used to add additional element(s) to the end of the
|
||||
# Probe Response frames. The format for these element(s) is a hexdump of the
|
||||
# raw information elements (id+len+payload for one or more elements).
|
||||
# These elements are added after the 'vendor_elements'.
|
||||
#presp_elements=
|
||||
|
||||
##### Multiple BSSID support ##################################################
|
||||
#
|
||||
|
|
|
@ -21,7 +21,7 @@
|
|||
|
||||
static const char *const hostapd_cli_version =
|
||||
"hostapd_cli v" VERSION_STR "\n"
|
||||
"Copyright (c) 2004-2022, Jouni Malinen <j@w1.fi> and contributors";
|
||||
"Copyright (c) 2004-2024, Jouni Malinen <j@w1.fi> and contributors";
|
||||
|
||||
static struct wpa_ctrl *ctrl_conn;
|
||||
static int hostapd_cli_quit = 0;
|
||||
|
@ -54,7 +54,11 @@ static void usage(void)
|
|||
fprintf(stderr, "%s\n", hostapd_cli_version);
|
||||
fprintf(stderr,
|
||||
"\n"
|
||||
"usage: hostapd_cli [-p<path>] [-i<ifname>] [-hvBr] "
|
||||
"usage: hostapd_cli [-p<path>] [-i<ifname>] "
|
||||
#ifdef CONFIG_IEEE80211BE
|
||||
"[-l<link_id>] "
|
||||
#endif /* CONFIG_IEEE80211BE */
|
||||
"[-hvBr] "
|
||||
"[-a<path>] \\\n"
|
||||
" [-P<pid file>] [-G<ping interval>] [command..]\n"
|
||||
"\n"
|
||||
|
@ -74,7 +78,11 @@ static void usage(void)
|
|||
" -B run a daemon in the background\n"
|
||||
" -i<ifname> Interface to listen on (default: first "
|
||||
"interface found in the\n"
|
||||
" socket path)\n\n");
|
||||
" socket path)\n"
|
||||
#ifdef CONFIG_IEEE80211BE
|
||||
" -l<link_id> Link ID of the interface in case of Multi-Link Operation\n"
|
||||
#endif /* CONFIG_IEEE80211BE */
|
||||
"\n");
|
||||
print_help(stderr, NULL);
|
||||
}
|
||||
|
||||
|
@ -1168,6 +1176,15 @@ static int hostapd_cli_cmd_fst(struct wpa_ctrl *ctrl, int argc, char *argv[])
|
|||
#endif /* CONFIG_FST */
|
||||
|
||||
|
||||
#ifdef CONFIG_IEEE80211AX
|
||||
static int hostapd_cli_cmd_color_change(struct wpa_ctrl *ctrl,
|
||||
int argc, char *argv[])
|
||||
{
|
||||
return hostapd_cli_cmd(ctrl, "COLOR_CHANGE", 1, argc, argv);
|
||||
}
|
||||
#endif /* CONFIG_IEEE80211AX */
|
||||
|
||||
|
||||
static int hostapd_cli_cmd_chan_switch(struct wpa_ctrl *ctrl,
|
||||
int argc, char *argv[])
|
||||
{
|
||||
|
@ -1215,14 +1232,14 @@ static int hostapd_cli_cmd_notify_cw_change(struct wpa_ctrl *ctrl,
|
|||
|
||||
|
||||
static int hostapd_cli_cmd_enable(struct wpa_ctrl *ctrl, int argc,
|
||||
char *argv[])
|
||||
char *argv[])
|
||||
{
|
||||
return wpa_ctrl_command(ctrl, "ENABLE");
|
||||
}
|
||||
|
||||
|
||||
static int hostapd_cli_cmd_reload(struct wpa_ctrl *ctrl, int argc,
|
||||
char *argv[])
|
||||
char *argv[])
|
||||
{
|
||||
return wpa_ctrl_command(ctrl, "RELOAD");
|
||||
}
|
||||
|
@ -1243,7 +1260,7 @@ static int hostapd_cli_cmd_reload_config(struct wpa_ctrl *ctrl, int argc,
|
|||
|
||||
|
||||
static int hostapd_cli_cmd_disable(struct wpa_ctrl *ctrl, int argc,
|
||||
char *argv[])
|
||||
char *argv[])
|
||||
{
|
||||
return wpa_ctrl_command(ctrl, "DISABLE");
|
||||
}
|
||||
|
@ -1257,19 +1274,26 @@ static int hostapd_cli_cmd_enable_mld(struct wpa_ctrl *ctrl, int argc,
|
|||
|
||||
|
||||
static int hostapd_cli_cmd_disable_mld(struct wpa_ctrl *ctrl, int argc,
|
||||
char *argv[])
|
||||
char *argv[])
|
||||
{
|
||||
return wpa_ctrl_command(ctrl, "DISABLE_MLD");
|
||||
}
|
||||
|
||||
|
||||
static int hostapd_cli_cmd_update_beacon(struct wpa_ctrl *ctrl, int argc,
|
||||
char *argv[])
|
||||
char *argv[])
|
||||
{
|
||||
return wpa_ctrl_command(ctrl, "UPDATE_BEACON");
|
||||
}
|
||||
|
||||
|
||||
static int hostapd_cli_cmd_stop_ap(struct wpa_ctrl *ctrl, int argc,
|
||||
char *argv[])
|
||||
{
|
||||
return wpa_ctrl_command(ctrl, "STOP_AP");
|
||||
}
|
||||
|
||||
|
||||
static int hostapd_cli_cmd_vendor(struct wpa_ctrl *ctrl, int argc, char *argv[])
|
||||
{
|
||||
char cmd[256];
|
||||
|
@ -1598,6 +1622,13 @@ static int hostapd_cli_cmd_req_beacon(struct wpa_ctrl *ctrl, int argc,
|
|||
}
|
||||
|
||||
|
||||
static int hostapd_cli_cmd_req_link_measurement(struct wpa_ctrl *ctrl, int argc,
|
||||
char *argv[])
|
||||
{
|
||||
return hostapd_cli_cmd(ctrl, "REQ_LINK_MEASUREMENT", 1, argc, argv);
|
||||
}
|
||||
|
||||
|
||||
static int hostapd_cli_cmd_reload_wpa_psk(struct wpa_ctrl *ctrl, int argc,
|
||||
char *argv[])
|
||||
{
|
||||
|
@ -1732,6 +1763,11 @@ static const struct hostapd_cli_cmd hostapd_cli_commands[] = {
|
|||
"<cs_count> <freq> [sec_channel_offset=] [center_freq1=]\n"
|
||||
" [center_freq2=] [bandwidth=] [blocktx] [ht|vht]\n"
|
||||
" = initiate channel switch announcement" },
|
||||
#ifdef CONFIG_IEEE80211AX
|
||||
{ "color_change", hostapd_cli_cmd_color_change, NULL,
|
||||
"<color> = initiate BSS color change to set the specified color\n"
|
||||
"Value 0 will disable the color.\n"},
|
||||
#endif /* CONFIG_IEEE80211AX */
|
||||
{ "notify_cw_change", hostapd_cli_cmd_notify_cw_change, NULL,
|
||||
"<channel_width> = 0 - 20 MHz, 1 - 40 MHz, 2 - 80 MHz, 3 - 160 MHz" },
|
||||
{ "hs20_wnm_notif", hostapd_cli_cmd_hs20_wnm_notif, NULL,
|
||||
|
@ -1759,6 +1795,8 @@ static const struct hostapd_cli_cmd hostapd_cli_commands[] = {
|
|||
"= disable AP MLD to which the interface is affiliated" },
|
||||
{ "update_beacon", hostapd_cli_cmd_update_beacon, NULL,
|
||||
"= update Beacon frame contents\n"},
|
||||
{ "stop_ap", hostapd_cli_cmd_stop_ap, NULL,
|
||||
"= stop AP\n"},
|
||||
{ "erp_flush", hostapd_cli_cmd_erp_flush, NULL,
|
||||
"= drop all ERP keys"},
|
||||
{ "log_level", hostapd_cli_cmd_log_level, NULL,
|
||||
|
@ -1838,6 +1876,8 @@ static const struct hostapd_cli_cmd hostapd_cli_commands[] = {
|
|||
"<addr> = poll a STA to check connectivity with a QoS null frame" },
|
||||
{ "req_beacon", hostapd_cli_cmd_req_beacon, NULL,
|
||||
"<addr> [req_mode=] <measurement request hexdump> = send a Beacon report request to a station" },
|
||||
{ "req_link_measurement", hostapd_cli_cmd_req_link_measurement, NULL,
|
||||
"<addr> = send a link measurement report request to a station"},
|
||||
{ "reload_wpa_psk", hostapd_cli_cmd_reload_wpa_psk, NULL,
|
||||
"= reload wpa_psk_file only" },
|
||||
#ifdef CONFIG_IEEE80211R_AP
|
||||
|
@ -2180,12 +2220,15 @@ int main(int argc, char *argv[])
|
|||
int c;
|
||||
int daemonize = 0;
|
||||
int reconnect = 0;
|
||||
#ifdef CONFIG_IEEE80211BE
|
||||
int link_id = -1;
|
||||
#endif /* CONFIG_IEEE80211BE */
|
||||
|
||||
if (os_program_init())
|
||||
return -1;
|
||||
|
||||
for (;;) {
|
||||
c = getopt(argc, argv, "a:BhG:i:p:P:rs:v");
|
||||
c = getopt(argc, argv, "a:BhG:i:l:p:P:rs:v");
|
||||
if (c < 0)
|
||||
break;
|
||||
switch (c) {
|
||||
|
@ -2220,6 +2263,11 @@ int main(int argc, char *argv[])
|
|||
case 's':
|
||||
client_socket_dir = optarg;
|
||||
break;
|
||||
#ifdef CONFIG_IEEE80211BE
|
||||
case 'l':
|
||||
link_id = atoi(optarg);
|
||||
break;
|
||||
#endif /* CONFIG_IEEE80211BE */
|
||||
default:
|
||||
usage();
|
||||
return -1;
|
||||
|
@ -2253,6 +2301,24 @@ int main(int argc, char *argv[])
|
|||
closedir(dir);
|
||||
}
|
||||
}
|
||||
|
||||
#ifdef CONFIG_IEEE80211BE
|
||||
if (link_id >= 0 && ctrl_ifname) {
|
||||
int ret;
|
||||
char buf[300];
|
||||
|
||||
ret = os_snprintf(buf, sizeof(buf), "%s_%s%d",
|
||||
ctrl_ifname, WPA_CTRL_IFACE_LINK_NAME,
|
||||
link_id);
|
||||
if (os_snprintf_error(sizeof(buf), ret))
|
||||
return -1;
|
||||
|
||||
os_free(ctrl_ifname);
|
||||
ctrl_ifname = os_strdup(buf);
|
||||
link_id = -1;
|
||||
}
|
||||
#endif /* CONFIG_IEEE80211BE */
|
||||
|
||||
hostapd_cli_reconnect(ctrl_ifname);
|
||||
if (ctrl_conn) {
|
||||
if (warning_displayed)
|
||||
|
|
|
@ -158,6 +158,9 @@ static int hostapd_driver_init(struct hostapd_iface *iface)
|
|||
struct hostapd_bss_config *conf = hapd->conf;
|
||||
u8 *b = conf->bssid;
|
||||
struct wpa_driver_capa capa;
|
||||
#ifdef CONFIG_IEEE80211BE
|
||||
struct hostapd_data *h_hapd = NULL;
|
||||
#endif /* CONFIG_IEEE80211BE */
|
||||
|
||||
if (hapd->driver == NULL || hapd->driver->hapd_init == NULL) {
|
||||
wpa_printf(MSG_ERROR, "No hostapd driver wrapper available");
|
||||
|
@ -165,30 +168,12 @@ static int hostapd_driver_init(struct hostapd_iface *iface)
|
|||
}
|
||||
|
||||
#ifdef CONFIG_IEEE80211BE
|
||||
for (i = 0; conf->mld_ap && i < iface->interfaces->count; i++) {
|
||||
struct hostapd_iface *h = iface->interfaces->iface[i];
|
||||
struct hostapd_data *h_hapd = h->bss[0];
|
||||
struct hostapd_bss_config *hconf = h_hapd->conf;
|
||||
|
||||
if (h == iface) {
|
||||
wpa_printf(MSG_DEBUG, "MLD: Skip own interface");
|
||||
continue;
|
||||
}
|
||||
|
||||
if (!hconf->mld_ap || hconf->mld_id != conf->mld_id) {
|
||||
wpa_printf(MSG_DEBUG,
|
||||
"MLD: Skip non matching mld_id");
|
||||
continue;
|
||||
}
|
||||
|
||||
wpa_printf(MSG_DEBUG, "MLD: Found matching MLD interface");
|
||||
if (!h_hapd->drv_priv) {
|
||||
wpa_printf(MSG_DEBUG,
|
||||
"MLD: Matching MLD BSS not initialized yet");
|
||||
continue;
|
||||
}
|
||||
if (conf->mld_ap)
|
||||
h_hapd = hostapd_mld_get_first_bss(hapd);
|
||||
|
||||
if (h_hapd) {
|
||||
hapd->drv_priv = h_hapd->drv_priv;
|
||||
hapd->interface_added = h_hapd->interface_added;
|
||||
|
||||
/*
|
||||
* All interfaces participating in the AP MLD would have
|
||||
|
@ -198,20 +183,17 @@ static int hostapd_driver_init(struct hostapd_iface *iface)
|
|||
* is not configured, and otherwise it would be the
|
||||
* configured BSSID.
|
||||
*/
|
||||
os_memcpy(hapd->mld_addr, h_hapd->mld_addr, ETH_ALEN);
|
||||
if (is_zero_ether_addr(b)) {
|
||||
os_memcpy(hapd->own_addr, h_hapd->mld_addr, ETH_ALEN);
|
||||
os_memcpy(hapd->own_addr, h_hapd->mld->mld_addr,
|
||||
ETH_ALEN);
|
||||
random_mac_addr_keep_oui(hapd->own_addr);
|
||||
} else {
|
||||
os_memcpy(hapd->own_addr, b, ETH_ALEN);
|
||||
}
|
||||
|
||||
/*
|
||||
* Mark the interface as a secondary interface, as this
|
||||
* is needed for the de-initialization flow
|
||||
*/
|
||||
hapd->mld_first_bss = h_hapd;
|
||||
hapd->mld_link_id = hapd->mld_first_bss->mld_next_link_id++;
|
||||
wpa_printf(MSG_DEBUG,
|
||||
"Setup of non first link (%d) BSS of MLD %s",
|
||||
hapd->mld_link_id, hapd->conf->iface);
|
||||
|
||||
goto setup_mld;
|
||||
}
|
||||
|
@ -288,13 +270,15 @@ static int hostapd_driver_init(struct hostapd_iface *iface)
|
|||
* configured, and otherwise it would be the configured BSSID.
|
||||
*/
|
||||
if (hapd->conf->mld_ap) {
|
||||
os_memcpy(hapd->mld_addr, hapd->own_addr, ETH_ALEN);
|
||||
hapd->mld_next_link_id = 0;
|
||||
hapd->mld_link_id = hapd->mld_next_link_id++;
|
||||
os_memcpy(hapd->mld->mld_addr, hapd->own_addr, ETH_ALEN);
|
||||
|
||||
if (!b)
|
||||
random_mac_addr_keep_oui(hapd->own_addr);
|
||||
else
|
||||
os_memcpy(hapd->own_addr, b, ETH_ALEN);
|
||||
|
||||
wpa_printf(MSG_DEBUG, "Setup of first link (%d) BSS of MLD %s",
|
||||
hapd->mld_link_id, hapd->conf->iface);
|
||||
}
|
||||
|
||||
setup_mld:
|
||||
|
@ -306,6 +290,7 @@ setup_mld:
|
|||
|
||||
iface->drv_flags = capa.flags;
|
||||
iface->drv_flags2 = capa.flags2;
|
||||
iface->drv_rrm_flags = capa.rrm_flags;
|
||||
iface->probe_resp_offloads = capa.probe_resp_offloads;
|
||||
/*
|
||||
* Use default extended capa values from per-radio information
|
||||
|
@ -348,11 +333,17 @@ setup_mld:
|
|||
wpa_printf(MSG_DEBUG,
|
||||
"MLD: Set link_id=%u, mld_addr=" MACSTR
|
||||
", own_addr=" MACSTR,
|
||||
hapd->mld_link_id, MAC2STR(hapd->mld_addr),
|
||||
hapd->mld_link_id, MAC2STR(hapd->mld->mld_addr),
|
||||
MAC2STR(hapd->own_addr));
|
||||
|
||||
hostapd_drv_link_add(hapd, hapd->mld_link_id,
|
||||
hapd->own_addr);
|
||||
if (hostapd_drv_link_add(hapd, hapd->mld_link_id,
|
||||
hapd->own_addr)) {
|
||||
wpa_printf(MSG_ERROR,
|
||||
"MLD: Failed to add link %d in MLD %s",
|
||||
hapd->mld_link_id, hapd->conf->iface);
|
||||
return -1;
|
||||
}
|
||||
hostapd_mld_add_link(hapd);
|
||||
}
|
||||
#endif /* CONFIG_IEEE80211BE */
|
||||
|
||||
|
@ -568,7 +559,7 @@ static void show_version(void)
|
|||
"hostapd v%s\n"
|
||||
"User space daemon for IEEE 802.11 AP management,\n"
|
||||
"IEEE 802.1X/WPA/WPA2/EAP/RADIUS Authenticator\n"
|
||||
"Copyright (c) 2002-2022, Jouni Malinen <j@w1.fi> "
|
||||
"Copyright (c) 2002-2024, Jouni Malinen <j@w1.fi> "
|
||||
"and contributors\n",
|
||||
VERSION_STR);
|
||||
}
|
||||
|
@ -749,6 +740,30 @@ static void hostapd_periodic(void *eloop_ctx, void *timeout_ctx)
|
|||
}
|
||||
|
||||
|
||||
static void hostapd_global_cleanup_mld(struct hapd_interfaces *interfaces)
|
||||
{
|
||||
#ifdef CONFIG_IEEE80211BE
|
||||
size_t i;
|
||||
|
||||
if (!interfaces || !interfaces->mld)
|
||||
return;
|
||||
|
||||
for (i = 0; i < interfaces->mld_count; i++) {
|
||||
if (!interfaces->mld[i])
|
||||
continue;
|
||||
|
||||
interfaces->mld_ctrl_iface_deinit(interfaces->mld[i]);
|
||||
os_free(interfaces->mld[i]);
|
||||
interfaces->mld[i] = NULL;
|
||||
}
|
||||
|
||||
os_free(interfaces->mld);
|
||||
interfaces->mld = NULL;
|
||||
interfaces->mld_count = 0;
|
||||
#endif /* CONFIG_IEEE80211BE */
|
||||
}
|
||||
|
||||
|
||||
int main(int argc, char *argv[])
|
||||
{
|
||||
struct hapd_interfaces interfaces;
|
||||
|
@ -783,6 +798,10 @@ int main(int argc, char *argv[])
|
|||
interfaces.global_iface_path = NULL;
|
||||
interfaces.global_iface_name = NULL;
|
||||
interfaces.global_ctrl_sock = -1;
|
||||
#ifdef CONFIG_IEEE80211BE
|
||||
interfaces.mld_ctrl_iface_init = hostapd_mld_ctrl_iface_init;
|
||||
interfaces.mld_ctrl_iface_deinit = hostapd_mld_ctrl_iface_deinit;
|
||||
#endif /* CONFIG_IEEE80211BE */
|
||||
dl_list_init(&interfaces.global_ctrl_dst);
|
||||
#ifdef CONFIG_ETH_P_OUI
|
||||
dl_list_init(&interfaces.eth_p_oui);
|
||||
|
@ -1029,6 +1048,8 @@ int main(int argc, char *argv[])
|
|||
interfaces.iface = NULL;
|
||||
interfaces.count = 0;
|
||||
|
||||
hostapd_global_cleanup_mld(&interfaces);
|
||||
|
||||
#ifdef CONFIG_DPP
|
||||
dpp_global_deinit(interfaces.dpp);
|
||||
#endif /* CONFIG_DPP */
|
||||
|
|
78
src/ap/acs.c
78
src/ap/acs.c
|
@ -12,6 +12,7 @@
|
|||
|
||||
#include "utils/common.h"
|
||||
#include "utils/list.h"
|
||||
#include "utils/eloop.h"
|
||||
#include "common/ieee802_11_defs.h"
|
||||
#include "common/hw_features_common.h"
|
||||
#include "common/wpa_ctrl.h"
|
||||
|
@ -75,7 +76,7 @@
|
|||
*
|
||||
* This corresponds to:
|
||||
* ---
|
||||
* (busy time - tx time) / (active time - tx time) * 2^(chan_nf + band_min_nf)
|
||||
* (busy time - tx time) / (active time - tx time) * 2^(chan_nf - band_min_nf)
|
||||
* ---
|
||||
*
|
||||
* The coefficient of 2 reflects the way power in "far-field"
|
||||
|
@ -92,7 +93,7 @@
|
|||
* calculated easily.
|
||||
* ---
|
||||
* (busy time - tx time) / (active time - tx time) *
|
||||
* 2^(10^(chan_nf/10) + 10^(band_min_nf/10))
|
||||
* 2^(10^(chan_nf/10) - 10^(band_min_nf/10))
|
||||
* ---
|
||||
*
|
||||
* However to account for cases where busy/rx time is 0 (channel load is then
|
||||
|
@ -100,7 +101,7 @@
|
|||
* channel with lower noise floor is preferred. The equation becomes:
|
||||
* ---
|
||||
* 10^(chan_nf/5) + (busy time - tx time) / (active time - tx time) *
|
||||
* 2^(10^(chan_nf/10) + 10^(band_min_nf/10))
|
||||
* 2^(10^(chan_nf/10) - 10^(band_min_nf/10))
|
||||
* ---
|
||||
*
|
||||
* All this "interference factor" is purely subjective and only time
|
||||
|
@ -307,6 +308,7 @@ static const struct bw_item *bw_desc[] = {
|
|||
|
||||
static int acs_request_scan(struct hostapd_iface *iface);
|
||||
static int acs_survey_is_sufficient(struct freq_survey *survey);
|
||||
static void acs_scan_retry(void *eloop_data, void *user_data);
|
||||
|
||||
|
||||
static void acs_clean_chan_surveys(struct hostapd_channel_data *chan)
|
||||
|
@ -352,6 +354,8 @@ void acs_cleanup(struct hostapd_iface *iface)
|
|||
|
||||
iface->chans_surveyed = 0;
|
||||
iface->acs_num_completed_scans = 0;
|
||||
iface->acs_num_retries = 0;
|
||||
eloop_cancel_timeout(acs_scan_retry, iface, NULL);
|
||||
}
|
||||
|
||||
|
||||
|
@ -507,7 +511,7 @@ static int acs_survey_list_is_sufficient(struct hostapd_channel_data *chan)
|
|||
}
|
||||
|
||||
if (ret == -1)
|
||||
ret = 1; /* no survey list entries */
|
||||
ret = 0; /* no survey list entries */
|
||||
|
||||
if (!ret) {
|
||||
wpa_printf(MSG_INFO,
|
||||
|
@ -830,6 +834,9 @@ acs_find_ideal_chan_mode(struct hostapd_iface *iface,
|
|||
int bw320_offset = 0, ideal_bw320_offset = 0;
|
||||
unsigned int k;
|
||||
int secondary_channel = 1, freq_offset;
|
||||
#ifdef CONFIG_IEEE80211BE
|
||||
int index_primary = 0;
|
||||
#endif /* CONFIG_IEEE80211BE */
|
||||
|
||||
if (is_24ghz_mode(mode->mode))
|
||||
secondary_channel = iface->conf->secondary_channel;
|
||||
|
@ -969,6 +976,9 @@ acs_find_ideal_chan_mode(struct hostapd_iface *iface,
|
|||
best->chan, chan->chan,
|
||||
chan->interference_factor,
|
||||
best->interference_factor);
|
||||
#ifdef CONFIG_IEEE80211BE
|
||||
index_primary = (chan->freq - best->freq) / 20;
|
||||
#endif /* CONFIG_IEEE80211BE */
|
||||
chan = best;
|
||||
}
|
||||
|
||||
|
@ -1057,7 +1067,8 @@ acs_find_ideal_chan_mode(struct hostapd_iface *iface,
|
|||
if (iface->conf->ieee80211be)
|
||||
acs_update_puncturing_bitmap(iface, mode, bw,
|
||||
n_chans, chan,
|
||||
factor, 0);
|
||||
factor,
|
||||
index_primary);
|
||||
#endif /* CONFIG_IEEE80211BE */
|
||||
}
|
||||
|
||||
|
@ -1317,6 +1328,7 @@ static void acs_scan_complete(struct hostapd_iface *iface)
|
|||
int err;
|
||||
|
||||
iface->scan_cb = NULL;
|
||||
iface->acs_num_retries = 0;
|
||||
|
||||
wpa_printf(MSG_DEBUG, "ACS: Using survey based algorithm (acs_num_scans=%d)",
|
||||
iface->conf->acs_num_scans);
|
||||
|
@ -1329,7 +1341,7 @@ static void acs_scan_complete(struct hostapd_iface *iface)
|
|||
|
||||
if (++iface->acs_num_completed_scans < iface->conf->acs_num_scans) {
|
||||
err = acs_request_scan(iface);
|
||||
if (err) {
|
||||
if (err && err != -EBUSY) {
|
||||
wpa_printf(MSG_ERROR, "ACS: Failed to request scan");
|
||||
goto fail;
|
||||
}
|
||||
|
@ -1382,7 +1394,7 @@ static int * acs_request_scan_add_freqs(struct hostapd_iface *iface,
|
|||
static int acs_request_scan(struct hostapd_iface *iface)
|
||||
{
|
||||
struct wpa_driver_scan_params params;
|
||||
int i, *freq;
|
||||
int i, *freq, ret;
|
||||
int num_channels;
|
||||
struct hostapd_hw_modes *mode;
|
||||
|
||||
|
@ -1415,24 +1427,62 @@ static int acs_request_scan(struct hostapd_iface *iface)
|
|||
return -1;
|
||||
}
|
||||
|
||||
iface->scan_cb = acs_scan_complete;
|
||||
if (!iface->acs_num_retries)
|
||||
wpa_printf(MSG_DEBUG, "ACS: Scanning %d / %d",
|
||||
iface->acs_num_completed_scans + 1,
|
||||
iface->conf->acs_num_scans);
|
||||
else
|
||||
wpa_printf(MSG_DEBUG,
|
||||
"ACS: Re-try scanning attempt %d (%d / %d)",
|
||||
iface->acs_num_retries,
|
||||
iface->acs_num_completed_scans + 1,
|
||||
iface->conf->acs_num_scans);
|
||||
|
||||
wpa_printf(MSG_DEBUG, "ACS: Scanning %d / %d",
|
||||
iface->acs_num_completed_scans + 1,
|
||||
iface->conf->acs_num_scans);
|
||||
ret = hostapd_driver_scan(iface->bss[0], ¶ms);
|
||||
os_free(params.freqs);
|
||||
|
||||
if (hostapd_driver_scan(iface->bss[0], ¶ms) < 0) {
|
||||
if (ret == -EBUSY) {
|
||||
iface->acs_num_retries++;
|
||||
if (iface->acs_num_retries >= ACS_SCAN_RETRY_MAX_COUNT) {
|
||||
wpa_printf(MSG_ERROR,
|
||||
"ACS: Failed to request initial scan (all re-attempts failed)");
|
||||
acs_fail(iface);
|
||||
return -1;
|
||||
}
|
||||
|
||||
wpa_printf(MSG_INFO,
|
||||
"Failed to request acs scan ret=%d (%s) - try to scan after %d seconds",
|
||||
ret, strerror(-ret), ACS_SCAN_RETRY_INTERVAL);
|
||||
eloop_cancel_timeout(acs_scan_retry, iface, NULL);
|
||||
eloop_register_timeout(ACS_SCAN_RETRY_INTERVAL, 0,
|
||||
acs_scan_retry, iface, NULL);
|
||||
return 0;
|
||||
}
|
||||
|
||||
if (ret < 0) {
|
||||
wpa_printf(MSG_ERROR, "ACS: Failed to request initial scan");
|
||||
acs_cleanup(iface);
|
||||
os_free(params.freqs);
|
||||
return -1;
|
||||
}
|
||||
|
||||
os_free(params.freqs);
|
||||
iface->scan_cb = acs_scan_complete;
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
|
||||
static void acs_scan_retry(void *eloop_data, void *user_data)
|
||||
{
|
||||
struct hostapd_iface *iface = eloop_data;
|
||||
|
||||
if (acs_request_scan(iface)) {
|
||||
wpa_printf(MSG_ERROR,
|
||||
"ACS: Failed to request re-try of initial scan");
|
||||
acs_fail(iface);
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
enum hostapd_chan_status acs_init(struct hostapd_iface *iface)
|
||||
{
|
||||
int err;
|
||||
|
|
|
@ -15,6 +15,9 @@
|
|||
enum hostapd_chan_status acs_init(struct hostapd_iface *iface);
|
||||
void acs_cleanup(struct hostapd_iface *iface);
|
||||
|
||||
#define ACS_SCAN_RETRY_MAX_COUNT 15
|
||||
#define ACS_SCAN_RETRY_INTERVAL 5
|
||||
|
||||
#else /* CONFIG_ACS */
|
||||
|
||||
static inline enum hostapd_chan_status acs_init(struct hostapd_iface *iface)
|
||||
|
|
|
@ -92,6 +92,7 @@ void hostapd_config_defaults_bss(struct hostapd_bss_config *bss)
|
|||
bss->eap_sim_id = 3;
|
||||
bss->eap_sim_aka_fast_reauth_limit = 1000;
|
||||
bss->ap_max_inactivity = AP_MAX_INACTIVITY;
|
||||
bss->bss_max_idle = 1;
|
||||
bss->eapol_version = EAPOL_VERSION;
|
||||
|
||||
bss->max_listen_interval = 65535;
|
||||
|
@ -121,9 +122,10 @@ void hostapd_config_defaults_bss(struct hostapd_bss_config *bss)
|
|||
#endif /* CONFIG_IEEE80211R_AP */
|
||||
|
||||
bss->radius_das_time_window = 300;
|
||||
bss->radius_require_message_authenticator = 1;
|
||||
|
||||
bss->anti_clogging_threshold = 5;
|
||||
bss->sae_sync = 5;
|
||||
bss->sae_sync = 3;
|
||||
|
||||
bss->gas_frag_limit = 1400;
|
||||
|
||||
|
@ -163,6 +165,8 @@ void hostapd_config_defaults_bss(struct hostapd_bss_config *bss)
|
|||
/* Default to strict CRL checking. */
|
||||
bss->check_crl_strict = 1;
|
||||
|
||||
bss->multi_ap_profile = MULTI_AP_PROFILE_2;
|
||||
|
||||
#ifdef CONFIG_TESTING_OPTIONS
|
||||
bss->sae_commit_status = -1;
|
||||
bss->test_assoc_comeback_type = -1;
|
||||
|
@ -487,20 +491,33 @@ int hostapd_setup_sae_pt(struct hostapd_bss_config *conf)
|
|||
#ifdef CONFIG_SAE
|
||||
struct hostapd_ssid *ssid = &conf->ssid;
|
||||
struct sae_password_entry *pw;
|
||||
int *groups = conf->sae_groups;
|
||||
int default_groups[] = { 19, 0, 0 };
|
||||
|
||||
if ((conf->sae_pwe == SAE_PWE_HUNT_AND_PECK &&
|
||||
!hostapd_sae_pw_id_in_use(conf) &&
|
||||
!wpa_key_mgmt_sae_ext_key(conf->wpa_key_mgmt) &&
|
||||
!wpa_key_mgmt_sae_ext_key(conf->wpa_key_mgmt |
|
||||
conf->rsn_override_key_mgmt |
|
||||
conf->rsn_override_key_mgmt_2) &&
|
||||
!hostapd_sae_pk_in_use(conf)) ||
|
||||
conf->sae_pwe == SAE_PWE_FORCE_HUNT_AND_PECK ||
|
||||
!wpa_key_mgmt_sae(conf->wpa_key_mgmt))
|
||||
!wpa_key_mgmt_sae(conf->wpa_key_mgmt |
|
||||
conf->rsn_override_key_mgmt |
|
||||
conf->rsn_override_key_mgmt_2))
|
||||
return 0; /* PT not needed */
|
||||
|
||||
if (!groups) {
|
||||
groups = default_groups;
|
||||
if (wpa_key_mgmt_sae_ext_key(conf->wpa_key_mgmt |
|
||||
conf->rsn_override_key_mgmt |
|
||||
conf->rsn_override_key_mgmt_2))
|
||||
default_groups[1] = 20;
|
||||
}
|
||||
|
||||
sae_deinit_pt(ssid->pt);
|
||||
ssid->pt = NULL;
|
||||
if (ssid->wpa_passphrase) {
|
||||
ssid->pt = sae_derive_pt(conf->sae_groups, ssid->ssid,
|
||||
ssid->ssid_len,
|
||||
ssid->pt = sae_derive_pt(groups, ssid->ssid, ssid->ssid_len,
|
||||
(const u8 *) ssid->wpa_passphrase,
|
||||
os_strlen(ssid->wpa_passphrase),
|
||||
NULL);
|
||||
|
@ -510,8 +527,7 @@ int hostapd_setup_sae_pt(struct hostapd_bss_config *conf)
|
|||
|
||||
for (pw = conf->sae_passwords; pw; pw = pw->next) {
|
||||
sae_deinit_pt(pw->pt);
|
||||
pw->pt = sae_derive_pt(conf->sae_groups, ssid->ssid,
|
||||
ssid->ssid_len,
|
||||
pw->pt = sae_derive_pt(groups, ssid->ssid, ssid->ssid_len,
|
||||
(const u8 *) pw->password,
|
||||
os_strlen(pw->password),
|
||||
pw->identifier);
|
||||
|
@ -555,6 +571,10 @@ static void hostapd_config_free_radius(struct hostapd_radius_server *servers,
|
|||
|
||||
for (i = 0; i < num_servers; i++) {
|
||||
os_free(servers[i].shared_secret);
|
||||
os_free(servers[i].ca_cert);
|
||||
os_free(servers[i].client_cert);
|
||||
os_free(servers[i].private_key);
|
||||
os_free(servers[i].private_key_passwd);
|
||||
}
|
||||
os_free(servers);
|
||||
}
|
||||
|
@ -952,6 +972,11 @@ void hostapd_config_free_bss(struct hostapd_bss_config *conf)
|
|||
|
||||
#ifdef CONFIG_TESTING_OPTIONS
|
||||
wpabuf_free(conf->own_ie_override);
|
||||
wpabuf_free(conf->rsne_override);
|
||||
wpabuf_free(conf->rsnoe_override);
|
||||
wpabuf_free(conf->rsno2e_override);
|
||||
wpabuf_free(conf->rsnxe_override);
|
||||
wpabuf_free(conf->rsnxoe_override);
|
||||
wpabuf_free(conf->sae_commit_override);
|
||||
wpabuf_free(conf->rsne_override_eapol);
|
||||
wpabuf_free(conf->rsnxe_override_eapol);
|
||||
|
@ -961,6 +986,7 @@ void hostapd_config_free_bss(struct hostapd_bss_config *conf)
|
|||
wpabuf_free(conf->igtk_rsc_override);
|
||||
wpabuf_free(conf->eapol_m1_elements);
|
||||
wpabuf_free(conf->eapol_m3_elements);
|
||||
wpabuf_free(conf->presp_elements);
|
||||
#endif /* CONFIG_TESTING_OPTIONS */
|
||||
|
||||
os_free(conf->no_probe_resp_if_seen_on);
|
||||
|
|
|
@ -309,6 +309,7 @@ struct hostapd_bss_config {
|
|||
struct hostapd_ip_addr own_ip_addr;
|
||||
char *nas_identifier;
|
||||
struct hostapd_radius_servers *radius;
|
||||
int radius_require_message_authenticator;
|
||||
int acct_interim_interval;
|
||||
int radius_request_cui;
|
||||
struct hostapd_radius_attr *radius_auth_req_attr;
|
||||
|
@ -357,7 +358,11 @@ struct hostapd_bss_config {
|
|||
int wpa; /* bitfield of WPA_PROTO_WPA, WPA_PROTO_RSN */
|
||||
int extended_key_id;
|
||||
int wpa_key_mgmt;
|
||||
int rsn_override_key_mgmt;
|
||||
int rsn_override_key_mgmt_2;
|
||||
enum mfp_options ieee80211w;
|
||||
enum mfp_options rsn_override_mfp;
|
||||
enum mfp_options rsn_override_mfp_2;
|
||||
int group_mgmt_cipher;
|
||||
int beacon_prot;
|
||||
/* dot11AssociationSAQueryMaximumTimeout (in TUs) */
|
||||
|
@ -386,9 +391,13 @@ struct hostapd_bss_config {
|
|||
u32 wpa_pairwise_update_count;
|
||||
int wpa_disable_eapol_key_retries;
|
||||
int rsn_pairwise;
|
||||
int rsn_override_pairwise;
|
||||
int rsn_override_pairwise_2;
|
||||
int rsn_preauth;
|
||||
char *rsn_preauth_interfaces;
|
||||
|
||||
int rsn_override_omit_rsnxe;
|
||||
|
||||
#ifdef CONFIG_IEEE80211R_AP
|
||||
/* IEEE 802.11r - Fast BSS Transition */
|
||||
u8 mobility_domain[MOBILITY_DOMAIN_ID_LEN];
|
||||
|
@ -465,6 +474,9 @@ struct hostapd_bss_config {
|
|||
*/
|
||||
|
||||
int ap_max_inactivity;
|
||||
int bss_max_idle;
|
||||
int max_acceptable_idle_period;
|
||||
bool no_disconnect_on_group_keyerror;
|
||||
int ignore_broadcast_ssid;
|
||||
int no_probe_resp_if_max_sta;
|
||||
|
||||
|
@ -684,6 +696,11 @@ struct hostapd_bss_config {
|
|||
u8 bss_load_test[5];
|
||||
u8 bss_load_test_set;
|
||||
struct wpabuf *own_ie_override;
|
||||
struct wpabuf *rsne_override;
|
||||
struct wpabuf *rsnoe_override;
|
||||
struct wpabuf *rsno2e_override;
|
||||
struct wpabuf *rsnxe_override;
|
||||
struct wpabuf *rsnxoe_override;
|
||||
int sae_reflection_attack;
|
||||
int sae_commit_status;
|
||||
int sae_pk_omit;
|
||||
|
@ -708,7 +725,9 @@ struct hostapd_bss_config {
|
|||
struct wpabuf *eapol_m1_elements;
|
||||
struct wpabuf *eapol_m3_elements;
|
||||
bool eapol_m3_no_encrypt;
|
||||
bool eapol_key_reserved_random;
|
||||
int test_assoc_comeback_type;
|
||||
struct wpabuf *presp_elements;
|
||||
|
||||
#ifdef CONFIG_IEEE80211BE
|
||||
u16 eht_oper_puncturing_override;
|
||||
|
@ -800,6 +819,14 @@ struct hostapd_bss_config {
|
|||
#define BACKHAUL_BSS 1
|
||||
#define FRONTHAUL_BSS 2
|
||||
int multi_ap; /* bitmap of BACKHAUL_BSS, FRONTHAUL_BSS */
|
||||
int multi_ap_profile;
|
||||
/* Multi-AP Profile-1 clients not allowed to connect */
|
||||
#define PROFILE1_CLIENT_ASSOC_DISALLOW BIT(0)
|
||||
/* Multi-AP Profile-2 clients not allowed to connect */
|
||||
#define PROFILE2_CLIENT_ASSOC_DISALLOW BIT(1)
|
||||
unsigned int multi_ap_client_disallow;
|
||||
/* Primary VLAN ID to use in Multi-AP */
|
||||
int multi_ap_vlanid;
|
||||
|
||||
#ifdef CONFIG_AIRTIME_POLICY
|
||||
unsigned int airtime_weight;
|
||||
|
@ -948,6 +975,8 @@ struct hostapd_bss_config {
|
|||
char *config_id;
|
||||
bool xrates_supported;
|
||||
|
||||
bool ssid_protection;
|
||||
|
||||
#ifdef CONFIG_IEEE80211BE
|
||||
/* The AP is part of an AP MLD */
|
||||
u8 mld_ap;
|
||||
|
@ -1217,6 +1246,9 @@ struct hostapd_config {
|
|||
MBSSID_ENABLED = 1,
|
||||
ENHANCED_MBSSID_ENABLED = 2,
|
||||
} mbssid;
|
||||
|
||||
/* Whether to enable TWT responder in HT and VHT modes */
|
||||
bool ht_vht_twt_responder;
|
||||
};
|
||||
|
||||
|
||||
|
|
|
@ -208,6 +208,9 @@ int hostapd_build_ap_extra_ies(struct hostapd_data *hapd,
|
|||
|
||||
add_buf(&beacon, hapd->conf->vendor_elements);
|
||||
add_buf(&proberesp, hapd->conf->vendor_elements);
|
||||
#ifdef CONFIG_TESTING_OPTIONS
|
||||
add_buf(&proberesp, hapd->conf->presp_elements);
|
||||
#endif /* CONFIG_TESTING_OPTIONS */
|
||||
add_buf(&assocresp, hapd->conf->assocresp_elements);
|
||||
|
||||
*beacon_ret = beacon;
|
||||
|
@ -265,8 +268,8 @@ int hostapd_set_ap_wps_ie(struct hostapd_data *hapd)
|
|||
}
|
||||
|
||||
|
||||
static bool hostapd_sta_is_link_sta(struct hostapd_data *hapd,
|
||||
struct sta_info *sta)
|
||||
bool hostapd_sta_is_link_sta(struct hostapd_data *hapd,
|
||||
struct sta_info *sta)
|
||||
{
|
||||
#ifdef CONFIG_IEEE80211BE
|
||||
if (ap_sta_is_mld(hapd, sta) &&
|
||||
|
@ -572,12 +575,33 @@ int hostapd_if_add(struct hostapd_data *hapd, enum wpa_driver_if_type type,
|
|||
}
|
||||
|
||||
|
||||
#ifdef CONFIG_IEEE80211BE
|
||||
int hostapd_if_link_remove(struct hostapd_data *hapd,
|
||||
enum wpa_driver_if_type type,
|
||||
const char *ifname, u8 link_id)
|
||||
{
|
||||
if (!hapd->driver || !hapd->drv_priv || !hapd->driver->link_remove)
|
||||
return -1;
|
||||
|
||||
return hapd->driver->link_remove(hapd->drv_priv, type, ifname,
|
||||
hapd->mld_link_id);
|
||||
}
|
||||
#endif /* CONFIG_IEEE80211BE */
|
||||
|
||||
|
||||
int hostapd_if_remove(struct hostapd_data *hapd, enum wpa_driver_if_type type,
|
||||
const char *ifname)
|
||||
{
|
||||
if (hapd->driver == NULL || hapd->drv_priv == NULL ||
|
||||
hapd->driver->if_remove == NULL)
|
||||
return -1;
|
||||
|
||||
#ifdef CONFIG_IEEE80211BE
|
||||
if (hapd->conf->mld_ap)
|
||||
return hostapd_if_link_remove(hapd, type, ifname,
|
||||
hapd->mld_link_id);
|
||||
#endif /* CONFIG_IEEE80211BE */
|
||||
|
||||
return hapd->driver->if_remove(hapd->drv_priv, type, ifname);
|
||||
}
|
||||
|
||||
|
@ -603,9 +627,17 @@ int hostapd_get_seqnum(const char *ifname, struct hostapd_data *hapd,
|
|||
|
||||
int hostapd_flush(struct hostapd_data *hapd)
|
||||
{
|
||||
int link_id = -1;
|
||||
|
||||
if (hapd->driver == NULL || hapd->driver->flush == NULL)
|
||||
return 0;
|
||||
return hapd->driver->flush(hapd->drv_priv);
|
||||
|
||||
#ifdef CONFIG_IEEE80211BE
|
||||
if (hapd->conf && hapd->conf->mld_ap)
|
||||
link_id = hapd->mld_link_id;
|
||||
#endif /* CONFIG_IEEE80211BE */
|
||||
|
||||
return hapd->driver->flush(hapd->drv_priv, link_id);
|
||||
}
|
||||
|
||||
|
||||
|
@ -629,7 +661,7 @@ int hostapd_set_freq(struct hostapd_data *hapd, enum hostapd_hw_mode mode,
|
|||
&cmode->he_capab[IEEE80211_MODE_AP] : NULL,
|
||||
cmode ?
|
||||
&cmode->eht_capab[IEEE80211_MODE_AP] :
|
||||
NULL))
|
||||
NULL, hostapd_get_punct_bitmap(hapd)))
|
||||
return -1;
|
||||
|
||||
if (hapd->driver == NULL)
|
||||
|
@ -758,6 +790,8 @@ int hostapd_driver_scan(struct hostapd_data *hapd,
|
|||
struct wpa_scan_results * hostapd_driver_get_scan_results(
|
||||
struct hostapd_data *hapd)
|
||||
{
|
||||
if (hapd->driver && hapd->driver->get_scan_results)
|
||||
return hapd->driver->get_scan_results(hapd->drv_priv, NULL);
|
||||
if (hapd->driver && hapd->driver->get_scan_results2)
|
||||
return hapd->driver->get_scan_results2(hapd->drv_priv);
|
||||
return NULL;
|
||||
|
@ -840,7 +874,7 @@ int hostapd_drv_sta_deauth(struct hostapd_data *hapd,
|
|||
|
||||
link_id = hapd->mld_link_id;
|
||||
if (ap_sta_is_mld(hapd, sta))
|
||||
own_addr = hapd->mld_addr;
|
||||
own_addr = hapd->mld->mld_addr;
|
||||
}
|
||||
#endif /* CONFIG_IEEE80211BE */
|
||||
|
||||
|
@ -861,7 +895,7 @@ int hostapd_drv_sta_disassoc(struct hostapd_data *hapd,
|
|||
struct sta_info *sta = ap_get_sta(hapd, addr);
|
||||
|
||||
if (ap_sta_is_mld(hapd, sta))
|
||||
own_addr = hapd->mld_addr;
|
||||
own_addr = hapd->mld->mld_addr;
|
||||
}
|
||||
#endif /* CONFIG_IEEE80211BE */
|
||||
|
||||
|
@ -919,7 +953,7 @@ static int hapd_drv_send_action(struct hostapd_data *hapd, unsigned int freq,
|
|||
sta = ap_get_sta(hapd, dst);
|
||||
|
||||
if (ap_sta_is_mld(hapd, sta)) {
|
||||
own_addr = hapd->mld_addr;
|
||||
own_addr = hapd->mld->mld_addr;
|
||||
bssid = own_addr;
|
||||
}
|
||||
#endif /* CONFIG_IEEE80211BE */
|
||||
|
@ -977,7 +1011,8 @@ int hostapd_start_dfs_cac(struct hostapd_iface *iface,
|
|||
center_segment1,
|
||||
cmode->vht_capab,
|
||||
&cmode->he_capab[IEEE80211_MODE_AP],
|
||||
&cmode->eht_capab[IEEE80211_MODE_AP])) {
|
||||
&cmode->eht_capab[IEEE80211_MODE_AP],
|
||||
hostapd_get_punct_bitmap(hapd))) {
|
||||
wpa_printf(MSG_ERROR, "Can't set freq params");
|
||||
return -1;
|
||||
}
|
||||
|
@ -999,7 +1034,8 @@ int hostapd_start_dfs_cac(struct hostapd_iface *iface,
|
|||
int hostapd_drv_set_qos_map(struct hostapd_data *hapd,
|
||||
const u8 *qos_map_set, u8 qos_map_set_len)
|
||||
{
|
||||
if (!hapd->driver || !hapd->driver->set_qos_map || !hapd->drv_priv)
|
||||
if (!hapd->driver || !hapd->driver->set_qos_map || !hapd->drv_priv ||
|
||||
!(hapd->iface->drv_flags & WPA_DRIVER_FLAGS_QOS_MAPPING))
|
||||
return 0;
|
||||
return hapd->driver->set_qos_map(hapd->drv_priv, qos_map_set,
|
||||
qos_map_set_len);
|
||||
|
@ -1214,3 +1250,14 @@ int hostapd_drv_set_secure_ranging_ctx(struct hostapd_data *hapd,
|
|||
return hapd->driver->set_secure_ranging_ctx(hapd->drv_priv, ¶ms);
|
||||
}
|
||||
#endif /* CONFIG_PASN */
|
||||
|
||||
|
||||
struct hostapd_multi_hw_info *
|
||||
hostapd_get_multi_hw_info(struct hostapd_data *hapd,
|
||||
unsigned int *num_multi_hws)
|
||||
{
|
||||
if (!hapd->driver || !hapd->driver->get_multi_hw_info)
|
||||
return NULL;
|
||||
|
||||
return hapd->driver->get_multi_hw_info(hapd->drv_priv, num_multi_hws);
|
||||
}
|
||||
|
|
|
@ -26,6 +26,8 @@ void hostapd_free_ap_extra_ies(struct hostapd_data *hapd, struct wpabuf *beacon,
|
|||
struct wpabuf *assocresp);
|
||||
int hostapd_reset_ap_wps_ie(struct hostapd_data *hapd);
|
||||
int hostapd_set_ap_wps_ie(struct hostapd_data *hapd);
|
||||
bool hostapd_sta_is_link_sta(struct hostapd_data *hapd,
|
||||
struct sta_info *sta);
|
||||
int hostapd_set_authorized(struct hostapd_data *hapd,
|
||||
struct sta_info *sta, int authorized);
|
||||
int hostapd_set_sta_flags(struct hostapd_data *hapd, struct sta_info *sta);
|
||||
|
@ -59,6 +61,9 @@ int hostapd_if_add(struct hostapd_data *hapd, enum wpa_driver_if_type type,
|
|||
const char *bridge, int use_existing);
|
||||
int hostapd_if_remove(struct hostapd_data *hapd, enum wpa_driver_if_type type,
|
||||
const char *ifname);
|
||||
int hostapd_if_link_remove(struct hostapd_data *hapd,
|
||||
enum wpa_driver_if_type type,
|
||||
const char *ifname, u8 link_id);
|
||||
int hostapd_set_ieee8021x(struct hostapd_data *hapd,
|
||||
struct wpa_bss_params *params);
|
||||
int hostapd_get_seqnum(const char *ifname, struct hostapd_data *hapd,
|
||||
|
@ -388,9 +393,15 @@ static inline int hostapd_drv_vendor_cmd(struct hostapd_data *hapd,
|
|||
|
||||
static inline int hostapd_drv_stop_ap(struct hostapd_data *hapd)
|
||||
{
|
||||
int link_id = -1;
|
||||
|
||||
if (!hapd->driver || !hapd->driver->stop_ap || !hapd->drv_priv)
|
||||
return 0;
|
||||
return hapd->driver->stop_ap(hapd->drv_priv);
|
||||
#ifdef CONFIG_IEEE80211BE
|
||||
if (hapd->conf->mld_ap)
|
||||
link_id = hapd->mld_link_id;
|
||||
#endif /* CONFIG_IEEE80211BE */
|
||||
return hapd->driver->stop_ap(hapd->drv_priv, link_id);
|
||||
}
|
||||
|
||||
static inline int hostapd_drv_channel_info(struct hostapd_data *hapd,
|
||||
|
@ -443,15 +454,32 @@ hostapd_drv_register_frame(struct hostapd_data *hapd, u16 type,
|
|||
#endif /* CONFIG_TESTING_OPTIONS */
|
||||
|
||||
#ifdef CONFIG_IEEE80211BE
|
||||
|
||||
static inline int hostapd_drv_link_add(struct hostapd_data *hapd,
|
||||
u8 link_id, const u8 *addr)
|
||||
{
|
||||
if (!hapd->driver || !hapd->drv_priv || !hapd->driver->link_add)
|
||||
return -1;
|
||||
|
||||
return hapd->driver->link_add(hapd->drv_priv, link_id, addr);
|
||||
return hapd->driver->link_add(hapd->drv_priv, link_id, addr, hapd);
|
||||
|
||||
}
|
||||
|
||||
static inline int hostapd_drv_link_sta_remove(struct hostapd_data *hapd,
|
||||
const u8 *addr)
|
||||
{
|
||||
if (!hapd->conf->mld_ap || !hapd->driver || !hapd->drv_priv ||
|
||||
!hapd->driver->link_sta_remove)
|
||||
return -1;
|
||||
|
||||
return hapd->driver->link_sta_remove(hapd->drv_priv, hapd->mld_link_id,
|
||||
addr);
|
||||
}
|
||||
|
||||
#endif /* CONFIG_IEEE80211BE */
|
||||
|
||||
struct hostapd_multi_hw_info *
|
||||
hostapd_get_multi_hw_info(struct hostapd_data *hapd,
|
||||
unsigned int *num_multi_hws);
|
||||
|
||||
#endif /* AP_DRV_OPS */
|
||||
|
|
|
@ -107,13 +107,20 @@ static int hostapd_setup_radius_srv(struct hostapd_data *hapd)
|
|||
struct radius_server_conf srv;
|
||||
struct hostapd_bss_config *conf = hapd->conf;
|
||||
|
||||
if (hapd->mld_first_bss) {
|
||||
#ifdef CONFIG_IEEE80211BE
|
||||
if (!hostapd_mld_is_first_bss(hapd)) {
|
||||
struct hostapd_data *first;
|
||||
|
||||
wpa_printf(MSG_DEBUG,
|
||||
"MLD: Using RADIUS server of the first BSS");
|
||||
|
||||
hapd->radius_srv = hapd->mld_first_bss->radius_srv;
|
||||
first = hostapd_mld_get_first_bss(hapd);
|
||||
if (!first)
|
||||
return -1;
|
||||
hapd->radius_srv = first->radius_srv;
|
||||
return 0;
|
||||
}
|
||||
#endif /* CONFIG_IEEE80211BE */
|
||||
|
||||
os_memset(&srv, 0, sizeof(srv));
|
||||
srv.client_file = conf->radius_server_clients;
|
||||
|
@ -249,18 +256,34 @@ static struct eap_config * authsrv_eap_config(struct hostapd_data *hapd)
|
|||
|
||||
int authsrv_init(struct hostapd_data *hapd)
|
||||
{
|
||||
if (hapd->mld_first_bss) {
|
||||
#ifdef CONFIG_IEEE80211BE
|
||||
if (!hostapd_mld_is_first_bss(hapd)) {
|
||||
struct hostapd_data *first;
|
||||
|
||||
first = hostapd_mld_get_first_bss(hapd);
|
||||
if (!first)
|
||||
return -1;
|
||||
|
||||
if (!first->eap_cfg) {
|
||||
wpa_printf(MSG_DEBUG,
|
||||
"MLD: First BSS auth_serv does not exist. Init on its behalf");
|
||||
|
||||
if (authsrv_init(first))
|
||||
return -1;
|
||||
}
|
||||
|
||||
wpa_printf(MSG_DEBUG, "MLD: Using auth_serv of the first BSS");
|
||||
|
||||
#ifdef EAP_TLS_FUNCS
|
||||
hapd->ssl_ctx = hapd->mld_first_bss->ssl_ctx;
|
||||
hapd->ssl_ctx = first->ssl_ctx;
|
||||
#endif /* EAP_TLS_FUNCS */
|
||||
hapd->eap_cfg = hapd->mld_first_bss->eap_cfg;
|
||||
hapd->eap_cfg = first->eap_cfg;
|
||||
#ifdef EAP_SIM_DB
|
||||
hapd->eap_sim_db_priv = hapd->mld_first_bss->eap_sim_db_priv;
|
||||
hapd->eap_sim_db_priv = first->eap_sim_db_priv;
|
||||
#endif /* EAP_SIM_DB */
|
||||
return 0;
|
||||
}
|
||||
#endif /* CONFIG_IEEE80211BE */
|
||||
|
||||
#ifdef EAP_TLS_FUNCS
|
||||
if (hapd->conf->eap_server &&
|
||||
|
@ -376,7 +399,8 @@ int authsrv_init(struct hostapd_data *hapd)
|
|||
|
||||
void authsrv_deinit(struct hostapd_data *hapd)
|
||||
{
|
||||
if (hapd->mld_first_bss) {
|
||||
#ifdef CONFIG_IEEE80211BE
|
||||
if (!hostapd_mld_is_first_bss(hapd)) {
|
||||
wpa_printf(MSG_DEBUG,
|
||||
"MLD: Deinit auth_serv of a non-first BSS");
|
||||
|
||||
|
@ -390,6 +414,7 @@ void authsrv_deinit(struct hostapd_data *hapd)
|
|||
#endif /* EAP_TLS_FUNCS */
|
||||
return;
|
||||
}
|
||||
#endif /* CONFIG_IEEE80211BE */
|
||||
|
||||
#ifdef RADIUS_SERVER
|
||||
radius_server_deinit(hapd->radius_srv);
|
||||
|
|
813
src/ap/beacon.c
813
src/ap/beacon.c
File diff suppressed because it is too large
Load diff
|
@ -33,4 +33,7 @@ void sta_track_claim_taxonomy_info(struct hostapd_iface *iface, const u8 *addr,
|
|||
|
||||
const u8 * hostapd_wpa_ie(struct hostapd_data *hapd, u8 eid);
|
||||
|
||||
u8 * hostapd_unsol_bcast_probe_resp(struct hostapd_data *hapd,
|
||||
struct unsol_bcast_probe_resp *ubpr);
|
||||
|
||||
#endif /* BEACON_H */
|
||||
|
|
|
@ -277,6 +277,14 @@ static int hostapd_ctrl_iface_sta_mib(struct hostapd_data *hapd,
|
|||
return len;
|
||||
len += ret;
|
||||
|
||||
if (sta->max_idle_period) {
|
||||
ret = os_snprintf(buf + len, buflen - len,
|
||||
"max_idle_period=%d\n", sta->max_idle_period);
|
||||
if (os_snprintf_error(buflen - len, ret))
|
||||
return len;
|
||||
len += ret;
|
||||
}
|
||||
|
||||
res = ieee802_11_get_mib_sta(hapd, sta, buf + len, buflen - len);
|
||||
if (res >= 0)
|
||||
len += res;
|
||||
|
@ -348,11 +356,15 @@ static int hostapd_ctrl_iface_sta_mib(struct hostapd_data *hapd,
|
|||
|
||||
if (sta->supp_op_classes &&
|
||||
buflen - len > (unsigned) (17 + 2 * sta->supp_op_classes[0])) {
|
||||
len += os_snprintf(buf + len, buflen - len, "supp_op_classes=");
|
||||
res = os_snprintf(buf + len, buflen - len, "supp_op_classes=");
|
||||
if (!os_snprintf_error(buflen - len, res))
|
||||
len += res;
|
||||
len += wpa_snprintf_hex(buf + len, buflen - len,
|
||||
sta->supp_op_classes + 1,
|
||||
sta->supp_op_classes[0]);
|
||||
len += os_snprintf(buf + len, buflen - len, "\n");
|
||||
res = os_snprintf(buf + len, buflen - len, "\n");
|
||||
if (!os_snprintf_error(buflen - len, res))
|
||||
len += res;
|
||||
}
|
||||
|
||||
if (sta->power_capab) {
|
||||
|
@ -364,6 +376,34 @@ static int hostapd_ctrl_iface_sta_mib(struct hostapd_data *hapd,
|
|||
len += ret;
|
||||
}
|
||||
|
||||
#ifdef CONFIG_IEEE80211AX
|
||||
if ((sta->flags & WLAN_STA_HE) && sta->he_capab) {
|
||||
res = os_snprintf(buf + len, buflen - len, "he_capab=");
|
||||
if (!os_snprintf_error(buflen - len, res))
|
||||
len += res;
|
||||
len += wpa_snprintf_hex(buf + len, buflen - len,
|
||||
(const u8 *) sta->he_capab,
|
||||
sta->he_capab_len);
|
||||
res = os_snprintf(buf + len, buflen - len, "\n");
|
||||
if (!os_snprintf_error(buflen - len, res))
|
||||
len += res;
|
||||
}
|
||||
#endif /* CONFIG_IEEE80211AX */
|
||||
|
||||
#ifdef CONFIG_IEEE80211BE
|
||||
if ((sta->flags & WLAN_STA_EHT) && sta->eht_capab) {
|
||||
res = os_snprintf(buf + len, buflen - len, "eht_capab=");
|
||||
if (!os_snprintf_error(buflen - len, res))
|
||||
len += res;
|
||||
len += wpa_snprintf_hex(buf + len, buflen - len,
|
||||
(const u8 *) sta->eht_capab,
|
||||
sta->eht_capab_len);
|
||||
res = os_snprintf(buf + len, buflen - len, "\n");
|
||||
if (!os_snprintf_error(buflen - len, res))
|
||||
len += res;
|
||||
}
|
||||
#endif /* CONFIG_IEEE80211BE */
|
||||
|
||||
#ifdef CONFIG_IEEE80211AC
|
||||
if ((sta->flags & WLAN_STA_VHT) && sta->vht_capabilities) {
|
||||
res = os_snprintf(buf + len, buflen - len,
|
||||
|
@ -372,6 +412,16 @@ static int hostapd_ctrl_iface_sta_mib(struct hostapd_data *hapd,
|
|||
vht_capabilities_info));
|
||||
if (!os_snprintf_error(buflen - len, res))
|
||||
len += res;
|
||||
|
||||
res = os_snprintf(buf + len, buflen - len, "vht_capab=");
|
||||
if (!os_snprintf_error(buflen - len, res))
|
||||
len += res;
|
||||
len += wpa_snprintf_hex(buf + len, buflen - len,
|
||||
(const u8 *) sta->vht_capabilities,
|
||||
sizeof(*sta->vht_capabilities));
|
||||
res = os_snprintf(buf + len, buflen - len, "\n");
|
||||
if (!os_snprintf_error(buflen - len, res))
|
||||
len += res;
|
||||
}
|
||||
#endif /* CONFIG_IEEE80211AC */
|
||||
|
||||
|
@ -386,11 +436,15 @@ static int hostapd_ctrl_iface_sta_mib(struct hostapd_data *hapd,
|
|||
|
||||
if (sta->ext_capability &&
|
||||
buflen - len > (unsigned) (11 + 2 * sta->ext_capability[0])) {
|
||||
len += os_snprintf(buf + len, buflen - len, "ext_capab=");
|
||||
res = os_snprintf(buf + len, buflen - len, "ext_capab=");
|
||||
if (!os_snprintf_error(buflen - len, res))
|
||||
len += res;
|
||||
len += wpa_snprintf_hex(buf + len, buflen - len,
|
||||
sta->ext_capability + 1,
|
||||
sta->ext_capability[0]);
|
||||
len += os_snprintf(buf + len, buflen - len, "\n");
|
||||
res = os_snprintf(buf + len, buflen - len, "\n");
|
||||
if (!os_snprintf_error(buflen - len, res))
|
||||
len += res;
|
||||
}
|
||||
|
||||
if (sta->flags & WLAN_STA_WDS && sta->ifname_wds) {
|
||||
|
@ -419,6 +473,21 @@ static int hostapd_ctrl_iface_sta_mib(struct hostapd_data *hapd,
|
|||
len += ret;
|
||||
}
|
||||
|
||||
#ifdef CONFIG_IEEE80211BE
|
||||
if (sta->mld_info.mld_sta) {
|
||||
for (i = 0; i < MAX_NUM_MLD_LINKS; ++i) {
|
||||
if (!sta->mld_info.links[i].valid)
|
||||
continue;
|
||||
ret = os_snprintf(
|
||||
buf + len, buflen - len,
|
||||
"peer_addr[%d]=" MACSTR "\n",
|
||||
i, MAC2STR(sta->mld_info.links[i].peer_addr));
|
||||
if (!os_snprintf_error(buflen - len, ret))
|
||||
len += ret;
|
||||
}
|
||||
}
|
||||
#endif /* CONFIG_IEEE80211BE */
|
||||
|
||||
return len;
|
||||
}
|
||||
|
||||
|
@ -592,15 +661,18 @@ int hostapd_ctrl_iface_deauthenticate(struct hostapd_data *hapd,
|
|||
}
|
||||
#endif /* CONFIG_P2P_MANAGER */
|
||||
|
||||
if (os_strstr(txtaddr, " tx=0"))
|
||||
hostapd_drv_sta_remove(hapd, addr);
|
||||
else
|
||||
hostapd_drv_sta_deauth(hapd, addr, reason);
|
||||
sta = ap_get_sta(hapd, addr);
|
||||
if (sta)
|
||||
ap_sta_deauthenticate(hapd, sta, reason);
|
||||
else if (addr[0] == 0xff)
|
||||
hostapd_free_stas(hapd);
|
||||
if (os_strstr(txtaddr, " tx=0")) {
|
||||
hostapd_drv_sta_remove(hapd, addr);
|
||||
if (sta)
|
||||
ap_free_sta(hapd, sta);
|
||||
} else {
|
||||
hostapd_drv_sta_deauth(hapd, addr, reason);
|
||||
if (sta)
|
||||
ap_sta_deauthenticate(hapd, sta, reason);
|
||||
else if (addr[0] == 0xff)
|
||||
hostapd_free_stas(hapd);
|
||||
}
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
@ -654,15 +726,18 @@ int hostapd_ctrl_iface_disassociate(struct hostapd_data *hapd,
|
|||
}
|
||||
#endif /* CONFIG_P2P_MANAGER */
|
||||
|
||||
if (os_strstr(txtaddr, " tx=0"))
|
||||
hostapd_drv_sta_remove(hapd, addr);
|
||||
else
|
||||
hostapd_drv_sta_disassoc(hapd, addr, reason);
|
||||
sta = ap_get_sta(hapd, addr);
|
||||
if (sta)
|
||||
ap_sta_disassociate(hapd, sta, reason);
|
||||
else if (addr[0] == 0xff)
|
||||
hostapd_free_stas(hapd);
|
||||
if (os_strstr(txtaddr, " tx=0")) {
|
||||
hostapd_drv_sta_remove(hapd, addr);
|
||||
if (sta)
|
||||
ap_free_sta(hapd, sta);
|
||||
} else {
|
||||
hostapd_drv_sta_disassoc(hapd, addr, reason);
|
||||
if (sta)
|
||||
ap_sta_disassociate(hapd, sta, reason);
|
||||
else if (addr[0] == 0xff)
|
||||
hostapd_free_stas(hapd);
|
||||
}
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
@ -841,6 +916,42 @@ int hostapd_ctrl_iface_status(struct hostapd_data *hapd, char *buf,
|
|||
return len;
|
||||
len += ret;
|
||||
}
|
||||
|
||||
if (hapd->conf->mld_ap) {
|
||||
struct hostapd_data *link_bss;
|
||||
|
||||
ret = os_snprintf(buf + len, buflen - len,
|
||||
"num_links=%d\n",
|
||||
hapd->mld->num_links);
|
||||
if (os_snprintf_error(buflen - len, ret))
|
||||
return len;
|
||||
len += ret;
|
||||
|
||||
/* Self BSS */
|
||||
ret = os_snprintf(buf + len, buflen - len,
|
||||
"link_id=%d\n"
|
||||
"link_addr=" MACSTR "\n",
|
||||
hapd->mld_link_id,
|
||||
MAC2STR(hapd->own_addr));
|
||||
if (os_snprintf_error(buflen - len, ret))
|
||||
return len;
|
||||
len += ret;
|
||||
|
||||
/* Partner BSSs */
|
||||
for_each_mld_link(link_bss, hapd) {
|
||||
if (link_bss == hapd)
|
||||
continue;
|
||||
|
||||
ret = os_snprintf(buf + len, buflen - len,
|
||||
"partner_link[%d]=" MACSTR
|
||||
"\n",
|
||||
link_bss->mld_link_id,
|
||||
MAC2STR(link_bss->own_addr));
|
||||
if (os_snprintf_error(buflen - len, ret))
|
||||
return len;
|
||||
len += ret;
|
||||
}
|
||||
}
|
||||
}
|
||||
#endif /* CONFIG_IEEE80211BE */
|
||||
|
||||
|
@ -966,8 +1077,8 @@ int hostapd_ctrl_iface_status(struct hostapd_data *hapd, char *buf,
|
|||
"mld_addr[%d]=" MACSTR "\n"
|
||||
"mld_id[%d]=%d\n"
|
||||
"mld_link_id[%d]=%d\n",
|
||||
(int) i, MAC2STR(bss->mld_addr),
|
||||
(int) i, bss->conf->mld_id,
|
||||
(int) i, MAC2STR(bss->mld->mld_addr),
|
||||
(int) i, hostapd_get_mld_id(bss),
|
||||
(int) i, bss->mld_link_id);
|
||||
if (os_snprintf_error(buflen - len, ret))
|
||||
return len;
|
||||
|
@ -1032,8 +1143,9 @@ int hostapd_parse_csa_settings(const char *pos,
|
|||
SET_CSA_SETTING_EXT(punct_bitmap);
|
||||
settings->freq_params.ht_enabled = !!os_strstr(pos, " ht");
|
||||
settings->freq_params.vht_enabled = !!os_strstr(pos, " vht");
|
||||
settings->freq_params.he_enabled = !!os_strstr(pos, " he");
|
||||
settings->freq_params.eht_enabled = !!os_strstr(pos, " eht");
|
||||
settings->freq_params.he_enabled = !!os_strstr(pos, " he") ||
|
||||
settings->freq_params.eht_enabled;
|
||||
settings->block_tx = !!os_strstr(pos, " blocktx");
|
||||
#undef SET_CSA_SETTING
|
||||
#undef SET_CSA_SETTING_EXT
|
||||
|
|
46
src/ap/dfs.c
46
src/ap/dfs.c
|
@ -14,6 +14,7 @@
|
|||
#include "common/hw_features_common.h"
|
||||
#include "common/wpa_ctrl.h"
|
||||
#include "hostapd.h"
|
||||
#include "beacon.h"
|
||||
#include "ap_drv_ops.h"
|
||||
#include "drivers/driver.h"
|
||||
#include "dfs.h"
|
||||
|
@ -252,6 +253,13 @@ static int dfs_find_channel(struct hostapd_iface *iface,
|
|||
for (i = 0; i < mode->num_channels; i++) {
|
||||
chan = &mode->channels[i];
|
||||
|
||||
if (!chan_in_current_hw_info(iface->current_hw_info, chan)) {
|
||||
wpa_printf(MSG_DEBUG,
|
||||
"DFS: channel %d (%d) is not under current hardware index",
|
||||
chan->freq, chan->chan);
|
||||
continue;
|
||||
}
|
||||
|
||||
/* Skip HT40/VHT incompatible channels */
|
||||
if (iface->conf->ieee80211n &&
|
||||
iface->conf->secondary_channel &&
|
||||
|
@ -972,6 +980,7 @@ static int hostapd_dfs_request_channel_switch(struct hostapd_iface *iface,
|
|||
struct csa_settings csa_settings;
|
||||
u8 new_vht_oper_chwidth;
|
||||
unsigned int i;
|
||||
unsigned int num_err = 0;
|
||||
|
||||
wpa_printf(MSG_DEBUG, "DFS will switch to a new channel %d", channel);
|
||||
wpa_msg(iface->bss[0]->msg_ctx, MSG_INFO, DFS_EVENT_NEW_CHANNEL
|
||||
|
@ -1009,7 +1018,8 @@ static int hostapd_dfs_request_channel_switch(struct hostapd_iface *iface,
|
|||
oper_centr_freq_seg1_idx,
|
||||
cmode->vht_capab,
|
||||
&cmode->he_capab[ieee80211_mode],
|
||||
&cmode->eht_capab[ieee80211_mode]);
|
||||
&cmode->eht_capab[ieee80211_mode],
|
||||
hostapd_get_punct_bitmap(iface->bss[0]));
|
||||
|
||||
if (err) {
|
||||
wpa_printf(MSG_ERROR,
|
||||
|
@ -1021,10 +1031,10 @@ static int hostapd_dfs_request_channel_switch(struct hostapd_iface *iface,
|
|||
for (i = 0; i < iface->num_bss; i++) {
|
||||
err = hostapd_switch_channel(iface->bss[i], &csa_settings);
|
||||
if (err)
|
||||
break;
|
||||
num_err++;
|
||||
}
|
||||
|
||||
if (err) {
|
||||
if (num_err == iface->num_bss) {
|
||||
wpa_printf(MSG_WARNING,
|
||||
"DFS failed to schedule CSA (%d) - trying fallback",
|
||||
err);
|
||||
|
@ -1141,14 +1151,23 @@ int hostapd_dfs_complete_cac(struct hostapd_iface *iface, int success, int freq,
|
|||
int cf1, int cf2)
|
||||
{
|
||||
wpa_msg(iface->bss[0]->msg_ctx, MSG_INFO, DFS_EVENT_CAC_COMPLETED
|
||||
"success=%d freq=%d ht_enabled=%d chan_offset=%d chan_width=%d cf1=%d cf2=%d",
|
||||
success, freq, ht_enabled, chan_offset, chan_width, cf1, cf2);
|
||||
"success=%d freq=%d ht_enabled=%d chan_offset=%d chan_width=%d cf1=%d cf2=%d radar_detected=%d",
|
||||
success, freq, ht_enabled, chan_offset, chan_width, cf1, cf2,
|
||||
iface->radar_detected);
|
||||
|
||||
if (success) {
|
||||
/* Complete iface/ap configuration */
|
||||
if (iface->drv_flags & WPA_DRIVER_FLAGS_DFS_OFFLOAD) {
|
||||
/* Complete AP configuration for the first bring up. */
|
||||
if (iface->state != HAPD_IFACE_ENABLED)
|
||||
/* Complete AP configuration for the first bring up. If
|
||||
* a radar was detected in this channel, interface setup
|
||||
* will be handled in
|
||||
* 1. hostapd_event_ch_switch() if switching to a
|
||||
* non-DFS channel
|
||||
* 2. on next CAC complete event if switching to another
|
||||
* DFS channel.
|
||||
*/
|
||||
if (iface->state != HAPD_IFACE_ENABLED &&
|
||||
!iface->radar_detected)
|
||||
hostapd_setup_interface_complete(iface, 0);
|
||||
else
|
||||
iface->cac_started = 0;
|
||||
|
@ -1193,6 +1212,7 @@ int hostapd_dfs_complete_cac(struct hostapd_iface *iface, int success, int freq,
|
|||
hostapd_dfs_update_background_chain(iface);
|
||||
}
|
||||
|
||||
iface->radar_detected = false;
|
||||
return 0;
|
||||
}
|
||||
|
||||
|
@ -1436,6 +1456,8 @@ int hostapd_dfs_radar_detected(struct hostapd_iface *iface, int freq,
|
|||
"freq=%d ht_enabled=%d chan_offset=%d chan_width=%d cf1=%d cf2=%d",
|
||||
freq, ht_enabled, chan_offset, chan_width, cf1, cf2);
|
||||
|
||||
iface->radar_detected = true;
|
||||
|
||||
/* Proceed only if DFS is not offloaded to the driver */
|
||||
if (iface->drv_flags & WPA_DRIVER_FLAGS_DFS_OFFLOAD)
|
||||
return 0;
|
||||
|
@ -1529,9 +1551,17 @@ int hostapd_dfs_start_cac(struct hostapd_iface *iface, int freq,
|
|||
iface->radar_background.cac_started = 1;
|
||||
} else {
|
||||
/* This is called when the driver indicates that an offloaded
|
||||
* DFS has started CAC. */
|
||||
* DFS has started CAC. radar_detected might be set for previous
|
||||
* DFS channel. Clear it for this new CAC process. */
|
||||
hostapd_set_state(iface, HAPD_IFACE_DFS);
|
||||
iface->cac_started = 1;
|
||||
|
||||
/* Clear radar_detected in case it is for the previous
|
||||
* frequency. Also remove disabled link's information in RNR
|
||||
* element from other links. */
|
||||
iface->radar_detected = false;
|
||||
if (iface->interfaces && iface->interfaces->count > 1)
|
||||
ieee802_11_set_beacons(iface);
|
||||
}
|
||||
/* TODO: How to check CAC time for ETSI weather channels? */
|
||||
iface->dfs_cac_ms = 60000;
|
||||
|
|
|
@ -3941,6 +3941,7 @@ int hostapd_dpp_push_button(struct hostapd_data *hapd, const char *cmd)
|
|||
eloop_register_timeout(100, 0, hostapd_dpp_push_button_expire,
|
||||
hapd, NULL);
|
||||
|
||||
wpa_msg(hapd->msg_ctx, MSG_INFO, DPP_EVENT_PB_STATUS "started");
|
||||
return 0;
|
||||
}
|
||||
|
||||
|
|
|
@ -73,6 +73,8 @@ void hostapd_notify_assoc_fils_finish(struct hostapd_data *hapd,
|
|||
p = hostapd_eid_assoc_fils_session(sta->wpa_sm, p,
|
||||
elems.fils_session,
|
||||
sta->fils_hlp_resp);
|
||||
if (!p)
|
||||
return;
|
||||
|
||||
reply_res = hostapd_sta_assoc(hapd, sta->addr,
|
||||
sta->fils_pending_assoc_is_reassoc,
|
||||
|
@ -248,6 +250,52 @@ out:
|
|||
#endif /* CONFIG_IEEE80211BE */
|
||||
|
||||
|
||||
#if defined(HOSTAPD) || defined(CONFIG_IEEE80211BE)
|
||||
static struct hostapd_data * hostapd_find_by_sta(struct hostapd_iface *iface,
|
||||
const u8 *src, bool rsn,
|
||||
struct sta_info **sta_ret)
|
||||
{
|
||||
struct hostapd_data *hapd;
|
||||
struct sta_info *sta;
|
||||
unsigned int j;
|
||||
|
||||
if (sta_ret)
|
||||
*sta_ret = NULL;
|
||||
|
||||
for (j = 0; j < iface->num_bss; j++) {
|
||||
hapd = iface->bss[j];
|
||||
sta = ap_get_sta(hapd, src);
|
||||
if (sta && (sta->flags & WLAN_STA_ASSOC) &&
|
||||
(!rsn || sta->wpa_sm)) {
|
||||
if (sta_ret)
|
||||
*sta_ret = sta;
|
||||
return hapd;
|
||||
}
|
||||
#ifdef CONFIG_IEEE80211BE
|
||||
if (hapd->conf->mld_ap) {
|
||||
struct hostapd_data *p_hapd;
|
||||
|
||||
for_each_mld_link(p_hapd, hapd) {
|
||||
if (p_hapd == hapd)
|
||||
continue;
|
||||
|
||||
sta = ap_get_sta(p_hapd, src);
|
||||
if (sta && (sta->flags & WLAN_STA_ASSOC) &&
|
||||
(!rsn || sta->wpa_sm)) {
|
||||
if (sta_ret)
|
||||
*sta_ret = sta;
|
||||
return p_hapd;
|
||||
}
|
||||
}
|
||||
}
|
||||
#endif /* CONFIG_IEEE80211BE */
|
||||
}
|
||||
|
||||
return NULL;
|
||||
}
|
||||
#endif /* HOSTAPD || CONFIG_IEEE80211BE */
|
||||
|
||||
|
||||
int hostapd_notif_assoc(struct hostapd_data *hapd, const u8 *addr,
|
||||
const u8 *req_ies, size_t req_ies_len,
|
||||
const u8 *resp_ies, size_t resp_ies_len,
|
||||
|
@ -513,11 +561,13 @@ int hostapd_notif_assoc(struct hostapd_data *hapd, const u8 *addr,
|
|||
"Failed to initialize WPA state machine");
|
||||
return -1;
|
||||
}
|
||||
wpa_auth_set_rsn_selection(sta->wpa_sm, elems.rsn_selection,
|
||||
elems.rsn_selection_len);
|
||||
#ifdef CONFIG_IEEE80211BE
|
||||
if (ap_sta_is_mld(hapd, sta)) {
|
||||
wpa_printf(MSG_DEBUG,
|
||||
"MLD: Set ML info in RSN Authenticator");
|
||||
wpa_auth_set_ml_info(sta->wpa_sm, hapd->mld_addr,
|
||||
wpa_auth_set_ml_info(sta->wpa_sm,
|
||||
sta->mld_assoc_link_id,
|
||||
&sta->mld_info);
|
||||
}
|
||||
|
@ -528,7 +578,7 @@ int hostapd_notif_assoc(struct hostapd_data *hapd, const u8 *addr,
|
|||
elems.rsnxe ? elems.rsnxe - 2 : NULL,
|
||||
elems.rsnxe ? elems.rsnxe_len + 2 : 0,
|
||||
elems.mdie, elems.mdie_len,
|
||||
elems.owe_dh, elems.owe_dh_len);
|
||||
elems.owe_dh, elems.owe_dh_len, NULL);
|
||||
reason = WLAN_REASON_INVALID_IE;
|
||||
status = WLAN_STATUS_INVALID_IE;
|
||||
switch (res) {
|
||||
|
@ -773,6 +823,9 @@ skip_wpa_check:
|
|||
p = hostapd_eid_assoc_fils_session(sta->wpa_sm, p,
|
||||
elems.fils_session,
|
||||
sta->fils_hlp_resp);
|
||||
if (!p)
|
||||
goto fail;
|
||||
|
||||
wpa_hexdump(MSG_DEBUG, "FILS Assoc Resp BUF (IEs)",
|
||||
buf, p - buf);
|
||||
}
|
||||
|
@ -910,6 +963,54 @@ fail:
|
|||
}
|
||||
|
||||
|
||||
static void hostapd_remove_sta(struct hostapd_data *hapd, struct sta_info *sta)
|
||||
{
|
||||
ap_sta_set_authorized(hapd, sta, 0);
|
||||
sta->flags &= ~(WLAN_STA_AUTH | WLAN_STA_ASSOC);
|
||||
hostapd_set_sta_flags(hapd, sta);
|
||||
wpa_auth_sm_event(sta->wpa_sm, WPA_DISASSOC);
|
||||
sta->acct_terminate_cause = RADIUS_ACCT_TERMINATE_CAUSE_USER_REQUEST;
|
||||
ieee802_1x_notify_port_enabled(sta->eapol_sm, 0);
|
||||
ap_free_sta(hapd, sta);
|
||||
}
|
||||
|
||||
|
||||
#ifdef CONFIG_IEEE80211BE
|
||||
static void hostapd_notif_disassoc_mld(struct hostapd_data *assoc_hapd,
|
||||
struct sta_info *sta,
|
||||
const u8 *addr)
|
||||
{
|
||||
unsigned int link_id, i;
|
||||
struct hostapd_data *tmp_hapd;
|
||||
struct hapd_interfaces *interfaces = assoc_hapd->iface->interfaces;
|
||||
|
||||
/* Remove STA entry in non-assoc links */
|
||||
for (link_id = 0; link_id < MAX_NUM_MLD_LINKS; link_id++) {
|
||||
if (!sta->mld_info.links[link_id].valid)
|
||||
continue;
|
||||
|
||||
for (i = 0; i < interfaces->count; i++) {
|
||||
struct sta_info *tmp_sta;
|
||||
|
||||
tmp_hapd = interfaces->iface[i]->bss[0];
|
||||
|
||||
if (!tmp_hapd->conf->mld_ap ||
|
||||
assoc_hapd == tmp_hapd ||
|
||||
assoc_hapd->conf->mld_id != tmp_hapd->conf->mld_id)
|
||||
continue;
|
||||
|
||||
tmp_sta = ap_get_sta(tmp_hapd, addr);
|
||||
if (tmp_sta)
|
||||
ap_free_sta(tmp_hapd, tmp_sta);
|
||||
}
|
||||
}
|
||||
|
||||
/* Remove STA in assoc link */
|
||||
hostapd_remove_sta(assoc_hapd, sta);
|
||||
}
|
||||
#endif /* CONFIG_IEEE80211BE */
|
||||
|
||||
|
||||
void hostapd_notif_disassoc(struct hostapd_data *hapd, const u8 *addr)
|
||||
{
|
||||
struct sta_info *sta;
|
||||
|
@ -931,6 +1032,50 @@ void hostapd_notif_disassoc(struct hostapd_data *hapd, const u8 *addr)
|
|||
HOSTAPD_LEVEL_INFO, "disassociated");
|
||||
|
||||
sta = ap_get_sta(hapd, addr);
|
||||
#ifdef CONFIG_IEEE80211BE
|
||||
if (hostapd_is_mld_ap(hapd)) {
|
||||
struct hostapd_data *assoc_hapd;
|
||||
unsigned int i;
|
||||
|
||||
if (!sta) {
|
||||
/* Find non-MLO cases from any of the affiliated AP
|
||||
* links. */
|
||||
for (i = 0; i < hapd->iface->interfaces->count; ++i) {
|
||||
struct hostapd_iface *h =
|
||||
hapd->iface->interfaces->iface[i];
|
||||
struct hostapd_data *h_hapd = h->bss[0];
|
||||
struct hostapd_bss_config *hconf = h_hapd->conf;
|
||||
|
||||
if (!hconf->mld_ap ||
|
||||
hconf->mld_id != hapd->conf->mld_id)
|
||||
continue;
|
||||
|
||||
sta = ap_get_sta(h_hapd, addr);
|
||||
if (sta) {
|
||||
if (!sta->mld_info.mld_sta) {
|
||||
hapd = h_hapd;
|
||||
goto legacy;
|
||||
}
|
||||
break;
|
||||
}
|
||||
}
|
||||
} else if (!sta->mld_info.mld_sta) {
|
||||
goto legacy;
|
||||
}
|
||||
if (!sta) {
|
||||
wpa_printf(MSG_DEBUG,
|
||||
"Disassociation notification for unknown STA "
|
||||
MACSTR, MAC2STR(addr));
|
||||
return;
|
||||
}
|
||||
sta = hostapd_ml_get_assoc_sta(hapd, sta, &assoc_hapd);
|
||||
if (sta)
|
||||
hostapd_notif_disassoc_mld(assoc_hapd, sta, addr);
|
||||
return;
|
||||
}
|
||||
|
||||
legacy:
|
||||
#endif /* CONFIG_IEEE80211BE */
|
||||
if (sta == NULL) {
|
||||
wpa_printf(MSG_DEBUG,
|
||||
"Disassociation notification for unknown STA "
|
||||
|
@ -938,19 +1083,27 @@ void hostapd_notif_disassoc(struct hostapd_data *hapd, const u8 *addr)
|
|||
return;
|
||||
}
|
||||
|
||||
ap_sta_set_authorized(hapd, sta, 0);
|
||||
sta->flags &= ~(WLAN_STA_AUTH | WLAN_STA_ASSOC);
|
||||
hostapd_set_sta_flags(hapd, sta);
|
||||
wpa_auth_sm_event(sta->wpa_sm, WPA_DISASSOC);
|
||||
sta->acct_terminate_cause = RADIUS_ACCT_TERMINATE_CAUSE_USER_REQUEST;
|
||||
ieee802_1x_notify_port_enabled(sta->eapol_sm, 0);
|
||||
ap_free_sta(hapd, sta);
|
||||
hostapd_remove_sta(hapd, sta);
|
||||
}
|
||||
|
||||
|
||||
void hostapd_event_sta_low_ack(struct hostapd_data *hapd, const u8 *addr)
|
||||
{
|
||||
struct sta_info *sta = ap_get_sta(hapd, addr);
|
||||
#ifdef CONFIG_IEEE80211BE
|
||||
struct hostapd_data *orig_hapd = hapd;
|
||||
|
||||
if (!sta && hapd->conf->mld_ap) {
|
||||
hapd = hostapd_find_by_sta(hapd->iface, addr, true, &sta);
|
||||
if (!hapd) {
|
||||
wpa_printf(MSG_DEBUG,
|
||||
"No partner link BSS found for STA " MACSTR
|
||||
" - fallback to received context",
|
||||
MAC2STR(addr));
|
||||
hapd = orig_hapd;
|
||||
}
|
||||
}
|
||||
#endif /* CONFIG_IEEE80211BE */
|
||||
|
||||
if (!sta || !hapd->conf->disassoc_low_ack || sta->agreed_to_steer)
|
||||
return;
|
||||
|
@ -1451,7 +1604,6 @@ int hostapd_probe_req_rx(struct hostapd_data *hapd, const u8 *sa, const u8 *da,
|
|||
|
||||
#ifdef CONFIG_IEEE80211R_AP
|
||||
static void hostapd_notify_auth_ft_finish(void *ctx, const u8 *dst,
|
||||
const u8 *bssid,
|
||||
u16 auth_transaction, u16 status,
|
||||
const u8 *ies, size_t ies_len)
|
||||
{
|
||||
|
@ -1527,7 +1679,7 @@ static void hostapd_notif_auth(struct hostapd_data *hapd,
|
|||
status = WLAN_STATUS_UNSPECIFIED_FAILURE;
|
||||
goto fail;
|
||||
}
|
||||
wpa_ft_process_auth(sta->wpa_sm, rx_auth->bssid,
|
||||
wpa_ft_process_auth(sta->wpa_sm,
|
||||
rx_auth->auth_transaction, rx_auth->ies,
|
||||
rx_auth->ies_len,
|
||||
hostapd_notify_auth_ft_finish, hapd);
|
||||
|
@ -1663,10 +1815,38 @@ switch_link_hapd(struct hostapd_data *hapd, int link_id)
|
|||
}
|
||||
|
||||
|
||||
static struct hostapd_data *
|
||||
switch_link_scan(struct hostapd_data *hapd, u64 scan_cookie)
|
||||
{
|
||||
#ifdef CONFIG_IEEE80211BE
|
||||
if (hapd->conf->mld_ap && scan_cookie != 0) {
|
||||
unsigned int i;
|
||||
|
||||
for (i = 0; i < hapd->iface->interfaces->count; i++) {
|
||||
struct hostapd_iface *h;
|
||||
struct hostapd_data *h_hapd;
|
||||
|
||||
h = hapd->iface->interfaces->iface[i];
|
||||
h_hapd = h->bss[0];
|
||||
if (!hostapd_is_ml_partner(hapd, h_hapd))
|
||||
continue;
|
||||
|
||||
if (h_hapd->scan_cookie == scan_cookie) {
|
||||
h_hapd->scan_cookie = 0;
|
||||
return h_hapd;
|
||||
}
|
||||
}
|
||||
}
|
||||
#endif /* CONFIG_IEEE80211BE */
|
||||
|
||||
return hapd;
|
||||
}
|
||||
|
||||
|
||||
#define HAPD_BROADCAST ((struct hostapd_data *) -1)
|
||||
|
||||
static struct hostapd_data * get_hapd_bssid(struct hostapd_iface *iface,
|
||||
const u8 *bssid)
|
||||
const u8 *bssid, int link_id)
|
||||
{
|
||||
size_t i;
|
||||
|
||||
|
@ -1677,8 +1857,35 @@ static struct hostapd_data * get_hapd_bssid(struct hostapd_iface *iface,
|
|||
return HAPD_BROADCAST;
|
||||
|
||||
for (i = 0; i < iface->num_bss; i++) {
|
||||
if (ether_addr_equal(bssid, iface->bss[i]->own_addr))
|
||||
return iface->bss[i];
|
||||
struct hostapd_data *hapd;
|
||||
#ifdef CONFIG_IEEE80211BE
|
||||
struct hostapd_data *p_hapd;
|
||||
#endif /* CONFIG_IEEE80211BE */
|
||||
|
||||
hapd = iface->bss[i];
|
||||
if (ether_addr_equal(bssid, hapd->own_addr))
|
||||
return hapd;
|
||||
|
||||
#ifdef CONFIG_IEEE80211BE
|
||||
if (ether_addr_equal(bssid, hapd->own_addr) ||
|
||||
(hapd->conf->mld_ap &&
|
||||
ether_addr_equal(bssid, hapd->mld->mld_addr) &&
|
||||
link_id == hapd->mld_link_id))
|
||||
return hapd;
|
||||
|
||||
if (!hapd->conf->mld_ap)
|
||||
continue;
|
||||
|
||||
for_each_mld_link(p_hapd, hapd) {
|
||||
if (p_hapd == hapd)
|
||||
continue;
|
||||
|
||||
if (ether_addr_equal(bssid, p_hapd->own_addr) ||
|
||||
(ether_addr_equal(bssid, p_hapd->mld->mld_addr) &&
|
||||
link_id == p_hapd->mld_link_id))
|
||||
return p_hapd;
|
||||
}
|
||||
#endif /* CONFIG_IEEE80211BE */
|
||||
}
|
||||
|
||||
return NULL;
|
||||
|
@ -1689,7 +1896,7 @@ static void hostapd_rx_from_unknown_sta(struct hostapd_data *hapd,
|
|||
const u8 *bssid, const u8 *addr,
|
||||
int wds)
|
||||
{
|
||||
hapd = get_hapd_bssid(hapd->iface, bssid);
|
||||
hapd = get_hapd_bssid(hapd->iface, bssid, -1);
|
||||
if (hapd == NULL || hapd == HAPD_BROADCAST)
|
||||
return;
|
||||
|
||||
|
@ -1704,8 +1911,9 @@ static int hostapd_mgmt_rx(struct hostapd_data *hapd, struct rx_mgmt *rx_mgmt)
|
|||
const u8 *bssid;
|
||||
struct hostapd_frame_info fi;
|
||||
int ret;
|
||||
bool is_mld = false;
|
||||
|
||||
if (rx_mgmt->ctx)
|
||||
hapd = rx_mgmt->ctx;
|
||||
hapd = switch_link_hapd(hapd, rx_mgmt->link_id);
|
||||
iface = hapd->iface;
|
||||
|
||||
|
@ -1729,14 +1937,7 @@ static int hostapd_mgmt_rx(struct hostapd_data *hapd, struct rx_mgmt *rx_mgmt)
|
|||
if (bssid == NULL)
|
||||
return 0;
|
||||
|
||||
#ifdef CONFIG_IEEE80211BE
|
||||
if (hapd->conf->mld_ap &&
|
||||
ether_addr_equal(hapd->mld_addr, bssid))
|
||||
is_mld = true;
|
||||
#endif /* CONFIG_IEEE80211BE */
|
||||
|
||||
if (!is_mld)
|
||||
hapd = get_hapd_bssid(iface, bssid);
|
||||
hapd = get_hapd_bssid(iface, bssid, rx_mgmt->link_id);
|
||||
|
||||
if (!hapd) {
|
||||
u16 fc = le_to_host16(hdr->frame_control);
|
||||
|
@ -1788,22 +1989,17 @@ static void hostapd_mgmt_tx_cb(struct hostapd_data *hapd, const u8 *buf,
|
|||
struct ieee80211_hdr *hdr;
|
||||
struct hostapd_data *orig_hapd, *tmp_hapd;
|
||||
|
||||
#ifdef CONFIG_IEEE80211BE
|
||||
if (hapd->conf->mld_ap && link_id != -1) {
|
||||
tmp_hapd = hostapd_mld_get_link_bss(hapd, link_id);
|
||||
if (tmp_hapd)
|
||||
hapd = tmp_hapd;
|
||||
}
|
||||
#endif /* CONFIG_IEEE80211BE */
|
||||
orig_hapd = hapd;
|
||||
|
||||
hdr = (struct ieee80211_hdr *) buf;
|
||||
tmp_hapd = get_hapd_bssid(hapd->iface, get_hdr_bssid(hdr, len));
|
||||
hapd = switch_link_hapd(hapd, link_id);
|
||||
tmp_hapd = get_hapd_bssid(hapd->iface, get_hdr_bssid(hdr, len), link_id);
|
||||
if (tmp_hapd) {
|
||||
hapd = tmp_hapd;
|
||||
#ifdef CONFIG_IEEE80211BE
|
||||
} else if (hapd->conf->mld_ap &&
|
||||
ether_addr_equal(hapd->mld_addr, get_hdr_bssid(hdr, len))) {
|
||||
ether_addr_equal(hapd->mld->mld_addr,
|
||||
get_hdr_bssid(hdr, len))) {
|
||||
/* AP MLD address match - use hapd pointer as-is */
|
||||
#endif /* CONFIG_IEEE80211BE */
|
||||
} else {
|
||||
|
@ -1814,7 +2010,7 @@ static void hostapd_mgmt_tx_cb(struct hostapd_data *hapd, const u8 *buf,
|
|||
if (stype != WLAN_FC_STYPE_ACTION || len <= 25 ||
|
||||
buf[24] != WLAN_ACTION_PUBLIC)
|
||||
return;
|
||||
hapd = get_hapd_bssid(orig_hapd->iface, hdr->addr2);
|
||||
hapd = get_hapd_bssid(orig_hapd->iface, hdr->addr2, link_id);
|
||||
if (!hapd || hapd == HAPD_BROADCAST)
|
||||
return;
|
||||
/*
|
||||
|
@ -1850,57 +2046,6 @@ static int hostapd_event_new_sta(struct hostapd_data *hapd, const u8 *addr)
|
|||
}
|
||||
|
||||
|
||||
static struct hostapd_data * hostapd_find_by_sta(struct hostapd_iface *iface,
|
||||
const u8 *src, bool rsn)
|
||||
{
|
||||
struct sta_info *sta;
|
||||
unsigned int j;
|
||||
|
||||
for (j = 0; j < iface->num_bss; j++) {
|
||||
sta = ap_get_sta(iface->bss[j], src);
|
||||
if (sta && (sta->flags & WLAN_STA_ASSOC) &&
|
||||
(!rsn || sta->wpa_sm))
|
||||
return iface->bss[j];
|
||||
}
|
||||
|
||||
return NULL;
|
||||
}
|
||||
|
||||
|
||||
#ifdef CONFIG_IEEE80211BE
|
||||
static bool search_mld_sta(struct hostapd_data **p_hapd, const u8 *src)
|
||||
{
|
||||
struct hostapd_data *hapd = *p_hapd;
|
||||
unsigned int i;
|
||||
|
||||
/* Search for STA on other MLO BSSs */
|
||||
for (i = 0; i < hapd->iface->interfaces->count; i++) {
|
||||
struct hostapd_iface *h =
|
||||
hapd->iface->interfaces->iface[i];
|
||||
struct hostapd_data *h_hapd = h->bss[0];
|
||||
struct hostapd_bss_config *hconf = h_hapd->conf;
|
||||
|
||||
if (!hconf->mld_ap ||
|
||||
hconf->mld_id != hapd->conf->mld_id)
|
||||
continue;
|
||||
|
||||
h_hapd = hostapd_find_by_sta(h, src, false);
|
||||
if (h_hapd) {
|
||||
struct sta_info *sta = ap_get_sta(h_hapd, src);
|
||||
|
||||
if (sta && sta->mld_info.mld_sta &&
|
||||
sta->mld_assoc_link_id != h_hapd->mld_link_id)
|
||||
continue;
|
||||
*p_hapd = h_hapd;
|
||||
return true;
|
||||
}
|
||||
}
|
||||
|
||||
return false;
|
||||
}
|
||||
#endif /* CONFIG_IEEE80211BE */
|
||||
|
||||
|
||||
static void hostapd_event_eapol_rx(struct hostapd_data *hapd, const u8 *src,
|
||||
const u8 *data, size_t data_len,
|
||||
enum frame_encryption encrypted,
|
||||
|
@ -1909,28 +2054,10 @@ static void hostapd_event_eapol_rx(struct hostapd_data *hapd, const u8 *src,
|
|||
struct hostapd_data *orig_hapd = hapd;
|
||||
|
||||
#ifdef CONFIG_IEEE80211BE
|
||||
if (link_id != -1) {
|
||||
struct hostapd_data *h_hapd;
|
||||
|
||||
hapd = switch_link_hapd(hapd, link_id);
|
||||
h_hapd = hostapd_find_by_sta(hapd->iface, src, true);
|
||||
if (!h_hapd)
|
||||
h_hapd = hostapd_find_by_sta(orig_hapd->iface, src,
|
||||
true);
|
||||
if (!h_hapd)
|
||||
h_hapd = hostapd_find_by_sta(hapd->iface, src, false);
|
||||
if (!h_hapd)
|
||||
h_hapd = hostapd_find_by_sta(orig_hapd->iface, src,
|
||||
false);
|
||||
if (h_hapd)
|
||||
hapd = h_hapd;
|
||||
} else if (hapd->conf->mld_ap) {
|
||||
search_mld_sta(&hapd, src);
|
||||
} else {
|
||||
hapd = hostapd_find_by_sta(hapd->iface, src, false);
|
||||
}
|
||||
hapd = switch_link_hapd(hapd, link_id);
|
||||
hapd = hostapd_find_by_sta(hapd->iface, src, true, NULL);
|
||||
#else /* CONFIG_IEEE80211BE */
|
||||
hapd = hostapd_find_by_sta(hapd->iface, src, false);
|
||||
hapd = hostapd_find_by_sta(hapd->iface, src, false, NULL);
|
||||
#endif /* CONFIG_IEEE80211BE */
|
||||
|
||||
if (!hapd) {
|
||||
|
@ -2257,6 +2384,136 @@ err:
|
|||
#endif /* CONFIG_OWE */
|
||||
|
||||
|
||||
#ifdef NEED_AP_MLME
|
||||
static void hostapd_eapol_tx_status(struct hostapd_data *hapd, const u8 *dst,
|
||||
const u8 *data, size_t len, int ack,
|
||||
int link_id)
|
||||
{
|
||||
struct sta_info *sta;
|
||||
|
||||
hapd = switch_link_hapd(hapd, link_id);
|
||||
hapd = hostapd_find_by_sta(hapd->iface, dst, false, &sta);
|
||||
|
||||
if (!sta) {
|
||||
wpa_printf(MSG_DEBUG, "Ignore TX status for Data frame to STA "
|
||||
MACSTR " that is not currently associated",
|
||||
MAC2STR(dst));
|
||||
return;
|
||||
}
|
||||
|
||||
ieee802_1x_eapol_tx_status(hapd, sta, data, len, ack);
|
||||
}
|
||||
#endif /* NEED_AP_MLME */
|
||||
|
||||
|
||||
#ifdef CONFIG_IEEE80211AX
|
||||
static void hostapd_event_color_change(struct hostapd_data *hapd, bool success)
|
||||
{
|
||||
struct hostapd_data *bss;
|
||||
size_t i;
|
||||
|
||||
for (i = 0; i < hapd->iface->num_bss; i++) {
|
||||
bss = hapd->iface->bss[i];
|
||||
if (bss->cca_color == 0)
|
||||
continue;
|
||||
|
||||
if (success)
|
||||
hapd->iface->conf->he_op.he_bss_color = bss->cca_color;
|
||||
|
||||
bss->cca_in_progress = 0;
|
||||
if (ieee802_11_set_beacon(bss)) {
|
||||
wpa_printf(MSG_ERROR, "Failed to remove BCCA element");
|
||||
bss->cca_in_progress = 1;
|
||||
} else {
|
||||
hostapd_cleanup_cca_params(bss);
|
||||
}
|
||||
}
|
||||
}
|
||||
#endif /* CONFIG_IEEE80211AX */
|
||||
|
||||
|
||||
static void hostapd_iface_enable(struct hostapd_data *hapd)
|
||||
{
|
||||
wpa_msg(hapd->msg_ctx, MSG_INFO, INTERFACE_ENABLED);
|
||||
if (hapd->disabled && hapd->started) {
|
||||
hapd->disabled = 0;
|
||||
/*
|
||||
* Try to re-enable interface if the driver stopped it
|
||||
* when the interface got disabled.
|
||||
*/
|
||||
if (hapd->wpa_auth)
|
||||
wpa_auth_reconfig_group_keys(hapd->wpa_auth);
|
||||
else
|
||||
hostapd_reconfig_encryption(hapd);
|
||||
hapd->reenable_beacon = 1;
|
||||
ieee802_11_set_beacon(hapd);
|
||||
#ifdef NEED_AP_MLME
|
||||
} else if (hapd->disabled && hapd->iface->cac_started) {
|
||||
wpa_printf(MSG_DEBUG, "DFS: restarting pending CAC");
|
||||
hostapd_handle_dfs(hapd->iface);
|
||||
#endif /* NEED_AP_MLME */
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
static void hostapd_iface_disable(struct hostapd_data *hapd)
|
||||
{
|
||||
hostapd_free_stas(hapd);
|
||||
wpa_msg(hapd->msg_ctx, MSG_INFO, INTERFACE_DISABLED);
|
||||
hapd->disabled = 1;
|
||||
}
|
||||
|
||||
|
||||
#ifdef CONFIG_IEEE80211BE
|
||||
|
||||
static void hostapd_mld_iface_enable(struct hostapd_data *hapd)
|
||||
{
|
||||
struct hostapd_data *first_link, *link_bss;
|
||||
|
||||
first_link = hostapd_mld_is_first_bss(hapd) ? hapd :
|
||||
hostapd_mld_get_first_bss(hapd);
|
||||
|
||||
/* Links have been removed. Re-add all links and enable them, but
|
||||
* enable the first link BSS before doing that. */
|
||||
if (hostapd_drv_link_add(first_link, first_link->mld_link_id,
|
||||
first_link->own_addr)) {
|
||||
wpa_printf(MSG_ERROR, "MLD: Failed to re-add link %d in MLD %s",
|
||||
first_link->mld_link_id, first_link->conf->iface);
|
||||
return;
|
||||
}
|
||||
|
||||
hostapd_iface_enable(first_link);
|
||||
|
||||
/* Add other affiliated links */
|
||||
for_each_mld_link(link_bss, first_link) {
|
||||
if (link_bss == first_link)
|
||||
continue;
|
||||
|
||||
if (hostapd_drv_link_add(link_bss, link_bss->mld_link_id,
|
||||
link_bss->own_addr)) {
|
||||
wpa_printf(MSG_ERROR,
|
||||
"MLD: Failed to re-add link %d in MLD %s",
|
||||
link_bss->mld_link_id,
|
||||
link_bss->conf->iface);
|
||||
continue;
|
||||
}
|
||||
|
||||
hostapd_iface_enable(link_bss);
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
static void hostapd_mld_iface_disable(struct hostapd_data *hapd)
|
||||
{
|
||||
struct hostapd_data *link_bss;
|
||||
|
||||
for_each_mld_link(link_bss, hapd)
|
||||
hostapd_iface_disable(link_bss);
|
||||
}
|
||||
|
||||
#endif /* CONFIG_IEEE80211BE */
|
||||
|
||||
|
||||
void wpa_supplicant_event(void *ctx, enum wpa_event_type event,
|
||||
union wpa_event_data *data)
|
||||
{
|
||||
|
@ -2289,8 +2546,29 @@ void wpa_supplicant_event(void *ctx, enum wpa_event_type event,
|
|||
michael_mic_failure(hapd, data->michael_mic_failure.src, 1);
|
||||
break;
|
||||
case EVENT_SCAN_RESULTS:
|
||||
#ifdef NEED_AP_MLME
|
||||
if (data)
|
||||
hapd = switch_link_scan(hapd,
|
||||
data->scan_info.scan_cookie);
|
||||
#endif /* NEED_AP_MLME */
|
||||
if (hapd->iface->scan_cb)
|
||||
hapd->iface->scan_cb(hapd->iface);
|
||||
#ifdef CONFIG_IEEE80211BE
|
||||
if (!hapd->iface->scan_cb && hapd->conf->mld_ap) {
|
||||
/* Other links may be waiting for HT scan result */
|
||||
unsigned int i;
|
||||
|
||||
for (i = 0; i < hapd->iface->interfaces->count; i++) {
|
||||
struct hostapd_iface *h =
|
||||
hapd->iface->interfaces->iface[i];
|
||||
struct hostapd_data *h_hapd = h->bss[0];
|
||||
|
||||
if (hostapd_is_ml_partner(hapd, h_hapd) &&
|
||||
h_hapd->iface->scan_cb)
|
||||
h_hapd->iface->scan_cb(h_hapd->iface);
|
||||
}
|
||||
}
|
||||
#endif /* CONFIG_IEEE80211BE */
|
||||
break;
|
||||
case EVENT_WPS_BUTTON_PUSHED:
|
||||
hostapd_wps_button_pushed(hapd, NULL);
|
||||
|
@ -2314,11 +2592,11 @@ void wpa_supplicant_event(void *ctx, enum wpa_event_type event,
|
|||
}
|
||||
break;
|
||||
case EVENT_EAPOL_TX_STATUS:
|
||||
hapd = switch_link_hapd(hapd, data->eapol_tx_status.link_id);
|
||||
hostapd_eapol_tx_status(hapd, data->eapol_tx_status.dst,
|
||||
data->eapol_tx_status.data,
|
||||
data->eapol_tx_status.data_len,
|
||||
data->eapol_tx_status.ack);
|
||||
data->eapol_tx_status.ack,
|
||||
data->eapol_tx_status.link_id);
|
||||
break;
|
||||
case EVENT_DRIVER_CLIENT_POLL_OK:
|
||||
hostapd_client_poll_ok(hapd, data->client_poll.addr);
|
||||
|
@ -2513,30 +2791,22 @@ void wpa_supplicant_event(void *ctx, enum wpa_event_type event,
|
|||
break;
|
||||
#endif /* NEED_AP_MLME */
|
||||
case EVENT_INTERFACE_ENABLED:
|
||||
wpa_msg(hapd->msg_ctx, MSG_INFO, INTERFACE_ENABLED);
|
||||
if (hapd->disabled && hapd->started) {
|
||||
hapd->disabled = 0;
|
||||
/*
|
||||
* Try to re-enable interface if the driver stopped it
|
||||
* when the interface got disabled.
|
||||
*/
|
||||
if (hapd->wpa_auth)
|
||||
wpa_auth_reconfig_group_keys(hapd->wpa_auth);
|
||||
else
|
||||
hostapd_reconfig_encryption(hapd);
|
||||
hapd->reenable_beacon = 1;
|
||||
ieee802_11_set_beacon(hapd);
|
||||
#ifdef NEED_AP_MLME
|
||||
} else if (hapd->disabled && hapd->iface->cac_started) {
|
||||
wpa_printf(MSG_DEBUG, "DFS: restarting pending CAC");
|
||||
hostapd_handle_dfs(hapd->iface);
|
||||
#endif /* NEED_AP_MLME */
|
||||
#ifdef CONFIG_IEEE80211BE
|
||||
if (hapd->conf->mld_ap) {
|
||||
hostapd_mld_iface_enable(hapd);
|
||||
break;
|
||||
}
|
||||
#endif /* CONFIG_IEEE80211BE */
|
||||
hostapd_iface_enable(hapd);
|
||||
break;
|
||||
case EVENT_INTERFACE_DISABLED:
|
||||
hostapd_free_stas(hapd);
|
||||
wpa_msg(hapd->msg_ctx, MSG_INFO, INTERFACE_DISABLED);
|
||||
hapd->disabled = 1;
|
||||
#ifdef CONFIG_IEEE80211BE
|
||||
if (hapd->conf->mld_ap) {
|
||||
hostapd_mld_iface_disable(hapd);
|
||||
break;
|
||||
}
|
||||
#endif /* CONFIG_IEEE80211BE */
|
||||
hostapd_iface_disable(hapd);
|
||||
break;
|
||||
#ifdef CONFIG_ACS
|
||||
case EVENT_ACS_CHANNEL_SELECTED:
|
||||
|
@ -2561,28 +2831,41 @@ void wpa_supplicant_event(void *ctx, enum wpa_event_type event,
|
|||
/* The BSS color is shared amongst all BBSs on a specific phy.
|
||||
* Therefore we always start the color change on the primary
|
||||
* BSS. */
|
||||
hapd = switch_link_hapd(hapd,
|
||||
data->bss_color_collision.link_id);
|
||||
wpa_printf(MSG_DEBUG, "BSS color collision on %s",
|
||||
hapd->conf->iface);
|
||||
hostapd_switch_color(hapd->iface->bss[0],
|
||||
data->bss_color_collision.bitmap);
|
||||
break;
|
||||
case EVENT_CCA_STARTED_NOTIFY:
|
||||
wpa_printf(MSG_DEBUG, "CCA started on on %s",
|
||||
hapd = switch_link_hapd(hapd,
|
||||
data->bss_color_collision.link_id);
|
||||
wpa_printf(MSG_DEBUG, "CCA started on %s",
|
||||
hapd->conf->iface);
|
||||
break;
|
||||
case EVENT_CCA_ABORTED_NOTIFY:
|
||||
wpa_printf(MSG_DEBUG, "CCA aborted on on %s",
|
||||
hapd = switch_link_hapd(hapd,
|
||||
data->bss_color_collision.link_id);
|
||||
wpa_printf(MSG_DEBUG, "CCA aborted on %s",
|
||||
hapd->conf->iface);
|
||||
hostapd_cleanup_cca_params(hapd);
|
||||
hostapd_event_color_change(hapd, false);
|
||||
break;
|
||||
case EVENT_CCA_NOTIFY:
|
||||
wpa_printf(MSG_DEBUG, "CCA finished on on %s",
|
||||
hapd = switch_link_hapd(hapd,
|
||||
data->bss_color_collision.link_id);
|
||||
wpa_printf(MSG_DEBUG, "CCA finished on %s",
|
||||
hapd->conf->iface);
|
||||
if (hapd->cca_color)
|
||||
hapd->iface->conf->he_op.he_bss_color = hapd->cca_color;
|
||||
hostapd_cleanup_cca_params(hapd);
|
||||
hostapd_event_color_change(hapd, true);
|
||||
break;
|
||||
#endif /* CONFIG_IEEE80211AX */
|
||||
#ifdef CONFIG_IEEE80211BE
|
||||
case EVENT_MLD_INTERFACE_FREED:
|
||||
wpa_printf(MSG_DEBUG, "MLD: Interface %s freed",
|
||||
hapd->conf->iface);
|
||||
hostapd_mld_interface_freed(hapd);
|
||||
break;
|
||||
#endif /* CONFIG_IEEE80211BE */
|
||||
default:
|
||||
wpa_printf(MSG_DEBUG, "Unknown event %d", event);
|
||||
break;
|
||||
|
|
852
src/ap/hostapd.c
852
src/ap/hostapd.c
File diff suppressed because it is too large
Load diff
127
src/ap/hostapd.h
127
src/ap/hostapd.h
|
@ -44,6 +44,7 @@ struct mesh_conf;
|
|||
#endif /* CONFIG_CTRL_IFACE_UDP */
|
||||
|
||||
struct hostapd_iface;
|
||||
struct hostapd_mld;
|
||||
|
||||
struct hapd_interfaces {
|
||||
int (*reload_config)(struct hostapd_iface *iface);
|
||||
|
@ -93,6 +94,12 @@ struct hapd_interfaces {
|
|||
unsigned char ctrl_iface_cookie[CTRL_IFACE_COOKIE_LEN];
|
||||
#endif /* CONFIG_CTRL_IFACE_UDP */
|
||||
|
||||
#ifdef CONFIG_IEEE80211BE
|
||||
struct hostapd_mld **mld;
|
||||
size_t mld_count;
|
||||
int (*mld_ctrl_iface_init)(struct hostapd_mld *mld);
|
||||
void (*mld_ctrl_iface_deinit)(struct hostapd_mld *mld);
|
||||
#endif /* CONFIG_IEEE80211BE */
|
||||
};
|
||||
|
||||
enum hostapd_chan_status {
|
||||
|
@ -162,6 +169,21 @@ struct hostapd_sae_commit_queue {
|
|||
u8 msg[];
|
||||
};
|
||||
|
||||
struct mld_link_info {
|
||||
u8 valid:1;
|
||||
u8 nstr_bitmap_len:2;
|
||||
u8 local_addr[ETH_ALEN];
|
||||
u8 peer_addr[ETH_ALEN];
|
||||
|
||||
u8 nstr_bitmap[2];
|
||||
|
||||
u16 capability;
|
||||
|
||||
u16 status;
|
||||
u16 resp_sta_profile_len;
|
||||
u8 *resp_sta_profile;
|
||||
};
|
||||
|
||||
/**
|
||||
* struct hostapd_data - hostapd per-BSS data structure
|
||||
*/
|
||||
|
@ -175,12 +197,6 @@ struct hostapd_data {
|
|||
unsigned int reenable_beacon:1;
|
||||
|
||||
u8 own_addr[ETH_ALEN];
|
||||
u8 mld_addr[ETH_ALEN];
|
||||
u8 mld_link_id;
|
||||
/* Used for mld_link_id assignment - valid on the first MLD BSS only */
|
||||
u8 mld_next_link_id;
|
||||
|
||||
struct hostapd_data *mld_first_bss;
|
||||
|
||||
int num_sta; /* number of entries in sta_list */
|
||||
struct sta_info *sta_list; /* STA info list head */
|
||||
|
@ -293,7 +309,8 @@ struct hostapd_data {
|
|||
void *wps_event_cb_ctx;
|
||||
|
||||
void (*sta_authorized_cb)(void *ctx, const u8 *mac_addr,
|
||||
int authorized, const u8 *p2p_dev_addr);
|
||||
int authorized, const u8 *p2p_dev_addr,
|
||||
const u8 *ip);
|
||||
void *sta_authorized_cb_ctx;
|
||||
|
||||
void (*setup_complete_cb)(void *ctx);
|
||||
|
@ -405,8 +422,10 @@ struct hostapd_data {
|
|||
u8 beacon_req_token;
|
||||
u8 lci_req_token;
|
||||
u8 range_req_token;
|
||||
u8 link_measurement_req_token;
|
||||
unsigned int lci_req_active:1;
|
||||
unsigned int range_req_active:1;
|
||||
unsigned int link_mesr_req_active:1;
|
||||
|
||||
int dhcp_sock; /* UDP socket used with the DHCP server */
|
||||
|
||||
|
@ -471,6 +490,17 @@ struct hostapd_data {
|
|||
|
||||
#ifdef CONFIG_IEEE80211BE
|
||||
u8 eht_mld_bss_param_change;
|
||||
struct hostapd_mld *mld;
|
||||
struct dl_list link;
|
||||
u8 mld_link_id;
|
||||
|
||||
/* Cached partner info for ML probe response */
|
||||
struct mld_link_info partner_links[MAX_NUM_MLD_LINKS];
|
||||
|
||||
/* 5 characters for "_link", up to 2 characters for <link ID>, so in
|
||||
* total, additional 7 characters required. */
|
||||
char ctrl_sock_iface[IFNAMSIZ + 7 + 1];
|
||||
|
||||
#ifdef CONFIG_TESTING_OPTIONS
|
||||
u8 eht_mld_link_removal_count;
|
||||
#endif /* CONFIG_TESTING_OPTIONS */
|
||||
|
@ -479,6 +509,9 @@ struct hostapd_data {
|
|||
#ifdef CONFIG_NAN_USD
|
||||
struct nan_de *nan_de;
|
||||
#endif /* CONFIG_NAN_USD */
|
||||
|
||||
u64 scan_cookie; /* Scan instance identifier for the ongoing HT40 scan
|
||||
*/
|
||||
};
|
||||
|
||||
|
||||
|
@ -492,6 +525,33 @@ struct hostapd_sta_info {
|
|||
#endif /* CONFIG_TAXONOMY */
|
||||
};
|
||||
|
||||
#ifdef CONFIG_IEEE80211BE
|
||||
/**
|
||||
* struct hostapd_mld - hostapd per-mld data structure
|
||||
*/
|
||||
struct hostapd_mld {
|
||||
char name[IFNAMSIZ + 1];
|
||||
u8 mld_addr[ETH_ALEN];
|
||||
u8 next_link_id;
|
||||
u8 num_links;
|
||||
/* Number of hostapd_data (hapd) referencing this. num_links cannot be
|
||||
* used since num_links can go to 0 even when a BSS is disabled and
|
||||
* when it is re-enabled, the MLD should exist and hence it cannot be
|
||||
* freed when num_links is 0.
|
||||
*/
|
||||
u8 refcount;
|
||||
|
||||
struct hostapd_data *fbss;
|
||||
struct dl_list links; /* List head of all affiliated links */
|
||||
|
||||
int ctrl_sock;
|
||||
struct dl_list ctrl_dst;
|
||||
char *ctrl_interface; /* Directory for UNIX domain sockets */
|
||||
};
|
||||
|
||||
#define HOSTAPD_MLD_MAX_REF_COUNT 0xFF
|
||||
#endif /* CONFIG_IEEE80211BE */
|
||||
|
||||
/**
|
||||
* struct hostapd_iface - hostapd per-interface data structure
|
||||
*/
|
||||
|
@ -548,6 +608,7 @@ struct hostapd_iface {
|
|||
|
||||
u64 drv_flags;
|
||||
u64 drv_flags2;
|
||||
unsigned int drv_rrm_flags;
|
||||
|
||||
/*
|
||||
* A bitmap of supported protocols for probe response offload. See
|
||||
|
@ -573,6 +634,8 @@ struct hostapd_iface {
|
|||
int *basic_rates;
|
||||
int freq;
|
||||
|
||||
bool radar_detected;
|
||||
|
||||
/* Background radar configuration */
|
||||
struct {
|
||||
int channel;
|
||||
|
@ -648,6 +711,7 @@ struct hostapd_iface {
|
|||
|
||||
#ifdef CONFIG_ACS
|
||||
unsigned int acs_num_completed_scans;
|
||||
unsigned int acs_num_retries;
|
||||
#endif /* CONFIG_ACS */
|
||||
|
||||
void (*scan_cb)(struct hostapd_iface *iface);
|
||||
|
@ -674,6 +738,12 @@ struct hostapd_iface {
|
|||
|
||||
/* Configured freq of interface is NO_IR */
|
||||
bool is_no_ir;
|
||||
|
||||
bool is_ch_switch_dfs; /* Channel switch from ACS to DFS */
|
||||
|
||||
struct hostapd_multi_hw_info *multi_hw_info;
|
||||
unsigned int num_multi_hws;
|
||||
struct hostapd_multi_hw_info *current_hw_info;
|
||||
};
|
||||
|
||||
/* hostapd.c */
|
||||
|
@ -716,6 +786,8 @@ void hostapd_chan_switch_config(struct hostapd_data *hapd,
|
|||
struct hostapd_freq_params *freq_params);
|
||||
int hostapd_switch_channel(struct hostapd_data *hapd,
|
||||
struct csa_settings *settings);
|
||||
int hostapd_force_channel_switch(struct hostapd_iface *iface,
|
||||
struct csa_settings settings);
|
||||
void
|
||||
hostapd_switch_channel_fallback(struct hostapd_iface *iface,
|
||||
const struct hostapd_freq_params *freq_params);
|
||||
|
@ -780,24 +852,37 @@ int hostapd_mbssid_get_bss_index(struct hostapd_data *hapd);
|
|||
struct hostapd_data * hostapd_mld_get_link_bss(struct hostapd_data *hapd,
|
||||
u8 link_id);
|
||||
int hostapd_link_remove(struct hostapd_data *hapd, u32 count);
|
||||
bool hostapd_is_ml_partner(struct hostapd_data *hapd1,
|
||||
struct hostapd_data *hapd2);
|
||||
u8 hostapd_get_mld_id(struct hostapd_data *hapd);
|
||||
int hostapd_mld_add_link(struct hostapd_data *hapd);
|
||||
int hostapd_mld_remove_link(struct hostapd_data *hapd);
|
||||
struct hostapd_data * hostapd_mld_get_first_bss(struct hostapd_data *hapd);
|
||||
|
||||
void free_beacon_data(struct beacon_data *beacon);
|
||||
int hostapd_fill_cca_settings(struct hostapd_data *hapd,
|
||||
struct cca_settings *settings);
|
||||
|
||||
#ifdef CONFIG_IEEE80211BE
|
||||
#define for_each_mld_link(_link, _bss_idx, _iface_idx, _ifaces, _mld_id) \
|
||||
for (_iface_idx = 0; \
|
||||
_iface_idx < (_ifaces)->count; \
|
||||
_iface_idx++) \
|
||||
for (_bss_idx = 0; \
|
||||
_bss_idx < \
|
||||
(_ifaces)->iface[_iface_idx]->num_bss; \
|
||||
_bss_idx++) \
|
||||
for (_link = \
|
||||
(_ifaces)->iface[_iface_idx]->bss[_bss_idx]; \
|
||||
_link && _link->conf->mld_ap && \
|
||||
_link->conf->mld_id == _mld_id; \
|
||||
_link = NULL)
|
||||
|
||||
bool hostapd_mld_is_first_bss(struct hostapd_data *hapd);
|
||||
void hostapd_mld_interface_freed(struct hostapd_data *hapd);
|
||||
|
||||
#define for_each_mld_link(partner, self) \
|
||||
dl_list_for_each(partner, &self->mld->links, struct hostapd_data, link)
|
||||
|
||||
#else /* CONFIG_IEEE80211BE */
|
||||
#define for_each_mld_link(_link, _bss_idx, _iface_idx, _ifaces, _mld_id) \
|
||||
|
||||
static inline bool hostapd_mld_is_first_bss(struct hostapd_data *hapd)
|
||||
{
|
||||
return true;
|
||||
}
|
||||
|
||||
#define for_each_mld_link(partner, self) \
|
||||
if (false)
|
||||
|
||||
#endif /* CONFIG_IEEE80211BE */
|
||||
|
||||
u16 hostapd_get_punct_bitmap(struct hostapd_data *hapd);
|
||||
|
||||
#endif /* HOSTAPD_H */
|
||||
|
|
|
@ -76,12 +76,15 @@ int hostapd_get_hw_features(struct hostapd_iface *iface)
|
|||
{
|
||||
struct hostapd_data *hapd = iface->bss[0];
|
||||
int i, j;
|
||||
unsigned int k;
|
||||
u16 num_modes, flags;
|
||||
struct hostapd_hw_modes *modes;
|
||||
u8 dfs_domain;
|
||||
enum hostapd_hw_mode mode = HOSTAPD_MODE_IEEE80211ANY;
|
||||
bool is_6ghz = false;
|
||||
bool orig_mode_valid = false;
|
||||
struct hostapd_multi_hw_info *multi_hw_info;
|
||||
unsigned int num_multi_hws;
|
||||
|
||||
if (hostapd_drv_none(hapd))
|
||||
return -1;
|
||||
|
@ -107,9 +110,7 @@ int hostapd_get_hw_features(struct hostapd_iface *iface)
|
|||
*/
|
||||
orig_mode_valid = true;
|
||||
mode = iface->current_mode->mode;
|
||||
is_6ghz = mode == HOSTAPD_MODE_IEEE80211A &&
|
||||
iface->current_mode->num_channels > 0 &&
|
||||
is_6ghz_freq(iface->current_mode->channels[0].freq);
|
||||
is_6ghz = iface->current_mode->is_6ghz;
|
||||
iface->current_mode = NULL;
|
||||
}
|
||||
hostapd_free_hw_features(iface->hw_features, iface->num_hw_features);
|
||||
|
@ -170,6 +171,25 @@ int hostapd_get_hw_features(struct hostapd_iface *iface)
|
|||
__func__);
|
||||
}
|
||||
|
||||
multi_hw_info = hostapd_get_multi_hw_info(hapd, &num_multi_hws);
|
||||
if (!multi_hw_info)
|
||||
return 0;
|
||||
|
||||
hostapd_free_multi_hw_info(iface->multi_hw_info);
|
||||
iface->multi_hw_info = multi_hw_info;
|
||||
iface->num_multi_hws = num_multi_hws;
|
||||
|
||||
wpa_printf(MSG_DEBUG, "Multiple underlying hardwares info:");
|
||||
|
||||
for (k = 0; k < num_multi_hws; k++) {
|
||||
struct hostapd_multi_hw_info *hw_info = &multi_hw_info[k];
|
||||
|
||||
wpa_printf(MSG_DEBUG,
|
||||
" %d. hw_idx=%u, frequency range: %d-%d MHz",
|
||||
k + 1, hw_info->hw_idx, hw_info->start_freq,
|
||||
hw_info->end_freq);
|
||||
}
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
|
@ -508,6 +528,12 @@ static void ap_ht40_scan_retry(void *eloop_data, void *user_data)
|
|||
else
|
||||
ieee80211n_scan_channels_5g(iface, ¶ms);
|
||||
|
||||
params.link_id = -1;
|
||||
#ifdef CONFIG_IEEE80211BE
|
||||
if (iface->bss[0]->conf->mld_ap)
|
||||
params.link_id = iface->bss[0]->mld_link_id;
|
||||
#endif /* CONFIG_IEEE80211BE */
|
||||
|
||||
ret = hostapd_driver_scan(iface->bss[0], ¶ms);
|
||||
iface->num_ht40_scan_tries++;
|
||||
os_free(params.freqs);
|
||||
|
@ -523,6 +549,7 @@ static void ap_ht40_scan_retry(void *eloop_data, void *user_data)
|
|||
|
||||
if (ret == 0) {
|
||||
iface->scan_cb = ieee80211n_check_scan;
|
||||
iface->bss[0]->scan_cookie = params.scan_cookie;
|
||||
return;
|
||||
}
|
||||
|
||||
|
@ -558,6 +585,11 @@ static int ieee80211n_check_40mhz(struct hostapd_iface *iface)
|
|||
else
|
||||
ieee80211n_scan_channels_5g(iface, ¶ms);
|
||||
|
||||
params.link_id = -1;
|
||||
#ifdef CONFIG_IEEE80211BE
|
||||
if (iface->bss[0]->conf->mld_ap)
|
||||
params.link_id = iface->bss[0]->mld_link_id;
|
||||
#endif /* CONFIG_IEEE80211BE */
|
||||
ret = hostapd_driver_scan(iface->bss[0], ¶ms);
|
||||
os_free(params.freqs);
|
||||
|
||||
|
@ -579,6 +611,7 @@ static int ieee80211n_check_40mhz(struct hostapd_iface *iface)
|
|||
}
|
||||
|
||||
iface->scan_cb = ieee80211n_check_scan;
|
||||
iface->bss[0]->scan_cookie = params.scan_cookie;
|
||||
return 1;
|
||||
}
|
||||
|
||||
|
@ -1070,9 +1103,7 @@ static bool skip_mode(struct hostapd_iface *iface,
|
|||
return true;
|
||||
|
||||
if (is_6ghz_op_class(iface->conf->op_class) && iface->freq == 0 &&
|
||||
(mode->mode != HOSTAPD_MODE_IEEE80211A ||
|
||||
mode->num_channels == 0 ||
|
||||
!is_6ghz_freq(mode->channels[0].freq)))
|
||||
!mode->is_6ghz)
|
||||
return true;
|
||||
|
||||
return false;
|
||||
|
@ -1382,3 +1413,34 @@ int hostapd_hw_skip_mode(struct hostapd_iface *iface,
|
|||
}
|
||||
return 0;
|
||||
}
|
||||
|
||||
|
||||
void hostapd_free_multi_hw_info(struct hostapd_multi_hw_info *multi_hw_info)
|
||||
{
|
||||
os_free(multi_hw_info);
|
||||
}
|
||||
|
||||
|
||||
int hostapd_set_current_hw_info(struct hostapd_iface *iface, int oper_freq)
|
||||
{
|
||||
struct hostapd_multi_hw_info *hw_info;
|
||||
unsigned int i;
|
||||
|
||||
if (!iface->num_multi_hws)
|
||||
return 0;
|
||||
|
||||
for (i = 0; i < iface->num_multi_hws; i++) {
|
||||
hw_info = &iface->multi_hw_info[i];
|
||||
|
||||
if (hw_info->start_freq <= oper_freq &&
|
||||
hw_info->end_freq >= oper_freq) {
|
||||
iface->current_hw_info = hw_info;
|
||||
wpa_printf(MSG_DEBUG,
|
||||
"Mode: Selected underlying hardware: hw_idx=%u",
|
||||
iface->current_hw_info->hw_idx);
|
||||
return 0;
|
||||
}
|
||||
}
|
||||
|
||||
return -1;
|
||||
}
|
||||
|
|
|
@ -30,6 +30,8 @@ void hostapd_stop_setup_timers(struct hostapd_iface *iface);
|
|||
int hostapd_hw_skip_mode(struct hostapd_iface *iface,
|
||||
struct hostapd_hw_modes *mode);
|
||||
int hostapd_determine_mode(struct hostapd_iface *iface);
|
||||
void hostapd_free_multi_hw_info(struct hostapd_multi_hw_info *multi_hw_info);
|
||||
int hostapd_set_current_hw_info(struct hostapd_iface *iface, int oper_freq);
|
||||
#else /* NEED_AP_MLME */
|
||||
static inline void
|
||||
hostapd_free_hw_features(struct hostapd_hw_modes *hw_features,
|
||||
|
@ -103,6 +105,16 @@ static inline int hostapd_determine_mode(struct hostapd_iface *iface)
|
|||
return 0;
|
||||
}
|
||||
|
||||
static inline
|
||||
void hostapd_free_multi_hw_info(struct hostapd_multi_hw_info *multi_hw_info)
|
||||
{
|
||||
}
|
||||
|
||||
static inline int hostapd_set_current_hw_info(struct hostapd_iface *iface,
|
||||
u32 oper_freq)
|
||||
{
|
||||
return 0;
|
||||
}
|
||||
#endif /* NEED_AP_MLME */
|
||||
|
||||
#endif /* HW_FEATURES_H */
|
||||
|
|
1256
src/ap/ieee802_11.c
1256
src/ap/ieee802_11.c
File diff suppressed because it is too large
Load diff
|
@ -63,7 +63,7 @@ u8 * hostapd_eid_ht_operation(struct hostapd_data *hapd, u8 *eid);
|
|||
u8 * hostapd_eid_vht_capabilities(struct hostapd_data *hapd, u8 *eid, u32 nsts);
|
||||
u8 * hostapd_eid_vht_operation(struct hostapd_data *hapd, u8 *eid);
|
||||
u8 * hostapd_eid_vendor_vht(struct hostapd_data *hapd, u8 *eid);
|
||||
u8 * hostapd_eid_wb_chsw_wrapper(struct hostapd_data *hapd, u8 *eid);
|
||||
u8 * hostapd_eid_chsw_wrapper(struct hostapd_data *hapd, u8 *eid);
|
||||
u8 * hostapd_eid_txpower_envelope(struct hostapd_data *hapd, u8 *eid);
|
||||
u8 * hostapd_eid_he_capab(struct hostapd_data *hapd, u8 *eid,
|
||||
enum ieee80211_op_mode opmode);
|
||||
|
@ -129,11 +129,10 @@ u16 copy_sta_he_6ghz_capab(struct hostapd_data *hapd, struct sta_info *sta,
|
|||
const u8 *he_6ghz_capab);
|
||||
int hostapd_get_he_twt_responder(struct hostapd_data *hapd,
|
||||
enum ieee80211_op_mode mode);
|
||||
bool hostapd_get_ht_vht_twt_responder(struct hostapd_data *hapd);
|
||||
u8 * hostapd_eid_cca(struct hostapd_data *hapd, u8 *eid);
|
||||
void hostapd_tx_status(struct hostapd_data *hapd, const u8 *addr,
|
||||
const u8 *buf, size_t len, int ack);
|
||||
void hostapd_eapol_tx_status(struct hostapd_data *hapd, const u8 *dst,
|
||||
const u8 *data, size_t len, int ack);
|
||||
void ieee802_11_rx_from_unknown(struct hostapd_data *hapd, const u8 *src,
|
||||
int wds);
|
||||
u8 * hostapd_eid_assoc_comeback_time(struct hostapd_data *hapd,
|
||||
|
@ -148,7 +147,8 @@ u8 * hostapd_eid_time_adv(struct hostapd_data *hapd, u8 *eid);
|
|||
u8 * hostapd_eid_time_zone(struct hostapd_data *hapd, u8 *eid);
|
||||
int hostapd_update_time_adv(struct hostapd_data *hapd);
|
||||
void hostapd_client_poll_ok(struct hostapd_data *hapd, const u8 *addr);
|
||||
u8 * hostapd_eid_bss_max_idle_period(struct hostapd_data *hapd, u8 *eid);
|
||||
u8 * hostapd_eid_bss_max_idle_period(struct hostapd_data *hapd, u8 *eid,
|
||||
u16 value);
|
||||
|
||||
int auth_sae_init_committed(struct hostapd_data *hapd, struct sta_info *sta);
|
||||
#ifdef CONFIG_SAE
|
||||
|
@ -227,8 +227,10 @@ void auth_sae_process_commit(void *eloop_ctx, void *user_ctx);
|
|||
u8 * hostapd_eid_rsnxe(struct hostapd_data *hapd, u8 *eid, size_t len);
|
||||
u16 check_ext_capab(struct hostapd_data *hapd, struct sta_info *sta,
|
||||
const u8 *ext_capab_ie, size_t ext_capab_ie_len);
|
||||
size_t hostapd_eid_rnr_len(struct hostapd_data *hapd, u32 type);
|
||||
u8 * hostapd_eid_rnr(struct hostapd_data *hapd, u8 *eid, u32 type);
|
||||
size_t hostapd_eid_rnr_len(struct hostapd_data *hapd, u32 type,
|
||||
bool include_mld_params);
|
||||
u8 * hostapd_eid_rnr(struct hostapd_data *hapd, u8 *eid, u32 type,
|
||||
bool include_mld_params);
|
||||
int ieee802_11_set_radius_info(struct hostapd_data *hapd, struct sta_info *sta,
|
||||
int res, struct radius_sta *info);
|
||||
size_t hostapd_eid_eht_capab_len(struct hostapd_data *hapd,
|
||||
|
@ -248,8 +250,6 @@ u8 * hostapd_eid_mbssid(struct hostapd_data *hapd, u8 *eid, u8 *end,
|
|||
u8 **elem_offset,
|
||||
const u8 *known_bss, size_t known_bss_len, u8 *rnr_eid,
|
||||
u8 *rnr_count, u8 **rnr_offset, size_t rnr_len);
|
||||
void punct_update_legacy_bw(u16 bitmap, u8 pri_chan,
|
||||
enum oper_chan_width *width, u8 *seg0, u8 *seg1);
|
||||
bool hostapd_is_mld_ap(struct hostapd_data *hapd);
|
||||
const char * sae_get_password(struct hostapd_data *hapd,
|
||||
struct sta_info *sta, const char *rx_id,
|
||||
|
|
|
@ -128,6 +128,9 @@ static int hostapd_radius_acl_query(struct hostapd_data *hapd, const u8 *addr,
|
|||
goto fail;
|
||||
}
|
||||
|
||||
if (!radius_msg_add_msg_auth(msg))
|
||||
goto fail;
|
||||
|
||||
os_snprintf(buf, sizeof(buf), RADIUS_ADDR_FORMAT, MAC2STR(addr));
|
||||
if (!radius_msg_add_attr(msg, RADIUS_ATTR_USER_NAME, (u8 *) buf,
|
||||
os_strlen(buf))) {
|
||||
|
@ -505,7 +508,9 @@ hostapd_acl_recv_radius(struct radius_msg *msg, struct radius_msg *req,
|
|||
"Found matching Access-Request for RADIUS message (id=%d)",
|
||||
query->radius_id);
|
||||
|
||||
if (radius_msg_verify(msg, shared_secret, shared_secret_len, req, 0)) {
|
||||
if (radius_msg_verify(
|
||||
msg, shared_secret, shared_secret_len, req,
|
||||
hapd->conf->radius_require_message_authenticator)) {
|
||||
wpa_printf(MSG_INFO,
|
||||
"Incoming RADIUS packet did not have correct authenticator - dropped");
|
||||
return RADIUS_RX_INVALID_AUTHENTICATOR;
|
||||
|
@ -596,7 +601,8 @@ hostapd_acl_recv_radius(struct radius_msg *msg, struct radius_msg *req,
|
|||
|
||||
if (query->radius_psk) {
|
||||
struct sta_info *sta;
|
||||
bool success = cache->accepted == HOSTAPD_ACL_ACCEPT;
|
||||
bool success = cache->accepted == HOSTAPD_ACL_ACCEPT ||
|
||||
cache->accepted == HOSTAPD_ACL_ACCEPT_TIMEOUT;
|
||||
|
||||
sta = ap_get_sta(hapd, query->addr);
|
||||
if (!sta || !sta->wpa_sm) {
|
||||
|
|
|
@ -206,19 +206,11 @@ u8 * hostapd_eid_eht_operation(struct hostapd_data *hapd, u8 *eid)
|
|||
enum oper_chan_width chwidth;
|
||||
size_t elen = 1 + 4;
|
||||
bool eht_oper_info_present;
|
||||
u16 punct_bitmap = conf->punct_bitmap;
|
||||
u16 punct_bitmap = hostapd_get_punct_bitmap(hapd);
|
||||
|
||||
if (!hapd->iface->current_mode)
|
||||
return eid;
|
||||
|
||||
#ifdef CONFIG_TESTING_OPTIONS
|
||||
if (!punct_bitmap && hapd->conf->eht_oper_puncturing_override) {
|
||||
wpa_printf(MSG_DEBUG, "EHT: Puncturing mask override=0x%x",
|
||||
hapd->conf->eht_oper_puncturing_override);
|
||||
punct_bitmap = hapd->conf->eht_oper_puncturing_override;
|
||||
}
|
||||
#endif /* CONFIG_TESTING_OPTIONS */
|
||||
|
||||
if (is_6ghz_op_class(conf->op_class))
|
||||
chwidth = op_class_to_ch_width(conf->op_class);
|
||||
else
|
||||
|
@ -458,6 +450,8 @@ static u8 * hostapd_eid_eht_basic_ml_common(struct hostapd_data *hapd,
|
|||
size_t len, slice_len;
|
||||
u8 link_id;
|
||||
u8 common_info_len;
|
||||
u16 mld_cap;
|
||||
u8 max_simul_links, active_links;
|
||||
|
||||
/*
|
||||
* As the Multi-Link element can exceed the size of 255 bytes need to
|
||||
|
@ -495,7 +489,7 @@ static u8 * hostapd_eid_eht_basic_ml_common(struct hostapd_data *hapd,
|
|||
wpabuf_put_u8(buf, common_info_len);
|
||||
|
||||
/* Own MLD MAC Address */
|
||||
wpabuf_put_data(buf, hapd->mld_addr, ETH_ALEN);
|
||||
wpabuf_put_data(buf, hapd->mld->mld_addr, ETH_ALEN);
|
||||
|
||||
/* Own Link ID */
|
||||
wpabuf_put_u8(buf, hapd->mld_link_id);
|
||||
|
@ -507,14 +501,31 @@ static u8 * hostapd_eid_eht_basic_ml_common(struct hostapd_data *hapd,
|
|||
hapd->iface->mld_eml_capa);
|
||||
wpabuf_put_le16(buf, hapd->iface->mld_eml_capa);
|
||||
|
||||
mld_cap = hapd->iface->mld_mld_capa;
|
||||
max_simul_links = mld_cap & EHT_ML_MLD_CAPA_MAX_NUM_SIM_LINKS_MASK;
|
||||
active_links = hapd->mld->num_links - 1;
|
||||
|
||||
if (active_links > max_simul_links) {
|
||||
wpa_printf(MSG_ERROR,
|
||||
"MLD: Error in max simultaneous links, advertised: 0x%x current: 0x%x",
|
||||
max_simul_links, active_links);
|
||||
active_links = max_simul_links;
|
||||
}
|
||||
|
||||
mld_cap &= ~EHT_ML_MLD_CAPA_MAX_NUM_SIM_LINKS_MASK;
|
||||
mld_cap |= active_links & EHT_ML_MLD_CAPA_MAX_NUM_SIM_LINKS_MASK;
|
||||
|
||||
/* TODO: Advertise T2LM based on driver support as well */
|
||||
mld_cap &= ~EHT_ML_MLD_CAPA_TID_TO_LINK_MAP_NEG_SUPP_MSK;
|
||||
|
||||
wpa_printf(MSG_DEBUG, "MLD: MLD Capabilities and Operations=0x%x",
|
||||
hapd->iface->mld_mld_capa);
|
||||
wpabuf_put_le16(buf, hapd->iface->mld_mld_capa);
|
||||
mld_cap);
|
||||
wpabuf_put_le16(buf, mld_cap);
|
||||
|
||||
if (include_mld_id) {
|
||||
wpa_printf(MSG_DEBUG, "MLD: AP MLD ID=0x%x",
|
||||
hapd->conf->mld_id);
|
||||
wpabuf_put_u8(buf, hapd->conf->mld_id);
|
||||
hostapd_get_mld_id(hapd));
|
||||
wpabuf_put_u8(buf, hostapd_get_mld_id(hapd));
|
||||
}
|
||||
|
||||
if (!mld_info)
|
||||
|
@ -578,7 +589,8 @@ static u8 * hostapd_eid_eht_basic_ml_common(struct hostapd_data *hapd,
|
|||
wpabuf_put_le64(buf, 0);
|
||||
|
||||
/* DTIM Info */
|
||||
wpabuf_put_le16(buf, link_bss->conf->dtim_period);
|
||||
wpabuf_put_u8(buf, 0); /* DTIM Count */
|
||||
wpabuf_put_u8(buf, link_bss->conf->dtim_period);
|
||||
|
||||
/* BSS Parameters Change Count */
|
||||
wpabuf_put_u8(buf, hapd->eht_mld_bss_param_change);
|
||||
|
@ -812,7 +824,7 @@ struct wpabuf * hostapd_ml_auth_resp(struct hostapd_data *hapd)
|
|||
wpabuf_put_u8(buf, WLAN_EID_EXT_MULTI_LINK);
|
||||
wpabuf_put_le16(buf, MULTI_LINK_CONTROL_TYPE_BASIC);
|
||||
wpabuf_put_u8(buf, ETH_ALEN + 1);
|
||||
wpabuf_put_data(buf, hapd->mld_addr, ETH_ALEN);
|
||||
wpabuf_put_data(buf, hapd->mld->mld_addr, ETH_ALEN);
|
||||
|
||||
return buf;
|
||||
}
|
||||
|
@ -859,6 +871,8 @@ sae_commit_skip_fixed_fields(const struct ieee80211_mgmt *mgmt, size_t len,
|
|||
|
||||
wpa_printf(MSG_DEBUG, "EHT: SAE scalar length is %zu", prime_len);
|
||||
|
||||
if (len - 2 < prime_len * (ec ? 3 : 2))
|
||||
goto truncated;
|
||||
/* scalar */
|
||||
pos += prime_len;
|
||||
|
||||
|
@ -870,6 +884,7 @@ sae_commit_skip_fixed_fields(const struct ieee80211_mgmt *mgmt, size_t len,
|
|||
}
|
||||
|
||||
if (pos - mgmt->u.auth.variable > (int) len) {
|
||||
truncated:
|
||||
wpa_printf(MSG_DEBUG,
|
||||
"EHT: Too short SAE commit Authentication frame");
|
||||
return NULL;
|
||||
|
@ -893,16 +908,38 @@ sae_confirm_skip_fixed_fields(struct hostapd_data *hapd,
|
|||
return pos;
|
||||
|
||||
/* send confirm integer */
|
||||
if (len < 2)
|
||||
goto truncated;
|
||||
pos += 2;
|
||||
|
||||
/*
|
||||
* At this stage we should already have an MLD station and actually SA
|
||||
* will be replaced with the MLD MAC address by the driver.
|
||||
* will be replaced with the MLD MAC address by the driver. However,
|
||||
* there is at least a theoretical race condition in a case where the
|
||||
* peer sends the SAE confirm message quickly enough for the driver
|
||||
* translation mechanism to not be available to update the SAE confirm
|
||||
* message addresses. Work around that by searching for the STA entry
|
||||
* using the link address of the non-AP MLD if no match is found based
|
||||
* on the MLD MAC address.
|
||||
*/
|
||||
sta = ap_get_sta(hapd, mgmt->sa);
|
||||
if (!sta) {
|
||||
wpa_printf(MSG_DEBUG, "SAE: No MLD STA for SAE confirm");
|
||||
return NULL;
|
||||
for (sta = hapd->sta_list; sta; sta = sta->next) {
|
||||
int link_id = hapd->mld_link_id;
|
||||
|
||||
if (!sta->mld_info.mld_sta ||
|
||||
sta->mld_info.links[link_id].valid ||
|
||||
!ether_addr_equal(
|
||||
mgmt->sa,
|
||||
sta->mld_info.links[link_id].peer_addr))
|
||||
continue;
|
||||
wpa_printf(MSG_DEBUG,
|
||||
"SAE: Found MLD STA for SAE confirm based on link address");
|
||||
break;
|
||||
}
|
||||
if (!sta)
|
||||
return NULL;
|
||||
}
|
||||
|
||||
if (!sta->sae || sta->sae->state < SAE_COMMITTED || !sta->sae->tmp) {
|
||||
|
@ -917,9 +954,12 @@ sae_confirm_skip_fixed_fields(struct hostapd_data *hapd,
|
|||
wpa_printf(MSG_DEBUG, "SAE: confirm: kck_len=%zu",
|
||||
sta->sae->tmp->kck_len);
|
||||
|
||||
if (len - 2 < sta->sae->tmp->kck_len)
|
||||
goto truncated;
|
||||
pos += sta->sae->tmp->kck_len;
|
||||
|
||||
if (pos - mgmt->u.auth.variable > (int) len) {
|
||||
truncated:
|
||||
wpa_printf(MSG_DEBUG,
|
||||
"EHT: Too short SAE confirm Authentication frame");
|
||||
return NULL;
|
||||
|
@ -1018,7 +1058,7 @@ const u8 * hostapd_process_ml_auth(struct hostapd_data *hapd,
|
|||
static int hostapd_mld_validate_assoc_info(struct hostapd_data *hapd,
|
||||
struct sta_info *sta)
|
||||
{
|
||||
u8 i, link_id;
|
||||
u8 link_id;
|
||||
struct mld_info *info = &sta->mld_info;
|
||||
|
||||
if (!ap_sta_is_mld(hapd, sta)) {
|
||||
|
@ -1038,32 +1078,18 @@ static int hostapd_mld_validate_assoc_info(struct hostapd_data *hapd,
|
|||
for (link_id = 0; link_id < MAX_NUM_MLD_LINKS; link_id++) {
|
||||
struct hostapd_data *other_hapd;
|
||||
|
||||
if (!info->links[link_id].valid)
|
||||
if (!info->links[link_id].valid || link_id == hapd->mld_link_id)
|
||||
continue;
|
||||
|
||||
for (i = 0; i < hapd->iface->interfaces->count; i++) {
|
||||
other_hapd = hapd->iface->interfaces->iface[i]->bss[0];
|
||||
|
||||
if (hapd == other_hapd)
|
||||
continue;
|
||||
|
||||
if (other_hapd->conf->mld_ap &&
|
||||
other_hapd->conf->mld_id == hapd->conf->mld_id &&
|
||||
link_id == other_hapd->mld_link_id)
|
||||
break;
|
||||
}
|
||||
|
||||
if (i == hapd->iface->interfaces->count &&
|
||||
link_id != hapd->mld_link_id) {
|
||||
other_hapd = hostapd_mld_get_link_bss(hapd, link_id);
|
||||
if (!other_hapd) {
|
||||
wpa_printf(MSG_DEBUG, "MLD: Invalid link ID=%u",
|
||||
link_id);
|
||||
return -1;
|
||||
}
|
||||
|
||||
if (i < hapd->iface->interfaces->count)
|
||||
os_memcpy(info->links[link_id].local_addr,
|
||||
other_hapd->own_addr,
|
||||
ETH_ALEN);
|
||||
os_memcpy(info->links[link_id].local_addr, other_hapd->own_addr,
|
||||
ETH_ALEN);
|
||||
}
|
||||
|
||||
return 0;
|
||||
|
|
|
@ -12,6 +12,7 @@
|
|||
#include "utils/common.h"
|
||||
#include "common/ieee802_11_defs.h"
|
||||
#include "common/ieee802_11_common.h"
|
||||
#include "common/hw_features_common.h"
|
||||
#include "hostapd.h"
|
||||
#include "ap_config.h"
|
||||
#include "beacon.h"
|
||||
|
@ -224,10 +225,11 @@ u8 * hostapd_eid_he_operation(struct hostapd_data *hapd, u8 *eid)
|
|||
u8 seg0 = hapd->iconf->he_oper_centr_freq_seg0_idx;
|
||||
u8 seg1 = hostapd_get_oper_centr_freq_seg1_idx(hapd->iconf);
|
||||
u8 control;
|
||||
|
||||
#ifdef CONFIG_IEEE80211BE
|
||||
if (hapd->iconf->punct_bitmap) {
|
||||
punct_update_legacy_bw(hapd->iconf->punct_bitmap,
|
||||
u16 punct_bitmap = hostapd_get_punct_bitmap(hapd);
|
||||
|
||||
if (punct_bitmap) {
|
||||
punct_update_legacy_bw(punct_bitmap,
|
||||
hapd->iconf->channel,
|
||||
&oper_chwidth, &seg0, &seg1);
|
||||
}
|
||||
|
|
|
@ -79,6 +79,51 @@ u8 * hostapd_eid_ht_capabilities(struct hostapd_data *hapd, u8 *eid)
|
|||
}
|
||||
|
||||
|
||||
static void set_ht_param(struct hostapd_data *hapd,
|
||||
struct ieee80211_ht_operation *oper)
|
||||
{
|
||||
int secondary_channel = hapd->iconf->secondary_channel;
|
||||
#ifdef CONFIG_IEEE80211BE
|
||||
enum oper_chan_width chwidth = hostapd_get_oper_chwidth(hapd->iconf);
|
||||
u16 bw = 0, punct_bitmap = hostapd_get_punct_bitmap(hapd);
|
||||
u8 offset, chan_bit_pos;
|
||||
|
||||
switch (chwidth) {
|
||||
case CONF_OPER_CHWIDTH_80MHZ:
|
||||
bw = 80;
|
||||
offset = 6;
|
||||
break;
|
||||
case CONF_OPER_CHWIDTH_160MHZ:
|
||||
bw = 160;
|
||||
offset = 14;
|
||||
break;
|
||||
case CONF_OPER_CHWIDTH_320MHZ:
|
||||
bw = 320;
|
||||
offset = 30;
|
||||
break;
|
||||
default:
|
||||
goto no_update;
|
||||
}
|
||||
|
||||
chan_bit_pos = (hapd->iconf->channel -
|
||||
hostapd_get_oper_centr_freq_seg0_idx(hapd->iconf) +
|
||||
offset) / 4;
|
||||
/* Check if secondary channel is punctured */
|
||||
if (bw >= 80 && punct_bitmap && secondary_channel &&
|
||||
(punct_bitmap & BIT(chan_bit_pos + secondary_channel)))
|
||||
return; /* Do not indicate punctured secondary channel for HT */
|
||||
no_update:
|
||||
#endif /* CONFIG_IEEE80211BE */
|
||||
|
||||
if (secondary_channel == 1)
|
||||
oper->ht_param |= HT_INFO_HT_PARAM_SECONDARY_CHNL_ABOVE |
|
||||
HT_INFO_HT_PARAM_STA_CHNL_WIDTH;
|
||||
if (secondary_channel == -1)
|
||||
oper->ht_param |= HT_INFO_HT_PARAM_SECONDARY_CHNL_BELOW |
|
||||
HT_INFO_HT_PARAM_STA_CHNL_WIDTH;
|
||||
}
|
||||
|
||||
|
||||
u8 * hostapd_eid_ht_operation(struct hostapd_data *hapd, u8 *eid)
|
||||
{
|
||||
struct ieee80211_ht_operation *oper;
|
||||
|
@ -96,12 +141,7 @@ u8 * hostapd_eid_ht_operation(struct hostapd_data *hapd, u8 *eid)
|
|||
|
||||
oper->primary_chan = hapd->iconf->channel;
|
||||
oper->operation_mode = host_to_le16(hapd->iface->ht_op_mode);
|
||||
if (hapd->iconf->secondary_channel == 1)
|
||||
oper->ht_param |= HT_INFO_HT_PARAM_SECONDARY_CHNL_ABOVE |
|
||||
HT_INFO_HT_PARAM_STA_CHNL_WIDTH;
|
||||
if (hapd->iconf->secondary_channel == -1)
|
||||
oper->ht_param |= HT_INFO_HT_PARAM_SECONDARY_CHNL_BELOW |
|
||||
HT_INFO_HT_PARAM_STA_CHNL_WIDTH;
|
||||
set_ht_param(hapd, oper);
|
||||
|
||||
pos += sizeof(*oper);
|
||||
|
||||
|
|
|
@ -121,7 +121,7 @@ void ieee802_11_send_sa_query_req(struct hostapd_data *hapd,
|
|||
|
||||
#ifdef CONFIG_IEEE80211BE
|
||||
if (ap_sta_is_mld(hapd, sta))
|
||||
own_addr = hapd->mld_addr;
|
||||
own_addr = hapd->mld->mld_addr;
|
||||
#endif /* CONFIG_IEEE80211BE */
|
||||
|
||||
mgmt->frame_control = IEEE80211_FC(WLAN_FC_TYPE_MGMT,
|
||||
|
@ -219,7 +219,7 @@ static void ieee802_11_send_sa_query_resp(struct hostapd_data *hapd,
|
|||
|
||||
#ifdef CONFIG_IEEE80211BE
|
||||
if (ap_sta_is_mld(hapd, sta))
|
||||
own_addr = hapd->mld_addr;
|
||||
own_addr = hapd->mld->mld_addr;
|
||||
#endif /* CONFIG_IEEE80211BE */
|
||||
|
||||
resp->frame_control = IEEE80211_FC(WLAN_FC_TYPE_MGMT,
|
||||
|
@ -441,6 +441,8 @@ static void hostapd_ext_capab_byte(struct hostapd_data *hapd, u8 *pos, int idx,
|
|||
if (hostapd_get_he_twt_responder(hapd, IEEE80211_MODE_AP))
|
||||
*pos |= 0x40; /* Bit 78 - TWT responder */
|
||||
#endif /* CONFIG_IEEE80211AX */
|
||||
if (hostapd_get_ht_vht_twt_responder(hapd))
|
||||
*pos |= 0x40; /* Bit 78 - TWT responder */
|
||||
break;
|
||||
case 10: /* Bits 80-87 */
|
||||
#ifdef CONFIG_SAE
|
||||
|
@ -735,12 +737,14 @@ int hostapd_update_time_adv(struct hostapd_data *hapd)
|
|||
}
|
||||
|
||||
|
||||
u8 * hostapd_eid_bss_max_idle_period(struct hostapd_data *hapd, u8 *eid)
|
||||
u8 * hostapd_eid_bss_max_idle_period(struct hostapd_data *hapd, u8 *eid,
|
||||
u16 value)
|
||||
{
|
||||
u8 *pos = eid;
|
||||
|
||||
#ifdef CONFIG_WNM_AP
|
||||
if (hapd->conf->ap_max_inactivity > 0) {
|
||||
if (hapd->conf->ap_max_inactivity > 0 &&
|
||||
hapd->conf->bss_max_idle) {
|
||||
unsigned int val;
|
||||
*pos++ = WLAN_EID_BSS_MAX_IDLE_PERIOD;
|
||||
*pos++ = 3;
|
||||
|
@ -753,9 +757,13 @@ u8 * hostapd_eid_bss_max_idle_period(struct hostapd_data *hapd, u8 *eid)
|
|||
val = 1;
|
||||
if (val > 65535)
|
||||
val = 65535;
|
||||
if (value)
|
||||
val = value;
|
||||
WPA_PUT_LE16(pos, val);
|
||||
pos += 2;
|
||||
*pos++ = 0x00; /* TODO: Protected Keep-Alive Required */
|
||||
/* Set the Protected Keep-Alive Required bit based on
|
||||
* configuration */
|
||||
*pos++ = hapd->conf->bss_max_idle == 2 ? BIT(0) : 0x00;
|
||||
}
|
||||
#endif /* CONFIG_WNM_AP */
|
||||
|
||||
|
@ -1089,7 +1097,7 @@ u8 * hostapd_eid_rsnxe(struct hostapd_data *hapd, u8 *eid, size_t len)
|
|||
{
|
||||
u8 *pos = eid;
|
||||
bool sae_pk = false;
|
||||
u16 capab = 0;
|
||||
u32 capab = 0, tmp;
|
||||
size_t flen;
|
||||
|
||||
if (!(hapd->conf->wpa & WPA_PROTO_RSN))
|
||||
|
@ -1118,18 +1126,28 @@ u8 * hostapd_eid_rsnxe(struct hostapd_data *hapd, u8 *eid, size_t len)
|
|||
capab |= BIT(WLAN_RSNX_CAPAB_SECURE_RTT);
|
||||
if (hapd->iface->drv_flags2 & WPA_DRIVER_FLAGS2_PROT_RANGE_NEG_AP)
|
||||
capab |= BIT(WLAN_RSNX_CAPAB_URNM_MFPR);
|
||||
if (hapd->conf->ssid_protection)
|
||||
capab |= BIT(WLAN_RSNX_CAPAB_SSID_PROTECTION);
|
||||
|
||||
flen = (capab & 0xff00) ? 2 : 1;
|
||||
if (len < 2 + flen || !capab)
|
||||
if (!capab)
|
||||
return eid; /* no supported extended RSN capabilities */
|
||||
tmp = capab;
|
||||
flen = 0;
|
||||
while (tmp) {
|
||||
flen++;
|
||||
tmp >>= 8;
|
||||
}
|
||||
|
||||
if (len < 2 + flen)
|
||||
return eid; /* no supported extended RSN capabilities */
|
||||
capab |= flen - 1; /* bit 0-3 = Field length (n - 1) */
|
||||
|
||||
*pos++ = WLAN_EID_RSNX;
|
||||
*pos++ = flen;
|
||||
*pos++ = capab & 0x00ff;
|
||||
capab >>= 8;
|
||||
if (capab)
|
||||
*pos++ = capab;
|
||||
while (capab) {
|
||||
*pos++ = capab & 0xff;
|
||||
capab >>= 8;
|
||||
}
|
||||
|
||||
return pos;
|
||||
}
|
||||
|
@ -1138,13 +1156,11 @@ u8 * hostapd_eid_rsnxe(struct hostapd_data *hapd, u8 *eid, size_t len)
|
|||
u16 check_ext_capab(struct hostapd_data *hapd, struct sta_info *sta,
|
||||
const u8 *ext_capab_ie, size_t ext_capab_ie_len)
|
||||
{
|
||||
#ifdef CONFIG_INTERWORKING
|
||||
/* check for QoS Map support */
|
||||
if (ext_capab_ie_len >= 5) {
|
||||
if (ext_capab_ie[4] & 0x01)
|
||||
sta->qos_map_enabled = 1;
|
||||
}
|
||||
#endif /* CONFIG_INTERWORKING */
|
||||
|
||||
if (ext_capab_ie_len > 0) {
|
||||
sta->ecsa_supported = !!(ext_capab_ie[0] & BIT(2));
|
||||
|
@ -1200,3 +1216,13 @@ struct sta_info * hostapd_ml_get_assoc_sta(struct hostapd_data *hapd,
|
|||
|
||||
return sta;
|
||||
}
|
||||
|
||||
|
||||
bool hostapd_get_ht_vht_twt_responder(struct hostapd_data *hapd)
|
||||
{
|
||||
return hapd->iconf->ht_vht_twt_responder &&
|
||||
((hapd->iconf->ieee80211n && !hapd->conf->disable_11n) ||
|
||||
(hapd->iconf->ieee80211ac && !hapd->conf->disable_11ac)) &&
|
||||
(hapd->iface->drv_flags2 &
|
||||
WPA_DRIVER_FLAGS2_HT_VHT_TWT_RESPONDER);
|
||||
}
|
||||
|
|
|
@ -12,6 +12,7 @@
|
|||
|
||||
#include "utils/common.h"
|
||||
#include "common/ieee802_11_defs.h"
|
||||
#include "common/hw_features_common.h"
|
||||
#include "hostapd.h"
|
||||
#include "ap_config.h"
|
||||
#include "sta_info.h"
|
||||
|
@ -79,6 +80,9 @@ u8 * hostapd_eid_vht_operation(struct hostapd_data *hapd, u8 *eid)
|
|||
hostapd_get_oper_chwidth(hapd->iconf);
|
||||
u8 seg0 = hapd->iconf->vht_oper_centr_freq_seg0_idx;
|
||||
u8 seg1 = hapd->iconf->vht_oper_centr_freq_seg1_idx;
|
||||
#ifdef CONFIG_IEEE80211BE
|
||||
u16 punct_bitmap = hostapd_get_punct_bitmap(hapd);
|
||||
#endif /* CONFIG_IEEE80211BE */
|
||||
|
||||
if (is_6ghz_op_class(hapd->iconf->op_class))
|
||||
return eid;
|
||||
|
@ -90,8 +94,8 @@ u8 * hostapd_eid_vht_operation(struct hostapd_data *hapd, u8 *eid)
|
|||
os_memset(oper, 0, sizeof(*oper));
|
||||
|
||||
#ifdef CONFIG_IEEE80211BE
|
||||
if (hapd->iconf->punct_bitmap) {
|
||||
punct_update_legacy_bw(hapd->iconf->punct_bitmap,
|
||||
if (punct_bitmap) {
|
||||
punct_update_legacy_bw(punct_bitmap,
|
||||
hapd->iconf->channel,
|
||||
&oper_chwidth, &seg0, &seg1);
|
||||
}
|
||||
|
|
|
@ -172,8 +172,7 @@ static void ieee802_1x_ml_set_sta_authorized(struct hostapd_data *hapd,
|
|||
struct hostapd_data *tmp_hapd =
|
||||
hapd->iface->interfaces->iface[i]->bss[0];
|
||||
|
||||
if (!tmp_hapd->conf->mld_ap ||
|
||||
hapd->conf->mld_id != tmp_hapd->conf->mld_id)
|
||||
if (!hostapd_is_ml_partner(hapd, tmp_hapd))
|
||||
continue;
|
||||
|
||||
for (tmp_sta = tmp_hapd->sta_list; tmp_sta;
|
||||
|
@ -768,6 +767,9 @@ void ieee802_1x_encapsulate_radius(struct hostapd_data *hapd,
|
|||
goto fail;
|
||||
}
|
||||
|
||||
if (!radius_msg_add_msg_auth(msg))
|
||||
goto fail;
|
||||
|
||||
if (sm->identity &&
|
||||
!radius_msg_add_attr(msg, RADIUS_ATTR_USER_NAME,
|
||||
sm->identity, sm->identity_len)) {
|
||||
|
@ -2040,16 +2042,7 @@ ieee802_1x_receive_auth(struct radius_msg *msg, struct radius_msg *req,
|
|||
}
|
||||
sta = sm->sta;
|
||||
|
||||
/* RFC 2869, Ch. 5.13: valid Message-Authenticator attribute MUST be
|
||||
* present when packet contains an EAP-Message attribute */
|
||||
if (hdr->code == RADIUS_CODE_ACCESS_REJECT &&
|
||||
radius_msg_get_attr(msg, RADIUS_ATTR_MESSAGE_AUTHENTICATOR, NULL,
|
||||
0) < 0 &&
|
||||
radius_msg_get_attr(msg, RADIUS_ATTR_EAP_MESSAGE, NULL, 0) < 0) {
|
||||
wpa_printf(MSG_DEBUG,
|
||||
"Allowing RADIUS Access-Reject without Message-Authenticator since it does not include EAP-Message");
|
||||
} else if (radius_msg_verify(msg, shared_secret, shared_secret_len,
|
||||
req, 1)) {
|
||||
if (radius_msg_verify(msg, shared_secret, shared_secret_len, req, 1)) {
|
||||
wpa_printf(MSG_INFO,
|
||||
"Incoming RADIUS packet did not have correct Message-Authenticator - dropped");
|
||||
return RADIUS_RX_INVALID_AUTHENTICATOR;
|
||||
|
@ -2540,13 +2533,29 @@ int ieee802_1x_init(struct hostapd_data *hapd)
|
|||
struct eapol_auth_config conf;
|
||||
struct eapol_auth_cb cb;
|
||||
|
||||
if (hapd->mld_first_bss) {
|
||||
#ifdef CONFIG_IEEE80211BE
|
||||
if (!hostapd_mld_is_first_bss(hapd)) {
|
||||
struct hostapd_data *first;
|
||||
|
||||
first = hostapd_mld_get_first_bss(hapd);
|
||||
if (!first)
|
||||
return -1;
|
||||
|
||||
if (!first->eapol_auth) {
|
||||
wpa_printf(MSG_DEBUG,
|
||||
"MLD: First BSS IEEE 802.1X state machine does not exist. Init on its behalf");
|
||||
|
||||
if (ieee802_1x_init(first))
|
||||
return -1;
|
||||
}
|
||||
|
||||
wpa_printf(MSG_DEBUG,
|
||||
"MLD: Using IEEE 802.1X state machine of the first BSS");
|
||||
|
||||
hapd->eapol_auth = hapd->mld_first_bss->eapol_auth;
|
||||
hapd->eapol_auth = first->eapol_auth;
|
||||
return 0;
|
||||
}
|
||||
#endif /* CONFIG_IEEE80211BE */
|
||||
|
||||
dl_list_init(&hapd->erp_keys);
|
||||
|
||||
|
@ -2632,13 +2641,15 @@ void ieee802_1x_erp_flush(struct hostapd_data *hapd)
|
|||
|
||||
void ieee802_1x_deinit(struct hostapd_data *hapd)
|
||||
{
|
||||
if (hapd->mld_first_bss) {
|
||||
#ifdef CONFIG_IEEE80211BE
|
||||
if (!hostapd_mld_is_first_bss(hapd)) {
|
||||
wpa_printf(MSG_DEBUG,
|
||||
"MLD: Deinit IEEE 802.1X state machine of a non-first BSS");
|
||||
|
||||
hapd->eapol_auth = NULL;
|
||||
return;
|
||||
}
|
||||
#endif /* CONFIG_IEEE80211BE */
|
||||
|
||||
#ifdef CONFIG_WEP
|
||||
eloop_cancel_timeout(ieee802_1x_rekey, hapd, NULL);
|
||||
|
|
|
@ -158,7 +158,7 @@ int hostapd_nan_usd_init(struct hostapd_data *hapd)
|
|||
cb.subscribe_terminated = hostapd_nan_de_subscribe_terminated;
|
||||
cb.receive = hostapd_nan_de_receive;
|
||||
|
||||
hapd->nan_de = nan_de_init(hapd->own_addr, true, &cb);
|
||||
hapd->nan_de = nan_de_init(hapd->own_addr, false, true, &cb);
|
||||
if (!hapd->nan_de)
|
||||
return -1;
|
||||
return 0;
|
||||
|
@ -192,7 +192,7 @@ void hostapd_nan_usd_flush(struct hostapd_data *hapd)
|
|||
int hostapd_nan_usd_publish(struct hostapd_data *hapd, const char *service_name,
|
||||
enum nan_service_protocol_type srv_proto_type,
|
||||
const struct wpabuf *ssi,
|
||||
struct nan_publish_params *params)
|
||||
struct nan_publish_params *params, bool p2p)
|
||||
{
|
||||
int publish_id;
|
||||
struct wpabuf *elems = NULL;
|
||||
|
@ -201,7 +201,7 @@ int hostapd_nan_usd_publish(struct hostapd_data *hapd, const char *service_name,
|
|||
return -1;
|
||||
|
||||
publish_id = nan_de_publish(hapd->nan_de, service_name, srv_proto_type,
|
||||
ssi, elems, params);
|
||||
ssi, elems, params, p2p);
|
||||
wpabuf_free(elems);
|
||||
return publish_id;
|
||||
}
|
||||
|
@ -231,7 +231,7 @@ int hostapd_nan_usd_subscribe(struct hostapd_data *hapd,
|
|||
const char *service_name,
|
||||
enum nan_service_protocol_type srv_proto_type,
|
||||
const struct wpabuf *ssi,
|
||||
struct nan_subscribe_params *params)
|
||||
struct nan_subscribe_params *params, bool p2p)
|
||||
{
|
||||
int subscribe_id;
|
||||
struct wpabuf *elems = NULL;
|
||||
|
@ -240,7 +240,7 @@ int hostapd_nan_usd_subscribe(struct hostapd_data *hapd,
|
|||
return -1;
|
||||
|
||||
subscribe_id = nan_de_subscribe(hapd->nan_de, service_name,
|
||||
srv_proto_type, ssi, elems, params);
|
||||
srv_proto_type, ssi, elems, params, p2p);
|
||||
wpabuf_free(elems);
|
||||
return subscribe_id;
|
||||
}
|
||||
|
|
|
@ -21,7 +21,7 @@ void hostapd_nan_usd_flush(struct hostapd_data *hapd);
|
|||
int hostapd_nan_usd_publish(struct hostapd_data *hapd, const char *service_name,
|
||||
enum nan_service_protocol_type srv_proto_type,
|
||||
const struct wpabuf *ssi,
|
||||
struct nan_publish_params *params);
|
||||
struct nan_publish_params *params, bool p2p);
|
||||
void hostapd_nan_usd_cancel_publish(struct hostapd_data *hapd, int publish_id);
|
||||
int hostapd_nan_usd_update_publish(struct hostapd_data *hapd, int publish_id,
|
||||
const struct wpabuf *ssi);
|
||||
|
@ -29,7 +29,7 @@ int hostapd_nan_usd_subscribe(struct hostapd_data *hapd,
|
|||
const char *service_name,
|
||||
enum nan_service_protocol_type srv_proto_type,
|
||||
const struct wpabuf *ssi,
|
||||
struct nan_subscribe_params *params);
|
||||
struct nan_subscribe_params *params, bool p2p);
|
||||
void hostapd_nan_usd_cancel_subscribe(struct hostapd_data *hapd,
|
||||
int subscribe_id);
|
||||
int hostapd_nan_usd_transmit(struct hostapd_data *hapd, int handle,
|
||||
|
|
|
@ -61,6 +61,7 @@ void sta_ip6addr_del(struct hostapd_data *hapd, struct sta_info *sta)
|
|||
dl_list_for_each_safe(ip6addr, prev, &sta->ip6addr, struct ip6addr,
|
||||
list) {
|
||||
hostapd_drv_br_delete_ip_neigh(hapd, 6, (u8 *) &ip6addr->addr);
|
||||
dl_list_del(&ip6addr->list);
|
||||
os_free(ip6addr);
|
||||
}
|
||||
}
|
||||
|
|
|
@ -99,7 +99,10 @@ static void hostapd_neighbor_clear_entry(struct hostapd_neighbor_entry *nr)
|
|||
nr->civic = NULL;
|
||||
os_memset(nr->bssid, 0, sizeof(nr->bssid));
|
||||
os_memset(&nr->ssid, 0, sizeof(nr->ssid));
|
||||
os_memset(&nr->lci_date, 0, sizeof(nr->lci_date));
|
||||
nr->stationary = 0;
|
||||
nr->short_ssid = 0;
|
||||
nr->bss_parameters = 0;
|
||||
}
|
||||
|
||||
|
||||
|
@ -165,6 +168,14 @@ fail:
|
|||
}
|
||||
|
||||
|
||||
static void hostapd_neighbor_free(struct hostapd_neighbor_entry *nr)
|
||||
{
|
||||
hostapd_neighbor_clear_entry(nr);
|
||||
dl_list_del(&nr->list);
|
||||
os_free(nr);
|
||||
}
|
||||
|
||||
|
||||
int hostapd_neighbor_remove(struct hostapd_data *hapd, const u8 *bssid,
|
||||
const struct wpa_ssid_value *ssid)
|
||||
{
|
||||
|
@ -174,9 +185,7 @@ int hostapd_neighbor_remove(struct hostapd_data *hapd, const u8 *bssid,
|
|||
if (!nr)
|
||||
return -1;
|
||||
|
||||
hostapd_neighbor_clear_entry(nr);
|
||||
dl_list_del(&nr->list);
|
||||
os_free(nr);
|
||||
hostapd_neighbor_free(nr);
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
@ -188,9 +197,7 @@ void hostapd_free_neighbor_db(struct hostapd_data *hapd)
|
|||
|
||||
dl_list_for_each_safe(nr, prev, &hapd->nr_db,
|
||||
struct hostapd_neighbor_entry, list) {
|
||||
hostapd_neighbor_clear_entry(nr);
|
||||
dl_list_del(&nr->list);
|
||||
os_free(nr);
|
||||
hostapd_neighbor_free(nr);
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -325,3 +332,35 @@ void hostapd_neighbor_set_own_report(struct hostapd_data *hapd)
|
|||
wpabuf_free(nr);
|
||||
#endif /* NEED_AP_MLME */
|
||||
}
|
||||
|
||||
|
||||
static struct hostapd_neighbor_entry *
|
||||
hostapd_neighbor_get_diff_short_ssid(struct hostapd_data *hapd, const u8 *bssid)
|
||||
{
|
||||
struct hostapd_neighbor_entry *nr;
|
||||
|
||||
dl_list_for_each(nr, &hapd->nr_db, struct hostapd_neighbor_entry,
|
||||
list) {
|
||||
if (ether_addr_equal(bssid, nr->bssid) &&
|
||||
nr->short_ssid != hapd->conf->ssid.short_ssid)
|
||||
return nr;
|
||||
}
|
||||
return NULL;
|
||||
}
|
||||
|
||||
|
||||
int hostapd_neighbor_sync_own_report(struct hostapd_data *hapd)
|
||||
{
|
||||
struct hostapd_neighbor_entry *nr;
|
||||
|
||||
nr = hostapd_neighbor_get_diff_short_ssid(hapd, hapd->own_addr);
|
||||
if (!nr)
|
||||
return -1;
|
||||
|
||||
/* Clear old entry due to SSID change */
|
||||
hostapd_neighbor_free(nr);
|
||||
|
||||
hostapd_neighbor_set_own_report(hapd);
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
|
|
@ -20,6 +20,7 @@ int hostapd_neighbor_set(struct hostapd_data *hapd, const u8 *bssid,
|
|||
const struct wpabuf *civic, int stationary,
|
||||
u8 bss_parameters);
|
||||
void hostapd_neighbor_set_own_report(struct hostapd_data *hapd);
|
||||
int hostapd_neighbor_sync_own_report(struct hostapd_data *hapd);
|
||||
int hostapd_neighbor_remove(struct hostapd_data *hapd, const u8 *bssid,
|
||||
const struct wpa_ssid_value *ssid);
|
||||
void hostapd_free_neighbor_db(struct hostapd_data *hapd);
|
||||
|
|
121
src/ap/rrm.c
121
src/ap/rrm.c
|
@ -334,6 +334,53 @@ static void hostapd_handle_nei_report_req(struct hostapd_data *hapd,
|
|||
}
|
||||
|
||||
|
||||
static void hostapd_link_mesr_rep_timeout_handler(void *eloop_data,
|
||||
void *user_ctx)
|
||||
{
|
||||
struct hostapd_data *hapd = eloop_data;
|
||||
|
||||
wpa_printf(MSG_DEBUG,
|
||||
"RRM: Link measurement request (token %u) timed out",
|
||||
hapd->link_measurement_req_token);
|
||||
hapd->link_mesr_req_active = 0;
|
||||
}
|
||||
|
||||
|
||||
static void hostapd_handle_link_mesr_report(struct hostapd_data *hapd,
|
||||
const u8 *buf, size_t len)
|
||||
{
|
||||
const struct ieee80211_mgmt *mgmt = (const struct ieee80211_mgmt *) buf;
|
||||
const struct rrm_link_measurement_report *report;
|
||||
const u8 *pos, *end;
|
||||
char report_msg[2 * 8 + 1];
|
||||
|
||||
end = buf + len;
|
||||
pos = mgmt->u.action.u.rrm.variable;
|
||||
report = (const struct rrm_link_measurement_report *) (pos - 1);
|
||||
if (end - (const u8 *) report < (int) sizeof(*report))
|
||||
return;
|
||||
|
||||
if (!hapd->link_mesr_req_active ||
|
||||
(hapd->link_measurement_req_token != report->dialog_token)) {
|
||||
wpa_printf(MSG_INFO,
|
||||
"Unexpected Link measurement report, token %u",
|
||||
report->dialog_token);
|
||||
return;
|
||||
}
|
||||
|
||||
hapd->link_mesr_req_active = 0;
|
||||
eloop_cancel_timeout(hostapd_link_mesr_rep_timeout_handler, hapd, NULL);
|
||||
|
||||
report_msg[0] = '\0';
|
||||
if (wpa_snprintf_hex(report_msg, sizeof(report_msg),
|
||||
pos, end - pos) < 0)
|
||||
return;
|
||||
|
||||
wpa_msg(hapd->msg_ctx, MSG_INFO, LINK_MSR_RESP_RX MACSTR " %u %s",
|
||||
MAC2STR(mgmt->sa), report->dialog_token, report_msg);
|
||||
}
|
||||
|
||||
|
||||
void hostapd_handle_radio_measurement(struct hostapd_data *hapd,
|
||||
const u8 *buf, size_t len)
|
||||
{
|
||||
|
@ -356,6 +403,9 @@ void hostapd_handle_radio_measurement(struct hostapd_data *hapd,
|
|||
case WLAN_RRM_NEIGHBOR_REPORT_REQUEST:
|
||||
hostapd_handle_nei_report_req(hapd, buf, len);
|
||||
break;
|
||||
case WLAN_RRM_LINK_MEASUREMENT_REPORT:
|
||||
hostapd_handle_link_mesr_report(hapd, buf, len);
|
||||
break;
|
||||
default:
|
||||
wpa_printf(MSG_DEBUG, "RRM action %u is not supported",
|
||||
mgmt->u.action.u.rrm.action);
|
||||
|
@ -563,6 +613,7 @@ void hostapd_clean_rrm(struct hostapd_data *hapd)
|
|||
hapd->lci_req_active = 0;
|
||||
eloop_cancel_timeout(hostapd_range_rep_timeout_handler, hapd, NULL);
|
||||
hapd->range_req_active = 0;
|
||||
eloop_cancel_timeout(hostapd_link_mesr_rep_timeout_handler, hapd, NULL);
|
||||
}
|
||||
|
||||
|
||||
|
@ -672,3 +723,73 @@ void hostapd_rrm_beacon_req_tx_status(struct hostapd_data *hapd,
|
|||
" %u ack=%d", MAC2STR(mgmt->da),
|
||||
mgmt->u.action.u.rrm.dialog_token, ok);
|
||||
}
|
||||
|
||||
|
||||
int hostapd_send_link_measurement_req(struct hostapd_data *hapd, const u8 *addr)
|
||||
{
|
||||
struct wpabuf *buf;
|
||||
struct sta_info *sta;
|
||||
int ret;
|
||||
|
||||
wpa_printf(MSG_DEBUG, "Request Link Measurement: dest addr " MACSTR,
|
||||
MAC2STR(addr));
|
||||
|
||||
if (!(hapd->iface->drv_rrm_flags &
|
||||
WPA_DRIVER_FLAGS_TX_POWER_INSERTION)) {
|
||||
wpa_printf(MSG_INFO,
|
||||
"Request Link Measurement: the driver does not support TX power insertion");
|
||||
return -1;
|
||||
}
|
||||
|
||||
sta = ap_get_sta(hapd, addr);
|
||||
if (!sta || !(sta->flags & WLAN_STA_AUTHORIZED)) {
|
||||
wpa_printf(MSG_INFO,
|
||||
"Request Link Measurement: specied STA is not connected");
|
||||
return -1;
|
||||
}
|
||||
|
||||
if (!(sta->rrm_enabled_capa[0] & WLAN_RRM_CAPS_LINK_MEASUREMENT)) {
|
||||
wpa_printf(MSG_INFO,
|
||||
"Request Link Measurement: destination STA does not support link measurement");
|
||||
return -1;
|
||||
}
|
||||
|
||||
if (hapd->link_mesr_req_active) {
|
||||
wpa_printf(MSG_DEBUG,
|
||||
"Request Link Measurement: request already in process - overriding");
|
||||
hapd->link_mesr_req_active = 0;
|
||||
eloop_cancel_timeout(hostapd_link_mesr_rep_timeout_handler,
|
||||
hapd, NULL);
|
||||
}
|
||||
|
||||
/* Action + Action type + token + Tx Power used + Max Tx Power = 5 */
|
||||
buf = wpabuf_alloc(5);
|
||||
if (!buf)
|
||||
return -1;
|
||||
|
||||
hapd->link_measurement_req_token++;
|
||||
if (!hapd->link_measurement_req_token)
|
||||
hapd->link_measurement_req_token++;
|
||||
|
||||
wpabuf_put_u8(buf, WLAN_ACTION_RADIO_MEASUREMENT);
|
||||
wpabuf_put_u8(buf, WLAN_RRM_LINK_MEASUREMENT_REQUEST);
|
||||
wpabuf_put_u8(buf, hapd->link_measurement_req_token);
|
||||
/* NOTE: The driver is expected to fill the Tx Power Used and Max Tx
|
||||
* Power */
|
||||
wpabuf_put_u8(buf, 0);
|
||||
wpabuf_put_u8(buf, 0);
|
||||
|
||||
ret = hostapd_drv_send_action(hapd, hapd->iface->freq, 0, addr,
|
||||
wpabuf_head(buf), wpabuf_len(buf));
|
||||
wpabuf_free(buf);
|
||||
if (ret < 0)
|
||||
return ret;
|
||||
|
||||
hapd->link_mesr_req_active = 1;
|
||||
|
||||
eloop_register_timeout(HOSTAPD_RRM_REQUEST_TIMEOUT, 0,
|
||||
hostapd_link_mesr_rep_timeout_handler, hapd,
|
||||
NULL);
|
||||
|
||||
return hapd->link_measurement_req_token;
|
||||
}
|
||||
|
|
|
@ -29,5 +29,7 @@ int hostapd_send_beacon_req(struct hostapd_data *hapd, const u8 *addr,
|
|||
void hostapd_rrm_beacon_req_tx_status(struct hostapd_data *hapd,
|
||||
const struct ieee80211_mgmt *mgmt,
|
||||
size_t len, int ok);
|
||||
int hostapd_send_link_measurement_req(struct hostapd_data *hapd,
|
||||
const u8 *addr);
|
||||
|
||||
#endif /* RRM_H */
|
||||
|
|
|
@ -180,13 +180,48 @@ void ap_free_sta_pasn(struct hostapd_data *hapd, struct sta_info *sta)
|
|||
sta->pasn->fils.erp_resp = NULL;
|
||||
#endif /* CONFIG_FILS */
|
||||
|
||||
bin_clear_free(sta->pasn, sizeof(*sta->pasn));
|
||||
pasn_data_deinit(sta->pasn);
|
||||
sta->pasn = NULL;
|
||||
}
|
||||
}
|
||||
|
||||
#endif /* CONFIG_PASN */
|
||||
|
||||
|
||||
static void __ap_free_sta(struct hostapd_data *hapd, struct sta_info *sta)
|
||||
{
|
||||
#ifdef CONFIG_IEEE80211BE
|
||||
if (hostapd_sta_is_link_sta(hapd, sta) &&
|
||||
!hostapd_drv_link_sta_remove(hapd, sta->addr))
|
||||
return;
|
||||
#endif /* CONFIG_IEEE80211BE */
|
||||
|
||||
hostapd_drv_sta_remove(hapd, sta->addr);
|
||||
}
|
||||
|
||||
|
||||
#ifdef CONFIG_IEEE80211BE
|
||||
static void clear_wpa_sm_for_each_partner_link(struct hostapd_data *hapd,
|
||||
struct sta_info *psta)
|
||||
{
|
||||
struct sta_info *lsta;
|
||||
struct hostapd_data *lhapd;
|
||||
|
||||
if (!ap_sta_is_mld(hapd, psta))
|
||||
return;
|
||||
|
||||
for_each_mld_link(lhapd, hapd) {
|
||||
if (lhapd == hapd)
|
||||
continue;
|
||||
|
||||
lsta = ap_get_sta(lhapd, psta->addr);
|
||||
if (lsta)
|
||||
lsta->wpa_sm = NULL;
|
||||
}
|
||||
}
|
||||
#endif /* CONFIG_IEEE80211BE */
|
||||
|
||||
|
||||
void ap_free_sta(struct hostapd_data *hapd, struct sta_info *sta)
|
||||
{
|
||||
int set_beacon = 0;
|
||||
|
@ -200,6 +235,7 @@ void ap_free_sta(struct hostapd_data *hapd, struct sta_info *sta)
|
|||
if ((sta->flags & WLAN_STA_WDS) ||
|
||||
(sta->flags & WLAN_STA_MULTI_AP &&
|
||||
(hapd->conf->multi_ap & BACKHAUL_BSS) &&
|
||||
hapd->conf->wds_sta &&
|
||||
!(sta->flags & WLAN_STA_WPS)))
|
||||
hostapd_set_wds_sta(hapd, NULL, sta->addr, sta->aid, 0);
|
||||
|
||||
|
@ -209,7 +245,7 @@ void ap_free_sta(struct hostapd_data *hapd, struct sta_info *sta)
|
|||
|
||||
if (!hapd->iface->driver_ap_teardown &&
|
||||
!(sta->flags & WLAN_STA_PREAUTH)) {
|
||||
hostapd_drv_sta_remove(hapd, sta->addr);
|
||||
__ap_free_sta(hapd, sta);
|
||||
sta->added_unassoc = 0;
|
||||
}
|
||||
|
||||
|
@ -304,9 +340,17 @@ void ap_free_sta(struct hostapd_data *hapd, struct sta_info *sta)
|
|||
|
||||
#ifdef CONFIG_IEEE80211BE
|
||||
if (!ap_sta_is_mld(hapd, sta) ||
|
||||
hapd->mld_link_id == sta->mld_assoc_link_id)
|
||||
hapd->mld_link_id == sta->mld_assoc_link_id) {
|
||||
wpa_auth_sta_deinit(sta->wpa_sm);
|
||||
#else
|
||||
/* Remove references from partner links. */
|
||||
clear_wpa_sm_for_each_partner_link(hapd, sta);
|
||||
}
|
||||
|
||||
/* Release group references in case non-association link STA is removed
|
||||
* before association link STA */
|
||||
if (hostapd_sta_is_link_sta(hapd, sta))
|
||||
wpa_release_link_auth_ref(sta->wpa_sm, hapd->mld_link_id);
|
||||
#else /* CONFIG_IEEE80211BE */
|
||||
wpa_auth_sta_deinit(sta->wpa_sm);
|
||||
#endif /* CONFIG_IEEE80211BE */
|
||||
|
||||
|
@ -454,6 +498,27 @@ void hostapd_free_stas(struct hostapd_data *hapd)
|
|||
}
|
||||
|
||||
|
||||
#ifdef CONFIG_IEEE80211BE
|
||||
void hostapd_free_link_stas(struct hostapd_data *hapd)
|
||||
{
|
||||
struct sta_info *sta, *prev;
|
||||
|
||||
sta = hapd->sta_list;
|
||||
while (sta) {
|
||||
prev = sta;
|
||||
sta = sta->next;
|
||||
|
||||
if (!hostapd_sta_is_link_sta(hapd, prev))
|
||||
continue;
|
||||
|
||||
wpa_printf(MSG_DEBUG, "Removing link station from MLD " MACSTR,
|
||||
MAC2STR(prev->addr));
|
||||
ap_free_sta(hapd, prev);
|
||||
}
|
||||
}
|
||||
#endif /* CONFIG_IEEE80211BE */
|
||||
|
||||
|
||||
/**
|
||||
* ap_handle_timer - Per STA timer handler
|
||||
* @eloop_ctx: struct hostapd_data *
|
||||
|
@ -468,6 +533,7 @@ void ap_handle_timer(void *eloop_ctx, void *timeout_ctx)
|
|||
struct sta_info *sta = timeout_ctx;
|
||||
unsigned long next_time = 0;
|
||||
int reason;
|
||||
int max_inactivity = hapd->conf->ap_max_inactivity;
|
||||
|
||||
wpa_printf(MSG_DEBUG, "%s: %s: " MACSTR " flags=0x%x timeout_next=%d",
|
||||
hapd->conf->iface, __func__, MAC2STR(sta->addr), sta->flags,
|
||||
|
@ -480,6 +546,9 @@ void ap_handle_timer(void *eloop_ctx, void *timeout_ctx)
|
|||
return;
|
||||
}
|
||||
|
||||
if (sta->max_idle_period)
|
||||
max_inactivity = (sta->max_idle_period * 1024 + 999) / 1000;
|
||||
|
||||
if ((sta->flags & WLAN_STA_ASSOC) &&
|
||||
(sta->timeout_next == STA_NULLFUNC ||
|
||||
sta->timeout_next == STA_DISASSOC)) {
|
||||
|
@ -501,7 +570,7 @@ void ap_handle_timer(void *eloop_ctx, void *timeout_ctx)
|
|||
* Anyway, try again after the next inactivity timeout,
|
||||
* but do not disconnect the station now.
|
||||
*/
|
||||
next_time = hapd->conf->ap_max_inactivity + fuzz;
|
||||
next_time = max_inactivity + fuzz;
|
||||
} else if (inactive_sec == -ENOENT) {
|
||||
wpa_msg(hapd->msg_ctx, MSG_DEBUG,
|
||||
"Station " MACSTR " has lost its driver entry",
|
||||
|
@ -510,20 +579,19 @@ void ap_handle_timer(void *eloop_ctx, void *timeout_ctx)
|
|||
/* Avoid sending client probe on removed client */
|
||||
sta->timeout_next = STA_DISASSOC;
|
||||
goto skip_poll;
|
||||
} else if (inactive_sec < hapd->conf->ap_max_inactivity) {
|
||||
} else if (inactive_sec < max_inactivity) {
|
||||
/* station activity detected; reset timeout state */
|
||||
wpa_msg(hapd->msg_ctx, MSG_DEBUG,
|
||||
"Station " MACSTR " has been active %is ago",
|
||||
MAC2STR(sta->addr), inactive_sec);
|
||||
sta->timeout_next = STA_NULLFUNC;
|
||||
next_time = hapd->conf->ap_max_inactivity + fuzz -
|
||||
inactive_sec;
|
||||
next_time = max_inactivity + fuzz - inactive_sec;
|
||||
} else {
|
||||
wpa_msg(hapd->msg_ctx, MSG_DEBUG,
|
||||
"Station " MACSTR " has been "
|
||||
"inactive too long: %d sec, max allowed: %d",
|
||||
MAC2STR(sta->addr), inactive_sec,
|
||||
hapd->conf->ap_max_inactivity);
|
||||
max_inactivity);
|
||||
|
||||
if (hapd->conf->skip_inactivity_poll)
|
||||
sta->timeout_next = STA_DISASSOC;
|
||||
|
@ -539,7 +607,7 @@ void ap_handle_timer(void *eloop_ctx, void *timeout_ctx)
|
|||
/* data nullfunc frame poll did not produce TX errors; assume
|
||||
* station ACKed it */
|
||||
sta->timeout_next = STA_NULLFUNC;
|
||||
next_time = hapd->conf->ap_max_inactivity;
|
||||
next_time = max_inactivity;
|
||||
}
|
||||
|
||||
skip_poll:
|
||||
|
@ -727,6 +795,7 @@ struct sta_info * ap_sta_add(struct hostapd_data *hapd, const u8 *addr)
|
|||
{
|
||||
struct sta_info *sta;
|
||||
int i;
|
||||
int max_inactivity = hapd->conf->ap_max_inactivity;
|
||||
|
||||
sta = ap_get_sta(hapd, addr);
|
||||
if (sta)
|
||||
|
@ -760,12 +829,15 @@ struct sta_info * ap_sta_add(struct hostapd_data *hapd, const u8 *addr)
|
|||
}
|
||||
sta->supported_rates_len = i;
|
||||
|
||||
if (sta->max_idle_period)
|
||||
max_inactivity = (sta->max_idle_period * 1024 + 999) / 1000;
|
||||
|
||||
if (!(hapd->iface->drv_flags & WPA_DRIVER_FLAGS_INACTIVITY_TIMER)) {
|
||||
wpa_printf(MSG_DEBUG, "%s: register ap_handle_timer timeout "
|
||||
"for " MACSTR " (%d seconds - ap_max_inactivity)",
|
||||
__func__, MAC2STR(addr),
|
||||
hapd->conf->ap_max_inactivity);
|
||||
eloop_register_timeout(hapd->conf->ap_max_inactivity, 0,
|
||||
max_inactivity);
|
||||
eloop_register_timeout(max_inactivity, 0,
|
||||
ap_handle_timer, hapd, sta);
|
||||
}
|
||||
|
||||
|
@ -869,9 +941,11 @@ static void ap_sta_disconnect_common(struct hostapd_data *hapd,
|
|||
ieee802_1x_free_station(hapd, sta);
|
||||
#ifdef CONFIG_IEEE80211BE
|
||||
if (!hapd->conf->mld_ap ||
|
||||
hapd->mld_link_id == sta->mld_assoc_link_id)
|
||||
hapd->mld_link_id == sta->mld_assoc_link_id) {
|
||||
wpa_auth_sta_deinit(sta->wpa_sm);
|
||||
#else
|
||||
clear_wpa_sm_for_each_partner_link(hapd, sta);
|
||||
}
|
||||
#else /* CONFIG_IEEE80211BE */
|
||||
wpa_auth_sta_deinit(sta->wpa_sm);
|
||||
#endif /* CONFIG_IEEE80211BE */
|
||||
|
||||
|
@ -970,16 +1044,15 @@ static bool ap_sta_ml_disconnect(struct hostapd_data *hapd,
|
|||
interfaces = assoc_hapd->iface->interfaces;
|
||||
|
||||
for (link_id = 0; link_id < MAX_NUM_MLD_LINKS; link_id++) {
|
||||
if (!assoc_sta->mld_info.links[link_id].valid)
|
||||
continue;
|
||||
|
||||
for (i = 0; i < interfaces->count; i++) {
|
||||
struct sta_info *tmp_sta;
|
||||
|
||||
if (!assoc_sta->mld_info.links[link_id].valid)
|
||||
continue;
|
||||
|
||||
tmp_hapd = interfaces->iface[i]->bss[0];
|
||||
|
||||
if (!tmp_hapd->conf->mld_ap ||
|
||||
assoc_hapd->conf->mld_id != tmp_hapd->conf->mld_id)
|
||||
if (!hostapd_is_ml_partner(tmp_hapd, assoc_hapd))
|
||||
continue;
|
||||
|
||||
for (tmp_sta = tmp_hapd->sta_list; tmp_sta;
|
||||
|
@ -1433,6 +1506,7 @@ void ap_sta_set_authorized_event(struct hostapd_data *hapd,
|
|||
u8 addr[ETH_ALEN];
|
||||
u8 ip_addr_buf[4];
|
||||
#endif /* CONFIG_P2P */
|
||||
const u8 *ip_ptr = NULL;
|
||||
|
||||
#ifdef CONFIG_P2P
|
||||
if (hapd->p2p_group == NULL) {
|
||||
|
@ -1449,10 +1523,6 @@ void ap_sta_set_authorized_event(struct hostapd_data *hapd,
|
|||
#endif /* CONFIG_P2P */
|
||||
os_snprintf(buf, sizeof(buf), MACSTR, MAC2STR(sta->addr));
|
||||
|
||||
if (hapd->sta_authorized_cb)
|
||||
hapd->sta_authorized_cb(hapd->sta_authorized_cb_ctx,
|
||||
sta->addr, authorized, dev_addr);
|
||||
|
||||
if (authorized) {
|
||||
const u8 *dpp_pkhash;
|
||||
const char *keyid;
|
||||
|
@ -1469,6 +1539,7 @@ void ap_sta_set_authorized_event(struct hostapd_data *hapd,
|
|||
" ip_addr=%u.%u.%u.%u",
|
||||
ip_addr_buf[0], ip_addr_buf[1],
|
||||
ip_addr_buf[2], ip_addr_buf[3]);
|
||||
ip_ptr = ip_addr_buf;
|
||||
}
|
||||
#endif /* CONFIG_P2P */
|
||||
|
||||
|
@ -1508,6 +1579,11 @@ void ap_sta_set_authorized_event(struct hostapd_data *hapd,
|
|||
AP_STA_DISCONNECTED "%s", buf);
|
||||
}
|
||||
|
||||
if (hapd->sta_authorized_cb)
|
||||
hapd->sta_authorized_cb(hapd->sta_authorized_cb_ctx,
|
||||
sta->addr, authorized, dev_addr,
|
||||
ip_ptr);
|
||||
|
||||
#ifdef CONFIG_FST
|
||||
if (hapd->iface->fst) {
|
||||
if (authorized)
|
||||
|
@ -1725,10 +1801,8 @@ static void ap_sta_remove_link_sta(struct hostapd_data *hapd,
|
|||
struct sta_info *sta)
|
||||
{
|
||||
struct hostapd_data *tmp_hapd;
|
||||
unsigned int i, j;
|
||||
|
||||
for_each_mld_link(tmp_hapd, i, j, hapd->iface->interfaces,
|
||||
hapd->conf->mld_id) {
|
||||
for_each_mld_link(tmp_hapd, hapd) {
|
||||
struct sta_info *tmp_sta;
|
||||
|
||||
if (hapd == tmp_hapd)
|
||||
|
|
|
@ -81,22 +81,7 @@ struct mld_info {
|
|||
u16 mld_capa;
|
||||
} common_info;
|
||||
|
||||
struct mld_link_info {
|
||||
u8 valid:1;
|
||||
u8 nstr_bitmap_len:2;
|
||||
u8 local_addr[ETH_ALEN];
|
||||
u8 peer_addr[ETH_ALEN];
|
||||
|
||||
u8 nstr_bitmap[2];
|
||||
|
||||
u16 capability;
|
||||
|
||||
u16 status;
|
||||
u16 resp_sta_profile_len;
|
||||
u8 *resp_sta_profile;
|
||||
|
||||
const u8 *rsne, *rsnxe;
|
||||
} links[MAX_NUM_MLD_LINKS];
|
||||
struct mld_link_info links[MAX_NUM_MLD_LINKS];
|
||||
};
|
||||
|
||||
struct sta_info {
|
||||
|
@ -334,6 +319,9 @@ struct sta_info {
|
|||
struct mld_info mld_info;
|
||||
u8 mld_assoc_link_id;
|
||||
#endif /* CONFIG_IEEE80211BE */
|
||||
|
||||
u16 max_idle_period; /* if nonzero, the granted BSS max idle period in
|
||||
* units of 1000 TUs */
|
||||
};
|
||||
|
||||
|
||||
|
@ -440,4 +428,6 @@ static inline void ap_sta_set_mld(struct sta_info *sta, bool mld)
|
|||
|
||||
void ap_sta_free_sta_profile(struct mld_info *info);
|
||||
|
||||
void hostapd_free_link_stas(struct hostapd_data *hapd);
|
||||
|
||||
#endif /* STA_INFO_H */
|
||||
|
|
|
@ -51,7 +51,7 @@ static const u8 * wnm_ap_get_own_addr(struct hostapd_data *hapd,
|
|||
|
||||
#ifdef CONFIG_IEEE80211BE
|
||||
if (hapd->conf->mld_ap && (!sta || ap_sta_is_mld(hapd, sta)))
|
||||
own_addr = hapd->mld_addr;
|
||||
own_addr = hapd->mld->mld_addr;
|
||||
#endif /* CONFIG_IEEE80211BE */
|
||||
|
||||
return own_addr;
|
||||
|
|
File diff suppressed because it is too large
Load diff
|
@ -17,7 +17,7 @@
|
|||
struct vlan_description;
|
||||
struct mld_info;
|
||||
|
||||
#define MAX_OWN_IE_OVERRIDE 256
|
||||
#define MAX_OWN_IE_OVERRIDE 257
|
||||
|
||||
#ifdef _MSC_VER
|
||||
#pragma pack(push, 1)
|
||||
|
@ -173,6 +173,8 @@ struct wpa_auth_config {
|
|||
int wpa;
|
||||
int extended_key_id;
|
||||
int wpa_key_mgmt;
|
||||
int rsn_override_key_mgmt;
|
||||
int rsn_override_key_mgmt_2;
|
||||
int wpa_pairwise;
|
||||
int wpa_group;
|
||||
int wpa_group_rekey;
|
||||
|
@ -184,6 +186,8 @@ struct wpa_auth_config {
|
|||
u32 wpa_pairwise_update_count;
|
||||
int wpa_disable_eapol_key_retries;
|
||||
int rsn_pairwise;
|
||||
int rsn_override_pairwise;
|
||||
int rsn_override_pairwise_2;
|
||||
int rsn_preauth;
|
||||
int eapol_version;
|
||||
int wmm_enabled;
|
||||
|
@ -192,15 +196,17 @@ struct wpa_auth_config {
|
|||
int okc;
|
||||
int tx_status;
|
||||
enum mfp_options ieee80211w;
|
||||
enum mfp_options rsn_override_mfp;
|
||||
enum mfp_options rsn_override_mfp_2;
|
||||
int beacon_prot;
|
||||
int group_mgmt_cipher;
|
||||
int sae_require_mfp;
|
||||
#ifdef CONFIG_OCV
|
||||
int ocv; /* Operating Channel Validation */
|
||||
#endif /* CONFIG_OCV */
|
||||
#ifdef CONFIG_IEEE80211R_AP
|
||||
u8 ssid[SSID_MAX_LEN];
|
||||
size_t ssid_len;
|
||||
#ifdef CONFIG_IEEE80211R_AP
|
||||
u8 mobility_domain[MOBILITY_DOMAIN_ID_LEN];
|
||||
u8 r0_key_holder[FT_R0KH_ID_MAX_LEN];
|
||||
size_t r0_key_holder_len;
|
||||
|
@ -224,6 +230,21 @@ struct wpa_auth_config {
|
|||
double corrupt_gtk_rekey_mic_probability;
|
||||
u8 own_ie_override[MAX_OWN_IE_OVERRIDE];
|
||||
size_t own_ie_override_len;
|
||||
bool rsne_override_set;
|
||||
u8 rsne_override[MAX_OWN_IE_OVERRIDE];
|
||||
size_t rsne_override_len;
|
||||
bool rsnoe_override_set;
|
||||
u8 rsnoe_override[MAX_OWN_IE_OVERRIDE];
|
||||
size_t rsnoe_override_len;
|
||||
bool rsno2e_override_set;
|
||||
u8 rsno2e_override[MAX_OWN_IE_OVERRIDE];
|
||||
size_t rsno2e_override_len;
|
||||
bool rsnxe_override_set;
|
||||
u8 rsnxe_override[MAX_OWN_IE_OVERRIDE];
|
||||
size_t rsnxe_override_len;
|
||||
bool rsnxoe_override_set;
|
||||
u8 rsnxoe_override[MAX_OWN_IE_OVERRIDE];
|
||||
size_t rsnxoe_override_len;
|
||||
u8 rsne_override_eapol[MAX_OWN_IE_OVERRIDE];
|
||||
size_t rsne_override_eapol_len;
|
||||
u8 rsnxe_override_eapol[MAX_OWN_IE_OVERRIDE];
|
||||
|
@ -245,6 +266,7 @@ struct wpa_auth_config {
|
|||
struct wpabuf *eapol_m1_elements;
|
||||
struct wpabuf *eapol_m3_elements;
|
||||
bool eapol_m3_no_encrypt;
|
||||
bool eapol_key_reserved_random;
|
||||
#endif /* CONFIG_TESTING_OPTIONS */
|
||||
unsigned int oci_freq_override_eapol_m3;
|
||||
unsigned int oci_freq_override_eapol_g1;
|
||||
|
@ -281,10 +303,22 @@ struct wpa_auth_config {
|
|||
|
||||
bool radius_psk;
|
||||
|
||||
bool no_disconnect_on_group_keyerror;
|
||||
|
||||
/* Pointer to Multi-BSSID transmitted BSS authenticator instance.
|
||||
* Set only in nontransmitted BSSs, i.e., is NULL for transmitted BSS
|
||||
* and in BSSs that are not part of a Multi-BSSID set. */
|
||||
struct wpa_authenticator *tx_bss_auth;
|
||||
|
||||
#ifdef CONFIG_IEEE80211BE
|
||||
const u8 *mld_addr;
|
||||
int link_id;
|
||||
struct wpa_authenticator *first_link_auth;
|
||||
#endif /* CONFIG_IEEE80211BE */
|
||||
|
||||
bool ssid_protection;
|
||||
|
||||
int rsn_override_omit_rsnxe;
|
||||
};
|
||||
|
||||
typedef enum {
|
||||
|
@ -297,16 +331,6 @@ typedef enum {
|
|||
WPA_EAPOL_keyDone, WPA_EAPOL_inc_EapolFramesTx
|
||||
} wpa_eapol_variable;
|
||||
|
||||
struct wpa_auth_ml_rsn_info {
|
||||
unsigned int n_mld_links;
|
||||
|
||||
struct wpa_auth_ml_link_rsn_info {
|
||||
unsigned int link_id;
|
||||
const u8 *rsn_ies;
|
||||
size_t rsn_ies_len;
|
||||
} links[MAX_NUM_MLD_LINKS];
|
||||
};
|
||||
|
||||
struct wpa_auth_ml_key_info {
|
||||
unsigned int n_mld_links;
|
||||
bool mgmt_frame_prot;
|
||||
|
@ -400,8 +424,8 @@ struct wpa_auth_callbacks {
|
|||
size_t ltf_keyseed_len);
|
||||
#endif /* CONFIG_PASN */
|
||||
#ifdef CONFIG_IEEE80211BE
|
||||
int (*get_ml_rsn_info)(void *ctx, struct wpa_auth_ml_rsn_info *info);
|
||||
int (*get_ml_key_info)(void *ctx, struct wpa_auth_ml_key_info *info);
|
||||
int (*get_ml_key_info)(void *ctx, struct wpa_auth_ml_key_info *info,
|
||||
bool rekey);
|
||||
#endif /* CONFIG_IEEE80211BE */
|
||||
int (*get_drv_flags)(void *ctx, u64 *drv_flags, u64 *drv_flags2);
|
||||
};
|
||||
|
@ -429,7 +453,8 @@ wpa_validate_wpa_ie(struct wpa_authenticator *wpa_auth,
|
|||
const u8 *wpa_ie, size_t wpa_ie_len,
|
||||
const u8 *rsnxe, size_t rsnxe_len,
|
||||
const u8 *mdie, size_t mdie_len,
|
||||
const u8 *owe_dh, size_t owe_dh_len);
|
||||
const u8 *owe_dh, size_t owe_dh_len,
|
||||
struct wpa_state_machine *assoc_sm);
|
||||
int wpa_validate_osen(struct wpa_authenticator *wpa_auth,
|
||||
struct wpa_state_machine *sm,
|
||||
const u8 *osen_ie, size_t osen_ie_len);
|
||||
|
@ -520,9 +545,9 @@ u8 * wpa_sm_write_assoc_resp_ies(struct wpa_state_machine *sm, u8 *pos,
|
|||
size_t max_len, int auth_alg,
|
||||
const u8 *req_ies, size_t req_ies_len,
|
||||
int omit_rsnxe);
|
||||
void wpa_ft_process_auth(struct wpa_state_machine *sm, const u8 *bssid,
|
||||
void wpa_ft_process_auth(struct wpa_state_machine *sm,
|
||||
u16 auth_transaction, const u8 *ies, size_t ies_len,
|
||||
void (*cb)(void *ctx, const u8 *dst, const u8 *bssid,
|
||||
void (*cb)(void *ctx, const u8 *dst,
|
||||
u16 auth_transaction, u16 resp,
|
||||
const u8 *ies, size_t ies_len),
|
||||
void *ctx);
|
||||
|
@ -605,7 +630,10 @@ u8 * wpa_auth_write_assoc_resp_fils(struct wpa_state_machine *sm,
|
|||
bool wpa_auth_write_fd_rsn_info(struct wpa_authenticator *wpa_auth,
|
||||
u8 *fd_rsn_info);
|
||||
void wpa_auth_set_auth_alg(struct wpa_state_machine *sm, u16 auth_alg);
|
||||
void wpa_auth_set_rsn_selection(struct wpa_state_machine *sm, const u8 *ie,
|
||||
size_t len);
|
||||
void wpa_auth_set_dpp_z(struct wpa_state_machine *sm, const struct wpabuf *z);
|
||||
void wpa_auth_set_ssid_protection(struct wpa_state_machine *sm, bool val);
|
||||
void wpa_auth_set_transition_disable(struct wpa_authenticator *wpa_auth,
|
||||
u8 val);
|
||||
|
||||
|
@ -639,12 +667,20 @@ void wpa_auth_set_ocv_override_freq(struct wpa_authenticator *wpa_auth,
|
|||
|
||||
void wpa_auth_sta_radius_psk_resp(struct wpa_state_machine *sm, bool success);
|
||||
|
||||
void wpa_auth_set_ml_info(struct wpa_state_machine *sm, const u8 *mld_addr,
|
||||
void wpa_auth_set_ml_info(struct wpa_state_machine *sm,
|
||||
u8 mld_assoc_link_id, struct mld_info *info);
|
||||
void wpa_auth_ml_get_rsn_info(struct wpa_authenticator *a,
|
||||
struct wpa_auth_ml_link_rsn_info *info);
|
||||
void wpa_auth_ml_get_key_info(struct wpa_authenticator *a,
|
||||
struct wpa_auth_ml_link_key_info *info,
|
||||
bool mgmt_frame_prot, bool beacon_prot);
|
||||
bool mgmt_frame_prot, bool beacon_prot,
|
||||
bool rekey);
|
||||
|
||||
void wpa_release_link_auth_ref(struct wpa_state_machine *sm,
|
||||
int release_link_id);
|
||||
|
||||
#define for_each_sm_auth(sm, link_id) \
|
||||
for (link_id = 0; link_id < MAX_NUM_MLD_LINKS; link_id++) \
|
||||
if (sm->mld_links[link_id].valid && \
|
||||
sm->mld_links[link_id].wpa_auth && \
|
||||
sm->wpa_auth != sm->mld_links[link_id].wpa_auth)
|
||||
|
||||
#endif /* WPA_AUTH_H */
|
||||
|
|
|
@ -3442,9 +3442,9 @@ out:
|
|||
}
|
||||
|
||||
|
||||
void wpa_ft_process_auth(struct wpa_state_machine *sm, const u8 *bssid,
|
||||
void wpa_ft_process_auth(struct wpa_state_machine *sm,
|
||||
u16 auth_transaction, const u8 *ies, size_t ies_len,
|
||||
void (*cb)(void *ctx, const u8 *dst, const u8 *bssid,
|
||||
void (*cb)(void *ctx, const u8 *dst,
|
||||
u16 auth_transaction, u16 status,
|
||||
const u8 *ies, size_t ies_len),
|
||||
void *ctx)
|
||||
|
@ -3462,7 +3462,8 @@ void wpa_ft_process_auth(struct wpa_state_machine *sm, const u8 *bssid,
|
|||
|
||||
wpa_printf(MSG_DEBUG, "FT: Received authentication frame: STA=" MACSTR
|
||||
" BSSID=" MACSTR " transaction=%d",
|
||||
MAC2STR(sm->addr), MAC2STR(bssid), auth_transaction);
|
||||
MAC2STR(sm->addr), MAC2STR(sm->wpa_auth->addr),
|
||||
auth_transaction);
|
||||
sm->ft_pending_cb = cb;
|
||||
sm->ft_pending_cb_ctx = ctx;
|
||||
sm->ft_pending_auth_transaction = auth_transaction;
|
||||
|
@ -3480,8 +3481,7 @@ void wpa_ft_process_auth(struct wpa_state_machine *sm, const u8 *bssid,
|
|||
MAC2STR(sm->addr), auth_transaction + 1, status,
|
||||
status2str(status));
|
||||
wpa_hexdump(MSG_DEBUG, "FT: Response IEs", resp_ies, resp_ies_len);
|
||||
cb(ctx, sm->addr, bssid, auth_transaction + 1, status,
|
||||
resp_ies, resp_ies_len);
|
||||
cb(ctx, sm->addr, auth_transaction + 1, status, resp_ies, resp_ies_len);
|
||||
os_free(resp_ies);
|
||||
}
|
||||
|
||||
|
@ -3810,7 +3810,7 @@ int wpa_ft_action_rx(struct wpa_state_machine *sm, const u8 *data, size_t len)
|
|||
}
|
||||
|
||||
|
||||
static void wpa_ft_rrb_rx_request_cb(void *ctx, const u8 *dst, const u8 *bssid,
|
||||
static void wpa_ft_rrb_rx_request_cb(void *ctx, const u8 *dst,
|
||||
u16 auth_transaction, u16 resp,
|
||||
const u8 *ies, size_t ies_len)
|
||||
{
|
||||
|
@ -4339,7 +4339,7 @@ static void ft_finish_pull(struct wpa_state_machine *sm)
|
|||
wpa_printf(MSG_DEBUG, "FT: Postponed auth callback result for " MACSTR
|
||||
" - status %u", MAC2STR(sm->addr), status);
|
||||
|
||||
sm->ft_pending_cb(sm->ft_pending_cb_ctx, sm->addr, sm->wpa_auth->addr,
|
||||
sm->ft_pending_cb(sm->ft_pending_cb_ctx, sm->addr,
|
||||
sm->ft_pending_auth_transaction + 1, status,
|
||||
resp_ies, resp_ies_len);
|
||||
os_free(resp_ies);
|
||||
|
|
|
@ -45,6 +45,8 @@ static void hostapd_wpa_auth_conf(struct hostapd_bss_config *conf,
|
|||
wconf->wpa = conf->wpa;
|
||||
wconf->extended_key_id = conf->extended_key_id;
|
||||
wconf->wpa_key_mgmt = conf->wpa_key_mgmt;
|
||||
wconf->rsn_override_key_mgmt = conf->rsn_override_key_mgmt;
|
||||
wconf->rsn_override_key_mgmt_2 = conf->rsn_override_key_mgmt_2;
|
||||
wconf->wpa_pairwise = conf->wpa_pairwise;
|
||||
wconf->wpa_group = conf->wpa_group;
|
||||
wconf->wpa_group_rekey = conf->wpa_group_rekey;
|
||||
|
@ -56,6 +58,8 @@ static void hostapd_wpa_auth_conf(struct hostapd_bss_config *conf,
|
|||
conf->wpa_disable_eapol_key_retries;
|
||||
wconf->wpa_pairwise_update_count = conf->wpa_pairwise_update_count;
|
||||
wconf->rsn_pairwise = conf->rsn_pairwise;
|
||||
wconf->rsn_override_pairwise = conf->rsn_override_pairwise;
|
||||
wconf->rsn_override_pairwise_2 = conf->rsn_override_pairwise_2;
|
||||
wconf->rsn_preauth = conf->rsn_preauth;
|
||||
wconf->eapol_version = conf->eapol_version;
|
||||
#ifdef CONFIG_MACSEC
|
||||
|
@ -70,14 +74,17 @@ static void hostapd_wpa_auth_conf(struct hostapd_bss_config *conf,
|
|||
#endif /* CONFIG_OCV */
|
||||
wconf->okc = conf->okc;
|
||||
wconf->ieee80211w = conf->ieee80211w;
|
||||
wconf->rsn_override_mfp = conf->rsn_override_mfp;
|
||||
wconf->rsn_override_mfp_2 = conf->rsn_override_mfp_2;
|
||||
wconf->beacon_prot = conf->beacon_prot;
|
||||
wconf->group_mgmt_cipher = conf->group_mgmt_cipher;
|
||||
wconf->sae_require_mfp = conf->sae_require_mfp;
|
||||
#ifdef CONFIG_IEEE80211R_AP
|
||||
wconf->ssid_protection = conf->ssid_protection;
|
||||
wconf->ssid_len = conf->ssid.ssid_len;
|
||||
if (wconf->ssid_len > SSID_MAX_LEN)
|
||||
wconf->ssid_len = SSID_MAX_LEN;
|
||||
os_memcpy(wconf->ssid, conf->ssid.ssid, wconf->ssid_len);
|
||||
#ifdef CONFIG_IEEE80211R_AP
|
||||
os_memcpy(wconf->mobility_domain, conf->mobility_domain,
|
||||
MOBILITY_DOMAIN_ID_LEN);
|
||||
if (conf->nas_identifier &&
|
||||
|
@ -125,6 +132,46 @@ static void hostapd_wpa_auth_conf(struct hostapd_bss_config *conf,
|
|||
wpabuf_head(conf->own_ie_override),
|
||||
wconf->own_ie_override_len);
|
||||
}
|
||||
if (conf->rsne_override &&
|
||||
wpabuf_len(conf->rsne_override) <= MAX_OWN_IE_OVERRIDE) {
|
||||
wconf->rsne_override_len = wpabuf_len(conf->rsne_override);
|
||||
os_memcpy(wconf->rsne_override,
|
||||
wpabuf_head(conf->rsne_override),
|
||||
wconf->rsne_override_len);
|
||||
wconf->rsne_override_set = true;
|
||||
}
|
||||
if (conf->rsnoe_override &&
|
||||
wpabuf_len(conf->rsnoe_override) <= MAX_OWN_IE_OVERRIDE) {
|
||||
wconf->rsnoe_override_len = wpabuf_len(conf->rsnoe_override);
|
||||
os_memcpy(wconf->rsnoe_override,
|
||||
wpabuf_head(conf->rsnoe_override),
|
||||
wconf->rsnoe_override_len);
|
||||
wconf->rsnoe_override_set = true;
|
||||
}
|
||||
if (conf->rsno2e_override &&
|
||||
wpabuf_len(conf->rsno2e_override) <= MAX_OWN_IE_OVERRIDE) {
|
||||
wconf->rsno2e_override_len = wpabuf_len(conf->rsno2e_override);
|
||||
os_memcpy(wconf->rsno2e_override,
|
||||
wpabuf_head(conf->rsno2e_override),
|
||||
wconf->rsno2e_override_len);
|
||||
wconf->rsno2e_override_set = true;
|
||||
}
|
||||
if (conf->rsnxe_override &&
|
||||
wpabuf_len(conf->rsnxe_override) <= MAX_OWN_IE_OVERRIDE) {
|
||||
wconf->rsnxe_override_len = wpabuf_len(conf->rsnxe_override);
|
||||
os_memcpy(wconf->rsnxe_override,
|
||||
wpabuf_head(conf->rsnxe_override),
|
||||
wconf->rsnxe_override_len);
|
||||
wconf->rsnxe_override_set = true;
|
||||
}
|
||||
if (conf->rsnxoe_override &&
|
||||
wpabuf_len(conf->rsnxoe_override) <= MAX_OWN_IE_OVERRIDE) {
|
||||
wconf->rsnxoe_override_len = wpabuf_len(conf->rsnxoe_override);
|
||||
os_memcpy(wconf->rsnxoe_override,
|
||||
wpabuf_head(conf->rsnxoe_override),
|
||||
wconf->rsnxoe_override_len);
|
||||
wconf->rsnxoe_override_set = true;
|
||||
}
|
||||
if (conf->rsne_override_eapol &&
|
||||
wpabuf_len(conf->rsne_override_eapol) <= MAX_OWN_IE_OVERRIDE) {
|
||||
wconf->rsne_override_eapol_set = 1;
|
||||
|
@ -189,6 +236,7 @@ static void hostapd_wpa_auth_conf(struct hostapd_bss_config *conf,
|
|||
if (conf->eapol_m3_elements)
|
||||
wconf->eapol_m3_elements = wpabuf_dup(conf->eapol_m3_elements);
|
||||
wconf->eapol_m3_no_encrypt = conf->eapol_m3_no_encrypt;
|
||||
wconf->eapol_key_reserved_random = conf->eapol_key_reserved_random;
|
||||
#endif /* CONFIG_TESTING_OPTIONS */
|
||||
#ifdef CONFIG_P2P
|
||||
os_memcpy(wconf->ip_addr_go, conf->ip_addr_go, 4);
|
||||
|
@ -224,6 +272,11 @@ static void hostapd_wpa_auth_conf(struct hostapd_bss_config *conf,
|
|||
#endif /* CONFIG_PASN */
|
||||
|
||||
wconf->radius_psk = conf->wpa_psk_radius == PSK_RADIUS_DURING_4WAY_HS;
|
||||
wconf->no_disconnect_on_group_keyerror =
|
||||
conf->bss_max_idle && conf->ap_max_inactivity &&
|
||||
conf->no_disconnect_on_group_keyerror;
|
||||
|
||||
wconf->rsn_override_omit_rsnxe = conf->rsn_override_omit_rsnxe;
|
||||
}
|
||||
|
||||
|
||||
|
@ -1533,54 +1586,12 @@ static int hostapd_set_ltf_keyseed(void *ctx, const u8 *peer_addr,
|
|||
|
||||
#ifdef CONFIG_IEEE80211BE
|
||||
|
||||
static int hostapd_wpa_auth_get_ml_rsn_info(void *ctx,
|
||||
struct wpa_auth_ml_rsn_info *info)
|
||||
{
|
||||
struct hostapd_data *hapd = ctx;
|
||||
unsigned int i, j;
|
||||
|
||||
wpa_printf(MSG_DEBUG, "WPA_AUTH: MLD: Get RSN info CB: n_mld_links=%u",
|
||||
info->n_mld_links);
|
||||
|
||||
if (!hapd->conf->mld_ap || !hapd->iface || !hapd->iface->interfaces)
|
||||
return -1;
|
||||
|
||||
for (i = 0; i < info->n_mld_links; i++) {
|
||||
unsigned int link_id = info->links[i].link_id;
|
||||
|
||||
wpa_printf(MSG_DEBUG,
|
||||
"WPA_AUTH: MLD: Get link RSN CB: link_id=%u",
|
||||
link_id);
|
||||
|
||||
for (j = 0; j < hapd->iface->interfaces->count; j++) {
|
||||
struct hostapd_iface *iface =
|
||||
hapd->iface->interfaces->iface[j];
|
||||
|
||||
if (!iface->bss[0]->conf->mld_ap ||
|
||||
hapd->conf->mld_id != iface->bss[0]->conf->mld_id ||
|
||||
link_id != iface->bss[0]->mld_link_id ||
|
||||
!iface->bss[0]->wpa_auth)
|
||||
continue;
|
||||
|
||||
wpa_auth_ml_get_rsn_info(iface->bss[0]->wpa_auth,
|
||||
&info->links[i]);
|
||||
break;
|
||||
}
|
||||
|
||||
if (j == hapd->iface->interfaces->count)
|
||||
wpa_printf(MSG_DEBUG,
|
||||
"WPA_AUTH: MLD: link=%u not found", link_id);
|
||||
}
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
|
||||
static int hostapd_wpa_auth_get_ml_key_info(void *ctx,
|
||||
struct wpa_auth_ml_key_info *info)
|
||||
struct wpa_auth_ml_key_info *info,
|
||||
bool rekey)
|
||||
{
|
||||
struct hostapd_data *hapd = ctx;
|
||||
unsigned int i, j;
|
||||
unsigned int i;
|
||||
|
||||
wpa_printf(MSG_DEBUG, "WPA_AUTH: MLD: Get key info CB: n_mld_links=%u",
|
||||
info->n_mld_links);
|
||||
|
@ -1589,30 +1600,37 @@ static int hostapd_wpa_auth_get_ml_key_info(void *ctx,
|
|||
return -1;
|
||||
|
||||
for (i = 0; i < info->n_mld_links; i++) {
|
||||
struct hostapd_data *bss;
|
||||
u8 link_id = info->links[i].link_id;
|
||||
bool link_bss_found = false;
|
||||
|
||||
wpa_printf(MSG_DEBUG,
|
||||
"WPA_AUTH: MLD: Get link info CB: link_id=%u",
|
||||
link_id);
|
||||
|
||||
for (j = 0; j < hapd->iface->interfaces->count; j++) {
|
||||
struct hostapd_iface *iface =
|
||||
hapd->iface->interfaces->iface[j];
|
||||
|
||||
if (!iface->bss[0]->conf->mld_ap ||
|
||||
hapd->conf->mld_id != iface->bss[0]->conf->mld_id ||
|
||||
link_id != iface->bss[0]->mld_link_id ||
|
||||
!iface->bss[0]->wpa_auth)
|
||||
continue;
|
||||
|
||||
wpa_auth_ml_get_key_info(iface->bss[0]->wpa_auth,
|
||||
if (hapd->mld_link_id == link_id) {
|
||||
wpa_auth_ml_get_key_info(hapd->wpa_auth,
|
||||
&info->links[i],
|
||||
info->mgmt_frame_prot,
|
||||
info->beacon_prot);
|
||||
info->beacon_prot,
|
||||
rekey);
|
||||
continue;
|
||||
}
|
||||
|
||||
for_each_mld_link(bss, hapd) {
|
||||
if (bss == hapd || bss->mld_link_id != link_id)
|
||||
continue;
|
||||
|
||||
wpa_auth_ml_get_key_info(bss->wpa_auth,
|
||||
&info->links[i],
|
||||
info->mgmt_frame_prot,
|
||||
info->beacon_prot,
|
||||
rekey);
|
||||
link_bss_found = true;
|
||||
break;
|
||||
}
|
||||
|
||||
if (j == hapd->iface->interfaces->count)
|
||||
if (!link_bss_found)
|
||||
wpa_printf(MSG_DEBUG,
|
||||
"WPA_AUTH: MLD: link=%u not found", link_id);
|
||||
}
|
||||
|
@ -1688,7 +1706,6 @@ int hostapd_setup_wpa(struct hostapd_data *hapd)
|
|||
.set_ltf_keyseed = hostapd_set_ltf_keyseed,
|
||||
#endif /* CONFIG_PASN */
|
||||
#ifdef CONFIG_IEEE80211BE
|
||||
.get_ml_rsn_info = hostapd_wpa_auth_get_ml_rsn_info,
|
||||
.get_ml_key_info = hostapd_wpa_auth_get_ml_key_info,
|
||||
#endif /* CONFIG_IEEE80211BE */
|
||||
.get_drv_flags = hostapd_wpa_auth_get_drv_flags,
|
||||
|
@ -1739,6 +1756,27 @@ int hostapd_setup_wpa(struct hostapd_data *hapd)
|
|||
!!(hapd->iface->drv_flags2 &
|
||||
WPA_DRIVER_FLAGS2_PROT_RANGE_NEG_AP);
|
||||
|
||||
#ifdef CONFIG_IEEE80211BE
|
||||
_conf.mld_addr = NULL;
|
||||
_conf.link_id = -1;
|
||||
_conf.first_link_auth = NULL;
|
||||
|
||||
if (hapd->conf->mld_ap) {
|
||||
struct hostapd_data *lhapd;
|
||||
|
||||
_conf.mld_addr = hapd->mld->mld_addr;
|
||||
_conf.link_id = hapd->mld_link_id;
|
||||
|
||||
for_each_mld_link(lhapd, hapd) {
|
||||
if (lhapd == hapd)
|
||||
continue;
|
||||
|
||||
if (lhapd->wpa_auth)
|
||||
_conf.first_link_auth = lhapd->wpa_auth;
|
||||
}
|
||||
}
|
||||
#endif /* CONFIG_IEEE80211BE */
|
||||
|
||||
hapd->wpa_auth = wpa_init(hapd->own_addr, &_conf, &cb, hapd);
|
||||
if (hapd->wpa_auth == NULL) {
|
||||
wpa_printf(MSG_ERROR, "WPA initialization failed.");
|
||||
|
|
|
@ -111,6 +111,8 @@ struct wpa_state_machine {
|
|||
size_t wpa_ie_len;
|
||||
u8 *rsnxe;
|
||||
size_t rsnxe_len;
|
||||
u8 *rsn_selection;
|
||||
size_t rsn_selection_len;
|
||||
|
||||
enum {
|
||||
WPA_VERSION_NO_WPA = 0 /* WPA not used */,
|
||||
|
@ -124,6 +126,9 @@ struct wpa_state_machine {
|
|||
u32 dot11RSNAStatsTKIPLocalMICFailures;
|
||||
u32 dot11RSNAStatsTKIPRemoteMICFailures;
|
||||
|
||||
bool rsn_override;
|
||||
bool rsn_override_2;
|
||||
|
||||
#ifdef CONFIG_IEEE80211R_AP
|
||||
u8 xxkey[PMK_LEN_MAX]; /* PSK or the second 256 bits of MSK, or the
|
||||
* first 384 bits of MSK */
|
||||
|
@ -136,7 +141,7 @@ struct wpa_state_machine {
|
|||
size_t r0kh_id_len;
|
||||
u8 *assoc_resp_ftie;
|
||||
|
||||
void (*ft_pending_cb)(void *ctx, const u8 *dst, const u8 *bssid,
|
||||
void (*ft_pending_cb)(void *ctx, const u8 *dst,
|
||||
u16 auth_transaction, u16 status,
|
||||
const u8 *ies, size_t ies_len);
|
||||
void *ft_pending_cb_ctx;
|
||||
|
@ -172,7 +177,6 @@ struct wpa_state_machine {
|
|||
#endif /* CONFIG_TESTING_OPTIONS */
|
||||
|
||||
#ifdef CONFIG_IEEE80211BE
|
||||
u8 own_mld_addr[ETH_ALEN];
|
||||
u8 peer_mld_addr[ETH_ALEN];
|
||||
s8 mld_assoc_link_id;
|
||||
u8 n_mld_affiliated_links;
|
||||
|
@ -180,14 +184,12 @@ struct wpa_state_machine {
|
|||
struct mld_link {
|
||||
bool valid;
|
||||
u8 peer_addr[ETH_ALEN];
|
||||
u8 own_addr[ETH_ALEN];
|
||||
|
||||
const u8 *rsne;
|
||||
size_t rsne_len;
|
||||
const u8 *rsnxe;
|
||||
size_t rsnxe_len;
|
||||
struct wpa_authenticator *wpa_auth;
|
||||
} mld_links[MAX_NUM_MLD_LINKS];
|
||||
#endif /* CONFIG_IEEE80211BE */
|
||||
|
||||
bool ssid_protection;
|
||||
};
|
||||
|
||||
|
||||
|
@ -262,6 +264,13 @@ struct wpa_authenticator {
|
|||
#ifdef CONFIG_P2P
|
||||
struct bitfield *ip_pool;
|
||||
#endif /* CONFIG_P2P */
|
||||
|
||||
#ifdef CONFIG_IEEE80211BE
|
||||
bool is_ml;
|
||||
u8 mld_addr[ETH_ALEN];
|
||||
u8 link_id;
|
||||
bool primary_auth;
|
||||
#endif /* CONFIG_IEEE80211BE */
|
||||
};
|
||||
|
||||
|
||||
|
|
|
@ -89,7 +89,8 @@ static int wpa_write_wpa_ie(struct wpa_auth_config *conf, u8 *buf, size_t len)
|
|||
}
|
||||
|
||||
|
||||
static u16 wpa_own_rsn_capab(struct wpa_auth_config *conf)
|
||||
static u16 wpa_own_rsn_capab(struct wpa_auth_config *conf,
|
||||
enum mfp_options mfp)
|
||||
{
|
||||
u16 capab = 0;
|
||||
|
||||
|
@ -99,9 +100,9 @@ static u16 wpa_own_rsn_capab(struct wpa_auth_config *conf)
|
|||
/* 4 PTKSA replay counters when using WMM */
|
||||
capab |= (RSN_NUM_REPLAY_COUNTERS_16 << 2);
|
||||
}
|
||||
if (conf->ieee80211w != NO_MGMT_FRAME_PROTECTION) {
|
||||
if (mfp != NO_MGMT_FRAME_PROTECTION) {
|
||||
capab |= WPA_CAPABILITY_MFPC;
|
||||
if (conf->ieee80211w == MGMT_FRAME_PROTECTION_REQUIRED)
|
||||
if (mfp == MGMT_FRAME_PROTECTION_REQUIRED)
|
||||
capab |= WPA_CAPABILITY_MFPR;
|
||||
}
|
||||
#ifdef CONFIG_OCV
|
||||
|
@ -119,24 +120,19 @@ static u16 wpa_own_rsn_capab(struct wpa_auth_config *conf)
|
|||
}
|
||||
|
||||
|
||||
int wpa_write_rsn_ie(struct wpa_auth_config *conf, u8 *buf, size_t len,
|
||||
const u8 *pmkid)
|
||||
static u8 * rsne_write_data(u8 *buf, size_t len, u8 *pos, int group,
|
||||
int pairwise, int key_mgmt, u16 rsn_capab,
|
||||
const u8 *pmkid, enum mfp_options mfp,
|
||||
int group_mgmt_cipher)
|
||||
{
|
||||
struct rsn_ie_hdr *hdr;
|
||||
int num_suites, res;
|
||||
u8 *pos, *count;
|
||||
u8 *count;
|
||||
u32 suite;
|
||||
|
||||
hdr = (struct rsn_ie_hdr *) buf;
|
||||
hdr->elem_id = WLAN_EID_RSN;
|
||||
WPA_PUT_LE16(hdr->version, RSN_VERSION);
|
||||
pos = (u8 *) (hdr + 1);
|
||||
|
||||
suite = wpa_cipher_to_suite(WPA_PROTO_RSN, conf->wpa_group);
|
||||
suite = wpa_cipher_to_suite(WPA_PROTO_RSN, group);
|
||||
if (suite == 0) {
|
||||
wpa_printf(MSG_DEBUG, "Invalid group cipher (%d).",
|
||||
conf->wpa_group);
|
||||
return -1;
|
||||
wpa_printf(MSG_DEBUG, "Invalid group cipher (%d).", group);
|
||||
return NULL;
|
||||
}
|
||||
RSN_SELECTOR_PUT(pos, suite);
|
||||
pos += RSN_SELECTOR_LEN;
|
||||
|
@ -153,7 +149,7 @@ int wpa_write_rsn_ie(struct wpa_auth_config *conf, u8 *buf, size_t len,
|
|||
}
|
||||
#endif /* CONFIG_RSN_TESTING */
|
||||
|
||||
res = rsn_cipher_put_suites(pos, conf->rsn_pairwise);
|
||||
res = rsn_cipher_put_suites(pos, pairwise);
|
||||
num_suites += res;
|
||||
pos += res * RSN_SELECTOR_LEN;
|
||||
|
||||
|
@ -167,8 +163,8 @@ int wpa_write_rsn_ie(struct wpa_auth_config *conf, u8 *buf, size_t len,
|
|||
|
||||
if (num_suites == 0) {
|
||||
wpa_printf(MSG_DEBUG, "Invalid pairwise cipher (%d).",
|
||||
conf->rsn_pairwise);
|
||||
return -1;
|
||||
pairwise);
|
||||
return NULL;
|
||||
}
|
||||
WPA_PUT_LE16(count, num_suites);
|
||||
|
||||
|
@ -184,102 +180,102 @@ int wpa_write_rsn_ie(struct wpa_auth_config *conf, u8 *buf, size_t len,
|
|||
}
|
||||
#endif /* CONFIG_RSN_TESTING */
|
||||
|
||||
if (conf->wpa_key_mgmt & WPA_KEY_MGMT_IEEE8021X) {
|
||||
if (key_mgmt & WPA_KEY_MGMT_IEEE8021X) {
|
||||
RSN_SELECTOR_PUT(pos, RSN_AUTH_KEY_MGMT_UNSPEC_802_1X);
|
||||
pos += RSN_SELECTOR_LEN;
|
||||
num_suites++;
|
||||
}
|
||||
if (conf->wpa_key_mgmt & WPA_KEY_MGMT_PSK) {
|
||||
if (key_mgmt & WPA_KEY_MGMT_PSK) {
|
||||
RSN_SELECTOR_PUT(pos, RSN_AUTH_KEY_MGMT_PSK_OVER_802_1X);
|
||||
pos += RSN_SELECTOR_LEN;
|
||||
num_suites++;
|
||||
}
|
||||
#ifdef CONFIG_IEEE80211R_AP
|
||||
if (conf->wpa_key_mgmt & WPA_KEY_MGMT_FT_IEEE8021X) {
|
||||
if (key_mgmt & WPA_KEY_MGMT_FT_IEEE8021X) {
|
||||
RSN_SELECTOR_PUT(pos, RSN_AUTH_KEY_MGMT_FT_802_1X);
|
||||
pos += RSN_SELECTOR_LEN;
|
||||
num_suites++;
|
||||
}
|
||||
#ifdef CONFIG_SHA384
|
||||
if (conf->wpa_key_mgmt & WPA_KEY_MGMT_FT_IEEE8021X_SHA384) {
|
||||
if (key_mgmt & WPA_KEY_MGMT_FT_IEEE8021X_SHA384) {
|
||||
RSN_SELECTOR_PUT(pos, RSN_AUTH_KEY_MGMT_FT_802_1X_SHA384);
|
||||
pos += RSN_SELECTOR_LEN;
|
||||
num_suites++;
|
||||
}
|
||||
#endif /* CONFIG_SHA384 */
|
||||
if (conf->wpa_key_mgmt & WPA_KEY_MGMT_FT_PSK) {
|
||||
if (key_mgmt & WPA_KEY_MGMT_FT_PSK) {
|
||||
RSN_SELECTOR_PUT(pos, RSN_AUTH_KEY_MGMT_FT_PSK);
|
||||
pos += RSN_SELECTOR_LEN;
|
||||
num_suites++;
|
||||
}
|
||||
#endif /* CONFIG_IEEE80211R_AP */
|
||||
#ifdef CONFIG_SHA384
|
||||
if (conf->wpa_key_mgmt & WPA_KEY_MGMT_IEEE8021X_SHA384) {
|
||||
if (key_mgmt & WPA_KEY_MGMT_IEEE8021X_SHA384) {
|
||||
RSN_SELECTOR_PUT(pos, RSN_AUTH_KEY_MGMT_802_1X_SHA384);
|
||||
pos += RSN_SELECTOR_LEN;
|
||||
num_suites++;
|
||||
}
|
||||
#endif /* CONFIG_SHA384 */
|
||||
if (conf->wpa_key_mgmt & WPA_KEY_MGMT_IEEE8021X_SHA256) {
|
||||
if (key_mgmt & WPA_KEY_MGMT_IEEE8021X_SHA256) {
|
||||
RSN_SELECTOR_PUT(pos, RSN_AUTH_KEY_MGMT_802_1X_SHA256);
|
||||
pos += RSN_SELECTOR_LEN;
|
||||
num_suites++;
|
||||
}
|
||||
if (conf->wpa_key_mgmt & WPA_KEY_MGMT_PSK_SHA256) {
|
||||
if (key_mgmt & WPA_KEY_MGMT_PSK_SHA256) {
|
||||
RSN_SELECTOR_PUT(pos, RSN_AUTH_KEY_MGMT_PSK_SHA256);
|
||||
pos += RSN_SELECTOR_LEN;
|
||||
num_suites++;
|
||||
}
|
||||
#ifdef CONFIG_SAE
|
||||
if (conf->wpa_key_mgmt & WPA_KEY_MGMT_SAE) {
|
||||
if (key_mgmt & WPA_KEY_MGMT_SAE) {
|
||||
RSN_SELECTOR_PUT(pos, RSN_AUTH_KEY_MGMT_SAE);
|
||||
pos += RSN_SELECTOR_LEN;
|
||||
num_suites++;
|
||||
}
|
||||
if (conf->wpa_key_mgmt & WPA_KEY_MGMT_SAE_EXT_KEY) {
|
||||
if (key_mgmt & WPA_KEY_MGMT_SAE_EXT_KEY) {
|
||||
RSN_SELECTOR_PUT(pos, RSN_AUTH_KEY_MGMT_SAE_EXT_KEY);
|
||||
pos += RSN_SELECTOR_LEN;
|
||||
num_suites++;
|
||||
}
|
||||
if (conf->wpa_key_mgmt & WPA_KEY_MGMT_FT_SAE) {
|
||||
if (key_mgmt & WPA_KEY_MGMT_FT_SAE) {
|
||||
RSN_SELECTOR_PUT(pos, RSN_AUTH_KEY_MGMT_FT_SAE);
|
||||
pos += RSN_SELECTOR_LEN;
|
||||
num_suites++;
|
||||
}
|
||||
if (conf->wpa_key_mgmt & WPA_KEY_MGMT_FT_SAE_EXT_KEY) {
|
||||
if (key_mgmt & WPA_KEY_MGMT_FT_SAE_EXT_KEY) {
|
||||
RSN_SELECTOR_PUT(pos, RSN_AUTH_KEY_MGMT_FT_SAE_EXT_KEY);
|
||||
pos += RSN_SELECTOR_LEN;
|
||||
num_suites++;
|
||||
}
|
||||
#endif /* CONFIG_SAE */
|
||||
if (conf->wpa_key_mgmt & WPA_KEY_MGMT_IEEE8021X_SUITE_B) {
|
||||
if (key_mgmt & WPA_KEY_MGMT_IEEE8021X_SUITE_B) {
|
||||
RSN_SELECTOR_PUT(pos, RSN_AUTH_KEY_MGMT_802_1X_SUITE_B);
|
||||
pos += RSN_SELECTOR_LEN;
|
||||
num_suites++;
|
||||
}
|
||||
if (conf->wpa_key_mgmt & WPA_KEY_MGMT_IEEE8021X_SUITE_B_192) {
|
||||
if (key_mgmt & WPA_KEY_MGMT_IEEE8021X_SUITE_B_192) {
|
||||
RSN_SELECTOR_PUT(pos, RSN_AUTH_KEY_MGMT_802_1X_SUITE_B_192);
|
||||
pos += RSN_SELECTOR_LEN;
|
||||
num_suites++;
|
||||
}
|
||||
#ifdef CONFIG_FILS
|
||||
if (conf->wpa_key_mgmt & WPA_KEY_MGMT_FILS_SHA256) {
|
||||
if (key_mgmt & WPA_KEY_MGMT_FILS_SHA256) {
|
||||
RSN_SELECTOR_PUT(pos, RSN_AUTH_KEY_MGMT_FILS_SHA256);
|
||||
pos += RSN_SELECTOR_LEN;
|
||||
num_suites++;
|
||||
}
|
||||
if (conf->wpa_key_mgmt & WPA_KEY_MGMT_FILS_SHA384) {
|
||||
if (key_mgmt & WPA_KEY_MGMT_FILS_SHA384) {
|
||||
RSN_SELECTOR_PUT(pos, RSN_AUTH_KEY_MGMT_FILS_SHA384);
|
||||
pos += RSN_SELECTOR_LEN;
|
||||
num_suites++;
|
||||
}
|
||||
#ifdef CONFIG_IEEE80211R_AP
|
||||
if (conf->wpa_key_mgmt & WPA_KEY_MGMT_FT_FILS_SHA256) {
|
||||
if (key_mgmt & WPA_KEY_MGMT_FT_FILS_SHA256) {
|
||||
RSN_SELECTOR_PUT(pos, RSN_AUTH_KEY_MGMT_FT_FILS_SHA256);
|
||||
pos += RSN_SELECTOR_LEN;
|
||||
num_suites++;
|
||||
}
|
||||
if (conf->wpa_key_mgmt & WPA_KEY_MGMT_FT_FILS_SHA384) {
|
||||
if (key_mgmt & WPA_KEY_MGMT_FT_FILS_SHA384) {
|
||||
RSN_SELECTOR_PUT(pos, RSN_AUTH_KEY_MGMT_FT_FILS_SHA384);
|
||||
pos += RSN_SELECTOR_LEN;
|
||||
num_suites++;
|
||||
|
@ -287,28 +283,28 @@ int wpa_write_rsn_ie(struct wpa_auth_config *conf, u8 *buf, size_t len,
|
|||
#endif /* CONFIG_IEEE80211R_AP */
|
||||
#endif /* CONFIG_FILS */
|
||||
#ifdef CONFIG_OWE
|
||||
if (conf->wpa_key_mgmt & WPA_KEY_MGMT_OWE) {
|
||||
if (key_mgmt & WPA_KEY_MGMT_OWE) {
|
||||
RSN_SELECTOR_PUT(pos, RSN_AUTH_KEY_MGMT_OWE);
|
||||
pos += RSN_SELECTOR_LEN;
|
||||
num_suites++;
|
||||
}
|
||||
#endif /* CONFIG_OWE */
|
||||
#ifdef CONFIG_DPP
|
||||
if (conf->wpa_key_mgmt & WPA_KEY_MGMT_DPP) {
|
||||
if (key_mgmt & WPA_KEY_MGMT_DPP) {
|
||||
RSN_SELECTOR_PUT(pos, RSN_AUTH_KEY_MGMT_DPP);
|
||||
pos += RSN_SELECTOR_LEN;
|
||||
num_suites++;
|
||||
}
|
||||
#endif /* CONFIG_DPP */
|
||||
#ifdef CONFIG_HS20
|
||||
if (conf->wpa_key_mgmt & WPA_KEY_MGMT_OSEN) {
|
||||
if (key_mgmt & WPA_KEY_MGMT_OSEN) {
|
||||
RSN_SELECTOR_PUT(pos, RSN_AUTH_KEY_MGMT_OSEN);
|
||||
pos += RSN_SELECTOR_LEN;
|
||||
num_suites++;
|
||||
}
|
||||
#endif /* CONFIG_HS20 */
|
||||
#ifdef CONFIG_PASN
|
||||
if (conf->wpa_key_mgmt & WPA_KEY_MGMT_PASN) {
|
||||
if (key_mgmt & WPA_KEY_MGMT_PASN) {
|
||||
RSN_SELECTOR_PUT(pos, RSN_AUTH_KEY_MGMT_PASN);
|
||||
pos += RSN_SELECTOR_LEN;
|
||||
num_suites++;
|
||||
|
@ -325,18 +321,18 @@ int wpa_write_rsn_ie(struct wpa_auth_config *conf, u8 *buf, size_t len,
|
|||
|
||||
if (num_suites == 0) {
|
||||
wpa_printf(MSG_DEBUG, "Invalid key management type (%d).",
|
||||
conf->wpa_key_mgmt);
|
||||
return -1;
|
||||
key_mgmt);
|
||||
return NULL;
|
||||
}
|
||||
WPA_PUT_LE16(count, num_suites);
|
||||
|
||||
/* RSN Capabilities */
|
||||
WPA_PUT_LE16(pos, wpa_own_rsn_capab(conf));
|
||||
WPA_PUT_LE16(pos, rsn_capab);
|
||||
pos += 2;
|
||||
|
||||
if (pmkid) {
|
||||
if (2 + PMKID_LEN > buf + len - pos)
|
||||
return -1;
|
||||
return NULL;
|
||||
/* PMKID Count */
|
||||
WPA_PUT_LE16(pos, 1);
|
||||
pos += 2;
|
||||
|
@ -344,18 +340,19 @@ int wpa_write_rsn_ie(struct wpa_auth_config *conf, u8 *buf, size_t len,
|
|||
pos += PMKID_LEN;
|
||||
}
|
||||
|
||||
if (conf->ieee80211w != NO_MGMT_FRAME_PROTECTION &&
|
||||
conf->group_mgmt_cipher != WPA_CIPHER_AES_128_CMAC) {
|
||||
|
||||
if (mfp != NO_MGMT_FRAME_PROTECTION &&
|
||||
group_mgmt_cipher != WPA_CIPHER_AES_128_CMAC) {
|
||||
if (2 + 4 > buf + len - pos)
|
||||
return -1;
|
||||
if (pmkid == NULL) {
|
||||
return NULL;
|
||||
if (!pmkid) {
|
||||
/* PMKID Count */
|
||||
WPA_PUT_LE16(pos, 0);
|
||||
pos += 2;
|
||||
}
|
||||
|
||||
/* Management Group Cipher Suite */
|
||||
switch (conf->group_mgmt_cipher) {
|
||||
switch (group_mgmt_cipher) {
|
||||
case WPA_CIPHER_AES_128_CMAC:
|
||||
RSN_SELECTOR_PUT(pos, RSN_CIPHER_SUITE_AES_128_CMAC);
|
||||
break;
|
||||
|
@ -371,8 +368,8 @@ int wpa_write_rsn_ie(struct wpa_auth_config *conf, u8 *buf, size_t len,
|
|||
default:
|
||||
wpa_printf(MSG_DEBUG,
|
||||
"Invalid group management cipher (0x%x)",
|
||||
conf->group_mgmt_cipher);
|
||||
return -1;
|
||||
group_mgmt_cipher);
|
||||
return NULL;
|
||||
}
|
||||
pos += RSN_SELECTOR_LEN;
|
||||
}
|
||||
|
@ -384,12 +381,12 @@ int wpa_write_rsn_ie(struct wpa_auth_config *conf, u8 *buf, size_t len,
|
|||
* the element.
|
||||
*/
|
||||
int pmkid_count_set = pmkid != NULL;
|
||||
if (conf->ieee80211w != NO_MGMT_FRAME_PROTECTION)
|
||||
if (mfp != NO_MGMT_FRAME_PROTECTION)
|
||||
pmkid_count_set = 1;
|
||||
/* PMKID Count */
|
||||
WPA_PUT_LE16(pos, 0);
|
||||
pos += 2;
|
||||
if (conf->ieee80211w == NO_MGMT_FRAME_PROTECTION) {
|
||||
if (mfp == NO_MGMT_FRAME_PROTECTION) {
|
||||
/* Management Group Cipher Suite */
|
||||
RSN_SELECTOR_PUT(pos, RSN_CIPHER_SUITE_AES_128_CMAC);
|
||||
pos += RSN_SELECTOR_LEN;
|
||||
|
@ -399,6 +396,27 @@ int wpa_write_rsn_ie(struct wpa_auth_config *conf, u8 *buf, size_t len,
|
|||
pos += 17;
|
||||
}
|
||||
#endif /* CONFIG_RSN_TESTING */
|
||||
return pos;
|
||||
}
|
||||
|
||||
|
||||
int wpa_write_rsn_ie(struct wpa_auth_config *conf, u8 *buf, size_t len,
|
||||
const u8 *pmkid)
|
||||
{
|
||||
struct rsn_ie_hdr *hdr;
|
||||
u8 *pos;
|
||||
|
||||
hdr = (struct rsn_ie_hdr *) buf;
|
||||
hdr->elem_id = WLAN_EID_RSN;
|
||||
WPA_PUT_LE16(hdr->version, RSN_VERSION);
|
||||
pos = (u8 *) (hdr + 1);
|
||||
|
||||
pos = rsne_write_data(buf, len, pos, conf->wpa_group,
|
||||
conf->rsn_pairwise, conf->wpa_key_mgmt,
|
||||
wpa_own_rsn_capab(conf, conf->ieee80211w), pmkid,
|
||||
conf->ieee80211w, conf->group_mgmt_cipher);
|
||||
if (!pos)
|
||||
return -1;
|
||||
|
||||
hdr->len = (pos - buf) - 2;
|
||||
|
||||
|
@ -406,16 +424,74 @@ int wpa_write_rsn_ie(struct wpa_auth_config *conf, u8 *buf, size_t len,
|
|||
}
|
||||
|
||||
|
||||
int wpa_write_rsnxe(struct wpa_auth_config *conf, u8 *buf, size_t len)
|
||||
static int wpa_write_rsne_override(struct wpa_auth_config *conf, u8 *buf,
|
||||
size_t len)
|
||||
{
|
||||
u8 *pos = buf;
|
||||
u16 capab = 0;
|
||||
size_t flen;
|
||||
u8 *pos, *len_pos;
|
||||
|
||||
if (wpa_key_mgmt_sae(conf->wpa_key_mgmt) &&
|
||||
pos = buf;
|
||||
*pos++ = WLAN_EID_VENDOR_SPECIFIC;
|
||||
len_pos = pos++;
|
||||
|
||||
WPA_PUT_BE32(pos, RSNE_OVERRIDE_IE_VENDOR_TYPE);
|
||||
pos += 4;
|
||||
|
||||
WPA_PUT_LE16(pos, RSN_VERSION);
|
||||
pos += 2;
|
||||
|
||||
pos = rsne_write_data(buf, len, pos, conf->wpa_group,
|
||||
conf->rsn_override_pairwise,
|
||||
conf->rsn_override_key_mgmt,
|
||||
wpa_own_rsn_capab(conf, conf->rsn_override_mfp),
|
||||
NULL, conf->rsn_override_mfp,
|
||||
conf->group_mgmt_cipher);
|
||||
if (!pos)
|
||||
return -1;
|
||||
|
||||
*len_pos = (pos - buf) - 2;
|
||||
|
||||
return pos - buf;
|
||||
}
|
||||
|
||||
|
||||
static int wpa_write_rsne_override_2(struct wpa_auth_config *conf, u8 *buf,
|
||||
size_t len)
|
||||
{
|
||||
u8 *pos, *len_pos;
|
||||
|
||||
pos = buf;
|
||||
*pos++ = WLAN_EID_VENDOR_SPECIFIC;
|
||||
len_pos = pos++;
|
||||
|
||||
WPA_PUT_BE32(pos, RSNE_OVERRIDE_2_IE_VENDOR_TYPE);
|
||||
pos += 4;
|
||||
|
||||
WPA_PUT_LE16(pos, RSN_VERSION);
|
||||
pos += 2;
|
||||
|
||||
pos = rsne_write_data(buf, len, pos, conf->wpa_group,
|
||||
conf->rsn_override_pairwise_2,
|
||||
conf->rsn_override_key_mgmt_2,
|
||||
wpa_own_rsn_capab(conf, conf->rsn_override_mfp_2),
|
||||
NULL, conf->rsn_override_mfp_2,
|
||||
conf->group_mgmt_cipher);
|
||||
if (!pos)
|
||||
return -1;
|
||||
|
||||
*len_pos = (pos - buf) - 2;
|
||||
|
||||
return pos - buf;
|
||||
}
|
||||
|
||||
|
||||
static u32 rsnxe_capab(struct wpa_auth_config *conf, int key_mgmt)
|
||||
{
|
||||
u32 capab = 0;
|
||||
|
||||
if (wpa_key_mgmt_sae(key_mgmt) &&
|
||||
(conf->sae_pwe == SAE_PWE_HASH_TO_ELEMENT ||
|
||||
conf->sae_pwe == SAE_PWE_BOTH || conf->sae_pk ||
|
||||
wpa_key_mgmt_sae_ext_key(conf->wpa_key_mgmt))) {
|
||||
wpa_key_mgmt_sae_ext_key(key_mgmt))) {
|
||||
capab |= BIT(WLAN_RSNX_CAPAB_SAE_H2E);
|
||||
#ifdef CONFIG_SAE_PK
|
||||
if (conf->sae_pk)
|
||||
|
@ -429,20 +505,75 @@ int wpa_write_rsnxe(struct wpa_auth_config *conf, u8 *buf, size_t len)
|
|||
capab |= BIT(WLAN_RSNX_CAPAB_SECURE_RTT);
|
||||
if (conf->prot_range_neg)
|
||||
capab |= BIT(WLAN_RSNX_CAPAB_URNM_MFPR);
|
||||
if (conf->ssid_protection)
|
||||
capab |= BIT(WLAN_RSNX_CAPAB_SSID_PROTECTION);
|
||||
|
||||
return capab;
|
||||
}
|
||||
|
||||
|
||||
int wpa_write_rsnxe(struct wpa_auth_config *conf, u8 *buf, size_t len)
|
||||
{
|
||||
u8 *pos = buf;
|
||||
u32 capab = 0, tmp;
|
||||
size_t flen;
|
||||
|
||||
capab = rsnxe_capab(conf, conf->wpa_key_mgmt);
|
||||
|
||||
flen = (capab & 0xff00) ? 2 : 1;
|
||||
if (!capab)
|
||||
return 0; /* no supported extended RSN capabilities */
|
||||
tmp = capab;
|
||||
flen = 0;
|
||||
while (tmp) {
|
||||
flen++;
|
||||
tmp >>= 8;
|
||||
}
|
||||
if (len < 2 + flen)
|
||||
return -1;
|
||||
capab |= flen - 1; /* bit 0-3 = Field length (n - 1) */
|
||||
|
||||
*pos++ = WLAN_EID_RSNX;
|
||||
*pos++ = flen;
|
||||
*pos++ = capab & 0x00ff;
|
||||
capab >>= 8;
|
||||
if (capab)
|
||||
*pos++ = capab;
|
||||
while (capab) {
|
||||
*pos++ = capab & 0xff;
|
||||
capab >>= 8;
|
||||
}
|
||||
|
||||
return pos - buf;
|
||||
}
|
||||
|
||||
|
||||
static int wpa_write_rsnxe_override(struct wpa_auth_config *conf, u8 *buf,
|
||||
size_t len)
|
||||
{
|
||||
u8 *pos = buf;
|
||||
u32 capab, tmp;
|
||||
size_t flen;
|
||||
|
||||
capab = rsnxe_capab(conf, conf->rsn_override_key_mgmt |
|
||||
conf->rsn_override_key_mgmt_2);
|
||||
|
||||
if (!capab)
|
||||
return 0; /* no supported extended RSN capabilities */
|
||||
tmp = capab;
|
||||
flen = 0;
|
||||
while (tmp) {
|
||||
flen++;
|
||||
tmp >>= 8;
|
||||
}
|
||||
if (len < 2 + flen)
|
||||
return -1;
|
||||
capab |= flen - 1; /* bit 0-3 = Field length (n - 1) */
|
||||
|
||||
*pos++ = WLAN_EID_VENDOR_SPECIFIC;
|
||||
*pos++ = 4 + flen;
|
||||
WPA_PUT_BE32(pos, RSNXE_OVERRIDE_IE_VENDOR_TYPE);
|
||||
pos += 4;
|
||||
|
||||
while (capab) {
|
||||
*pos++ = capab & 0xff;
|
||||
capab >>= 8;
|
||||
}
|
||||
|
||||
return pos - buf;
|
||||
}
|
||||
|
@ -501,7 +632,7 @@ static u8 * wpa_write_osen(struct wpa_auth_config *conf, u8 *eid)
|
|||
|
||||
int wpa_auth_gen_wpa_ie(struct wpa_authenticator *wpa_auth)
|
||||
{
|
||||
u8 *pos, buf[128];
|
||||
u8 *pos, buf[1500];
|
||||
int res;
|
||||
|
||||
#ifdef CONFIG_TESTING_OPTIONS
|
||||
|
@ -527,17 +658,54 @@ int wpa_auth_gen_wpa_ie(struct wpa_authenticator *wpa_auth)
|
|||
pos = wpa_write_osen(&wpa_auth->conf, pos);
|
||||
}
|
||||
if (wpa_auth->conf.wpa & WPA_PROTO_RSN) {
|
||||
#ifdef CONFIG_TESTING_OPTIONS
|
||||
if (wpa_auth->conf.rsne_override_set) {
|
||||
wpa_hexdump(MSG_DEBUG,
|
||||
"RSN: Forced own RSNE for testing",
|
||||
wpa_auth->conf.rsne_override,
|
||||
wpa_auth->conf.rsne_override_len);
|
||||
if (sizeof(buf) - (pos - buf) <
|
||||
wpa_auth->conf.rsne_override_len)
|
||||
return -1;
|
||||
os_memcpy(pos, wpa_auth->conf.rsne_override,
|
||||
wpa_auth->conf.rsne_override_len);
|
||||
pos += wpa_auth->conf.rsne_override_len;
|
||||
goto rsnxe;
|
||||
}
|
||||
#endif /* CONFIG_TESTING_OPTIONS */
|
||||
res = wpa_write_rsn_ie(&wpa_auth->conf,
|
||||
pos, buf + sizeof(buf) - pos, NULL);
|
||||
if (res < 0)
|
||||
return res;
|
||||
pos += res;
|
||||
res = wpa_write_rsnxe(&wpa_auth->conf, pos,
|
||||
buf + sizeof(buf) - pos);
|
||||
#ifdef CONFIG_TESTING_OPTIONS
|
||||
rsnxe:
|
||||
if (wpa_auth->conf.rsnxe_override_set) {
|
||||
wpa_hexdump(MSG_DEBUG,
|
||||
"RSN: Forced own RSNXE for testing",
|
||||
wpa_auth->conf.rsnxe_override,
|
||||
wpa_auth->conf.rsnxe_override_len);
|
||||
if (sizeof(buf) - (pos - buf) <
|
||||
wpa_auth->conf.rsnxe_override_len)
|
||||
return -1;
|
||||
os_memcpy(pos, wpa_auth->conf.rsnxe_override,
|
||||
wpa_auth->conf.rsnxe_override_len);
|
||||
pos += wpa_auth->conf.rsnxe_override_len;
|
||||
goto fte;
|
||||
}
|
||||
#endif /* CONFIG_TESTING_OPTIONS */
|
||||
if (wpa_auth->conf.rsn_override_omit_rsnxe)
|
||||
res = 0;
|
||||
else
|
||||
res = wpa_write_rsnxe(&wpa_auth->conf, pos,
|
||||
buf + sizeof(buf) - pos);
|
||||
if (res < 0)
|
||||
return res;
|
||||
pos += res;
|
||||
}
|
||||
#ifdef CONFIG_TESTING_OPTIONS
|
||||
fte:
|
||||
#endif /* CONFIG_TESTING_OPTIONS */
|
||||
#ifdef CONFIG_IEEE80211R_AP
|
||||
if (wpa_key_mgmt_ft(wpa_auth->conf.wpa_key_mgmt)) {
|
||||
res = wpa_write_mdie(&wpa_auth->conf, pos,
|
||||
|
@ -554,7 +722,87 @@ int wpa_auth_gen_wpa_ie(struct wpa_authenticator *wpa_auth)
|
|||
return res;
|
||||
pos += res;
|
||||
}
|
||||
if ((wpa_auth->conf.wpa & WPA_PROTO_RSN) &&
|
||||
wpa_auth->conf.rsn_override_key_mgmt) {
|
||||
#ifdef CONFIG_TESTING_OPTIONS
|
||||
if (wpa_auth->conf.rsnoe_override_set) {
|
||||
wpa_hexdump(MSG_DEBUG,
|
||||
"RSN: Forced own RSNOE for testing",
|
||||
wpa_auth->conf.rsnoe_override,
|
||||
wpa_auth->conf.rsnoe_override_len);
|
||||
if (sizeof(buf) - (pos - buf) <
|
||||
wpa_auth->conf.rsnoe_override_len)
|
||||
return -1;
|
||||
os_memcpy(pos, wpa_auth->conf.rsnoe_override,
|
||||
wpa_auth->conf.rsnoe_override_len);
|
||||
pos += wpa_auth->conf.rsnoe_override_len;
|
||||
goto rsno2e;
|
||||
}
|
||||
#endif /* CONFIG_TESTING_OPTIONS */
|
||||
res = wpa_write_rsne_override(&wpa_auth->conf,
|
||||
pos, buf + sizeof(buf) - pos);
|
||||
if (res < 0)
|
||||
return res;
|
||||
pos += res;
|
||||
}
|
||||
#ifdef CONFIG_TESTING_OPTIONS
|
||||
rsno2e:
|
||||
#endif /* CONFIG_TESTING_OPTIONS */
|
||||
if ((wpa_auth->conf.wpa & WPA_PROTO_RSN) &&
|
||||
wpa_auth->conf.rsn_override_key_mgmt_2) {
|
||||
#ifdef CONFIG_TESTING_OPTIONS
|
||||
if (wpa_auth->conf.rsno2e_override_set) {
|
||||
wpa_hexdump(MSG_DEBUG,
|
||||
"RSN: Forced own RSNO2E for testing",
|
||||
wpa_auth->conf.rsno2e_override,
|
||||
wpa_auth->conf.rsno2e_override_len);
|
||||
if (sizeof(buf) - (pos - buf) <
|
||||
wpa_auth->conf.rsno2e_override_len)
|
||||
return -1;
|
||||
os_memcpy(pos, wpa_auth->conf.rsno2e_override,
|
||||
wpa_auth->conf.rsno2e_override_len);
|
||||
pos += wpa_auth->conf.rsno2e_override_len;
|
||||
goto rsnxoe;
|
||||
}
|
||||
#endif /* CONFIG_TESTING_OPTIONS */
|
||||
res = wpa_write_rsne_override_2(&wpa_auth->conf, pos,
|
||||
buf + sizeof(buf) - pos);
|
||||
if (res < 0)
|
||||
return res;
|
||||
pos += res;
|
||||
}
|
||||
#ifdef CONFIG_TESTING_OPTIONS
|
||||
rsnxoe:
|
||||
#endif /* CONFIG_TESTING_OPTIONS */
|
||||
if ((wpa_auth->conf.wpa & WPA_PROTO_RSN) &&
|
||||
(wpa_auth->conf.rsn_override_key_mgmt ||
|
||||
wpa_auth->conf.rsn_override_key_mgmt_2)) {
|
||||
#ifdef CONFIG_TESTING_OPTIONS
|
||||
if (wpa_auth->conf.rsnxoe_override_set) {
|
||||
wpa_hexdump(MSG_DEBUG,
|
||||
"RSN: Forced own RSNXOE for testing",
|
||||
wpa_auth->conf.rsnxoe_override,
|
||||
wpa_auth->conf.rsnxoe_override_len);
|
||||
if (sizeof(buf) - (pos - buf) <
|
||||
wpa_auth->conf.rsnxoe_override_len)
|
||||
return -1;
|
||||
os_memcpy(pos, wpa_auth->conf.rsnxoe_override,
|
||||
wpa_auth->conf.rsnxoe_override_len);
|
||||
pos += wpa_auth->conf.rsnxoe_override_len;
|
||||
goto done;
|
||||
}
|
||||
#endif /* CONFIG_TESTING_OPTIONS */
|
||||
res = wpa_write_rsnxe_override(&wpa_auth->conf, pos,
|
||||
buf + sizeof(buf) - pos);
|
||||
if (res < 0)
|
||||
return res;
|
||||
pos += res;
|
||||
}
|
||||
#ifdef CONFIG_TESTING_OPTIONS
|
||||
done:
|
||||
#endif /* CONFIG_TESTING_OPTIONS */
|
||||
|
||||
wpa_hexdump(MSG_DEBUG, "RSN: Own IEs", buf, pos - buf);
|
||||
os_free(wpa_auth->wpa_ie);
|
||||
wpa_auth->wpa_ie = os_malloc(pos - buf);
|
||||
if (wpa_auth->wpa_ie == NULL)
|
||||
|
@ -608,7 +856,8 @@ wpa_validate_wpa_ie(struct wpa_authenticator *wpa_auth,
|
|||
const u8 *wpa_ie, size_t wpa_ie_len,
|
||||
const u8 *rsnxe, size_t rsnxe_len,
|
||||
const u8 *mdie, size_t mdie_len,
|
||||
const u8 *owe_dh, size_t owe_dh_len)
|
||||
const u8 *owe_dh, size_t owe_dh_len,
|
||||
struct wpa_state_machine *assoc_sm)
|
||||
{
|
||||
struct wpa_auth_config *conf = &wpa_auth->conf;
|
||||
struct wpa_ie_data data;
|
||||
|
@ -765,7 +1014,13 @@ wpa_validate_wpa_ie(struct wpa_authenticator *wpa_auth,
|
|||
return WPA_INVALID_GROUP;
|
||||
}
|
||||
|
||||
key_mgmt = data.key_mgmt & wpa_auth->conf.wpa_key_mgmt;
|
||||
if (sm->rsn_override_2)
|
||||
key_mgmt = data.key_mgmt &
|
||||
wpa_auth->conf.rsn_override_key_mgmt_2;
|
||||
else if (sm->rsn_override)
|
||||
key_mgmt = data.key_mgmt & wpa_auth->conf.rsn_override_key_mgmt;
|
||||
else
|
||||
key_mgmt = data.key_mgmt & wpa_auth->conf.wpa_key_mgmt;
|
||||
if (!key_mgmt) {
|
||||
wpa_printf(MSG_DEBUG, "Invalid WPA key mgmt (0x%x) from "
|
||||
MACSTR, data.key_mgmt, MAC2STR(sm->addr));
|
||||
|
@ -834,7 +1089,13 @@ wpa_validate_wpa_ie(struct wpa_authenticator *wpa_auth,
|
|||
else
|
||||
sm->wpa_key_mgmt = WPA_KEY_MGMT_PSK;
|
||||
|
||||
if (version == WPA_PROTO_RSN)
|
||||
if (version == WPA_PROTO_RSN && sm->rsn_override_2)
|
||||
ciphers = data.pairwise_cipher &
|
||||
wpa_auth->conf.rsn_override_pairwise_2;
|
||||
else if (version == WPA_PROTO_RSN && sm->rsn_override)
|
||||
ciphers = data.pairwise_cipher &
|
||||
wpa_auth->conf.rsn_override_pairwise;
|
||||
else if (version == WPA_PROTO_RSN)
|
||||
ciphers = data.pairwise_cipher & wpa_auth->conf.rsn_pairwise;
|
||||
else
|
||||
ciphers = data.pairwise_cipher & wpa_auth->conf.wpa_pairwise;
|
||||
|
@ -956,6 +1217,15 @@ wpa_validate_wpa_ie(struct wpa_authenticator *wpa_auth,
|
|||
else
|
||||
sm->wpa = WPA_VERSION_WPA;
|
||||
|
||||
if (assoc_sm) {
|
||||
/* For ML association link STA cannot choose a different
|
||||
* AKM or pairwise cipher from association STA */
|
||||
if (sm->wpa_key_mgmt != assoc_sm->wpa_key_mgmt)
|
||||
return WPA_INVALID_AKMP;
|
||||
if (sm->pairwise != assoc_sm->pairwise)
|
||||
return WPA_INVALID_PAIRWISE;
|
||||
}
|
||||
|
||||
#if defined(CONFIG_IEEE80211R_AP) && defined(CONFIG_FILS)
|
||||
if ((sm->wpa_key_mgmt == WPA_KEY_MGMT_FT_FILS_SHA256 ||
|
||||
sm->wpa_key_mgmt == WPA_KEY_MGMT_FT_FILS_SHA384) &&
|
||||
|
@ -1212,7 +1482,7 @@ bool wpa_auth_write_fd_rsn_info(struct wpa_authenticator *wpa_auth,
|
|||
return false;
|
||||
|
||||
/* RSN Capability (B0..B15) */
|
||||
WPA_PUT_LE16(pos, wpa_own_rsn_capab(conf));
|
||||
WPA_PUT_LE16(pos, wpa_own_rsn_capab(conf, conf->ieee80211w));
|
||||
pos += 2;
|
||||
|
||||
/* Group Data Cipher Suite Selector (B16..B21) */
|
||||
|
|
|
@ -80,16 +80,19 @@ endif
|
|||
_DIRS := $(BUILDDIR)/$(PROJ)
|
||||
.PHONY: _make_dirs
|
||||
_make_dirs:
|
||||
@mkdir -p $(_DIRS)
|
||||
@mkdir -p $(sort $(_DIRS))
|
||||
|
||||
$(BUILDDIR)/$(PROJ)/src/%.o: $(ROOTDIR)src/%.c $(CONFIG_FILE) | _make_dirs
|
||||
@echo $(CURDIR): '$(CC) -c -o $@ $(CFLAGS) $<' >$@.cmd
|
||||
$(Q)$(CC) -c -o $@ $(CFLAGS) $<
|
||||
@$(E) " CC " $<
|
||||
$(BUILDDIR)/$(PROJ)/%.o: %.c $(CONFIG_FILE) | _make_dirs
|
||||
@echo $(CURDIR): '$(CC) -c -o $@ $(CFLAGS) $<' >$@.cmd
|
||||
$(Q)$(CC) -c -o $@ $(CFLAGS) $<
|
||||
@$(E) " CC " $<
|
||||
# for the fuzzing tests
|
||||
$(BUILDDIR)/$(PROJ)/wpa_supplicant/%.o: $(ROOTDIR)wpa_supplicant/%.c $(CONFIG_FILE) | _make_dirs
|
||||
@echo $(CURDIR): '$(CC) -c -o $@ $(CFLAGS) $<' >$@.cmd
|
||||
$(Q)$(CC) -c -o $@ $(CFLAGS) $<
|
||||
@$(E) " CC " $<
|
||||
|
||||
|
|
|
@ -532,4 +532,9 @@ enum sae_pwe {
|
|||
SAE_PWE_NOT_SET = 4,
|
||||
};
|
||||
|
||||
#define USEC_80211_TU 1024
|
||||
|
||||
#define USEC_TO_TU(m) ((m) / USEC_80211_TU)
|
||||
#define TU_TO_USEC(m) ((m) * USEC_80211_TU)
|
||||
|
||||
#endif /* DEFS_H */
|
||||
|
|
|
@ -1035,6 +1035,10 @@ struct wpabuf * dpp_build_conf_req_helper(struct dpp_authentication *auth,
|
|||
json_value_sep(json);
|
||||
json_add_string(json, "pkcs10", csr);
|
||||
}
|
||||
#ifdef CONFIG_DPP3
|
||||
json_value_sep(json);
|
||||
json_add_int(json, "capabilities", DPP_ENROLLEE_CAPAB_SAE_PW_ID);
|
||||
#endif /* CONFIG_DPP3 */
|
||||
if (extra_name && extra_value && extra_name[0] && extra_value[0]) {
|
||||
json_value_sep(json);
|
||||
wpabuf_printf(json, "\"%s\":%s", extra_name, extra_value);
|
||||
|
@ -1139,8 +1143,18 @@ int dpp_configuration_valid(const struct dpp_configuration *conf)
|
|||
return 0;
|
||||
if (dpp_akm_psk(conf->akm) && !conf->passphrase && !conf->psk_set)
|
||||
return 0;
|
||||
if (dpp_akm_psk(conf->akm) && conf->passphrase) {
|
||||
size_t len = os_strlen(conf->passphrase);
|
||||
|
||||
if (len > 63 || len < 8)
|
||||
return 0;
|
||||
}
|
||||
if (dpp_akm_sae(conf->akm) && !conf->passphrase)
|
||||
return 0;
|
||||
#ifdef CONFIG_DPP3
|
||||
if (conf->idpass && (!conf->passphrase || !dpp_akm_sae(conf->akm)))
|
||||
return 0;
|
||||
#endif /* CONFIG_DPP3 */
|
||||
return 1;
|
||||
}
|
||||
|
||||
|
@ -1150,6 +1164,9 @@ void dpp_configuration_free(struct dpp_configuration *conf)
|
|||
if (!conf)
|
||||
return;
|
||||
str_clear_free(conf->passphrase);
|
||||
#ifdef CONFIG_DPP3
|
||||
os_free(conf->idpass);
|
||||
#endif /* CONFIG_DPP3 */
|
||||
os_free(conf->group_id);
|
||||
os_free(conf->csrattrs);
|
||||
os_free(conf->extra_name);
|
||||
|
@ -1228,14 +1245,28 @@ static int dpp_configuration_parse_helper(struct dpp_authentication *auth,
|
|||
end = os_strchr(pos, ' ');
|
||||
pass_len = end ? (size_t) (end - pos) : os_strlen(pos);
|
||||
pass_len /= 2;
|
||||
if (pass_len > 63 || pass_len < 8)
|
||||
goto fail;
|
||||
conf->passphrase = os_zalloc(pass_len + 1);
|
||||
if (!conf->passphrase ||
|
||||
hexstr2bin(pos, (u8 *) conf->passphrase, pass_len) < 0)
|
||||
goto fail;
|
||||
}
|
||||
|
||||
#ifdef CONFIG_DPP3
|
||||
pos = os_strstr(cmd, " idpass=");
|
||||
if (pos) {
|
||||
size_t idpass_len;
|
||||
|
||||
pos += 8;
|
||||
end = os_strchr(pos, ' ');
|
||||
idpass_len = end ? (size_t) (end - pos) : os_strlen(pos);
|
||||
idpass_len /= 2;
|
||||
conf->idpass = os_zalloc(idpass_len + 1);
|
||||
if (!conf->idpass ||
|
||||
hexstr2bin(pos, (u8 *) conf->idpass, idpass_len) < 0)
|
||||
goto fail;
|
||||
}
|
||||
#endif /* CONFIG_DPP3 */
|
||||
|
||||
pos = os_strstr(cmd, " psk=");
|
||||
if (pos) {
|
||||
pos += 5;
|
||||
|
@ -1595,6 +1626,13 @@ static void dpp_build_legacy_cred_params(struct wpabuf *buf,
|
|||
if (conf->passphrase && os_strlen(conf->passphrase) < 64) {
|
||||
json_add_string_escape(buf, "pass", conf->passphrase,
|
||||
os_strlen(conf->passphrase));
|
||||
#ifdef CONFIG_DPP3
|
||||
if (conf->idpass) {
|
||||
json_value_sep(buf);
|
||||
json_add_string_escape(buf, "idpass", conf->idpass,
|
||||
os_strlen(conf->idpass));
|
||||
}
|
||||
#endif /* CONFIG_DPP3 */
|
||||
} else if (conf->psk_set) {
|
||||
char psk[2 * sizeof(conf->psk) + 1];
|
||||
|
||||
|
@ -1917,6 +1955,16 @@ dpp_build_conf_obj_legacy(struct dpp_authentication *auth,
|
|||
const char *akm_str;
|
||||
size_t len = 1000;
|
||||
|
||||
|
||||
#ifdef CONFIG_DPP3
|
||||
if (conf->idpass &&
|
||||
!(auth->enrollee_capabilities & DPP_ENROLLEE_CAPAB_SAE_PW_ID)) {
|
||||
wpa_printf(MSG_DEBUG,
|
||||
"DPP: Enrollee does not support SAE Password Identifier - cannot generate config object");
|
||||
return NULL;
|
||||
}
|
||||
#endif /* CONFIG_DPP3 */
|
||||
|
||||
if (conf->extra_name && conf->extra_value)
|
||||
len += 10 + os_strlen(conf->extra_name) +
|
||||
os_strlen(conf->extra_value);
|
||||
|
@ -2535,6 +2583,18 @@ dpp_conf_req_rx(struct dpp_authentication *auth, const u8 *attr_start,
|
|||
cont:
|
||||
#endif /* CONFIG_DPP2 */
|
||||
|
||||
#ifdef CONFIG_DPP3
|
||||
token = json_get_member(root, "capabilities");
|
||||
if (token && token->type == JSON_NUMBER) {
|
||||
wpa_printf(MSG_DEBUG, "DPP: capabilities = 0x%x",
|
||||
token->number);
|
||||
wpa_msg(auth->msg_ctx, MSG_INFO,
|
||||
DPP_EVENT_ENROLLEE_CAPABILITY "%d",
|
||||
token->number);
|
||||
auth->enrollee_capabilities = token->number;
|
||||
}
|
||||
#endif /* CONFIG_DPP3 */
|
||||
|
||||
resp = dpp_build_conf_resp(auth, e_nonce, e_nonce_len, netrole,
|
||||
cert_req);
|
||||
|
||||
|
@ -2558,13 +2618,25 @@ static int dpp_parse_cred_legacy(struct dpp_config_obj *conf,
|
|||
|
||||
if (pass && pass->type == JSON_STRING) {
|
||||
size_t len = os_strlen(pass->string);
|
||||
#ifdef CONFIG_DPP3
|
||||
struct json_token *saepi = json_get_member(cred, "idpass");
|
||||
#endif /* CONFIG_DPP3 */
|
||||
|
||||
wpa_hexdump_ascii_key(MSG_DEBUG, "DPP: Legacy passphrase",
|
||||
pass->string, len);
|
||||
if (len < 8 || len > 63)
|
||||
if (dpp_akm_psk(conf->akm) && (len < 8 || len > 63)) {
|
||||
wpa_printf(MSG_DEBUG,
|
||||
"DPP: Unexpected pass length %zu for a config object that includes PSK",
|
||||
len);
|
||||
return -1;
|
||||
}
|
||||
os_strlcpy(conf->passphrase, pass->string,
|
||||
sizeof(conf->passphrase));
|
||||
#ifdef CONFIG_DPP3
|
||||
if (saepi && saepi->type == JSON_STRING)
|
||||
os_strlcpy(conf->password_id, saepi->string,
|
||||
sizeof(conf->password_id));
|
||||
#endif /* CONFIG_DPP3 */
|
||||
} else if (psk_hex && psk_hex->type == JSON_STRING) {
|
||||
if (dpp_akm_sae(conf->akm) && !dpp_akm_psk(conf->akm)) {
|
||||
wpa_printf(MSG_DEBUG,
|
||||
|
|
|
@ -134,6 +134,9 @@ enum dpp_connector_key {
|
|||
#define DPP_MAX_SHARED_SECRET_LEN 66
|
||||
#define DPP_CP_LEN 64
|
||||
|
||||
/* DPP Configuration Request - Enrollee Capabilities */
|
||||
#define DPP_ENROLLEE_CAPAB_SAE_PW_ID BIT(0)
|
||||
|
||||
struct dpp_curve_params {
|
||||
const char *name;
|
||||
size_t hash_len;
|
||||
|
@ -260,6 +263,7 @@ struct dpp_configuration {
|
|||
|
||||
/* For legacy configuration */
|
||||
char *passphrase;
|
||||
char *idpass;
|
||||
u8 psk[32];
|
||||
int psk_set;
|
||||
|
||||
|
@ -356,6 +360,9 @@ struct dpp_authentication {
|
|||
u8 ssid_len;
|
||||
int ssid_charset;
|
||||
char passphrase[64];
|
||||
#ifdef CONFIG_DPP3
|
||||
char password_id[64];
|
||||
#endif /* CONFIG_DPP3 */
|
||||
u8 psk[PMK_LEN];
|
||||
int psk_set;
|
||||
enum dpp_akm akm;
|
||||
|
@ -393,6 +400,7 @@ struct dpp_authentication {
|
|||
char *e_name;
|
||||
char *e_mud_url;
|
||||
int *e_band_support;
|
||||
unsigned int enrollee_capabilities;
|
||||
#ifdef CONFIG_TESTING_OPTIONS
|
||||
char *config_obj_override;
|
||||
char *discovery_override;
|
||||
|
|
|
@ -381,6 +381,75 @@ int check_40mhz_2g4(struct hostapd_hw_modes *mode,
|
|||
}
|
||||
|
||||
|
||||
static void punct_update_legacy_bw_80(u8 bitmap, u8 pri_chan, u8 *seg0)
|
||||
{
|
||||
u8 first_chan = *seg0 - 6, sec_chan;
|
||||
|
||||
switch (bitmap) {
|
||||
case 0x6:
|
||||
*seg0 = 0;
|
||||
return;
|
||||
case 0x8:
|
||||
case 0x4:
|
||||
case 0x2:
|
||||
case 0x1:
|
||||
case 0xC:
|
||||
case 0x3:
|
||||
if (pri_chan < *seg0)
|
||||
*seg0 -= 4;
|
||||
else
|
||||
*seg0 += 4;
|
||||
break;
|
||||
}
|
||||
|
||||
if (pri_chan < *seg0)
|
||||
sec_chan = pri_chan + 4;
|
||||
else
|
||||
sec_chan = pri_chan - 4;
|
||||
|
||||
if (bitmap & BIT((sec_chan - first_chan) / 4))
|
||||
*seg0 = 0;
|
||||
}
|
||||
|
||||
|
||||
static void punct_update_legacy_bw_160(u8 bitmap, u8 pri,
|
||||
enum oper_chan_width *width, u8 *seg0)
|
||||
{
|
||||
if (pri < *seg0) {
|
||||
*seg0 -= 8;
|
||||
if (bitmap & 0x0F) {
|
||||
*width = 0;
|
||||
punct_update_legacy_bw_80(bitmap & 0xF, pri, seg0);
|
||||
}
|
||||
} else {
|
||||
*seg0 += 8;
|
||||
if (bitmap & 0xF0) {
|
||||
*width = 0;
|
||||
punct_update_legacy_bw_80((bitmap & 0xF0) >> 4, pri,
|
||||
seg0);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
void punct_update_legacy_bw(u16 bitmap, u8 pri, enum oper_chan_width *width,
|
||||
u8 *seg0, u8 *seg1)
|
||||
{
|
||||
if (*width == CONF_OPER_CHWIDTH_80MHZ && (bitmap & 0xF)) {
|
||||
*width = CONF_OPER_CHWIDTH_USE_HT;
|
||||
punct_update_legacy_bw_80(bitmap & 0xF, pri, seg0);
|
||||
}
|
||||
|
||||
if (*width == CONF_OPER_CHWIDTH_160MHZ && (bitmap & 0xFF)) {
|
||||
*width = CONF_OPER_CHWIDTH_80MHZ;
|
||||
*seg1 = 0;
|
||||
punct_update_legacy_bw_160(bitmap & 0xFF, pri, width, seg0);
|
||||
}
|
||||
|
||||
/* TODO: 320 MHz */
|
||||
}
|
||||
|
||||
|
||||
int hostapd_set_freq_params(struct hostapd_freq_params *data,
|
||||
enum hostapd_hw_mode mode,
|
||||
int freq, int channel, int enable_edmg,
|
||||
|
@ -391,8 +460,12 @@ int hostapd_set_freq_params(struct hostapd_freq_params *data,
|
|||
int center_segment0,
|
||||
int center_segment1, u32 vht_caps,
|
||||
struct he_capabilities *he_cap,
|
||||
struct eht_capabilities *eht_cap)
|
||||
struct eht_capabilities *eht_cap,
|
||||
u16 punct_bitmap)
|
||||
{
|
||||
enum oper_chan_width oper_chwidth_legacy;
|
||||
u8 seg0_legacy, seg1_legacy;
|
||||
|
||||
if (!he_cap || !he_cap->he_supported)
|
||||
he_enabled = 0;
|
||||
if (!eht_cap || !eht_cap->eht_supported)
|
||||
|
@ -578,6 +651,14 @@ int hostapd_set_freq_params(struct hostapd_freq_params *data,
|
|||
break;
|
||||
}
|
||||
|
||||
oper_chwidth_legacy = oper_chwidth;
|
||||
seg0_legacy = center_segment0;
|
||||
seg1_legacy = center_segment1;
|
||||
if (punct_bitmap)
|
||||
punct_update_legacy_bw(punct_bitmap, channel,
|
||||
&oper_chwidth_legacy,
|
||||
&seg0_legacy, &seg1_legacy);
|
||||
|
||||
if (data->eht_enabled || data->he_enabled ||
|
||||
data->vht_enabled) switch (oper_chwidth) {
|
||||
case CONF_OPER_CHWIDTH_USE_HT:
|
||||
|
@ -602,7 +683,8 @@ int hostapd_set_freq_params(struct hostapd_freq_params *data,
|
|||
/* fall through */
|
||||
case CONF_OPER_CHWIDTH_80MHZ:
|
||||
data->bandwidth = 80;
|
||||
if (!sec_channel_offset) {
|
||||
if (!sec_channel_offset &&
|
||||
oper_chwidth_legacy != CONF_OPER_CHWIDTH_USE_HT) {
|
||||
wpa_printf(MSG_ERROR,
|
||||
"80/80+80 MHz: no second channel offset");
|
||||
return -1;
|
||||
|
@ -660,7 +742,8 @@ int hostapd_set_freq_params(struct hostapd_freq_params *data,
|
|||
"160 MHz: center segment 1 should not be set");
|
||||
return -1;
|
||||
}
|
||||
if (!sec_channel_offset) {
|
||||
if (!sec_channel_offset &&
|
||||
oper_chwidth_legacy != CONF_OPER_CHWIDTH_USE_HT) {
|
||||
wpa_printf(MSG_ERROR,
|
||||
"160 MHz: second channel offset not set");
|
||||
return -1;
|
||||
|
@ -950,3 +1033,18 @@ bool is_punct_bitmap_valid(u16 bw, u16 pri_ch_bit_pos, u16 punct_bitmap)
|
|||
|
||||
return false;
|
||||
}
|
||||
|
||||
|
||||
bool chan_in_current_hw_info(struct hostapd_multi_hw_info *current_hw_info,
|
||||
struct hostapd_channel_data *chan)
|
||||
{
|
||||
/* Assuming that if current_hw_info is not set full
|
||||
* iface->current_mode->channels[] can be used to scan for channels,
|
||||
* hence we return true.
|
||||
*/
|
||||
if (!current_hw_info)
|
||||
return true;
|
||||
|
||||
return current_hw_info->start_freq <= chan->freq &&
|
||||
current_hw_info->end_freq >= chan->freq;
|
||||
}
|
||||
|
|
|
@ -35,6 +35,8 @@ int check_40mhz_5g(struct wpa_scan_results *scan_res,
|
|||
int check_40mhz_2g4(struct hostapd_hw_modes *mode,
|
||||
struct wpa_scan_results *scan_res, int pri_chan,
|
||||
int sec_chan);
|
||||
void punct_update_legacy_bw(u16 bitmap, u8 pri_chan,
|
||||
enum oper_chan_width *width, u8 *seg0, u8 *seg1);
|
||||
int hostapd_set_freq_params(struct hostapd_freq_params *data,
|
||||
enum hostapd_hw_mode mode,
|
||||
int freq, int channel, int edmg, u8 edmg_channel,
|
||||
|
@ -45,7 +47,8 @@ int hostapd_set_freq_params(struct hostapd_freq_params *data,
|
|||
int center_segment0,
|
||||
int center_segment1, u32 vht_caps,
|
||||
struct he_capabilities *he_caps,
|
||||
struct eht_capabilities *eht_cap);
|
||||
struct eht_capabilities *eht_cap,
|
||||
u16 punct_bitmap);
|
||||
void set_disable_ht40(struct ieee80211_ht_capabilities *htcaps,
|
||||
int disabled);
|
||||
int ieee80211ac_cap_check(u32 hw, u32 conf);
|
||||
|
@ -55,5 +58,7 @@ int chan_bw_allowed(const struct hostapd_channel_data *chan, u32 bw,
|
|||
int ht40_plus, int pri);
|
||||
int chan_pri_allowed(const struct hostapd_channel_data *chan);
|
||||
bool is_punct_bitmap_valid(u16 bw, u16 pri_ch_bit_pos, u16 punct_bitmap);
|
||||
bool chan_in_current_hw_info(struct hostapd_multi_hw_info *current_hw_info,
|
||||
struct hostapd_channel_data *chan);
|
||||
|
||||
#endif /* HW_FEATURES_COMMON_H */
|
||||
|
|
|
@ -140,6 +140,28 @@ static int ieee802_11_parse_vendor_specific(const u8 *pos, size_t elen,
|
|||
elems->sae_pk = pos + 4;
|
||||
elems->sae_pk_len = elen - 4;
|
||||
break;
|
||||
case WFA_RSNE_OVERRIDE_OUI_TYPE:
|
||||
elems->rsne_override = pos;
|
||||
elems->rsne_override_len = elen;
|
||||
break;
|
||||
case WFA_RSNE_OVERRIDE_2_OUI_TYPE:
|
||||
elems->rsne_override_2 = pos;
|
||||
elems->rsne_override_2_len = elen;
|
||||
break;
|
||||
case WFA_RSN_SELECTION_OUI_TYPE:
|
||||
if (elen < 4 + 1) {
|
||||
wpa_printf(MSG_DEBUG,
|
||||
"Too short RSN Selection element ignored");
|
||||
return -1;
|
||||
}
|
||||
elems->rsn_selection = pos + 4;
|
||||
elems->rsn_selection_len = elen - 4;
|
||||
break;
|
||||
case P2P2_OUI_TYPE:
|
||||
/* Wi-Fi Alliance - P2P2 IE */
|
||||
elems->p2p2_ie = pos;
|
||||
elems->p2p2_ie_len = elen;
|
||||
break;
|
||||
default:
|
||||
wpa_printf(MSG_MSGDUMP, "Unknown WFA "
|
||||
"information element ignored "
|
||||
|
@ -607,6 +629,12 @@ static ParseRes __ieee802_11_parse_elems(const u8 *start, size_t len,
|
|||
elems->rrm_enabled = pos;
|
||||
elems->rrm_enabled_len = elen;
|
||||
break;
|
||||
case WLAN_EID_MULTIPLE_BSSID:
|
||||
if (elen < 1)
|
||||
break;
|
||||
elems->mbssid = pos;
|
||||
elems->mbssid_len = elen;
|
||||
break;
|
||||
case WLAN_EID_CAG_NUMBER:
|
||||
elems->cag_number = pos;
|
||||
elems->cag_number_len = elen;
|
||||
|
@ -1487,8 +1515,6 @@ ieee80211_freq_to_channel_ext(unsigned int freq, int sec_channel,
|
|||
*op_class = 126;
|
||||
else if (sec_channel == -1)
|
||||
*op_class = 127;
|
||||
else if (freq <= 5805)
|
||||
*op_class = 124;
|
||||
else
|
||||
*op_class = 125;
|
||||
|
||||
|
@ -2040,6 +2066,13 @@ int is_dfs_global_op_class(u8 op_class)
|
|||
}
|
||||
|
||||
|
||||
bool is_80plus_op_class(u8 op_class)
|
||||
{
|
||||
/* Operating classes with "80+" behavior indication in Table E-4 */
|
||||
return op_class == 130 || op_class == 135;
|
||||
}
|
||||
|
||||
|
||||
static int is_11b(u8 rate)
|
||||
{
|
||||
return rate == 0x02 || rate == 0x04 || rate == 0x0b || rate == 0x16;
|
||||
|
@ -2406,9 +2439,17 @@ const struct oper_class_map global_op_class[] = {
|
|||
* channel center frequency index value, but it happens to be a 20 MHz
|
||||
* channel and the channel number in the channel set would match the
|
||||
* value in for the frequency center.
|
||||
*
|
||||
* Operating class value pair 128 and 130 is used to describe a 80+80
|
||||
* MHz channel on the 5 GHz band. 130 is identified with "80+", so this
|
||||
* is encoded with two octets 130 and 128. Similarly, operating class
|
||||
* value pair 133 and 135 is used to describe a 80+80 MHz channel on
|
||||
* the 6 GHz band (135 being the one with "80+" indication). All other
|
||||
* operating classes listed here are used as 1-octet values.
|
||||
*/
|
||||
{ HOSTAPD_MODE_IEEE80211A, 128, 36, 177, 4, BW80, P2P_SUPP },
|
||||
{ HOSTAPD_MODE_IEEE80211A, 129, 36, 177, 4, BW160, P2P_SUPP },
|
||||
{ HOSTAPD_MODE_IEEE80211A, 130, 36, 177, 4, BW80P80, P2P_SUPP },
|
||||
{ HOSTAPD_MODE_IEEE80211A, 131, 1, 233, 4, BW20, P2P_SUPP },
|
||||
{ HOSTAPD_MODE_IEEE80211A, 132, 1, 233, 8, BW40, P2P_SUPP },
|
||||
{ HOSTAPD_MODE_IEEE80211A, 133, 1, 233, 16, BW80, P2P_SUPP },
|
||||
|
@ -2416,6 +2457,9 @@ const struct oper_class_map global_op_class[] = {
|
|||
{ HOSTAPD_MODE_IEEE80211A, 135, 1, 233, 16, BW80P80, NO_P2P_SUPP },
|
||||
{ HOSTAPD_MODE_IEEE80211A, 136, 2, 2, 4, BW20, NO_P2P_SUPP },
|
||||
|
||||
/* IEEE P802.11be/D5.0, Table E-4 (Global operating classes) */
|
||||
{ HOSTAPD_MODE_IEEE80211A, 137, 31, 191, 32, BW320, NO_P2P_SUPP },
|
||||
|
||||
/*
|
||||
* IEEE Std 802.11ad-2012 and P802.ay/D5.0 60 GHz operating classes.
|
||||
* Class 180 has the legacy channels 1-6. Classes 181-183 include
|
||||
|
@ -2426,11 +2470,6 @@ const struct oper_class_map global_op_class[] = {
|
|||
{ HOSTAPD_MODE_IEEE80211AD, 182, 17, 20, 1, BW6480, P2P_SUPP },
|
||||
{ HOSTAPD_MODE_IEEE80211AD, 183, 25, 27, 1, BW8640, P2P_SUPP },
|
||||
|
||||
/* Keep the operating class 130 as the last entry as a workaround for
|
||||
* the OneHundredAndThirty Delimiter value used in the Supported
|
||||
* Operating Classes element to indicate the end of the Operating
|
||||
* Classes field. */
|
||||
{ HOSTAPD_MODE_IEEE80211A, 130, 36, 177, 4, BW80P80, P2P_SUPP },
|
||||
{ -1, 0, 0, 0, 0, BW20, NO_P2P_SUPP }
|
||||
};
|
||||
|
||||
|
@ -2558,21 +2597,141 @@ size_t mbo_add_ie(u8 *buf, size_t len, const u8 *attr, size_t attr_len)
|
|||
}
|
||||
|
||||
|
||||
size_t add_multi_ap_ie(u8 *buf, size_t len, u8 value)
|
||||
u16 check_multi_ap_ie(const u8 *multi_ap_ie, size_t multi_ap_len,
|
||||
struct multi_ap_params *multi_ap)
|
||||
{
|
||||
const struct element *elem;
|
||||
bool ext_present = false;
|
||||
unsigned int vlan_id;
|
||||
|
||||
os_memset(multi_ap, 0, sizeof(*multi_ap));
|
||||
|
||||
/* Default profile is 1, when Multi-AP profile subelement is not
|
||||
* present in the element. */
|
||||
multi_ap->profile = 1;
|
||||
|
||||
for_each_element(elem, multi_ap_ie, multi_ap_len) {
|
||||
u8 id = elem->id, elen = elem->datalen;
|
||||
const u8 *pos = elem->data;
|
||||
|
||||
switch (id) {
|
||||
case MULTI_AP_SUB_ELEM_TYPE:
|
||||
if (elen >= 1) {
|
||||
multi_ap->capability = *pos;
|
||||
ext_present = true;
|
||||
} else {
|
||||
wpa_printf(MSG_DEBUG,
|
||||
"Multi-AP invalid Multi-AP subelement");
|
||||
return WLAN_STATUS_INVALID_IE;
|
||||
}
|
||||
break;
|
||||
case MULTI_AP_PROFILE_SUB_ELEM_TYPE:
|
||||
if (elen < 1) {
|
||||
wpa_printf(MSG_DEBUG,
|
||||
"Multi-AP IE invalid Multi-AP profile subelement");
|
||||
return WLAN_STATUS_INVALID_IE;
|
||||
}
|
||||
|
||||
multi_ap->profile = *pos;
|
||||
if (multi_ap->profile > MULTI_AP_PROFILE_MAX) {
|
||||
wpa_printf(MSG_DEBUG,
|
||||
"Multi-AP IE with invalid profile 0x%02x",
|
||||
multi_ap->profile);
|
||||
return WLAN_STATUS_ASSOC_DENIED_UNSPEC;
|
||||
}
|
||||
break;
|
||||
case MULTI_AP_VLAN_SUB_ELEM_TYPE:
|
||||
if (multi_ap->profile < MULTI_AP_PROFILE_2) {
|
||||
wpa_printf(MSG_DEBUG,
|
||||
"Multi-AP IE invalid profile to read VLAN IE");
|
||||
return WLAN_STATUS_INVALID_IE;
|
||||
}
|
||||
if (elen < 2) {
|
||||
wpa_printf(MSG_DEBUG,
|
||||
"Multi-AP IE invalid Multi-AP VLAN subelement");
|
||||
return WLAN_STATUS_INVALID_IE;
|
||||
}
|
||||
|
||||
vlan_id = WPA_GET_LE16(pos);
|
||||
if (vlan_id < 1 || vlan_id > 4094) {
|
||||
wpa_printf(MSG_INFO,
|
||||
"Multi-AP IE invalid Multi-AP VLAN ID %d",
|
||||
vlan_id);
|
||||
return WLAN_STATUS_INVALID_IE;
|
||||
}
|
||||
multi_ap->vlanid = vlan_id;
|
||||
break;
|
||||
default:
|
||||
wpa_printf(MSG_DEBUG,
|
||||
"Ignore unknown subelement %u in Multi-AP IE",
|
||||
id);
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
if (!for_each_element_completed(elem, multi_ap_ie, multi_ap_len)) {
|
||||
wpa_printf(MSG_DEBUG, "Multi AP IE parse failed @%d",
|
||||
(int) (multi_ap_ie + multi_ap_len -
|
||||
(const u8 *) elem));
|
||||
wpa_hexdump(MSG_MSGDUMP, "IEs", multi_ap_ie, multi_ap_len);
|
||||
}
|
||||
|
||||
if (!ext_present) {
|
||||
wpa_printf(MSG_DEBUG,
|
||||
"Multi-AP element without Multi-AP Extension subelement");
|
||||
return WLAN_STATUS_INVALID_IE;
|
||||
}
|
||||
|
||||
return WLAN_STATUS_SUCCESS;
|
||||
}
|
||||
|
||||
|
||||
size_t add_multi_ap_ie(u8 *buf, size_t len,
|
||||
const struct multi_ap_params *multi_ap)
|
||||
{
|
||||
u8 *pos = buf;
|
||||
u8 *len_ptr;
|
||||
|
||||
if (len < 9)
|
||||
if (len < 6)
|
||||
return 0;
|
||||
|
||||
*pos++ = WLAN_EID_VENDOR_SPECIFIC;
|
||||
*pos++ = 7; /* len */
|
||||
len_ptr = pos; /* Length field to be set at the end */
|
||||
pos++;
|
||||
WPA_PUT_BE24(pos, OUI_WFA);
|
||||
pos += 3;
|
||||
*pos++ = MULTI_AP_OUI_TYPE;
|
||||
|
||||
/* Multi-AP Extension subelement */
|
||||
if (buf + len - pos < 3)
|
||||
return 0;
|
||||
*pos++ = MULTI_AP_SUB_ELEM_TYPE;
|
||||
*pos++ = 1; /* len */
|
||||
*pos++ = value;
|
||||
*pos++ = multi_ap->capability;
|
||||
|
||||
/* Add Multi-AP Profile subelement only for R2 or newer configuration */
|
||||
if (multi_ap->profile >= MULTI_AP_PROFILE_2) {
|
||||
if (buf + len - pos < 3)
|
||||
return 0;
|
||||
*pos++ = MULTI_AP_PROFILE_SUB_ELEM_TYPE;
|
||||
*pos++ = 1;
|
||||
*pos++ = multi_ap->profile;
|
||||
}
|
||||
|
||||
/* Add Multi-AP Default 802.1Q Setting subelement only for backhaul BSS
|
||||
*/
|
||||
if (multi_ap->vlanid &&
|
||||
multi_ap->profile >= MULTI_AP_PROFILE_2 &&
|
||||
(multi_ap->capability & MULTI_AP_BACKHAUL_BSS)) {
|
||||
if (buf + len - pos < 4)
|
||||
return 0;
|
||||
*pos++ = MULTI_AP_VLAN_SUB_ELEM_TYPE;
|
||||
*pos++ = 2;
|
||||
WPA_PUT_LE16(pos, multi_ap->vlanid);
|
||||
pos += 2;
|
||||
}
|
||||
|
||||
*len_ptr = pos - len_ptr - 1;
|
||||
|
||||
return pos - buf;
|
||||
}
|
||||
|
@ -2737,6 +2896,8 @@ int oper_class_bw_to_int(const struct oper_class_map *map)
|
|||
case BW80P80:
|
||||
case BW160:
|
||||
return 160;
|
||||
case BW320:
|
||||
return 320;
|
||||
case BW2160:
|
||||
return 2160;
|
||||
default:
|
||||
|
@ -2984,8 +3145,12 @@ bool ieee802_11_rsnx_capab_len(const u8 *rsnxe, size_t rsnxe_len,
|
|||
|
||||
bool ieee802_11_rsnx_capab(const u8 *rsnxe, unsigned int capab)
|
||||
{
|
||||
return ieee802_11_rsnx_capab_len(rsnxe ? rsnxe + 2 : NULL,
|
||||
rsnxe ? rsnxe[1] : 0, capab);
|
||||
if (!rsnxe)
|
||||
return false;
|
||||
if (rsnxe[0] == WLAN_EID_VENDOR_SPECIFIC && rsnxe[1] >= 4 + 1)
|
||||
return ieee802_11_rsnx_capab_len(rsnxe + 2 + 4, rsnxe[1] - 4,
|
||||
capab);
|
||||
return ieee802_11_rsnx_capab_len(rsnxe + 2, rsnxe[1], capab);
|
||||
}
|
||||
|
||||
|
||||
|
|
|
@ -30,6 +30,12 @@ struct mb_ies_info {
|
|||
u8 nof_ies;
|
||||
};
|
||||
|
||||
struct multi_ap_params {
|
||||
u8 capability;
|
||||
u8 profile;
|
||||
u16 vlanid;
|
||||
};
|
||||
|
||||
/* Parsed Information Elements */
|
||||
struct ieee802_11_elems {
|
||||
const u8 *ssid;
|
||||
|
@ -59,6 +65,7 @@ struct ieee802_11_elems {
|
|||
const u8 *vendor_ht_cap;
|
||||
const u8 *vendor_vht;
|
||||
const u8 *p2p;
|
||||
const u8 *p2p2_ie;
|
||||
const u8 *wfd;
|
||||
const u8 *link_id;
|
||||
const u8 *interworking;
|
||||
|
@ -109,6 +116,10 @@ struct ieee802_11_elems {
|
|||
const u8 *tdls_mle;
|
||||
const u8 *prior_access_mle;
|
||||
const u8 *mbssid_known_bss;
|
||||
const u8 *mbssid;
|
||||
const u8 *rsne_override;
|
||||
const u8 *rsne_override_2;
|
||||
const u8 *rsn_selection;
|
||||
|
||||
u8 ssid_len;
|
||||
u8 supp_rates_len;
|
||||
|
@ -129,6 +140,7 @@ struct ieee802_11_elems {
|
|||
u8 vendor_ht_cap_len;
|
||||
u8 vendor_vht_len;
|
||||
u8 p2p_len;
|
||||
u8 p2p2_ie_len;
|
||||
u8 wfd_len;
|
||||
u8 interworking_len;
|
||||
u8 qos_map_set_len;
|
||||
|
@ -171,6 +183,10 @@ struct ieee802_11_elems {
|
|||
size_t tdls_mle_len;
|
||||
size_t prior_access_mle_len;
|
||||
u8 mbssid_known_bss_len;
|
||||
u8 mbssid_len;
|
||||
size_t rsne_override_len;
|
||||
size_t rsne_override_2_len;
|
||||
size_t rsn_selection_len;
|
||||
|
||||
struct mb_ies_info mb_ies;
|
||||
|
||||
|
@ -235,6 +251,7 @@ int ieee80211_chaninfo_to_channel(unsigned int freq, enum chan_width chanwidth,
|
|||
int ieee80211_is_dfs(int freq, const struct hostapd_hw_modes *modes,
|
||||
u16 num_modes);
|
||||
int is_dfs_global_op_class(u8 op_class);
|
||||
bool is_80plus_op_class(u8 op_class);
|
||||
enum phy_type ieee80211_get_phy_type(int freq, int ht, int vht);
|
||||
|
||||
int supp_rates_11b_only(struct ieee802_11_elems *elems);
|
||||
|
@ -253,7 +270,7 @@ struct oper_class_map {
|
|||
u8 max_chan;
|
||||
u8 inc;
|
||||
enum { BW20, BW40PLUS, BW40MINUS, BW40, BW80, BW2160, BW160, BW80P80,
|
||||
BW4320, BW6480, BW8640} bw;
|
||||
BW320, BW4320, BW6480, BW8640} bw;
|
||||
enum { P2P_SUPP, NO_P2P_SUPP } p2p;
|
||||
};
|
||||
|
||||
|
@ -266,7 +283,10 @@ const u8 * get_vendor_ie(const u8 *ies, size_t len, u32 vendor_type);
|
|||
|
||||
size_t mbo_add_ie(u8 *buf, size_t len, const u8 *attr, size_t attr_len);
|
||||
|
||||
size_t add_multi_ap_ie(u8 *buf, size_t len, u8 value);
|
||||
u16 check_multi_ap_ie(const u8 *multi_ap_ie, size_t multi_ap_len,
|
||||
struct multi_ap_params *multi_ap);
|
||||
size_t add_multi_ap_ie(u8 *buf, size_t len,
|
||||
const struct multi_ap_params *multi_ap);
|
||||
|
||||
struct country_op_class {
|
||||
u8 country_op_class;
|
||||
|
|
|
@ -504,6 +504,7 @@
|
|||
#define WLAN_EID_EXT_HE_MU_EDCA_PARAMS 38
|
||||
#define WLAN_EID_EXT_SPATIAL_REUSE 39
|
||||
#define WLAN_EID_EXT_COLOR_CHANGE_ANNOUNCEMENT 42
|
||||
#define WLAN_EID_EXT_MAX_CHANNEL_SWITCH_TIME 52
|
||||
#define WLAN_EID_EXT_OCV_OCI 54
|
||||
#define WLAN_EID_EXT_MULTIPLE_BSSID_CONFIGURATION 55
|
||||
#define WLAN_EID_EXT_NON_INHERITANCE 56
|
||||
|
@ -524,6 +525,7 @@
|
|||
#define WLAN_EID_EXT_MULTI_LINK_TRAFFIC_INDICATION 110
|
||||
#define WLAN_EID_EXT_QOS_CHARACTERISTICS 113
|
||||
#define WLAN_EID_EXT_AKM_SUITE_SELECTOR 114
|
||||
#define WLAN_EID_EXT_BANDWIDTH_INDICATION 135
|
||||
|
||||
/* Extended Capabilities field */
|
||||
#define WLAN_EXT_CAPAB_20_40_COEX 0
|
||||
|
@ -616,6 +618,7 @@
|
|||
#define WLAN_RSNX_CAPAB_SECURE_RTT 9
|
||||
#define WLAN_RSNX_CAPAB_URNM_MFPR_X20 10
|
||||
#define WLAN_RSNX_CAPAB_URNM_MFPR 15
|
||||
#define WLAN_RSNX_CAPAB_SSID_PROTECTION 21
|
||||
|
||||
/* Multiple BSSID element subelements */
|
||||
#define WLAN_MBSSID_SUBELEMENT_NONTRANSMITTED_BSSID_PROFILE 0
|
||||
|
@ -1424,6 +1427,7 @@ struct ieee80211_ampe_ie {
|
|||
#define WPS_IE_VENDOR_TYPE 0x0050f204
|
||||
#define OUI_WFA 0x506f9a
|
||||
#define P2P_IE_VENDOR_TYPE 0x506f9a09
|
||||
#define P2P2_IE_VENDOR_TYPE 0x506f9a28
|
||||
#define WFD_IE_VENDOR_TYPE 0x506f9a0a
|
||||
#define WFD_OUI_TYPE 10
|
||||
#define HS20_IE_VENDOR_TYPE 0x506f9a10
|
||||
|
@ -1445,13 +1449,30 @@ struct ieee80211_ampe_ie {
|
|||
#define QM_IE_OUI_TYPE 0x22
|
||||
#define WFA_CAPA_IE_VENDOR_TYPE 0x506f9a23
|
||||
#define WFA_CAPA_OUI_TYPE 0x23
|
||||
#define WFA_RSNE_OVERRIDE_OUI_TYPE 0x29
|
||||
#define WFA_RSNE_OVERRIDE_2_OUI_TYPE 0x2a
|
||||
#define WFA_RSNXE_OVERRIDE_OUI_TYPE 0x2b
|
||||
#define WFA_RSN_SELECTION_OUI_TYPE 0x2c
|
||||
#define RSNE_OVERRIDE_IE_VENDOR_TYPE 0x506f9a29
|
||||
#define RSNE_OVERRIDE_2_IE_VENDOR_TYPE 0x506f9a2a
|
||||
#define RSNXE_OVERRIDE_IE_VENDOR_TYPE 0x506f9a2b
|
||||
#define RSN_SELECTION_IE_VENDOR_TYPE 0x506f9a2c
|
||||
|
||||
#define MULTI_AP_SUB_ELEM_TYPE 0x06
|
||||
#define MULTI_AP_PROFILE_SUB_ELEM_TYPE 0x07
|
||||
#define MULTI_AP_VLAN_SUB_ELEM_TYPE 0x08
|
||||
|
||||
#define MULTI_AP_PROFILE2_BACKHAUL_STA_DISALLOWED BIT(2)
|
||||
#define MULTI_AP_PROFILE1_BACKHAUL_STA_DISALLOWED BIT(3)
|
||||
#define MULTI_AP_TEAR_DOWN BIT(4)
|
||||
#define MULTI_AP_FRONTHAUL_BSS BIT(5)
|
||||
#define MULTI_AP_BACKHAUL_BSS BIT(6)
|
||||
#define MULTI_AP_BACKHAUL_STA BIT(7)
|
||||
|
||||
#define MULTI_AP_PROFILE_1 1
|
||||
#define MULTI_AP_PROFILE_2 2
|
||||
#define MULTI_AP_PROFILE_MAX 6
|
||||
|
||||
#define WMM_OUI_TYPE 2
|
||||
#define WMM_OUI_SUBTYPE_INFORMATION_ELEMENT 0
|
||||
#define WMM_OUI_SUBTYPE_PARAMETER_ELEMENT 1
|
||||
|
@ -1700,6 +1721,7 @@ enum mbo_transition_reject_reason {
|
|||
/* Wi-Fi Direct (P2P) */
|
||||
|
||||
#define P2P_OUI_TYPE 9
|
||||
#define P2P2_OUI_TYPE 0x28
|
||||
|
||||
enum p2p_attr_id {
|
||||
P2P_ATTR_STATUS = 0,
|
||||
|
@ -1730,6 +1752,13 @@ enum p2p_attr_id {
|
|||
P2P_ATTR_SESSION_ID = 26,
|
||||
P2P_ATTR_FEATURE_CAPABILITY = 27,
|
||||
P2P_ATTR_PERSISTENT_GROUP = 28,
|
||||
P2P_ATTR_CAPABILITY_EXTENSION = 29,
|
||||
P2P_ATTR_WLAN_AP_INFORMATION = 30,
|
||||
P2P_ATTR_DEVICE_IDENTITY_KEY = 31,
|
||||
P2P_ATTR_DEVICE_IDENTITY_RESOLUTION = 32,
|
||||
P2P_ATTR_PAIRING_AND_BOOTSTRAPPING = 33,
|
||||
P2P_ATTR_PASSWORD = 34,
|
||||
P2P_ATTR_ACTION_FRAME_WRAPPER = 35,
|
||||
P2P_ATTR_VENDOR_SPECIFIC = 221
|
||||
};
|
||||
|
||||
|
@ -1754,6 +1783,31 @@ enum p2p_attr_id {
|
|||
#define P2P_GROUP_CAPAB_GROUP_FORMATION BIT(6)
|
||||
#define P2P_GROUP_CAPAB_IP_ADDR_ALLOCATION BIT(7)
|
||||
|
||||
/* P2P Capability Extension attribute - Capability info */
|
||||
#define P2P_PCEA_LEN_MASK (BIT(0) | BIT(1) | BIT(2) | BIT(3))
|
||||
#define P2P_PCEA_6GHZ BIT(4)
|
||||
#define P2P_PCEA_REG_INFO BIT(5)
|
||||
#define P2P_PCEA_DFS_OWNER BIT(6)
|
||||
#define P2P_PCEA_CLI_REQ_CS BIT(7)
|
||||
#define P2P_PCEA_PAIRING_CAPABLE BIT(8)
|
||||
#define P2P_PCEA_PAIRING_SETUP_ENABLED BIT(9)
|
||||
#define P2P_PCEA_PMK_CACHING BIT(10)
|
||||
#define P2P_PCEA_PASN_TYPE BIT(11)
|
||||
#define P2P_PCEA_TWT_POWER_MGMT BIT(12)
|
||||
|
||||
/* P2P Pairing Bootstrapping Method attribute - Bootstrapping Method */
|
||||
#define P2P_PBMA_OPPORTUNISTIC BIT(0)
|
||||
#define P2P_PBMA_PIN_CODE_DISPLAY BIT(1)
|
||||
#define P2P_PBMA_PASSPHRASE_DISPLAY BIT(2)
|
||||
#define P2P_PBMA_QR_DISPLAY BIT(3)
|
||||
#define P2P_PBMA_NFC_TAG BIT(4)
|
||||
#define P2P_PBMA_PIN_CODE_KEYPAD BIT(5)
|
||||
#define P2P_PBMA_PASSPHRASE_KEYPAD BIT(6)
|
||||
#define P2P_PBMA_QR_SCAN BIT(7)
|
||||
#define P2P_PBMA_NFC_READER BIT(8)
|
||||
#define P2P_PBMA_SERVICE_MANAGED BIT(14)
|
||||
#define P2P_PBMA_HANDSHAKE_SKIP BIT(15)
|
||||
|
||||
/* P2PS Coordination Protocol Transport Bitmap */
|
||||
#define P2PS_FEATURE_CAPAB_UDP_TRANSPORT BIT(0)
|
||||
#define P2PS_FEATURE_CAPAB_MAC_TRANSPORT BIT(1)
|
||||
|
@ -1785,6 +1839,7 @@ enum p2p_status_code {
|
|||
P2P_SC_FAIL_INCOMPATIBLE_PROV_METHOD = 10,
|
||||
P2P_SC_FAIL_REJECTED_BY_USER = 11,
|
||||
P2P_SC_SUCCESS_DEFERRED = 12,
|
||||
P2P_SC_COMEBACK = 13,
|
||||
};
|
||||
|
||||
enum p2p_role_indication {
|
||||
|
@ -2853,6 +2908,33 @@ enum ieee80211_eht_ml_sub_elem {
|
|||
EHT_ML_SUB_ELEM_FRAGMENT = 254,
|
||||
};
|
||||
|
||||
/* IEEE P802.11be/D7.0, 9.4.2.329 (Bandwidth Indication element) defines the
|
||||
* Bandwidth Indication Information field to have the same definition as the
|
||||
* EHT Operation Information field in the EHT Operation element.
|
||||
*/
|
||||
struct ieee80211_bw_ind_info {
|
||||
u8 control; /* B0..B2: Channel Width */
|
||||
u8 ccfs0;
|
||||
u8 ccfs1;
|
||||
le16 disabled_chan_bitmap; /* 0 or 2 octets */
|
||||
} STRUCT_PACKED;
|
||||
|
||||
/* Control subfield: Channel Width subfield; see Table 9-417e (Channel width,
|
||||
* CCFS0, and CCFS1 subfields) in IEEE P802.11be/D7.0. */
|
||||
#define BW_IND_CHANNEL_WIDTH_20MHZ EHT_OPER_CHANNEL_WIDTH_20MHZ
|
||||
#define BW_IND_CHANNEL_WIDTH_40MHZ EHT_OPER_CHANNEL_WIDTH_40MHZ
|
||||
#define BW_IND_CHANNEL_WIDTH_80MHZ EHT_OPER_CHANNEL_WIDTH_80MHZ
|
||||
#define BW_IND_CHANNEL_WIDTH_160MHZ EHT_OPER_CHANNEL_WIDTH_160MHZ
|
||||
#define BW_IND_CHANNEL_WIDTH_320MHZ EHT_OPER_CHANNEL_WIDTH_320MHZ
|
||||
|
||||
/* IEEE P802.11be/D7.0, 9.4.2.329 (Bandwidth Indication element) */
|
||||
struct ieee80211_bw_ind_element {
|
||||
u8 bw_ind_params; /* Bandwidth Indication Parameters */
|
||||
struct ieee80211_bw_ind_info bw_ind_info; /* 3 or 5 octets */
|
||||
} STRUCT_PACKED;
|
||||
|
||||
#define BW_IND_PARAMETER_DISABLED_SUBCHAN_BITMAP_PRESENT BIT(1)
|
||||
|
||||
/* IEEE P802.11ay/D4.0, 9.4.2.251 - EDMG Operation element */
|
||||
#define EDMG_BSS_OPERATING_CHANNELS_OFFSET 6
|
||||
#define EDMG_OPERATING_CHANNEL_WIDTH_OFFSET 7
|
||||
|
|
|
@ -58,10 +58,12 @@ struct nan_de_service {
|
|||
struct os_reltime next_publish_state;
|
||||
struct os_reltime next_publish_chan;
|
||||
unsigned int next_publish_duration;
|
||||
bool is_p2p;
|
||||
};
|
||||
|
||||
struct nan_de {
|
||||
u8 nmi[ETH_ALEN];
|
||||
bool offload;
|
||||
bool ap;
|
||||
struct nan_callbacks cb;
|
||||
|
||||
|
@ -77,7 +79,7 @@ struct nan_de {
|
|||
};
|
||||
|
||||
|
||||
struct nan_de * nan_de_init(const u8 *nmi, bool ap,
|
||||
struct nan_de * nan_de_init(const u8 *nmi, bool offload, bool ap,
|
||||
const struct nan_callbacks *cb)
|
||||
{
|
||||
struct nan_de *de;
|
||||
|
@ -87,6 +89,7 @@ struct nan_de * nan_de_init(const u8 *nmi, bool ap,
|
|||
return NULL;
|
||||
|
||||
os_memcpy(de->nmi, nmi, ETH_ALEN);
|
||||
de->offload = offload;
|
||||
de->ap = ap;
|
||||
os_memcpy(&de->cb, cb, sizeof(*cb));
|
||||
|
||||
|
@ -590,7 +593,7 @@ static void nan_de_timer(void *eloop_ctx, void *timeout_ctx)
|
|||
if (srv_next >= 0 && (next == -1 || srv_next < next))
|
||||
next = srv_next;
|
||||
|
||||
if (srv_next == 0 && !started &&
|
||||
if (srv_next == 0 && !started && !de->offload &&
|
||||
de->listen_freq == 0 && de->ext_listen_freq == 0 &&
|
||||
de->tx_wait_end_freq == 0 &&
|
||||
nan_de_next_multicast(de, srv, &now) == 0) {
|
||||
|
@ -598,7 +601,7 @@ static void nan_de_timer(void *eloop_ctx, void *timeout_ctx)
|
|||
nan_de_tx_multicast(de, srv, 0);
|
||||
}
|
||||
|
||||
if (!started && de->cb.listen &&
|
||||
if (!started && !de->offload && de->cb.listen &&
|
||||
de->listen_freq == 0 && de->ext_listen_freq == 0 &&
|
||||
de->tx_wait_end_freq == 0 &&
|
||||
((srv->type == NAN_DE_PUBLISH &&
|
||||
|
@ -774,6 +777,34 @@ static void nan_de_get_sdea(const u8 *buf, size_t len, u8 instance_id,
|
|||
}
|
||||
|
||||
|
||||
static void nan_de_process_elem_container(struct nan_de *de, const u8 *buf,
|
||||
size_t len, const u8 *peer_addr,
|
||||
unsigned int freq, bool p2p)
|
||||
{
|
||||
const u8 *elem;
|
||||
u16 elem_len;
|
||||
|
||||
elem = nan_de_get_attr(buf, len, NAN_ATTR_ELEM_CONTAINER, 0);
|
||||
if (!elem)
|
||||
return;
|
||||
|
||||
elem++;
|
||||
elem_len = WPA_GET_LE16(elem);
|
||||
elem += 2;
|
||||
/* Skip the attribute if there is not enough froom for an element. */
|
||||
if (elem_len < 1 + 2)
|
||||
return;
|
||||
|
||||
/* Skip Map ID */
|
||||
elem++;
|
||||
elem_len--;
|
||||
|
||||
if (p2p && de->cb.process_p2p_usd_elems)
|
||||
de->cb.process_p2p_usd_elems(de->cb.ctx, elem, elem_len,
|
||||
peer_addr, freq);
|
||||
}
|
||||
|
||||
|
||||
static void nan_de_rx_publish(struct nan_de *de, struct nan_de_service *srv,
|
||||
const u8 *peer_addr, u8 instance_id,
|
||||
u8 req_instance_id, u16 sdea_control,
|
||||
|
@ -787,13 +818,13 @@ static void nan_de_rx_publish(struct nan_de *de, struct nan_de_service *srv,
|
|||
nan_de_run_timer(de);
|
||||
}
|
||||
|
||||
if (srv->subscribe.active && req_instance_id == 0) {
|
||||
if (!de->offload && srv->subscribe.active && req_instance_id == 0) {
|
||||
/* Active subscriber replies with a Subscribe message if it
|
||||
* received a matching unsolicited Publish message. */
|
||||
nan_de_tx_multicast(de, srv, instance_id);
|
||||
}
|
||||
|
||||
if (!srv->subscribe.active && req_instance_id == 0) {
|
||||
if (!de->offload && !srv->subscribe.active && req_instance_id == 0) {
|
||||
/* Passive subscriber replies with a Follow-up message without
|
||||
* Service Specific Info field if it received a matching
|
||||
* unsolicited Publish message. */
|
||||
|
@ -873,6 +904,9 @@ static void nan_de_rx_subscribe(struct nan_de *de, struct nan_de_service *srv,
|
|||
return;
|
||||
}
|
||||
|
||||
if (de->offload)
|
||||
goto offload;
|
||||
|
||||
/* Reply with a solicited Publish message */
|
||||
/* Service Descriptor attribute */
|
||||
sda_len = NAN_SERVICE_ID_LEN + 1 + 1 + 1;
|
||||
|
@ -939,6 +973,7 @@ static void nan_de_rx_subscribe(struct nan_de *de, struct nan_de_service *srv,
|
|||
|
||||
nan_de_pause_state(srv, peer_addr, instance_id);
|
||||
|
||||
offload:
|
||||
if (!srv->publish.disable_events && de->cb.replied)
|
||||
de->cb.replied(de->cb.ctx, srv->id, peer_addr, instance_id,
|
||||
srv_proto_type, ssi, ssi_len);
|
||||
|
@ -1094,6 +1129,8 @@ static void nan_de_rx_sda(struct nan_de *de, const u8 *peer_addr,
|
|||
wpa_hexdump(MSG_MSGDUMP, "NAN: ssi",
|
||||
ssi, ssi_len);
|
||||
}
|
||||
nan_de_process_elem_container(de, buf, len, peer_addr,
|
||||
freq, srv->is_p2p);
|
||||
}
|
||||
|
||||
switch (type) {
|
||||
|
@ -1196,10 +1233,23 @@ static int nan_de_derive_service_id(struct nan_de_service *srv)
|
|||
}
|
||||
|
||||
|
||||
const u8 * nan_de_get_service_id(struct nan_de *de, int id)
|
||||
{
|
||||
struct nan_de_service *srv;
|
||||
|
||||
if (id < 1 || id > NAN_DE_MAX_SERVICE)
|
||||
return NULL;
|
||||
srv = de->service[id - 1];
|
||||
if (!srv)
|
||||
return NULL;
|
||||
return srv->service_id;
|
||||
}
|
||||
|
||||
|
||||
int nan_de_publish(struct nan_de *de, const char *service_name,
|
||||
enum nan_service_protocol_type srv_proto_type,
|
||||
const struct wpabuf *ssi, const struct wpabuf *elems,
|
||||
struct nan_publish_params *params)
|
||||
struct nan_publish_params *params, bool p2p)
|
||||
{
|
||||
int publish_id;
|
||||
struct nan_de_service *srv;
|
||||
|
@ -1209,6 +1259,12 @@ int nan_de_publish(struct nan_de *de, const char *service_name,
|
|||
return -1;
|
||||
}
|
||||
|
||||
if (!params->unsolicited && !params->solicited) {
|
||||
wpa_printf(MSG_INFO,
|
||||
"NAN: Publish() - both unsolicited and solicited disabled is invalid");
|
||||
return -1;
|
||||
}
|
||||
|
||||
publish_id = nan_de_get_handle(de);
|
||||
if (publish_id < 1)
|
||||
return -1;
|
||||
|
@ -1255,6 +1311,7 @@ int nan_de_publish(struct nan_de *de, const char *service_name,
|
|||
wpa_printf(MSG_DEBUG, "NAN: Assigned new publish handle %d for %s",
|
||||
publish_id, service_name);
|
||||
srv->id = publish_id;
|
||||
srv->is_p2p = p2p;
|
||||
nan_de_add_srv(de, srv);
|
||||
nan_de_run_timer(de);
|
||||
return publish_id;
|
||||
|
@ -1306,7 +1363,7 @@ int nan_de_update_publish(struct nan_de *de, int publish_id,
|
|||
int nan_de_subscribe(struct nan_de *de, const char *service_name,
|
||||
enum nan_service_protocol_type srv_proto_type,
|
||||
const struct wpabuf *ssi, const struct wpabuf *elems,
|
||||
struct nan_subscribe_params *params)
|
||||
struct nan_subscribe_params *params, bool p2p)
|
||||
{
|
||||
int subscribe_id;
|
||||
struct nan_de_service *srv;
|
||||
|
@ -1331,6 +1388,17 @@ int nan_de_subscribe(struct nan_de *de, const char *service_name,
|
|||
if (nan_de_derive_service_id(srv) < 0)
|
||||
goto fail;
|
||||
os_memcpy(&srv->subscribe, params, sizeof(*params));
|
||||
|
||||
if (params->freq_list) {
|
||||
size_t len;
|
||||
|
||||
len = (int_array_len(params->freq_list) + 1) * sizeof(int);
|
||||
srv->freq_list = os_memdup(params->freq_list, len);
|
||||
if (!srv->freq_list)
|
||||
goto fail;
|
||||
}
|
||||
srv->subscribe.freq_list = NULL;
|
||||
|
||||
srv->srv_proto_type = srv_proto_type;
|
||||
if (ssi) {
|
||||
srv->ssi = wpabuf_dup(ssi);
|
||||
|
@ -1346,6 +1414,7 @@ int nan_de_subscribe(struct nan_de *de, const char *service_name,
|
|||
wpa_printf(MSG_DEBUG, "NAN: Assigned new subscribe handle %d for %s",
|
||||
subscribe_id, service_name);
|
||||
srv->id = subscribe_id;
|
||||
srv->is_p2p = p2p;
|
||||
nan_de_add_srv(de, srv);
|
||||
nan_de_run_timer(de);
|
||||
return subscribe_id;
|
||||
|
|
|
@ -53,9 +53,13 @@ struct nan_callbacks {
|
|||
void (*receive)(void *ctx, int id, int peer_instance_id,
|
||||
const u8 *ssi, size_t ssi_len,
|
||||
const u8 *peer_addr);
|
||||
|
||||
void (*process_p2p_usd_elems)(void *ctx, const u8 *buf,
|
||||
u16 buf_len, const u8 *peer_addr,
|
||||
unsigned int freq);
|
||||
};
|
||||
|
||||
struct nan_de * nan_de_init(const u8 *nmi, bool ap,
|
||||
struct nan_de * nan_de_init(const u8 *nmi, bool offload, bool ap,
|
||||
const struct nan_callbacks *cb);
|
||||
void nan_de_flush(struct nan_de *de);
|
||||
void nan_de_deinit(struct nan_de *de);
|
||||
|
@ -68,6 +72,7 @@ void nan_de_tx_wait_ended(struct nan_de *de);
|
|||
|
||||
void nan_de_rx_sdf(struct nan_de *de, const u8 *peer_addr, unsigned int freq,
|
||||
const u8 *buf, size_t len);
|
||||
const u8 * nan_de_get_service_id(struct nan_de *de, int id);
|
||||
|
||||
struct nan_publish_params {
|
||||
/* configuration_parameters */
|
||||
|
@ -105,7 +110,7 @@ struct nan_publish_params {
|
|||
int nan_de_publish(struct nan_de *de, const char *service_name,
|
||||
enum nan_service_protocol_type srv_proto_type,
|
||||
const struct wpabuf *ssi, const struct wpabuf *elems,
|
||||
struct nan_publish_params *params);
|
||||
struct nan_publish_params *params, bool p2p);
|
||||
|
||||
void nan_de_cancel_publish(struct nan_de *de, int publish_id);
|
||||
|
||||
|
@ -124,6 +129,9 @@ struct nan_subscribe_params {
|
|||
/* Selected frequency */
|
||||
unsigned int freq;
|
||||
|
||||
/* Multi-channel frequencies (publishChannelList) */
|
||||
const int *freq_list;
|
||||
|
||||
/* Query period in ms; 0 = use default */
|
||||
unsigned int query_period;
|
||||
};
|
||||
|
@ -132,7 +140,7 @@ struct nan_subscribe_params {
|
|||
int nan_de_subscribe(struct nan_de *de, const char *service_name,
|
||||
enum nan_service_protocol_type srv_proto_type,
|
||||
const struct wpabuf *ssi, const struct wpabuf *elems,
|
||||
struct nan_subscribe_params *params);
|
||||
struct nan_subscribe_params *params, bool p2p);
|
||||
|
||||
void nan_de_cancel_subscribe(struct nan_de *de, int subscribe_id);
|
||||
|
||||
|
|
|
@ -19,6 +19,8 @@ struct ptksa_cache {
|
|||
unsigned int n_ptksa;
|
||||
};
|
||||
|
||||
#ifdef CONFIG_PTKSA_CACHE
|
||||
|
||||
static void ptksa_cache_set_expiration(struct ptksa_cache *ptksa);
|
||||
|
||||
|
||||
|
@ -342,3 +344,44 @@ struct ptksa_cache_entry * ptksa_cache_add(struct ptksa_cache *ptksa,
|
|||
|
||||
return entry;
|
||||
}
|
||||
|
||||
#else /* CONFIG_PTKSA_CACHE */
|
||||
|
||||
struct ptksa_cache * ptksa_cache_init(void)
|
||||
{
|
||||
return (struct ptksa_cache *) 1;
|
||||
}
|
||||
|
||||
|
||||
void ptksa_cache_deinit(struct ptksa_cache *ptksa)
|
||||
{
|
||||
}
|
||||
|
||||
|
||||
struct ptksa_cache_entry *
|
||||
ptksa_cache_get(struct ptksa_cache *ptksa, const u8 *addr, u32 cipher)
|
||||
{
|
||||
return NULL;
|
||||
}
|
||||
|
||||
|
||||
int ptksa_cache_list(struct ptksa_cache *ptksa, char *buf, size_t len)
|
||||
{
|
||||
return -1;
|
||||
}
|
||||
|
||||
|
||||
struct ptksa_cache_entry *
|
||||
ptksa_cache_add(struct ptksa_cache *ptksa, const u8 *own_addr, const u8 *addr,
|
||||
u32 cipher, u32 life_time, const struct wpa_ptk *ptk,
|
||||
void (*cb)(struct ptksa_cache_entry *e), void *ctx, u32 akmp)
|
||||
{
|
||||
return NULL;
|
||||
}
|
||||
|
||||
|
||||
void ptksa_cache_flush(struct ptksa_cache *ptksa, const u8 *addr, u32 cipher)
|
||||
{
|
||||
}
|
||||
|
||||
#endif /* CONFIG_PTKSA_CACHE */
|
||||
|
|
|
@ -29,7 +29,6 @@ struct ptksa_cache_entry {
|
|||
u32 akmp;
|
||||
};
|
||||
|
||||
#ifdef CONFIG_PTKSA_CACHE
|
||||
|
||||
struct ptksa_cache;
|
||||
|
||||
|
@ -48,41 +47,4 @@ struct ptksa_cache_entry * ptksa_cache_add(struct ptksa_cache *ptksa,
|
|||
void *ctx, u32 akmp);
|
||||
void ptksa_cache_flush(struct ptksa_cache *ptksa, const u8 *addr, u32 cipher);
|
||||
|
||||
#else /* CONFIG_PTKSA_CACHE */
|
||||
|
||||
static inline struct ptksa_cache * ptksa_cache_init(void)
|
||||
{
|
||||
return (struct ptksa_cache *) 1;
|
||||
}
|
||||
|
||||
static inline void ptksa_cache_deinit(struct ptksa_cache *ptksa)
|
||||
{
|
||||
}
|
||||
|
||||
static inline struct ptksa_cache_entry *
|
||||
ptksa_cache_get(struct ptksa_cache *ptksa, const u8 *addr, u32 cipher)
|
||||
{
|
||||
return NULL;
|
||||
}
|
||||
|
||||
static inline int ptksa_cache_list(struct ptksa_cache *ptksa,
|
||||
char *buf, size_t len)
|
||||
{
|
||||
return -1;
|
||||
}
|
||||
|
||||
static inline struct ptksa_cache_entry *
|
||||
ptksa_cache_add(struct ptksa_cache *ptksa, const u8 *own_addr, const u8 *addr,
|
||||
u32 cipher, u32 life_time, const struct wpa_ptk *ptk,
|
||||
void (*cb)(struct ptksa_cache_entry *e), void *ctx, u32 akmp)
|
||||
{
|
||||
return NULL;
|
||||
}
|
||||
|
||||
static inline void ptksa_cache_flush(struct ptksa_cache *ptksa,
|
||||
const u8 *addr, u32 cipher)
|
||||
{
|
||||
}
|
||||
|
||||
#endif /* CONFIG_PTKSA_CACHE */
|
||||
#endif /* PTKSA_CACHE_H */
|
||||
|
|
File diff suppressed because it is too large
Load diff
|
@ -2103,8 +2103,11 @@ static int sae_parse_rejected_groups(struct sae_data *sae,
|
|||
|
||||
wpa_hexdump(MSG_DEBUG, "SAE: Possible elements at the end of the frame",
|
||||
*pos, end - *pos);
|
||||
if (!sae_is_rejected_groups_elem(*pos, end))
|
||||
if (!sae_is_rejected_groups_elem(*pos, end)) {
|
||||
wpabuf_free(sae->tmp->peer_rejected_groups);
|
||||
sae->tmp->peer_rejected_groups = NULL;
|
||||
return WLAN_STATUS_SUCCESS;
|
||||
}
|
||||
|
||||
epos = *pos;
|
||||
epos++; /* skip IE type */
|
||||
|
@ -2113,6 +2116,12 @@ static int sae_parse_rejected_groups(struct sae_data *sae,
|
|||
return WLAN_STATUS_UNSPECIFIED_FAILURE;
|
||||
epos++; /* skip ext ID */
|
||||
len--;
|
||||
if (len & 1) {
|
||||
wpa_printf(MSG_DEBUG,
|
||||
"SAE: Invalid length of the Rejected Groups element payload: %u",
|
||||
len);
|
||||
return WLAN_STATUS_UNSPECIFIED_FAILURE;
|
||||
}
|
||||
|
||||
wpabuf_free(sae->tmp->peer_rejected_groups);
|
||||
sae->tmp->peer_rejected_groups = wpabuf_alloc(len);
|
||||
|
@ -2196,6 +2205,9 @@ u16 sae_parse_commit(struct sae_data *sae, const u8 *data, size_t len,
|
|||
res = sae_parse_rejected_groups(sae, &pos, end);
|
||||
if (res != WLAN_STATUS_SUCCESS)
|
||||
return res;
|
||||
} else {
|
||||
wpabuf_free(sae->tmp->peer_rejected_groups);
|
||||
sae->tmp->peer_rejected_groups = NULL;
|
||||
}
|
||||
|
||||
/* Optional Anti-Clogging Token Container element */
|
||||
|
|
|
@ -82,6 +82,8 @@ struct sae_temporary_data {
|
|||
bool omit_pk_elem;
|
||||
#endif /* CONFIG_TESTING_OPTIONS */
|
||||
#endif /* CONFIG_SAE_PK */
|
||||
|
||||
struct os_reltime disabled_until;
|
||||
};
|
||||
|
||||
struct sae_pt {
|
||||
|
|
|
@ -9,6 +9,6 @@
|
|||
#define GIT_VERSION_STR_POSTFIX ""
|
||||
#endif /* GIT_VERSION_STR_POSTFIX */
|
||||
|
||||
#define VERSION_STR "2.11-devel" VERSION_STR_POSTFIX GIT_VERSION_STR_POSTFIX
|
||||
#define VERSION_STR "2.12-devel" VERSION_STR_POSTFIX GIT_VERSION_STR_POSTFIX
|
||||
|
||||
#endif /* VERSION_H */
|
||||
|
|
|
@ -1031,9 +1031,6 @@ static int wpa_ft_parse_ftie(const u8 *ie, size_t ie_len,
|
|||
const u8 *end, *pos;
|
||||
u8 link_id;
|
||||
|
||||
parse->ftie = ie;
|
||||
parse->ftie_len = ie_len;
|
||||
|
||||
pos = opt;
|
||||
end = ie + ie_len;
|
||||
wpa_hexdump(MSG_DEBUG, "FT: Parse FTE subelements", pos, end - pos);
|
||||
|
@ -1104,7 +1101,7 @@ static int wpa_ft_parse_ftie(const u8 *ie, size_t ie_len,
|
|||
link_id = pos[2] & 0x0f;
|
||||
wpa_printf(MSG_DEBUG, "FT: MLO GTK (Link ID %u)",
|
||||
link_id);
|
||||
if (link_id >= MAX_NUM_MLO_LINKS)
|
||||
if (link_id >= MAX_NUM_MLD_LINKS)
|
||||
break;
|
||||
parse->valid_mlo_gtks |= BIT(link_id);
|
||||
parse->mlo_gtk[link_id] = pos;
|
||||
|
@ -1119,7 +1116,7 @@ static int wpa_ft_parse_ftie(const u8 *ie, size_t ie_len,
|
|||
link_id = pos[2 + 6] & 0x0f;
|
||||
wpa_printf(MSG_DEBUG, "FT: MLO IGTK (Link ID %u)",
|
||||
link_id);
|
||||
if (link_id >= MAX_NUM_MLO_LINKS)
|
||||
if (link_id >= MAX_NUM_MLD_LINKS)
|
||||
break;
|
||||
parse->valid_mlo_igtks |= BIT(link_id);
|
||||
parse->mlo_igtk[link_id] = pos;
|
||||
|
@ -1134,7 +1131,7 @@ static int wpa_ft_parse_ftie(const u8 *ie, size_t ie_len,
|
|||
link_id = pos[2 + 6] & 0x0f;
|
||||
wpa_printf(MSG_DEBUG, "FT: MLO BIGTK (Link ID %u)",
|
||||
link_id);
|
||||
if (link_id >= MAX_NUM_MLO_LINKS)
|
||||
if (link_id >= MAX_NUM_MLD_LINKS)
|
||||
break;
|
||||
parse->valid_mlo_bigtks |= BIT(link_id);
|
||||
parse->mlo_bigtk[link_id] = pos;
|
||||
|
@ -1339,6 +1336,11 @@ int wpa_ft_parse_ies(const u8 *ies, size_t ies_len, struct wpa_ft_ies *parse,
|
|||
}
|
||||
if (res < 0)
|
||||
goto fail;
|
||||
|
||||
/* FTE might be fragmented. If it is, the separate Fragment
|
||||
* elements are included in MIC calculation as full elements. */
|
||||
parse->ftie = fte;
|
||||
parse->ftie_len = fte_len;
|
||||
}
|
||||
|
||||
if (prot_ie_count == 0)
|
||||
|
@ -1353,7 +1355,7 @@ int wpa_ft_parse_ies(const u8 *ies, size_t ies_len, struct wpa_ft_ies *parse,
|
|||
|
||||
/* TODO: This count should be done based on all _requested_,
|
||||
* not _accepted_ links. */
|
||||
for (link_id = 0; link_id < MAX_NUM_MLO_LINKS; link_id++) {
|
||||
for (link_id = 0; link_id < MAX_NUM_MLD_LINKS; link_id++) {
|
||||
if (parse->mlo_gtk[link_id]) {
|
||||
if (parse->rsn)
|
||||
prot_ie_count--;
|
||||
|
@ -1888,6 +1890,14 @@ int wpa_parse_wpa_ie_rsn(const u8 *rsn_ie, size_t rsn_ie_len,
|
|||
data->has_group = 1;
|
||||
data->key_mgmt = WPA_KEY_MGMT_OSEN;
|
||||
data->proto = WPA_PROTO_OSEN;
|
||||
} else if (rsn_ie_len >= 2 + 4 + 2 && rsn_ie[1] >= 4 + 2 &&
|
||||
rsn_ie[1] == rsn_ie_len - 2 &&
|
||||
(WPA_GET_BE32(&rsn_ie[2]) == RSNE_OVERRIDE_IE_VENDOR_TYPE ||
|
||||
WPA_GET_BE32(&rsn_ie[2]) ==
|
||||
RSNE_OVERRIDE_2_IE_VENDOR_TYPE) &&
|
||||
WPA_GET_LE16(&rsn_ie[2 + 4]) == RSN_VERSION) {
|
||||
pos = rsn_ie + 2 + 4 + 2;
|
||||
left = rsn_ie_len - 2 - 4 - 2;
|
||||
} else {
|
||||
const struct rsn_ie_hdr *hdr;
|
||||
|
||||
|
@ -3438,7 +3448,7 @@ static int wpa_parse_generic(const u8 *pos, struct wpa_eapol_ie_parse *ie)
|
|||
const u8 *p;
|
||||
size_t left;
|
||||
u8 link_id;
|
||||
char title[50];
|
||||
char title[100];
|
||||
int ret;
|
||||
|
||||
if (len == 0)
|
||||
|
@ -3551,7 +3561,7 @@ static int wpa_parse_generic(const u8 *pos, struct wpa_eapol_ie_parse *ie)
|
|||
selector == RSN_KEY_DATA_MLO_GTK) {
|
||||
link_id = (p[0] & RSN_MLO_GTK_KDE_PREFIX0_LINK_ID_MASK) >>
|
||||
RSN_MLO_GTK_KDE_PREFIX0_LINK_ID_SHIFT;
|
||||
if (link_id >= MAX_NUM_MLO_LINKS)
|
||||
if (link_id >= MAX_NUM_MLD_LINKS)
|
||||
return 2;
|
||||
|
||||
ie->valid_mlo_gtks |= BIT(link_id);
|
||||
|
@ -3569,7 +3579,7 @@ static int wpa_parse_generic(const u8 *pos, struct wpa_eapol_ie_parse *ie)
|
|||
selector == RSN_KEY_DATA_MLO_IGTK) {
|
||||
link_id = (p[8] & RSN_MLO_IGTK_KDE_PREFIX8_LINK_ID_MASK) >>
|
||||
RSN_MLO_IGTK_KDE_PREFIX8_LINK_ID_SHIFT;
|
||||
if (link_id >= MAX_NUM_MLO_LINKS)
|
||||
if (link_id >= MAX_NUM_MLD_LINKS)
|
||||
return 2;
|
||||
|
||||
ie->valid_mlo_igtks |= BIT(link_id);
|
||||
|
@ -3587,7 +3597,7 @@ static int wpa_parse_generic(const u8 *pos, struct wpa_eapol_ie_parse *ie)
|
|||
selector == RSN_KEY_DATA_MLO_BIGTK) {
|
||||
link_id = (p[8] & RSN_MLO_BIGTK_KDE_PREFIX8_LINK_ID_MASK) >>
|
||||
RSN_MLO_BIGTK_KDE_PREFIX8_LINK_ID_SHIFT;
|
||||
if (link_id >= MAX_NUM_MLO_LINKS)
|
||||
if (link_id >= MAX_NUM_MLD_LINKS)
|
||||
return 2;
|
||||
|
||||
ie->valid_mlo_bigtks |= BIT(link_id);
|
||||
|
@ -3605,7 +3615,7 @@ static int wpa_parse_generic(const u8 *pos, struct wpa_eapol_ie_parse *ie)
|
|||
selector == RSN_KEY_DATA_MLO_LINK) {
|
||||
link_id = (p[0] & RSN_MLO_LINK_KDE_LI_LINK_ID_MASK) >>
|
||||
RSN_MLO_LINK_KDE_LI_LINK_ID_SHIFT;
|
||||
if (link_id >= MAX_NUM_MLO_LINKS)
|
||||
if (link_id >= MAX_NUM_MLD_LINKS)
|
||||
return 2;
|
||||
|
||||
ie->valid_mlo_links |= BIT(link_id);
|
||||
|
@ -3619,6 +3629,57 @@ static int wpa_parse_generic(const u8 *pos, struct wpa_eapol_ie_parse *ie)
|
|||
return 0;
|
||||
}
|
||||
|
||||
if (left >= 1 && selector == WFA_KEY_DATA_RSN_OVERRIDE_LINK) {
|
||||
link_id = p[0];
|
||||
if (link_id >= MAX_NUM_MLD_LINKS)
|
||||
return 2;
|
||||
|
||||
ie->rsn_override_link[link_id] = p;
|
||||
ie->rsn_override_link_len[link_id] = left;
|
||||
ret = os_snprintf(title, sizeof(title),
|
||||
"RSN: Link ID %u - RSN Override Link KDE in EAPOL-Key",
|
||||
link_id);
|
||||
if (!os_snprintf_error(sizeof(title), ret))
|
||||
wpa_hexdump(MSG_DEBUG, title, pos, dlen);
|
||||
return 0;
|
||||
}
|
||||
|
||||
if (selector == RSNE_OVERRIDE_IE_VENDOR_TYPE) {
|
||||
ie->rsne_override = pos;
|
||||
ie->rsne_override_len = dlen;
|
||||
wpa_hexdump(MSG_DEBUG,
|
||||
"RSN: RSNE Override element in EAPOL-Key",
|
||||
ie->rsne_override, ie->rsne_override_len);
|
||||
return 0;
|
||||
}
|
||||
|
||||
if (selector == RSNE_OVERRIDE_2_IE_VENDOR_TYPE) {
|
||||
ie->rsne_override_2 = pos;
|
||||
ie->rsne_override_2_len = dlen;
|
||||
wpa_hexdump(MSG_DEBUG,
|
||||
"RSN: RSNE Override 2 element in EAPOL-Key",
|
||||
ie->rsne_override_2, ie->rsne_override_2_len);
|
||||
return 0;
|
||||
}
|
||||
|
||||
if (selector == RSNXE_OVERRIDE_IE_VENDOR_TYPE) {
|
||||
ie->rsnxe_override = pos;
|
||||
ie->rsnxe_override_len = dlen;
|
||||
wpa_hexdump(MSG_DEBUG,
|
||||
"RSN: RSNXE Override element in EAPOL-Key",
|
||||
ie->rsnxe_override, ie->rsnxe_override_len);
|
||||
return 0;
|
||||
}
|
||||
|
||||
if (selector == RSN_SELECTION_IE_VENDOR_TYPE) {
|
||||
ie->rsn_selection = p;
|
||||
ie->rsn_selection_len = left;
|
||||
wpa_hexdump(MSG_DEBUG,
|
||||
"RSN: RSN Selection element in EAPOL-Key",
|
||||
ie->rsn_selection, ie->rsn_selection_len);
|
||||
return 0;
|
||||
}
|
||||
|
||||
return 2;
|
||||
}
|
||||
|
||||
|
@ -3743,6 +3804,11 @@ int wpa_parse_kde_ies(const u8 *buf, size_t len, struct wpa_eapol_ie_parse *ie)
|
|||
ie->supp_oper_classes = pos + 2;
|
||||
ie->supp_oper_classes_len = pos[1];
|
||||
}
|
||||
} else if (*pos == WLAN_EID_SSID) {
|
||||
ie->ssid = pos + 2;
|
||||
ie->ssid_len = pos[1];
|
||||
wpa_hexdump_ascii(MSG_DEBUG, "RSN: SSID in EAPOL-Key",
|
||||
ie->ssid, ie->ssid_len);
|
||||
} else if (*pos == WLAN_EID_VENDOR_SPECIFIC) {
|
||||
ret = wpa_parse_generic(pos, ie);
|
||||
if (ret == 1) {
|
||||
|
@ -4253,3 +4319,24 @@ int wpa_pasn_add_extra_ies(struct wpabuf *buf, const u8 *extra_ies, size_t len)
|
|||
}
|
||||
|
||||
#endif /* CONFIG_PASN */
|
||||
|
||||
|
||||
void rsn_set_snonce_cookie(u8 *snonce)
|
||||
{
|
||||
u8 *pos;
|
||||
|
||||
pos = snonce + WPA_NONCE_LEN - 6;
|
||||
WPA_PUT_BE24(pos, OUI_WFA);
|
||||
pos += 3;
|
||||
WPA_PUT_BE24(pos, 0x000029);
|
||||
}
|
||||
|
||||
|
||||
bool rsn_is_snonce_cookie(const u8 *snonce)
|
||||
{
|
||||
const u8 *pos;
|
||||
|
||||
pos = snonce + WPA_NONCE_LEN - 6;
|
||||
return WPA_GET_BE24(pos) == OUI_WFA &&
|
||||
WPA_GET_BE24(pos + 3) == 0x000029;
|
||||
}
|
||||
|
|
|
@ -9,12 +9,15 @@
|
|||
#ifndef WPA_COMMON_H
|
||||
#define WPA_COMMON_H
|
||||
|
||||
#include "common/defs.h"
|
||||
|
||||
/* IEEE 802.11i */
|
||||
#define PMKID_LEN 16
|
||||
#define PMK_LEN 32
|
||||
#define PMK_LEN_SUITE_B_192 48
|
||||
#define PMK_LEN_MAX 64
|
||||
#define WPA_REPLAY_COUNTER_LEN 8
|
||||
#define RSN_PN_LEN 6
|
||||
#define WPA_NONCE_LEN 32
|
||||
#define WPA_KEY_RSC_LEN 8
|
||||
#define WPA_GMK_LEN 32
|
||||
|
@ -141,6 +144,7 @@ WPA_CIPHER_BIP_CMAC_256)
|
|||
#define WFA_KEY_DATA_IP_ADDR_ALLOC RSN_SELECTOR(0x50, 0x6f, 0x9a, 5)
|
||||
#define WFA_KEY_DATA_TRANSITION_DISABLE RSN_SELECTOR(0x50, 0x6f, 0x9a, 0x20)
|
||||
#define WFA_KEY_DATA_DPP RSN_SELECTOR(0x50, 0x6f, 0x9a, 0x21)
|
||||
#define WFA_KEY_DATA_RSN_OVERRIDE_LINK RSN_SELECTOR(0x50, 0x6f, 0x9a, 0x2d)
|
||||
|
||||
#define WPA_OUI_TYPE RSN_SELECTOR(0x00, 0x50, 0xf2, 1)
|
||||
|
||||
|
@ -336,52 +340,54 @@ struct rsn_ie_hdr {
|
|||
} STRUCT_PACKED;
|
||||
|
||||
|
||||
#define KDE_HDR_LEN (1 + 1 + RSN_SELECTOR_LEN)
|
||||
|
||||
struct rsn_error_kde {
|
||||
be16 mui;
|
||||
be16 error_type;
|
||||
} STRUCT_PACKED;
|
||||
|
||||
#define WPA_IGTK_KDE_PREFIX_LEN (2 + 6)
|
||||
#define WPA_IGTK_KDE_PREFIX_LEN (2 + RSN_PN_LEN)
|
||||
struct wpa_igtk_kde {
|
||||
u8 keyid[2];
|
||||
u8 pn[6];
|
||||
u8 pn[RSN_PN_LEN];
|
||||
u8 igtk[WPA_IGTK_MAX_LEN];
|
||||
} STRUCT_PACKED;
|
||||
|
||||
#define WPA_BIGTK_KDE_PREFIX_LEN (2 + 6)
|
||||
#define WPA_BIGTK_KDE_PREFIX_LEN (2 + RSN_PN_LEN)
|
||||
struct wpa_bigtk_kde {
|
||||
u8 keyid[2];
|
||||
u8 pn[6];
|
||||
u8 pn[RSN_PN_LEN];
|
||||
u8 bigtk[WPA_BIGTK_MAX_LEN];
|
||||
} STRUCT_PACKED;
|
||||
|
||||
#define RSN_MLO_GTK_KDE_PREFIX_LENGTH (1 + 6)
|
||||
#define RSN_MLO_GTK_KDE_PREFIX_LENGTH (1 + RSN_PN_LEN)
|
||||
#define RSN_MLO_GTK_KDE_PREFIX0_KEY_ID_MASK 0x03
|
||||
#define RSN_MLO_GTK_KDE_PREFIX0_TX 0x04
|
||||
#define RSN_MLO_GTK_KDE_PREFIX0_LINK_ID_SHIFT 4
|
||||
#define RSN_MLO_GTK_KDE_PREFIX0_LINK_ID_MASK 0xF0
|
||||
|
||||
#define RSN_MLO_IGTK_KDE_PREFIX_LENGTH (2 + 6 + 1)
|
||||
#define RSN_MLO_IGTK_KDE_PREFIX_LENGTH (2 + RSN_PN_LEN + 1)
|
||||
#define RSN_MLO_IGTK_KDE_PREFIX8_LINK_ID_SHIFT 4
|
||||
#define RSN_MLO_IGTK_KDE_PREFIX8_LINK_ID_MASK 0xF0
|
||||
struct rsn_mlo_igtk_kde {
|
||||
u8 keyid[2];
|
||||
u8 pn[6];
|
||||
u8 pn[RSN_PN_LEN];
|
||||
u8 prefix8;
|
||||
u8 igtk[WPA_IGTK_MAX_LEN];
|
||||
} STRUCT_PACKED;
|
||||
|
||||
#define RSN_MLO_BIGTK_KDE_PREFIX_LENGTH (2 + 6 + 1)
|
||||
#define RSN_MLO_BIGTK_KDE_PREFIX_LENGTH (2 + RSN_PN_LEN + 1)
|
||||
#define RSN_MLO_BIGTK_KDE_PREFIX8_LINK_ID_SHIFT 4
|
||||
#define RSN_MLO_BIGTK_KDE_PREFIX8_LINK_ID_MASK 0xF0
|
||||
struct rsn_mlo_bigtk_kde {
|
||||
u8 keyid[2];
|
||||
u8 pn[6];
|
||||
u8 pn[RSN_PN_LEN];
|
||||
u8 prefix8;
|
||||
u8 bigtk[WPA_BIGTK_MAX_LEN];
|
||||
} STRUCT_PACKED;
|
||||
|
||||
#define RSN_MLO_LINK_KDE_FIXED_LENGTH (1 + 6)
|
||||
#define RSN_MLO_LINK_KDE_FIXED_LENGTH (1 + ETH_ALEN)
|
||||
#define RSN_MLO_LINK_KDE_LINK_INFO_INDEX 0
|
||||
#define RSN_MLO_LINK_KDE_LI_LINK_ID_SHIFT 0
|
||||
#define RSN_MLO_LINK_KDE_LI_LINK_ID_MASK 0x0F
|
||||
|
@ -557,8 +563,6 @@ int wpa_compare_rsn_ie(int ft_initial_assoc,
|
|||
const u8 *ie2, size_t ie2len);
|
||||
int wpa_insert_pmkid(u8 *ies, size_t *ies_len, const u8 *pmkid, bool replace);
|
||||
|
||||
#define MAX_NUM_MLO_LINKS 15
|
||||
|
||||
struct wpa_ft_ies {
|
||||
const u8 *mdie;
|
||||
size_t mdie_len;
|
||||
|
@ -596,14 +600,14 @@ struct wpa_ft_ies {
|
|||
const u8 *rsnxe;
|
||||
size_t rsnxe_len;
|
||||
u16 valid_mlo_gtks; /* bitmap of valid link GTK subelements */
|
||||
const u8 *mlo_gtk[MAX_NUM_MLO_LINKS];
|
||||
size_t mlo_gtk_len[MAX_NUM_MLO_LINKS];
|
||||
const u8 *mlo_gtk[MAX_NUM_MLD_LINKS];
|
||||
size_t mlo_gtk_len[MAX_NUM_MLD_LINKS];
|
||||
u16 valid_mlo_igtks; /* bitmap of valid link IGTK subelements */
|
||||
const u8 *mlo_igtk[MAX_NUM_MLO_LINKS];
|
||||
size_t mlo_igtk_len[MAX_NUM_MLO_LINKS];
|
||||
const u8 *mlo_igtk[MAX_NUM_MLD_LINKS];
|
||||
size_t mlo_igtk_len[MAX_NUM_MLD_LINKS];
|
||||
u16 valid_mlo_bigtks; /* bitmap of valid link BIGTK subelements */
|
||||
const u8 *mlo_bigtk[MAX_NUM_MLO_LINKS];
|
||||
size_t mlo_bigtk_len[MAX_NUM_MLO_LINKS];
|
||||
const u8 *mlo_bigtk[MAX_NUM_MLD_LINKS];
|
||||
size_t mlo_bigtk_len[MAX_NUM_MLD_LINKS];
|
||||
|
||||
struct wpabuf *fte_buf;
|
||||
};
|
||||
|
@ -640,6 +644,14 @@ struct wpa_pasn_params_data {
|
|||
#define WPA_PASN_PUBKEY_COMPRESSED_1 0x03
|
||||
#define WPA_PASN_PUBKEY_UNCOMPRESSED 0x04
|
||||
|
||||
/* WPA3 specification - RSN Selection element */
|
||||
enum rsn_selection_variant {
|
||||
RSN_SELECTION_RSNE = 0,
|
||||
RSN_SELECTION_RSNE_OVERRIDE = 1,
|
||||
RSN_SELECTION_RSNE_OVERRIDE_2 = 2,
|
||||
};
|
||||
|
||||
|
||||
int wpa_ft_parse_ies(const u8 *ies, size_t ies_len, struct wpa_ft_ies *parse,
|
||||
int key_mgmt, bool reassoc_resp);
|
||||
void wpa_ft_parse_ies_free(struct wpa_ft_ies *parse);
|
||||
|
@ -695,22 +707,34 @@ struct wpa_eapol_ie_parse {
|
|||
size_t supp_channels_len;
|
||||
const u8 *supp_oper_classes;
|
||||
size_t supp_oper_classes_len;
|
||||
const u8 *ssid;
|
||||
size_t ssid_len;
|
||||
u8 qosinfo;
|
||||
u16 aid;
|
||||
const u8 *wmm;
|
||||
size_t wmm_len;
|
||||
const u8 *rsn_selection;
|
||||
size_t rsn_selection_len;
|
||||
const u8 *rsne_override;
|
||||
size_t rsne_override_len;
|
||||
const u8 *rsne_override_2;
|
||||
size_t rsne_override_2_len;
|
||||
const u8 *rsnxe_override;
|
||||
size_t rsnxe_override_len;
|
||||
u16 valid_mlo_gtks; /* bitmap of valid link GTK KDEs */
|
||||
const u8 *mlo_gtk[MAX_NUM_MLO_LINKS];
|
||||
size_t mlo_gtk_len[MAX_NUM_MLO_LINKS];
|
||||
const u8 *mlo_gtk[MAX_NUM_MLD_LINKS];
|
||||
size_t mlo_gtk_len[MAX_NUM_MLD_LINKS];
|
||||
u16 valid_mlo_igtks; /* bitmap of valid link IGTK KDEs */
|
||||
const u8 *mlo_igtk[MAX_NUM_MLO_LINKS];
|
||||
size_t mlo_igtk_len[MAX_NUM_MLO_LINKS];
|
||||
const u8 *mlo_igtk[MAX_NUM_MLD_LINKS];
|
||||
size_t mlo_igtk_len[MAX_NUM_MLD_LINKS];
|
||||
u16 valid_mlo_bigtks; /* bitmap of valid link BIGTK KDEs */
|
||||
const u8 *mlo_bigtk[MAX_NUM_MLO_LINKS];
|
||||
size_t mlo_bigtk_len[MAX_NUM_MLO_LINKS];
|
||||
const u8 *mlo_bigtk[MAX_NUM_MLD_LINKS];
|
||||
size_t mlo_bigtk_len[MAX_NUM_MLD_LINKS];
|
||||
u16 valid_mlo_links; /* bitmap of valid MLO link KDEs */
|
||||
const u8 *mlo_link[MAX_NUM_MLO_LINKS];
|
||||
size_t mlo_link_len[MAX_NUM_MLO_LINKS];
|
||||
const u8 *mlo_link[MAX_NUM_MLD_LINKS];
|
||||
size_t mlo_link_len[MAX_NUM_MLD_LINKS];
|
||||
const u8 *rsn_override_link[MAX_NUM_MLD_LINKS];
|
||||
size_t rsn_override_link_len[MAX_NUM_MLD_LINKS];
|
||||
};
|
||||
|
||||
int wpa_parse_kde_ies(const u8 *buf, size_t len, struct wpa_eapol_ie_parse *ie);
|
||||
|
@ -782,4 +806,7 @@ int wpa_pasn_parse_parameter_ie(const u8 *data, u8 len, bool from_ap,
|
|||
void wpa_pasn_add_rsnxe(struct wpabuf *buf, u16 capab);
|
||||
int wpa_pasn_add_extra_ies(struct wpabuf *buf, const u8 *extra_ies, size_t len);
|
||||
|
||||
void rsn_set_snonce_cookie(u8 *snonce);
|
||||
bool rsn_is_snonce_cookie(const u8 *snonce);
|
||||
|
||||
#endif /* WPA_COMMON_H */
|
||||
|
|
|
@ -13,6 +13,8 @@
|
|||
extern "C" {
|
||||
#endif
|
||||
|
||||
#define WPA_CTRL_IFACE_LINK_NAME "link"
|
||||
|
||||
/* wpa_supplicant control interface - fixed message prefixes */
|
||||
|
||||
/** Interactive request for identity/password/pin */
|
||||
|
@ -204,6 +206,7 @@ extern "C" {
|
|||
#define DPP_EVENT_CONFOBJ_SSID "DPP-CONFOBJ-SSID "
|
||||
#define DPP_EVENT_CONFOBJ_SSID_CHARSET "DPP-CONFOBJ-SSID-CHARSET "
|
||||
#define DPP_EVENT_CONFOBJ_PASS "DPP-CONFOBJ-PASS "
|
||||
#define DPP_EVENT_CONFOBJ_IDPASS "DPP-CONFOBJ-IDPASS "
|
||||
#define DPP_EVENT_CONFOBJ_PSK "DPP-CONFOBJ-PSK "
|
||||
#define DPP_EVENT_CONNECTOR "DPP-CONNECTOR "
|
||||
#define DPP_EVENT_C_SIGN_KEY "DPP-C-SIGN-KEY "
|
||||
|
@ -225,6 +228,7 @@ extern "C" {
|
|||
#define DPP_EVENT_CHIRP_STOPPED "DPP-CHIRP-STOPPED "
|
||||
#define DPP_EVENT_MUD_URL "DPP-MUD-URL "
|
||||
#define DPP_EVENT_BAND_SUPPORT "DPP-BAND-SUPPORT "
|
||||
#define DPP_EVENT_ENROLLEE_CAPABILITY "DPP-ENROLLEE-CAPABILITY "
|
||||
#define DPP_EVENT_CSR "DPP-CSR "
|
||||
#define DPP_EVENT_CHIRP_RX "DPP-CHIRP-RX "
|
||||
#define DPP_EVENT_CONF_NEEDED "DPP-CONF-NEEDED "
|
||||
|
@ -413,6 +417,9 @@ extern "C" {
|
|||
/* parameters: <STA address> <dialog token> <report mode> <beacon report> */
|
||||
#define BEACON_RESP_RX "BEACON-RESP-RX "
|
||||
|
||||
/* parameters: <STA address> <dialog token> <link measurement report> */
|
||||
#define LINK_MSR_RESP_RX "LINK-MSR-RESP-RX "
|
||||
|
||||
/* PMKSA cache entry added; parameters: <BSSID> <network_id> */
|
||||
#define PMKSA_CACHE_ADDED "PMKSA-CACHE-ADDED "
|
||||
/* PMKSA cache entry removed; parameters: <BSSID> <network_id> */
|
||||
|
|
|
@ -1835,6 +1835,7 @@ int omac1_aes_vector(const u8 *key, size_t key_len, size_t num_elem,
|
|||
ret = 0;
|
||||
fail:
|
||||
EVP_MAC_CTX_free(ctx);
|
||||
EVP_MAC_free(emac);
|
||||
return ret;
|
||||
#else /* OpenSSL version >= 3.0 */
|
||||
CMAC_CTX *ctx;
|
||||
|
@ -3932,9 +3933,10 @@ static int openssl_evp_pkey_ec_prime_len(struct crypto_ec_key *key)
|
|||
group = EC_GROUP_new_by_curve_name(nid);
|
||||
prime = BN_new();
|
||||
if (!group || !prime)
|
||||
return -1;
|
||||
goto fail;
|
||||
if (EC_GROUP_get_curve(group, prime, NULL, NULL, NULL) == 1)
|
||||
prime_len = BN_num_bytes(prime);
|
||||
fail:
|
||||
EC_GROUP_free(group);
|
||||
BN_free(prime);
|
||||
return prime_len;
|
||||
|
@ -4880,7 +4882,7 @@ hpke_labeled_expand(struct hpke_context *ctx, bool kem, const u8 *prk,
|
|||
#if OPENSSL_VERSION_NUMBER >= 0x30000000L
|
||||
hmac = EVP_MAC_fetch(NULL, "HMAC", NULL);
|
||||
if (!hmac)
|
||||
return -1;
|
||||
goto fail;
|
||||
|
||||
params[0] = OSSL_PARAM_construct_utf8_string(
|
||||
"digest",
|
||||
|
@ -4889,7 +4891,7 @@ hpke_labeled_expand(struct hpke_context *ctx, bool kem, const u8 *prk,
|
|||
#else /* OpenSSL version >= 3.0 */
|
||||
hctx = HMAC_CTX_new();
|
||||
if (!hctx)
|
||||
return -1;
|
||||
goto fail;
|
||||
#endif /* OpenSSL version >= 3.0 */
|
||||
|
||||
while (left > 0) {
|
||||
|
@ -4898,7 +4900,7 @@ hpke_labeled_expand(struct hpke_context *ctx, bool kem, const u8 *prk,
|
|||
EVP_MAC_CTX_free(hctx);
|
||||
hctx = EVP_MAC_CTX_new(hmac);
|
||||
if (!hctx)
|
||||
return -1;
|
||||
goto fail;
|
||||
|
||||
if (EVP_MAC_init(hctx, prk, mdlen, params) != 1)
|
||||
goto fail;
|
||||
|
|
|
@ -27,6 +27,10 @@
|
|||
#endif /* CONFIG_MACSEC */
|
||||
#include "utils/list.h"
|
||||
|
||||
struct nan_subscribe_params;
|
||||
struct nan_publish_params;
|
||||
enum nan_service_protocol_type;
|
||||
|
||||
#define HOSTAPD_CHAN_DISABLED 0x00000001
|
||||
#define HOSTAPD_CHAN_NO_IR 0x00000002
|
||||
#define HOSTAPD_CHAN_RADAR 0x00000008
|
||||
|
@ -43,6 +47,7 @@
|
|||
|
||||
#define HOSTAPD_CHAN_VHT_80MHZ_SUBCHANNEL 0x00000800
|
||||
#define HOSTAPD_CHAN_VHT_160MHZ_SUBCHANNEL 0x00001000
|
||||
#define HOSTAPD_CHAN_EHT_320MHZ_SUBCHANNEL 0x00002000
|
||||
|
||||
#define HOSTAPD_CHAN_INDOOR_ONLY 0x00010000
|
||||
#define HOSTAPD_CHAN_GO_CONCURRENT 0x00020000
|
||||
|
@ -246,6 +251,11 @@ struct hostapd_hw_modes {
|
|||
*/
|
||||
enum hostapd_hw_mode mode;
|
||||
|
||||
/**
|
||||
* is_6ghz - Whether the mode information is for the 6 GHz band
|
||||
*/
|
||||
bool is_6ghz;
|
||||
|
||||
/**
|
||||
* num_channels - Number of entries in the channels array
|
||||
*/
|
||||
|
@ -311,6 +321,27 @@ struct hostapd_hw_modes {
|
|||
};
|
||||
|
||||
|
||||
/**
|
||||
* struct hostapd_multi_hw_info: Supported multiple underlying hardware info
|
||||
*/
|
||||
struct hostapd_multi_hw_info {
|
||||
/**
|
||||
* hw_idx - Hardware index
|
||||
*/
|
||||
u8 hw_idx;
|
||||
|
||||
/**
|
||||
* start_freq - Frequency range start in MHz
|
||||
*/
|
||||
int start_freq;
|
||||
|
||||
/**
|
||||
* end_freq - Frequency range end in MHz
|
||||
*/
|
||||
int end_freq;
|
||||
};
|
||||
|
||||
|
||||
#define IEEE80211_CAP_ESS 0x0001
|
||||
#define IEEE80211_CAP_IBSS 0x0002
|
||||
#define IEEE80211_CAP_PRIVACY 0x0010
|
||||
|
@ -695,6 +726,14 @@ struct wpa_driver_scan_params {
|
|||
*/
|
||||
unsigned int min_probe_req_content:1;
|
||||
|
||||
/**
|
||||
* link_id - Specify the link that is requesting the scan on an MLD
|
||||
*
|
||||
* This is set when operating as an AP MLD and doing an OBSS scan.
|
||||
* -1 indicates that no particular link ID is set.
|
||||
*/
|
||||
s8 link_id;
|
||||
|
||||
/*
|
||||
* NOTE: Whenever adding new parameters here, please make sure
|
||||
* wpa_scan_clone_params() and wpa_scan_free_params() get updated with
|
||||
|
@ -1349,6 +1388,12 @@ struct wpa_driver_associate_params {
|
|||
* mld_params - MLD association parameters
|
||||
*/
|
||||
struct wpa_driver_mld_params mld_params;
|
||||
|
||||
|
||||
/**
|
||||
* rsn_overriding - wpa_supplicant RSN overriding support
|
||||
*/
|
||||
bool rsn_overriding;
|
||||
};
|
||||
|
||||
enum hide_ssid {
|
||||
|
@ -1372,6 +1417,23 @@ struct wowlan_triggers {
|
|||
u8 rfkill_release;
|
||||
};
|
||||
|
||||
struct unsol_bcast_probe_resp {
|
||||
/**
|
||||
* Unsolicited broadcast Probe Response interval in TUs
|
||||
*/
|
||||
unsigned int unsol_bcast_probe_resp_interval;
|
||||
|
||||
/**
|
||||
* Unsolicited broadcast Probe Response template data
|
||||
*/
|
||||
u8 *unsol_bcast_probe_resp_tmpl;
|
||||
|
||||
/**
|
||||
* Unsolicited broadcast Probe Response template length
|
||||
*/
|
||||
size_t unsol_bcast_probe_resp_tmpl_len;
|
||||
};
|
||||
|
||||
struct wpa_driver_ap_params {
|
||||
/**
|
||||
* head - Beacon head from IEEE 802.11 header to IEs before TIM IE
|
||||
|
@ -1714,21 +1776,6 @@ struct wpa_driver_ap_params {
|
|||
*/
|
||||
size_t fd_frame_tmpl_len;
|
||||
|
||||
/**
|
||||
* Unsolicited broadcast Probe Response interval in TUs
|
||||
*/
|
||||
unsigned int unsol_bcast_probe_resp_interval;
|
||||
|
||||
/**
|
||||
* Unsolicited broadcast Probe Response template data
|
||||
*/
|
||||
u8 *unsol_bcast_probe_resp_tmpl;
|
||||
|
||||
/**
|
||||
* Unsolicited broadcast Probe Response template length
|
||||
*/
|
||||
size_t unsol_bcast_probe_resp_tmpl_len;
|
||||
|
||||
/**
|
||||
* mbssid_tx_iface - Transmitting interface of the MBSSID set
|
||||
*/
|
||||
|
@ -1795,6 +1842,9 @@ struct wpa_driver_ap_params {
|
|||
*/
|
||||
u8 **rnr_elem_offset;
|
||||
|
||||
/* Unsolicited broadcast Probe Response data */
|
||||
struct unsol_bcast_probe_resp ubpr;
|
||||
|
||||
/**
|
||||
* allowed_freqs - List of allowed 20 MHz channel center frequencies in
|
||||
* MHz for AP operation. Drivers which support this parameter will
|
||||
|
@ -2309,6 +2359,12 @@ struct wpa_driver_capa {
|
|||
#define WPA_DRIVER_FLAGS2_OWE_OFFLOAD_AP 0x0000000000080000ULL
|
||||
/** Driver support AP SAE authentication offload */
|
||||
#define WPA_DRIVER_FLAGS2_SAE_OFFLOAD_AP 0x0000000000100000ULL
|
||||
/** Driver supports TWT responder in HT and VHT modes */
|
||||
#define WPA_DRIVER_FLAGS2_HT_VHT_TWT_RESPONDER 0x0000000000200000ULL
|
||||
/** Driver supports RSN override elements */
|
||||
#define WPA_DRIVER_FLAGS2_RSN_OVERRIDE_STA 0x0000000000400000ULL
|
||||
/** Driver supports NAN offload */
|
||||
#define WPA_DRIVER_FLAGS2_NAN_OFFLOAD 0x0000000000800000ULL
|
||||
u64 flags2;
|
||||
|
||||
#define FULL_AP_CLIENT_STATE_SUPP(drv_flags) \
|
||||
|
@ -2711,6 +2767,7 @@ struct beacon_data {
|
|||
* @counter_offset_presp: Offset to the count field in probe resp.
|
||||
* @punct_bitmap - Preamble puncturing bitmap
|
||||
* @link_id: Link ID to determine the link for MLD; -1 for non-MLD
|
||||
* @ubpr: Unsolicited broadcast Probe Response frame data
|
||||
*/
|
||||
struct csa_settings {
|
||||
u8 cs_count;
|
||||
|
@ -2725,6 +2782,8 @@ struct csa_settings {
|
|||
|
||||
u16 punct_bitmap;
|
||||
int link_id;
|
||||
|
||||
struct unsol_bcast_probe_resp ubpr;
|
||||
};
|
||||
|
||||
/**
|
||||
|
@ -2736,6 +2795,8 @@ struct csa_settings {
|
|||
* @beacon_after: Next Beacon/Probe Response/(Re)Association Response frame info
|
||||
* @counter_offset_beacon: Offset to the count field in Beacon frame tail
|
||||
* @counter_offset_presp: Offset to the count field in Probe Response frame
|
||||
* @ubpr: Unsolicited broadcast Probe Response frame data
|
||||
* @link_id: If >= 0 indicates the link of the AP MLD to configure
|
||||
*/
|
||||
struct cca_settings {
|
||||
u8 cca_count;
|
||||
|
@ -2746,6 +2807,10 @@ struct cca_settings {
|
|||
|
||||
u16 counter_offset_beacon;
|
||||
u16 counter_offset_presp;
|
||||
|
||||
struct unsol_bcast_probe_resp ubpr;
|
||||
|
||||
int link_id;
|
||||
};
|
||||
|
||||
/* TDLS peer capabilities for send_tdls_mgmt() */
|
||||
|
@ -3360,6 +3425,17 @@ struct wpa_driver_ops {
|
|||
int (*update_ft_ies)(void *priv, const u8 *md, const u8 *ies,
|
||||
size_t ies_len);
|
||||
|
||||
/**
|
||||
* get_scan_results - Fetch the latest scan results
|
||||
* @priv: Private driver interface data
|
||||
* @bssid: Return results only for the specified BSSID, %NULL for all
|
||||
*
|
||||
* Returns: Allocated buffer of scan results (caller is responsible for
|
||||
* freeing the data structure) on success, NULL on failure
|
||||
*/
|
||||
struct wpa_scan_results * (*get_scan_results)(void *priv,
|
||||
const u8 *bssid);
|
||||
|
||||
/**
|
||||
* get_scan_results2 - Fetch the latest scan results
|
||||
* @priv: private driver interface data
|
||||
|
@ -3561,13 +3637,15 @@ struct wpa_driver_ops {
|
|||
/**
|
||||
* flush - Flush all association stations (AP only)
|
||||
* @priv: Private driver interface data
|
||||
* @link_id: In case of MLO, valid link ID on which all associated
|
||||
* stations will be flushed, -1 otherwise.
|
||||
* Returns: 0 on success, -1 on failure
|
||||
*
|
||||
* This function requests the driver to disassociate all associated
|
||||
* stations. This function does not need to be implemented if the
|
||||
* driver does not process association frames internally.
|
||||
*/
|
||||
int (*flush)(void *priv);
|
||||
int (*flush)(void *priv, int link_id);
|
||||
|
||||
/**
|
||||
* set_generic_elem - Add IEs into Beacon/Probe Response frames (AP)
|
||||
|
@ -4544,13 +4622,14 @@ struct wpa_driver_ops {
|
|||
/**
|
||||
* stop_ap - Removes beacon from AP
|
||||
* @priv: Private driver interface data
|
||||
* @link_id: Link ID of the specified link; -1 for non-MLD
|
||||
* Returns: 0 on success, -1 on failure (or if not supported)
|
||||
*
|
||||
* This optional function can be used to disable AP mode related
|
||||
* configuration. Unlike deinit_ap, it does not change to station
|
||||
* mode.
|
||||
*/
|
||||
int (*stop_ap)(void *priv);
|
||||
int (*stop_ap)(void *priv, int link_id);
|
||||
|
||||
/**
|
||||
* get_survey - Retrieve survey data
|
||||
|
@ -5130,15 +5209,137 @@ struct wpa_driver_ops {
|
|||
* @priv: Private driver interface data
|
||||
* @link_id: The link ID
|
||||
* @addr: The MAC address to use for the link
|
||||
* @bss_ctx: BSS context for %WPA_IF_AP_BSS interfaces
|
||||
* Returns: 0 on success, negative value on failure
|
||||
*/
|
||||
int (*link_add)(void *priv, u8 link_id, const u8 *addr);
|
||||
int (*link_add)(void *priv, u8 link_id, const u8 *addr, void *bss_ctx);
|
||||
|
||||
/**
|
||||
* link_remove - Remove a link from the AP MLD interface
|
||||
* @priv: Private driver interface data
|
||||
* @type: Interface type
|
||||
* @ifname: Interface name of the virtual interface from where the link
|
||||
* is to be removed.
|
||||
* @link_id: Valid link ID to remove
|
||||
* Returns: 0 on success, -1 on failure
|
||||
*/
|
||||
int (*link_remove)(void *priv, enum wpa_driver_if_type type,
|
||||
const char *ifname, u8 link_id);
|
||||
|
||||
/**
|
||||
* is_drv_shared - Check whether the driver interface is shared
|
||||
* @priv: Private driver interface data from init()
|
||||
* @link_id: Link ID to match
|
||||
* Returns: true if it is being used or else false.
|
||||
*
|
||||
* Checks whether the driver interface is being used by other partner
|
||||
* BSS(s) or not. This is used to decide whether the driver interface
|
||||
* needs to be deinitilized when one interface is getting deinitialized.
|
||||
*
|
||||
* NOTE: @link_id will be used only when there is only one BSS
|
||||
* present and if that single link is active. In that case, the
|
||||
* link ID is matched with the active link_id to decide whether the
|
||||
* driver interface is being used by other partner BSS(s).
|
||||
*/
|
||||
bool (*is_drv_shared)(void *priv, int link_id);
|
||||
|
||||
/**
|
||||
* link_sta_remove - Remove a link STA from an MLD STA
|
||||
* @priv: Private driver interface data
|
||||
* @link_id: The link ID which the link STA is using
|
||||
* @addr: The MLD MAC address of the MLD STA
|
||||
* Returns: 0 on success, negative value on failure
|
||||
*/
|
||||
int (*link_sta_remove)(void *priv, u8 link_id, const u8 *addr);
|
||||
|
||||
/**
|
||||
* nan_flush - Flush all NAN offload services
|
||||
* @priv: Private driver interface data
|
||||
* Returns: 0 on success, negative value on failure
|
||||
*/
|
||||
int (*nan_flush)(void *priv);
|
||||
|
||||
/**
|
||||
* nan_publish - NAN offload for Publish()
|
||||
* @priv: Private driver interface data
|
||||
* @src: Source P2P device addr
|
||||
* @publish_id: Publish instance to add
|
||||
* @service_name: Service name
|
||||
* @service_id: Service ID (6 octet value derived from service name)
|
||||
* @srv_proto_type: Service protocol type
|
||||
* @ssi: Service specific information or %NULL
|
||||
* @elems: Information elements for Element Container attribute or %NULL
|
||||
* @params: Configuration parameters
|
||||
* Returns: 0 on success, negative value on failure
|
||||
*/
|
||||
int (*nan_publish)(void *priv, const u8 *src, int publish_id,
|
||||
const char *service_name, const u8 *service_id,
|
||||
enum nan_service_protocol_type srv_proto_type,
|
||||
const struct wpabuf *ssi, const struct wpabuf *elems,
|
||||
struct nan_publish_params *params);
|
||||
|
||||
/**
|
||||
* nan_cancel_publish - NAN offload for CancelPublish()
|
||||
* @priv: Private driver interface data
|
||||
* @publish_id: Publish instance to cancel
|
||||
* Returns: 0 on success, negative value on failure
|
||||
*/
|
||||
int (*nan_cancel_publish)(void *priv, int publish_id);
|
||||
|
||||
/**
|
||||
* nan_update_publish - NAN offload for UpdatePublish()
|
||||
* @priv: Private driver interface data
|
||||
* @ssi: Service specific information or %NULL
|
||||
* Returns: 0 on success, negative value on failure
|
||||
*/
|
||||
int (*nan_update_publish)(void *priv, int publish_id,
|
||||
const struct wpabuf *ssi);
|
||||
|
||||
/**
|
||||
* nan_subscribe - NAN offload for Subscribe()
|
||||
* @priv: Private driver interface data
|
||||
* @src: Source P2P device addr
|
||||
* @subscribe_id: Subscribe instance to add
|
||||
* @service_name: Service name
|
||||
* @service_id: Service ID (6 octet value derived from service name)
|
||||
* @srv_proto_type: Service protocol type
|
||||
* @ssi: Service specific information or %NULL
|
||||
* @elems: Information elements for Element Container attribute or %NULL
|
||||
* @params: Configuration parameters
|
||||
* Returns: 0 on success, negative value on failure
|
||||
*/
|
||||
int (*nan_subscribe)(void *priv, const u8 *src, int subscribe_id,
|
||||
const char *service_name, const u8 *service_id,
|
||||
enum nan_service_protocol_type srv_proto_type,
|
||||
const struct wpabuf *ssi,
|
||||
const struct wpabuf *elems,
|
||||
struct nan_subscribe_params *params);
|
||||
|
||||
/**
|
||||
* nan_cancel_subscribe - NAN offload for CancelSubscribe()
|
||||
* @priv: Private driver interface data
|
||||
* @subscribe_id: Subscribe instance to cancel
|
||||
* Returns: 0 on success, negative value on failure
|
||||
*/
|
||||
int (*nan_cancel_subscribe)(void *priv, int subscribe_id);
|
||||
|
||||
#ifdef CONFIG_TESTING_OPTIONS
|
||||
int (*register_frame)(void *priv, u16 type,
|
||||
const u8 *match, size_t match_len,
|
||||
bool multicast);
|
||||
#endif /* CONFIG_TESTING_OPTIONS */
|
||||
|
||||
/**
|
||||
* get_multi_hw_info - Get multiple underlying hardware information
|
||||
* (hardware IDx and supported frequency range)
|
||||
* @priv: Private driver interface data
|
||||
* @num_multi_hws: Variable for returning the number of returned
|
||||
* hardware info data
|
||||
* Returns: Pointer to allocated multiple hardware data on success
|
||||
* or %NULL on failure. Caller is responsible for freeing this.
|
||||
*/
|
||||
struct hostapd_multi_hw_info *
|
||||
(*get_multi_hw_info)(void *priv, unsigned int *num_multi_hws);
|
||||
};
|
||||
|
||||
/**
|
||||
|
@ -5766,6 +5967,11 @@ enum wpa_event_type {
|
|||
* EVENT_LINK_RECONFIG - Notification that AP links removed
|
||||
*/
|
||||
EVENT_LINK_RECONFIG,
|
||||
|
||||
/**
|
||||
* EVENT_MLD_INTERFACE_FREED - Notification of AP MLD interface removal
|
||||
*/
|
||||
EVENT_MLD_INTERFACE_FREED,
|
||||
};
|
||||
|
||||
|
||||
|
@ -6292,6 +6498,14 @@ union wpa_event_data {
|
|||
*/
|
||||
void *drv_priv;
|
||||
|
||||
/**
|
||||
* ctx - Pointer to store ctx of private BSS information
|
||||
*
|
||||
* If not set to NULL, this is used for forwarding the packet
|
||||
* to right link BSS of ML BSS.
|
||||
*/
|
||||
void *ctx;
|
||||
|
||||
/**
|
||||
* freq - Frequency (in MHz) on which the frame was received
|
||||
*/
|
||||
|
@ -6342,6 +6556,8 @@ union wpa_event_data {
|
|||
* (if available).
|
||||
* @scan_start_tsf_bssid: The BSSID according to which %scan_start_tsf
|
||||
* is set.
|
||||
* @scan_cookie: Unique identification representing the corresponding
|
||||
* scan request. 0 if no unique identification is available.
|
||||
*/
|
||||
struct scan_info {
|
||||
int aborted;
|
||||
|
@ -6353,6 +6569,7 @@ union wpa_event_data {
|
|||
int nl_scan_event;
|
||||
u64 scan_start_tsf;
|
||||
u8 scan_start_tsf_bssid[ETH_ALEN];
|
||||
u64 scan_cookie;
|
||||
} scan_info;
|
||||
|
||||
/**
|
||||
|
@ -6709,6 +6926,7 @@ union wpa_event_data {
|
|||
*/
|
||||
struct bss_color_collision {
|
||||
u64 bitmap;
|
||||
int link_id;
|
||||
} bss_color_collision;
|
||||
|
||||
/**
|
||||
|
|
|
@ -632,7 +632,7 @@ atheros_get_seqnum(const char *ifname, void *priv, const u8 *addr, int idx,
|
|||
|
||||
|
||||
static int
|
||||
atheros_flush(void *priv)
|
||||
atheros_flush(void *priv, int link_id)
|
||||
{
|
||||
u8 allsta[IEEE80211_ADDR_LEN];
|
||||
os_memset(allsta, 0xff, IEEE80211_ADDR_LEN);
|
||||
|
|
|
@ -946,7 +946,7 @@ bsd_get_seqnum(const char *ifname, void *priv, const u8 *addr, int idx,
|
|||
|
||||
|
||||
static int
|
||||
bsd_flush(void *priv)
|
||||
bsd_flush(void *priv, int link_id)
|
||||
{
|
||||
u8 allsta[IEEE80211_ADDR_LEN];
|
||||
|
||||
|
|
|
@ -100,6 +100,7 @@ const char * event_to_string(enum wpa_event_type event)
|
|||
E2S(LINK_CH_SWITCH_STARTED);
|
||||
E2S(TID_LINK_MAP);
|
||||
E2S(LINK_RECONFIG);
|
||||
E2S(MLD_INTERFACE_FREED);
|
||||
}
|
||||
|
||||
return "UNKNOWN";
|
||||
|
|
|
@ -572,7 +572,7 @@ static int hostap_set_ssid(void *priv, const u8 *buf, int len)
|
|||
}
|
||||
|
||||
|
||||
static int hostap_flush(void *priv)
|
||||
static int hostap_flush(void *priv, int link_id)
|
||||
{
|
||||
struct hostap_driver_data *drv = priv;
|
||||
struct prism2_hostapd_param param;
|
||||
|
|
|
@ -19,6 +19,7 @@
|
|||
#include <netlink/route/link.h>
|
||||
#include <netlink/route/link/macsec.h>
|
||||
#include <linux/if_macsec.h>
|
||||
#include <linux/version.h>
|
||||
#include <inttypes.h>
|
||||
|
||||
#include "utils/common.h"
|
||||
|
@ -32,7 +33,8 @@
|
|||
|
||||
#define UNUSED_SCI 0xffffffffffffffff
|
||||
|
||||
#if LIBNL_VER_NUM >= LIBNL_VER(3, 6)
|
||||
#if (LIBNL_VER_NUM >= LIBNL_VER(3, 6) && \
|
||||
LINUX_VERSION_CODE >= KERNEL_VERSION(5, 7, 0))
|
||||
#define LIBNL_HAS_OFFLOAD
|
||||
#endif
|
||||
|
||||
|
|
File diff suppressed because it is too large
Load diff
|
@ -55,7 +55,6 @@ struct nl80211_wiphy_data {
|
|||
struct i802_link {
|
||||
unsigned int beacon_set:1;
|
||||
|
||||
s8 link_id;
|
||||
int freq;
|
||||
int bandwidth;
|
||||
u8 addr[ETH_ALEN];
|
||||
|
@ -66,9 +65,9 @@ struct i802_bss {
|
|||
struct wpa_driver_nl80211_data *drv;
|
||||
struct i802_bss *next;
|
||||
|
||||
size_t n_links;
|
||||
u16 valid_links;
|
||||
struct i802_link links[MAX_NUM_MLD_LINKS];
|
||||
struct i802_link *flink;
|
||||
struct i802_link *flink, *scan_link;
|
||||
|
||||
int ifindex;
|
||||
int br_ifindex;
|
||||
|
@ -201,6 +200,7 @@ struct wpa_driver_nl80211_data {
|
|||
unsigned int secure_ranging_ctx_vendor_cmd_avail:1;
|
||||
unsigned int puncturing:1;
|
||||
unsigned int qca_ap_allowed_freqs:1;
|
||||
unsigned int connect_ext_vendor_cmd_avail:1;
|
||||
|
||||
u32 ignore_next_local_disconnect;
|
||||
u32 ignore_next_local_deauth;
|
||||
|
@ -353,6 +353,20 @@ const char * nl80211_iftype_str(enum nl80211_iftype mode);
|
|||
|
||||
void nl80211_restore_ap_mode(struct i802_bss *bss);
|
||||
struct i802_link * nl80211_get_link(struct i802_bss *bss, s8 link_id);
|
||||
u8 nl80211_get_link_id_from_link(struct i802_bss *bss, struct i802_link *link);
|
||||
int nl80211_remove_link(struct i802_bss *bss, int link_id);
|
||||
|
||||
static inline bool nl80211_link_valid(u16 links, s8 link_id)
|
||||
{
|
||||
if (link_id < 0 || link_id >= MAX_NUM_MLD_LINKS)
|
||||
return false;
|
||||
|
||||
if (links & BIT(link_id))
|
||||
return true;
|
||||
|
||||
return false;
|
||||
}
|
||||
|
||||
|
||||
static inline bool
|
||||
nl80211_attr_supported(struct wpa_driver_nl80211_data *drv, unsigned int attr)
|
||||
|
@ -391,11 +405,14 @@ int wpa_driver_nl80211_scan(struct i802_bss *bss,
|
|||
int wpa_driver_nl80211_sched_scan(void *priv,
|
||||
struct wpa_driver_scan_params *params);
|
||||
int wpa_driver_nl80211_stop_sched_scan(void *priv);
|
||||
struct wpa_scan_results * wpa_driver_nl80211_get_scan_results(void *priv);
|
||||
struct wpa_scan_results * wpa_driver_nl80211_get_scan_results(void *priv,
|
||||
const u8 *bssid);
|
||||
void nl80211_dump_scan(struct wpa_driver_nl80211_data *drv);
|
||||
int wpa_driver_nl80211_abort_scan(void *priv, u64 scan_cookie);
|
||||
int wpa_driver_nl80211_vendor_scan(struct i802_bss *bss,
|
||||
struct wpa_driver_scan_params *params);
|
||||
int nl80211_set_default_scan_ies(void *priv, const u8 *ies, size_t ies_len);
|
||||
struct hostapd_multi_hw_info *
|
||||
nl80211_get_multi_hw_info(struct i802_bss *bss, unsigned int *num_multi_hws);
|
||||
|
||||
#endif /* DRIVER_NL80211_H */
|
||||
|
|
|
@ -889,6 +889,10 @@ static void wiphy_info_extended_capab(struct wpa_driver_nl80211_data *drv,
|
|||
nla_get_u16(tb1[NL80211_ATTR_MLD_CAPA_AND_OPS]);
|
||||
}
|
||||
|
||||
wpa_printf(MSG_DEBUG,
|
||||
"nl80211: EML Capability: 0x%x MLD Capability: 0x%x",
|
||||
capa->eml_capa, capa->mld_capa_and_ops);
|
||||
|
||||
drv->num_iface_capa++;
|
||||
if (drv->num_iface_capa == NL80211_IFTYPE_MAX)
|
||||
break;
|
||||
|
@ -1116,6 +1120,9 @@ static int wiphy_info_handler(struct nl_msg *msg, void *arg)
|
|||
case QCA_NL80211_VENDOR_SUBCMD_SECURE_RANGING_CONTEXT:
|
||||
drv->secure_ranging_ctx_vendor_cmd_avail = 1;
|
||||
break;
|
||||
case QCA_NL80211_VENDOR_SUBCMD_CONNECT_EXT:
|
||||
drv->connect_ext_vendor_cmd_avail = 1;
|
||||
break;
|
||||
#endif /* CONFIG_DRIVER_NL80211_QCA */
|
||||
}
|
||||
#ifdef CONFIG_DRIVER_NL80211_BRCM
|
||||
|
@ -1437,6 +1444,14 @@ static void qca_nl80211_get_features(struct wpa_driver_nl80211_data *drv)
|
|||
if (check_feature(QCA_WLAN_VENDOR_FEATURE_AP_ALLOWED_FREQ_LIST,
|
||||
&info))
|
||||
drv->qca_ap_allowed_freqs = 1;
|
||||
if (check_feature(QCA_WLAN_VENDOR_FEATURE_HT_VHT_TWT_RESPONDER, &info))
|
||||
drv->capa.flags2 |= WPA_DRIVER_FLAGS2_HT_VHT_TWT_RESPONDER;
|
||||
if (check_feature(QCA_WLAN_VENDOR_FEATURE_RSN_OVERRIDE_STA, &info)) {
|
||||
wpa_printf(MSG_DEBUG,
|
||||
"The driver supports RSN overriding in STA mode");
|
||||
drv->capa.flags2 |= WPA_DRIVER_FLAGS2_RSN_OVERRIDE_STA;
|
||||
}
|
||||
|
||||
os_free(info.flags);
|
||||
}
|
||||
|
||||
|
@ -1464,6 +1479,7 @@ int wpa_driver_nl80211_capa(struct wpa_driver_nl80211_data *drv)
|
|||
WPA_DRIVER_CAPA_KEY_MGMT_WPA_PSK |
|
||||
WPA_DRIVER_CAPA_KEY_MGMT_WPA2 |
|
||||
WPA_DRIVER_CAPA_KEY_MGMT_WPA2_PSK |
|
||||
WPA_DRIVER_CAPA_KEY_MGMT_PSK_SHA256 |
|
||||
WPA_DRIVER_CAPA_KEY_MGMT_SUITE_B |
|
||||
WPA_DRIVER_CAPA_KEY_MGMT_OWE |
|
||||
WPA_DRIVER_CAPA_KEY_MGMT_DPP;
|
||||
|
@ -1479,6 +1495,7 @@ int wpa_driver_nl80211_capa(struct wpa_driver_nl80211_data *drv)
|
|||
WPA_DRIVER_CAPA_KEY_MGMT_FILS_SHA384 |
|
||||
WPA_DRIVER_CAPA_KEY_MGMT_FT_FILS_SHA256 |
|
||||
WPA_DRIVER_CAPA_KEY_MGMT_FT_FILS_SHA384 |
|
||||
WPA_DRIVER_CAPA_KEY_MGMT_SAE_EXT_KEY |
|
||||
WPA_DRIVER_CAPA_KEY_MGMT_SAE;
|
||||
else if (drv->capa.flags & WPA_DRIVER_FLAGS_FILS_SK_OFFLOAD)
|
||||
drv->capa.key_mgmt |=
|
||||
|
@ -2156,6 +2173,9 @@ wpa_driver_nl80211_postprocess_modes(struct hostapd_hw_modes *modes,
|
|||
for (m = 0; m < *num_modes; m++) {
|
||||
if (!modes[m].num_channels)
|
||||
continue;
|
||||
|
||||
modes[m].is_6ghz = false;
|
||||
|
||||
if (modes[m].channels[0].freq < 2000) {
|
||||
modes[m].num_channels = 0;
|
||||
continue;
|
||||
|
@ -2167,10 +2187,14 @@ wpa_driver_nl80211_postprocess_modes(struct hostapd_hw_modes *modes,
|
|||
break;
|
||||
}
|
||||
}
|
||||
} else if (modes[m].channels[0].freq > 50000)
|
||||
} else if (modes[m].channels[0].freq > 50000) {
|
||||
modes[m].mode = HOSTAPD_MODE_IEEE80211AD;
|
||||
else
|
||||
} else if (is_6ghz_freq(modes[m].channels[0].freq)) {
|
||||
modes[m].mode = HOSTAPD_MODE_IEEE80211A;
|
||||
modes[m].is_6ghz = true;
|
||||
} else {
|
||||
modes[m].mode = HOSTAPD_MODE_IEEE80211A;
|
||||
}
|
||||
}
|
||||
|
||||
/* Remove unsupported bands */
|
||||
|
@ -2398,6 +2422,57 @@ static void nl80211_reg_rule_vht(struct nlattr *tb[],
|
|||
}
|
||||
|
||||
|
||||
static void nl80211_set_6ghz_mode(struct hostapd_hw_modes *mode, int start,
|
||||
int end, int max_bw)
|
||||
{
|
||||
int c;
|
||||
|
||||
for (c = 0; c < mode->num_channels; c++) {
|
||||
struct hostapd_channel_data *chan = &mode->channels[c];
|
||||
|
||||
if (chan->freq - 10 < start || chan->freq + 10 > end)
|
||||
continue;
|
||||
|
||||
if (max_bw >= 80)
|
||||
chan->flag |= HOSTAPD_CHAN_VHT_80MHZ_SUBCHANNEL;
|
||||
|
||||
if (max_bw >= 160)
|
||||
chan->flag |= HOSTAPD_CHAN_VHT_160MHZ_SUBCHANNEL;
|
||||
|
||||
if (max_bw >= 320)
|
||||
chan->flag |= HOSTAPD_CHAN_EHT_320MHZ_SUBCHANNEL;
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
static void nl80211_reg_rule_6ghz(struct nlattr *tb[],
|
||||
struct phy_info_arg *results)
|
||||
{
|
||||
u32 start, end, max_bw;
|
||||
u16 m;
|
||||
|
||||
if (!tb[NL80211_ATTR_FREQ_RANGE_START] ||
|
||||
!tb[NL80211_ATTR_FREQ_RANGE_END] ||
|
||||
!tb[NL80211_ATTR_FREQ_RANGE_MAX_BW])
|
||||
return;
|
||||
|
||||
start = nla_get_u32(tb[NL80211_ATTR_FREQ_RANGE_START]) / 1000;
|
||||
end = nla_get_u32(tb[NL80211_ATTR_FREQ_RANGE_END]) / 1000;
|
||||
max_bw = nla_get_u32(tb[NL80211_ATTR_FREQ_RANGE_MAX_BW]) / 1000;
|
||||
|
||||
if (max_bw < 80)
|
||||
return;
|
||||
|
||||
for (m = 0; m < *results->num_modes; m++) {
|
||||
if (results->modes[m].num_channels == 0 ||
|
||||
!is_6ghz_freq(results->modes[m].channels[0].freq))
|
||||
continue;
|
||||
|
||||
nl80211_set_6ghz_mode(&results->modes[m], start, end, max_bw);
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
static void nl80211_set_dfs_domain(enum nl80211_dfs_regions region,
|
||||
u8 *dfs_domain)
|
||||
{
|
||||
|
@ -2516,6 +2591,13 @@ static int nl80211_get_reg(struct nl_msg *msg, void *arg)
|
|||
nl80211_reg_rule_vht(tb_rule, results);
|
||||
}
|
||||
|
||||
nla_for_each_nested(nl_rule, tb_msg[NL80211_ATTR_REG_RULES], rem_rule)
|
||||
{
|
||||
nla_parse(tb_rule, NL80211_FREQUENCY_ATTR_MAX,
|
||||
nla_data(nl_rule), nla_len(nl_rule), reg_policy);
|
||||
nl80211_reg_rule_6ghz(tb_rule, results);
|
||||
}
|
||||
|
||||
return NL_SKIP;
|
||||
}
|
||||
|
||||
|
@ -2657,3 +2739,133 @@ nl80211_get_hw_feature_data(void *priv, u16 *num_modes, u16 *flags,
|
|||
|
||||
return NULL;
|
||||
}
|
||||
|
||||
|
||||
static int phy_multi_hw_info_parse(struct hostapd_multi_hw_info *hw_info,
|
||||
struct nlattr *radio_attr)
|
||||
{
|
||||
struct nlattr *tb_freq[NL80211_WIPHY_RADIO_FREQ_ATTR_MAX + 1];
|
||||
int start_freq, end_freq;
|
||||
|
||||
switch (nla_type(radio_attr)) {
|
||||
case NL80211_WIPHY_RADIO_ATTR_INDEX:
|
||||
hw_info->hw_idx = nla_get_u32(radio_attr);
|
||||
return NL_OK;
|
||||
case NL80211_WIPHY_RADIO_ATTR_FREQ_RANGE:
|
||||
nla_parse_nested(tb_freq, NL80211_WIPHY_RADIO_FREQ_ATTR_MAX,
|
||||
radio_attr, NULL);
|
||||
|
||||
if (!tb_freq[NL80211_WIPHY_RADIO_FREQ_ATTR_START] ||
|
||||
!tb_freq[NL80211_WIPHY_RADIO_FREQ_ATTR_END])
|
||||
return NL_STOP;
|
||||
|
||||
start_freq = nla_get_u32(
|
||||
tb_freq[NL80211_WIPHY_RADIO_FREQ_ATTR_START]);
|
||||
end_freq = nla_get_u32(
|
||||
tb_freq[NL80211_WIPHY_RADIO_FREQ_ATTR_END]);
|
||||
|
||||
/* Convert to MHz and store */
|
||||
hw_info->start_freq = start_freq / 1000;
|
||||
hw_info->end_freq = end_freq / 1000;
|
||||
return NL_OK;
|
||||
default:
|
||||
return NL_OK;
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
struct phy_multi_hw_info_arg {
|
||||
bool failed;
|
||||
unsigned int *num_multi_hws;
|
||||
struct hostapd_multi_hw_info *multi_hws;
|
||||
};
|
||||
|
||||
|
||||
static int phy_multi_hw_info_handler(struct nl_msg *msg, void *arg)
|
||||
{
|
||||
struct genlmsghdr *gnlh = nlmsg_data(nlmsg_hdr(msg));
|
||||
struct phy_multi_hw_info_arg *multi_hw_info = arg;
|
||||
struct hostapd_multi_hw_info *multi_hws, hw_info;
|
||||
struct nlattr *tb_msg[NL80211_ATTR_MAX + 1];
|
||||
struct nlattr *nl_hw, *radio_attr;
|
||||
int rem_hw, rem_radio_prop, res;
|
||||
|
||||
nla_parse(tb_msg, NL80211_ATTR_MAX, genlmsg_attrdata(gnlh, 0),
|
||||
genlmsg_attrlen(gnlh, 0), NULL);
|
||||
|
||||
if (!tb_msg[NL80211_ATTR_WIPHY_RADIOS])
|
||||
return NL_SKIP;
|
||||
|
||||
*multi_hw_info->num_multi_hws = 0;
|
||||
|
||||
nla_for_each_nested(nl_hw, tb_msg[NL80211_ATTR_WIPHY_RADIOS], rem_hw) {
|
||||
os_memset(&hw_info, 0, sizeof(hw_info));
|
||||
|
||||
nla_for_each_nested(radio_attr, nl_hw, rem_radio_prop) {
|
||||
res = phy_multi_hw_info_parse(&hw_info, radio_attr);
|
||||
if (res != NL_OK)
|
||||
goto out;
|
||||
}
|
||||
|
||||
if (hw_info.start_freq == 0 || hw_info.end_freq == 0)
|
||||
goto out;
|
||||
|
||||
multi_hws = os_realloc_array(multi_hw_info->multi_hws,
|
||||
*multi_hw_info->num_multi_hws + 1,
|
||||
sizeof(*multi_hws));
|
||||
if (!multi_hws)
|
||||
goto out;
|
||||
|
||||
multi_hw_info->multi_hws = multi_hws;
|
||||
os_memcpy(&multi_hws[*(multi_hw_info->num_multi_hws)],
|
||||
&hw_info, sizeof(struct hostapd_multi_hw_info));
|
||||
*(multi_hw_info->num_multi_hws) += 1;
|
||||
}
|
||||
|
||||
return NL_OK;
|
||||
out:
|
||||
multi_hw_info->failed = true;
|
||||
return NL_STOP;
|
||||
}
|
||||
|
||||
|
||||
struct hostapd_multi_hw_info *
|
||||
nl80211_get_multi_hw_info(struct i802_bss *bss, unsigned int *num_multi_hws)
|
||||
{
|
||||
u32 feat;
|
||||
struct wpa_driver_nl80211_data *drv = bss->drv;
|
||||
int nl_flags = 0;
|
||||
struct nl_msg *msg;
|
||||
struct phy_multi_hw_info_arg result = {
|
||||
.failed = false,
|
||||
.num_multi_hws = num_multi_hws,
|
||||
.multi_hws = NULL,
|
||||
};
|
||||
|
||||
*num_multi_hws = 0;
|
||||
|
||||
if (!drv->has_capability || !(drv->capa.flags2 & WPA_DRIVER_FLAGS2_MLO))
|
||||
return NULL;
|
||||
|
||||
feat = get_nl80211_protocol_features(drv);
|
||||
if (feat & NL80211_PROTOCOL_FEATURE_SPLIT_WIPHY_DUMP)
|
||||
nl_flags = NLM_F_DUMP;
|
||||
if (!(msg = nl80211_cmd_msg(bss, nl_flags, NL80211_CMD_GET_WIPHY)) ||
|
||||
nla_put_flag(msg, NL80211_ATTR_SPLIT_WIPHY_DUMP)) {
|
||||
nlmsg_free(msg);
|
||||
return NULL;
|
||||
}
|
||||
|
||||
if (send_and_recv_resp(drv, msg, phy_multi_hw_info_handler,
|
||||
&result) == 0) {
|
||||
if (result.failed) {
|
||||
os_free(result.multi_hws);
|
||||
*num_multi_hws = 0;
|
||||
return NULL;
|
||||
}
|
||||
|
||||
return result.multi_hws;
|
||||
}
|
||||
|
||||
return NULL;
|
||||
}
|
||||
|
|
|
@ -22,7 +22,7 @@
|
|||
|
||||
|
||||
static void
|
||||
nl80211_control_port_frame_tx_status(struct wpa_driver_nl80211_data *drv,
|
||||
nl80211_control_port_frame_tx_status(struct i802_bss *bss,
|
||||
const u8 *frame, size_t len,
|
||||
struct nlattr *ack, struct nlattr *cookie);
|
||||
|
||||
|
@ -186,6 +186,7 @@ static const char * nl80211_command_to_string(enum nl80211_commands cmd)
|
|||
C2S(NL80211_CMD_REMOVE_LINK_STA)
|
||||
C2S(NL80211_CMD_SET_HW_TIMESTAMP)
|
||||
C2S(NL80211_CMD_LINKS_REMOVED)
|
||||
C2S(NL80211_CMD_SET_TID_TO_LINK_MAPPING)
|
||||
C2S(__NL80211_CMD_AFTER_LAST)
|
||||
}
|
||||
#undef C2S
|
||||
|
@ -477,10 +478,7 @@ static void qca_nl80211_link_reconfig_event(struct wpa_driver_nl80211_data *drv,
|
|||
* links when the link used for (re)association is removed.
|
||||
*/
|
||||
if (removed_links & BIT(drv->sta_mlo_info.assoc_link_id)) {
|
||||
for (i = 0; i < MAX_NUM_MLD_LINKS; i++) {
|
||||
if (!(drv->sta_mlo_info.valid_links & BIT(i)))
|
||||
continue;
|
||||
|
||||
for_each_link(drv->sta_mlo_info.valid_links, i) {
|
||||
os_memcpy(drv->bssid, drv->sta_mlo_info.links[i].bssid,
|
||||
ETH_ALEN);
|
||||
drv->sta_mlo_info.assoc_link_id = i;
|
||||
|
@ -702,10 +700,7 @@ static int nl80211_update_rejected_links_info(struct driver_sta_mlo_info *mlo,
|
|||
}
|
||||
|
||||
/* Get MLO links info for rejected links */
|
||||
for (i = 0; i < MAX_NUM_MLD_LINKS; i++) {
|
||||
if (!((mlo->req_links & ~mlo->valid_links) & BIT(i)))
|
||||
continue;
|
||||
|
||||
for_each_link((mlo->req_links & ~mlo->valid_links), i) {
|
||||
os_memcpy(mlo->links[i].bssid, resp_info.addr[i], ETH_ALEN);
|
||||
os_memcpy(mlo->links[i].addr, req_info.addr[i], ETH_ALEN);
|
||||
}
|
||||
|
@ -875,9 +870,7 @@ qca_nl80211_tid_to_link_map_event(struct wpa_driver_nl80211_data *drv,
|
|||
wpa_printf(MSG_DEBUG,
|
||||
"nl80211: TID-to-link: Received uplink %x downlink %x",
|
||||
uplink, downlink);
|
||||
for (i = 0; i < MAX_NUM_MLD_LINKS; i++) {
|
||||
if (!(drv->sta_mlo_info.valid_links & BIT(i)))
|
||||
continue;
|
||||
for_each_link(drv->sta_mlo_info.valid_links, i) {
|
||||
if (uplink & BIT(i))
|
||||
event.t2l_map_info.t2lmap[i].uplink |=
|
||||
BIT(tidnum);
|
||||
|
@ -1212,9 +1205,6 @@ static void mlme_event_ch_switch(struct wpa_driver_nl80211_data *drv,
|
|||
int chan_offset = 0;
|
||||
int ifidx;
|
||||
|
||||
wpa_printf(MSG_DEBUG, "nl80211: Channel switch%s event",
|
||||
finished ? "" : " started");
|
||||
|
||||
if (!freq)
|
||||
return;
|
||||
|
||||
|
@ -1226,6 +1216,9 @@ static void mlme_event_ch_switch(struct wpa_driver_nl80211_data *drv,
|
|||
return;
|
||||
}
|
||||
|
||||
wpa_printf(MSG_DEBUG, "nl80211: Channel switch%s event for %s",
|
||||
finished ? "" : " started", bss->ifname);
|
||||
|
||||
if (type) {
|
||||
enum nl80211_channel_type ch_type = nla_get_u32(type);
|
||||
|
||||
|
@ -1268,13 +1261,31 @@ static void mlme_event_ch_switch(struct wpa_driver_nl80211_data *drv,
|
|||
if (cf2)
|
||||
data.ch_switch.cf2 = nla_get_u32(cf2);
|
||||
|
||||
if (finished)
|
||||
bss->flink->freq = data.ch_switch.freq;
|
||||
|
||||
if (link)
|
||||
if (link) {
|
||||
data.ch_switch.link_id = nla_get_u8(link);
|
||||
else
|
||||
wpa_printf(MSG_DEBUG, "nl80211: Link ID: %d",
|
||||
data.ch_switch.link_id);
|
||||
} else {
|
||||
data.ch_switch.link_id = NL80211_DRV_LINK_ID_NA;
|
||||
}
|
||||
|
||||
if (finished) {
|
||||
if (data.ch_switch.link_id != NL80211_DRV_LINK_ID_NA) {
|
||||
struct i802_link *mld_link;
|
||||
|
||||
mld_link = nl80211_get_link(bss,
|
||||
data.ch_switch.link_id);
|
||||
mld_link->freq = data.ch_switch.freq;
|
||||
if (bw)
|
||||
mld_link->bandwidth = channel_width_to_int(
|
||||
data.ch_switch.ch_width);
|
||||
} else {
|
||||
bss->flink->freq = data.ch_switch.freq;
|
||||
if (bw)
|
||||
bss->flink->bandwidth = channel_width_to_int(
|
||||
data.ch_switch.ch_width);
|
||||
}
|
||||
}
|
||||
|
||||
if (link && is_sta_interface(drv->nlmode)) {
|
||||
u8 link_id = data.ch_switch.link_id;
|
||||
|
@ -1293,6 +1304,14 @@ static void mlme_event_ch_switch(struct wpa_driver_nl80211_data *drv,
|
|||
return;
|
||||
}
|
||||
|
||||
if (link && is_ap_interface(drv->nlmode) &&
|
||||
!nl80211_link_valid(bss->valid_links, data.ch_switch.link_id)) {
|
||||
wpa_printf(MSG_WARNING,
|
||||
"nl80211: Unknown link ID (%d) for channel switch (%s), ignoring",
|
||||
data.ch_switch.link_id, bss->ifname);
|
||||
return;
|
||||
}
|
||||
|
||||
drv->assoc_freq = data.ch_switch.freq;
|
||||
|
||||
wpa_supplicant_event(bss->ctx, finished ?
|
||||
|
@ -1366,18 +1385,20 @@ static void mlme_event_mgmt(struct i802_bss *bss,
|
|||
event.rx_mgmt.frame_len = len;
|
||||
event.rx_mgmt.ssi_signal = ssi_signal;
|
||||
event.rx_mgmt.drv_priv = bss;
|
||||
event.rx_mgmt.ctx = bss->ctx;
|
||||
event.rx_mgmt.link_id = link_id;
|
||||
|
||||
wpa_supplicant_event(drv->ctx, EVENT_RX_MGMT, &event);
|
||||
}
|
||||
|
||||
|
||||
static void mlme_event_mgmt_tx_status(struct wpa_driver_nl80211_data *drv,
|
||||
static void mlme_event_mgmt_tx_status(struct i802_bss *bss,
|
||||
struct nlattr *cookie, const u8 *frame,
|
||||
size_t len, struct nlattr *ack)
|
||||
{
|
||||
union wpa_event_data event;
|
||||
const struct ieee80211_hdr *hdr = (const struct ieee80211_hdr *) frame;
|
||||
struct wpa_driver_nl80211_data *drv = bss->drv;
|
||||
u16 fc = le_to_host16(hdr->frame_control);
|
||||
u64 cookie_val = 0;
|
||||
|
||||
|
@ -1396,7 +1417,7 @@ static void mlme_event_mgmt_tx_status(struct wpa_driver_nl80211_data *drv,
|
|||
WPA_GET_BE16(frame + 2 * ETH_ALEN) == ETH_P_PAE) {
|
||||
wpa_printf(MSG_DEBUG,
|
||||
"nl80211: Work around misdelivered control port TX status for EAPOL");
|
||||
nl80211_control_port_frame_tx_status(drv, frame, len, ack,
|
||||
nl80211_control_port_frame_tx_status(bss, frame, len, ack,
|
||||
cookie);
|
||||
return;
|
||||
}
|
||||
|
@ -1432,7 +1453,7 @@ static void mlme_event_mgmt_tx_status(struct wpa_driver_nl80211_data *drv,
|
|||
event.tx_status.ack = ack != NULL;
|
||||
event.tx_status.link_id = cookie_val == drv->send_frame_cookie ?
|
||||
drv->send_frame_link_id : NL80211_DRV_LINK_ID_NA;
|
||||
wpa_supplicant_event(drv->ctx, EVENT_TX_STATUS, &event);
|
||||
wpa_supplicant_event(bss->ctx, EVENT_TX_STATUS, &event);
|
||||
}
|
||||
|
||||
|
||||
|
@ -1618,18 +1639,17 @@ static void mlme_event_unprot_beacon(struct wpa_driver_nl80211_data *drv,
|
|||
}
|
||||
|
||||
|
||||
static struct i802_link *
|
||||
nl80211_get_mld_link_by_freq(struct i802_bss *bss, unsigned int freq)
|
||||
static s8
|
||||
nl80211_get_link_id_by_freq(struct i802_bss *bss, unsigned int freq)
|
||||
{
|
||||
unsigned int i;
|
||||
|
||||
for (i = 0; i < bss->n_links; i++) {
|
||||
if ((unsigned int) bss->links[i].freq == freq &&
|
||||
bss->links[i].link_id != -1)
|
||||
return &bss->links[i];
|
||||
for_each_link(bss->valid_links, i) {
|
||||
if ((unsigned int) bss->links[i].freq == freq)
|
||||
return i;
|
||||
}
|
||||
|
||||
return NULL;
|
||||
return NL80211_DRV_LINK_ID_NA;
|
||||
}
|
||||
|
||||
|
||||
|
@ -1663,12 +1683,12 @@ static void mlme_event(struct i802_bss *bss,
|
|||
/* Determine the MLD link either by an explicitly provided link id or
|
||||
* finding a match based on the frequency. */
|
||||
if (link)
|
||||
mld_link = nl80211_get_link(bss, nla_get_u8(link));
|
||||
link_id = nla_get_u8(link);
|
||||
else if (freq)
|
||||
mld_link = nl80211_get_mld_link_by_freq(bss, nla_get_u32(freq));
|
||||
link_id = nl80211_get_link_id_by_freq(bss, nla_get_u32(freq));
|
||||
|
||||
if (mld_link)
|
||||
link_id = mld_link->link_id;
|
||||
if (nl80211_link_valid(bss->valid_links, link_id))
|
||||
mld_link = nl80211_get_link(bss, link_id);
|
||||
|
||||
data = nla_data(frame);
|
||||
len = nla_len(frame);
|
||||
|
@ -1741,7 +1761,7 @@ static void mlme_event(struct i802_bss *bss,
|
|||
nla_len(frame), link_id);
|
||||
break;
|
||||
case NL80211_CMD_FRAME_TX_STATUS:
|
||||
mlme_event_mgmt_tx_status(drv, cookie, nla_data(frame),
|
||||
mlme_event_mgmt_tx_status(bss, cookie, nla_data(frame),
|
||||
nla_len(frame), ack);
|
||||
break;
|
||||
case NL80211_CMD_UNPROT_DEAUTHENTICATE:
|
||||
|
@ -1920,7 +1940,7 @@ static void mlme_event_dh_event(struct wpa_driver_nl80211_data *drv,
|
|||
os_memset(&data, 0, sizeof(data));
|
||||
addr = nla_data(tb[NL80211_ATTR_MAC]);
|
||||
|
||||
if (bss->links[0].link_id == NL80211_DRV_LINK_ID_NA &&
|
||||
if (!bss->valid_links &&
|
||||
(tb[NL80211_ATTR_MLO_LINK_ID] ||
|
||||
tb[NL80211_ATTR_MLD_ADDR])) {
|
||||
wpa_printf(MSG_ERROR,
|
||||
|
@ -1957,9 +1977,10 @@ static void mlme_event_dh_event(struct wpa_driver_nl80211_data *drv,
|
|||
}
|
||||
|
||||
|
||||
static void send_scan_event(struct wpa_driver_nl80211_data *drv, int aborted,
|
||||
static void send_scan_event(struct i802_bss *bss, int aborted,
|
||||
struct nlattr *tb[], int external_scan)
|
||||
{
|
||||
struct wpa_driver_nl80211_data *drv = bss->drv;
|
||||
union wpa_event_data event;
|
||||
struct nlattr *nl;
|
||||
int rem;
|
||||
|
@ -1967,6 +1988,8 @@ static void send_scan_event(struct wpa_driver_nl80211_data *drv, int aborted,
|
|||
#define MAX_REPORT_FREQS 110
|
||||
int freqs[MAX_REPORT_FREQS];
|
||||
int num_freqs = 0;
|
||||
struct i802_link *mld_link;
|
||||
void *ctx = bss->ctx;
|
||||
|
||||
if (!external_scan && drv->scan_for_auth) {
|
||||
drv->scan_for_auth = 0;
|
||||
|
@ -2030,13 +2053,30 @@ static void send_scan_event(struct wpa_driver_nl80211_data *drv, int aborted,
|
|||
ETH_ALEN);
|
||||
}
|
||||
|
||||
wpa_supplicant_event(drv->ctx, EVENT_SCAN_RESULTS, &event);
|
||||
/* Need to pass to the correct link ctx during AP MLD operation */
|
||||
if (is_ap_interface(drv->nlmode)) {
|
||||
mld_link = bss->scan_link;
|
||||
if (!mld_link) {
|
||||
wpa_printf(MSG_DEBUG,
|
||||
"nl80211: Scan event on unknown link");
|
||||
} else if (mld_link->ctx) {
|
||||
u8 link_id = nl80211_get_link_id_from_link(bss,
|
||||
mld_link);
|
||||
|
||||
wpa_printf(MSG_DEBUG,
|
||||
"nl80211: Scan event for link_id %d",
|
||||
link_id);
|
||||
ctx = mld_link->ctx;
|
||||
}
|
||||
}
|
||||
|
||||
wpa_supplicant_event(ctx, EVENT_SCAN_RESULTS, &event);
|
||||
}
|
||||
|
||||
|
||||
static void nl80211_cqm_event(struct wpa_driver_nl80211_data *drv,
|
||||
struct nlattr *tb[])
|
||||
static void nl80211_cqm_event(struct i802_bss *bss, struct nlattr *tb[])
|
||||
{
|
||||
struct wpa_driver_nl80211_data *drv = bss->drv;
|
||||
static struct nla_policy cqm_policy[NL80211_ATTR_CQM_MAX + 1] = {
|
||||
[NL80211_ATTR_CQM_RSSI_THOLD] = { .type = NLA_U32 },
|
||||
[NL80211_ATTR_CQM_RSSI_HYST] = { .type = NLA_U8 },
|
||||
|
@ -2071,7 +2111,7 @@ static void nl80211_cqm_event(struct wpa_driver_nl80211_data *drv,
|
|||
wpa_printf(MSG_DEBUG, "nl80211: Packet loss event for " MACSTR
|
||||
" (num_packets %u)",
|
||||
MAC2STR(ed.low_ack.addr), ed.low_ack.num_packets);
|
||||
wpa_supplicant_event(drv->ctx, EVENT_STATION_LOW_ACK, &ed);
|
||||
wpa_supplicant_event(bss->ctx, EVENT_STATION_LOW_ACK, &ed);
|
||||
return;
|
||||
}
|
||||
|
||||
|
@ -2184,7 +2224,7 @@ static void nl80211_new_station_event(struct wpa_driver_nl80211_data *drv,
|
|||
u8 *req_ies = NULL, *resp_ies = NULL;
|
||||
size_t req_ies_len = 0, resp_ies_len = 0;
|
||||
|
||||
if (bss->links[0].link_id == NL80211_DRV_LINK_ID_NA &&
|
||||
if (!bss->valid_links &&
|
||||
(tb[NL80211_ATTR_MLO_LINK_ID] ||
|
||||
tb[NL80211_ATTR_MLD_ADDR])) {
|
||||
wpa_printf(MSG_ERROR,
|
||||
|
@ -2403,10 +2443,33 @@ static void nl80211_tdls_oper_event(struct wpa_driver_nl80211_data *drv,
|
|||
}
|
||||
|
||||
|
||||
static void nl80211_stop_ap(struct wpa_driver_nl80211_data *drv,
|
||||
struct nlattr **tb)
|
||||
static void nl80211_stop_ap(struct i802_bss *bss, struct nlattr **tb)
|
||||
{
|
||||
wpa_supplicant_event(drv->ctx, EVENT_INTERFACE_UNAVAILABLE, NULL);
|
||||
struct i802_link *mld_link = NULL;
|
||||
void *ctx = bss->ctx;
|
||||
int link_id = -1;
|
||||
|
||||
if (tb[NL80211_ATTR_MLO_LINK_ID]) {
|
||||
link_id = nla_get_u8(tb[NL80211_ATTR_MLO_LINK_ID]);
|
||||
if (!nl80211_link_valid(bss->valid_links, link_id)) {
|
||||
wpa_printf(MSG_DEBUG,
|
||||
"nl80211: Ignoring STOP_AP event for invalid link ID %d (valid: 0x%04x)",
|
||||
link_id, bss->valid_links);
|
||||
return;
|
||||
}
|
||||
|
||||
mld_link = nl80211_get_link(bss, link_id);
|
||||
wpa_printf(MSG_DEBUG,
|
||||
"nl80211: STOP_AP event on link %d", link_id);
|
||||
ctx = mld_link->ctx;
|
||||
|
||||
/* The driver would have already deleted the link and this call
|
||||
* will return an error. Ignore that since nl80211_remove_link()
|
||||
* is called here only to update the bss->links[] state. */
|
||||
nl80211_remove_link(bss, link_id);
|
||||
}
|
||||
|
||||
wpa_supplicant_event(ctx, EVENT_INTERFACE_UNAVAILABLE, NULL);
|
||||
}
|
||||
|
||||
|
||||
|
@ -2452,7 +2515,6 @@ static void nl80211_radar_event(struct wpa_driver_nl80211_data *drv,
|
|||
{
|
||||
union wpa_event_data data;
|
||||
enum nl80211_radar_event event_type;
|
||||
struct i802_link *mld_link = NULL;
|
||||
|
||||
if (!tb[NL80211_ATTR_WIPHY_FREQ] || !tb[NL80211_ATTR_RADAR_EVENT])
|
||||
return;
|
||||
|
@ -2462,11 +2524,13 @@ static void nl80211_radar_event(struct wpa_driver_nl80211_data *drv,
|
|||
data.dfs_event.freq = nla_get_u32(tb[NL80211_ATTR_WIPHY_FREQ]);
|
||||
event_type = nla_get_u32(tb[NL80211_ATTR_RADAR_EVENT]);
|
||||
|
||||
if (data.dfs_event.freq) {
|
||||
mld_link = nl80211_get_mld_link_by_freq(drv->first_bss,
|
||||
data.dfs_event.freq);
|
||||
if (mld_link)
|
||||
data.dfs_event.link_id = mld_link->link_id;
|
||||
if (tb[NL80211_ATTR_MLO_LINK_ID]) {
|
||||
data.dfs_event.link_id =
|
||||
nla_get_u8(tb[NL80211_ATTR_MLO_LINK_ID]);
|
||||
} else if (data.dfs_event.freq) {
|
||||
data.dfs_event.link_id =
|
||||
nl80211_get_link_id_by_freq(drv->first_bss,
|
||||
data.dfs_event.freq);
|
||||
}
|
||||
|
||||
/* Check HT params */
|
||||
|
@ -2832,7 +2896,6 @@ static void qca_nl80211_dfs_offload_radar_event(
|
|||
{
|
||||
union wpa_event_data data;
|
||||
struct nlattr *tb[NL80211_ATTR_MAX + 1];
|
||||
struct i802_link *mld_link = NULL;
|
||||
|
||||
wpa_printf(MSG_DEBUG,
|
||||
"nl80211: DFS offload radar vendor event received");
|
||||
|
@ -2851,11 +2914,13 @@ static void qca_nl80211_dfs_offload_radar_event(
|
|||
data.dfs_event.freq = nla_get_u32(tb[NL80211_ATTR_WIPHY_FREQ]);
|
||||
data.dfs_event.link_id = NL80211_DRV_LINK_ID_NA;
|
||||
|
||||
if (data.dfs_event.freq) {
|
||||
mld_link = nl80211_get_mld_link_by_freq(drv->first_bss,
|
||||
data.dfs_event.freq);
|
||||
if (mld_link)
|
||||
data.dfs_event.link_id = mld_link->link_id;
|
||||
if (tb[NL80211_ATTR_MLO_LINK_ID]) {
|
||||
data.dfs_event.link_id =
|
||||
nla_get_u8(tb[NL80211_ATTR_MLO_LINK_ID]);
|
||||
} else if (data.dfs_event.freq) {
|
||||
data.dfs_event.link_id =
|
||||
nl80211_get_link_id_by_freq(drv->first_bss,
|
||||
data.dfs_event.freq);
|
||||
}
|
||||
|
||||
wpa_printf(MSG_DEBUG, "nl80211: DFS event on freq %d MHz, link=%d",
|
||||
|
@ -2967,6 +3032,7 @@ static void send_vendor_scan_event(struct wpa_driver_nl80211_data *drv,
|
|||
info = &event.scan_info;
|
||||
info->aborted = aborted;
|
||||
info->external_scan = external_scan;
|
||||
info->scan_cookie = nla_get_u64(tb[QCA_WLAN_VENDOR_ATTR_SCAN_COOKIE]);
|
||||
|
||||
if (tb[QCA_WLAN_VENDOR_ATTR_SCAN_SSIDS]) {
|
||||
nla_for_each_nested(nl,
|
||||
|
@ -3044,7 +3110,7 @@ static void qca_nl80211_scan_done_event(struct wpa_driver_nl80211_data *drv,
|
|||
drv->scan_state = SCAN_ABORTED;
|
||||
|
||||
eloop_cancel_timeout(wpa_driver_nl80211_scan_timeout, drv,
|
||||
drv->ctx);
|
||||
drv->first_bss->ctx);
|
||||
drv->vendor_scan_cookie = 0;
|
||||
drv->last_scan_cmd = 0;
|
||||
}
|
||||
|
@ -3655,8 +3721,7 @@ static void nl80211_sta_opmode_change_event(struct wpa_driver_nl80211_data *drv,
|
|||
}
|
||||
|
||||
|
||||
static void nl80211_control_port_frame(struct wpa_driver_nl80211_data *drv,
|
||||
struct nlattr **tb)
|
||||
static void nl80211_control_port_frame(struct i802_bss *bss, struct nlattr **tb)
|
||||
{
|
||||
u8 *src_addr;
|
||||
u16 ethertype;
|
||||
|
@ -3685,7 +3750,7 @@ static void nl80211_control_port_frame(struct wpa_driver_nl80211_data *drv,
|
|||
MAC2STR(src_addr));
|
||||
break;
|
||||
case ETH_P_PAE:
|
||||
drv_event_eapol_rx2(drv->ctx, src_addr,
|
||||
drv_event_eapol_rx2(bss->ctx, src_addr,
|
||||
nla_data(tb[NL80211_ATTR_FRAME]),
|
||||
nla_len(tb[NL80211_ATTR_FRAME]),
|
||||
encrypted, link_id);
|
||||
|
@ -3701,10 +3766,11 @@ static void nl80211_control_port_frame(struct wpa_driver_nl80211_data *drv,
|
|||
|
||||
|
||||
static void
|
||||
nl80211_control_port_frame_tx_status(struct wpa_driver_nl80211_data *drv,
|
||||
nl80211_control_port_frame_tx_status(struct i802_bss *bss,
|
||||
const u8 *frame, size_t len,
|
||||
struct nlattr *ack, struct nlattr *cookie)
|
||||
{
|
||||
struct wpa_driver_nl80211_data *drv = bss->drv;
|
||||
union wpa_event_data event;
|
||||
|
||||
if (!cookie || len < ETH_HLEN)
|
||||
|
@ -3723,7 +3789,7 @@ nl80211_control_port_frame_tx_status(struct wpa_driver_nl80211_data *drv,
|
|||
nla_get_u64(cookie) == drv->eapol_tx_cookie ?
|
||||
drv->eapol_tx_link_id : NL80211_DRV_LINK_ID_NA;
|
||||
|
||||
wpa_supplicant_event(drv->ctx, EVENT_EAPOL_TX_STATUS, &event);
|
||||
wpa_supplicant_event(bss->ctx, EVENT_EAPOL_TX_STATUS, &event);
|
||||
}
|
||||
|
||||
|
||||
|
@ -3749,8 +3815,11 @@ static void nl80211_frame_wait_cancel(struct wpa_driver_nl80211_data *drv,
|
|||
(long long unsigned int) cookie,
|
||||
match ? " (match)" : "",
|
||||
drv->send_frame_cookie == cookie ? " (match-saved)" : "");
|
||||
if (drv->send_frame_cookie == cookie)
|
||||
if (drv->send_frame_cookie == cookie) {
|
||||
drv->send_frame_cookie = (u64) -1;
|
||||
if (!match)
|
||||
goto send_event;
|
||||
}
|
||||
if (!match)
|
||||
return;
|
||||
|
||||
|
@ -3760,6 +3829,7 @@ static void nl80211_frame_wait_cancel(struct wpa_driver_nl80211_data *drv,
|
|||
(drv->num_send_frame_cookies - i - 1) * sizeof(u64));
|
||||
drv->num_send_frame_cookies--;
|
||||
|
||||
send_event:
|
||||
wpa_supplicant_event(drv->ctx, EVENT_TX_WAIT_EXPIRE, NULL);
|
||||
}
|
||||
|
||||
|
@ -3777,48 +3847,62 @@ static void nl80211_assoc_comeback(struct wpa_driver_nl80211_data *drv,
|
|||
|
||||
#ifdef CONFIG_IEEE80211AX
|
||||
|
||||
static void nl80211_obss_color_collision(struct i802_bss *bss,
|
||||
struct nlattr *tb[])
|
||||
static void nl80211_obss_color_event(struct i802_bss *bss,
|
||||
enum nl80211_commands cmd,
|
||||
struct nlattr *tb[])
|
||||
{
|
||||
union wpa_event_data data;
|
||||
|
||||
if (!tb[NL80211_ATTR_OBSS_COLOR_BITMAP])
|
||||
return;
|
||||
enum wpa_event_type event_type;
|
||||
|
||||
os_memset(&data, 0, sizeof(data));
|
||||
data.bss_color_collision.bitmap =
|
||||
nla_get_u64(tb[NL80211_ATTR_OBSS_COLOR_BITMAP]);
|
||||
data.bss_color_collision.link_id = NL80211_DRV_LINK_ID_NA;
|
||||
|
||||
wpa_printf(MSG_DEBUG, "nl80211: BSS color collision - bitmap %08llx",
|
||||
(long long unsigned int) data.bss_color_collision.bitmap);
|
||||
wpa_supplicant_event(bss->ctx, EVENT_BSS_COLOR_COLLISION, &data);
|
||||
}
|
||||
switch (cmd) {
|
||||
case NL80211_CMD_OBSS_COLOR_COLLISION:
|
||||
event_type = EVENT_BSS_COLOR_COLLISION;
|
||||
if (!tb[NL80211_ATTR_OBSS_COLOR_BITMAP])
|
||||
return;
|
||||
data.bss_color_collision.bitmap =
|
||||
nla_get_u64(tb[NL80211_ATTR_OBSS_COLOR_BITMAP]);
|
||||
wpa_printf(MSG_DEBUG,
|
||||
"nl80211: BSS color collision - bitmap %08llx",
|
||||
(long long unsigned int)
|
||||
data.bss_color_collision.bitmap);
|
||||
break;
|
||||
case NL80211_CMD_COLOR_CHANGE_STARTED:
|
||||
event_type = EVENT_CCA_STARTED_NOTIFY;
|
||||
wpa_printf(MSG_DEBUG, "nl80211: CCA started");
|
||||
break;
|
||||
case NL80211_CMD_COLOR_CHANGE_ABORTED:
|
||||
event_type = EVENT_CCA_ABORTED_NOTIFY;
|
||||
wpa_printf(MSG_DEBUG, "nl80211: CCA aborted");
|
||||
break;
|
||||
case NL80211_CMD_COLOR_CHANGE_COMPLETED:
|
||||
event_type = EVENT_CCA_NOTIFY;
|
||||
wpa_printf(MSG_DEBUG, "nl80211: CCA completed");
|
||||
break;
|
||||
default:
|
||||
wpa_printf(MSG_DEBUG, "nl80211: Unknown CCA command %d", cmd);
|
||||
return;
|
||||
}
|
||||
|
||||
if (tb[NL80211_ATTR_MLO_LINK_ID]) {
|
||||
data.bss_color_collision.link_id =
|
||||
nla_get_u8(tb[NL80211_ATTR_MLO_LINK_ID]);
|
||||
|
||||
static void nl80211_color_change_announcement_started(struct i802_bss *bss)
|
||||
{
|
||||
union wpa_event_data data = {};
|
||||
if (!nl80211_link_valid(bss->valid_links,
|
||||
data.bss_color_collision.link_id)) {
|
||||
wpa_printf(MSG_DEBUG,
|
||||
"nl80211: Invalid BSS color event link ID %d",
|
||||
data.bss_color_collision.link_id);
|
||||
return;
|
||||
}
|
||||
|
||||
wpa_printf(MSG_DEBUG, "nl80211: CCA started");
|
||||
wpa_supplicant_event(bss->ctx, EVENT_CCA_STARTED_NOTIFY, &data);
|
||||
}
|
||||
wpa_printf(MSG_DEBUG, "nl80211: BSS color event - Link ID %d",
|
||||
data.bss_color_collision.link_id);
|
||||
}
|
||||
|
||||
|
||||
static void nl80211_color_change_announcement_aborted(struct i802_bss *bss)
|
||||
{
|
||||
union wpa_event_data data = {};
|
||||
|
||||
wpa_printf(MSG_DEBUG, "nl80211: CCA aborted");
|
||||
wpa_supplicant_event(bss->ctx, EVENT_CCA_ABORTED_NOTIFY, &data);
|
||||
}
|
||||
|
||||
|
||||
static void nl80211_color_change_announcement_completed(struct i802_bss *bss)
|
||||
{
|
||||
union wpa_event_data data = {};
|
||||
|
||||
wpa_printf(MSG_DEBUG, "nl80211: CCA completed");
|
||||
wpa_supplicant_event(bss->ctx, EVENT_CCA_NOTIFY, &data);
|
||||
wpa_supplicant_event(bss->ctx, event_type, &data);
|
||||
}
|
||||
|
||||
#endif /* CONFIG_IEEE80211AX */
|
||||
|
@ -3865,7 +3949,7 @@ static void do_process_drv_event(struct i802_bss *bss, int cmd,
|
|||
|
||||
switch (cmd) {
|
||||
case NL80211_CMD_TRIGGER_SCAN:
|
||||
wpa_dbg(drv->ctx, MSG_DEBUG, "nl80211: Scan trigger");
|
||||
wpa_dbg(bss->ctx, MSG_DEBUG, "nl80211: Scan trigger");
|
||||
drv->scan_state = SCAN_STARTED;
|
||||
if (drv->scan_for_auth) {
|
||||
/*
|
||||
|
@ -3877,40 +3961,40 @@ static void do_process_drv_event(struct i802_bss *bss, int cmd,
|
|||
wpa_printf(MSG_DEBUG, "nl80211: Do not indicate scan-start event due to internal scan_for_auth");
|
||||
break;
|
||||
}
|
||||
wpa_supplicant_event(drv->ctx, EVENT_SCAN_STARTED, NULL);
|
||||
wpa_supplicant_event(bss->ctx, EVENT_SCAN_STARTED, NULL);
|
||||
break;
|
||||
case NL80211_CMD_START_SCHED_SCAN:
|
||||
wpa_dbg(drv->ctx, MSG_DEBUG, "nl80211: Sched scan started");
|
||||
wpa_dbg(bss->ctx, MSG_DEBUG, "nl80211: Sched scan started");
|
||||
drv->scan_state = SCHED_SCAN_STARTED;
|
||||
break;
|
||||
case NL80211_CMD_SCHED_SCAN_STOPPED:
|
||||
wpa_dbg(drv->ctx, MSG_DEBUG, "nl80211: Sched scan stopped");
|
||||
wpa_dbg(bss->ctx, MSG_DEBUG, "nl80211: Sched scan stopped");
|
||||
drv->scan_state = SCHED_SCAN_STOPPED;
|
||||
wpa_supplicant_event(drv->ctx, EVENT_SCHED_SCAN_STOPPED, NULL);
|
||||
wpa_supplicant_event(bss->ctx, EVENT_SCHED_SCAN_STOPPED, NULL);
|
||||
break;
|
||||
case NL80211_CMD_NEW_SCAN_RESULTS:
|
||||
wpa_dbg(drv->ctx, MSG_DEBUG,
|
||||
wpa_dbg(bss->ctx, MSG_DEBUG,
|
||||
"nl80211: New scan results available");
|
||||
if (drv->last_scan_cmd != NL80211_CMD_VENDOR)
|
||||
drv->scan_state = SCAN_COMPLETED;
|
||||
drv->scan_complete_events = 1;
|
||||
if (drv->last_scan_cmd == NL80211_CMD_TRIGGER_SCAN) {
|
||||
eloop_cancel_timeout(wpa_driver_nl80211_scan_timeout,
|
||||
drv, drv->ctx);
|
||||
drv, bss->ctx);
|
||||
drv->last_scan_cmd = 0;
|
||||
} else {
|
||||
external_scan_event = 1;
|
||||
}
|
||||
send_scan_event(drv, 0, tb, external_scan_event);
|
||||
send_scan_event(bss, 0, tb, external_scan_event);
|
||||
break;
|
||||
case NL80211_CMD_SCHED_SCAN_RESULTS:
|
||||
wpa_dbg(drv->ctx, MSG_DEBUG,
|
||||
wpa_dbg(bss->ctx, MSG_DEBUG,
|
||||
"nl80211: New sched scan results available");
|
||||
drv->scan_state = SCHED_SCAN_RESULTS;
|
||||
send_scan_event(drv, 0, tb, 0);
|
||||
send_scan_event(bss, 0, tb, 0);
|
||||
break;
|
||||
case NL80211_CMD_SCAN_ABORTED:
|
||||
wpa_dbg(drv->ctx, MSG_DEBUG, "nl80211: Scan aborted");
|
||||
wpa_dbg(bss->ctx, MSG_DEBUG, "nl80211: Scan aborted");
|
||||
if (drv->last_scan_cmd != NL80211_CMD_VENDOR)
|
||||
drv->scan_state = SCAN_ABORTED;
|
||||
if (drv->last_scan_cmd == NL80211_CMD_TRIGGER_SCAN) {
|
||||
|
@ -3919,12 +4003,12 @@ static void do_process_drv_event(struct i802_bss *bss, int cmd,
|
|||
* order not to make wpa_supplicant stop its scanning.
|
||||
*/
|
||||
eloop_cancel_timeout(wpa_driver_nl80211_scan_timeout,
|
||||
drv, drv->ctx);
|
||||
drv, bss->ctx);
|
||||
drv->last_scan_cmd = 0;
|
||||
} else {
|
||||
external_scan_event = 1;
|
||||
}
|
||||
send_scan_event(drv, 1, tb, external_scan_event);
|
||||
send_scan_event(bss, 1, tb, external_scan_event);
|
||||
break;
|
||||
case NL80211_CMD_AUTHENTICATE:
|
||||
case NL80211_CMD_ASSOCIATE:
|
||||
|
@ -4002,7 +4086,7 @@ static void do_process_drv_event(struct i802_bss *bss, int cmd,
|
|||
mlme_event_remain_on_channel(drv, 1, tb);
|
||||
break;
|
||||
case NL80211_CMD_NOTIFY_CQM:
|
||||
nl80211_cqm_event(drv, tb);
|
||||
nl80211_cqm_event(bss, tb);
|
||||
break;
|
||||
case NL80211_CMD_REG_CHANGE:
|
||||
case NL80211_CMD_WIPHY_REG_CHANGE:
|
||||
|
@ -4039,7 +4123,7 @@ static void do_process_drv_event(struct i802_bss *bss, int cmd,
|
|||
nl80211_radar_event(drv, tb);
|
||||
break;
|
||||
case NL80211_CMD_STOP_AP:
|
||||
nl80211_stop_ap(drv, tb);
|
||||
nl80211_stop_ap(bss, tb);
|
||||
break;
|
||||
case NL80211_CMD_VENDOR:
|
||||
nl80211_vendor_event(drv, tb);
|
||||
|
@ -4064,7 +4148,7 @@ static void do_process_drv_event(struct i802_bss *bss, int cmd,
|
|||
case NL80211_CMD_CONTROL_PORT_FRAME_TX_STATUS:
|
||||
if (!frame)
|
||||
break;
|
||||
nl80211_control_port_frame_tx_status(drv,
|
||||
nl80211_control_port_frame_tx_status(bss,
|
||||
nla_data(frame),
|
||||
nla_len(frame),
|
||||
tb[NL80211_ATTR_ACK],
|
||||
|
@ -4079,16 +4163,10 @@ static void do_process_drv_event(struct i802_bss *bss, int cmd,
|
|||
break;
|
||||
#ifdef CONFIG_IEEE80211AX
|
||||
case NL80211_CMD_OBSS_COLOR_COLLISION:
|
||||
nl80211_obss_color_collision(bss, tb);
|
||||
break;
|
||||
case NL80211_CMD_COLOR_CHANGE_STARTED:
|
||||
nl80211_color_change_announcement_started(bss);
|
||||
break;
|
||||
case NL80211_CMD_COLOR_CHANGE_ABORTED:
|
||||
nl80211_color_change_announcement_aborted(bss);
|
||||
break;
|
||||
case NL80211_CMD_COLOR_CHANGE_COMPLETED:
|
||||
nl80211_color_change_announcement_completed(bss);
|
||||
nl80211_obss_color_event(bss, cmd, tb);
|
||||
break;
|
||||
#endif /* CONFIG_IEEE80211AX */
|
||||
case NL80211_CMD_LINKS_REMOVED:
|
||||
|
@ -4179,7 +4257,16 @@ int process_global_event(struct nl_msg *msg, void *arg)
|
|||
wdev_id == bss->wdev_id)) {
|
||||
processed = true;
|
||||
do_process_drv_event(bss, gnlh->cmd, tb);
|
||||
if (!wiphy_idx_set)
|
||||
/* There are two types of events that may need
|
||||
* to be delivered to multiple interfaces:
|
||||
* 1. Events for a wiphy, as it can have
|
||||
* multiple interfaces.
|
||||
* 2. "Global" events, like
|
||||
* NL80211_CMD_REG_CHANGE.
|
||||
*
|
||||
* Terminate early only if the event is directed
|
||||
* to a specific interface or wdev. */
|
||||
if (ifidx != -1 || wdev_id_set)
|
||||
return NL_SKIP;
|
||||
/* The driver instance could have been removed,
|
||||
* e.g., due to NL80211_CMD_RADAR_DETECT event,
|
||||
|
@ -4237,7 +4324,7 @@ int process_bss_event(struct nl_msg *msg, void *arg)
|
|||
nl80211_external_auth(bss->drv, tb);
|
||||
break;
|
||||
case NL80211_CMD_CONTROL_PORT_FRAME:
|
||||
nl80211_control_port_frame(bss->drv, tb);
|
||||
nl80211_control_port_frame(bss, tb);
|
||||
break;
|
||||
default:
|
||||
wpa_printf(MSG_DEBUG, "nl80211: Ignored unknown event "
|
||||
|
|
|
@ -153,6 +153,7 @@ fail:
|
|||
void wpa_driver_nl80211_scan_timeout(void *eloop_ctx, void *timeout_ctx)
|
||||
{
|
||||
struct wpa_driver_nl80211_data *drv = eloop_ctx;
|
||||
struct i802_bss *bss;
|
||||
|
||||
wpa_printf(MSG_DEBUG, "nl80211: Scan timeout - try to abort it");
|
||||
#ifdef CONFIG_DRIVER_NL80211_QCA
|
||||
|
@ -160,14 +161,27 @@ void wpa_driver_nl80211_scan_timeout(void *eloop_ctx, void *timeout_ctx)
|
|||
nl80211_abort_vendor_scan(drv, drv->vendor_scan_cookie) == 0)
|
||||
return;
|
||||
#endif /* CONFIG_DRIVER_NL80211_QCA */
|
||||
if (!drv->vendor_scan_cookie &&
|
||||
nl80211_abort_scan(drv->first_bss) == 0)
|
||||
|
||||
for (bss = drv->first_bss; bss; bss = bss->next) {
|
||||
if (bss->scan_link)
|
||||
break;
|
||||
}
|
||||
|
||||
if (!bss) {
|
||||
wpa_printf(MSG_DEBUG, "nl80211: Failed to find scan BSS");
|
||||
return;
|
||||
}
|
||||
|
||||
if (!drv->vendor_scan_cookie &&
|
||||
nl80211_abort_scan(bss) == 0) {
|
||||
bss->scan_link = NULL;
|
||||
return;
|
||||
}
|
||||
|
||||
wpa_printf(MSG_DEBUG, "nl80211: Failed to abort scan");
|
||||
|
||||
if (drv->ap_scan_as_station != NL80211_IFTYPE_UNSPECIFIED)
|
||||
nl80211_restore_ap_mode(drv->first_bss);
|
||||
nl80211_restore_ap_mode(bss);
|
||||
|
||||
wpa_printf(MSG_DEBUG, "nl80211: Try to get scan results");
|
||||
wpa_supplicant_event(timeout_ctx, EVENT_SCAN_RESULTS, NULL);
|
||||
|
@ -347,7 +361,7 @@ int wpa_driver_nl80211_scan(struct i802_bss *bss,
|
|||
int ret = -1, timeout;
|
||||
struct nl_msg *msg = NULL;
|
||||
|
||||
wpa_dbg(drv->ctx, MSG_DEBUG, "nl80211: scan request");
|
||||
wpa_dbg(bss->ctx, MSG_DEBUG, "nl80211: scan request");
|
||||
drv->scan_for_auth = 0;
|
||||
|
||||
if (TEST_FAIL())
|
||||
|
@ -402,23 +416,52 @@ int wpa_driver_nl80211_scan(struct i802_bss *bss,
|
|||
wpa_printf(MSG_DEBUG, "nl80211: Scan trigger failed: ret=%d "
|
||||
"(%s)", ret, strerror(-ret));
|
||||
if (drv->hostapd && is_ap_interface(drv->nlmode)) {
|
||||
enum nl80211_iftype old_mode = drv->nlmode;
|
||||
#ifdef CONFIG_IEEE80211BE
|
||||
/* For multi link BSS, retry scan if any other links
|
||||
* are busy scanning. */
|
||||
if (ret == -EBUSY &&
|
||||
nl80211_link_valid(bss->valid_links,
|
||||
params->link_id)) {
|
||||
struct i802_bss *link_bss;
|
||||
u8 link_id;
|
||||
|
||||
wpa_printf(MSG_DEBUG,
|
||||
"nl80211: Scan trigger on multi link BSS failed (requested link=%d on interface %s)",
|
||||
params->link_id, bss->ifname);
|
||||
|
||||
for (link_bss = drv->first_bss; link_bss;
|
||||
link_bss = link_bss->next) {
|
||||
if (link_bss->scan_link)
|
||||
break;
|
||||
}
|
||||
|
||||
if (!link_bss) {
|
||||
wpa_printf(MSG_DEBUG,
|
||||
"nl80211: BSS information already running scan not available");
|
||||
goto fail;
|
||||
}
|
||||
|
||||
link_id = nl80211_get_link_id_from_link(
|
||||
link_bss, link_bss->scan_link);
|
||||
wpa_printf(MSG_DEBUG,
|
||||
"nl80211: Scan already running on interface %s link %d",
|
||||
link_bss->ifname, link_id);
|
||||
goto fail;
|
||||
}
|
||||
#endif /* CONFIG_IEEE80211BE */
|
||||
|
||||
/*
|
||||
* mac80211 does not allow scan requests in AP mode, so
|
||||
* try to do this in station mode.
|
||||
*/
|
||||
drv->ap_scan_as_station = drv->nlmode;
|
||||
if (wpa_driver_nl80211_set_mode(
|
||||
bss, NL80211_IFTYPE_STATION))
|
||||
goto fail;
|
||||
|
||||
if (wpa_driver_nl80211_scan(bss, params)) {
|
||||
wpa_driver_nl80211_set_mode(bss, old_mode);
|
||||
bss, NL80211_IFTYPE_STATION) ||
|
||||
wpa_driver_nl80211_scan(bss, params)) {
|
||||
nl80211_restore_ap_mode(bss);
|
||||
goto fail;
|
||||
}
|
||||
|
||||
/* Restore AP mode when processing scan results */
|
||||
drv->ap_scan_as_station = old_mode;
|
||||
ret = 0;
|
||||
} else
|
||||
goto fail;
|
||||
|
@ -440,11 +483,20 @@ int wpa_driver_nl80211_scan(struct i802_bss *bss,
|
|||
}
|
||||
wpa_printf(MSG_DEBUG, "Scan requested (ret=%d) - scan timeout %d "
|
||||
"seconds", ret, timeout);
|
||||
eloop_cancel_timeout(wpa_driver_nl80211_scan_timeout, drv, drv->ctx);
|
||||
eloop_cancel_timeout(wpa_driver_nl80211_scan_timeout, drv, bss->ctx);
|
||||
eloop_register_timeout(timeout, 0, wpa_driver_nl80211_scan_timeout,
|
||||
drv, drv->ctx);
|
||||
drv, bss->ctx);
|
||||
drv->last_scan_cmd = NL80211_CMD_TRIGGER_SCAN;
|
||||
|
||||
bss->scan_link = bss->flink;
|
||||
if (is_ap_interface(drv->nlmode) &&
|
||||
nl80211_link_valid(bss->valid_links, params->link_id)) {
|
||||
wpa_dbg(bss->ctx, MSG_DEBUG,
|
||||
"nl80211: Scan requested for link %d",
|
||||
params->link_id);
|
||||
bss->scan_link = nl80211_get_link(bss, params->link_id);
|
||||
}
|
||||
|
||||
fail:
|
||||
nlmsg_free(msg);
|
||||
return ret;
|
||||
|
@ -728,7 +780,7 @@ static int nl80211_scan_filtered(struct wpa_driver_nl80211_data *drv,
|
|||
|
||||
static struct wpa_scan_res *
|
||||
nl80211_parse_bss_info(struct wpa_driver_nl80211_data *drv,
|
||||
struct nl_msg *msg)
|
||||
struct nl_msg *msg, const u8 *bssid)
|
||||
{
|
||||
struct nlattr *tb[NL80211_ATTR_MAX + 1];
|
||||
struct genlmsghdr *gnlh = nlmsg_data(nlmsg_hdr(msg));
|
||||
|
@ -762,6 +814,9 @@ nl80211_parse_bss_info(struct wpa_driver_nl80211_data *drv,
|
|||
if (nla_parse_nested(bss, NL80211_BSS_MAX, tb[NL80211_ATTR_BSS],
|
||||
bss_policy))
|
||||
return NULL;
|
||||
if (bssid && bss[NL80211_BSS_BSSID] &&
|
||||
!ether_addr_equal(bssid, nla_data(bss[NL80211_BSS_BSSID])))
|
||||
return NULL;
|
||||
if (bss[NL80211_BSS_INFORMATION_ELEMENTS]) {
|
||||
ie = nla_data(bss[NL80211_BSS_INFORMATION_ELEMENTS]);
|
||||
ie_len = nla_len(bss[NL80211_BSS_INFORMATION_ELEMENTS]);
|
||||
|
@ -866,6 +921,7 @@ nl80211_parse_bss_info(struct wpa_driver_nl80211_data *drv,
|
|||
struct nl80211_bss_info_arg {
|
||||
struct wpa_driver_nl80211_data *drv;
|
||||
struct wpa_scan_results *res;
|
||||
const u8 *bssid;
|
||||
};
|
||||
|
||||
static int bss_info_handler(struct nl_msg *msg, void *arg)
|
||||
|
@ -875,7 +931,7 @@ static int bss_info_handler(struct nl_msg *msg, void *arg)
|
|||
struct wpa_scan_res **tmp;
|
||||
struct wpa_scan_res *r;
|
||||
|
||||
r = nl80211_parse_bss_info(_arg->drv, msg);
|
||||
r = nl80211_parse_bss_info(_arg->drv, msg, _arg->bssid);
|
||||
if (!r)
|
||||
return NL_SKIP;
|
||||
|
||||
|
@ -973,7 +1029,7 @@ static void nl80211_update_scan_res_noise(struct wpa_scan_res *res,
|
|||
|
||||
|
||||
static struct wpa_scan_results *
|
||||
nl80211_get_scan_results(struct wpa_driver_nl80211_data *drv)
|
||||
nl80211_get_scan_results(struct wpa_driver_nl80211_data *drv, const u8 *bssid)
|
||||
{
|
||||
struct nl_msg *msg;
|
||||
struct wpa_scan_results *res;
|
||||
|
@ -993,6 +1049,7 @@ try_again:
|
|||
|
||||
arg.drv = drv;
|
||||
arg.res = res;
|
||||
arg.bssid = bssid;
|
||||
ret = send_and_recv_resp(drv, msg, bss_info_handler, &arg);
|
||||
if (ret == -EAGAIN) {
|
||||
count++;
|
||||
|
@ -1029,16 +1086,18 @@ try_again:
|
|||
|
||||
/**
|
||||
* wpa_driver_nl80211_get_scan_results - Fetch the latest scan results
|
||||
* @priv: Pointer to private wext data from wpa_driver_nl80211_init()
|
||||
* @priv: Pointer to private nl80211 data from wpa_driver_nl80211_init()
|
||||
* @bssid: Return results only for the specified BSSID, %NULL for all
|
||||
* Returns: Scan results on success, -1 on failure
|
||||
*/
|
||||
struct wpa_scan_results * wpa_driver_nl80211_get_scan_results(void *priv)
|
||||
struct wpa_scan_results * wpa_driver_nl80211_get_scan_results(void *priv,
|
||||
const u8 *bssid)
|
||||
{
|
||||
struct i802_bss *bss = priv;
|
||||
struct wpa_driver_nl80211_data *drv = bss->drv;
|
||||
struct wpa_scan_results *res;
|
||||
|
||||
res = nl80211_get_scan_results(drv);
|
||||
res = nl80211_get_scan_results(drv, bssid);
|
||||
if (res)
|
||||
wpa_driver_nl80211_check_bss_status(drv, res);
|
||||
return res;
|
||||
|
@ -1055,7 +1114,7 @@ static int nl80211_dump_scan_handler(struct nl_msg *msg, void *arg)
|
|||
struct nl80211_dump_scan_ctx *ctx = arg;
|
||||
struct wpa_scan_res *r;
|
||||
|
||||
r = nl80211_parse_bss_info(ctx->drv, msg);
|
||||
r = nl80211_parse_bss_info(ctx->drv, msg, NULL);
|
||||
if (!r)
|
||||
return NL_SKIP;
|
||||
wpa_printf(MSG_DEBUG, "nl80211: %d " MACSTR " %d%s",
|
||||
|
@ -1268,6 +1327,11 @@ int wpa_driver_nl80211_vendor_scan(struct i802_bss *bss,
|
|||
goto fail;
|
||||
}
|
||||
|
||||
if (is_ap_interface(drv->nlmode) &&
|
||||
params->link_id != NL80211_DRV_LINK_ID_NA &&
|
||||
nla_put_u8(msg, QCA_WLAN_VENDOR_ATTR_SCAN_LINK_ID, params->link_id))
|
||||
goto fail;
|
||||
|
||||
nla_nest_end(msg, attr);
|
||||
|
||||
ret = send_and_recv_resp(drv, msg, scan_cookie_handler, &cookie);
|
||||
|
@ -1287,9 +1351,9 @@ int wpa_driver_nl80211_vendor_scan(struct i802_bss *bss,
|
|||
wpa_printf(MSG_DEBUG,
|
||||
"nl80211: Vendor scan requested (ret=%d) - scan timeout 30 seconds, scan cookie:0x%llx",
|
||||
ret, (long long unsigned int) cookie);
|
||||
eloop_cancel_timeout(wpa_driver_nl80211_scan_timeout, drv, drv->ctx);
|
||||
eloop_cancel_timeout(wpa_driver_nl80211_scan_timeout, drv, bss->ctx);
|
||||
eloop_register_timeout(30, 0, wpa_driver_nl80211_scan_timeout,
|
||||
drv, drv->ctx);
|
||||
drv, bss->ctx);
|
||||
drv->last_scan_cmd = NL80211_CMD_VENDOR;
|
||||
|
||||
fail:
|
||||
|
|
File diff suppressed because it is too large
Load diff
|
@ -255,8 +255,18 @@ static void * eap_wsc_init(struct eap_sm *sm)
|
|||
cfg.new_ap_settings = &new_ap_settings;
|
||||
}
|
||||
|
||||
if (os_strstr(phase1, "multi_ap=1"))
|
||||
cfg.multi_ap_backhaul_sta = 1;
|
||||
pos = os_strstr(phase1, "multi_ap=");
|
||||
if (pos) {
|
||||
u16 id = atoi(pos + 9);
|
||||
|
||||
if (id != 0) {
|
||||
cfg.multi_ap_backhaul_sta = 1;
|
||||
cfg.multi_ap_profile = id;
|
||||
} else {
|
||||
wpa_printf(MSG_DEBUG,
|
||||
"EAP-WSC: Invalid multi_ap setting");
|
||||
}
|
||||
}
|
||||
|
||||
data->wps = wps_init(&cfg);
|
||||
if (data->wps == NULL) {
|
||||
|
|
|
@ -18,11 +18,6 @@
|
|||
#include "fst/fst_ctrl_defs.h"
|
||||
#endif /* CONFIG_FST_TEST */
|
||||
|
||||
#define US_80211_TU 1024
|
||||
|
||||
#define US_TO_TU(m) ((m) * / US_80211_TU)
|
||||
#define TU_TO_US(m) ((m) * US_80211_TU)
|
||||
|
||||
#define FST_LLT_SWITCH_IMMEDIATELY 0
|
||||
|
||||
#define fst_printf_session(s, level, format, ...) \
|
||||
|
@ -182,7 +177,8 @@ static void fst_session_timeout_handler(void *eloop_data, void *user_ctx)
|
|||
static void fst_session_stt_arm(struct fst_session *s)
|
||||
{
|
||||
/* Action frames sometimes get delayed. Use relaxed timeout (2*) */
|
||||
eloop_register_timeout(0, 2 * TU_TO_US(FST_DEFAULT_SESSION_TIMEOUT_TU),
|
||||
eloop_register_timeout(0,
|
||||
2 * TU_TO_USEC(FST_DEFAULT_SESSION_TIMEOUT_TU),
|
||||
fst_session_timeout_handler, NULL, s);
|
||||
s->stt_armed = true;
|
||||
}
|
||||
|
|
|
@ -30,6 +30,9 @@
|
|||
#include "eloop.h"
|
||||
#include "l2_packet.h"
|
||||
|
||||
#ifndef ETHER_VLAN_ENCAP_LEN
|
||||
#define ETHER_VLAN_ENCAP_LEN 4
|
||||
#endif
|
||||
|
||||
static const u8 pae_group_addr[ETH_ALEN] =
|
||||
{ 0x01, 0x80, 0xc2, 0x00, 0x00, 0x03 };
|
||||
|
|
249
src/p2p/p2p.c
249
src/p2p/p2p.c
|
@ -954,6 +954,7 @@ static void p2p_device_free(struct p2p_data *p2p, struct p2p_device *dev)
|
|||
dev->info.wps_vendor_ext[i] = NULL;
|
||||
}
|
||||
|
||||
os_free(dev->bootstrap_params);
|
||||
wpabuf_free(dev->info.wfd_subelems);
|
||||
wpabuf_free(dev->info.vendor_elems);
|
||||
wpabuf_free(dev->go_neg_conf);
|
||||
|
@ -1599,7 +1600,8 @@ int p2p_connect(struct p2p_data *p2p, const u8 *peer_addr,
|
|||
int go_intent, const u8 *own_interface_addr,
|
||||
unsigned int force_freq, int persistent_group,
|
||||
const u8 *force_ssid, size_t force_ssid_len,
|
||||
int pd_before_go_neg, unsigned int pref_freq, u16 oob_pw_id)
|
||||
int pd_before_go_neg, unsigned int pref_freq, u16 oob_pw_id,
|
||||
bool p2p2, u16 bootstrap, const char *password)
|
||||
{
|
||||
struct p2p_device *dev;
|
||||
|
||||
|
@ -1683,6 +1685,10 @@ int p2p_connect(struct p2p_data *p2p, const u8 *peer_addr,
|
|||
|
||||
dev->wps_method = wps_method;
|
||||
dev->oob_pw_id = oob_pw_id;
|
||||
dev->p2p2 = p2p2;
|
||||
dev->req_bootstrap_method = bootstrap;
|
||||
if (password && os_strlen(password) < sizeof(dev->password))
|
||||
os_strlcpy(dev->password, password, sizeof(dev->password));
|
||||
dev->status = P2P_SC_SUCCESS;
|
||||
|
||||
if (p2p->p2p_scan_running) {
|
||||
|
@ -1701,7 +1707,8 @@ int p2p_authorize(struct p2p_data *p2p, const u8 *peer_addr,
|
|||
int go_intent, const u8 *own_interface_addr,
|
||||
unsigned int force_freq, int persistent_group,
|
||||
const u8 *force_ssid, size_t force_ssid_len,
|
||||
unsigned int pref_freq, u16 oob_pw_id)
|
||||
unsigned int pref_freq, u16 oob_pw_id, u16 bootstrap,
|
||||
const char *password)
|
||||
{
|
||||
struct p2p_device *dev;
|
||||
|
||||
|
@ -1735,6 +1742,10 @@ int p2p_authorize(struct p2p_data *p2p, const u8 *peer_addr,
|
|||
dev->flags &= ~P2P_DEV_USER_REJECTED;
|
||||
dev->go_neg_req_sent = 0;
|
||||
dev->go_state = UNKNOWN_GO;
|
||||
dev->req_bootstrap_method = bootstrap;
|
||||
|
||||
if (password && os_strlen(password) < sizeof(dev->password))
|
||||
os_strlcpy(dev->password, password, sizeof(dev->password));
|
||||
p2p_set_dev_persistent(dev, persistent_group);
|
||||
p2p->go_intent = go_intent;
|
||||
os_memcpy(p2p->intended_addr, own_interface_addr, ETH_ALEN);
|
||||
|
@ -1924,10 +1935,10 @@ static void p2p_rx_p2p_action(struct p2p_data *p2p, const u8 *sa,
|
|||
p2p_process_invitation_resp(p2p, sa, data + 1, len - 1);
|
||||
break;
|
||||
case P2P_PROV_DISC_REQ:
|
||||
p2p_process_prov_disc_req(p2p, sa, data + 1, len - 1, rx_freq);
|
||||
p2p_handle_prov_disc_req(p2p, sa, data + 1, len - 1, rx_freq);
|
||||
break;
|
||||
case P2P_PROV_DISC_RESP:
|
||||
p2p_process_prov_disc_resp(p2p, sa, data + 1, len - 1);
|
||||
p2p_handle_prov_disc_resp(p2p, sa, data + 1, len - 1, rx_freq);
|
||||
break;
|
||||
case P2P_DEV_DISC_REQ:
|
||||
p2p_process_dev_disc_req(p2p, sa, data + 1, len - 1, rx_freq);
|
||||
|
@ -2968,6 +2979,44 @@ bool is_p2p_6ghz_disabled(struct p2p_data *p2p)
|
|||
}
|
||||
|
||||
|
||||
static void p2p_pairing_info_deinit(struct p2p_data *p2p)
|
||||
{
|
||||
os_free(p2p->pairing_info);
|
||||
}
|
||||
|
||||
|
||||
static int p2p_pairing_info_init(struct p2p_data *p2p)
|
||||
{
|
||||
struct p2p_pairing_info *pairing_info;
|
||||
|
||||
if (p2p->cfg->pairing_config.dik_len > DEVICE_IDENTITY_KEY_MAX_LEN)
|
||||
return -1;
|
||||
|
||||
pairing_info = os_zalloc(sizeof(struct p2p_pairing_info));
|
||||
if (!pairing_info)
|
||||
return -1;
|
||||
|
||||
pairing_info->enable_pairing_setup =
|
||||
p2p->cfg->pairing_config.enable_pairing_setup;
|
||||
pairing_info->enable_pairing_cache =
|
||||
p2p->cfg->pairing_config.enable_pairing_cache;
|
||||
pairing_info->supported_bootstrap =
|
||||
p2p->cfg->pairing_config.bootstrap_methods;
|
||||
|
||||
pairing_info->dev_ik.cipher_version =
|
||||
p2p->cfg->pairing_config.dik_cipher;
|
||||
pairing_info->dev_ik.dik_len = p2p->cfg->pairing_config.dik_len;
|
||||
os_memcpy(pairing_info->dev_ik.dik_data,
|
||||
p2p->cfg->pairing_config.dik_data,
|
||||
p2p->cfg->pairing_config.dik_len);
|
||||
|
||||
p2p_pairing_info_deinit(p2p);
|
||||
p2p->pairing_info = pairing_info;
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
|
||||
struct p2p_data * p2p_init(const struct p2p_config *cfg)
|
||||
{
|
||||
struct p2p_data *p2p;
|
||||
|
@ -3023,6 +3072,10 @@ struct p2p_data * p2p_init(const struct p2p_config *cfg)
|
|||
p2p->go_timeout = 100;
|
||||
p2p->client_timeout = 20;
|
||||
p2p->num_p2p_sd_queries = 0;
|
||||
/* Default comeback after one second */
|
||||
if (!p2p->cfg->comeback_after)
|
||||
p2p->cfg->comeback_after = 977; /* TUs */
|
||||
p2p_pairing_info_init(p2p);
|
||||
|
||||
p2p_dbg(p2p, "initialized");
|
||||
p2p_channels_dump(p2p, "channels", &p2p->cfg->channels);
|
||||
|
@ -3066,6 +3119,7 @@ void p2p_deinit(struct p2p_data *p2p)
|
|||
p2p_remove_wps_vendor_extensions(p2p);
|
||||
os_free(p2p->no_go_freq.range);
|
||||
p2p_service_flush_asp(p2p);
|
||||
p2p_pairing_info_deinit(p2p);
|
||||
|
||||
os_free(p2p);
|
||||
}
|
||||
|
@ -3332,7 +3386,7 @@ skip_sd:
|
|||
}
|
||||
|
||||
|
||||
static void p2p_sd_cb(struct p2p_data *p2p, int success)
|
||||
void p2p_sd_query_cb(struct p2p_data *p2p, int success)
|
||||
{
|
||||
p2p_dbg(p2p, "Service Discovery Query TX callback: success=%d",
|
||||
success);
|
||||
|
@ -3399,7 +3453,7 @@ static void p2p_retry_pd(struct p2p_data *p2p)
|
|||
if (!ether_addr_equal(p2p->pending_pd_devaddr,
|
||||
dev->info.p2p_device_addr))
|
||||
continue;
|
||||
if (!dev->req_config_methods)
|
||||
if (!dev->req_config_methods && !dev->req_bootstrap_method)
|
||||
continue;
|
||||
|
||||
p2p_dbg(p2p, "Send pending Provision Discovery Request to "
|
||||
|
@ -3835,7 +3889,7 @@ void p2p_send_action_cb(struct p2p_data *p2p, unsigned int freq, const u8 *dst,
|
|||
p2p_go_neg_conf_cb(p2p, result);
|
||||
break;
|
||||
case P2P_PENDING_SD:
|
||||
p2p_sd_cb(p2p, success);
|
||||
p2p_sd_query_cb(p2p, success);
|
||||
break;
|
||||
case P2P_PENDING_PD:
|
||||
p2p_prov_disc_cb(p2p, success);
|
||||
|
@ -5688,3 +5742,184 @@ void set_p2p_allow_6ghz(struct p2p_data *p2p, bool value)
|
|||
{
|
||||
p2p->allow_6ghz = value;
|
||||
}
|
||||
|
||||
|
||||
static int p2p_derive_nonce_tag(struct p2p_data *p2p)
|
||||
{
|
||||
u8 dira_nonce[DEVICE_IDENTITY_NONCE_LEN];
|
||||
u8 dira_tag[DEVICE_MAX_HASH_LEN];
|
||||
u8 data[DIR_STR_LEN + DEVICE_IDENTITY_NONCE_LEN + ETH_ALEN];
|
||||
struct p2p_id_key *dev_ik;
|
||||
|
||||
dev_ik = &p2p->pairing_info->dev_ik;
|
||||
|
||||
if (dev_ik->cipher_version != DIRA_CIPHER_VERSION_128) {
|
||||
wpa_printf(MSG_INFO,
|
||||
"P2P: Unsupported DIRA Cipher version = %d",
|
||||
dev_ik->cipher_version);
|
||||
return -1;
|
||||
}
|
||||
|
||||
if (dev_ik->dik_len != DEVICE_IDENTITY_KEY_LEN) {
|
||||
wpa_printf(MSG_INFO, "P2P: Invalid DIK length = %zu",
|
||||
dev_ik->dik_len);
|
||||
return -1;
|
||||
}
|
||||
|
||||
os_memset(data, 0, sizeof(data));
|
||||
|
||||
if (os_get_random(dira_nonce, DEVICE_IDENTITY_NONCE_LEN) < 0) {
|
||||
wpa_printf(MSG_ERROR, "P2P: Failed to generate DIRA nonce");
|
||||
return -1;
|
||||
}
|
||||
|
||||
/* Tag = Truncate-64(HMAC-SHA-256(DevIK,
|
||||
* "DIR" || P2P Device Address || Nonce))
|
||||
*/
|
||||
os_memcpy(data, "DIR", DIR_STR_LEN);
|
||||
os_memcpy(&data[DIR_STR_LEN], p2p->cfg->dev_addr, ETH_ALEN);
|
||||
os_memcpy(&data[DIR_STR_LEN + ETH_ALEN], dira_nonce,
|
||||
DEVICE_IDENTITY_NONCE_LEN);
|
||||
|
||||
if (hmac_sha256(dev_ik->dik_data, dev_ik->dik_len, data, sizeof(data),
|
||||
dira_tag) < 0) {
|
||||
wpa_printf(MSG_ERROR, "P2P: Could not derive DIRA tag");
|
||||
return -1;
|
||||
}
|
||||
|
||||
dev_ik->dira_nonce_len = DEVICE_IDENTITY_NONCE_LEN;
|
||||
os_memcpy(dev_ik->dira_nonce, dira_nonce, DEVICE_IDENTITY_NONCE_LEN);
|
||||
dev_ik->dira_tag_len = DEVICE_IDENTITY_TAG_LEN;
|
||||
os_memcpy(dev_ik->dira_tag, dira_tag, DEVICE_IDENTITY_TAG_LEN);
|
||||
|
||||
wpa_hexdump_key(MSG_DEBUG, "P2P: DIK", dev_ik->dik_data,
|
||||
dev_ik->dik_len);
|
||||
wpa_hexdump_key(MSG_DEBUG, "P2P: DIRA-NONCE", dev_ik->dira_nonce,
|
||||
dev_ik->dira_nonce_len);
|
||||
wpa_hexdump_key(MSG_DEBUG, "P2P: DIRA-TAG", dev_ik->dira_tag,
|
||||
dev_ik->dira_tag_len);
|
||||
return 0;
|
||||
}
|
||||
|
||||
|
||||
struct wpabuf * p2p_usd_elems(struct p2p_data *p2p)
|
||||
{
|
||||
struct wpabuf *buf;
|
||||
u8 *len;
|
||||
u8 group_capab;
|
||||
|
||||
buf = wpabuf_alloc(1000);
|
||||
if (!buf)
|
||||
return NULL;
|
||||
|
||||
len = p2p_buf_add_ie_hdr(buf);
|
||||
|
||||
/* P2P Capability attribute */
|
||||
group_capab = 0;
|
||||
if (p2p->num_groups) {
|
||||
group_capab |= P2P_GROUP_CAPAB_GROUP_OWNER;
|
||||
if ((p2p->dev_capab & P2P_DEV_CAPAB_CONCURRENT_OPER) &&
|
||||
(p2p->dev_capab & P2P_DEV_CAPAB_INFRA_MANAGED) &&
|
||||
p2p->cross_connect)
|
||||
group_capab |= P2P_GROUP_CAPAB_CROSS_CONN;
|
||||
}
|
||||
if (p2p->cfg->p2p_intra_bss)
|
||||
group_capab |= P2P_GROUP_CAPAB_INTRA_BSS_DIST;
|
||||
p2p_buf_add_capability(buf, p2p->dev_capab &
|
||||
~P2P_DEV_CAPAB_CLIENT_DISCOVERABILITY,
|
||||
group_capab);
|
||||
|
||||
/* P2P Device Info attribute */
|
||||
p2p_buf_add_device_info(buf, p2p, NULL);
|
||||
|
||||
p2p_buf_update_ie_hdr(buf, len);
|
||||
|
||||
len = p2p_buf_add_p2p2_ie_hdr(buf);
|
||||
|
||||
/* P2P Capability Extension attribute */
|
||||
p2p_buf_add_pcea(buf, p2p);
|
||||
|
||||
/* P2P Pairing Bootstrapping Method attribute */
|
||||
p2p_buf_add_pbma(buf, p2p->cfg->pairing_config.bootstrap_methods, NULL,
|
||||
0, 0);
|
||||
|
||||
/* P2P Device Identity Resolution attribute */
|
||||
if (p2p->pairing_info &&
|
||||
p2p->cfg->pairing_config.pairing_capable &&
|
||||
p2p->cfg->pairing_config.enable_pairing_cache &&
|
||||
p2p->cfg->pairing_config.enable_pairing_verification &&
|
||||
p2p_derive_nonce_tag(p2p) == 0)
|
||||
p2p_buf_add_dira(buf, p2p);
|
||||
|
||||
p2p_buf_update_ie_hdr(buf, len);
|
||||
|
||||
return buf;
|
||||
}
|
||||
|
||||
|
||||
void p2p_process_usd_elems(struct p2p_data *p2p, const u8 *ies, u16 ies_len,
|
||||
const u8 *peer_addr, unsigned int freq)
|
||||
{
|
||||
struct p2p_device *dev;
|
||||
struct p2p_message msg;
|
||||
const u8 *p2p_dev_addr;
|
||||
|
||||
os_memset(&msg, 0, sizeof(msg));
|
||||
if (p2p_parse_ies(ies, ies_len, &msg)) {
|
||||
p2p_dbg(p2p, "Failed to parse P2P IE for a device entry");
|
||||
p2p_parse_free(&msg);
|
||||
return;
|
||||
}
|
||||
if (msg.p2p_device_addr)
|
||||
p2p_dev_addr = msg.p2p_device_addr;
|
||||
else
|
||||
p2p_dev_addr = peer_addr;
|
||||
|
||||
dev = p2p_create_device(p2p, p2p_dev_addr);
|
||||
if (!dev) {
|
||||
p2p_parse_free(&msg);
|
||||
p2p_dbg(p2p, "Failed to add a peer P2P Device");
|
||||
return;
|
||||
}
|
||||
|
||||
dev->p2p2 = true;
|
||||
/* Reset info from old IEs */
|
||||
dev->info.reg_info = 0;
|
||||
os_memset(&dev->info.pairing_config, 0,
|
||||
sizeof(struct p2p_pairing_config));
|
||||
|
||||
os_get_reltime(&dev->last_seen);
|
||||
dev->listen_freq = freq;
|
||||
dev->oper_freq = freq;
|
||||
|
||||
if (msg.capability) {
|
||||
/*
|
||||
* P2P Client Discoverability bit is reserved in all frames
|
||||
* that use this function, so do not change its value here.
|
||||
*/
|
||||
dev->info.dev_capab &= P2P_DEV_CAPAB_CLIENT_DISCOVERABILITY;
|
||||
dev->info.dev_capab |= msg.capability[0] &
|
||||
~P2P_DEV_CAPAB_CLIENT_DISCOVERABILITY;
|
||||
dev->info.group_capab = msg.capability[1];
|
||||
}
|
||||
|
||||
if (msg.pcea_info && msg.pcea_info_len >= 2)
|
||||
p2p_process_pcea(p2p, &msg, dev);
|
||||
|
||||
if (msg.pbma_info && msg.pbma_info_len == 2)
|
||||
dev->info.pairing_config.bootstrap_methods =
|
||||
WPA_GET_LE16(msg.pbma_info);
|
||||
|
||||
if (!ether_addr_equal(peer_addr, p2p_dev_addr))
|
||||
os_memcpy(dev->interface_addr, peer_addr, ETH_ALEN);
|
||||
|
||||
p2p_dbg(p2p, "Updated device entry based on USD frame: " MACSTR
|
||||
" dev_capab=0x%x group_capab=0x%x listen_freq=%d",
|
||||
MAC2STR(dev->info.p2p_device_addr), dev->info.dev_capab,
|
||||
dev->info.group_capab, dev->listen_freq);
|
||||
|
||||
p2p->cfg->dev_found(p2p->cfg->cb_ctx, dev->info.p2p_device_addr,
|
||||
&dev->info, !(dev->flags & P2P_DEV_REPORTED_ONCE));
|
||||
|
||||
p2p_parse_free(&msg);
|
||||
}
|
||||
|
|
125
src/p2p/p2p.h
125
src/p2p/p2p.h
|
@ -12,6 +12,16 @@
|
|||
#include "common/ieee802_11_defs.h"
|
||||
#include "wps/wps.h"
|
||||
|
||||
#define DEVICE_IDENTITY_KEY_MAX_LEN 64
|
||||
#define DEVICE_IDENTITY_KEY_LEN 16
|
||||
#define DEVICE_IDENTITY_TAG_LEN 8
|
||||
#define DEVICE_IDENTITY_NONCE_LEN 8
|
||||
#define DEVICE_MAX_HASH_LEN 32
|
||||
#define DIR_STR_LEN 3
|
||||
|
||||
/* DIRA Cipher versions */
|
||||
#define DIRA_CIPHER_VERSION_128 0
|
||||
|
||||
struct weighted_pcl;
|
||||
|
||||
/* P2P ASP Setup Capability */
|
||||
|
@ -320,6 +330,50 @@ enum p2p_scan_type {
|
|||
|
||||
#define P2P_MAX_WPS_VENDOR_EXT 10
|
||||
|
||||
/**
|
||||
* struct p2p_pairing_config - P2P pairing configuration
|
||||
*/
|
||||
struct p2p_pairing_config {
|
||||
/**
|
||||
* Pairing capable
|
||||
*/
|
||||
bool pairing_capable;
|
||||
|
||||
/**
|
||||
* Enable P2P pairing setup
|
||||
*/
|
||||
bool enable_pairing_setup;
|
||||
|
||||
/**
|
||||
* Enable pairing cache to allow verification
|
||||
*/
|
||||
bool enable_pairing_cache;
|
||||
|
||||
/**
|
||||
* Enable P2P pairing verification with cached NIK/NPK
|
||||
*/
|
||||
bool enable_pairing_verification;
|
||||
|
||||
/**
|
||||
* P2P bootstrapping methods supported
|
||||
*/
|
||||
u16 bootstrap_methods;
|
||||
|
||||
/**
|
||||
* Bitmap of supported PASN types
|
||||
*/
|
||||
u8 pasn_type;
|
||||
|
||||
/* Cipher version type */
|
||||
int dik_cipher;
|
||||
|
||||
/* Buffer to hold the DevIK */
|
||||
u8 dik_data[DEVICE_IDENTITY_KEY_MAX_LEN];
|
||||
|
||||
/* Length of DevIK in octets */
|
||||
size_t dik_len;
|
||||
};
|
||||
|
||||
/**
|
||||
* struct p2p_peer_info - P2P peer information
|
||||
*/
|
||||
|
@ -411,6 +465,21 @@ struct p2p_peer_info {
|
|||
* p2ps_instance - P2PS Application Service Info
|
||||
*/
|
||||
struct wpabuf *p2ps_instance;
|
||||
|
||||
/**
|
||||
* pcea_cap_info - Capability info in PCEA
|
||||
*/
|
||||
u16 pcea_cap_info;
|
||||
|
||||
/**
|
||||
* The regulatory info encoding for operation in 6 GHz band
|
||||
*/
|
||||
u8 reg_info;
|
||||
|
||||
/**
|
||||
* p2p_pairing_config - P2P pairing configuration
|
||||
*/
|
||||
struct p2p_pairing_config pairing_config;
|
||||
};
|
||||
|
||||
enum p2p_prov_disc_status {
|
||||
|
@ -589,6 +658,33 @@ struct p2p_config {
|
|||
*/
|
||||
unsigned int passphrase_len;
|
||||
|
||||
/**
|
||||
* p2p_pairing_config - P2P pairing configuration
|
||||
*/
|
||||
struct p2p_pairing_config pairing_config;
|
||||
|
||||
/**
|
||||
* reg_info - Regulatory info encoding for operation in 6 GHz band
|
||||
*/
|
||||
u8 reg_info;
|
||||
|
||||
/**
|
||||
* dfs_owner - Enable P2P GO to act as DFS Owner
|
||||
*/
|
||||
bool dfs_owner;
|
||||
|
||||
/**
|
||||
* twt_power_mgmt - Enable TWT based power management for P2P
|
||||
*/
|
||||
bool twt_power_mgmt;
|
||||
|
||||
/**
|
||||
* comeback_after - Bootstrap request unauthorized for peer
|
||||
*
|
||||
* Ask to come back after this many TUs.
|
||||
*/
|
||||
u16 comeback_after;
|
||||
|
||||
/**
|
||||
* cb_ctx - Context to use with callback functions
|
||||
*/
|
||||
|
@ -1136,6 +1232,19 @@ struct p2p_config {
|
|||
int (*get_pref_freq_list)(void *ctx, int go,
|
||||
unsigned int *len,
|
||||
struct weighted_pcl *freq_list);
|
||||
|
||||
/**
|
||||
* register_bootstrap_comeback - Register timeout to initiate bootstrap
|
||||
* comeback request
|
||||
* @ctx: Callback context from cb_ctx
|
||||
* @addr: P2P Device Address to which comeback request is to be sent
|
||||
* @comeback_after: Time in TUs after which comeback request is sent
|
||||
*
|
||||
* This function can be used to send comeback request after given
|
||||
* timeout.
|
||||
*/
|
||||
void (*register_bootstrap_comeback)(void *ctx, const u8 *addr,
|
||||
u16 comeback_after);
|
||||
};
|
||||
|
||||
|
||||
|
@ -1319,6 +1428,10 @@ void p2p_stop_listen(struct p2p_data *p2p);
|
|||
* formation
|
||||
* @pref_freq: Preferred operating frequency in MHz or 0 (this is only used if
|
||||
* force_freq == 0)
|
||||
* @oob_pw_id: OOB password identifier
|
||||
* @p2p2: Device supports P2P2 features
|
||||
* @bootstrap: Bootstrapping method requested for P2P2 provision discovery
|
||||
* @password: P2P2 pairing password or %NULL for opportunistic method
|
||||
* Returns: 0 on success, -1 on failure
|
||||
*/
|
||||
int p2p_connect(struct p2p_data *p2p, const u8 *peer_addr,
|
||||
|
@ -1326,7 +1439,8 @@ int p2p_connect(struct p2p_data *p2p, const u8 *peer_addr,
|
|||
int go_intent, const u8 *own_interface_addr,
|
||||
unsigned int force_freq, int persistent_group,
|
||||
const u8 *force_ssid, size_t force_ssid_len,
|
||||
int pd_before_go_neg, unsigned int pref_freq, u16 oob_pw_id);
|
||||
int pd_before_go_neg, unsigned int pref_freq, u16 oob_pw_id,
|
||||
bool p2p2, u16 bootstrap, const char *password);
|
||||
|
||||
/**
|
||||
* p2p_authorize - Authorize P2P group formation (GO negotiation)
|
||||
|
@ -1344,6 +1458,9 @@ int p2p_connect(struct p2p_data *p2p, const u8 *peer_addr,
|
|||
* @force_ssid_len: Length of $force_ssid buffer
|
||||
* @pref_freq: Preferred operating frequency in MHz or 0 (this is only used if
|
||||
* force_freq == 0)
|
||||
* @oob_pw_id: OOB password identifier
|
||||
* @bootstrap: Bootstrapping method requested for P2P2 provision discovery
|
||||
* @password: P2P2 pairing password or %NULL for opportunistic method
|
||||
* Returns: 0 on success, -1 on failure
|
||||
*
|
||||
* This is like p2p_connect(), but the actual group negotiation is not
|
||||
|
@ -1354,7 +1471,8 @@ int p2p_authorize(struct p2p_data *p2p, const u8 *peer_addr,
|
|||
int go_intent, const u8 *own_interface_addr,
|
||||
unsigned int force_freq, int persistent_group,
|
||||
const u8 *force_ssid, size_t force_ssid_len,
|
||||
unsigned int pref_freq, u16 oob_pw_id);
|
||||
unsigned int pref_freq, u16 oob_pw_id, u16 bootstrap,
|
||||
const char *password);
|
||||
|
||||
/**
|
||||
* p2p_reject - Reject peer device (explicitly block connection attempts)
|
||||
|
@ -2429,5 +2547,8 @@ bool is_p2p_allow_6ghz(struct p2p_data *p2p);
|
|||
void set_p2p_allow_6ghz(struct p2p_data *p2p, bool value);
|
||||
int p2p_remove_6ghz_channels(struct weighted_pcl *pref_freq_list, int size);
|
||||
int p2p_channel_to_freq(int op_class, int channel);
|
||||
struct wpabuf * p2p_usd_elems(struct p2p_data *p2p);
|
||||
void p2p_process_usd_elems(struct p2p_data *p2p, const u8 *ies, u16 ies_len,
|
||||
const u8 *peer_addr, unsigned int freq);
|
||||
|
||||
#endif /* P2P_H */
|
||||
|
|
|
@ -55,11 +55,24 @@ u8 * p2p_buf_add_ie_hdr(struct wpabuf *buf)
|
|||
|
||||
void p2p_buf_update_ie_hdr(struct wpabuf *buf, u8 *len)
|
||||
{
|
||||
/* Update P2P IE Length */
|
||||
/* Update P2P/P2P2 IE Length */
|
||||
*len = (u8 *) wpabuf_put(buf, 0) - len - 1;
|
||||
}
|
||||
|
||||
|
||||
u8 * p2p_buf_add_p2p2_ie_hdr(struct wpabuf *buf)
|
||||
{
|
||||
u8 *len;
|
||||
|
||||
/* P2P2 IE header */
|
||||
wpabuf_put_u8(buf, WLAN_EID_VENDOR_SPECIFIC);
|
||||
len = wpabuf_put(buf, 1); /* IE length to be filled */
|
||||
wpabuf_put_be32(buf, P2P2_IE_VENDOR_TYPE);
|
||||
wpa_printf(MSG_DEBUG, "P2P: * P2P2 IE header");
|
||||
return len;
|
||||
}
|
||||
|
||||
|
||||
void p2p_buf_add_capability(struct wpabuf *buf, u8 dev_capab, u8 group_capab)
|
||||
{
|
||||
/* P2P Capability */
|
||||
|
@ -709,6 +722,111 @@ void p2p_buf_add_persistent_group_info(struct wpabuf *buf, const u8 *dev_addr,
|
|||
}
|
||||
|
||||
|
||||
void p2p_buf_add_pcea(struct wpabuf *buf, struct p2p_data *p2p)
|
||||
{
|
||||
u8 *len;
|
||||
u16 capability_info = 0;
|
||||
|
||||
/* P2P Capability Extension */
|
||||
wpabuf_put_u8(buf, P2P_ATTR_CAPABILITY_EXTENSION);
|
||||
/* Length to be filled */
|
||||
len = wpabuf_put(buf, 2);
|
||||
|
||||
if (!p2p->cfg->p2p_6ghz_disable)
|
||||
capability_info |= P2P_PCEA_6GHZ;
|
||||
|
||||
if (p2p->cfg->reg_info)
|
||||
capability_info |= P2P_PCEA_REG_INFO;
|
||||
|
||||
if (p2p->cfg->dfs_owner)
|
||||
capability_info |= P2P_PCEA_DFS_OWNER;
|
||||
|
||||
if (p2p->cfg->pairing_config.pairing_capable)
|
||||
capability_info |= P2P_PCEA_PAIRING_CAPABLE;
|
||||
|
||||
if (p2p->cfg->pairing_config.enable_pairing_setup)
|
||||
capability_info |= P2P_PCEA_PAIRING_SETUP_ENABLED;
|
||||
|
||||
if (p2p->cfg->pairing_config.enable_pairing_cache)
|
||||
capability_info |= P2P_PCEA_PMK_CACHING;
|
||||
|
||||
if (p2p->cfg->pairing_config.pasn_type)
|
||||
capability_info |= P2P_PCEA_PASN_TYPE;
|
||||
|
||||
if (p2p->cfg->twt_power_mgmt)
|
||||
capability_info |= P2P_PCEA_TWT_POWER_MGMT;
|
||||
|
||||
/* Field length is (n-1), n in octets */
|
||||
capability_info |= (2 - 1) & P2P_PCEA_LEN_MASK;
|
||||
wpabuf_put_le16(buf, capability_info);
|
||||
|
||||
if (capability_info & P2P_PCEA_REG_INFO)
|
||||
wpabuf_put_u8(buf, p2p->cfg->reg_info);
|
||||
|
||||
if (capability_info & P2P_PCEA_PASN_TYPE)
|
||||
wpabuf_put_u8(buf, p2p->cfg->pairing_config.pasn_type);
|
||||
|
||||
/* Update attribute length */
|
||||
WPA_PUT_LE16(len, (u8 *) wpabuf_put(buf, 0) - len - 2);
|
||||
|
||||
wpa_printf(MSG_DEBUG, "P2P: * Capability Extension info=0x%x",
|
||||
capability_info);
|
||||
}
|
||||
|
||||
|
||||
void p2p_buf_add_pbma(struct wpabuf *buf, u16 bootstrap, const u8 *cookie,
|
||||
size_t cookie_len, int comeback_after)
|
||||
{
|
||||
u8 *len;
|
||||
|
||||
/* P2P Pairing and Bootstrapping methods */
|
||||
wpabuf_put_u8(buf, P2P_ATTR_PAIRING_AND_BOOTSTRAPPING);
|
||||
/* Length to be filled */
|
||||
len = wpabuf_put(buf, 2);
|
||||
|
||||
if (cookie && cookie_len) {
|
||||
if (comeback_after)
|
||||
wpabuf_put_le16(buf, comeback_after);
|
||||
wpabuf_put_u8(buf, cookie_len);
|
||||
wpabuf_put_data(buf, cookie, cookie_len);
|
||||
}
|
||||
wpabuf_put_le16(buf, bootstrap);
|
||||
|
||||
/* Update attribute length */
|
||||
WPA_PUT_LE16(len, (u8 *) wpabuf_put(buf, 0) - len - 2);
|
||||
|
||||
wpa_printf(MSG_DEBUG, "P2P: * Bootstrapping method=0x%x",
|
||||
bootstrap);
|
||||
}
|
||||
|
||||
|
||||
void p2p_buf_add_dira(struct wpabuf *buf, struct p2p_data *p2p)
|
||||
{
|
||||
u8 *len;
|
||||
struct p2p_id_key *dev_ik;
|
||||
|
||||
if (!p2p->cfg->pairing_config.pairing_capable ||
|
||||
!p2p->cfg->pairing_config.enable_pairing_cache ||
|
||||
!p2p->cfg->pairing_config.enable_pairing_verification)
|
||||
return;
|
||||
|
||||
dev_ik = &p2p->pairing_info->dev_ik;
|
||||
/* P2P DIRA */
|
||||
wpabuf_put_u8(buf, P2P_ATTR_DEVICE_IDENTITY_RESOLUTION);
|
||||
/* Length to be filled */
|
||||
len = wpabuf_put(buf, 2);
|
||||
|
||||
wpabuf_put_u8(buf, dev_ik->cipher_version);
|
||||
wpabuf_put_data(buf, dev_ik->dira_nonce, dev_ik->dira_nonce_len);
|
||||
wpabuf_put_data(buf, dev_ik->dira_tag, dev_ik->dira_tag_len);
|
||||
|
||||
/* Update attribute length */
|
||||
WPA_PUT_LE16(len, (u8 *) wpabuf_put(buf, 0) - len - 2);
|
||||
|
||||
wpa_printf(MSG_DEBUG, "P2P: * DIRA");
|
||||
}
|
||||
|
||||
|
||||
static int p2p_add_wps_string(struct wpabuf *buf, enum wps_attribute attr,
|
||||
const char *val)
|
||||
{
|
||||
|
|
|
@ -244,6 +244,8 @@ int p2p_connect_send(struct p2p_data *p2p, struct p2p_device *dev)
|
|||
config_method = WPS_CONFIG_PUSHBUTTON;
|
||||
else if (dev->wps_method == WPS_P2PS)
|
||||
config_method = WPS_CONFIG_P2PS;
|
||||
else if (dev->p2p2 && dev->req_bootstrap_method)
|
||||
config_method = WPS_NOT_READY;
|
||||
else
|
||||
return -1;
|
||||
return p2p_prov_disc_req(p2p, dev->info.p2p_device_addr,
|
||||
|
|
|
@ -36,6 +36,26 @@ enum p2p_go_state {
|
|||
REMOTE_GO
|
||||
};
|
||||
|
||||
/**
|
||||
* struct bootstrap_params - P2P Device bootstrap request parameters
|
||||
*/
|
||||
struct p2p_bootstrap_params {
|
||||
/* Bootstrap method */
|
||||
u16 bootstrap_method;
|
||||
|
||||
/* Status code */
|
||||
enum p2p_status_code status;
|
||||
|
||||
/* Cookie for comeback */
|
||||
u8 cookie[50];
|
||||
|
||||
/* Cookie length */
|
||||
size_t cookie_len;
|
||||
|
||||
/* Comeback time in TUs after which receiver is requested to retry */
|
||||
int comeback_after;
|
||||
};
|
||||
|
||||
/**
|
||||
* struct p2p_device - P2P Device data (internal to P2P module)
|
||||
*/
|
||||
|
@ -150,6 +170,18 @@ struct p2p_device {
|
|||
|
||||
int sd_pending_bcast_queries;
|
||||
bool support_6ghz;
|
||||
|
||||
/* Supports P2P2 */
|
||||
bool p2p2;
|
||||
|
||||
/* Requested bootstrap method */
|
||||
u16 req_bootstrap_method;
|
||||
|
||||
/* Bootstrap parameters received from peer */
|
||||
struct p2p_bootstrap_params *bootstrap_params;
|
||||
|
||||
/* Password for P2P2 GO negotiation */
|
||||
char password[100];
|
||||
};
|
||||
|
||||
struct p2p_sd_query {
|
||||
|
@ -160,6 +192,39 @@ struct p2p_sd_query {
|
|||
struct wpabuf *tlvs;
|
||||
};
|
||||
|
||||
/* P2P Device Identity Key parameters */
|
||||
struct p2p_id_key {
|
||||
/* AKMP used for DevIK derviation */
|
||||
int akmp;
|
||||
/* Cipher version type */
|
||||
int cipher_version;
|
||||
/* Buffer to hold the DevIK */
|
||||
u8 dik_data[DEVICE_IDENTITY_KEY_MAX_LEN];
|
||||
/* Length of DevIK */
|
||||
size_t dik_len;
|
||||
/* Nonce used in DIRA attribute */
|
||||
u8 dira_nonce[DEVICE_IDENTITY_NONCE_LEN];
|
||||
/* Length of nonce */
|
||||
size_t dira_nonce_len;
|
||||
/* Tag computed for nonce using NIK */
|
||||
u8 dira_tag[DEVICE_IDENTITY_TAG_LEN];
|
||||
/* Length of tag in octets */
|
||||
size_t dira_tag_len;
|
||||
};
|
||||
|
||||
struct p2p_pairing_info {
|
||||
/* P2P device own address */
|
||||
u8 own_addr[ETH_ALEN];
|
||||
/* device capability to enable pairing setup */
|
||||
bool enable_pairing_setup;
|
||||
/* device capability to enable pairing cache */
|
||||
bool enable_pairing_cache;
|
||||
/* device supported bootstrapping */
|
||||
u16 supported_bootstrap;
|
||||
/* P2P Device Identity Key info */
|
||||
struct p2p_id_key dev_ik;
|
||||
};
|
||||
|
||||
/**
|
||||
* struct p2p_data - P2P module data (internal to P2P module)
|
||||
*/
|
||||
|
@ -554,6 +619,8 @@ struct p2p_data {
|
|||
bool p2p_6ghz_capable;
|
||||
bool include_6ghz;
|
||||
bool allow_6ghz;
|
||||
|
||||
struct p2p_pairing_info *pairing_info;
|
||||
};
|
||||
|
||||
/**
|
||||
|
@ -561,6 +628,7 @@ struct p2p_data {
|
|||
*/
|
||||
struct p2p_message {
|
||||
struct wpabuf *p2p_attributes;
|
||||
struct wpabuf *p2p2_attributes;
|
||||
struct wpabuf *wps_attributes;
|
||||
struct wpabuf *wfd_subelems;
|
||||
|
||||
|
@ -659,6 +727,12 @@ struct p2p_message {
|
|||
|
||||
const u8 *pref_freq_list;
|
||||
size_t pref_freq_list_len;
|
||||
|
||||
const u8 *pcea_info;
|
||||
size_t pcea_info_len;
|
||||
|
||||
const u8 *pbma_info;
|
||||
size_t pbma_info_len;
|
||||
};
|
||||
|
||||
|
||||
|
@ -748,6 +822,7 @@ void p2p_buf_add_action_hdr(struct wpabuf *buf, u8 subtype, u8 dialog_token);
|
|||
void p2p_buf_add_public_action_hdr(struct wpabuf *buf, u8 subtype,
|
||||
u8 dialog_token);
|
||||
u8 * p2p_buf_add_ie_hdr(struct wpabuf *buf);
|
||||
u8 * p2p_buf_add_p2p2_ie_hdr(struct wpabuf *buf);
|
||||
void p2p_buf_add_status(struct wpabuf *buf, u8 status);
|
||||
void p2p_buf_add_device_info(struct wpabuf *buf, struct p2p_data *p2p,
|
||||
struct p2p_device *peer);
|
||||
|
@ -788,6 +863,10 @@ void p2p_buf_add_feature_capability(struct wpabuf *buf, u16 len,
|
|||
const u8 *mask);
|
||||
void p2p_buf_add_persistent_group_info(struct wpabuf *buf, const u8 *dev_addr,
|
||||
const u8 *ssid, size_t ssid_len);
|
||||
void p2p_buf_add_pcea(struct wpabuf *buf, struct p2p_data *p2p);
|
||||
void p2p_buf_add_pbma(struct wpabuf *buf, u16 bootstrap, const u8 *cookie,
|
||||
size_t cookie_len, int comeback_after);
|
||||
void p2p_buf_add_dira(struct wpabuf *buf, struct p2p_data *p2p);
|
||||
int p2p_build_wps_ie(struct p2p_data *p2p, struct wpabuf *buf, int pw_id,
|
||||
int all_attr);
|
||||
void p2p_buf_add_pref_channel_list(struct wpabuf *buf,
|
||||
|
@ -826,14 +905,16 @@ void p2p_check_pref_chan(struct p2p_data *p2p, int go,
|
|||
struct p2p_device *dev, struct p2p_message *msg);
|
||||
|
||||
/* p2p_pd.c */
|
||||
void p2p_process_prov_disc_req(struct p2p_data *p2p, const u8 *sa,
|
||||
void p2p_handle_prov_disc_req(struct p2p_data *p2p, const u8 *sa,
|
||||
const u8 *data, size_t len, int rx_freq);
|
||||
void p2p_handle_prov_disc_resp(struct p2p_data *p2p, const u8 *sa,
|
||||
const u8 *data, size_t len, int rx_freq);
|
||||
void p2p_process_prov_disc_resp(struct p2p_data *p2p, const u8 *sa,
|
||||
const u8 *data, size_t len);
|
||||
int p2p_send_prov_disc_req(struct p2p_data *p2p, struct p2p_device *dev,
|
||||
int join, int force_freq);
|
||||
void p2p_reset_pending_pd(struct p2p_data *p2p);
|
||||
void p2ps_prov_free(struct p2p_data *p2p);
|
||||
void p2p_process_pcea(struct p2p_data *p2p, struct p2p_message *msg,
|
||||
struct p2p_device *dev);
|
||||
|
||||
/* p2p_invitation.c */
|
||||
void p2p_process_invitation_req(struct p2p_data *p2p, const u8 *sa,
|
||||
|
@ -899,6 +980,9 @@ void p2p_pref_channel_filter(const struct p2p_channels *a,
|
|||
const struct weighted_pcl *freq_list,
|
||||
unsigned int num_channels,
|
||||
struct p2p_channels *res, bool go);
|
||||
|
||||
void p2p_sd_query_cb(struct p2p_data *p2p, int success);
|
||||
|
||||
void p2p_dbg(struct p2p_data *p2p, const char *fmt, ...)
|
||||
PRINTF_FORMAT(2, 3);
|
||||
void p2p_info(struct p2p_data *p2p, const char *fmt, ...)
|
||||
|
|
Some files were not shown because too many files have changed in this diff Show more
Loading…
Add table
Reference in a new issue