#!/bin/bash
#
# netdump This starts, stops, and reloads the netconsole
# and netcrashdump facility
#
# chkconfig: - 50 50
# description: Initialize console side of netconsole and netcrashdump facility
# config: /etc/sysconfig/netdump
#
# Copyright 2002 Red Hat, Inc.
#
# Based in part on a shell script by
# Andreas Dilger <adilger@turbolinux.com> Sep 26, 2001
PATH=/sbin:/usr/sbin:$PATH
RETVAL=0
SERVER_ADDRESS_RESOLUTION=
prog=netdump
# Check that networking is up.
. /etc/sysconfig/network
if [ ${NETWORKING} = "no" ]
then
exit 0
fi
# Source function library.
. /etc/rc.d/init.d/functions
# Default values
LOCALPORT=6666
DEV=eth0
NETDUMPADDR=
NETDUMPMACADDR=
NETDUMPPORT=6666
IDLETIMEOUT=
NETDUMPKEYEXCHANGE=
SYSLOGADDR=
SYSLOGPORT=514
SYSLOGMACADDR=
NETLOGADDR=
NETLOGMACADDR=
NETLOGPORT=
kernel=`uname -r | cut -d. -f1-2`
[ -f /etc/sysconfig/netdump ] || exit 0
. /etc/sysconfig/netdump
[ -n "$NETDUMPADDR" ] || [ -n "$SYSLOGADDR" ] || [ -n "$NETLOGADDR" ] || {
echo "Server address not specified in /etc/sysconfig/netdump" 1>&2
exit 1
}
usage ()
{
echo "Usage: service netdump {start|stop|status|restart|condrestart|propagate}" 1>&2
RETVAL=1
}
dquad_to_hex ()
{
echo $1 | sed -e "s/[()]//g" -e "s/\./ /g" | while read I0 I1 I2 I3 ; do
printf "0x%02X%02X%02X%02X" $I0 $I1 $I2 $I3
done
}
print_address_info ()
{
# fill the arp cache with needed data and print info for host
# usage: print_address_info host
local host=$1
local ping_output line host_ip trc_output mac_ip
local arp_output hostname ipaddr at mac iftype on iface
# use ping to make sure the netdump server is reachable; also,
# ensure that the IP address is numeric
ping_output="$(ping -c 1 -I $DEV $host 2> /dev/null)"
[ $? -ne 0 ] && echo "$prog: cannot ping $host" 1>&2 && exit 1
ping_output="$(echo $ping_output | grep '^PING ' | awk '{print $3}' | \
sed 's/^(//' | sed 's/)$//')"
for line in $ping_output; do host_ip=$line; done
# the needed MAC address is directly associated with the host
# IP address only if client and server are on the same subnet
# if not, the needed MAC address is that of the gateway port;
# either way, this will be the first IP address from traceroute
trc_output="$(traceroute -i $DEV -n -m 1 $host_ip 2> /dev/null)"
[ $? -ne 0 ] && echo "$prog: cannot traceroute $host_ip" 1>&2
trc_output="$(echo $trc_output | grep '^1 ' | awk '{print $2}')"
for line in $trc_output; do mac_ip=$line; done
arping -c 1 -I $DEV $mac_ip &> /dev/null
[ $? -ne 0 ] && echo "$prog: cannot arp $mac_ip" 1>&2
# output from arp -a of the form:
# good: host.domain (A.B.C.D) at 00:50:BF:06:48:C1 [ether] on eth0
# 1 2 3 4 5 6 7
# bad: ? (A.B.C.D) at <incomplete> on eth0
arp_output="$(LC_ALL=C arp -a | grep -v incomplete)"
echo "$arp_output" | ( while read hostname ipaddr at mac iftype on iface;
do
: echo hostname=$hostname ipaddr=$ipaddr at=$at mac=$mac iftype=$iftype
: echo on=$on iface=$iface
if [ "$ipaddr" = "($mac_ip)" ] || expr "$hostname" : "$host" &>/dev/null;
then
echo HOSTNAME=$host IPADDR=$host_ip AT=$at MAC=$mac \
TYPE=$iftype ON=$on IFACE=$iface
fi
done )
}
random_hex_int ()
{
dd if=/dev/urandom bs=4 count=1 2>/dev/null | od -x | awk '/0000000/ {print $2$3}'
}
ip_of_device ()
{
LC_ALL=C /sbin/ifconfig $1 | sed 's/:/ /' | awk '/inet addr/ {print $3}'
}
netdump_failure ()
{
echo -n "$1"
failure
echo
exit 1
}
start ()
{
# netdump/netconsole server
NETDUMPOPTS=
if [ -n "$NETDUMPADDR" ]
then
eval $(print_address_info $NETDUMPADDR)
if [ "$HOSTNAME" = "?" -a -z "$MAC" ]
then
echo "$prog: can't resolve $NETDUMPADDR MAC address" 1>&2
netdump_failure "netdump server address resolution"
fi
[ -z "$NETDUMPMACADDR" ] && NETDUMPMACADDR=$MAC
[ -z "$DEV" ] && DEV=$IFACE
if [ "$DEV" = "$IFACE" -a "$TYPE" != "[ether]" ]
then
echo "$prog: $DEV must be an ethernet interface" 1>&2
netdump_failure "netdump $DEV configuration"
fi
# Now we are ready to tell the netdump server how to talk to us
MAGIC1=$(random_hex_int)
MAGIC2=$(random_hex_int)
LOCALADDR=$(ip_of_device $DEV)
case "$NETDUMPKEYEXCHANGE" in
none)
# magic can be anything (except 0) if security is disabled
NETDUMPOPTS="magic1=0x11111111 magic2=0x11111111 "
;;
*)
ssh -x -i /etc/sysconfig/netdump_id_dsa netdump@$NETDUMPADDR echo "$MAGIC2$MAGIC1" \> /var/crash/magic/$LOCALADDR
if [ $? -ne 0 ]; then
echo "$prog: could not ssh to server $NETDUMPADDR"
netdump_failure "netdump server ssh key exchange"
fi
NETDUMPOPTS="magic1=0x$MAGIC1 magic2=0x$MAGIC2 "
;;
esac
IPHEX=`dquad_to_hex $IPADDR`
eval $(echo $NETDUMPMACADDR | sed "s/:/ /g" | ( read M0 M1 M2 M3 M4 M5;
echo M0=$M0\; M1=$M1\; M2=$M2\; M3=$M3\; M4=$M4\; M5=$M5\; ))
TGTMAC="netdump_target_eth_byte0=0x$M0 netdump_target_eth_byte1=0x$M1 \
netdump_target_eth_byte2=0x$M2 netdump_target_eth_byte3=0x$M3 \
netdump_target_eth_byte4=0x$M4 netdump_target_eth_byte5=0x$M5 \
netlog_target_eth_byte0=0x$M0 netlog_target_eth_byte1=0x$M1 \
netlog_target_eth_byte2=0x$M2 netlog_target_eth_byte3=0x$M3 \
netlog_target_eth_byte4=0x$M4 netlog_target_eth_byte5=0x$M5"
MHZ="mhz=$(awk '/cpu MHz/ { print int($4) ; exit }' < /proc/cpuinfo)"
if [ "$MHZ" == 0 ] ; then
# something went wrong; make some reasonable guess
MHZ=1000
fi
if [ -n "$IDLETIMEOUT" ] ; then
IDLETIMEOUT="idle_timeout=$IDLETIMEOUT"
fi
if [ $kernel = 2.4 ]; then
NETDUMPOPTS=$NETDUMPOPTS"\
dev=$DEV netdump_target_ip=$IPHEX netlog_target_ip=$IPHEX \
source_port=$LOCALPORT netdump_target_port=$NETDUMPPORT \
netlog_target_port=$NETDUMPPORT \
$TGTMAC $MHZ $IDLETIMEOUT"
else
NETDUMPOPTS=$NETDUMPOPTS"\
netdump=@$LOCALADDR/$DEV,$NETDUMPPORT@$IPADDR/$NETDUMPMACADDR"
fi
else
# The netdump subsystem of the netconsole module is not configured.
# However, the netconsole module minimally needs the following
# options in order for the syslog subsystem to run alone.
if [ $kernel = 2.4 ]; then
NETDUMPOPTS="magic1=0x11111111 magic2=0x11111111 dev=$DEV source_port=$LOCALPORT"
else
NETDUMPOPTS="magic1=0x11111111 magic2=0x11111111"
fi
fi
# This section must come after NETDUMPOPTS, as it inherits IP address
# from it.
if [ $kernel = 2.6 ]; then
# Make these the same as netdump opts
if [ -z $NETLOGADDR ]; then
NETLOGOPTS="netlog=@$LOCALADDR/$DEV,$NETDUMPPORT@$IPADDR/$NETDUMPMACADDR"
elif [ $NETLOGADDR = "NONE" ]; then
NETLOGOPTS=
elif [ -n "$NETLOGADDR" ]; then
eval $(print_address_info $NETLOGADDR)
[ "$HOSTNAME" = "?" -a -z "$MAC" ] &&
netdump_failure "netlog server address resolution"
[ -z "$NETLOGMACADDR" ] && NETLOGMACADDR=$MAC
NETLOGOPTS="netlog=@$LOCALDDR/$DEV,$NETLOGPORT@$IPADDR/$NETLOGMACADDR "
fi
fi
SYSLOGOPTS=
# syslogd server, if any
if [ -n "$SYSLOGADDR" ] ; then
eval $(print_address_info $SYSLOGADDR)
[ "$SERVER_ADDRESS_RESOLUTION" = "unresolved" ] &&
netdump_failure "syslog server address resolution"
[ -z "$SYSLOGMACADDR" ] && SYSLOGMACADDR=$MAC
SYSLOGIPHEX=`dquad_to_hex $IPADDR`
eval $(echo $SYSLOGMACADDR | sed "s/:/ /g" | ( read M0 M1 M2 M3 M4 M5;
echo M0=$M0\; M1=$M1\; M2=$M2\; M3=$M3\; M4=$M4\; M5=$M5\; ))
SYSLOGMAC="syslog_target_eth_byte0=0x$M0 syslog_target_eth_byte1=0x$M1 \
syslog_target_eth_byte2=0x$M2 syslog_target_eth_byte3=0x$M3 \
syslog_target_eth_byte4=0x$M4 syslog_target_eth_byte5=0x$M5"
if [ $kernel = 2.4 ]; then
SYSLOGOPTS="syslog_target_ip=$SYSLOGIPHEX syslog_target_port=$SYSLOGPORT $SYSLOGMAC"
else
SYSLOGOPTS="netconsole=@$LOCALADDR/$DEV,$SYSLOGPORT@$SYSLOGADDR/$SYSLOGMACADDR "
fi
fi
logger -p daemon.info -t netdump: inserting netconsole module with arguments \
$NETDUMPOPTS $SYSLOGOPTS
if [ $kernel = 2.4 ]; then
action $"initializing netdump" modprobe netconsole \
$NETDUMPOPTS $SYSLOGOPTS
else
if [ -n "$NETDUMPADDR" ]; then
action $"initializing netdump" modprobe netdump \
$NETDUMPOPTS
fi
if [ -n "$SYSLOGOPTS" ] || [ -n "$NETLOGOPTS" ] ; then
action $"initializing netconsole" modprobe netconsole \
$SYSLOGOPTS $NETLOGOPTS
fi
fi
touch /var/lock/subsys/netdump
}
stop ()
{
if [ $kernel = 2.4 ]; then
if /sbin/lsmod | grep netconsole >/dev/null 2>&1 ; then
action $"disabling netdump" rmmod netconsole
fi
else
if /sbin/lsmod | grep netconsole >/dev/null 2>&1 ; then
action $"disabling netconsole" rmmod netconsole;
fi
if /sbin/lsmod | grep netdump >/dev/null 2>&1 ; then
action $"disabling netdump" rmmod netdump
fi
fi
rm -f /var/lock/subsys/netdump
}
status ()
{
if [ $kernel = 2.6 ]; then
if /sbin/lsmod | grep netdump >/dev/null 2>&1 ; then
echo "netdump module loaded"
else
echo "netdump module not loaded"
fi
fi
if /sbin/lsmod | grep netconsole >/dev/null 2>&1 ; then
echo "netconsole module loaded"
else
echo "netconsole module not loaded"
fi
}
restart ()
{
stop
start
}
condrestart ()
{
[ -e /var/lock/subsys/netdump ] && restart
}
propagate ()
{
# propagate netdump ssh public key to the crashdump server
cat /etc/sysconfig/netdump_id_dsa.pub | \
ssh -x netdump@$NETDUMPADDR cat '>>' /var/crash/.ssh/authorized_keys2
}
case "$1" in
stop) stop ;;
status) status ;;
start|restart|reload) restart ;;
condrestart) condrestart ;;
propagate) propagate ;;
*) usage ;;
esac
exit $RETVAL
syntax highlighted by Code2HTML, v. 0.9.1