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