1224ba2bdSOllivier Robert#!/usr/bin/perl -w 2c0b746e5SOllivier Robert;# 3c0b746e5SOllivier Robert;# ntp.pl,v 3.1 1993/07/06 01:09:09 jbj Exp 4c0b746e5SOllivier Robert;# 5c0b746e5SOllivier Robert;# process loop filter statistics file and either 6c0b746e5SOllivier Robert;# - show statistics periodically using gnuplot 7c0b746e5SOllivier Robert;# - or print a single plot 8c0b746e5SOllivier Robert;# 9c0b746e5SOllivier Robert;# Copyright (c) 1992 10c0b746e5SOllivier Robert;# Rainer Pruy Friedrich-Alexander Universitaet Erlangen-Nuernberg 11c0b746e5SOllivier Robert;# 12c0b746e5SOllivier Robert;# 13c0b746e5SOllivier Robert;############################################################# 14c0b746e5SOllivier Robert 15c0b746e5SOllivier Robertpackage ntp; 16c0b746e5SOllivier Robert 17c0b746e5SOllivier Robert$NTP_version = 2; 18c0b746e5SOllivier Robert$ctrl_mode=6; 19c0b746e5SOllivier Robert 20c0b746e5SOllivier Robert$byte1 = (($NTP_version & 0x7)<< 3) & 0x34 | ($ctrl_mode & 0x7); 21c0b746e5SOllivier Robert$MAX_DATA = 468; 22c0b746e5SOllivier Robert 23c0b746e5SOllivier Robert$sequence = 0; # initial sequence number incred before used 24c0b746e5SOllivier Robert$pad=4; 25c0b746e5SOllivier Robert$do_auth=0; # no possibility today 26c0b746e5SOllivier Robert$keyid=0; 27c0b746e5SOllivier Robert;#list if known keys (passwords) 28c0b746e5SOllivier Robert%KEYS = ( 0, "\200\200\200\200\200\200\200\200", 29c0b746e5SOllivier Robert ); 30c0b746e5SOllivier Robert 31c0b746e5SOllivier Robert;#----------------------------------------------------------------------------- 32c0b746e5SOllivier Robert;# access routines for ntp control packet 33c0b746e5SOllivier Robert ;# NTP control message format 34c0b746e5SOllivier Robert ;# C LI|VN|MODE LI 2bit=00 VN 3bit=2(3) MODE 3bit=6 : $byte1 35c0b746e5SOllivier Robert ;# C R|E|M|Op R response E error M more Op opcode 36c0b746e5SOllivier Robert ;# n sequence 37c0b746e5SOllivier Robert ;# n status 38c0b746e5SOllivier Robert ;# n associd 39c0b746e5SOllivier Robert ;# n offset 40c0b746e5SOllivier Robert ;# n count 41c0b746e5SOllivier Robert ;# a+ data (+ padding) 42c0b746e5SOllivier Robert ;# optional authentication data 43c0b746e5SOllivier Robert ;# N key 44c0b746e5SOllivier Robert ;# N2 checksum 45c0b746e5SOllivier Robert 46224ba2bdSOllivier Robert;# first byte of packet 47c0b746e5SOllivier Robertsub pkt_LI { return ($_[$[] >> 6) & 0x3; } 48c0b746e5SOllivier Robertsub pkt_VN { return ($_[$[] >> 3) & 0x7; } 49c0b746e5SOllivier Robertsub pkt_MODE { return ($_[$[] ) & 0x7; } 50c0b746e5SOllivier Robert 51c0b746e5SOllivier Robert;# second byte of packet 52c0b746e5SOllivier Robertsub pkt_R { return ($_[$[] & 0x80) == 0x80; } 53c0b746e5SOllivier Robertsub pkt_E { return ($_[$[] & 0x40) == 0x40; } 54c0b746e5SOllivier Robertsub pkt_M { return ($_[$[] & 0x20) == 0x20; } 55c0b746e5SOllivier Robertsub pkt_OP { return $_[$[] & 0x1f; } 56c0b746e5SOllivier Robert 57c0b746e5SOllivier Robert;#----------------------------------------------------------------------------- 58c0b746e5SOllivier Robert 59c0b746e5SOllivier Robertsub setkey 60c0b746e5SOllivier Robert{ 61c0b746e5SOllivier Robert local($id,$key) = @_; 62c0b746e5SOllivier Robert 63c0b746e5SOllivier Robert $KEYS{$id} = $key if (defined($key)); 64c0b746e5SOllivier Robert if (! defined($KEYS{$id})) 65c0b746e5SOllivier Robert { 66c0b746e5SOllivier Robert warn "Key $id not yet specified - key not changed\n"; 67c0b746e5SOllivier Robert return undef; 68c0b746e5SOllivier Robert } 69c0b746e5SOllivier Robert return ($keyid,$keyid = $id)[$[]; 70c0b746e5SOllivier Robert} 71c0b746e5SOllivier Robert 72c0b746e5SOllivier Robert;#----------------------------------------------------------------------------- 73c0b746e5SOllivier Robertsub numerical { $a <=> $b; } 74c0b746e5SOllivier Robert 75c0b746e5SOllivier Robert;#----------------------------------------------------------------------------- 76c0b746e5SOllivier Robert 77c0b746e5SOllivier Robertsub send #' 78c0b746e5SOllivier Robert{ 79c0b746e5SOllivier Robert local($fh,$opcode, $associd, $data,$address) = @_; 80c0b746e5SOllivier Robert $fh = caller(0)."'$fh"; 81c0b746e5SOllivier Robert 82c0b746e5SOllivier Robert local($junksize,$junk,$packet,$offset,$ret); 83c0b746e5SOllivier Robert $offset = 0; 84c0b746e5SOllivier Robert 85c0b746e5SOllivier Robert $sequence++; 86c0b746e5SOllivier Robert while(1) 87c0b746e5SOllivier Robert { 88c0b746e5SOllivier Robert $junksize = length($data); 89c0b746e5SOllivier Robert $junksize = $MAX_DATA if $junksize > $MAX_DATA; 90c0b746e5SOllivier Robert 91c0b746e5SOllivier Robert ($junk,$data) = $data =~ /^(.{$junksize})(.*)$/; 92c0b746e5SOllivier Robert $packet 93c0b746e5SOllivier Robert = pack("C2n5a".(($junk eq "") ? 0 : &pad($junksize+12,$pad)-12), 94c0b746e5SOllivier Robert $byte1, 95c0b746e5SOllivier Robert ($opcode & 0x1f) | ($data ? 0x20 : 0), 96c0b746e5SOllivier Robert $sequence, 97c0b746e5SOllivier Robert 0, $associd, 98c0b746e5SOllivier Robert $offset, $junksize, $junk); 99c0b746e5SOllivier Robert if ($do_auth) 100c0b746e5SOllivier Robert { 101c0b746e5SOllivier Robert ;# not yet 102c0b746e5SOllivier Robert } 103c0b746e5SOllivier Robert $offset += $junksize; 104c0b746e5SOllivier Robert 105c0b746e5SOllivier Robert if (defined($address)) 106c0b746e5SOllivier Robert { 107c0b746e5SOllivier Robert $ret = send($fh, $packet, 0, $address); 108c0b746e5SOllivier Robert } 109c0b746e5SOllivier Robert else 110c0b746e5SOllivier Robert { 111c0b746e5SOllivier Robert $ret = send($fh, $packet, 0); 112c0b746e5SOllivier Robert } 113c0b746e5SOllivier Robert 114c0b746e5SOllivier Robert if (! defined($ret)) 115c0b746e5SOllivier Robert { 116c0b746e5SOllivier Robert warn "send failed: $!\n"; 117c0b746e5SOllivier Robert return undef; 118c0b746e5SOllivier Robert } 119c0b746e5SOllivier Robert elsif ($ret != length($packet)) 120c0b746e5SOllivier Robert { 121c0b746e5SOllivier Robert warn "send failed: sent only $ret from ".length($packet). "bytes\n"; 122c0b746e5SOllivier Robert return undef; 123c0b746e5SOllivier Robert } 124c0b746e5SOllivier Robert return $sequence unless $data; 125c0b746e5SOllivier Robert } 126c0b746e5SOllivier Robert} 127c0b746e5SOllivier Robert 128c0b746e5SOllivier Robert;#----------------------------------------------------------------------------- 129c0b746e5SOllivier Robert;# status interpretation 130c0b746e5SOllivier Robert;# 131c0b746e5SOllivier Robertsub getval 132c0b746e5SOllivier Robert{ 133c0b746e5SOllivier Robert local($val,*list) = @_; 134c0b746e5SOllivier Robert 135c0b746e5SOllivier Robert return $list{$val} if defined($list{$val}); 136c0b746e5SOllivier Robert return sprintf("%s#%d",$list{"-"},$val) if defined($list{"-"}); 137c0b746e5SOllivier Robert return "unknown-$val"; 138c0b746e5SOllivier Robert} 139c0b746e5SOllivier Robert 140c0b746e5SOllivier Robert;#--------------------------------- 141c0b746e5SOllivier Robert;# system status 142c0b746e5SOllivier Robert;# 143c0b746e5SOllivier Robert;# format: |LI|CS|SECnt|SECode| LI=2bit CS=6bit SECnt=4bit SECode=4bit 144c0b746e5SOllivier Robertsub ssw_LI { return ($_[$[] >> 14) & 0x3; } 145c0b746e5SOllivier Robertsub ssw_CS { return ($_[$[] >> 8) & 0x3f; } 146c0b746e5SOllivier Robertsub ssw_SECnt { return ($_[$[] >> 4) & 0xf; } 147c0b746e5SOllivier Robertsub ssw_SECode { return $_[$[] & 0xf; } 148c0b746e5SOllivier Robert 149c0b746e5SOllivier Robert%LI = ( 0, "leap_none", 1, "leap_add_sec", 2, "leap_del_sec", 3, "sync_alarm", "-", "leap"); 150c0b746e5SOllivier Robert%ClockSource = (0, "sync_unspec", 151*2b15cb3dSCy Schubert 1, "sync_pps", 152*2b15cb3dSCy Schubert 2, "sync_lf_clock", 153c0b746e5SOllivier Robert 3, "sync_hf_clock", 154*2b15cb3dSCy Schubert 4, "sync_uhf_clock", 155*2b15cb3dSCy Schubert 5, "sync_local_proto", 156*2b15cb3dSCy Schubert 6, "sync_ntp", 157*2b15cb3dSCy Schubert 7, "sync_udp/time", 158*2b15cb3dSCy Schubert 8, "sync_wristwatch", 159*2b15cb3dSCy Schubert 9, "sync_telephone", 160c0b746e5SOllivier Robert "-", "ClockSource", 161c0b746e5SOllivier Robert ); 162c0b746e5SOllivier Robert 163c0b746e5SOllivier Robert%SystemEvent = (0, "event_unspec", 164*2b15cb3dSCy Schubert 1, "event_freq_not_set", 165*2b15cb3dSCy Schubert 2, "event_freq_set", 166*2b15cb3dSCy Schubert 3, "event_spike_detect", 167*2b15cb3dSCy Schubert 4, "event_freq_mode", 168*2b15cb3dSCy Schubert 5, "event_clock_sync", 169*2b15cb3dSCy Schubert 6, "event_restart", 170*2b15cb3dSCy Schubert 7, "event_panic_stop", 171*2b15cb3dSCy Schubert 8, "event_no_sys_peer", 172*2b15cb3dSCy Schubert 9, "event_leap_armed", 173*2b15cb3dSCy Schubert 10, "event_leap_disarmed", 174*2b15cb3dSCy Schubert 11, "event_leap_event", 175*2b15cb3dSCy Schubert 12, "event_clock_step", 176*2b15cb3dSCy Schubert 13, "event_kern", 177*2b15cb3dSCy Schubert 14, "event_loaded_leaps", 178*2b15cb3dSCy Schubert 15, "event_stale_leaps", 179c0b746e5SOllivier Robert "-", "event", 180c0b746e5SOllivier Robert ); 181c0b746e5SOllivier Robertsub LI 182c0b746e5SOllivier Robert{ 183c0b746e5SOllivier Robert &getval(&ssw_LI($_[$[]),*LI); 184c0b746e5SOllivier Robert} 185c0b746e5SOllivier Robertsub ClockSource 186c0b746e5SOllivier Robert{ 187c0b746e5SOllivier Robert &getval(&ssw_CS($_[$[]),*ClockSource); 188c0b746e5SOllivier Robert} 189c0b746e5SOllivier Robert 190c0b746e5SOllivier Robertsub SystemEvent 191c0b746e5SOllivier Robert{ 192c0b746e5SOllivier Robert &getval(&ssw_SECode($_[$[]),*SystemEvent); 193c0b746e5SOllivier Robert} 194c0b746e5SOllivier Robert 195c0b746e5SOllivier Robertsub system_status 196c0b746e5SOllivier Robert{ 197c0b746e5SOllivier Robert return sprintf("%s, %s, %d event%s, %s", &LI($_[$[]), &ClockSource($_[$[]), 198c0b746e5SOllivier Robert &ssw_SECnt($_[$[]), ((&ssw_SECnt($_[$[])==1) ? "" : "s"), 199c0b746e5SOllivier Robert &SystemEvent($_[$[])); 200c0b746e5SOllivier Robert} 201c0b746e5SOllivier Robert;#--------------------------------- 202c0b746e5SOllivier Robert;# peer status 203c0b746e5SOllivier Robert;# 204c0b746e5SOllivier Robert;# format: |PStat|PSel|PCnt|PCode| Pstat=6bit PSel=2bit PCnt=4bit PCode=4bit 205c0b746e5SOllivier Robertsub psw_PStat_config { return ($_[$[] & 0x8000) == 0x8000; } 206c0b746e5SOllivier Robertsub psw_PStat_authenable { return ($_[$[] & 0x4000) == 0x4000; } 207c0b746e5SOllivier Robertsub psw_PStat_authentic { return ($_[$[] & 0x2000) == 0x2000; } 208c0b746e5SOllivier Robertsub psw_PStat_reach { return ($_[$[] & 0x1000) == 0x1000; } 209*2b15cb3dSCy Schubertsub psw_PStat_bcast { return ($_[$[] & 0x0800) == 0x0800; } 210c0b746e5SOllivier Robertsub psw_PStat { return ($_[$[] >> 10) & 0x3f; } 211c0b746e5SOllivier Robertsub psw_PSel { return ($_[$[] >> 8) & 0x3; } 212c0b746e5SOllivier Robertsub psw_PCnt { return ($_[$[] >> 4) & 0xf; } 213c0b746e5SOllivier Robertsub psw_PCode { return $_[$[] & 0xf; } 214c0b746e5SOllivier Robert 215c0b746e5SOllivier Robert%PeerSelection = (0, "sel_reject", 216*2b15cb3dSCy Schubert 1, "sel_falsetick", 217*2b15cb3dSCy Schubert 2, "sel_excess", 218*2b15cb3dSCy Schubert 3, "sel_outlier", 219*2b15cb3dSCy Schubert 4, "sel_candidate", 220*2b15cb3dSCy Schubert 5, "sel_backup", 221*2b15cb3dSCy Schubert 6, "sel_sys.peer", 222*2b15cb3dSCy Schubert 6, "sel_pps.peer", 223c0b746e5SOllivier Robert "-", "PeerSel", 224c0b746e5SOllivier Robert ); 225c0b746e5SOllivier Robert%PeerEvent = (0, "event_unspec", 226*2b15cb3dSCy Schubert 1, "event_mobilize", 227*2b15cb3dSCy Schubert 2, "event_demobilize", 228c0b746e5SOllivier Robert 3, "event_unreach", 229c0b746e5SOllivier Robert 4, "event_reach", 230*2b15cb3dSCy Schubert 5, "event_restart", 231*2b15cb3dSCy Schubert 6, "event_no_reply", 232*2b15cb3dSCy Schubert 7, "event_rate_exceed", 233*2b15cb3dSCy Schubert 8, "event_denied", 234*2b15cb3dSCy Schubert 9, "event_leap_armed", 235*2b15cb3dSCy Schubert 10, "event_sys_peer", 236*2b15cb3dSCy Schubert 11, "event_clock_event", 237*2b15cb3dSCy Schubert 12, "event_bad_auth", 238*2b15cb3dSCy Schubert 13, "event_popcorn", 239*2b15cb3dSCy Schubert 14, "event_intlv_mode", 240*2b15cb3dSCy Schubert 15, "event_intlv_err", 241c0b746e5SOllivier Robert "-", "event", 242c0b746e5SOllivier Robert ); 243c0b746e5SOllivier Robert 244c0b746e5SOllivier Robertsub PeerSelection 245c0b746e5SOllivier Robert{ 246c0b746e5SOllivier Robert &getval(&psw_PSel($_[$[]),*PeerSelection); 247c0b746e5SOllivier Robert} 248224ba2bdSOllivier Robert 249c0b746e5SOllivier Robertsub PeerEvent 250c0b746e5SOllivier Robert{ 251c0b746e5SOllivier Robert &getval(&psw_PCode($_[$[]),*PeerEvent); 252c0b746e5SOllivier Robert} 253c0b746e5SOllivier Robert 254c0b746e5SOllivier Robertsub peer_status 255c0b746e5SOllivier Robert{ 256c0b746e5SOllivier Robert local($x) = (""); 257c0b746e5SOllivier Robert $x .= "config," if &psw_PStat_config($_[$[]); 258c0b746e5SOllivier Robert $x .= "authenable," if &psw_PStat_authenable($_[$[]); 259c0b746e5SOllivier Robert $x .= "authentic," if &psw_PStat_authentic($_[$[]); 260c0b746e5SOllivier Robert $x .= "reach," if &psw_PStat_reach($_[$[]); 261*2b15cb3dSCy Schubert $x .= "bcast," if &psw_PStat_bcast($_[$[]); 262c0b746e5SOllivier Robert 263c0b746e5SOllivier Robert $x .= sprintf(" %s, %d event%s, %s", &PeerSelection($_[$[]), 264c0b746e5SOllivier Robert &psw_PCnt($_[$[]), ((&psw_PCnt($_[$[]) == 1) ? "" : "s"), 265c0b746e5SOllivier Robert &PeerEvent($_[$[])); 266c0b746e5SOllivier Robert return $x; 267c0b746e5SOllivier Robert} 268c0b746e5SOllivier Robert 269c0b746e5SOllivier Robert;#--------------------------------- 270c0b746e5SOllivier Robert;# clock status 271c0b746e5SOllivier Robert;# 272c0b746e5SOllivier Robert;# format: |CStat|CEvnt| CStat=8bit CEvnt=8bit 273c0b746e5SOllivier Robertsub csw_CStat { return ($_[$[] >> 8) & 0xff; } 274c0b746e5SOllivier Robertsub csw_CEvnt { return $_[$[] & 0xff; } 275c0b746e5SOllivier Robert 276c0b746e5SOllivier Robert%ClockStatus = (0, "clk_nominal", 277c0b746e5SOllivier Robert 1, "clk_timeout", 278c0b746e5SOllivier Robert 2, "clk_badreply", 279c0b746e5SOllivier Robert 3, "clk_fault", 280*2b15cb3dSCy Schubert 4, "clk_badsig", 281c0b746e5SOllivier Robert 5, "clk_baddate", 282c0b746e5SOllivier Robert 6, "clk_badtime", 283c0b746e5SOllivier Robert "-", "clk", 284c0b746e5SOllivier Robert ); 285c0b746e5SOllivier Robert 286c0b746e5SOllivier Robertsub clock_status 287c0b746e5SOllivier Robert{ 288c0b746e5SOllivier Robert return sprintf("%s, last %s", 289c0b746e5SOllivier Robert &getval(&csw_CStat($_[$[]),*ClockStatus), 290c0b746e5SOllivier Robert &getval(&csw_CEvnt($_[$[]),*ClockStatus)); 291c0b746e5SOllivier Robert} 292c0b746e5SOllivier Robert 293c0b746e5SOllivier Robert;#--------------------------------- 294c0b746e5SOllivier Robert;# error status 295c0b746e5SOllivier Robert;# 296c0b746e5SOllivier Robert;# format: |Err|reserved| Err=8bit 297c0b746e5SOllivier Robert;# 298c0b746e5SOllivier Robertsub esw_Err { return ($_[$[] >> 8) & 0xff; } 299c0b746e5SOllivier Robert 300c0b746e5SOllivier Robert%ErrorStatus = (0, "err_unspec", 301c0b746e5SOllivier Robert 1, "err_auth_fail", 302c0b746e5SOllivier Robert 2, "err_invalid_fmt", 303c0b746e5SOllivier Robert 3, "err_invalid_opcode", 304c0b746e5SOllivier Robert 4, "err_unknown_assoc", 305c0b746e5SOllivier Robert 5, "err_unknown_var", 306c0b746e5SOllivier Robert 6, "err_invalid_value", 307c0b746e5SOllivier Robert 7, "err_adm_prohibit", 308c0b746e5SOllivier Robert ); 309c0b746e5SOllivier Robert 310c0b746e5SOllivier Robertsub error_status 311c0b746e5SOllivier Robert{ 312c0b746e5SOllivier Robert return sprintf("%s", &getval(&esw_Err($_[$[]),*ErrorStatus)); 313c0b746e5SOllivier Robert} 314c0b746e5SOllivier Robert 315c0b746e5SOllivier Robert;#----------------------------------------------------------------------------- 316c0b746e5SOllivier Robert;# 317c0b746e5SOllivier Robert;# cntrl op name translation 318c0b746e5SOllivier Robert 319*2b15cb3dSCy Schubert%CntrlOpName = (0, "reserved", 320*2b15cb3dSCy Schubert 1, "read_status", 321c0b746e5SOllivier Robert 2, "read_variables", 322c0b746e5SOllivier Robert 3, "write_variables", 323c0b746e5SOllivier Robert 4, "read_clock_variables", 324c0b746e5SOllivier Robert 5, "write_clock_variables", 325c0b746e5SOllivier Robert 6, "set_trap", 326c0b746e5SOllivier Robert 7, "trap_response", 327*2b15cb3dSCy Schubert 8, "configure", 328*2b15cb3dSCy Schubert 9, "saveconf", 329*2b15cb3dSCy Schubert 10, "read_mru", 330*2b15cb3dSCy Schubert 11, "read_ordlist", 331*2b15cb3dSCy Schubert 12, "rqst_nonce", 332c0b746e5SOllivier Robert 31, "unset_trap", # !!! unofficial !!! 333c0b746e5SOllivier Robert "-", "cntrlop", 334c0b746e5SOllivier Robert ); 335c0b746e5SOllivier Robert 336c0b746e5SOllivier Robertsub cntrlop_name 337c0b746e5SOllivier Robert{ 338c0b746e5SOllivier Robert return &getval($_[$[],*CntrlOpName); 339c0b746e5SOllivier Robert} 340c0b746e5SOllivier Robert 341c0b746e5SOllivier Robert;#----------------------------------------------------------------------------- 342c0b746e5SOllivier Robert 343c0b746e5SOllivier Robert$STAT_short_pkt = 0; 344c0b746e5SOllivier Robert$STAT_pkt = 0; 345c0b746e5SOllivier Robert 346c0b746e5SOllivier Robert;# process a NTP control message (response) packet 347c0b746e5SOllivier Robert;# returns a list ($ret,$data,$status,$associd,$op,$seq,$auth_keyid) 348c0b746e5SOllivier Robert;# $ret: undef --> not yet complete 349c0b746e5SOllivier Robert;# "" --> complete packet received 350c0b746e5SOllivier Robert;# "ERROR" --> error during receive, bad packet, ... 351c0b746e5SOllivier Robert;# else --> error packet - list may contain useful info 352c0b746e5SOllivier Robert 353c0b746e5SOllivier Robert 354c0b746e5SOllivier Robertsub handle_packet 355c0b746e5SOllivier Robert{ 356c0b746e5SOllivier Robert local($pkt,$from) = @_; # parameters 357c0b746e5SOllivier Robert local($len_pkt) = (length($pkt)); 358c0b746e5SOllivier Robert;# local(*FRAGS,*lastseen); 359c0b746e5SOllivier Robert local($li_vn_mode,$r_e_m_op,$seq,$status,$associd,$offset,$count,$data); 360c0b746e5SOllivier Robert local($autch_keyid,$auth_cksum); 361c0b746e5SOllivier Robert 362c0b746e5SOllivier Robert $STAT_pkt++; 363c0b746e5SOllivier Robert if ($len_pkt < 12) 364c0b746e5SOllivier Robert { 365c0b746e5SOllivier Robert $STAT_short_pkt++; 366c0b746e5SOllivier Robert return ("ERROR","short packet received"); 367c0b746e5SOllivier Robert } 368c0b746e5SOllivier Robert 369c0b746e5SOllivier Robert ;# now break packet apart 370c0b746e5SOllivier Robert ($li_vn_mode,$r_e_m_op,$seq,$status,$associd,$offset,$count,$data) = 371c0b746e5SOllivier Robert unpack("C2n5a".($len_pkt-12),$pkt); 372c0b746e5SOllivier Robert $data=substr($data,$[,$count); 373c0b746e5SOllivier Robert if ((($len_pkt - 12) - &pad($count,4)) >= 12) 374c0b746e5SOllivier Robert { 375c0b746e5SOllivier Robert ;# looks like an authenticator 376c0b746e5SOllivier Robert ($auth_keyid,$auth_cksum) = 377c0b746e5SOllivier Robert unpack("Na8",substr($pkt,$len_pkt-12+$[,12)); 378c0b746e5SOllivier Robert $STAT_auth++; 379c0b746e5SOllivier Robert ;# no checking of auth_cksum (yet ?) 380c0b746e5SOllivier Robert } 381c0b746e5SOllivier Robert 382c0b746e5SOllivier Robert if (&pkt_VN($li_vn_mode) != $NTP_version) 383c0b746e5SOllivier Robert { 384c0b746e5SOllivier Robert $STAT_bad_version++; 385c0b746e5SOllivier Robert return ("ERROR","version ".&pkt_VN($li_vn_mode)."packet ignored"); 386c0b746e5SOllivier Robert } 387c0b746e5SOllivier Robert 388c0b746e5SOllivier Robert if (&pkt_MODE($li_vn_mode) != $ctrl_mode) 389c0b746e5SOllivier Robert { 390c0b746e5SOllivier Robert $STAT_bad_mode++; 391c0b746e5SOllivier Robert return ("ERROR", "mode ".&pkt_MODE($li_vn_mode)." packet ignored"); 392c0b746e5SOllivier Robert } 393c0b746e5SOllivier Robert 394c0b746e5SOllivier Robert ;# handle single fragment fast 395c0b746e5SOllivier Robert if ($offset == 0 && &pkt_M($r_e_m_op) == 0) 396c0b746e5SOllivier Robert { 397c0b746e5SOllivier Robert $STAT_single_frag++; 398c0b746e5SOllivier Robert if (&pkt_E($r_e_m_op)) 399c0b746e5SOllivier Robert { 400c0b746e5SOllivier Robert $STAT_err_pkt++; 401c0b746e5SOllivier Robert return (&error_status($status), 402c0b746e5SOllivier Robert $data,$status,$associd,&pkt_OP($r_e_m_op),$seq, 403c0b746e5SOllivier Robert $auth_keyid); 404c0b746e5SOllivier Robert } 405c0b746e5SOllivier Robert else 406c0b746e5SOllivier Robert { 407c0b746e5SOllivier Robert return ("", 408c0b746e5SOllivier Robert $data,$status,$associd,&pkt_OP($r_e_m_op),$seq, 409c0b746e5SOllivier Robert $auth_keyid); 410c0b746e5SOllivier Robert } 411c0b746e5SOllivier Robert } 412c0b746e5SOllivier Robert else 413c0b746e5SOllivier Robert { 414c0b746e5SOllivier Robert ;# fragment - set up local name space 415c0b746e5SOllivier Robert $id = "$from$seq".&pkt_OP($r_e_m_op); 416c0b746e5SOllivier Robert $ID{$id} = 1; 417c0b746e5SOllivier Robert *FRAGS = "$id FRAGS"; 418c0b746e5SOllivier Robert *lastseen = "$id lastseen"; 419c0b746e5SOllivier Robert 420c0b746e5SOllivier Robert $STAT_frag++; 421c0b746e5SOllivier Robert 422c0b746e5SOllivier Robert $lastseen = 1 if !&pkt_M($r_e_m_op); 423*2b15cb3dSCy Schubert if (!%FRAGS) 424c0b746e5SOllivier Robert { 425224ba2bdSOllivier Robert print((&pkt_M($r_e_m_op) ? " more" : "")."\n"); 426c0b746e5SOllivier Robert $FRAGS{$offset} = $data; 427c0b746e5SOllivier Robert ;# save other info 428c0b746e5SOllivier Robert @FRAGS = ($status,$associd,&pkt_OP($r_e_m_op),$seq,$auth_keyid,$r_e_m_op); 429c0b746e5SOllivier Robert } 430c0b746e5SOllivier Robert else 431c0b746e5SOllivier Robert { 432224ba2bdSOllivier Robert print((&pkt_M($r_e_m_op) ? " more" : "")."\n"); 433c0b746e5SOllivier Robert ;# add frag to previous - combine on the fly 434c0b746e5SOllivier Robert if (defined($FRAGS{$offset})) 435c0b746e5SOllivier Robert { 436c0b746e5SOllivier Robert $STAT_dup_frag++; 437c0b746e5SOllivier Robert return ("ERROR","duplicate fragment at $offset seq=$seq"); 438c0b746e5SOllivier Robert } 439c0b746e5SOllivier Robert 440c0b746e5SOllivier Robert $FRAGS{$offset} = $data; 441c0b746e5SOllivier Robert 442c0b746e5SOllivier Robert undef($loff); 443c0b746e5SOllivier Robert foreach $off (sort numerical keys(%FRAGS)) 444c0b746e5SOllivier Robert { 445c0b746e5SOllivier Robert next unless defined($FRAGS{$off}); 446c0b746e5SOllivier Robert if (defined($loff) && 447c0b746e5SOllivier Robert ($loff + length($FRAGS{$loff})) == $off) 448c0b746e5SOllivier Robert { 449c0b746e5SOllivier Robert $FRAGS{$loff} .= $FRAGS{$off}; 450c0b746e5SOllivier Robert delete $FRAGS{$off}; 451c0b746e5SOllivier Robert last; 452c0b746e5SOllivier Robert } 453c0b746e5SOllivier Robert $loff = $off; 454c0b746e5SOllivier Robert } 455c0b746e5SOllivier Robert 456c0b746e5SOllivier Robert ;# return packet if all frags arrived 457c0b746e5SOllivier Robert ;# at most two frags with possible padding ??? 458c0b746e5SOllivier Robert if ($lastseen && defined($FRAGS{0}) && 459c0b746e5SOllivier Robert (((scalar(@x=sort numerical keys(%FRAGS)) == 2) && 460c0b746e5SOllivier Robert (length($FRAGS{0}) + 8) > $x[$[+1]) || 461c0b746e5SOllivier Robert (scalar(@x=sort numerical keys(%FRAGS)) < 2))) 462c0b746e5SOllivier Robert { 463c0b746e5SOllivier Robert @x=((&pkt_E($r_e_m_op) ? &error_status($status) : ""), 464c0b746e5SOllivier Robert $FRAGS{0},@FRAGS); 465c0b746e5SOllivier Robert &pkt_E($r_e_m_op) ? $STAT_err_frag++ : $STAT_frag_all++; 466c0b746e5SOllivier Robert undef(%FRAGS); 467c0b746e5SOllivier Robert undef(@FRAGS); 468c0b746e5SOllivier Robert undef($lastseen); 469c0b746e5SOllivier Robert delete $ID{$id}; 470c0b746e5SOllivier Robert &main'clear_timeout($id); 471c0b746e5SOllivier Robert return @x; 472c0b746e5SOllivier Robert } 473c0b746e5SOllivier Robert else 474c0b746e5SOllivier Robert { 475c0b746e5SOllivier Robert &main'set_timeout($id,time+$timeout,"&ntp'handle_packet_timeout(\"".unpack("H*",$id)."\");"); #'"; 476c0b746e5SOllivier Robert } 477c0b746e5SOllivier Robert } 478c0b746e5SOllivier Robert return (undef); 479c0b746e5SOllivier Robert } 480c0b746e5SOllivier Robert} 481c0b746e5SOllivier Robert 482c0b746e5SOllivier Robertsub handle_packet_timeout 483c0b746e5SOllivier Robert{ 484c0b746e5SOllivier Robert local($id) = @_; 485c0b746e5SOllivier Robert local($r_e_m_op,*FRAGS,*lastseen,@x) = (@FRAGS[$[+5]); 486c0b746e5SOllivier Robert 487c0b746e5SOllivier Robert *FRAGS = "$id FRAGS"; 488c0b746e5SOllivier Robert *lastseen = "$id lastseen"; 489c0b746e5SOllivier Robert 490c0b746e5SOllivier Robert @x=((&pkt_E($r_e_m_op) ? &error_status($status) : "TIMEOUT"), 491c0b746e5SOllivier Robert $FRAGS{0},@FRAGS[$[ .. $[+4]); 492c0b746e5SOllivier Robert $STAT_frag_timeout++; 493c0b746e5SOllivier Robert undef(%FRAGS); 494c0b746e5SOllivier Robert undef(@FRAGS); 495c0b746e5SOllivier Robert undef($lastseen); 496c0b746e5SOllivier Robert delete $ID{$id}; 497c0b746e5SOllivier Robert return @x; 498c0b746e5SOllivier Robert} 499c0b746e5SOllivier Robert 500c0b746e5SOllivier Robert 501c0b746e5SOllivier Robertsub pad 502c0b746e5SOllivier Robert{ 503c0b746e5SOllivier Robert return $_[$[+1] * int(($_[$[] + $_[$[+1] - 1) / $_[$[+1]); 504c0b746e5SOllivier Robert} 505c0b746e5SOllivier Robert 506c0b746e5SOllivier Robert1; 507