#!/bin/sh
# Written to simply set the IP stuff up from the
# bootpc data.
# Last updated : Tue Apr 16 17:16:07 1996
#  Jon Peatfield
#
# with modifications as suggested by Austin Donnelly, Chris Hall,
# Donal K Fellows and choltje@ux1.cso.uiuc.edu.
#
# Paranoid checks as required for broken PWF bootp server (This is a
# novell bootp server which can give the same address to different
# machines!!)
#
# Setup of hosts file modified as suggested by Carl Olson
# <c-olson@uiuc.edu> to get the local IP address right when using some
# resolver options...
#
# Version 0.50
#set -x

## The following options are policy decisions you may want to choose
## for the machines on your site.  i.e. if you don't edit it you get
## what I use!   -- Jon

#  If your bootp server gives the same IP address 2 machines
#  occasionally this does extra checks to ensure noone else has the
#  address it was given.
PARANOID='y'

# If you want the error from the paranoid check to mention an contact
# Then put it here
ADMINIST='You might try the help-desk for example.'

# If you prefer FQDN names rather than leafnames set to 'y';
# This causes the code to ignore the HOSTNAME returned by the BOOTP
# server and do a gethostbyname() on the IP number we were given.
# This will only work if the resolver can be set up or you have the
# correct entry in /etc/hosts (!)
FORCEFQDN='y'

# If you want to add any extra options to ifconfig (e.g. pointopoint)
# The first is used before the bootp the 2nd afterwards and is
# expanded using `eval echo ${IFCONFOPTS2}` so will expand variables
# then (when they are known) not now.
##IFCONFOPTS1='mtu 400 pointopoint'
##IFCONFOPTS2='mtu 400 pointopoint $SERVER'

# Put search not domain line in resolv.conf for 4.9.3 based resolver
# code (still works with older code too) if you like the old 4.8.3
# search rules with the new resolver code then set to 'y'
MAKESEARCH='y'

## YOU MAY NEED TO EDIT THESE FOR DIFFERENT DISTRIBUTIONS
# Location of the bootpc program
BOOTPC=/usr/local/sbin/bootpc
# location of ifconfig
IFCONFIG=/sbin/ifconfig
# location of route
ROUTE=/sbin/route
# location of hostname binary
BINHOST=/bin/hostname

## Details of bootp to perform
# What device to do the bootp on
DEV=eth0

# What address to send bootp request to (broadcast by default)
ASKSERVER="255.255.255.255"

# To set the time we are willing to wait for a reply (roughly)
# This defaults to 70 seconds anyway in the code.
TW="--timeoutwait 70"

# If you want bootpc to exit on failure and take down networking then
# uncomment these line:
RIF="--returniffail"
RIFMESSAGE="Bootp failed -- disabling network."

## Shouldn't change location, but...
# The location of the resolver config file
RCONF=/etc/resolv.conf
# location of the hosts file
EHOSTS=/etc/hosts
# location of the local hosts file..
LHOSTS=/etc/hosts.local

## Location of tmp file for storing options
TMPFILE=/tmp/bootp-results.$$

# For testing purposes I uncomment these They probably arn't usefult
# to you.  -- Jon
#BOOTPC=./bootpc
#IFCONFIG='echo ifconfig'
#ROUTE='echo route'
#BINHOST='echo hostname'
#RCONF=/tmp/resolv.conf
#EHOSTS=/tmp/hosts
#LHOSTS=/dev/null
#ASKSERVER="131.111.255.255"
#TW="--timeoutwait 20"
## This will fail when testing as we reply to our own PING...
#PARANOID=''
#set -x

## Start of the functions
# Stick the nameserver lines in the resolver file.
setservers() {
# Insert the DNS servers themselves
  for i in $1
  do
    echo "nameserver $i" >> ${RCONF}
  done
}

# A function for setting the DNS stuff if we have all the info
setresolv() {
  [ -f ${RCONF} ] && mv -f ${RCONF} ${RCONF}.old
# Insert provided information
  if [ "${MAKESEARCH}" = 'y' ]; then
    echo "search $2" > ${RCONF}
  else
    echo "domain $1" > ${RCONF}
  fi
  setservers "$3"
}

