#!/bin/sh
# $Id: udhcpc-post,v 1.15 2009-08-25 11:04:49 c00jhs00 Exp $
#
# Modified by Steven Shiau <steven _at_ nchc org tw>
# and K. L. Huang < c00hkl00@nchc.org.tw>, to fit DRBL, 2003/01/05
# Now you can specified the kernel you want, and it will scan the specific
# kernel
# 2006/02/28
# Thanks to James MacLean for providing clientdir method in kernel cmdline.
# Now it looks like:
# append initrd=initrd-pxe.img ramdisk_size=12288 devfs=nomount drblthincli=off selinux=0 clientdir=node_root

# Load setting
. /etc/linuxrc.conf

# Functions
get_drbl_nfsroot(){
  # Priority for NFSroot server
  # (1) If ipappend of syslinux is assigned, we use the bootp next server shown in /proc/cmdline first.
  #     Ref: http://www.syslinux.org/wiki/index.php?title=SYSLINUX
  # (2) If grub mechanism is assigned (drbl_bootp=<ip>), we use that
  # (3) Use the one "nfsroot_srv_ip" assigned in /etc/linuxrc.conf
  # (4) Use the bootp next server, i.e. "siaddr" from environmental variable.
  # (5) Use the DHCP server "serverid" 
  # Ref: https://udhcp.busybox.net/README.udhcpc for (4) and (5).

  # (1) ip=<client-ip>:<boot-server-ip>:<gw-ip>:<netmask> in /proc/cmdline
  #     e.g., ip=192.168.1.1:192.168.1.254:192.168.1.254:255.255.255.0
  nfsroot_srv="$(LC_ALL=C grep -Eo "ip=[[:digit:]\.:]+([[:space:]]|$)+" /proc/cmdline | sed -e "s/ip=//g" | cut -d":" -f2)"
  if [ -n "$nfsroot_srv" ]; then
    echo "NFS root - use the bootp next server found from PXELinux in /proc/cmdline: $nfsroot_srv"
  fi

  # (2) grub way
  if [ -z "$nfsroot_srv" ]; then
    nfsroot_srv="$(LC_ALL=C grep -Eo "drbl_bootp=[[:digit:]\.]+([[:space:]]|$)+" /proc/cmdline | cut -d"=" -f2)"
    if [ -n "$nfsroot_srv" ]; then
      echo "NFS root - use the bootp next server found from Grub in /proc/cmdline: $nfsroot_srv"
    fi
  fi

  # (3) Use nfsroot_srv_ip from /etc/linuxrc.conf
  if [ -z "$nfsroot_srv" ]; then
     if [ -n "$nfsroot_srv_ip" ]; then
       nfsroot_srv="$nfsroot_srv_ip"
       echo "NFS root - use the NFS root server assigned in /etc/linuxrc.conf: $nfsroot_srv_ip"
     fi
  fi

  # (4) Use bootp next server "siaddr"
  if [ -z "$nfsroot_srv" ]; then
     if [ -n "$siaddr" ]; then
       nfsroot_srv="$siaddr"
       echo "NFS root - use the bootp next server assigned from DHCP server: $nfsroot_srv"
     fi
  fi

  # (5) Use DHCP server "serverid"
  if [ -z "$nfsroot_srv" ]; then
     if [ -n "$serverid" ]; then
       nfsroot_srv="$serverid"
       echo "NFS root - use the DHCP server: $nfsroot_srv"
     fi
  fi

  if [ -z "$nfsroot_srv" ]; then
     echo "*****************************************"
     echo "DRBL NFS root server IP address NOT found!"
     echo "*****************************************"
     echo "Program terminated!"
     exit 1
  fi
} # end of get_drbl_nfsroot
#
#RWSIZE_OPT="rsize=65536,wsize=65536"
RWSIZE_OPT=""
case "$nfs_prot_in_initrd" in
  nfs4) # NFS4
	ROOT_NFS_OPT="ro,nolock,$RWSIZE_OPT"
	# fstype is used for mount -t $fstype
	fstype="nfs4"
	;;
     *) # NFS3
	ROOT_NFS_OPT="ro,nfsvers=3,tcp,nolock,$RWSIZE_OPT"
	# fstype is used for mount -t $fstype
	fstype="nfs"
	;;
esac

