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