📄 sntpdate.c
字号:
/* smtpdate.c * Simple ntpdate * * Copyright 2003 Norimasa Matsumoto <matsu@netfort.gr.jp> * * This program is free software; you can redistribute it and/or modify it * under the terms of the GNU General Public License as published by the * Free Software Foundation. * * This program is distributed in the hope that it will be useful, but * WITHOUT ANY WARRANTY; without even the implied warranty of * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU * General Public License for more details. * */#include <stdio.h>#include <string.h>#include <stdarg.h>#include <unistd.h>#include <stdlib.h>#include <sys/types.h>#include <sys/time.h>#include <sys/socket.h>#include <netinet/in.h>#include <netdb.h>#include <time.h>#include "ntp.h"#define BUFFSIZE 128#define my_abs( x ) ( (x<0)?(-x):(x) )void error( char *format, ... );int ntp_query( char *host, double *offset, double *delay );int ntp_send( int sock, unsigned int ip, int port );int ntp_recv( int sock, unsigned int ip, int port, struct pkt *rcv_pkt, ntp_time *rcv_time );void calc_offset( struct pkt *rcv_pkt, ntp_time *rcv_time, double *offset, double *delay );void getipport( char *arg, unsigned int *ip, int *port );unsigned int getip( char *hostname );int getport( char *service, char *prot );void getsysntptime( ntp_time *ntm );int setsystime( double offset );char *ipstr( char *buff, int len, unsigned int ip );#ifdef DEBUGchar *ntp_time_str( char *buff, int len, ntp_time *tm );void pr_pkt_info( struct pkt *rcv_pkt, ntp_time *rcv_time );int prtime( char *str );int sock_info( struct sockaddr_in *addr );#endif /* DEBUG */intmain( int argc, char *argv[]){ int i, opt_i; double offset, delay, opt_offset, opt_delay; if( argc < 2 ){ error( "usage: sntpdate host[:port] [host[:port] ... ]\n" ); } printf( "delay(sec) offset(sec) server\n" ); opt_i=-1; opt_delay = 0.; opt_offset = 0.; for( i=1; i<argc; i++ ){ ntp_query( argv[i], &offset, &delay ); printf( "%10.6f %10.6f %s\n", delay, offset, argv[i] ); if( (opt_i<0)||( my_abs(delay) < my_abs(opt_delay) )) { opt_i = i; opt_delay = delay; opt_offset = offset; } } if( setsystime( opt_offset ) == 0 ){ printf( "------------------------------------\n" ); printf( "%10.6f %10.6f %s\n", opt_delay, opt_offset, argv[opt_i] ); } return 0;}intntp_query( char *host, double *offset, double *delay ){ int sock; struct pkt rcv_pkt; ntp_time rcv_time; unsigned int ip; int port; getipport( host, &ip, &port ); if( (sock=socket(AF_INET, SOCK_DGRAM, 0))<0){ error( "socket"); } ntp_send( sock, ip, port ); ntp_recv( sock, ip, port, &rcv_pkt, &rcv_time );#ifdef DEBUG pr_pkt_info( &rcv_pkt, &rcv_time );#endif /* DEBUG */ calc_offset( &rcv_pkt, &rcv_time, offset, delay ); close(sock); return 0;}voiderror( char *format, ... ){ va_list arg; int ret; va_start( arg, format ); ret = fprintf( stderr, format, arg ); va_end(arg); exit(1);}intntp_send( int sock, unsigned int ip, int port ){ struct sockaddr_in dst; struct pkt snd_pkt; bzero( &dst, sizeof(dst)); dst.sin_family = AF_INET; dst.sin_addr.s_addr = htonl( ip ); dst.sin_port = htons((unsigned short)port); bzero( &snd_pkt, sizeof(snd_pkt)); snd_pkt.li_vn_mode = (NTP_VN <<3) + NTP_MODE_CLIENT;#ifdef DEBUG prtime( "send(start):" );#endif /* DEBUG */ getsysntptime( &(snd_pkt.xmt) ); sendto( sock, (void *)&snd_pkt, sizeof(snd_pkt), 0, (struct sockaddr *)&dst, sizeof( dst ) );#ifdef DEBUG prtime( "send(end):" );#endif /* DEBUG */ return 0;}intntp_recv( int sock, unsigned int ip, int port, struct pkt *rcv_pkt, ntp_time *rcv_time ){ struct sockaddr_in dst; int dst_len, len, ret; char recv[BUFFSIZE]; fd_set rfds; struct timeval tv; while(1){ dst_len=sizeof(dst); bzero( &dst, dst_len ); FD_ZERO(&rfds); FD_SET( sock, &rfds); tv.tv_sec = NTP_TIMEOUT_SEC; tv.tv_usec = NTP_TIMEOUT_USEC; ret = select( sock+1, &rfds, NULL, NULL, &tv ); getsysntptime( rcv_time );#ifdef DEBUG prtime( "select:" );#endif /* DEBUG */ if( ret ){ len=recvfrom( sock, recv, BUFFSIZE, 0, (struct sockaddr *)&dst, &dst_len );#ifdef DEBUG prtime( "recv:" );#endif /* DEBUG */ if( ntohl(dst.sin_addr.s_addr) != ip ){ continue; } if( ntohs(dst.sin_port) != port ){ continue; } break; }else{ error( "time out\n" ); } } if( len < sizeof(*rcv_pkt) ){ error( "packet size\n" ); } memcpy( rcv_pkt, recv, sizeof(*rcv_pkt) ); if( ntp_vn(rcv_pkt->li_vn_mode) != NTP_VN || ntp_mode(rcv_pkt->li_vn_mode) != NTP_MODE_SERVER ){ error( "illeagal packer\n"); } return 0;}voidcalc_offset( struct pkt *rcv_pkt, ntp_time *rcv_time, double *offset, double *delay ){ double t1,t2,t3,t4; unsigned int sof; sof = min( min( ntohl(rcv_pkt->org.sec), ntohl(rcv_pkt->rec.sec)), min( ntohl(rcv_pkt->xmt.sec), ntohl(rcv_time->sec )) ); t1 = (double)(ntohl(rcv_pkt->org.sec) - sof) +(double)(ntohl(rcv_pkt->org.fsec))/4294967296.; t2 = (double)(ntohl(rcv_pkt->rec.sec) - sof) +(double)(ntohl(rcv_pkt->rec.fsec))/4294967296.; t3 = (double)(ntohl(rcv_pkt->xmt.sec) - sof) +(double)(ntohl(rcv_pkt->xmt.fsec))/4294967296.; t4 = (double)(ntohl(rcv_time->sec) - sof) +(double)(ntohl(rcv_time->fsec))/4294967296.; *offset = ( (t2-t1) + (t3-t4) )/2.; *delay = (t4-t1) -(t2-t3);#ifdef DEBUG printf( "T1: %10.6f\n", t1 ); printf( "T2: %10.6f\n", t2 ); printf( "T3: %10.6f\n", t3 ); printf( "T4: %10.6f\n", t4 ); printf( "delay = ( (T2-T1) + (T3-T4) )/2\n" ); printf( "offset = (T4-T1) - (T2-T3)\n" );#endif /* DEBUG */}voidgetipport( char *arg, unsigned int *ip, int *port ){ char *buff; char *p; buff = malloc( strlen(arg) +2 ); if( buff == NULL ){ error( "malloc: " ); } strcpy( buff, arg ); p = strchr( buff, ':' ); if( p == NULL ){ *ip = getip( buff ); *port = getport( NTP_SERV, "udp" ); }else{ *p++ = '\0'; *ip = getip( buff ); *port = getport( p, "udp" ); } free(buff);}unsigned intgetip( char *hostname ){ struct hostent *host; unsigned int ip; host = gethostbyname( hostname ); if( host == NULL ){ fprintf( stderr, "[%s ]", hostname ); error( "host name error: " ); } ip = ((unsigned int)(0xff & host->h_addr_list[0][0] ) <<24 ) +((unsigned int)(0xff & host->h_addr_list[0][1] ) <<16 ) +((unsigned int)(0xff & host->h_addr_list[0][2] ) <<8 ) +((unsigned int)(0xff & host->h_addr_list[0][3] ) ); return ip;}intgetport( char *service, char *prot ){ struct servent *ent; int port; if( sscanf( service, "%d", &port) < 1 ){ ent = getservbyname( service, prot ); if( ent == NULL ){ error( "service name error: " ); } port = ntohs((unsigned short)(ent->s_port)); } return port;}voidgetsysntptime( ntp_time *ntm ){ struct timeval tv; struct timezone tz; gettimeofday( &tv, &tz ); ntm->sec = htonl( (unsigned int)tv.tv_sec +(unsigned int)(70*365+17)*(24*60*60) ); ntm->fsec = htonl( (unsigned int)( 4294967296. * (double)tv.tv_usec/1000000. +.5) );}intsetsystime( double offset ){ struct timeval tv; struct timezone tz; int offset_s, offset_us; offset_s = (int)offset; if( offset_s < 0 ){ offset_s -= 1; } offset_us = (int)((offset - (double)offset_s)*1000000. +.5); gettimeofday( &tv, &tz ); tv.tv_sec += offset_s; tv.tv_usec += offset_us; if( tv.tv_usec >= 1000000 ){ tv.tv_usec -= 1000000; tv.tv_sec += 1; }else if( tv.tv_usec < 0 ){ tv.tv_usec += 1000000; tv.tv_sec -= 1; } if( settimeofday( &tv, &tz ) == 0 ){ fprintf( stderr, "set time\n" ); return 0; }else{ return -1; }}char *ipstr( char *buff, int len, unsigned int ip ){ snprintf( buff, len, "%d.%d.%d.%d", 0xff&(ip>>24), 0xff&(ip>>16), 0xff&(ip>> 8), 0xff&(ip ) ); return buff;}#ifdef DEBUGchar *ntp_time_str( char *buff, int len, ntp_time *tm ){ time_t ttm; unsigned int fsec; struct tm *ltm; fsec = ntohl(tm->fsec); ttm = ntohl(tm->sec) - (unsigned int)(70*365+17)*(24*60*60); ltm = localtime( &ttm ); snprintf( buff, len, "%d/%2.2d/%2.2d %2.2d:%2.2d:%2.2d.%6.6d", ltm->tm_year+1900, ltm->tm_mon+1, ltm->tm_mday, ltm->tm_hour, ltm->tm_min, ltm->tm_sec, (int)(((double)fsec/4294967296.)*1000000. +.5) ); return buff;}intprtime( char *str ){ ntp_time ntm; char buff[BUFFSIZE]; getsysntptime( &ntm ); printf( "%s %s\n", str, ntp_time_str( buff, BUFFSIZE, &ntm ) ); return 0;}voidpr_pkt_info( struct pkt *rcv_pkt, ntp_time *rcv_time ){ char buff[BUFFSIZE]; printf( "LI: %d\n", ntp_li(rcv_pkt->li_vn_mode) ); printf( "VN: %d\n", ntp_vn(rcv_pkt->li_vn_mode) ); printf( "MODE: %d\n", ntp_mode(rcv_pkt->li_vn_mode) ); printf( "stratum: %u\n", rcv_pkt->stratum ); printf( "ppoll: %u\n", rcv_pkt->ppoll ); printf( "precision: %d\n", rcv_pkt->precision ); printf( "rootdelay: %u\n", ntohl(rcv_pkt->rootdelay) ); printf( "rootdispersion: %u\n", ntohl(rcv_pkt->rootdispersion) ); printf( "refid: %s\n", ipstr( buff, BUFFSIZE, ntohl(rcv_pkt->refid)) ); printf( "reftime: %s\n", ntp_time_str( buff,BUFFSIZE, &(rcv_pkt->reftime) ) ); printf( "T1(org): %s\n", ntp_time_str( buff,BUFFSIZE, &(rcv_pkt->org) ) ); printf( "T2(rec): %s\n", ntp_time_str( buff,BUFFSIZE, &(rcv_pkt->rec) ) ); printf( "T3(xmt): %s\n", ntp_time_str( buff,BUFFSIZE, &(rcv_pkt->xmt) ) ); printf( "T4: %s\n", ntp_time_str( buff,BUFFSIZE, rcv_time ) );}#endif /* DEBUG */
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -