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