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