#!/bin/sh
# -*- mode: sh; sh-shell: sh -*-
# quick look at current connections and related information
# Copyright (C) 1998, 1999  Henry Spencer.
# Copyright (C) 2012-2019 Paul Wouters <pwouters@redhat.com>
# Copyright (C) 2015 Tuomo Soini <tis@foobar.fi>
# Copyright (C) 2018-2019 Andrew Cagney <cagney@gnu.org>
#
# This program is free software; you can redistribute it and/or modify it
# under the terms of the GNU General Public License as published by the
# Free Software Foundation; either version 2 of the License, or (at your
# option) any later version.  See <https://www.gnu.org/licenses/gpl2.txt>.
#
# This program is distributed in the hope that it will be useful, but
# WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY
# or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU General Public License
# for more details.
#

LC_ALL=C
export LC_ALL

me="ipsec look"

case "$1" in
    --help)
	echo "Usage: ${me}"
	exit 0
	;;
    --version)
	echo "$me $IPSEC_VERSION"
	exit 0
	;;
esac

# The ability to select what is displayed is internal, but is used for
# testing.

firewall_cmd() {
    HAVE_IPTABLES=true
    HAVE_NFTABLES=false
    if [ "${HAVE_NFTABLES}" = true ]; then #nft has precedence
        FIREWALL=NFTABLES
    elif [ "${HAVE_IPTABLES}" = true ]; then
        FIREWALL=IPTABLES
    else
        FIREWALL=""
    fi
}

default()
{
    look_state=$1
    look_policy=$1
    test "${FIREWALL}" = IPTABLES && look_iptables=$1 || look_iptables=false
    test "${FIREWALL}" = NFTABLES && look_nftables=$1 || look_nftables=false
    look_route=$1
    look_nss=$1
}

firewall_cmd

if test $# -eq 0 ; then
    default true
else
    default false
    while test $# -gt 0 ; do
	case "$1" in
     	    state) look_state=true ;;
     	    policy) look_policy=true ;;
	    iptables)  look_iptables=true ;;
	    nftables) look_nftables=true ;;
	    route ) look_route=true ;;
	    nss ) look_nss=true ;;
	    * ) echo Usage: ${me} ; exit 1 ;;
	esac
	shift
    done
fi

# label it just to be sure
echo "$(hostname) $(date)"

# xfrm

if ${look_state} ; then
    if [ -f /proc/sys/net/core/xfrm_acq_expires ]; then
	echo "XFRM state:"
	ip xfrm state
    fi
fi

if ${look_policy} ; then
    if [ -f /proc/sys/net/core/xfrm_acq_expires ]; then
	echo "XFRM policy:"
	# Force the order by feeding sort with lines prefixed by '[46]
	# TYPE PRIORITY |'.
	#
	# XXX: should this also sort the direction?
	ip -o xfrm policy | {
	    # clean up the input: drop socket lines; strip trailing
	    # white space (either end of line or before \\); strip
	    # double \\s
	    sed -e '/socket/d' \
		-e 's/\s*\\/\\/g' \
		-e 's/\\\\/\\/g' \
		-e 's/[\\]*\s*$//g'
	} | {
	    # Build the '<[46]> <type> <priority> |' prefix ready for
	    # sorting.  For each field, start with the assumption that
	    # the value is unknown (setting it to the default), and
	    # then adjust it as necessary.  For instance, for the
	    # protocol, start out assuming it is '4' (IPv4) and then
	    # if the line contains a ':' switch the prefix to '6'
	    # (IPv6).
	    sed -e 's/^/| /' \
		\
		-e 's/^/0 /' \
		-e 's/^0 \(.* priority \([0-9][0-9]*\)\)/\2 \1/' \
		\
		-e 's/^/0 /' \
		-e 's/^0 \(.*:.* type \([0-9][0-9]*\)\)/\2 \1/' \
		\
		-e 's/^/4 /' \
		-e 's/^4 \(.*:\)/6 \1/'
	} | {
	    # sort by each of the prefixes individually, and then by
	    # the rest of the line.  Shorter forms like -n and -k1,3n
	    # don't do what is wanted.
	    #
	    # XXX: Should add 'V' so .24. is before .200.?
	    sort -b -k1,1n -k2,2n -k3,3n -k5
	} | {
	    # strip the sort prefixes
	    sed -e 's/^.* | //'
	} | {
	    # convert \ into line breaks
	    tr '\\' '\012'
	}
    fi
fi

if ${look_state} || ${look_policy} ; then
    if [ -f /proc/sys/net/core/xfrm_acq_expires ]; then
	echo "XFRM done"
    fi
fi

if ${look_nftables} ; then
    echo nft list ruleset
    nft list ruleset
fi

if ${look_iptables} ; then
    echo IPSEC mangle TABLES
    if grep -q ^mangle /proc/net/ip_tables_names 2>/dev/null; then
	iptables -n -t mangle -L IPSEC
    fi
    if grep -q ^mangle /proc/net/ip6_tables_names 2>/dev/null; then
	ip6tables -n -t mangle -L IPSEC
    fi
    echo iptables filter TABLE
    iptables -n -t filter -L
fi

if ${look_route} ; then
    echo ROUTING TABLES
    # The IP command includes extra and evoling white space
    {
	ip -4 route
	ip -6 route
    } | sed -e 's/  / /g' -e 's/ $//'
fi

if ${look_nss} ; then
    if [ -f /var/lib/ipsec/nss/cert9.db ]; then
	echo NSS_CERTIFICATES
	certutil -L -d sql:/var/lib/ipsec/nss | head -4
	certutil -L -d sql:/var/lib/ipsec/nss | \
	    grep -E -v '^NSS_CERTIFICATES|^$|Trust Attributes|MIME,' | LC_ALL=C sort
    elif [ -f /var/lib/ipsec/nss/cert8.db ]; then
	echo NSS_CERTIFICATES
	certutil -L -d /var/lib/ipsec/nss | head -4
	certutil -L -d /var/lib/ipsec/nss | \
	    grep -E -v '^NSS_CERTIFICATES|^$|Trust Attributes|MIME,' | LC_ALL=C sort
    fi
fi

