Annotation of embedaddon/ntp/sntp/main.c, revision 1.1.1.1

1.1       misho       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>