Source code pulled from OpenBSD for OpenNTPD. The place to contribute to this code is via the OpenBSD CVS tree.
You can not select more than 25 topics Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.

464 lines
8.9 KiB

20 years ago
  1. /* $OpenBSD: parse.y,v 1.29 2006/06/01 06:06:59 otto Exp $ */
  2. /*
  3. * Copyright (c) 2002, 2003, 2004 Henning Brauer <henning@openbsd.org>
  4. * Copyright (c) 2001 Markus Friedl. All rights reserved.
  5. * Copyright (c) 2001 Daniel Hartmeier. All rights reserved.
  6. * Copyright (c) 2001 Theo de Raadt. All rights reserved.
  7. *
  8. * Permission to use, copy, modify, and distribute this software for any
  9. * purpose with or without fee is hereby granted, provided that the above
  10. * copyright notice and this permission notice appear in all copies.
  11. *
  12. * THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES
  13. * WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF
  14. * MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR
  15. * ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES
  16. * WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN
  17. * ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF
  18. * OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.
  19. */
  20. %{
  21. #include <sys/types.h>
  22. #include <sys/socket.h>
  23. #include <netinet/in.h>
  24. #include <arpa/inet.h>
  25. #include <ctype.h>
  26. #include <errno.h>
  27. #include <limits.h>
  28. #include <stdarg.h>
  29. #include <stdio.h>
  30. #include <stdlib.h>
  31. #include <string.h>
  32. #include <syslog.h>
  33. #include "ntpd.h"
  34. static struct ntpd_conf *conf;
  35. static FILE *fin = NULL;
  36. static int lineno = 1;
  37. static int errors = 0;
  38. const char *infile;
  39. int yyerror(const char *, ...);
  40. int yyparse(void);
  41. int kw_cmp(const void *, const void *);
  42. int lookup(char *);
  43. int lgetc(FILE *);
  44. int lungetc(int);
  45. int findeol(void);
  46. int yylex(void);
  47. typedef struct {
  48. union {
  49. u_int32_t number;
  50. char *string;
  51. struct ntp_addr_wrap *addr;
  52. } v;
  53. int lineno;
  54. } YYSTYPE;
  55. %}
  56. %token LISTEN ON
  57. %token SERVER SERVERS SENSOR WEIGHT
  58. %token ERROR
  59. %token <v.string> STRING
  60. %type <v.addr> address
  61. %type <v.number> number weight
  62. %%
  63. grammar : /* empty */
  64. | grammar '\n'
  65. | grammar conf_main '\n'
  66. | grammar error '\n' { errors++; }
  67. ;
  68. conf_main : LISTEN ON address {
  69. struct listen_addr *la;
  70. struct ntp_addr *h, *next;
  71. if ((h = $3->a) == NULL &&
  72. (host_dns($3->name, &h) == -1 || !h)) {
  73. yyerror("could not resolve \"%s\"", $3->name);
  74. free($3->name);
  75. free($3);
  76. YYERROR;
  77. }
  78. for (; h != NULL; h = next) {
  79. next = h->next;
  80. if (h->ss.ss_family == AF_UNSPEC) {
  81. conf->listen_all = 1;
  82. free(h);
  83. continue;
  84. }
  85. la = calloc(1, sizeof(struct listen_addr));
  86. if (la == NULL)
  87. fatal("listen on calloc");
  88. la->fd = -1;
  89. memcpy(&la->sa, &h->ss,
  90. sizeof(struct sockaddr_storage));
  91. TAILQ_INSERT_TAIL(&conf->listen_addrs, la,
  92. entry);
  93. free(h);
  94. }
  95. free($3->name);
  96. free($3);
  97. }
  98. | SERVERS address weight {
  99. struct ntp_peer *p;
  100. struct ntp_addr *h, *next;
  101. h = $2->a;
  102. do {
  103. if (h != NULL) {
  104. next = h->next;
  105. if (h->ss.ss_family != AF_INET &&
  106. h->ss.ss_family != AF_INET6) {
  107. yyerror("IPv4 or IPv6 address "
  108. "or hostname expected");
  109. free(h);
  110. free($2->name);
  111. free($2);
  112. YYERROR;
  113. }
  114. h->next = NULL;
  115. } else
  116. next = NULL;
  117. p = new_peer();
  118. p->weight = $3;
  119. p->addr = h;
  120. p->addr_head.a = h;
  121. p->addr_head.pool = 1;
  122. p->addr_head.name = strdup($2->name);
  123. if (p->addr_head.name == NULL)
  124. fatal(NULL);
  125. if (p->addr != NULL)
  126. p->state = STATE_DNS_DONE;
  127. TAILQ_INSERT_TAIL(&conf->ntp_peers, p, entry);
  128. h = next;
  129. } while (h != NULL);
  130. free($2->name);
  131. free($2);
  132. }
  133. | SERVER address weight {
  134. struct ntp_peer *p;
  135. struct ntp_addr *h, *next;
  136. p = new_peer();
  137. for (h = $2->a; h != NULL; h = next) {
  138. next = h->next;
  139. if (h->ss.ss_family != AF_INET &&
  140. h->ss.ss_family != AF_INET6) {
  141. yyerror("IPv4 or IPv6 address "
  142. "or hostname expected");
  143. free(h);
  144. free(p);
  145. free($2->name);
  146. free($2);
  147. YYERROR;
  148. }
  149. h->next = p->addr;
  150. p->addr = h;
  151. }
  152. p->weight = $3;
  153. p->addr_head.a = p->addr;
  154. p->addr_head.pool = 0;
  155. p->addr_head.name = strdup($2->name);
  156. if (p->addr_head.name == NULL)
  157. fatal(NULL);
  158. if (p->addr != NULL)
  159. p->state = STATE_DNS_DONE;
  160. TAILQ_INSERT_TAIL(&conf->ntp_peers, p, entry);
  161. free($2->name);
  162. free($2);
  163. }
  164. | SENSOR STRING weight {
  165. struct ntp_conf_sensor *s;
  166. s = new_sensor($2);
  167. s->weight = $3;
  168. free($2);
  169. TAILQ_INSERT_TAIL(&conf->ntp_conf_sensors, s, entry);
  170. }
  171. ;
  172. address : STRING {
  173. if (($$ = calloc(1, sizeof(struct ntp_addr_wrap))) ==
  174. NULL)
  175. fatal(NULL);
  176. if (host($1, &$$->a) == -1) {
  177. yyerror("could not parse address spec \"%s\"",
  178. $1);
  179. free($1);
  180. free($$);
  181. YYERROR;
  182. }
  183. $$->name = $1;
  184. }
  185. ;
  186. number : STRING {
  187. u_long ulval;
  188. const char *errstr;
  189. ulval = strtonum($1, 0, LONG_MAX, &errstr);
  190. if (errstr) {
  191. yyerror("\"%s\" invalid: %s", $1, errstr);
  192. free($1);
  193. YYERROR;
  194. } else
  195. $$ = ulval;
  196. free($1);
  197. }
  198. ;
  199. weight : /* empty */ { $$ = 1; }
  200. | WEIGHT number {
  201. if ($2 < 1 || $2 > 10) {
  202. yyerror("weight must be between 1 and 10");
  203. YYERROR;
  204. }
  205. $$ = $2;
  206. }
  207. ;
  208. %%
  209. struct keywords {
  210. const char *k_name;
  211. int k_val;
  212. };
  213. int
  214. yyerror(const char *fmt, ...)
  215. {
  216. va_list ap;
  217. char *nfmt;
  218. errors = 1;
  219. va_start(ap, fmt);
  220. if (asprintf(&nfmt, "%s:%d: %s", infile, yylval.lineno, fmt) == -1)
  221. fatalx("yyerror asprintf");
  222. vlog(LOG_CRIT, nfmt, ap);
  223. va_end(ap);
  224. free(nfmt);
  225. return (0);
  226. }
  227. int
  228. kw_cmp(const void *k, const void *e)
  229. {
  230. return (strcmp(k, ((const struct keywords *)e)->k_name));
  231. }
  232. int
  233. lookup(char *s)
  234. {
  235. /* this has to be sorted always */
  236. static const struct keywords keywords[] = {
  237. { "listen", LISTEN},
  238. { "on", ON},
  239. { "sensor", SENSOR},
  240. { "server", SERVER},
  241. { "servers", SERVERS},
  242. { "weight", WEIGHT}
  243. };
  244. const struct keywords *p;
  245. p = bsearch(s, keywords, sizeof(keywords)/sizeof(keywords[0]),
  246. sizeof(keywords[0]), kw_cmp);
  247. if (p)
  248. return (p->k_val);
  249. else
  250. return (STRING);
  251. }
  252. #define MAXPUSHBACK 128
  253. char *parsebuf;
  254. int parseindex;
  255. char pushback_buffer[MAXPUSHBACK];
  256. int pushback_index = 0;
  257. int
  258. lgetc(FILE *f)
  259. {
  260. int c, next;
  261. if (parsebuf) {
  262. /* Read character from the parsebuffer instead of input. */
  263. if (parseindex >= 0) {
  264. c = parsebuf[parseindex++];
  265. if (c != '\0')
  266. return (c);
  267. parsebuf = NULL;
  268. } else
  269. parseindex++;
  270. }
  271. if (pushback_index)
  272. return (pushback_buffer[--pushback_index]);
  273. while ((c = getc(f)) == '\\') {
  274. next = getc(f);
  275. if (next != '\n') {
  276. c = next;
  277. break;
  278. }
  279. yylval.lineno = lineno;
  280. lineno++;
  281. }
  282. if (c == '\t' || c == ' ') {
  283. /* Compress blanks to a single space. */
  284. do {
  285. c = getc(f);
  286. } while (c == '\t' || c == ' ');
  287. ungetc(c, f);
  288. c = ' ';
  289. }
  290. return (c);
  291. }
  292. int
  293. lungetc(int c)
  294. {
  295. if (c == EOF)
  296. return (EOF);
  297. if (parsebuf) {
  298. parseindex--;
  299. if (parseindex >= 0)
  300. return (c);
  301. }
  302. if (pushback_index < MAXPUSHBACK-1)
  303. return (pushback_buffer[pushback_index++] = c);
  304. else
  305. return (EOF);
  306. }
  307. int
  308. findeol(void)
  309. {
  310. int c;
  311. parsebuf = NULL;
  312. pushback_index = 0;
  313. /* skip to either EOF or the first real EOL */
  314. while (1) {
  315. c = lgetc(fin);
  316. if (c == '\n') {
  317. lineno++;
  318. break;
  319. }
  320. if (c == EOF)
  321. break;
  322. }
  323. return (ERROR);
  324. }
  325. int
  326. yylex(void)
  327. {
  328. char buf[8096];
  329. char *p;
  330. int endc, c;
  331. int token;
  332. p = buf;
  333. while ((c = lgetc(fin)) == ' ')
  334. ; /* nothing */
  335. yylval.lineno = lineno;
  336. if (c == '#')
  337. while ((c = lgetc(fin)) != '\n' && c != EOF)
  338. ; /* nothing */
  339. switch (c) {
  340. case '\'':
  341. case '"':
  342. endc = c;
  343. while (1) {
  344. if ((c = lgetc(fin)) == EOF)
  345. return (0);
  346. if (c == endc) {
  347. *p = '\0';
  348. break;
  349. }
  350. if (c == '\n') {
  351. lineno++;
  352. continue;
  353. }
  354. if (p + 1 >= buf + sizeof(buf) - 1) {
  355. yyerror("string too long");
  356. return (findeol());
  357. }
  358. *p++ = (char)c;
  359. }
  360. yylval.v.string = strdup(buf);
  361. if (yylval.v.string == NULL)
  362. fatal("yylex: strdup");
  363. return (STRING);
  364. }
  365. #define allowed_in_string(x) \
  366. (isalnum(x) || (ispunct(x) && x != '(' && x != ')' && \
  367. x != '{' && x != '}' && x != '<' && x != '>' && \
  368. x != '!' && x != '=' && x != '/' && x != '#' && \
  369. x != ','))
  370. if (isalnum(c) || c == ':' || c == '_' || c == '*') {
  371. do {
  372. *p++ = c;
  373. if ((unsigned)(p-buf) >= sizeof(buf)) {
  374. yyerror("string too long");
  375. return (findeol());
  376. }
  377. } while ((c = lgetc(fin)) != EOF && (allowed_in_string(c)));
  378. lungetc(c);
  379. *p = '\0';
  380. if ((token = lookup(buf)) == STRING)
  381. if ((yylval.v.string = strdup(buf)) == NULL)
  382. fatal("yylex: strdup");
  383. return (token);
  384. }
  385. if (c == '\n') {
  386. yylval.lineno = lineno;
  387. lineno++;
  388. }
  389. if (c == EOF)
  390. return (0);
  391. return (c);
  392. }
  393. int
  394. parse_config(const char *filename, struct ntpd_conf *xconf)
  395. {
  396. conf = xconf;
  397. lineno = 1;
  398. errors = 0;
  399. TAILQ_INIT(&conf->listen_addrs);
  400. TAILQ_INIT(&conf->ntp_peers);
  401. TAILQ_INIT(&conf->ntp_conf_sensors);
  402. if ((fin = fopen(filename, "r")) == NULL) {
  403. log_warn("%s", filename);
  404. return (-1);
  405. }
  406. infile = filename;
  407. yyparse();
  408. fclose(fin);
  409. return (errors ? -1 : 0);
  410. }