# A function for setting the DNS stuff if we don't know out domainname
fakeresolv() {
  [ -f ${RCONF} ] && mv -f ${RCONF} ${RCONF}.fake
# This means nothing, but provides a domain line (some(old) revolvers
#  break if there isn't one present.)
  echo "domain ." > ${RCONF}
  setservers "$1"
}

# And putting the original back if it exists
unfakeresolv() {
  [ -f ${RCONF}.fake ] && mv -f ${RCONF}.fake ${RCONF}
}

# update the DNSSERVERS but not the domainname, in case of
# reverse lookup failure.
updateresolv() {
  [ -f ${RCONF} ] && mv -f ${RCONF} ${RCONF}.old
# Copy over the domainname from the old file
  grep 'domain|search' ${RCONF}.old > ${RCONF}
  setservers "$1"
}

# Remove the networking by taking down the interface
netdown() {
  ${ROUTE} del default
  ${IFCONFIG} ${DEV} down
}
## End of the functions

## Start of the actual work
# Bring up minimal networking use 0.0.0.0 as our address as we don't
# know it yet (Means "Me but I don't know my address or network")
${IFCONFIG} ${DEV} up ${IFCONFOPTS1} 0.0.0.0
${ROUTE} add default dev ${DEV}

# Perform the bootp  --  doesn't return unless it gets an answer
if ${BOOTPC} --dev ${DEV} --server ${ASKSERVER} ${RIF} ${TW} > ${TMPFILE}
then
# Take down networking (use the 0.0.0.0 for as short a time as possible)
  netdown
# Read in the values   
  eval ${TMPFILE}
# And delete the temporary file
  rm ${TMPFILE}
else
# Take down networking (use the 0.0.0.0 for as short a time as possible)
  netdown
# give message and quit
  echo ${RIFMESSAGE}
  exit 1
fi

# If being paranoid do the ping test
if [ "$PARANOID" = 'y' ]; then
# Bring up networking with the network number as our IP address
# This is are problems (either in Linux's IP code or in many vendors
# ICMP handlers), which mean we don't see replies if we send them out
# from 0.0.0.0.  We can't use OUR IP address here or we will always
# reply to our ping test, so we use the netnumber and zero host which
# means "Me on this network"
  ${IFCONFIG} ${DEV} up ${IFCONFOPTS1} ${NETWORK}
  ${ROUTE} add default dev ${DEV}

  if ${BOOTPC} --ping ${IPADDR}; then
# Remove networking as we can now 
    netdown
    cat <<EOERROR

			WARNING WARNING WARNING

	The IP address allocated to this machine by the bootp server is
	already in use by another machine.  This is an unrecoverable error.
	This machine will now loop, reboot to retry.

	Please report this to your network administrator or bootp server
	manager.  ${ADMINIST}

	They may be helped by knowing the following information:

	IP-ADDRESS: ${IPADDR}	SERVER: ${SERVER}

EOERROR
# Hang here.
    while :; do sleep 600 ; done
    exit 2
  fi
# Ping wasn't replied to, so take down networking (again)
  netdown
fi

# Only SERVER and IPADDR are guarenteed by the bootp (assuming
# It works), so check the rest.

# Start the loopback interface and add a route to it
${IFCONFIG} lo 127.0.0.1
${ROUTE} add -net 127.0.0.0

# Setup of IP stuff needs doing first
#
if [ -z "${NETMASK}" ] ; then
# No netmask info, all this is guessed from the IP number
# If this is wrong for your network FIX the bootpd to know
# what it should send in the RFC1497 cookie!  11/02/94 JSP
#
  ${IFCONFIG} ${DEV} up ${IPADDR} broadcast ${BROADCAST} `eval echo ${IFCONFOPTS2}`
  ${ROUTE} -n add -net ${NETWORK} dev ${DEV}
else
# We will have NETMASK, BROADCAST, and NETWORK defined 
  ${IFCONFIG} ${DEV} up ${IPADDR} broadcast ${BROADCAST} netmask ${NETMASK} `eval echo ${IFCONFOPTS2}`
  ${ROUTE} -n add -net ${NETWORK} dev ${DEV}
fi

