#!/bin/bash
# lastact: [arturo@2024-2-28]
# desc: script que permite añadir una dirección IP manual a la interfaz cableada (uso preferente: epoptes-server)

FICHFUNCS="/usr/bin/vx-funcs-bash"
[ -f "${FICHFUNCS}" ] && . "${FICHFUNCS}" "null"

# 0) Comprobamos si se solicita ayuda y se muestra:
function vx_nmcli_help() {
    DESCRIPCION="Permite añadir o quitar una dirección IP manual a la interfaz wifi o cableada que se usaría para alcanzar dicha IP:
    1. '--add-ip' => Añade una o varias direcciones ip a la interfaz preferente de red (wifi o cableada)
    2. '--add-ip-ethernet' => Añade una o varias direcciones ip a la interfaz preferente de red ethernet (cableada)
    3. '--del-ip' => Elimina una o varias direcciones ip en el caso de estar configurada en alguna interfaz de red del equipo"
    EJEMPLOS=( "${0} \"--add-ip-ethernet\" \"192.168.4.91/22\"" )
    EJEMPLOS+=( "${0} \"--add-ip\" \"192.168.4.91/22,172.30.1.91/24\"" )
    EJEMPLOS+=( "${0} \"--del-ip\" \"192.168.4.91/22,172.30.1.91/24\"" )
    vx-show_help_script "${0}" "${DESCRIPCION}" "${EJEMPLOS[@]}"
}

# 0) Comprobamos si se pide ayuda de como usar el comando:
vx-check_need_help "${1}" && vx_nmcli_help && exit 0

# 1) Comprobamos que es el usuario root quien quiere ejecutar el programa, sino salimos:
MENSAJE="Necesitas permisos de root para ejecutar este script"
vx-check_user_root "${MENSAJE}"

# 2) Definimos las variables y funciones locales que se usarán más adelante:
function add_ip_ethernet() {
    # Comprobamos que conexiones ethernet hay activas y las guardamos en un array:
    _TIPO_ETH=":802-3-ethernet:" # nmcli utiliza ":" para delimitar los campos. Ejemplo:
    # Recorremos la lista anterior para detectar cual es la primaria (tiene un gateway):
    # systemctl restart NetworkManager
    for ELE in "${LISTA_CON[@]}" ; do
        mapfile -d ":" -t _CON <<< "${ELE}"
        _TIPO="${_CON[2]}"
        [[ "${_TIPO}" != "${_TIPO_ETH}" ]] && continue
        _UUID="${_CON[1]}"
        _DEV="${_CON[0]}"
        # nmcli dev show "${_DEV}" | grep IPV4.GATEWAY | tr -d " " | grep -qv ":\-\-"
        nmcli con show "${_UUID}" | grep ipv4.gateway | tr -d " " | grep -qv ":\-\-" && \
        nmcli connection modify "${_UUID}" +ipv4.addresses "${IPS}" && \
        echo "#> Se ha configurado: ${_CON[0]}. Se le ha añdido las IPs: ${IPS}" && \
        break
    done
}

