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