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