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