#!/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