]> git.ipfire.org Git - people/pmueller/ipfire-2.x.git/blame - src/initscripts/networking/functions.network
make.sh: Run "update-contributors"
[people/pmueller/ipfire-2.x.git] / src / initscripts / networking / functions.network
CommitLineData
8ae238a5 1#!/bin/bash
66c36198
PM
2###############################################################################
3# #
4# IPFire.org - A linux based firewall #
5# Copyright (C) 2007-2022 IPFire Team <info@ipfire.org> #
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###############################################################################
71ea0d68 21
71ea0d68
SS
22eval $(/usr/local/bin/readhash /var/ipfire/ethernet/settings)
23eval $(/usr/local/bin/readhash /var/ipfire/dns/settings)
24
3f863ee7
MT
25ip2bin() {
26 local address="${1}"
27
28 local IFS='.'
29 local octet
30
31 local n=0
32
33 for octet in ${address}; do
34 # Shift n
35 (( n <<= 8 ))
36
37 # Apply the octet
38 (( n |= octet ))
39 done
40
41 echo "${n}"
42}
43
44bin2ip() {
45 local n="${1}"
46
47 local IFS='.'
48 local address=()
49
50 for i in {3..0}; do
51 address+=( $(( n >> (8 * i) & 0xff )) )
52 done
53
54 echo "${address[*]}"
55}
56
db151ad7 57network_get_intfs() {
79cce701
MT
58 local zone="${1}"
59
d99826dc 60 case "${zone^^}" in
79cce701
MT
61 RED)
62 # For PPPoE, the RED interface is called ppp0 (unless we use QMI)
63 if [ "${RED_TYPE}" = "PPPOE" ] && [ "${RED_DRIVER}" != "qmi_wwan" ]; then
64 echo "ppp0"
65 return 0
66
67 # Otherwise we return RED_DEV
68 elif [ -n "${RED_DEV}" ]; then
69 echo "${RED_DEV}"
70 return 0
71 fi
72 ;;
73
74 GREEN)
75 if [ -n "${GREEN_DEV}" ]; then
76 echo "${GREEN_DEV}"
77 return 0
78 fi
79 ;;
80
81 ORANGE)
82 if [ -n "${ORANGE_DEV}" ]; then
83 echo "${ORANGE_DEV}"
84 return 0
85 fi
86 ;;
87
88 BLUE)
89 if [ -n "${BLUE_DEV}" ]; then
90 echo "${BLUE_DEV}"
91 return 0
92 fi
93 ;;
94
d99826dc
MT
95 IPSEC)
96 local VARS=(
97 id status x1 x2 type x3 x4 x5 x6 x7 x8 x9 x10
98 x11 x12 x13 x14 x15 x16 x17 x18 x19 x20
99 x21 x22 x23 x24 x25 x26 x27 x28 x29 x30
100 x31 x32 x33 x34 interface_mode rest
101 )
102
103 while IFS="," read -r "${VARS[@]}"; do
104 # Check if the connection is enabled
105 [ "${status}" = "on" ] || continue
106
107 # Check if this a net-to-net connection
108 [ "${type}" = "net" ] || continue
109
110 # Determine the interface name
111 case "${interface_mode}" in
112 gre|vti)
113 echo "${interface_mode}${id}"
114 ;;
115 esac
116 done < /var/ipfire/vpn/config
117
118 return 0
119 ;;
120
1b7d1abd
MT
121 WIREGUARD|WG)
122 echo "wg+"
123 return 0
124 ;;
125
79cce701
MT
126 OPENVPN|OVPN)
127 # OpenVPN is using all tun devices
128 echo "tun+"
1b7d1abd 129 return 0
79cce701
MT
130 ;;
131 esac
132
133 # Not found
134 return 1
135}
136
3f863ee7
MT
137network_get_address() {
138 local network="${1}"
139
140 # Return everything before the slash
141 echo "${network%%/*}"
142}
143
144network_get_prefix() {
145 local network="${1}"
146
147 # Consider everything after the / the prefix
148 local prefix="${network##*/}"
149
150 # If the prefix is valid, return it
151 if network_prefix_is_valid "${prefix}"; then
152 echo "${prefix}"
153
154 # Otherwise it might be a subnet mask
155 else
156 network_netmask_to_prefix "${prefix}"
157 fi
158}
159
160network_get_netmask() {
161 local network="${1}"
162
163 # Consider everything after the / the netmask
164 local netmask="${network##*/}"
165
166 # If we have a prefix, we need to convert
167 if network_prefix_is_valid "${netmask}"; then
168 network_prefix_to_netmask "${netmask}"
169
170 # Otherwise return what we got
171 else
172 echo "${netmask}"
173 fi
174}
175
176network_prefix_is_valid() {
177 local prefix="${1}"
178
179 # The prefix must be numbers only
180 if ! [[ "${prefix}" =~ ^[0-9]+$ ]]; then
181 return 1
182 fi
183
184 # Must be a number between 0 and 32 (inclusive)
185 [ "${prefix}" -ge 0 -a "${prefix}" -le 32 ]
186}
187
188network_prefix_to_netmask() {
189 local prefix="${1}"
190
191 # Set n with all bits set
192 local n=0xffffffff
193
194 # Shift
195 (( n <<= (32 - prefix) ))
196
197 # Convert back
198 bin2ip "${n}"
199}
200
201network_netmask_to_prefix() {
202 local netmask="${1}"
203
204 local prefix=0
205
206 # Convert to binary
207 local n="$(ip2bin "${netmask}")"
208
209 while [ "${n}" -gt 0 ]; do
210 # If the highest bit is not set, we are done
211 [ "$(( n & (1 << 31) ))" -eq 0 ] && break
212
213 # Increment prefix & shift n
214 (( prefix++ ))
215 (( n <<= 1 ))
216 done
217
218 echo "${prefix}"
219}
220
221network_address_in_network() {
222 local address="${1}"
223 local network="${2}"
224
225 # Split the network into its address & mask
226 local netaddr="$(network_get_address "${network}")"
227 local netmask="$(network_get_netmask "${network}")"
228
229 # Abort if we could not parse the network
230 if [ -z "${netaddr}" -o -z "${netmask}" ]; then
231 return 1
232 fi
233
234 # Convert everything to binary
235 address="$(ip2bin "${address}")"
236 netaddr="$(ip2bin "${netaddr}")"
237 netmask="$(ip2bin "${netmask}")"
238
239 # Ensure the network address is the first address
240 (( netaddr &= netmask ))
241
242 # Compute broadcast
243 local broadcast=$(( netaddr | (~netmask & 0xffffffff) ))
244
245 # Return true if address is in the network
246 [ "${address}" -ge "${netaddr}" -a "${address}" -le "${broadcast}" ]
247}
248
76ea485d
MT
249# Takes a network and list of IP addresses and will return the first IP address
250# that is in the given network.
251first_address_in_network() {
252 local network="${1}"
253 shift
254
255 local addr
256 for addr in $@; do
257 if network_address_in_network "${addr}" "${network}"; then
258 echo "${addr}"
259 return 0
260 fi
261 done
262
263 return 1
264}
265
266# Returns the first of IPFire's own IP addresses that is in any of the given networks
267ipfire_address_in_networks() {
268 local addresses=()
269
270 local var
271 for var in GREEN_ADDRESS BLUE_ADDRESS ORANGE_ADDRESS; do
272 if [ -n "${!var}" ]; then
273 addresses+=( "${!var}" )
274 fi
275 done
276
277 local network
278 for network in $@; do
279 # Find and end after the first match
280 if first_address_in_network "${network}" "${addresses[@]}"; then
281 return 0
282 fi
283 done
284
285 # Nothing found
286 return 1
287}
288
71ea0d68
SS
289dhcpcd_get_pid() {
290 # This function returns the pid of a dhcpcd by a given
291 # network device, if a pidfile exists.
292
293 local device="$1"
18136c5c 294 local pidfile="/var/run/dhcpcd/${device}.pid"
71ea0d68
SS
295
296 # Check if a pid file exists.
297 if [ -f "${pidfile}" ] ; then
298
299 # Get the pid from the file.
300 local pid="$(<"${pidfile}")"
301
302 echo "${pid}"
303 fi
304}
305
306dhcpcd_is_running() {
307 # This functions checks if a dhcpcd is running by a given pid.
308
309 local pid="$1"
310
311 # Check if a dhcpcd is running.
312 if [ -n "${pid}" -a -d "/proc/${pid}" ]; then
313 # Return "0" (True) if a dhcpcd is running.
314 return 0
315 fi
316
317 # Return 1 (False) no dhcpcd is running.
318 return 1
319}
320
321dhcpcd_start() {
322 # This function will start a dhcpcd on a speciefied device.
71ea0d68 323 local device="$1"
c6551e73
MT
324 shift
325
5d0d1144 326 local dhcp_start=()
71ea0d68
SS
327
328 boot_mesg -n "Starting dhcpcd on the ${device} interface..."
329
330 # Check if a dhcpcd is already running.
331 local pid="$(dhcpcd_get_pid "${device}")"
332
333 if dhcpcd_is_running "${pid}"; then
334 boot_mesg "dhcpcd already running!" ${WARNING}
335 echo_warning
336 exit 2
337 fi
338
339 # Check if a DHCP hostname has been set.
340 if [ -n "${RED_DHCP_HOSTNAME}" ]; then
5d0d1144
MT
341 dhcp_start+=( "-h" "${RED_DHCP_HOSTNAME}" )
342 fi
343
344 # Tell dhcpcd to use the configured MTU
345 if [ -n "${RED_DHCP_FORCE_MTU}" ]; then
346 dhcp_start+=( "--static" "mtu=${RED_DHCP_FORCE_MTU}" )
71ea0d68
SS
347 fi
348
c6551e73
MT
349 # Append any further command line options
350 dhcp_start+=( $@ )
351
71ea0d68 352 # Start dhcpcd.
5d0d1144 353 /sbin/dhcpcd "${dhcp_start[@]}" ${device} >/dev/null 2>&1
71ea0d68
SS
354 ret="$?"
355
356 if [ "${ret}" -eq 0 ]; then
357 . /var/ipfire/dhcpc/dhcpcd-"${device}".info
71ea0d68 358
f938083f
AF
359 if [ $ip_address ]; then
360 echo ""
361 echo_ok
362 boot_mesg " DHCP Assigned Settings for ${device}:"
71ea0d68 363 boot_mesg_flush
f938083f
AF
364 boot_mesg " IP Address: $ip_address"
365 boot_mesg_flush
366
367 if [ -n "${RED_DHCP_HOSTNAME}" ]; then
368 boot_mesg " Hostname: $RED_DHCP_HOSTNAME"
369 boot_mesg_flush
370 fi
71ea0d68 371
f938083f
AF
372 boot_mesg " Subnet Mask: $subnet_mask"
373 boot_mesg_flush
374 boot_mesg " Default Gateway: $routers"
375 boot_mesg_flush
376 boot_mesg " DNS Server: $domain_name_servers"
377 boot_mesg_flush
378 else
379 echo ""
380 echo_ok
381 boot_mesg "DHCP for ${device} still running..."
382 boot_mesg_flush
383 fi
71ea0d68
SS
384 else
385 echo ""
386 $(exit "${ret}")
387 evaluate_retval
388 fi
389}
390
391dhcpcd_stop() {
392 # This function stops a previously started dhcpcd on a given device.
393
394 local device="$1"
395 local dhcp_stop="-k"
396 local leaseinfo="/var/ipfire/dhcpc/dhcpcd-${device}.info"
397
398 boot_mesg -n "Stopping dhcpcd on the ${device} interface..."
399
400 # Check if a dhcpcd is running.
401 local pid="$(dhcpcd_get_pid "${device}")"
402
403 if ! dhcpcd_is_running "${pid}"; then
02d67e75 404 boot_mesg " Not running." ${WARNING}
71ea0d68
SS
405 echo_warning
406 exit 1
407 fi
408
d43bb759 409 # Stop dhcpcd.
2e28ecea 410 /sbin/dhcpcd ${dhcp_stop} ${device} &> /dev/null
d43bb759
AF
411 ret="$?"
412
413 # Wait until dhcpd has stopped.
414 while [ -d "/proc/${pid}" ]; do
415 sleep 1
66acb7f1
AF
416 # repeat stop if dhcp was still running
417 /sbin/dhcpcd ${dhcp_stop} ${device} &> /dev/null
d43bb759
AF
418 done
419
420 # Display console message, depended on the exit code
421 # of the stopped dhcpcd.
422 if [ "${ret}" -eq 0 ]; then
423 boot_mesg
424 echo_ok
425 elif [ "${ret}" -eq 1 ]; then
426 boot_mesg "failed to stop dhcpcd!" ${WARNING}
427 echo_warning
428 else
429 boot_mesg
430 echo_failure
71ea0d68
SS
431 fi
432}
957863f7
MT
433
434# QMI stuff
435
436qmi_find_device() {
437 local intf="${1}"
438 local _intf
439
440 local path
441 for path in /dev/cdc-*; do
442 if [ -c "${path}" ]; then
580c249a 443 _intf="$(qmi_find_interface "${path}")"
957863f7
MT
444
445 # Check if the interface matches
446 if [ "${intf}" = "${_intf}" ]; then
447 echo "${path}"
448 return 0
449 fi
450 fi
451 done
452
453 # Nothing found
454 return 1
455}
456
580c249a
MT
457qmi_find_interface() {
458 local device="${1}"
459
460 qmicli --device="${device}" --device-open-proxy --get-wwan-iface
461}
462
957863f7
MT
463qmi_enable_rawip_mode() {
464 local intf="${1}"
465
466 # Shut down the device first
467 ip link set "${intf}" down &>/dev/null
468
469 echo "Y" > "/sys/class/net/${intf}/qmi/raw_ip"
470}
471
472qmi_configure_apn() {
473 local device="${1}"
474
475 # APN settings
476 local apn="${2}"
477 local auth="${3}"
478 local username="${4}"
479 local password="${5}"
480
481 local args=(
482 # We only support IPv4 right now
483 "ip-type=4"
484 )
485
486 # Set APN
487 if [ -n "${apn}" ]; then
488 args+=( "apn=${apn}" )
489 fi
490
491 # Set auth
492 case "${auth}" in
493 PAP|CHAP)
494 args+=( "auth=${auth}" )
495 ;;
496 esac
497
498 # Set username
499 if [ -n "${username}" ]; then
500 args+=( "username=${username}" )
501 fi
502
503 # Set password
504 if [ -n "${password}" ]; then
505 args+=( "password=${password}" )
506 fi
507
508 local _args
509
510 local arg
511 for arg in ${args[@]}; do
512 if [ -n "${_args}" ]; then
513 _args="${_args},"
514 fi
515 _args="${_args}${arg}"
516 done
517
518 qmicli --device="${device}" --device-open-proxy \
519 --wds-start-network="${_args}" \
b1ff8adb 520 --client-no-release-cid &>/dev/null
957863f7
MT
521}
522
523qmi_reset() {
524 local device="${1}"
525
526 qmicli --device="${device}" --device-open-proxy \
b1ff8adb 527 --wds-reset &>/dev/null
957863f7 528}
580c249a
MT
529
530# Assigns a "static" MAC address
531qmi_assign_address() {
532 local intf="${1}"
533
534 # Find the device
535 local device="$(qmi_find_device "${intf}")"
536
caef75c5
SS
537 # Switch off the raw_ip mode to be able to proper
538 # assign the generated MAC address.
539 echo "N" > "/sys/class/net/${intf}/qmi/raw_ip"
540
580c249a
MT
541 local address
542
543 # Generate a "random" MAC address using the device number
544 printf -v address "02:ff:ff:ff:ff:%02x" "${device:12}"
545
546 # Change the MAC address
547 ip link set "${intf}" address "${address}"
548}