]> git.ipfire.org Git - people/stevee/network.git/blob - src/hooks/zones/pppoe
network fix parameter passing when using ""
[people/stevee/network.git] / src / hooks / zones / pppoe
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 . /usr/lib/network/header-zone
23
24 HOOK_SETTINGS="HOOK ACCESS_CONCENTRATOR AUTH USERNAME PASSWORD"
25 HOOK_SETTINGS="${HOOK_SETTINGS} SERVICE_NAME MTU IPV6 PREFIX_DELEGATION"
26
27 # User credentials for the dialin.
28 USERNAME=""
29 PASSWORD=""
30
31 # Set the authentication mechanism.
32 AUTH=
33
34 # Access Concentrator.
35 ACCESS_CONCENTRATOR=""
36
37 # Service name.
38 SERVICE_NAME=""
39
40 # Maximum Transmission Unit.
41 MTU=
42
43 # This hook can work with all authentication methods supported by pppd.
44 PPPOE_SUPPORTED_AUTH_METHODS="${PPP_SUPPORTED_AUTH_METHODS}"
45 PPPOE_PLUGIN="rp-pppoe.so"
46
47 # Request an IPv6 address.
48 IPV6="true"
49
50 # Use IPv6 prefix delegation.
51 PREFIX_DELEGATION="true"
52
53 hook_check_settings() {
54 assert isset USERNAME
55 assert isset PASSWORD
56
57 isset AUTH && assert isoneof AUTH ${PPPOE_SUPPORTED_AUTH_METHODS}
58
59 assert isset IPV6
60 assert isset PREFIX_DELEGATION
61 }
62
63 hook_parse_cmdline() {
64 while [ $# -gt 0 ]; do
65 case "${1}" in
66 --access-concentrator=*)
67 ACCESS_CONCENTRATOR=$(cli_get_val "${1}")
68 ;;
69 --auth=*)
70 AUTH=$(cli_get_val "${1}")
71 ;;
72 --ipv6=*)
73 local value="$(cli_get_val "${1}")"
74 if enabled value; then
75 IPV6="true"
76 else
77 IPV6="false"
78 fi
79 ;;
80 --mtu=*)
81 MTU=$(cli_get_val "${1}")
82 ;;
83 --password=*)
84 PASSWORD=$(cli_get_val "${1}")
85 ;;
86 --prefix-delegation=*)
87 PREFIX_DELEGATION="$(cli_get_bool "${1}")"
88 ;;
89 --service-name=*)
90 SERVICE_NAME=$(cli_get_val "${1}")
91 ;;
92 --username=*)
93 USERNAME=$(cli_get_val "${1}")
94 ;;
95 *)
96 warning "Unknown argument: ${1}" >&2
97 ;;
98 esac
99 shift
100 done
101 }
102
103 hook_up() {
104 local zone=${1}
105 assert isset zone
106
107 # If this zone's port is not set, we will return
108 # with EXIT_OK so that this zone will remain active,
109 # but we cannot start pppd.
110 local port=$(__hook_get_port "${zone}")
111 if ! isset port || ! port_exists "${port}"; then
112 log WARNING "Could not bring up zone '${zone}' because no port is attached"
113 exit ${EXIT_OK}
114 fi
115
116 zone_settings_read "${zone}"
117
118 # Load the pppoe kernel module
119 module_load "pppoe"
120
121 # Bring up the port.
122 port_up "${port}"
123
124 # Start the ppp daemon.
125 pppd_start ${zone}
126
127 exit ${EXIT_OK}
128 }
129
130 hook_down() {
131 local zone=${1}
132 assert isset zone
133
134 zone_settings_read "${zone}"
135
136 # Stop the ppp daemon.
137 pppd_stop ${zone}
138
139 # Bring down the port.
140 local port=$(__hook_get_port "${zone}")
141 if isset port; then
142 log DEBUG "Bringing down port '${port}'"
143 port_down "${port}"
144 fi
145
146 exit ${EXIT_OK}
147 }
148
149 hook_hotplug() {
150 local zone="${1}"
151
152 case "$(hotplug_action)" in
153 add)
154 if hotplug_event_interface_is_port_of_zone "${zone}"; then
155 # Bring up the zone if it is enabled but not active, yet.
156 zone_start_auto "${zone}"
157
158 exit ${EXIT_OK}
159 fi
160 ;;
161 remove)
162 # PPPoE cannot work if the ethernet device has been removed
163 if hotplug_event_interface_is_port_of_zone "${zone}"; then
164 if zone_is_active "${zone}"; then
165 zone_stop "${zone}"
166 fi
167
168 exit ${EXIT_OK}
169 fi
170 ;;
171 esac
172
173 exit ${EXIT_NOT_HANDLED}
174 }
175
176 hook_discover() {
177 local device=${1}
178
179 # This obviously only works on ethernet (or compatible) devices
180 if ! device_is_ethernet_compatible "${device}"; then
181 exit ${EXIT_ERROR}
182 fi
183
184 local output
185 output=$(pppoe-discovery -I ${device} -U $(uuid) 2>&1)
186
187 # Exit if there was not output
188 [ -z "${output}" ] && exit ${DISCOVER_ERROR}
189
190 # Exit if PADI timed out
191 grep -q "Timeout" <<<${output} && exit ${DISCOVER_ERROR}
192
193 local ac
194 while read line; do
195 case "${line}" in
196 Access-Concentrator:*)
197 ac="${line#Access-Concentrator: }"
198 ;;
199 esac
200 done <<<"${output}"
201
202 echo "ACCESS_CONCENTRATOR=\"$ac\""
203
204 exit ${DISCOVER_OK}
205 }
206
207 hook_status() {
208 local zone=${1}
209 assert isset zone
210
211 cli_device_headline ${zone}
212
213 zone_settings_read "${zone}"
214
215 cli_headline 2 "Configuration"
216 cli_print_fmt1 2 "Username" "${USERNAME}"
217 cli_print_fmt1 2 "Password" "<hidden>"
218
219 local port=$(__hook_get_port "${zone}")
220 if isset port; then
221 cli_print_fmt1 2 "Port" "${port}"
222 fi
223 cli_space
224
225 # Exit if zone is down
226 if ! zone_is_up ${zone}; then
227 echo # Empty line
228 exit ${EXIT_ERROR}
229 fi
230
231 # XXX display time since connection started
232
233 cli_headline 2 "Point-to-Point-over-Ethernet protocol"
234 cli_print_fmt1 2 "MAC-Remote" "$(db_get "${zone}/remote-address")"
235 cli_space
236
237 local proto
238 for proto in ${IP_SUPPORTED_PROTOCOLS}; do
239 db_exists "${zone}/${proto}" || continue
240
241 local headline
242 case "${proto}" in
243 ipv6)
244 headline="Internet Protocol Version 6"
245 ;;
246 ipv4)
247 headline="Internet Protocol Version 4"
248 ;;
249 *)
250 headline="Unkown protocol"
251 ;;
252 esac
253 cli_headline 3 "${headline}"
254
255 cli_print_fmt1 3 "IP address" "$(db_get "${zone}/${proto}/local-ip-address")"
256 cli_print_fmt1 3 "Gateway" "$(db_get "${zone}/${proto}/remote-ip-address")"
257 cli_print_fmt1 3 "DNS servers" "$(db_get "${zone}/${proto}/domain-name-servers")"
258 cli_space
259 done
260
261 exit ${EXIT_OK}
262 }
263
264 hook_ppp_write_config() {
265 local zone=${1}
266 assert isset zone
267
268 local file=${2}
269 assert isset file
270
271 # Read in the configuration files.
272 zone_settings_read "${zone}"
273
274 # A port has to be assigned for this action
275 local port=$(__hook_get_port "${zone}")
276 if ! isset port; then
277 error "No port assigned to pppoe hook of zone '${zone}'"
278 exit ${EXIT_ERROR}
279 fi
280
281 # Prepare the command line options for the pppoe plugin.
282 local plugin_options
283
284 # Add the access concentrator (if any).
285 if isset ACCESS_CONCENTRATOR; then
286 plugin_options="${plugin_options} rp_pppoe_ac '${ACCESS_CONCENTRATOR}'"
287 fi
288
289 # Add the service name (if any).
290 if isset SERVICE_NAME; then
291 plugin_options="${plugin_options} rp_pppoe_service '${SERVICE_NAME}'"
292 fi
293
294 # The last argument must be the interface.
295 plugin_options="${plugin_options} ${port}"
296
297 pppd_write_config ${file} \
298 --interface="${zone}" \
299 --username="${USERNAME}" \
300 --password="${PASSWORD}" \
301 --mtu="${MTU}" \
302 --auth="${AUTH}" \
303 --ipv6="${IPV6}" \
304 \
305 --plugin="${PPPOE_PLUGIN}" \
306 --plugin-options="${plugin_options}"
307
308 exit ${EXIT_OK}
309 }
310
311 __hook_get_port() {
312 local zone="${1}"
313
314 local port
315 for port in $(zone_get_ports "${zone}"); do
316 echo "${port}"
317 return ${EXIT_OK}
318 done
319
320 return ${EXIT_ERROR}
321 }
322
323 hook_port_attach() {
324 # Excepting at least two arguments here
325 assert [ $# -ge 2 ]
326
327 local zone="${1}"
328 local port="${2}"
329 shift 2
330
331 # PPPoE can only use one port
332 local ports_num="$(zone_get_ports_num "${zone}")"
333 if [ ${ports_num} -ge 1 ]; then
334 local ports="$(zone_get_ports "${zone}")"
335 error "The pppoe zone hook only supports assigning one port"
336 error " port '${ports}' has already been assigned to zone '${zone}'"
337 return ${EXIT_ERROR}
338 fi
339
340 if ! zone_port_settings_write "${zone}" "${port}"; then
341 exit ${EXIT_ERROR}
342 fi
343
344 exit ${EXIT_OK}
345 }
346
347 hook_port_detach() {
348 assert [ $# -eq 2 ]
349
350 local zone="${1}"
351 local port="${2}"
352
353 # Shut down the entire zone here, because it cannot
354 # run without a port any way and removing the port would
355 # create a hotplug event which will be processed after the
356 # port has already been detached...
357 zone_stop "${zone}"
358
359 if ! zone_port_settings_remove "${zone}" "${port}"; then
360 exit ${EXIT_ERROR}
361 fi
362
363 exit ${EXIT_OK}
364 }
365
366 hook_ppp_ipv6_up() {
367 local zone="${1}"
368
369 ppp_common_ipv6_up "${zone}"
370
371 # Read configuration
372 zone_settings_read "${zone}"
373
374 if enabled PREFIX_DELEGATION; then
375 dhclient_start "${zone}" ipv6
376 fi
377
378 exit ${EXIT_OK}
379 }
380
381 hook_ppp_ipv6_down() {
382 local zone="${1}"
383
384 ppp_common_ipv6_down "${zone}"
385
386 # Read configuration
387 zone_settings_read "${zone}"
388
389 if enabled PREFIX_DELEGATION; then
390 dhclient_stop "${zone}" ipv6
391 fi
392
393 exit ${EXIT_OK}
394 }