From ddb71eb635d8f8f23482bd00cb1560d2546f6880 Mon Sep 17 00:00:00 2001 From: bergware Date: Mon, 9 Jun 2025 02:29:04 +0200 Subject: [PATCH] More networking fixes --- etc/rc.d/rc.docker | 88 +++++++++++++++++++++++++---------------- etc/rc.d/rc.inet1 | 19 +++++++-- sbin/create_network_ini | 12 ++++-- sbin/monitor_interface | 30 +++++++++----- 4 files changed, 99 insertions(+), 50 deletions(-) diff --git a/etc/rc.d/rc.docker b/etc/rc.d/rc.docker index 389e388a0..4d1e3290e 100755 --- a/etc/rc.d/rc.docker +++ b/etc/rc.d/rc.docker @@ -30,6 +30,7 @@ DOCKER_TIMEOUT=$(awk -F'"' '/^DOCKER_TIMEOUT=/{print $2}' $DOCKER_CFG 2>/dev/nul # network file references INI=/var/local/emhttp/network.ini +STA=/var/local/emhttp/statics.ini TMP=/var/tmp/network.tmp # run & log functions @@ -57,6 +58,19 @@ carrier(){ return 1 } +# add entry to watch list +add_entry(){ + rm -f /var/tmp/${1%% *}.down + [[ -e $STA ]] && echo "$1" >>$STA +} + +# delete enty from watch list +del_entry(){ + touch /var/tmp/$1.down + [[ -e $STA ]] && sed -i "/^$1 .*/d" $STA + sleep 0.5 +} + # initialize docker settings docker_read_options(){ # determine active port name @@ -178,11 +192,6 @@ network(){ docker network ls --filter driver="$1" --format='{{.Name}}' 2>/dev/null | grep -P "^[a-z]+$2(\$|\.)" | tr '\n' ' ' } -# Does the ipv4 address exist? -ipv4_exist(){ - ip -4 -br addr show to $2 dev $1 | awk '{print $3;exit}' -} - # Is container running? container_running(){ local CONTAINER @@ -414,22 +423,29 @@ docker_network_start(){ done # hack to let containers talk to host if [[ $TYPE == br ]]; then - LINK=shim-$NETWORK + SHIM=shim-$NETWORK if [[ $DOCKER_ALLOW_ACCESS == yes && -n $IPV4 ]]; then # create shim interface - [[ -e $SYSTEM/$LINK ]] || run ip link add link $NETWORK name $LINK type $ATTACH mode $MODE + if [[ ! -e $SYSTEM/$SHIM ]]; then + run ip link add link $NETWORK name $SHIM type $ATTACH mode $MODE + run ip link set $SHIM up + fi # disable IPv6 on shim interface - echo 1 >$CONF6/$LINK/disable_ipv6 - run ip -6 addr flush dev $LINK + echo 1 >$CONF6/$SHIM/disable_ipv6 + run ip -6 addr flush dev $SHIM # copy parent IPv4 address to shim interface - run ip addr add $IPV4 dev $LINK metric 0 - run ip link set $LINK up - log "created network $LINK for host access" - elif [[ -e $SYSTEM/$LINK ]]; then - # remove shim interface - run ip addr flush dev $LINK - run ip link set $LINK down - run ip link del $LINK + run ip -4 addr add $IPV4 dev $SHIM metric 0 + add_entry "$SHIM $IPV4 metric 0" + GW4=$(ip -4 route show to default dev $NETWORK | awk '{print $3;exit}') + if [[ -n $GW4 ]]; then + run ip -4 route add default via $GW4 dev $SHIM metric 0 + add_entry "$SHIM GW4 default via $GW4 metric 0" + fi + log "created network $SHIM for host access" + elif [[ -e $SYSTEM/$SHIM ]]; then + # remove shim interface assignment + del_entry $SHIM + run ip -4 addr del $IPV4 dev $SHIM metric 0 fi else if [[ $TYPE == wlan ]]; then @@ -442,11 +458,18 @@ docker_network_start(){ echo 1 >$CONF6/$VHOST/disable_ipv6 run ip -6 addr flush dev $VHOST # copy parent IPv4 address to vhost interface - [[ -z $(ipv4_exist $VHOST ${IPV4%/*}) ]] && run ip addr add $IPV4 dev $VHOST metric 0 + run ip -4 addr add $IPV4 dev $VHOST metric 0 + add_entry "$VHOST $IPV4 metric 0" + GW4=$(ip -4 route show to default dev $NETWORK | awk '{print $3;exit}') + if [[ -n $GW4 ]]; then + run ip -4 route add default via $GW4 dev $VHOST metric 0 + add_entry "$VHOST GW4 default via $GW4 metric 0" + fi log "created network $VHOST for host access" - elif [[ -n $IPV4 && -e $SYSTEM/$VHOST && -n $(ipv4_exist $VHOST ${IPV4%/*}) ]]; then - # remove parent IPv4 address from vhost interface - run ip addr del $IPV4 dev $VHOST metric 0 + elif [[ -n $IPV4 && -e $SYSTEM/$VHOST ]]; then + # remove vhost interface assignment + del_entry $VHOST + run ip -4 addr del $IPV4 dev $VHOST metric 0 fi fi fi @@ -468,25 +491,24 @@ docker_network_stop(){ [[ ${NIC:0:3} == eth ]] && NIC=$(active $NIC) driver ${NIC//[0-9]/} forced for NETWORK in $(network $ATTACH ${NIC//[^0-9]/}); do + IPV4=$(ip -4 -br addr show scope global primary dev $NETWORK | awk '{print $3;exit}') [[ $STOCK =~ ${NETWORK%%[0-9]*} || $DOCKER_USER_NETWORKS != preserve ]] && docker network rm $NETWORK &>/dev/null TYPE=${NETWORK//[0-9.]/} - if [[ $TYPE == br ]]; then - LINK=shim-$NETWORK - if [[ -e $SYSTEM/$LINK ]]; then - run ip addr flush dev $LINK - run ip link set $LINK down - run ip link del $LINK + if [[ $TYPE == br || $TYPE == wlan ]]; then + SHIM=shim-$NETWORK + if [[ -e $SYSTEM/$SHIM ]]; then + del_entry $SHIM + run ip -4 addr del $IPV4 dev $SHIM metric 0 fi - elif [[ $TYPE != wlan ]]; then + else VHOST=vhost${NETWORK//[^0-9.]/} - [[ -e $SYSTEM/$VHOST ]] && run ip addr flush dev $VHOST + if [[ -e $SYSTEM/$VHOST ]]; then + del_entry $VHOST + run ip -4 addr del $IPV4 dev $VHOST metric 0 + fi fi done done - if [[ -e $SYSTEM/shim-wlan0 ]]; then - IPV4=$(ip -4 -br addr show scope global primary dev shim-wlan0 | awk '{print $3,$4,$5;exit}') - [[ -n $IPV4 ]] && run ip addr del $IPV4 dev shim-wlan0 - fi log "Network stopped." } diff --git a/etc/rc.d/rc.inet1 b/etc/rc.d/rc.inet1 index aa12699d5..dcfe07faa 100755 --- a/etc/rc.d/rc.inet1 +++ b/etc/rc.d/rc.inet1 @@ -87,6 +87,7 @@ # Adapted by Bergware for use in Unraid OS - June 2025 # - revert metric assignment to static addresses # - remove duplicate ipv6 parameters +# - improve gateway creation ########### # LOGGING # @@ -632,8 +633,13 @@ gateway_up(){ [[ -z ${i[1]} ]] && DEV=${IFNAME[$i]} || DEV=${IFNAME[$i]}.${VLANID[$x]} IP=${PROTOCOL[$x]:-ipv4} AD=${METRIC[$x]} - [[ -n $AD ]] && AD="metric $AD" - EXIST=$(ip -4 route show to default via $(unzero $GW) dev $DEV | grep "$AD ") + if [[ -z $AD ]]; then + AD="metric 1" + EXIST=$(ip -4 route show to default via $(unzero $GW) dev $DEV | grep -vm1 metric) + else + AD="metric $AD" + EXIST=$(ip -4 route show to default via $(unzero $GW) dev $DEV | grep -m1 "$AD ") + fi [[ $IP != ipv6 && -z $EXIST ]] && run ip -4 route add default via $(unzero $GW) dev $DEV $AD done for GW6 in ${GATEWAY6[@]}; do @@ -644,8 +650,13 @@ gateway_up(){ [[ -z ${i[1]} ]] && DEV=${IFNAME[$i]} || DEV=${IFNAME[$i]}.${VLANID[$x]} IP=${PROTOCOL[$x]:-ipv4} AD6=${METRIC6[$x]} - [[ -n $AD6 ]] && AD6="metric $AD6" - EXIST=$(ip -6 route show to default via $(unzero6 $GW6) dev $DEV | grep "$AD6 ") + if [[ -z $AD6 ]]; then + AD6="metric 1" + EXIST=$(ip -6 route show to default via $(unzero6 $GW6) dev $DEV | grep -vm1 metric) + else + AD6="metric $AD6" + EXIST=$(ip -6 route show to default via $(unzero6 $GW6) dev $DEV | grep -m1 "$AD6 ") + fi [[ $IP != ipv4 && -z $EXIST ]] && run ip -6 route add default via $(unzero6 $GW6) dev $DEV $AD6 done } diff --git a/sbin/create_network_ini b/sbin/create_network_ini index 9fef5aad5..4938f5539 100755 --- a/sbin/create_network_ini +++ b/sbin/create_network_ini @@ -163,7 +163,8 @@ for ((i=0; i<${SYSNICS:-1}; i++)); do IPV4="$(ip -4 -br addr show scope global primary dev $IFACE | awk '{$2="";print;exit}')" if [[ -n $IPV4 ]]; then echo "$IPV4" >>$STA - echo "$IFACE GW4 $(ip -4 route show to default dev $IFACE)" >>$STA + GW4="$(ip -4 route show to default dev $IFACE)" + [[ -n $GW4 ]] && echo "$IFACE GW4 $GW4" >>$STA fi fi echo "USE_DHCP6:0=\"${USE_DHCP6[$i]}\"" >>$INI @@ -187,7 +188,8 @@ for ((i=0; i<${SYSNICS:-1}; i++)); do IPV6="$(ip -6 -br addr show scope global primary -deprecated dev $IFACE | awk '{$2="";print;exit}')" if [[ -n $IPV6 ]]; then echo "$IPV6" >>$STA - echo "$IFACE GW6 $(ip -6 route show to default dev $IFACE)" >>$STA + GW6="$(ip -6 route show to default dev $IFACE)" + [[ -n $GW6 ]] && echo "$IFACE GW6 $GW6" >>$STA fi fi echo "USE_MTU=\"${USE_MTU[$i]}\"" >>$INI @@ -219,7 +221,8 @@ for ((i=0; i<${SYSNICS:-1}; i++)); do IPV4="$(ip -4 -br addr show scope global primary dev $DEV | awk '{$2="";print;exit}')" if [[ -n $IPV4 ]]; then echo "${IPV4/@$IFACE/}" >>$STA - echo "$DEV GW4 $(ip -4 route show to default dev $DEV)" >>$STA + GW4="$(ip -4 route show to default dev $DEV)" + [[ -n $GW4 ]] && echo "$DEV GW4 $GW4" >>$STA fi fi echo "USE_DHCP6:$j=\"${USE_DHCP6[$i,$j]}\"" >>$INI @@ -244,7 +247,8 @@ for ((i=0; i<${SYSNICS:-1}; i++)); do IPV6="$(ip -6 -br addr show scope global primary -deprecated dev $DEV | awk '{$2="";print;exit}')" if [[ -n $IPV6 ]]; then echo "${IPV6/@$IFACE/}" >>$STA - echo "$DEV GW6 $(ip -6 route show to default dev $DEV)" >>$STA + GW6="$(ip -6 route show to default dev $DEV)" + [[ -n $GW6 ]] && echo "$DEV GW6 $GW6" >>$STA fi fi done diff --git a/sbin/monitor_interface b/sbin/monitor_interface index db826a52f..e75779358 100755 --- a/sbin/monitor_interface +++ b/sbin/monitor_interface @@ -58,32 +58,44 @@ while :; do for i in ${!TASK[@]}; do ADDR=(${TASK[$i]}) PORT=${ADDR[0]} - [[ $LAST != $PORT ]] && STATE=$(state $PORT) + [[ $LAST != ${PORT%.*} ]] && STATE=$(state ${PORT%.*}) case $STATE in 1) # up case ${ADDR[1]} in GW4) # no existing default and new default is defined? - ROUTE=$(ip -4 route show to default dev $PORT) - [[ -z $ROUTE && "${TASK[$i]}" =~ "default" ]] && ip -4 route add dev ${TASK[$i]/GW4/} + IPV4=$(ip -4 -br addr show scope global primary dev $PORT | awk '{print $3;exit}') + if [[ -n $IPV4 ]]; then + ROUTE=$(ip -4 route show to default dev $PORT) + [[ -z $ROUTE ]] && ip -4 route add dev ${TASK[$i]/GW4/} + fi ;; GW6) # no existing default and new default is defined? - ROUTE=$(ip -6 route show to default dev $PORT) - [[ -z $ROUTE && "${TASK[$i]}" =~ "default" ]] && ip -6 route add dev ${TASK[$i]/GW6/} + IPV6=$(ip -6 -br addr show scope global primary -deprecated dev $PORT | awk '{print $3;exit}') + if [[ -n $IPV6 ]]; then + ROUTE=$(ip -6 route show to default dev $PORT) + [[ -z $ROUTE ]] && ip -6 route add dev ${TASK[$i]/GW6/} + fi ;; *) - # IP address not present? create it - [[ "$(ip -br addr show dev $PORT)" =~ "${ADDR[1]}" ]] || ip addr add dev ${TASK[$i]} + IPA=$(ip -br addr show to ${ADDR[1]} dev $PORT) + if [[ -f /var/tmp/$PORT.down ]]; then + # Special treatment for shim and vhost interfaces + [[ -n $IPA ]] && ip addr del dev ${TASK[$i]} + else + # IP address not present? create it + [[ -z $IPA ]] && ip addr add dev ${TASK[$i]} + fi ;; esac ;; 0) # down # IP address present, remove it - [[ "$(ip -br addr show dev $PORT)" =~ "${ADDR[1]}" ]] && ip addr del dev ${TASK[$i]} + [[ -n $(ip -br addr show to ${ADDR[1]} dev $PORT) ]] && ip addr del dev ${TASK[$i]} ;; esac - LAST=$PORT + LAST=${PORT%.*} done fi # check every 3 seconds