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