#include #include #include #include #include #include /* system data types */ /* #include */ #include /* network */ #include /* get/set precise time */ #include /* internet structures */ #include /* get IP from hostname */ #define IN_T_PORT 37 /* typedef uint32_t in_addr_t; /* some Linux versions need it */ in_addr_t get_ip_by_name(char *hostname) { struct hostent *he; if((he=gethostbyname(hostname))==NULL) { herror(hostname); return -1; } else return *(in_addr_t *)he->h_addr; } void fill_sa_in(struct sockaddr_in *sai, in_addr_t addr,unsigned short port) { sai->sin_family=AF_INET; sai->sin_port=htons(port); sai->sin_addr.s_addr=addr; memset(sai->sin_zero,0,sizeof(sai->sin_zero)); } void show_ip_and_port(struct sockaddr_in *in) { typedef unsigned char byte; char buf[64]; sprintf(buf,"\n\n=== request from %u.%u.%u.%u:%u ===\n", ((byte *)&in->sin_addr.s_addr)[0], ((byte *)&in->sin_addr.s_addr)[1], ((byte *)&in->sin_addr.s_addr)[2], ((byte *)&in->sin_addr.s_addr)[3], ntohs(in->sin_port)); write(1, buf, strlen(buf)); } struct sockaddr_in ts_in,rp_in; char *es; int net_init(char *host, int tl) { in_addr_t ip; int sk; /* ask DNS for the server address */ alarm(tl); ip=get_ip_by_name(host); alarm(0); if((ip)==-1) { es="nslook"; return -1; } /* setup IP address, open socket... */ fill_sa_in(&ts_in,ip,IN_T_PORT); if((sk=socket(AF_INET,SOCK_DGRAM,0))==-1) { es="socket"; return -1; } /* show_ip_and_port(&ts_in); */ return sk; } unsigned long ask_time(int sk, int tl) { socklen_t fl; long nt; alarm(tl); if(sendto(sk, NULL, 0, MSG_DONTROUTE | MSG_DONTWAIT, (struct sockaddr *)&ts_in, sizeof(ts_in))==-1) { es="send"; goto err; } do { fl=sizeof(rp_in); if(recvfrom(sk, &nt, sizeof(nt), 0, (struct sockaddr *)&rp_in, &fl)==-1) { es="recv"; goto err; } } while (memcmp(&rp_in,&ts_in,sizeof(rp_in))!=0); alarm(0); return ntohl(nt)-2208988800UL; err: alarm(0); return 0; } int comp_time(int sk, int tl, double *td0, double *td1) { struct timeval tv0,tv1; long nt; gettimeofday(&tv0,NULL);/* ask time from local host */ nt=ask_time(sk,2); /* ask time from remote server, timeout=2 seconds */ gettimeofday(&tv1,NULL);/* ask time from local host */ if(nt==0) return -1; *td0= tv0.tv_sec-nt+tv0.tv_usec*0.000001; *td1= tv1.tv_sec-nt+tv1.tv_usec*0.000001; return 0; } char usage[]="Usage: %s {-q|-s}[times] host-with-in.timed-service\n" "\t-q means query, -s set time from the server;\n" "\t'times' specifies how many times to repeat.\n" "Example: '%s -q5 my.time.server.net' queries 5 times.\n"; int main(int ac, char **av) { int sk,rep; double td0,td1; /* if no args display usage info */ if(ac!=3 || av[1][0]!='-' || ((sk=av[1][1])!='q' && sk!='s')) { es=strrchr(av[0],'/'); if(es==NULL) es=av[0]; else es++; fprintf(stderr,usage,es,es); return -1; } rep=0; sscanf(av[1]+2,"%u",&rep); /* initialize network, timeout=120 seconds */ sk=net_init(av[2],120); /* get and compare time as many times as requested */ do { comp_time(sk,2,&td0,&td1); printf("local-remote time=%12.6lf/%12.6lf\n",td0,td1); } while(--rep>0); close(sk); return 0; err: fprintf(stderr,"in.timed client: "); perror(es); return -1; }