Make the script to configure the network cross-platform and general purpose

Change-Id: I977f1c85141433cba158e221f22a25372010e0bb
diff --git a/ifup-qemu-mac.sh b/ifup-qemu-mac.sh
deleted file mode 100755
index 9075b24..0000000
--- a/ifup-qemu-mac.sh
+++ /dev/null
@@ -1,85 +0,0 @@
-#!/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.
-
-set -eo pipefail; [[ "${TRACE}" ]] && set -x
-
-if [[ `uname -s` -ne Darwin ]]
-then
-  echo '$0 only supports macOS right now.'
-  exit 1
-fi
-
-INTERFACE=$1
-SUBNET_PREFIX=${SUBNET_PREFIX:-192.168.3}
-LEASE_FILE=/tmp/fuchsia-dhcp-leases.$INTERFACE
-
-if [[ -z "$INTERFACE" ]]
-then
-  echo "Missing interface name."
-  exit 1
-fi
-
-if [[ ! "$SUBNET_PREFIX" =~ ^[0-9]+\.[0-9]+\.[0-9]$ ]]
-then
-  echo "Invalid SUBNET_PREFIX '$SUBNET_PREFIX'. Must be in the form '1.2.3'"
-  exit 1
-fi
-
-# Check if dnsmasq is running.
-DNSMASQ_PID=`ps -Ac -o pid,comm | awk '/^ *[0-9]+ dnsmasq$/ {print $1}'`
-
-# 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`
-
-# Bring up the network.
-echo "Bringing up the network interface: $INTERFACE"
-sudo ifconfig $INTERFACE inet ${SUBNET_PREFIX}.1
-sudo ifconfig $INTERFACE inet6 $LINK_LOCAL
-if [[ -n "$DNSMASQ_PID" ]]
-then
-  echo "Killing the old dnsmasq (pid: $DNSMASQ_PID)..."
-  sudo kill $DNSMASQ_PID
-fi
-
-if [[ -f "$LEASE_FILE" ]]
-then
-  echo "Removing the old dnsmasq lease file $LEASE_FILE ..."
-  sudo rm $LEASE_FILE
-fi
-
-
-# Look for dnsmasq in the path and then homebrew.
-DNSMASQ_PATH=$(which dnsmasq) || \
-  DNSMASQ_PATH=$(brew --prefix)/sbin/dnsmasq && test -x $DNSMASQ_PATH || \
-  (
-    echo dnsmasq not found. Install it from homebrew.
-    exit 1
-  )
-
-echo Starting dnsmasq...
-sudo $DNSMASQ_PATH --interface=$INTERFACE \
-  --dhcp-range=$INTERFACE,${SUBNET_PREFIX}.50,${SUBNET_PREFIX}.150,24h \
-  --dhcp-leasefile=$LEASE_FILE \
-  --listen-address=${SUBNET_PREFIX}.1
-
-echo "Enable IP forwarding..."
-DEFAULT_INTERFACE=`route -n get default | grep interface | awk '{print $2}'` || true
-if [[ -z "$DEFAULT_INTERFACE" ]]
-then
-  echo "No default route, not enabling forwarding."
-else
-  sudo sysctl -q net.inet.ip.forwarding=1
-  echo "
-  nat on $DEFAULT_INTERFACE from ${SUBNET_PREFIX}.0/24 to any -> ($DEFAULT_INTERFACE)
-  pass out on $DEFAULT_INTERFACE inet from ${SUBNET_PREFIX}.0/24 to any
-  " | sudo pfctl -q -ef - >& /dev/null || true
-fi
diff --git a/start-dhcp-server.sh b/start-dhcp-server.sh
new file mode 100755
index 0000000..7d80c6f
--- /dev/null
+++ b/start-dhcp-server.sh
@@ -0,0 +1,151 @@
+#!/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