#!/bin/bash
###############################################################################
# #
# IPFire.org - A linux based firewall #
# Copyright (C) 2011 Michael Tremer & Christian Schmidt #
# #
# This program is free software: you can redistribute it and/or modify #
# it under the terms of the GNU General Public License as published by #
# the Free Software Foundation, either version 3 of the License, or #
# (at your option) any later version. #
# #
# This program is distributed in the hope that it will be useful, #
# but WITHOUT ANY WARRANTY; without even the implied warranty of #
# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the #
# GNU General Public License for more details. #
# #
# You should have received a copy of the GNU General Public License #
# along with this program. If not, see . #
# #
###############################################################################
function isdn_config_dir() {
local device=${1}
local dir="${RUN_DIR}/isdn/${device}"
[ -d "${dir}" ] || mkdir -p ${dir}
echo "${dir}"
}
function isdn_create_device() {
local device=${1}
if device_exists ${device}; then
return ${EXIT_OK}
fi
log INFO "Creating ISDN interface ${device}."
isdnctrl addif ${device} >/dev/null
}
function isdn_remove_device() {
local device=${1}
if ! device_exists ${device}; then
return ${EXIT_OK}
fi
log INFO "Removing ISDN interface ${device}."
isdnctrl delif ${device} >/dev/null
}
function isdn_add_slave() {
local device=${1}
local slave=${2}
assert device_exists ${device}
assert isset slave
log INFO "Creating ISDN slave interface ${slave} for device ${device}."
isdnctrl addslave ${device} ${slave}
local ret=$?
case "${ret}" in
0)
return ${EXIT_OK}
;;
255)
log ERROR "Could not create slave device for ${device}."
;;
esac
return ${EXIT_ERROR}
}
function isdn_rem_slave() {
local device=${1}
local slave=${2}
assert device_exists ${device}
assert isset slave
log INFO "Removing ISDN slave interface ${slave}."
isdnctrl delslave ${device} ${slave} >/dev/null
}
function isdn_addlink() {
local device=${1}
assert device_exists ${device}
log INFO "Adding link to ISDN interface ${device}."
isdnctrl addlink ${device} >/dev/null
}
function isdn_get_encap() {
local device=${1}
assert device_exists ${device}
isdnctrl encap ${device} | awk '{ print $NF }'
}
function isdn_set_encap() {
local device=${1}
local encap=${2}
assert device_exists ${device}
assert isset encap
case "${encap}" in
syncppp) ;;
*)
log ERROR "Cannot set unknown encapsulation: ${encap}"
return ${EXIT_ERROR}
;;
esac
isdnctrl encap ${device} ${encap} >/dev/null
}
function isdn_get_l2proto() {
local device=${1}
assert device_exists ${device}
isdnctrl l2_prot ${device} | awk '{ print $NF }'
}
function isdn_set_l2proto() {
local device=${1}
local proto=${2}
assert device_exists ${device}
assert isset proto
case "${proto}" in
hdlc) ;;
*)
log ERROR "Cannot set unknown l2 proto: ${proto}"
return ${EXIT_ERROR}
;;
esac
isdnctrl l2_prot ${device} ${proto} >/dev/null
}
function isdn_get_l3proto() {
local device=${1}
assert device_exists ${device}
isdnctrl l3_prot ${device} | awk '{ print $NF }'
}
function isdn_set_l3proto() {
local device=${1}
local proto=${2}
assert device_exists ${device}
assert isset proto
case "${proto}" in
trans) ;;
*)
log ERROR "Cannot set unknown l3 proto: ${proto}"
return ${EXIT_ERROR}
;;
esac
isdnctrl l3_prot ${device} ${proto} >/dev/null
}
function isdn_set_dialmax() {
local device=${1}
local dialmax=${2}
assert device_exists ${device}
assert [ ${dialmax} -gt 0 ]
isdnctrl dialmax ${device} ${dialmax} >/dev/null
}
function isdn_set_eaz() {
local device=${1}
local eaz=${2}
assert device_exists ${device}
assert isset eaz
isdnctrl eaz ${device} ${eaz} >/dev/null
}
function isdn_set_dialmode() {
local device=${1}
local mode=${2}
assert device_exists ${device}
case "${proto}" in
auto) ;;
*)
log ERROR "Cannot set unknown dialmode: ${mode}"
return ${EXIT_ERROR}
;;
esac
isdnctrl dialmode ${device} ${mode} >/dev/null
}
function isdn_set_huptimeout() {
local device=${1}
local timeout=${2}
assert device_exists ${device}
assert isinteger timeout
isdnctrl huptimeout ${device} ${mode} >/dev/null
}
function isdn_addphone() {
local device=${1}
local type=${2}
local number=${3}
assert device_exists ${device}
assert isoneof type in out
assert isset number
isdnctrl addphone ${device} ${type} ${number} >/dev/null
}
function isdn_dial() {
local device=${1}
shift
assert device_exists ${device}
local mode="persistent"
local channels="auto"
local ipppd_args
while [ $# -gt 0 ]; do
case "${1}" in
--mode=*)
mode=${1#--mode=}
;;
--channels=*)
channels=${1#--channels=}
;;
*)
ipppd_args="${ipppd_args} ${1}"
;;
esac
shift
done
assert isset channels
assert isset mode
assert isoneof channels 1 2 auto
# Start ippp daemon.
ipppd_start ${ipppd_args}
case "${mode}" in
dialondemand)
isdn_set_dialmode ${device} auto
;;
persistent)
case "${channels}" in
auto)
ibod_start ${device}
;;
1)
# Do nothing.
;;
2)
isdn_addlink ${device}
;;
esac
# Establish the connection immediately.
isdnctrl dial ${device} >/dev/null
;;
*)
log ERROR "Unknown dial mode given: ${mode}."
return ${EXIT_ERROR}
;;
esac
}
function isdn_hangup() {
local device=${1}
assert device_exists ${device}
# Bring isdn device down.
ip link set ${device} down
# Kill ippp daemon.
ipppd_stop ${device}
}
function ipppd_start() {
local device=${1}
shift
assert device_exists ${device}
ipppd_write_config ${device} $@
# Actually run the service.
service_start "ipppd@${device}.service"
}
function ipppd_write_config() {
local device=${1}
shift
local value
local auth="chap"
local user
local mppe="on"
local mtu="1500"
local proxyarp="on"
local local_address
local remote_address
local netmask
local dns_servers
# mode tells us if we are running in server or
# client mode. The collection of variables to
# be set depends on this.
local mode="client"
while [ $# -gt 0 ]; do
case "${1}" in
--mode=*)
mode=${1#--mode=}
;;
--auth=*)
auth=${1#--auth=}
;;
--user=*)
user=${1#--user=}
;;
--mppe=*)
mppe=${1#--mppe=}
;;
--mtu=*)
mtu=${1#--mtu=}
;;
--proxyarp=*)
value=${1#--proxyarp=}
if enabled value; then
proxyarp="on"
else
proxyarp="off"
fi
;;
--netmask=*)
netmask=${1#--netmask=}
;;
--local-address=*)
local_address=${1#--local-address=}
;;
--remote-address=*)
remote_address=${1#--remote-address=}
;;
--dns-server=*)
value=${1#--dns-server=}
# XXX check if this is actually an IP address
dns_servers="${dns_servers} ${value}"
;;
*)
log WARN "Unknown argument given: ${1}"
;;
esac
shift
done
# Check if all common variables are correctly set.
assert isset mtu
assert isinteger mtu
case "${mode}" in
client)
# Check if all variables for client mode are set.
assert isset auth
assert isset user
;;
server)
assert isset local_address
assert isset remote_address
assert isset netmask
;;
*)
log CRITICAL "Invalid mode given: ${mode}"
exit ${EXIT_ERROR}
;;
esac
# Make a configuration file.
local config="$(isdn_config_dir ${device})/config"
cat >${config} <>${config} <>${config} < ${config}
# Set the device to watch.
echo "DEVICE ${device}" >> ${config}
# We could set some more options here to
# configure when ibod is bringing the second
# channel up and down. I guess that is not
# required at the moment.
# See man ibod.cf.
}
function ibod_stop() {
local device=${1}
log INFO "Stopping ibod on device ${device}..."
service_stop "ibod@${device}.service"
# Remove ibod configuration file.
rm -f $(ibod_config_file ${device})
}