#!/bin/bash
#
# Copyright (C) 2013-2018 Draios Inc dba Sysdig.
#
# This file is part of sysdig .
#
# 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.
#
#
# Simple script that desperately tries to load sysdig-probe looking
# for it in a bunch of ways. Convenient when running sysdig inside
# a container or in other weird environments.
#
#
# --- WORKFLOW ---
#
# By default, the script uses the following approaches to build or fetch
# or find the sysdig-probe, in the following order:
# 1) In the kernel module case, use modprobe, which looks for the kernel
#    module already installed in /lib/modules
# 2) Look for the appropriate sysdig-probe (kernel module or eBPF) for the
#    currently running kernel, in the .sysdig directory
# 3) Fetch the appropriate sysdig-probe (kernel module or eBPF) for the
#    currently running kernel, from download.sysdig.com
#
# Workflow variations:
# A) If the environment variable SYSDIG_FORCE_DOWNLOAD_PROBE is defined,
#    the script ONLY tries to download the appropriate sysdig-probe (kernel module or eBPF).
#    The script won't try to build the probe.
# B) If the environment variable SYSDIG_FORCE_BUILD_PROBE is defined,
#    the script ONLY tries to build the appropriate sysdig-probe (kernel module or eBPF).
#    The script won't try to download the probe.
#
# Note:
# SYSDIG_FORCE_DOWNLOAD_PROBE and SYSDIG_FORCE_BUILD_PROBE cannot be simultaneously defined. If so, the
# probe loader raises an error.
#
# --- ENVIRONMENT VARIABLES ---
#
# By default, the following naming conventions are used.
# A) Probe filename
# kernel module: sysdigcloud-probe-<SYSDIG_VERSION>-<ARCH>-<KERNEL_RELEASE>-<KERNEL_CONFIG_HASH>.ko
# eBPF probe: sysdigcloud-probe-bpf-<SYSDIG_VERSION>-<ARCH>-<KERNEL_RELEASE>-<KERNEL_CONFIG_HASH>.o
# Where:
#   <SYSDIG_VERSION> = sysdig release version (e.g. 12.0.3)
#   <ARCH> = CPU architecture (e.g. x86_64)
#   <KERNEL_RELEASE> = uname -r output (e.g. 4.18.0-147.56.1.el8_1.x86_64)
#   <KERNEL_CONFIG_HASH> = result of hash, calculated over kernel config file, 32 hex digits
# So, an example kernel module filename would be
#   sysdigcloud-probe-12.0.3-x86_64-4.18.0-147.56.1.el8_1.x86_64-2f4c51e1d6af404393d778653f50135.ko
#
# B) Download URL
# <DOWNLOAD_URL_HOST>/<DOWNLOAD_REPOSITORY>/sysdig-probe-binaries/<PROBE_FILENAME>
# Where:
#   DOWNLOAD_URL_HOST = "download.sysdig.com" by default
#   DOWNLOAD_REPOSITORY = "stable" by default
#
# The following environment variables may be used to override defaults for different
# aspects of the object names:
#
# 1) SYSDIG_PROBE_OVERRIDE_FULL_URL
# - Overrides everything -- URL AND Probe filename
# - This is particularly useful when the user needs to download a probe built onsite,
#   from a locally-hosted location, and doesn't want to worry about mimicing any
#   naming conventions
# - Also particularly useful when the host doesn't have sufficient files (kernel headers,
#   kernel config file) available, because it avoids the necessity of finding and
#   calculating the checksum of the kernel config file on the local system.
#
# 2) SYSDIG_PROBE_URL
# - Finer-grain override
# - Allows the user to override only the DOWNLOAD_URL_HOST value from item B above,
#   to specify a different host + optional port number (e.g. "probe-host.mydomain.com:80"
#   vs. the default "download.sysdig.com"),
# - While retaining/mimicing the standard Sysdig directory structure and filename format
#
# 3) SYSDIG_REPOSITORY
# - Finer-grain override
# - Allows the user (or build script) to override only the DOWNLOAD_REPOSITORY value
#   from item B above, to specify a top-level directory (e.g. "dev" instead of "stable")
# - While retaining/mimicing the standard Sysdig directory structure and filename format