# Gateways need IP to be able to add the (primary) route.
#
if [ -z "${GATEWAYS}" ] ; then
# No gateways defined
  echo "No IP gateways defined in rc.bootp setup"
else
# First one listed is supposedly our best, so only use it.
  ( set - ${GATEWAYS} ; ${ROUTE} add default gw ${1} )
fi

# May need Gateways if the DNS servers are on the other side of the
# gateways, this needs IP to be up.
#
# Can we set up DNS?
if [ ! -z "${DNSSRVS}" ]; then
  if [ ! -z "${DOMAIN}" ]; then
    setresolv "${DOMAIN}" "${SEARCH}" "${DNSSRVS}" 
  else
# At least we have DNS, so use reverse lookup to get the information
# Fake the resolver setup to do the reverse lookup.
    fakeresolv "${DNSSRVS}" 
    eval `${BOOTPC} --in2host ${IPADDR}`
    unfakeresolv
    if [ ! -z "${HOSTDOMAIN}" ]; then
# Got a domain, so use it
      setresolv "${HOSTDOMAIN}" "${HOSTSEARCH}" "${DNSSRVS}"
    else
# We have DNSSRVS but no DOMAIN, and reverse lookup failed
# If the resolver file is there use it's domainname
      if [ -f ${RCONF} ] ; then
	echo "Using old value from /etc/resolve.conf for domain/search"
	updateresolv "${DNSSRVS}"
      else
        echo "No BOOTP DOMAIN supplied"
	echo "  reverse lookup failed"
	echo "  and no existing resolver file"
	echo "=>   resolver setup failed"
      fi
    fi
  fi
else
  echo "No DNSSRVS supplied, resolver setup not possible"
fi

# May need DNS lookups if not provided by bootpd
#
# Set the hostname from what we got via bootp or reverse lookup

echo "127.0.0.1	loopback localhost">${EHOSTS}

if [ ! -z "${HOSTNAME}" -a "${FORCEFQDN}" != 'y' ]; then
  ${BINHOST} "${HOSTNAME}"
  echo "${IPADDR}	${HOSTNAME}" >>${EHOSTS}
else
  if [ -z "${DONEIN2HOST}" ] ; then
    eval `${BOOTPC} --in2host ${IPADDR}`
  fi
  if [ -z "${FORCEFQDN}" ]; then
# Use the leafname from the result
    if [ ! -z "${HOSTLEAF}" ]; then
      ${BINHOST} "${HOSTLEAF}"
      echo "${IPADDR}	${HOSTLEAF} ${HOSTFULL}">>${EHOSTS}
    fi
  else
# Use the FQDN from the result
    if [ ! -z "${HOSTFULL}" ]; then
      ${BINHOST} "${HOSTFULL}"
      echo "${IPADDR}	${HOSTFULL} ${HOSTLEAF}">>${EHOSTS}
    fi
  fi
fi
#
# And add the local hosts file (if any in too)
#
if [ -f ${LHOSTS} ]; then
  cat ${LHOSTS} >> ${EHOSTS}
fi

# None of this is relevant to IP startup but may be handy for some people
#
# Tell them about other info we got back, but don't use it
# 'cos I'm too lazy to write code for this...
#
# Print out a value if present  JSP
printifhere() {
  [ ! -z "$2" ] && echo "$1 = $2"
}

printifhere	TIMESRVS	"${TIMESRVS}"
printifhere	IEN116SRVS	"${IEN116SRVS}"
printifhere	LOGSRVS		"${LOGSRVS}"
printifhere	QODSRVS		"${QODSRVS}"
printifhere	LPRSRVS		"${LPRSRVS}"
printifhere	IMPRESSSRVS	"${IMPRESSSRVS}"
printifhere	RLPSRVS		"${RLPSRVS}"
printifhere	SWAPSRVR	"${SWAPSRVR}"
printifhere	BOOTFILE	"${BOOTFILE}"
printifhere	TIMEOFFSET	"${TIMEOFFSET}"
printifhere	BOOTSIZE	"${BOOTSIZE}"
printifhere	YPDOMAIN	"${YPDOMAIN}"
printifhere	YPSRVR		"${YPSRVR}"
printifhere	NTPSRVS		"${NTPSRVS}"


#
#
## End of the main work
