⭐ 欢迎来到虫虫下载站! | 📦 资源下载 📁 资源专辑 ℹ️ 关于我们
⭐ 虫虫下载站

📄 ntptrap

📁 Unix/Linux 网络时间协议版本3 Network Time Protocol Version 3 (NTP) distribution for Unix systems
💻
字号:
#!/local/bin/perl --*-perl-*-;#;# ntptrap,v 3.1 1993/07/06 01:09:15 jbj Exp;#;# a client for the xntp mode 6 trap mechanism;#;# Copyright (c) 1992 ;#  Rainer Pruy Friedrich-Alexander Universitaet Erlangen-Nuernberg;#;#;#############################################################$0 =~ s!^.*/([^/]+)$!\1!;		# strip to filename;# enforce STDOUT and STDERR to be line buffered$| = 1;select((select(STDERR),$|=1)[$[]);;#######################################;# load utility routines and definitions;#require('ntp.pl');			# implementation of the NTP protocoleval { require('sys/socket.ph'); require('netinet/in.ph') unless defined(&INADDR_ANY); } ||do {  die("$0: $@") unless $[ == index($@, "Can't locate ");  warn "$0: $@";  warn "$0: supplying some default definitions\n";  eval 'sub INADDR_ANY { 0; } sub AF_INET {2;} sub SOCK_DGRAM {2;} 1;' || die "$0: $@";};require('getopts.pl');			# option parsingrequire('ctime.pl');			# date/time formatting;######################################;# define some global constants;#$BASE_TIMEOUT=10;$FRAG_TIMEOUT=10;$MAX_TRY = 5;$REFRESH_TIME=60*15;		# 15 minutes (server uses 1 hour)$ntp'timeout = $FRAG_TIMEOUT; #';;######################################;# now process options;#sub usage{    die("usage: $0 [-n] [-p <port>] [-l <logfile>] [host] ...\n");}$opt_l = "/dev/null";	# where to write debug messages to$opt_p = 0;		# port to use locally - (0 does mean: will be choosen by kernel)&usage unless &Getopts('l:p:');&Getopts if 0;	# make -w happy@Hosts = ($#ARGV < $[) ? ("localhost") : @ARGV;;# setup for debug output$DEBUGFILE=$opt_l;$DEBUGFILE="&STDERR" if $DEBUGFILE eq '-';open(DEBUG,">>$DEBUGFILE") || die("Cannot open \"$DEBUGFILE\": $!\n");select((select(DEBUG),$|=1)[$[]);;# &log prints a single trap record (adding a (local) time stamp)sub log{    chop($date=&ctime(time));    print "$date ",@_,"\n";}sub debug{    print DEBUG @_,"\n";};# $proto_udp = (getprotobyname('udp'))[$[+2] ||		(warn("$0: Could not get protocoll number for 'udp' using 17"), 17);$ntp_port = (getservbyname('ntp','udp'))[$[+2] ||	      (warn("$0: Could not get port number for service ntp/udp using 123"), 123);;# socket(S, &AF_INET, &SOCK_DGRAM, $proto_udp) || die("Cannot open socket: $!\n");;# bind(S, pack("S n N x8", &AF_INET, $opt_p, &INADDR_ANY)) ||    die("Cannot bind: $!\n");($my_port, $my_addr) = (unpack("S n a4 x8",getsockname(S)))[$[+1,$[+2];&log(sprintf("Listening at address %d.%d.%d.%d port %d",	     unpack("C4",$my_addr), $my_port));;# disregister with all servers in case of terminationsub cleanup{    &log("Aborted by signal \"$_[$[]\"") if defined($_[$[]);    foreach (@Hosts)    {	&ntp'send(S,31,0,"",pack("Sna4x8",&AF_INET,$ntp_port,$Hosts{$_})); #';    }    close(S);    exit(2);}$SIG{'HUP'} = 'cleanup';$SIG{'INT'} = 'cleanup';$SIG{'QUIT'} = 'cleanup';$SIG{'TERM'} = 'cleanup';0 && $a && $b;sub timeouts			# sort timeout id array{    $TIMEOUTS{$a} <=> $TIMEOUTS{$b};};# a Request element looks like: pack("a4SC",addr,associd,op)@Requests= ();;# compute requests for set trap control msgs to each host given{    local($name,$addr);        foreach (@Hosts)    {	if (/^(\d+)\.(\d+)\.(\d+)\.(\d+)$/)	{	    ($name,$addr) =		(gethostbyaddr(pack("C4",$1,$2,$3,$4),&AF_INET))[$[,$[+4];	    unless (defined($name))	    {		$name = sprintf("[[%d.%d.%d.%d]]",$1,$2,$3,$4);		$addr = pack("C4",$1,$2,$3,$4);	    }	}	else	{	    ($name,$addr) = (gethostbyname($_))[$[,$[+4];	    unless (defined($name))	    {		warn "$0: unknown host \"$_\" - ignored\n";		next;	    }	}	next if defined($Host{$name});	$Host{$name} = $addr;	push(@Requests,pack("a4SC",$addr,0,6));	# schedule a set trap request for $name    }}sub hostname{    local($addr) = @_;    return $HostName{$addr} if defined($HostName{$addr});    local($name) = gethostbyaddr($addr,&AF_INET);    &debug(sprintf("hostname(%d.%d.%d.%d) = \"%s\"",unpack("C4",$addr),$name))	if defined($name);    defined($name) && ($HostName{$addr} = $name) && (return $name);    &debug(sprintf("Failed to get name for %d.%d.%d.%d",unpack("C4",$addr)));    return sprintf("[%d.%d.%d.%d]",unpack("C4",$addr));};# when no hosts were given on the commandline no requests have been scheduled&usage unless (@Requests);&debug(sprintf("%d request(s) scheduled",scalar(@Requests)));grep(&debug("    - ".$_),keys(%Host));;# allocate variables;$addr="";$assoc=0;$op = 0;$timeout = 0;$ret="";%TIMEOUTS = ();%TIMEOUT_PROCS = ();@TIMEOUTS = ();		$len = 512;$buf = " " x $len;while (1){    if (@Requests || @TIMEOUTS)		# if there is some work pending    {	if (@Requests)	{	    ($addr,$assoc,$op) = unpack("a4SC",($req = shift(@Requests)));	    &debug(sprintf("Request: %s: %s(%d)",&hostname($addr), &ntp'cntrlop_name($op), $assoc)); #';))	    $ret = &ntp'send(S,$op,$assoc,"", #'(                             pack("Sna4x8",&AF_INET,$ntp_port,$addr));	    &set_timeout("retry-".unpack("H*",$req),time+$BASE_TIMEOUT,			 sprintf("&retry(\"%s\");",unpack("H*",$req)));	    last unless (defined($ret)); # warn called by ntp'send();	    ;# if there are more requests just have a quick look for new messages	    ;# otherwise grant server time for a response	    $timeout = @Requests ? 0 : $BASE_TIMEOUT;	}	if ($timeout && @TIMEOUTS)	{	    ;# ensure not to miss a timeout	    if ($timeout + time > $TIMEOUTS{$TIMEOUTS[$[]})	    {		$timeout = $TIMEOUTS{$TIMEOUTS[$[]} - time;		$timeout = 0 if $timeout < 0;	    }	}    }    else    {	;# no work yet - wait for some messages dropping in	;# usually this will not hapen as the refresh semantic will	;# always have a pending timeout	undef($timeout);    }    vec($mask="",fileno(S),1) = 1;    $ret = select($mask,undef,undef,$timeout);    warn("$0: select: $!\n"),last if $ret < 0;	# give up on error return from select    if ($ret == 0)    {	;# timeout	if (@TIMEOUTS && time > $TIMEOUTS{$TIMEOUTS[$[]})	{	    ;# handle timeout	    $timeout_proc =		(delete $TIMEOUT_PROCS{$TIMEOUTS[$[]},		 delete $TIMEOUTS{shift(@TIMEOUTS)})[$[];	    eval $timeout_proc;	    die "timeout eval (\"$timeout_proc\"): $@\n" if $@;	}	;# else: there may be something to be sent    }    else    {	;# data avail	$from = recv(S,$buf,$len,0);	;# give up on error return from recv	warn("$0: recv: $!\n"), last unless (defined($from));	$from = (unpack("Sna4",$from))[$[+2]; # keep host addr only	;# could check for ntp_port - but who cares	&debug("-Packet from ",&hostname($from));	;# stuff packet into ntp mode 6 receive machinery	($ret,$data,$status,$associd,$op,$seq,$auth_keyid) =	    &ntp'handle_packet($buf,$from); # ';	&debug(sprintf("%s uses auth_keyid %d",&hostname($from),$auth_keyid)) if defined($auth_keyid);	next unless defined($ret);	if ($ret eq "")	{	    ;# handle packet	    ;# simple trap response messages have neither timeout nor retries	    &clear_timeout("retry-".unpack("H*",pack("a4SC",$from,$associd,$op))) unless $op == 7;	    delete $RETRY{pack("a4SC",$from,$associd,$op)} unless $op == 7;	    &process_response($from,$ret,$data,$status,$associd,$op,$seq,$auth_keyid);	}	else	{	    ;# some kind of error	    &log(sprintf("%50s: %s: %s",(gethostbyaddr($from,&AF_INET))[$[],$ret,$data));	    if ($ret ne "TIMEOUT" && $ret ne "ERROR")	    {		&clear_timeout("retry-".unpack("H*",pack("a4SC",$from,$associd,$op)));	    }	}    }    }warn("$0: terminating\n");&cleanup;exit 0;;##################################################;# timeout support;#sub set_timeout{    local($id,$time,$proc) = @_;        $TIMEOUTS{$id} = $time;    $TIMEOUT_PROCS{$id} = $proc;    @TIMEOUTS = sort timeouts keys(%TIMEOUTS);    chop($date=&ctime($time));    &debug(sprintf("Schedule timeout \"%s\" for %s", $id, $date));}sub clear_timeout{    local($id) = @_;    delete $TIMEOUTS{$id};    delete $TIMEOUT_PROCS{$id};    @TIMEOUTS = sort timeouts keys(%TIMEOUTS);    &debug("Clear  timeout \"$id\"");}0 && &refresh;sub refresh{    local($addr) = @_;    $addr = pack("H*",$addr);    &debug(sprintf("Refreshing trap for %s", &hostname($addr)));    push(@Requests,pack("a4SC",$addr,0,6));}0 && &retry;sub retry{    local($tag) = @_;    $tag = pack("H*",$tag);    $RETRY{$tag} = 0 if (!defined($RETRY{$tag}));    if (++$RETRY{$tag} > $MAX_TRY)    {	&debug(sprintf("Retry failed: %s assoc %5d op %d",		       &hostname(substr($tag,$[,4)),		       unpack("x4SC",$tag)));	return;    }    &debug(sprintf("Retrying: %s assoc %5d op %d",		       &hostname(substr($tag,$[,4)),		       unpack("x4SC",$tag)));    push(@Requests,$tag);}sub process_response{    local($from,$ret,$data,$status,$associd,$op,$seq,$auth_keyid) = @_;        $msg="";    if ($op == 7)		# trap response    {	$msg .= sprintf("%40s trap#%-5d",			&hostname($from),$seq);	&debug (sprintf("\nTrap %d associd %d:\n%s\n===============\n",$seq,$associd,$data));	if ($associd == 0)	# system event	{	    $msg .= "  SYSTEM   ";	    $evnt = &ntp'SystemEvent($status); #';	    $msg .= "$evnt ";	    ;# for special cases add additional info	    ($stratum) = ($data =~ /stratum=(\d+)/);	    ($refid) = ($data =~ /refid=([\w\.]+)/);	    $msg .= "stratum=$stratum refid=$refid";	    if ($refid =~ /\[?(\d+)\.(\d+)\.(\d+)\.(\d+)/)	    {		$msg .= " " . (gethostbyaddr(pack("C4",$1,$2,$3,$4),&AF_INET))[$[];	    }	    if ($evnt eq "event_sync_chg")	    {		$msg .= sprintf("%s %s ",				&ntp'LI($status), #',				&ntp'ClockSource($status) #'				);	    }	    elsif ($evnt eq "event_sync/strat_chg")	    {		($peer) = ($data =~ /peer=([0-9]+)/);		$msg .= " peer=$peer";	    }	    elsif ($evnt eq "event_clock_excptn")	    {		if (($device) = ($data =~ /device=\"([^\"]+)\"/))		{		    ($cstatus) = ($data =~ /refclockstatus=0?x?([\da-fA-F]+)/);		    $Cstatus = hex($cstatus);		    $msg .= sprintf("- %-32s",&ntp'clock_status($Cstatus)); #');		    ($timecode) = ($data =~ /timecode=\"([^\"]+)\"/);		    $msg .= " \"$device\" \"$timecode\"";		}		else		{		    push(@Requests,pack("a4SC",$from, $associd, 4));		}	    }	}	else			# peer event	{	    $msg .= sprintf("peer %5d ",$associd);	    ($srcadr) = ($data =~ /srcadr=\[?([\d\.]+)/);	    $msg .= sprintf("%-18s %40s ", "[$srcadr]",			    &hostname(pack("C4",split(/\./,$srcadr))));	    $evnt = &ntp'PeerEvent($status); #';	    $msg .= "$evnt ";	    ;# for special cases include additional info	    if ($evnt eq "event_clock_excptn")	    {		if (($device) = ($data =~ /device=\"([^\"]+)\"/))		{		    ;#&debug("----\n$data\n====\n");		    ($cstatus) = ($data =~ /refclockstatus=0?x?([\da-fA-F]+)/);		    $Cstatus = hex($cstatus);		    $msg .= sprintf("- %-32s",&ntp'clock_status($Cstatus)); #');		    ($timecode) = ($data =~ /timecode=\"([^\"]+)\"/);		    $msg .= " \"$device\" \"$timecode\"";		}		else		{		    ;# no clockvars included - post a cv request		    push(@Requests,pack("a4SC",$from, $associd, 4));		}	    }	    elsif ($evnt eq "event_stratum_chg")	    {		($stratum) = ($data =~ /stratum=(\d+)/);		$msg .= "new stratum $stratum";	    }	}    }    elsif ($op == 6)		# set trap resonse    {	&debug("Set trap ok from ",&hostname($from));	&set_timeout("refresh-".unpack("H*",$from),time+$REFRESH_TIME,		     sprintf("&refresh(\"%s\");",unpack("H*",$from)));	return;    }    elsif ($op == 4)		# read clock variables response    {	;# status of clock	$msg .= sprintf(" %40s ", &hostname($from));	if ($associd == 0)	{	    $msg .= "system clock status: ";	}	else	{	    $msg .= sprintf("peer %5d clock",$associd);	}	$msg .= sprintf("%-32s",&ntp'clock_status($status)); #');	($device) = ($data =~ /device=\"([^\"]+)\"/);	($timecode) = ($data =~ /timecode=\"([^\"]+)\"/);	$msg .= " \"$device\" \"$timecode\"";    }    elsif ($op == 31)		# unset trap response (UNOFFICIAL op)    {	;# clear timeout	&debug("Clear Trap ok from ",&hostname($from));	&clear_timeout("refresh-".unpack("H*",$from));	return;    }    else			# unexpected response    {	$msg .= "unexpected response to op $op assoc=$associd";	$msg .= sprintf(" status=%04x",$status);    }    &log($msg);}

⌨️ 快捷键说明

复制代码 Ctrl + C
搜索代码 Ctrl + F
全屏模式 F11
切换主题 Ctrl + Shift + D
显示快捷键 ?
增大字号 Ctrl + =
减小字号 Ctrl + -