1abb0f93cSkardel#!/local/bin/perl --*-perl-*- 2abb0f93cSkardel;# 3abb0f93cSkardel;# ntptrap,v 3.1 1993/07/06 01:09:15 jbj Exp 4abb0f93cSkardel;# 5abb0f93cSkardel;# a client for the xntp mode 6 trap mechanism 6abb0f93cSkardel;# 7abb0f93cSkardel;# Copyright (c) 1992 8abb0f93cSkardel;# Rainer Pruy Friedrich-Alexander Universitaet Erlangen-Nuernberg 9abb0f93cSkardel;# 10abb0f93cSkardel;# 11abb0f93cSkardel;############################################################# 12abb0f93cSkardel$0 =~ s!^.*/([^/]+)$!$1!; # strip to filename 13abb0f93cSkardel;# enforce STDOUT and STDERR to be line buffered 14abb0f93cSkardel$| = 1; 15abb0f93cSkardelselect((select(STDERR),$|=1)[$[]); 16abb0f93cSkardel 17abb0f93cSkardel;####################################### 18abb0f93cSkardel;# load utility routines and definitions 19abb0f93cSkardel;# 20abb0f93cSkardelrequire('ntp.pl'); # implementation of the NTP protocol 21abb0f93cSkardeluse Socket; 22abb0f93cSkardel 23abb0f93cSkardel#eval { require('sys/socket.ph'); require('netinet/in.ph') unless defined(&INADDR_ANY); } || 24abb0f93cSkardel#do { 25abb0f93cSkardel #die("$0: $@") unless $[ == index($@, "Can't locate "); 26abb0f93cSkardel #warn "$0: $@"; 27abb0f93cSkardel #warn "$0: supplying some default definitions\n"; 28abb0f93cSkardel #eval 'sub INADDR_ANY { 0; } sub AF_INET {2;} sub SOCK_DGRAM {2;} 1;' || die "$0: $@"; 29abb0f93cSkardel#}; 30abb0f93cSkardelrequire('getopts.pl'); # option parsing 31abb0f93cSkardelrequire('ctime.pl'); # date/time formatting 32abb0f93cSkardel 33abb0f93cSkardel;###################################### 34abb0f93cSkardel;# define some global constants 35abb0f93cSkardel;# 36abb0f93cSkardel$BASE_TIMEOUT=10; 37abb0f93cSkardel$FRAG_TIMEOUT=10; 38abb0f93cSkardel$MAX_TRY = 5; 39abb0f93cSkardel$REFRESH_TIME=60*15; # 15 minutes (server uses 1 hour) 40abb0f93cSkardel$ntp'timeout = $FRAG_TIMEOUT; #'; 41abb0f93cSkardel$ntp'timeout if 0; 42abb0f93cSkardel 43abb0f93cSkardel;###################################### 44abb0f93cSkardel;# now process options 45abb0f93cSkardel;# 46abb0f93cSkardelsub usage 47abb0f93cSkardel{ 48*b8ecfcfeSchristos die("usage: $0 [-p <port>] [-l <logfile>] [host] ...\n"); 49abb0f93cSkardel} 50abb0f93cSkardel 51abb0f93cSkardel&usage unless &Getopts('l:p:'); 52abb0f93cSkardel&Getopts if 0; # make -w happy 53abb0f93cSkardel 54*b8ecfcfeSchristos$opt_l = "/dev/null" # where to write debug messages to 55*b8ecfcfeSchristos if (!$opt_l); 56*b8ecfcfeSchristos$opt_p = 0 # port to use locally - (0 does mean: will be chosen by kernel) 57*b8ecfcfeSchristos if (!$opt_p); 58*b8ecfcfeSchristos 59abb0f93cSkardel@Hosts = ($#ARGV < $[) ? ("localhost") : @ARGV; 60abb0f93cSkardel 61abb0f93cSkardel;# setup for debug output 62abb0f93cSkardel$DEBUGFILE=$opt_l; 63abb0f93cSkardel$DEBUGFILE="&STDERR" if $DEBUGFILE eq '-'; 64abb0f93cSkardel 65abb0f93cSkardelopen(DEBUG,">>$DEBUGFILE") || die("Cannot open \"$DEBUGFILE\": $!\n"); 66abb0f93cSkardelselect((select(DEBUG),$|=1)[$[]); 67abb0f93cSkardel 68abb0f93cSkardel;# &log prints a single trap record (adding a (local) time stamp) 69abb0f93cSkardelsub log 70abb0f93cSkardel{ 71abb0f93cSkardel chop($date=&ctime(time)); 72abb0f93cSkardel print "$date ",@_,"\n"; 73abb0f93cSkardel} 74abb0f93cSkardel 75abb0f93cSkardelsub debug 76abb0f93cSkardel{ 77abb0f93cSkardel print DEBUG @_,"\n"; 78abb0f93cSkardel} 79abb0f93cSkardel;# 80abb0f93cSkardel$proto_udp = (getprotobyname('udp'))[$[+2] || 81abb0f93cSkardel (warn("$0: Could not get protocoll number for 'udp' using 17"), 17); 82abb0f93cSkardel 83abb0f93cSkardel$ntp_port = (getservbyname('ntp','udp'))[$[+2] || 84abb0f93cSkardel (warn("$0: Could not get port number for service ntp/udp using 123"), 123); 85abb0f93cSkardel 86abb0f93cSkardel;# 87abb0f93cSkardelsocket(S, &AF_INET, &SOCK_DGRAM, $proto_udp) || die("Cannot open socket: $!\n"); 88abb0f93cSkardel 89abb0f93cSkardel;# 90abb0f93cSkardelbind(S, pack("S n a4 x8", &AF_INET, $opt_p, &INADDR_ANY)) || 91abb0f93cSkardel die("Cannot bind: $!\n"); 92abb0f93cSkardel 93abb0f93cSkardel($my_port, $my_addr) = (unpack("S n a4 x8",getsockname(S)))[$[+1,$[+2]; 94abb0f93cSkardel&log(sprintf("Listening at address %d.%d.%d.%d port %d", 95abb0f93cSkardel unpack("C4",$my_addr), $my_port)); 96abb0f93cSkardel 97abb0f93cSkardel;# disregister with all servers in case of termination 98abb0f93cSkardelsub cleanup 99abb0f93cSkardel{ 100abb0f93cSkardel &log("Aborted by signal \"$_[$[]\"") if defined($_[$[]); 101abb0f93cSkardel 102abb0f93cSkardel foreach (@Hosts) 103abb0f93cSkardel { 104abb0f93cSkardel if ( ! defined($Host{$_}) ) 105abb0f93cSkardel { 106abb0f93cSkardel print "no info for host '$_'\n"; 107abb0f93cSkardel next; 108abb0f93cSkardel } 109abb0f93cSkardel &ntp'send(S,31,0,"",pack("Sna4x8",&AF_INET,$ntp_port,$Host{$_})); #'; 110abb0f93cSkardel } 111abb0f93cSkardel close(S); 112abb0f93cSkardel exit(2); 113abb0f93cSkardel} 114abb0f93cSkardel 115abb0f93cSkardel$SIG{'HUP'} = 'cleanup'; 116abb0f93cSkardel$SIG{'INT'} = 'cleanup'; 117abb0f93cSkardel$SIG{'QUIT'} = 'cleanup'; 118abb0f93cSkardel$SIG{'TERM'} = 'cleanup'; 119abb0f93cSkardel 120abb0f93cSkardel0 && $a && $b; 121abb0f93cSkardelsub timeouts # sort timeout id array 122abb0f93cSkardel{ 123abb0f93cSkardel $TIMEOUTS{$a} <=> $TIMEOUTS{$b}; 124abb0f93cSkardel} 125abb0f93cSkardel 126abb0f93cSkardel;# a Request element looks like: pack("a4SC",addr,associd,op) 127abb0f93cSkardel@Requests= (); 128abb0f93cSkardel 129abb0f93cSkardel;# compute requests for set trap control msgs to each host given 130abb0f93cSkardel{ 131abb0f93cSkardel local($name,$addr); 132abb0f93cSkardel 133abb0f93cSkardel foreach (@Hosts) 134abb0f93cSkardel { 135abb0f93cSkardel if (/^(\d+)\.(\d+)\.(\d+)\.(\d+)$/) 136abb0f93cSkardel { 137abb0f93cSkardel ($name,$addr) = 138abb0f93cSkardel (gethostbyaddr(pack("C4",$1,$2,$3,$4),&AF_INET))[$[,$[+4]; 139abb0f93cSkardel unless (defined($name)) 140abb0f93cSkardel { 141abb0f93cSkardel $name = sprintf("[[%d.%d.%d.%d]]",$1,$2,$3,$4); 142abb0f93cSkardel $addr = pack("C4",$1,$2,$3,$4); 143abb0f93cSkardel } 144abb0f93cSkardel } 145abb0f93cSkardel else 146abb0f93cSkardel { 147abb0f93cSkardel ($name,$addr) = (gethostbyname($_))[$[,$[+4]; 148abb0f93cSkardel unless (defined($name)) 149abb0f93cSkardel { 150abb0f93cSkardel warn "$0: unknown host \"$_\" - ignored\n"; 151abb0f93cSkardel next; 152abb0f93cSkardel } 153abb0f93cSkardel } 154abb0f93cSkardel next if defined($Host{$name}); 155abb0f93cSkardel $Host{$name} = $addr; 156abb0f93cSkardel $Host{$_} = $addr; 157abb0f93cSkardel push(@Requests,pack("a4SC",$addr,0,6)); # schedule a set trap request for $name 158abb0f93cSkardel } 159abb0f93cSkardel} 160abb0f93cSkardel 161abb0f93cSkardelsub hostname 162abb0f93cSkardel{ 163abb0f93cSkardel local($addr) = @_; 164abb0f93cSkardel return $HostName{$addr} if defined($HostName{$addr}); 165abb0f93cSkardel local($name) = gethostbyaddr($addr,&AF_INET); 166abb0f93cSkardel &debug(sprintf("hostname(%d.%d.%d.%d) = \"%s\"",unpack("C4",$addr),$name)) 167abb0f93cSkardel if defined($name); 168abb0f93cSkardel defined($name) && ($HostName{$addr} = $name) && (return $name); 169abb0f93cSkardel &debug(sprintf("Failed to get name for %d.%d.%d.%d",unpack("C4",$addr))); 170abb0f93cSkardel return sprintf("[%d.%d.%d.%d]",unpack("C4",$addr)); 171abb0f93cSkardel} 172abb0f93cSkardel 173abb0f93cSkardel;# when no hosts were given on the commandline no requests have been scheduled 174abb0f93cSkardel&usage unless (@Requests); 175abb0f93cSkardel 176abb0f93cSkardel&debug(sprintf("%d request(s) scheduled",scalar(@Requests))); 177abb0f93cSkardelgrep(&debug(" - ".$_),keys(%Host)); 178abb0f93cSkardel 179abb0f93cSkardel;# allocate variables; 180abb0f93cSkardel$addr=""; 181abb0f93cSkardel$assoc=0; 182abb0f93cSkardel$op = 0; 183abb0f93cSkardel$timeout = 0; 184abb0f93cSkardel$ret=""; 185abb0f93cSkardel%TIMEOUTS = (); 186abb0f93cSkardel%TIMEOUT_PROCS = (); 187abb0f93cSkardel@TIMEOUTS = (); 188abb0f93cSkardel 189abb0f93cSkardel$len = 512; 190abb0f93cSkardel$buf = " " x $len; 191abb0f93cSkardel 192abb0f93cSkardelwhile (1) 193abb0f93cSkardel{ 194abb0f93cSkardel if (@Requests || @TIMEOUTS) # if there is some work pending 195abb0f93cSkardel { 196abb0f93cSkardel if (@Requests) 197abb0f93cSkardel { 198abb0f93cSkardel ($addr,$assoc,$op) = unpack("a4SC",($req = shift(@Requests))); 199abb0f93cSkardel &debug(sprintf("Request: %s: %s(%d)",&hostname($addr), &ntp'cntrlop_name($op), $assoc)); #';)) 200abb0f93cSkardel $ret = &ntp'send(S,$op,$assoc,"", #'( 201abb0f93cSkardel pack("Sna4x8",&AF_INET,$ntp_port,$addr)); 202abb0f93cSkardel &set_timeout("retry-".unpack("H*",$req),time+$BASE_TIMEOUT, 203abb0f93cSkardel sprintf("&retry(\"%s\");",unpack("H*",$req))); 204abb0f93cSkardel 205abb0f93cSkardel last unless (defined($ret)); # warn called by ntp'send(); 206abb0f93cSkardel 207abb0f93cSkardel ;# if there are more requests just have a quick look for new messages 208abb0f93cSkardel ;# otherwise grant server time for a response 209abb0f93cSkardel $timeout = @Requests ? 0 : $BASE_TIMEOUT; 210abb0f93cSkardel } 211abb0f93cSkardel if ($timeout && @TIMEOUTS) 212abb0f93cSkardel { 213abb0f93cSkardel ;# ensure not to miss a timeout 214abb0f93cSkardel if ($timeout + time > $TIMEOUTS{$TIMEOUTS[$[]}) 215abb0f93cSkardel { 216abb0f93cSkardel $timeout = $TIMEOUTS{$TIMEOUTS[$[]} - time; 217abb0f93cSkardel $timeout = 0 if $timeout < 0; 218abb0f93cSkardel } 219abb0f93cSkardel } 220abb0f93cSkardel } 221abb0f93cSkardel else 222abb0f93cSkardel { 223abb0f93cSkardel ;# no work yet - wait for some messages dropping in 224abb0f93cSkardel ;# usually this will not hapen as the refresh semantic will 225abb0f93cSkardel ;# always have a pending timeout 226abb0f93cSkardel undef($timeout); 227abb0f93cSkardel } 228abb0f93cSkardel 229abb0f93cSkardel vec($mask="",fileno(S),1) = 1; 230abb0f93cSkardel $ret = select($mask,undef,undef,$timeout); 231abb0f93cSkardel 232abb0f93cSkardel warn("$0: select: $!\n"),last if $ret < 0; # give up on error return from select 233abb0f93cSkardel 234abb0f93cSkardel if ($ret == 0) 235abb0f93cSkardel { 236abb0f93cSkardel ;# timeout 237abb0f93cSkardel if (@TIMEOUTS && time > $TIMEOUTS{$TIMEOUTS[$[]}) 238abb0f93cSkardel { 239abb0f93cSkardel ;# handle timeout 240abb0f93cSkardel $timeout_proc = 241abb0f93cSkardel (delete $TIMEOUT_PROCS{$TIMEOUTS[$[]}, 242abb0f93cSkardel delete $TIMEOUTS{shift(@TIMEOUTS)})[$[]; 243abb0f93cSkardel eval $timeout_proc; 244abb0f93cSkardel die "timeout eval (\"$timeout_proc\"): $@\n" if $@; 245abb0f93cSkardel } 246abb0f93cSkardel ;# else: there may be something to be sent 247abb0f93cSkardel } 248abb0f93cSkardel else 249abb0f93cSkardel { 250abb0f93cSkardel ;# data avail 251abb0f93cSkardel $from = recv(S,$buf,$len,0); 252abb0f93cSkardel ;# give up on error return from recv 253abb0f93cSkardel warn("$0: recv: $!\n"), last unless (defined($from)); 254abb0f93cSkardel 255abb0f93cSkardel $from = (unpack("Sna4",$from))[$[+2]; # keep host addr only 256abb0f93cSkardel ;# could check for ntp_port - but who cares 257abb0f93cSkardel &debug("-Packet from ",&hostname($from)); 258abb0f93cSkardel 259abb0f93cSkardel ;# stuff packet into ntp mode 6 receive machinery 260abb0f93cSkardel ($ret,$data,$status,$associd,$op,$seq,$auth_keyid) = 261abb0f93cSkardel &ntp'handle_packet($buf,$from); # '; 262abb0f93cSkardel &debug(sprintf("%s uses auth_keyid %d",&hostname($from),$auth_keyid)) if defined($auth_keyid); 263abb0f93cSkardel next unless defined($ret); 264abb0f93cSkardel 265abb0f93cSkardel if ($ret eq "") 266abb0f93cSkardel { 267abb0f93cSkardel ;# handle packet 268abb0f93cSkardel ;# simple trap response messages have neither timeout nor retries 269abb0f93cSkardel &clear_timeout("retry-".unpack("H*",pack("a4SC",$from,$associd,$op))) unless $op == 7; 270abb0f93cSkardel delete $RETRY{pack("a4SC",$from,$associd,$op)} unless $op == 7; 271abb0f93cSkardel 272abb0f93cSkardel &process_response($from,$ret,$data,$status,$associd,$op,$seq,$auth_keyid); 273abb0f93cSkardel } 274abb0f93cSkardel else 275abb0f93cSkardel { 276abb0f93cSkardel ;# some kind of error 277abb0f93cSkardel &log(sprintf("%50s: %s: %s",(gethostbyaddr($from,&AF_INET))[$[],$ret,$data)); 278abb0f93cSkardel if ($ret ne "TIMEOUT" && $ret ne "ERROR") 279abb0f93cSkardel { 280abb0f93cSkardel &clear_timeout("retry-".unpack("H*",pack("a4SC",$from,$associd,$op))); 281abb0f93cSkardel } 282abb0f93cSkardel } 283abb0f93cSkardel } 284abb0f93cSkardel 285abb0f93cSkardel} 286abb0f93cSkardel 287abb0f93cSkardelwarn("$0: terminating\n"); 288abb0f93cSkardel&cleanup; 289abb0f93cSkardelexit 0; 290abb0f93cSkardel 291abb0f93cSkardel;################################################## 292abb0f93cSkardel;# timeout support 293abb0f93cSkardel;# 294abb0f93cSkardelsub set_timeout 295abb0f93cSkardel{ 296abb0f93cSkardel local($id,$time,$proc) = @_; 297abb0f93cSkardel 298abb0f93cSkardel $TIMEOUTS{$id} = $time; 299abb0f93cSkardel $TIMEOUT_PROCS{$id} = $proc; 300abb0f93cSkardel @TIMEOUTS = sort timeouts keys(%TIMEOUTS); 301abb0f93cSkardel chop($date=&ctime($time)); 302abb0f93cSkardel &debug(sprintf("Schedule timeout \"%s\" for %s", $id, $date)); 303abb0f93cSkardel} 304abb0f93cSkardel 305abb0f93cSkardelsub clear_timeout 306abb0f93cSkardel{ 307abb0f93cSkardel local($id) = @_; 308abb0f93cSkardel delete $TIMEOUTS{$id}; 309abb0f93cSkardel delete $TIMEOUT_PROCS{$id}; 310abb0f93cSkardel @TIMEOUTS = sort timeouts keys(%TIMEOUTS); 311abb0f93cSkardel &debug("Clear timeout \"$id\""); 312abb0f93cSkardel} 313abb0f93cSkardel 314abb0f93cSkardel0 && &refresh; 315abb0f93cSkardelsub refresh 316abb0f93cSkardel{ 317abb0f93cSkardel local($addr) = @_[$[]; 318abb0f93cSkardel $addr = pack("H*",$addr); 319abb0f93cSkardel &debug(sprintf("Refreshing trap for %s", &hostname($addr))); 320abb0f93cSkardel push(@Requests,pack("a4SC",$addr,0,6)); 321abb0f93cSkardel} 322abb0f93cSkardel 323abb0f93cSkardel0 && &retry; 324abb0f93cSkardelsub retry 325abb0f93cSkardel{ 326abb0f93cSkardel local($tag) = @_; 327abb0f93cSkardel $tag = pack("H*",$tag); 328abb0f93cSkardel $RETRY{$tag} = 0 if (!defined($RETRY{$tag})); 329abb0f93cSkardel 330abb0f93cSkardel if (++$RETRY{$tag} > $MAX_TRY) 331abb0f93cSkardel { 332abb0f93cSkardel &debug(sprintf("Retry failed: %s assoc %5d op %d", 333abb0f93cSkardel &hostname(substr($tag,$[,4)), 334abb0f93cSkardel unpack("x4SC",$tag))); 335abb0f93cSkardel return; 336abb0f93cSkardel } 337abb0f93cSkardel &debug(sprintf("Retrying: %s assoc %5d op %d", 338abb0f93cSkardel &hostname(substr($tag,$[,4)), 339abb0f93cSkardel unpack("x4SC",$tag))); 340abb0f93cSkardel push(@Requests,$tag); 341abb0f93cSkardel} 342abb0f93cSkardel 343abb0f93cSkardelsub process_response 344abb0f93cSkardel{ 345abb0f93cSkardel local($from,$ret,$data,$status,$associd,$op,$seq,$auth_keyid) = @_; 346abb0f93cSkardel 347abb0f93cSkardel $msg=""; 348abb0f93cSkardel if ($op == 7) # trap response 349abb0f93cSkardel { 350abb0f93cSkardel $msg .= sprintf("%40s trap#%-5d", 351abb0f93cSkardel &hostname($from),$seq); 352abb0f93cSkardel &debug (sprintf("\nTrap %d associd %d:\n%s\n===============\n",$seq,$associd,$data)); 353abb0f93cSkardel if ($associd == 0) # system event 354abb0f93cSkardel { 355abb0f93cSkardel $msg .= " SYSTEM "; 356abb0f93cSkardel $evnt = &ntp'SystemEvent($status); #'; 357abb0f93cSkardel $msg .= "$evnt "; 358abb0f93cSkardel ;# for special cases add additional info 359abb0f93cSkardel ($stratum) = ($data =~ /stratum=(\d+)/); 360abb0f93cSkardel ($refid) = ($data =~ /refid=([\w\.]+)/); 361abb0f93cSkardel $msg .= "stratum=$stratum refid=$refid"; 362abb0f93cSkardel if ($refid =~ /\[?(\d+)\.(\d+)\.(\d+)\.(\d+)/) 363abb0f93cSkardel { 364abb0f93cSkardel local($x) = (gethostbyaddr(pack("C4",$1,$2,$3,$4),&AF_INET)); 365abb0f93cSkardel $msg .= " " . $x if defined($x) 366abb0f93cSkardel } 367abb0f93cSkardel if ($evnt eq "event_sync_chg") 368abb0f93cSkardel { 369abb0f93cSkardel $msg .= sprintf("%s %s ", 370abb0f93cSkardel &ntp'LI($status), #', 371abb0f93cSkardel &ntp'ClockSource($status) #' 372abb0f93cSkardel ); 373abb0f93cSkardel } 374abb0f93cSkardel elsif ($evnt eq "event_sync/strat_chg") 375abb0f93cSkardel { 376abb0f93cSkardel ($peer) = ($data =~ /peer=([0-9]+)/); 377abb0f93cSkardel $msg .= " peer=$peer"; 378abb0f93cSkardel } 379abb0f93cSkardel elsif ($evnt eq "event_clock_excptn") 380abb0f93cSkardel { 381abb0f93cSkardel if (($device) = ($data =~ /device=\"([^\"]+)\"/)) 382abb0f93cSkardel { 383abb0f93cSkardel ($cstatus) = ($data =~ /refclockstatus=0?x?([\da-fA-F]+)/); 384abb0f93cSkardel $Cstatus = hex($cstatus); 385abb0f93cSkardel $msg .= sprintf("- %-32s",&ntp'clock_status($Cstatus)); #'); 386abb0f93cSkardel ($timecode) = ($data =~ /timecode=\"([^\"]+)\"/); 387abb0f93cSkardel $msg .= " \"$device\" \"$timecode\""; 388abb0f93cSkardel } 389abb0f93cSkardel else 390abb0f93cSkardel { 391abb0f93cSkardel push(@Requests,pack("a4SC",$from, $associd, 4)); 392abb0f93cSkardel } 393abb0f93cSkardel } 394abb0f93cSkardel } 395abb0f93cSkardel else # peer event 396abb0f93cSkardel { 397abb0f93cSkardel $msg .= sprintf("peer %5d ",$associd); 398abb0f93cSkardel ($srcadr) = ($data =~ /srcadr=\[?([\d\.]+)/); 399abb0f93cSkardel $msg .= sprintf("%-18s %40s ", "[$srcadr]", 400abb0f93cSkardel &hostname(pack("C4",split(/\./,$srcadr)))); 401abb0f93cSkardel $evnt = &ntp'PeerEvent($status); #'; 402abb0f93cSkardel $msg .= "$evnt "; 403abb0f93cSkardel ;# for special cases include additional info 404abb0f93cSkardel if ($evnt eq "event_clock_excptn") 405abb0f93cSkardel { 406abb0f93cSkardel if (($device) = ($data =~ /device=\"([^\"]+)\"/)) 407abb0f93cSkardel { 408abb0f93cSkardel ;#&debug("----\n$data\n====\n"); 409abb0f93cSkardel ($cstatus) = ($data =~ /refclockstatus=0?x?([\da-fA-F]+)/); 410abb0f93cSkardel $Cstatus = hex($cstatus); 411abb0f93cSkardel $msg .= sprintf("- %-32s",&ntp'clock_status($Cstatus)); #'); 412abb0f93cSkardel ($timecode) = ($data =~ /timecode=\"([^\"]+)\"/); 413abb0f93cSkardel $msg .= " \"$device\" \"$timecode\""; 414abb0f93cSkardel } 415abb0f93cSkardel else 416abb0f93cSkardel { 417abb0f93cSkardel ;# no clockvars included - post a cv request 418abb0f93cSkardel push(@Requests,pack("a4SC",$from, $associd, 4)); 419abb0f93cSkardel } 420abb0f93cSkardel } 421abb0f93cSkardel elsif ($evnt eq "event_stratum_chg") 422abb0f93cSkardel { 423abb0f93cSkardel ($stratum) = ($data =~ /stratum=(\d+)/); 424abb0f93cSkardel $msg .= "new stratum $stratum"; 425abb0f93cSkardel } 426abb0f93cSkardel } 427abb0f93cSkardel } 428abb0f93cSkardel elsif ($op == 6) # set trap resonse 429abb0f93cSkardel { 430abb0f93cSkardel &debug("Set trap ok from ",&hostname($from)); 431abb0f93cSkardel &set_timeout("refresh-".unpack("H*",$from),time+$REFRESH_TIME, 432abb0f93cSkardel sprintf("&refresh(\"%s\");",unpack("H*",$from))); 433abb0f93cSkardel return; 434abb0f93cSkardel } 435abb0f93cSkardel elsif ($op == 4) # read clock variables response 436abb0f93cSkardel { 437abb0f93cSkardel ;# status of clock 438abb0f93cSkardel $msg .= sprintf(" %40s ", &hostname($from)); 439abb0f93cSkardel if ($associd == 0) 440abb0f93cSkardel { 441abb0f93cSkardel $msg .= "system clock status: "; 442abb0f93cSkardel } 443abb0f93cSkardel else 444abb0f93cSkardel { 445abb0f93cSkardel $msg .= sprintf("peer %5d clock",$associd); 446abb0f93cSkardel } 447abb0f93cSkardel $msg .= sprintf("%-32s",&ntp'clock_status($status)); #'); 448abb0f93cSkardel ($device) = ($data =~ /device=\"([^\"]+)\"/); 449abb0f93cSkardel ($timecode) = ($data =~ /timecode=\"([^\"]+)\"/); 450abb0f93cSkardel $msg .= " \"$device\" \"$timecode\""; 451abb0f93cSkardel } 452abb0f93cSkardel elsif ($op == 31) # unset trap response (UNOFFICIAL op) 453abb0f93cSkardel { 454abb0f93cSkardel ;# clear timeout 455abb0f93cSkardel &debug("Clear Trap ok from ",&hostname($from)); 456abb0f93cSkardel &clear_timeout("refresh-".unpack("H*",$from)); 457abb0f93cSkardel return; 458abb0f93cSkardel } 459abb0f93cSkardel else # unexpected response 460abb0f93cSkardel { 461abb0f93cSkardel $msg .= "unexpected response to op $op assoc=$associd"; 462abb0f93cSkardel $msg .= sprintf(" status=%04x",$status); 463abb0f93cSkardel } 464abb0f93cSkardel &log($msg); 465abb0f93cSkardel} 466