#!/bin/sh
#
# Starts networking, including network bridge for USB gadgets
#
# Things have become a bit complex:
# a) We may have two USB interfaces, one for the host port and one for
#    the device port.
#    The first interface (host port) is used for the master-slave communication where
#    the slave communicates via its host port with the device port of the master.
#    The latter interface (device port) is for logging in via a USB cable
#    (does not work on masters.)
# b) We need two interfaces on the 'br-usb-device' bridge, one for RNDIS (to be able to
#    talk to Windows 10) and one for CDC_Ether (to talk to cdc_ether driver on Linux.)
#    The gadgets are created in S39prepare_networking, the bridge is created here
#    and the two gadgets are added to it here. Their MAC addresses are derived
#    from the MAC address of the bridge by replacing just the first octet
#    (42 for the bridge) by '02', '12', '22', or '32'.
#

. /lib/ebee_funcs
. /opt/ebee/lib/net_funcs


# Interface names of the bridge and the two gadgets

bridge_name="br-usb-device"

rndis_name="usb-rndis"
cdc_ether_name="usb-cdc-ether"

bridge_up()
{
    # After an update, the etc/network/interfaces file may still contain
    # the old 'usb0' interface name for the bridge.
    # Replace it by the new 'br-usb-device' interface name for the bridge
    # to make sure 'ifup -a' will bring it up later.

    local readonly interfaces=$(readlink -f /opt/ebee/etc/network/interfaces)
    old_name="usb0"
    if grep -q "iface ${old_name} inet static" ${interfaces}
    then
        cp -a ${interfaces} ${interfaces}.tmp && \
        sed -i "s/${old_name}/${bridge_name}/" ${interfaces}.tmp \
        && sync && mv ${interfaces}.tmp ${interfaces} && sync
    fi

    # Get MAC address of the bridge. We rely on it not to start with
    # '[0123]2' as addresses starting that way are used for the
    # interfaces in the bridge. If it does, fix it by setting the
    # first octet to '42'.

    br_mac=$(get_mac.sh "${bridge_name}")
    if (echo "${br_mac}" | grep -q '^[0123]2')
    then
        echo "Fixing bridge MAC address '${br_mac}'"
        br_mac="42$(echo -n ${br_mac} | sed 's/[^:]*//')"
    fi

    # Create the bridge and set its MAC address

    brctl addbr "${bridge_name}"
    ip link set "${bridge_name}" address "${br_mac}"

    # Add USB gadgets to the bridge.
    # The MAC of the RNDIS and CDC_Ether interfaces are the
    # same as that of the bridge, just differing only in
    # the first octet. Add those 2 interfaces to the bridge
    # after checking that they exist and renaming them.

    mac="$(echo -n ${br_mac} | sed 's/[^:]*//')"

	rndis_mac="02${mac}"                  # as set by S39prepare_networking
    old_name="$(find_net_interface_by_mac ${rndis_mac})"
    if [ -z "${old_name}" ]
    then
        echo "USB RNDIS gadget not working"
    else
        ip link set "${old_name}" name "${rndis_name}"
        ifconfig "${rndis_name}" 0.0.0.0
        brctl addif "${bridge_name}" "${rndis_name}"
    fi

    cdc_ether_mac="22${mac}"              # as set by S39prepare_networking
    old_name="$(find_net_interface_by_mac ${cdc_ether_mac})"
    if [ -z "${old_name}" ]
    then
        echo "USB CDC-Ether gadget not working"
    else
        ip link set "${old_name}" name "${cdc_ether_name}"
        ifconfig "${cdc_ether_name}" 0.0.0.0
        brctl addif "${bridge_name}" "${cdc_ether_name}"
    fi
}

bridge_down()
{
    # Tear down the bridge as well as the interfaces it was controlling

    ifconfig "${cdc_ether_name}" down
    ifconfig "${rndis_name}" down

    ifconfig "${bridge_name}" down

    brctl delif "${bridge_name}" "${cdc_ether_name}"
    brctl delif "${bridge_name}" "${rndis_name}"

    brctl delbr "${bridge_name}"
}


start_network()
{
    echo -n "Starting network: "

    # Attach the two interfaces, one for RNDIS and one for CDC_Ether
    # (started by S39prepare_networing), to a bridge named 'br-usb-device'.
    bridge_up

    # Bring up all interfaces marked 'auto' in /etc/network/interfaces.

    ifup -a

    echo "done"
}

stop_network()
{
    echo -n "Stopping network: "

    # Take down all interfaces that are currently up.
    ifdown -a

    # Detach the two related interfaces from the bridge and remove the bridge.
    bridge_down

    echo "done"
}


case "$1" in
    start)
        start_network
        ;;

    stop)
        stop_network
        ;;

    restart|reload)
        "$0" stop
        "$0" start
        ;;

    *)
        echo "Usage: $0 {start|stop|restart}"
        exit 1
        ;;
esac


# Local variables:
# tab-width: 4
# indent-tabs-mode: nil
# End:
