2e2c49
#!/bin/bash
2e2c49
2e2c49
ROOTDIR="$1"
2e2c49
CONFIG_FILES="${3:-/etc/named-chroot.files}"
2e2c49
2e2c49
usage()
2e2c49
{
2e2c49
  echo
2e2c49
  echo 'This script setups chroot environment for BIND'
2e2c49
  echo 'Usage: setup-named-chroot.sh ROOTDIR <on|off> [chroot.files]'
2e2c49
}
2e2c49
2e2c49
if ! [ "$#" -ge 2 -a "$#" -le 3 ]; then
2e2c49
  echo 'Wrong number of arguments'
2e2c49
  usage
2e2c49
  exit 1
2e2c49
fi
2e2c49
2e2c49
# Exit if ROOTDIR doesn't exist
2e2c49
if ! [ -d "$ROOTDIR" ]; then
2e2c49
  echo "Root directory $ROOTDIR doesn't exist"
2e2c49
  usage
2e2c49
  exit 1
2e2c49
fi
2e2c49
2e2c49
if ! [ -r "$CONFIG_FILES" ]; then
2e2c49
  echo "Files list $CONFIG_FILES doesn't exist" 2>&1
2e2c49
  usage
2e2c49
  exit 1
2e2c49
fi
2e2c49
2e2c49
dev_create()
2e2c49
{
2e2c49
  DEVNAME="$ROOTDIR/dev/$1"
2e2c49
  shift
2e2c49
  if ! [ -e "$DEVNAME" ]; then
2e2c49
    /bin/mknod -m 0664 "$DEVNAME" $@
2e2c49
    /bin/chgrp named "$DEVNAME"
2e2c49
    if [ -x /usr/sbin/selinuxenabled -a -x /sbin/restorecon ]; then
2e2c49
      /usr/sbin/selinuxenabled && /sbin/restorecon "$DEVNAME" > /dev/null || :
2e2c49
    fi
2e2c49
  fi
2e2c49
}
2e2c49
2e2c49
dev_chroot_prep()
2e2c49
{
89a891
  dev_create random  c 1 8
89a891
  dev_create urandom c 1 9
89a891
  dev_create zero    c 1 5
89a891
  dev_create null    c 1 3
2e2c49
}
2e2c49
2e2c49
files_comment_filter()
2e2c49
{
2e2c49
  if [ -d "$1" ]; then
2e2c49
    grep -v '^[[:space:]]*#' "$1"/*.files
2e2c49
  else
2e2c49
    grep -v '^[[:space:]]*#' "$1"
2e2c49
  fi
2e2c49
}
2e2c49
2e2c49
mount_chroot_conf()
2e2c49
{
2e2c49
  if [ -n "$ROOTDIR" ]; then
2e2c49
    # Check devices are prepared
2e2c49
    dev_chroot_prep
2e2c49
    files_comment_filter "$CONFIG_FILES" | while read -r all; do
2e2c49
      # Skip nonexistant files
2e2c49
      [ -e "$all" ] || continue
2e2c49
2e2c49
      # If mount source is a file
2e2c49
      if ! [ -d "$all" ]; then
2e2c49
        # mount it only if it is not present in chroot or it is empty
2e2c49
        if ! [ -e "$ROOTDIR$all" ] || [ `stat -c'%s' "$ROOTDIR$all"` -eq 0 ]; then
2e2c49
          touch "$ROOTDIR$all"
2e2c49
          mount --bind "$all" "$ROOTDIR$all"
2e2c49
        fi
2e2c49
      else
2e2c49
        # Mount source is a directory. Mount it only if directory in chroot is
2e2c49
        # empty.
2e2c49
        if [ -e "$all" ] && [ `ls -1A $ROOTDIR$all | wc -l` -eq 0 ]; then
2e2c49
          mount --bind --make-private "$all" "$ROOTDIR$all"
2e2c49
        fi
2e2c49
      fi
2e2c49
    done
2e2c49
  fi
2e2c49
}
2e2c49
2e2c49
umount_chroot_conf()
2e2c49
{
2e2c49
  if [ -n "$ROOTDIR" ]; then
2e2c49
    files_comment_filter "$CONFIG_FILES" | while read -r all; do
2e2c49
      # Check if file is mount target. Do not use /proc/mounts because detecting
2e2c49
      # of modified mounted files can fail.
2e2c49
      if mount | grep -q '.* on '"$ROOTDIR$all"' .*'; then
2e2c49
        umount "$ROOTDIR$all"
2e2c49
        # Remove temporary created files
2e2c49
        [ -f "$all" ] && rm -f "$ROOTDIR$all"
2e2c49
      fi
2e2c49
    done
2e2c49
  fi
2e2c49
}
2e2c49
2e2c49
case "$2" in
2e2c49
  on)
2e2c49
    mount_chroot_conf
2e2c49
    ;;
2e2c49
  off)
2e2c49
    umount_chroot_conf
2e2c49
    ;;
2e2c49
  *)
2e2c49
    echo 'Second argument has to be "on" or "off"'
2e2c49
    usage
2e2c49
    exit 1
2e2c49
esac
2e2c49
2e2c49
exit 0