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