function add_ip() {
    # Revisamos la lista de IPs para saber cuales tiene y cuales no tiene asignadas:
    _ASIGNADAS=()
    for _IP in "${LISTA_IPS[@]}" ; do
        # Configuramos la IP en la interfaz que se usaría para alcanzar dicha IP:
        # 1) Obtenemos la interfaz de red a través de la cual alcanzaríamos dicha IP:
        # _IP es del formato IP/mascara: 192.168.1.65/24 (quitamos la máscara para ip route get)
        _DEV="$(ip route get "${_IP%/*}" | grep -oP 'dev \K\S+')"
        [[ "${_DEV}" == "lo" ]] && \
        echo "#> La dirección IP ${_IP} ya está configurada en el equipo" && \
        continue
        # 2) Comprobamos que esa interfaz de red no tenga ya configuradas las direcciones IP pasadas como parámetro:
        CONFIGURAR="false"
        nmcli -t -f GENERAL.DEVICE,IP4.ADDRESS dev show "${_DEV}" | grep -qE "^IP4.ADDRESS.*:${_IP}$" || CONFIGURAR="true"
        ! "${CONFIGURAR}" && \
        echo "#> La interfaz ${_DEV} ya tiene configuradas la IP: ${_IP}" && \
        continue
        # 3) Averiguamos que UUID tiene la INTERFAZ a través de las conexiones activas:
        _UUID="$(nmcli -t -f DEVICE,uuid,type,NAME con show --active | grep -E "^${_DEV}:" | cut -d":" -f2)"
        # 4) Configuramos en dicha interfaz la lista de direcciones IP indicadas como parámetro:
        [[ "${_UUID}" ]] && \
        nmcli connection modify "${_UUID}" +ipv4.addresses "${_IP}" && \
        _ASIGNADAS+=( "${_IP}" )
    done
    (( ${#_ASIGNADAS[@]} > 0 )) && \
    echo "#> Configurado: ${_DEV} - ${_UUID}. IPs añadidas: ${_ASIGNADAS[*]}. Reiniciamos la red." && \
    systemctl restart NetworkManager
}

function del_ip() {
    for _IP in "${LISTA_IPS[@]}" ; do
        # _IP es del formato IP/mascara: 192.168.1.65/24
        ENCONTRADO="false"
        for ELE in "${LISTA_CON[@]}" ; do
            mapfile -d ":" -t _CON <<< "${ELE}"
            _TIPO="${_CON[2]}"
            _UUID="${_CON[1]}"
            _DEV="${_CON[0]}"
            nmcli -t -f GENERAL.DEVICE,IP4.ADDRESS dev show "${_DEV}" | grep -qE "^IP4.ADDRESS.*:${_IP}$" && \
            ENCONTRADO="true" && \
            nmcli connection modify "${_UUID}" -ipv4.addresses "${_IP}" && \
            ip addr del "${_IP}" dev "${_DEV[0]}" && \
            echo "#> Se ha desconfigurado: ${_DEV[0]}. Se le ha eliminado las IPs: ${_IP}"
        done
        ! "${ENCONTRADO}" && \
        echo "#> No se ha encontrado asignada la dirección ${_IP} en ninguna interfaz de red del equipo"
    done
}

[ -z "${2}" ] && vx_nmcli_help && exit 1

# Creamos una lista con las IPs pasadas como parámetro:
IPS="${2}"
# mapfile -d "," -t LISTA_IPS <<< "${IPS}"
IFS=',' read -r -a LISTA_IPS <<< "${IPS}"

# Comprobamos que las direcciones IPs indicada como parámetro son válidas.
# Usaremos luego la primera IP para determinar la interfaz a configurar:
IP_REGEX='^((25[0-5]|2[0-4][0-9]|[01]?[0-9][0-9]?)\.){3}(25[0-5]|2[0-4][0-9]|[01]?[0-9][0-9]?)$'
IP1="${LISTA_IPS[0]%/*}"
for IP in "${LISTA_IPS[@]}" ; do
    ! [[ "${IP%/*}" =~ $IP_REGEX ]] && \
    echo "#> La IP indicada no es válida: ${IP}" && \
    vx_nmcli_help && exit 1
done

# Obtenemos una lista de las conexiones activas:
# nmcli -t -f DEVICE,uuid,type,NAME con show --active
# enp0s3:f761f17e-1904-3996-9717-25ae79584669:802-3-ethernet:Conexión cableada 1
# enp0s8:383c3f79-8d45-34f9-bb72-52fa567d491b:802-3-ethernet:Conexión cableada 2
mapfile -t LISTA_CON <<< "$(nmcli -t -f DEVICE,uuid,type,NAME con show --active)"
[[ -z "${LISTA_CON[0]}" ]] && \
echo "#> No se ha detectado ninguna interfaz de red activa donde configurar las IPs indicadas: ${IPS}" && \
exit 2

# 3) Comprobamos a través del primer parámetro la acción a realizar:
case "${1}" in
    "--add-ip-ethernet" ) 
        add_ip_ethernet
        ;;
    "--add-ip" )
        add_ip
        ;;
    "--del-ip" )
        del_ip
        ;;
    * )
        vx_nmcli_help
        exit 1
    ;;
esac
exit 0