206 lines
4.7 KiB
Bash
206 lines
4.7 KiB
Bash
#!/usr/bin/env bash
|
|
#
|
|
# lib/common
|
|
#
|
|
# Copyright (c) 2011-2013 LibreVPN <vpn@hackcoop.com.ar>
|
|
#
|
|
# See AUTHORS for a list of contributors
|
|
#
|
|
# This program is free software; you can redistribute it and/or modify
|
|
# it under the terms of the GNU Affero 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 Affero General
|
|
# Public License along with this program. If not, see
|
|
# <http://www.gnu.org/licenses/>.
|
|
#
|
|
#
|
|
|
|
# Terminar ante el menor error
|
|
set -e
|
|
|
|
# Habilitar debug tan pronto como sea posible si se usa -d en algún lado
|
|
echo "$*" | grep -q " -\([a-z]\+\)\?d" && set -x
|
|
|
|
# Comprueba si los programas necesarios existen en el sistema
|
|
requires() {
|
|
local missing=()
|
|
local bin
|
|
for bin in "$@"; do
|
|
if ! type "$bin" &>/dev/null; then
|
|
missing+=("$bin")
|
|
fi
|
|
done
|
|
|
|
if [[ ${#missing[@]} -ne 0 ]]; then
|
|
printf "Los siguientes programas no se encuentran en PATH:%s\n" "${missing[*]}"
|
|
exit 1
|
|
fi
|
|
}
|
|
|
|
trap_exit() {
|
|
msg "ARGH! Algo pasó" 1>&2
|
|
exit 1
|
|
}
|
|
|
|
trap 'trap_exit' TERM HUP QUIT INT ERR
|
|
|
|
. "${LVPN_LIBDIR}/msg"
|
|
|
|
self="$(basename $0)"
|
|
|
|
# Agrega una linea a un archivo
|
|
add_to_file(){
|
|
f=$1; shift
|
|
|
|
echo "$*" >>"$f"
|
|
}
|
|
|
|
# Obtiene el directorio del nodo
|
|
# $1 nombre del nodo
|
|
get_node_dir() {
|
|
node="$(get_node_name "$1")"
|
|
dir="${LVPN_DIR}/nodos/${node}"
|
|
|
|
if [ ! -d "${dir}" ] || [ ! -f "${dir}/tinc.conf" ]; then
|
|
fatal_error "El nodo no existe o es inválido"
|
|
fi
|
|
|
|
echo "${dir}"
|
|
}
|
|
|
|
# Obtiene el archivo del nodo en el directorio del nodo
|
|
get_node_file() {
|
|
node="$(get_node_name "$1")"
|
|
dir="$(get_node_dir "$1")"
|
|
file="${dir}/hosts/${node}"
|
|
|
|
if [ ! -f "${file}" ]; then
|
|
fatal_error "El archivo host de %s no existe" "$1"
|
|
fi
|
|
|
|
echo "${file}"
|
|
}
|
|
|
|
# Limpia el hostname, convierte todo lo no alfanumérico a _
|
|
# Ver tincd.conf(5)
|
|
get_node_name() {
|
|
echo "$1" | sed -e "s/[^a-z0-9_]/_/gi"
|
|
}
|
|
|
|
get_host_file() {
|
|
node="$(get_node_name "${1}")"
|
|
test -f "${LVPN_HOSTS}/${node}" || \
|
|
error "El archivo host de %s no existe" "$node" || \
|
|
return 1
|
|
|
|
echo "${LVPN_HOSTS}/${node}"
|
|
}
|
|
|
|
# Obtiene un evento válido
|
|
get_event() {
|
|
echo "$1" | grep -qE "^host|subnet|tinc$" && echo "$1"
|
|
}
|
|
|
|
# Obtener un script
|
|
get_script() {
|
|
script_dir="${LVPN_LIBDIR}/skel/scripts"
|
|
|
|
test -f "${script_dir}/$1" && echo "${script_dir}/$1"
|
|
}
|
|
|
|
# Encontrar el tipo de init que se va a usar para tinc
|
|
# Devuelve "tipo ubicacion"
|
|
# Ver lib/lvpn-install
|
|
find_init_system() {
|
|
if [ -f /etc/debian_version ]; then
|
|
echo "deb /etc/tinc/nets.boot"
|
|
elif [ -f /etc/os-release ]; then
|
|
echo "systemd /etc/systemd/system/multi-user.target.wants/tincd@${NETWORK}.service"
|
|
else
|
|
echo "unknown unknown"
|
|
fi
|
|
}
|
|
|
|
# Obtiene la id del responsable del nodo
|
|
get_id() {
|
|
if [ -n "$(git config --get user.name)" ]; then
|
|
echo "# $(git config --get user.name) <$(git config --get user.email)>"
|
|
else
|
|
echo "# $USER@$HOSTNAME"
|
|
fi
|
|
}
|
|
|
|
# Encuentra una IP libre entre los archivos de host
|
|
get_ipv4() {
|
|
# Las subnets encontradas
|
|
local subnets=/tmp/$$.subnets
|
|
local ip=""
|
|
local fourth=0
|
|
local tries=0
|
|
|
|
# Armar la lista de IPs
|
|
grep -i "subnet\s*=" ${LVPN_HOSTS}/* | cut -d'=' -f2 | sort > ${subnets}
|
|
|
|
# Fallar si hay 250 nodos...
|
|
if [ $(wc -l ${subnets} | cut -d' ' -f1 2>/dev/null) -ge 250 ]; then
|
|
# No detecta si hay varios rangos en uso pero por ahora sirve
|
|
error "Este rango está agotado"
|
|
return 1
|
|
fi
|
|
|
|
# Hasta que encontremos una IP libre elegir el cuarto octeto al azar
|
|
until [ -n "${ip}" ]; do
|
|
let fourth=${RANDOM}%250
|
|
local tmpip="${LVPN_SUBNET%.*}.${fourth}/32"
|
|
|
|
# Está en la lista?
|
|
if ! grep -q "${tmpip}" "${subnets}"; then
|
|
ip="${tmpip}"
|
|
fi
|
|
|
|
# Aumentar la cantidad de intentos
|
|
# Por alguna razon let devuelve 1
|
|
let tries++ || true
|
|
|
|
if [ ${tries} -ge 250 ]; then
|
|
error "No hay IPs libres"
|
|
return 1
|
|
fi
|
|
done
|
|
|
|
echo "${ip}"
|
|
}
|
|
|
|
# Genera una dirección IPv6 /128
|
|
get_ipv6() {
|
|
# Compatibilidad para versión standalone
|
|
arch=$(uname -m)
|
|
|
|
# probar los posibles nombres de generate-ipv6-address y no devolver
|
|
# nada si no hay
|
|
for gia in {${arch}-,}generate-ipv6-address; do
|
|
if type ${gia} &>/dev/null; then
|
|
echo "$(${gia} ${LVPN_SUBNET6%/*})/128"
|
|
return
|
|
fi
|
|
done
|
|
}
|
|
|
|
if $root ; then
|
|
# Salir si no se es root y no existe sudo, sino usarlo
|
|
if [ ! -w / ]; then
|
|
if ! type sudo &>/dev/null; then
|
|
fatal_error "Correr como root"
|
|
else
|
|
export sudo=sudo
|
|
fi
|
|
fi
|
|
fi
|