#
# Returns 1 if $cos_ver > $base_ver, 0 otherwise
#
cos_version_greater()
{
	if [[ $cos_ver == $base_ver ]]; then
		return 0
	fi

	#
	# COS build numbers are in the format x.y.z
	#
	a=`echo $cos_ver | cut -d. -f1`
	b=`echo $cos_ver | cut -d. -f2`
	c=`echo $cos_ver | cut -d. -f3`

	d=`echo $base_ver | cut -d. -f1`
	e=`echo $base_ver | cut -d. -f2`
	f=`echo $base_ver | cut -d. -f3`

	# Test the first component
	if [[ $a -gt $d ]]; then
		return 1
	elif [[ $d -gt $a ]]; then
		return 0
	fi

	# Test the second component
	if [[ $b -gt $e ]]; then
		return 1
	elif [[ $e -gt $b ]]; then
		return 0
	fi

	# Test the third component
	if [[ $c -gt $f ]]; then
		return 1
	elif [[ $f -gt $c ]]; then
		return 0
	fi

	# If we get here, probably malformed version string?

	return 0
}


#
# Looks for the kernel configuration and stores its hash in KERNEL_CONFIG_PATH.
# Returns 0 on success, 1 otherwise (cannot find kernel configuration).
#
get_kernel_config_hash() {
	echo "* Looking for kernel configuration"

	if [ -f /proc/config.gz ]; then
		echo "  Found kernel config at /proc/config.gz"
		KERNEL_CONFIG_PATH=/proc/config.gz
	elif [ -f "/boot/config-${KERNEL_RELEASE}" ]; then
		echo "  Found kernel config at /boot/config-${KERNEL_RELEASE}"
		KERNEL_CONFIG_PATH=/boot/config-${KERNEL_RELEASE}
	elif [ ! -z "${SYSDIG_HOST_ROOT}" ] && [ -f "${SYSDIG_HOST_ROOT}/boot/config-${KERNEL_RELEASE}" ]; then
		echo "  Found kernel config at ${SYSDIG_HOST_ROOT}/boot/config-${KERNEL_RELEASE}"
		KERNEL_CONFIG_PATH="${SYSDIG_HOST_ROOT}/boot/config-${KERNEL_RELEASE}"
	elif [ -f "/usr/lib/ostree-boot/config-${KERNEL_RELEASE}" ]; then
		echo "  Found kernel config at /usr/lib/ostree-boot/config-${KERNEL_RELEASE}"
		KERNEL_CONFIG_PATH="/usr/lib/ostree-boot/config-${KERNEL_RELEASE}"
	elif [ ! -z "${SYSDIG_HOST_ROOT}" ] && [ -f "${SYSDIG_HOST_ROOT}/usr/lib/ostree-boot/config-${KERNEL_RELEASE}" ]; then
		echo "  Found kernel config at ${SYSDIG_HOST_ROOT}/usr/lib/ostree-boot/config-${KERNEL_RELEASE}"
		KERNEL_CONFIG_PATH="${SYSDIG_HOST_ROOT}/usr/lib/ostree-boot/config-${KERNEL_RELEASE}"
	elif [ -f /lib/modules/${KERNEL_RELEASE}/config ]; then
		# this code works both for native host and agent container assuming that
		# Dockerfile sets up the desired symlink /lib/modules -> $SYSDIG_HOST_ROOT/lib/modules
		echo "  Found kernel config at /lib/modules/${KERNEL_RELEASE}/config"
		KERNEL_CONFIG_PATH="/lib/modules/${KERNEL_RELEASE}/config"
	fi

	if [ -z "${KERNEL_CONFIG_PATH}" ]; then
		echo "Cannot find kernel configuration"
		return 1
	fi

	if [[ "${KERNEL_CONFIG_PATH}" == *.gz ]]; then
		HASH=$(zcat "${KERNEL_CONFIG_PATH}" | md5sum - | cut -d' ' -f1)
	else
		HASH=$(md5sum "${KERNEL_CONFIG_PATH}" | cut -d' ' -f1)
	fi

	return 0
}


