Annotation of embedaddon/ntp/ntpdate/ntptime_config.c, revision 1.1.1.1

1.1       misho       1: /*
                      2:  * ntptime_config.c
                      3:  *
                      4:  * What follows is a simplified version of the config parsing code
                      5:  * in ntpd/ntp_config.c.  We only parse a subset of the configuration
                      6:  * syntax, and don't bother whining about things we don't understand.
                      7:  *
                      8:  */
                      9: 
                     10: #ifdef HAVE_CONFIG_H
                     11: # include <config.h>
                     12: #endif
                     13: 
                     14: #include "ntp_fp.h"
                     15: #include "ntp.h"
                     16: #include "ntp_io.h"
                     17: #include "ntp_unixtime.h"
                     18: #include "ntp_filegen.h"
                     19: #include "ntpdate.h"
                     20: #include "ntp_syslog.h"
                     21: #include "ntp_stdlib.h"
                     22: 
                     23: #include <stdio.h>
                     24: #include <signal.h>
                     25: #include <ctype.h>
                     26: 
                     27: /*
                     28:  * These routines are used to read the configuration file at
                     29:  * startup time.  An entry in the file must fit on a single line.
                     30:  * Entries are processed as multiple tokens separated by white space
                     31:  * Lines are considered terminated when a '#' is encountered.  Blank
                     32:  * lines are ignored.
                     33:  */
                     34: 
                     35: /*
                     36:  * Configuration file name
                     37:  */
                     38: #ifndef CONFIG_FILE
                     39: # ifndef SYS_WINNT
                     40: #  define      CONFIG_FILE "/etc/ntp.conf"
                     41: # else /* SYS_WINNT */
                     42: #  define      CONFIG_FILE     "%windir%\\ntp.conf"
                     43: #  define      ALT_CONFIG_FILE "%windir%\\ntp.ini"
                     44: # endif /* SYS_WINNT */
                     45: #endif /* not CONFIG_FILE */
                     46: 
                     47: /*
                     48:  *
                     49:  * We understand the following configuration entries and defaults.
                     50:  *
                     51:  * peer [ addr ] [ version 3 ] [ key 0 ] [ minpoll 6 ] [ maxpoll 10 ]
                     52:  * server [ addr ] [ version 3 ] [ key 0 ] [ minpoll 6 ] [ maxpoll 10 ]
                     53:  * keys file_name
                     54:  */
                     55: 
                     56: #define CONFIG_UNKNOWN         0
                     57: 
                     58: #define CONFIG_PEER            1
                     59: #define CONFIG_SERVER          2
                     60: #define CONFIG_KEYS            8
                     61: 
                     62: #define CONF_MOD_VERSION       1
                     63: #define CONF_MOD_KEY           2
                     64: #define CONF_MOD_MINPOLL       3
                     65: #define CONF_MOD_MAXPOLL       4
                     66: #define CONF_MOD_PREFER        5
                     67: #define CONF_MOD_BURST         6
                     68: #define CONF_MOD_SKEY          7
                     69: #define CONF_MOD_TTL           8
                     70: #define CONF_MOD_MODE          9
                     71: 
                     72: /*
                     73:  * Translation table - keywords to function index
                     74:  */
                     75: struct keyword {
                     76:        const char *text;
                     77:        int keytype;
                     78: };
                     79: 
                     80: /*
                     81:  * Command keywords
                     82:  */
                     83: static struct keyword keywords[] = {
                     84:        { "peer",       CONFIG_PEER },
                     85:        { "server",     CONFIG_SERVER },
                     86:        { "keys",       CONFIG_KEYS },
                     87:        { "",           CONFIG_UNKNOWN }
                     88: };
                     89: 
                     90: /*
                     91:  * "peer", "server", "broadcast" modifier keywords
                     92:  */
                     93: static struct keyword mod_keywords[] = {
                     94:        { "version",    CONF_MOD_VERSION },
                     95:        { "key",    CONF_MOD_KEY },
                     96:        { "minpoll",    CONF_MOD_MINPOLL },
                     97:        { "maxpoll",    CONF_MOD_MAXPOLL },
                     98:        { "prefer", CONF_MOD_PREFER },
                     99:        { "burst",  CONF_MOD_BURST },
                    100:        { "autokey",    CONF_MOD_SKEY },
                    101:        { "mode",   CONF_MOD_MODE },    /* reference clocks */
                    102:        { "ttl",    CONF_MOD_TTL },     /* NTP peers */
                    103:        { "",       CONFIG_UNKNOWN }
                    104: };
                    105: 
                    106: /*
                    107:  * Limits on things
                    108:  */
                    109: #define MAXTOKENS      20      /* 20 tokens on line */
                    110: #define MAXLINE        1024    /* maximum length of line */
                    111: #define MAXFILENAME 128 /* maximum length of a file name (alloca()?) */
                    112: 
                    113: /*
                    114:  * Miscellaneous macros
                    115:  */
                    116: #define STRSAME(s1, s2)        (*(s1) == *(s2) && strcmp((s1), (s2)) == 0)
                    117: #define ISEOL(c)               ((c) == '#' || (c) == '\n' || (c) == '\0')
                    118: #define ISSPACE(c)             ((c) == ' ' || (c) == '\t')
                    119: #define STREQ(a, b)    (*(a) == *(b) && strcmp((a), (b)) == 0)
                    120: 
                    121: /*
                    122:  * Systemwide parameters and flags
                    123:  */
                    124: extern struct server **sys_servers;    /* the server list */
                    125: extern int sys_numservers;     /* number of servers to poll */
                    126: extern char *key_file;
                    127: 
                    128: /*
                    129:  * Function prototypes
                    130:  */
                    131: static int gettokens   P((FILE *, char *, char **, int *));
                    132: static int matchkey    P((char *, struct keyword *));
                    133: static int getnetnum   P((const char *num, struct sockaddr_in *addr,
                    134:                           int complain));
                    135: 
                    136: 
                    137: /*
                    138:  * loadservers - load list of NTP servers from configuration file
                    139:  */
                    140: void
                    141: loadservers(
                    142:        char *cfgpath
                    143:        )
                    144: {
                    145:        register int i;
                    146:        int errflg;
                    147:        int peerversion;
                    148:        int minpoll;
                    149:        int maxpoll;
                    150:        /* int ttl; */
                    151:        int srvcnt;
                    152:        /* u_long peerkey; */
                    153:        int peerflags;
                    154:        struct sockaddr_in peeraddr;
                    155:        FILE *fp;
                    156:        char line[MAXLINE];
                    157:        char *(tokens[MAXTOKENS]);
                    158:        int ntokens;
                    159:        int tok;
                    160:        const char *config_file;
                    161: #ifdef SYS_WINNT
                    162:        char *alt_config_file;
                    163:        LPTSTR temp;
                    164:        char config_file_storage[MAX_PATH];
                    165:        char alt_config_file_storage[MAX_PATH];
                    166: #endif /* SYS_WINNT */
                    167:        struct server *server, *srvlist;
                    168: 
                    169:        /*
                    170:         * Initialize, initialize
                    171:         */
                    172:        srvcnt = 0;
                    173:        srvlist = 0;
                    174:        errflg = 0;
                    175: #ifdef DEBUG
                    176:        debug = 0;
                    177: #endif /* DEBUG */
                    178: #ifndef SYS_WINNT
                    179:        config_file = cfgpath ? cfgpath : CONFIG_FILE;
                    180: #else
                    181:        if (cfgpath) {
                    182:                config_file = cfgpath;
                    183:        } else {
                    184:                temp = CONFIG_FILE;
                    185:                if (!ExpandEnvironmentStrings((LPCTSTR)temp, (LPTSTR)config_file_storage, (DWORD)sizeof(config_file_storage))) {
                    186:                        msyslog(LOG_ERR, "ExpandEnvironmentStrings CONFIG_FILE failed: %m\n");
                    187:                        exit(1);
                    188:                }
                    189:                config_file = config_file_storage;
                    190:        }
                    191: 
                    192:        temp = ALT_CONFIG_FILE;
                    193:        if (!ExpandEnvironmentStrings((LPCTSTR)temp, (LPTSTR)alt_config_file_storage, (DWORD)sizeof(alt_config_file_storage))) {
                    194:                msyslog(LOG_ERR, "ExpandEnvironmentStrings ALT_CONFIG_FILE failed: %m\n");
                    195:                exit(1);
                    196:        }
                    197:        alt_config_file = alt_config_file_storage;
                    198: M
                    199: #endif /* SYS_WINNT */
                    200: 
                    201:        if ((fp = fopen(FindConfig(config_file), "r")) == NULL)
                    202:        {
                    203:                fprintf(stderr, "getconfig: Couldn't open <%s>\n", FindConfig(config_file));
                    204:                msyslog(LOG_INFO, "getconfig: Couldn't open <%s>", FindConfig(config_file));
                    205: #ifdef SYS_WINNT
                    206:                /* Under WinNT try alternate_config_file name, first NTP.CONF, then NTP.INI */
                    207: 
                    208:                if ((fp = fopen(FindConfig(alt_config_file), "r")) == NULL) {
                    209: 
                    210:                        /*
                    211:                         * Broadcast clients can sometimes run without
                    212:                         * a configuration file.
                    213:                         */
                    214: 
                    215:                        fprintf(stderr, "getconfig: Couldn't open <%s>\n", FindConfig(alt_config_file));
                    216:                        msyslog(LOG_INFO, "getconfig: Couldn't open <%s>", FindConfig(alt_config_file));
                    217:                        return;
                    218:                }
                    219: #else  /* not SYS_WINNT */
                    220:                return;
                    221: #endif /* not SYS_WINNT */
                    222:        }
                    223: 
                    224:        while ((tok = gettokens(fp, line, tokens, &ntokens))
                    225:               != CONFIG_UNKNOWN) {
                    226:                switch(tok) {
                    227:                    case CONFIG_PEER:
                    228:                    case CONFIG_SERVER:
                    229:                        
                    230:                        if (ntokens < 2) {
                    231:                                msyslog(LOG_ERR,
                    232:                                        "No address for %s, line ignored",
                    233:                                        tokens[0]);
                    234:                                break;
                    235:                        }
                    236:                        
                    237:                        if (!getnetnum(tokens[1], &peeraddr, 1)) {
                    238:                                /* Resolve now, or lose! */
                    239:                                break;
                    240:                        } else {
                    241:                                errflg = 0;
                    242:                                
                    243:                                /* Shouldn't be able to specify multicast */
                    244:                                if (IN_CLASSD(ntohl(peeraddr.sin_addr.s_addr))
                    245:                                    || ISBADADR(&peeraddr)) {
                    246:                                        msyslog(LOG_ERR,
                    247:                                                "attempt to configure invalid address %s",
                    248:                                                ntoa(&peeraddr));
                    249:                                        break;
                    250:                                }
                    251:                        }
                    252: 
                    253:                        peerversion = NTP_VERSION;
                    254:                        minpoll = NTP_MINDPOLL;
                    255:                        maxpoll = NTP_MAXDPOLL;
                    256:                        /* peerkey = 0; */
                    257:                        peerflags = 0;
                    258:                        /* ttl = 0; */
                    259:                        for (i = 2; i < ntokens; i++)
                    260:                            switch (matchkey(tokens[i], mod_keywords)) {
                    261:                                case CONF_MOD_VERSION:
                    262:                                    if (i >= ntokens-1) {
                    263:                                            msyslog(LOG_ERR,
                    264:                                                    "peer/server version requires an argument");
                    265:                                            errflg = 1;
                    266:                                            break;
                    267:                                    }
                    268:                                    peerversion = atoi(tokens[++i]);
                    269:                                    if ((u_char)peerversion > NTP_VERSION
                    270:                                        || (u_char)peerversion < NTP_OLDVERSION) {
                    271:                                            msyslog(LOG_ERR,
                    272:                                                    "inappropriate version number %s, line ignored",
                    273:                                                    tokens[i]);
                    274:                                            errflg = 1;
                    275:                                    }
                    276:                                    break;
                    277:                                        
                    278:                                case CONF_MOD_KEY:
                    279:                                    if (i >= ntokens-1) {
                    280:                                            msyslog(LOG_ERR,
                    281:                                                    "key: argument required");
                    282:                                            errflg = 1;
                    283:                                            break;
                    284:                                    }
                    285:                                    ++i;
                    286:                                    /* peerkey = (int)atol(tokens[i]); */
                    287:                                    peerflags |= FLAG_AUTHENABLE;
                    288:                                    break;
                    289: 
                    290:                                case CONF_MOD_MINPOLL:
                    291:                                    if (i >= ntokens-1) {
                    292:                                            msyslog(LOG_ERR,
                    293:                                                    "minpoll: argument required");
                    294:                                            errflg = 1;
                    295:                                            break;
                    296:                                    }
                    297:                                    minpoll = atoi(tokens[++i]);
                    298:                                    if (minpoll < NTP_MINPOLL)
                    299:                                        minpoll = NTP_MINPOLL;
                    300:                                    break;
                    301: 
                    302:                                case CONF_MOD_MAXPOLL:
                    303:                                    if (i >= ntokens-1) {
                    304:                                            msyslog(LOG_ERR,
                    305:                                                    "maxpoll: argument required"
                    306:                                                    );
                    307:                                            errflg = 1;
                    308:                                            break;
                    309:                                    }
                    310:                                    maxpoll = atoi(tokens[++i]);
                    311:                                    if (maxpoll > NTP_MAXPOLL)
                    312:                                        maxpoll = NTP_MAXPOLL;
                    313:                                    break;
                    314: 
                    315:                                case CONF_MOD_PREFER:
                    316:                                    peerflags |= FLAG_PREFER;
                    317:                                    break;
                    318: 
                    319:                                case CONF_MOD_BURST:
                    320:                                    peerflags |= FLAG_BURST;
                    321:                                    break;
                    322: 
                    323:                                case CONF_MOD_SKEY:
                    324:                                    peerflags |= FLAG_SKEY | FLAG_AUTHENABLE;
                    325:                                    break;
                    326: 
                    327:                                case CONF_MOD_TTL:
                    328:                                    if (i >= ntokens-1) {
                    329:                                            msyslog(LOG_ERR,
                    330:                                                    "ttl: argument required");
                    331:                                            errflg = 1;
                    332:                                            break;
                    333:                                    }
                    334:                                    ++i;
                    335:                                    /* ttl = atoi(tokens[i]); */
                    336:                                    break;
                    337: 
                    338:                                case CONF_MOD_MODE:
                    339:                                    if (i >= ntokens-1) {
                    340:                                            msyslog(LOG_ERR,
                    341:                                                    "mode: argument required");
                    342:                                            errflg = 1;
                    343:                                            break;
                    344:                                    }
                    345:                                    ++i;
                    346:                                    /* ttl = atoi(tokens[i]); */
                    347:                                    break;
                    348: 
                    349:                                case CONFIG_UNKNOWN:
                    350:                                    errflg = 1;
                    351:                                    break;
                    352:                            }
                    353:                        if (minpoll > maxpoll) {
                    354:                                msyslog(LOG_ERR, "config error: minpoll > maxpoll");
                    355:                                errflg = 1;
                    356:                        }
                    357:                        if (errflg == 0) {
                    358:                                server = (struct server *)emalloc(sizeof(struct server));
                    359:                                memset((char *)server, 0, sizeof(struct server));
                    360:                                server->srcadr = peeraddr;
                    361:                                server->version = peerversion;
                    362:                                server->dispersion = PEER_MAXDISP;
                    363:                                server->next_server = srvlist;
                    364:                                srvlist = server;
                    365:                                srvcnt++;
                    366:                        }
                    367:                        break;
                    368:                        
                    369:                        case CONFIG_KEYS:
                    370:                        if (ntokens >= 2) {
                    371:                                key_file = (char *) emalloc(strlen(tokens[1]) + 1);
                    372:                                strcpy(key_file, tokens[1]);
                    373:                        }
                    374:                        break;
                    375:                }
                    376:        }
                    377:        (void) fclose(fp);
                    378: 
                    379:        /* build final list */
                    380:        sys_numservers = srvcnt;
                    381:        sys_servers = (struct server **) 
                    382:            emalloc(sys_numservers * sizeof(struct server *));
                    383:        for(i=0;i<sys_numservers;i++) {
                    384:                sys_servers[i] = srvlist;
                    385:                srvlist = srvlist->next_server;
                    386:        }
                    387: }
                    388: 
                    389: 
                    390: 
                    391: /*
                    392:  * gettokens - read a line and return tokens
                    393:  */
                    394: static int
                    395: gettokens(
                    396:        FILE *fp,
                    397:        char *line,
                    398:        char **tokenlist,
                    399:        int *ntokens
                    400:        )
                    401: {
                    402:        register char *cp;
                    403:        register int eol;
                    404:        register int ntok;
                    405:        register int quoted = 0;
                    406: 
                    407:        /*
                    408:         * Find start of first token
                    409:         */
                    410:        again:
                    411:        while ((cp = fgets(line, MAXLINE, fp)) != NULL) {
                    412:                cp = line;
                    413:                while (ISSPACE(*cp))
                    414:                        cp++;
                    415:                if (!ISEOL(*cp))
                    416:                        break;
                    417:        }
                    418:        if (cp == NULL) {
                    419:                *ntokens = 0;
                    420:                return CONFIG_UNKNOWN;  /* hack.  Is recognized as EOF */
                    421:        }
                    422: 
                    423:        /*
                    424:         * Now separate out the tokens
                    425:         */
                    426:        eol = 0;
                    427:        ntok = 0;
                    428:        while (!eol) {
                    429:                tokenlist[ntok++] = cp;
                    430:                while (!ISEOL(*cp) && (!ISSPACE(*cp) || quoted))
                    431:                        quoted ^= (*cp++ == '"');
                    432: 
                    433:                if (ISEOL(*cp)) {
                    434:                        *cp = '\0';
                    435:                        eol = 1;
                    436:                } else {                /* must be space */
                    437:                        *cp++ = '\0';
                    438:                        while (ISSPACE(*cp))
                    439:                                cp++;
                    440:                        if (ISEOL(*cp))
                    441:                                eol = 1;
                    442:                }
                    443:                if (ntok == MAXTOKENS)
                    444:                        eol = 1;
                    445:        }
                    446: 
                    447:        /*
                    448:         * Return the match
                    449:         */
                    450:        *ntokens = ntok;
                    451:        ntok = matchkey(tokenlist[0], keywords);
                    452:        if (ntok == CONFIG_UNKNOWN)
                    453:                goto again;
                    454:        return ntok;
                    455: }
                    456: 
                    457: 
                    458: 
                    459: /*
                    460:  * matchkey - match a keyword to a list
                    461:  */
                    462: static int
                    463: matchkey(
                    464:        register char *word,
                    465:        register struct keyword *keys
                    466:        )
                    467: {
                    468:        for (;;) {
                    469:                if (keys->keytype == CONFIG_UNKNOWN) {
                    470:                        return CONFIG_UNKNOWN;
                    471:                }
                    472:                if (STRSAME(word, keys->text))
                    473:                        return keys->keytype;
                    474:                keys++;
                    475:        }
                    476: }
                    477: 
                    478: 
                    479: /*
                    480:  * getnetnum - return a net number (this is crude, but careful)
                    481:  */
                    482: static int
                    483: getnetnum(
                    484:        const char *num,
                    485:        struct sockaddr_in *addr,
                    486:        int complain
                    487:        )
                    488: {
                    489:        register const char *cp;
                    490:        register char *bp;
                    491:        register int i;
                    492:        register int temp;
                    493:        char buf[80];           /* will core dump on really stupid stuff */
                    494:        u_int32 netnum;
                    495: 
                    496:        /* XXX ELIMINATE replace with decodenetnum */
                    497:        cp = num;
                    498:        netnum = 0;
                    499:        for (i = 0; i < 4; i++) {
                    500:                bp = buf;
                    501:                while (isdigit((int)*cp))
                    502:                        *bp++ = *cp++;
                    503:                if (bp == buf)
                    504:                        break;
                    505: 
                    506:                if (i < 3) {
                    507:                        if (*cp++ != '.')
                    508:                                break;
                    509:                } else if (*cp != '\0')
                    510:                        break;
                    511: 
                    512:                *bp = '\0';
                    513:                temp = atoi(buf);
                    514:                if (temp > 255)
                    515:                        break;
                    516:                netnum <<= 8;
                    517:                netnum += temp;
                    518: #ifdef DEBUG
                    519:                if (debug > 3)
                    520:                        printf("getnetnum %s step %d buf %s temp %d netnum %lu\n",
                    521:                           num, i, buf, temp, (u_long)netnum);
                    522: #endif
                    523:        }
                    524: 
                    525:        if (i < 4) {
                    526:                if (complain)
                    527:                        msyslog(LOG_ERR,
                    528:                                "getnetnum: \"%s\" invalid host number, line ignored",
                    529:                                num);
                    530: #ifdef DEBUG
                    531:                if (debug > 3)
                    532:                        printf(
                    533:                                "getnetnum: \"%s\" invalid host number, line ignored\n",
                    534:                                num);
                    535: #endif
                    536:                return 0;
                    537:        }
                    538: 
                    539:        /*
                    540:         * make up socket address.      Clear it out for neatness.
                    541:         */
                    542:        memset((void *)addr, 0, sizeof(struct sockaddr_in));
                    543:        addr->sin_family = AF_INET;
                    544:        addr->sin_port = htons(NTP_PORT);
                    545:        addr->sin_addr.s_addr = htonl(netnum);
                    546: #ifdef DEBUG
                    547:        if (debug > 1)
                    548:                printf("getnetnum given %s, got %s (%lx)\n",
                    549:                   num, ntoa(addr), (u_long)netnum);
                    550: #endif
                    551:        return 1;
                    552: }

FreeBSD-CVSweb <freebsd-cvsweb@FreeBSD.org>