1/* ntp_parser.y
2 *
3 * The parser for the NTP configuration file.
4 *
5 * Written By:	Sachin Kamboj
6 *		University of Delaware
7 *		Newark, DE 19711
8 * Copyright (c) 2006
9 */
10
11%{
12  #ifdef HAVE_CONFIG_H
13  # include <config.h>
14  #endif
15
16  #include "ntpd.h"
17  #include "ntp_machine.h"
18  #include "ntp.h"
19  #include "ntp_stdlib.h"
20  #include "ntp_filegen.h"
21  #include "ntp_data_structures.h"
22  #include "ntp_scanner.h"
23  #include "ntp_config.h"
24  #include "ntp_crypto.h"
25
26  #include "ntpsim.h"		/* HMS: Do we really want this all the time? */
27				/* SK: It might be a good idea to always
28				   include the simulator code. That way
29				   someone can use the same configuration file
30				   for both the simulator and the daemon
31				*/
32
33
34  struct FILE_INFO *ip_file;   /* Pointer to the configuration file stream */
35
36  #define YYMALLOC	emalloc
37  #define YYFREE	free
38  #define YYERROR_VERBOSE
39  #define YYMAXDEPTH	1000   /* stop the madness sooner */
40  void yyerror (char *msg);
41  extern int input_from_file;  /* 0=input from ntpq :config */
42%}
43
44/*
45 * Enable generation of token names array even without YYDEBUG.
46 * We access via token_name() defined below.
47 */
48%token-table
49
50%union {
51    char   *String;
52    double  Double;
53    int     Integer;
54    void   *VoidPtr;
55    queue  *Queue;
56    struct attr_val *Attr_val;
57    struct address_node *Address_node;
58    struct setvar_node *Set_var;
59
60    /* Simulation types */
61    server_info *Sim_server;
62    script_info *Sim_script;
63}
64
65/* TERMINALS (do not appear left of colon) */
66%token	<Integer>	T_Age
67%token	<Integer>	T_All
68%token	<Integer>	T_Allan
69%token	<Integer>	T_Auth
70%token	<Integer>	T_Autokey
71%token	<Integer>	T_Automax
72%token	<Integer>	T_Average
73%token	<Integer>	T_Bclient
74%token	<Integer>	T_Beacon
75%token	<Integer>	T_Bias
76%token	<Integer>	T_Broadcast
77%token	<Integer>	T_Broadcastclient
78%token	<Integer>	T_Broadcastdelay
79%token	<Integer>	T_Burst
80%token	<Integer>	T_Calibrate
81%token	<Integer>	T_Calldelay
82%token	<Integer>	T_Ceiling
83%token	<Integer>	T_Clockstats
84%token	<Integer>	T_Cohort
85%token	<Integer>	T_ControlKey
86%token	<Integer>	T_Crypto
87%token	<Integer>	T_Cryptostats
88%token	<Integer>	T_Day
89%token	<Integer>	T_Default
90%token	<Integer>	T_Digest
91%token	<Integer>	T_Disable
92%token	<Integer>	T_Discard
93%token	<Integer>	T_Dispersion
94%token	<Double>	T_Double
95%token	<Integer>	T_Driftfile
96%token	<Integer>	T_Drop
97%token	<Integer>	T_Enable
98%token	<Integer>	T_End
99%token	<Integer>	T_False
100%token	<Integer>	T_File
101%token	<Integer>	T_Filegen
102%token	<Integer>	T_Flag1
103%token	<Integer>	T_Flag2
104%token	<Integer>	T_Flag3
105%token	<Integer>	T_Flag4
106%token	<Integer>	T_Flake
107%token	<Integer>	T_Floor
108%token	<Integer>	T_Freq
109%token	<Integer>	T_Fudge
110%token	<Integer>	T_Host
111%token	<Integer>	T_Huffpuff
112%token	<Integer>	T_Iburst
113%token	<Integer>	T_Ident
114%token	<Integer>	T_Ignore
115%token	<Integer>	T_Includefile
116%token	<Integer>	T_Integer
117%token	<Integer>	T_Interface
118%token	<Integer>	T_Ipv4
119%token	<Integer>	T_Ipv4_flag
120%token	<Integer>	T_Ipv6
121%token	<Integer>	T_Ipv6_flag
122%token	<Integer>	T_Kernel
123%token	<Integer>	T_Key
124%token	<Integer>	T_Keys
125%token	<Integer>	T_Keysdir
126%token	<Integer>	T_Kod
127%token	<Integer>	T_Mssntp
128%token	<Integer>	T_Leapfile
129%token	<Integer>	T_Limited
130%token	<Integer>	T_Link
131%token	<Integer>	T_Listen
132%token	<Integer>	T_Logconfig
133%token	<Integer>	T_Logfile
134%token	<Integer>	T_Loopstats
135%token	<Integer>	T_Lowpriotrap
136%token	<Integer>	T_Manycastclient
137%token	<Integer>	T_Manycastserver
138%token	<Integer>	T_Mask
139%token	<Integer>	T_Maxclock
140%token	<Integer>	T_Maxdist
141%token	<Integer>	T_Maxpoll
142%token	<Integer>	T_Minclock
143%token	<Integer>	T_Mindist
144%token	<Integer>	T_Minimum
145%token	<Integer>	T_Minpoll
146%token	<Integer>	T_Minsane
147%token	<Integer>	T_Mode
148%token	<Integer>	T_Monitor
149%token	<Integer>	T_Month
150%token	<Integer>	T_Multicastclient
151%token	<Integer>	T_Nic
152%token	<Integer>	T_Nolink
153%token	<Integer>	T_Nomodify
154%token	<Integer>	T_None
155%token	<Integer>	T_Nopeer
156%token	<Integer>	T_Noquery
157%token	<Integer>	T_Noselect
158%token	<Integer>	T_Noserve
159%token	<Integer>	T_Notrap
160%token	<Integer>	T_Notrust
161%token	<Integer>	T_Ntp
162%token	<Integer>	T_Ntpport
163%token	<Integer>	T_NtpSignDsocket
164%token	<Integer>	T_Orphan
165%token	<Integer>	T_Panic
166%token	<Integer>	T_Peer
167%token	<Integer>	T_Peerstats
168%token	<Integer>	T_Phone
169%token	<Integer>	T_Pid
170%token	<Integer>	T_Pidfile
171%token	<Integer>	T_Pool
172%token	<Integer>	T_Port
173%token	<Integer>	T_Preempt
174%token	<Integer>	T_Prefer
175%token	<Integer>	T_Protostats
176%token	<Integer>	T_Pw
177%token	<Integer>	T_Qos
178%token	<Integer>	T_Randfile
179%token	<Integer>	T_Rawstats
180%token	<Integer>	T_Refid
181%token	<Integer>	T_Requestkey
182%token	<Integer>	T_Restrict
183%token	<Integer>	T_Revoke
184%token	<Integer>	T_Saveconfigdir
185%token	<Integer>	T_Server
186%token	<Integer>	T_Setvar
187%token	<Integer>	T_Sign
188%token	<Integer>	T_Statistics
189%token	<Integer>	T_Stats
190%token	<Integer>	T_Statsdir
191%token	<Integer>	T_Step
192%token	<Integer>	T_Stepout
193%token	<Integer>	T_Stratum
194%token	<String>	T_String
195%token	<Integer>	T_Sysstats
196%token	<Integer>	T_Tick
197%token	<Integer>	T_Time1
198%token	<Integer>	T_Time2
199%token	<Integer>	T_Timingstats
200%token	<Integer>	T_Tinker
201%token	<Integer>	T_Tos
202%token	<Integer>	T_Trap
203%token	<Integer>	T_True
204%token	<Integer>	T_Trustedkey
205%token	<Integer>	T_Ttl
206%token	<Integer>	T_Type
207%token	<Integer>	T_Unconfig
208%token	<Integer>	T_Unpeer
209%token	<Integer>	T_Version
210%token	<Integer>	T_WanderThreshold	/* Not a token */
211%token	<Integer>	T_Week
212%token	<Integer>	T_Wildcard
213%token	<Integer>	T_Xleave
214%token	<Integer>	T_Year
215%token	<Integer>	T_Flag		/* Not an actual token */
216%token	<Integer>	T_Void		/* Not an actual token */
217%token	<Integer>	T_EOC
218
219
220/* NTP Simulator Tokens */
221%token	<Integer>	T_Simulate
222%token	<Integer>	T_Beep_Delay
223%token	<Integer>	T_Sim_Duration
224%token	<Integer>	T_Server_Offset
225%token	<Integer>	T_Duration
226%token	<Integer>	T_Freq_Offset
227%token	<Integer>	T_Wander
228%token	<Integer>	T_Jitter
229%token	<Integer>	T_Prop_Delay
230%token	<Integer>	T_Proc_Delay
231
232
233
234/*** NON-TERMINALS ***/
235%type	<Integer>	access_control_flag
236%type	<Queue>		ac_flag_list
237%type	<Address_node>	address
238%type	<Queue>		address_list
239%type	<Integer>	boolean
240%type	<Integer>	client_type
241%type	<Attr_val>	crypto_command
242%type	<Queue>		crypto_command_line
243%type	<Queue>		crypto_command_list
244%type	<Attr_val>	discard_option
245%type	<Queue>		discard_option_list
246%type	<Attr_val>	filegen_option
247%type	<Queue>		filegen_option_list
248%type	<Integer>	filegen_type
249%type	<Attr_val>	fudge_factor
250%type	<Queue>		fudge_factor_list
251%type	<Queue>		integer_list
252%type	<Integer>	nic_rule_action
253%type	<Queue>		interface_command
254%type	<Integer>	interface_nic
255%type	<Address_node>	ip_address
256%type	<Attr_val>	log_config_command
257%type	<Queue>		log_config_list
258%type	<Integer>	nic_rule_class
259%type	<Double>	number
260%type	<Attr_val>	option
261%type	<Queue>		option_list
262%type	<Integer>	stat
263%type	<Queue>		stats_list
264%type	<Queue>		string_list
265%type	<Attr_val>	system_option
266%type	<Queue>		system_option_list
267%type	<Attr_val>	tinker_option
268%type	<Queue>		tinker_option_list
269%type	<Attr_val>	tos_option
270%type	<Queue>		tos_option_list
271%type	<Attr_val>	trap_option
272%type	<Queue>		trap_option_list
273%type	<Integer>	unpeer_keyword
274%type	<Set_var>	variable_assign
275
276/* NTP Simulator non-terminals */
277%type	<Queue>		sim_init_statement_list
278%type	<Attr_val>	sim_init_statement
279%type	<Queue>		sim_server_list
280%type	<Sim_server>	sim_server
281%type	<Double>	sim_server_offset
282%type	<Address_node>	sim_server_name
283%type	<Queue>		sim_act_list
284%type	<Sim_script>	sim_act
285%type	<Queue>		sim_act_stmt_list
286%type	<Attr_val>	sim_act_stmt
287
288%%
289
290/* ntp.conf
291 * Configuration File Grammar
292 * --------------------------
293 */
294
295configuration
296	:	command_list
297	;
298
299command_list
300	:	command_list command T_EOC
301	|	command T_EOC
302	|	error T_EOC
303		{
304			/* I will need to incorporate much more fine grained
305			 * error messages. The following should suffice for
306			 * the time being.
307			 */
308			msyslog(LOG_ERR,
309				"syntax error in %s line %d, column %d",
310				ip_file->fname,
311				ip_file->err_line_no,
312				ip_file->err_col_no);
313		}
314	;
315
316command :	/* NULL STATEMENT */
317	|	server_command
318	|	unpeer_command
319	|	other_mode_command
320	|	authentication_command
321	|	monitoring_command
322	|	access_control_command
323	|	orphan_mode_command
324	|	fudge_command
325	|	system_option_command
326	|	tinker_command
327	|	miscellaneous_command
328	|	simulate_command
329	;
330
331/* Server Commands
332 * ---------------
333 */
334
335server_command
336	:	client_type address option_list
337		{
338			struct peer_node *my_node =  create_peer_node($1, $2, $3);
339			if (my_node)
340				enqueue(cfgt.peers, my_node);
341		}
342	|	client_type address
343		{
344			struct peer_node *my_node = create_peer_node($1, $2, NULL);
345			if (my_node)
346				enqueue(cfgt.peers, my_node);
347		}
348	;
349
350client_type
351	:	T_Server
352	|	T_Pool
353	|	T_Peer
354	|	T_Broadcast
355	|	T_Manycastclient
356	;
357
358address
359	:	ip_address
360	|	T_Ipv4_flag T_String	{ $$ = create_address_node($2, AF_INET); }
361	|	T_Ipv6_flag T_String	{ $$ = create_address_node($2, AF_INET6); }
362	;
363
364ip_address
365	:	T_String { $$ = create_address_node($1, 0); }
366	;
367
368option_list
369	:	option_list option { $$ = enqueue($1, $2); }
370	|	option { $$ = enqueue_in_new_queue($1); }
371	;
372
373option
374	:	T_Autokey		{ $$ = create_attr_ival(T_Flag, $1); }
375	|	T_Bias number		{ $$ = create_attr_dval($1, $2); }
376	|	T_Burst			{ $$ = create_attr_ival(T_Flag, $1); }
377	|	T_Iburst		{ $$ = create_attr_ival(T_Flag, $1); }
378	|	T_Key T_Integer		{ $$ = create_attr_ival($1, $2); }
379	|	T_Minpoll T_Integer	{ $$ = create_attr_ival($1, $2); }
380	|	T_Maxpoll T_Integer	{ $$ = create_attr_ival($1, $2); }
381	|	T_Noselect		{ $$ = create_attr_ival(T_Flag, $1); }
382	|	T_Preempt		{ $$ = create_attr_ival(T_Flag, $1); }
383	|	T_Prefer		{ $$ = create_attr_ival(T_Flag, $1); }
384	|	T_True			{ $$ = create_attr_ival(T_Flag, $1); }
385	|	T_Xleave		{ $$ = create_attr_ival(T_Flag, $1); }
386	|	T_Ttl T_Integer		{ $$ = create_attr_ival($1, $2); }
387	|	T_Mode T_Integer	{ $$ = create_attr_ival($1, $2); }
388	|	T_Version T_Integer	{ $$ = create_attr_ival($1, $2); }
389	;
390
391
392/* unpeer commands
393 * ---------------
394 */
395
396unpeer_command
397	:	unpeer_keyword address
398		{
399			struct unpeer_node *my_node = create_unpeer_node($2);
400			if (my_node)
401				enqueue(cfgt.unpeers, my_node);
402		}
403	;
404unpeer_keyword
405	:	T_Unconfig
406	|	T_Unpeer
407	;
408
409
410/* Other Modes
411 * (broadcastclient manycastserver multicastclient)
412 * ------------------------------------------------
413 */
414
415other_mode_command
416	:	T_Broadcastclient
417			{ cfgt.broadcastclient = 1; }
418	|	T_Manycastserver address_list
419			{ append_queue(cfgt.manycastserver, $2); }
420	|	T_Multicastclient address_list
421			{ append_queue(cfgt.multicastclient, $2); }
422	;
423
424
425
426/* Authentication Commands
427 * -----------------------
428 */
429
430authentication_command
431	:	T_Automax T_Integer
432			{ enqueue(cfgt.vars, create_attr_ival($1, $2)); }
433	|	T_ControlKey T_Integer
434			{ cfgt.auth.control_key = $2; }
435	|	T_Crypto crypto_command_line
436		{
437			cfgt.auth.cryptosw++;
438			append_queue(cfgt.auth.crypto_cmd_list, $2);
439		}
440	|	T_Keys T_String
441			{ cfgt.auth.keys = $2; }
442	|	T_Keysdir T_String
443			{ cfgt.auth.keysdir = $2; }
444	|	T_Requestkey T_Integer
445			{ cfgt.auth.request_key = $2; }
446	|	T_Revoke T_Integer
447			{ cfgt.auth.revoke = $2; }
448	|	T_Trustedkey integer_list
449			{ cfgt.auth.trusted_key_list = $2; }
450	|	T_NtpSignDsocket T_String
451			{ cfgt.auth.ntp_signd_socket = $2; }
452	;
453
454crypto_command_line
455	:	crypto_command_list
456	|	/* Null list */
457			{ $$ = create_queue(); }
458	;
459
460crypto_command_list
461	:	crypto_command_list crypto_command
462		{
463			if ($2 != NULL)
464				$$ = enqueue($1, $2);
465			else
466				$$ = $1;
467		}
468	|	crypto_command
469		{
470			if ($1 != NULL)
471				$$ = enqueue_in_new_queue($1);
472			else
473				$$ = create_queue();
474		}
475	;
476
477crypto_command
478	:	T_Host	T_String
479			{ $$ = create_attr_sval($1, $2); }
480	|	T_Ident	T_String
481			{ $$ = create_attr_sval($1, $2); }
482	|	T_Pw T_String
483			{ $$ = create_attr_sval($1, $2); }
484	|	T_Randfile T_String
485			{ $$ = create_attr_sval($1, $2); }
486	|	T_Sign	T_String
487			{ $$ = create_attr_sval($1, $2); }
488	|	T_Digest T_String
489			{ $$ = create_attr_sval($1, $2); }
490	|	T_Revoke T_Integer
491		{
492			$$ = NULL;
493			cfgt.auth.revoke = $2;
494			msyslog(LOG_WARNING,
495				"'crypto revoke %d' is deprecated, "
496				"please use 'revoke %d' instead.",
497				cfgt.auth.revoke, cfgt.auth.revoke);
498		}
499	;
500
501
502/* Orphan Mode Commands
503 * --------------------
504 */
505
506orphan_mode_command
507	:	T_Tos tos_option_list
508			{ append_queue(cfgt.orphan_cmds,$2); }
509	;
510
511tos_option_list
512	:	tos_option_list tos_option { $$ = enqueue($1, $2); }
513	|	tos_option { $$ = enqueue_in_new_queue($1); }
514	;
515
516tos_option
517	:	T_Ceiling T_Integer
518			{ $$ = create_attr_dval($1, (double)$2); }
519	|	T_Floor T_Integer
520			{ $$ = create_attr_dval($1, (double)$2); }
521	|	T_Cohort boolean
522			{ $$ = create_attr_dval($1, (double)$2); }
523	|	T_Orphan T_Integer
524			{ $$ = create_attr_dval($1, (double)$2); }
525	|	T_Mindist number
526			{ $$ = create_attr_dval($1, $2); }
527	|	T_Maxdist number
528			{ $$ = create_attr_dval($1, $2); }
529	|	T_Minclock number
530			{ $$ = create_attr_dval($1, $2); }
531	|	T_Maxclock number
532			{ $$ = create_attr_dval($1, $2); }
533	|	T_Minsane T_Integer
534			{ $$ = create_attr_dval($1, (double)$2); }
535	|	T_Beacon T_Integer
536			{ $$ = create_attr_dval($1, (double)$2); }
537	;
538
539
540/* Monitoring Commands
541 * -------------------
542 */
543
544monitoring_command
545	:	T_Statistics stats_list
546			{ append_queue(cfgt.stats_list, $2); }
547	|	T_Statsdir T_String
548		{
549			if (input_from_file)
550				cfgt.stats_dir = $2;
551			else {
552				free($2);
553				yyerror("statsdir remote configuration ignored");
554			}
555		}
556	|	T_Filegen stat filegen_option_list
557		{
558			enqueue(cfgt.filegen_opts,
559				create_filegen_node($2, $3));
560		}
561	;
562
563stats_list
564	:	stats_list stat { $$ = enqueue($1, create_ival($2)); }
565	|	stat { $$ = enqueue_in_new_queue(create_ival($1)); }
566	;
567
568stat
569	:	T_Clockstats
570	|	T_Cryptostats
571	|	T_Loopstats
572	|	T_Peerstats
573	|	T_Rawstats
574	|	T_Sysstats
575	|	T_Timingstats
576	|	T_Protostats
577	;
578
579filegen_option_list
580	:	filegen_option_list filegen_option
581		{
582			if ($2 != NULL)
583				$$ = enqueue($1, $2);
584			else
585				$$ = $1;
586		}
587	|	filegen_option
588		{
589			if ($1 != NULL)
590				$$ = enqueue_in_new_queue($1);
591			else
592				$$ = create_queue();
593		}
594	;
595
596filegen_option
597	:	T_File T_String
598		{
599			if (input_from_file)
600				$$ = create_attr_sval($1, $2);
601			else {
602				$$ = NULL;
603				free($2);
604				yyerror("filegen file remote configuration ignored");
605			}
606		}
607	|	T_Type filegen_type
608		{
609			if (input_from_file)
610				$$ = create_attr_ival($1, $2);
611			else {
612				$$ = NULL;
613				yyerror("filegen type remote configuration ignored");
614			}
615		}
616	|	T_Link
617		{
618			if (input_from_file)
619				$$ = create_attr_ival(T_Flag, $1);
620			else {
621				$$ = NULL;
622				yyerror("filegen link remote configuration ignored");
623			}
624		}
625	|	T_Nolink
626		{
627			if (input_from_file)
628				$$ = create_attr_ival(T_Flag, $1);
629			else {
630				$$ = NULL;
631				yyerror("filegen nolink remote configuration ignored");
632			}
633		}
634	|	T_Enable	{ $$ = create_attr_ival(T_Flag, $1); }
635	|	T_Disable	{ $$ = create_attr_ival(T_Flag, $1); }
636	;
637
638filegen_type
639	:	T_None
640	|	T_Pid
641	|	T_Day
642	|	T_Week
643	|	T_Month
644	|	T_Year
645	|	T_Age
646	;
647
648
649/* Access Control Commands
650 * -----------------------
651 */
652
653access_control_command
654	:	T_Discard discard_option_list
655		{
656			append_queue(cfgt.discard_opts, $2);
657		}
658	|	T_Restrict address ac_flag_list
659		{
660			enqueue(cfgt.restrict_opts,
661				create_restrict_node($2, NULL, $3, ip_file->line_no));
662		}
663	|	T_Restrict T_Default ac_flag_list
664		{
665			enqueue(cfgt.restrict_opts,
666				create_restrict_node(NULL, NULL, $3, ip_file->line_no));
667		}
668	|	T_Restrict T_Ipv4_flag T_Default ac_flag_list
669		{
670			enqueue(cfgt.restrict_opts,
671				create_restrict_node(
672					create_address_node(
673						estrdup("0.0.0.0"),
674						AF_INET),
675					create_address_node(
676						estrdup("255.255.255.255"),
677						AF_INET),
678					$4,
679					ip_file->line_no));
680		}
681	|	T_Restrict T_Ipv6_flag T_Default ac_flag_list
682		{
683			enqueue(cfgt.restrict_opts,
684				create_restrict_node(
685					create_address_node(
686						estrdup("::"),
687						AF_INET6),
688					create_address_node(
689						estrdup("ffff:ffff:ffff:ffff:ffff:ffff:ffff:ffff"),
690						AF_INET6),
691					$4,
692					ip_file->line_no));
693		}
694	|	T_Restrict ip_address T_Mask ip_address ac_flag_list
695		{
696			enqueue(cfgt.restrict_opts,
697				create_restrict_node($2, $4, $5, ip_file->line_no));
698		}
699	;
700
701ac_flag_list
702	:	/* Null statement */
703			{ $$ = create_queue(); }
704	|	ac_flag_list access_control_flag
705			{ $$ = enqueue($1, create_ival($2)); }
706	;
707
708access_control_flag
709	:	T_Flake
710	|	T_Ignore
711	|	T_Kod
712	|	T_Mssntp
713	|	T_Limited
714	|	T_Lowpriotrap
715	|	T_Nomodify
716	|	T_Nopeer
717	|	T_Noquery
718	|	T_Noserve
719	|	T_Notrap
720	|	T_Notrust
721	|	T_Ntpport
722	|	T_Version
723	;
724
725discard_option_list
726	:	discard_option_list discard_option
727			{ $$ = enqueue($1, $2); }
728	|	discard_option
729			{ $$ = enqueue_in_new_queue($1); }
730	;
731
732discard_option
733	:	T_Average T_Integer { $$ = create_attr_ival($1, $2); }
734	|	T_Minimum T_Integer { $$ = create_attr_ival($1, $2); }
735	|	T_Monitor T_Integer { $$ = create_attr_ival($1, $2); }
736	;
737
738/* Fudge Commands
739 * --------------
740 */
741
742fudge_command
743	:	T_Fudge address fudge_factor_list
744			{ enqueue(cfgt.fudge, create_addr_opts_node($2, $3)); }
745	;
746
747fudge_factor_list
748	:	fudge_factor_list fudge_factor
749			{ enqueue($1, $2); }
750	|	fudge_factor
751			{ $$ = enqueue_in_new_queue($1); }
752	;
753
754fudge_factor
755	:	T_Time1 number		{ $$ = create_attr_dval($1, $2); }
756	|	T_Time2 number		{ $$ = create_attr_dval($1, $2); }
757	|	T_Stratum T_Integer	{ $$ = create_attr_ival($1, $2); }
758	|	T_Refid T_String	{ $$ = create_attr_sval($1, $2); }
759	|	T_Flag1 boolean		{ $$ = create_attr_ival($1, $2); }
760	|	T_Flag2	boolean		{ $$ = create_attr_ival($1, $2); }
761	|	T_Flag3	boolean		{ $$ = create_attr_ival($1, $2); }
762	|	T_Flag4 boolean		{ $$ = create_attr_ival($1, $2); }
763	;
764
765/* Command for System Options
766 * --------------------------
767 */
768
769system_option_command
770	:	T_Enable system_option_list
771			{ append_queue(cfgt.enable_opts, $2);  }
772	|	T_Disable system_option_list
773			{ append_queue(cfgt.disable_opts, $2);  }
774	;
775
776system_option_list
777	:	system_option_list system_option
778		{
779			if ($2 != NULL)
780				$$ = enqueue($1, $2);
781			else
782				$$ = $1;
783		}
784	|	system_option
785		{
786			if ($1 != NULL)
787				$$ = enqueue_in_new_queue($1);
788			else
789				$$ = create_queue();
790		}
791	;
792
793system_option
794	:	T_Auth      { $$ = create_attr_ival(T_Flag, $1); }
795	|	T_Bclient   { $$ = create_attr_ival(T_Flag, $1); }
796	|	T_Calibrate { $$ = create_attr_ival(T_Flag, $1); }
797	|	T_Kernel    { $$ = create_attr_ival(T_Flag, $1); }
798	|	T_Monitor   { $$ = create_attr_ival(T_Flag, $1); }
799	|	T_Ntp       { $$ = create_attr_ival(T_Flag, $1); }
800	|	T_Stats
801		{
802			if (input_from_file)
803				$$ = create_attr_ival(T_Flag, $1);
804			else {
805				$$ = NULL;
806				yyerror("enable/disable stats remote configuration ignored");
807			}
808		}
809	;
810
811/* Tinker Commands
812 * ---------------
813 */
814
815tinker_command
816	:	T_Tinker tinker_option_list  { append_queue(cfgt.tinker, $2); }
817	;
818
819tinker_option_list
820	:	tinker_option_list tinker_option  { $$ = enqueue($1, $2); }
821	|	tinker_option { $$ = enqueue_in_new_queue($1); }
822	;
823
824tinker_option
825	:	T_Allan number	    { $$ = create_attr_dval($1, $2); }
826	|	T_Dispersion number { $$ = create_attr_dval($1, $2); }
827	|	T_Freq number	    { $$ = create_attr_dval($1, $2); }
828	|	T_Huffpuff number   { $$ = create_attr_dval($1, $2); }
829	|	T_Panic number	    { $$ = create_attr_dval($1, $2); }
830	|	T_Step number	    { $$ = create_attr_dval($1, $2); }
831	|	T_Stepout number    { $$ = create_attr_dval($1, $2); }
832	;
833
834
835/* Miscellaneous Commands
836 * ----------------------
837 */
838
839miscellaneous_command
840	:	interface_command
841	|	T_Includefile T_String command
842		{
843			if (curr_include_level >= MAXINCLUDELEVEL) {
844				fprintf(stderr, "getconfig: Maximum include file level exceeded.\n");
845				msyslog(LOG_ERR, "getconfig: Maximum include file level exceeded.");
846			}
847			else {
848				fp[curr_include_level + 1] = F_OPEN(FindConfig($2), "r");
849				if (fp[curr_include_level + 1] == NULL) {
850					fprintf(stderr, "getconfig: Couldn't open <%s>\n", FindConfig($2));
851					msyslog(LOG_ERR, "getconfig: Couldn't open <%s>", FindConfig($2));
852				}
853				else
854					ip_file = fp[++curr_include_level];
855			}
856		}
857	|	T_End
858		{
859			while (curr_include_level != -1)
860				FCLOSE(fp[curr_include_level--]);
861		}
862
863	|	T_Broadcastdelay number
864			{ enqueue(cfgt.vars, create_attr_dval($1, $2)); }
865	|	T_Calldelay T_Integer
866			{ enqueue(cfgt.vars, create_attr_ival($1, $2)); }
867	|	T_Tick number
868			{ enqueue(cfgt.vars, create_attr_dval($1, $2)); }
869	|	T_Driftfile drift_parm
870			{ /* Null action, possibly all null parms */ }
871	|	T_Leapfile T_String
872			{ enqueue(cfgt.vars, create_attr_sval($1, $2)); }
873
874	|	T_Pidfile T_String
875			{ enqueue(cfgt.vars, create_attr_sval($1, $2)); }
876	|	T_Logfile T_String
877		{
878			if (input_from_file)
879				enqueue(cfgt.vars,
880					create_attr_sval($1, $2));
881			else {
882				free($2);
883				yyerror("logfile remote configuration ignored");
884			}
885		}
886
887	|	T_Logconfig log_config_list
888			{ append_queue(cfgt.logconfig, $2); }
889	|	T_Phone string_list
890			{ append_queue(cfgt.phone, $2); }
891	|	T_Saveconfigdir	T_String
892		{
893			if (input_from_file)
894				enqueue(cfgt.vars,
895					create_attr_sval($1, $2));
896			else {
897				free($2);
898				yyerror("saveconfigdir remote configuration ignored");
899			}
900		}
901	|	T_Setvar variable_assign
902			{ enqueue(cfgt.setvar, $2); }
903	|	T_Trap ip_address
904			{ enqueue(cfgt.trap, create_addr_opts_node($2, NULL)); }
905	|	T_Trap ip_address trap_option_list
906			{ enqueue(cfgt.trap, create_addr_opts_node($2, $3)); }
907	|	T_Ttl integer_list
908			{ append_queue(cfgt.ttl, $2); }
909	|	T_Qos T_String
910			{ enqueue(cfgt.qos, create_attr_sval($1, $2)); }
911	;
912
913drift_parm
914	:	T_String
915			{ enqueue(cfgt.vars, create_attr_sval(T_Driftfile, $1)); }
916	|	T_String T_Double
917			{ enqueue(cfgt.vars, create_attr_dval(T_WanderThreshold, $2));
918			  enqueue(cfgt.vars, create_attr_sval(T_Driftfile, $1)); }
919	|	/* Null driftfile,  indicated by null string "\0" */
920			{ enqueue(cfgt.vars, create_attr_sval(T_Driftfile, "\0")); }
921	;
922
923variable_assign
924	:	T_String '=' T_String T_Default
925			{ $$ = create_setvar_node($1, $3, $4); }
926	|	T_String '=' T_String
927			{ $$ = create_setvar_node($1, $3, 0); }
928	;
929
930trap_option_list
931	:	trap_option_list trap_option
932				{ $$ = enqueue($1, $2); }
933	|	trap_option	{ $$ = enqueue_in_new_queue($1); }
934	;
935
936trap_option
937	:	T_Port T_Integer	{ $$ = create_attr_ival($1, $2); }
938	|	T_Interface ip_address	{ $$ = create_attr_pval($1, $2); }
939	;
940
941log_config_list
942	:	log_config_list log_config_command { $$ = enqueue($1, $2); }
943	|	log_config_command  { $$ = enqueue_in_new_queue($1); }
944	;
945
946log_config_command
947	:	T_String
948		{
949			char prefix = $1[0];
950			char *type = $1 + 1;
951
952			if (prefix != '+' && prefix != '-' && prefix != '=') {
953				yyerror("Logconfig prefix is not '+', '-' or '='\n");
954			}
955			else
956				$$ = create_attr_sval(prefix, estrdup(type));
957			YYFREE($1);
958		}
959	;
960
961interface_command
962	:	interface_nic nic_rule_action nic_rule_class
963		{
964			enqueue(cfgt.nic_rules,
965				create_nic_rule_node($3, NULL, $2));
966		}
967	|	interface_nic nic_rule_action T_String
968		{
969			enqueue(cfgt.nic_rules,
970				create_nic_rule_node(0, $3, $2));
971		}
972	;
973
974interface_nic
975	:	T_Interface
976	|	T_Nic
977	;
978
979nic_rule_class
980	:	T_All
981	|	T_Ipv4
982	|	T_Ipv6
983	|	T_Wildcard
984	;
985
986nic_rule_action
987	:	T_Listen
988	|	T_Ignore
989	|	T_Drop
990	;
991
992
993
994/* Miscellaneous Rules
995 * -------------------
996 */
997
998integer_list
999	:	integer_list T_Integer { $$ = enqueue($1, create_ival($2)); }
1000	|	T_Integer { $$ = enqueue_in_new_queue(create_ival($1)); }
1001	;
1002
1003string_list
1004	:	string_list T_String { $$ = enqueue($1, create_pval($2)); }
1005	|	T_String { $$ = enqueue_in_new_queue(create_pval($1)); }
1006	;
1007
1008address_list
1009	:	address_list address { $$ = enqueue($1, $2); }
1010	|	address { $$ = enqueue_in_new_queue($1); }
1011	;
1012
1013boolean
1014	:	T_Integer
1015		{
1016			if ($1 != 0 && $1 != 1) {
1017				yyerror("Integer value is not boolean (0 or 1). Assuming 1");
1018				$$ = 1;
1019			}
1020			else
1021				$$ = $1;
1022		}
1023	|	T_True    { $$ = 1; }
1024	|	T_False   { $$ = 0; }
1025	;
1026
1027number
1028	:	T_Integer { $$ = (double)$1; }
1029	|	T_Double
1030	;
1031
1032
1033/* Simulator Configuration Commands
1034 * --------------------------------
1035 */
1036
1037simulate_command
1038	:	sim_conf_start '{' sim_init_statement_list sim_server_list '}'
1039		{
1040			cfgt.sim_details = create_sim_node($3, $4);
1041
1042			/* Reset the old_config_style variable */
1043			old_config_style = 1;
1044		}
1045	;
1046
1047/* The following is a terrible hack to get the configuration file to
1048 * treat newlines as whitespace characters within the simulation.
1049 * This is needed because newlines are significant in the rest of the
1050 * configuration file.
1051 */
1052sim_conf_start
1053	:	T_Simulate { old_config_style = 0; }
1054	;
1055
1056sim_init_statement_list
1057	:	sim_init_statement_list sim_init_statement T_EOC { $$ = enqueue($1, $2); }
1058	|	sim_init_statement T_EOC			 { $$ = enqueue_in_new_queue($1); }
1059	;
1060
1061sim_init_statement
1062	:	T_Beep_Delay '=' number   { $$ = create_attr_dval($1, $3); }
1063	|	T_Sim_Duration '=' number { $$ = create_attr_dval($1, $3); }
1064	;
1065
1066sim_server_list
1067	:	sim_server_list sim_server { $$ = enqueue($1, $2); }
1068	|	sim_server		   { $$ = enqueue_in_new_queue($1); }
1069	;
1070
1071sim_server
1072	:	sim_server_name '{' sim_server_offset sim_act_list '}'
1073		{ $$ = create_sim_server($1, $3, $4); }
1074	;
1075
1076sim_server_offset
1077	:	T_Server_Offset '=' number T_EOC { $$ = $3; }
1078	;
1079
1080sim_server_name
1081	:	T_Server '=' address { $$ = $3; }
1082	;
1083
1084sim_act_list
1085	:	sim_act_list sim_act { $$ = enqueue($1, $2); }
1086	|	sim_act		     { $$ = enqueue_in_new_queue($1); }
1087	;
1088
1089sim_act
1090	:	T_Duration '=' number '{' sim_act_stmt_list '}'
1091			{ $$ = create_sim_script_info($3, $5); }
1092	;
1093
1094sim_act_stmt_list
1095	:	sim_act_stmt_list sim_act_stmt T_EOC { $$ = enqueue($1, $2); }
1096	|	sim_act_stmt T_EOC		     { $$ = enqueue_in_new_queue($1); }
1097	;
1098
1099sim_act_stmt
1100	:	T_Freq_Offset '=' number
1101			{ $$ = create_attr_dval($1, $3); }
1102	|	T_Wander '=' number
1103			{ $$ = create_attr_dval($1, $3); }
1104	|	T_Jitter '=' number
1105			{ $$ = create_attr_dval($1, $3); }
1106	|	T_Prop_Delay '=' number
1107			{ $$ = create_attr_dval($1, $3); }
1108	|	T_Proc_Delay '=' number
1109			{ $$ = create_attr_dval($1, $3); }
1110	;
1111
1112
1113%%
1114
1115void yyerror (char *msg)
1116{
1117	int retval;
1118
1119	ip_file->err_line_no = ip_file->prev_token_line_no;
1120	ip_file->err_col_no = ip_file->prev_token_col_no;
1121
1122	msyslog(LOG_ERR,
1123		"line %d column %d %s",
1124		ip_file->err_line_no,
1125		ip_file->err_col_no,
1126		msg);
1127	if (!input_from_file) {
1128		/* Save the error message in the correct buffer */
1129		retval = snprintf(remote_config.err_msg + remote_config.err_pos,
1130				  MAXLINE - remote_config.err_pos,
1131				  "column %d %s",
1132				  ip_file->err_col_no, msg);
1133
1134		/* Increment the value of err_pos */
1135		if (retval > 0)
1136			remote_config.err_pos += retval;
1137
1138		/* Increment the number of errors */
1139		++remote_config.no_errors;
1140	}
1141}
1142
1143
1144/*
1145 * token_name - convert T_ token integers to text
1146 *		example: token_name(T_Server) returns "T_Server"
1147 */
1148const char *
1149token_name(
1150	int token
1151	)
1152{
1153	return yytname[YYTRANSLATE(token)];
1154}
1155
1156
1157/* Initial Testing function -- ignore
1158int main(int argc, char *argv[])
1159{
1160	ip_file = FOPEN(argv[1], "r");
1161	if (!ip_file) {
1162		fprintf(stderr, "ERROR!! Could not open file: %s\n", argv[1]);
1163	}
1164	key_scanner = create_keyword_scanner(keyword_list);
1165	print_keyword_scanner(key_scanner, 0);
1166	yyparse();
1167	return 0;
1168}
1169*/
1170
1171