#
# Tries to remove the kernel probe.
# Returns 0 on success, 1 otherwise (kernel probe still loaded).
#
remove_kernel_probe() {
	echo "* Unloading ${PROBE_NAME}, if present"

	# Tries to remove the module within a predefined time ($MAX_RMMOD_WAIT)
	rmmod "${PROBE_NAME}" 2>/dev/null
	WAIT_TIME=0
	KMOD_NAME=$(echo "${PROBE_NAME}" | tr "-" "_")
	while lsmod | grep "${KMOD_NAME}" > /dev/null 2>&1 && [ $WAIT_TIME -lt $MAX_RMMOD_WAIT ]; do
		if rmmod "${PROBE_NAME}" 2>/dev/null; then
			echo "* Unloading ${PROBE_NAME} succeeded after ${WAIT_TIME}s"
			break
		fi
		((++WAIT_TIME))
		if (( $WAIT_TIME % 5 == 0 )); then
			echo "* ${PROBE_NAME} still loaded, waited ${WAIT_TIME}s (max wait ${MAX_RMMOD_WAIT}s)"
		fi
		sleep 1
	done

	# Still loaded
	if lsmod | grep "${KMOD_NAME}" > /dev/null 2>&1; then
		echo "* ${PROBE_NAME} seems to still be loaded, hoping the best"
		return 1
	fi

	return 0
}


#
# Evaluates variables override.
# Returns 1 on success, 0 otherwise.
#
get_variable_override_kernel_probe() {
	echo "* Evaluating override of environment variables"

	if [ ! -z ${SYSDIG_PROBE_OVERRIDE_FULL_URL} ]; then
		SYSDIG_PROBE_FILENAME=$(basename "${SYSDIG_PROBE_OVERRIDE_FULL_URL}")
		URL=$(echo "${SYSDIG_PROBE_OVERRIDE_FULL_URL}" | sed s/+/%2B/g)
	else
		# Tries to get the hash of the kernel configuration
		get_kernel_config_hash
		if [ $? -eq 1 ]; then
			return 1
		fi

		SYSDIG_PROBE_FILENAME="${PROBE_NAME}-${SYSDIG_VERSION}-${ARCH}-${KERNEL_RELEASE}-${HASH}.ko"
		URL=$(echo "${SYSDIG_PROBE_URL}/${SYSDIG_REPOSITORY}/sysdig-probe-binaries/${SYSDIG_PROBE_FILENAME}" | sed s/+/%2B/g)
	fi

	return 0
}


#
# Loads a precompiled kernel probe for the current kernel via insmod.
# Returns 0 on success, 1 otherwise.
#
load_precompiled_kernel_probe() {
	echo "* Loading module"
	insmod_out1=$(insmod "${HOME}/.sysdig/${SYSDIG_PROBE_FILENAME}" 2>&1)
	exit_status1=$?
	if [ $exit_status1 -ne 0 ]; then
		# Fedora 35+ distros on some cloud variants like AWS will
		# carry some default SELinux policy preventing it from
		# loading a .ko from a file descriptor through finit_module()
		# (which is what insmod does).
		# Compressing it with .xz forces insmod to decompress it into memory first,
		# and load it through init_module() instead, circumventing the issue.
		echo "* Loading module (xz)"
		xz -zkf "${HOME}/.sysdig/${SYSDIG_PROBE_FILENAME}"
		insmod_out2=$(insmod "${HOME}/.sysdig/${SYSDIG_PROBE_FILENAME}.xz" 2>&1)
		exit_status2=$?
		if [ $exit_status2 -ne 0 ]; then
			echo "Cannot insmod, exit status $exit_status1, error: $insmod_out1"
			echo "Cannot insmod even after xz, exit status $exit_status1, error: $insmod_out2"
			return 1
		fi
	fi
	return 0
}


