Initial import from FreeBSD RELENG_4:
[games.git] / usr.sbin / rrenumd / parser.y
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(__FreeBSD__) && __FreeBSD__ >= 3
43 #include <net/if_var.h>
44 #endif /* __FreeBSD__ >= 3 */
45
46 #include <netinet/in.h>
47 #include <netinet/in_var.h>
48 #include <netinet/icmp6.h>
49
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 __P((const char *s));
67 extern int yylex __P((void));
68 static struct payload_list * pllist_lookup __P((int seqnum));
69 static void pllist_enqueue __P((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 = (struct icmp6_router_renum *)&ple_cur.pl_irr;
342                         rpm = (struct rr_pco_match *)(irr + 1);
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
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 }