xref: /freebsd/usr.sbin/rrenumd/parser.y (revision 9a4365d0)
1 /*
2  * Copyright (C) 1995, 1996, 1997, and 1998 WIDE Project.
3  * All rights reserved.
4  *
5  * Redistribution and use in source and binary forms, with or without
6  * modification, are permitted provided that the following conditions
7  * are met:
8  * 1. Redistributions of source code must retain the above copyright
9  *    notice, this list of conditions and the following disclaimer.
10  * 2. Redistributions in binary form must reproduce the above copyright
11  *    notice, this list of conditions and the following disclaimer in the
12  *    documentation and/or other materials provided with the distribution.
13  * 3. Neither the name of the project nor the names of its contributors
14  *    may be used to endorse or promote products derived from this software
15  *    without specific prior written permission.
16  *
17  * THIS SOFTWARE IS PROVIDED BY THE PROJECT AND CONTRIBUTORS ``AS IS'' AND
18  * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
19  * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
20  * ARE DISCLAIMED.  IN NO EVENT SHALL THE PROJECT OR CONTRIBUTORS BE LIABLE
21  * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
22  * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
23  * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
24  * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
25  * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
26  * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
27  * SUCH DAMAGE.
28  *
29  * $FreeBSD$
30  */
31 
32 %{
33 #include <sys/param.h>
34 #include <sys/ioctl.h>
35 #include <sys/socket.h>
36 #include <sys/uio.h>
37 
38 #include <net/if.h>
39 #include <net/if_var.h>
40 
41 #include <netinet/in.h>
42 #include <netinet/in_var.h>
43 #include <netinet/icmp6.h>
44 
45 #include <netdb.h>
46 #include <string.h>
47 
48 #include "rrenumd.h"
49 
50 struct config_is_set {
51 	u_short	cis_dest : 1;
52 } cis;
53 
54 struct	dst_list *dl_head;
55 struct	payload_list *pl_head, ple_cur;
56 u_int	retry;
57 char	errbuf[LINE_MAX];
58 
59 extern int	lineno;
60 extern void	yyerror __P((const char *s));
61 static struct	payload_list * pllist_lookup __P((int seqnum));
62 static void	pllist_enqueue __P((struct payload_list *pl_entry));
63 
64 #define	MAX_RETRYNUM 10 /* upper limit of retry in this rrenumd program */
65 #define	MAX_SEQNUM 256 /* upper limit of seqnum in this rrenumd program */
66 #define	NOSPEC	-1
67 
68 %}
69 
70 %union {
71 	u_long	num;
72 	struct {
73 		char 	*cp;
74 		int	len;
75 	} cs;
76 	struct	in_addr addr4;
77 	struct	in6_addr addr6;
78 	struct {
79 		struct	in6_addr addr;
80 		u_char	plen;
81 	} prefix;
82 	struct	dst_list *dl;
83 	struct	payload_list *pl;
84 	struct	sockaddr *sa;
85 }
86 
87 %token <num> ADD CHANGE SETGLOBAL
88 %token DEBUG_CMD DEST_CMD RETRY_CMD SEQNUM_CMD
89 %token MATCH_PREFIX_CMD MAXLEN_CMD MINLEN_CMD
90 %token USE_PREFIX_CMD KEEPLEN_CMD
91 %token VLTIME_CMD PLTIME_CMD
92 %token RAF_ONLINK_CMD RAF_AUTO_CMD RAF_DECRVALID_CMD RAF_DECRPREFD_CMD
93 %token <num> DAYS HOURS MINUTES SECONDS INFINITY
94 %token <num> ON OFF
95 %token BCL ECL EOS ERROR
96 %token <cs> NAME HOSTNAME QSTRING DECSTRING
97 %token <addr4> IPV4ADDR
98 %token <addr6> IPV6ADDR
99 %token <num> PREFIXLEN
100 
101 %type <num> retrynum seqnum rrenum_cmd
102 %type <num> prefixlen maxlen minlen keeplen vltime pltime
103 %type <num> lifetime days hours minutes seconds
104 %type <num> decstring
105 %type <num> raf_onlink raf_auto raf_decrvalid raf_decrprefd flag
106 %type <dl> dest_addrs dest_addr sin6
107 %type <pl> rrenum_statement
108 %type <cs> ifname
109 %type <prefix> prefixval
110 
111 %%
112 config:
113 		/* empty */
114 	| 	statements
115 	;
116 
117 statements:
118 		statement
119 	| 	statements statement
120 	;
121 
122 statement:
123 		debug_statement
124 	|	destination_statement
125 	|	rrenum_statement_without_seqnum
126 	|	rrenum_statement_with_seqnum
127 	|	error EOS
128 		{
129 			yyerrok;
130 		}
131 	|	EOS
132 	;
133 
134 debug_statement:
135 		DEBUG_CMD flag EOS
136 		{
137 #ifdef YYDEBUG
138 			yydebug = $2;
139 #endif /* YYDEBUG */
140 		}
141 	;
142 
143 destination_statement:
144 		DEST_CMD dest_addrs retrynum EOS
145 		{
146 			dl_head = $2;
147 			retry = $3;
148 		}
149 	;
150 
151 dest_addrs:
152 		dest_addr
153 	|	dest_addrs dest_addr
154 		{
155 			$2->dl_next = $1;
156 			$$ = $2;
157 		}
158 	;
159 
160 dest_addr :
161 		sin6
162 		{
163 			with_v6dest = 1;
164 		}
165 	|	sin6 ifname
166 		{
167 			struct sockaddr_in6 *sin6;
168 
169 			sin6 = (struct sockaddr_in6 *)$1->dl_dst;
170 			sin6->sin6_scope_id = if_nametoindex($2.cp);
171 			with_v6dest = 1;
172 			$$ = $1;
173 		}
174 	|	HOSTNAME
175 		{
176 			struct sockaddr_storage *ss;
177 			struct addrinfo hints, *res;
178 			int error;
179 
180 			memset(&hints, 0, sizeof(hints));
181 			hints.ai_flags = AI_CANONNAME;
182 			hints.ai_family = AF_INET6;
183 			hints.ai_socktype = SOCK_RAW;
184 			hints.ai_protocol = 0;
185 			error = getaddrinfo($1.cp, 0, &hints, &res);
186 			if (error) {
187 				sprintf(errbuf, "name resolution failed for %s"
188 				":%s", $1, gai_strerror(error));
189 				yyerror(errbuf);
190 			}
191 			ss = (struct sockaddr_storage *)malloc(sizeof(*ss));
192 			memset(ss, 0, sizeof(*ss));
193 			memcpy(ss, res->ai_addr, res->ai_addr->sa_len);
194 			freeaddrinfo(res);
195 
196 			$$ = (struct dst_list *)
197 			     malloc(sizeof(struct dst_list));
198 			memset($$, 0, sizeof(struct dst_list));
199 			$$->dl_dst = (struct sockaddr *)ss;
200 		}
201 	;
202 
203 sin6:
204 		IPV6ADDR
205 		{
206 			struct sockaddr_in6 *sin6;
207 
208 			sin6 = (struct sockaddr_in6 *)malloc(sizeof(*sin6));
209 			memset(sin6, 0, sizeof(*sin6));
210 			sin6->sin6_len = sizeof(*sin6);
211 			sin6->sin6_family = AF_INET6;
212 			sin6->sin6_addr = $1;
213 
214 			$$ = (struct dst_list *)
215 			     malloc(sizeof(struct dst_list));
216 			memset($$, 0, sizeof(struct dst_list));
217 			$$->dl_dst = (struct sockaddr *)sin6;
218 		}
219 
220 ifname:
221 		NAME
222 		{
223 			$$.cp = strdup($1.cp);
224 			$$.len = $1.len;
225 		}
226 	|	QSTRING
227 		{
228 			$1.cp[$1.len - 1] = 0;
229 			$$.cp = strdup(&$1.cp[1]);
230 			$$.len = $1.len - 2;
231 		}
232 	;
233 
234 retrynum:
235 		/* empty */
236 		{
237 			$$ = 2;
238 		}
239 	|	RETRY_CMD decstring
240 		{
241 			if ($2 > MAX_RETRYNUM)
242 				$2 = MAX_RETRYNUM;
243 			$$ = $2;
244 		}
245 	;
246 
247 rrenum_statement_with_seqnum:
248 		SEQNUM_CMD seqnum
249 		{
250 			if (pllist_lookup($2)) {
251 				sprintf(errbuf, "duplicate seqnum %d specified"
252 					" at %d", $2, lineno);
253 				yyerror(errbuf);
254 			}
255 		}
256 		BCL rrenum_statement EOS ECL EOS
257 		{
258 			$5->pl_irr.rr_seqnum = $2;
259 			pllist_enqueue($5);
260 		}
261 	;
262 
263 seqnum:
264 		/* empty */
265 		{
266 			$$ = 0;
267 		}
268 	|	decstring
269 		{
270 			if ($1 > MAX_SEQNUM) {
271 				sprintf(errbuf, "seqnum %d is illegal for this"
272 					" program. should be between 0 and %d",
273 					$1, MAX_SEQNUM);
274 				yyerror(errbuf);
275 			}
276 			$$ = $1;
277 		}
278 	;
279 
280 rrenum_statement_without_seqnum:
281 		rrenum_statement EOS
282 		{
283 			if (pllist_lookup(0)) {
284 				sprintf(errbuf, "duplicate seqnum %d specified"
285 					" at %d", 0, lineno);
286 				yyerror(errbuf);
287 			}
288 			$1->pl_irr.rr_seqnum = 0;
289 			pllist_enqueue($1);
290 		}
291 	;
292 
293 rrenum_statement:
294 		match_prefix_definition use_prefix_definition
295 		{
296 			$$ = (struct payload_list *)
297 			     malloc(sizeof(struct payload_list));
298 			memcpy($$, &ple_cur, sizeof(ple_cur));
299 		}
300 	;
301 
302 match_prefix_definition:
303 		rrenum_cmd MATCH_PREFIX_CMD prefixval maxlen minlen
304 		{
305 			struct icmp6_router_renum *irr;
306 			struct rr_pco_match *rpm;
307 
308 			irr = (struct icmp6_router_renum *)&ple_cur.pl_irr;
309 			rpm = (struct rr_pco_match *)(irr + 1);
310 			memset(rpm, 0, sizeof(*rpm));
311 
312 			rpm->rpm_code = $1;
313 			rpm->rpm_prefix = $3.addr;
314 			rpm->rpm_matchlen = $3.plen;
315 			rpm->rpm_maxlen = $4;
316 			rpm->rpm_minlen = $5;
317 		}
318 	;
319 
320 rrenum_cmd:
321 		/* empty */
322 		{
323 			$$ = RPM_PCO_ADD;
324 		}
325 	|	ADD
326 	|	CHANGE
327 	|	SETGLOBAL
328 	;
329 
330 prefixval:
331 		IPV6ADDR prefixlen
332 		{
333 			$$.addr = $1;
334 			$$.plen = $2;
335 		}
336 	;
337 
338 prefixlen:
339 		/* empty */
340 		{
341 			$$ = 64;
342 		}
343 	|	PREFIXLEN
344 	;
345 
346 maxlen:
347 		/* empty */
348 		{
349 			$$ = 128;
350 		}
351 	|	MAXLEN_CMD decstring
352 		{
353 			if ($2 > 128)
354 				$2 = 128;
355 			$$ = $2;
356 		}
357 	;
358 
359 minlen:
360 		/* empty */
361 		{
362 			$$ = 0;
363 		}
364 	|	MINLEN_CMD decstring
365 		{
366 			if ($2 > 128)
367 				$2 = 128;
368 			$$ = $2;
369 		}
370 	;
371 
372 use_prefix_definition:
373 		/* empty */
374 		{
375 			struct icmp6_router_renum *irr;
376 			struct rr_pco_match *rpm;
377 			struct rr_pco_use *rpu;
378 
379 			irr = (struct icmp6_router_renum *)&ple_cur.pl_irr;
380 			rpm = (struct rr_pco_match *)(irr + 1);
381 			rpu = (struct rr_pco_use *)(rpm + 1);
382 			memset(rpu, 0, sizeof(*rpu));
383 		}
384 	|	USE_PREFIX_CMD prefixval keeplen use_prefix_values
385 		{
386 			struct icmp6_router_renum *irr;
387 			struct rr_pco_match *rpm;
388 			struct rr_pco_use *rpu;
389 
390 			irr = (struct icmp6_router_renum *)&ple_cur.pl_irr;
391 			rpm = (struct rr_pco_match *)(irr + 1);
392 			rpu = (struct rr_pco_use *)(rpm + 1);
393 
394 			rpu->rpu_prefix = $2.addr;
395 			rpu->rpu_uselen = $2.plen;
396 			rpu->rpu_keeplen = $3;
397 		}
398 	;
399 
400 use_prefix_values:
401 		/* empty */
402 		{
403 			struct icmp6_router_renum *irr;
404 			struct rr_pco_match *rpm;
405 			struct rr_pco_use *rpu;
406 
407 			irr = (struct icmp6_router_renum *)&ple_cur.pl_irr;
408 			rpm = (struct rr_pco_match *)(irr + 1);
409 			rpu = (struct rr_pco_use *)(rpm + 1);
410 			memset(rpu, 0, sizeof(*rpu));
411 
412 			rpu->rpu_vltime = DEF_VLTIME;
413 			rpu->rpu_pltime = DEF_PLTIME;
414 			rpu->rpu_ramask = 0;
415 			rpu->rpu_flags = 0;
416 		}
417 	|	BCL vltime pltime raf_onlink raf_auto raf_decrvalid raf_decrprefd ECL
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 			memset(rpu, 0, sizeof(*rpu));
427 
428 			rpu->rpu_vltime = $2;
429 			rpu->rpu_pltime = $3;
430 			if ($4 == NOSPEC)
431 				rpu->rpu_ramask &=
432 					~ICMP6_RR_PCOUSE_RAFLAGS_ONLINK;
433 			else {
434 				rpu->rpu_ramask |=
435 					ICMP6_RR_PCOUSE_RAFLAGS_ONLINK;
436 				if ($4 == ON)
437 					rpu->rpu_raflags |=
438 						ICMP6_RR_PCOUSE_RAFLAGS_ONLINK;
439 				else
440 					rpu->rpu_raflags &=
441 						~ICMP6_RR_PCOUSE_RAFLAGS_ONLINK;
442 			}
443 			if ($5 == NOSPEC)
444 				rpu->rpu_ramask &=
445 					ICMP6_RR_PCOUSE_RAFLAGS_AUTO;
446 			else {
447 				rpu->rpu_ramask |=
448 					ICMP6_RR_PCOUSE_RAFLAGS_AUTO;
449 				if ($5 == ON)
450 					rpu->rpu_raflags |=
451 						ICMP6_RR_PCOUSE_RAFLAGS_AUTO;
452 				else
453 					rpu->rpu_raflags &=
454 						~ICMP6_RR_PCOUSE_RAFLAGS_AUTO;
455 			}
456 			rpu->rpu_flags = 0;
457 			if ($6 == ON)
458 				rpu->rpu_flags |=
459 					ICMP6_RR_PCOUSE_FLAGS_DECRVLTIME;
460 			if ($7 == ON)
461 				rpu->rpu_flags |=
462 					ICMP6_RR_PCOUSE_FLAGS_DECRPLTIME;
463 		}
464 	;
465 
466 keeplen:
467 		/* empty */
468 		{
469 			$$ = 0;
470 		}
471 	|	KEEPLEN_CMD decstring
472 		{
473 			if ($2 > 128)
474 				$2 = 128;
475 			$$ = $2;
476 		}
477 	;
478 
479 
480 vltime:
481 		/* empty */
482 		{
483 			$$ = DEF_VLTIME;
484 		}
485 	|	VLTIME_CMD lifetime
486 		{
487 			$$ = htonl($2);
488 		}
489 	;
490 
491 pltime:
492 		/* empty */
493 		{
494 			$$ = DEF_PLTIME;
495 		}
496 	|	PLTIME_CMD lifetime
497 		{
498 			$$ = htonl($2);
499 		}
500 
501 raf_onlink:
502 		/* empty */
503 		{
504 			$$ = NOSPEC;
505 		}
506 	|	RAF_ONLINK_CMD flag
507 		{
508 			$$ = $2;
509 		}
510 	;
511 
512 raf_auto:
513 		/* empty */
514 		{
515 			$$ = NOSPEC;
516 		}
517 	|	RAF_AUTO_CMD flag
518 		{
519 			$$ = $2;
520 		}
521 	;
522 
523 raf_decrvalid:
524 		/* empty */
525 		{
526 			$$ = NOSPEC;
527 		}
528 	|	RAF_DECRVALID_CMD flag
529 		{
530 			$$ = $2;
531 		}
532 	;
533 
534 raf_decrprefd:
535 		/* empty */
536 		{
537 			$$ = NOSPEC;
538 		}
539 	|	RAF_DECRPREFD_CMD flag
540 		{
541 			$$ = $2;
542 		}
543 	;
544 
545 flag:
546 		ON
547 	|	OFF
548 	;
549 
550 lifetime:
551 		decstring
552 	|	INFINITY
553 		{
554 			$$ = 0xffffffff;
555 		}
556 	|	days hours minutes seconds
557 		{
558 			int d, h, m, s;
559 
560 			d = $1 * 24 * 60 * 60;
561 			h = $2 * 60 * 60;
562 			m = $3 * 60;
563 			s = $4;
564 			$$ = d + h + m + s;
565 		}
566 	;
567 
568 days:
569 		/* empty */
570 		{
571 			$$ = 0;
572 		}
573 	|	DAYS
574 	;
575 
576 hours:
577 		/* empty */
578 		{
579 			$$ = 0;
580 		}
581 	|	HOURS
582 	;
583 
584 minutes:
585 		/* empty */
586 		{
587 			$$ = 0;
588 		}
589 	|	MINUTES
590 	;
591 
592 seconds:
593 		/* empty */
594 		{
595 			$$ = 0;
596 		}
597 	|	SECONDS
598 	;
599 
600 decstring:
601 		DECSTRING
602 		{
603 			int dval;
604 
605 			dval = atoi($1.cp);
606 			$$ = dval;
607 		}
608 	;
609 
610 %%
611 
612 static struct payload_list *
613 pllist_lookup(int seqnum)
614 {
615 	struct payload_list *pl;
616 	for (pl = pl_head; pl && pl->pl_irr.rr_seqnum != seqnum;
617 	     pl = pl->pl_next)
618 		continue;
619 	return (pl);
620 }
621 
622 static void
623 pllist_enqueue(struct payload_list *pl_entry)
624 {
625 	struct payload_list *pl, *pl_last;
626 	if (pl_head == NULL) {
627 		pl_head = pl_entry;
628 		return;
629 	}
630 	for (pl = pl_head;
631 	     pl && pl->pl_irr.rr_seqnum < pl_entry->pl_irr.rr_seqnum;
632 	     pl_last = pl, pl = pl->pl_next)
633 		continue;
634 	pl_last->pl_next = pl_entry;
635 
636 	return;
637 }
638