]> git.ipfire.org Git - people/ms/network.git/blame - src/functions/functions.hostapd
wireless-ap: Automatically enable all supported ciphers
[people/ms/network.git] / src / functions / functions.hostapd
CommitLineData
0e035311
MT
1#!/bin/bash
2###############################################################################
3# #
4# IPFire.org - A linux based firewall #
5# Copyright (C) 2012 IPFire Network Development Team #
6# #
7# This program is free software: you can redistribute it and/or modify #
8# it under the terms of the GNU General Public License as published by #
9# the Free Software Foundation, either version 3 of the License, or #
10# (at your option) any later version. #
11# #
12# This program is distributed in the hope that it will be useful, #
13# but WITHOUT ANY WARRANTY; without even the implied warranty of #
14# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the #
15# GNU General Public License for more details. #
16# #
17# You should have received a copy of the GNU General Public License #
18# along with this program. If not, see <http://www.gnu.org/licenses/>. #
19# #
20###############################################################################
21
49ec20d8 22HOSTAPD_CONTROL_INTERFACE_DIR="/run/hostapd/ctrl"
0e035311 23
6c262922
MT
24HOSTAPD_SUPPORTED_MODES="802.11a 802.11a/n 802.11ac 802.11g 802.11g/n"
25
2e4e3c88
MT
26HOSTAPD_SUPPORTED_PAIRWISE_CIPHERS=(
27 "GCMP-256" # Galois/counter mode protocol with 256 bit key
28 "CCMP-256" # AES in Counter mode with CBC-MAC with 256 bit key
29 "GCMP-128" # Galois/counter mode protocol with 128 bit key
30 "CCMP-128" # AES in Counter mode with CBC-MAC with 128 bit key
31)
32
33# This must be supported by all stations on the network and therefore
34# can effectively only be CCMP
35HOSTAPD_SUPPORTED_GROUP_CIPHERS=(
36 "CCMP-128"
37)
38
1c6a4e30 39hostapd_config_write() {
0e035311 40 local device=${1}
49ec20d8 41 assert isset device
0e035311 42
49ec20d8
MT
43 local file=${2}
44 assert isset file
45
46 # Shift the device and file argument.
47 shift 2
0e035311 48
2e4e3c88
MT
49 # Device must exist
50 if ! device_exists "${device}"; then
51 error "Cannot write hostapd configuration for non-existant device: ${device}"
52 return ${EXIT_ERROR}
53 fi
54
55 # Get the phy for device
56 local phy="$(device_get_phy "${device}")"
57 assert isset phy
58
0e035311
MT
59 local broadcast_ssid
60 local channel
f9e980d9 61 local channel_bandwidth
31670741 62 local country_code="$(wireless_get_reg_domain)"
7b297fb2 63 local dfs="on"
0e035311 64 local encryption
7842c2ce 65 local environment="${WIRELESS_DEFAULT_ENVIRONMENT}"
0e035311 66 local key
34ca3936 67 local mfp="off"
0e035311
MT
68 local mode
69 local ssid
19c166f8 70 local wmm="1"
0e035311
MT
71
72 while [ $# -gt 0 ]; do
73 case "${1}" in
74 --broadcast-ssid=*)
2212045f 75 broadcast_ssid=$(cli_get_val "${1}")
0e035311
MT
76 ;;
77 --channel=*)
2212045f 78 channel=$(cli_get_val "${1}")
0e035311 79 ;;
f9e980d9
MT
80 --channel-bandwidth=*)
81 channel_bandwidth="$(cli_get_val "${1}")"
82 ;;
7b297fb2
MT
83 --dfs=*)
84 dfs="$(cli_get_val "${1}")"
85 ;;
0e035311 86 --encryption=*)
2212045f 87 encryption=$(cli_get_val "${1}")
0e035311 88 ;;
7842c2ce
MT
89 --environment=*)
90 environment="$(cli_get_val "${1}")"
91 ;;
0e035311 92 --key=*)
2212045f 93 key=$(cli_get_val "${1}")
0e035311 94 ;;
34ca3936
MT
95 --mfp=*)
96 mfp="$(cli_get_val "${1}")"
97 ;;
4cfc085f 98 --mode=*)
2212045f 99 mode=$(cli_get_val "${1}")
6c262922
MT
100
101 if ! isoneof mode ${HOSTAPD_SUPPORTED_MODES}; then
102 error "Unsupported mode: ${mode}"
103 return ${EXIT_ERROR}
104 fi
4cfc085f
MT
105 ;;
106 --ssid=*)
2212045f 107 ssid=$(cli_get_val "${1}")
4cfc085f 108 ;;
19c166f8
MT
109 --wmm=*)
110 local val="$(cli_get_val "${1}")"
111 if enabled val; then
112 wmm="1"
113 else
114 wmm="0"
115 fi
116 ;;
0e035311
MT
117 *)
118 warning_log "Ignoring unknown argument '${1}'."
119 ;;
120 esac
121 shift
122 done
123
6c262922
MT
124 # Check if mode is set
125 if ! isset mode; then
126 error "Mode is not set"
127 return ${EXIT_ERROR}
128 fi
129
0e035311
MT
130 assert isset broadcast_ssid
131 assert isbool broadcast_ssid
132
133 assert isset channel
134 assert isinteger channel
135
0e035311
MT
136 assert isset mode
137 assert isset ssid
138
139 # Check if key is set when encryption is used.
140 if isset encryption; then
141 assert isoneof encryption WPA WPA2 WPA/WPA2
142 assert isset key
143 fi
144
7842c2ce
MT
145 # Check wireless environment
146 if ! wireless_environment_is_valid "${environment}"; then
147 error "Invalid wireless environment: ${environment}"
148 return ${EXIT_ERROR}
149 fi
150
1b4aa2ca
MT
151 # With channel 0, ACS must be supported
152 if [ ${channel} -eq 0 ] && ! wireless_supports_acs "${device}"; then
153 error "ACS requested, but not supported by ${device}"
154 return ${EXIT_ERROR}
155 fi
156
f9e980d9
MT
157 # Check channel bandwidth for validity
158 if isset channel_bandwidth && ! wireless_channel_bandwidth_is_valid "${mode}" "${channel_bandwidth}"; then
159 error "Invalid channel bandwidth for ${mode}: ${channel_bandwidth}"
160 return ${EXIT_ERROR}
161 fi
162
34ca3936
MT
163 # Management Frame Proection
164 if ! isbool mfp; then
165 error "Invalid value for --mfp: ${mfp}"
166 return ${EXIT_ERROR}
167 fi
168
6c262922
MT
169 # 802.11ac/n flags
170 local ieee80211ac
171 local ieee80211n
172 local vht_caps
f9e980d9 173 local vht_oper_chwidth="0"
6c262922
MT
174 local ht_caps
175
176 local hw_mode
177 case "${mode}" in
178 802.11a)
179 hw_mode="a"
180 ;;
181
182 802.11a/n)
183 hw_mode="a"
184 ieee80211n="1"
185
186 # Fetch HT caps
187 ht_caps="$(wireless_get_ht_caps "${device}")"
188 ;;
189
190 802.11g)
191 hw_mode="g"
192 ;;
193
194 802.11g/n)
195 hw_mode="g"
196 ieee80211n="1"
197
198 # Fetch HT caps
199 ht_caps="$(wireless_get_ht_caps "${device}")"
200 ;;
201
202 802.11ac)
203 hw_mode="a"
204 ieee80211ac="1"
205 ieee80211n="1"
206
207 # Fetch VHT caps
208 vht_caps="$(wireless_get_vht_caps "${device}")"
1526e219 209
6c262922
MT
210 # Fetch HT caps
211 ht_caps="$(wireless_get_ht_caps "${device}")"
f9e980d9
MT
212
213 case "${channel_bandwidth}" in
214 80)
215 vht_oper_chwidth="1"
216 ;;
217 160)
218 vht_oper_chwidth="2"
219 ;;
220 80+80)
221 vht_oper_chwidth="3"
222 ;;
223 esac
6c262922
MT
224 ;;
225 esac
0e1c630c 226
2e4e3c88
MT
227 # Cryptography
228 local cipher
229
230 # Get all supported pairwise ciphers
231 local pairwise_ciphers=()
232 for cipher in ${HOSTAPD_SUPPORTED_PAIRWISE_CIPHERS[*]}; do
233 if phy_supports_cipher "${phy}" "${cipher}"; then
234 pairwise_ciphers+=( "$(hostapd_cipher_name "${cipher}")" )
235 fi
236 done
237
238 # Get all supported group ciphers
239 local group_ciphers=()
240 for cipher in ${HOSTAPD_SUPPORTED_GROUP_CIPHERS[*]}; do
241 if phy_supports_cipher "${phy}" "${cipher}"; then
242 group_ciphers+=( "$(hostapd_cipher_name "${cipher}")" )
243 fi
244 done
245
49ec20d8
MT
246 # Create configuration directory.
247 local config_dir=$(dirname ${file})
248 mkdir -p ${HOSTAPD_CONTROL_INTERFACE_DIR} ${config_dir} 2>/dev/null
249
250 config_header "hostapd" > ${file}
251
252 # Interface configuration
253 (
254 print "# Interface configuration"
255 print "driver=nl80211"
256 print "interface=${device}"
257 print
258 ) >> ${file}
259
260 # Wireless configuration
0e035311
MT
261 local ignore_broadcast_ssid
262 if enabled broadcast_ssid; then
263 ignore_broadcast_ssid="0"
264 else
265 ignore_broadcast_ssid="1"
266 fi
267
49ec20d8 268 (
b6ec3dd6
MT
269 # Advertise country code and maximum transmission power
270 print "ieee80211d=1"
7842c2ce
MT
271 print "country_code=${country_code}"
272
273 # Wireless Environment
274 case "${environment}" in
275 indoor)
276 print "country3=0x49"
277 country3
278 ;;
279 outdoor)
280 print "country3=0x4f"
281 ;;
282 indoor+outdoor)
283 print "country3=0x20"
284 ;;
285 esac
b6ec3dd6 286
96026172
MT
287 # Always advertise TPC
288 print "local_pwr_constraint=3"
289 print "spectrum_mgmt_required=1"
290
6c262922 291 # Enable Radar Detection
dc6d97fb 292 if enabled dfs && wireless_supports_dfs "${device}"; then
7b297fb2
MT
293 print "ieee80211h=1"
294 else
295 print "ieee80211h=0"
296 fi
6c262922
MT
297
298 print # empty line
299
49ec20d8 300 print "# Wireless configuration"
6c262922
MT
301 print "hw_mode=${hw_mode}"
302
303 if isset ieee80211ac; then
304 print "ieee80211ac=${ieee80211ac}"
305 fi
306
307 if isset ieee80211n; then
308 print "ieee80211n=${ieee80211n}"
309 fi
310
49ec20d8 311 print "channel=${channel}"
49ec20d8 312 print "ignore_broadcast_ssid=${ignore_broadcast_ssid}"
0e035311 313
4873f329
MT
314 print "ssid2=\"${ssid}\""
315 print "utf8_ssid=1"
0e035311 316
4d4bca7e
MT
317 # Kick stations that are too far away
318 print "disassoc_low_ack=1"
319
fcdbed86 320 # WMM & WMM-PS Unscheduled Automatic Power Save Delivery
19c166f8 321 print "wmm_enabled=${wmm}"
fcdbed86
MT
322 print "uapsd_advertisement_enabled=1"
323
324 # Low Priority / AC_BK = Background
325 print "wmm_ac_bk_cwmin=4"
326 print "wmm_ac_bk_cwmax=10"
327 print "wmm_ac_bk_aifs=7"
328 print "wmm_ac_bk_txop_limit=0"
329 print "wmm_ac_bk_acm=0"
330 print "tx_queue_data3_aifs=7"
331 print "tx_queue_data3_cwmin=15"
332 print "tx_queue_data3_cwmax=1023"
333 print "tx_queue_data3_burst=0"
334
335 # Normal Priority / AC_BE = Best Effort
336 print "wmm_ac_be_aifs=3"
337 print "wmm_ac_be_cwmin=4"
338 print "wmm_ac_be_cwmax=10"
339 print "wmm_ac_be_txop_limit=0"
340 print "wmm_ac_be_acm=0"
341 print "tx_queue_data2_aifs=3"
342 print "tx_queue_data2_cwmin=15"
343 print "tx_queue_data2_cwmax=63"
344 print "tx_queue_data2_burst=0"
345
346 # High Priority / AC_VI = Video
347 print "wmm_ac_vi_aifs=2"
348 print "wmm_ac_vi_cwmin=3"
349 print "wmm_ac_vi_cwmax=4"
350 print "wmm_ac_vi_txop_limit=94"
351 print "wmm_ac_vi_acm=0"
352 print "tx_queue_data1_aifs=1"
353 print "tx_queue_data1_cwmin=7"
354 print "tx_queue_data1_cwmax=15"
355 print "tx_queue_data1_burst=3.0"
356
357 # Highest Priority / AC_VO = Voice
358 print "wmm_ac_vo_aifs=2"
359 print "wmm_ac_vo_cwmin=2"
360 print "wmm_ac_vo_cwmax=3"
361 print "wmm_ac_vo_txop_limit=47"
362 print "wmm_ac_vo_acm=0"
363 print "tx_queue_data0_aifs=1"
364 print "tx_queue_data0_cwmin=3"
365 print "tx_queue_data0_cwmax=7"
366 print "tx_queue_data0_burst=1.5"
19c166f8 367
1526e219
MT
368 # Enable VHT caps
369 if isset vht_caps; then
370 print "vht_capab=${vht_caps}"
371 fi
372
0e1c630c
MT
373 # Enable HT caps
374 print "ht_capab=${ht_caps}"
375
f9e980d9
MT
376 # Wider Channels
377 print "vht_oper_chwidth=${vht_oper_chwidth}"
378
49ec20d8 379 print
34ca3936
MT
380
381 # 802.11w - Management Frame Protection (MFP)
382 if enabled mfp; then
383 print "ieee80211w=2" # required
384 else
385 print "ieee80211w=0"
386 fi
49ec20d8 387 ) >> ${file}
0e035311 388
49ec20d8
MT
389 # Control interface.
390 (
391 print "# Control interface"
392 print "ctrl_interface=${HOSTAPD_CONTROL_INTERFACE_DIR}"
393 print "ctrl_interface_group=0"
394 print
395 ) >> ${file}
0e035311 396
49ec20d8 397 # Encryption settings
0e035311
MT
398 if isset encryption; then
399 local encryption_mode=0
400 case "${encryption}" in
401 WPA)
402 encryption_mode=1
403 ;;
404 WPA2)
405 encryption_mode=2
406 ;;
407 WPA/WPA2)
408 encryption_mode=3
409 ;;
410 esac
411
49ec20d8
MT
412 (
413 print "# Encryption settings"
414 print "wpa=${encryption_mode}"
415 print "wpa_passphrase=${key}"
416 print "wpa_key_mgmt=WPA-PSK"
2e4e3c88
MT
417 print "wpa_pairwise=${pairwise_ciphers[*]}"
418 print "rsn_pairwise=${pairwise_ciphers[*]}"
419 print "group_cipher=${group_ciphers[*]}"
49ec20d8
MT
420 print
421 ) >> ${file}
0e035311
MT
422 fi
423
7c91c167
MT
424 # Log configuration file
425 file_to_log DEBUG "${file}"
426
0e035311
MT
427 return ${EXIT_OK}
428}
429
1c6a4e30 430hostapd_start() {
0e035311 431 local device=${1}
0e035311
MT
432 assert isset device
433
0e035311
MT
434 service_start "hostapd@${device}.service"
435 local ret=$?
436
49ec20d8
MT
437 if [ ${ret} -eq ${EXIT_OK} ]; then
438 log DEBUG "hostapd has been successfully started on '${device}'"
439 else
440 log ERROR "Could not start hostapd on '${device}': ${ret}"
441 return ${EXIT_ERROR}
442 fi
443
444 return ${EXIT_OK}
0e035311
MT
445}
446
1c6a4e30 447hostapd_stop() {
0e035311
MT
448 local device=${1}
449 assert isset device
450
451 service_stop "hostapd@${device}.service"
0e035311 452}
2e4e3c88
MT
453
454hostapd_cipher_name() {
455 local cipher="${1}"
456
457 case "${cipher}" in
458 CCMP-128)
459 print "CCMP"
460 ;;
461
462 GCMP-128)
463 print "GCMP"
464 ;;
465
466 *)
467 print "${cipher}"
468 ;;
469 esac
470}