# We can assign the root directory for clients, but it's rare, and you still
# have to modify a lot of settings, such as /etc/exports in server.
# For PXE, it's clientdir=node_root in /proc/cmdline, while 
# for GRUB uEFI NB, it's clientdir=\"node_root\"
#(added by function add_opt_in_grub_efi_cfg_block) in /proc/cmdline.
# It should be converted to be clientdir="node_root" by grub, 
# like the cases in the booting of CD or USB flash drive.
# However somehow the GRUB uEFI NB has different behavior.
# Therefore here we have to deal with clientdir=node_root or clientdir=\"node_root\"
clientdir="$(LC_ALL=C grep clientdir /proc/cmdline | sed -e "s/.*clientdir=\([^ ]\+\).*$/\1/" | sed -e 's|\"||g' -e 's|\\||g')"
if [ -z "$clientdir" ]; then
  # Use the default one if not assigned. Normally we will use node_root always. 
  clientdir=node_root
fi

if [ "$1" = "deconfig" ]; then
  ifconfig $interface 0.0.0.0 up
  TIMEOUT="$sleep_time_after_NIC_up"
  echo -n "Sleep for $sleep_time_after_NIC_up sec(s) to wait for this NIC ready... "
  while [ "$TIMEOUT" -gt 0 ]; do
    echo -n "$TIMEOUT "
    sleep 1
    TIMEOUT="$((TIMEOUT - 1))"
  done
  echo
else if [ "$1" = "bound" ] ; then
    echo $sname > /dev/sname
    # Do we want to check server name ?
    case "$check_server_name" in
      n|N|[nN][oO])
	echo "I do not care which DHCP server provides me an IP address..."
	echo "DHCP server name now is: $sname"
        ;;
      *)
	echo "I just want DHCP server with server name \"$dhcp_server_name\" provides me an IP address..."
	echo "DHCP server name now is: $sname"
        # force to get the right dhcp server, i.e we want $dhcp_server_name server
        [ "$sname" != "$dhcp_server_name" ] && exit
        ;;
    esac

    # If the rootpath is empty, it's not DRBL server,
    #we will try to get another IP from dhcpd server 
    #[ -z "$rootpath" ] && exit 1
    echo "UDHCPC: I am $ip, booting from $serverid"
    [ -n "$hostname" ] && echo $hostname > /proc/sys/kernel/hostname
    [ -n "$broadcast" ] && BROADCAST="broadcast $broadcast"
    [ -n "$subnet" ] && NETMASK="netmask $subnet" 
    ifconfig $interface $ip $BROADCAST $NETMASK
    route add default gw $router dev $interface
    echo -n > /etc/resolv.conf
    for i in $dns; do
      echo nameserver $i >> /etc/resolv.conf
    done
    get_drbl_nfsroot  # Obtain $nfsroot_srv
    case "$nfs_prot_in_initrd" in
      nfs4) # NFS4
            # Start idmapd, in initrd only root account is available. Later we will stop rpc.idmapd before exiting initrd.
            echo "Starting rpc.idmapd..."
            rpc.idmapd -U root &
            [ -z "$rootpath" ] && rootpath="$nfsroot_srv:/$clientdir"
	    ;;
         *) # NFS3
            [ -z "$rootpath" ] && rootpath="$nfsroot_srv:/tftpboot/$clientdir"
	    ;;
    esac
    # erase the space
    rootpath_=`echo $rootpath | sed -e "s/ //g"`
    rootpath="$rootpath_"
    echo "rootpath=$rootpath"
    echo "Mounting root filesystem $rootpath at /sysroot..."
    echo "If this appears to hang, check"
    kernel_ver=`uname -r`
    echo "1. Is the driver of the network card loaded successfully in this computer ? Press Shift-PageUp to check the message in the screen ? If not, maybe this network card is too new so in this kernel \"$kernel_ver\" a suitable driver is not available! Run /bin/ls_pciid.sh then compare the results with the file /usr/lib/mkpxeinitrd-net/initrd-skel/etc/pcitable in the DRBL server."
    echo "2. The TCPwrapper setting (/etc/hosts.allow and /etc/hosts.deny) and firewall rules in your DRBL server, do you block the clients ?"
    echo "3. Is there any other dhcp server in this subnet ?"
    echo "4. The server of $rootpath is able to reverse-map my IP address $ip to obtain my hostname $hostname."
    echo "check http://drbl.org/faq for more details!"

    echo "Mounting root filesystem $rootpath at /sysroot with option \"$ROOT_NFS_OPT\"..."
    mount -t $fstype -n -o $ROOT_NFS_OPT $rootpath /sysroot
    retv=$?
    if [ "$retv" -eq 0 ]; then
      echo "Mounted the root filesystem successfully! Continue..."
    else
      echo "Failed to mount the root filesystem! Something went wrong!!!"
    fi

  fi
fi
