xref: /freebsd/usr.sbin/rrenumd/parser.y (revision 1f474190)
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$
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 
56 struct config_is_set {
57 	u_short cis_dest : 1;
58 } cis;
59 
60 struct dst_list *dl_head;
61 struct payload_list *pl_head, ple_cur;
62 u_int retry;
63 char errbuf[LINE_MAX];
64 
65 extern int lineno;
66 extern void yyerror(const char *s);
67 extern int yylex(void);
68 static struct payload_list * pllist_lookup(int seqnum);
69 static 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 %%
119 config:
120 		/* empty */
121 	| 	statements
122 	;
123 
124 statements:
125 		statement
126 	| 	statements statement
127 	;
128 
129 statement:
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 
141 debug_statement:
142 		DEBUG_CMD flag EOS
143 		{
144 #if YYDEBUG
145 			yydebug = $2;
146 #endif /* YYDEBUG */
147 		}
148 	;
149 
150 destination_statement:
151 		DEST_CMD dest_addrs retrynum EOS
152 		{
153 			dl_head = $2;
154 			retry = $3;
155 		}
156 	;
157 
158 dest_addrs:
159 		dest_addr
160 	|	dest_addrs dest_addr
161 		{
162 			$2->dl_next = $1;
163 			$$ = $2;
164 		}
165 	;
166 
167 dest_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 
215 sin:
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 
233 sin6:
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 
250 ifname:
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 
264 retrynum:
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 
277 rrenum_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 
294 seqnum:
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 
312 rrenum_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 
326 rrenum_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 
335 match_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 = &ple_cur.pl_irr;
342 			rpm = &ple_cur.pl_rpm;
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 
353 rrenum_cmd:
354 		/* empty */
355 		{
356 			$$ = RPM_PCO_ADD;
357 		}
358 	|	ADD
359 	|	CHANGE
360 	|	SETGLOBAL
361 	;
362 
363 prefixval:
364 		IPV6ADDR prefixlen
365 		{
366 			$$.addr = $1;
367 			$$.plen = $2;
368 		}
369 	;
370 
371 prefixlen:
372 		/* empty */
373 		{
374 			$$ = 64;
375 		}
376 	|	PREFIXLEN
377 	;
378 
379 maxlen:
380 		/* empty */
381 		{
382 			$$ = 128;
383 		}
384 	|	MAXLEN_CMD decstring
385 		{
386 			if ($2 > 128)
387 				$2 = 128;
388 			$$ = $2;
389 		}
390 	;
391 
392 minlen:
393 		/* empty */
394 		{
395 			$$ = 0;
396 		}
397 	|	MINLEN_CMD decstring
398 		{
399 			if ($2 > 128)
400 				$2 = 128;
401 			$$ = $2;
402 		}
403 	;
404 
405 use_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 
433 use_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 
503 keeplen:
504 		/* empty */
505 		{
506 			$$ = 0;
507 		}
508 	|	KEEPLEN_CMD decstring
509 		{
510 			if ($2 > 128)
511 				$2 = 128;
512 			$$ = $2;
513 		}
514 	;
515 
516 
517 vltime:
518 		/* empty */
519 		{
520 			$$ = htonl(DEF_VLTIME);
521 		}
522 	|	VLTIME_CMD lifetime
523 		{
524 			$$ = htonl($2);
525 		}
526 	;
527 
528 pltime:
529 		/* empty */
530 		{
531 			$$ = htonl(DEF_PLTIME);
532 		}
533 	|	PLTIME_CMD lifetime
534 		{
535 			$$ = htonl($2);
536 		}
537 
538 raf_onlink:
539 		/* empty */
540 		{
541 			$$ = NOSPEC;
542 		}
543 	|	RAF_ONLINK_CMD flag
544 		{
545 			$$ = $2;
546 		}
547 	;
548 
549 raf_auto:
550 		/* empty */
551 		{
552 			$$ = NOSPEC;
553 		}
554 	|	RAF_AUTO_CMD flag
555 		{
556 			$$ = $2;
557 		}
558 	;
559 
560 raf_decrvalid:
561 		/* empty */
562 		{
563 			$$ = NOSPEC;
564 		}
565 	|	RAF_DECRVALID_CMD flag
566 		{
567 			$$ = $2;
568 		}
569 	;
570 
571 raf_decrprefd:
572 		/* empty */
573 		{
574 			$$ = NOSPEC;
575 		}
576 	|	RAF_DECRPREFD_CMD flag
577 		{
578 			$$ = $2;
579 		}
580 	;
581 
582 flag:
583 		ON { $$ = ON; }
584 	|	OFF { $$ = OFF; }
585 	;
586 
587 lifetime:
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 
605 days:
606 		/* empty */
607 		{
608 			$$ = 0;
609 		}
610 	|	DAYS
611 	;
612 
613 hours:
614 		/* empty */
615 		{
616 			$$ = 0;
617 		}
618 	|	HOURS
619 	;
620 
621 minutes:
622 		/* empty */
623 		{
624 			$$ = 0;
625 		}
626 	|	MINUTES
627 	;
628 
629 seconds:
630 		/* empty */
631 		{
632 			$$ = 0;
633 		}
634 	|	SECONDS
635 	;
636 
637 decstring:
638 		DECSTRING
639 		{
640 			int dval;
641 
642 			dval = atoi($1.cp);
643 			$$ = dval;
644 		}
645 	;
646 
647 %%
648 
649 static struct payload_list *
650 pllist_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 
659 static void
660 pllist_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