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