aboutsummaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authorEirik Oeverby <ltning@anduin.net>2009-03-14 00:27:08 +0100
committerEirik Oeverby <ltning@anduin.net>2009-03-14 00:27:08 +0100
commitf9a5fbfa1079f9a8dcfdfe4ad1bd50c1317ec8ac (patch)
tree406f5d5a94b035ff18efbc398c562dd8924ce388
parent662b06322bd35b323b9f1fb528abaa4a424515d1 (diff)
downloadpfsense-packages-f9a5fbfa1079f9a8dcfdfe4ad1bd50c1317ec8ac.tar.gz
pfsense-packages-f9a5fbfa1079f9a8dcfdfe4ad1bd50c1317ec8ac.tar.bz2
pfsense-packages-f9a5fbfa1079f9a8dcfdfe4ad1bd50c1317ec8ac.zip
Added pfJailctl and jail_template packages
See http://doc.pfsense.org/index.php/PfJailctl_package for details.
-rw-r--r--config/jail_template/jail_template.img.uzipbin0 -> 63200768 bytes
-rw-r--r--config/jail_template/jail_template.inc32
-rwxr-xr-xconfig/jailctl/jailctl1053
-rw-r--r--config/jailctl/jailctl-utils.inc272
-rw-r--r--config/jailctl/jailctl.inc217
-rw-r--r--config/jailctl/jailctl.xml233
-rw-r--r--config/jailctl/jailctl_defaults.xml122
-rw-r--r--config/jailctl/jailctl_list.inc112
-rw-r--r--config/jailctl/jailctl_settings.xml121
-rwxr-xr-xconfig/jailctl/sysinstallbin0 -> 447888 bytes
-rwxr-xr-xpkg_config.7.xml26
11 files changed, 2188 insertions, 0 deletions
diff --git a/config/jail_template/jail_template.img.uzip b/config/jail_template/jail_template.img.uzip
new file mode 100644
index 00000000..1c92fb90
--- /dev/null
+++ b/config/jail_template/jail_template.img.uzip
Binary files differ
diff --git a/config/jail_template/jail_template.inc b/config/jail_template/jail_template.inc
new file mode 100644
index 00000000..f9c00b79
--- /dev/null
+++ b/config/jail_template/jail_template.inc
@@ -0,0 +1,32 @@
+<?php
+function jail_template_install() {
+ exec('mkdir /usr/jail_template');
+ ## exec('tar -C /usr/jail_template -yxf /tmp/jail_template.tar.bz2 2&gt;&amp;1 &amp;');
+ $_rcfile['file']='000.jail_template.sh';
+ $_rcfile['start']='';
+ $_rcfile['stop']='';
+ $_rcfile['start'].='mount -o ro /dev/`mdconfig -af /usr/jail_template.img.uzip`.uzip /usr/jail_template '."\n\t";
+ $_rcfile['stop'].='umount -f /usr/jail_template '."\n\t";
+ $_rcfile['stop'].='mdconfig -d -u `expr "$(mdconfig -l -v | grep jail_template | grep -v grep)" : "md\([0-9]*\)"` '."\n\t";
+ write_rcfile($_rcfile);
+ exec('mount -o ro /dev/`mdconfig -af /usr/jail_template.img.uzip`.uzip /usr/jail_template');
+
+ $GLOBALS['config']['installedpackages']['pfjailctltemplates']['config'][0]['templates']['jail_template']['name']=
+ 'pfSense default jail template';
+ $GLOBALS['config']['installedpackages']['pfjailctltemplates']['config'][0]['templates']['jail_template']['path']=
+ '/usr/jail_template';
+}
+
+function jail_template_deinstall() {
+ exec('umount -f /usr/jail_template');
+ exec('mdconfig -d -u `expr "$(mdconfig -l -v | grep jail_template | grep -v grep)" : "md\([0-9]*\)');
+ unset($GLOBALS['config']['installedpackages']['pfjailctltemplates']['config'][0]['templates']['jail_template']);
+}
+
+function jail_template_resync() {
+ $GLOBALS['config']['installedpackages']['pfjailctltemplates']['config'][0]['templates']['jail_template']['name']=
+ 'pfSense default jail template';
+ $GLOBALS['config']['installedpackages']['pfjailctltemplates']['config'][0]['templates']['jail_template']['path']=
+ '/usr/jail_template';
+}
+?> \ No newline at end of file
diff --git a/config/jailctl/jailctl b/config/jailctl/jailctl
new file mode 100755
index 00000000..542c2db6
--- /dev/null
+++ b/config/jailctl/jailctl
@@ -0,0 +1,1053 @@
+#!/bin/sh
+
+# -------------------------------------
+# Jail management script
+# Copyright (c) 2004-2008 Eirik Oeverby
+# All rights reserved.
+# Redistribution and use in source and binary forms, with or without
+# modification, are permitted provided that the following conditions are met:
+#
+# * Redistributions of source code must retain the above copyright notice,
+# this list of conditions and the following disclaimer.
+# * Redistributions in binary form must reproduce the above copyright notice,
+# this list of conditions and the following disclaimer in the documentation
+# and/or other materials provided with the distribution.
+# * The name(s) of the author(s) may not be used to endorse or promote
+# products derived from this software without specific prior written
+# permission.
+#
+# THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS"
+# AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
+# IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
+# ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE
+# LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
+# CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
+# SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
+# INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
+# CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
+# ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
+# POSSIBILITY OF SUCH DAMAGE.
+# -------------------------------------
+
+##############################################################################
+# Configuration section #
+# #
+# Change the CFGFILE variable to point to your jail configuration file. #
+##############################################################################
+
+# Clear the hook lists (for security reasons)
+unset BEFORESTART_HOOKS
+unset AFTERSTART_HOOKS
+unset BEFORESTOP_HOOKS
+unset AFTERSTOP_HOOKS
+unset BEFORESTATUS_HOOKS
+unset AFTERSTATUS_HOOKS
+unset BEFOREBACKUP_HOOKS
+unset AFTERBACKUP_HOOKS
+unset BEFORERESTORE_HOOKS
+unset AFTERRESTORE_HOOKS
+unset BEFORECREATE_HOOKS
+unset AFTERCREATE_HOOKS
+unset BEFOREUPGRADE_HOOKS
+unset AFTERUPGRADE_HOOKS
+unset BEFOREDELETE_HOOKS
+unset AFTERDELETE_HOOKS
+
+CFGFILE="/usr/local/etc/jails.conf"
+. ${CFGFILE}
+
+PROCFS=`expr "$PROCFS" : "[tT][rR][uU][eE]"`
+LINPROCFS=`expr "$LINPROCFS" : "[tT][rR][uU][eE]"`
+
+##############################################################################
+# Main function section #
+# #
+# These functions are wrappers for the action functions below. They do #
+# various sanity checking of input parameters, and verify the existence and #
+# required states of the affected jail(s). #
+##############################################################################
+
+usage() {
+ ## Output usage information
+ echo "Usage:" >&2
+ echo "jailctl <command> <jail> [<path>]" >&2
+ echo "<command> = start|stop|status|create|delete|upgrade|backup|restore" >&2
+ echo "<jail> = hostname|all" >&2
+ echo "<path> = Backup destination / restore source" >&2
+ echo >&2
+}
+
+jail_status() {
+ ## Output the status of one or several jails
+ if [ ! $JAIL ] || [ $JAIL = "all" ] || jail_exists ; then
+ # Jail exists (or "all" was specified), we can query its status
+ if [ ! $JAIL ] || [ $JAIL = "all" ] ; then
+ # Output a brief list for all jails
+ echo "Jail status (*=running, !=not configured):"
+ for JAIL in $JAILS ; do
+ # Loop through jails
+ JAIL=`expr "$JAIL" : "\(.*\):.*"`
+ # Run hooks
+ jail_run_hooks before-status
+ if jail_exists && jail_running ; then
+ # Jail is running
+ echo "*$JAIL ($(jail_ip))"
+ elif jail_exists ; then
+ # Jail not running
+ echo " $JAIL ($(jail_ip))"
+ else
+ # Jail nonexistant or not configured
+ echo "!$JAIL ($(jail_ip))"
+ fi
+ # Run hooks
+ jail_run_hooks after-status
+ done
+ else
+ # Output information for a specific jail
+ # Run hooks
+ jail_run_hooks before-status
+ if jail_running ; then
+ # Jail is running, be verbose
+ echo "$JAIL ($(jail_ip)) is up."
+ echo "Path: $(jail_path)"
+ echo "Interface: $(jail_if)"
+ echo "Process list:"
+ # Output process list for jail
+ jps
+ elif jail_exists; then
+ # Jail not running
+ echo "$JAIL ($(jail_ip)) is down."
+ echo "Path: $(jail_path)"
+ echo "Interface: $(jail_if)"
+ else
+ # Jail nonexistant or not configured
+ echo "Unable to query jail $JAIL!"
+ echo "Incomplete configuration?"
+ fi
+ # Run hooks
+ jail_run_hooks after-status
+ fi
+ else
+ echo "Path: $(jail_path)"
+ echo "Interface: $(jail_if)"
+ # No jail was specified, or the specified jail doesn't exist (on disk
+ # or in jails.conf. Show usage information)
+ echo "No valid jail specified!"
+ echo
+ usage
+ fi
+}
+
+jail_start() {
+ ## Start one or several jails
+ if [ $JAIL ] && (jail_exists || [ $JAIL = "all" ]) ; then
+ # Jail exists (or "all" was specified), we can attempt to start it
+ if [ $JAIL = "all" ] ; then
+ # Attempting to start all jails
+ for JAIL in $JAILS ; do
+ # Loop through jails
+ JAIL=`expr "$JAIL" : "\(.*\):.*"`
+ if jail_running ; then
+ # Jail is running, cannot start
+ echo "Jail already running!"
+ elif jail_exists ; then
+ # Jail not running, starting
+ echo "Starting jail $JAIL..."
+ jstart
+ else
+ # Jail nonexistant or not configured
+ echo "Unable to start jail $JAIL!"
+ echo "Incomplete configuration?"
+ fi
+ done
+ else
+ # Start a specific jail
+ if jail_running && [ ! $FORCE ] ; then
+ # Jail is running, cannot start
+ echo "Jail already running!"
+ elif jail_exists ; then
+ # Jail not running, starting
+ echo "Starting jail $JAIL..."
+ jstart
+ else
+ # Jail nonexistant or not configured
+ echo "Unable to start jail $JAIL!"
+ echo "Incomplete configuration?"
+ fi
+ fi
+ else
+ # No jail was specified, or the specified jail doesn't exist (on disk
+ # or in jails.conf. Show usage information)
+ echo "No valid jail specified!"
+ echo
+ usage
+ fi
+}
+
+jail_stop() {
+ ## Stop one or several jails
+ if [ $JAIL ] && (jail_exists || [ $JAIL = "all" ]) ; then
+ # Jail exists (or "all" was specified), we can attempt to stop it
+ if [ $JAIL = "all" ] ; then
+ # Attempting to stop all jails
+ if [ $VERSION -eq 4 ] && [ `ls /proc | wc -l` -eq 0 ] ; then
+ # We are on FreeBSD 4.x, and we have no /proc to rely on
+ jstop
+ else
+ for JAIL in $JAILS ; do
+ # Loop through jails
+ JAIL=`expr "$JAIL" : "\(.*\):.*"`
+ if jail_exists && jail_running ; then
+ # Jail is running, stopping
+ echo "Stopping jail $JAIL..."
+ jstop
+ elif jail_exists && ! jail_running ; then
+ # Jail not running, cannot stop
+ echo "Jail not running ($JAIL)!"
+ else
+ # Jail nonexistant or not configured
+ echo "Unable to stop jail $JAIL!"
+ echo "Incomplete configuration?"
+ fi
+ done
+ fi
+ else
+ if jail_exists && jail_running ; then
+ if [ $VERSION -eq 4 ] && [ `ls /proc | wc -l` -eq 0 ] ; then
+ # We are on FreeBSD 4.x, and we have no /proc to rely on
+ echo 'Without a proc filesystem, you must use "jailctl stop all"!'
+ else
+ # Jail running, stopping
+ echo "Stopping jail $JAIL..."
+ jstop
+ fi
+ elif jail_exists && ! jail_running ; then
+ # Jail not running, cannot stop
+ echo "Jail not running!"
+ else
+ # Jail nonexistant or not configured
+ echo "Unable to start jail $JAIL!"
+ echo "Incomplete configuration?"
+ fi
+ fi
+ else
+ # No jail was specified, or the specified jail doesn't exist (on disk
+ # or in jails.conf. Show usage information)
+ echo "No valid jail specified!"
+ echo
+ usage
+ fi
+}
+
+jail_create() {
+ ## Create a jail
+ # Be more specific in distinguishing return codes from jail_exists
+ jail_exists ; RC=$?
+ if [ $JAIL ] && [ $RC -eq 1 ] ; then
+ # If the jail is configured but does not exist on disk, create the jail
+ echo "Creating jail $JAIL..."
+ jcreate
+ else
+ # Jail not configured or already exists
+ echo "Jail $JAIL cannot be created!"
+ fi
+ return 0
+}
+
+jail_upgrade() {
+ ## Upgrade one or several jails
+ if [ $JAIL ] && (jail_exists || [ $JAIL = "all" ]) ; then
+ # Jail exists (or "all" was specified), we can attempt to upgrade it
+ if [ $JAIL = "all" ] ; then
+ # Attempting to upgrade all jails
+ for JAIL in $JAILS ; do
+ # Loop through jails
+ JAIL=`expr "$JAIL" : "\(.*\):.*"`
+ if jail_exists ; then
+ # Jail exists and is not running, upgrading
+ echo "Upgrading jail $JAIL..."
+ jupgrade
+ else
+ # Jail nonexistant or not configured
+ echo "Jail does not exist, or not configured!"
+ fi
+ done
+ else
+ if jail_exists ; then
+ # Jail exists and is not running, upgrading
+ echo "Upgrading jail $JAIL..."
+ jupgrade
+ else
+ # Jail nonexistant or not configured
+ echo "Jail does not exist, or not configured!"
+ fi
+ fi
+ else
+ # No jail was specified, or the specified jail doesn't exist (on disk
+ # or in jails.conf. Show usage information)
+ echo "No valid jail specified!"
+ echo
+ usage
+ fi
+}
+
+jail_delete() {
+ ## Delete a specific jail
+ if [ $JAIL ] && ((jail_exists && ! jail_running) || [ $FORCE ]) ; then
+ # Jail exists and is not running, deleting
+ echo "Deleting jail $JAIL..."
+ jdelete
+ else
+ # Jail nonexistant, running or not configured, cannot delete
+ echo "Jail $JAIL cannot be deleted!"
+ fi
+ return 0
+}
+
+jail_backup() {
+ ## Back up one or several jails
+ if [ $JAIL ] && (jail_exists || [ $JAIL = "all" ]) ; then
+ # Jail exists (or "all" was specified), we can attempt to back it up
+ if [ $JAIL = "all" ] ; then
+ # Attempting to back up all jails
+ for JAIL in $JAILS ; do
+ # Loop through jails
+ JAIL=`expr "$JAIL" : "\(.*\):.*"`
+ if jail_exists && ! jail_running ; then
+ # Jail exists and is not running, doing cold backup
+ echo "Doing cold backup of jail $JAIL..."
+ jbackup cold
+ elif jail_exists && jail_running ; then
+ # Jail is running, doing warm backup
+ echo "Doing warm backup of jail $JAIL..."
+ jbackup
+ else
+ # Jail nonexistant or not configured
+ echo "Jail does not exist, or not configured!"
+ fi
+ done
+ else
+ if jail_exists && ! jail_running ; then
+ # Jail exists and is not running, doing cold backup
+ echo "Doing cold backup of jail $JAIL..."
+ jbackup cold
+ elif jail_exists && jail_running ; then
+ # Jail is running, doing warm backup
+ echo "Doing warm backup of jail $JAIL..."
+ jbackup
+ else
+ # Jail nonexistant or not configured
+ echo "Jail does not exist, or not configured!"
+ fi
+ fi
+ else
+ # No jail was specified, or the specified jail doesn't exist (on disk
+ # or in jails.conf. Show usage information)
+ echo "No valid jail specified!"
+ echo
+ usage
+ fi
+}
+
+jail_restore() {
+ ## Restore a jail
+ # Be more specific in distinguishing return codes from jail_exists
+ jail_exists ; RC=$?
+ if [ $JAIL ] && [ $RC -eq 1 ] ; then
+ echo "Restoring jail $JAIL from backup"
+ local JP=$(jail_path)
+ # Restore the jail
+ jrestore
+ else
+ # No jail was specified, or the specified jail doesn't exist (on disk
+ # or in jails.conf. Show usage information)
+ echo "No valid jail specified!"
+ echo
+ usage
+ fi
+}
+
+
+#
+### Helper function section
+#
+
+jail_exists() {
+ ## Query a jails existence
+ local J=`echo $JAILS | tr " " "\n" | grep "^${JAIL}:"`
+# for J in $JAILS ; do
+ # Loop through configured jails
+ local J_NAME=`expr "$J" : "\(.*\):.*"`
+ if [ $J_NAME = $JAIL ] && [ -d "$(jail_path)" ] && \
+ [ `expr $(ls -a $(jail_path) | grep -v "^.snap$" | wc -l)` -gt 2 ]; then
+ # Jail is configured, its directory exists, and the
+ # directory contains more than . and ..
+ return 0
+ elif [ $J_NAME = $JAIL ] && [ ! -d "$(jail_path)" ] || \
+ ( [ -d "$(jail_path)" ] && \
+ [ `expr $(ls -a $(jail_path) | grep -v "^.snap$" | wc -l)` -le 2 ]); then
+ # Jail is defined, but not yet created (directory missing or empty)
+ return 1
+ fi
+# done
+ # Jail doesn't exist
+ return 2
+}
+
+jail_name() {
+ ## Query the name of a jail
+ ## Must be updated to be able to search per IP. Searching per name makes
+ ## no sense
+ local J=`echo $JAILS | tr " " "\n" | grep "^${JAIL}:"`
+# for J in $JAILS ; do
+ # Loop through configured jails
+ local J_NAME=`expr "$J" : "\(.*\):.*"`
+ if [ $J_NAME = $JAIL ] ; then
+ # Name part of jail definition matches
+ echo $J_NAME
+ return 0
+ fi
+# done
+ # Jail not found or error
+ return 1
+}
+
+jail_ip() {
+ ## Query the IP of a jail
+ local J=`echo $JAILS | tr " " "\n" | grep "^${JAIL}:"`
+# for J in $JAILS ; do
+ # Loop through configured jails
+ local J_NAME=`expr "$J" : "\([^;].*\):.*"`
+ if [ $J_NAME = $JAIL ] ; then
+ # Name part of jail definition matches, output IP
+echo $J > debug.file
+ local J_IP=`expr "$J" : ".*:\([^;]*\)"`
+ echo $J_IP
+ return 0
+ fi
+# done
+ # Jail not found or error
+ return 1
+}
+
+jail_path() {
+ ## Query the path to a jail
+ local J=`echo $JAILS | tr " " "\n" | grep "^${JAIL}:"`
+# for J in $JAILS ; do
+ # Loop through configured jails
+ local J_NAME=`expr "$J" : "\(.*\):.*"`
+ if [ $J_NAME = $JAIL ] ; then
+ # Name part of jail definition matches, output path
+ local J_HOME=`expr "$J" : "[^;]*;\([^;]*\).*$"`
+ if [ -n "$J_HOME" ] ; then
+ if [ `expr "$J_HOME" : ".*\/$"` -gt 0 ] ; then
+ local J_PATH=`expr "$J_HOME" : "\(.*\)/$"`
+ else
+ local J_PATH="${J_HOME}/${J_NAME}"
+ fi
+ else
+ local J_PATH="${JAIL_HOME}$J_NAME"
+ fi
+ echo $J_PATH
+ return 0
+ fi
+# done
+ # Jail not found or error
+ return 1
+}
+
+jail_if() {
+ ## Query the path to a jail
+ local J=`echo $JAILS | tr " " "\n" | grep "^${JAIL}:"`
+# for J in $JAILS ; do
+ # Loop through configured jails
+ local J_NAME=`expr "$J" : "\(.*\):.*"`
+ if [ $J_NAME = $JAIL ] ; then
+ # Name part of jail definition matches, output path
+ local J_HOME=`expr "$J" : "[^;]*;\([^;]*\).*$"`
+ local J_IF=`expr "$J" : ".*;[^;]*;\([^;]*\).*$"`
+ if [ -z "$J_IF" ] ; then
+ local J_IF=$IF
+ fi
+ echo $J_IF
+ return 0
+ fi
+# done
+ # Jail not found or error
+ return 1
+}
+
+jail_running() {
+ ## Query the running state of a jail
+ if [ $VERSION -ge 5 ] ; then
+ # We are on FreeBSD 5.x, using jls(1) tool
+ local JLS="`/usr/sbin/jls | grep \"\/${JAIL}$\"`"
+ if [ ! "$JLS" ] ; then
+ # Jail is not running
+ return 1
+ fi
+ for i in "$JLS" ; do
+ # Fetching output string, concatenating
+ local J_LIST="$J_LIST $i"
+ done
+ # Setting JAIL_ID variable; this is the system jail ID
+ JAIL_ID=`echo $J_LIST | cut -d \ -f 1`
+ local JPS=`expr "\`/usr/sbin/jexec $JAIL_ID /bin/ps ax | grep -v \"ps\ ax\" | wc -l | cut -f 2\`" : "[[:space:]]*\([0-9]*\).*"`
+ if [ "$JPS" -lt 2 ] ; then
+ # Jail is not running (no processes, anyway)
+ return 1
+ fi
+ else
+ # We are on FreeBSD 4.x, use old dirty trick
+ if [ ! -f "/var/run/jails/${JAIL}.running" ] ; then
+ # Jail is not running
+ return 1
+ fi
+ fi
+ # Jail is running
+ return 0
+}
+
+#
+### Activity function section
+#
+
+jail_run_hooks() {
+ ## Select a hook list to run
+ case $1 in
+ before-start)
+ jrunhooks "$1" "$BEFORESTART_HOOKS"
+ ;;
+ after-start)
+ jrunhooks "$1" "$AFTERSTART_HOOKS"
+ ;;
+ before-stop)
+ jrunhooks "$1" "$BEFORESTOP_HOOKS"
+ ;;
+ after-stop)
+ jrunhooks "$1" "$AFTERSTOP_HOOKS"
+ ;;
+ before-status)
+ jrunhooks "$1" "$BEFORESTATUS_HOOKS"
+ ;;
+ after-status)
+ jrunhooks "$1" "$AFTERSTATUS_HOOKS"
+ ;;
+ before-backup)
+ jrunhooks "$1" "$BEFOREBACKUP_HOOKS"
+ ;;
+ after-backup)
+ jrunhooks "$1" "$AFTERBACKUP_HOOKS"
+ ;;
+ before-restore)
+ jrunhooks "$1" "$BEFORERESTORE_HOOKS"
+ ;;
+ after-restore)
+ jrunhooks "$1" "$AFTERRESTORE_HOOKS"
+ ;;
+ before-create)
+ jrunhooks "$1" "$BEFORECREATE_HOOKS"
+ ;;
+ after-create)
+ jrunhooks "$1" "$AFTERCREATE_HOOKS"
+ ;;
+ before-upgrade)
+ jrunhooks "$1" "$BEFOREUPGRADE_HOOKS"
+ ;;
+ after-upgrade)
+ jrunhooks "$1" "$AFTERUPGRADE_HOOKS"
+ ;;
+ before-delete)
+ jrunhooks "$1" "$BEFOREDELETE_HOOKS"
+ ;;
+ after-delete)
+ jrunhooks "$1" "$AFTERDELETE_HOOKS"
+ ;;
+ esac
+}
+
+jps() {
+ ## List running processes in a jail
+ if [ $VERSION -ge 5 ] ; then
+ # We are on FreeBSD 5.x, use jexec(1) tool
+ /usr/sbin/jexec $JAIL_ID ps auxwww
+ else
+ # We are on FreeBSD 4.x, use old dirty trick (requires /proc on host!)
+ echo "CMD PID TIME UTIME STIME"
+ cat /proc/*/status | grep "${JAIL}" | cut -d \ -f 1 -f 2 -f 8 -f 9 -f 10
+ fi
+ return 0
+}
+
+jstart() {
+ ## Start a jail
+ local JP=$(jail_path)
+ local IP=$(jail_ip)
+ local JIF=$(jail_if)
+ if [ $PROCFS -gt 0 ] ; then
+ # Mount proc filesystem into jail
+ /sbin/mount_procfs procfs ${JP}/proc
+ fi
+ if [ $LINPROCFS -gt 0 ] ; then
+ # Mount Linux proc filesystem into jail
+ /sbin/mount_linprocfs linprocfs ${JP}/compat/linux/proc
+ fi
+
+ if [ $VERSION -ge 5 ] ; then
+ # Run hooks
+ jail_run_hooks before-start
+ # We are on FreeBSD 5.x, use devfs
+ /sbin/mount -t devfs devfs ${JP}/dev
+ devfs -m ${JP}/dev ruleset 4
+ devfs -m ${JP}/dev rule applyset
+ fi
+
+ # Bring up network interface alias and start jail
+ [ $(echo $JIF | cut -c 1-4) != 'carp' ] && ifconfig $JIF inet $IP netmask 0xffffffff alias
+ echo >> ${JP}/var/log/jailstart.log
+ echo $(date) >> ${JP}/var/log/jailstart.log
+ jail $JP $JAIL $IP /bin/sh /etc/rc 2>&1 >${JP}/var/log/jailstart.log &
+
+ if [ $VERSION -eq 4 ] ; then
+ # We're on FreeBSD 4.x, Create run file
+ touch /var/run/jails/${JAIL}.running
+ fi
+
+ if [ $VERSION -ge 5 ] ; then
+ # Run hooks
+ jail_run_hooks after-start
+ fi
+
+ return 0
+}
+
+jstop() {
+ ## Stop a jail
+ local JP=$(jail_path)
+ local IP=$(jail_ip)
+ local JIF=$(jail_if)
+
+ if [ $VERSION -ge 5 ] ; then
+ # Run hooks
+ jail_run_hooks before-stop
+ fi
+
+ echo "Sending TERM signal to jail processes..."
+ if [ $VERSION -ge 5 ] ; then
+ # We are on FreeBSD 5.x, use jexec(1) tool
+ /usr/sbin/jexec $JAIL_ID /bin/sh /etc/rc.shutdown
+ sleep 2
+ /usr/sbin/jexec $JAIL_ID kill -15 -1
+ # Waiting for processes to die
+ sleep 4
+ while jail_running ; do
+ # Some processes are still running, do a kill -9 -1
+ echo "Some processes would not terminate; sending KILL signal..."
+ /usr/sbin/jexec $JAIL_ID kill -9 -1
+ # Give processes some time to die
+ sleep 2
+ done
+ umount -f ${JP}/dev
+ else
+ # We are on FreeBSD 4.x
+ if [ "$JAIL" = "all" ] ; then
+ # /proc is unavailable, so we can only stop ALL jails at once
+ local PS="`ps ax|cut -c 1-16|grep J|cut -d \ -f 1`"
+ for PID in "$PS" ; do
+ kill -15 $PID 2>/dev/null 1>/dev/null
+ done
+ # Waiting for processes to die
+ sleep 4
+ local PS="`ps ax|cut -c 1-16|grep J|cut -d \ -f 1`"
+ while [ "$PS" ] ; do
+ # Some processes are still running, do a kill -9 on each
+ echo "Some processes would not terminate; sending KILL signal..."
+ for PID in "$PS" ; do
+ # Sending KILL signal to all processes in the jail
+ kill -9 $PID 2>/dev/null 1>/dev/null
+ done
+ # Give processes some time to die
+ sleep 2
+ local PS="`ps ax|cut -c 1-16|grep J|cut -d \ -f 1`"
+ done
+ else
+ # Use /proc filesystem (REQUIRED for single-jail operation!)
+ local PS="`cat /proc/*/status | cut -d \ -f 2 -f 15 2>/dev/null | grep \" ${JAIL} \" | cut -d \ -f 1`"
+ for PID in "$PS" ; do
+ # Sending TERM signal to all processes in the jail
+ kill -15 $PID 2>/dev/null 1>/dev/null
+ done
+ # Waiting for processes to die
+ sleep 4
+ local PS="`cat /proc/*/status | cut -d \ -f 2 -f 15 2>/dev/null | grep \" ${JAIL} \" | cut -d \ -f 1`"
+ while [ "$PS" ] ; do
+ # Some processes are still running, do a kill -9 on each
+ echo "Some processes would not terminate; sending KILL signal..."
+ for PID in "$PS" ; do
+ # Sending KILL signal to all processes in the jail
+ kill -9 $PID 2>/dev/null 1>/dev/null
+ done
+ # Give processes some time to die
+ sleep 2
+ local PS="`cat /proc/*/status | cut -d \ -f 2 -f 15 2>/dev/null | grep \" ${JAIL} \" | cut -d \ -f 1`"
+ done
+ fi
+ fi
+
+ if [ $PROCFS -gt 0 ] ; then
+ # Unmount the jail proc filesystem
+ umount -f ${JP}/proc
+ fi
+ if [ $LINPROCFS -gt 0 ] ; then
+ # Unmount the jail Linux proc filesystem
+ umount -f ${JP}/compat/linux/proc
+ fi
+
+ if [ $VERSION -eq 4 ] ; then
+ # We are on FreeBSD 4.x, remove runfile
+ rm /var/run/jails/${JAIL}.running
+ fi
+
+ # Bring down network interface alias
+ [ $(echo $JIF | cut -c 1-4) != 'carp' ] && ifconfig $JIF inet $IP netmask 0xffffffff -alias
+
+ if [ $VERSION -ge 5 ] ; then
+ # Run hooks
+ jail_run_hooks after-stop
+ fi
+
+ return 0
+}
+
+jcreate() {
+ jail_run_hooks before-create
+ ## Create a jail
+ local JP=$(jail_path)
+ local IP=$(jail_ip)
+ local JIF=$(jail_if)
+
+ # Create jail directory
+ mkdir -p $JP
+ # Populate jail directory
+ jpopulate
+ # Initialize jail directory contents
+ jinit
+ # Remove unneeded files and clean up
+ jcleanup
+ jail_run_hooks after-create
+ return 0
+}
+
+jupgrade() {
+ jail_run_hooks before-upgrade
+ ## Upgrade a jail
+ local JP=$(jail_path)
+ # Run mergemaster to prepare the jail for upgrade
+ mergemaster -Upi -D $JP
+ # Populate jail directory
+ jpopulate
+ # Run mergemaster to update default configuration files
+ mergemaster -Ui -D $JP
+ # Remove unneeded files and clean up
+ jcleanup
+ if jail_running ; then
+ echo "Jail running, please restart!"
+ fi
+ jail_run_hooks after-upgrade
+
+}
+
+jdelete() {
+ jail_run_hooks before-delete
+ ## Delete a jail
+ local JP=$(jail_path)
+ local m_search=""
+ if [ $PROCFS -gt 0 ] ; then m_search="${JP}/proc" ; fi
+ if [ $LINPROCFS -gt 0 ] ; then
+ if [ -n "${m_search}" ] ; then m_search="${m_search}\|" ; fi
+ m_search="${m_search}${JP}/compat/linux/proc"
+ fi
+ if [ $VERSION -ge 5 ] ; then
+ if [ -n "${m_search}" ] ; then m_search="${m_search}\|" ; fi
+ m_search="${m_search}${JP}/dev"
+ fi
+ MOUNTS=`mount | grep "$JP" | grep -v "${m_search} | cut -d \ -f 3"`
+ MOUNTS_NO=`echo -n $MOUNTS | wc -l`
+ if [ $MOUNTS_NO -gt 0 ]; then
+ echo "WARNING: Mounted directories found in ${JP}:"
+ echo $MOUNTS
+ echo -n "Unmount ('n' will cancel delete)? [y/n] "
+ read ANS
+ if [ x$ANS = xy ]; then
+ for m in $MOUNTS ; do
+ echo -n "Unmounting $m ..."
+ umount_msg=`umount -f $m 2>&1`
+ umount_res=$?
+ sleep 1
+ if [ $umount_res -ne 0 ] ; then
+ echo "FAILED!"
+ echo "$umount_msg"
+ else
+ echo "ok."
+ fi
+ done
+ MOUNTS=`mount | grep "$JP" | grep -v "${m_search}"`
+ MOUNTS_NO=`echo -n $MOUNTS | wc -l`
+ echo $MOUNTS_NO
+ if [ $MOUNTS_NO -gt 0 ] ; then
+ echo "Unmounting failed. Jail not deleted."
+ else
+ echo "All filesystems unmounted successfully. Deleting jail."
+ # Pass one: removing unprotected files
+ rm -Rf $JP 2>&1 > /dev/null
+ # Pass two: removing SCHG flag from jail tree
+ chflags -R noschg $JP
+ # Pass three: Removing jail directory
+ rm -Rf $JP
+ fi
+ fi
+ else
+ # Pass one: removing unprotected files
+ rm -Rf $JP 2>&1 > /dev/null
+ # Pass two: removing SCHG flag from jail tree
+ chflags -R noschg $JP
+ # Pass three: Removing jail directory
+ rm -Rf $JP
+ fi
+ jail_run_hooks after-delete
+
+}
+
+jbackup() {
+ ## Back up a jail
+ local JP=$(jail_path)
+
+ # Determine target file for backup
+ if [ -n "$CMD" ] ; then
+ TARGET=$CMD
+ else
+ TARGET="${BACKUPDIR}/${JAIL}.tar"
+ fi
+
+ # Run backup
+ jail_run_hooks before-backup
+ if [ ! "$1" = "cold" -a $VERSION -ge 5 ] ; then
+ # Run warm backup - FreeBSD >=5 only
+ if [ -z "$GPG" ] ; then
+ /usr/sbin/jexec $JAIL_ID /usr/bin/tar --one-file-system -C / $BACKUP_EXCLUDE -cf - ./. | gzip --fast > ${TARGET}.gz
+ else
+ /usr/sbin/jexec $JAIL_ID /usr/bin/tar --one-file-system -C / $BACKUP_EXCLUDE -cf - ./. | gzip --fast | $GPG -o ${TARGET}.gz.gpg
+ fi
+ else
+ # Run cold backup
+ if [ -z "$GPG" ] ; then
+ chroot $JP /usr/bin/tar --one-file-system -C / $BACKUP_EXCLUDE -cf - ./. | gzip --fast > ${TARGET}.gz
+ else
+ chroot $JP /usr/bin/tar --one-file-system -C / $BACKUP_EXCLUDE -cf - ./. | gzip --fast | $GPG -o ${TARGET}.gz.gpg
+ fi
+ fi
+ jail_run_hooks after-backup
+}
+
+jrestore() {
+ ## Restore a jail from backup
+ # Create jail home
+ mkdir -p $JP && cd $JP
+
+ # Determine source file for backup
+ if [ -n "$CMD" ] ; then
+ SOURCE=$CMD
+ else
+ SOURCE="${BACKUPDIR}/${JAIL}.tar.gz"
+ fi
+
+ [ -f $SOURCE ] && jail_run_hooks before-restore
+ # Restore
+ tar -zpxf $SOURCE
+ [ $? -eq 0 ] && jail_run_hooks after-restore
+}
+
+
+#
+### Activity helper function section
+#
+
+jpopulate() {
+ ## Populate a jail directory
+ cd /usr/src
+ # Running installworld into jail directory
+ make installworld ${INSTALLWORLD_FLAGS} DESTDIR=${JP} 2>&1 | grep '>>>'
+}
+
+jcleanup() {
+ ## Remove unneeded files and clean up a jail
+ # Copying the most recent list of files to delete
+ if [ $VERSION -ge 5 ] ; then
+ cp ${JAIL_HOME}addons/dellist5.txt $JP/dellist.txt
+ else
+ cp ${JAIL_HOME}addons/dellist4.txt $JP/dellist.txt
+ fi
+ # Removing protection from files to be deleted
+ chroot $JP chflags -R noschg $(cat ${JP}/dellist.txt) 2>/dev/null 1>/dev/null
+ # Deleting files
+ chroot $JP rm -Rf $(cat ${JP}/dellist.txt) 2>/dev/null 1>/dev/null
+
+ # Changing binaries to be jail compatible
+ chroot ${JP} ln -f /usr/bin/true /sbin/mount
+ chroot ${JP} ln -f /usr/bin/true /sbin/umount
+ chroot ${JP} ln -f /usr/bin/true /sbin/swapon
+ chroot ${JP} ln -f /usr/bin/true /sbin/swapoff
+ chroot ${JP} chflags noschg /sbin/init
+ chroot ${JP} rm /sbin/init
+ chroot ${JP} ln -f /usr/bin/true /sbin/init
+ chroot ${JP} ln -f /usr/bin/true /sbin/adjkerntz
+ chroot ${JP} ln -f /usr/bin/true /sbin/ifconfig
+
+ # Copy timezone information from host
+ cp /etc/localtime ${JP}/etc/localtime
+}
+
+jinit() {
+ ## Install default set of configuration files
+ cd /usr/src/etc
+ # Installing distribution files to jail directory
+ make distribution DESTDIR=${JP} -DNO_MAKEDEV_RUN 2>/dev/null 1>/dev/null
+
+ # Create directories in jail
+ mkdir -p ${JP}/proc
+ mkdir -p ${JP}/usr/home
+ mkdir -p ${JP}/root/.ssh
+ mkdir -p ${JP}/compat/linux/proc
+ mkdir -p ${JP}/usr/local/bin
+ chroot ${JP} ln -sf /usr/home /home
+
+ # Update passwd database with default root user/pw
+ IFS2=$IFS
+ IFS=$(echo -e '\n\t')
+ if [ -z "$BATCH" ] ; then
+ echo "Setting root password in jail"
+ chroot ${JP} /usr/bin/passwd root
+ else
+ for L in $(cat ${JP}/etc/master.passwd) ; do
+ if [ "$L" = 'root::0:0::0:0:Charlie &:/root:/bin/csh' ] ; then
+ echo "root:${ROOT_PW}:0:0::0:0:Charlie &:/root:/bin/csh" >> ${JP}/tmp/jailctl.001
+ else
+ echo $L >> ${JP}/tmp/jailctl.001
+ fi
+ done
+ pwd_mkdb -p -d ${JP}/etc ${JP}/tmp/jailctl.001
+ IFS=$IFS2
+ fi
+
+ # Install jail hostname and IP into hosts file
+ JAIL_HOST=$(expr $JAIL : "\([a-zA-Z0-9\-]*\)\..*")
+ JAIL_DOMAIN=$(expr $JAIL : "${JAIL_HOST}\.\(.*\)")
+ echo "$IP $JAIL $JAIL_HOST" >> ${JP}/etc/hosts
+
+ # Create new rc.conf
+ echo '# Default jail rc.conf' > ${JP}/etc/rc.conf
+ for L in $RC_CONF ; do
+ echo $L >> ${JP}/etc/rc.conf
+ done
+ echo "hostname=\"$JAIL\"" >> ${JP}/etc/rc.conf
+
+ # Update SSH configuration
+ sed -i .jailctl -Ee "s/#?PermitRootLogin no/PermitRootLogin yes/" ${JP}/etc/ssh/sshd_config
+
+ # Update resolv.conf
+ echo "domain $JAIL_DOMAIN" > ${JP}/etc/resolv.conf
+ # Update resolv.conf
+ for L in $NAMESERVERS ; do
+ echo "nameserver $L" >> ${JP}/etc/resolv.conf
+ done
+
+ # Creating symlinks
+ chroot ${JP} ln -sf /dev/null /kernel
+ if [ $VERSION -ge 5 ] ; then
+ # We are on FreeBSD 5.x, work around distribution bug
+ chroot ${JP} ln -sf /lib/libm.so.3 /lib/libm.so.2
+ fi
+
+ if [ $VERSION -eq 4 ] ; then
+ # We are on FreeBSD 4.x, initializing device tree
+ cd ${JP}/dev
+ sh MAKEDEV jail
+ fi
+
+ # Installing addons
+ cp -R ${JAIL_HOME}addons/* ${JP}/
+
+ # Starting jail for the first time, calling runme.sh to install software
+ [ $(echo $JIF | cut -c 1-4) != 'carp' ] && ifconfig $JIF inet $IP netmask 0xffffffff alias
+ JSTART=$(jail $JP $JAIL $IP /bin/sh /runme.sh)
+ [ $(echo $JIF | cut -c 1-4) != 'carp' ] && ifconfig $JIF inet $IP netmask 0xffffffff -alias
+
+ # Output commmands used to run installation script for easy re-run
+ [ $(echo $JIF | cut -c 1-4) != 'carp' ] && echo "ifconfig $JIF inet $IP netmask 0xffffffff alias"
+ echo "jail $JP $JAIL $IP /bin/sh /runme.sh"
+ [ $(echo $JIF | cut -c 1-4) != 'carp' ] && echo "ifconfig $JIF inet $IP netmask 0xffffffff -alias"
+}
+
+jrunhooks() {
+ ## Run a hook list
+ # Find jail ID on FreeBSD >5
+ local JAIL_ID=0
+ if [ $VERSION -ge 5 ] && jail_running ; then
+ local JLS="`/usr/sbin/jls | grep \"\/${JAIL}$\"`"
+ for i in "$JLS" ; do
+ # Fetching output string, concatenating
+ local J_LIST="$J_LIST $i"
+ done
+ # Setting JAIL_ID variable; this is the system jail ID
+ local JAIL_ID=`echo $J_LIST | cut -d \ -f 1`
+ fi
+
+ for HOOK in $@; do
+ # Skip first parameter
+ [ ! "$HOOK" = "$1" ] && $HOOK $1 $JAIL $(jail_path) $JAIL_ID
+ done
+}
+
+#
+### Main block
+#
+
+## Get current working directory
+CWD=$(pwd)
+
+## Get command line parameters
+ACTION=$1
+JAIL=$2
+CMD=$3
+
+if [ "$CMD" = "force" ] ; then
+ FORCE=1
+fi
+
+## Checking current FreeBSD version
+VERSION="`uname -r | cut -c 1`"
+
+if [ $VERSION -eq 4 ] ; then
+ # We are on FreeBSD 4.x, creating statefile directory
+ if [ ! -d "/var/run/jails" ] ; then
+ mkdir -p /var/run/jails
+ fi
+fi
+
+case "$ACTION" in
+status) jail_status ;;
+start) jail_start ;;
+stop) jail_stop ;;
+create) jail_create ;;
+upgrade) jail_upgrade ;;
+delete) jail_delete ;;
+backup) jail_backup ;;
+restore) jail_restore ;;
+*) usage ;;
+
+esac
+
+cd $CWD
+
+exit 0
+
diff --git a/config/jailctl/jailctl-utils.inc b/config/jailctl/jailctl-utils.inc
new file mode 100644
index 00000000..df16750c
--- /dev/null
+++ b/config/jailctl/jailctl-utils.inc
@@ -0,0 +1,272 @@
+<?php
+$GLOBALS['jailctl_tmp']['mounts'][]='bin';
+$GLOBALS['jailctl_tmp']['mounts'][]='lib';
+$GLOBALS['jailctl_tmp']['mounts'][]='libexec';
+$GLOBALS['jailctl_tmp']['mounts'][]='sbin';
+$GLOBALS['jailctl_tmp']['mounts'][]='usr/bin';
+$GLOBALS['jailctl_tmp']['mounts'][]='usr/include';
+$GLOBALS['jailctl_tmp']['mounts'][]='usr/lib';
+$GLOBALS['jailctl_tmp']['mounts'][]='usr/libdata';
+$GLOBALS['jailctl_tmp']['mounts'][]='usr/libexec';
+$GLOBALS['jailctl_tmp']['mounts'][]='usr/sbin';
+$GLOBALS['jailctl_tmp']['mounts'][]='usr/share';
+
+$GLOBALS['jailctl_tmp']['unionmounts'][]='etc';
+$GLOBALS['jailctl_tmp']['unionmounts'][]='var';
+$GLOBALS['jailctl_tmp']['unionmounts'][]='usr/local/etc';
+
+$GLOBALS['jailctl_tmp']['mount_unionfs']='mount -t unionfs -o below ';
+$GLOBALS['jailctl_tmp']['mount_nullfs']='mount -t nullfs -o ro';
+
+function jailctl_initialize_jail($jail, $jstatus, $jconfig) {
+ $cmd='sed -I "" -e s/"^root:[^:]*:"/"root:'.addcslashes($jconfig['jpasswd'], '$/').':"/ '.$jstatus['jpath'].'/etc/master.passwd '."\n";
+ $cmd.='sed -I "" -e s/"^.PermitRootLogin.*"/"PermitRootLogin yes"/ '.$jstatus['jpath'].'/etc/ssh/sshd_config '."\n";
+ $cmd.="pwd_mkdb -d ".$jstatus['jpath']."/etc ".$jstatus['jpath']."/etc/master.passwd \n";
+ $cmd.="echo '".$jail['jip']." ".$jail['jname']." ".$jstatus['jhostname'][0]."' >> ".$jstatus['jpath']."/etc/hosts \n";
+ $cmd.="echo 'hostname=\"".$jail['jname']."\"' > ".$jstatus['jpath']."/etc/rc.conf \n";
+
+ if(is_array($jconfig['row']) {
+ foreach($jconfig['row'] as $_row) {
+ $cmd.="echo '".$_row['rcconfline']."' >> ".$jstatus['jpath']."/etc/rc.conf \n";
+ #$cmd.="echo '".str_replace(' ', "\n", $jconfig['jrcconf'])."' >> ".$jstatus['jpath']."/etc/rc.conf \n";
+ }
+ }
+ $cmd.="echo 'domain ".$jstatus['jhostname'][1]."' > ".$jstatus['jpath']."/etc/resolv.conf \n";
+ foreach(explode(' ', trim($jconfig['jdnsservers'])) as $_ns) {
+ $cmd.="echo 'nameserver ".str_replace(' ', "\nnameserver ", $_ns)."' >> ".$jstatus['jpath']."/etc/resolv.conf \n";
+ }
+ return $cmd;
+}
+
+function jailctl_create_template($jail, $jstatus, $jconfig) {
+ $mounts=$GLOBALS['jailctl_tmp']['mounts'];
+ $unionmounts=$GLOBALS['jailctl_tmp']['unionmounts'];
+ $mount_unionfs=$GLOBALS['jailctl_tmp']['mount_unionfs'];
+ $mount_nullfs=$GLOBALS['jailctl_tmp']['mount_nullfs'];
+
+ $_path=$jstatus['jpath'];
+ $_name=$jail['name'];
+ $_ip=$jail['jip'];
+ $_hostname=$jstatus['jhostname'];
+ $_dnsservers=$jconfig['jdnsservers'];
+ $_passwd=$jconfig['jpasswd'];
+ $_template=$jail['jtemplates'];
+
+ exec('mkdir -p '.$_path.'/dev');
+ exec('mkdir -p '.$_path.'/root');
+ exec('ln -s /usr/home '.$_path.'/home');
+
+ $jail['juse_unionfs']=='on' ? $mount=$mount_unionfs : $mount=$mount_nullfs ;
+
+ foreach($mounts as $mp) {
+ $cmd[]='mkdir -p '.$_path.'/'.$mp;
+ $cmd[]=$mount.' '.$_template.'/'.$mp.' '.$_path.'/'.$mp;
+ }
+
+ foreach($unionmounts as $mp) {
+ $cmd[]='mkdir -p '.$_path.'/'.$mp;
+ $cmd[]=$mount_unionfs.' '.$_template.'/'.$mp.' '.$_path.'/'.$mp;
+ }
+
+ foreach($cmd as $_t) {
+# exec($_t.' 2>&1 ', $_mount);
+ exec($_t.' 2>&1 ');
+ }
+# foreach($_mount as $_out) {
+# echo $_out."<br>";
+# }
+
+ $cmd=jailctl_initialize_jail($jail, $jstatus, $jconfig);
+ $fd=fopen('/tmp/jcreate_'.$jail['jname'], 'w+');
+ fwrite($fd, $cmd);
+ fclose($fd);
+ exec("sh /tmp/jcreate_".$jail['jname']." 2>&1 >/var/log/jcreate_exec &");
+
+ foreach(array_reverse($mounts, true) as $mp) {
+ exec('umount -f '.$_path.'/'.$mp);
+ }
+
+ foreach(array_reverse($unionmounts, true) as $mp) {
+ exec('umount -f '.$_path.'/'.$mp);
+ }
+}
+
+function jailctl_create_sysinstall($jail, $jstatus, $jconfig) {
+ exec('mkdir -p '.$jstatus['jpath']);
+ $cmd="sysinstall ";
+ $cmd.="_ftpPath=".$jconfig['jftpmirror']." ";
+ $cmd.="nonInteractive=yes ";
+ $cmd.="mediaSetFTP ";
+ $cmd.="releaseName=7.1-RELEASE ";
+ if($jail['jdists']) {
+ $cmd.="dists=\"base ".str_replace(',', ' ', $jail['jdists'])."\" ";
+ $cmd.="distSetCustom ";
+ } else {
+ $cmd.=$jail['jdistset']." ";
+ }
+ $cmd.="installRoot=".$jstatus['jpath']." ";
+ $cmd.="installCommit ";
+ $cmd.="> /var/log/jcreate.log 2>/var/log/jcreate.err \n";
+ $cmd.="\n";
+
+ $cmd.=jailctl_initialize_jail($jail, $jstatus, $jconfig);
+
+ $fd=fopen('/tmp/jcreate_'.$jail['jname'], 'w+');
+ fwrite($fd, $cmd);
+ fclose($fd);
+
+ exec("sh /tmp/jcreate_".$jail['jname']." 2>&1 >/var/log/jcreate_exec &");
+}
+
+function jailctl_find_if($ip) {
+ exec("ifconfig | grep -C 1 '".addcslashes($ip, ".")."'", $_ifconfig);
+ $if=explode(':', $_ifconfig[0]);
+
+ return $if[0];
+}
+
+function jailctl_addinterfaces($config) {
+ $vips=$config['virtualip']['vip'];
+ ?>
+ <script type="text/javascript">
+ function isValidIPAddress(ipaddr) {
+ var re = /^\d{1,3}\.\d{1,3}\.\d{1,3}\.\d{1,3}$/;
+ if (re.test(ipaddr)) {
+ var parts = ipaddr.split(".");
+ if (parseInt(parseFloat(parts[0])) == 0) { return false; }
+ for (var i=0; i<parts.length; i++) {
+ if (parseInt(parseFloat(parts[i])) > 255) { return false; }
+ }
+ return true;
+ } else {
+ return false;
+ }
+ }
+ function addinterfaces() {
+ <?php
+
+ foreach($vips as $vip) {
+ if($vip['mode']=='carp') {
+ echo("document.forms['iform'].jif.appendChild(new Option('".$vip['descr']." (".$vip['subnet'].")', '".$vip['subnet']."'));");
+ }
+ }
+
+ ?>
+ }
+ addinterfaces();
+
+ for (var i=0; i < document.forms['iform'].jif.length; i++) {
+ <?php
+ $jif=$config['installedpackages']['pfjailctl']['config'][$_GET['id']]['jif'];
+ echo('if (document.forms["iform"].jif[i].value == "'.$jif.'") {');
+ ?>
+ document.forms['iform'].jif[i].selected = true;
+ } else {
+ document.forms['iform'].jif[i].selected = false;
+ }
+ }
+ if (isValidIPAddress(document.forms['iform'].jif.value)) {
+ document.forms['iform'].jip.disabled=true;
+ }
+
+ function setdisableip() {
+ if (isValidIPAddress(document.forms['iform'].jif.value)) {
+ document.forms['iform'].jip.value=document.forms['iform'].jif.value;
+ document.forms['iform'].jip.disabled=true;
+ } else {
+ // document.forms['iform'].jip.value='';
+ document.forms['iform'].jip.disabled=false;
+ }
+ }
+ document.forms['iform'].jif.addEventListener('change', setdisableip, true);
+ </script>
+ <?php
+}
+
+function jailctl_addtemplates($config) {
+ $templates=$config['installedpackages']['pfjailctltemplates']['config'][0]['templates'];
+ ?>
+ <script type="text/javascript">
+ function addtemplates() {
+ <?php
+ foreach($templates as $template) {
+ echo("document.forms['iform'].jtemplates.appendChild(new Option('".$template['name']."', '".$template['path']."'));");
+ }
+ ?>
+ }
+ addtemplates();
+ </script>
+ <?php
+}
+
+
+function jailctl_jailstatus($config, $jail) {
+ $jconfig=$config['installedpackages']['pfjailctlsettings']['config'][0];
+ #echo("<pre>"); print_r($jail); echo("</pre>");
+
+
+ $jname=$jail['jname'];
+ $jhostname=explode('.', $jname, 2);
+ $jpath=$jconfig['jstorage']."/".$jname;
+ $jip=$jail['jip'];
+ $jif=$jail['jif'];
+
+ if(is_ipaddr($jif)) {
+ $jrealif=jailctl_find_if($jif);
+ #$jrealif=guess_interface_from_ip($jif);
+ #$jrealif=link_carp_interface_to_parent($jif);
+ } else {
+ $jrealif=$config['interfaces'][$jif]['if'];
+ }
+
+ if($config['interfaces'][$jif]['descr']) {
+ $jifdesc=$config['interfaces'][$jif]['descr'];
+ } elseif(is_ipaddr($jif)) {
+ $vips=$config['virtualip']['vip'];
+ foreach($vips as $vip) {
+ if($vip['mode']=='carp' and $vip['subnet']==$jif) {
+ $jifdesc='CARP on '.strtoupper($vip['interface']);
+ }
+ }
+ } else {
+ $jifdesc=strtoupper($jail['jif']);
+ }
+
+ $_out=Array();
+ exec('ps axwww | grep "sysinstall.*'.$jname.'" | grep -v grep', $_out);
+ if(count($_out)) {
+ $jstate='Building';
+ } else {
+ $_out=Array();
+ exec('/usr/local/sbin/jailctl status '.$jname, $_out);
+ #echo("<pre>"); print_r($_out); echo("</pre>");
+ if (substr($_out[0], 0, strlen($jname))==$jname) {
+ $_tmp=Array();
+ ereg("is (.*)\.", array_shift($_out), $_tmp);
+ switch ($_tmp[1]) {
+ case 'down':
+ $jstate='Stopped';
+ break;
+ case 'up':
+ $jstate='Running';
+ break;
+ default:
+ $jstate='Undefined';
+ break;
+ }
+ } else {
+ $jstate='New';
+ }
+ }
+
+ $jstatus['jstate']=$jstate;
+ $jstatus['jpath']=$jpath;
+ $jstatus['jrealif']=$jrealif;
+ $jstatus['jifdesc']=$jifdesc;
+ $jstatus['jhostname']=$jhostname;
+
+ return $jstatus;
+}
+
+
+?> \ No newline at end of file
diff --git a/config/jailctl/jailctl.inc b/config/jailctl/jailctl.inc
new file mode 100644
index 00000000..d6b7344c
--- /dev/null
+++ b/config/jailctl/jailctl.inc
@@ -0,0 +1,217 @@
+<?php
+/* $Id$ */
+include("jailctl-utils.inc");
+
+if($_POST['xml']=='jailctl_settings.xml' && $_POST['jpasswd']) {
+ $_POST['jpasswd']=crypt($_POST['jpasswd']);
+} elseif($_POST['xml']=='jailctl_settings.xml' && !$_POST['jpasswd']) {
+ $_POST['jpasswd']=$config['installedpackages']['pfjailctlsettings']['config'][0]['jpasswd'];
+}
+
+if($_POST['xml']=='jailctl_settings.xml') {
+ $_count=0;
+ while($_count <= count(array_keys($_POST))) {
+ if(isset($_POST['rcconfline'.$_count])) {
+ $_POST['rcconfline'.$_count]=addcslashes($_POST['rcconfline'.$_count], '"');
+ }
+ $_count++;
+ }
+} elseif($_GET['xml']=='jailctl_settings.xml') {
+ $config['installedpackages']['pfjailctlsettings']['config'][0]['jpasswd']='';
+} elseif($_POST['xml']=='jailctl.xml' && is_ipaddr($_POST['jif'])) {
+ $_POST['jip']=$_POST['jif'];
+} elseif($_POST['xml']=='jailctl.xml') {
+ # Stuff goes here?
+}
+
+
+function jailctl_create($config, $jail) {
+ $jstatus=jailctl_jailstatus($config, $jail);
+ $jconfig=$config['installedpackages']['pfjailctlsettings']['config'][0];
+ if($jail['jtemplates']) {
+ jailctl_create_template($jail, $jstatus, $jconfig);
+ } else {
+ jailctl_create_sysinstall($jail, $jstatus, $jconfig);
+ }
+}
+
+function jailctl_delete() {
+ global $config, $jconfig, $jails;
+
+ $jpath=$jconfig['jstorage']."/".$jails[$_GET['id']]['jname'];
+ exec("rm -Rf '".$jpath."' >/dev/null 2>/dev/null &");
+# sync_package_jailctl();
+}
+
+function jailctl_deinstall() {
+# unset($GLOBALS['config']['installedpackages']['pfjailctlsettings']);
+# unset($GLOBALS['config']['installedpackages']['pfjailctl']);
+}
+
+function jailctl_install() {
+ $jails=$GLOBALS['config']['installedpackages']['pfjailctl']['config'];
+ for($i=0;$i<=count($jails);$i++) {
+ if(is_array($jails[$i]) and ! $jails[$i]['jname'])
+ unset($GLOBALS['config']['installedpackages']['pfjailctl']['config'][$i]);
+ }
+
+ if(!$GLOBALS['config']['installedpackages']['pfjailctlsettings']['config'][0]['jif']) {
+ $settings['jif']='lan';
+ $settings['jdnsservers']=$GLOBALS['config']['interfaces']['lan']['ipaddr'];
+ $settings['jstorage']='/usr/local/jails';
+ $settings['jbackup']=$settings['jstorage'];
+ $settings['jbackupexcludes']='--exclude ./usr/ports/* --exclude ./tmp/* --exclude ./var/tmp/* --exclude ./usr/src/*';
+ $settings['jrcconf']='sshd_enable="YES"';
+ $settings['jpasswd']='$1$e4.8A4lV$oU.OQciTOnonltQkK12ff0';
+
+ $GLOBALS['config']['installedpackages']['pfjailctlsettings']['config'][0]=$settings;
+ }
+}
+
+function jailctl_servicestatus() {
+ global $config;
+ $jconfig=$config['installedpackages']['pfjailctlsettings']['config'][0];
+ $jails=$config['installedpackages']['pfjailctl']['config'];
+ is_array($jails) ? $num_jails=count($jails) : $num_jails=0;
+
+ if($num_jails) {
+ for ($i=0;$i<$num_jails;$i++) {
+ $jname=$jails[$i]['jname'];
+ $jstatus=Array();
+ $_jcreate=Array();
+ exec('/usr/local/sbin/jailctl status '.$jname, $jstatus);
+
+ if (substr($jstatus[0], 0, strlen($jname))==$jname) {
+ $_tmp=Array();
+ ereg("is (.*)\.", array_shift($jstatus), $_tmp);
+ switch ($_tmp[1]) {
+ case 'up':
+ break;
+ default:
+ return false;
+ }
+ } else {
+ return false;
+ }
+ }
+ } else {
+ return false;
+ }
+ return true;
+}
+
+function jailctl_do_xmlrpc_sync($config) {
+ $jails=$config['installedpackages']['pfjailctl']['config'][0];
+ $jconfig=$config['installedpackages']['pfjailctlsettings']['config'][0];
+ $sync=$config['installedpackages']['carpsettings']['config'][0];
+
+ if(!$sync['synchronizetoip'] or !$sync['password'])
+ return;
+
+ if($config['system']['webgui']['protocol'] != "") {
+ $synchronizetoip = $config['system']['webgui']['protocol'];
+ $synchronizetoip .= "://";
+ }
+ $port = $config['system']['webgui']['port'];
+ /* if port is empty lets rely on the protocol selection */
+ if($port == "") {
+ if($config['system']['webgui']['protocol'] == "http")
+ $port = "80";
+ else
+ $port = "443";
+ }
+ $synchronizetoip .= $sync['synchronizetoip'];
+
+ /* xml will hold the sections to sync */
+ $xml = array();
+ $xml['pfjailctl'] = $config['installedpackages']['pfjailctl'];
+ $xml['pfjailctlsettings'] = $config['installedpackages']['pfjailctlsettings'];
+
+ /* assemble xmlrpc payload */
+ $params = array(
+ XML_RPC_encode($sync['password']),
+ XML_RPC_encode($xml)
+ );
+
+ /* set a few variables needed for sync code borrowed from filter.inc */
+ $url = $synchronizetoip;
+ log_error("Beginning pfJailctl XMLRPC sync to {$url}:{$port}.");
+ $method = 'pfsense.merge_installedpackages_section_xmlrpc';
+ $msg = new XML_RPC_Message($method, $params);
+ $cli = new XML_RPC_Client('/xmlrpc.php', $url, $port);
+ $cli->setCredentials('admin', $sync['password']);
+ /* send our XMLRPC message and timeout after 25 seconds */
+ $resp = $cli->send($msg, "25");
+ if(!$resp) {
+ $error = "A communications error occured while attempting pfJailctl XMLRPC sync with {$url}:{$port}.";
+ log_error($error);
+ file_notice("sync_settings", $error, "pfJailctl Settings Sync", "");
+ } elseif($resp->faultCode()) {
+ $cli->setDebug(1);
+ $resp = $cli->send($msg, "250");
+ $error = "An error code was received while attempting pfJailctl XMLRPC sync with {$url}:{$port} - Code " . $resp->faultCode() . ": " . $resp->faultString();
+ log_error($error);
+ file_notice("sync_settings", $error, "pfJailctl Settings Sync", "");
+ } else {
+ log_error("pfJailctl XMLRPC sync successfully completed with {$url}:{$port}.");
+ }
+ #echo "done.<br>";
+}
+
+function sync_package_jailctl() {
+ global $config, $g;
+ $jconfig=$config['installedpackages']['pfjailctlsettings']['config'][0];
+ $jails=$config['installedpackages']['pfjailctl']['config'];
+ is_array($jails) ? $num_jails=count($jails) : $num_jails=0;
+
+ $jdefaultif=$config['interfaces']['lan']['if'];
+
+ conf_mount_rw();
+ config_lock();
+ $fd = fopen("/usr/local/etc/jails.conf","w");
+
+ fwrite($fd, 'IF="'.$jdefaultif.'"'."\n");
+ fwrite($fd, 'JAIL_HOME="'.$jconfig['jstorage'].'/"'."\n");
+ fwrite($fd, 'BACKUPDIR="'.$jconfig['jbackup'].'"'."\n");
+ fwrite($fd, 'BACKUP_EXCLUDE="'.$jconfig['jbackupexcludes'].'"'."\n");
+ fwrite($fd, 'INSTALLWORLD_FLAGS="'.$jconfig['jinstallflags'].'"'."\n");
+ fwrite($fd, 'BATCH="'.$jconfig['jbatchcreate'].'"'."\n");
+ fwrite($fd, 'ROOT_PW="'.$jconfig['jpasswd'].'"'."\n");
+ fwrite($fd, 'NAMESERVERS="'.$jconfig['jdnsservers'].'"'."\n");
+ fwrite($fd, 'RC_CONF=\''.$jconfig['jrcconf'].'\''."\n");
+
+ fwrite($fd, "\nJAILS=''\n");
+
+ $_rcfile['file']='jails.sh';
+ $_rcfile['start']='';
+ $_rcfile['stop']='';
+ if($num_jails) {
+ for ($i=0;$i<$num_jails;$i++) {
+ $jname=$jails[$i]['jname'];
+ $jpath=$jconfig['jstorage']."/".$jname."/";
+ $jif=$jails[$i]['jif'];
+ if(is_ipaddr($jif)) {
+ $jip=$jif;
+ #$jif=guess_interface_from_ip($jif);
+ $jif=jailctl_find_if($jif);
+ } else {
+ $jif=$config['interfaces'][$jails[$i]['jif']]['if'];
+ $jip=$jails[$i]['jip'];
+ }
+
+ $_cfg="JAILS=\"\$JAILS $jname:$jip;$jpath;$jif\"\n";
+ fwrite($fd, $_cfg);
+
+ if($jails[$i]['jautostart']=='on') {
+ $_rcfile['start'].="/usr/local/sbin/jailctl start $jname \n\t";
+ $_rcfile['stop'].="/usr/local/sbin/jailctl stop $jname \n\t";
+ }
+ }
+ }
+
+ write_rcfile($_rcfile);
+ fclose($fd);
+ jailctl_do_xmlrpc_sync($config);
+}
+
+?>
diff --git a/config/jailctl/jailctl.xml b/config/jailctl/jailctl.xml
new file mode 100644
index 00000000..079ddb6b
--- /dev/null
+++ b/config/jailctl/jailctl.xml
@@ -0,0 +1,233 @@
+<?xml version="1.0" encoding="utf-8" ?>
+<!DOCTYPE packagegui SYSTEM "./schema/packages.dtd">
+<?xml-stylesheet type="text/xsl" href="./xsl/package.xsl"?>
+<packagegui>
+ <description>Jail management</description>
+ <requirements>Disk space...</requirements>
+ <faq>Currently there are no FAQ items provided.</faq>
+ <name>pfJailctl</name>
+ <version>0.1</version>
+ <title>Jails</title>
+ <!-- Menu is where this packages menu will appear -->
+ <menu>
+ <name>Jails</name>
+ <tooltiptext>Jail management</tooltiptext>
+ <section>Services</section>
+ <configfile>jailctl.xml</configfile>
+ </menu>
+ <service>
+ <name>Jails</name>
+ <rcfile>jails.sh</rcfile>
+ <description>All jails with autostart enabled.</description>
+ <custom_php_service_status_command>
+ include("/usr/local/pkg/jailctl.inc");
+ jailctl_servicestatus();
+ </custom_php_service_status_command>
+ </service>
+ <!-- configpath gets expanded out automatically and config items will be
+ stored in that location -->
+ <configpath>['installedpackages']['$packagename']['config']</configpath>
+ <additional_files_needed>
+ <prefix>/usr/local/pkg/</prefix>
+ <chmod>0644</chmod>
+ <item>http://www.pfsense.com/packages/config/jailctl/jailctl_defaults.xml</item>
+ </additional_files_needed>
+ <additional_files_needed>
+ <prefix>/usr/local/pkg/</prefix>
+ <chmod>0644</chmod>
+ <item>http://www.pfsense.com/packages/config/jailctl/jailctl_settings.xml</item>
+ </additional_files_needed>
+ <additional_files_needed>
+ <prefix>/usr/local/pkg/</prefix>
+ <chmod>0644</chmod>
+ <item>http://www.pfsense.com/packages/config/jailctl/jailctl.inc</item>
+ </additional_files_needed>
+ <additional_files_needed>
+ <prefix>/usr/local/pkg/</prefix>
+ <chmod>0644</chmod>
+ <item>http://www.pfsense.com/packages/config/jailctl/jailctl-utils.inc</item>
+ </additional_files_needed>
+ <additional_files_needed>
+ <prefix>/usr/local/pkg/</prefix>
+ <chmod>0644</chmod>
+ <item>http://www.pfsense.com/packages/config/jailctl/jailctl_list.inc</item>
+ </additional_files_needed>
+ <additional_files_needed>
+ <prefix>/usr/local/sbin/</prefix>
+ <chmod>0755</chmod>
+ <item>http://www.pfsense.com/packages/config/jailctl/jailctl</item>
+ </additional_files_needed>
+ <additional_files_needed>
+ <prefix>/usr/sbin/</prefix>
+ <chmod>0755</chmod>
+ <item>http://www.pfsense.com/packages/config/jailctl/sysinstall</item>
+ </additional_files_needed>
+
+ <tabs>
+ <tab>
+ <text>Jails</text>
+ <url>/pkg.php?xml=jailctl.xml</url>
+ <active/>
+ </tab>
+ <tab>
+ <text>Global settings</text>
+ <url>/pkg_edit.php?xml=jailctl_settings.xml&amp;id=0</url>
+ </tab>
+<!-- <tab>
+ <text>Jail defaults</text>
+ <url>/pkg_edit.php?xml=jailctl_defaults.xml&amp;id=0</url>
+ </tab> -->
+ </tabs>
+
+
+ <adddeleteeditpagefields>
+ <columnitem>
+ <fielddescr>State</fielddescr>
+ <fieldname>jstate</fieldname>
+ </columnitem>
+ <columnitem>
+ <fielddescr>Jail name</fielddescr>
+ <fieldname>jname</fieldname>
+ </columnitem>
+ <columnitem>
+ <fielddescr>Jail IF</fielddescr>
+ <fieldname>jifdesc</fieldname>
+ </columnitem>
+ <columnitem>
+ <fielddescr>Jail IP</fielddescr>
+ <fieldname>jip</fieldname>
+ </columnitem>
+ <columnitem>
+ <fielddescr>Jail path</fielddescr>
+ <fieldname>jpath</fieldname>
+ </columnitem>
+ <columnitem>
+ <fielddescr>Actions</fielddescr>
+ <fieldname>jactions</fieldname>
+ </columnitem>
+
+ </adddeleteeditpagefields>
+
+ <fields>
+ <field>
+ <fielddescr>Jail hostname</fielddescr>
+ <fieldname>jname</fieldname>
+ <description>FQDN of the jail</description>
+ <type>input</type>
+ </field>
+ <field>
+ <fielddescr>Network interface</fielddescr>
+ <fieldname>jif</fieldname>
+ <description>Jail will be bound to this interface</description>
+ <type>interfaces_selection</type>
+ </field>
+ <field>
+ <fielddescr>IP address</fielddescr>
+ <fieldname>jip</fieldname>
+ <description>Must be in the same subnet as the parent interface</description>
+ <type>input</type>
+ </field>
+ <field>
+ <fielddescr>Autostart jail on boot?</fielddescr>
+ <fieldname>jautostart</fieldname>
+ <description>Start this jail automatically when the system boots?</description>
+ <type>checkbox</type>
+ </field>
+
+
+ <field>
+ <fielddescr>Jail templates</fielddescr>
+ <fieldname>jselect_templates</fieldname>
+ <type>listtopic</type>
+ <name>Select a predefined template for your jail:</name>
+ </field>
+ <field>
+ <fielddescr>Templates</fielddescr>
+ <fieldname>jtemplates</fieldname>
+ <description>Files from the templates will be read-only inside the jail.</description>
+ <type>select</type>
+ <options>
+ <option><name> --- select --- </name><value></value></option>
+ </options>
+ <default_value>jtemplate_default</default_value>
+ </field>
+ <field>
+ <fielddescr>Use unionfs</fielddescr>
+ <fieldname>juse_unionfs</fieldname>
+ <description>Use unionfs instead of nullfs to mount the template contents into the jail</description>
+ <type>checkbox</type>
+ </field>
+
+ <field>
+ <fielddescr>Package sets</fielddescr>
+ <fieldname>jselect_sets</fieldname>
+ <type>listtopic</type>
+ <name>OR select a distribution set to install:</name>
+ </field>
+ <field>
+ <fielddescr>Distribution sets</fielddescr>
+ <fieldname>jdistset</fieldname>
+ <description>Select a standard set of distributions to install</description>
+ <type>select</type>
+ <options>
+ <option><name> --- select --- </name><value></value></option>
+ <option><name>User (binaries only)</name><value>distSetUser</value></option>
+ <option><name>Developer (src/all, binaries)</name><value>distSetDeveloper</value></option>
+ <option><name>Kernel developer (src/kern, binaries)</name><value>distSetKernDeveloper</value></option>
+ <option><name>Minimum (minimal binaries)</name><value>distSet</value></option>
+ </options>
+ <default_value></default_value>
+ </field>
+
+ <field>
+ <fielddescr>Individual packages</fielddescr>
+ <fieldname>jselect_individual</fieldname>
+ <type>listtopic</type>
+ <name>OR select individual distributions in addition to 'base':</name>
+ </field>
+
+ <field>
+ <fielddescr>Individual distributions</fielddescr>
+ <fieldname>jdists</fieldname>
+ <description>Select individual distributions (multiple selection)</description>
+ <type>select</type>
+ <options>
+ <option><name>Manual pages</name><value>manpages</value></option>
+ <option><name>The Ports collection</name><value>ports</value></option>
+ <option><name>Miscellaneous documentation</name><value>doc</value></option>
+ <option><name>Local additions collection</name><value>local</value></option>
+ <option><name>X.org client binaries</name><value>Xbin</value></option>
+ <option><name>X.org libraries</name><value>Xlib</value></option>
+ <option><name>X.org manual pages</name><value>Xman</value></option>
+ <option><name>X.org imake distribution</name><value>Xprog</value></option>
+ <option><name>Games</name><value>games</value></option>
+ </options>
+ <multiple/>
+ </field>
+
+ </fields>
+
+
+ <!-- php hooks -->
+ <include_file>/usr/local/pkg/jailctl_list.inc</include_file>
+ <custom_add_php_command>
+ sync_package_jailctl();
+ </custom_add_php_command>
+ <custom_delete_php_command>
+ jailctl_delete();
+ </custom_delete_php_command>
+ <custom_php_resync_config_command>
+ sync_package_jailctl();
+ </custom_php_resync_config_command>
+ <custom_php_install_command>
+ jailctl_install();
+ </custom_php_install_command>
+ <custom_php_deinstall_command>
+ jailctl_deinstall();
+ </custom_php_deinstall_command>
+ <custom_php_after_form_command>
+ jailctl_addinterfaces($config);
+ jailctl_addtemplates($config);
+ </custom_php_after_form_command>
+</packagegui>
+
diff --git a/config/jailctl/jailctl_defaults.xml b/config/jailctl/jailctl_defaults.xml
new file mode 100644
index 00000000..c499abcb
--- /dev/null
+++ b/config/jailctl/jailctl_defaults.xml
@@ -0,0 +1,122 @@
+<?xml version="1.0" encoding="utf-8" ?>
+<!DOCTYPE packagegui SYSTEM "./schema/packages.dtd">
+<?xml-stylesheet type="text/xsl" href="./xsl/package.xsl"?>
+<packagegui>
+ <description>Jail management</description>
+ <requirements>Built world in /usr/obj</requirements>
+ <faq>Currently there are no FAQ items provided.</faq>
+ <name>pfJailctl_Defaults</name>
+ <version>0.1</version>
+ <title>Jails: Jail building defaults</title>
+ <!-- configpath gets expanded out automatically and config items will be
+ stored in that location -->
+ <configpath>['installedpackages']['package']['$packagename']['config']</configpath>
+
+ <tabs>
+ <tab>
+ <text>Jails</text>
+ <url>/pkg.php?xml=jailctl.xml</url>
+ </tab>
+ <tab>
+ <text>Global settings</text>
+ <url>/pkg_edit.php?xml=jailctl_settings.xml&amp;id=0</url>
+ </tab>
+ <tab>
+ <text>Jail defaults</text>
+ <url>/pkg_edit.php?xml=jailctl_defaults.xml&amp;id=0</url>
+ <active/>
+ </tab>
+ </tabs>
+
+ <fields>
+ <field>
+ <fielddescr>Package sets</fielddescr>
+ <fieldname>jdist_select_sets</fieldname>
+ <type>listtopic</type>
+ <name>Select a distribution set:</name>
+ </field>
+ <field>
+ <fielddescr>Distribution set</fielddescr>
+ <fieldname>jdist_set</fieldname>
+ <description>Select a standard set of distributions to install</description>
+ <type>select</type>
+ <value>eng</value>
+ <options>
+ <option><name>Developer (src/all, binaries)</name><value>distSetDeveloper</value></option>
+ <option><name>Kernel developer (src/kern, binaries)</name><value>distSetKernDeveloper</value></option>
+ <option><name>User (binaries only)</name><value>distSetUser</value></option>
+ <option><name>Minimum (minimal binaries)</name><value>distSet</value></option>
+ </options>
+ <default_value>distSetUser</default_value>
+ </field>
+ <field>
+ <fielddescr>Individual packages</fielddescr>
+ <fieldname>jdist_select_individual</fieldname>
+ <type>listtopic</type>
+ <name>OR select individual distributions in addition to base:</name>
+ </field>
+ <field>
+ <fielddescr>Manual pages</fielddescr>
+ <fieldname>jdist_manpages</fieldname>
+ <type>checkbox</type>
+ </field>
+ <field>
+ <fielddescr>Games</fielddescr>
+ <fieldname>jdist_games</fieldname>
+ <type>checkbox</type>
+ </field>
+ <field>
+ <fielddescr>The Ports collection</fielddescr>
+ <fieldname>jdist_ports</fieldname>
+ <type>checkbox</type>
+ </field>
+ <field>
+ <fielddescr>Miscellaneous documentation</fielddescr>
+ <fieldname>jdist_doc</fieldname>
+ <type>checkbox</type>
+ </field>
+ <field>
+ <fielddescr>X.Org client binaries</fielddescr>
+ <fieldname>jdist_xbin</fieldname>
+ <type>checkbox</type>
+ </field>
+ <field>
+ <fielddescr>X.Org libraries</fielddescr>
+ <fieldname>jdist_xlib</fieldname>
+ <type>checkbox</type>
+ </field>
+ <field>
+ <fielddescr>X.Org manual pages</fielddescr>
+ <fieldname>jdist_xman</fieldname>
+ <type>checkbox</type>
+ </field>
+ <field>
+ <fielddescr>X.Org imake distribution</fielddescr>
+ <fieldname>jdist_xprog</fieldname>
+ <type>checkbox</type>
+ </field>
+ <field>
+ <fielddescr>Local additions collection</fielddescr>
+ <fieldname>jdist_local</fieldname>
+ <type>checkbox</type>
+ </field>
+ </fields>
+
+
+ <!-- php hooks -->
+ <include_file>/usr/local/pkg/jailctl.inc</include_file>
+ <custom_add_php_command>
+ sync_package_jailctl();
+ </custom_add_php_command>
+ <custom_delete_php_command>
+ sync_package_jailctl();
+ </custom_delete_php_command>
+ <custom_php_resync_config_command>
+ sync_package_jailctl();
+ </custom_php_resync_config_command>
+ <custom_php_install_command>
+ </custom_php_install_command>
+ <custom_php_deinstall_command>
+ </custom_php_deinstall_command>
+</packagegui>
+
diff --git a/config/jailctl/jailctl_list.inc b/config/jailctl/jailctl_list.inc
new file mode 100644
index 00000000..d1869bd6
--- /dev/null
+++ b/config/jailctl/jailctl_list.inc
@@ -0,0 +1,112 @@
+<?php
+include('/usr/local/pkg/jailctl.inc');
+
+$jconfig=$config['installedpackages']['pfjailctlsettings']['config'][0];
+$jails=$config['installedpackages']['pfjailctl']['config'];
+is_array($jails) ? $num_jails=count($jails) : $num_jails=0;
+
+
+if($num_jails) {
+ for ($i=0;$i<$num_jails;$i++) {
+ $jail=$jails[$i];
+ $jstatus=jailctl_jailstatus($config, $jail);
+ $_path=$jstatus['jpath'];
+ $_name=$jail['jname'];
+ $_ip=$jail['jip'];
+ $_hostname=$jstatus['jhostname'];
+ $_dnsservers=$jconfig['jdnsservers'];
+ $_passwd=$jconfig['jpasswd'];
+ $_template=$jail['jtemplates'];
+ $mounts=$GLOBALS['jailctl_tmp']['mounts'];
+ $unionmounts=$GLOBALS['jailctl_tmp']['unionmounts'];
+ $mount_unionfs=$GLOBALS['jailctl_tmp']['mount_unionfs'];
+ $mount_nullfs=$GLOBALS['jailctl_tmp']['mount_nullfs'];
+
+ if($_GET['jaction'] && $_GET['id']==$i) {
+ switch ($_GET['jaction']) {
+ case 'create':
+# if($jstate!='New') break;
+ jailctl_create($config, $jail);
+ if($jconfig['debug']) {
+ echo("Create script:<br><pre>");
+ echo(file_get_contents("/tmp/jcreate_".$_name));
+ echo("</pre>");
+ } else {
+ header('Location: /pkg.php?xml=jailctl.xml');
+ }
+ flush();
+ exit;
+
+ case 'start':
+# if($jstate!='Stopped') break;
+ exec('umount -f '.$_path.'/dev');
+ if($_template) {
+ $jail['juse_unionfs']=='on' ? $mount=$mount_unionfs : $mount=$mount_nullfs ;
+ foreach($mounts as $mp) {
+ exec($mount.' '.$_template.'/'.$mp.' '.$_path.'/'.$mp, $_cmd);
+ }
+ foreach($unionmounts as $mp) {
+ exec($mount_unionfs.' '.$_template.'/'.$mp.' '.$_path.'/'.$mp, $_cmd);
+ }
+ }
+
+ $cmd='jailctl start '.$_name;
+ exec($cmd, $_cmd);
+ if($jconfig['debug']) {
+ echo("<script>alert('".addcslashes(implode("\\n", $_cmd), "'")."'); this.location.replace('/pkg.php?xml=jailctl.xml');</script>");
+ } else {
+ header('Location: /pkg.php?xml=jailctl.xml');
+ }
+ flush();
+ exit;
+
+ case 'stop':
+# if($jstate!='Running') break;
+ $cmd='jailctl stop '.$_name;
+ exec($cmd, $_cmd);
+ if($_template) {
+ foreach($mounts as $mp) {
+ exec('umount -f '.$_template.'/'.$mp.' '.$_path.'/'.$mp, $_cmd);
+ }
+ foreach($unionmounts as $mp) {
+ exec('umount -f '.$_template.'/'.$mp.' '.$_path.'/'.$mp, $_cmd);
+ }
+ }
+ exec('umount -f '.$_path.'/dev');
+ if($jconfig['debug']) {
+ echo("<script>alert('".addcslashes(implode("\\n", $_cmd), "'")."'); this.location.replace('/pkg.php?xml=jailctl.xml');</script>");
+ } else {
+ header('Location: /pkg.php?xml=jailctl.xml');
+ }
+ flush();
+ exit;
+ }
+ }
+
+ $config['installedpackages']['pfjailctl']['config'][$i]['jstate']=$jstatus['jstate'];
+ $config['installedpackages']['pfjailctl']['config'][$i]['jpath']=$jstatus['jpath'];
+ $config['installedpackages']['pfjailctl']['config'][$i]['jifdesc']=
+ $jstatus['jifdesc']." (".$jstatus['jrealif'].")";
+
+ $jactions=Array();
+ switch ($jstatus['jstate']) {
+ case 'Building':
+ $jactions[]="";
+ break;
+ case 'New':
+ $jactions[]="<a href='/pkg.php?xml=jailctl.xml&jaction=create&id=".$i."'>Create</a>";
+ break;
+ case 'Stopped':
+ $jactions[]="<a href='/pkg.php?xml=jailctl.xml&jaction=start&id=".$i."'>Start</a>";
+ #$jactions[]="<a href='/pkg.php?xml=jailctl.xml&jaction=upgrade&id=".$i."'>Upgrade</a>";
+ break;
+ case 'Running':
+ $jactions[]="<a href='/pkg.php?xml=jailctl.xml&jaction=stop&id=".$i."'>Stop</a>";
+ break;
+ }
+ $config['installedpackages']['pfjailctl']['config'][$i]['jactions']=implode(' | ', $jactions);
+ }
+}
+
+
+?> \ No newline at end of file
diff --git a/config/jailctl/jailctl_settings.xml b/config/jailctl/jailctl_settings.xml
new file mode 100644
index 00000000..e82eea6c
--- /dev/null
+++ b/config/jailctl/jailctl_settings.xml
@@ -0,0 +1,121 @@
+<?xml version="1.0" encoding="utf-8" ?>
+<!DOCTYPE packagegui SYSTEM "./schema/packages.dtd">
+<?xml-stylesheet type="text/xsl" href="./xsl/package.xsl"?>
+<packagegui>
+ <description>Jail management</description>
+ <requirements>Built world in /usr/obj</requirements>
+ <faq>Currently there are no FAQ items provided.</faq>
+ <name>pfJailctl_Settings</name>
+ <version>0.1</version>
+ <title>Jails: Settings</title>
+ <!-- configpath gets expanded out automatically and config items will be
+ stored in that location -->
+ <configpath>['installedpackages']['$packagename']['config']</configpath>
+
+ <tabs>
+ <tab>
+ <text>Jails</text>
+ <url>/pkg.php?xml=jailctl.xml</url>
+ </tab>
+ <tab>
+ <text>Global settings</text>
+ <url>/pkg_edit.php?xml=jailctl_settings.xml&amp;id=0</url>
+ <active/>
+ </tab>
+<!-- <tab>
+ <text>Jail defaults</text>
+ <url>/pkg_edit.php?xml=jailctl_defaults.xml&amp;id=0</url>
+ </tab> -->
+ </tabs>
+
+ <fields>
+ <field>
+ <fielddescr>FTP mirror</fielddescr>
+ <fieldname>jftpmirror</fieldname>
+ <description>Select a FTP server (mirror) to use for sysinstall</description>
+ <type>select</type>
+ <options>
+ <option><name>ftp.FreeBSD.org</name><value>ftp://ftp.FreeBSD.org/pub/FreeBSD/</value></option>
+ <option><name>ftp.no.FreeBSD.org</name><value>ftp://ftp.no.FreeBSD.org/pub/FreeBSD/</value></option>
+ <option><name>ftp.de.FreeBSD.org</name><value>ftp://ftp.de.FreeBSD.org/pub/FreeBSD/</value></option>
+ <option><name>ftp.se.FreeBSD.org</name><value>ftp://ftp.se.FreeBSD.org/pub/FreeBSD/</value></option>
+ </options>
+ <default_value>ftp://ftp.FreeBSD.org/pub/FreeBSD/</default_value>
+ </field>
+ <field>
+ <fielddescr>DNS servers</fielddescr>
+ <description>DNS servers to be added to /etc/resolv.conf of jails, space separated IP addresses</description>
+ <fieldname>jdnsservers</fieldname>
+ <type>textarea</type>
+ </field>
+ <field>
+ <fielddescr>Location for jails</fielddescr>
+ <fieldname>jstorage</fieldname>
+ <description>Jails will be stored here</description>
+ <type>input</type>
+ <default>/usr/local/jails</default>
+ <default_value>/usr/local/jails</default_value>
+ </field>
+ <field>
+ <fielddescr>Location for jail backups</fielddescr>
+ <fieldname>jbackup</fieldname>
+ <description>Backups are .tgz files of the jail directory</description>
+ <type>input</type>
+ <default_value>/usr/local/jails</default_value>
+ </field>
+ <field>
+ <fielddescr>Files to exclude from backup</fielddescr>
+ <fieldname>jbackupexcludes</fieldname>
+ <description>Files to exclude from backup</description>
+ <type>input</type>
+ <default_value>--exclude ./usr/ports/* --exclude ./tmp/* --exclude ./var/tmp/* --exclude ./usr/src/*</default_value>
+ </field>
+ <field>
+ <fielddescr>System configuration</fielddescr>
+ <fieldname>jrcconf</fieldname>
+ <type>rowhelper</type>
+ <rowhelper>
+ <rowhelperfield>
+ <fielddescr>Lines to add to /etc/rc.conf</fielddescr>
+ <type>input</type>
+ <size>25</size>
+ <fieldname>rcconfline</fieldname>
+ </rowhelperfield>
+ </rowhelper>
+ </field>
+ <field>
+ <fielddescr>Default password for jails</fielddescr>
+ <fieldname>jpasswd</fieldname>
+ <description>Set to &quot;system&quot; by default.&lt;br&gt;
+ &lt;b&gt;NOTE: Only type here if you want to change the current default password!&lt;/b&gt;&lt;br&gt;
+ This field will show as empty even if a password has been set. Changing this will not affect existing jails.</description>
+ <type>password</type>
+ <default_value>system</default_value>
+ </field>
+ <field>
+ <fielddescr>Debug mode</fielddescr>
+ <fieldname>debug</fieldname>
+ <type>checkbox</type>
+ <description>Enable debug information do be shown by the GUI</description>
+ </field>
+
+ </fields>
+
+
+ <!-- php hooks -->
+ <include_file>/usr/local/pkg/jailctl.inc</include_file>
+ <custom_add_php_command>
+ sync_package_jailctl();
+ </custom_add_php_command>
+ <custom_delete_php_command>
+ sync_package_jailctl();
+ </custom_delete_php_command>
+ <custom_php_resync_config_command>
+ sync_package_jailctl();
+ </custom_php_resync_config_command>
+ <custom_php_install_command>
+ </custom_php_install_command>
+ <custom_php_deinstall_command>
+ </custom_php_deinstall_command>
+</packagegui>
+
diff --git a/config/jailctl/sysinstall b/config/jailctl/sysinstall
new file mode 100755
index 00000000..d4a05fb1
--- /dev/null
+++ b/config/jailctl/sysinstall
Binary files differ
diff --git a/pkg_config.7.xml b/pkg_config.7.xml
index 1d922329..7fa97460 100755
--- a/pkg_config.7.xml
+++ b/pkg_config.7.xml
@@ -628,5 +628,31 @@
<required_version>1.2.1</required_version>
<maximum_version>1.2.3</maximum_version>
</package>
+ <package>
+ <name>pfJailctl</name>
+ <descr>pfSense wrapper for jailctl - a jail management tool. Allows you to run jails on pfSense.</descr>
+ <website>http://anduin.net/jailctl/</website>
+ <category>System</category>
+ <version>0.5</version>
+ <required_version>1.2.3</required_version>
+ <status>BETA</status>
+ <pkginfolink>http://doc.pfsense.org/index.php/PfJailctl_package</pkginfolink>
+ <config_file>http://www.pfsense.com/packages/config/jailctl.xml</config_file>
+ <configurationfile>jailctl.xml</configurationfile>
+ <maintainer>ltning-jailctl@anduin.net</maintainer>
+ </package>
+ <package>
+ <name>jail_template</name>
+ <descr>Basic template for jails, probably requires pfJailctl to be useful. Includes 'base' and 'manpages' dists.</descr>
+ <website>http://anduin.net/jailctl/</website>
+ <category>System</category>
+ <version>0.2</version>
+ <required_version>1.2.3</required_version>
+ <status>BETA</status>
+ <pkginfolink>http://doc.pfsense.org/index.php/PfJailctl_package</pkginfolink>
+ <config_file>http://www.pfsense.com/packages/config/jail_template.xml</config_file>
+ <configurationfile>jail_template.xml</configurationfile>
+ <maintainer>ltning-jailctl@anduin.net</maintainer>
+ </package>
</packages>
</pfsensepkgs>