#
# Downloads a precompiled kernel probe for the current kernel.
# Returns 0 on success, 1 otherwise (download failed).
#
download_kernel_probe() {
	echo "* Trying to download precompiled module from ${URL}"

	curl_out=$(curl --create-dirs "${SYSDIG_PROBE_CURL_OPTIONS}" -o "${HOME}/.sysdig/${SYSDIG_PROBE_FILENAME}" "${URL}" 2>&1)
	if [ "$?" = "0" ]; then
		echo "  Download succeeded"
		return 0
	fi

	echo "Download of ${PROBE_NAME} for version ${SYSDIG_VERSION} failed."

	# "curl: (22) The requested URL returned error: 404 Not Found" - The probe doesn't exist in the repo.
	if [[ "$curl_out" =~ "404 Not Found" ]]; then
		echo  "The probe for this version does not exist in the repo."
		# Enriches error message
		if [ ! -z "${KERNEL_ERR_MESSAGE}" ]; then
			echo "${KERNEL_ERR_MESSAGE}"
		else
			echo "Consider compiling your own ${PROBE_NAME} and loading it or getting in touch with the Sysdig community."
		fi
	else
		echo "$curl_out"
	fi

	return 1
}


#
# Builds and installs the probe kernel module via dkms.
# Returns 0 on success, 1 otherwise.
#
build_kernel_probe() {
	echo "* Running dkms install for ${PACKAGE_NAME}"

	if dkms install -m "${PACKAGE_NAME}" -v "${SYSDIG_VERSION}" -k "${KERNEL_RELEASE}"; then
		echo "  dkms install done"

		echo "* Trying to load the dkms ${PROBE_NAME} via insmod"
		if insmod "/var/lib/dkms/${PACKAGE_NAME}/${SYSDIG_VERSION}/${KERNEL_RELEASE}/${ARCH}/module/${PROBE_NAME}.ko" > /dev/null 2>&1; then
			echo "  ${PROBE_NAME} found and loaded in dkms"
			return 0
		elif insmod "/var/lib/dkms/${PACKAGE_NAME}/${SYSDIG_VERSION}/${KERNEL_RELEASE}/${ARCH}/module/${PROBE_NAME}.ko.xz" > /dev/null 2>&1; then
			echo "  ${PROBE_NAME} found and loaded in dkms (xz)"
			return 0
		else
			echo "  Unable to insmod"
		fi
	else
		DKMS_LOG="/var/lib/dkms/${PACKAGE_NAME}/${SYSDIG_VERSION}/build/make.log"
		if [ -f "${DKMS_LOG}" ]; then
			echo "  Running dkms build failed, dumping ${DKMS_LOG}"
			cat "${DKMS_LOG}"
		else
			echo "  Running dkms build failed, couldn't find ${DKMS_LOG}"
		fi
	fi

	return 1
}


