#!/usr/bin/perl use strict; use warnings; use Data::Dumper; use IO::Socket::INET; use Time::HiRes qw( time gettimeofday clock ); use constant MAXBYTES => scalar 1024; use constant ARGUMENTS => scalar 1; # flush after every write $| = 1; my ($received_data,$Peer_Port); #printf "This is the number of arguments: ".ARGUMENTS."\n"; my $IP = $ARGV[0] or die "Please provide IP of Server $!\n"; if (@ARGV > ARGUMENTS) { print "\nPlease no more than ".ARGUMENTS." arguments (ARGV[])!\n"; print "\nCorrect Syntax: perl $0 IP (e.g. 127.0.0.1)\n\n"; exit(); } else { #my %response = get_ntp_response(<127.0.0.1>,123); #printf "This is the responce: ".Dumper(\%response)."\n"; # We call IO::Socket::INET->new() to create the UDP Socket # and bind with the PeerAddr. my $localhost = "127.0.0.2"; my $port = "12345"; my $client_socket = new IO::Socket::INET ( PeerHost => $IP || $localhost, Type => SOCK_DGRAM, PeerPort => $port || "12345", # Default NTP port 123, due to permission denied switch to 12345 Proto => 'udp' ) or die "ERROR in Socket Creation: $!\n"; $Peer_Port = $client_socket->peerport(); # $li = 0; is the client we have no waring for asynchronization my $dec_li = "0"; my $li = sprintf ("%02b",$dec_li); #print "\$dec_li: ".$dec_li."\n"; # $vn = 3; is the version 3 only IPV4 my $dec_vn = "3"; my $vn = sprintf ("%03b",$dec_vn); # $mode = 3; is the client (mode 3) my $dec_mode = "3"; my $mode = sprintf ("%03b",$dec_mode); # $stratum = 0; is the client clock which is unspecified my $dec_stratum = "0"; my $stratum = sprintf ("%08b",$dec_stratum); #print "\$dec_stratum: ".$dec_stratum."\n"; # $poll = 6; is the poll interval between messages 6 = 64 sec my $dec_poll = "6"; my $poll = sprintf ("%08b",$dec_poll); # $precision = 0; is the precission interval undefined local clock pecision my $dec_precision = "0"; my $precision = sprintf ("%08b",$dec_precision); # $root_delay = 0; is the roundtrip delay 32 bit client is 0 my $dec_root_delay = "0"; my $root_delay = sprintf ("%032b",$dec_root_delay); # $root_dispersion = 0; is the nominal error relative to the primary reference my $dec_root_dispersion = "0"; my $root_dispersion = sprintf ("%032b",$dec_root_dispersion); # $reference_identifier = 0; is the nominal error relative to the primary reference my $dec_reference_identifier = "0"; my $reference_identifier = sprintf ("%032b",$dec_reference_identifier); # $epoc_ref = time(); local clock last updated my ($dec_epoc_ref, $usec_ref) = gettimeofday(); my $epoc_ref = sprintf ("%064b",$dec_epoc_ref); # $epoc_send = time(); local clock when packet was send my ($dec_epoc_send, $usec_send) = gettimeofday(); my $epoc_send = sprintf ("%064b",$dec_epoc_send); my $ntp_packet = $li . $vn . $mode . $stratum . $poll . $precision . $root_delay . $root_dispersion . $reference_identifier . $epoc_ref . $epoc_send; my $clock_t0 = clock(); $client_socket->send($ntp_packet) or die "Client send: $!\n"; printf "\nNumber of seconds since Jan 1, 1970 - ".$dec_epoc_send." time of message departure.\n"; #read operation # For verification purposes causing 2 sec delay. sleep(2); $client_socket->recv($received_data,MAXBYTES) or die "Client send: $!\n"; my $clock_t1 = clock(); my ($epoc_receive, $usec_receive) = gettimeofday(); #my $roundtrip_time = $clock_t1 - $clock_t0; printf "Number of seconds since Jan 1, 1970 - ".$epoc_receive." time of message arrival.\n"; if ($received_data eq 'Invalid Request') { printf("Server send: ".$received_data.", please check the message send!\n"); exit(); } else { my $server_li_binary = substr($received_data, 0, 2); my $server_li = oct("0b".$server_li_binary); my $server_vn_binary = substr($received_data, 2, 3); my $server_vn = oct("0b".$server_vn_binary); my $server_mode_binary = substr($received_data, 5, 3); my $server_mode = oct("0b".$server_mode_binary); my $server_stratum_binary = substr($received_data, 8, 8); my $server_stratum = oct("0b".$server_stratum_binary); my $server_poll_interval_binary = substr($received_data, 16, 8); my $server_poll_interval = oct("0b".$server_poll_interval_binary); my $server_precision_binary = substr($received_data, 24, 8); my $server_precision = oct("0b".$server_precision_binary); my $server_root_delay_binary = substr($received_data, 32, 32); my $server_root_delay = oct("0b".$server_root_delay_binary); my $server_root_dispersion_binary = substr($received_data, 64, 32); my $server_root_dispersion = oct("0b".$server_root_dispersion_binary); my $server_root_identifier_binary = substr($received_data, 96, 32); my $server_root_identifier = pack("B32", $server_root_identifier_binary); my $ref_server_epoch_binary = substr($received_data, 128, 64); my $ref_server_epoch = oct("0b".$ref_server_epoch_binary); my $originate_server_epoch_binary = substr($received_data, 192, 64); my $originate_server_epoch = oct("0b".$originate_server_epoch_binary); my $receive_server_epoch_binary = substr($received_data, 256, 64); my $receive_server_epoch = oct("0b".$receive_server_epoch_binary); my $transmit_server_epoch_binary = substr($received_data, 320, 64); my $transmit_server_epoch = oct("0b".$transmit_server_epoch_binary); # RFC2030 reference http://tools.ietf.org/html/rfc2030 print "\n\n Timestamp Name ID When Generated ------------------------------------------------------------ Originate Timestamp T1 time request sent by client Receive Timestamp T2 time request received by server Transmit Timestamp T3 time reply sent by server Destination Timestamp T4 time reply received by client The roundtrip delay d and local clock offset t are defined as d = (T4 - T1) - (T2 - T3) t = ((T2 - T1) + (T3 - T4)) / 2.\n\n"; my $d = (($epoc_receive - $dec_epoc_send) - ($receive_server_epoch - $transmit_server_epoch)); my $t = ((($receive_server_epoch - $dec_epoc_send) + ($transmit_server_epoch - $epoc_receive))/2); printf "Round Trip delay: ".$d."\n"; printf "Clock offset: ".$t."\n"; print "\n Field Name Unicast/Anycast Request \t Reply ----------------------------------------------- LI \t $dec_li \t\t $server_li VN \t $dec_vn \t\t $server_vn Mode \t $dec_mode \t\t $server_mode Stratum \t $dec_stratum \t\t $server_stratum Poll \t $dec_poll \t\t $server_poll_interval Precision \t $dec_precision \t\t $server_precision Root Delay \t $dec_root_delay \t\t $server_root_delay Root Dispersion \t $dec_root_dispersion \t\t $server_root_dispersion Reference Identifier \t $dec_reference_identifier \t\t $server_root_identifier Reference Timestamp \t $dec_epoc_send \t $ref_server_epoch Originate Timestamp \t $dec_epoc_send \t $originate_server_epoch Receive Timestamp \t $epoc_receive \t $receive_server_epoch Transmit Timestamp \t 0 \t\t $transmit_server_epoch\n\n"; } $client_socket->close(); # Close socket() } # End of else condition (ARGV[])