parser.y revision 62638
1/*	$KAME$	*/
2
3/*
4 * Copyright (C) 1995, 1996, 1997, and 1998 WIDE Project.
5 * All rights reserved.
6 *
7 * Redistribution and use in source and binary forms, with or without
8 * modification, are permitted provided that the following conditions
9 * are met:
10 * 1. Redistributions of source code must retain the above copyright
11 *    notice, this list of conditions and the following disclaimer.
12 * 2. Redistributions in binary form must reproduce the above copyright
13 *    notice, this list of conditions and the following disclaimer in the
14 *    documentation and/or other materials provided with the distribution.
15 * 3. Neither the name of the project nor the names of its contributors
16 *    may be used to endorse or promote products derived from this software
17 *    without specific prior written permission.
18 *
19 * THIS SOFTWARE IS PROVIDED BY THE PROJECT AND CONTRIBUTORS ``AS IS'' AND
20 * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
21 * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
22 * ARE DISCLAIMED.  IN NO EVENT SHALL THE PROJECT OR CONTRIBUTORS BE LIABLE
23 * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
24 * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
25 * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
26 * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
27 * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
28 * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
29 * SUCH DAMAGE.
30 *
31 * $FreeBSD: head/usr.sbin/rrenumd/parser.y 62638 2000-07-05 11:12:53Z kris $
32 */
33
34%{
35#include <sys/param.h>
36#include <sys/ioctl.h>
37#include <sys/socket.h>
38#include <sys/uio.h>
39
40#include <net/if.h>
41#if defined(__FreeBSD__) && __FreeBSD__ >= 3
42#include <net/if_var.h>
43#endif /* __FreeBSD__ >= 3 */
44
45#include <netinet/in.h>
46#include <netinet/in_var.h>
47#include <netinet/icmp6.h>
48
49#include <netdb.h>
50#include <string.h>
51
52#include "rrenumd.h"
53
54struct config_is_set {
55	u_short cis_dest : 1;
56} cis;
57
58struct dst_list *dl_head;
59struct payload_list *pl_head, ple_cur;
60u_int retry;
61char errbuf[LINE_MAX];
62
63extern int lineno;
64extern void yyerror __P((const char *s));
65static struct payload_list * pllist_lookup __P((int seqnum));
66static void pllist_enqueue __P((struct payload_list *pl_entry));
67
68#define MAX_RETRYNUM 10 /* upper limit of retry in this rrenumd program */
69#define MAX_SEQNUM 256 /* upper limit of seqnum in this rrenumd program */
70#define NOSPEC	-1
71
72%}
73
74%union {
75	u_long num;
76	struct {
77		char *cp;
78		int len;
79	} cs;
80	struct in_addr addr4;
81	struct in6_addr addr6;
82	struct {
83		struct in6_addr addr;
84		u_char plen;
85	} prefix;
86	struct dst_list *dl;
87	struct payload_list *pl;
88	struct sockaddr *sa;
89}
90
91%token <num> ADD CHANGE SETGLOBAL
92%token DEBUG_CMD DEST_CMD RETRY_CMD SEQNUM_CMD
93%token MATCH_PREFIX_CMD MAXLEN_CMD MINLEN_CMD
94%token USE_PREFIX_CMD KEEPLEN_CMD
95%token VLTIME_CMD PLTIME_CMD
96%token RAF_ONLINK_CMD RAF_AUTO_CMD RAF_DECRVALID_CMD RAF_DECRPREFD_CMD
97%token <num> DAYS HOURS MINUTES SECONDS INFINITY
98%token <num> ON OFF
99%token BCL ECL EOS ERROR
100%token <cs> NAME HOSTNAME QSTRING DECSTRING
101%token <addr4> IPV4ADDR
102%token <addr6> IPV6ADDR
103%token <num> PREFIXLEN
104
105%type <num> retrynum seqnum rrenum_cmd
106%type <num> prefixlen maxlen minlen keeplen vltime pltime
107%type <num> lifetime days hours minutes seconds
108%type <num> decstring
109%type <num> raf_onlink raf_auto raf_decrvalid raf_decrprefd flag
110%type <dl> dest_addrs dest_addr sin sin6
111%type <pl> rrenum_statement
112%type <cs> ifname
113%type <prefix> prefixval
114
115%%
116config:
117		/* empty */
118	| 	statements
119	;
120
121statements:
122		statement
123	| 	statements statement
124	;
125
126statement:
127		debug_statement
128	|	destination_statement
129	|	rrenum_statement_without_seqnum
130	|	rrenum_statement_with_seqnum
131	|	error EOS
132		{
133			yyerrok;
134		}
135	|	EOS
136	;
137
138debug_statement:
139		DEBUG_CMD flag EOS
140		{
141#ifdef YYDEBUG
142			yydebug = $2;
143#endif /* YYDEBUG */
144		}
145	;
146
147destination_statement:
148		DEST_CMD dest_addrs retrynum EOS
149		{
150			dl_head = $2;
151			retry = $3;
152		}
153	;
154
155dest_addrs:
156		dest_addr
157	|	dest_addrs dest_addr
158		{
159			$2->dl_next = $1;
160			$$ = $2;
161		}
162	;
163
164dest_addr :
165		sin
166		{
167			with_v4dest = 1;
168		}
169	|	sin6
170		{
171			with_v6dest = 1;
172		}
173	|	sin6 ifname
174		{
175			struct sockaddr_in6 *sin6;
176
177			sin6 = (struct sockaddr_in6 *)$1->dl_dst;
178			sin6->sin6_scope_id = if_nametoindex($2.cp);
179			with_v6dest = 1;
180			$$ = $1;
181		}
182	|	HOSTNAME
183		{
184			struct sockaddr_storage *ss;
185			struct addrinfo hints, *res;
186			int error;
187
188			memset(&hints, 0, sizeof(hints));
189			hints.ai_flags = AI_CANONNAME;
190			hints.ai_family = AF_UNSPEC;
191			hints.ai_socktype = SOCK_RAW;
192			hints.ai_protocol = 0;
193			error = getaddrinfo($1.cp, 0, &hints, &res);
194			if (error) {
195				sprintf(errbuf, "name resolution failed for %s"
196				":%s", $1, gai_strerror(error));
197				yyerror(errbuf);
198			}
199			ss = (struct sockaddr_storage *)malloc(sizeof(*ss));
200			memset(ss, 0, sizeof(*ss));
201			memcpy(ss, res->ai_addr, res->ai_addr->sa_len);
202			freeaddrinfo(res);
203
204			$$ = (struct dst_list *)
205			     malloc(sizeof(struct dst_list));
206			memset($$, 0, sizeof(struct dst_list));
207			$$->dl_dst = (struct sockaddr *)ss;
208		}
209	;
210
211sin:
212		IPV4ADDR
213		{
214			struct sockaddr_in *sin;
215
216			sin = (struct sockaddr_in *)malloc(sizeof(*sin));
217			memset(sin, 0, sizeof(*sin));
218			sin->sin_len = sizeof(*sin);
219			sin->sin_family = AF_INET;
220			sin->sin_addr = $1;
221
222			$$ = (struct dst_list *)
223			     malloc(sizeof(struct dst_list));
224			memset($$, 0, sizeof(struct dst_list));
225			$$->dl_dst = (struct sockaddr *)sin;
226		}
227	;
228
229sin6:
230		IPV6ADDR
231		{
232			struct sockaddr_in6 *sin6;
233
234			sin6 = (struct sockaddr_in6 *)malloc(sizeof(*sin6));
235			memset(sin6, 0, sizeof(*sin6));
236			sin6->sin6_len = sizeof(*sin6);
237			sin6->sin6_family = AF_INET6;
238			sin6->sin6_addr = $1;
239
240			$$ = (struct dst_list *)
241			     malloc(sizeof(struct dst_list));
242			memset($$, 0, sizeof(struct dst_list));
243			$$->dl_dst = (struct sockaddr *)sin6;
244		}
245
246ifname:
247		NAME
248		{
249			$$.cp = strdup($1.cp);
250			$$.len = $1.len;
251		}
252	|	QSTRING
253		{
254			$1.cp[$1.len - 1] = 0;
255			$$.cp = strdup(&$1.cp[1]);
256			$$.len = $1.len - 2;
257		}
258	;
259
260retrynum:
261		/* empty */
262		{
263			$$ = 2;
264		}
265	|	RETRY_CMD decstring
266		{
267			if ($2 > MAX_RETRYNUM)
268				$2 = MAX_RETRYNUM;
269			$$ = $2;
270		}
271	;
272
273rrenum_statement_with_seqnum:
274		SEQNUM_CMD seqnum
275		{
276			if (pllist_lookup($2)) {
277				sprintf(errbuf, "duplicate seqnum %d specified"
278					" at %d", $2, lineno);
279				yyerror(errbuf);
280			}
281		}
282		BCL rrenum_statement EOS ECL EOS
283		{
284			$5->pl_irr.rr_seqnum = $2;
285			pllist_enqueue($5);
286		}
287	;
288
289seqnum:
290		/* empty */
291		{
292			$$ = 0;
293		}
294	|	decstring
295		{
296			if ($1 > MAX_SEQNUM) {
297				sprintf(errbuf, "seqnum %d is illegal for this"
298					" program. should be between 0 and %d",
299					$1, MAX_SEQNUM);
300				yyerror(errbuf);
301			}
302			$$ = $1;
303		}
304	;
305
306rrenum_statement_without_seqnum:
307		rrenum_statement EOS
308		{
309			if (pllist_lookup(0)) {
310				sprintf(errbuf, "duplicate seqnum %d specified"
311					" at %d", 0, lineno);
312				yyerror(errbuf);
313			}
314			$1->pl_irr.rr_seqnum = 0;
315			pllist_enqueue($1);
316		}
317	;
318
319rrenum_statement:
320		match_prefix_definition use_prefix_definition
321		{
322			$$ = (struct payload_list *)
323			     malloc(sizeof(struct payload_list));
324			memcpy($$, &ple_cur, sizeof(ple_cur));
325		}
326	;
327
328match_prefix_definition:
329		rrenum_cmd MATCH_PREFIX_CMD prefixval maxlen minlen
330		{
331			struct icmp6_router_renum *irr;
332			struct rr_pco_match *rpm;
333
334			irr = (struct icmp6_router_renum *)&ple_cur.pl_irr;
335			rpm = (struct rr_pco_match *)(irr + 1);
336			memset(rpm, 0, sizeof(*rpm));
337
338			rpm->rpm_code = $1;
339			rpm->rpm_prefix = $3.addr;
340			rpm->rpm_matchlen = $3.plen;
341			rpm->rpm_maxlen = $4;
342			rpm->rpm_minlen = $5;
343		}
344	;
345
346rrenum_cmd:
347		/* empty */
348		{
349			$$ = RPM_PCO_ADD;
350		}
351	|	ADD
352	|	CHANGE
353	|	SETGLOBAL
354	;
355
356prefixval:
357		IPV6ADDR prefixlen
358		{
359			$$.addr = $1;
360			$$.plen = $2;
361		}
362	;
363
364prefixlen:
365		/* empty */
366		{
367			$$ = 64;
368		}
369	|	PREFIXLEN
370	;
371
372maxlen:
373		/* empty */
374		{
375			$$ = 128;
376		}
377	|	MAXLEN_CMD decstring
378		{
379			if ($2 > 128)
380				$2 = 128;
381			$$ = $2;
382		}
383	;
384
385minlen:
386		/* empty */
387		{
388			$$ = 0;
389		}
390	|	MINLEN_CMD decstring
391		{
392			if ($2 > 128)
393				$2 = 128;
394			$$ = $2;
395		}
396	;
397
398use_prefix_definition:
399		/* empty */
400		{
401			struct icmp6_router_renum *irr;
402			struct rr_pco_match *rpm;
403			struct rr_pco_use *rpu;
404
405			irr = (struct icmp6_router_renum *)&ple_cur.pl_irr;
406			rpm = (struct rr_pco_match *)(irr + 1);
407			rpu = (struct rr_pco_use *)(rpm + 1);
408			memset(rpu, 0, sizeof(*rpu));
409		}
410	|	USE_PREFIX_CMD prefixval keeplen use_prefix_values
411		{
412			struct icmp6_router_renum *irr;
413			struct rr_pco_match *rpm;
414			struct rr_pco_use *rpu;
415
416			irr = (struct icmp6_router_renum *)&ple_cur.pl_irr;
417			rpm = (struct rr_pco_match *)(irr + 1);
418			rpu = (struct rr_pco_use *)(rpm + 1);
419
420			rpu->rpu_prefix = $2.addr;
421			rpu->rpu_uselen = $2.plen;
422			rpu->rpu_keeplen = $3;
423		}
424	;
425
426use_prefix_values:
427		/* empty */
428		{
429			struct icmp6_router_renum *irr;
430			struct rr_pco_match *rpm;
431			struct rr_pco_use *rpu;
432
433			irr = (struct icmp6_router_renum *)&ple_cur.pl_irr;
434			rpm = (struct rr_pco_match *)(irr + 1);
435			rpu = (struct rr_pco_use *)(rpm + 1);
436			memset(rpu, 0, sizeof(*rpu));
437
438			rpu->rpu_vltime = DEF_VLTIME;
439			rpu->rpu_pltime = DEF_PLTIME;
440			rpu->rpu_ramask = 0;
441			rpu->rpu_flags = 0;
442		}
443	|	BCL vltime pltime raf_onlink raf_auto raf_decrvalid raf_decrprefd ECL
444		{
445			struct icmp6_router_renum *irr;
446			struct rr_pco_match *rpm;
447			struct rr_pco_use *rpu;
448
449			irr = (struct icmp6_router_renum *)&ple_cur.pl_irr;
450			rpm = (struct rr_pco_match *)(irr + 1);
451			rpu = (struct rr_pco_use *)(rpm + 1);
452			memset(rpu, 0, sizeof(*rpu));
453
454			rpu->rpu_vltime = $2;
455			rpu->rpu_pltime = $3;
456			if ($4 == NOSPEC) {
457				rpu->rpu_ramask &=
458				    ~ICMP6_RR_PCOUSE_RAFLAGS_ONLINK;
459			} else {
460				rpu->rpu_ramask |=
461				    ICMP6_RR_PCOUSE_RAFLAGS_ONLINK;
462				if ($4 == ON) {
463					rpu->rpu_raflags |=
464					    ICMP6_RR_PCOUSE_RAFLAGS_ONLINK;
465				} else {
466					rpu->rpu_raflags &=
467					    ~ICMP6_RR_PCOUSE_RAFLAGS_ONLINK;
468				}
469			}
470			if ($5 == NOSPEC) {
471				rpu->rpu_ramask &=
472				    ICMP6_RR_PCOUSE_RAFLAGS_AUTO;
473			} else {
474				rpu->rpu_ramask |=
475				    ICMP6_RR_PCOUSE_RAFLAGS_AUTO;
476				if ($5 == ON) {
477					rpu->rpu_raflags |=
478					    ICMP6_RR_PCOUSE_RAFLAGS_AUTO;
479				} else {
480					rpu->rpu_raflags &=
481					    ~ICMP6_RR_PCOUSE_RAFLAGS_AUTO;
482				}
483			}
484			rpu->rpu_flags = 0;
485			if ($6 == ON) {
486				rpu->rpu_flags |=
487				    ICMP6_RR_PCOUSE_FLAGS_DECRVLTIME;
488			}
489			if ($7 == ON) {
490				rpu->rpu_flags |=
491				    ICMP6_RR_PCOUSE_FLAGS_DECRPLTIME;
492			}
493		}
494	;
495
496keeplen:
497		/* empty */
498		{
499			$$ = 0;
500		}
501	|	KEEPLEN_CMD decstring
502		{
503			if ($2 > 128)
504				$2 = 128;
505			$$ = $2;
506		}
507	;
508
509
510vltime:
511		/* empty */
512		{
513			$$ = DEF_VLTIME;
514		}
515	|	VLTIME_CMD lifetime
516		{
517			$$ = htonl($2);
518		}
519	;
520
521pltime:
522		/* empty */
523		{
524			$$ = DEF_PLTIME;
525		}
526	|	PLTIME_CMD lifetime
527		{
528			$$ = htonl($2);
529		}
530
531raf_onlink:
532		/* empty */
533		{
534			$$ = NOSPEC;
535		}
536	|	RAF_ONLINK_CMD flag
537		{
538			$$ = $2;
539		}
540	;
541
542raf_auto:
543		/* empty */
544		{
545			$$ = NOSPEC;
546		}
547	|	RAF_AUTO_CMD flag
548		{
549			$$ = $2;
550		}
551	;
552
553raf_decrvalid:
554		/* empty */
555		{
556			$$ = NOSPEC;
557		}
558	|	RAF_DECRVALID_CMD flag
559		{
560			$$ = $2;
561		}
562	;
563
564raf_decrprefd:
565		/* empty */
566		{
567			$$ = NOSPEC;
568		}
569	|	RAF_DECRPREFD_CMD flag
570		{
571			$$ = $2;
572		}
573	;
574
575flag:
576		ON
577	|	OFF
578	;
579
580lifetime:
581		decstring
582	|	INFINITY
583		{
584			$$ = 0xffffffff;
585		}
586	|	days hours minutes seconds
587		{
588			int d, h, m, s;
589
590			d = $1 * 24 * 60 * 60;
591			h = $2 * 60 * 60;
592			m = $3 * 60;
593			s = $4;
594			$$ = d + h + m + s;
595		}
596	;
597
598days:
599		/* empty */
600		{
601			$$ = 0;
602		}
603	|	DAYS
604	;
605
606hours:
607		/* empty */
608		{
609			$$ = 0;
610		}
611	|	HOURS
612	;
613
614minutes:
615		/* empty */
616		{
617			$$ = 0;
618		}
619	|	MINUTES
620	;
621
622seconds:
623		/* empty */
624		{
625			$$ = 0;
626		}
627	|	SECONDS
628	;
629
630decstring:
631		DECSTRING
632		{
633			int dval;
634
635			dval = atoi($1.cp);
636			$$ = dval;
637		}
638	;
639
640%%
641
642static struct payload_list *
643pllist_lookup(int seqnum)
644{
645	struct payload_list *pl;
646	for (pl = pl_head; pl && pl->pl_irr.rr_seqnum != seqnum;
647	     pl = pl->pl_next)
648		continue;
649	return (pl);
650}
651
652static void
653pllist_enqueue(struct payload_list *pl_entry)
654{
655	struct payload_list *pl, *pl_last;
656	if (pl_head == NULL) {
657		pl_head = pl_entry;
658		return;
659	}
660	for (pl = pl_head;
661	     pl && pl->pl_irr.rr_seqnum < pl_entry->pl_irr.rr_seqnum;
662	     pl_last = pl, pl = pl->pl_next)
663		continue;
664	pl_last->pl_next = pl_entry;
665
666	return;
667}
668