#
# Tries to load the appropriate kernel probe.
# Returns 0 on success, 1 otherwise.
#
load_kernel_probe() {
	echo "* Loading kernel probe"

	# Required utils
	if ! hash lsmod > /dev/null 2>&1; then
		echo "This program requires lsmod"
		return 1
	fi

	if ! hash modprobe > /dev/null 2>&1; then
		echo "This program requires modprobe"
		return 1
	fi

	if ! hash rmmod > /dev/null 2>&1; then
		echo "This program requires rmmod"
		return 1
	fi

	# Removes leftover kernel probe
	remove_kernel_probe
	if [ $? -eq 1 ]; then
		return 0
	fi

	local SYSDIG_PROBE_FILENAME
	local URL

	# Evaluates variables override, returns if cannot (cannot find kernel config)
	get_variable_override_kernel_probe
	if [ $? -eq 1 ]; then
		return 1
	fi

	# Forces probe download, skips build
	if [ -v SYSDIG_FORCE_DOWNLOAD_PROBE ]; then
		echo "* Skipping build, FORCE_DOWNLOAD_PROBE is enabled"
	else
		# Builds the probe via dkms; skips UEK hosts, the build will always fail
		if [[ $(uname -r) == *uek* ]]; then
			echo "* Skipping dkms install for UEK host"
		else
			build_kernel_probe
			if [ $? -eq 0 ]; then
				return 0
			fi
		fi

		echo "* Trying to load a system ${PROBE_NAME}, if present"

		if modprobe "${PROBE_NAME}" > /dev/null 2>&1; then
			echo "${PROBE_NAME} found and loaded with modprobe"
			return 0
		fi

		echo "* Trying to find precompiled ${PROBE_NAME} for ${KERNEL_RELEASE}"

		# Looks for a precompiled kernel probe locally
		echo "* Trying to find precompiled ${PROBE_NAME} for ${KERNEL_RELEASE}"
		if [ -f "${HOME}/.sysdig/${SYSDIG_PROBE_FILENAME}" ]; then
			echo "  Found precompiled module at ~/.sysdig/${SYSDIG_PROBE_FILENAME}"
			load_precompiled_kernel_probe
			return $?
		fi
	fi

	# Skip download, the probe build has failed
	if [ -v SYSDIG_FORCE_BUILD_PROBE ]; then
		echo "* Skipping download, FORCE_BUILD_PROBE is enabled"
		return 1;
	fi;

	download_kernel_probe
	if [ $? -eq 1 ]; then
		return 1
	fi
	load_precompiled_kernel_probe
	return $?
}


#
# Makes a symlink to the BPF probe.
# Return 0 on success, 1 otherwise.
#
function make_symlink_bpf_probe() {
	echo "* Making symlink to BPF probe"

	if [ ! -f "${HOME}/.sysdig/${BPF_PROBE_FILENAME}" ]; then
		echo "  BPF probe not found"
		return 1
	fi

	if [ ! -f /proc/sys/net/core/bpf_jit_enable ]; then
		echo "**********************************************************"
		echo "** BPF doesn't have JIT enabled, performance might be   **"
		echo "** degraded. Please ensure to run on a kernel with      **"
		echo "** CONFIG_BPF_JIT enabled and/or use --net=host if      **"
		echo "** running inside a container.                          **"
		echo "**********************************************************"
	fi

	echo "  BPF probe located, it's now possible to start Sysdig"

	symlink_out=$(ln -sf "${HOME}/.sysdig/${BPF_PROBE_FILENAME}" "${HOME}/.sysdig/${BPF_PROBE_NAME}.o")
	if [ $? -ne 0 ]; then
		echo "  Cannot ln, error $symlink_out"
		return 1
	fi

	return 0
}


#
# Downloads the BPF probe.
# Returns 0 on success, 1 otherwise.
#
download_bpf_probe() {
	echo "* Trying to download precompiled BPF probe from ${URL}"

	curl --create-dirs "${SYSDIG_PROBE_CURL_OPTIONS}" -o "${HOME}/.sysdig/${BPF_PROBE_FILENAME}" "${URL}"

	if [ ! -f "${HOME}/.sysdig/${BPF_PROBE_FILENAME}" ]; then
		echo "  Download failed"
		return 1
	fi

	echo "  Download succeeded"
	return 0
}


