File: dhcp-all-interfaces.sh

package info (click to toggle)
python-diskimage-builder 3.37.0-2
  • links: PTS, VCS
  • area: main
  • in suites: forky, sid, trixie
  • size: 5,572 kB
  • sloc: sh: 7,380; python: 6,444; makefile: 37
file content (219 lines) | stat: -rwxr-xr-x 8,436 bytes parent folder | download | duplicates (2)
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
194
195
196
197
198
199
200
201
202
203
204
205
206
207
208
209
210
211
212
213
214
215
216
217
218
219
#!/bin/bash

if [ ${DIB_DEBUG_TRACE:-0} -gt 0 ]; then
    set -x
fi
set -eu
set -o pipefail

INTERFACE=${1:-} #optional, if not specified configure all available interfaces
ENI_FILE="/etc/network/interfaces"

PATH=/sbin:$PATH

if [ -d "/etc/network" ]; then
    CONF_TYPE="eni"
elif [ -d "/etc/sysconfig/network-scripts/" ]; then
    CONF_TYPE="rhel-netscripts"
    SCRIPTS_PATH="/etc/sysconfig/network-scripts/"
elif [ -d "/etc/sysconfig/network/" ]; then
    # SUSE network scripts location
    CONF_TYPE="suse-netscripts"
    SCRIPTS_PATH="/etc/sysconfig/network/"
else
    echo "Unsupported network configuration type!"
    exit 1
fi

ARGS="$0 $@"

function serialize_me() {
    if [ "$CONF_TYPE" == "eni" ]; then
        # Serialize runs so that we don't miss hot-add interfaces
        FLOCKED=${FLOCKED:-}
        if [ -z "$FLOCKED" ] ; then
            FLOCKED=true exec flock -x $ENI_FILE $ARGS
        fi
    fi
}

function get_if_link() {
    cat /sys/class/net/${1}/carrier || echo 0
}

function get_if_type() {
    cat /sys/class/net/${1}/type
}

function interface_is_vlan() {
    # Check if this is a vlan interface created on top of an Ethernet interface.
    local interface=$1

    # When the vlan interface is created, its mac address is copied from the
    # underlying address and the address assignment type is set to 2
    mac_addr_type=$(cat /sys/class/net/${interface}/addr_assign_type)
    if [ "$mac_addr_type" != "2" ]; then
        return 1
    fi

    # Only check for vlan interfaces named <interface>.<vlan>
    lower_interface="$(echo $interface | cut -f1 -d'.')"
    if [[ ! -z $lower_interface ]]; then
        mac_addr_type=$(cat /sys/class/net/${lower_interface}/addr_assign_type)
        if [ "$mac_addr_type" == "0" ]; then
            return 0 # interface is vlan
        fi
    fi

    return 1
}

function enable_interface() {
    local interface=$1
    local ipv6_init=$2
    local ipv6_AdvManagedFlag=$3
    local ipv6_AdvOtherConfigFlag=$4

    serialize_me
    if [ "$CONF_TYPE" == "eni" ]; then
        printf "auto $interface\niface $interface inet dhcp\n\n" >>$ENI_FILE
        if [ "$ipv6_init" == "True" ]; then
            # Make DUID-UUID Type 4 (RFC 6355)
            echo "default-duid \"\\x00\\x04$(sed 's/.\{2\}/\\x&/g' < /etc/machine-id)\";" >"/var/lib/dhcp/dhclient6--$interface.lease"
            if [ $ipv6_AdvManagedFlag == "Yes" ]; then
                # IPv6 DHCPv6 Stateful address configuration
                printf "iface $interface inet6 dhcp\n\n" >>$ENI_FILE
                echo "DHCPv6 Stateful Configured."
            elif [ $ipv6_AdvOtherConfigFlag == "Yes" ]; then
                # IPv6 DHCPv6 Stateless address configursation
                printf "iface $interface inet6 auto\n\tdhcp 1\n\n" >>$ENI_FILE
                echo "DHCPv6 Stateless Configured."
            else
                # IPv6 Autoconfiguration (SLAAC)
                printf "iface $interface inet6 auto\n\tdhcp 0\n\n" >>$ENI_FILE
                echo "IPv6 SLAAC Configured"
            fi
        fi
        printf "\n" >>$ENI_FILE
    elif [ "$CONF_TYPE" == "rhel-netscripts" ]; then
        if [ "$(get_if_type $interface)" == "32" ]; then
            printf "DEVICE=\"$interface\"\nBOOTPROTO=\"dhcp\"\nONBOOT=\"yes\"\nTYPE=\"InfiniBand\"\nCONNECTED_MODE=\"no\"\nDEFROUTE=\"yes\"\nPEERDNS=\"yes\"\nPEERROUTES=\"yes\"\nIPV4_FAILURE_FATAL=\"yes\"\nIPV6INIT=\"no\"" >"${SCRIPTS_PATH}ifcfg-$interface"
        else
            if interface_is_vlan $interface; then
                printf "DEVICE=\"$interface\"\nBOOTPROTO=\"dhcp\"\nONBOOT=\"yes\"\nVLAN=\"yes\"\n" >"${SCRIPTS_PATH}ifcfg-$interface"
            else
                printf "DEVICE=\"$interface\"\nBOOTPROTO=\"dhcp\"\nONBOOT=\"yes\"\nTYPE=\"Ethernet\"\n" >"${SCRIPTS_PATH}ifcfg-$interface"
            fi
            if [ "$ipv6_init" == "True" ]; then
                # Make DUID-UUID Type 4 (RFC 6355)
                echo "default-duid \"\\x00\\x04$(sed 's/.\{2\}/\\x&/g' < /etc/machine-id)\";" >"/var/lib/dhclient/dhclient6--$interface.lease"
                printf "IPV6INIT=\"yes\"\n" >>"${SCRIPTS_PATH}ifcfg-$interface"
                if [ $ipv6_AdvManagedFlag == "Yes" ]; then
                    # IPv6 DHCPv6 Stateful address configuration
                    printf "IPV6_FORCE_ACCEPT_RA=\"yes\"\nDHCPV6C=\"yes\"\n" >>"${SCRIPTS_PATH}ifcfg-$interface"
                    echo "DHCPv6 Stateful Configured"
                elif [ $ipv6_AdvOtherConfigFlag == "Yes" ]; then
                    # IPv6 DHCPv6 Stateless address configursation
                    printf "IPV6_AUTOCONF=\"yes\"\nDHCPV6C=\"yes\"\nDHCPV6C_OPTIONS=\"-S\"\n" >>"${SCRIPTS_PATH}ifcfg-$interface"
                    echo "DHCPv6 Stateless Configured"
                else
                    # IPv6 Autoconfiguration (SLAAC)
                    printf "IPV6_AUTOCONF=\"yes\"\n" >>"${SCRIPTS_PATH}ifcfg-$interface"
                    echo "IPv6 SLAAC Configured"
                fi
            fi
    fi
    elif [ "$CONF_TYPE" == "suse-netscripts" ]; then
        printf "BOOTPROTO=\"dhcp\"\nSTARTMODE=\"auto\"" >"${SCRIPTS_PATH}ifcfg-$interface"
    fi
    echo "Configured $1"

}


