]> git.ipfire.org Git - people/ms/network.git/blob - src/functions/functions.hostapd
wireless-ap: Remove support for WPA
[people/ms/network.git] / src / functions / functions.hostapd
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
22 HOSTAPD_CONTROL_INTERFACE_DIR="/run/hostapd/ctrl"
23
24 HOSTAPD_SUPPORTED_MODES="802.11a 802.11a/n 802.11ac 802.11g 802.11g/n"
25
26 HOSTAPD_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
35 HOSTAPD_SUPPORTED_GROUP_CIPHERS=(
36 "CCMP-128"
37 )
38
39 hostapd_config_write() {
40 local device=${1}
41 assert isset device
42
43 local file=${2}
44 assert isset file
45
46 # Shift the device and file argument.
47 shift 2
48
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
59 local broadcast_ssid
60 local channel
61 local channel_bandwidth
62 local country_code="$(wireless_get_reg_domain)"
63 local dfs="on"
64 local encryption
65 local environment="${WIRELESS_DEFAULT_ENVIRONMENT}"
66 local key
67 local mfp="off"
68 local mode
69 local ssid
70 local wmm="1"
71
72 while [ $# -gt 0 ]; do
73 case "${1}" in
74 --broadcast-ssid=*)
75 broadcast_ssid=$(cli_get_val "${1}")
76 ;;
77 --channel=*)
78 channel=$(cli_get_val "${1}")
79 ;;
80 --channel-bandwidth=*)
81 channel_bandwidth="$(cli_get_val "${1}")"
82 ;;
83 --dfs=*)
84 dfs="$(cli_get_val "${1}")"
85 ;;
86 --encryption=*)
87 encryption=$(cli_get_val "${1}")
88 ;;
89 --environment=*)
90 environment="$(cli_get_val "${1}")"
91 ;;
92 --key=*)
93 key=$(cli_get_val "${1}")
94 ;;
95 --mfp=*)
96 mfp="$(cli_get_val "${1}")"
97 ;;
98 --mode=*)
99 mode=$(cli_get_val "${1}")
100
101 if ! isoneof mode ${HOSTAPD_SUPPORTED_MODES}; then
102 error "Unsupported mode: ${mode}"
103 return ${EXIT_ERROR}
104 fi
105 ;;
106 --ssid=*)
107 ssid=$(cli_get_val "${1}")
108 ;;
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 ;;
117 *)
118 warning_log "Ignoring unknown argument '${1}'."
119 ;;
120 esac
121 shift
122 done
123
124 # Check if mode is set
125 if ! isset mode; then
126 error "Mode is not set"
127 return ${EXIT_ERROR}
128 fi
129
130 assert isset broadcast_ssid
131 assert isbool broadcast_ssid
132
133 assert isset channel
134 assert isinteger channel
135
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 WPA2
142 assert isset key
143 fi
144
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
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
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
163 # Management Frame Proection
164 if ! isbool mfp; then
165 error "Invalid value for --mfp: ${mfp}"
166 return ${EXIT_ERROR}
167 fi
168
169 # 802.11ac/n flags
170 local ieee80211ac
171 local ieee80211n
172 local vht_caps
173 local vht_oper_chwidth="0"
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}")"
209
210 # Fetch HT caps
211 ht_caps="$(wireless_get_ht_caps "${device}")"
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
224 ;;
225 esac
226
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
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
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
268 (
269 # Advertise country code and maximum transmission power
270 print "ieee80211d=1"
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
286
287 # Always advertise TPC
288 print "local_pwr_constraint=3"
289 print "spectrum_mgmt_required=1"
290
291 # Enable Radar Detection
292 if enabled dfs && wireless_supports_dfs "${device}"; then
293 print "ieee80211h=1"
294 else
295 print "ieee80211h=0"
296 fi
297
298 print # empty line
299
300 print "# Wireless configuration"
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
311 print "channel=${channel}"
312 print "ignore_broadcast_ssid=${ignore_broadcast_ssid}"
313
314 print "ssid2=\"${ssid}\""
315 print "utf8_ssid=1"
316
317 # Kick stations that are too far away
318 print "disassoc_low_ack=1"
319
320 # WMM & WMM-PS Unscheduled Automatic Power Save Delivery
321 print "wmm_enabled=${wmm}"
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"
367
368 # Enable VHT caps
369 if isset vht_caps; then
370 print "vht_capab=${vht_caps}"
371 fi
372
373 # Enable HT caps
374 print "ht_capab=${ht_caps}"
375
376 # Wider Channels
377 print "vht_oper_chwidth=${vht_oper_chwidth}"
378
379 print
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
387 ) >> ${file}
388
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}
396
397 # Encryption settings
398 if isset encryption; then
399 local encryption_mode=0
400 case "${encryption}" in
401 WPA2)
402 encryption_mode=2
403 ;;
404 esac
405
406 (
407 print "# Encryption settings"
408 print "wpa=${encryption_mode}"
409 print "wpa_passphrase=${key}"
410 print "wpa_key_mgmt=WPA-PSK-SHA256 WPA-PSK"
411 print "wpa_pairwise=${pairwise_ciphers[*]}"
412 print "rsn_pairwise=${pairwise_ciphers[*]}"
413 print "group_cipher=${group_ciphers[*]}"
414 print
415 ) >> ${file}
416 fi
417
418 # Log configuration file
419 file_to_log DEBUG "${file}"
420
421 return ${EXIT_OK}
422 }
423
424 hostapd_start() {
425 local device=${1}
426 assert isset device
427
428 service_start "hostapd@${device}.service"
429 local ret=$?
430
431 if [ ${ret} -eq ${EXIT_OK} ]; then
432 log DEBUG "hostapd has been successfully started on '${device}'"
433 else
434 log ERROR "Could not start hostapd on '${device}': ${ret}"
435 return ${EXIT_ERROR}
436 fi
437
438 return ${EXIT_OK}
439 }
440
441 hostapd_stop() {
442 local device=${1}
443 assert isset device
444
445 service_stop "hostapd@${device}.service"
446 }
447
448 hostapd_cipher_name() {
449 local cipher="${1}"
450
451 case "${cipher}" in
452 CCMP-128)
453 print "CCMP"
454 ;;
455
456 GCMP-128)
457 print "GCMP"
458 ;;
459
460 *)
461 print "${cipher}"
462 ;;
463 esac
464 }