1: #include <config.h>
2:
3: #include "main.h"
4: #include "kod_management.h"
5: #include "networking.h"
6: #include "utilities.h"
7: #include "log.h"
8:
9: int ai_fam_pref = AF_UNSPEC;
10:
11: struct key *keys = NULL;
12:
13: void set_li_vn_mode (struct pkt *spkt, char leap, char version, char mode);
14: int sntp_main (int argc, char **argv);
15: int on_wire (struct addrinfo *host, struct addrinfo *bcastaddr);
16: int set_time (double offset);
17:
18: #define NORMALIZE_TIMEVAL(tv) \
19: do { \
20: while ((tv).tv_usec < 0) { \
21: (tv).tv_usec += 1000000; \
22: (tv).tv_sec--; \
23: } \
24: while ((tv).tv_usec > 999999) { \
25: (tv).tv_usec -= 1000000; \
26: (tv).tv_sec++; \
27: } \
28: } while (0)
29:
30:
31: /*
32: * The actual main function.
33: */
34: int
35: sntp_main (
36: int argc,
37: char **argv
38: )
39: {
40: register int c;
41: struct kod_entry *reason = NULL;
42: int optct;
43: /* boolean, u_int quiets gcc4 signed overflow warning */
44: u_int sync_data_suc;
45: struct addrinfo **bcastaddr = NULL;
46: struct addrinfo **resh = NULL;
47: struct addrinfo *ai;
48: int resc;
49: int kodc;
50: int ow_ret;
51: int bcast = 0;
52: char *hostname;
53:
54: optct = optionProcess(&sntpOptions, argc, argv);
55: argc -= optct;
56: argv += optct;
57:
58: /* Initialize logging system */
59: init_logging();
60: if (HAVE_OPT(LOGFILE))
61: open_logfile(OPT_ARG(LOGFILE));
62:
63: msyslog(LOG_NOTICE, "Started sntp");
64:
65: /* IPv6 available? */
66: if (isc_net_probeipv6() != ISC_R_SUCCESS) {
67: ai_fam_pref = AF_INET;
68: #ifdef DEBUG
69: printf("No ipv6 support available, forcing ipv4\n");
70: #endif
71: } else {
72: /* Check for options -4 and -6 */
73: if (HAVE_OPT(IPV4))
74: ai_fam_pref = AF_INET;
75: else if (HAVE_OPT(IPV6))
76: ai_fam_pref = AF_INET6;
77: }
78:
79: /* Parse config file if declared TODO */
80:
81: /*
82: * If there's a specified KOD file init KOD system. If not use
83: * default file. For embedded systems with no writable
84: * filesystem, -K /dev/null can be used to disable KoD storage.
85: */
86: if (HAVE_OPT(KOD))
87: kod_init_kod_db(OPT_ARG(KOD));
88: else
89: kod_init_kod_db("/var/db/ntp-kod");
90:
91: if (HAVE_OPT(KEYFILE))
92: auth_init(OPT_ARG(KEYFILE), &keys);
93:
94: #ifdef EXERCISE_KOD_DB
95: add_entry("192.168.169.170", "DENY");
96: add_entry("192.168.169.171", "DENY");
97: add_entry("192.168.169.172", "DENY");
98: add_entry("192.168.169.173", "DENY");
99: add_entry("192.168.169.174", "DENY");
100: delete_entry("192.168.169.174", "DENY");
101: delete_entry("192.168.169.172", "DENY");
102: delete_entry("192.168.169.170", "DENY");
103: if ((kodc = search_entry("192.168.169.173", &reason)) == 0)
104: printf("entry for 192.168.169.173 not found but should have been!\n");
105: else
106: free(reason);
107: #endif
108:
109: /* Considering employing a variable that prevents functions of doing anything until
110: * everything is initialized properly
111: */
112: resc = resolve_hosts((const char **)argv, argc, &resh, ai_fam_pref);
113: if (resc < 1) {
114: printf("Unable to resolve hostname(s)\n");
115: return -1;
116: }
117: bcast = ENABLED_OPT(BROADCAST);
118: if (bcast) {
119: const char * myargv[2];
120:
121: myargv[0] = OPT_ARG(BROADCAST);
122: myargv[1] = NULL;
123: bcast = resolve_hosts(myargv, 1, &bcastaddr, ai_fam_pref);
124: }
125:
126: /* Select a certain ntp server according to simple criteria? For now
127: * let's just pay attention to previous KoDs.
128: */
129: sync_data_suc = FALSE;
130: for (c = 0; c < resc && !sync_data_suc; c++) {
131: ai = resh[c];
132: do {
133: hostname = addrinfo_to_str(ai);
134: if ((kodc = search_entry(hostname, &reason)) == 0) {
135: if (is_reachable(ai)) {
136: ow_ret = on_wire(ai, bcast ? bcastaddr[0] : NULL);
137: if (0 == ow_ret)
138: sync_data_suc = TRUE;
139: }
140: } else {
141: printf("%d prior KoD%s for %s, skipping.\n",
142: kodc, (kodc > 1) ? "s" : "", hostname);
143: free(reason);
144: }
145: free(hostname);
146: ai = ai->ai_next;
147: } while (NULL != ai);
148: freeaddrinfo(resh[c]);
149: }
150: free(resh);
151:
152: if (!sync_data_suc)
153: return 1;
154: return 0;
155: }
156:
157: static union {
158: struct pkt pkt;
159: char buf[1500];
160: } rbuf;
161:
162: #define r_pkt rbuf.pkt
163:
164: int
165: generate_pkt (
166: struct pkt *x_pkt,
167: const struct timeval *tv_xmt,
168: int key_id,
169: struct key *pkt_key
170: )
171: {
172: l_fp xmt;
173: int pkt_len = LEN_PKT_NOMAC;
174: memset(x_pkt, 0, sizeof(struct pkt));
175: TVTOTS(tv_xmt, &xmt);
176: HTONL_FP(&xmt, &(x_pkt->xmt));
177: x_pkt->stratum = STRATUM_TO_PKT(STRATUM_UNSPEC);
178: x_pkt->ppoll = 8;
179: /* FIXME! Modus broadcast + adr. check -> bdr. pkt */
180: set_li_vn_mode(x_pkt, LEAP_NOTINSYNC, 4, 3);
181: if (pkt_key != NULL) {
182: int mac_size = 20; /* max room for MAC */
183: x_pkt->exten[0] = htonl(key_id);
184: mac_size = make_mac((char *)x_pkt, pkt_len, mac_size, pkt_key, (char *)&x_pkt->exten[1]);
185: if (mac_size)
186: pkt_len += mac_size + 4;
187: }
188: return pkt_len;
189: }
190:
191: int
192: handle_pkt (
193: int rpktl,
194: struct pkt *rpkt,
195: struct addrinfo *host
196: )
197: {
198: struct timeval tv_dst;
199: int sw_case, digits;
200: char *hostname = NULL, *ref, *ts_str = NULL;
201: double offset, precision, root_dispersion;
202: char addr_buf[INET6_ADDRSTRLEN];
203: char *p_SNTP_PRETEND_TIME;
204: time_t pretend_time;
205:
206: if(rpktl > 0)
207: sw_case = 1;
208: else
209: sw_case = rpktl;
210:
211: switch(sw_case) {
212: case SERVER_UNUSEABLE:
213: return -1;
214: break;
215:
216: case PACKET_UNUSEABLE:
217: break;
218:
219: case SERVER_AUTH_FAIL:
220: break;
221:
222: case KOD_DEMOBILIZE:
223: /* Received a DENY or RESTR KOD packet */
224: hostname = addrinfo_to_str(host);
225: ref = (char *)&rpkt->refid;
226: add_entry(hostname, ref);
227:
228: if (ENABLED_OPT(NORMALVERBOSE))
229: printf("sntp handle_pkt: Received KOD packet with code: %c%c%c%c from %s, demobilizing all connections\n",
230: ref[0], ref[1], ref[2], ref[3],
231: hostname);
232:
233: msyslog(LOG_WARNING, "Received a KOD packet with code %c%c%c%c from %s, demobilizing all connections",
234: ref[0], ref[1], ref[2], ref[3], hostname);
235: break;
236:
237: case KOD_RATE:
238: /* Hmm... probably we should sleep a bit here */
239: break;
240:
241: case 1:
242: if (ENABLED_OPT(NORMALVERBOSE)) {
243: getnameinfo(host->ai_addr, host->ai_addrlen, addr_buf,
244: sizeof(addr_buf), NULL, 0, NI_NUMERICHOST);
245: printf("sntp handle_pkt: Received %i bytes from %s\n", rpktl, addr_buf);
246: }
247:
248: GETTIMEOFDAY(&tv_dst, (struct timezone *)NULL);
249:
250: p_SNTP_PRETEND_TIME = getenv("SNTP_PRETEND_TIME");
251: if (p_SNTP_PRETEND_TIME) {
252: #if SIZEOF_TIME_T == 4
253: sscanf(p_SNTP_PRETEND_TIME, "%ld", &pretend_time);
254: #elif SIZEOF_TIME_T == 8
255: sscanf(p_SNTP_PRETEND_TIME, "%lld", &pretend_time);
256: #else
257: # include "GRONK: unexpected value for SIZEOF_TIME_T"
258: #endif
259: tv_dst.tv_sec = pretend_time;
260: }
261:
262: offset_calculation(rpkt, rpktl, &tv_dst, &offset,
263: &precision, &root_dispersion);
264:
265: for (digits = 0; (precision *= 10.) < 1.; ++digits)
266: /* empty */ ;
267: if (digits > 6)
268: digits = 6;
269:
270: ts_str = tv_to_str(&tv_dst);
271: printf("%s ", ts_str);
272: if (offset > 0)
273: printf("+");
274: printf("%.*f", digits, offset);
275: if (root_dispersion > 0.)
276: printf(" +/- %f secs", root_dispersion);
277: printf("\n");
278: free(ts_str);
279:
280: if (p_SNTP_PRETEND_TIME)
281: return 0;
282:
283: if (ENABLED_OPT(SETTOD) || ENABLED_OPT(ADJTIME))
284: return set_time(offset);
285:
286: return 0;
287: }
288:
289: return 1;
290: }
291:
292: void
293: offset_calculation (
294: struct pkt *rpkt,
295: int rpktl,
296: struct timeval *tv_dst,
297: double *offset,
298: double *precision,
299: double *root_dispersion
300: )
301: {
302: l_fp p_rec, p_xmt, p_ref, p_org, tmp, dst;
303: u_fp p_rdly, p_rdsp;
304: double t21, t34, delta;
305:
306: /* Convert timestamps from network to host byte order */
307: p_rdly = NTOHS_FP(rpkt->rootdelay);
308: p_rdsp = NTOHS_FP(rpkt->rootdisp);
309: NTOHL_FP(&rpkt->reftime, &p_ref);
310: NTOHL_FP(&rpkt->org, &p_org);
311: NTOHL_FP(&rpkt->rec, &p_rec);
312: NTOHL_FP(&rpkt->xmt, &p_xmt);
313:
314: *precision = LOGTOD(rpkt->precision);
315: #ifdef DEBUG
316: printf("sntp precision: %f\n", *precision);
317: #endif /* DEBUG */
318:
319: *root_dispersion = FPTOD(p_rdsp);
320:
321: #ifdef DEBUG
322: printf("sntp rootdelay: %f\n", FPTOD(p_rdly));
323: printf("sntp rootdisp: %f\n", *root_dispersion);
324:
325: pkt_output(rpkt, rpktl, stdout);
326:
327: printf("sntp offset_calculation: rpkt->reftime:\n");
328: l_fp_output(&(rpkt->reftime), stdout);
329: printf("sntp offset_calculation: rpkt->org:\n");
330: l_fp_output(&(rpkt->org), stdout);
331: printf("sntp offset_calculation: rpkt->rec:\n");
332: l_fp_output(&(rpkt->rec), stdout);
333: printf("sntp offset_calculation: rpkt->rec:\n");
334: l_fp_output_bin(&(rpkt->rec), stdout);
335: printf("sntp offset_calculation: rpkt->rec:\n");
336: l_fp_output_dec(&(rpkt->rec), stdout);
337: printf("sntp offset_calculation: rpkt->xmt:\n");
338: l_fp_output(&(rpkt->xmt), stdout);
339: #endif
340:
341: /* Compute offset etc. */
342: tmp = p_rec;
343: L_SUB(&tmp, &p_org);
344: LFPTOD(&tmp, t21);
345: TVTOTS(tv_dst, &dst);
346: dst.l_ui += JAN_1970;
347: tmp = p_xmt;
348: L_SUB(&tmp, &dst);
349: LFPTOD(&tmp, t34);
350: *offset = (t21 + t34) / 2.;
351: delta = t21 - t34;
352:
353: if (ENABLED_OPT(NORMALVERBOSE))
354: printf("sntp offset_calculation:\tt21: %.6f\t\t t34: %.6f\n\t\tdelta: %.6f\t offset: %.6f\n",
355: t21, t34, delta, *offset);
356: }
357:
358: /* The heart of (S)NTP, exchange NTP packets and compute values to correct the local clock */
359: int
360: on_wire (
361: struct addrinfo *host,
362: struct addrinfo *bcast
363: )
364: {
365: char addr_buf[INET6_ADDRSTRLEN];
366: register int try;
367: SOCKET sock;
368: struct key *pkt_key = NULL;
369: int key_id = 0;
370: struct timeval tv_xmt;
371: struct pkt x_pkt;
372: int error, rpktl, handle_pkt_res;
373:
374:
375: if (ENABLED_OPT(AUTHENTICATION)) {
376: key_id = (int) OPT_ARG(AUTHENTICATION);
377: get_key(key_id, &pkt_key);
378: }
379: for (try=0; try<5; try++) {
380: memset(&r_pkt, 0, sizeof rbuf);
381:
382: error = GETTIMEOFDAY(&tv_xmt, (struct timezone *)NULL);
383: tv_xmt.tv_sec += JAN_1970;
384:
385: #ifdef DEBUG
386: printf("sntp on_wire: Current time sec: %i msec: %i\n", (unsigned int) tv_xmt.tv_sec,
387: (unsigned int) tv_xmt.tv_usec);
388: #endif
389:
390: if (bcast) {
391: create_socket(&sock, (sockaddr_u *)bcast->ai_addr);
392: rpktl = recv_bcst_pkt(sock, &r_pkt, sizeof rbuf, (sockaddr_u *)bcast->ai_addr);
393: closesocket(sock);
394: } else {
395: int pkt_len = generate_pkt(&x_pkt, &tv_xmt, key_id, pkt_key);
396:
397: create_socket(&sock, (sockaddr_u *)host->ai_addr);
398: sendpkt(sock, (sockaddr_u *)host->ai_addr, &x_pkt, pkt_len);
399: rpktl = recvpkt(sock, &r_pkt, sizeof rbuf, &x_pkt);
400: closesocket(sock);
401: }
402:
403: handle_pkt_res = handle_pkt(rpktl, &r_pkt, host);
404: if (handle_pkt_res < 1)
405: return handle_pkt_res;
406: }
407:
408: getnameinfo(host->ai_addr, host->ai_addrlen, addr_buf, sizeof(addr_buf), NULL, 0, NI_NUMERICHOST);
409: msyslog(LOG_DEBUG, "Received no useable packet from %s!", addr_buf);
410:
411: return -1;
412: }
413:
414: /* Compute the 8 bits for li_vn_mode */
415: void
416: set_li_vn_mode (
417: struct pkt *spkt,
418: char leap,
419: char version,
420: char mode
421: )
422: {
423: if (leap > 3) {
424: msyslog(LOG_DEBUG, "set_li_vn_mode: leap > 3 using max. 3");
425: leap = 3;
426: }
427:
428: if (mode > 7) {
429: msyslog(LOG_DEBUG, "set_li_vn_mode: mode > 7, using client mode 3");
430: mode = 3;
431: }
432:
433: spkt->li_vn_mode = leap << 6;
434: spkt->li_vn_mode |= version << 3;
435: spkt->li_vn_mode |= mode;
436: }
437:
438: /* set_time corrects the local clock by offset with either settimeofday() or by default
439: * with adjtime()/adjusttimeofday().
440: */
441: int
442: set_time(
443: double offset
444: )
445: {
446: struct timeval tp;
447:
448: if (ENABLED_OPT(SETTOD)) {
449: GETTIMEOFDAY(&tp, NULL);
450:
451: tp.tv_sec += (long)offset;
452: tp.tv_usec += 1e6 * (offset - (long)offset);
453: NORMALIZE_TIMEVAL(tp);
454:
455: if (SETTIMEOFDAY(&tp, NULL) < 0) {
456: msyslog(LOG_ERR, "Time not set: settimeofday(): %m");
457: return -1;
458: }
459: return 0;
460: }
461:
462: tp.tv_sec = (long)offset;
463: tp.tv_usec = 1e6 * (offset - (long)offset);
464: NORMALIZE_TIMEVAL(tp);
465:
466: if (ADJTIMEOFDAY(&tp, NULL) < 0) {
467: msyslog(LOG_ERR, "Time not set: adjtime(): %m");
468: return -1;
469: }
470: return 0;
471: }
FreeBSD-CVSweb <freebsd-cvsweb@FreeBSD.org>