xref: /freebsd/usr.sbin/rrenumd/parser.y (revision a0ee8cc6)
1 /*	$KAME: parser.y,v 1.8 2000/11/08 03:03:34 jinmei Exp $	*/
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$
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 #ifdef 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 icmp6_router_renum *irr;
337 			struct rr_pco_match *rpm;
338 
339 			irr = (struct icmp6_router_renum *)&ple_cur.pl_irr;
340 			rpm = (struct rr_pco_match *)(irr + 1);
341 			memset(rpm, 0, sizeof(*rpm));
342 
343 			rpm->rpm_code = $1;
344 			rpm->rpm_prefix = $3.addr;
345 			rpm->rpm_matchlen = $3.plen;
346 			rpm->rpm_maxlen = $4;
347 			rpm->rpm_minlen = $5;
348 		}
349 	;
350 
351 rrenum_cmd:
352 		/* empty */
353 		{
354 			$$ = RPM_PCO_ADD;
355 		}
356 	|	ADD
357 	|	CHANGE
358 	|	SETGLOBAL
359 	;
360 
361 prefixval:
362 		IPV6ADDR prefixlen
363 		{
364 			$$.addr = $1;
365 			$$.plen = $2;
366 		}
367 	;
368 
369 prefixlen:
370 		/* empty */
371 		{
372 			$$ = 64;
373 		}
374 	|	PREFIXLEN
375 	;
376 
377 maxlen:
378 		/* empty */
379 		{
380 			$$ = 128;
381 		}
382 	|	MAXLEN_CMD decstring
383 		{
384 			if ($2 > 128)
385 				$2 = 128;
386 			$$ = $2;
387 		}
388 	;
389 
390 minlen:
391 		/* empty */
392 		{
393 			$$ = 0;
394 		}
395 	|	MINLEN_CMD decstring
396 		{
397 			if ($2 > 128)
398 				$2 = 128;
399 			$$ = $2;
400 		}
401 	;
402 
403 use_prefix_definition:
404 		/* empty */
405 		{
406 			struct icmp6_router_renum *irr;
407 			struct rr_pco_match *rpm;
408 			struct rr_pco_use *rpu;
409 
410 			irr = (struct icmp6_router_renum *)&ple_cur.pl_irr;
411 			rpm = (struct rr_pco_match *)(irr + 1);
412 			rpu = (struct rr_pco_use *)(rpm + 1);
413 			memset(rpu, 0, sizeof(*rpu));
414 		}
415 	|	USE_PREFIX_CMD prefixval keeplen use_prefix_values
416 		{
417 			struct icmp6_router_renum *irr;
418 			struct rr_pco_match *rpm;
419 			struct rr_pco_use *rpu;
420 
421 			irr = (struct icmp6_router_renum *)&ple_cur.pl_irr;
422 			rpm = (struct rr_pco_match *)(irr + 1);
423 			rpu = (struct rr_pco_use *)(rpm + 1);
424 
425 			rpu->rpu_prefix = $2.addr;
426 			rpu->rpu_uselen = $2.plen;
427 			rpu->rpu_keeplen = $3;
428 		}
429 	;
430 
431 use_prefix_values:
432 		/* empty */
433 		{
434 			struct icmp6_router_renum *irr;
435 			struct rr_pco_match *rpm;
436 			struct rr_pco_use *rpu;
437 
438 			irr = (struct icmp6_router_renum *)&ple_cur.pl_irr;
439 			rpm = (struct rr_pco_match *)(irr + 1);
440 			rpu = (struct rr_pco_use *)(rpm + 1);
441 			memset(rpu, 0, sizeof(*rpu));
442 
443 			rpu->rpu_vltime = htonl(DEF_VLTIME);
444 			rpu->rpu_pltime = htonl(DEF_PLTIME);
445 			rpu->rpu_ramask = 0;
446 			rpu->rpu_flags = 0;
447 		}
448 	|	BCL vltime pltime raf_onlink raf_auto raf_decrvalid raf_decrprefd ECL
449 		{
450 			struct icmp6_router_renum *irr;
451 			struct rr_pco_match *rpm;
452 			struct rr_pco_use *rpu;
453 
454 			irr = (struct icmp6_router_renum *)&ple_cur.pl_irr;
455 			rpm = (struct rr_pco_match *)(irr + 1);
456 			rpu = (struct rr_pco_use *)(rpm + 1);
457 			memset(rpu, 0, sizeof(*rpu));
458 
459 			rpu->rpu_vltime = $2;
460 			rpu->rpu_pltime = $3;
461 			if ($4 == NOSPEC) {
462 				rpu->rpu_ramask &=
463 				    ~ICMP6_RR_PCOUSE_RAFLAGS_ONLINK;
464 			} else {
465 				rpu->rpu_ramask |=
466 				    ICMP6_RR_PCOUSE_RAFLAGS_ONLINK;
467 				if ($4 == ON) {
468 					rpu->rpu_raflags |=
469 					    ICMP6_RR_PCOUSE_RAFLAGS_ONLINK;
470 				} else {
471 					rpu->rpu_raflags &=
472 					    ~ICMP6_RR_PCOUSE_RAFLAGS_ONLINK;
473 				}
474 			}
475 			if ($5 == NOSPEC) {
476 				rpu->rpu_ramask &=
477 				    ICMP6_RR_PCOUSE_RAFLAGS_AUTO;
478 			} else {
479 				rpu->rpu_ramask |=
480 				    ICMP6_RR_PCOUSE_RAFLAGS_AUTO;
481 				if ($5 == ON) {
482 					rpu->rpu_raflags |=
483 					    ICMP6_RR_PCOUSE_RAFLAGS_AUTO;
484 				} else {
485 					rpu->rpu_raflags &=
486 					    ~ICMP6_RR_PCOUSE_RAFLAGS_AUTO;
487 				}
488 			}
489 			rpu->rpu_flags = 0;
490 			if ($6 == ON) {
491 				rpu->rpu_flags |=
492 				    ICMP6_RR_PCOUSE_FLAGS_DECRVLTIME;
493 			}
494 			if ($7 == ON) {
495 				rpu->rpu_flags |=
496 				    ICMP6_RR_PCOUSE_FLAGS_DECRPLTIME;
497 			}
498 		}
499 	;
500 
501 keeplen:
502 		/* empty */
503 		{
504 			$$ = 0;
505 		}
506 	|	KEEPLEN_CMD decstring
507 		{
508 			if ($2 > 128)
509 				$2 = 128;
510 			$$ = $2;
511 		}
512 	;
513 
514 
515 vltime:
516 		/* empty */
517 		{
518 			$$ = htonl(DEF_VLTIME);
519 		}
520 	|	VLTIME_CMD lifetime
521 		{
522 			$$ = htonl($2);
523 		}
524 	;
525 
526 pltime:
527 		/* empty */
528 		{
529 			$$ = htonl(DEF_PLTIME);
530 		}
531 	|	PLTIME_CMD lifetime
532 		{
533 			$$ = htonl($2);
534 		}
535 
536 raf_onlink:
537 		/* empty */
538 		{
539 			$$ = NOSPEC;
540 		}
541 	|	RAF_ONLINK_CMD flag
542 		{
543 			$$ = $2;
544 		}
545 	;
546 
547 raf_auto:
548 		/* empty */
549 		{
550 			$$ = NOSPEC;
551 		}
552 	|	RAF_AUTO_CMD flag
553 		{
554 			$$ = $2;
555 		}
556 	;
557 
558 raf_decrvalid:
559 		/* empty */
560 		{
561 			$$ = NOSPEC;
562 		}
563 	|	RAF_DECRVALID_CMD flag
564 		{
565 			$$ = $2;
566 		}
567 	;
568 
569 raf_decrprefd:
570 		/* empty */
571 		{
572 			$$ = NOSPEC;
573 		}
574 	|	RAF_DECRPREFD_CMD flag
575 		{
576 			$$ = $2;
577 		}
578 	;
579 
580 flag:
581 		ON { $$ = ON; }
582 	|	OFF { $$ = OFF; }
583 	;
584 
585 lifetime:
586 		decstring
587 	|	INFINITY
588 		{
589 			$$ = 0xffffffff;
590 		}
591 	|	days hours minutes seconds
592 		{
593 			int d, h, m, s;
594 
595 			d = $1 * 24 * 60 * 60;
596 			h = $2 * 60 * 60;
597 			m = $3 * 60;
598 			s = $4;
599 			$$ = d + h + m + s;
600 		}
601 	;
602 
603 days:
604 		/* empty */
605 		{
606 			$$ = 0;
607 		}
608 	|	DAYS
609 	;
610 
611 hours:
612 		/* empty */
613 		{
614 			$$ = 0;
615 		}
616 	|	HOURS
617 	;
618 
619 minutes:
620 		/* empty */
621 		{
622 			$$ = 0;
623 		}
624 	|	MINUTES
625 	;
626 
627 seconds:
628 		/* empty */
629 		{
630 			$$ = 0;
631 		}
632 	|	SECONDS
633 	;
634 
635 decstring:
636 		DECSTRING
637 		{
638 			int dval;
639 
640 			dval = atoi($1.cp);
641 			$$ = dval;
642 		}
643 	;
644 
645 %%
646 
647 static struct payload_list *
648 pllist_lookup(int seqnum)
649 {
650 	struct payload_list *pl;
651 	for (pl = pl_head; pl && pl->pl_irr.rr_seqnum != seqnum;
652 	     pl = pl->pl_next)
653 		continue;
654 	return (pl);
655 }
656 
657 static void
658 pllist_enqueue(struct payload_list *pl_entry)
659 {
660 	struct payload_list *pl, *pl_last;
661 
662 	pl_last = NULL;
663 	for (pl = pl_head;
664 	     pl && pl->pl_irr.rr_seqnum < pl_entry->pl_irr.rr_seqnum;
665 	     pl_last = pl, pl = pl->pl_next)
666 		continue;
667 	if (pl_last)
668 		pl_last->pl_next = pl_entry;
669 	else
670 		pl_head = pl_entry;
671 
672 	return;
673 }
674