File:  [ELWIX - Embedded LightWeight unIX -] / embedaddon / ntp / ntpdate / ntptime_config.c
Revision 1.1.1.1 (vendor branch): download - view: text, annotated - select for diffs - revision graph
Tue May 29 12:08:38 2012 UTC (12 years, 1 month ago) by misho
Branches: ntp, MAIN
CVS tags: v4_2_6p5p0, v4_2_6p5, HEAD
ntp 4.2.6p5

    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>