wireless-ap: Allow setting the wireless environment (indoor/outdoor)
[people/ms/network.git] / src / hooks / ports / wireless-ap
1 #!/bin/bash
2 ###############################################################################
3 #                                                                             #
4 # IPFire.org - A linux based firewall                                         #
5 # Copyright (C) 2010  Michael Tremer & Christian Schmidt                      #
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 . /usr/lib/network/header-port
23
24 HOOK_PORT_PATTERN="${PORT_PATTERN_ACCESSPOINT}"
25
26 HOOK_SETTINGS="ADDRESS BROADCAST_SSID CHANNEL CHANNEL_BANDWIDTH DFS MODE PHY"
27 HOOK_SETTINGS="${HOOK_SETTINGS} ENCRYPTION ENVIRONMENT KEY SSID"
28
29 ADDRESS=$(mac_generate)
30 BROADCAST_SSID=on
31 CHANNEL=
32 CHANNEL_BANDWIDTH=
33 ENCRYPTION=""
34 KEY=""
35 SSID=
36
37 # Perform radar detection by default when possible
38 DFS="on"
39
40 ENVIRONMENT="${WIRELESS_DEFAULT_ENVIRONMENT}"
41
42 hook_check_settings() {
43         assert isset ADDRESS
44         assert ismac ADDRESS
45         assert isset BROADCAST_SSID
46         assert isbool BROADCAST_SSID
47         assert isset CHANNEL
48         assert isbool DFS
49         assert isset MODE
50         assert isoneof MODE ${HOSTAPD_SUPPORTED_MODES}
51         assert isset PHY
52         assert ismac PHY
53         assert isset SSID
54
55         if isset ENCRYPTION; then
56                 assert isoneof ENCRYPTION WPA WPA2 WPA/WPA2
57
58                 assert isset KEY
59                 assert [ ${#KEY} -ge 8 ]
60                 assert [ ${#KEY} -le 63 ]
61         fi
62
63         assert wireless_environment_is_valid "${ENVIRONMENT}"
64 }
65
66 hook_parse_cmdline() {
67         while [ $# -gt 0 ]; do
68                 case "${1}" in
69                         --broadcast-ssid=*)
70                                 BROADCAST_SSID=$(cli_get_val "${1}")
71                                 ;;
72                         --channel=*)
73                                 CHANNEL=$(cli_get_val "${1}")
74                                 ;;
75                         --channel-bandwidth=*)
76                                 CHANNEL_BANDWIDTH="$(cli_get_val "${1}")"
77                                 ;;
78                         --dfs=*)
79                                 DFS="$(cli_get_val "${1}")"
80
81                                 if enabled DFS; then
82                                         DFS="on"
83                                 elif disabled DFS; then
84                                         DFS="off"
85                                 else
86                                         error "Invalid value for DFS: ${DFS}"
87                                         return ${EXIT_ERROR}
88                                 fi
89                                 ;;
90                         --encryption=*)
91                                 ENCRYPTION=$(cli_get_val "${1}")
92                                 ;;
93                         --environment=*)
94                                 ENVIRONMENT="$(cli_get_val "${1}")"
95
96                                 if ! wireless_environment_is_valid "${ENVIRONMENT}"; then
97                                         error "Invalid wireless environment: ${ENVIRONMENT}"
98                                         return ${EXIT_ERROR}
99                                 fi
100                                 ;;
101                         --key=*)
102                                 KEY=$(cli_get_val "${1}")
103                                 ;;
104                         --mac=*)
105                                 ADDRESS=$(cli_get_val "${1}")
106                                 ;;
107                         --mode=*)
108                                 MODE=$(cli_get_val "${1}")
109
110                                 if ! isoneof MODE ${HOSTAPD_SUPPORTED_MODES}; then
111                                         error "Unsupported mode: ${MODE}"
112                                         error "Mode must be one of ${HOSTAPD_SUPPORTED_MODES}"
113                                         return ${EXIT_ERROR}
114                                 fi
115                                 ;;
116                         --phy=*)
117                                 PHY=$(cli_get_val "${1}")
118                                 ;;
119                         --ssid=*)
120                                 SSID=$(cli_get_val "${1}")
121                                 ;;
122                         *)
123                                 warning "Ignoring unknown argument '${1}'"
124                                 ;;
125                 esac
126                 shift
127         done
128
129         # Generate a random MAC address if none is set
130         if ! isset ADDRESS; then
131                 ADDRESS="$(mac_generate)"
132         fi
133
134         # MODE must be set
135         if ! isset MODE; then
136                 error "--mode is not set"
137                 return ${EXIT_ERROR}
138         fi
139
140         # Automatically enable ACS if no channel is set and ACS is available
141         if ! isset CHANNEL && phy_supports_acs "${PHY}"; then
142                 CHANNEL="0"
143
144                 log INFO "Automatic Channel Selection (ACS) enabled"
145         fi
146
147         # Channel bandwidth must match the mode
148         if isset CHANNEL_BANDWIDTH && ! wireless_channel_bandwidth_is_valid "${MODE}" "${CHANNEL_BANDWIDTH}"; then
149                 error "Channel Bandwidth '${CHANNEL_BANDWIDTH}' is not supported for ${MODE}"
150                 return ${EXIT_ERROR}
151         fi
152
153         # Save address of phy do identify it again
154         PHY=$(phy_get ${PHY})
155         PHY=$(phy_get_address ${PHY})
156 }
157
158 hook_edit() {
159         local port=${1}
160         assert isset port
161
162         if ! hook_default_edit "$@"; then
163                 return ${EXIT_ERROR}
164         fi
165
166         # To apply all changes, we need to restart the port
167         port_restart "${port}"
168 }
169
170 hook_create() {
171         local port="${1}"
172         assert isset port
173
174         device_exists "${port}" && exit ${EXIT_OK}
175
176         port_settings_read "${port}" ${HOOK_SETTINGS}
177
178         # Check if the PHY is present.
179         local phy=$(phy_get ${PHY})
180         if ! isset phy; then
181                 log DEBUG "phy '${PHY}' is not present"
182                 exit ${EXIT_ERROR}
183         fi
184
185         # Create the wireless device
186         wireless_create "${port}" \
187                 --phy="${phy}" \
188                 --type="ap" \
189                 --address="${ADDRESS}"
190
191         exit ${EXIT_OK}
192 }
193
194 hook_remove() {
195         local port="${1}"
196         assert isset port
197
198         # Remove the device if present
199         if device_exists "${port}"; then
200                 wireless_remove "${port}"
201         fi
202
203         exit ${EXIT_OK}
204 }
205
206 hook_up() {
207         local port="${1}"
208         assert isset port
209
210         # The port must already exist before
211         # hostapd is started. Otherwise it will
212         # fail horribly over and over again.
213         assert device_exists "${port}"
214
215         hostapd_start "${port}"
216 }
217
218 hook_down() {
219         local port="${1}"
220         assert isset port
221
222         hostapd_stop "${port}"
223 }
224
225 hook_hotplug() {
226         local port="${1}"
227         assert isset port
228
229         case "$(hotplug_action)" in
230                 add)
231                         # Create the port when the phy is plugged in
232                         if hotplug_event_port_uses_phy "${port}"; then
233                                 hook_create "${port}"
234                         fi
235                         ;;
236
237                 remove)
238                         # Stop hostapd
239                         if hotplug_event_port_is_interface "${port}"; then
240                                 hostapd_stop "${port}"
241
242                                 exit ${EXIT_OK}
243                         fi
244                         ;;
245         esac
246
247         exit ${EXIT_NOT_HANDLED}
248 }