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