#
# Evaluates variables override.
# Returns 1 on success, 0 otherwise.
#
get_variable_override_bpf_probe() {
	echo "* Evaluating override of environment variables"

	if [ ! -z ${SYSDIG_PROBE_OVERRIDE_FULL_URL} ]; then
		BPF_PROBE_FILENAME=$(basename "${SYSDIG_PROBE_OVERRIDE_FULL_URL}")
		URL=$(echo "${SYSDIG_PROBE_OVERRIDE_FULL_URL}" | sed s/+/%2B/g)
	else
		# Tries to get the hash of the kernel configuration
		get_kernel_config_hash
		if [ $? -eq 1 ]; then
			return 1
		fi

		BPF_PROBE_FILENAME="${BPF_PROBE_NAME}-${SYSDIG_VERSION}-${ARCH}-${KERNEL_RELEASE}-${HASH}.o"
		URL=$(echo "${SYSDIG_PROBE_URL}/${SYSDIG_REPOSITORY}/sysdig-probe-binaries/${BPF_PROBE_FILENAME}" | sed s/+/%2B/g)
	fi

	return 0
}

#
# Builds the BPF probe.
# Returns 0, always.
#
build_bpf_probe() {
	local BPF_KERNEL_SOURCES_URL=""
	local STRIP_COMPONENTS=1

	customize_kernel_build() {
		if [ -n "${KERNEL_EXTRA_VERSION}" ]; then
			sed -i "s/LOCALVERSION=\"\"/LOCALVERSION=\"${KERNEL_EXTRA_VERSION}\"/" .config
		fi
		make olddefconfig > /dev/null
		make modules_prepare > /dev/null
	}

	if [ -n "${COS}" ]; then
		echo "  COS detected (build ${BUILD_ID}), using cos kernel headers..."

		BPF_KERNEL_SOURCES_URL="https://storage.googleapis.com/cos-tools/${BUILD_ID}/kernel-headers.tgz"
		KERNEL_EXTRA_VERSION="+"
		STRIP_COMPONENTS=0

		customize_kernel_build() {
			pushd usr/src/* > /dev/null

			# Note: this overrides the KERNELDIR set while untarring the tarball
			export KERNELDIR=`pwd`

			sed -i '/^#define randomized_struct_fields_start	struct {$/d' include/linux/compiler-clang.h
			sed -i '/^#define randomized_struct_fields_end	};$/d' include/linux/compiler-clang.h

			popd > /dev/null

			# Might need to configure our own sources depending on COS version
			cos_ver=${BUILD_ID}
			base_ver=11553.0.0

			cos_version_greater
			greater_ret=$?

			if [[ greater_ret -eq 1 ]]; then
				export KBUILD_EXTRA_CPPFLAGS=-DCOS_73_WORKAROUND
			fi
		}
	fi

	if [ -n "${MINIKUBE}" ]; then
		echo "  Minikube detected (${MINIKUBE_VERSION}), using linux kernel sources for minikube kernel"
		local kernel_version=$(uname -r)
		local -r kernel_version_major=$(echo ${kernel_version} | cut -d. -f1)
		local -r kernel_version_minor=$(echo ${kernel_version} | cut -d. -f2)
		local -r kernel_version_patch=$(echo ${kernel_version} | cut -d. -f3)

		if [ "${kernel_version_patch}" == "0" ]; then
			kernel_version="${kernel_version_major}.${kernel_version_minor}"
		fi

		BPF_KERNEL_SOURCES_URL="http://mirrors.edge.kernel.org/pub/linux/kernel/v${kernel_version_major}.x/linux-${kernel_version}.tar.gz"
	fi

	if [ -n "${SYSDIG_BPF_USE_LOCAL_KERNEL_SOURCES}" ]; then
		local -r kernel_version_major=$(uname -r | cut -d. -f1)
		local -r kernel_version=$(uname -r | cut -d- -f1)
		KERNEL_EXTRA_VERSION="-$(uname -r | cut -d- -f2)"

		echo "  Using downloaded kernel sources for kernel version ${kernel_version}..."

		BPF_KERNEL_SOURCES_URL="http://mirrors.edge.kernel.org/pub/linux/kernel/v${kernel_version_major}.x/linux-${kernel_version}.tar.gz"
	fi

	if [ -n "${BPF_KERNEL_SOURCES_URL}" ]; then
		echo "  Downloading kernel sources from ${BPF_KERNEL_SOURCES_URL}"

		mkdir -p /tmp/kernel
		cd /tmp/kernel
		cd `mktemp -d -p /tmp/kernel`
		if ! curl -o kernel-sources.tgz --create-dirs "${SYSDIG_PROBE_CURL_OPTIONS}" "${BPF_KERNEL_SOURCES_URL}"; then
			exit 1;
		fi

		echo "  Extracting kernel sources"

		mkdir kernel-sources && tar xf kernel-sources.tgz -C kernel-sources --strip-components "${STRIP_COMPONENTS}"

		cd kernel-sources
		export KERNELDIR=`pwd`

		if [[ "${KERNEL_CONFIG_PATH}" == *.gz ]]; then
			zcat "${KERNEL_CONFIG_PATH}" > .config
		else
			cat "${KERNEL_CONFIG_PATH}" > .config
		fi

		echo "  Configuring kernel"
		customize_kernel_build
	fi

	echo "  Trying to compile BPF probe ${BPF_PROBE_NAME} (${BPF_PROBE_FILENAME})"

	make -C "/usr/src/${PACKAGE_NAME}-${SYSDIG_VERSION}/bpf" > /dev/null

	mkdir -p ~/.sysdig
	mv "/usr/src/${PACKAGE_NAME}-${SYSDIG_VERSION}/bpf/probe.o" "${HOME}/.sysdig/${BPF_PROBE_FILENAME}"

	if [ -n "${BPF_KERNEL_SOURCES_URL}" ]; then
		rm -r /tmp/kernel
	fi

	return 0
}


#
# Tries to load the appropriate BPF probe.
# Returns 0 on success, a non zero value otherwise.
#
load_bpf_probe() {
	echo "* Loading BPF probe"

	# Makes checks and set variables
	if [ ! -d /sys/kernel/debug/tracing ]; then
		echo "* Mounting debugfs"
		mount -t debugfs nodev /sys/kernel/debug
	fi

	if [ ! -z "${SYSDIG_HOST_ROOT}" ] && [ -f "${SYSDIG_HOST_ROOT}/etc/os-release" ]; then
		. "${SYSDIG_HOST_ROOT}/etc/os-release"

		if [ "${ID}" == "cos" ]; then
			COS=1
		fi
	fi

	if [ ! -z "${SYSDIG_HOST_ROOT}" ] && [ -f "${SYSDIG_HOST_ROOT}/etc/VERSION" ]; then
		MINIKUBE=1
		MINIKUBE_VERSION="$(cat ${SYSDIG_HOST_ROOT}/etc/VERSION)"
	fi

	local BPF_PROBE_FILENAME
	local URL

	# Evaluates variables override, returns if cannot (cannot find kernel config)
	get_variable_override_bpf_probe
	if [ $? -eq 1 ]; then
		return 1
	fi

	# Forces probe download, skips build
	if [ -v SYSDIG_FORCE_DOWNLOAD_PROBE ]; then
		echo "* Skipping build, FORCE_DOWNLOAD_PROBE is enabled"
	else
		# Builds the bpf probe
		echo "* Building BPF probe"
		if [ ! -f "${HOME}/.sysdig/${BPF_PROBE_FILENAME}" ]; then
			build_bpf_probe
		else
			echo "  Will not build, the BPF probe ${BPF_PROBE_FILENAME} already exists at ${HOME}/.sysdig/"
		fi
	fi

	# Skip download
	if [ -v SYSDIG_FORCE_BUILD_PROBE ]; then
		echo "* Skipping download, FORCE_BUILD_PROBE is enabled"
		make_symlink_bpf_probe
		return $?;
	fi;

	# Prevents installing a leftover probe
	if [ -v SYSDIG_FORCE_DOWNLOAD_PROBE ] && [ -f "${HOME}/.sysdig/${BPF_PROBE_FILENAME}" ]; then
		rm ${HOME}/.sysdig/${BPF_PROBE_FILENAME}
		if [ ! -f "${HOME}/.sysdig/${BPF_PROBE_FILENAME}" ]; then
			echo "* Removed existing bpf probe ${HOME}/.sysdig/${BPF_PROBE_FILENAME}"
		else
			echo "* Cannot remove existing bpf probe ${HOME}/.sysdig/${BPF_PROBE_FILENAME}"
		fi
	fi

	# Downloads the bpf probe
	if [ ! -f "${HOME}/.sysdig/${BPF_PROBE_FILENAME}" ]; then
		download_bpf_probe
		if [ $? -eq 1 ]; then
			return 1;
		fi
	else
		echo "  Will not download, the BPF probe ${BPF_PROBE_FILENAME} already exists at ${HOME}/.sysdig/"
	fi

	make_symlink_bpf_probe
	return $?
}


###################
### Entry point ###
###################

# Inits variables and makes required checks
ARCH=$(uname -m)
KERNEL_RELEASE=$(uname -r)
SCRIPT_NAME=$(basename "${0}")
SYSDIG_PROBE_URL=${SYSDIG_PROBE_URL:-https://download.sysdig.com}

if [ -n "$SYSDIG_PROBE_INSECURE_DOWNLOAD" ]
then
	SYSDIG_PROBE_CURL_OPTIONS=-fsSk
else
	SYSDIG_PROBE_CURL_OPTIONS=-fsS
fi

if [ -n "$SYSDIG_PROBE_BASIC_AUTH" ]
then
	SYSDIG_PROBE_CURL_OPTIONS="-u ${SYSDIG_PROBE_BASIC_AUTH_USER} ${SYSDIG_PROBE_CURL_OPTIONS}"
fi

MAX_RMMOD_WAIT=60
KERNEL_ERR_MESSAGE=""
if [[ $# -ge 1 ]]; then
	KERNEL_ERR_MESSAGE="$1"
fi

if [ -z "${SYSDIG_REPOSITORY}" ]; then
	SYSDIG_REPOSITORY="stable"
fi

if [ "${SCRIPT_NAME}" = "sysdig-probe-loader" ]; then
	if [ -z "$SYSDIG_VERSION" ]; then
		SYSDIG_VERSION=$(sysdig --version | cut -d' ' -f3)
	fi
	PROBE_NAME="sysdig-probe"
	BPF_PROBE_NAME="sysdig-probe-bpf"
	PACKAGE_NAME="sysdig"
elif [ "${SCRIPT_NAME}" = "sysdigcloud-probe-loader" ]; then
	EXEPATH=$(dirname "$(readlink -f "${0}")")
	if [ -z "$SYSDIG_VERSION" ]; then
		SYSDIG_VERSION=$("${EXEPATH}"/dragent --version)
	fi
	PROBE_NAME="sysdigcloud-probe"
	BPF_PROBE_NAME="sysdigcloud-probe-bpf"
	PACKAGE_NAME="draios-agent"
else
	echo "This script must be called as sysdig-probe-loader or sysdigcloud-probe-loader"
	exit 1
fi

if [ "$(id -u)" != 0 ]; then
	echo "Installer must be run as root (or with sudo)."
	exit 1
fi

if ! hash curl > /dev/null 2>&1; then
	echo "This program requires curl"
	exit 1
fi

if [ -v SYSDIG_FORCE_BUILD_PROBE ] && [ -v SYSDIG_FORCE_DOWNLOAD_PROBE ] ; then
	echo "Cannot define SYSDIG_FORCE_BUILD_PROBE and SYSDIG_FORCE_DOWNLOAD_PROBE simultaneously."
	echo "Cannot load the probe"
	exit 1
fi

# Loads the probe
if [ -v SYSDIG_BPF_PROBE ] || [ "${1}" = "bpf" ]; then
	load_bpf_probe
else
	load_kernel_probe
fi

# Echoes the result
if [ $? -eq 1 ]; then
	echo "Cannot load the probe"
	exit 1
fi
echo "Probe loaded"
exit 0