a72a2a85c034b53402d31ba8bb39b5d7ea783f38
[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 # 1492 is a very common value for that.
42 MTU=1492
43
44 # This hook can work with all authentication methods supported by pppd.
45 PPPOE_SUPPORTED_AUTH_METHODS="${PPP_SUPPORTED_AUTH_METHODS}"
46 PPPOE_PLUGIN="rp-pppoe.so"
47
48 # Request an IPv6 address.
49 IPV6="true"
50
51 # Use IPv6 prefix delegation.
52 PREFIX_DELEGATION="false"
53
54 function hook_check() {
55         assert isset USERNAME
56         assert isset PASSWORD
57
58         isset AUTH && assert isoneof AUTH ${PPPOE_SUPPORTED_AUTH_METHODS}
59
60         assert isset IPV6
61         assert isset PREFIX_DELEGATION
62 }
63
64 function hook_parse_cmdline() {
65         while [ $# -gt 0 ]; do
66                 case "${1}" in
67                         --access-concentrator=*)
68                                 ACCESS_CONCENTRATOR=$(cli_get_val ${1})
69                                 ;;
70                         --auth=*)
71                                 AUTH=$(cli_get_val ${1})
72                                 ;;
73                         --ipv6=*)
74                                 local value="$(cli_get_val "${1}")"
75                                 if enabled value; then
76                                         IPV6="true"
77                                 else
78                                         IPV6="false"
79                                 fi
80                                 ;;
81                         --mtu=*)
82                                 MTU=$(cli_get_val ${1})
83                                 ;;
84                         --password=*)
85                                 PASSWORD=$(cli_get_val ${1})
86                                 ;;
87                         --prefix-delegation=*)
88                                 PREFIX_DELEGATION="$(cli_get_bool "${1}")"
89                                 ;;
90                         --service-name=*)
91                                 SERVICE_NAME=$(cli_get_val ${1})
92                                 ;;
93                         --username=*)
94                                 USERNAME=$(cli_get_val ${1})
95                                 ;;
96                         *)
97                                 warning "Unknown argument: ${1}" >&2
98                                 ;;
99                 esac
100                 shift
101         done
102 }
103
104 function hook_up() {
105         local zone=${1}
106         assert isset zone
107
108         zone_settings_read "${zone}" ${HOOK_SETTINGS}
109
110         # Bring up the port.
111         local port=$(__hook_get_port "${zone}")
112         port_up "${port}"
113
114         # Start the ppp daemon.
115         pppd_start ${zone}
116
117         exit ${EXIT_OK}
118 }
119
120 function hook_down() {
121         local zone=${1}
122         assert isset zone
123
124         zone_settings_read "${zone}" ${HOOK_SETTINGS}
125
126         # Stop the ppp daemon.
127         pppd_stop ${zone}
128
129         # Bring down the port.
130         log DEBUG "Bringing down port '${PORT}'."
131         port_down ${PORT}
132
133         exit ${EXIT_OK}
134 }
135
136 function hook_discover() {
137         local device=${1}
138
139         if [ "$(device_get_type ${device})" != "real" ]; then
140                 exit ${EXIT_ERROR}
141         fi
142
143         local output
144         output=$(pppoe-discovery -I ${device} -U $(uuid) 2>&1)
145
146         # Exit if there was not output
147         [ -z "${output}" ] && exit ${DISCOVER_ERROR}
148
149         # Exit if PADI timed out
150         grep -q "Timeout" <<<${output} && exit ${DISCOVER_ERROR}
151
152         local ac
153         while read line; do
154                 case "${line}" in
155                         Access-Concentrator:*)
156                                 ac="${line#Access-Concentrator: }"
157                                 ;;
158                 esac
159         done <<<"${output}"
160
161         echo "ACCESS_CONCENTRATOR=\"$ac\""
162
163         exit ${DISCOVER_OK}
164 }
165
166 function hook_status() {
167         local zone=${1}
168         assert isset zone
169
170         cli_device_headline ${zone}
171
172         zone_settings_read "${zone}" ${HOOK_SETTINGS}
173
174         cli_headline 2 "Configuration"
175         cli_print_fmt1 2 "Username" "${USERNAME}"
176         cli_print_fmt1 2 "Password" "<hidden>"
177
178         local port=$(__hook_get_port "${zone}")
179         if isset port; then
180                 cli_print_fmt1 2 "Port" "${port}"
181         fi
182         cli_space
183
184         # Exit if zone is down
185         if ! zone_is_up ${zone}; then
186                 echo # Empty line
187                 exit ${EXIT_ERROR}
188         fi
189
190         # XXX display time since connection started
191
192         cli_headline 2 "Point-to-Point-over-Ethernet protocol"
193         local proto
194         for proto in ${IP_SUPPORTED_PROTOCOLS}; do
195                 routing_db_exists ${zone} ${proto} || continue
196
197                 local headline
198                 case "${proto}" in
199                         ipv6)
200                                 headline="Internet Protocol Version 6"
201                                 ;;
202                         ipv4)
203                                 headline="Internet Protocol Version 4"
204                                 ;;
205                         *)
206                                 headline="Unkown protocol"
207                                 ;;
208                 esac
209                 cli_headline 3 "${headline}"
210
211                 cli_print_fmt1 3 "IP address"  "$(routing_db_get ${zone} ${proto} local-ip-address)"
212                 cli_print_fmt1 3 "Gateway"     "$(routing_db_get ${zone} ${proto} remote-ip-address)"
213                 cli_print_fmt1 3 "DNS servers" "$(routing_db_get ${zone} ${proto} dns)"
214                 cli_space
215                 cli_print_fmt1 3 "MAC-Remote"  "$(routing_db_get ${zone} ${proto} remote-address)"
216                 cli_space
217         done
218
219         exit ${EXIT_OK}
220 }
221
222 function hook_ppp_write_config() {
223         local zone=${1}
224         assert isset zone
225
226         local file=${2}
227         assert isset file
228
229         # Read in the configuration files.
230         zone_settings_read "${zone}" ${HOOK_SETTINGS}
231
232         # A port has to be assigned for this action
233         local port=$(__hook_get_port "${zone}")
234         if ! isset port; then
235                 error "No port assigned to pppoe hook of zone '${zone}'"
236                 exit ${EXIT_ERROR}
237         fi
238
239         # Prepare the command line options for the pppoe plugin.
240         local plugin_options
241
242         # Add the access concentrator (if any).
243         if isset ACCESS_CONCENTRATOR; then
244                 plugin_options="${plugin_options} rp_pppoe_ac '${ACCESS_CONCENTRATOR}'"
245         fi
246
247         # Add the service name (if any).
248         if isset SERVICE_NAME; then
249                 plugin_options="${plugin_options} rp_pppoe_service '${SERVICE_NAME}'"
250         fi
251
252         # The last argument must be the interface.
253         plugin_options="${plugin_options} ${port}"
254
255         pppd_write_config ${file} \
256                 --interface="${zone}" \
257                 --username="${USERNAME}" \
258                 --password="${PASSWORD}" \
259                 --mtu="${MTU}" \
260                 --auth="${AUTH}" \
261                 --ipv6="${IPV6}" \
262                 \
263                 --plugin="${PPPOE_PLUGIN}" \
264                 --plugin-options="${plugin_options}"
265
266         exit ${EXIT_OK}
267 }
268
269 function __hook_get_port() {
270         local zone="${1}"
271
272         local port
273         for port in $(zone_get_ports "${zone}"); do
274                 echo "${port}"
275                 return ${EXIT_OK}
276         done
277
278         return ${EXIT_ERROR}
279 }
280
281 function hook_port_add() {
282         # Excepting at least two arguments here
283         assert [ $# -ge 2 ]
284
285         local zone="${1}"
286         local port="${2}"
287         shift 2
288
289         # PPPoE can only use one port
290         local ports_num="$(zone_get_ports_num "${zone}")"
291         if [ ${ports_num} -ge 1 ]; then
292                 local port=$(__hook_get_port "${zone}")
293                 error "The pppoe zone hook only supports assigning one port"
294                 error "  port '${port}' has already been assigned to zone '${zone}'"
295                 return ${EXIT_ERROR}
296         fi
297
298         zone_port_settings_write "${zone}" "${port}"
299         log INFO "Port '${port}' has been added to zone '${zone}'"
300
301         exit ${EXIT_OK}
302 }
303
304 function hook_port_remove() {
305         assert [ $# -eq 2 ]
306
307         local zone="${1}"
308         local port="${2}"
309
310         # Shut down the port (if possible)
311         port_down "${port}"
312
313         log INFO "Port '${port}' has been removed from zone '${zone}'"
314         zone_port_settings_remove "${zone}" "${port}"
315
316         exit ${EXIT_OK}
317 }