function config_exists() {
    local interface=$1
    if [[ "$CONF_TYPE" =~ "netscripts" ]]; then
        if [ -f "${SCRIPTS_PATH}ifcfg-$interface" ]; then
            return 0
        fi
    else
        if ifquery $interface >/dev/null 2>&1; then
            if [ -z "$(ifquery $interface 2>&1)" ]; then
                return 1
            else
                return 0
            fi
        else
            return 1
        fi
    fi
    return 1
}

function inspect_interface() {
    local interface=$1
    local mac_addr_type
    mac_addr_type=$(cat /sys/class/net/${interface}/addr_assign_type)

    echo -n "Inspecting interface: $interface..."
    if config_exists $interface; then
        echo "Has config, skipping."
    elif interface_is_vlan $interface || [ "$mac_addr_type" == "0" ]; then
        local has_link
        local tries=DIB_DHCP_TIMEOUT
        for ((; tries > 0; tries--)); do
            # Need to set the link up on each iteration
            ip link set dev $interface up &>/dev/null
            has_link=$(get_if_link $interface)
            [ "$has_link" == "1" ] && break
            sleep 1
        done
        if [ "$has_link" == "1" ]; then
            local ipv6_init=False
            local ipv6_AdvManagedFlag=No
            local ipv6_AdvOtherConfigFlag=No
            if type rdisc6 &>/dev/null; then
                # We have rdisc6, let's try to configure IPv6 autoconfig/dhcpv6
                tries=DIB_DHCP_TIMEOUT
                for ((; tries > 0; tries--)); do
                    # Need to retry this, link-local-address required for
                    # Neighbor Discovery, DHCPv6 etc.
                    set +e # Do not exit on error, capture rdisc6 error codes.
                    RA=$(rdisc6 --retry 3 --single "$interface" 2>/dev/null)
                    local return_code=$?
                    set -e # Re-enable exit on error.
                    if [ $return_code -eq 0 ]; then
                        ipv6_init=True
                        ipv6_AdvManagedFlag=$(echo "$RA" | grep "Stateful address conf." | awk -F: '{ print $2 }')
                        ipv6_AdvOtherConfigFlag=$(echo "$RA" | grep "Stateful other conf." | awk -F: '{ print $2 }')
                        break
                    elif [ $return_code -eq 1 ]; then
                        sleep 1
                    elif [ $return_code -eq 2 ]; then
                        # If rdisc6 does not receive any response after the
                        # specified number of attempts waiting for wait_ms
                        # (1000ms by default) milliseconds each time, it will
                        # exit with code 2.
                        break
                    fi
                done
            else
                echo "rdisc6 not available, skipping IPv6 configuration."
            fi
            enable_interface "$interface" "$ipv6_init" "$ipv6_AdvManagedFlag" "$ipv6_AdvOtherConfigFlag"
        else
            echo "No link detected, skipping"
        fi
    else
        echo "Device has generated MAC, skipping."
    fi
}

if [ -n "$INTERFACE" ]; then
    inspect_interface $INTERFACE
else
    for iface in $(ls /sys/class/net | grep -v ^lo$); do
        inspect_interface $iface
    done
fi