diff options
Diffstat (limited to 'sysutils/pfSense-upgrade/files/RaptorGuard-upgrade')
-rwxr-xr-x | sysutils/pfSense-upgrade/files/RaptorGuard-upgrade | 1146 |
1 files changed, 1146 insertions, 0 deletions
diff --git a/sysutils/pfSense-upgrade/files/RaptorGuard-upgrade b/sysutils/pfSense-upgrade/files/RaptorGuard-upgrade new file mode 100755 index 0000000..52ad05a --- /dev/null +++ b/sysutils/pfSense-upgrade/files/RaptorGuard-upgrade @@ -0,0 +1,1146 @@ +#!/bin/sh +# +# pfSense-upgrade +# +# part of pfSense (https://www.pfsense.org) +# Copyright (c) 2015-2016 Rubicon Communications, LLC (Netgate) +# All rights reserved. +# +# Licensed under the Apache License, Version 2.0 (the "License"); +# you may not use this file except in compliance with the License. +# You may obtain a copy of the License at +# +# http://www.apache.org/licenses/LICENSE-2.0 +# +# Unless required by applicable law or agreed to in writing, software +# distributed under the License is distributed on an "AS IS" BASIS, +# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +# See the License for the specific language governing permissions and +# limitations under the License. + +usage() { + me=$(basename $0) + cat << EOD >&2 +Usage: ${me} [-46bdfhnRUy] [-l logfile] [-p socket] [-c|-u|[-i|-d] pkg_name]" + -4 - Force IPv4" + -6 - Force IPv6" + -b - Platform is booting" + -d - Turn on debug" + -f - Force package installation" + -h - Show this usage help" + -l logfile - Logfile path (defaults to /cf/conf/upgrade_log.txt)" + -n - Dry run" + -p socket - Write pkg progress to socket" + -R - Do not reboot (this can be dangerous)" + -U - Do not update repository information" + -y - Assume yes as the answer to any possible interaction" +" +The following parameters are mutually exclusive:" + -c - Check if upgrade is necessary" + -i pkg_name - Install package PKG_NAME" + -r pkg_name - Remove package PKG_NAME" + -u - Update repository information" +EOD +} + +_echo() { + local _n="" + if [ "${1}" = "-n" ]; then + shift + _n="-n" + fi + + if [ -z "${logfile}" ]; then + logfile=/dev/null + fi + + echo ${_n} "${@}" | tee -a ${logfile} +} + +_exec() { + local _cmd="${1}" + local _msg="${2}" + local _mute="${3}" + local _ignore_result="${4}" + local _stdout="${stdout}" + + if [ -z "${_cmd}" -o -z "${_msg}" ]; then + return 1 + fi + + if [ "${_mute}" != "mute" ]; then + _stdout='' + fi + + _echo -n ">>> ${_msg}... " + if [ -z "${_stdout}" ]; then + _echo "" + # Ref. https://stackoverflow.com/a/30658405 + exec 4>&1 + local _result=$( \ + { { ${_cmd} 2>&1 3>&-; printf $? 1>&3; } 4>&- \ + | tee -a ${logfile} 1>&4; } 3>&1) + exec 4>&- + else + # Ref. https://stackoverflow.com/a/30658405 + exec 4>&1 + local _result=$( \ + { { ${_cmd} >${_stdout} 2>&1 3>&-; printf $? 1>&3; } 4>&- \ + | tee -a ${logfile} 1>&4; } 3>&1) + exec 4>&- + fi + + if [ ${_result} -eq 0 -o -n "${_ignore_result}" ]; then + [ -n "${_stdout}" ] \ + && _echo "done." + return 0 + else + [ -n "${_stdout}" ] \ + && _echo "failed." + _exit 1 + fi +} + +_exit() { + trap "-" 1 2 15 EXIT + + if [ -n "${delete_pid}" -a -f "${pid_file}" ]; then + rm -f ${pid_file} + fi + + if [ -z "${booting}" -o "${boot_stage}" != "2" ]; then + php /etc/rc.conf_mount_ro + fi + + if [ -n "${nc_pid}" ] && ps -p ${nc_pid} >/dev/null 2>&1; then + kill ${nc_pid} + fi + + if [ -n "${delete_annotation}" ]; then + pkg annotate -q -D ${kernel_pkg} next_stage + fi + + if [ -n "${unlock_additional_pkgs}" ]; then + pkg_unlock "${pkg_prefix}*" + fi + + local _rc=${1:-"0"} + + # If EVENT_PIPE is defined, GUI is calling + if [ -n "${progress_socket}" ]; then + local _need_reboot_str="" + [ -n "${need_reboot}" ] \ + && _need_reboot_str=" __REBOOT_AFTER=${reboot_after}" + _echo "__RC=${_rc}${_need_reboot_str}" + fi + + exit ${_rc} +} + +pkg_with_pb() { + local _event_pipe="" + + if [ -n "${progress_socket}" ]; then + if [ -e "${progress_socket}" ]; then + rm -f ${progress_socket} + fi + + _event_pipe="-o EVENT_PIPE=${progress_socket}" + + nc -lU ${progress_socket} >> ${progress_file} & + nc_pid=$! + + while [ ! -e "${progress_socket}" ]; do + sleep 0.1 + done + fi + + pkg ${_event_pipe} $@ + local _pkg_result=$? + nc_pid="" + return ${_pkg_result} +} + +fetch_upgrade_packages() { + _exec "pkg_with_pb upgrade -F" "Downloading upgrade packages" +} + +pkg_lock() { + local _pkgs="$@" + + if [ -z "${_pkgs}" ]; then + return + fi + + for _pkg in ${_pkgs}; do + for _pkg_name in $(pkg query -g %n "${_pkg}"); do + _locked=$(pkg query %k ${_pkg_name}) + if [ "${_locked}" != "0" ]; then + continue + fi + _exec "pkg lock ${_pkg_name}" \ + "Locking package ${_pkg_name}" mute + done + done +} + +pkg_unlock() { + local _pkgs="$@" + + if [ -z "${_pkgs}" ]; then + return + fi + + for _pkg in ${_pkgs}; do + for _pkg_name in $(pkg query -g %n "${_pkg}"); do + _locked=$(pkg query %k ${_pkg_name}) + if [ "${_locked}" != "1" ]; then + continue + fi + _exec "pkg unlock ${_pkg_name}" \ + "Unlocking package ${_pkg_name}" mute + done + done +} + +set_vital_flag() { + for _pkg in "$@"; do + local _vflag=$(pkg query %V ${_pkg} 2>/dev/null) + + [ "${_vflag}" != "0" ] \ + && continue + + _exec "pkg set -y -v 1 ${_pkg}" \ + "Setting vital flag on ${_pkg}" mute + done +} + +abi_setup() { + local _freebsd_version=$(uname -r) + local _pkg_repo_conf="/usr/local/etc/pkg/repos/${product}.conf" + + local _arch=$(uname -p) + + CUR_ABI="FreeBSD:${_freebsd_version%%.*}:${_arch}" + CUR_ALTABI="freebsd:${_freebsd_version%%.*}" + + if [ "${_arch}" = "armv6" ]; then + CUR_ALTABI="${CUR_ALTABI}:${_arch}:32:el:eabi:hardfp" + elif [ "${_arch}" = "i386" ]; then + CUR_ALTABI="${CUR_ALTABI}:x86:32" + else + CUR_ALTABI="${CUR_ALTABI}:x86:64" + fi + + if [ ! -e ${_pkg_repo_conf} ]; then + validate_repo_conf + fi + + local _repo_abi_file=$(readlink ${_pkg_repo_conf}) + + if [ -f ${_repo_abi_file%%.conf}.abi ]; then + ABI=$(cat ${_repo_abi_file%%.conf}.abi) + else + ABI=${CUR_ABI} + fi + + if [ -f ${_repo_abi_file%%.conf}.altabi ]; then + ALTABI=$(cat ${_repo_abi_file%%.conf}.altabi) + else + ALTABI=${CUR_ALTABI} + fi + + # Make sure pkg.conf is set properly so GUI can work + echo "ABI=${ABI}" > /usr/local/etc/pkg.conf + echo "ALTABI=${ALTABI}" >> /usr/local/etc/pkg.conf + + if [ "${CUR_ABI}" = "${ABI}" -o "${CUR_ABI}" = "${ALTABI}" ] ; then + NEW_MAJOR="" + else + NEW_MAJOR=1 + ABI="${ALTABI}" + fi + + export CUR_ABI CUR_ALTABI ABI ALTABI NEW_MAJOR +} + +pkg_update() { + local _force="" + local _mute="" + + [ "${1}" = "force" ] \ + && _force=" -f" + + if [ -z "${_force}" -a -n "${dont_update}" ]; then + return 0 + fi + + [ "${2}" = "mute" ] \ + && _mute="mute" + + abi_setup + + _exec "pkg update${_force}" "Updating repositories metadata" ${_mute} +} + +pkg_upgrade_repo() { + if [ -z "${NEW_MAJOR}" -a "$(compare_pkg_version pkg)" = "<" ]; then + _exec "pkg upgrade${dont_update} pkg" "Upgrading pkg" mute + pkg_update force + fi + + local _repo_pkg="${product}-repo" + + # Deprecated pa + if is_pkg_installed ${product}-repo-devel; then + _exec "pkg set -A 1 ${product}-repo-devel" \ + "Scheduling package ${product}-repo-devel for removal" + _exec "pkg install${dont_update} ${_repo_pkg}" \ + "Installing ${_repo_pkg}" mute + _exec "pkg delete ${product}-repo-devel" \ + "Removing ${product}-repo-devel" mute ignore_result + validate_repo_conf + pkg_update force + fi + + [ -n "${NEW_MAJOR}" ] \ + && return + + case "$(compare_pkg_version ${_repo_pkg})" in + "<") + local _force="" + ;; + ">") + local _force=" -f" + ;; + "=") + return + ;; + *) + _echo "ERROR: Unable to compare version of ${_repo_pkg}" + _exit 1 + esac + + cp /usr/local/etc/pkg/repos/${product}.conf /tmp/${product}.conf.copy + _exec "pkg upgrade${dont_update}${_force} ${_repo_pkg}" \ + "Upgrading ${_repo_pkg}" mute + abi_setup + # If conf differs, for an update + if ! cmp -s /usr/local/etc/pkg/repos/${product}.conf \ + /tmp/${product}.conf.copy; then + pkg_update force + + # New repo may contain newer pkg + if [ -z "${NEW_MAJOR}" -a "$(compare_pkg_version pkg)" = "<" ] + then + _exec "pkg upgrade pkg" "Upgrading pkg" mute + pkg_update force + fi + fi + rm -f /tmp/${product}.conf.copy +} + +upgrade_available() { + # XXX locked packages message should be printed on stderr by pkg? + local _lines=$(pkg upgrade${dont_update} -nq "$@" 2>/dev/null \ + | sed -e '/^$/d; /is locked and may not be modified/d' \ + | wc -l) + + test ${_lines} -gt 0 + return $? +} + +pkg_upgrade() { + # figure out which kernel variant is running + export kernel_pkg=$(pkg query %n $(pkg info ${product}-kernel-\* | \ + grep -v -- -debug-)) + + # Detect if has u-boot package installed + unset uboot_bin + unset uboot_pkg + unset uboot_mntp + if pkg info ${product}-u-boot-ufw\* >/dev/null 2>&1; then + export uboot_pkg=$(pkg query %n \ + $(pkg info ${product}-u-boot-ufw\*)) + export uboot_mntp=/boot/msdos + export uboot_bin=u-boot.img + fi + if pkg info ${product}-u-boot-sg3100\* >/dev/null 2>&1; then + export uboot_pkg=$(pkg query %n \ + $(pkg info ${product}-u-boot-sg3100\*)) + export uboot_mntp=/boot/u-boot + export uboot_bin=u-boot.bin + fi + + if [ -n "${uboot_pkg}" -a \ + "$(compare_pkg_version ${uboot_pkg})" = "<" ]; then + if [ ! -f ${uboot_mntp}/${uboot_bin} ]; then + # Try to mount /boot/msdos + mount ${uboot_mntp} >/dev/null 2>&1 + fi + + if [ ! -f ${uboot_mntp}/${uboot_bin} ]; then + _echo "ERROR: u-boot partition (${uboot_mntp}) is not" \ + "properly mounted" + _exit 1 + fi + fi + + if [ -z "${kernel_pkg}" ]; then + _echo "ERROR: It was not possible to identify which" \ + "${product} kernel is installed" + _exit 1 + fi + + export next_stage=$(pkg annotate -q -S ${kernel_pkg} next_stage) + export is_pkg_locked=$(pkg annotate -q -S ${kernel_pkg} new_major) + + if [ -n "${next_stage}" -a -n "${booting}" -a -n "${boot_stage}" ]; then + if [ ${boot_stage} != ${next_stage} ]; then + _exit 0 + fi + fi + + # If it's booting and first stage didn't run, just exit + if [ -n "${booting}" -a -z "${next_stage}" ]; then + _exit 0 + fi + + need_reboot=1 + # First upgrade stage + if [ -z "${next_stage}" ]; then + if [ -f "${logfile}" ]; then + rm -f ${logfile} + fi + + pkg_update + + # Lock pkg to avoid having pkg binary for version N+1 installed + # on N + if [ -n "${NEW_MAJOR}" ]; then + pkg_lock pkg + fi + + pkg_upgrade_repo + + # If a new version of pfSense-upgrade is available, upgrade it + # and return a special code 99 used by wrapper to run newer + # version again using the same parameters + if [ "$(compare_pkg_version ${product}-upgrade)" = "<" ]; then + _exec "pkg upgrade${dont_update} ${product}-upgrade" \ + "Upgrading ${product}-upgrade" mute + [ -n "${NEW_MAJOR}" ] \ + && pkg_unlock pkg + _exit 99 + fi + + # Old versions used to lock kernel and uboot, make sure we + # get it reverted + if pkg lock -l 2>&1 | grep -q "kernel"; then + pkg_unlock ${kernel_pkg} + fi + if [ -n "${uboot_pkg}" ] && \ + pkg lock -l 2>&1 | grep -q "u-boot"; then + pkg_unlock ${uboot_pkg} + fi + + # Always make sure important packages are set as vital + set_vital_flag pkg ${kernel_pkg} ${product} ${product}-rc \ + ${product}-base ${uboot_pkg} + + if ! upgrade_available; then + [ -n "${NEW_MAJOR}" ] \ + && pkg_unlock pkg + _echo "Your packages are up to date" + _exit 0 + fi + + if [ -n "${dry_run}" ]; then + [ -n "${NEW_MAJOR}" ] \ + && pkg_unlock pkg + pkg upgrade${dont_update} -nq 2>&1 | tee -a ${logfile} + _exit 0 + fi + + local _meta_pkg=$(get_meta_pkg_name) + if [ "${platform}" = "nanobsd" ]; then + _echo "**** WARNING ****" + _echo "" + _echo "NanoBSD platform is no longer supported." + _echo "" + _echo "You can find instructions on how to convert it" + "to Full Installation at http://bit.ly/2wDinm8" + _exit 1 + fi + + # ZFS panics with reroot, do not use it in this case + # https://redmine.pfsense.org/issues/6045 + if ! kldstat -qm zfs; then + # If kernel is not going to be upgraded, reroot + if ! upgrade_available ${kernel_pkg}; then + reboot_params="-r" + fi + fi + + if [ -z "${yes}" ]; then + # Show user which packages are going to be upgraded + pkg upgrade${dont_update} -nq 2>&1 | tee -a ${logfile} + + _echo "" + _echo "**** WARNING ****" + _echo "Reboot will be required!!" + _echo -n "Proceed with upgrade? (y/N) " + read answer + if [ "${answer}" != "y" ]; then + _echo "Aborting..." + _exit 0 + fi + fi + + # Unlock pkg to make sure it's downloaded + if [ -n "${NEW_MAJOR}" ]; then + pkg_unlock pkg + fi + + # Download all upgrade packages first + fetch_upgrade_packages + + # Then lock it again + if [ -n "${NEW_MAJOR}" ]; then + pkg_lock pkg + fi + + if upgrade_available ${kernel_pkg}; then + # pfSense-SG-3100 is obsolete and must be removed + # before upgrade kernel / rc and preserve + # loader.rc.local just to be extra safe + if is_pkg_installed ${product}-SG-3100; then + rm -f /tmp/loader.rc.local >/dev/null 2>&1 + [ -f /boot/loader.rc.local ] \ + && cp /boot/loader.rc.local /tmp 2>/dev/null + _exec "pkg delete ${product}-SG-3100" \ + "Removing ${product}-SG-3100" mute \ + ignore_result + [ -f /tmp/loader.rc.local ] \ + && cp /tmp/loader.rc.local /boot 2>/dev/null + fi + _exec "pkg upgrade -U ${kernel_pkg}" \ + "Upgrading ${product} kernel" + fi + + if [ -n "${uboot_pkg}" ] && upgrade_available ${uboot_pkg}; then + _exec "pkg upgrade -U ${uboot_pkg}" \ + "Upgrading ${product} u-boot" + fi + + if [ -n "${NEW_MAJOR}" ]; then + pkg annotate -q -M ${kernel_pkg} new_major 1 + fi + + pkg annotate -q -M ${kernel_pkg} next_stage 2 + next_stage=2 + + do_reboot + _exit 0 + fi + + if [ "${next_stage}" = "2" ]; then + pkg_lock "${pkg_prefix}*" + unlock_additional_pkgs=1 + + # XXX: Workaround to upgrade strongswan + # If those symlinks are present, pkg exit because it expects + # them to be a directory + if upgrade_available strongswan; then + [ -L /usr/local/etc/ipsec.d ] \ + && rm -f /usr/local/etc/ipsec.d + [ -L /usr/local/etc/ipsec.conf ] \ + && rm -f /usr/local/etc/ipsec.conf + [ -L /usr/local/etc/strongswan.d ] \ + && rm -f /usr/local/etc/strongswan.d + [ -L /usr/local/etc/strongswan.conf ] \ + && rm -f /usr/local/etc/strongswan.conf + fi + + if upgrade_available; then + delete_annotation=1 + if [ -n "${is_pkg_locked}" ]; then + # Upgrade pkg + pkg_unlock pkg + pkg annotate -q -D ${kernel_pkg} new_major + _exec "pkg-static install -f pkg" \ + "Reinstalling pkg due to ABI change" + + # Upgrade base packages using pkg-static + _exec "pkg-static upgrade -r ${product}-core" \ + "Upgrading necessary core packages" + + # Make sure PHP setup is fine + /etc/rc.php_ini_setup >/dev/null 2>&1 + fi + + _exec "pkg upgrade${dont_update}" \ + "Upgrading necessary packages" + delete_annotation="" + + # Always make sure important packages are set as vital + set_vital_flag pkg ${kernel_pkg} ${product} \ + ${product}-rc ${product}-base ${uboot_pkg} + fi + + pkg annotate -q -M ${kernel_pkg} next_stage 3 + next_stage=3 + + pkg_unlock "${pkg_prefix}*" + unlock_additional_pkgs="" + + # 2nd reboot during new major version upgrade + if [ -n "${is_pkg_locked}" ]; then + # Reboot immediately + do_reboot now + _exit 0 + fi + + if [ -n "${booting}" ]; then + _exit 0 + fi + fi + + if [ "${next_stage}" = "3" ]; then + if upgrade_available; then + delete_annotation=1 + _exec "pkg upgrade${dont_update}" \ + "Upgrading necessary packages" + delete_annotation="" + fi + + pkg annotate -q -D ${kernel_pkg} next_stage + + # cleanup caches + _exec "pkg autoremove" "Removing unnecessary packages" mute \ + ignore_result + _exec "pkg clean" "Cleanup pkg cache" mute ignore_result + fi + + gitsync=$(read_xml_tag.sh boolean system/gitsync/synconupgrade) + if [ "${gitsync}" = "true" ]; then + repository_url=$(read_xml_tag.sh string \ + system/gitsync/repositoryurl) + branch=$(read_xml_tag.sh string system/gitsync/branch) + + minimal=$(read_xml_tag.sh boolean system/gitsync/minimal) + diff=$(read_xml_tag.sh boolean system/gitsync/diff) + show_files=$(read_xml_tag.sh boolean system/gitsync/show_files) + show_command=$(read_xml_tag.sh boolean \ + system/gitsync/show_command) + dryrun=$(read_xml_tag.sh boolean system/gitsync/dryrun) + + mute='mute' + options='' + if [ "${minimal}" = "true" ]; then + options=${options}' --minimal' + fi + if [ "${diff}" = "true" ]; then + options=${options}' --diff' + fi + if [ "${show_files}" = "true" ]; then + options=${options}' --show-files' + mute='off' + fi + if [ "${show_command}" = "true" ]; then + options=${options}' --show-command' + mute='off' + fi + if [ "${dryrun}" = "true" ]; then + options=${options}' --dry-run' + fi + + # Repository URL is not mandatory + if [ -n "${branch}" ]; then + _exec "pfSsh.php playback gitsync ${repositoryurl} \ + ${branch} ${options} --upgrading" \ + "Running gitsync" ${mute} ignore_result + fi + fi + + # Save a copy of latest finished upgrade process + cp -f ${logfile} ${upgrade_logfile} +} + +get_meta_pkg_name() { + # figure out main meta package name + if is_pkg_installed ${product}-vmware; then + echo "${product}-vmware" + elif is_pkg_installed ${product}; then + echo "${product}" + else + _echo "ERROR: It was not possible to identify which" \ + "${product} meta package is installed" + _exit 1 + fi +} + +check_upgrade() { + local _meta_pkg=$(get_meta_pkg_name) + local _core_pkgs=$(pkg query -e \ + "%n ~ ${product}-kernel-* || %n ~ ${product}-base*" %n) + + pkg_update "" mute + + pkg_upgrade_repo + + for _pkg in ${_meta_pkg} ${_core_pkgs}; do + [ "$(compare_pkg_version ${_pkg})" != "<" ] \ + && continue + + local _new_version=$(pkg rquery -U %v ${_pkg}) + _echo "${_new_version} version of ${product} is available" + _exit 2 + done + + _echo "Your system is up to date" + _exit 0 +} + +is_pkg_installed() { + local _pkg_name="${1}" + + pkg info -e ${_pkg_name} + return $? +} + +compare_pkg_version() { + local _pkg_name="${1}" + + if [ -z "${_pkg_name}" ]; then + echo '!' + return 1 + fi + + if ! is_pkg_installed ${_pkg_name}; then + echo '!' + return 1 + fi + + local _lver=$(pkg query %v ${_pkg_name}) + + if [ -z "${_lver}" ]; then + _echo "ERROR: It was not possible to determine ${_pkg_name}" \ + "local version" + _exit 1 + fi + + local _rver=$(pkg rquery -U %v ${_pkg_name}) + + if [ -z "${_rver}" ]; then + _echo "ERROR: It was not possible to determine ${_pkg_name}" \ + "remote version" + _exit 1 + fi + + local _version=$(pkg version -t ${_lver} ${_rver}) + + if [ $? -ne 0 ]; then + _echo "ERROR: Error comparing ${_pkg_name} local and remote" \ + "versions" + _exit 1 + fi + + echo ${_version} + return 0 +} + +pkg_install() { + local _pkg_name="${1}" + + local _force="" + if [ -n "${2}" ]; then + _force="-f" + fi + + if [ -z "${_pkg_name}" ]; then + _echo "ERROR: Blank package name" + _exit 1 + fi + + if is_pkg_installed ${_pkg_name}; then + local _cversion=$(compare_pkg_version ${_pkg_name}) + + if [ -z "${_force}" ]; then + if [ "${_cversion}" = "=" ]; then + _echo "Package ${_pkg_name} is up to date" + _exit 0 + elif [ "${_cversion}" = ">" ]; then + _echo "Installed ${_pkg_name} version is" \ + "newer than remote" + _exit 0 + fi + fi + local _cmd="upgrade ${_force}" + local _msg="Upgrading" + else + local _cmd="install" + local _msg="Installing" + fi + + _exec "pkg_with_pb ${_cmd}${dry_run:+ }${dry_run} ${_pkg_name}" \ + "${_msg} ${_pkg_name}" + _exec "pkg clean" "Cleaning up cache" mute ignore_result +} + +# Reinstall every pfSense-pkg-* package +pkg_reinstall_all() { + for _pkg in $(pkg query -e '%a == 0' %n); do + case ${_pkg} in "${pkg_prefix}"* ) + _echo "Reinstalling ${_pkg}" + pkg_install ${_pkg} 1 + ;; + esac + done +} + +pkg_delete() { + local _pkg_name="${1}" + + if [ -z "${_pkg_name}" ]; then + _echo "ERROR: Blank package name" + _exit 1 + fi + + if ! is_pkg_installed ${_pkg_name}; then + _echo "ERROR: Package ${_pkg_name} is not installed" + _exit 1 + fi + + _exec "pkg_with_pb delete${dry_run:+ }${dry_run} ${_pkg_name}" \ + "Removing ${_pkg_name}" + _exec "pkg autoremove" "Removing stale packages" mute ignore_result +} + +# Delete every pfSense-pkg-* package +pkg_delete_all() { + for _pkg in $(pkg query -e '%a == 0' %n); do + case ${_pkg} in "${pkg_prefix}"* ) + _echo "Removing ${_pkg}" + pkg_delete ${_pkg} + ;; + esac + done +} + +do_reboot() { + local _now="$1" + + local _msg="" + if [ "${_now}" = "now" ]; then + _msg="now." + else + _msg="in ${reboot_after} seconds." + fi + + if [ -z "${dont_reboot}" ]; then + _echo "Upgrade is complete. Rebooting ${_msg}" + echo "Upgrade is complete. Rebooting ${_msg}" | wall + /etc/rc.notify_message -e -g -m \ + "Upgrade is complete. Rebooting ${_msg}" >/dev/null 2>&1 + if [ "${_now}" = "now" ]; then + /etc/rc.reboot ${reboot_params} + else + (sleep ${reboot_after} \ + && /etc/rc.reboot ${reboot_params}) & + fi + else + _echo "Upgrade is complete." + echo "Upgrade is complete." | wall + /etc/rc.notify_message -e -g -m "Upgrade is complete." \ + >/dev/null 2>&1 + fi +} + +validate_repo_conf() { + # Make sure to use default repo conf when it doesn't exist + pkg_repo_conf="/usr/local/etc/pkg/repos/${product}.conf" + default="/usr/local/share/${product}/pkg/repos/${product}-repo.conf" + + pkg_repo_conf_path=$(read_xml_tag.sh string system/pkg_repo_conf_path) + + if [ -z "${pkg_repo_conf_path}" -o ! -f "${pkg_repo_conf_path}" ]; then + pkg_repo_conf_path=${default} + fi + + if [ -f "${pkg_repo_conf_path}" ]; then + if [ -e "${pkg_repo_conf}" -a ! -L "${pkg_repo_conf}" ]; then + rm -f ${pkg_repo_conf} + ln -sf ${pkg_repo_conf_path} ${pkg_repo_conf} + fi + + if [ "$(readlink ${pkg_repo_conf})" != \ + "${pkg_repo_conf_path}" ]; then + mkdir -p /usr/local/etc/pkg/repos + ln -sf ${pkg_repo_conf_path} ${pkg_repo_conf} + fi + fi +} + +export LANG=C + +pid_file="/var/run/$(basename $0).pid" +logfile="/cf/conf/upgrade_log.txt" +upgrade_logfile="/cf/conf/upgrade_log.latest.txt" +stdout='/dev/null' + +# Export necessary PATH +export PATH=/bin:/sbin:/usr/bin:/usr/sbin:/usr/local/bin:/usr/local/sbin + +# Setup proxy settings +HTTP_PROXY=$(read_xml_tag.sh string system/proxyurl) +if [ "${HTTP_PROXY}" != "" ]; then + HTTP_PROXY_PORT=$(read_xml_tag.sh string system/proxyport) + if [ "${HTTP_PROXY_PORT}" != "" ]; then + HTTP_PROXY="${HTTP_PROXY}:${HTTP_PROXY_PORT}" + fi + export HTTP_PROXY +fi + +# Only set proxy variables on FreeBSD 11 until the fix is on 10 +# https://bugs.freebsd.org/bugzilla/show_bug.cgi?id=194483 +if $(uname -r | grep -q '^11'); then + HTTP_PROXY_USER=$(read_xml_tag.sh string system/proxyuser) + HTTP_PROXY_PASS=$(read_xml_tag.sh string system/proxypass) + if [ "${HTTP_PROXY_USER}" != "" ] && + [ "${HTTP_PROXY_PASS}" != "" ]; then + HTTP_PROXY_AUTH="${HTTP_PROXY_USER}:${HTTP_PROXY_PASS}" + HTTP_PROXY_AUTH="basic:*:${HTTP_PROXY_AUTH}" + export HTTP_PROXY_AUTH + fi +fi + +# pkg should not ask for confirmations +export ASSUME_ALWAYS_YES=true +export FETCH_TIMEOUT=5 +export FETCH_RETRY=2 + +export product=$(php -n /usr/local/sbin/read_global_var product_name pfSense) +export pkg_prefix=$(php -n /usr/local/sbin/read_global_var pkg_prefix \ + pfSense-pkg-) +export platform=$(cat /etc/platform) + +USE_MFS_TMPVAR=$(read_xml_tag.sh boolean system/use_mfs_tmpvar) +if [ "${USE_MFS_TMPVAR}" = "true" ]; then + export PKG_DBDIR=/root/var/db/pkg + export PKG_CACHEDIR=/root/var/cache/pkg +fi + +product_version=$(cat /etc/version) +do_not_send_uniqueid=$(read_xml_tag.sh boolean system/do_not_send_uniqueid) +if [ "${do_not_send_uniqueid}" != "true" ]; then + uniqueid=$(gnid) + export HTTP_USER_AGENT="${product}/${product_version}:${uniqueid}" +else + export HTTP_USER_AGENT="${product}/${product_version}" +fi + +validate_repo_conf + +# Flags used in _exit +export delete_annotation="" +export unlock_additional_pkgs="" +export delete_pid="" + +# Save nc_pid to be able to kill it +export nc_pid="" + +# Reboot after 10 seconds +export reboot_after=10 + +# Used to set -r and reroot +export reboot_params="" + +unset dry_run +unset dont_reboot +unset dont_update +unset booting +unset boot_stage +unset force +unset yes +unset progress_file +unset progress_socket +unset action +unset action_pkg +unset force_ipv4 +unset force_ipv6 +while getopts 46b:cdfi:hp:l:nr:RuUy opt; do + case ${opt} in + 4) + if [ -n "${force_ipv6}" ]; then + usage + exit 1 + fi + force_ipv4=1 + ;; + 6) + if [ -n "${force_ipv4}" ]; then + usage + exit 1 + fi + force_ipv6=1 + ;; + b) + booting=1 + boot_stage="${OPTARG}" + ;; + c) + action="check" + ;; + d) + stdout='' + ;; + f) + force=1 + ;; + i) + if [ -n "${action}" ]; then + usage + exit 1 + fi + action="install" + action_pkg="${OPTARG}" + ;; + h) + usage + exit 0 + ;; + l) + logfile="${OPTARG}" + if [ -z "${logfile}" ]; then + usage + exit 1 + fi + ;; + n) + dry_run="-n" + ;; + p) + progress_socket="${OPTARG}" + if [ -z "${progress_socket}" ]; then + usage + exit 1 + fi + ;; + r) + if [ -n "${action}" ]; then + usage + exit 1 + fi + action="delete" + action_pkg="${OPTARG}" + ;; + R) + dont_reboot=1 + ;; + u) + if [ -n "${action}" ]; then + usage + exit 1 + fi + action="update" + ;; + U) + dont_update=" -U" + ;; + y) + yes=1 + ;; + *) + usage + exit 1 + ;; + esac +done + +if [ -n "${force_ipv4}" ]; then + export IP_VERSION="4" +elif [ -n "${force_ipv6}" ]; then + export IP_VERSION="6" +fi + +# Set default action when no parameter is set +: ${action:="upgrade"} + +if pgrep -qF ${pid_file} >/dev/null 2>&1; then + echo "Another instance is already running... Aborting!" + exit 1 +fi + +echo $$ > ${pid_file} + +# Since this point it's safe to remove pid_file +delete_pid=1 + +trap _exit 1 2 15 EXIT + +block_external_services=$(read_xml_tag.sh boolean \ + system/block_external_services) + +if [ "${block_external_services}" = "true" ]; then + echo "Aborted due to block_external_services flag" + exit 0 +fi + +if [ -z "${booting}" -o "${boot_stage}" != "2" ]; then + php /etc/rc.conf_mount_rw +fi + +if [ -n "${booting}" ]; then + export REPO_AUTOUPDATE=false +fi + +if [ "${action}" != "upgrade" -a -f "${logfile}" ]; then + rm -f ${logfile} +fi + +progress_file=${logfile%.*}.json + +if [ -e "${progress_file}" ]; then + rm -f ${progress_file} +fi + +abi_setup + +if [ -n "${NEW_MAJOR}" -a "${action}" = "install" ]; then + _echo "WARNING: Current pkg repository has a new OS major version." + _echo " ${product} should be upgraded before doing any other" + _echo " operation" + _exit 1 +fi + +case "${action}" in + check) + check_upgrade + ;; + upgrade) + pkg_upgrade + ;; + update) + pkg_update force + ;; + install) + if [ ${action_pkg} = "ALL_PACKAGES" ] && [ -n ${force} ]; then + pkg_reinstall_all + else + pkg_install ${action_pkg} ${force} + fi + ;; + delete) + if [ ${action_pkg} = "ALL_PACKAGES" ] && [ -n ${force} ]; then + pkg_delete_all + else + pkg_delete ${action_pkg} + fi + ;; + *) + _echo "ERROR: Invalid action!" + _exit 1 +esac + +_exit 0 |