blob: 7d80c6f7bc6363554490334edfacf66143c03fbc [file] [log] [blame]
#!/bin/bash
# Copyright 2017 The Fuchsia Authors. All rights reserved.
# Use of this source code is governed by a BSD-style license that can be
# found in the LICENSE file.
# This script take a network interface (eg: tap0) as its only argument. It sets
# up that interface for running a Fuchsia device. It runs dnsmasq to provide
# DHCP and DNS to the Fuchsia device. It configures NAT. It will do its best to
# kill old instances of dnsmasq from previous runs of the script for this
# interface.
#
# If the environment variable FUCHSIA_IP is set it will give that IP to the
# Fuchsia device, otherwise, for historical reasons it will allocate
# 192.168.3.53.
set -eo pipefail; [[ "${TRACE}" ]] && set -x
INTERFACE=$1
LEASE_FILE=/tmp/fuchsia-dhcp-$INTERFACE.leases
PID_FILE=/tmp/fuchsia-dhcp-$INTERFACE.pid
LOG_FILE=/tmp/fuchsia-dhcp-$INTERFACE.log
if [[ -z "$INTERFACE" ]]
then
echo "Missing interface name."
exit 1
fi
FUCHSIA_IP=${FUCHSIA_IP:-192.168.3.53} # is this a good dfault?
if [[ ! ${FUCHSIA_IP} =~ (^[0-9]+\.[0-9]+\.[0-9]+)\.[0-9]+$ ]]
then
echo "Invalid FUCHSIA_IP '${FUCHSIA_IP}'. Must be a valid IPv4 address."
exit 1
fi
SUBNET_PREFIX=${BASH_REMATCH[1]}
FUCHSIA_NETWORK=${SUBNET_PREFIX}.0/24
HOST_IP=${SUBNET_PREFIX}.1
DARWIN=false
if [[ $(uname -s) == Darwin ]]
then
DARWIN=true
fi
# Find the dnsmasq binary.
DNSMASQ=$(which dnsmasq) || DNSMASQ=$(brew --prefix)/sbin/dnsmasq
if [[ ! -x "$DNSMASQ" ]]
then
echo "dnsmasq not found."
if $DARWIN
then
echo " brew install dnsmasq"
else
echo " apt-get install dnsmasq"
fi
exit 1
fi
# Check if dnsmasq is running.
if [[ -r ${PID_FILE} ]]
then
# Read the PID file.
DNSMASQ_PID=$(<${PID_FILE})
# Check that the PID file actually refers to a dnsmasq process.
if $DARWIN
then
DNSMASQ_PID_NAME=$( (ps -A -o comm ${DNSMASQ_PID} || true) | tail +2)
if [[ "${DNSMASQ_PID_NAME}" -ne "${DNSMASQ}" ]]
then
# There's a PID file but the process name isn't right.
unset DNSMASQ_PID
fi
else
if [[ /proc/$DNSMASQ_PID/exe -ef $DNSMASQ ]]
then
# There's a PID file but the process name isn't right.
unset DNSMASQ_PID
fi
fi
if [[ -n "$DNSMASQ_PID" ]]
then
echo "Killing the old dnsmasq (pid: $DNSMASQ_PID)..."
sudo kill $DNSMASQ_PID || true
sudo rm -f ${PID_FILE}
fi
fi
if [[ -f "$LEASE_FILE" ]]
then
echo "Removing the old dnsmasq lease file $LEASE_FILE ..."
sudo rm $LEASE_FILE
fi
# Bring up the network.
echo "Bringing up the network interface: $INTERFACE"
sudo ifconfig $INTERFACE inet ${HOST_IP}
if $DARWIN
then
# On macOS the IPv6 link local address needs to be explicitly configured.
# Calculate the link-local IPv6 address for $INTERFACE
function calc_link_local() {
local mac
IFS=':' read -ra mac <<< "$1"
mac[0]=$(printf "%x\n" "$((0x${mac[0]} ^ 0x2))")
echo fe80::${mac[0]}${mac[1]}:${mac[2]}ff:fe${mac[3]}:${mac[4]}${mac[5]}
}
MAC=`ifconfig $INTERFACE | awk '/ether/ {print $2}'`
LINK_LOCAL=`calc_link_local $MAC`
sudo ifconfig $INTERFACE inet6 $LINK_LOCAL
fi
echo Starting dnsmasq...
# TODO: can we use --dhcp-host instead of --dhcp-range
sudo $DNSMASQ --interface=$INTERFACE \
--dhcp-range=$INTERFACE,${FUCHSIA_IP},${FUCHSIA_IP},24h \
--dhcp-leasefile=$LEASE_FILE \
--pid-file=${PID_FILE} \
--log-facility=${LOG_FILE} \
--listen-address=${HOST_IP}
if $DARWIN
then
DEFAULT_INTERFACE=$(route -n get default | awk '/interface:/ { print $2 }') || true
else
DEFAULT_INTERFACE=$(ip route get 8.8.8.8 | awk '/^8.8.8.8/ { print $5 }')
fi
if [[ -z "$DEFAULT_INTERFACE" ]]
then
echo "No default route, not enabling forwarding."
else
echo "Enable IP forwarding..."
if $DARWIN
then
sudo sysctl -q net.inet.ip.forwarding=1
echo "
nat on $DEFAULT_INTERFACE from ${FUCHSIA_NETWORK} to any -> ($DEFAULT_INTERFACE)
pass out on $DEFAULT_INTERFACE inet from ${FUCHSIA_NETWORK} to any
" | sudo pfctl -q -ef - >& /dev/null || true
else
sudo /bin/bash -c "echo 1 > /proc/sys/net/ipv4/ip_forward"
sudo iptables -t nat -A POSTROUTING -o ${DEFAULT_INTERFACE} -j MASQUERADE
sudo iptables -A FORWARD -i ${DEFAULT_INTERFACE} -o ${INTERFACE} -m state --state RELATED,ESTABLISHED -j ACCEPT
sudo iptables -A FORWARD -i ${INTERFACE} -o ${DEFAULT_INTERFACE} -j ACCEPT
fi
fi