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