1 #include <sys/types.h>
2 #include <sys/time.h>
3 #include <sys/param.h>
4 #include <sys/socket.h>
5 #include <netinet/in.h>
6 #include "strerr.h"
7 #include "ip.h"
8 #include "str.h"
9 #include "byte.h"
10 #include "substdio.h"
11 #include "readwrite.h"
12 #include "select.h"
13 #include "taia.h"
14 
15 char outbuf[16];
16 substdio ssout = SUBSTDIO_FDBUF(write,1,outbuf,sizeof outbuf);
17 
18 #define FATAL "taiclock: fatal: "
19 #define WARNING "taiclock: warning: "
20 
die_usage()21 void die_usage()
22 {
23   strerr_die1x(100,"taiclock: usage: taiclock ip.ad.dr.ess");
24 }
25 
26 char *host;
27 struct ip_address ipremote;
28 struct sockaddr_in sa;
29 int s;
30 
31 char initdeltaoffset[] = {0,0,0,0,0,2,163,0,0,0,0,0,0,0,0,0};
32 char initdeltamin[] = {0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0};
33 char initdeltamax[] = {0,0,0,0,0,5,70,0,0,0,0,0,0,0,0,0};
34 char initerrmin[] = {255,255,255,255,255,255,255,254,0,0,0,0,0,0,0,0};
35 char initerrmax[] = {0,0,0,0,0,0,0,2,0,0,0,0,0,0,0,0};
36 struct taia deltaoffset;
37 struct taia deltamin;
38 struct taia deltamax;
39 struct taia errmin;
40 struct taia errmax;
41 
42 struct taia ta0;
43 struct taia ta1;
44 
45 unsigned char query[32];
46 unsigned char response[32];
47 struct taia taremote;
48 
49 struct taia temp1;
50 struct taia temp2;
51 
52 unsigned char adj[16];
53 
main(argc,argv)54 void main(argc,argv)
55 int argc;
56 char **argv;
57 {
58   struct timeval tvselect;
59   fd_set rfds;
60   char *x;
61   unsigned long u;
62   int r;
63   int loop;
64 
65   taia_unpack(initdeltamin,&deltamin);
66   taia_unpack(initdeltamax,&deltamax);
67   taia_unpack(initdeltaoffset,&deltaoffset);
68   taia_unpack(initerrmin,&errmin);
69   taia_unpack(initerrmax,&errmax);
70 
71   host = argv[1];
72   if (!host) die_usage();
73   if (!str_diff(host,"0")) host = "127.0.0.1";
74   if (host[ip_scan(host,&ipremote)]) die_usage();
75 
76   s = socket(AF_INET,SOCK_DGRAM,0);
77   if (s == -1)
78     strerr_die2sys(111,FATAL,"unable to create socket: ");
79 
80   byte_zero(&sa,sizeof(sa));
81   byte_copy(&sa.sin_addr,4,&ipremote);
82   x = (char *) &sa.sin_port;
83   x[0] = 15;
84   x[1] = 174;
85   sa.sin_family = AF_INET;
86 
87   for (loop = 0;loop < 10;++loop) {
88     byte_zero(query,sizeof query);
89     query[0] = 'c';
90     query[1] = 't';
91     query[2] = 'a';
92     query[3] = 'i';
93 
94     /* XXX: cookie-building time */
95     taia_now(&ta0);
96     taia_pack(query + 16,&ta0);
97     u = getpid();
98     query[30] = u; u >>= 8;
99     query[31] = u;
100 
101     taia_now(&ta0);
102     if (sendto(s,query,sizeof query,0,(struct sockaddr *) &sa,sizeof sa) == -1)
103       strerr_die2sys(111,FATAL,"unable to send request: ");
104     FD_ZERO(&rfds);
105     FD_SET(s,&rfds);
106     tvselect.tv_sec = 1;
107     tvselect.tv_usec = 0;
108     if (select(s + 1,&rfds,(fd_set *) 0,(fd_set *) 0,&tvselect) != 1) {
109       strerr_warn2(WARNING,"unable to read clock: timed out",0);
110       continue;
111     }
112     r = recv(s,response,sizeof response,0);
113     if (r == -1) {
114       strerr_warn2(WARNING,"unable to read clock: ",&strerr_sys);
115       continue;
116     }
117     taia_now(&ta1);
118     if (   (r != sizeof response)
119 	|| (response[0] != 's')
120 	|| byte_diff(query + 1,3,response + 1)
121 	|| byte_diff(query + 20,12,response + 20)
122        ) {
123       strerr_warn2(WARNING,"unable to read clock: bad response format",0);
124       continue;
125     }
126 
127     taia_unpack(response + 4,&taremote);
128     taia_add(&taremote,&taremote,&deltaoffset);
129 
130     taia_add(&temp1,&deltamax,&ta0);
131     taia_add(&temp2,&deltamin,&ta0);
132     if (taia_less(&taremote,&temp1) && !taia_less(&taremote,&temp2)) {
133       taia_sub(&temp1,&taremote,&ta0);
134       deltamax = temp1;
135     }
136     taia_add(&temp1,&deltamax,&ta1);
137     taia_add(&temp2,&deltamin,&ta1);
138     if (taia_less(&temp2,&taremote) && !taia_less(&temp1,&taremote)) {
139       taia_sub(&temp2,&taremote,&ta1);
140       deltamin = temp2;
141     }
142   }
143 
144   taia_sub(&temp1,&deltamax,&deltamin);
145   if (taia_less(&errmax,&temp1) && taia_less(&temp1,&errmin))
146     strerr_die2x(111,FATAL,"time uncertainty too large");
147 
148   taia_add(&temp1,&deltamax,&deltamin);
149   taia_half(&temp1,&temp1);
150   taia_sub(&temp1,&temp1,&deltaoffset);
151 
152   taia_pack(adj,&temp1);
153 
154   if (substdio_putflush(&ssout,adj,sizeof adj) == -1)
155     strerr_die2sys(111,FATAL,"unable to write output: ");
156   _exit(0);
157 }
158